一、Configmap概述
1.1 什么是configmap
Configmap 是 k8s 中的资源对象,用于保存非机密性的配置的,数据可以用 key/value 键值对的形式保存,也可通过文件的形式保存。
1.2 Configmap能解决哪些问题?
我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个 服务:nginx、tomcat、apache 等,那么这些配置都存在这个节点上,假如一台服务 器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署 多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置, 如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改, 这种方式肯定满足不了线上大批量的配置变更要求。 所以,k8s 中引入了 Configmap 资源对象,可以当成 volume 挂载到 pod 中,实现统一的配置管理。
1、Configmap 是 k8s 中的资源, 相当于配置文件,可以有一个或者多个 Configmap; 2、Configmap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内 部指定目录上; 3、容器中应用程序按照原有方式读取容器特定目录上的配置文件。 4、在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。
1.3 configmap应用场景
1、使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像, configmap 可以将配置信息和 docker 镜像解耦,以便实现镜像的可移植性和可复用 性,因为一个 configMap 其实就是一系列配置信息的集合,可直接注入到 Pod 中给容 器使用。configmap 注入方式有两种,一种将 configMap 做为存储卷,一种是将 configMap 通过 env 中 configMapKeyRef 注入到容器中。
2、使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配 置的话,那么更新配置就很麻烦,使用 configmap 可以友好的进行配置共享。
1.4 configmap局限性
ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过 1 MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数 据库或者文件服务
1.5 configmap创建方法
# 1.命令行直接创建 # 直接在命令行中指定 configmap 参数创建,通过--from-literal 指定参数 kubectl create configmap --help [root@master ds]# kubectl create configmap tomcat-config --from-literal=tomcat_port=8080 --from-literal=server_name=myapp.tomcat.com configmap/tomcat-config created # kubectl get configmap [root@master ds]# kubectl get cs NAME DATA AGE calico-config 4 16d coredns 1 25d extension-apiserver-authentication 6 25d kube-proxy 2 25d kube-root-ca.crt 1 25d kubeadm-config 2 25d kubelet-config-1.20 1 25d metrics-server-config 1 16d tomcat-config 2 50s [root@master ds]# kubectl describe cm tomcat-config Name: tomcat-config Namespace: kube-system Labels: <none> Annotations: <none> Data ==== server_name: ---- myapp.tomcat.com tomcat_port: ---- 8080 Events: <none>
#2.通过文件创建 通过指定文件创建一个 configmap,--from-file=<文件> [root@master configmap]# kubectl create configmap www-nginx --from-file=www=./nginx.conf configmap/www-nginx created [root@master configmap]# kubectl describe cm www-nginx Name: www-nginx Namespace: kube-system Labels: <none> Annotations: <none> Data ==== www: ---- nginx.conf的内容 Events: <none> # 指定文件创建configmap [root@master configmap]# kubectl create configmap www-nginx-1 --from-file=./nginx.conf configmap/www-nginx-1 created
# 3.指定目录创建configmap mkdir /root/test-a cd /root/test-a [root@master test-a]# cat my-server.cnf server-id=1 [root@master test-a]# cat my-slave.cnf server-id=2 [root@master ~]# kubectl create configmap mysql-config --from-file=/root/test-a/ configmap/mysql-config created [root@master ~]# kubectl describe cm mysql-config Name: mysql-config Namespace: kube-system Labels: <none> Annotations: <none> Data ==== my-server.cnf: ---- server-id=1 my-slave.cnf: ---- server-id=2 Events: <none>
1.6 configmap资源清单编写技巧
[root@master ds]# kubectl explain configmap KIND: ConfigMap VERSION: v1 FIELDS: apiVersion <string> binaryData <map[string]string> data <map[string]string> immutable <boolean> kind <string> metadata <Object> [root@master configmap]# cat mysql-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: master.cnf: | # |表示有多行,下面按行分离 [mysqld] log-bin log_bin_trust_function_creators=1 lower_case_table_names=1 slave.cnf: | [mysqld] super-read-only log_bin_trust_function_creators=1
1.7 使用configmap
# 1.通过环境变量引入:使用 configMapKeyRef #创建一个存储 mysql 配置的 configmap [root@master configmap]# cat configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: log: "1" lower: "1" [root@master configmap]# kubectl apply -f configmap.yaml configmap/mysql created [root@master configmap]# kubectl get cm NAME DATA AGE mysql 2 11s # 创建pod,引入mysql [root@master configmap]# cat mysql-pod.yaml apiVersion: v1 kind: Pod metadata: name: mysql-pod namespace: default spec: containers: - name: mysql image: busybox imagePullPolicy: IfNotPresent command: [ "/bin/sh", "-c", "sleep 3600" ] env: - name: log_bin # 定义环境变量log_bin valueFrom: configMapKeyRef: name: mysql # 指定configmap名字 key: log # 指定configmap的key - name: lower valueFrom: configMapKeyRef: name: mysql key: lower restartPolicy: Never [root@master configmap]# kubectl apply -f mysql-pod.yaml pod/mysql-pod created [root@master configmap]# kubectl get pods NAME READY STATUS RESTARTS AGE mysql-pod 1/1 Running 0 7s [root@master configmap]# kubectl exec -it mysql-pod -c mysql -- /bin/sh / # printenv log_bin=1 KUBERNETES_SERVICE_PORT=443 KUBERNETES_PORT=tcp://10.96.0.1:443 METRICS_SERVER_PORT_443_TCP_ADDR=10.105.85.228 KUBE_DNS_SERVICE_PORT_DNS_TCP=53 HOSTNAME=mysql-pod METRICS_SERVER_PORT_443_TCP_PORT=443 SHLVL=1 METRICS_SERVER_PORT_443_TCP_PROTO=tcp HOME=/root SPRINGBOOT_SERVICE_PORT_SERVER=8080 KUBE_DNS_SERVICE_HOST=10.96.0.10 KUBE_DNS_PORT_9153_TCP_ADDR=10.96.0.10 KUBE_DNS_PORT_9153_TCP_PORT=9153 METRICS_SERVER_PORT_443_TCP=tcp://10.105.85.228:443 KUBE_DNS_PORT_9153_TCP_PROTO=tcp KUBE_DNS_PORT=udp://10.96.0.10:53 METRICS_SERVER_SERVICE_HOST=10.105.85.228 KUBE_DNS_SERVICE_PORT=53 TERM=xterm lower=1 KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 SPRINGBOOT_SERVICE_HOST=10.105.225.164 SPRINGBOOT_PORT_8080_TCP_ADDR=10.105.225.164 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin SPRINGBOOT_PORT_8081_TCP_ADDR=10.105.225.164 KUBE_DNS_PORT_53_TCP_ADDR=10.96.0.10 KUBERNETES_PORT_443_TCP_PORT=443 KUBE_DNS_SERVICE_PORT_METRICS=9153 SPRINGBOOT_PORT_8080_TCP_PORT=8080 METRICS_SERVER_SERVICE_PORT=443 METRICS_SERVER_PORT=tcp://10.105.85.228:443 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBE_DNS_PORT_9153_TCP=tcp://10.96.0.10:9153 KUBE_DNS_PORT_53_UDP_ADDR=10.96.0.10 SPRINGBOOT_PORT_8081_TCP_PORT=8081 SPRINGBOOT_PORT_8080_TCP_PROTO=tcp SPRINGBOOT_PORT_8081_TCP_PROTO=tcp KUBE_DNS_PORT_53_TCP_PORT=53 KUBE_DNS_PORT_53_TCP_PROTO=tcp KUBE_DNS_PORT_53_UDP_PORT=53 SPRINGBOOT_PORT=tcp://10.105.225.164:8080 SPRINGBOOT_SERVICE_PORT=8080 KUBE_DNS_SERVICE_PORT_DNS=53 KUBE_DNS_PORT_53_UDP_PROTO=udp KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 SPRINGBOOT_PORT_8080_TCP=tcp://10.105.225.164:8080 KUBERNETES_SERVICE_HOST=10.96.0.1 SPRINGBOOT_PORT_8081_TCP=tcp://10.105.225.164:8081 PWD=/ KUBE_DNS_PORT_53_TCP=tcp://10.96.0.10:53 KUBE_DNS_PORT_53_UDP=udp://10.96.0.10:53 SPRINGBOOT_SERVICE_PORT_MANAGEMENT=8081
# 2. 通过环境变量引入:使用envfrom [root@master configmap]# cat mysql-pod-envFrom.yaml apiVersion: v1 kind: Pod metadata: name: mysql-pod-envfrom spec: containers: - name: mysql image: busybox imagePullPolicy: IfNotPresent command: [ "/bin/sh", "-c", "sleep 3600" ] envFrom: - configMapRef: name: mysql restartPolicy: Never [root@master configmap]# kubectl exec -it mysql-pod-envfrom -- /bin/sh / # printenv lower=1 log=1
# 常用方式:把 configmap 做成 volume,挂载到 pod [root@master configmap]# cat configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: log: "1" lower: "1" my.cnf: | [mysqld] Welcome=cxiong [root@master configmap]# kubectl apply -f configmap.yaml configmap/mysql configured [root@master configmap]# kubectl describe cm mysql Name: mysql Namespace: kube-system Labels: app=mysql Annotations: <none> Data ==== log: ---- 1 lower: ---- 1 my.cnf: ---- [mysqld] Welcome=cxiong Events: <none> [root@master configmap]# cat mysql-pod-volume.yaml apiVersion: v1 kind: Pod metadata: name: mysql-pod-volume spec: containers: - name: mysql image: busybox imagePullPolicy: IfNotPresent command: [ "/bin/sh", "-c", "sleep 3600" ] volumeMounts: - name: mysql-config mountPath: /tmp/config volumes: - name: mysql-config configMap: name: mysql restartPolicy: Never [root@master configmap]# kubectl apply -f mysql-pod-volume.yaml pod/mysql-pod-volume created [root@master configmap]# kubectl exec -it mysql-pod-volume -c mysql -- /bin/sh / # cd /tmp/config /tmp/config # ls log lower my.cnf /tmp/config # cat log 1 /tmp/config # cat lower 1 /tmp/config # cat my.cnf [mysqld] Welcome=cxiong
1.8 configmap热更新
# 将log=1 改为log=2 [root@master configmap]# kubectl edit cm mysql configmap/mysql edited [root@master configmap]# kubectl exec -it mysql-pod-volume -c mysql -- /bin/sh / # cd /tmp/config /tmp/config # cat log 1 ... /tmp/config # cat log # 需要等一会才能生效 2 注意: 更新 ConfigMap 后: 使用该 ConfigMap 挂载的 Env 不会同步更新 :mysql-pod-envfrom中log还是1,也没有Welcome,不会随环境变量变化而变化,会随卷变化 使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概 10 秒)才能同步更新
二、Secret概述
2.1 secret是什么?
上面我们学习的 Configmap 一般是用来存放明文数据的,如配置文件;对于一些敏感数据,如密码、私钥等数据时,要用 secret 类型。
Secret 解决了密码、token、秘钥等敏感数据的配置问题,而不需要把这些敏感数据 暴露到镜像或者 Pod Spec 中。Secret 可以以 Volume 或者环境变量的方式使用。
要使用 secret,pod 需要引用 secret。Pod 可以用两种方式使用 secret:作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里,或者当 kubelet 为 pod 拉取 镜像时使用。
secret 可选参数有三种:
generic: 通用类型,通常用于存储密码数据。
tls:此类型仅用于存储私钥和证书。
docker-registry: 若要保存 docker 仓库的认证信息的话,就必须使用此种类型来创建。
Secret 类型:
Service Account:用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录 中。
Opaque:base64 编码格式的 Secret,用来存储密码、秘钥等。可以通过 base64 -- decode 解码获得原始数据,因此安全性弱
kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息。
2.2 使用secret
# 1.通过环境变量引入secret [root@master secret]# kubectl create secret generic mysql-password --from-literal=password=mysql**@123 secret/mysql-password created [root@master secret]# kubectl get secret | grep mysql-password mysql-password Opaque 1 19s [root@master secret]# kubectl describe secret mysql-password Name: mysql-password Namespace: kube-system Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 11 bytes #password 的值是加密的,
#但 secret 的加密是一种伪加密,它仅仅是将数据做了 base64 的编码.
[root@master secret]# cat pod-secret.yaml apiVersion: v1 kind: Pod metadata: name: pod-secret labels: app: myapp spec: containers: - name: myapp image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 env: - name: MYSQL_ROOT_PASSWORD #它是 Pod 启动成功后,Pod 中容器的环境变量名. valueFrom: secretKeyRef: name: mysql-password # secret对象名 key: password # secret中的key名 [root@master secret]# kubectl apply -f pod-secret.yaml pod/pod-secret created pod-secret 1/1 Running 0 16s [root@master secret]# kubectl exec -it pod-secret -c myapp -- /bin/sh / # printenv MYSQL_ROOT_PASSWORD=mysql**@123
#2.通过 volume 挂载 Secret #手动加密,基于 base64 加密 [root@master secret]# echo -n "admin" | base64 YWRtaW4= # 解密 [root@master secret]# echo YWRtaW4= | base64 -d admin [root@master configmap]# echo -n "mysql**@123" | base64 bXlzcWwqKkAxMjM= [root@master configmap]# echo -n "mysql" | base64 bXlzcWw= [root@master secret]# kubectl apply -f secret.yaml secret/mysecret created [root@master secret]# kubectl get secret | grep mysecret mysecret Opaque 2 15s [root@master secret]# kubectl describe secret mysecret Name: mysecret Namespace: kube-system Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 11 bytes username: 5 bytes [root@master secret]# cat pod-secret-volume.yaml apiVersion: v1 kind: Pod metadata: name: pod-secret-volume spec: containers: - name: myapp image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1 imagePullPolicy: IfNotPresent volumeMounts: - name: secret-volume mountPath: /etc/secret readOnly: true volumes: - name: secret-volume secret: secretName: mysecret [root@master secret]# kubectl apply -f pod-secret-volume.yaml pod/pod-secret-volume created pod-secret-volume 1/1 Running 0 50s [root@master secret]# kubectl exec -it pod-secret-volume -c myapp -- /bin/sh / # cd /etc/secret /etc/secret # ls password username /etc/secret # cat password mysql**@123 /etc/secret # cat username mysql