Secret 资源
用于保存密码文件、tls证书/私钥文件、token令牌字符串、镜像私有仓库认证信息 等需要加密的敏感的信息
Secret资源的 4 种类型
- Opaque:默认的Secret资源类型,可以通过选项引用文件、目录、键值对的方式创建Secret资源,并且资源数据的键值会自动转换成base64编码格式
- kubernetes.io/tls:用于存储 tls 证书和私钥文件的信息
- kubernetes.io/dockerconfigjson:用于存储K8S从harbor等镜像私有仓库拉取镜像时做认证的信息
- kubernetes.io/service-account-token:当创建serviceaccount账户资源后K8S会自动创建相关的Secret资源,当Pod访问apiserver时需要使用此Secret资源做认证
Pod 需要先引用才能使用某个 secret,Pod 有 3 种方式来使用 secret:
●作为挂载到一个或多个容器上的卷 中的文件。
●作为容器的环境变量。
●由 kubelet 在为 Pod 拉取镜像时使用。
应用场景:凭据
https://kubernetes.io/docs/concepts/configuration/secret/
创建 Secret资源
kubectl create secret generic|tls|docker-registry <资源名称> 选项 generic <资源名称> --from-file=文件|目录 --from-literal=<键名>=<键值> tls <资源名称> --cert=证书文件路径 --key=私有文件路径 docker-registry <资源名称> --docker-server=私有仓库URL地址 --docker-username=用户名 --docker-password=密码 --docker-email=邮箱
使用 Secret资源
挂载的方式
在 Pod 资源配置中的 spec.volumes 字段设置 secret 类型的存储卷
在容器配置中用volumeMounts将卷挂载到容器的挂载点目录上,Secret资源数据的键名会作为文件名,Secret资源数据的键值会作为文件内容容器环境变量引用的方式
在容器配置中用 env.name 字段自定义容器的环境变量名,在 env.valueFrom.secretKeyRef.name/key 字段指定自定义的变量的值从哪个 Secret资源 的 键 获取 值
在容器配置中用 envFrom.secretRef.name 字段指定 Secret资源的名称,使得 Secret资源的 键 和 值 直接作为容器的环境变量名和环境变量的值
创建 Secret (Opaque类型)
方法1 陈述式 自动转码
1、用kubectl create secret命令创建Secret
echo -n 'zhangsan' > username.txt echo -n 'abc1234' > password.txt
根据文件内容生成secret
kubectl create secret generic mysecret --from-file=username.txt --from-file=password.txt
kubectl get secrets NAME TYPE DATA AGE default-token-8pqp6 kubernetes.io/service-account-token 3 3d1h mysecret Opaque 2 51s
kubectl describe secret mysecret Name: mysecret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password.txt: 7 bytes username.txt: 8 bytes
//get或describe指令都不会展示secret的实际内容,这是出于对数据的保护的考虑
方法2 声明式 注意声明式需要先手动转码!!! 不然明文保存
内容用 base64 编码,创建Secret
使用echo输出到base64查看转码后结果 echo -n zhangsan | base64 emhhbmdzYW4K= echo -n abc1234 | base64 YWJjMTIzNAo==
将base64转码后的结构写入yaml文件 vim secret.yaml apiVersion: v1 kind: Secret metadata: name: mysecret1 type: Opaque data: username: emhhbmdzYW4K= password: YWJjMTIzNAo==
kubectl create -f secret.yaml
由于是base64编码,所以密码可以反推,也不是足够安全。
kubectl get secrets NAME TYPE DATA AGE default-token-8pqp6 kubernetes.io/service-account-token 3 3d1h mysecret Opaque 2 43m mysecret1 Opaque 2 6s
kubectl get secret mysecret1 -o yaml apiVersion: v1 data: password: YWJjMTIzNAo== username: emhhbmdzYW4K= kind: Secret metadata: creationTimestamp: 2021-05-24T09:11:18Z name: mysecret1 namespace: default resourceVersion: "45641" selfLink: /api/v1/namespaces/default/secrets/mysecret1 uid: fffb7902-bc6f-11eb-acba-000c29d88bba type: Opaque
创建 Secret (tls类型)
这里使用陈述式创建。tls类型需要指定证书以及秘钥。
cd /etc/kubernetes/pki #k8s证书文件夹 kubectl create secret tls ca-secret --cert=./ca.crt --key=./ca.key #根据证书创建tls类型secret
创建 Secret (docker-registry类型)
这里使用陈述式创建。docker-registry类型指定harbor服务器ip,用户,密码,邮箱 。用于从harbor仓库拉取镜像时做认证。
kubectl create secret docker-registry harbor-secret --docker-server=http://192.168.80.105 --docker-username=admin --docker-password=Harbor123456 --docker-email=admin@gmail.com
创建后使用时需要在yaml文件进行更改,添加imagepullsecret指定刚刚创建的 docker-registry类型的secret。这样就能拉取仓库中需要登录信息才能获取的镜像。
注意,secret也存在命名空间。若创建的资源(例如pod.yaml内 容器需要拉取私有镜像)与docker-registry不处于同一个命名空间,拉取仍然会因为没有认证信息而失败。-n 指定命名空间
使用方式
1、挂载使用方式
将 Secret 挂载到 Volume 中,以 Volume 的形式挂载到 Pod 的某个目录下
vim secret-test.yaml apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: nginx image: nginx volumeMounts: - name: secrets #挂载name为secret的存储卷 mountPath: "/etc/secrets" readOnly: true volumes: #存储卷 - name: secrets secret: #secret方式 secretName: mysecret #刚刚创建的secret资源name
kubectl create -f secret-test.yaml
kubectl get pods NAME READY STATUS RESTARTS AGE seret-test 1/1 Running 0 16s
kubectl exec -it seret-test bash # cd /etc/secrets/ # ls password.txt username.txt # vi password.txt # vi username.txt
可见外部加密的信息,挂载后自动解密。
2、变量使用方式
将 Secret 导出到环境变量中
vim secret-test1.yaml apiVersion: v1 kind: Pod metadata: name: mypod1 spec: containers: - name: nginx image: nginx env: #环境变量 - name: TEST_USER valueFrom: #名为TEST_USER的环境变量的取值,从secret取 secretKeyRef: #secretKeyRef引用方式 name: mysecret1 #指明引用哪个secret资源 key: username #指明引用的secret中的键 - name: TEST_PASSWORD valueFrom: secretKeyRef: name: mysecret1 key: password envFrom: #也可以不用上面先自定义环境变量name,再从secret中选择键的值为其赋值。而是直接使用secret中的键值对作为环境变量的name与key。 - secretRef: name: mysecret1 #指明引用哪个secret资源
kubectl apply -f secret-test1.yaml
kubectl get pods NAME READY STATUS RESTARTS AGE mypod1 1/1 Running 0 77s
kubectl exec -it mypod bash # echo $TEST_USER zhangsan # echo $TEST_PASSWORD abc1234
ConfigMap资源
ConfigMap 资源 (简称 cm)
用于保存 配置文件 环境变量 命令行参数 之类的不需要加密的信息
创建 cm资源
kubectl create cm <资源名称> --from-file=文件|目录 --from-literal=<键名>=<键值>
查看 cm资源
kubectl get cm <资源名称> -o yaml 或 kubectl describe cm <资源名称>
使用 cm资源
挂载的方式
在 Pod 资源配置中的 spec.volumes 字段设置 configMap 类型的存储卷
在容器配置中用volumeMounts将卷挂载到容器的挂载点目录上,cm资源数据的键名会作为文件名,cm资源数据的键值会作为文件内容(以目录形式挂载的cm卷支持热更新)
在容器配置中用volumeMounts.subPath指定文件名,可实现将卷挂载到容器的文件上(以文件形式挂载的cm卷不支持热更新)容器环境变量引用的方式(不支持热更新)
在容器配置中用 env.name 字段自定义容器的环境变量名,在 env.valueFrom.configMapKeyRef.name/key 字段指定自定义的变量的值从哪个 cm资源 的 键 获取 值
在容器配置中用 envFrom.configMapRef.name 字段指定 cm资源的名称,使得 cm资源的 键 和 值 作为容器的环境变量名和环境变量的值
Pod 中使用 ConfigMap (通过挂载方式)
CM的简单示例,创建cm,挂载使用cm中的内容(挂载到容器内的目录,目录方式挂载),热更新
创建网页文件
echo "114514" > index.html
从这个文件创建cm
kubectl create cm myapp-cm --from-file=./index.html 更改index.html下的内容
创建pod,创建存储卷时引用刚刚的cm(cm存储了网页文件名以及网页内容),再让pod挂载,即为cm中内容挂载到了pod的网页发布目录,借由pod中nginx 发布。
但是注意,虽然这个cm里面只有一个文件,但是在此处并未指定文件方式挂载,而是默认的目录方式挂载,会把整个目录覆盖。若只需要覆盖某个文件,使用下方实例的文件挂载(加上subpath参数)。
并且支持热更新,只需要更改cm内容,即可实现对pod内资源更改,并不需要对pod本身进行更改
kubectl edit cm myapp-cm 更改index.html下的内容
CM的简单示例,挂载使用cm中的内容(挂载到容器内的文件,文件方式挂载)
事先准备好nginx.conf文件,写入cm。然后作为存储卷,让pod挂载。
kubectl create cm myapp-cm --from-file=./nginx.conf
由于此时并不能像上一个实例一样覆盖掉整个文件夹,需要只单独覆盖一个文件,所以此时需要加上subPath选项,让系统识别目录中的子文件。
注意,挂载如果使用subpath选项 默认认为是目录,无论文件后缀
另外,像这种文件方式挂载,无法进行热更新(目录挂载可以)
完整的创建 ConfigMap 方法
1、使用目录创建
mkdir /opt/configmap/
vim /opt/configmap/game.config enemy.types=aliens,monsters player.maximum-lives=5
vim /opt/configmap/ui.config color.good=purple color.bad=yellow allow.textmode=true
ls /opt/configmap/ game.config ui.config
kubectl create configmap game-config --from-file=/opt/configmap/
--from-file 指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容
kubectl get cm NAME DATA AGE game-config 2 10s kubectl get cm game-config -o yaml apiVersion: v1 data: game.config: | enemy.types=aliens,monsters player.maximum-lives=5 ui.config: | color.good=purple color.bad=yellow allow.textmode=true kind: ConfigMap metadata: creationTimestamp: 2021-05-25T06:49:18Z name: game-config namespace: default resourceVersion: "87803" selfLink: /api/v1/namespaces/default/configmaps/game-config uid: 541b5302-bd25-11eb-acba-000c29d88bba
2、使用文件创建
只要指定为一个文件就可以从单个文件中创建 ConfigMap
--from-file 这个参数可以使用多次,即可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的kubectl create configmap game-config-2 --from-file=/opt/configmap/game.properties --from-file=/opt/configmap/ui.properties
kubectl get configmaps game-config-2 -o yaml
kubectl describe cm game-config-2
3、使用字面值创建
使用文字值创建,利用 --from-literal 参数传递配置信息,该参数可以使用多次,格式如下kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=good
kubectl get configmaps special-config -o yaml apiVersion: v1 data: special.how: very #key-value 结构 special.type: good kind: ConfigMap metadata: creationTimestamp: 2021-05-25T06:59:37Z name: special-config namespace: default resourceVersion: "88610" selfLink: /api/v1/namespaces/default/configmaps/special-config uid: c4f45936-bd26-11eb-acba-000c29d88bba
kubectl delete cm --all kubectl delete pod --all
Pod 中使用 ConfigMap (通过环境变量方式)
1、使用 ConfigMap 来替代环境变量
创建ConfigMap配置文件vim env.yaml apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very special.type: good --- apiVersion: v1 kind: ConfigMap metadata: name: env-config namespace: default data: log_level: INFO 上方yaml文件也可以用命令代替(陈述式与声明式写法区别) kubectl create cm special-config --from-literal=special.how=very --from-literal=special.type=good kubectl create cm env-config --from-literal=log_level=INFO
kubectl create -f env.yaml
kubectl get cm NAME DATA AGE env-config 1 6s special-config 2 6s
创建Pod调用ConfigMap资源
vim test-pod.yaml apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - name: busybox image: busybox:1.28.4 command: [ "/bin/sh", "-c", "env" ] env: #定义环境变量,定义名称,值则来自cm - name: SPECIAL_HOW_KEY valueFrom: configMapKeyRef: #引用CM name: special-config #上面创建CM的名字 key: special.how #CM中的键 - name: SPECIAL_TYPE_KEY valueFrom: configMapKeyRef: #引用CM name: special-config #上面创建CM的名字 key: special.type #CM中的键 envFrom: #或者直接把cm内的值作为容器的变量,键值全部从cm取,而不是上面env的键自定义,只有值从cm取 - configMapRef: #引用CM name: env-config restartPolicy: Never
kubectl create -f test-pod.yaml
kubectl get pods NAME READY STATUS RESTARTS AGE pod-test 0/1 Completed 0 33s
kubectl logs pod-test KUBERNETES_SERVICE_PORT=443 KUBERNETES_PORT=tcp://10.0.0.1:443 HOSTNAME=pod-test SHLVL=1 SPECIAL_HOW_KEY=very #赋值变量 SPECIAL_HOW_KEY 的值为 special-config 的 special.how: very HOME=/root SPECIAL_TYPE_KEY=good #赋值变量 SPECIAL_TYPE_KEY 的值为 special-config 的 special.type: good KUBERNETES_PORT_443_TCP_ADDR=10.0.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 log_level=INFO #引入 env-config 的变量 log_level: INFO KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_SERVICE_HOST=10.0.0.1 PWD=/
注意这种环境变量方式也不支持热更新。只有文件挂载的目录挂载才可以热更新
2、用 ConfigMap 设置命令行参数vim test-pod2.yaml apiVersion: v1 kind: Pod metadata: name: test-pod2 spec: containers: - name: busybox image: busybox:1.28.4 command: - /bin/sh - -c - echo "$(SPECIAL_HOW_KEY) $(SPECIAL_TYPE_KEY)" env: - name: SPECIAL_HOW_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name: SPECIAL_TYPE_KEY valueFrom: configMapKeyRef: name: special-config key: special.type envFrom: - configMapRef: name: env-config restartPolicy: Never
kubectl create -f test-pod2.yaml
kubectl get pods NAME READY STATUS RESTARTS AGE test-pod2 0/1 Completed 0 34s
kubectl logs test-pod2 very good
3、通过数据卷插件使用ConfigMap
在数据卷里面使用 ConfigMap,就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容vim test-pod3.yaml apiVersion: v1 kind: Pod metadata: name: test-pod3 spec: containers: - name: busybox image: busybox:1.28.4 command: [ "/bin/sh", "-c", "sleep 36000" ] volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: special-config restartPolicy: Never
kubectl create -f test-pod3.yaml
kubectl get pod NAME READY STATUS RESTARTS AGE test-pod3 1/1 Running 0 5s
kubectl exec -it test-pod3 sh # cd /etc/config/ # ls special.how special.type # vi special.how # vi special.type
ConfigMap 的热更新
vim test-pod4.yaml apiVersion: v1 kind: ConfigMap metadata: name: log-config namespace: default data: log_level: INFO --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-nginx spec: replicas: 1 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: log-config
kubectl apply -f test-pod5.yaml
kubectl get pods NAME READY STATUS RESTARTS AGE my-nginx-76b6489f44-6dwxh 1/1 Running 0 46s
kubectl exec -it my-nginx-76b6489f44-6dwxh -- cat /etc/config/log_level INFO
kubectl edit configmap log-config apiVersion: v1 data: log_level: DEBUG #INFO 修改成 DEBUG kind: ConfigMap metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","data":{"log_level":"DEBUG"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"log-config","namespace":"default"}} #INFO 修改成 DEBUG creationTimestamp: 2021-05-25T07:59:18Z name: log-config namespace: default resourceVersion: "93616" selfLink: /api/v1/namespaces/default/configmaps/log-config uid: 1b8115de-bd2f-11eb-acba-000c29d88bba
//等大概10秒左右,使用该 ConfigMap 挂载的 Volume 中的数据同步更新kubectl exec -it my-nginx-76b6489f44-6dwxh -- cat /etc/config/log_level DEBUG
ConfigMap 更新后滚动更新 Pod
更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过在 .spec.template.metadata.annotations 中添加 version/config ,每次通过修改 version/config 来触发滚动更新
kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20210525" }}}}}'
kubectl get pods NAME READY STATUS RESTARTS AGE my-nginx-665dd4dc8c-j4k9t 0/1 ContainerCreating 0 4s my-nginx-76b6489f44-6dwxh 0/1 Terminating 0 10m
kubectl get pods NAME READY STATUS RESTARTS AGE my-nginx-665dd4dc8c-j4k9t 1/1 Running 0 74s
PS:更新 ConfigMap 后
●使用该 ConfigMap 挂载的 Env 不会同步更新(只有文件挂载才能热更新)。
●使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新。