一、Secret热更新背景

实际使用ConfigMap和Secret时,一般情况下都是直接使用文件创建,也就是使用--from-file=xxx的格式进行创建。创建的ConfigMap可能因为换行的问题,导致使用kubectl edit cm xxx时排版很乱,编辑起来很受影响。

另外,使用kubectl edit secret xxx时,由于Secret数据为加密数据,无法直接编辑。

二、通过YAML文件热更新Secret

1.定义一个yaml文件

[root@k8s-master01 conf]# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

2.创建Secret

[root@k8s-master01 conf]# kubectl create -f secret.yaml

3.通过yaml文件更新Secret,修改username为YWRtaW4xMjM=

[root@k8s-master01 conf]# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4xMjM=
  password: MWYyZDFlMmU2N2Rm

[root@k8s-master01 conf]# kubectl replace -f secret.yaml

4.验证,观察到username变更为YWRtaW4xMjM=

[root@k8s-master01 conf]# kubectl get secret mysecret -oyaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4xMjM=
kind: Secret
metadata:
  creationTimestamp: "2023-05-03T01:53:14Z"
  name: mysecret
  namespace: default
  resourceVersion: "958931"
  uid: 90337d19-6054-4b15-924b-65ba3a33dc8f
type: Opaque

三、通过Kubectl命令热更新Secret

1.将凭据保存到文件,其中-n 标志用来确保生成文件的文末没有多余的换行符。这很重要,因为当 kubectl 读取文件并将内容编码为 base64 字符串时,额外的换行符也会被编码。 你不需要对文件中包含的字符串中的特殊字符进行转义。

$ echo -n 'admin' > ./username.txt
$ echo -n 'S!B\*d$zDsb=' > ./password.txt

2.在 kubectl 命令中传递文件路径,默认键名为文件名。你也可以通过 --from-file=[key=]source 设置键名

$ kubectl create secret generic db-user-pass --from-file=username=./username.txt --from-file=password=./password.txt

3.检查 Secret 是否已创建

[root@k8s-master01 conf]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
db-user-pass          Opaque                                2      10s
default-token-8s8wl   kubernetes.io/service-account-token   3      52d

4.查看 Secret 的细节

[root@k8s-master01 conf]# kubectl describe secret db-user-pass
Name:         db-user-pass
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
username:  5 bytes
password:  12 bytes

注意:kubectl getkubectl describe 命令默认不显示 Secret 的内容。 这是为了防止 Secret 被意外暴露或存储在终端日志中.

5.查看你所创建的 Secret 内容

[root@k8s-master01 conf]# kubectl get secret db-user-pass -o jsonpath='{.data}'
{"password":"UyFCXCpkJHpEc2I9","username":"YWRtaW4="}

当然了,你也可以使用-oyaml查看你所创建的 Secret 内容

[root@k8s-master01 conf]# kubectl get secret db-user-pass -oyaml
apiVersion: v1
data:
  password: UyFCXCpkJHpEc2I9
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2023-05-03T01:38:58Z"
  name: db-user-pass
  namespace: default
  resourceVersion: "877358"
  uid: f609641c-7002-4079-9756-705fa18b5f44
type: Opaque

6.更新源文件,这里修改username为admin123

$ echo -n 'admin123' > ./username.txt

7.更新Secret

[root@k8s-master01 conf]# kubectl create secret generic db-user-pass --from-file=username=./username.txt --from-file=password=./password.txt --dry-run=client -oyaml | kubectl replace -f -

上面参数说明:

  • db-user-pass:ConfigMap的名称
  • generic:指定为通用型Secret
  • --dry-run=client -oyaml:只运行命令,并不真正地创建,并以YAML的格式输出
  • kubectl replace -f -:通过文件创建的Secret和ConfigMap不能被直接替换,但是通过YAML文件创建可以被替换,所以先使用dry-run -oyaml生成YAML文件,再进行replace即可实现热更新,该方法可以用于其他资源类型,通过YAML文件替换已经创建的资源也是可以的。

8.查看更改后的内容,观察到已更新

[root@k8s-master01 conf]# echo "admin123" | base64
YWRtaW4xMjMK

[root@k8s-master01 conf]# kubectl get secret db-user-pass -oyaml
apiVersion: v1
data:
  password: UyFCXCpkJHpEc2I9
  username: YWRtaW4xMjMK
kind: Secret
metadata:
  creationTimestamp: "2023-05-03T01:38:58Z"
  name: db-user-pass
  namespace: default
  resourceVersion: "962391"
  uid: f609641c-7002-4079-9756-705fa18b5f44
type: Opaque

注意:上面更新默认将字符串末尾换行符也进行了加密!

四、Secret限制

Secret在使用时有很多局限性,目前具有的限制如下:

  • envFrom和valueFrom无法热更新环境变量
  • 引用key必须存在
  • envFrom配置环境变量,如果key是无效的,会直接跳过
  • Secret和引用它的Pod需要在同一个命名空间
  • SubPath无法热更新
  • Secret最好不要太大

五、不可更改的Secret

Kubernetes 允许你将特定的 Secret(和 ConfigMap)标记为 不可更改(Immutable)。 禁止更改现有 Secret 的数据有下列好处:

  • 防止意外(或非预期的)更新导致应用程序中断
  • (对于大量使用 Secret 的集群而言,至少数万个不同的 Secret 供 Pod 挂载), 通过将 Secret 标记为不可变,可以极大降低 kube-apiserver 的负载,提升集群性能。 kubelet 不需要监视那些被标记为不可更改的 Secret。

你可以通过将 Secret 的 immutable 字段设置为 true 创建不可更改的 Secret。 例如:

1.将凭据保存到文件,其中-n 标志用来确保生成文件的文末没有多余的换行符。这很重要,因为当 kubectl 读取文件并将内容编码为 base64 字符串时,额外的换行符也会被编码。 你不需要对文件中包含的字符串中的特殊字符进行转义。

$ echo -n 'admin' > ./username.txt
$ echo -n 'S!B\*d$zDsb=' > ./password.txt

2.在 kubectl 命令中传递文件路径,默认键名为文件名。你也可以通过 --from-file=[key=]source 设置键名

$ kubectl create secret generic db-user-pass --from-file=username=./username.txt --from-file=password=./password.txt

3.检查 Secret 是否已创建

[root@k8s-master01 conf]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
db-user-pass          Opaque                                2      10s
default-token-8s8wl   kubernetes.io/service-account-token   3      52d

4.在线编辑Secret,在末尾处添加immutable: true

[root@k8s-master01 conf]# kubectl edit secret db-user-pass
...
...

#在末尾处添加
immutable: true

5.验证,再次进行在线编辑,提示不可更改

[root@k8s-master01 conf]# kubectl edit secret db-user-pass

不可更改的Secret-1