kubernetes之ConfigMap and Secret

目录

 

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结束后会输出

very charm

使用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结束后会输出

very

将创建的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结束后会输出

very

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:

  1. 创建一个 secret 或者使用已有的 secret。多个 pod 可以引用同一个 secret。
  2. 修改您的 pod 的定义在 spec.volumes[] 下增加一个 volume。可以给这个 volume 随意命名,它的 spec.volumes[].secret.secretName 必须等于 secret 对象的名字。
  3. 将 spec.containers[].volumeMounts[] 加到需要用到该 secret 的容器中。指定 spec.containers[].volumeMounts[].readOnly = true 和 spec.containers[].volumeMounts[].mountPath 为您想要该 secret 出现的尚未使用的目录。
  4. 修改您的镜像并且/或者命令行让程序从该目录下寻找文件。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 中的环境变量使用:

  1. 创建一个 secret 或者使用一个已存在的 secret。多个 pod 可以引用同一个 secret。
  2. 在每个容器中修改您想要使用 secret key 的 Pod 定义,为要使用的每个 secret key 添加一个环境变量。消费secret key 的环境变量应填充 secret 的名称,并键入 env[].valueFrom.secretKeyRef
  3. 修改镜像并/或者命令行,以便程序在指定的环境变量中查找值。

 折叠源码

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-filedotfile-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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值