k8s ConfigMap & Secret
一、ConfigMap
ConfigMap中包含了Map单词(Map其实就是key:value),主要是管理一些可变配置信息,如应用的配置文件、应用里面的环境变量、命令行参数。它可以让一些可变配置和容器进行解耦,保证了容器的可移植性。
kubectl命令创建ConfigMap时,可以指定文件、指定目录或直接指定键值对。
指定文件和目录的命令如下:
kubectl create configmap XXX --from-file=XXX -n kube-system
若指定的是文件,文件名就是Map中的key,文件内容就是Map中的value。
若指定的是目录,目录中的每个配置文件名都被会被设置为key。
直接指定键值对的命令如下:
kubectl create configmap XXX --from-literal=key=value --from-literal=key=value
指定的数据键值对,会直接映射到Map的key:value
被创建的ConfigMap除了apiVersion、kind、metadata外,还包括data部分
以下面的配置清单为例,可以看到它管理了两个直接指定的键值对和一个配置文件
kind: ConfigMap
apiVersion: v1
metadata:
name: five-nginx
namespace: default
data:
example.property.1: hello
example.property.2: world
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
Pod里使用ConfigMap有以下几种方式:
(1)填充环境变量。
通过configMapKeyRef指定ConfigMapKeySelector
ConfigMapKeyRef字段中,name是指定ConfigMap名,key是ConfigMap.data里面的key。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: example-config # 需使用的ConfigMap名称,必须已存在
key: example.property.1 # 对应ConfigMap data的key
restartPolicy: Never
(2)通过Volume挂载的方式将ConfigMap里的内容直接挂到容器的某一个目录下面去:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh","-c","ls -l /etc/config/path/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: example-config
restartPolicy: Never
创建的文件可以通过defaultMode指定默认文件权限,注意:由于json文件不支持八进制,使用时应使用十进制
直接指定的键值对,创建的文件名为key、文件内容就是value;配置文件则原样不变。
若ConfigMap中有多个文件::
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cfgmap
data:
app.conf: file data
......
只想把其中一个文件从ConfigMap挂载到Pod,可以通过subPath的方式,具体配置有两种方法:
(1)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
(2)这种方式使用ConfigMap,就不再要求ConfigMap中的key跟挂载的文件名必须一致,但需要在items指定key和path对应关系:
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 # 指定Configmap中的文件对应的key
path: app.conf # 指定生成的配置文件名称
二、Secret
Secret是一个主要用来存储敏感信息的资源对象。采用base-64编码保存。
Secret的创建:
- 系统创建:比如k8s为每一个namespace的默认用户(default ServiceAccount)创建 Secret,名称为default-token-xxxxx
- 用户手动创建:使用kubectl命令行工具时,data参数的写法与ConfigMap一致,相对ConfigMap会多一个 type 参数,不指定的话默认是Opaque类型。
kubectl create secret generic xxx —from-file=xxx —type=kubernetes.io/dockerconfigjson
kubectl create secret generic xxx —from-literal=key=value —from-literal=key=value
被创建的Secret除了apiVersion、kind、metadata外,还增加了type字段,指出Secret的类型,包括:
- Opaque:普通的Secret文件,
- kubernetes.io/service-account-token:是用于service-account身份认证用的Secret
- kubernetes.io/dockerconfigjson:拉取私有仓库镜像的用的Secret
- kubernetes.io/bootstrap.token:用于节点接入集群校验用的Secret
它和ConfigMap一样也有data字段,是存储的Secret的数据,它也是key-value的形式存储的。
apiVersion: v1
kind: Secret
metadata:
name: example-secret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
Pod里使用Secret有以下几种方式:
(1)填充环境变量。
通过secretKeyRef指定SecretKeySelector
(2)通过volume挂载的方式直接把Secret中的内容挂到容器的某一个目录下
k8s会自动把default-token-xxxxx挂载到容器 /var/run/secrets/kubernetes.io/serviceaccount目录下。该secret包括三个文件:ca.crt、namespace(空文件)、token,它们保存了认证相关信息
(3)拉取镜像文件。
通过命令创建:
kubectl create secret docker-registry ${secret_name} --docker-server=xxx --docker-username=xxx --docker-password=Axxx -n xxx
将私有镜像仓库的信息存储在Secret里面
apiVersion: v1
kind: Secret
metadata:
name: image-test-secret
namespace: default
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: xxxxxxx
加密部分的明文为:
{
"auths": {
"xxx": {
"username": "xxxxx",
"password": "xxxxx",
"auth": "xxxxxxxxx"
}
}
}
其中auth部分的密文是username:passward的base64结果
Pod通过Pod.spec.impagePullSecrets字段使用该Secret:
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: default
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: image-test-secret
此外,还可以提前在Pod会使用的serviceaccount里配置imagePullSecrets:
kubectl -n css patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-css-user"}]}'
Pod创建时系统会自动注入此Secret。
三、注意要点
Secret注意要点
Secret采用了base-64编码,安全程度不高。推荐可以使用开源的vault来解决敏感信息的加密和权限管理。
Secret读取不要用list/watch,否则会把namespace下的所有Secret全部拉取下来。推荐使用get,只获取需要的那个Secret。
共通的注意要点
虽然ConfigMap/Secret文件没有大小限制。但是在Etcd里面数据的写入是有大小限制的,现在是限制在1MB以内;
只有通过apiserver创建的Pod才能使用ConfigMap/Secret,kubelet通过manifest创建的static Pod不能使用。
把ConfigMap/Secret里面所有的信息导入成环境变量时,如果有些key是无效的(比如key里带有数字),那么这个环境变量会直接被忽略,不会注入容器,但是这个Pod本身是可以创建的。
ConfigMap/Secret具有热更新能力,但只有整个作为Volume挂载到容器中的时候,才能热更新。通过环境变量、通过subPath挂载都不行。Pod内感知到Volume更新的时间与kubelet的--sync-frequency配置有关。
参考资料: