写在前面
我们知道k8s的数据都是存储到kv数据库etcd中的,那么我们程序中使用到各种配置信息是否可以也存储到etcd,然后在pod中使用呢?是可以的,k8s为了实现将自定义的数据存储到etcd,定义了ConfigMap 和secret两种API对象 。其中ConfigMap用来保存明文数据,如端口号,普通配置参数等,Secret用来配置需要加密的数据,如密码,秘钥等。本文就一起来看下这两个对象的定义以及如何在pod中使用。
1:ConfigMap
先来生成yaml模板:
dongyunqi@dongyunqi-virtual-machine:~/test$ export out="--dry-run=client -o yaml" && kubectl create configmap info $out
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: null
name: info
修改完善后如下:
apiVersion: v1
kind: ConfigMap
metadata:
name: info
data:
count: '10'
debug: 'on'
path: '/etc/systemd'
greeting: |
say hello to kubernetes.
这里主要增加了data,即需要存储到etcd的配置项,如果是我们想要在生成模板时就生成data内容,则可以增加--from-literal=k=v
,如 kubectl create cm info --from-literal=k=v $out
,yaml文件编写完了,我们就可以apply了,如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl apply -f configmap.yml
configmap/info created
执行完毕数据就写到etcd中了,如下查看:
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get configmap
NAME DATA AGE
info 4 97s
...
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl describe configmap info
Name: info
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
count:
----
10
debug:
----
on
greeting:
----
say hello to kubernetes.
path:
----
/etc/systemd
BinaryData
====
Events: <none>
可以看到数据已经成功写到etcd数据库中了,明文存储方式就看完了,接下来我们看下加密存储方式。
2:Secret
Secret API对象提供了对于配置项的加密存储功能,首先生成yaml模板,如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ export out="--dry-run=client -o yaml" && kubectl create secret generic user --from-literal=name=root $out
apiVersion: v1
data:
name: cm9vdA==
kind: Secret
metadata:
creationTimestamp: null
name: user
–from-literal=name=root 是指定初始写入的kv,cm9vdA==是base64(root)后的结果,
generic user:是设置secret的加密类型,这里是一般机密信息,完整的包括:
1:访问私有镜像仓库的认证信息
2:身份识别的凭证信息
3:HTTPS 通信的证书和私钥
4:一般的机密信息(格式由用户自行解释)
这里先只看4。
对yaml文件修改完善后如下:
apiVersion: v1
kind: Secret
metadata:
name: user
data:
name: cm9vdA== # root
pwd: MTIzNDU2 # 123456
db: bXlzcWw= # mysql
base 64结果可以通过命令:
echo -n "123456" | base64
获取,其中-n用来删除隐含的换行符,否则就会因为多了换行符而造成加密错误。
然后创建并查看结果:
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl apply -f secret.yml
secret/user created
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get secret
NAME TYPE DATA AGE
default-token-vw5c8 kubernetes.io/service-account-token 3 4d1h
user Opaque 3 10s
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl describe secret user
Name: user
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
db: 5 bytes
name: 4 bytes
pwd: 6 bytes
可以看到已经存储数据到etcd数据库中,但是因为是加密存储,所以这里只能看到字节数。现在基于ConfigMap和Secret两种API对象的存储方式都看完了,配置信息也都存储完毕了,那么该如何在Pod中使用呢,接下来继续看下这部分内容。
3:在Pod中使用
在Pod中有两种使用方式,一种是以环境变量的方式来使用,另一种是Volume,即文件卷的方式。
3.1:环境变量方式使用
这种方式需要使用valueFrom
,如果是引用ConfigMap,则要进一步使用configMapKeyRef
,引用Secret,则进一步使用secretKeyRef
,定义后如下:
apiVersion: v1
kind: Pod
metadata:
name: env-pod
spec:
containers:
- env:
- name: COUNT
valueFrom:
configMapKeyRef:
name: info
key: count
- name: GREETING
valueFrom:
configMapKeyRef:
name: info
key: greeting
- name: USERNAME
valueFrom:
secretKeyRef:
name: user
key: name
- name: PASSWORD
valueFrom:
secretKeyRef:
name: user
key: pwd
image: busybox
name: busy
imagePullPolicy: IfNotPresent
command: ["/bin/sleep", "300"]
命令休眠300秒,主要是为了留下进入容器验证环境变量的时间。文件比较长,主要还是看valueFrom部分的内容,其就是读取我们前面定义的名称为info的confimap,以及名称为user的secret,关系如下图:
看图的话会清晰很多,文字确实不是很好表达。创建Pod,如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl apply -f podUseCmAndSecret.yml
pod/env-pod created
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get pod
NAME READY STATUS RESTARTS AGE
env-pod 1/1 Running 0 6s
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl exec --it -c busy env-pod -- sh
error: unknown flag: --it
See 'kubectl exec --help' for usage.
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl exec -it -c busy env-pod -- sh
/ # echo $COUNT
10
/ # echo $GREETING
say hello to kubernetes.
/ # echo $USERNAME $PASSWORD
root 123456
/ #
可以看到环境变量设置成功了。
3.2:Volume方式使用
这种方式在使用上分为2步,第一步是要先使用ConfigMap/Secret定义Volume,此时会将里边的内容映射为磁盘文件的形式,具体后续我们可以看到,第二步是将第一步定义的Volume挂载到pod中容器指定的目录,首先第一步:
spec:
volumes:
- name: cm-vol
configMap:
name: info
- name: sec-vol
secret:
secretName: user
分别定义了Volumecm-vol
使用的数据源是ConfigMapinfo
,Volume sec-vol
使用的数据源是Secretuser
,接下来就是第二步将Volume挂载到pod中(其实是挂载到pod内的容器中)
,如下:
containers:
- volumeMounts:
- mountPath: /tmp/cm-items
name: cm-vol
- mountPath: /tmp/sec-items
name: sec-vol
此时的结构如下:
太难描述了,真的是一图胜万言
。完整yaml如下:
apiVersion: v1
kind: Pod
metadata:
name: vol-pod
spec:
volumes:
- name: cm-vol
configMap:
name: info
- name: sec-vol
secret:
secretName: user
containers:
- volumeMounts:
- mountPath: /tmp/cm-items
name: cm-vol
- mountPath: /tmp/sec-items
name: sec-vol
image: busybox
name: busy
imagePullPolicy: IfNotPresent
command: ["/bin/sleep", "300"]
运行并查看如下:
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl apply -f podUseVolume.yml
pod/vol-pod created
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl get pod | grep vol-pod
vol-pod 1/1 Running 0 18s
dongyunqi@dongyunqi-virtual-machine:~/test$ kubectl exec -it -c busy vol-pod -- sh
/ # ls /tmp/cm-items/
count debug greeting path
/ # ls /tmp/sec-items/
db name pwd
/ # cat /tmp/cm-items/greeting
say hello to kubernetes.
/ # cat /tmp/sec-items/pwd
123456/ #
可以看到我们定义的kv中的k映射成为了文件系统中文件名为k的文件,文件的内容是v。
写在后面
小结
本文分析了k8s提供的两种配置相关的API对象,分别是ConfigMap和Secret,然后看了其具体的使用,最后分析了在Pod中基于环境变量和Volume文件卷的两种使用方式。希望本文能帮助到你。