在生产环境中经常会遇到需要修改配置文件的情况,传统的修改方式不仅会影响到服务的正常运行,而且操作步骤也很繁琐。为了解决这个问题,kubernetes项目从1.2版本引入了ConfigMap功能,用于将应用的配置信息与程序的分离。这种方式不仅可以实现应用程序被的复用,而且还可以通过不同的配置实现更灵活的功能。在创建容器时,用户可以将应用程序打包为容器镜像后,通过环境变量或者外接挂载文件的方式进行配置注入。ConfigMap && Secret 是K8S中的针对应用的配置中心,它有效的解决了应用挂载的问题,并且支持加密以及热更新等功能,可以说是一个k8s提供的一件非常好用的功能
pod的配置中心,一般主要用于存放配置文件(明文存放)
例如 MySQL的配置文件需要挂载到Pod中,一般就使用configMap
格式:
kubectl create [存储卷] [存储卷名称] .......
# 将当前目录下 nginx.yaml写入到configmap中
root@k8s-master ~]# kubectl create configmap test --from-file=./nginx.yaml
configmap/test created
# 查看存储卷
[root@k8s-master ~]# kubectl get configmaps
NAME DATA AGE
test 1 10s
# 查看存储卷里面的详细信息 (里面能查看到上面指定加入的内容)
[root@k8s-master ~]# kubectl describe configmaps test
Name: test
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
nginx.yaml:
----
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
[root@k8s-master ~]# kubectl create configmap test1 --from-file=./k8spod/
configmap/test1 created
# 查看test1存储卷
[root@k8s-master ~]# kubectl get configmaps
NAME DATA AGE
test1 6 10s
# 查看存储卷里面的详细信息 (里面能查看到上面指定加入的k8s目录里的内容)
[root@k8s-master ~]# kubectl describe configmaps test1
[root@k8s-master ~]# kubectl create configmap test3 --from-literal=MYSQL_ROOT_PASSWORD=123456 --from-literal=MYSQL_DATABASES=wordpress
configmap/test3 created
[root@k8s-master ~]#
[root@k8s-master ~]#
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl describe configmaps test3
Name: test3
Namespace: default
Labels: >
Annotations: >
Data
====
MYSQL_DATABASES:
----
wordpress
MYSQL_ROOT_PASSWORD:
----
123456
Events: >
[root@k8s-master ~]# vim configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: test4
data:
MYSQL_ROOT_PASSWORD: "123456"
my.cnf: | # |相当于执行命令时的管道,相当于回车出下面的内容
[mysqld]
basedir=/usr/local/mysql
datadir=/mysql_data
port=3306
socket=/usr/local/mysql/mysql.sock
character-set-server=utf8.mb4
log-error=/var/log/mysqld.log
# 应用资源
root@k8s-master ~]# kubectl apply -f configmap.yaml
configmap/test4 created
[root@k8s-master ~]# kubectl get configmaps
NAME DATA AGE
kube-root-ca.crt 1 18d
test 1 15m
test1 6 10m
test3 2 6m46s
test4 2 7s
# 查看存储卷里的详细信息(能查看到上面加入的内容)
[root@k8s-master ~]# kubectl describe configmaps test4
Name: test4
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
MYSQL_ROOT_PASSWORD:
----
123456
my.cnf:
----
[mysqld]
basedir=/usr/local/mysql
datadir=/mysql_data
port=3306
socket=/usr/local/mysql/mysql.sock
character-set-server=utf8.mb4
log-error=/var/log/mysqld.log
Events: <none>
挂载存储卷会将挂载的目录中的所有文件全部删除,只留下挂载那一个文件
#编写存储卷资源清单
kind: Deployment
apiVersion: apps/v1
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumeMounts:
- mountPath: /opt/ # 挂载到容器的目录
name: mysqlcnf # 指定的是存储卷的名称(即volumes的name)
volumes: # 定义的存储卷
- name: mysqlcnf # 定义volumes的名称
configMap: # 存储卷类型
name: test4 # 所创建configmap的名称,容器内部文件的名称(与上次外面定义configmap存储卷名称一样,达到挂载的效果)
items:
- key: my.cnf # configmap里面的文件名或者变量名
path: my.cnf # configMap挂载到容器中的相对路径(所谓的相对路径指的是指定挂载容器目录的相对路径,在此时即表示/opt/my.cnf)
# 应用资源
[root@k8s-master ~]# kubectl apply -f deployment-configmap.yaml
deployment.apps/mysql created
# 查看pod运行状态
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-54ff6465fb-wc9b9 1/1 Running 0 4s
[root@k8s-master ~]#
# 验证:挂载存储卷会将挂载的目录中的所有文件全部删除
[root@k8s-master ~]# kubectl exec -it mysql-54ff6465fb-wc9b9 -- bash
root@mysql-54ff6465fb-wc9b9:/# cd /opt/
root@mysql-54ff6465fb-wc9b9:/opt# ls
my.cnf
root@mysql-54ff6465fb-wc9b9:/opt# cat my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/mysql_data
port=3306
socket=/usr/local/mysql/mysql.sock
character-set-server=utf8.mb4
log-error=/var/log/mysqld.log
验证:支持热更新 (可以说成实时更新)
# 修改挂载卷文件内容
[root@k8s-master ~]## kubectl edit configmaps test04
[mysqld]
basedir=/usr/local/mysql
datadir=/mysql_data
port=3306
socket=/usr/local/mysql/mysql.sock
character-set-server=utf8
log-error=/var/log/mysqld.log
server-id=12345 # 加上这一行
# 进入容器内部(去查看my.cnf文件,即可看到文件内容的增加,即可验证热更新)
[root@master-lm1 k8s]# kubectl exec -it mysql-79696f8d5c-xfrph -- bash
root@mysql-79696f8d5c-xfrph:/# cat /opt/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/mysql_data
port=3306
socket=/usr/local/mysql/mysql.sock
character-set-server=utf8
log-error=/var/log/mysqld.log
server-id=12345
configmap的另一种使用方式 (指定环境变量的方式),从configmap中直接加载密码变量
#编写存储卷资源清单
kind: Deployment
apiVersion: apps/v1
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
envFrom: # 指定环境变量的方式
- configMapRef: # 将configMap当中的某一项定义成内部的环境变量
name: test4 # configMap的名称
optional: true # 指定是否必须定义configMap
volumeMounts:
- mountPath: /opt/ # 挂载到容器的目录
name: mysqlconf # 指定的是存储卷的名称(即volumes的name)
volumes: # 定义的存储卷
- name: mysqlconf # 定义volumes的名称
configMap: # 存储卷类型
name: test4 # 所创建configmap的名称,容器内部文件的名称(与上次外面定义configmap存储卷名称一样,达到挂载的效果)
items:
- key: my.cnf # configmap里面的文件名或者变量名
path: my.cnf # configMap挂载到容器中的相对路径(所谓的相对路径指的是指定挂载容器目录的相对路径,在此时即表示/opt/my.cnf)
#应用资源
[root@k8s-master ~]## kubectl apply -f configmap-deployment.yaml
#查看pod信息
[root@k8s-master ~]## kubectl get pods
NAME READY STATUS RESTARTS AGE
discuz-cd966b5bc-zvcmc 1/1 Running 0 3h31m
mysql-5db8cd8bc5-w54nf 1/1 Running 0 11s
#进入pod容器内部
[root@k8s-master ~]## kubectl exec -it mysql-5db8cd8bc5-w54nf -- bash
# 查看环境变量
root@mysql-5db8cd8bc5-w54nf:/# printenv
MYSQL_ROOT_PASSWORD=123456
一旦使用了subPath 虽然文件不会被覆盖,但是configMap的热更新功能将丧失
#编写存储卷资源清单
kind: Deployment
apiVersion: apps/v1
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
envFrom: # 指定环境变量的方式
- configMapRef: # 将configMap当中的某一项定义成内部的环境变量
name: test4 # configMap的名称
optional: true # 指定是否必须定义configMap
volumeMounts:
- mountPath: /etc/mysql/conf.d/my.cnf # 挂载到容器的目录,普通文件的绝对路径(必须是文件的绝对路径)
name: mysqlconf # 指定的是存储卷的名称(即volumes的name)
subPath: my.cnf # 指定容器内部的相对路径
volumes: # 定义的存储卷
- name: mysqlconf # 定义volumes的名称
configMap: # 存储卷类型
name: test4 # 所创建configmap的名称,容器内部文件的名称(与上次外面定义configmap存储卷名称一样,达到挂载的效果)
items:
- key: my.cnf # configmap里面的文件名或者变量名
path: my.cnf
# 应用资源
[root@k8s-master ~]# # kubectl apply -f configmap-deployment.yaml
deployment.apps/mysql created
#查看pod运行详细信息
[root@k8s-master ~]# # kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-58d4bf5d86-klgrr 1/1 Running 0 10s
# 进入到pod容器内部
[root@k8s-master ~]# # kubectl exec -it mysql-58d4bf5d86-klgrr -- bash
# 查看文件没有被覆盖(验证完成)
root@mysql-58d4bf5d86-klgrr:/# ls /etc/mysql/conf.d
docker.cnf my.cnf mysql.cnf mysqldump.cnf
在kubernetes中,还存在一种和configmap非常类似的对象,成为secret对象,它主要用于存储敏感信息,例如:密码、密钥、证书等等。
也叫加密的配置中心,Secret中的配置文件全部使用base64加密过后的内容
Secret加密数据库密码,在外面看是加密的,进入容器内部查看就是解密的了(安全性有限,相对安全)
① Service Account:用来访问Kubbernetes,由Kubernetes自动创建,并且会自动挂载到pod的/run/secrets/kubernetes.io/serviceaccount目录中。主要用来存放证书、Token(比如:~/.ssh/id_rsa文件里)
② Opaque :base64编码格式的Secret。主要用来存储用户名密码等安全性较高的数据
③ kubernetes.io/dockerconfigjson/ DockerLogin:主要用来存放docker仓库登录信息
④ TLS:主要用来存放证书(Nginx的证书 ```c
[root@k8s-master ~]# echo -n "123456" | base64
MTIzNDU2
#编写资源配置清单
[root@k8s-master ~]# cat secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: test
data:
MYSQL_ROOT_PASSWORD: MTIzNDU2 # 加密过后的密码
# 应用资源
[root@k8s-master ~]# kubectl apply -f secret.yaml
secret/test created
[root@k8s-master ~]# kubectl get secrets
NAME TYPE DATA AGE
default-token-czh6g kubernetes.io/service-account-token 3 18d
test Opaque 1 11s
# 查看存储卷详细信息(密码为字节格式)
[root@k8s-master ~]# kubectl describe secrets test
Name: test
Namespace: default
Labels: >
Annotations: >
Type: Opaque
Data
====
MYSQL_ROOT_PASSWORD: 6 bytes
secret的使用
第一种使用类型(Opaque类型) (定义环境变量的方式)
# 编写资源配置清单
[root@k8s-master ~]# vim secret-deployment.yaml
kind: Secret
apiVersion: v1
metadata:
name: test
data:
MYSQL_ROOT_PASSWORD: MTIzNDU2 # 这里指定加密过后的密码
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: secret
spec:
selector:
matchLabels:
app: secret
template:
metadata:
labels:
app: secret
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
envFrom: # 指定环境变量
- secretRef: # 将secret当中的某一项定义成内部的环境变量
name: test # secret的名称
optional: true # 指定是否必须定义
# 应用资源
[root@k8s-master ~]# kubectl apply -f secret-deployment.yaml
secret/test unchanged
# 查看pod运行详情
[root@k8s-master ~]# kubectl get pods
secret-54c5965b4d-r827x 1/1 Running 0 9s
# 进入pod容器内部
[root@k8s-master ~]# kubectl exec -it secret-54c5965b4d-r827x -- bash
# 查看环境变量(里面包含数据库的密码)
root@secret-54c5965b4d-r827x:/# printenv
MYSQL_ROOT_PASSWORD=123456
第二种方式:(密码可以当存储卷挂载文件当中)
# 编写资源配置清单
[root@master-lm1 k8s]# vim secret-deployment.yaml
kind: Secret
apiVersion: v1
metadata:
name: test
data:
MYSQL_ROOT_PASSWORD: MTIzNDU2 # 这里指定加密过后的密码
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: secret
spec:
selector:
matchLabels:
app: secret
template:
metadata:
labels:
app: secret
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
envFrom:
- secretRef:
name: test
optional: true
volumeMounts: # 下面定义挂载信息
- mountPath: /opt/ # 需要挂载到容器的目录
name: test # 这个名字是使用下面存储卷的名字,不是secretName的名字
volumes: # 定义的存储卷
- name: test # 定义存储卷的名字
secret: # 指定secret存储卷
secretName: test # 定义secret的名字
optional: true # 指定是否必须定义
# 应用资源
[root@k8s-master ~]# kubectl apply -f secret-deployment.yaml
secret/test created
# 查看pod运行详情
[root@k8s-master ~]# kubectl get pods
secret-8cb97c4fb-x555q 1/1 Running 0 13s
# 进入pods容器内部
[root@k8s-master ~]# kubectl exec -it secret-8cb97c4fb-x555q -- bash
# 也能查看到数据库的密码
root@secret-8cb97c4fb-x555q:/# cd /opt
root@secret-8cb97c4fb-x555q:/opt# ls
MYSQL_ROOT_PASSWORD
root@secret-8cb97c4fb-x555q:/opt# cat MYSQL_ROOT_PASSWORD
123456
1.从宿主机master上docker login到私有仓库,输入用户名密码,会在当前节点生成/root/.docker/config.json文件
2.创建secret
kubectl create secret docker-registry harbor \
--namespace=default \
--from-file=.dockerconfigjson=/root/.docker/config.json \
--docker-server=harbor.bertwu.online \
--docker-username=admin \
--docker-password=Harbor12345
其中harbor为创建出的secrets名,可修改
–name-space 指定项目名称空间
–from-file指定宿主机的config.json路径
–docker-server填写第一步中指定的仓库地址
–docker-username指定用户名
–docker-password指定密码
–docker-email 可选
3.创建资源清单
root@k8s-master ~]# cat tomcat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat
spec:
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
imagePullSecrets:
- name: harbor # 指定自己创建的secret
containers:
- name: tomcat
image: harbor.bertwu.online/beijing/tomcat:latest
imagePullPolicy: IfNotPresent
4.应用资源
[root@k8s-master ~]# kubectl apply -f tomcat.yaml
deployment.apps/tomcat created
#查看资源
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat-799bd68685-ncbf5 0/1 ContainerCreating 0 5s
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat-799bd68685-ncbf5 0/1 ContainerCreating 0 15s
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat-799bd68685-ncbf5 1/1 Running 0 88s
Service Account用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中。
# 容器内存放证书的目录
/run/secrets/kubernetes.io/serviceaccount
# 查看secret存储卷的帮助信息
[root@master-lm1 k8s]# kubectl create secret -h