Kubernetes Secret原理 2

152 阅读4分钟

这是我参与更文挑战的第11天,活动详情查看: 更文挑战

对之前的文章进行补充说明,上文链接见 传送门 容器中使用secret 和ConfigMap一样,也是可以通过环境变量和volume的方式去使用Secret。环境变量适合命令行需要输入密码等场景,而volume适合用文件去进行远端验证场景。

环境变量使用secret

通过yaml文件test-secret-env.yaml创建pod

apiVersion: v1
kind: Pod
metadata:
  name: test-secret-env
spec:
  containers:
    - name: test-secret-env
      image: alpine
      imagePullPolicy: IfNotPresent
      command: [ "/bin/sh", "-c", "echo login to as user ${SUPERUSER} with password ${PASSWORD};env" ]
      env:
        - name: SUPERUSER
          valueFrom:
            secretKeyRef:
              name: test-secret-3
              key: superuser
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: test-secret-3
              key: password
      envFrom:
        - secretRef:
            name: test-secret-2
  restartPolicy: Never

这里的格式和ConfigMap差不多,也是单独导入和整体导入两种方法。

创建好pod查看下日志

[root@k8s-master Secret]# kubectl logs test-secret-env
login to as user admin with password Q%FvqS$*F$k^6i
secret1=d23hehuye8rq340p98du312rpur9er3eru038dfh3ry2098iuerewriu32987er98er

secret2=jp3oiur98sd7re=er=23r-sdf13i4%(eiru2p398(eur1p8u+o3iru2o3

KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=test-secret-env
SHLVL=1
HOME=/root
MYNGINX_SERVICE_SERVICE_PORT_HTTP=8080
MYNGINX_SERVICE_SERVICE_HOST=10.97.205.233
MYNGINX_SERVICE_PORT_8080_TCP_ADDR=10.97.205.233
SUPERUSER=admin
MYNGINX_SERVICE_PORT_8080_TCP_PORT=8080
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYNGINX_SERVICE_PORT_8080_TCP_PROTO=tcp
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYNGINX_SERVICE_SERVICE_PORT=8080
MYNGINX_SERVICE_PORT=tcp://10.97.205.233:8080
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
MYNGINX_SERVICE_PORT_8080_TCP=tcp://10.97.205.233:8080
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
PASSWORD=Q%FvqS$*F$k^6i

有两点要说明下:

这里的secret的内容已经经过了base64解码 通过文件创建的那两个secret的内容似乎多了一个换行符,要去掉 注意,如果是通过文件的方式创建的secret,要去掉每行后面的换行符才可以。

用下面的方法修改下文件,再重新创建secret即可。echo -n能去掉末尾的换行符。

[root@k8s-master Secret]# echo -n "d23hehuye8rq340p98du312rpur9er3eru038dfh3ry2098iuerewriu32987er98er" > secret1
[root@k8s-master Secret]# echo -n "jp3oiur98sd7re=er=23r-sdf13i4%(eiru2p398(eur1p8u+o3iru2o3" > secret2
[root@k8s-master Secret]# kubectl delete secret/test-secret-2
secret "test-secret-2" deleted
[root@k8s-master Secret]# kubectl delete pod test-secret-env
pod "test-secret-env" deleted
[root@k8s-master Secret]# kubectl create secret generic test-secret-2 --from-file=secret1 --from-file=secret2
secret/test-secret-2 created
[root@k8s-master Secret]# kubectl apply -f test-secret-env.yaml
pod/test-secret-env created
[root@k8s-master Secret]# kubectl logs test-secret-env
login to as user admin with password Q%FvqS$*F$k^6i
secret1=d23hehuye8rq340p98du312rpur9er3eru038dfh3ry2098iuerewriu32987er98er
secret2=jp3oiur98sd7re=er=23r-sdf13i4%(eiru2p398(eur1p8u+o3iru2o3
...
...

volume使用secret

通过yaml文件test-secret-volume.yaml创建pod

apiVersion: v1
kind: Pod
metadata:
  name: test-secret-volume
spec:
  containers:
    - name: test-secret-volume
      image: alpine
      command: ["/bin/sh","-c","ping 8.8.8.8"]
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secret
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: test-secret-2
  restartPolicy: Never

这里也是和ConfigMap差不多,只是多了readOnly: true这一条是为了防止容器对文件进行修改。

创建成功以后进入容器,发现两个文件已经被同步

[root@k8s-master Secret]# kubectl exec test-secret-volume -it -- /bin/sh
/ # cd /etc/secret/
/etc/secret # ls -al
total 0
drwxrwxrwt    3 root     root           120 May 10 12:07 .
drwxr-xr-x    1 root     root            20 May 10 12:07 ..
drwxr-xr-x    2 root     root            80 May 10 12:07 ..2020_05_10_12_07_22.158909929
lrwxrwxrwx    1 root     root            31 May 10 12:07 ..data -> ..2020_05_10_12_07_22.158909929
lrwxrwxrwx    1 root     root            14 May 10 12:07 secret1 -> ..data/secret1
lrwxrwxrwx    1 root     root            14 May 10 12:07 secret2 -> ..data/secret2
/etc/secret # cat secret1
d23hehuye8rq340p98du312rpur9er3eru038dfh3ry2098iuerewriu32987er98er/etc/secret #
/etc/secret # cat secret2
jp3oiur98sd7re=er=23r-sdf13i4%(eiru2p398(eur1p8u+o3iru2o3/etc/secret #

因为是走的volume,所以也是支持热更新的。

访问私有仓库 k8s里面还有一种特殊的secret,专门用于docker去私有仓库拉取镜像时使用。

DockerHub和Google GCR是两个使用最多的docker镜像仓库,如果是公共仓库里的镜像,则可以直接拉取,而如果是用户个人的私有仓库,必须要登录以后才能拉取,不然会出现ImagePullBackOff报错。

DockerHub提供了docker login命令去在本地生成一个用于认证的个人信息文件,这样以后在该机器上使用docker去拉取私有镜像就不会失败了。如下

[root@k8s-node1 ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: victor2019
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

如果是希望k8s也能拉取私有镜像,要将这份认证信息存储到k8s的secret中。