【Kubernetes】Pod 之 使用 Secrets

217 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

一、前言

ConfigMap传递敏感数据,就需要Secret

Secret 对象可以存储和管理敏感信息,比如 passwordsOAuth tokens、以及 ssh keys 等。把敏感信息存储到 Secret 对象中会比放到 Pod 的定义文件或是容器镜像中更加安全、灵活,使用 Secret 对象可以更好的控制数据的使用方式,并且减少意外泄露的风险。

不仅用户可以创建 Secret 对象,kubernetes 系统也会创建一些 Secret 对象。


二、使用

Pod 的容器中,Secrets 可以被挂载成为数据卷或是引用为环境变量来使用。 另外还可以在私有仓库 Docker 镜像拉取时配置进行使用。

  • Secrets 作为数据卷
  • Secrets 作为环境变量
  • 镜像拉取时配置

(1)Secrets 作为数据卷

通常将 Secret 作为挂载卷在 Pod 中使用的步骤如下:

  1. 创建一个 Secret 或是使用已经存在的 Secret。通常多个 Pods 会使用同一个 Secret。
  2. 修改 Pod YAML 文件定义,使用字段 .spec.volumes[] 挂载卷,卷的名称可以任意命名,在字段 .spec.volumes[].secret.secretName 中填写需要挂载的 Secret 对象的名称。
  3. 在每个需要 Secret 的容器中添加字段 .spec.containers[].volumeMounts[]。规定 .spec.containers[].volumeMounts[].readOnly = true 以及字段 .spec.containers[].volumeMounts[].mountPath 表示将 Secret 挂载到某个未使用过的目录下。
  4. 修改镜像或是命令行以便程序可以在对应的目录下找到需要的文件。Secret data 字段下的每个 key 都会被用作挂载目录下的文件名。

新建文件 mysecret-pod.yaml,这个 YAML 文件定义了将 mysecret 挂载到容器中的 /etc/foo 目录下:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mypod
      image: redis
      volumeMounts:
        - name: foo
          mountPath: "/etc/foo"
          readOnly: true
  volumes:
    - name: foo
      secret:
        secretName: mysecret

执行创建并进入到容器中查看:

$ kubectl exec -it mypod -- bash
root@mypod:/data# cd /etc/foo
root@mypod:/etc/foo# ls
password  username
root@mypod:/etc/foo# cat username
admin
root@mypod:/etc/foo# cat password
1f2d1e2e67dfroot

如果想要指定挂载的文件名可以使用 itemspath 字段,将上面的定义修改为:

# 将 username secret 的值存储到 /etc/foo/my-group/my-username 文件中,同时 username secret 不会被使用到
......
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username

(2)Secrets 作为环境变量

在 Pod 中使用 Secret 作为环境变量的步骤如下:

  1. 创建一个 Secret 或是使用已经存在的 Secret。通常多个 Pods 会使用同一个 Secret。
  2. 修改 Pod YAML 文件,在每个容器中添加环境变量引用需要的 Secret 的值,使用字段 env[].valueFrom.secretKeyRef
  3. 修改镜像或是命令行以便程序可以通过环境变量找到需要的值。

创建 YAML 文件 secret-env-pod.yaml,从环境变量中使用 Secret:

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
    - name: mycontainer
      image: redis
      env:
        - name: SECRET_USERNAME
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: username
        - name: SECRET_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: password
  restartPolicy: Never

执行创建并进入容器检查环境变量:

$ kubectl exec -it secret-env-pod -- bash
root@secret-env-pod:/data# echo $SECRET_USERNAME
admin
root@secret-env-pod:/data# echo $SECRET_PASSWORD
1f2d1e2e67df

(3)镜像拉取时配置

当我们需要从某个私有仓库拉取镜像时,可以使用 Secret 存储私有仓库的密码并借助 kubelet 传递密码,具体定义时通过指定 Pod 的字段 spc.ImagePullSecrets 来引用它。

这里有两个步骤:

  1. 创建包含 Docker 镜像仓库证书的 Secret
  2. 在 Pod 定义中使用字段 ImagePullSecrets 引用该 Secret

需要在 Docker Hub 上创建一个账号,使用该账号创建一个私有仓库。

使用如下命令创建用于 Docker 镜像仓库鉴权的 Secret:

# 这里的 xxxx 替换为你们自己的账号信息
kubectl create secret docker-registry mydockerhubsecret --docker-username=xxxx --docker-password=xxxx --docker-email=xxxx

查看详细信息:

$ kubectl get secret mydockerhubsecret -o yaml

可以看到 mydockerhubsecret Secret 有一个隐藏的 .dockerconfigjson 文件,这个文件就是用于帮助验证的。

然后在创建 Pod 的时候引用这个 mydockerhubsecret:

apiVersion: v1
kind: Pod
metadata:
  name: private-pod
spec:
  imagePullSecrets:
    - name: mydockerhubsecret
  containers:
    - image: username/private:tag # 这里根据你的实际情况添加私有仓库的镜像名
      name: main
  restartPolicy: Never