一、概述
1.概念
ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pod 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap将你的环境配置信息和容器镜像解耦,便于应用配置的修改。
2.作用
每个服务都有自己的配置文件,在k8s里面一个服务通常会有多个副本,如果没有cofigmap,当需要修改配置的时候就需要逐个修改pod,如果有了configmap,那么只需要修改configmap,再重启pod加载配置即可。
3.使用方式
- 在容器命令和参数内
- 容器的环境变量
- 在只读卷里面添加一个文件,让应用来读取
- 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
二、配置详解
kind: ConfigMap ## 资源类型
apiVersion: v1 ## 接口版本
metadata:
name: cm-nginx ## configmap名称
namespace: mx-test ## 命名空间
data: ## 配置数据
nginx: | ## nginx为key,|管道符下面是整段配置,方便生成配置文件,再挂载
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
test: helloworld ## k:v形式,方便环境变量调用及启动参数调用
三、演练
1.创建一个cm
[root@localhost base-image]# vim configmap-nginx.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: cm-nginx
namespace: mx-test
data:
nginx: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
test: helloworld
[root@localhost base-image]# kubectl apply -f configmap-nginx.yaml
configmap/cm-nginx created
查看详情
[root@iZbp19rn9u8eqyzc5hgemcZ base-image]# kubectl get cm -n mx-test
NAME DATA AGE
cm-nginx 2 20s
kube-root-ca.crt 1 17h
NOTE:DATA下面是2,代表里面有2个k:v配置
2.创建一个没有configmap的pod
[root@localhost base-image]# vim app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
namespace: mx-test
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-app-svc
namespace: mx-test
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx
[root@localhost base-image]# kubectl apply -f app-nginx.yaml
deployment.apps/nginx-app created
service/nginx-app-svc created
进入pod,查看配置
[root@localhost base-image]# kubectl get pod -n mx-test
NAME READY STATUS RESTARTS AGE
nginx-app-7848d4b86f-pj5wp 1/1 Running 0 63s
nginx-app-7848d4b86f-vqk5z 1/1 Running 0 63s
[root@localhost base-image]# kubectl exec -it nginx-app-7848d4b86f-pj5wp -n mx-test -- /bin/bash
root@nginx-app-7848d4b86f-pj5wp:/# cat /etc/nginx/conf.d/default.conf // 默认的nginx配置,有很多注释内容
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
3.以卷的形式挂载
[root@localhost base-image]# vim app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
namespace: mx-test
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts: ## 卷挂载信息
- name: nginx-conf ## 卷名称
mountPath: /etc/nginx/conf.d/ ## 挂载到容器的目录
volumes: ## 卷详细信息
- name: nginx-conf ## 卷名称
configMap: ## 卷类型:configmap
name: cm-nginx ## configmap名称
items: ## configmap的某个项
- key: nginx ## configmap的某一个key
path: default.conf ## 用configmap配置生成的文件名称
---
apiVersion: v1
kind: Service
metadata:
name: nginx-app-svc
namespace: mx-test
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx
[root@localhost base-image]# kubectl apply -f app-nginx.yaml
deployment.apps/nginx-app configured
service/nginx-app-svc unchanged
查看configmap挂载情况
[root@localhost ~]# kubectl get pod -n mx-test
NAME READY STATUS RESTARTS AGE
nginx-app-77fffffb59-bsll5 1/1 Running 0 14s
nginx-app-77fffffb59-gkgdb 1/1 Running 0 18s
[root@localhost ~]# kubectl exec -it nginx-app-77fffffb59-bsll5 -n mx-test -- /bin/bash
root@nginx-app-77fffffb59-bsll5:/# cat /etc/nginx/conf.d/default.conf ## 新挂载的配置由于文件名称一样,所以直接覆盖了默认配置文件
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
4.访问测试
[root@localhost base-image]# kubectl get pod -n mx-test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-77fffffb59-bsll5 1/1 Running 0 7m48s 100.64.49.226 izbp19rn9u8eqyzc5hgemdz <none> <none>
nginx-app-77fffffb59-gkgdb 1/1 Running 0 7m52s 100.64.49.225 izbp19rn9u8eqyzc5hgemdz <none> <none>
[root@localhost base-image]# curl 100.64.49.226
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
5.环境变量引用
pod yaml文件添加env环境变量
[root@localhost base-image]# vim app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
namespace: mx-test
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
env: ## 环境变量
- name: TEST ## 变量名称
valueFrom: ## 变量值来自哪里?
configMapKeyRef: ## 来自configmap
name: cm-nginx ## 那个configmap?
key: test ## 那个key?
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/conf.d/
volumes:
- name: nginx-conf
configMap:
name: cm-nginx
items:
- key: nginx
path: default.conf
---
apiVersion: v1
kind: Service
metadata:
name: nginx-app-svc
namespace: mx-test
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx
[root@localhost base-image]# kubectl apply -f app-nginx.yaml
deployment.apps/nginx-app configured
service/nginx-app-svc unchanged
查看环境变量
[root@localhost ~]# kubectl get pod -n mx-test
NAME READY STATUS RESTARTS AGE
nginx-app-67b764c499-8pvwg 1/1 Running 0 28s
nginx-app-67b764c499-jvq68 1/1 Running 0 24s
[root@localhost ~]# kubectl exec -it nginx-app-67b764c499-8pvwg -n mx-test -- /bin/bash
root@nginx-app-67b764c499-8pvwg:/# env
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=nginx-app-67b764c499-8pvwg
NGINX_APP_SVC_PORT_80_TCP_PROTO=tcp
NGINX_APP_SVC_PORT_80_TCP_PORT=80
PWD=/
NGINX_APP_SVC_PORT_80_TCP=tcp://10.96.88.30:80
PKG_RELEASE=1~bookworm
HOME=/root
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
NGINX_APP_SVC_PORT_80_TCP_ADDR=10.96.88.30
NJS_VERSION=0.7.12
TERM=xterm
NGINX_APP_SVC_PORT=tcp://10.96.88.30:80
SHLVL=1
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
NGINX_APP_SVC_SERVICE_HOST=10.96.88.30
NGINX_APP_SVC_SERVICE_PORT=80
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=1.25.1
TEST=helloworld ## TEST=helloworld
_=/usr/bin/env
root@nginx-app-67b764c499-8pvwg:/# env | grep -i test ## TEST=helloworld
TEST=helloworld
6.容器命令引用
创建一个pod
[root@localhost base-image]# vim pod-busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: test
namespace: mx-test
spec:
containers:
- name: test-container
image: busybox ## busybox 镜像
command: [ "/bin/echo", "$(TEST)" ] ## 启动命令输出一个TEST变量
env:
- name: TEST
valueFrom:
configMapKeyRef:
name: cm-nginx
key: test
restartPolicy: Never
[root@localhost base-image]# kubectl apply -f pod-busybox.yaml
pod/test created
查看pod log是否有输出变量的值
[root@localhost base-image]# kubectl get pod -n mx-test
NAME READY STATUS RESTARTS AGE
nginx-app-67b764c499-8pvwg 1/1 Running 0 10m
nginx-app-67b764c499-jvq68 1/1 Running 0 10m
test 0/1 Completed 0 8s
[root@iZbp19rn9u8eqyzc5hgemcZ base-image]# kubectl logs -f test -n mx-test --tail 20
helloworld
7.使用kubernetes API读取Configmap
先获取token,测试使用default sa的secret中的token
[root@localhost pki]# kubectl get sa default -n kube-system
NAME SECRETS AGE
default 1 78d
[root@localhost pki]# kubectl get sa default -n kube-system -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2023-05-25T02:21:18Z"
name: default
namespace: kube-system
resourceVersion: "347"
uid: d22f9c2a-7195-4f66-8f10-837724bda60a
secrets:
- name: default-token-ztl2m
[root@localhost pki]# kubectl describe secret default-token-ztl2m -n kube-system
Name: default-token-ztl2m
Namespace: kube-system
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: d22f9c2a-7195-4f66-8f10-837724bda60a
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1070 bytes
namespace: 11 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkoyZkhTSmF2SThXdDlhRUFUc3NJZnFXcFpKbnhzMUJpelRHeU9PdkFlUncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXp0bDJtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMjJmOWMyYS03MTk1LTRmNjYtOGYxMC04Mzc3MjRiZGE2MGEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.yYnIffR_GePEMucYQ0-XCzsSL3R5GtLbcnLtcYOMKqSJAhMj3G3TSZ99lyvPuRJzDLsKkwKjlrwGkM3a9HSEzBYFxy5e6JMIr_FB2udxEPsFTmOuN9ApWAFset1Pg8CVj39yB4Gvk_5_CoUmmcFULvfCs3ZHh9pdgd-6eb2_UkpTPVrE-uRTmDyIfc4MRHPvGN8tp-npiCbCXHETDDKWVaSvL_AzgOVk45XDyF9t5ILft7VPyL6F2xa9xH1VwIWhDBmUi4ARlKBv4jbXWfq7w8SeBgaTWLV-F_yQ1wQTOK2kXqE_xXUlJYIxsxotRYSuwPLLjL34y_hsxhzAE-1Jgg
赋值给TOKEN
[root@localhost pki]# TOKEN='eyJhbGciOiJSUzI1NiIsImtpZCI6IkoyZkhTSmF2SThXdDlhRUFUc3NJZnFXcFpKbnhzMUJpelRHeU9PdkFlUncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXp0bDJtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMjJmOWMyYS03MTk1LTRmNjYtOGYxMC04Mzc3MjRiZGE2MGEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.yYnIffR_GePEMucYQ0-XCzsSL3R5GtLbcnLtcYOMKqSJAhMj3G3TSZ99lyvPuRJzDLsKkwKjlrwGkM3a9HSEzBYFxy5e6JMIr_FB2udxEPsFTmOuN9ApWAFset1Pg8CVj39yB4Gvk_5_CoUmmcFULvfCs3ZHh9pdgd-6eb2_UkpTPVrE-uRTmDyIfc4MRHPvGN8tp-npiCbCXHETDDKWVaSvL_AzgOVk45XDyF9t5ILft7VPyL6F2xa9xH1VwIWhDBmUi4ARlKBv4jbXWfq7w8SeBgaTWLV-F_yQ1wQTOK2kXqE_xXUlJYIxsxotRYSuwPLLjL34y_hsxhzAE-1Jgg'
[root@localhost pki]# echo $TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6IkoyZkhTSmF2SThXdDlhRUFUc3NJZnFXcFpKbnhzMUJpelRHeU9PdkFlUncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXp0bDJtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMjJmOWMyYS03MTk1LTRmNjYtOGYxMC04Mzc3MjRiZGE2MGEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.yYnIffR_GePEMucYQ0-XCzsSL3R5GtLbcnLtcYOMKqSJAhMj3G3TSZ99lyvPuRJzDLsKkwKjlrwGkM3a9HSEzBYFxy5e6JMIr_FB2udxEPsFTmOuN9ApWAFset1Pg8CVj39yB4Gvk_5_CoUmmcFULvfCs3ZHh9pdgd-6eb2_UkpTPVrE-uRTmDyIfc4MRHPvGN8tp-npiCbCXHETDDKWVaSvL_AzgOVk45XDyF9t5ILft7VPyL6F2xa9xH1VwIWhDBmUi4ARlKBv4jbXWfq7w8SeBgaTWLV-F_yQ1wQTOK2kXqE_xXUlJYIxsxotRYSuwPLLjL34y_hsxhzAE-1Jgg
使用curl命令,GET方法访问apiserver
[root@localhost pki]# curl -XGET -k -H "Authorization: Bearer $TOKEN" https://apiserver.cluster.local:6443/api/v1/namespaces/mx-test/configmaps/cm-nginx
{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": {
"name": "cm-nginx",
"namespace": "mx-test",
"uid": "16d12f26-f886-4bed-af38-1054981860af",
"resourceVersion": "265265705",
"creationTimestamp": "2023-08-11T01:48:03Z",
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"data\":{\"nginx\":\"server {\\n listen 80;\\n server_name localhost;\\n location / {\\n root /usr/share/nginx/html;\\n index index.html index.htm;\\n }\\n error_page 500 502 503 504 /50x.html;\\n location = /50x.html {\\n root /usr/share/nginx/html;\\n }\\n}\\n\",\"test\":\"helloworld\"},\"kind\":\"ConfigMap\",\"metadata\":{\"annotations\":{},\"name\":\"cm-nginx\",\"namespace\":\"mx-test\"}}\n"
},
"managedFields": [
{
"manager": "kubectl-client-side-apply",
"operation": "Update",
"apiVersion": "v1",
"time": "2023-08-11T01:48:03Z",
"fieldsType": "FieldsV1",
"fieldsV1": {"f:data":{".":{},"f:nginx":{},"f:test":{}},"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{}}}}
}
]
},
"data": {
"nginx": "server {\n listen 80;\n server_name localhost;\n location / {\n root /usr/share/nginx/html;\n index index.html index.htm;\n }\n error_page 500 502 503 504 /50x.html;\n location = /50x.html {\n root /usr/share/nginx/html;\n }\n}\n",
"test": "helloworld"
}
}
通过jq工具格式化,拿出名称为cm-nginx中的nginx配置
[root@localhost pki]# curl -XGET -k -H "Authorization: Bearer $TOKEN" https://apiserver.cluster.local:6443/api/v1/namespaces/mx-test/configmaps/cm-nginx | jq -r .data.nginx
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1555 100 1555 0 0 126k 0 --:--:-- --:--:-- --:--:-- 126k
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Kubernetes API文档参考:http://kubernetes.kansea.com/docs/api-reference/v1/operations/
补充
configmap 多层嵌套例子
apiVersion: v1
kind: ConfigMap
metadata:
name: nested-configmap
data:
config.json: |
{
"level1": {
"level2": {
"key1": "value1",
"key2": "value2"
}
}
}
nested.properties: |
level1.level2.key3=value3
level1.level2.key4=value4
上段配置可以看出,多层嵌套有两种格式,其中:
config.json是用json对象格式
nested.properties是用键值对格式
官网链接:https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#create-a-configmap-from-generator
在实际应用场景中,如果嵌套层数比较多且配置比较多的话,推荐使用键值对格式,键值对格式key:value一目了然