5 min read

ConfigMap与Secret详解

ConfigMap与Secret详解

1. ConfigMap 概述

应用程序运行时需要依赖一些相关的配置,而这些配置通常会随着开发不断产生变化,为了处理这些变化,因此一般的应用程序设计都会将配置和程序分离。ConfigMap可以很好的帮助在kubernetes部署的程序读取这些配置,实现配置和程序分离的目的,避免因为需要修改配置而重新构建镜像。

ConfigMap使用场景:

  • 生成为容器内的环境变量;
  • 设置容器启动命令的启动参数(需设置为环境变量);
  • 以Volume的形式挂载为容器内部的文件或目录。
  • 使用Kubernetes API 读取 ConfigMap

configMap 默认不提供加密功能,因此不能存储机密数据

configMap 作用的对象一般为 Pod 但也可以是 k8s 的其他组件

2. ConfigMap 使用

2.1 挂载卷使用ConfigMap

  1. 多个pod可以使用同一个ConfigMap
  2. 向需要的每个容器添加ConfigMap卷
  3. 挂载卷的时候需要设置readOnly=True,并列出挂载目录
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    configMap:
      name: myconfigmap

注意静态pod的spec文件无法引用ConfigMap或其他API对象

2.2 热更新的ConfigMap

在卷中使用的ConfigMap更新时,ConfigMap在容器内也会进行更新。kubelet 会定期检查挂载的ConfigMap是否是最新的,但是默认情况下kubelet 会使用本地缓存获取ConfigMap的值。默认情况可以通过修改kubelet配置文件中 ConfigMapAndSecretChangeDetectionStrategy 的值来设置每次向k8s fetch 最新的值,还是使用TTL缓存,或者采用Watch机制。可以简单认为ConfigMap 到投射到所有的Pod中是存在一个总的时延。

注意作为环境变量使用的ConfigMap不会自动更新,需要对使用的Pod进行重启

2.3 不可变的ConfigMap

1.19 开始可以通过配置设定ConfigMap不可变

apiVersion: v1
kind: ConfigMap
metadata:
  ...
data:
  ...
immutable: true

3. Secret 概述

Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象[1]。Secret 可以被Pod使用从而使上层应用无需包含敏感数据。

注意事项:
1 默认情况下,Secrete 不加密的存储在API Server的数据库etcd中,任何拥有API访问权限或数据库访问权限的人都可以检索和修改Secret。任何有权限在命名空间中创建pod的敌手也可以使用该访问权限读取该命名空间中的任何Secret。
2 安全的使用Secret:

Secret 开启静态加密
启用RBAC规则来限制Secret读取方式(包括直接读取、间接读取方式)
使用RBAC机制来限制创建Secret和替换Secret功能的使用

4. Secret 使用

Pod引用Secret主要存在三种方法:

  1. 作为挂载到一个或多个容器上的 卷 中的文件。通过卷挂载的 secret 是存储在内存上的而非在磁盘上进行持久化,因此不容易通过磁盘进行窃取
  2. 作为容器的环境变量
  3. 由 kubelet 在为 Pod 拉取镜像时使用

4.1 Secret类型

secret 包含3种类型分别是

  1. Opaque Secret 使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱
  2. kubernetes.io/dockerconfigjson :用于存储docker registry的认证信息
  3. kubernetes.io/service-account-token 通过 service account 自动创建和绑定。 Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。这种情况下创建的secret 一般包含 ca.crt 、namespace 和一个 token。

自定义的 secret 也可以包含一些必要的文件或添加文件夹下所有的文件,也可以添加一部分自定义的项(因为是base64编码因此可以包含一些二进制项,也可以通过stringData 创建一些非base64编码的明文项),要注意以下两点:

  1. secret大小限制为 1MB
  2. 注意 Secret 对象名称必须包含合法的DNS子域名。

4.2 引导令牌Secret

引导令牌Secret 是一种持有者令牌( Bearer Token ),这种 Secret 会被 API 服务器上的启动引导认证组件读取,并做相应的身份认证。

apiVersion: v1
kind: Secret
metadata:
  # name 必须是 "bootstrap-token-<token id>" 格式的
  name: bootstrap-token-07401b
  namespace: kube-system

# type 必须是 'bootstrap.kubernetes.io/token'
type: bootstrap.kubernetes.io/token
stringData:
  # 供人阅读的描述,可选。
  description: "The default bootstrap token generated by 'kubeadm init'."

  # 令牌 ID 和秘密信息,必需。
  token-id: 07401b
  token-secret: base64(f395accd246ae52d)

  # 可选的过期时间字段
  expiration: "2017-03-10T03:22:11Z"
  # 允许的用法
  usage-bootstrap-authentication: "true"
  usage-bootstrap-signing: "true"

  # 令牌要认证为的额外组,必须以 "system:bootstrappers:" 开头
  auth-extra-groups: system:bootstrappers:worker,system:bootstrappers:ingress

5. Secret 静态加密

5.1 配置静态加密

kube-apiserver 的参数 --experimental-encryption-provider-config 开启和关闭在数据库中的加密方式,并创建 EncryptionConfiguration 资源如下:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  # resources.resources 字段是要加密的 Kubernetes 资源名称(resource 或 resource.group)的数组
  - resources:
    - secrets
    # providers 数组是可能的加密 provider 的有序列表
    providers:
      # provider 具体类型解析见[2]
    - identity: {}
    - aesgcm:
        keys:
        - name: key1
          secret: c2VjcmV0IGlzIHNlY3VyZQ==
        - name: key2
          secret: dGhpcyBpcyBwYXNzd29yZA==
    - aescbc:
        keys:
        - name: key1
          secret: c2VjcmV0IGlzIHNlY3VyZQ==
        - name: key2
          secret: dGhpcyBpcyBwYXNzd29yZA==
    - secretbox:
        keys:
        - name: key1
          secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=

6 参考

[1] https://kubernetes.io/zh/docs/concepts/configuration/secret/
[2] https://kubernetes.io/zh/docs/tasks/administer-cluster/encrypt-data/
[3] https://kubernetes.io/zh/docs/reference/access-authn-authz/bootstrap-tokens/