Kubernetes生产落地实践_05
ConfigMap
ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap 将你的环境配置信息和 容器镜像 解耦,便于应用配置的修改。
注意:
ConfigMap 并不提供保密或者加密功能。 如果你想存储的数据是机密的,请使用 Secret, 或者使用其他第三方工具来保证你的数据的私密性,而不是用 ConfigMap。
apiVersion: v1
kind: ConfigMap
metadata:
name: appvar
data:
# 类属性键;每一个键都映射到一个简单的值
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
#
# 类文件键
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
你可以使用四种方式来使用 ConfigMap 配置 Pod 中的容器:
- 在容器命令和参数内
- 容器的环境变量
- 在只读卷里面添加一个文件,让应用来读取
- 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
这些不同的方法适用于不同的数据使用方式。 对前三个方法,kubelet 使用 ConfigMap 中的数据在 Pod 中启动容器。
第四种方法意味着你必须编写代码才能读取 ConfigMap 和它的数据。然而, 由于你是直接使用 Kubernetes API,因此只要 ConfigMap 发生更改, 你的应用就能够通过订阅来获取更新,并且在这样的情况发生的时候做出反应。 通过直接进入 Kubernetes API,这个技术也可以让你能够获取到不同的名字空间里的 ConfigMap。
在pod中引用configMap的环境变量
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo-pod
spec:
containers:
- name: demo
image: alpine
command: ["sleep", "3600"]
env:
# 定义环境变量
- name: PLAYER_INITIAL_LIVES # 请注意这里和 ConfigMap 中的键名是不一样的
valueFrom:
configMapKeyRef:
name: game-demo # 这个值来自 ConfigMap
key: player_initial_lives # 需要取值的键
- name: UI_PROPERTIES_FILE_NAME
valueFrom:
configMapKeyRef:
name: game-demo
key: ui_properties_file_name
volumeMounts:
- name: config
mountPath: "/config"
readOnly: true
volumes:
# 你可以在 Pod 级别设置卷,然后将其挂载到 Pod 内的容器中
- name: config
configMap:
# 提供你想要挂载的 ConfigMap 的名字
name: game-demo
# 来自 ConfigMap 的一组键,将被创建为文件
items:
- key: "game.properties"
path: "game.properties"
- key: "user-interface.properties"
path: "user-interface.properties"
ConfigMap 不会区分单行属性值和多行类似文件的值,重要的是 Pods 和其他对象如何使用这些值。
上面的例子定义了一个卷并将它作为 /config
文件夹挂载到 demo
容器内, 创建两个文件,/config/game.properties
和 /config/user-interface.properties
, 尽管 ConfigMap 中包含了四个键。 这是因为 Pod 定义中在 volumes
节指定了一个 items
数组。 如果你完全忽略 items
数组,则 ConfigMap 中的每个键都会变成一个与该键同名的文件, 因此你会得到四个文件。
被挂载的 ConfigMap 内容会被自动更新
当卷中使用的 ConfigMap 被更新时,所投射的键最终也会被更新。 kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。 不过,kubelet 使用的是其本地的高速缓存来获得 ConfigMap 的当前值。 高速缓存的类型可以通过 KubeletConfiguration 结构. 的 ConfigMapAndSecretChangeDetectionStrategy
字段来配置。
ConfigMap 既可以通过 watch 操作实现内容传播(默认形式),也可实现基于 TTL 的缓存,还可以直接经过所有请求重定向到 API 服务器。 因此,从 ConfigMap 被更新的那一刻算起,到新的主键被投射到 Pod 中去, 这一时间跨度可能与 kubelet 的同步周期加上高速缓存的传播延迟相等。 这里的传播延迟取决于所选的高速缓存类型 (分别对应 watch 操作的传播延迟、高速缓存的 TTL 时长或者 0)。
以环境变量方式使用的 ConfigMap 数据不会被自动更新。 更新这些数据需要重新启动 Pod。
说明: 使用 ConfigMap 作为 subPath 卷挂载的容器将不会收到 ConfigMap 的更新。
使用环境变量的方式使用configMap
apiVersion: v1
kind: Pod
metadata:
name: pod-test
spec:
containers:
- name: test
image: busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: appvar
restartPolicy: Never
Secret秘钥
使用 Secret
Pod 可以用三种方式之一来使用 Secret:
- 作为挂载到一个或多个容器上的卷 中的文件。
- 作为容器的环境变量。
- 由 kubelet 在为 Pod 拉取镜像时使用。
Kubernetes 控制面也使用 Secret; 例如,引导令牌 Secret 是一种帮助自动化节点注册的机制。
创建 Secret
创建 Secret 有以下几种可选方式:
对 Secret 名称与数据的约束
Secret 对象的名称必须是合法的 DNS 子域名。
在为创建 Secret 编写配置文件时,你可以设置 data
与/或 stringData
字段。 data
和 stringData
字段都是可选的。data
字段中所有键值都必须是 base64 编码的字符串。如果不希望执行这种 base64 字符串的转换操作,你可以选择设置 stringData
字段,其中可以使用任何字符串作为其取值。
data
和 stringData
中的键名只能包含字母、数字、-
、_
或 .
字符。 stringData
字段中的所有键值对都会在内部被合并到 data
字段中。 如果某个主键同时出现在 data
和 stringData
字段中,stringData
所指定的键值具有高优先级。
编辑 Secret
你可以编辑一个已有的 Secret,除非它是不可变更的。 要编辑一个 Secret,可使用以下方法之一:
在 Pod 中以文件形式使用 Secret
如果你希望在 Pod 中访问 Secret 内的数据,一种方式是让 Kubernetes 将 Secret 以 Pod 中一个或多个容器的文件系统中的文件的形式呈现出来。
要配置这种行为,你需要:
- 创建一个 Secret 或者使用已有的 Secret。多个 Pod 可以引用同一个 Secret。
- 更改 Pod 定义,在
.spec.volumes[]
下添加一个卷。根据需要为卷设置其名称, 并将.spec.volumes[].secret.secretName
字段设置为 Secret 对象的名称。 - 为每个需要该 Secret 的容器添加
.spec.containers[].volumeMounts[]
。 并将.spec.containers[].volumeMounts[].readOnly
设置为true
, 将.spec.containers[].volumeMounts[].mountPath
设置为希望 Secret 被放置的、目前尚未被使用的路径名。 - 更改你的镜像或命令行,以便程序读取所设置的目录下的文件。Secret 的
data
映射中的每个主键都成为mountPath
下面的文件名。
下面是一个通过卷来挂载名为 mysecret
的 Secret 的 Pod 示例:
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
optional: false # 默认设置,意味着 "mysecret" 必须已经存在
你要访问的每个 Secret 都需要通过 .spec.volumes
来引用。
如果 Pod 中包含多个容器,则每个容器需要自己的 volumeMounts
块, 不过针对每个 Secret 而言,只需要一份 .spec.volumes
设置。
将 Secret 键投射到特定目录
你也可以控制 Secret 键所投射到的卷中的路径。 你可以使用 .spec.volumes[].secret.items
字段来更改每个主键的目标路径:
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
将发生的事情如下:
mysecret
中的键username
会出现在容器中的路径为/etc/foo/my-group/my-username
, 而不是/etc/foo/username
。- Secret 对象的
password
键不会被投射。
如果使用了 .spec.volumes[].secret.items
,则只有 items
中指定了的主键会被投射。 如果要使用 Secret 中的所有主键,则需要将它们全部枚举到 items
字段中。
如果你显式地列举了主键,则所列举的主键都必须在对应的 Secret 中存在。 否则所在的卷不会被创建。
Secret 文件的访问权限
你可以为某个 Secret 主键设置 POSIX 文件访问权限位。 如果你不指定访问权限,默认会使用 0644
。 你也可以为整个 Secret 卷设置默认的访问模式,然后再根据需要在主键层面重载。
例如,你可以像下面这样设置默认的模式:
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: 0400
该 Secret 被挂载在 /etc/foo
下,Secret 卷挂载所创建的所有文件的访问模式都是 0400
。
使用来自卷中的 Secret 值
在挂载了 Secret 卷的容器内,Secret 的主键都呈现为文件。 Secret 的取值都是 Base64 编码的,保存在这些文件中。
下面是在上例中的容器内执行命令的结果:
ls /etc/foo/
输出类似于:
username
password
cat /etc/foo/username
输出类似于:
admin
cat /etc/foo/password
输出类似于:
1f2d1e2e67df
容器中的程序要负责根据需要读取 Secret 数据。
挂载的 Secret 是被自动更新的
当卷中包含来自 Secret 的数据,而对应的 Secret 被更新,Kubernetes 会跟踪到这一操作并更新卷中的数据。更新的方式是保证最终一致性。
以环境变量的方式使用 Secret
如果需要在 Pod 中以环境变量的形式使用 Secret:
- 创建 Secret(或者使用现有 Secret)。多个 Pod 可以引用同一个 Secret。
- 更改 Pod 定义,在要使用 Secret 键值的每个容器中添加与所使用的主键对应的环境变量。 读取 Secret 主键的环境变量应该在
env[].valueFrom.secretKeyRef
中填写 Secret 的名称和主键名称。 - 更改你的镜像或命令行,以便程序读取环境变量中保存的值。
下面是一个通过环境变量来使用 Secret 的示例 Pod:
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
optional: false # 此值为默认值;意味着 "mysecret"
# 必须存在且包含名为 "username" 的主键
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
optional: false # 此值为默认值;意味着 "mysecret"
# 必须存在且包含名为 "password" 的主键
restartPolicy: Never
评论区