目录
1.2.1. kubernetes.io/service-account-token
1.2.3 kubernetes.io/dockerconfigjson
2.4.1 使用 kubectl create secret 命令陈述式创建 Secret
前言
Kubernetes 中的 Secret(提供加密模式)和 ConfigMap(提供配置)是关键的资源,用于安全地存储和管理敏感信息和配置数据。它们在应用程序开发和部署过程中扮演着重要的角色。本文将介绍如何有效地配置和管理这些资源,以便更好地利用 Kubernetes 的强大功能。
一、Secret
1.1.什么是Secret
在 K8s 中,Secret 是用于存储敏感信息的对象,如密码、token 令牌和 SSH 密钥。这类数据虽然也可以存放在 Pod 或者镜像中,但是放在 Secret 中是为了更方便的控制如何使用数据,并减少暴露的风险;这些信息以加密形式存储,并且只能被授权的 Pod 访问。通过使用 Secret,可以更安全地管理应用程序所需的敏感数据。
也就是说 K8s 解决了我们和 Docker 使用的一些弊端,比如:环境变量、存储问题都要去重新编辑 Dockerfile,而且密码还是明文的。
1.2.secret类型
1.2.1. kubernetes.io/service-account-token
由 Kubernetes 自动创建,用来加载 service-account 文件、访问 APIServer 的 Secret,Pod 会默认使用这个 Secret 与 APIServer 通信, 并且会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。
[root@master01 ~]# kubectl describe pod nginx-daemonset-bqmtg
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-n27bv (ro)
# /v……t 是容器内的路径,表示该容器可以在此路径下访问 Kubernetes 提供的服务账户相关的凭据信息
# default-token-n27bv 是挂载的名称,用于标识挂载点的来源
# (ro) 表示这个挂载是以只读(read-only)方式进行的
每一个容器启动的时候都会使用 secrets 下面的账号来进行挂载的,而且权限为只读;不可能让所有的 pod 都有权限访问 api-server。
1.2.2.Opaque
base64 编码格式的 Secret,用来存储用户自定义的密码、密钥等,默认的 Secret 类型;这是默认的 Secret 类型,用于存储任意类型的密钥-值对。
1.2.3 kubernetes.io/dockerconfigjson
用来存储私有 docker registry(标识符)的认证信息;这种类型的 Secret 主要用于存储 Docker 镜像仓库的认证信息,包括服务器地址、用户名和密码等。这种 Secret 类型通常用于在 Kubernetes 中拉取私有 Docker 镜像时进行身份验证。
1.2.4 kubernetes.io/tls
用于为 ssl 通信模式存储证书和私钥文件、存储与 TLS(传输层安全)相关的证书和密钥,命令创建时类型标识符为 tls。这种类型的 Secret 通常用于安全地存储与 HTTPS 或其他加密通信相关的证书、私钥和 CA(证书颁发机构)证书等敏感信息。
1.2.5 secrets 可选参数
① docker-registry(镜像)
- 当创建用于拉取私有 Docker 镜像的 Secret 时,可以指定该类型。这种 Secret 类型存储用于访问私有 Docker 镜像仓库所需的认证信息,包括服务器地址、用户名和密码等;
② tls(证书)
- 用于存储与 TLS(传输层安全)相关的证书和密钥;
③ generic
- 这是默认的 Secret 类型,用于存储任意类型的密钥-值对。它可以包含任何需要保密的信息,如用户名/密码、API 令牌等。
2.3. Secret 使用方式
① 作为挂载到一个或多个容器上的卷 中的文件;
② 作为容器的环境变量;
③ 由 kubelet 在为 Pod 拉取镜像时使用。
应用场景:官网
https://kubernetes.io/docs/concepts/configuration/secret/
2.4. 创建 Secret
2.4.1 使用 kubectl create secret 命令陈述式创建 Secret
① 指定用户名和密码文件信息
[root@master01 ~]# mkdir secrets;cd secrets
[root@master01 secrets]# echo -n 'lisi' > username.txt
[root@master01 secrets]# echo -n '1234' > password.txt
② 使用 kubectl 工具在 K8s 中创建一个名为 "mysecret" 的通用类型 Secret
[root@master01 secrets]# kubectl create secret generic mysecret --from-file=username.txt --from-file=password.txt
secret/mysecret created
# kubectl create secret generic mysecret
这部分指定了要创建一个名为 "mysecret" 的通用类型的 Secret
# --from-file=username.txt
这表示将 username.txt 文件的内容作为一个键值对添加到 Secret 中,键是文件名,值是文件的内容
# --from-file=password.txt
同样地,这表示将 password.txt 文件的内容作为另一个键值对添加到 Secret 中
③ 列出当前 K8s 集群中的所有 Secret
[root@master01 secrets]# kubectl get secret
NAME TYPE DATA AGE
mysecret Opaque 2 77s
# Opaque类型用于存储任意类型的密钥-值对
④ 获取名为 "mysecret" 的 Secret 的详细信息
[root@master01 secrets]# kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password.txt: 4 bytes # 保密的数据,包含4字节的数据
username.txt: 4 bytes
注:get 或 describe 指令都不会展示 secret 的实际内容,这是出于对数据的保护的考虑 。
2.4.2 使用 yaml 文件声明式创建 Secret
虽然 base64 编码并不等同于加密,但它确实提供了一种简单有效的方式来存储和传输敏感信息,同时也有助于保护这些信息不被轻易泄露。
① 将输入的文本内容进行 base64 编码
[root@master01 secrets]# echo -n lisi | base64 # 进行base64编码
bGlzaQ==
[root@master01 secrets]# echo -n 1234 | base64
MTIzNA==
② 使用 yaml 文件创建
apiVersion: v1
kind: Secret # 这是一个 Secret 对象
metadata: # 包含有关对象的元数据
name: mysecret1 # Secret 的名称
type: Opaque # Secret 的类型
data: # 包含了实际的密钥-值对数据
username: bGlzaQ== # 经过 base64 编码的值
password: MTIzNA==
③ 创建 mysecret1 的 Secret 对象
[root@master01 secrets]# kubectl create -f secret.yaml
④ 列出当前 K8s 集群中的所有 Secret
[root@master01 secrets]# kubectl get secrets
NAME TYPE DATA AGE
mysecret Opaque 2 20m
mysecret1 Opaque 2 33s
⑤ 获取名为 "mysecret1" 的 Secret 的详细信息
[root@master01 secrets]# kubectl describe secret mysecret1
Name: mysecret1
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 4 bytes
username: 4 bytes
# 两种格式基本一样
⑥ yaml 输出显示 Secret 对象的详细信息
[root@master01 secrets]# kubectl get secret mysecret1 -o yaml
# 包括它的类型、元数据以及经过 base64 编码的用户名和密码信息
2.5. 使用 Secret
上文介绍了陈述式和声明式简便的创建 Secret 的方法,当然了我们还可以通过挂载存储的方式来去挂载到 Pod 内部,或者导出到环境变量中。
2.5.1.以 Volume 的形式挂载
将 Secret 挂载到 Volume 中,以 Volume 的形式挂载到 Pod 的某个目录下
① 定义 yaml 文件
[root@master01 secrets]# vim secret-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec: # Pod 的规格
containers: # 列出了 Pod 中的容器
- name: nginx # 容器的名称
image: nginx # 镜像
volumeMounts: # 将卷挂载到容器中
- name: secrets # 将volumeMount与名为"secrets"的卷相关联
mountPath: "/etc/secrets" # 指定容器内卷将被挂载的路径,Volume将在这个路径下可见
readOnly: true # 该卷将以只读方式挂载
volumes: # 定义可以由容器挂载的卷
- name: secrets # 卷名,需与volumeMounts中的name一致
secret: # 卷的类型
secretName: mysecret # 引用将作为卷挂载到Pod内部的Kubernetes Secret资源的名称
② 启动 pod
[root@master01 secrets]# kubectl create -f secret-test.yaml
[root@master01 secrets]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mypod 1/1 Running 0 18s
③ 进入容器查看用户名和密码文件信息
[root@master01 secrets]# kubectl exec -it mypod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /etc/secrets/
# ls
password.txt username.txt
# cat username.txt
lisi#
# cat password.txt
1234#
2.5.2 使用环境变量的方式创建
将 Secret 导出到环境变量中
① 定义 yaml 文件
[root@master01 secrets]# vim secret-test1.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod1
spec:
containers:
- name: nginx
image: nginx
env: # 将环境变量传递给容器
- name: TEST_USER # 设置一个名为 "TEST_USER" 的环境变量
valueFrom: # 环境变量的值来源
secretKeyRef: # 该值来自于一个 Secret 中的特定键
name: mysecret1 # 包含该值的 Secret 的名称为 "mysecret1"
key: username # 要使用的 Secret 中的键名为 "username"
- name: TEST_PASSWORD # 设置一个名为 "TEST_PASSWORD" 的环境变量
valueFrom: # 指定该环境变量的值来源
secretKeyRef: # 该值来自于一个 Secret 中的特定键
name: mysecret1 # 包含该值的 Secret 的名称为 "mysecret1"
key: password # 要使用的 Secret 中的键名为 "password"
② 启动 pod
[root@master01 secrets]# kubectl apply -f secret-test1.yaml
[root@master01 secrets]# kubectl get pods
mypod1 1/1 Running 0 21s
③ 进入容器查看用户名和密码文件信息
[root@master01 secrets]# kubectl exec -it mypod1 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@mypod1:/# echo $TEST_USER
lisi
root@mypod1:/# echo $TEST_PASSWORD
1234
root@mypod1:/# env | grep TEST # 使用env指令查看系统所有内置变量
TEST_USER=lisi
TEST_PASSWORD=1234
2.5.3.总结
挂载的方式:
- volumes 定义类型 secret 的存储卷
- volumeMounts 把存储卷挂载到容器目录,secret 资源数据中的键将以文件名的形式显示,值文件内容
容器环境变量的方式:
- env 定义容器的环境变量名
- 使用 valueFrom.secretKeyRef.name 指定 secret 资源的名称
- valueFrom.secretKeyRef.name 指定这个 secret 资源数据的键名,从而确定引用那个键的值
二、ConfigMap
2.1.什么是ConfigMap
ConfigMap 是 K8s 中的一种资源对象,用于存储非敏感数据的配置信息,例如环境变量、命令行参数、配置文件等。ConfigMap 可以被挂载到 Pod 中,供应用程序使用其中的配置数据。这样做的好处是可以将配置信息与应用程序代码分离,使得配置更易管理和更新。
与Secret类似,区别在于 ConfigMap 保存的是不需要加密配置的信息。ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象。应用场景:应用配置。
2.2. ConfigMap 作用
配置数据的集中管理
- ConfigMap 允许将配置数据集中存储在 Kubernetes 集群中,而不是分散在各个 Pod 中。这样可以简化配置管理,提高可维护性。
与Pod解耦
- 将配置信息存储在 ConfigMap 中可以使应用程序与配置数据解耦,使得配置可以独立于应用程序进行更新和修改,而无需修改应用程序本身。
动态配置更新
- 通过使用 ConfigMap,可以实现动态更新应用程序的配置信息,而无需重新部署 Pod。这样可以减少应用程序 downtime,提高系统的可用性。
跨环境配置
- 可以为不同的环境(例如开发、测试、生产环境)创建不同的 ConfigMap,从而实现跨环境的配置管理,方便在不同环境中部署应用程序。
2.3. ConfigMap 和 Secret 对比
① 数据类型
- ConfigMap: 用于存储非敏感的配置数据,如环境变量、命令行参数、配置文件等。
- Secret: 用于存储敏感数据,如密码、API密钥、证书等。Secret会对存储的数据进行Base64编码,但并不提供加密功能。
② 安全性
- ConfigMap: 存储的数据是明文的,适用于不敏感的配置信息。不建议将敏感数据存储在ConfigMap中。
- Secret: 存储的数据会被Base64编码,但并不提供加密功能。虽然Secret中的数据相对于ConfigMap更安全,但仍然需要注意敏感数据的保护。
③ 用途
- ConfigMap: 用于存储应用程序的配置信息,如环境变量、配置文件等。
- Secret: 用于存储敏感数据,如密码、密钥等,以便应用程序安全地访问这些数据。
④ 访问方式
- ConfigMap: 可以通过环境变量、命令行参数或卷挂载的方式访问其中的数据。
- Secret: 可以通过环境变量、命令行参数或卷挂载的方式访问其中的数据,但需要注意敏感数据的保护和访问权限控制。
2.4. 创建 ConfigMap
2.4.1 使用目录创建
① 创建配置文件
[root@master01 ~]# mkdir /opt/configmap/
[root@master01 ~]# cd /opt/configmap/
[root@master01 configmap]# vim /opt/configmap/game.properties
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
[root@master01 configmap]# vim /opt/configmap/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
② 使用命令行创建
[root@master01 configmap]# kubectl create configmap game-config --from-file=/opt/configmap/
configmap/game-config created
# --from-file 指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容
③ 获取 ConfigMap 资源的信息
[root@master01 configmap]# kubectl get cm
NAME DATA AGE
game-config 2 7s
④ 以 yaml 格式查看了 game-config 的详细信息
[root@master01 configmap]# kubectl get cm game-config -o yaml
2.4.2 使用文件创建
只要指定为一个文件就可以从单个文件中创建 ConfigMap;--from-file 这个参数可以使用多次,即可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的。
① 创建 ConfigMap
[root@master01 configmap]# kubectl create configmap game-config-2 --from-file=/opt/configmap/game.properties --from-file=/opt/configmap/ui.properties
② 列出所有在 Kubernetes 中创建的 ConfigMap
[root@master01 configmap]# kubectl get cm
NAME DATA AGE
game-config 2 7m26s
game-config-2 2 2m15s
③ 以 yaml 格式查看了 game-config-2 的详细信息
[root@master01 configmap]# kubectl get configmaps game-config-2 -o yaml
④ 获取名为 game-config-2 的 ConfigMap 的详细描述信息
[root@master01 configmap]# kubectl describe cm game-config-2
2.4.3 使用字面值创建
使用文字值创建,利用 --from-literal 参数传递配置信息,该参数可以使用多次,格式如下:
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=good
查看ConfigMap详情:
kubectl get configmaps special-config -o yaml
删除所有ConfigMap和Pod:
kubectl delete cm --all
kubectl delete pod --all
示例:
[root@master01 configmap]# kubectl create configmap special-config --from-literal=name=wangwu --from-literal=age=10
configmap/special-config created
[root@master01 configmap]# kubectl get configmaps special-config -o yaml
apiVersion: v1
data:
age: "10"
name: wangwu
kind: ConfigMap
metadata:
creationTimestamp: "2024-06-02T16:00:51Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:age: {}
f:name: {}
manager: kubectl-create
operation: Update
time: "2024-06-02T16:00:51Z"
name: special-config
namespace: default
resourceVersion: "231163"
selfLink: /api/v1/namespaces/default/configmaps/special-config
uid: cfc5fbe1-52f6-43d0-9d7d-8dc87d72dd4f
2.5. 使用 ConfigMap
2.5.1 使用 ConfigMap 来替代环境变量
① 定义环境变量
[root@master01 configmap]# vim env.yaml
apiVersion: v1
kind: ConfigMap # 是一个ConfigMap对象
metadata:
name: special-config
namespace: default
data:
special.how: very # 存储了一个名为"special.how"的键值对,其值为"very"
special.type: good # 存储了一个名为"special.type"的键值对,其值为"good"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO # 存储了一个名为"log_level"的键值对,其值为"INFO"
② 创建资源
[root@master01 configmap]# kubectl delete configmaps --all
# 删除之前创建的configmaps
[root@master01 configmap]# kubectl create -f env.yaml
[root@master01 configmap]# kubectl get cm
NAME DATA AGE
env-config 1 24s
special-config 2 24s
③ 定义 Pod
[root@master01 configmap]# vim test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: busybox
image: busybox:1.28.4
command: [ "/bin/sh", "-c", "env" ]
env: # 容器内的环境变量
- name: SPECIAL_HOW_KEY # 定义了一个名为"SPECIAL_HOW_KEY"的环境变量
valueFrom: # 指定了该环境变量的值来源
configMapKeyRef: # 表明该值来自ConfigMap的特定键
name: special-config # 指定了所使用的ConfigMap的名称
key: special.how # 指定了要使用的ConfigMap中的键
- name: SPECIAL_TYPE_KEY # 定义了另一个名为"SPECIAL_TYPE_KEY"的环境变量
valueFrom: # 指定了该环境变量的值来源
configMapKeyRef: # 表明该值来自ConfigMap的特定键
name: special-config # 指定了所使用的ConfigMap的名称
key: special.type # 指定了要使用的ConfigMap中的键
envFrom: # 从ConfigMap中注入所有键值对作为环境变量
- configMapRef: # 指定了要引用的ConfigMap对象
name: env-config # 指定了要使用的ConfigMap的名称
restartPolicy: Never # 指定了Pod的重启策略为"Never"
④ 启动 Pod
[root@master01 configmap]# kubectl create -f test-pod.yam
[root@master01 configmap]# kubectl get pod
test-pod 0/1 Completed 0 10s
⑤ 获取日志信息
[root@master01 configmap]# kubectl logs test-pod
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=test-pod
SHLVL=1
SPECIAL_HOW_KEY=very
# 赋值变量 SPECIAL_HOW_KEY 的值为 special-config 的 special.how: very
HOME=/root
NGINX_PORT_80_TCP=tcp://10.96.75.23:80
NGINX_SERVICE_PORT_80_TCP=tcp://10.96.193.207:80
SPECIAL_TYPE_KEY=good
# 赋值变量 SPECIAL_TYPE_KEY 的值为 special-config 的 special.type: good
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_SERVICE_HOST=10.96.75.23
NGINX_SERVICE_SERVICE_HOST=10.96.193.207
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
NGINX_DEPLOYMENT_PORT_30000_TCP_ADDR=10.96.101.251
NGINX_DEPLOYMENT_PORT_30000_TCP_PORT=30000
NGINX_DEPLOYMENT_PORT_30000_TCP_PROTO=tcp
NGINX_DEPLOYMENT_SERVICE_HOST=10.96.101.251
NGINX_PORT=tcp://10.96.75.23:80
NGINX_SERVICE_PORT=tcp://10.96.193.207:80
NGINX_SERVICE_SERVICE_PORT=80
log_level=INFO
# 引入 env-config 的变量 log_level: INFO
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
NGINX_PORT_80_TCP_ADDR=10.96.75.23
NGINX_DEPLOYMENT_PORT=tcp://10.96.101.251:30000
NGINX_SERVICE_PORT_80_TCP_ADDR=10.96.193.207
NGINX_DEPLOYMENT_SERVICE_PORT=30000
NGINX_DEPLOYMENT_PORT_30000_TCP=tcp://10.96.101.251:30000
NGINX_PORT_80_TCP_PORT=80
NGINX_SERVICE_PORT_80_TCP_PORT=80
NGINX_PORT_80_TCP_PROTO=tcp
NGINX_SERVICE_PORT_80_TCP_PROTO=tcp
2.5.2 用 ConfigMap 设置命令行参数
① 定义环境变量的值
[root@master01 configmap]# vim test-pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod2
spec:
containers:
- name: busybox
image: busybox:1.28.4
command:
- /bin/sh
- -c
- echo "$(SPECIAL_HOW_KEY) $(SPECIAL_TYPE_KEY)"
# 在容器内部执行的命令。这个命令会打印环境变量"SPECIAL_HOW_KEY"和"SPECIAL_TYPE_KEY"的值
env: # 设置了容器内的环境变量
- name: SPECIAL_HOW_KEY # 定义了一个名为"SPECIAL_HOW_KEY"的环境变量
valueFrom: # 指定了该环境变量的值来源
configMapKeyRef: # 表明该值来自ConfigMap的特定键
name: special-config # 指定了所使用的ConfigMap的名称
key: special.how # 指定了要使用的ConfigMap中的键
- name: SPECIAL_TYPE_KEY # 定义了另一个名为"SPECIAL_TYPE_KEY"的环境变量
valueFrom: # 指定了该环境变量的值来源
configMapKeyRef: # 表明该值来自ConfigMap的特定键
name: special-config # 指定了所使用的ConfigMap的名称
key: special.type # 指定了要使用的ConfigMap中的键
envFrom: # 从ConfigMap中注入所有键值对作为环境变量
- configMapRef: # 指定了要引用的ConfigMap对象
name: env-config # 指定了要使用的ConfigMap的名称
restartPolicy: Never # 指定了Pod的重启策略为"Never"
② 启动 Pod
kubectl create -f test-pod2.yaml
③ 查看 Pod 信息
kubectl get pods
④ 获取日志信息
kubectl logs test-pod2
2.5.3 通过数据卷插件使用 ConfigMap
在数据卷里面使用 ConfigMap,就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。创建一个名为 test-pod3 的 Pod,该 Pod 使用 ConfigMapspecial-config 作为数据卷,并将 ConfigMap 中的键值对作为文件内容挂载到容器的文件系统中。
① 定义 Pod
[root@master01 configmap]# vim test-pod3.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod3
spec:
containers:
- name: busybox
image: busybox:1.28.4
command: [ "/bin/sh", "-c", "sleep 36000" ] # 定义了容器的启动命令
volumeMounts: # 挂载路径到容器内部
- name: config-volume # 挂载的卷的名称
mountPath: /etc/config # 将卷挂载到容器内的路径 "/etc/config"
volumes: # 定义了Pod中的卷
- name: config-volume # 卷的名称
configMap: # 表明这是一个ConfigMap类型的卷
name: special-config # 指定了要挂载的ConfigMap的名称
restartPolicy: Never # 指定了Pod的重启策略为"Never"
② 启动 Pod
[root@master01 configmap]# kubectl create -f test-pod3.yaml
[root@master01 configmap]# kubectl get pods
test-pod3 1/1 Running 0 7s
③ 进入容器
[root@master01 configmap]# kubectl exec -it test-pod3 sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /etc/config/
/etc/config # ls
special.how special.type
/etc/config # cat special.how
very/etc/config #
示例:
① 准备挂载文件
[root@master01 configmap]# echo 123 > index.html
② 创建 configmap
[root@master01 configmap]# kubectl create configmap web123 --from-file=/opt/configmap/index.html
[root@master01 configmap]# kubectl describe configmaps web123
Name: web123
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
index.html:
----
123
Events: <none>
③ 数据挂载
[root@master01 configmap]# vim web123.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-nginx
spec:
volumes:
- name: cm-web
configMap:
name: web123
containers:
- name: web-nginx
image: nginx:1.14
ports:
- containerPort: 80
volumeMounts:
- name: cm-web
mountPath: /usr/share/nginx/html
④ 启动 Pod
[root@master01 configmap]# kubectl apply -f web123.yaml
[root@master01 configmap]# kubectl get pod
[root@master01 configmap]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-nginx 1/1 Running 0 61s 10.244.2.53 node02 <none> <none>
⑤ 访问页面
[root@master01 configmap]# curl 10.244.2.53
123
2.5.4 ConfigMap 的热更新
2.5.4.1 更新 ConfigMap 中的配置数据
ConfigMap 的热更新指的是在不重启 Pods 的情况下更新 ConfigMap 中的配置数据,从而实现应用程序的动态配置更新。这种热更新的方式可以帮助避免应用程序重启所带来的服务中断,提高了系统的可用性。
① 编辑名为"web123"的 ConfigMap 资源
[root@master01 configmap]# kubectl edit configmap web123
② 访问页面
[root@master01 configmap]# curl 10.244.2.53
welcome
# 等大概10秒左右,使用该 ConfigMap 挂载的 Volume 中的数据同步更新
③ 查询容器内、宿主机文件
[root@master01 configmap]# kubectl exec -it web-nginx -- cat /usr/share/nginx/html/index.html
welcome
# 可以看到容器内的文件会修改
[root@master01 configmap]# cat index.html
123
# 宿主机的文件未被修改,它只是将宿主机的文件当作键(文件名)值(文件内容),设置为configmap
# 而后通过挂载的方式,将键值同步到容器当中 ,只有修改configmap的键值,容器中的内容才会同步更新
可以将配置文件等信息,使用陈述式命令指定文件,创建ConfigMap,可以做到在宿主机上,实时更新 pod 的配置信息以及其它有关信息。
2.5.4.2 subPath 字段热更新
通过使用 subPath,可以实现对特定文件的热更新,而不影响 Pod 中其他文件或配置。
① 创建 ConfigMap,将当前目录下的 nginx.conf 文件作为配置数据导入到 ConfigMap 中
[root@master01 configmap]# kubectl create configmap nginx-config --from-file=nginx.conf
[root@master01 configmap]# kubectl get cm
NAME DATA AGE
nginx-config 1 12s
web123 1 12h
② 定义两个 ConfigMap 来提供应用程序的配置和静态文件
指定 Pod 中的容器,这里定义了一个名为 web-nginx 的容器,使用了 nginx:1.14 镜像。容器暴露了 80 端口,并且使用了之前定义的两个卷 cm-web 和 cm-nginx。其中 cm-web 卷被挂载到了容器的 /usr/share/nginx/html 目录,cm-nginx 卷被挂载到了容器的 /etc/nginx/nginx.conf 目录,并且使用了 subPath 字段来指定了 nginx.conf 文件的名称。
[root@master01 configmap]# vim web-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-nginx
spec: # 描述 Pod 的规范
volumes: # 列出可以由此 Pod 中的容器挂载的卷
- name: cm-web # 定义名为 "cm-web" 的卷
configMap: # 指定此卷与 ConfigMap 相关联
name: web123 # 将此卷与名为 "web123" 的 ConfigMap 关联
- name: cm-nginx # 定义另一个名为 "cm-nginx" 的卷
configMap: # 表明此卷与 ConfigMap 相关联
name: nginx-config # 将此卷与名为 "nginx-config" 的 ConfigMap 关联
containers: # 列出构成此 Pod 的容器
- name: web-nginx # 将容器命名为 "web-nginx"
image: nginx:1.14 # 指定要在此容器中使用的 Docker 镜像及其版本
ports: # 列出此容器暴露的端口
- containerPort: 80 # 指定此容器监听端口 80
volumeMounts: # 列出要挂载到此容器中的卷
- name: cm-web # 将 "cm-web" 卷挂载到容器中
mountPath: /usr/share/nginx/html # 指定要将卷挂载到容器中的路径
- name: cm-nginx # 将 "cm-nginx" 卷挂载到容器中
mountPath: /etc/nginx/nginx.conf # 指定要将卷挂载到容器中的路径
subPath: nginx.conf # 表示只应挂载 ConfigMap 中的 "nginx.conf" 文件
③ 启动 Pod
[root@master01 configmap]# kubectl apply -f web-nginx.yaml
[root@master01 configmap]# kubectl get pod -o wide | grep web-nginx
web-nginx 1/1 Running 0 3s 10.244.1.208 node01 <none> <none>
④ 访问页面
[root@master01 configmap]# curl 10.244.1.208
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>
[root@master01 configmap]# kubectl edit cm nginx-config
……
location / {
root /usr/share/nginx/html; # 修改web页面路径
index index.html index.htm;
}
……
[root@master01 configmap]# kubectl delete -f web-nginx.yaml
pod "web-nginx" deleted
[root@master01 configmap]# kubectl apply -f web-nginx.yaml
pod/web-nginx created
[root@master01 configmap]# kubectl get pod -o wide | grep web-nginx
web-nginx 1/1 Running 0 4s 10.244.1.209 node01 <none> <none>
[root@master01 configmap]# curl 10.244.1.209
welcome
2.5.5 ConfigMap 更新后滚动更新 Pod
更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过在 .spec.template.metadata.annotations 中添加 version/config ,每次通过修改 version/config 来触发滚动更新。
① 定义 yaml
[root@master01 configmap]# vim nginx-d.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
[root@master01 configmap]# kubectl apply -f nginx-d.yaml
[root@master01 configmap]# kubectl get pod -o wide | grep nginx
nginx-d9d8cf5c7-q8mmn 1/1 Running 0 4s 10.244.1.216 node01 <none> <none>
[root@master01 configmap]# curl 10.244.1.216 -I
HTTP/1.1 200 OK
Server: nginx/1.14.2
② 修改 Deployment 对象的 Pod 模板
[root@master01 configmap]# kubectl patch deployment nginx --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "202406" }}}}}'
deployment.apps/nginx patched
nginx-78dc66b55c-7sllr 0/1 ContainerCreating 0 1s
nginx-78dc66b55c-7sllr 1/1 Running 0 2s
nginx-d9d8cf5c7-q8mmn 1/1 Terminating 0 2m30s
注意更新 ConfigMap 后:
- 使用该 ConfigMap 挂载的 Env 不会同步更新;
- 使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新。