Kubernetes ConfigMap
环境准备
bash
[root@master30 ~]# kubectl create ns ConfigMap
[root@master30 ~]# kubectl config set-context --current --namespace ConfigMap
ConfigMap
学习参考:ConfigMap
ConfigMap 介绍
ConfigMap 是一个存储其他对象所需要使用的配置的 PI 对象。 ConfigMap 使用 data 和 binaryData 字段,保存键值对数据。
data字段,用来保存 UTF-8 字符串。binaryData字段,用来保存二进制数据(base64 编码的字串) 。
ConfigMap 的名字必须是一个合法的 DNS 子域名 。data 或 binaryData 字段下面的每个键的名称都必须由字母、数字或者 -、_ 或 . 组成。在 data 下保存的键名不可以与在 binaryData 下出现的键名有重叠。
从 v1.19 开始,你可以添加一个 immutable 字段到 ConfigMap 定义中, 创建不可变更的 ConfigMap。
ConfigMap 使用建议
-
使用 ConfigMap 存储配置数据,不存数据 / 文件,上限 = 1 MiB。
-
**ConfigMap 在设计上不是用来保存大量数据的。**如果你需要保存大量数据,考虑使用挂载存储卷或者使用独立的数据库或者文件服务。
ConfigMap 创建
使用帮助
bash
kubectl create configmap NAME [--from-file=[key=]source]
[--from-literal=key1=value1] [--dry-run=server|client|none] [options]
键值对类型
bash
[root@master30 ~]# kubectl create configmap mysql --from-literal=password=redhat
[root@master30 ~]# kubectl get configmaps mysql -o yaml |grep ^data -A1
data:
password: redhat
文件类型
bash
[root@master30 ~]# echo Hello World > index.html
[root@master30 ~]# kubectl create configmap web1 --from-file=./index.html
[root@master30 ~]# kubectl get configmaps web1 -o yaml |grep ^data -A2
data:
index.html: |
Hello World
目录类型
bash
[root@master30 ~]# echo error > error.html
[root@master30 ~]# mkdir web2
[root@master30 ~]# mv index.html error.html web2
[root@master30 ~]# kubectl create configmap web2 --from-file=./web2
[root@master30 ~]# kubectl get configmaps web2 -o yaml |grep ^data -A4
data:
error.html: |
error
index.html: |
Hello World
ConfigMap 引用
环境变量方式引用
**注意:**环境变量属于特定容器级别。
bash
[root@master30 ~]# vim pod-cm-env.yaml
yaml
---
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
name: mysql
spec:
containers:
- image: docker.io/library/mysql:latest
imagePullPolicy: IfNotPresent
name: mysql
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
# 原先通过value设置环境变量值
valueFrom:
configMapKeyRef:
name: mysql
key: password
验证
bash
[root@master30 ~]# kubectl apply -f pod-cm-env.yaml
[root@master30 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql 1/1 Running 0 4m33s 10.224.193.70 worker32.aaa.cloud <none>
[root@master30 ~]# kubectl exec -it mysql -- bash -c 'echo $MYSQL_ROOT_PASSWORD'
redhat
[root@master30 ~]# apt install -y mysql-client
[root@master30 ~]# mysql -u root -predhat -h 10.224.193.70
mysql: [Warning] Using a password on the command line interface can be insecure.
......
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> quit
Bye
# 删除 pod
[root@master30 ~]# kubectl delete pod mysql --force
以 volume 方式引用
**注意:**volumes属于pod级别,通过volumeMounts挂载。
引用整体
bash
[root@master30 ~]# vim pod-cm-volume-all.yaml
yaml
---
apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
- image: docker.io/library/nginx:latest
imagePullPolicy: IfNotPresent
name: web
volumeMounts:
- name: webcontent
# mountPath值是一个挂载点
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web2
验证
bash
[root@master30 ~]# kubectl apply -f pod-cm-volume-all.yaml
[root@master30 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 1/1 Running 0 66s 10.224.193.69 worker32.aaa.cloud <none> <none>
[root@master30 ~]# kubectl exec web -- ls /usr/share/nginx/html
error.html
index.html
[root@master30 ~]# curl http://10.224.193.69
Hello World
[root@master30 ~]# curl http://10.224.193.69/error.html
error
引用特定key
bash
[root@master30 ~]# vim pod-cm-volume-single.yaml
yaml
---
apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
- image: docker.io/library/nginx:latest
imagePullPolicy: IfNotPresent
name: web
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web2
items:
- key: index.html
path: index.html
等同于
yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
- image: docker.io/library/nginx:latest
imagePullPolicy: IfNotPresent
name: web
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html/index.html"
subPath: index.html
volumes:
- name: webcontent
configMap:
name: web2
**被挂载的 ConfigMap 内容会被自动更新。**当卷中使用的 ConfigMap 被更新时,所投射的键最终也会被更新。 kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。
k8s 中 ConfigMap
以 kube-proxy 为例
bash
[root@master30 ~]# kubectl get configmaps -n kube-system
NAME DATA AGE
calico-config 4 37h
coredns 1 37h
extension-apiserver-authentication 6 37h
kube-apiserver-legacy-service-account-token-tracking 1 37h
kube-proxy 2 37h
kube-root-ca.crt 1 37h
kubeadm-config 1 37h
kubelet-config 1 37h
[root@master30 ~]# kubectl get configmaps kube-proxy -n kube-system -o yaml
apiVersion: v1
data:
config.conf: |-
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
bindAddressHardFail: false
clientConnection:
acceptContentTypes: ""
burst: 0
contentType: ""
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
qps: 0
clusterCIDR: 10.224.0.0/16
configSyncPeriod: 0s
conntrack:
maxPerCore: null
min: null
tcpCloseWaitTimeout: null
tcpEstablishedTimeout: null
detectLocalMode: ""
enableProfiling: false
healthzBindAddress: ""
hostnameOverride: ""
iptables:
masqueradeAll: false
masqueradeBit: null
minSyncPeriod: 0s
syncPeriod: 0s
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
strictARP: false
syncPeriod: 0s
tcpFinTimeout: 0s
tcpTimeout: 0s
udpTimeout: 0s
kind: KubeProxyConfiguration
metricsBindAddress: ""
mode: ""
nodePortAddresses: null
oomScoreAdj: null
portRange: ""
showHiddenMetricsForVersion: ""
udpIdleTimeout: 0s
winkernel:
enableDSR: false
networkName: ""
sourceVip: ""
kubeconfig.conf: |-
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
server: https://10.1.8.30:6443
name: default
contexts:
- context:
cluster: default
namespace: default
user: default
name: default
current-context: default
users:
- name: default
user:
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
kind: ConfigMap
metadata:
annotations:
kubeadm.kubernetes.io/component-config.hash: sha256:77333136e4f6883a76e786187738706eb9a60efd1f8641f2489dbd1e085726d9
creationTimestamp: "2021-07-03T03:07:55Z"
labels:
app: kube-proxy
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:config.conf: {}
f:kubeconfig.conf: {}
f:metadata:
f:annotations:
.: {}
f:kubeadm.kubernetes.io/component-config.hash: {}
f:labels:
.: {}
f:app: {}
manager: kubeadm
operation: Update
time: "2021-07-03T03:07:55Z"
name: kube-proxy
namespace: kube-system
resourceVersion: "193"
selfLink: /api/v1/namespaces/kube-system/configmaps/kube-proxy
uid: 2b6168fd-29c8-49c4-a465-08720e9f48db
# kube-proxy有两种工作模式ipvs和iptables
# 这里 mode 值为空,查看日志发现默认使用iptables。
[root@master30 ~]# kubectl logs -n kube-system kube-proxy-8kp8w
I1019 02:26:00.975333 1 server_others.go:69] "Using iptables proxy"
I1019 02:26:01.037589 1 node.go:141] Successfully retrieved node IP: 10.1.8.31
I1019 02:26:01.040909 1 conntrack.go:100] "Set sysctl" entry="net/netfilter/nf_conntrack_max" value=131072
I1019 02:26:01.041412 1 conntrack.go:52] "Setting nf_conntrack_max" nfConntrackMax=131072
I1019 02:26:01.041902 1 conntrack.go:100] "Set sysctl" entry="net/netfilter/nf_conntrack_tcp_timeout_close_wait" value=3600
......
# 更改模式为ipvs
[root@master30 ~]# kubectl edit cm -n kube-system kube-proxy
......
mode: "ipvs"
......
# 删除pod,等待控制器重新创建
[root@master30 ~]# kubectl get pod -n kube-system |grep kube-proxy
kube-proxy-8kp8w 1/1 Running 1 37d
kube-proxy-ghgxw 1/1 Running 1 37d
kube-proxy-p6qnk 1/1 Running 1 37d
[root@master30 ~]# kubectl delete pod -n kube-system kube-proxy-{8kp8w,ghgxw,p6qnk}
pod "kube-proxy-8kp8w" deleted
pod "kube-proxy-ghgxw" deleted
pod "kube-proxy-p6qnk" deleted
# 再次查看日志
[root@master30 ~]# kubectl get pod -n kube-system |grep kube-proxy
kube-proxy-8swmx 1/1 Running 0 18s
kube-proxy-948cw 1/1 Running 0 29s
kube-proxy-xlh7b 1/1 Running 0 24s
[root@master30 ~]# kubectl logs -n kube-system kube-proxy-8swmx
I1019 03:41:12.288952 1 node.go:141] Successfully retrieved node IP: 10.1.8.31
I1019 03:41:12.290902 1 conntrack.go:52] "Setting nf_conntrack_max" nfConntrackMax=131072
I1019 03:41:12.325988 1 server.go:632] "kube-proxy running in dual-stack mode" primary ipFamily="IPv4"
I1019 03:41:12.364416 1 server_others.go:218] "Using ipvs Proxier"
......
# 实验完成后,模式更改回来
综合案例:haproxy+web
需求:
-
创建一个名称为 haproxy 的pod,使用镜像 haproxy ,pod haproxy 的配置文件保存在 configmap 中,通过 volume 方式挂载到 /usr/local/etc/haproxy/haproxy.cfg 。将流量转发到pod webapp-1 和 webapp-2。
haproxy 的配置文件模板内容如下:
iniglobal daemon maxconn 256 defaults mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms frontend http-in bind *:8080 default_backend servers backend servers server app1 10.224.84.80:80 check server app2 10.224.149.25:80 check -
创建第一个pod,名称为webapp-1 ,使用镜像nginx 。为该pod创建一个cm,名称为webapp-1,该cm保存两个值:
- index.html="hello webapp-1"
- error.html="sorry, error."
这个两个值通过volume方式挂载到**/usr/share/nginx/html**目录。
-
创建第二个pod,名称为webapp-2 ,使用镜像nginx 。为该pod创建一个cm,名称为webapp-2,该cm保存两个值:
- index.html="hello webapp-2"
- error.html="sorry, error."
这个两个值通过volume方式挂载到**/usr/share/nginx/html**目录。
解答:
-
创建第一个cm和pod
bash[root@master30 ~]# mkdir web && cd web root@master30:~/web# kubectl create cm webapp-1 --from-literal=index.html="hello webapp-1" --from-literal=error.html="sorry, error." root@master30:~/web# vim pod-webapp-1.yamlyamlapiVersion: v1 kind: Pod metadata: name: webapp-1 spec: containers: - name: nginx image: docker.io/library/nginx:latest imagePullPolicy: IfNotPresent volumeMounts: - name: config mountPath: "/usr/share/nginx/html" readOnly: true volumes: - name: config configMap: name: webapp-1bashroot@master30:~/web# kubectl apply -f pod-webapp-1.yaml -
创建第二个cm和pod
bashroot@master30:~/web# kubectl create cm webapp-2 --from-literal=index.html="hello webapp-2" --from-literal=error.html="sorry, error." root@master30:~/web# vim pod-webapp-2.yamlyamlapiVersion: v1 kind: Pod metadata: name: webapp-2 spec: containers: - name: nginx image: docker.io/library/nginx:latest imagePullPolicy: IfNotPresent volumeMounts: - name: config mountPath: "/usr/share/nginx/html" readOnly: true volumes: - name: config configMap: name: webapp-2bashroot@master30:~/web# kubectl apply -f pod-webapp-2.yaml -
创建haproxy配置文件。
bash# 获取pod ip地址 root@master30:~/web# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES webapp-1 1/1 Running 0 63m 10.224.84.80 worker1.aaa.fun <none> <none> webapp-2 1/1 Running 0 63m 10.224.149.25 worker2.aaa.fun <none> <none> # haproxy内容如下: root@master30:~/web# vim haproxy.cfginiglobal daemon maxconn 256 defaults mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms frontend http-in bind *:8080 default_backend servers backend servers server app1 10.224.84.80:80 check server app2 10.224.149.25:80 checkbash# 创建haproxy.cfg configmap root@master30:~/web# kubectl create cm haproxy.cfg --from-file=haproxy.cfg=./haproxy.cfg # 创建pod haproxy root@master30:~/web# vim haproxy.yamlyaml--- apiVersion: v1 kind: Pod metadata: name: haproxy spec: containers: - name: haproxy image: docker.io/library/haproxy imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: true volumeMounts: - name: config mountPath: "/usr/local/etc/haproxy" readOnly: true volumes: - name: config configMap: name: haproxy.cfgbashroot@master30:~/web# kubectl apply -f haproxy.yaml # 验证 root@master30:~/web# kubectl get pods haproxy -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES haproxy 1/1 Running 0 33s 10.224.149.35 worker32.aaa.cloud <none> <none> [root@master30 ~]# curl http://10.224.149.35:8080 hello webapp-1 [root@master30 ~]# curl http://10.224.149.35:8080 hello webapp-2
环境清理
bash
[root@master30 ~]# kubectl delete ns ConfigMap