ConfigMap与Secret详解
ConfigMap与Secret详解
1. ConfigMap 概述
应用程序运行时需要依赖一些相关的配置,而这些配置通常会随着开发不断产生变化,为了处理这些变化,因此一般的应用程序设计都会将配置和程序分离。ConfigMap可以很好的帮助在kubernetes部署的程序读取这些配置,实现配置和程序分离的目的,避免因为需要修改配置而重新构建镜像。
ConfigMap使用场景:
- 生成为容器内的环境变量;
- 设置容器启动命令的启动参数(需设置为环境变量);
- 以Volume的形式挂载为容器内部的文件或目录。
- 使用Kubernetes API 读取 ConfigMap
configMap 默认不提供加密功能,因此不能存储机密数据
configMap 作用的对象一般为 Pod 但也可以是 k8s 的其他组件
2. ConfigMap 使用
2.1 挂载卷使用ConfigMap
- 多个pod可以使用同一个ConfigMap
- 向需要的每个容器添加ConfigMap卷
- 挂载卷的时候需要设置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主要存在三种方法:
- 作为挂载到一个或多个容器上的 卷 中的文件。通过卷挂载的 secret 是存储在内存上的而非在磁盘上进行持久化,因此不容易通过磁盘进行窃取
- 作为容器的环境变量
- 由 kubelet 在为 Pod 拉取镜像时使用
4.1 Secret类型
secret 包含3种类型分别是
- Opaque Secret 使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱
- kubernetes.io/dockerconfigjson :用于存储docker registry的认证信息
- 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编码的明文项),要注意以下两点:
- secret大小限制为 1MB
- 注意 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/
Member discussion