Kubernetes配置管理
ConfigMap
许多应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息的需求,这些配置信息我们肯定不会直接写死到应用程序中,这样不方便修改配置
1.ConfigMap编写语法格式
kind: ConfigMap
apiVersion: v1
metadata:
name: cm-demo
namespace: default
data:
data1: |
...
data2: >
...
data3: value
我们可以在data的下面进行编写配置我们所需要的内容,上面我们可以看到三种编写的格式,它们的区别如下:
|:yaml中表示保留换行,每行的缩进和行尾空白都会被去掉,而额外的缩进会被保留。
data1: |
我是第一行
我是第二行
我是第三行
我是第四行
我是第五行
#转化为JSON如下
{"lines": "我是第一行\n我是第二行\n 我是第三行\n 我是第四行\n我是第五行"}
>:号,用来表示折叠换行,只有空白行才会被识别为换行,原来的换行符都会被转换成空格。
data2: >
我是第一行
我也是第一行
我仍是第一行
我是第二行
我也是第二行
#转化为JSON如下
{"lines": "我是第一行 我也是第一行 我仍是第一行\n我是第二行 我也是第二行"}
2.ConfigMap的使用
资源清单编写如下:
#configmap-test.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: config-test
namespace: default
data:
mysql.conf: |
host=100.100.10.101
port=3306
redis.conf: |
host=100.100.10.102
port=6379
---
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
volumes:
- name: config-volume
configMap:
name: config-test
containers:
- name: test
image: busybox
command: [ "/bin/sh", "-c", "cat /etc/config/redis.conf" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config/redis.conf
subPath: redis.conf
使用apply创建并查看test容器的日志
[root@master ~]# kubectl apply -f configmap-test.yaml
configmap/config-test created
pod/test created
[root@master ~]# kubectl logs test
host=100.100.10.102
port=6379
我们也可以在ConfigMap值被映射的数据卷里去控制路径
#configmap-test2.yaml
apiVersion: v1
kind: Pod
metadata:
name: test2
spec:
volumes:
- name: config-volume
configMap:
name: config-test
items:
- key: mysql.conf
path: test/msyql.conf
containers:
- name: test2
image: busybox
command: ["/bin/sh","-c","cat /etc/config/test/msyql.conf"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
再使用apply创建并查看test2容器的日志
[root@master ~]# kubectl apply -f configmap-test2.yaml
pod/test2 created
[root@master ~]# kubectl logs test2
host=100.100.10.101
port=3306
注意:在使用ConfigMap的时候应该先用volumes声明挂载,再挂载到容器中使用!!!
3.通过命令来创建ConfigMap
#创建名为my-config,从/etc/nginx/conf.d目录下的文件获取内容
kubectl create configmap my-config --from-file=/etc/nginx/conf.d
#创建名为my-config,data1的内容从/etc/mysql.conf文件获取,data2的内容从/etc/redis.conf文件获取
kubectl create configmap my-config --from-file=data1=/etc/mysql.conf --from-file=data2=/etc/redis.conf
Secret
用来保存敏感信息,例如密码、OAuth令牌和ssh key等等,将这些信息放在Secret中比放在Pod的定义中或者Docker镜像中要更加安全和灵活。
Secret的分类:
- Opaque Secret(base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过 base64 –decode 解码得到原始数据,所有加密性很弱。)
- dockerconfigjson(用来存储私有 docker registry 的认证信息,~/.docker/config.json 文件的序列化形式)
- basic-auth(用于基本身份认证的凭据)
- ssh-auth(用于 SSH 身份认证的凭据)
- tls(该类型用来存放证书及其相关密钥,通常用在 TLS 场合。此类数据主要提供给 Ingress 资源,用以校验 TLS 链接)
- service-account-token(用于 ServiceAccount, ServiceAccount 创建时 Kubernetes 会默认创建一个对应的 Secret 对象,Pod 如果使用了 ServiceAccount,对应的 Secret 会自动挂载到 Pod 目录 /run/secrets/kubernetes.io/serviceaccount 中)
1.Opaque Secret
该Secret资源包含两种健值对:data和stringData,data用来存储 base64 编码的任意数据,stringData允许 Secret 使用未编码的字符串。它们的值必须由字母、数字、-,_ 或 . 组成。
例如创建一个用户名为 admin,密码为 test123的Secret对象:
echo -n "admin" | base64
YWRtaW4=
echo -n "test123" | base64
dGVzdDEyMw==
资源清单编写如下:
# secret-opaque.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: dGVzdDEyMw==
创建secret资源并查看
[root@master ~]# kubectl apply -f secret-demo.yaml
secret/mysecret created
[root@master ~]# kubectl get secret
NAME TYPE DATA AGE
default-token-gmh9l kubernetes.io/service-account-token 3 1d
mysecret Opaque 2 43s
[root@master ~]# kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 7 bytes
username: 5 bytes
[root@master ~]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
password: dGVzdDEyMw==
username: YWRtaW4=
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"password":"dGVzdDEyMw==","username":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"},"type":"Opaque"}
creationTimestamp: "2023-10-17T09:17:38Z"
name: mysecret
namespace: default
resourceVersion: "382393338"
uid: a044c521-7a2a-478b-a9aa-5a7ffcfe4d60
type: Opaque
环境变量使用
资源清单编写如下:
#secret-test1.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: secret-test1
spec:
template:
spec:
containers:
- name: secret-test1
image: busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
创建资源对象并查看日志
[root@master ~]# kubectl apply -f secret-test1.yaml
job.batch/secret-test1 created
[root@master ~]# kubectl logs secret-test1-2jh8r
USERNAME=admin
PASSWORD=test123
这里能够看到有 USERNAME 和 PASSWORD 两个环境变量输出出来
挂载使用
资源清单编写如下:
#secret-test2.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: secret-test2
spec:
template:
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
- name: secret-test2
image: busybox
command: [ "/bin/sh", "-c", "ls /etc/secrets" ]
volumeMounts:
- name: secrets
mountPath: /etc/secrets
创建资源对象并查看日志
[root@master ~]# kubectl apply -f secret-test2.yaml
job.batch/secret-test2 created
[root@master ~]# kubectl logs secret-test2-hq9sm
password
username
这里我们能够看到 Secret 把两个 key 挂载成了两个对应的文件
2.dockerconfigjson
该Secret资源可以用来创建用户作为docker仓库的认证,从而拉取镜像。
使用命令创建
kubectl create secret docker-registry mytest --docker-server=docker.registry.com --docker-username=admin --docker-password=password --docker-email=registry@email.com
除了上面的方法,还可以指定文件的方式来创建镜像仓库认证信息
kubectl create secret generic mytest --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson
创建好了之后查看Secret列表以及两个Secret的详细信息:
# 查看Secret列表
[root@master ~]# kubectl get secret
NAME TYPE DATA AGE
default-token-gmh9l kubernetes.io/service-account-token 3 1d
mytest kubernetes.io/dockerconfigjson 1 2m53s
mytest1 kubernetes.io/dockerconfigjson 1 7s
#查看第一种方式创建的secret,名为mytest
[root@master ~]# kubectl describe secret mytest
Name: mytest
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/dockerconfigjson
Data
====
.dockerconfigjson: 135 bytes
[root@master ~]# kubectl get secret mytest -o yaml
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyJkb2NrZXIucmVnaXN0cnkuY29tIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6InBhc3N3b3JkIiwiZW1haWwiOiJyZWdpc3RyeUBlbWFpbC5jb20iLCJhdXRoIjoiWVdSdGFXNDZjR0Z6YzNkdmNtUT0ifX19
kind: Secret
metadata:
creationTimestamp: "2023-10-18T03:48:00Z"
name: mytest
namespace: default
resourceVersion: "382782494"
uid: 1828f509-b9c6-4678-b2d6-6a6bd73fd98e
type: kubernetes.io/dockerconfigjson
#查看第二种方式创建的secret,名为mytest
[root@master ~]# kubectl describe secret mytest1
Name: mytest1
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/dockerconfigjson
Data
====
.dockerconfigjson: 151 bytes
[root@master ~]# kubectl get secret mytest1 -o yaml
apiVersion: v1
data:
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSJyZWdpc3RyeS0xLmRvY2tlci5pbyI6IHt9LAoJCSJzd3IuY24tc291dGgtMS5teWh1YXdlaWNsb3VkLmNvbSI6IHt9Cgl9LAoJImNyZWRzU3RvcmUiOiAiZGVza3RvcCIsCgkiY3VycmVudENvbnRleHQiOiAiZGVza3RvcC1saW51eCIKfQ==
kind: Secret
metadata:
creationTimestamp: "2023-10-18T03:50:46Z"
name: mytest1
namespace: default
resourceVersion: "382783463"
uid: f796fdce-47c0-4d9f-8ce1-32aad942e037
type: kubernetes.io/dockerconfigjson
之后,做一个base64的解码,查看data.dockerconfigjson里面的数据:
# mytest的base64解码数据
[root@master ~]# echo eyJhdXRocyI6eyJkb2NrZXIucmVnaXN0cnkuY29tIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6InBhc3N3b3JkIiwiZW1haWwiOiJyZWdpc3RyeUBlbWFpbC5jb20iLCJhdXRoIjoiWVdSdGFXNDZjR0Z6YzNkdmNtUT0ifX19 |base64 -d
{"auths":{"docker.registry.com":{"username":"admin","password":"password","email":"registry@email.com","auth":"YWRtaW46cGFzc3dvcmQ="}}}
# mytest1的base64解码数据
[root@master ~]# echo ewoJImF1dGhzIjogewoJCSJyZWdpc3RyeS0xLmRvY2tlci5pbyI6IHt9LAoJCSJzd3IuY24tc291dGgtMS5teWh1YXdlaWNsb3VkLmNvbSI6IHt9Cgl9LAoJImNyZWRzU3RvcmUiOiAiZGVza3RvcCIsCgkiY3VycmVudENvbnRleHQiOiAiZGVza3RvcC1saW51eCIKfQ== |base64 -d
{
"auths": {
"registry-1.docker.io": {},
"swr.cn-south-1.myhuaweicloud.com": {}
},
"credsStore": "desktop",
"currentContext": "desktop-linux"
}
从镜像仓库拉取镜像
资源清单编写如下:
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: docker.registry.com/test/test:v1
imagePullSecrets:
- name: mytest
3.basic-auth
该Secret时用来存放基本身份认证所需的凭证信息,该Secret的data字段必须包含以下两个键值对:
- username:用于身份认证的用户名
- password:用于身份认证的密码或令牌
当键值对为base64编码的字符串时,资源清单编写如下:
# secret-basic.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret-basic-auth
type: kubernetes.io/basic-auth
Data:
username: YWRtaW4=
password: dGVzdDEyMw==
当键值对为明文形式内容时,资源清单编写如下:
# secret-basic.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
username: admin
password: test123
4.ssh-auth
该Secret时用来存放SSH身份认证中所需要的凭据。
资源清单编写如下:
# secret-ssh.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret-ssh-auth
type: kubernetes.io/ssh-auth
data:
ssh-privatekey: |
MIIEpQIBAAKCAQEAulqb/Y ...
data下的值都为base64编码,具体内容需要base64解码之后查看
5.tls
该Secret时用来存放证书以及相关密钥(通常在TLS场合使用),主要提供给Ingress资源使用。
使用命令通过读取cert和key文件来创建:
kubectl create secret tls my-tls-secret \
--cert=/secret/cert/file \
--key=/secret/key/file
注意:用于--cert的公钥证书必须是.PEM编码的(Base64编码的DER格式),且与--key所给定的私钥匹配。
也可以通过yaml创建,资源清单编写如下:
# secret-tls.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret-tls
type: kubernetes.io/tls
data:
tls.crt: |
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVRRENDQX ...
tls.key: |
LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUU ...
data下的值都为base64编码,具体内容需要base64解码之后查看
6.service-account-token
该Secret在k8s创建时会默认创建一个,如下:
[root@master ~]# kubectl get secret
NAME TYPE DATA AGE
default-token-gmh9l kubernetes.io/service-account-token 3 1d
我们随便查看一个pod的详细信息:
[root@master ~]# kubectl get pod nginx-664b67cc86-fzbwv -o yaml
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-zhdd8
readOnly: true
......
serviceAccount: default
serviceAccountName: default
volumes:
- name: kube-api-access-zhdd8
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
当我们创建pod的时候,如果没有指定ServiceAccount,pod会使用命名空间中名为 default 的ServiceAccount,如上面所示。
还可以看到被Volume挂载到了容器的/var/run/secrets/kubernetes.io/serviceaccount目录下,这里我们挂载了一个downwardAPI来获取 namespace,通过ConfigMap来获取ca.crt证书,然后还有一个serviceAccountToken类型的数据源。
所以默认情况下当前namespace下面的pod会默认使用default这个ServiceAccount,对应的Secret会自动挂载到pod的/var/run/secrets/kubernetes.io/serviceaccount目录中,这样我们就可以在pod里面获取到用于身份认证的信息了。
我们可以使用自动挂载给Pod的ServiceAccount凭据访问API,我们也可以通过在 ServiceAccount 上设置automountServiceAccountToken: false来实现不给ServiceAccount自动挂载 API 凭据,资源清单编写如下:
apiVersion: v1
kind: ServiceAccount
metadata:
name: serviceaccount-demo
automountServiceAccountToken: false
...
也可以选择不给特定的pod自动挂载API凭据,资源清单编写如下:
apiVersion: v1
kind: Pod
metadata:
name: serviceaccount-pod
spec:
serviceAccountName: serviceaccount-demo
automountServiceAccountToken: false
...
注意:如果pod和ServiceAccount都指定了automountServiceAccountToken值,则pod优先于ServiceAccount