ConfigMap和Secret是Kubernetes系统上两种特殊类型的存储卷,ConfigMap对象用于为容器中的应用提供配置数据,Secret对象则用于提供密钥、证书等敏感的配置信息。它们将相应的配置信息保存于对象中,而后在Pod资源上以存储卷的形式将其挂载并获取相关的配置,以实现配置与镜像文件的解耦。
ConfigMap
配置本身源于代码,是为了提高代码的灵活性而提取出来的一些经常变化的或需要定制的内容。已有一些开源的分布式系统配置管理系统如Apollo、Diamond、Disconf等。ConfigMap则是Kubernetes提供的统一配置管理方案,一个ConfigMap对象就是一系列配置数据的集合,这些数据可“注入”到Pod对象中,并为容器应用所使用,注入方式有两种
- 挂载为存储卷
- 传递为环境变量
创建ConfigMap对象
ConfigMap对象将配置数据以键值对的形式进行存储,可以使用kubectl create命令创建
kubectl create configmap <map-name> <data-source>
map-name为ConfigMap对象的名称,而data-source是数据源,它可以通过这几种方式来获取
- 字面值
- 文件
- 目录
- 配置清单
无论采用哪一种方式,都要被转换为ConfigMap对象中的Key-Value数据。
基于字面值创建
使用--from-literal
选项可在命令行直接提供键值对:
kubectl create configmap literal-config --from-literal=key1=value1
创建后可以使用kubectl get configmaps dir-config -o yaml
命令查看。
基于文件创建
基于文件创建时要使用--from-file
选项:
kubectl create configmap file-config --from-file=8_config_file.txt
这种方式创建的ConfigMap对象,其数据存储的键为文件名,值为文件内容
apiVersion: v1
data:
8_config_file.txt: |-
test
config
from
file
kind: ConfigMap
自定义键名的方式:
kubectl create configmap file-config --from-file=file-key1=8_config_file.txt
基于目录创建
使用--from-file
选项时,如果指定的是文件目录,kubectl会将目录下的文件分别创建为键值数据。
kubectl create configmap dir-config --from-file=.
使用配置清单创建
配置清单需要指定apiVersion、kind、metadata、data字段,data字段用于存储键值数据:
apiVersion: v1
kind: ConfigMap
metadata:
name: yaml-config
data:
key1: value1
key2: value2
通过环境变量传递ConfigMap数据
ConfigMap是名称空间级别的资源,它必须与引用它的Pod资源在同一空间中;
通过环境变量传递ConfigMap的格式为:
env:
- name: <env-name>
valueFrom:
configMapKeyRef:
name: <configmap-name>
key: <key-name>
optional: <bool>
如果optional指定为false,则创建引用了ConfigMap资源的Pod对象时,被引用的资源必须事先存在,否则将无法启动容器,直到被依赖的资源创建完成为止。
示例:
apiVersion: v1
kind: Pod
metadata:
name: env-test-pod
labels:
app: label-env-test-pod
spec:
containers:
- name: env-test-container
image: busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: MY_KEY1
valueFrom:
configMapKeyRef:
name: yaml-config
key: key3
optional: true
- name: MY_KEY2
valueFrom:
configMapKeyRef:
name: yaml-config
key: key4
optional: true
envFrom
有时容器需要引用很多ConfigMap资源中的键值数据,这种情况下如果为容器逐一配置环境变量会非常繁琐,而且不好维护。使用envFrom字段可以直接将ConfigMap资源中的所有键值一次性导入。格式为:
envFrom:
- prefix: <prefix>
configMapRef:
name: <configmap-name>
optional: <bool>
通过ConfigMap存储卷传递数据
如果在ConfigMap中的值体积较大,比如存放的是给容器应用提供的配置文件,那么使用环境变量将其导入会使得变量值占据过多的内存空间而且不易处理。这时建议通过ConfigMap存储卷的方式可以将内容直接作为文件进行引用。
挂载整个存储卷
关联为Pod资源的存储卷时,ConfigMap对象中的每个键都对应地表现为一个文件,键名为文件名
apiVersion: v1
kind: Pod
metadata:
name: configmap-vol
labels:
app: configmap-vol
spec:
containers:
- name: configmap-vol
image: busybox
command: ["/bin/sh", "-c", "sleep 3600"]
volumeMounts:
- name: config-vol
mountPath: /etc/test
readOnly: true
volumes:
- name: config-vol
configMap:
name: file-config
挂载后可以将键名作为文件名来查看内容:
kubectl exec configmap-vol -- cat /etc/test/file-key1
挂载存储卷中的部分键值
有时并不希望挂载ConfigMap中的所有内容,可以只挂载存储卷中的部分键值。
格式为:
volumes:
- name: config-vol
configMap:
name: file-config
items:
- key: file-key1
path: file-key1
Secret
Secret资源的功能类似于ConfigMap,但它专用于存放敏感数据,例如密码、数字证书、私钥、令牌和SSH key等。
与ConfigMap类似,Secret以键值方式存储数据,在Pod资源中通过环境变量或存储卷进行数据访问。
Secret对象的数据的存储及打印格式为Base64编码的字符串,在容器中以环境变量或存储卷的方式访问时,它们会被自动解码为明文格式。
Secret对象主要有两种用途:
- 作为存储卷注入到Pod上由容器应用程序所使用
- 用于kubelet为Pod里的容器拉取镜像时向私有仓库提供认证信息
Secret资源分为四种类型:
- Opaque:自定义数据内容;base64编码,用来存储密码、密钥、信息、证书等数据,类型标识符为generic。
- kubernetes.io/service-account-token:Service Account的认证信息,可在创建Service Accout时由Kubernetes自动创建。
- kubernetes.io/dockerconfigjson:用来存储Docker镜像仓库的认证信息,类型标识为docker-registry。
- kubernetes.io/tls:用于为SSL通信模式存储证书和私钥文件,命令式创建时类型标识为tls。
创建Secret资源
命令式创建
直接使用字面值创建:
kubectl create secret generic mysql-auth --from-literal=username=root --from-literal=password=password1
查看base64编码后的内容:
✗ kubectl get secret mysql-auth -o yaml
apiVersion: v1
data:
password: cGFzc3dvcmQx
username: cm9vdA==
使用generic
标识创建的Secret为Opaque类型。下面的示例使用了tls
标识来创建tls类型的Secret:
kubectl create secret tls nginx-ssl --key=./nginx.key --cert=./nginx.crt
创建成功后名称固定为tls.key和tls.crt,不受证书和私钥文件的名称的影响。
基于配置清单创建
基于配置清单创建的示例:
apiVersion: v1
kind: Secret
metadata:
name: yaml-secret
stringData:
username: redis
password: password1
type: Opaqu
这里使用了stringData,可以用明文的形式设置secret数据,然后在创建为Secret对象时会自动进行Base64编码并保存于data字段中;stringData字段中的明文不会被API Server输出,但如果使用“kubectl apply”命令进行的创建,那么注解信息中还是可以看到明文信息的。如果用data字段,则必须直接提供Base64编码后的数据。
Secret存储卷
虽然Secret数据也可以痛殴环境变量注入,但并不推荐这样做,因为容器应用通常会在发生错误时将所有环境变量保存于日志信息中,甚至有些应用在启动时即会将运行环境打印到日志中;另外,容器应用调用第三方程序为子进程时,这些子进程能够继承并使用父进程的所有环境变量。
所以建议使用Secret存储卷来传递数据,使用方式与configMap基本相同,但字段为secret和secretName:
volumes:
- name: secret-vol
secret:
secretName: yaml-secret
items:
- key: username
path: username
- key: password
path: password
imagePullSecret资源对象
imagePullSecret资源可用于将Secret提供的密码传递给kubelet从而在拉取镜像前完成认证。
创建imagePullSecret的标识为docker-registry,有两种使用方式:
- 在定义Pod资源时通过“imagePullSecrets”字段指定
- 将其添加到某特定的ServiceAccount对象中
采用第一张方式,创建docker-registry:
kubectl create secret docker-registry local-registry --docker-username=user1 --docker-password=password1
然后在创建Pod的配置清单中,通过spec.imagePullSecrets字段为kubelet提供Secret信息:
spec:
imagePullSecrets:
- name: local-registry
但这种方式需要为每个Pod资源显式定义imagePullSecrets,基于ServiceAccount的的方式可以避免这个问题,后续再做详细了解。
学习资料
《Kubernetes实战进阶》 马永亮著