运维实战 容器部分 Kubernetes存储
CoinfigMap配置管理
在K8S
中, CoinfigMap
被用于保存配置信息.
其主要特点是以键值对方式存储
.
通过CoinfigMap
, K8S
提供了向Pod
中导入配置的方法.
这一操作结局了镜像与配置耦合度高的问题, 实现了镜像与配置的解耦, 同时也大大提高了镜像的复用性和可移植性.
通过导入配置, 镜像可以批量化的进行配置修改和迁移.
可能的应用场景
- 用于向容器内填充环境变量
- 设置容器内的命令行参数
- 作为容器内应用的配置文件存在
- 填充数据卷的配置文件
如何使用
常见的创建ConfigMap
的方式有4种
CLI
交互式创建, 即字面值方式创建- 使用文件进行创建
- 使用目录进行创建(实际就是批量文件创建)
- 通过编写
yaml
资源清单创建
分类实践及其特性
字面值方式创建
##采用CLI方式交互式填写键值对
[root@Server2 YAML]# kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
configmap/my-config created
##查看创建的ConfigMap
[root@Server2 YAML]# kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 5h31m
my-config 2 6s
[root@Server2 YAML]# kubectl describe cm my-config
Name: my-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
key1:
----
config1
key2:
----
config2
Events: <none>
##测试完成后清理环境
[root@Server2 YAML]# kubectl delete cm my-config
configmap "my-config" deleted
使用文件创建
默认情况下, 文件的名称会成为Key
, 而文件的内容会成为对应的Value
.
##使用DNS解析文件作为导入文件
[root@Server2 YAML]# kubectl create configmap my-config-2 --from-file=/etc/resolv.conf
configmap/my-config-2 created
##查看创建的ConfigMap
[root@Server2 YAML]# kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 5h32m
my-config-2 1 5s
[root@Server2 YAML]# kubectl describe cm my-config-2
Name: my-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
resolv.conf:
----
nameserver 114.114.114.114
Events: <none>
##测试完成后清理环境
[root@Server2 YAML]# kubectl delete cm my-config-2
configmap "my-config-2" deleted
使用目录创建
##创建测试目录并导入用于测试的文件
[root@Server2 mnt]# mkdir configMap
[root@Server2 mnt]# cd configMap/
[root@Server2 configMap]# cp /etc/passwd .
[root@Server2 configMap]# cp /etc/resolv.conf .
[root@Server2 configMap]# cp /etc/hosts .
##通过目录方式创建ConfigMap
[root@Server2 configMap]# kubectl create configmap my-config-3 --from-file=/etc/configMap
##查看创建的ConfigMap
[root@Server2 configMap]# kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 5h35m
[root@Server2 configMap]# kubectl create configmap my-config-3 --from-file=/mnt/configMap
configmap/my-config-3 created
[root@Server2 configMap]# kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 5h35m
my-config-3 3 3s
[root@Server2 configMap]# kubectl describe cm my-config-3
Name: my-config-3
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
hosts:
----
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.5.250 foundation4.ilt.example.com
172.25.5.1 Server1 reg.westos.org
172.25.5.2 Server2
172.25.5.3 Server3
172.25.5.4 Server4
172.25.5.5 Server5
172.25.5.6 Server6
172.25.5.7 Server7
172.25.5.8 Server8
passwd:
----
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
kubeadm:x:1000:1000::/home/kubeadm:/bin/bash
resolv.conf:
----
nameserver 114.114.114.114
Events: <none>
##测试完成后清理环境
[root@Server2 configMap]# kubectl delete cm my-config-3
configmap "my-config-3" deleted
使用资源清单创建
- 使用的
CM1.yaml
文件内容
vim CM1.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1-config
data:
db_host: "172.25.0.250"
db_port: "3306"
- 创建一个简单的
ConfigMap
[root@Server2 configMap]# vim CM1.yaml
##导入资源清单
[root@Server2 configMap]# kubectl apply -f CM1.yaml
configmap/cm1-config created
##查看创建的ConfigMap
[root@Server2 configMap]# kubectl get cm
NAME DATA AGE
cm1-config 2 7s
kube-root-ca.crt 1 5h37m
[root@Server2 configMap]# kubectl describe cm cm1-config
Name: cm1-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
db_host:
----
172.25.0.250
db_port:
----
3306
Events: <none>
如何使用ConfigMap
上文有提到, ConfigMap
的用法之一就是导入Pod
中, 那么如何在Pod
中使用自然也有不同的用法了.
通过环境变量直接传递
Pod1.yaml
内容
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: key1
valueFrom:
configMapKeyRef:
name: cm1-config
key: db_host
- name: key2
valueFrom:
configMapKeyRef:
name: cm1-config
key: db_port
restartPolicy: Never
实现目的
通过使用Pod1.yaml
, 可以创建一个自主式Pod
, 名称为pod1
,并将cm1-config
中的db_host
赋给了容器内的环境变量key1
, db_port
的值赋给了key2
, 在容器运行后采用终端输出环境变量.
相当于只是传递数值而并没有直接引入变量.
- 验证效果
[root@Server2 configMap]# vim Pod1.yaml
[root@Server2 configMap]# kubectl apply -f Pod1.yaml
pod/pod1 created
[root@Server2 configMap]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod1 0/1 ContainerCreating 0 6s
[root@Server2 configMap]# kubectl logs pod1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=pod1
SHLVL=1
HOME=/root
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
key1=172.25.0.250
KUBERNETES_PORT_443_TCP_PROTO=tcp
key2=3306
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
##进行环境清洁
[root@Server2 configMap]# kubectl delete -f Pod1.yaml
pod "pod1" deleted
env
命令的效果为打印环境变量.
上文代码框中的环境变量含有key1
和key2
, 其内容取自ConfigMap
的键.
另一种方式
当然, 也可以直接传递变量而不是赋值了.
Pod2.yaml
内容
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
containers:
- name: pod2
image: busybox
command: ["/bin/sh", "-c", "env"]
envFrom:
- configMapRef:
name: cm1-config
restartPolicy: Never
- 检查结果
[root@Server2 configMap]# vim Pod2.yaml
[root@Server2 configMap]# kubectl apply -f Pod2.yaml
pod/pod2 created
[root@Server2 configMap]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod2 0/1 ContainerCreating 0 3s
[root@Server2 configMap]# kubectl logs pod2
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=pod2
SHLVL=1
db_port=3306
HOME=/root
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
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
db_host=172.25.0.250
[root@Server2 configMap]# kubectl delete -f Pod2.yaml
pod "pod2" deleted
设置命令行参数方式
- 修改过的
Pod2.yaml
内容
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "echo $(db_host) $(db_port)"]
envFrom:
- configMapRef:
name: cm1-config
restartPolicy: Never
不难看出, 这里是将变量的值在命令行中直接显示, 实际的实现与上面的方式并无二样.
[root@Server2 configMap]# vim Pod2.yaml
[root@Server2 configMap]# kubectl apply -f Pod2.yaml
pod/pod1 created
[root@Server2 configMap]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod1 0/1 ContainerCreating 0 3s
[root@Server2 configMap]# kubectl logs pod1
172.25.0.250 3306
通过数据卷挂载进行使用
Pod3.yaml
内容
apiVersion: v1
kind: Pod
metadata:
name: pod3
spec:
containers:
- name: pod3
image: busybox
command: ["/bin/sh", "-c", "cat /config/db_host"]
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: cm1-config
restartPolicy: Never
上面的资源清单
做了以下几件事:
- 将
cm1-config
作为数据卷config-volume
- 将
config-volume
挂载到/config
下 - 在命令行中输出
/config/db_host
的内容, 实际就是读取了db_host
的值
[root@Server2 configMap]# kubectl delete -f Pod2.yaml
pod "pod1" deleted
[root@Server2 configMap]# kubectl apply -f Pod3.yaml
pod/pod3 created
[root@Server2 configMap]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod3 0/1 Completed 0 10s
[root@Server2 configMap]# kubectl logs pod3
172.25.0.250[root@Server2 configMap]#
数据卷模式下的ConfigMap热更新
- 通过以下实验, 我们可以验证
ConfigMap
热更新相关的问题 - 通过以下
YAML
文件创建控制器并将配置文件作为数据卷挂载
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
volumes:
- name: config-volume
configMap:
name: nginxconf
- 使用的
nginx.conf
内容
server {
listen 80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
- 创建
ConfigMap
并进行内容检测
[root@Server2 configMap]# kubectl create configmap nginxconf --from-file=nginx.conf
configmap/nginxconf created
[root@Server2 configMap]# kubectl get cm
kNAME DATA AGE
cm1-config 2 15m
kube-root-ca.crt 1 5h53m
nginxconf 1 10s
[root@Server2 configMap]# kubectl describe cm nginxconf
Name: nginxconf
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
nginx.conf:
----
server {
listen 80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
Events: <none>
- 不难发现, 此时
nginxconf
中的nginx.conf
的值中端口配置部分为listen 80
- 创建控制器并进行内容检测
[root@Server2 configMap]# kubectl apply -f Pod4.yaml
deployment.apps/my-nginx created
[root@Server2 configMap]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-86d5ccb8db-zsl8v 0/1 ContainerCreating 0 5s
[root@Server2 configMap]# kubectl exec -it my-nginx-86d5ccb8db-zsl8v -- bash
root@my-nginx-86d5ccb8db-zsl8v:/# cd /etc/nginx/conf.d/
root@my-nginx-86d5ccb8db-zsl8v:/etc/nginx/conf.d# ls
nginx.conf
root@my-nginx-86d5ccb8db-zsl8v:/etc/nginx/conf.d# cat nginx.conf
server {
listen 80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
##查看容器内挂载情况(此处节选有用部份)
root@my-nginx-86d5ccb8db-zsl8v:/etc/nginx/conf.d# mount
/dev/mapper/rhel-root on /etc/nginx/conf.d type xfs (ro,re