目录
- Volume
- ConfigMap
- 概述
- 创建ConfigMap
- 使用ConfigMap
- 用作环境变量
- 用作命令行参数
- 使用 volume 挂载
- 不可变 ConfigMap
- Secret
- 概述
- Secret 的种类
- 创建Secret
- kubectl创建
- yaml文件创建
- 使用Secret
- 使用 Volume 挂载
- 用作环境变量
- 挂载指定的 key
- 使用kubernetes.io/dockerconfigjson类型
- 使用subpath挂载
- 配置的热更新
Volume
容器的生命周期可能很短,会被频繁的创建和销毁。那么容器在销毁的时候,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器中的数据,Kubernetes 引入了 Volume 的概念。和 Docker 中的卷管理(匿名卷、具名卷、自定义挂载目录,都是挂载在本机,功能非常有限)不同的是,Kubernetes 天生就是集群,所以为了方便管理,Kubernetes 将 卷
抽取为一个对象资源,这样可以更方便的管理和存储数据。
Volume 是 Pod 中能够被多个容器访问的共享目录,它被定义在 Pod 上,然后被一个 Pod 里面的多个容器挂载到具体的文件目录下,Kubernetes 通过 Volume 实现同一个 Pod 中不同容器之间的数据共享以及数据的持久化存储。Volume 的生命周期不和 Pod 中的单个容器的生命周期有关,当容器终止或者重启的时候,Volume 中的数据也不会丢失。
Kubernetes 支持的 Volume 类型:
ConfigMap
参考:https://kubernetes.feisky.xyz/concepts/objects/configmap
概述
应用程序的运行可能会依赖一些配置,而这些配置又是可能会随着需求产生变化的,如果我们的应用程序架构不是应用和配置分离的,那么就会存在当我们需要去修改某些配置项的属性时需要重新构建镜像文件的窘境。现在,ConfigMap组件可以很好的帮助我们实现应用和配置分离,避免因为修改配置项而重新构建镜像。
ConfigMap 用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。
- Configmap 是 k8s 中的资源, 相当于配置文件,可以有一个或者多个 Configmap;
- Configmap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内部指定目录上;
- 容器中应用程序按照原有方式读取容器特定目录上的配置文件。
- 在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。
创建ConfigMap
可以使用 kubectl create configmap
从文件、目录或者 key-value 字符串创建等创建 ConfigMap。也可以通过 kubectl create -f file
创建。
使用 kubectl create configmap -h
可 查看示例,构建 configmap 对象。
- 从 key-value 字符串创建
这种方式适合配置参数比较少的情况
$ kubectl create configmap special-config --from-literal=special.how=very
configmap "special-config" created
$ kubectl get configmap special-config -o go-template='{{.data}}'
map[special.how:very]
- 从 env 文件创建
指定文件类型–from-env-file
$ echo -e "a=b\nc=d" | tee config.env
a=b
c=d
$ kubectl create configmap special-config --from-env-file=config.env
configmap "special-config" created
$ kubectl get configmap special-config -o go-template='{{.data}}'
map[a:b c:d]
- 从目录或文件创建
这种方式用的比较多
可以指定某个目录下:
$ mkdir config
$ echo a>config/a
$ echo b>config/b
$ kubectl create configmap special-config --from-file=config/
configmap "special-config" created
$ kubectl get configmap special-config -o go-template='{{.data}}'
map[a:a
b:b
]
也可以指定某个目录下的某个文件或某几个文件:
# 指定了从config目录下的文件file1.properties和file2.properties读取配置
kubectl create configmap my-config --from-file=/config/file1.properties --from-file=/config/file2.properties
还可以指定别名:
# 指定加载file1.properties文件的配置在ConfigMap的别名是key1,同理file2.properties文件的配置在ConfigMap的别名是key2
kubectl create configmap my-config --from-file=key1=/config/file1.properties --from-file=key2=/config/file2.properties
这种方式创建的 ConfigMap中的key的名字就是文件名。
- 从文件 Yaml/Json 文件创建
先创建文件config.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
再执行文件
$ kubectl create -f config.yaml
configmap "special-config" created
使用ConfigMap
ConfigMap 可以通过三种方式在 Pod 中使用,三种分别方式为:设置环境变量、设置容器命令行参数以及在 Volume 中直接挂载文件或目录。
注意
- ConfigMap 必须在 Pod 引用它之前创建
- 使用
envFrom
时,将会自动忽略无效的键- Pod 只能使用同一个命名空间内的 ConfigMap
用作环境变量
首先创建 ConfigMap:
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
查看:
kubectl get cm
# 结果如下,其中kube-root-ca.crt是系统自动生成的文件,不用管
NAME DATA AGE
env-config 1 6s
kube-root-ca.crt 1 18d
special-config 2 16s
查看详细信息:
kubectl describe cm special-config
# 结果如下
Name: special-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
special.type:
----
charm
special.how:
----
very
BinaryData
====
Events: <none>
test@testdembp yaml %
接着创建pod的yaml文件config-keyValue-pod.yaml,里面指定env配置:
apiVersion: v1
kind: Pod
metadata:
name: test-env-pod
spec:
containers:
- name: test-env-pod
image: alpine
command: ["/bin/sh", "-c", "env;sleep 3600"]
env:
- name: SPECIAL_LEVEL_KEY # 在pod里的环境变量名
valueFrom:
configMapKeyRef: # 通过configMap读取
name: special-config # configMap的名字
key: special.how # configMap的配置的key的名字
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
创建pod:
kubectl apply -f config-keyValue-pod.yaml
# pod/test-env-pod created
查看日志:
kubectl logs -f test-env-pod
其结果如下:
KUBERNETES_PORT=tcp://10.96.0.1:443
PGSQL_SVC_EXTERNAL_SERVICE_HOST=10.110.85.242
KUBERNETES_SERVICE_PORT=443
HOSTNAME=test-env-pod
SHLVL=1
HOME=/root
PGSQL_SVC_EXTERNAL_SERVICE_PORT=80
PGSQL_SVC_EXTERNAL_PORT=tcp://10.110.85.242:80
SPECIAL_TYPE_KEY=charm
PGSQL_SVC_EXTERNAL_PORT_80_TCP_ADDR=10.110.85.242
PGSQL_SVC_EXTERNAL_PORT_80_TCP_PORT=80
PGSQL_SVC_EXTERNAL_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
PGSQL_SVC_EXTERNAL_SERVICE_PORT_PGSQL=80
PGSQL_SVC_EXTERNAL_PORT_80_TCP=tcp://10.110.85.242:80
SPECIAL_LEVEL_KEY=very
log_level=INFO
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
找到我们从configMap里读取的配置SPECIAL_LEVEL_KEY和SPECIAL_TYPE_KEY。可以看到成功读取到了。
用作命令行参数
将 ConfigMap 用作命令行参数时,需要先把 ConfigMap 的数据保存在环境变量中,然后通过 $(VAR_NAME)
的方式引用环境变量。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: dapi-test-pod
image: alpine
command: ["/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
restartPolicy: Never
当 Pod 结束后会输出:
very charm
使用 volume 挂载
可以使用 volume 将 ConfigMap 作为文件或目录直接挂载。
首先创建文件db.properties,内容如下:
userName = aaa
password = 123456
创建ConfigMap:
kubectl create configmap file-config --from-file=config/db.properties
# configmap/file-config created
查看创建的ConfigMap:
kubectl describe cm file-config
# 结果如下
Name: file-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
db.properties: # ConfigMap中的key的名字就是文件名
----
userName = aaa
password = 123456
BinaryData
====
Events: <none>
创建pod,用来挂载创建好的configMap,yaml文件config-file-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: test-file-pod
spec:
containers:
- name: test-file-pod
image: alpine
command: ["/bin/sh", "-c", "env;sleep 3600"]
env:
- name: SPECIAL_LEVEL_KEY # 在pod里的环境变量名
valueFrom:
configMapKeyRef: # 通过configMap读取
name: special-config # configMap的名字
key: special.how # configMap的配置的key的名字
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
volumeMounts: # 加载数据卷
- name: db-config # 加载volums属性中的哪个数据卷
mountPath: "/usr/local/mysql/conf" # 将数据卷中的文件夹加载到容器中哪个目录
readOnly: true # 是否只读
volumes:
- name: db-config # 数据卷的名字,随意设置
configMap: # 数据卷的类型为configMap
name: file-config # configMap的名字,必须和创建的configMap名字一致
items: # 对configMap的key进行映射,如果不指定,默认会把configMap的所有key全部转换为一个同名的文件
- key: "db.properties" # configMap中的key
path: "db.properties" # 将该key的值转换为文件
restartPolicy: Never
创建pod:
kubectl apply -f config-file-pod.yaml
# pod/test-file-pod created
进入容器,查询挂载的文件,如下:
kubectl exec -it test-file-pod -- sh
/ # cd usr/local/mysql/conf/
/usr/local/mysql/conf # ls
db.properties
/usr/local/mysql/conf # cat db.properties
userName = aaa
这样,配置文件就成功挂载到容器中了。
不可变 ConfigMap
不可变 ConfigMap 在 v1.21.0 进入稳定版本。
当集群包含大量 ConfigMap 和 Secret 时,大量的 watch 事件会急剧增加 kube-apiserver 的负载,并会导致错误配置过快传播到整个集群。在这种情况中,给不需要经常修改的 ConfigMap 和 Secret 设置 immutable: true
就可以避免类似的问题。
不可变 ConfigMap 的好处包括:
- 保护应用,使之免受意外更新所带来的负面影响。
- 通过大幅降低对 kube-apiserver 的压力提升集群性能,这是因为 Kubernetes 会关闭不可变 ConfigMap 的监视操作。
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true
Secret
概述
与 ConfigMap 类似,用于存储配置信息,但是主要用于存储敏感信息、需要加密的信息,Secret 可以提供数据加密、解密功能。
在创建 Secret 时,要注意如果要加密的字符中,包含了有特殊字符,需要使用转义符转移,例如 $ 转移后为 $,也可以对特殊字符使用单引号描述,这样就不需要转移例如 1$289*-! 转换为 ‘1$289*-!’。
Secret 对象类型用来保存敏感信息,如:密码、OAuth2 令牌以及 SSH 密钥等。将这些信息放到 Secret 中比放在 Pod 的定义或者容器镜像中更加安全和灵活。
Secret 的种类
创建 Secret 时,你可以使用 Secret 资源的 type
字段,或者与其等价的 kubectl
命令行参数(如果有的话)为其设置类型。 Secret 类型有助于对 Secret 数据进行编程处理。
内置类型 | 用法 |
---|---|
Opaque | 用户定义的任意数据 |
kubernetes.io/service-account-token | 服务账号令牌 |
kubernetes.io/dockercfg | ~/.dockercfg 文件的序列化形式 |
kubernetes.io/dockerconfigjson | ~/.docker/config.json 文件的序列化形式 |
kubernetes.io/basic-auth | 用于基本身份认证的凭据 |
kubernetes.io/ssh-auth | 用于 SSH 身份认证的凭据 |
kubernetes.io/tls | 用于 TLS 客户端或者服务器端的数据 |
bootstrap.kubernetes.io/token | 启动引导令牌数据 |
通过为 Secret 对象的 type
字段设置一个非空的字符串值,你也可以定义并使用自己 Secret 类型(如果 type
值为空字符串,则被视为 Opaque
类型)。
Kubernetes 并不对类型的名称作任何限制。不过,如果你要使用内置类型之一, 则你必须满足为该类型所定义的所有要求。
如果你要定义一种公开使用的 Secret 类型,请遵守 Secret 类型的约定和结构, 在类型名签名添加域名,并用 /
隔开。 例如:cloud-hosting.example.net/cloud-api-credentials
。
创建Secret
kubectl创建
- 使用键值对
命令格式如下:
kubectl create secret generic db-user-pass \
--from-literal=username=admin \
--from-literal=password='S!B\*d$zDsb='
generic表示是通用的基础配置,db-user-pass才是secret的名字;
必须使用单引号
''
转义字符串中的特殊字符,如$
、\
、*
、=
和!
。
查看secret:
kubectl get secret
# 结果如下
NAME TYPE DATA AGE
db-user-pass Opaque 2 15s
也可以使用json的方式:
kubectl get secret db-user-pass -o jsonpath='{.data}'
# 结果如下
{"password":"UyFCXCpkJHpEc2I9","username":"YWRtaW4="}%
查看详细信息:
kubectl describe secret db-user-pass
# 结果如下
Name: db-user-pass
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
username: 5 bytes
password: 12 bytes
信息里不会输出具体的key的值,只会输出数据大小。
- 使用文件
kubectl create secret generic db-user-pass \
--from-file=./username.txt \
--from-file=./password.txt
无论使用哪种方法,输出都类似于:
secret/db-user-pass created
yaml文件创建
Secret资源包含 2 种键值对:data
和 stringData
。 data
字段用来存储 base64 编码的任意数据。 提供 stringData
字段是为了方便,它允许 Secret 使用未编码的字符串。 data
和 stringData
的键必须由字母、数字、-
、_
或 .
组成。
以下示例使用 data
字段在 Secret 中存储两个字符串:
- 将这些字符串转换为 base64:
echo -n 'admin' | base64
echo -n '1f2d1e2e67df' | base64
说明:
Secret 数据的 JSON 和 YAML 序列化结果是以 base64 编码的。 换行符在这些字符串中无效,必须省略。 在 Darwin/macOS 上使用
base64
工具时,用户不应该使用-b
选项分割长行。 相反地,Linux 用户应该在base64
地命令中添加-w 0
选项, 或者在-w
选项不可用的情况下,输入base64 | tr -d '\n'
。
输出类似于:
YWRtaW4=
MWYyZDFlMmU2N2Rm
- 创建清单:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
注意,Secret 对象的名称必须是有效的DNS 子域名。
- 使用
kubectl apply
创建 Secret:
kubectl apply -f ./secret.yaml
输出类似于:
secret/mysecret created
有的时候,觉得手动将数据编码,再配置到 yaml 文件的方式太繁琐,那么也可以将数据编码交给 Kubernetes:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: admin
password: "123456"
注意:
如果在
data
和stringData
中设置了同一个字段,则使用来自stringData
中的值。
使用Secret
Secret 使用场景通常有下列3种:
- 设置容器的环境变量。
- 向 Pod 提供 SSH 密钥或密码等凭据。
- 允许 kubelet 从私有镜像仓库中拉取镜像。
一般用来设置容器的环境变量使用的比较多。
在使用时,有如下方式:
创建好 secret 之后,有两种方式来使用它:
- 以 Volume 方式
- 以环境变量方式
使用 Volume 挂载
如下,把我们前面创建的名字为db-user-pass的secret挂载到容器中的/etc/secrets
目录下:
apiVersion: v1
kind: Pod
metadata:
labels:
name: db
name: db
spec:
volumes:
- name: secrets
secret:
secretName: db-user-pass
containers:
- image: gcr.io/my_project_id/pg:v1
name: db
volumeMounts:
- name: secrets
mountPath: "/etc/secrets"
readOnly: true
ports:
- name: cp
containerPort: 5432
hostPort: 5432
查看 Pod 中对应的信息:
ls /etc/secrets
# password username
cat /etc/secrets/username
# admin
cat /etc/secrets/password
# 123456
用作环境变量
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: wordpress-deployment
spec:
replicas: 2
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: wordpress
visualize: "true"
spec:
containers:
- name: "wordpress"
image: "wordpress"
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_USER
valueFrom:
secretKeyRef:
name: db-user-pass
key: username
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-user-pass
key: password
挂载指定的 key
apiVersion: v1
kind: Pod
metadata:
labels:
name: db
name: db
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
items:
- key: password
mode: 511
path: tst/psd
- key: username
mode: 511
path: tst/usr
containers:
- image: nginx
name: db
volumeMounts:
- name: secrets
mountPath: "/etc/secrets"
readOnly: true
ports:
- name: cp
containerPort: 80
hostPort: 5432
使用kubernetes.io/dockerconfigjson类型
kubernetes.io/dockerconfigjson
类型的 secret 也同样可以被挂载成文件 (目录)。 如果使用 kubernetes.io/dockerconfigjson
类型的 secret 会在目录下创建一个. dockercfg 文件。
可以直接用 kubectl 命令来创建用于 docker registry 认证的 secret:
kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
# secret "myregistrykey" created.
查看 secret 的内容:
kubectl get secret myregistrykey -o yaml
# 结果如下
apiVersion: v1
data:
.dockercfg: eyJjY3IuY2NzLnRlbmNlbnR5dW4uY29tL3RlbmNlbnR5dW4iOnsidXNlcm5hbWUiOiIzMzIxMzM3OTk0IiwicGFzc3dvcmQiOiIxMjM0NTYuY29tIiwiZW1haWwiOiIzMzIxMzM3OTk0QHFxLmNvbSIsImF1dGgiOiJNek15TVRNek56azVORG94TWpNME5UWXVZMjl0In19
kind: Secret
metadata:
creationTimestamp: 2017-08-04T02:06:05Z
name: myregistrykey
namespace: default
resourceVersion: "1374279324"
selfLink: /api/v1/namespaces/default/secrets/myregistrykey
uid: 78f6a423-78b9-11e7-a70a-525400bc11f0
type: kubernetes.io/dockercfg
通过 base64 对 secret 中的内容解码:
echo "eyJjY3IuY2NzLnRlbmNlbnR5dW4uY29tL3RlbmNlbnR5dW4iOnsidXNlcm5hbWUiOiIzMzIxMzM3OTk0IiwicGFzc3dvcmQiOiIxMjM0NTYuY29tIiwiZW1haWwiOiIzMzIxMzM3OTk0QHFxLmNvbSIsImF1dGgiOiJNek15TVRNek56azVORG94TWpNME5UWXVZMjl0XXXX" | base64 --decode
# 内容如下
{"ccr.ccs.tencentyun.com/XXXXXXX":{"username":"3321337XXX","password":"123456.com","email":"3321337XXX@qq.com","auth":"MzMyMTMzNzk5NDoxMjM0NTYuY29t"}}
也可以直接读取 ~/.dockercfg
的内容来创建:
kubectl create secret docker-registry myregistrykey \
--from-file="~/.dockercfg"
在创建 Pod 的时候,通过 imagePullSecrets
来引用刚创建的 myregistrykey
:
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
使用subpath挂载
在一般情况下 configmap 挂载文件时,会先覆盖掉挂载目录,然后再将 congfigmap 中的内容作为文件挂载进行。
下面来演示一下。
首先创建一个nginx的pod,编辑文件nginx-subPath-deploy.yaml,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-subpath-deploy
labels:
app: nginx-deploy
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # 指定副本数
template:
metadata:
labels:
app: nginx # 标签,用来选择资源使用
spec:
containers:
- name: nginx-subpath # 容器名字
image: nginx # 镜像名
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
创建:
kubectl apply -f nginx-subpath-deploy.yaml
# deployment.apps/nginx-subpath-deploy created
创建的Pod如下:
kubectl get po
# 结果如下
NAME READY STATUS RESTARTS AGE
nginx-subpath-deploy-7c75f7c858-b9lgc 1/1 Running 0 2m6s
nginx-subpath-deploy-7c75f7c858-n2r2k 1/1 Running 0 2m6s
进入容器找到nginx.conf的配置文件:
kubectl exec -it nginx-subpath-deploy-7c75f7c858-b9lgc -- sh
# cd etc/nginx
# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
可以看到,在etc/nginx目录下除了我们要的nginx.conf配置文件,还有许多其他文件。
下面我们把nginx.conf内容拷贝到本地文件,然后创建configMap,然后让Pod挂载我们的configMap。
拷贝到本地文件就不再演示了。拷贝好后,执行如下命令创建configMap:
kubectl create configmap nginx-conf-cm --from-file=config/nginx.conf
# configmap/nginx-conf-cm created
查看创建的configMap:
kubectl describe cm nginx-conf-cm
# 内容如下
Name: nginx-conf-cm
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
nginx.conf:
----
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
BinaryData
====
Events: <none>
现在想把原本的pod里的nginx.conf文件挂载到configMap,以后由configMap来管理配置文件。
下面就修改原来deployment的配置:
等待重启后,进入新的容器查看配置文件:
kubectl exec -it nginx-subpath-deploy-68bc554699-c6ldj -- sh
# cd etc/nginx
# ls
nginx.conf
看到结果,etc/nginx这个文件夹下除了挂载的nginx.conf文件,其他文件都没了。
为了挂载不影响其他文件,就要使用到subPath。
如果想不对原来的文件夹下的文件造成覆盖,只是将 configmap 中的每个 key,按照文件的方式挂载到目录下,可以使用 subpath 参数。
配置方式:
- 定义 volumes 时需要增加 items 属性,配置 key 和 path,且 path 的值不能从 / 开始
- 在容器内的 volumeMounts 中增加 subPath 属性,该值与 volumes 中 items.path 的值相同
修改我们deployment如下:
待重启完成后,重新进入容器查看:
kubectl get po
# pod如下
NAME READY STATUS RESTARTS AGE
nginx-subpath-deploy-677c66748d-c7n8g 1/1 Running 0 71s
nginx-subpath-deploy-677c66748d-l4tjj 1/1 Running 0 70s
进入容器查看:
kubectl exec -it nginx-subpath-deploy-677c66748d-c7n8g -- sh
# cd etc/nginx
# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
可以看到,原来的文件就都还在了。
配置的热更新
我们通常会将项目的配置文件作为 configmap 然后挂载到 pod,那么如果更新 configmap 中的配置,正常情况是可以更新到 pod 中的。但是更新更新周期是更新时间 + 缓存时间。
还有以下两种情况不会热更新:
- 使用subPath
- 变量形式:如果 pod 中的一个变量是从 configmap 或 secret 中得到,同样也是不会更新的
对于 subPath 的方式,我们可以取消 subPath 的使用,将配置文件挂载到一个不存在的目录,避免目录的覆盖,然后再利用软连接的形式,将该文件链接到目标位置
但是如果目标位置原本就有文件,可能无法创建软链接,此时可以基于前面讲过的 postStart 操作执行删除命令,将默认的软连接删除即可。
更改配置可以使用如下两种:
-
通过 edit 命令直接修改 configmap
-
通过 replace 替换
由于 configmap 我们创建通常都是基于文件创建,并不会编写 yaml 配置文件,因此修改时我们也是直接修改配置文件,而 replace 是没有 --from-file 参数的,因此无法实现基于源配置文件的替换,此时我们可以利用下方的命令实现
# 该命令的重点在于 --dry-run 参数,该参数的意思打印 yaml 文件,但不会将该文件发送给 apiserver,再结合 -o yaml 输出 yaml 文件就可以得到一个配置好但是没有发给 apiserver 的文件,然后再结合 replace 监听控制台输出得到 yaml 数据即可实现替换
kubectl create cm --from-file=nginx.conf --dry-run -oyaml | kubectl replace -f-
参考:https://www.yuque.com/fairy-era/yg511q/pyll1k