Kubernetes配置管理全攻略:ConfigMap与Secret详解
目录
一、Configmap 概述
什么是 Configmap?
Configmap 能解决哪些问题?
Configmap 应用场景
使用 ConfigMap 的限制条件
二、Configmap 创建方法
命令行直接创建
通过文件创建(常用)
指定目录创建 configmap(常用)
编写 configmap 资源清单 YAML 文件
三、使用 Configmap
通过环境变量引入
通过环境变量引入
把 configmap 做成 volume,挂载到 pod(常用)
四、Configmap 热更新
一、Secret概述
二、Secret 类型
kubectl 创建类型
三、Secret 使用
Opaque 类型 Secret 的使用
创建
挂载
作为环境变量
作为文件挂载及设置 POSIX 权限
Secret 绑定 serviceAccount(不用做)
查看 secret
TLS Secret
yaml 方式创建
kubectl 创建
Docker 镜像仓库 Secret
yaml 方式创建
kubectl 方式创建
ssh 类型 secret
通过文件创建
pod 挂载 ssh secret
一、Configmap 概述
什么是 Configmap?
Configmap 是 k8s 中的资源对象,用于保存非机密性的配置的,数据可以用 key/value 键值对的形式保存,也可通过文件的形式保存。
Configmap 能解决哪些问题?
ConfigMap 的主要作用就是为了让镜像和配置文件解耦,以便实现镜像的可移植性和可复用性。
我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、nginx、apache 等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、nginx、apache,新增加的服务器上还是要管理这些服务的配置, 如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改, 这种方式肯定满足不了线上大批量的配置变更要求。 所以,k8s 中引入了 Configmap 资源对象,可以当成 volume 挂载到 pod 中,实现统一的配置管理。
1、Configmap 是 k8s 中的资源, 相当于配置文件,可以有一个或者多个 Configmap;
2、Configmap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内部指定目录上;
3、容器中应用程序按照原有方式读取容器特定目录上的配置文件。
4、在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。
Configmap 应用场景
1、使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,configmap 可以将配置信息和 docker 镜像解耦,以便实现镜像的可移植性和可复用性,因为一个 configMap 其实就是一系列配置信息的集合,可直接注入到 Pod 中给容器使用。configmap 注入方式有两种,一种将 configMap 做为存储卷,一种是将configMap 通过 env 中 configMapKeyRef 注入到容器中。
2、使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用 configmap 可以友好的进行配置共享。
使用 ConfigMap 的限制条件
-
ConfigMap 需要在 Pod 启动前创建出来;
-
并且只有当 ConfigMap 和 Pod 处于同一命名空间时,才可以被 Pod 引用;
-
当 Pod 挂载 ConfigMap 绑定的目录时,目录下的目录并不会挂载到 Pod 内,只有目录下的文件会被挂载。
-
ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过 1MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。
二、Configmap 创建方法
命令行直接创建
直接在命令行中指定 configmap 参数创建,通过--from-literal 指定参数
[root@k8s-master01 ~]# kubectl create configmap nginx-config --from-literal=nginx_port=8080 --from-literal=server_name=myapp.nginx.com
[root@k8s-master01 ~]# kubectl get configmap
NAME DATA AGE
kube-root-ca.crt 1 13d
nginx-config 2 51s
[root@k8s-master01 ~]# kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 13d
nginx-config 2 66s
[root@k8s-master01 ~]# kubectl describe configmap nginx-config
Name: nginx-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
server_name:
----
nginx.jx.com
nginx_port:
----
8080
BinaryData
====
Events: <none>
###查看创建的configmap的yaml信息
[root@k8s-master01 ~]# kubectl get cm nginx-config -o yaml
apiVersion: v1
data:server_name: nginx.jx.comnginx_port: "8080"
kind: ConfigMap
metadata:creationTimestamp: "2024-02-01T06:57:54Z"name: nginx-confignamespace: defaultresourceVersion: "616425"uid: 062bd992-202a-4ac3-a578-32542792a43a
创建选项解析:
--allow-missing-template-keys
含义:如果设置为true,当模板中的字段或映射键在数据来源中缺失时,忽略模板中的任何错误。
--append-hash
含义:将configmap的哈希值附加到它的名称后面。
--as-group
含义:指定操作时要模拟的组。这个标志可以重复使用,以指定多个组,用于在操作中进行权限模拟。
--as-uid
含义:指定操作时要模拟的用户ID(UID)。
--as
含义:指定操作时要模拟的用户名。这个用户可以是普通用户或者服务账户,用于在操作中进行权限模拟。
--cache-dir
含义:默认的缓存目录路径。
--certificate-authority
含义:指向证书颁发机构(CA)证书文件的路径,用于验证服务器证书的合法性。
--client-certificate
含义:指向用于TLS(传输层安全协议)的客户端证书文件的路径。
--client-key
含义:指向用于TLS的客户端密钥文件的路径。
--cluster
含义:指定要使用的kubeconfig中的集群名称。kubeconfig是Kubernetes用于配置客户端访问集群的文件。
--context
含义:指定要使用的kubeconfig中的上下文名称。上下文包含了集群、用户和命名空间等信息,用于确定如何与集群进行交互。
--disable-compression
含义:如果设置为true,对发送到服务器的所有请求都不使用响应压缩。
--dry-run
含义:必须是“none”、“server”或“client”之一。如果是“client”策略,仅打印出将要发送到服务器的对象,而不实际执行创建操作;“server”可能在服务器端进行一些验证但不持久化;“none”则是正常执行操作。
--field-manager
含义:用于跟踪字段所有权的管理器名称。
--from-env-file
含义:指定一个文件路径,用于读取以键值对(key=val)形式的行来创建configmap。
--from-file
含义:可以使用文件路径来指定键文件,在这种情况下,文件的基本名称(不含路径)将被用作configmap中的键,文件内容作为值。
--from-literal
含义:指定一个键和一个字面量值,用于插入到configmap中(例如mykey=somevalue)。
--help
含义:显示configmap相关的帮助信息。
--insecure-skip-tls-verify
含义:如果设置为true,将不会检查服务器证书的有效性。这会使你的连接变得不安全,但在某些测试或特殊环境下可能会用到。
--kubeconfig
含义:指向用于命令行接口(CLI)请求的kubeconfig文件的路径。
--log-flush-frequency
含义:日志刷新的最大间隔秒数,即多久将日志缓冲区中的内容刷新输出一次。
--match-server-version
含义:要求服务器版本与客户端版本匹配。
--namespace
含义:如果存在此选项,它指定了这个命令行请求的命名空间范围。命名空间用于在Kubernetes集群中对资源进行隔离和分组。
--output
含义:输出格式。可以是以下之一:(json、yaml、name、go-template、go-template-file、template等),用于指定命令执行结果的输出格式。
--password
含义:用于对API服务器进行基本身份验证的密码。
--profile
含义:要捕获的性能分析(profile)名称。可以是(none、cpu、heap、goroutine、threadcreate、block、mutex)之一,用于对Kubernetes组件的性能进行分析。
--profile-output
含义:指定要将性能分析结果写入的文件名。
--request-timeout
含义:在放弃单个服务器请求之前等待的时间长度。非零值会设置请求超时时间,避免长时间等待无响应的服务器。
--save-config
含义:如果设置为true,当前对象的配置将保存在其注释中。否则,不会保存配置。
--server
含义:Kubernetes API服务器的地址和端口,用于指定客户端连接的服务器位置。
--show-managed-fields
含义:如果设置为true,在以JSON或YAML格式打印对象时,保留managedFields字段。这些字段通常用于记录资源的管理信息。
--template
含义:当-o=go-template、-o=go-template-file等输出格式选项被使用时,指定要使用的模板字符串或模板文件路径。
--tls-server-name
含义:用于服务器证书验证的服务器名称。如果未提供,将使用主机名进行验证。
--token
含义:用于对API服务器进行身份验证的承载令牌(Bearer Token)。
--username
含义:用于对API服务器进行基本身份验证的用户名。
--user
含义:指定要使用的kubeconfig用户的名称。
--validate
含义:必须是以下之一:strict(或true)、warn、ignore(或false),用于指定对资源配置的验证级别。
--vmodule
含义:逗号分隔的pattern=N设置列表,用于基于文件过滤的日志记录(仅适用于特定的日志系统)。
--v
含义:日志级别详细程度的数字表示,用于控制日志输出的信息量。
--warnings-as-errors
含义:将从服务器接收到的警告视为错误,并以非零退出码退出命令执行。
通过文件创建(常用)
通过指定文件创建一个 configmap,--from-file=<文件>,若没有定义key,则使用文件名作为key,文件内容作为value。
[root@k8s-master01 configmap]# cat nginx.conf
server {
server_name www.nginx.com;
listen 80;
root /home/nginx/www/
}
[root@k8s-master01 configmap]# kubectl create configmap nginx-conf --from-file=www.conf=./nginx.conf
configmap/nginx-conf created
[root@k8s-master01 configmap]# kubectl describe configmap nginx-config
Name: nginx-conf
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
www.conf:
----
server {
server_name www.nginx.com;
listen 80;
root /home/nginx/www/
}
BinaryData
====
Events: <none>
[root@k8s-master01 configmap]# kubectl get cm nginx-conf -o yaml
apiVersion: v1
data:www.conf: | server {
server_name www.nginx.com;
listen 80;
root /home/nginx/www/
}
kind: ConfigMap
metadata:creationTimestamp: "2024-02-01T07:12:53Z"name: nginx-confnamespace: defaultresourceVersion: "618054"uid: 3ee6f787-9372-4bda-b0f6-d350b2235d50##www.conf: | 作用是表示www.conf这个可以的内容是多行的。
指定目录创建 configmap(常用)
[root@k8s-master01 configmap]# mkdir mysql-test
[root@k8s-master01 configmap]# cd mysql-test/
[root@k8s-master01 mysql-test]# echo server_id=1 > mysql.cnf
[root@k8s-master01 mysql-test]# echo server_id=2 > mysql2.cnf
[root@k8s-master01 configmap]# kubectl create configmap mysql-cnf --from-file=/root/configmap/mysql-test/
configmap/mysql-cnf created
#查看 configmap 详细信息
[root@k8s-master01 configmap]# kubectl describe cm mysql-cnf
Name: mysql-cnf
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
mysql.cnf:
----
server_id=1
mysql2.cnf:
----
server_id=2
BinaryData
====
Events: <none>
[root@k8s-master01 configmap]# kubectl get cm mysql-cnf -o yaml
apiVersion: v1
data:mysql.cnf: |server_id=1mysql2.cnf: |server_id=2
kind: ConfigMap
metadata:creationTimestamp: "2024-02-01T07:16:32Z"name: mysql-cnfnamespace: defaultresourceVersion: "618449"uid: 3fc1c8ef-5ddd-477b-bc52-2ecf2de86e25
编写 configmap 资源清单 YAML 文件
[root@k8s-master01 configmap]# cat mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: mysqllabels:app: mysql
data:master.cnf: |[mysqld]log-binlog_bin_trust_function_creators=1lower_case_table_names=1slave.cnf: |[mysqld]super-read-onlylog_bin_trust_function_creators=1
#上面中的 | 表示master.cnf文件是多行文件
[root@k8s-master01 configmap]# kubectl get cm mysql -o yaml
apiVersion: v1
data:master.cnf: |[mysqld]log-binlog_bin_trust_function_creators=1lower_case_table_names=1slave.cnf: |[mysqld]super-read-onlylog_bin_trust_function_creators=1
kind: ConfigMap
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"v1","data":{"master.cnf":"[mysqld]\nlog-bin\nlog_bin_trust_function_creators=1\nlower_case_table_names=1\n","slave.cnf":"[mysqld]\nsuper-read-only\nlog_bin_trust_function_creators=1\n"},"kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app":"mysql"},"name":"mysql","namespace":"default"}}creationTimestamp: "2024-02-01T07:39:13Z"labels:app: mysqlname: mysqlnamespace: defaultresourceVersion: "620920"uid: acad5d26-6692-4c1b-a389-cd37bbe81d7d
三、使用 Configmap
通过环境变量引入
使用 configMapKeyRef变量
#创建一个存储 mysql 配置的 configmap
[root@k8s-master01 ~]# cat mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: mysqllabels:app: mysql
data:log: "1"lower: "1"
[root@k8s-master01 ~]# kubectl apply -f mysql-configmap.yaml
configmap/mysql created
[root@k8s-master01 ~]# kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 13d
mysql 2 82s
#创建 pod,引用 Configmap 中的内容
[root@k8s-master01 ~]# cat mysql-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: mysql-pod
spec:containers:- name: mysqlimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: [ "/bin/sh", "-c", "sleep 3600" ]env:- name: log_bin #定义环境变量 log_binvalueFrom:configMapKeyRef:name: mysql #指定 configmap 的名字key: log #指定 configmap 中的 key- name: lower #定义环境变量 lowervalueFrom:configMapKeyRef:name: mysqlkey: lowerrestartPolicy: Never
#更新资源清单文件
[root@k8s-master01 ~]# kubectl apply -f mysql-pod.yaml
[root@k8s-master01 ~]# kubectl exec -it mysql-pod -- /bin/sh
/ # env
log_bin=1
KUBERNETES_PORT=tcp://10.10.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=mysql-pod
NGINX_SVC_NODEPORT_PORT_8000_TCP_ADDR=10.10.166.16
SHLVL=1
HOME=/root
NGINX_SVC_NODEPORT_PORT_8000_TCP_PORT=8000
NGINX_SVC_NODEPORT_PORT_8000_TCP_PROTO=tcp
SERVICE_BLUE_SERVICE_HOST=10.10.157.201
NGINX_SVC_NODEPORT_SERVICE_HOST=10.10.166.16
SERVICE_BLUE_SERVICE_PORT=80
SERVICE_BLUE_PORT=tcp://10.10.157.201:80
NGINX_SVC_NODEPORT_PORT_8000_TCP=tcp://10.10.166.16:8000
TERM=xterm
lower=1
KUBERNETES_PORT_443_TCP_ADDR=10.10.0.1
NGINX_SVC_NODEPORT_PORT=tcp://10.10.166.16:8000
NGINX_SVC_NODEPORT_SERVICE_PORT=8000
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SERVICE_BLUE_PORT_80_TCP_ADDR=10.10.157.201
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
SERVICE_BLUE_PORT_80_TCP_PORT=80
SERVICE_BLUE_PORT_80_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.10.0.1:443
KUBERNETES_SERVICE_HOST=10.10.0.1
PWD=/
SERVICE_BLUE_PORT_80_TCP=tcp://10.10.157.201:80
通过环境变量引入
#使用 envfrom变量
[root@k8s-master01 ~]# cat mysql-pod-envfrom.yaml
apiVersion: v1
kind: Pod
metadata:name: mysql-pod-envfrom
spec:containers:- name: mysqlimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: [ "/bin/sh", "-c", "sleep 3600" ]envFrom:- configMapRef:name: mysql #指定configmap的名字restartPolicy: Never
#更新资源清单文件
[root@k8s-master01 ~]# kubectl apply -f mysql-pod-envfrom.yaml
pod/mysql-pod-envfrom created
[root@k8s-master01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-pod 1/1 Running 0 13m
mysql-pod-envfrom 1/1 Running 0 107s
[root@k8s-master01 ~]# kubectl exec -it mysql-pod-envfrom -c mysql -- /bin/sh
/ # env
KUBERNETES_PORT=tcp://10.10.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=mysql-pod-envfrom
NGINX_SVC_NODEPORT_PORT_8000_TCP_ADDR=10.10.166.16
SHLVL=1
HOME=/root
NGINX_SVC_NODEPORT_PORT_8000_TCP_PORT=8000
NGINX_SVC_NODEPORT_PORT_8000_TCP_PROTO=tcp
SERVICE_BLUE_SERVICE_HOST=10.10.157.201
NGINX_SVC_NODEPORT_SERVICE_HOST=10.10.166.16
SERVICE_BLUE_SERVICE_PORT=80
SERVICE_BLUE_PORT=tcp://10.10.157.201:80
NGINX_SVC_NODEPORT_PORT_8000_TCP=tcp://10.10.166.16:8000
TERM=xterm
lower=1
KUBERNETES_PORT_443_TCP_ADDR=10.10.0.1
NGINX_SVC_NODEPORT_PORT=tcp://10.10.166.16:8000
NGINX_SVC_NODEPORT_SERVICE_PORT=8000
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
log=1
KUBERNETES_PORT_443_TCP_PORT=443
SERVICE_BLUE_PORT_80_TCP_ADDR=10.10.157.201
KUBERNETES_PORT_443_TCP_PROTO=tcp
SERVICE_BLUE_PORT_80_TCP_PORT=80
SERVICE_BLUE_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.10.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.10.0.1
PWD=/
SERVICE_BLUE_PORT_80_TCP=tcp://10.10.157.201:80
/ #
把 configmap 做成 volume,挂载到 pod(常用)
[root@k8s-master01 ~]# cat mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: mysqllabels:app: mysql
data:log: "1"lower: "1"my.cnf: |[mysqld]welcome=duoduo
[root@k8s-master01 ~]# kubectl apply -f mysql-configmap.yaml
configmap/mysql configured
#查看详细配置信息
[root@k8s-master01 ~]# kubectl describe configmap mysql
Name: mysql
Namespace: default
Labels: app=mysql
Annotations: <none>
Data
====
log:
----
1
lower:
----
1
my.cnf:
----
[mysqld]
welcome=duoduo
BinaryData
====
Events: <none>
#创建pod资源清单文件,挂载configmap卷
[root@k8s-master01 ~]# cat mysql-pod-volume.yaml
apiVersion: v1
kind: Pod
metadata:name: mysql-pod-volume
spec:containers:- name: mysqlimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: [ "/bin/sh","-c","sleep 3600" ]volumeMounts:- name: mysql-configmountPath: /tmp/configvolumes:- name: mysql-configconfigMap:name: mysqlrestartPolicy: Never
[root@k8s-master01 ~]# kubectl apply -f mysql-pod-volume.yaml
pod/mysql-pod-volume created
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-volume -- /bin/sh
/ #
/ #
/ #
/ # cd /tmp/config/
/tmp/config # ls
log lower my.cnf
/tmp/config # ls -l
total 0
lrwxrwxrwx 1 root root 10 Feb 1 08:12 log -> ..data/log
lrwxrwxrwx 1 root root 12 Feb 1 08:12 lower -> ..data/lower
lrwxrwxrwx 1 root root 13 Feb 1 08:12 my.cnf -> ..data/my.cnf
四、Configmap 热更新
仅限于卷的形式,如果是环境变量的形式则不更新!!!
限于应用程序能够对配置文件进行动态感知。nginx不行,需要在apply之后对pod执行命令:
nginx -s reload
[root@k8s-master01 ~]# kubectl edit configmap mysql
#将log:1 变成 log:2
apiVersion:v1
data:log:"2"lower:"1"
重新执行一次资源清单文件[root@k8s-master01 test1]# kubectl apply -f mysql-pod-volume.yaml
pod/mysql-pod-volume configured
[root@k8s-master01 ~]# kubectl exec -it mysql-pod-volume -- /bin/sh
/ # cat /tmp/config/log
2/ #
#一次构建镜像,通过配置管理中心configmap 实现了 多场景运行
在 Kubernetes 1.24 版本中,如果 ConfigMap 无法进行热更新,可能有以下几种原因及解决方法:
一、检查更新方式
-
对于环境变量方式:
- 如果是通过环境变量的方式将 ConfigMap 中的值注入到容器中,那么 Kubernetes 本身是不支持自动热更新环境变量的。这种情况下,应用程序需要自己有重新读取环境变量的机制。例如,应用可以定期重新读取环境变量或者通过监听文件系统变化等方式来实现类似的效果,但这需要在应用层面进行开发。
- 示例代码(在应用中实现定期重新读取环境变量的伪代码):
python
import time
def reload_environment_variables():
# 重新获取环境变量的逻辑
pass
while True:
reload_environment_variables()
time.sleep(60) # 每分钟重新加载一次环境变量
- 注意,这只是一个简单的示例,实际实现可能因应用程序的编程语言和运行环境而有所不同。
-
对于挂载文件方式:
- 当以文件形式挂载 ConfigMap 到容器中时,Kubernetes 支持一定程度的热更新。但这也依赖于应用程序是否能够检测到文件内容的变化并重新加载。一些应用程序(如 NGINX)可以自动检测并重新加载配置文件的变化,而有些应用可能需要通过发送信号(如 SIGHUP)等方式来触发重新加载。
- 例如,对于 NGINX,当它检测到挂载的配置文件(来自 ConfigMap)发生变化时,它会自动重新加载配置。但如果应用没有这种自动检测和重新加载的机制,你可能需要在容器内编写一个脚本或使用工具来监控文件变化并触发应用的重新加载。
- 以下是一个使用 inotifywait(Linux 下的文件变化监控工具)来监控文件变化并执行重新加载命令的示例脚本(假设应用的重新加载命令是myapp reload
):
#!/bin/bash
while true; do
• inotifywait -e modify /path/to/config/file # 将/path/to/config/file替换为实际的挂载文件路径
• myapp reload # 执行应用的重新加载命令
done
- 这个脚本需要在容器内运行,并且需要安装 inotify-tools。你可以将其添加到容器的启动命令或者作为一个单独的进程运行。
二、检查相关组件和配置
-
确保 Kubernetes 版本和功能正常:
- 虽然 1.24 版本理论上应该支持 ConfigMap 的挂载文件热更新,但可能存在一些特定的配置或环境因素导致问题。确保你的 Kubernetes 集群是正确安装和配置的,并且相关的组件(如 kubelet 等)运行正常。可以检查 kubelet 的日志,看是否有任何与 ConfigMap 处理相关的错误或警告信息。
- 查看 kubelet 日志的命令(在节点上执行):
journalctl -u kubelet -f # -f 选项用于实时跟踪日志
-
检查 Pod 和容器配置:
- 确认 Pod 的配置正确地将 ConfigMap 挂载到容器中。检查 Pod 的 YAML 配置文件,确保挂载路径和方式正确。
- 例如,以下是一个 Pod 配置中挂载 ConfigMap 的示例片段:
apiVersion: v1
kind: Pod
metadata:
• name: myapp-pod
spec:
• containers:
• \- name: myapp-container
• image: myapp-image
• volumeMounts:
• \- name: config-volume
• mountPath: /etc/config # 挂载路径
• readOnly: true
• volumes:
• \- name: config-volume
• configMap:
• name: my-configmap
- 确保mountPath
是应用程序预期的路径,并且configMap
的名称正确指向你想要更新的 ConfigMap。
-
检查应用程序自身的行为:
- 有些应用程序可能在启动时读取配置文件并缓存了内容,之后不再重新读取。这种情况下,即使 ConfigMap 的文件内容更新了,应用程序也不会感知到变化。需要检查应用程序的文档或代码,了解它是否有这种行为,并根据需要进行调整。
- 例如,如果应用是用 Java 编写的,并且使用了类似 Spring 的框架,可能需要配置 Spring 的相关属性来支持配置文件的热更新。具体配置可能因应用架构和使用的技术栈而异。
三、其他可能的问题和解决方法
-
网络和存储问题:
- 如果 ConfigMap 的更新在存储后端(如 etcd)成功,但容器无法及时获取到更新后的内容,可能是网络或存储相关的问题。检查节点之间的网络连接,确保容器能够正常访问存储 ConfigMap 的 etcd 或其他存储系统。
- 可以使用网络诊断工具(如 ping、traceroute 等)来检查网络连通性。如果是存储系统的问题,可能需要进一步检查存储的配置和状态,看是否有性能瓶颈或错误。
-
权限问题:
- 容器内的应用程序可能没有足够的权限来读取更新后的 ConfigMap 文件。确保容器运行的用户或进程有对挂载目录的读取权限。
- 可以检查容器的安全上下文(security context)设置,确保它允许对挂载文件的正确访问。例如,在 Pod 的 YAML 配置文件中可以设置容器的安全上下文如下:
apiVersion: v1
kind: Pod
metadata:
• name: myapp-pod
spec:
• containers:
• \- name: myapp-container
• image: myapp-image
• volumeMounts:
• \- name: config-volume
• mountPath: /etc/config
• readOnly: true
• securityContext:
• runAsUser: 1000 # 设置容器内运行的用户 ID
• readOnlyRootFilesystem: false # 根据需要设置根文件系统的只读属性
- 这里的runAsUser
设置了容器内运行的用户 ID,你需要根据实际情况调整。
如果以上方法都无法解决问题,可能需要更深入地分析应用程序和 Kubernetes 环境的具体情况,或者考虑使用其他方式来实现配置的动态更新,例如使用一些专门的配置管理工具或框架来与 Kubernetes 集成。
一、Secret概述
k8s secrets用于存储和管理一些敏感数据,比如密码,token,密钥等敏感信息。它把 Pod 想要访问的加密数据存放到 Etcd 中。然后用户就可以通过在 Pod 的容器里挂载 Volume 的方式或者环境变量的方式访问到这些 Secret 里保存的信息了。
Secret 类似于 ConfigMap,但专门用于保存机密数据。
二、Secret 类型
内置类型 | 用法 |
---|---|
Opaque | 用户定义的任意数据 |
kubernetes.io/service-account-tokensymotion | 服务账号令牌 |
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 | 启动引导令牌数据 |
kubectl 创建类型
[root@k8s-master01 ~]# kubectl create secret dotfile -h
Create a secret using specified subcommand.
Available Commands:docker-registry 创建一个给 Docker registry 使用的 secretgeneric Create a secret from a local file, directory, or literal valuetls 创建一个 TLS secret
Usage:kubectl create secret [flags] [options]
Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).
-
docker-registry
: 连接私有镜像仓库的凭证(据) -
generic
: 常见 secret, 该类型 secret 与 configmap使用相同 -
tls
: 提供 tls 证书, 在 service mesh 中自动挂载
三、Secret 使用
使用场景:
-
设置容器的环境变量
-
向 Pod 提供 SSH 密钥或密码等凭据
-
允许 kubelet 从私有镜像仓库中拉取镜像
Opaque 类型 Secret 的使用
创建
-
kubectl create
[root@k8s-master01 ~]# kubectl create secret generic dotfile --from-literal=username=admin --from-literal=password=123456
[root@k8s-master01 ~]# kubectl get secret dotfile -o yaml
apiVersion: v1
data:password: MTIzNDU2username: YWRtaW4=
kind: Secret
metadata:creationTimestamp: "2024-01-09T07:45:19Z"name: dotfilenamespace: defaultresourceVersion: "621858"uid: ce3a3332-5b97-4af0-8312-ced355786e64
type: Opaque
[root@k8s-master01 ~]# echo -n "YWRtaW4=" | base64 -d
admin
-
yaml
以 yaml 方式创建需要你提前进行 base64
[root@k8s-master01 ~]# echo -n "admin" | base64
YWRtaW4=
[root@k8s-master01 ~]# echo -n "123456" | base64
MTIzNDU2
apiVersion: v1
kind: Secret
metadata:name: secret-volumenamespace: default
type: Opaque
data:password: MTIzNDU2username: YWRtaW4=
immutable: true
####警告信息
Warning: resource secrets/dotfile is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
#表示存在同名的secret
你可以通过将 Secret 的 immutable
字段设置为 true
创建不可更改的 Secret。
创建
$ kubectl create -f dotfile-secret.yaml
挂载
-
作为环境变量
创建 pod
[root@k8s-master01 secret]# cat secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: pod1
spec:containers:- image: busybox:1.28name: busyboxcommand: ["/bin/sh","-c","echo $username && env"]env:- name: usernamevalueFrom:secretKeyRef:key: usernamename: secret-volume # secret 名称
####pod不会运行,测试时需要查看日志#### ######或者########
[root@k8s-master01 secret]# cat secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: pod1
spec:containers:- image: busybox:1.28name: busyboxcommand: ["/bin/sh","-c","sleep 3600"]env:- name: usernamevalueFrom:secretKeyRef:key: usernamename: secret-volume # secret 名称
####pod会启动,需要进入容器中查看####
获取容器日志
# 创建
[root@k8s-master01 secret]# kubectl create -f pod1.yaml
[root@k8s-master01 secret]# kubectl logs pod1
admin
KUBERNETES_PORT=tcp://10.10.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=pod1
NGINX_SVC_NODEPORT_PORT_8000_TCP_ADDR=10.10.166.16
SHLVL=1
username=admin
HOME=/root
NGINX_SVC_NODEPORT_PORT_8000_TCP_PORT=8000
SERVICE_BLUE_SERVICE_HOST=10.10.157.201
NGINX_SVC_NODEPORT_PORT_8000_TCP_PROTO=tcp
NGINX_SVC_NODEPORT_SERVICE_HOST=10.10.166.16RVICE_BLUE_SERVICE_PORT=80
SERVICE_BLUE_PORT=tcp://10.10.157.201:80
NGINX_SVC_NODEPORT_PORT_8000_TCP=tcp://10.10.166.16:8000
KUBERNETES_PORT_443_TCP_ADDR=10.10.0.1
NGINX_SVC_NODEPORT_PORT=tcp://10.10.166.16:8000
NGINX_SVC_NODEPORT_SERVICE_PORT=8000
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SERVICE_BLUE_PORT_80_TCP_ADDR=10.10.157.201
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
SERVICE_BLUE_PORT_80_TCP_PORT=80
SERVICE_BLUE_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.10.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.10.0.1
PWD=/
SERVICE_BLUE_PORT_80_TCP=tcp://10.10.157.201:80
-
作为文件挂载及设置 POSIX 权限
创建 pod
apiVersion: v1
kind: Pod
metadata:name: pod2
spec:volumes:- name: secsecret:secretName: secret-volumedefaultMode: 0400 # 设置文件权限containers:- image: busybox:1.28name: busyboxcommand: ["sleep", "24h"]volumeMounts:- mountPath: /etc/configname: sec
注意: secret 挂载到容器后自动 base64 解码
$ kubectl exec pod2 -- ls -l /etc/config/
total 0
lrwxrwxrwx 1 root root 15 Jan 9 08:00 password -> ..data/password
lrwxrwxrwx 1 root root 15 Jan 9 08:00 username -> ..data/username
$ kubectl exec pod2 -- cat /etc/config/username
admin
Secret 绑定 serviceAccount(不用做)
k8s 中 pod 会挂载 serviceAccount
-
挂载路径: /var/run/secrets/kubernetes.io/serviceaccount
-
挂载内容该 serviceAccount 的:
ca.crt
,namespace
,token
secret:
apiVersion: v1
kind: Secret
metadata:name: sa-secretannotations:kubernetes.io/service-account.name: "tdd"
type: kubernetes.io/service-account-token
data:password: MTIzNDU2username: YWRtaW4=
我们为 secret 添加了 kubernetes.io/service-account.name
字段, 为其指定的 serviceAccount, 创建了 Secret 之后,等待 Kubernetes 在 data
字段中填充 token
主键。
查看 secret
可以看到 kubernetes 控制器自动为其填充了 namespace, token, ca
TLS Secret
创建方式
yaml 方式创建
apiVersion: v1
kind: Secret
metadata:name: secret-tls
type: kubernetes.io/tls
data:# 值为 base64 编码,这样会掩盖它们,但不会提供任何有用的机密性级别tls.crt: |LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNVakNDQWJzQ0FnMytNQTBHQ1NxR1NJYjNEUUVCQlFVQU1JR2JNUXN3Q1FZRFZRUUdFd0pLVURFT01Bd0cKQTFVRUNCTUZWRzlyZVc4eEVEQU9C...... # 在这个例子中,密钥数据不是真正的 PEM 编码的私钥tls.key: |RXhhbXBsZSBkYXRhIGZvciB0aGUgVExTIGNydCBmaWVsZA==
kubectl 创建
$ kubectl create secret tls my-tls-secret \--cert=path/to/cert/file \--key=path/to/key/file
Docker 镜像仓库 Secret
yaml 方式创建
apiVersion: v1
kind: Secret
metadata:name: secret-dockercfg
type: kubernetes.io/dockercfg
data:.dockercfg: |eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUvdjEvIjp7ImF1dGgiOiJvcGVuc2VzYW1lIn19fQo=
kubectl 方式创建
$ kubectl create secret docker-registry secret-tiger-docker \--docker-email=tiger@acme.example \--docker-username=tiger \--docker-password=pass1234 \--docker-server=my-registry.example:5000
$ kubectl get secret secret-tiger-docker -o jsonpath='{.data.*}' | base64 -d
输出等价于以下 JSON 文档(这也是一个有效的 Docker 配置文件):
{"auths": {"my-registry.example:5000": {"username": "tiger","password": "pass1234","email": "tiger@acme.example","auth": "dGlnZXI6cGFzczEyMzQ="}}
}
ssh 类型 secret
通过文件创建
$ kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub
pod 挂载 ssh secret
apiVersion: v1
kind: Pod
metadata:name: secret-test-podlabels:name: secret-test
spec:volumes:- name: secret-volumesecret:secretName: ssh-key-secretcontainers:- name: ssh-test-containerimage: mySshImagevolumeMounts:- name: secret-volumereadOnly: truemountPath: "/etc/secret-volume"
容器命令执行时,秘钥的数据可以在下面的位置访问到:
/etc/secret-volume/ssh-publickey
/etc/secret-volume/ssh-privatekey
容器就可以随便使用 Secret 数据来建立 SSH 连接。