目录
ConfigMap
名词解释
ConfigMap创建
ConfigMap使用
用作环境变量
用作命令行参数
使用volume将ConfigMap作为文件或目录直接挂载
Secret
名词解释
创建自己的Secret
使用 kubectl 创建 Secret
手动创建 Secret
解码 Secret
使用 Secret
在 Pod 中使用 Secret 文件
Secret 作为环境变量
消费环境变量里的 Secret 值
Secret 与 Pod 生命周期的联系
使用案例
使用案例:包含 ssh 密钥的 pod
使用案例:包含 prod/test 凭据的 pod
使用案例:secret 卷中以点号开头的文件
ConfigMap
名词解释
ConfigMap是一种快捷的修改容器内变量的方式,由k-v组成,用于保存配置数据的键值对,当修改configmap时,容器中的变量也会相应修改。
ConfigMap可以用来保存单个属性,也可以用来保存配置文件,它跟secret很类似,但它可以更方便地处理不包含敏感信息的字符串。
ConfigMap创建
可以使用kubectl create configmap从文件、目录或者key-value字符串创建等创建ConfigMap。
折叠源码
# 从key-value字符串创建ConfigMap $ kubectl create configmap special-config --from-literal=special.how=very configmap "special-config" created $ kubectl get configmap special-config -o go-template= '{{.data}}' map[special.how:very] # 从env文件创建 $ echo -e "a=b\nc=d" | tee config. env a=b c=d $ kubectl create configmap special-config --from- env - file =config. env configmap "special-config" created $ kubectl get configmap special-config -o go-template= '{{.data}}' map[a:b c:d] # 从目录创建 $ mkdir config $ echo a>config /a $ echo b>config /b $ kubectl create configmap special-config --from- file =config/ configmap "special-config" created $ kubectl get configmap special-config -o go-template= '{{.data}}' map[a:a b:b ] |
ConfigMap使用
ConfigMap可以通过多种方式在Pod中使用,比如设置环境变量、设置容器命令行参数、在Volume中创建配置文件等。
注意
- ConfigMap必须在Pod引用它之前创建
- 使用envFrom时,将会自动忽略无效的键
- Pod只能使用同一个命名空间内的ConfigMap
用作环境变量
首先创建ConfigMap:
$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special. type =charm $ kubectl create configmap env -config --from-literal=log_level=INFO |
然后以环境变量方式引用
折叠源码
apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - name : test-container image: harbor.k2software.com.cn/library/busybox : latest command: [ "/bin/sh" , "-c" , "env" ] env: - name : SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name : SPECIAL_TYPE_KEY valueFrom: configMapKeyRef: name: special-config key: special.type envFrom: - configMapRef : name: env-config restartPolicy: Never |
当pod运行结束后,它的输出会包括
SPECIAL_LEVEL_KEY=very SPECIAL_TYPE_KEY=charm log_level=INFO |
用作命令行参数
将ConfigMap用作命令行参数时,需要先把ConfigMap的数据保存在环境变量中,然后通过$(VAR_NAME)的方式引用环境变量.
折叠源码
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name : test-container image: harbor.k2software.com.cn/library/busybox : latest command: [ "/bin/sh" , "-c" , "while true; do echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY); sleep 2; done" ] env: - name : SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name : SPECIAL_TYPE_KEY valueFrom: configMapKeyRef: name: special-config key: special.type restartPolicy: Never |
当Pod结束后会输出
使用volume将ConfigMap作为文件或目录直接挂载
将创建的ConfigMap直接挂载至Pod的/etc/config目录下,其中每一个key-value键值对都会生成一个文件,key为文件名,value为内容
折叠源码
apiVersion: v1 kind: Pod metadata: name: vol-test-pod spec: containers: - name : test-container image: harbor.k2software.com.cn/library/busybox : latest command: [ "/bin/sh" , "-c" , "cat /etc/config/special.how" ] volumeMounts: - name : config-volume mountPath: /etc/config volumes: - name : config-volume configMap: name: special-config restartPolicy: Never |
当Pod结束后会输出
将创建的ConfigMap中special.how这个key挂载到/etc/config目录下的一个相对路径/keys/special.level。如果存在同名文件,直接覆盖。其他的key不挂载
折叠源码
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name : test-container image: harbor.k2software.com.cn/library/busybox : latest command: [ "/bin/sh" , "-c" , "cat /etc/config/keys/special.level" ] volumeMounts: - name : config-volume mountPath: /etc/config volumes: - name : config-volume configMap: name: special-config items: - key : special.how path: keys/special.level restartPolicy: Never |
当Pod结束后会输出
Secret
名词解释
Secret是用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。
用户可以创建自己的secret,系统也会有自己的secret。Pod需要先引用才能使用某个secret,Pod有2种方式来使用secret:作为volume的一个域被一个或多个容器挂载;在拉取镜像的时候被kubelet引用。
Secret有以下几种类型:
- Service Account:用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的
/run/secrets/kubernetes.io/serviceaccount
目录中; - Opaque:base64编码格式的Secret,用来存储密码、密钥等;
- kubernetes.io/tls:从本地文件生成机密;
kubernetes.io/dockerconfigjson
:用来存储私有docker registry的认证信息。
创建自己的Secret
使用 kubectl 创建 Secret
假设有些 pod 需要访问数据库。这些 pod 需要使用的用户名和密码在您本地机器的 ./username.txt
和 ./password.txt
文件里。
# Create files needed for rest of example. $ echo -n "admin" > . /username .txt $ echo -n "K2pass!!" > . /password .txt |
kubectl create secret
命令将这些文件打包到一个 Secret 中并在 API server 中创建了一个对象。
$ kubectl create secret generic db-user-pass --from- file =. /username .txt --from- file =. /password .txt secret "db-user-pass" created |
您可以这样检查刚创建的 secret:
$ kubectl get secrets NAME TYPE DATA AGE db-user-pass Opaque 2 51s $ kubectl describe secrets /db-user-pass Name: db-user-pass Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password.txt: 12 bytes username.txt: 5 bytes |
请注意,默认情况下,get
和 describe
命令都不会显示文件的内容。这是为了防止将 secret 中的内容被意外暴露给从终端日志记录中刻意寻找它们的人。
手动创建 Secret
您也可以先以 json 或 yaml 格式在文件中创建一个 secret 对象,然后创建该对象。
每一项必须是 base64 编码:
$ echo -n "admin" | base64 YWRtaW4= $ echo -n "K2pass!!" | base64 SzJwYXNzISE= |
现在可以像这样写一个 secret 对象:
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4= password: SzJwYXNzISE= |
使用 kubectl create
创建 secret:
$ kubectl create -f . /secret .yaml secret "mysecret" created |
解码 Secret
可以使用 kubectl get secret
命令获取 secret。例如,获取在上一节中创建的 secret:
$ kubectl get secret mysecret -o yaml apiVersion: v1 data: username: YWRtaW4= password: SzJwYXNzISE= kind: Secret metadata: creationTimestamp: 2016-01-22T18 : 41 : 56Z name: mysecret namespace: default resourceVersion: "164619" selfLink: /api/v1/namespaces/default/secrets/mysecret uid: cfee02d6-c137-11e5-8d73-42010af00002 type: Opaque |
base64解码:
$ echo "SzJwYXNzISE=" | base64 --decode K2pass!! |
使用 Secret
Secret 可以作为数据卷被挂载,或作为环境变量暴露出来以供 pod 中的容器使用。它们也可以被系统的其他部分使用,而不直接暴露在 pod 内。例如,它们可以保存凭据,系统的其他部分应该用它来代表您与外部系统进行交互。
在 Pod 中使用 Secret 文件
在 Pod 中的 volume 里使用 Secret:
- 创建一个 secret 或者使用已有的 secret。多个 pod 可以引用同一个 secret。
- 修改您的 pod 的定义在
spec.volumes[]
下增加一个 volume。可以给这个 volume 随意命名,它的 spec.volumes[].secret.secretName
必须等于 secret 对象的名字。 - 将
spec.containers[].volumeMounts[]
加到需要用到该 secret 的容器中。指定 spec.containers[].volumeMounts[].readOnly = true
和 spec.containers[].volumeMounts[].mountPath
为您想要该 secret 出现的尚未使用的目录。 - 修改您的镜像并且/或者命令行让程序从该目录下寻找文件。Secret 的
data
映射中的每一个键都成为了 mountPath
下的一个文件名。
这是一个在 pod 中使用 volume 挂在 secret 的例子:
折叠源码
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name : mypod image: redis volumeMounts: - name : foo mountPath: "/etc/foo" readOnly: true volumes: - name : foo secret: secretName: mysecret |
您想要用的每个 secret 都需要在 spec.volumes
中指明。
如果 pod 中有多个容器,每个容器都需要自己的 volumeMounts
配置块,但是每个 secret 只需要一个 spec.volumes
。
您可以打包多个文件到一个 secret 中,或者使用的多个 secret,怎样方便就怎样来。
向特性路径映射 secret 密钥
我们还可以控制 Secret key 映射在 volume 中的路径。您可以使用 spec.volumes[].secret.items
字段修改每个 key 的目标路径:
折叠源码
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name : mypod image: redis volumeMounts: - name : foo mountPath: "/etc/foo" readOnly: true volumes: - name : foo secret: secretName: mysecret items: - key : username path: my-group/my-username |
将会发生什么呢:
username
secret 存储在 /etc/foo/my-group/my-username
文件中而不是 /etc/foo/username
中。password
secret 没有被影射
如果使用了 spec.volumes[].secret.items
,只有在 items
中指定的 key 被影射。要使用 secret 中所有的 key,所有这些都必须列在 items
字段中。所有列出的密钥必须存在于相应的 secret 中。否则,不会创建卷。
Secret 文件权限
您还可以指定 secret 将拥有的权限模式位文件。如果不指定,默认使用 0644
。您可以为整个保密卷指定默认模式,如果需要,可以覆盖每个密钥。
折叠源码
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name : mypod image: redis volumeMounts: - name : foo mountPath: "/etc/foo" volumes: - name : foo secret: secretName: mysecret defaultMode: 256 |
然后,secret 将被挂载到 /etc/foo
目录,所有通过该 secret volume 挂载创建的文件的权限都是 0400
。
请注意,JSON 规范不支持八进制符号,因此使用 256 值作为 0400 权限。如果您使用 yaml 而不是 json 作为 pod,则可以使用八进制符号以更自然的方式指定权限。
您还可以是用映射,如上一个示例,并为不同的文件指定不同的权限,如下所示:
折叠源码
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name : mypod image: redis volumeMounts: - name : foo mountPath: "/etc/foo" volumes: - name : foo secret: secretName: mysecret items: - key : username path: my-group/my-username mode: 511 |
在这种情况下,导致 /etc/foo/my-group/my-username
的文件的权限值为 0777
。由于 JSON 限制,必须以十进制格式指定模式。
请注意,如果稍后阅读此权限值可能会以十进制格式显示。
从 Volume 中消费 secret 值
在挂载的 secret volume 的容器内,secret key 将作为文件,并且 secret 的值使用 base-64 解码并存储在这些文件中。这是在上面的示例容器内执行的命令的结果:
$ ls /etc/foo/ username password $ cat /etc/foo/username admin $ cat /etc/foo/password K2pass!! |
被挂载的secret内容自动更新
也就是如果修改一个Secret的内容,那么挂载了该Secret的容器中也将会取到更新后的值,但是这个时间间隔是由kubelet的同步时间决定的。最长的时间将是一个同步周期加上缓存生命周期(period+ttl)
特例:以subPath形式挂载到容器中的secret将不会自动更新
Secret 作为环境变量
将 secret 作为 pod 中的环境变量使用:
- 创建一个 secret 或者使用一个已存在的 secret。多个 pod 可以引用同一个 secret。
- 在每个容器中修改您想要使用 secret key 的 Pod 定义,为要使用的每个 secret key 添加一个环境变量。消费secret key 的环境变量应填充 secret 的名称,并键入
env[].valueFrom.secretKeyRef
。 - 修改镜像并/或者命令行,以便程序在指定的环境变量中查找值。
折叠源码
apiVersion: v1 kind: Pod metadata: name: secret-env-pod spec: containers: - name : mycontainer image: redis env: - name : SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name : SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password restartPolicy: Never |
消费环境变量里的 Secret 值
在一个消耗环境变量 secret 的容器中,secret key 作为包含 secret 数据的 base-64 解码值的常规环境变量。这是从上面的示例在容器内执行的命令的结果:
$ echo $SECRET_USERNAME admin $ echo $SECRET_PASSWORD K2pass!! |
Secret 与 Pod 生命周期的联系
通过 API 创建的 Pod 时,不会检查应用的 secret 是否存在。一旦 Pod 被调度,kubelet 就会尝试获取该 secret 的值。如果获取不到该 secret,或者暂时无法与 API server 建立连接,kubelet 将会定期重试。Kubelet 将会报告关于 pod 的事件,并解释它无法启动的原因。一旦获取的 secret,kubelet将创建并装载一个包含它的卷。在安装所有pod的卷之前,都不会启动 pod 的容器。
使用案例
使用案例:包含 ssh 密钥的 pod
创建一个包含 ssh key 的 secret:
$ kubectl create secret generic ssh -key-secret --from- file = ssh -privatekey= /root/ . ssh /id_rsa --from- file = ssh -publickey= /root/ . ssh /id_rsa .pub |
安全性注意事项:发送自己的 ssh 密钥之前要仔细思考:集群的其他用户可能有权访问该密钥。使用您想要共享 Kubernetes 群集的所有用户可以访问的服务帐户,如果它们遭到入侵,可以撤销。
现在我们可以创建一个使用 ssh 密钥引用 secret 的pod,并在一个卷中使用它:
折叠源码
kind: Pod apiVersion: v1 metadata: name: secret-test-pod labels: name: secret-test spec: volumes: - name : secret-volume secret: secretName: ssh-key-secret containers: - name : ssh-test-container image: redis volumeMounts: - name : secret-volume readOnly: true mountPath: "/etc/secret-volume" |
当容器中的命令运行时,密钥的片段将可在以下目录:
/etc/secret-volume/ssh-publickey
/etc/secret-volume/ssh-privatekey
然后容器可以自由使用密钥数据建立一个 ssh 连接。
使用案例:包含 prod/test 凭据的 pod
下面的例子说明一个 pod 消费一个包含 prod 凭据的 secret,另一个 pod 使用测试环境凭据消费 secret。
创建 secret:
$ kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 secret "prod-db-secret" created $ kubectl create secret generic test -db-secret --from-literal=username=testuser --from-literal=password=iluvtests secret "test-db-secret" created |
创建 pod :
折叠源码
apiVersion: v1 kind: List items: - kind : Pod apiVersion: v1 metadata: name: prod-db-client-pod labels: name: prod-db-client spec: volumes: - name : secret-volume secret: secretName: prod-db-secret containers: - name : db-client-container image: redis volumeMounts: - name : secret-volume readOnly: true mountPath: "/etc/secret-volume" - kind : Pod apiVersion: v1 metadata: name: test-db-client-pod labels: name: test-db-client spec: volumes: - name : secret-volume secret: secretName: test-db-secret containers: - name : db-client-container image: redis volumeMounts: - name : secret-volume readOnly: true mountPath: "/etc/secret-volume" |
这两个容器将在其文件系统上显示以下文件,其中包含每个容器环境的值:
/etc/secret-volume/username
/etc/secret-volume/password
使用案例:secret 卷中以点号开头的文件
为了将数据“隐藏”起来(即文件名以点号开头的文件),简单地说让该键以一个点开始。例如,当如下 secret 被挂载到卷中:
折叠源码
kind: Secret apiVersion: v1 metadata: name: dotfile-secret data: .secret-file: dmFsdWUtMg0KDQo= --- kind: Pod apiVersion: v1 metadata: name: secret-dotfiles-pod spec: volumes: - name : secret-volume secret: secretName: dotfile-secret containers: - name : dotfile-test-container image: redis volumeMounts: - name : secret-volume readOnly: true mountPath: "/etc/secret-volume" |
Secret-volume
将包含一个单独的文件,叫做 .secret-file
,dotfile-test-container
的 /etc/secret-volume/.secret-file
路径下将有该文件。
注意:以点号开头的文件在 ls -l
的输出中被隐藏起来了;列出目录内容时,必须使用 ls -la
才能查看它们。
参考文档:
https://feisky.gitbooks.io/kubernetes/concepts/configmap.html
https://jimmysong.io/kubernetes-handbook/guide/secret-configuration.html