一、ConfigMap
1. ConfigMap简介
在我们部署一些应用服务时,通常都会有一些配置文件,而在k8s中,我们如果在将这些配置文件写到代码应用程序中,需要修改配置的话,我们还得重新去修改代码,重新制作一个镜像,这样操作起来很麻烦。
还好kubernetes为我们提供了一个ConfigMap资源对象,它的主要作用就是为了让镜像和配置文件解耦,以便实现镜像的可移植性和可复用性,提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,还可以用来保存整个配置文件,我们只需要将配置文件以ConfigMap的方式挂载到应用Pod中,这样我们在更新配置信息的时候只需要更新这个ConfigMap对象即可。
ConfigMap使用场景:
- 通过环境变量的方式,直接传递给pod
- 通过在pod的命令行下运行的方式(启动命令中)
- 作为volume的方式挂载到pod内
2. 创建ConfigMap
2.1 通过目录创建
$ ls /app/web/configmap/kubectl/
ftp.properties
jdbc.properties
$ cat /app/web/configmap/kubectl/ftp.properties
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image
$ cat /app/web/configmap/kubectl/jdbc.properties
#database configuration
connection.url=jdbc:mysql://10.1.133.111:3306/web
connection.username=testdata
#connection.password=abcde
connection.password=SN9+koFJWHmf
创建Configmap对象
$ kubectl create configmap web-config --from-file=/app/web/configmap/kubectl
--from-file
:指定目录路径,该目录下的所有文件都会被用在ConfigMap里面创建一个键值对,键的名字就是文件名,值就是文件的内容。
查看Configmap信息
$ kubectl describe configmaps web-config
Name: web-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
ftp.properties:
----
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image
jdbc.properties:
----
#database configuration
connection.url=jdbc:mysql://10.1.133.111:3306/web
connection.username=testdata
#connection.password=abcde
connection.password=SN9+koFJWHmf
Events: <none>
如果配置文件信息较多的话,describe的输出信息会显示不全,我们可以使用以下命令来查看完整内容:
$ kubectl get configmaps web-config -o yaml
apiVersion: v1
data:
ftp.properties: |
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image
jdbc.properties: |
#database configuration
connection.url=jdbc:mysql://10.1.133.111:3306/web
connection.username=testdata
#connection.password=abcde
connection.password=SN9+koFJWHmf
kind: ConfigMap
metadata:
creationTimestamp: 2020-02-18T18:34:05Z
name: web-config
namespace: default
resourceVersion: "407"
selfLink: /api/v1/namespaces/default/configmaps/web-config
uid: 680944725-d62e-10e5-8cd0-68f123db1985
2.2 使用文件创建
$ kubectl create configmap web-config-2 --from-file=/app/web/configmap/kubectl/ftp.properties
$ kubectl get configmaps web-config-2 -o yaml
apiVersion: v1
data:
ftp.properties: |+
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image
kind: ConfigMap
metadata:
creationTimestamp: "2020-05-22T16:36:39Z"
name: web-config-2
namespace: default
resourceVersion: "33386795"
selfLink: /api/v1/namespaces/default/configmaps/web-config-2
uid: cffef22c-be55-4de3-8835-79195de8ec7e
--from-file
: 可以多次使用,指定多个文件
2.3 使用命令行创建
$ kubectl create configmap web-config-3 --from-literal=FTP_ADDRESS=192.168.133.11 --from-literal=FTP_PORT=21 --from-literal=FTP_USERNAME=ftpuser --from-literal=FTP_PASSWORD=ftpuser --from-literal=FTP_BASEPATH=/ --from-literal=IMAGE_BASE_URL=http://test.test.com/image
configmap/web-config-3 created
$ kubectl get configmap web-config-3 -o yaml
apiVersion: v1
data:
FTP_ADDRESS: 192.168.133.11
FTP_BASEPATH: /
FTP_PASSWORD: ftpuser
FTP_PORT: "21"
FTP_USERNAME: ftpuser
IMAGE_BASE_URL: http://test.test.com/image
kind: ConfigMap
metadata:
creationTimestamp: "2020-05-22T16:46:50Z"
name: web-config-3
namespace: default
resourceVersion: "33387937"
selfLink: /api/v1/namespaces/default/configmaps/web-config-3
uid: d69afbaf-0ac4-4405-a4ea-351ad613bdb4
--from-literal
:可以多次使用,指定多个值
3. 使用Configmp
3.1 使用ConfigMap来填充环境变量
编写Pod资源文件,使用上面名为web-config-3的configmap
apiVersion: v1
kind: Pod
metadata:
name: testweb-pod
spec:
containers:
- name: testweb
image: busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: FTP_ADDRESS
valueFrom:
configMapKeyRef:
name: web-config-3
key: FTP_ADDRESS #configmap的key值
- name: FTP_PORT
valueFrom:
configMapKeyRef:
name: web-config-3
key: FTP_PORT
envFrom:
- configMapRef:
name: web-config-3 #使用名为web-config-3的configmap对象
创建Pod并查看日志
$ kubectl logs -f testweb-pod
--------
FTP_ADDRESS=192.168.133.11
IDLE_LLAMA_NGINX_INGRESS_DEFAULT_BACKEND_PORT_80_TCP=tcp://10.98.12.71:80
PLUNDERING_MARMOT_NGINX_INGRESS_CONTROLLER_PORT_80_TCP_ADDR=10.108.129.64
FTP_PORT=21
MY_RELEASE_TOMCAT_PORT_80_TCP_ADDR=10.101.28.152
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
FTP_USERNAME=ftpuser
EXACERBATED_HEDGEHOG_NGINX_INGRESS_DEFAULT_BACKEND_SERVICE_PORT=80
PLUNDERING_MARMOT_NGINX_INGRESS_CONTROLLER_PORT_80_TCP=tcp://10.108.129.64:80
PLUNDERING_MARMOT_NGINX_INGRESS_CONTROLLER_PORT_443_TCP_ADDR=10.108.129.64
MYDB_MYSQL_SERVICE_PORT_MYSQL=3306
--------
3.2 使用ConfigMap设置命令行参数
apiVersion: v1
kind: Pod
metadata:
name: testweb2-pod
spec:
containers:
- name: testweb2
image: busybox
command: [ "/bin/sh", "-c", "echo $(FTP_ADDRESS) $(FTP_PORT)" ]
env:
- name: FTP_ADDRESS
valueFrom:
configMapKeyRef:
name: web-config-3
key: FTP_ADDRESS
- name: FTP_PORT
valueFrom:
configMapKeyRef:
name: web-config-3
key: FTP_PORT
查看Pod的输出信息
kubectl logs -f testweb2-pod
192.168.133.11 21
3.3 通过数据卷使用ConfigMap
apiVersion: v1
kind: Pod
metadata:
name: testweb3-pod
spec:
volumes:
- name: config-volume
configMap:
name: web-config-2
containers:
- name: testweb3
image: busybox
command: [ "/bin/sh", "-c", "cat /etc/config/ftp.properties" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
查看pod输出日志
$ kubectl logs -f testweb3-pod
FTP_ADDRESS=192.168.133.11
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/
IMAGE_BASE_URL=http://test.test.com/image
注意,当 ConfigMap 以数据卷的形式挂载进 Pod 的时,这时更新 ConfigMap(或删掉重建ConfigMap),Pod 内挂载的配置信息会热更新。这时可以增加一些监测配置文件变更的脚本,然后重新加载对应服务就可以实现应用的热更新。
二、Secret
1. Secret简介
一般情况下ConfigMap 是用来存储一些非安全的配置信息,因为ConfigMap是明文存储的,面对敏感信息时,我们就需要使用k8s的另一个对象Secret。
Secret用来保存敏感信息,例如密码、OAuth 令牌和 ssh key 等等,将这些信息放在 Secret 中比放在 Pod 的定义中或者 Docker 镜像中要更加安全和灵活。
Secret 主要使用的有以下三种类型:
- Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过base64 –decode解码得到原始数据,所有加密性很弱。
- kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息。
- kubernetes.io/service-account-token:用于被 ServiceAccount ServiceAccount 创建时 Kubernetes 会默认创建一个对应的 Secret 对象。Pod 如果使用了 ServiceAccount,对应的 Secret 会自动挂载到 Pod 目录 /run/secrets/kubernetes.io/serviceaccount 中。
bootstrap.kubernetes.io/token:用于节点接入集群的校验的 Secret
Secret对比ConfigMap
相同点
- key/value的形式
- 属于某个特定的命名空间
- 可以导出到环境变量
- 可以通过目录/文件形式挂载
- 通过 volume 挂载的配置信息均可热更新
不同点
- Secret 可以被 ServerAccount 关联
- Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像
- Secret 支持 Base64 加密
- Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三种类型,而 Configmap 不区分类型
2. Opaque Secret
2.1 手动创建Secret
$ echo -n "admin" | base64
YWRtaW4=
$ echo -n "adminpass" | base64
YWRtaW5wYXNz
Opaque 类型的数据是一个 map 类型,要求 value 必须是 base64 编码格式。
使用上面加密的编码编写Yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: YWRtaW5wYXNz
创建Secret
$ kubectl create -f secret-demo.yaml
secret/mysecret created
$ kubectl get secret
NAME TYPE DATA AGE
default-token-g7sqf kubernetes.io/service-account-token 3 219d
exacerbated-hedgehog-nginx-ingress-token-zrwpn kubernetes.io/service-account-token 3 174d
idle-llama-nginx-ingress-token-r2j5k kubernetes.io/service-account-token 3 174d
istio.default istio.io/key-and-cert 3 185d
mydb-mysql Opaque 2 181d
mysecret Opaque 2 6m13s
查看Secret信息
kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 9 bytes
username: 5 bytes
查看Secret详细信息
apiVersion: v1
data:
password: YWRtaW5wYXNz
username: YWRtaW4=
kind: Secret
metadata:
creationTimestamp: "2020-05-25T14:50:01Z"
name: mysecret
namespace: default
resourceVersion: "33864313"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: cf560ef9-eb67-4b3d-ac17-ed930e6799ce
type: Opaque
2.2 使用Secret作为环境变量
编写Yaml
apiVersion: v1
kind: Pod
metadata:
name: secret1-pod
spec:
containers:
- name: secret1
image: busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
secretKeyRef
:和前面Configmap定义相同,获取Secret的key值
创建Pod后查看日志输出
$ kubectl create -f testpod.yaml
pod/secret1-pod created
$ kubectl logs -f secret1-pod | grep USERNAME
USERNAME=admin
$ kubectl logs -f secret1-pod | grep PASSWORD
PASSWORD=adminpass
2.3 通过数据卷使用Secret
将Sercret挂载到Pod的/etc/secret路径下
apiVersion: v1
kind: Pod
metadata:
name: secret2-pod
spec:
containers:
- name: secret2
image: busybox
command: ["/bin/sh", "-c", "ls /etc/secrets"]
volumeMounts:
- name: secrets
mountPath: /etc/secrets
volumes:
- name: secrets
secret:
secretName: mysecret
创建Pod并查看日志输出
$ kubectl create -f testpod2.yaml
pod/secret2-pod created
$ kubectl logs -f secret2-pod
password
username
可以看到 Secret 把两个 key 以两个对应的文件挂载到了Pod中/etc/secret路径下,如果挂载到指定的文件上面,可以使用上面Configmap的数据卷挂载方式。
3. kubernetes.io/dockerconfigjson
3.1 创建Secret对象
这个类型的Secret对象用来创建建镜像仓库认证信息,如下:
$ kubectl create secret docker-registry harbor --docker-server=http://192.168.166.229 --docker-username=admin --docker-password=harbor123 --docker-email=test@163.com
secret/harbor created
查看创建的secret,注意Sercret对应的TYPE类型
$ kubectl get secret
NAME TYPE DATA AGE
default-token-g7sqf kubernetes.io/service-account-token 3 233d
exacerbated-hedgehog-nginx-ingress-token-zrwpn kubernetes.io/service-account-token 3 188d
harbor kubernetes.io/dockerconfigjson 1 66s
3.2 查看Secret信息
$ kubectl get secret harbor -o yaml
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyJodHRwOi8vMTkyLjE2OC4xNjYuMjI5Ijp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IkhhcmJvckAxYW4iLCJlbWFpbCI6InRlc3RAMTYzLmNvbSIsImF1dGgiOiJZV1J0YVc0NlNHRnlZbTl5UURGaGJnPT0ifX19
kind: Secret
metadata:
creationTimestamp: "2020-06-08T14:20:41Z"
name: harbor
namespace: default
resourceVersion: "36160653"
selfLink: /api/v1/namespaces/default/secrets/harbor
uid: 69f79c70-245a-4a91-b846-878a026e7ba6
type: kubernetes.io/dockerconfigjson
可以看到dockerconfigjson信息已经被加密了,我们可以使用base64解码查看
$ echo eyJhdXRocyI6eyJodHRwOi8vMTkyLjE2OC4xNjYuMjI5Ijp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IkhhcmJvckAxYW4iLCJlbWFpbCI6InRlc3RAMTYzLmNvbSIsImF1dGgiOiJZV1J0YVc0NlNHRnlZbTl5UURGaGJnPT0ifX19 | base64 -d
{"auths":{"http://192.168.166.229":{"username":"admin","password":"harbor123 ","email":"test@163.com","auth":"YWRtaW46SGFyYm9yQDFhbg=="}}}
3.3 Pod使用Secret对象
使用名为harbor的Secret拉取镜像:
apiVersion: v1
kind: Pod
metadata:
name: harbortest
spec:
containers:
- name: harbor
image: 192.168.166.229/test/node-exporter:latest
imagePullSecrets:
- name: harbor
查看Pod状态
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
harbortest 1/1 Running 0 2m26s
查看Pod创建过程,镜像是否符合定义
$ kubectl describe pod harbortest
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m2s default-scheduler Successfully assigned default/harbortest to kubesphere
Normal Pulling 2m57s kubelet, kubesphere Pulling image "192.168.166.229/test/node-exporter:latest"
Normal Pulled 2m57s kubelet, kubesphere Successfully pulled image "192.168.166.229/test/node-exporter:latest"
Normal Created 2m51s kubelet, kubesphere Created container harbor
Normal Started 2m51s kubelet, kubesphere Started container harbor
4.kubernetes.io/service-account-token
kubernetes.io/service-account-token
类型的Secret用于被 ServiceAccount (服务账户)引用。
Service Account:为Pod中的进程和外部用户提供身份信息。ServiceAccout 创建时 Kubernetes 会默认创建对应的 Secret。
集群创建时会创建一个默认的Service Account,
$ kubectl get sa
NAME SECRETS AGE
default 1 233d
$ kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-g7sqf
Tokens: default-token-g7sqf
Events: <none>
可以看到名为“default”的Service Account对应的service-account-token
为“default-token-g7sqf”,这是因为ServiceAccout 创建时 Kubernetes 会默认创建对应的 Secret。
然后我们查看之前创建pod的详细信息
$ kubectl describe pod web-0
.........................
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-g7sqf (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-g7sqf:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-g7sqf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events: <none>
可以看到创建的pod使用了名为“default-token-g7sqf”对应的service-account-token,这是因为我们使用kubectl
指令请求apiserver创建的时候,使用的Service Account服务账户为default
,而名为”default“ 的Service Account对应的service-account-token就是“default-token-g7sqf”。对应的 Secret 对象信息会通过 Volume 挂载到容器的/var/run/secrets/kubernetes.io/serviceaccount目录中。
关于Service Account 对象我会在下篇文章中详细解析,欢迎关注。