一、向容器传递参数或环境变量
1. 在 Docker 中定义命令与参数
- 容器运行的完整指令由两部分组成:命令
ENTRYPOINT
与参数CMD
ENTRYPOINT
定义容器启动时被调用的可执行程序CMD
指定传递给ENTRYPOINT
的参数
- 上述两种指令均支持以下两种形式:
- shell 形式:如
ENTRYPOINT node app.js
- exec 形式:如
ENTRYPOINT ["node", "app.js"]
- shell 形式:如
- 两者的区别在于指定的命令是否是在 shell 中被调用:
1 | # shell形式:在shell中执行node进程 |
- 虽然可以直接使用
CMD
指令指定镜像运行时想要执行的命令,但还是建议借助ENTRYPOINT
指令,仅仅用CMD
指定所需的默认参数
1 | $ cat Dockerfile |
2. 向容器传递命令行参数
- 在 K8s 中定义容器时,镜像的
ENTRYPOINT
与CMD
均可以被覆盖。仅需要在容器定义中设置属性command
和args
的值- 绝大多数情况下,只需要设置
args
。command
一般很少被覆盖,除非针对一些未定义ENTRYPOINT
的通用镜像,如 busybox command
和args
字段在 Pod 创建后无法被修改
- 绝大多数情况下,只需要设置
1 | kind: Pod |
3. 为容器设置环境变量
- K8s 可为 Pod 中的每个容器指定环境变量,环境变量列表无法在 Pod 创建后被修改
1 | kind: Pod |
- 在每个容器中,K8s 会自动暴露相同命名空间下每个 service 对应的环境变量
二、ConfigMap
1. 介绍
- K8s 允许将配置选项分离到单独的资源对象 ConfigMap 中。其本质为键值对映射,值可以为字面量或配置文件
- 应用无需直接读取 ConfigMap,其内容可以通过环境变量或卷文件的形式传递给容器
2. 创建 ConfigMap
- ConfigMap 的键名需仅包含数字、字母、破折号、下划线、圆点,圆点可首位。键名不合法则不会映射
1 | $ cat cm.yaml |
3. 传递 ConfigMap 作为环境变量
- 启动 Pod 时若无 ConfigMap,Pod 会正常调度,但容器启动失败。创建 ConfigMap 后,失败容器会重启。可设置
configMapKeyRef.optional=true
,这样即使 ConfigMap 不存在,容器也能启动
1 | kind: Pod |
- 将所有条目暴露为环境变量(如果不是合法的环境变量名称,K8s 不会自动转换键名,如
CONFIG_FOO-BAR
)
1 | spec: |
4. 传递 ConfigMap 作为命令行参数
- 使用 ConfigMap 初始化某个环境变量,然后在参数字段中引用该环境变量
1 | apiVersion: v1 |
5. 传递 ConfigMap 作为配置文件
- ConfigMap 卷会将每个条目暴露成一个文件,运行在容器中的进程可通过读取文件内容获取相应的值
1 | $ cat test-configmap.yaml |
- 暴露指定的 ConfigMap 条目
1 | spec: |
- 挂载时如何不影响文件夹中的其他文件?
- subPath 可用作挂载卷中的某个独立文件或文件夹,无需挂载整个卷
- 这种文件挂载方式会有文件更新的缺陷:如果挂载的是容器中的单个文件而不是完整的卷,ConfigMap 更新后对应的文件不会被更新
1 | spec: |
- 为 ConfigMap 卷中的文件设置权限
1 | volumes: |
6. 更新配置且不重启应用程序
- 更新 ConfigMap 后,卷中引用它的文件也会相应更新,进程发现文件改变后进行重载。K8s 也支持文件更新后手动通知容器
1 | $ kubectl edit configmap fortune-config |
- ConfigMap 卷中的文件是
..data
文件夹中文件的符号链接。ConfigMap 更新后,所有文件会被一次性更新:K8s 会创建一个文件夹写入所有文件,最终将符号..data
链接转为该文件夹
1 | $ kubectl exec -it test-configmap -- ls -lA /etc/nginx/conf.d |
三、Secret
- 与 ConfigMap 类似。区别:①K8s 仅将 Secret 分发到需要访问 Secret 的 Pod 所在的机器节点;②只存在于节点的内存中,不写入物理存储;③etcd 以加密形式存储 Secret
1. 默认令牌 Secret
- 默认被挂载到所有容器(可通过设置 Pod 定义中或 Pod 使用的服务账户中的
automountServiceAccountToken=false
来关闭该默认行为)
1 | $ kubectl get secrets |
2. 创建 Secret
1 | $ openssl genrsa -out https.key 2048 |
- Secret 条目的内容会被 Base64 编码。Secret 条目可涵盖二进制数据,Base64 编码可将二进制数据转为纯文本(但 Secret 大小限于 1MB)
- K8s 允许通过
stringData
字段设置条目的纯文本值
1 | apiVersion: v1 |
3. 使用 Secret
- 将 Secret 卷暴露给容器后,条目的值会被自动解码并以真实形式写入对应文件或环境变量
1 | $ cat test-secret.yaml |
- 暴露 Secret 为环境变量(不推荐,该方式可能无意中暴露 Secret 信息)
1 | env: |
4. 镜像拉取 Secret
- 从私有镜像仓库拉取镜像时,K8s 需拥有拉取镜像所需的证书,这时可以通过 Secret 来传递
1 | # 创建包含Docker镜像仓库证书的Secret |
- 可添加 Secret 到 ServiceAccount 使所有 Pod 都能自动添加上该 Secret