关于 Kubernetes 系列其他文章的传送门
-
《 部署 Kubernetes 也能如此简单吗? 》
-
《 初识 k8s,新时代的宠儿 》
-
《 深度学习 Pod 》
-
《 学会这 5 种 Pod 控制器,搞定发布、更新、回滚,从此告别人肉运维!! 》
-
《 k8s 中的网络入口 – Service 资源管理 》
-
《 k8s 中的 7 层调度 – Ingress 》
-
《 k8s 中的存储系统 – Volumes 》
-
《 k8s 中强大的配置中心 – ConfigMap 》 您当前所在位置
-
《 k8s 中的部署神器 – Statefulset 控制器 》
-
《 k8s 中的安全守护神 – 你不知道不代表它不在 》
-
《 k8s 中的图形接口 – Dashboard 》
-
《 k8s 中的网络插件 – flannel 和 Calico 》
-
《 k8s 中的调度器 – 亲和性、污点和容忍性 》
-
《 k8s 中对资源的监控 – 资源指标、Prometheus、弹性伸缩器 HPA 》
-
《 k8s 中的云原生应用管理利器 – Helm 》
-
《 理解 k8s 高可用,让你的集群稳如泰山 》

一、什么是 ConfigMap 以及它的作用
ConfigMap 的作用是把配置文件提升为标准的 k8s 资源,之后可以被 Pod 所引用,加载为容器内程序的配置文件,这类似于一个配置中心。
Pod 加载引用 ConfigMap 资源的方式有两种:
- 通过环境变量:某些容器支持通过在启动时传递一个环境变量来生成配置文件中的某些参数。对于这种容器,在创建 Pod 时可以通过引用 ConfigMap 资源的方式来获取值。但是这种方式只能在容器启动时加载一次,之后如果配置修改了,需要容器里的进程重载或重启才能加载;
- 通过存储卷:让 Pod 加载 ConfigMap 类型的存储卷,并挂载到容器的指定的目录或文件上;
- 注意:Pod 和要引用的 CM 必须都在同一名称空间下。
ConfigMap 资源的创建方式有两种:
-
使用 kubectl create configmap 命令直接在命令行创建:
from-literal=[]:直接在命令行给出;
from-file=[]:从文件加载。
-
通过配置清单配置,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| kind: ConfigMap apiVersion: v1 metadata: name: kube-flannel-cfg namespace: kube-system labels: tier: node app: flannel data: cni-conf.json: | { "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] } net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } }
|
通过环境变量引用 ConfigMap 的示例
先创建 ConfigMap 资源
创建一个 cm,并在命令行直接指定键值:
1 2 3 4
| ~]# kubectl create ns config
~]# kubectl create configmap filebeat-cfg -n config --from-literal=redis_host="redis.default.svc.cluster.local" --from-literal=log_level="Info" configmap/filebeat-cfg created
|
查看刚才创建的 cm,可以看到 data 字段有我们定义的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ~]# kubectl get cm -n config -o yaml apiVersion: v1 items: - apiVersion: v1 data: log_level: Info redis_host: redis.default.svc.cluster.local kind: ConfigMap metadata: creationTimestamp: "2019-11-13T05:20:13Z" name: filebeat-cfg namespace: config resourceVersion: "390355" selfLink: /api/v1/namespaces/config/configmaps/filebeat-cfg uid: 5fd2f0db-c24d-4e27-907b-7f55c632d407 kind: List metadata: resourceVersion: "" selfLink: ""
|
引用 ConfigMap
这里使用一个 filebeat 镜像作为示例,这个镜像启动时可传入两个环境变量 REDIS_HOST 和 LOG_LEVEL 来配置容器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ~]# vim pod-cfg.yaml
apiVersion: v1 kind: Pod metadata: name: pod-cfg-demo namespace: config spec: containers: - name: filebeat image: ikubernetes/filebeat:5.6.5-alpine env: - name: REDIS_HOST valueFrom: configMapKeyRef: name: filebeat-cfg key: redis_host - name: LOG_LEVEL valueFrom: configMapKeyRef: name: filebeat-cfg key: log_level
|
先创建 Pod:
1 2
| ~]# kubectl apply -f pod-cfg.yaml pod/pod-cfg-demo created
|
之后进入容器内查看环境变量是否加载成功:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ~]# kubectl exec -it pod-cfg-demo -n config -- /bin/sh
/ KUBERNETES_SERVICE_PORT=443 KUBERNETES_PORT=tcp://10.96.0.1:443 LOG_LEVEL=Info HOSTNAME=pod-cfg-demo SHLVL=1 HOME=/root TERM=xterm KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 KUBERNETES_SERVICE_PORT_HTTPS=443 PWD=/ KUBERNETES_SERVICE_HOST=10.96.0.1 REDIS_HOST=redis.default.svc.cluster.local FILEBEAT_VERSION=5.6.5
|
这种方式的配置参数只能在容器启动时加载一次,之后如果配置修改了,需要手动将容器里的进程重载或重启才能加载;
通过存储卷引用 ConfigMap
1. 创建 ConfigMap 资源
创建 2 个 nginx 的示例配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ~]# vim server1.conf server { server_name www.monster.com; listen 80; location / { root "/html/monster"; } }
~]# vim server2.conf server { server_name www.ilinux.com; listen 80; location / { root "/html/ilinux"; } }
|
把上面两个配置文件创建为 CM 资源:
1 2 3
| # ↓ 当直接指明使用哪个文件时,以文件名为键,文件的内容为值 ~]# kubectl create configmap nginx-cfg -n config --from-file=./server1.conf --from-file=server-ilinux.conf=./server2.conf # ↑ 也可以自定义键的名字,然后指定以哪个文件的内容为值
|
查看刚刚创建的 CM 资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| ~]# kubectl get cm nginx-cfg -n config -o yaml
apiVersion: v1 data: server-ilinux.conf: | server { server_name www.ilinux.com; Listen 80; Location / { root "/html/ilinux"; } } server1.conf: | server { server_name www.monster.com; Listen 80; Location / { root "/html/monster"; } } kind: ConfigMap metadata: creationTimestamp: "2019-11-13T08:26:05Z" name: nginx-cfg namespace: config resourceVersion: "404230" selfLink: /api/v1/namespaces/config/configmaps/nginx-cfg uid: 9b386a13-c753-4997-ad99-14cff55d233a
|
2. 引用 ConfigMap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ->
apiVersion: v1 kind: Pod metadata: name: nginx-pod namespace: config spec: containers: - name: nginx image: nginx:1.14-alpine volumeMounts: - name: config mountPath: /etc/nginx/conf.d/ volumes: - name: config configMap: name: nginx-cfg items: - key: server1.conf path: server-monster.com - key: server-ilinux.conf path: server-ilinux.conf
|
配置变更
如果需要对配置进行变更,修改 CM 资源即可;
使用下面的命令进入一个 vi 界面修改:
1
| ~]# kubectl edit cm nginx-cfg -n config
|
把 listen 80; 改为 listen 8080;;保存退出后,会被 Pod 中的容器自动加载到,并重载程序,这通常需要一点时间,一般在一分钟左右。如果无法自动重载程序,可以使用比如 nginx -s reload 的命令来手动完成。
不过要注意,所有引用了这个资源的 Pod,都会被更改。
二、什么是 Secret 以及它的作用
Secret 是一个将密码等敏感信息加密保存的资源。
Secret 的使用逻辑,和 ConfigMap 没什么区别,唯一不同的地方在于 Secret 的数据是被 base64 编码以后存放的。
Secret 有三种类型:
- TLS:专用于打包 SSl 中的证书和私钥,一般为 X509 格式的;而且不管之前证书和私钥的文件叫什么名字,都会被统一保存为
tls.crt 和 tls.key;
- generic:保存非 TLS 类型的普通类型的敏感信息,比如 MySQL 的管理员密码;该类型创建后会显示为 Opaque 类型,因为 k8s 将内容使用 base64 编码加密存储,不过可以通过
base64 --decode 解码获得原始数据,因此安全性弱。
- docker-registry:使被调度的目标节点上的 kubelet 进程,在加载私有仓库中的镜像时,能认证到私有仓库服务器上。
generic 的使用示例
创建一个 MySQL 的 root 密码的 Secret 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ~]# kubectl create secret generic mysql-root-password -n config --from-literal=password=monster
~]# kubectl get secret mysql-root-password -n config -o yaml apiVersion: v1 data: password: bW9uc3Rlcg== kind: Secret metadata: creationTimestamp: "2019-11-14T08:44:10Z" name: mysql-root-password namespace: config resourceVersion: "416363" selfLink: /api/v1/namespaces/config/secrets/mysql-root-password uid: fb06f569-3a73-4dfd-a4b5-7d3ee03a7e3f type: Opaque
|
创建 MySQL 的 Pod,并引用 Secret。
MySQL 的镜像初始化时必须传递一个变量 MYSQL_ROOT_PASSWORD 来配置数据库密码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| apiVersion: v1 kind: Pod metadata: name: mysql-secret namespace: config spec: containers: - name: mysql image: mysql:5.6 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-root-password key: password
-> pod/mysql-secret created
|
创建后连入 Pod 的交互式接口,使用刚才定义的 MySQL 密码 monster 测试能否登录:
1 2
| ~]# kubectl exec -it -n config mysql-secret -- /bin/sh # mysql -pmonster
|
查看环境变量应该也可以看到相关的配置:
TLS 的使用示例
创建证书
1 2 3
| ~]# openssl genrsa -out myapp.key 2048
~]# openssl req -new -x509 -key myapp.key -out myapp.crt -subj /C=CN/ST=Beijing/L=Beijing/O=Ops/CN=tls.com -days 365
|
导入证书到 k8s:
1
| ~]# kubectl create secret tls tls-cert --cert=myapp.crt --key=myapp.key
|
在 Ingress 中引用 TLS 的方法
创建一个新的 Ingress Controller,使用刚刚创建的证书:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ~]# vim myapp-tls-ingress.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: myapp-tls namespace: config annotations: kubernetes.io/ingress.class: "nginx" spec: tls: - hosts: - tls.com secretName: tls-cert rules: - host: tls.monster.com http: paths: - path: / backend: serviceName: myapp servicePort: 80
|
在 Pod 中使用存储卷引用 TLS 证书的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| apiVersion: v1 kind: Pod metadata: name: config spec: containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: config mountPath: /etc/nginx/conf.d/ - name: tls mountPath: /etc/nginx/certs/ volumes: - name: config configMap: name: nginx-cfg items: - key: server1.conf path: server-monster.com - key: server-ilinux.conf path: server-ilinux.conf - name: tls secret: secretName: mysql-cert items: - key: tls.crt path: myapp.crt - key: tls.key path: myapp.key mode: 0600
|