应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名密码或者秘钥。将这些信息直接保存在容器镜像中显然不妥,Kubernetes 提供的解决方案是 Secret。

Secret 会以密文的方式存储数据,避免了直接在配置文件中保存敏感信息。Secret 会以 Volume 的形式被 mount 到 Pod,容器可通过文件的方式使用 Secret 中的敏感数据;此外,容器也可以环境变量的方式使用这些数据。

创建Secret

有四种方法创建Secret

通过--from-literal

不建议使用,因为会在命令行中留下history

用户名为ammin,密码为123.com

[root@node1 ~]# kubectl create secret generic mysqlsecret --from-literal=username=admin --from-literal=password=123.com

通过--from-file

虽然是通过文件但依然有风险

[root@node1 ~]# echo -n amdin > ./username
[root@node1 ~]# echo -n 123.com > ./password
[root@node1 ~]# kubectl create secret generic mysqlsecret --from-file=./username \
--from-file=./password

通过--from-env-file

和上一种方法类似

[root@node1 ~]# vim env
username=admin
password=123.com
[root@node1 ~]# kubectl create secret generic mysqlsecret --from-env-file=env

通过K8s的Yaml配置文件

推荐使用

提前在某台主机或者虚拟主机生成一个加密的用户名和密码

$ echo -n admin | base64
YWRtaW4=
$ echo -n 123.com | base64
MTIzLmNvbQ==

编写文件

[root@node1 ~]# vim mysecret.yml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
data:
  username: YWRtaW4=
  password: MTIzLmNvbQ==

创建secret

[root@node1 ~]# kubectl apply -f mysecret.yml 
secret/mysecret created

查看secret

[root@node1 ~]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-zqqh6   kubernetes.io/service-account-token   3      45h
mysecret              Opaque                                2      60s

通过详情可以看到创建的两条加密项

[root@node1 ~]# kubectl describe secrets mysecret 
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  
Type:         Opaque

Data
====
username:  5 bytes  # 用户名admin,5个字节
password:  7 bytes  # 密码123.com,7个字节

如果想看在yaml文件中设置的值的话

[root@node1 ~]# kubectl edit secrets mysecret
...
data:
  password: MTIzLmNvbQ==
  username: YWRtaW4=
...

解码加密项

前提是需要知道使用什么加密的

[root@node2 ~]# echo -n YWRtaW4= | base64 --decode 
admin
[root@node2 ~]# echo -n MTIzLmNvbQ== | base64 --decode 
123.com

Volume使用Secret

编写一个Pod文件

[root@node1 ~]# vim mypod.yml
apiVersion: v1
kind: Pod
metadata:
  name: testsecret
spec:
  containers:
  - name: test
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 3000000
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: True
  volumes:
  - name: foo
    secret:
      secretName: mysecret   # 上面运行过的secret的name

因为之前的secret在写入data项的时候是以key: value的形式写入,key为文件名,value为文件内容

运行Pod

[root@node1 ~]# kubectl apply -f mypod.yml 
pod/testsecret created

进入容器查看挂载目录

[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # ls /etc/foo
password  username
/ # cat /etc/foo/username 
admin
/ # cat /etc/foo/password 
123.com

自定义Secret的key

[root@node1 ~]# vim mypod.yml 
apiVersion: v1
kind: Pod
metadata:
  name: testsecret
spec:
  containers:
  - name: test
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 3000000
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: True
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
      # 将mysecret中的key(username)改为/etc/foo/mygroup/my-username
        path: mygroup/my-username
      - key: password
        path: mygroup/my-password

将Pod删除,重新运行Pod

[root@node1 ~]# kubectl apply -f mypod.yml 
pod/testsecret created

进入容器查看

[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # ls /etc/foo
mygroup
/ # ls /etc/foo/mygroup/
my-password  my-username

动态更新volume方式的Secret

以 Volume 方式使用的 Secret 支持动态更新:Secret 更新后,容器中的数据也会更新。

尝试修改一个密码

$ echo -n 123456 | base64
MTIzNDU2

修改yml文件

[root@node1 ~]# vi mysecret.yml
  password: MTIzNDU2

重新运行一遍secret

[root@node1 ~]# kubectl apply -f mysecret.yml 
secret/mysecret configured

需要等待1-2分钟后

进入容器查看密码

[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # cat /etc/foo/mygroup/my-password 
123456

使用变量的Secret

先将之前的pod删除

[root@node1 ~]# kubectl delete -f mypod.yml 
pod "testsecret" deleted

修改yml文件

[root@node1 ~]# vim mypod.yml 

apiVersion: v1
kind: Pod
metadata:
  name: testsecret
spec:
  containers:
  - name: test
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 3000000
# volume内容全部替换为以下内容
    env:
      - name: SECRET_USERNAME   # 变量名
        valueFrom:   # 变量值来自于secret中的mysecret的username的值
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD  # 变量名
        valueFrom:   # 变量值来自于secret中的mysecret的password的值
          secretKeyRef:
            name: mysecret
            key: password

运行Pod

[root@node1 ~]# kubectl apply -f mypod.yml 
pod/testsecret created

进入容器验证变量

[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # echo $SECRET_USERNAME
admin
/ # echo $SECRET_PASSWORD
123456

需要注意的是,环境变量读取 Secret 很方便,但无法支撑 Secret 动态更新。

Secret 可以为 Pod 提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,则可以用 ConfigMap。请看下篇文档

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0