场景对比
- Secret:当你想要存储一些敏感数据时使用Secret,例如(passwords, OAuth tokens, ssh keys, credentials等)
- ConfigMap : 当需要存储一些非敏感配置数据时可以使用ConfigMap,例如应用程序的ini,json等配置文件。
ConfigMap:
创建ConfigMap
1kind: ConfigMap 2apiVersion: v1 3metadata: 4 name: example-config 5 namespace: default 6data: 7 example.property.1: hello #key-value形式,key规则必须满足dns域名规则。value为字符串。 8 example.property.2: world 9 example.property.file: |- #配置文件使用方式,直接把文件内容放入value即可 10 property.1=value-1 11 property.2=value-2 12 property.3=value-3
使用方式:
1.填充环境变量
1apiVersion: v1 2kind: Pod 3metadata: 4 name: dapi-test-pod 5spec: 6 containers: 7 - name: test-container 8 image: gcr.io/google_containers/busybox 9 command: [ "/bin/sh", "-c", "env" ] 10 env: 11 - name: SPECIAL_LEVEL_KEY 12 valueFrom: 13 configMapKeyRef: 14 name: example-config #需要使用的ConfigMap名称,必须已经存在 15 key: example.property.1 #对应ConfigMap data 的key 16 restartPolicy: Never
设置结果
SPECIAL_LEVEL_KEY=hello
2.设置容器启动命令行参数
1apiVersion: v1 2kind: Pod 3metadata: 4 name: dapi-test-pod 5spec: 6 containers: 7 - name: test-container 8 image: gcr.io/google_containers/busybox 9 command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] 10 env: 11 - name: SPECIAL_LEVEL_KEY 12 valueFrom: 13 configMapKeyRef: 14 name: example-config 15 key: example.property.1 16 - name: SPECIAL_TYPE_KEY 17 valueFrom: 18 configMapKeyRef: 19 name: example-config 20 key: example.property.2 21 restartPolicy: Never
运行结果:
hello world
3.挂载ConfigMap到文件
1apiVersion: v1 2kind: Pod 3metadata: 4 name: dapi-test-pod 5spec: 6 containers: 7 - name: test-container 8 image: gcr.io/google_containers/busybox 9 command: [ "/bin/sh","-c","ls -l /etc/config/path/" ] 10 volumeMounts: 11 - name: config-volume 12 mountPath: /etc/config 13 volumes: 14 - name: config-volume 15 configMap: 16 name: example-config 17 items: 18 - key: example.property.1 19 path: path/one/example.property.1 20 - key: example.property.2 21 path: path/two/example.property.2 22 - key: example.property.file 23 path: path/file/example.property.file 24 restartPolicy: Never
创建的文件如下:
1└── path 2 ├── file 3 │ └── example.property.file 4 ├── one 5 │ └── example.property.1 6 └── two 7 └── example.property.2 8 9#cat example.property.1 hello 10#cat example.property.2 world 11#cat example.property.file 12 property.1=value-1 13 property.2=value-2 14 property.3=value-3
注意:
- ConfigMap必须在使用之前被创建,如果引用了一个不存在的configMap,将会导致Pod无法启动
- ConfigMap只能被相同namespace内的应用使用。
3.1挂载ConfigMap到单个文件:
假设我的项目结构如下(项目路径为/usr/local):
1. 2├── Dockerfile 3├── Makefile 4├── app.conf 5├── controllers 6│ └── pod.go 7└── main.go
我只想把app.conf文件从ConfigMap挂载进来,其他文件保持不变,现在应该怎么做呢? 好,我们开始。
假设我的ConfigMap如下:
1apiVersion: v1 2kind: ConfigMap 3metadata: 4 name: test-cfgmap 5data: 6 app.conf: file data
- 第一种方式:
可以使用下面的定义文件使用ConfigMap:
1apiVersion: v1 2kind: Pod 3metadata: 4 name: test-pd-plus-cfgmap 5spec: 6 containers: 7 - image: ubuntu 8 name: bash 9 volumeMounts: 10 - mountPath: /usr/local/app.conf 11 name: cfgmap 12 subPath: app.conf 13 volumes: 14 - name: cfgmap 15 configMap: 16 name: test-cfgmap
注意,这种方式使用ConfigMap, ConfigMap的key、 volumeMounts.mountPath和volumeMounts.subPath名称一定要保持一致,否则会挂载不成功。
-
第二种方式:
apiVersion: v1 kind: Pod metadata: name: test-pd-plus-cfgmap spec: containers:
- image: ubuntu
name: bash
volumeMounts:
- mountPath: /usr/local/app.conf name: cfgmap subPath: app.conf volumes:
- name: cfgmap
configMap:
name: test-cfgmap
items:
- key: app.conf path: app.conf
- image: ubuntu
name: bash
volumeMounts:
注意,这种方式使用ConfigMap,就不再要求 ConfigMap的key跟挂载的文件名必须一致,但需要在items指定key和path对应关系。
- 其它方式:
当然,如果你愿意,你也可以挂载ConfigMap到一个其它路径,然后通过软连接的方式链接到你需要的文件。
实际使用例子(Redis配置):
例如当我们需要按照如下配置来启动Redis
1maxmemory 2mb 2maxmemory-policy allkeys-lru
首先,让我们来创建一个ConfigMap:
1apiVersion: v1 2data: 3 redis-config: | 4 maxmemory 2mb 5 maxmemory-policy allkeys-lru 6kind: ConfigMap 7metadata: 8 name: example-redis-config 9 namespace: default
下面我们来创建一个Pod来使用它:
1apiVersion: v1 2kind: Pod 3metadata: 4 name: redis 5spec: 6 containers: 7 - name: redis 8 image: kubernetes/redis:v1 9 env: 10 - name: MASTER 11 value: "true" 12 ports: 13 - containerPort: 6379 14 volumeMounts: 15 - mountPath: /redis-master 16 name: config 17 volumes: 18 - name: config 19 configMap: 20 name: example-redis-config 21 items: 22 - key: redis-config 23 path: redis.conf #指定生成的配置文件名称
当我们创建完Pod后,进入它: 生成的配置文件如下:
1redis-master 2`-- redis.conf -> ..data/redis.conf
我们发现在redis-master 目录下生成了一个文件redis.conf ,对应我们上面path定义的文件名。输出一下redis.conf内容:
1maxmemory 2mb 2maxmemory-policy allkeys-lru
下面我们看一下redis的配置:
1$ kubectl exec -it redis redis-cli 2127.0.0.1:6379> CONFIG GET maxmemory 31) "maxmemory" 42) "2097152" 5127.0.0.1:6379> CONFIG GET maxmemory-policy 61) "maxmemory-policy" 72) "allkeys-lru"
符合我们的预期。
注意: 虽然使用configMap可以很方便的把我们配置文件放入到容器中,但一定注意配置文件的大小,(尽量控制在1M以内)更不能滥用ConfigMap,否则可能会给apiserver和etcd造成较大压力,影响整个集群。
Secret:
当需要使用一些敏感的配置,比如密码,证书等信息时,建议使用Secret。
创建Secret
1apiVersion: v1 2kind: Secret 3metadata: 4 name: mysecret 5type: Opaque 6data: 7 username: YWRtaW4= 8 password: MWYyZDFlMmU2N2Rm
注意: Secret 的value必须经过base64, 以上明文为: username: admin password: 1f2d1e2e67df ,可以直接使用 echo -n "1f2d1e2e67df" | base64 进行base64,或者到这里可以进行base64加密解密
使用方式:
1.挂载到文件
1apiVersion: v1 2kind: Pod 3metadata: 4 name: mypod 5 namespace: default 6spec: 7 containers: 8 - image: redis 9 name: mypod 10 volumeMounts: 11 - mountPath: /etc/foo 12 name: foo 13 readOnly: true 14 volumes: 15 - name: foo 16 secret: 17 defaultMode: 420 #0644默认文件权限,由于json文件不支持八进制,使用json时应使用十进制 18 secretName: mysecret
运行结果:在/etc/foo/目录下生成两个文件username和password
1foo/ 2|-- password -> ..data/password 3`-- username -> ..data/username 4#cat username admin 5#cat password 1f2d1e2e67df
注意: 自动更新: 当Secrets被更新时,已经挂载的pod不会立即更新,而要等待kubelete检查周期,kubelet会定期检查secret变化并更新它。
2.通过环境变量使用
1apiVersion: v1 2kind: Pod 3metadata: 4 name: secret-env-pod 5spec: 6 containers: 7 - name: mycontainer 8 image: redis 9 env: 10 - name: SECRET_USERNAME 11 valueFrom: 12 secretKeyRef: 13 name: mysecret #指定secret名称 14 key: username #要使用的key 15 - name: SECRET_PASSWORD 16 valueFrom: 17 secretKeyRef: 18 name: mysecret 19 key: password 20 21 22$ echo $SECRET_USERNAME 23admin 24$ echo $SECRET_PASSWORD 251f2d1e2e67df
3.拉取镜像
1apiVersion: v1 2kind: Secret 3metadata: 4 name: image-test-secret 5 namespace: default 6type: kubernetes.io/dockerconfigjson 7data: 8 .dockerconfigjson: ew0KCSJhdXRocyI6IHsNCgkJImltYWdlLXRlc3QiOiB7DQoJCQkiYXV0aCI6ICJjbTl2ZERweWIyOTAiLA0KCQkJImVtYWlsIjogIiINCgkJfQ0KCX0NCn0=
加密部分的明文为:
1{ 2 "auths": { 3 "image-test": { 4 "auth": "cm9vdDpyb290", # 密文为"root:rootbase64"的结果 5 "email": "" 6 } 7 } 8}
部署文件使用如下:
1apiVersion: v1 2kind: Pod 3metadata: 4 name: foo 5 namespace: default 6spec: 7 containers: 8 - name: foo 9 image: janedoe/awesomeapp:v1 10 imagePullSecrets: 11 - name: image-test-secret
实际使用例子(挂载证书文件):
1kind: Secret 2apiVersion: v1 3metadata: 4 name: client-certs 5 namespace: default 6data: 7 ca.pem: *** #实际使用请替换成经过base64加密后的内容 8 kubernetes.pem: *** 9 kubernetes-key.pem: ***
使用deployment部署:
1apiVersion: extensions/v1beta1 2kind: Deployment 3metadata: 4 name: redis 5spec: 6 replicas: 1 7 selector: 8 matchLabels: 9 app: redis 10 template: 11 metadata: 12 labels: 13 app: redis 14 spec: 15 containers: 16 - name: redis 17 image: redis 18 ports: 19 - containerPort: 8080 20 volumeMounts: 21 - mountPath: /etc/kubernetes/certs 22 name: my-certs 23 volumes: 24 - name: my-certs 25 secret: 26 secretName: client-certs 27 items: 28 - key: ca.pem 29 path: ca.pem 30 - key: kubernetes.pem 31 path: kubernetes.pem 32 - key: kubernetes-key.pem 33 path: kubernetes-key.pem 34 imagePullSecrets: 35 - name: image-test-secret