k8s系列之九Secret 与Configmap
在应用启动过程中需要一些敏感信息,比如数据库用户名、密码,如果直接明文存储在容器镜像中是不安全的,K8S提供的方案是Secret。
在应用启动过程中需要一些敏感信息,比如数据库用户名、密码,如果直接明文存储在容器镜像中是不安全的,K8S提供的方案是Secret。
1.1 创建与查看Secret
Secret会以密文的方式存储数据,避免了直接在配置文件中保存敏感信息。Secret会以Volume的形式被mount到Pod,容器可通过文件的方式使用Secret中的敏感数据;此外,容器也可以环境变量的方式使用这些数据。
Secret可通过命令行或YAML创建。比如希望Secret中包含如下信息:用户名admin、密码123456。
这里假设我们要创建一个包含以下信息的Secret:用户名:Test 密码:Test123456*
有4种方法来创建Secret:
(1)通过 --from-literal:
kubectl create secret generic mysecret --from-literal=username=Test--from-literal=password=Test123456*
PS:每个 --from-literal 对应一个信息条目
(2)通过 --from-file:
echo -n Test> ./username
echo -n Test123456* > ./password
kubectl create secret generic mysecret --from-file=./username --from-file=./password
PS:每个文件内容对应一个信息条目
(3)通过 --from-env-file:
cat << EOF > env.txt
username=Test
password=Test123456*
EOF
kubectl create secret generic mysecret --from-env-file=env.txt
PS:文件 env.txt 中每行 Key=Value 对应一个信息条目
(4)通过YAML配置文件创建:(推荐方式)
由于配置文件中的敏感数据必须是通过base64编码后的结果,因此需要获取base64编码后的值:
[root@k8s-master ~]# echo -n Test | base64
VGVzdA==
[root@k8s-master ~]# echo -n Test123456* | base64
VGVzdDEyMzQ1Nio=
[root@k8s-master ~]#
vi secret-demo.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
data:
username: VGVzdA==
password: VGVzdDEyMzQ1Nio=
通过kubectl get secret查看存在的secret。
通过kubectl describe secret查看条目的Key。
[root@k8s-master ~]# vi secret-demo.yaml
[root@k8s-master ~]# kubectl apply -f secret-demo.yaml
secret/mysecret created
[root@k8s-master ~]# kubectl get secret mysecret
NAME TYPE DATA AGE
mysecret Opaque 2 16s
[root@k8s-master ~]# kubectl describe serect myserect
error: the server doesn't have a resource type "serect"
[root@k8s-master ~]# kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations:
Type: Opaque
Data
====
password: 11 bytes
username: 4 bytes
通过kubectl edit secret mysecret 查看value,然后通过base64将Value反编码。
password: VGVzdDEyMzQ1Nio=
username: VGVzdA==
[root@k8s-master ~]# echo -n VGVzdA== | base64 --decode
Test[root@k8s-master ~]# echo -n VGVzdDEyMzQ1Nio= | base64 --decode
Test123456*[root@k8s-master ~]#
1.2 在Pod中使用Secret
K8S中Pod中使用Secret有两种方式,一是Volume方式,二是环境变量的方式。
(1)Volume方式
这里我们以一个示例演示一下如何通过Volume方式使用Secret,首先定义一个Pod:
vi secret-demo-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-demo-pod
spec:
containers:
- name: secret-demo-pod
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
该Pod中会使用到刚刚定义的secret(edc-secret),然后volumeMounts定义了将foo mount到容器中的路径为/etc/foo的目录下,并且指定了读写权限为只读。
通过kubectl apply创建之后,我们试着在容器中读取secret来验证一下
[root@k8s-master ~]# kubectl apply -f secret-demo-pod.yaml
pod/secret-demo-pod created
[root@k8s-master ~]# kubectl exec -it secret-demo-pod /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
/ # ls /etc/foo/
password username
/ # cat /etc/foo/password
Test123456*/ #
/ # cat /etc/foo/username
Test/ #
我们也可以自定义存放数据的文件名。
apiVersion: v1
kind: Pod
metadata:
name: secret-demo-pod
spec:
containers:
- name: secret-demo-pod
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: edc-secret
items:
- key: username
path: /my-group/username
- key: password
path: /my-group/password
这时数据将分别存放在/etc/foo/my-group/my-username和/etc/foo/my-group/my-password中。
以Volume方式使用的Secret支持动态更新:Secret更新后,容器中的数据也会更新将password更新为abcdef,base64编码为YWJjZGVm。
几秒钟后,新的password会同步到容器。
[root@k8s-master ~]# vi secret-demo.yaml
[root@k8s-master ~]# kubectl apply -f secret-demo.yaml
secret/mysecret configured
[root@k8s-master ~]# kubectl exec -it secret-demo-pod /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
/ # cat /etc/foo/password
abcdefg/ #
1.3 环境变量⽅式
通过Volume使用Secret看起来稍微麻烦了一点,容器必须通过文件读取数据。K8S提供了另外一种方式,那就是环境变量方式。
下面仍以上面的例子为例,修改配置文件:
vi secret-demo-pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-demo-pod
spec:
containers:
- name: secret-demo-pod
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
env:
- name: MY_SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: MY_SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
通过环境变量SECRET_USERNAME和SECRET_PASSWORD成功读取到Secret的数据。
需要注意的是,环境变量读取Secret很方便,但无法支撑Secret动态更新。
[root@k8s-master ~]# vi secret-demo-pod2.yaml
[root@k8s-master ~]# kubectl apply -f secret-demo-pod2.yaml
pod/secret-demo-pod2 created
[root@k8s-master ~]# kubectl exec -it secret-demo-pod2 /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
/ # echo $MY_SECRET_USERNAME
Test
/ # echo $MY_SECRET_PASSWORD
abcdefg
1.4 使用Configmap
Secret可以为Pod提供密码、Token、私钥等敏感数据;对于⼀些非敏感数据,比如应用的配置信息,则可以用ConfigMap。
ConfigMap的创建和使用⽅式与Secret非常类似,主要的不同是数据以明文的形式存放。
和Secret一样,也可以通过Volume 或 环境变量两种方式来使用Configmap。
(1)Volume方式
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo
spec:
containers:
- name: configmap-demo-pod
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
configMap:
name: service-configmap
(2)环境变量方式
apiVersion: v1
kind: Pod
metadata:
name: secret-demo
spec:
containers:
- name: secret-demo-pod
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
env:
- name: SERVICE_LOG_LEVEL
valueFrom:
configMapKeyRef:
name: service-configmap
key: LogLevel
- name: SERVICE_LOG_FILE
valueFrom:
configMapKeyRef:
name: service-configmap
key: LogFile
- name: SERVICE_ALLOWED_HOSTS
valueFrom:
configMapKeyRef:
name: service-configmap
key: AllowedHosts
大多数情况下,大家建议的最佳实践是:
(1)创建ConfigMap采用YAML配置方式 => 便于复用和版本管理
(2)读取ConfigMap采用Volume方式 => 便于配置动态更新
更多推荐
所有评论(0)