Kubernetes Secret的创建与使用

前提条件

Secret简介

Kubernetes Secret 是一种用于存储敏感信息(如密码、令牌、密钥等)的对象。它可以让你将敏感数据以加密的方式存储在 Kubernetes 集群中,避免在配置文件或容器镜像中以明文形式暴露这些信息。这对于安全地部署应用程序至关重要,例如,在一个包含数据库连接的应用场景中,数据库的用户名和密码就可以存储在 Secret 中。

Secret如何保证数据安全

  • 存储加密
    • Base64 编码混淆 :虽然 Base64 编码不是真正的加密,但它可以对数据进行一定程度的混淆。在 Kubernetes 中,Secret 数据在存储时会进行 Base64 编码。例如,密码等敏感信息被编码后,以一种不可直接阅读的格式存储在data字段下。这使得在存储层面,数据内容不会以明文形式轻易暴露。
    • etcd 加密(可选):etcd 是存储 Kubernetes 集群状态包括 Secret 的数据库。可以启用 etcd 加密来增强存储安全。通过配置 API Server 与 etcd 之间的通信加密,使用 TLS(Transport Layer Security)来保护数据传输路径。同时,etcd 本身也支持加密存储数据,防止数据在存储介质上被未授权访问。
  • 访问控制
    • RBAC 严格授权:Role - Based Access Control(RBAC)是 Kubernetes 保障 Secret 安全访问的关键机制。通过定义精确的角色(Role)和角色绑定(RoleBinding),可以限制谁(用户、组或者服务账户)能够对 Secret 进行何种操作(如创建、读取、更新和删除)。例如,对于生产环境中的敏感 Secret,只有特定的运维团队角色可以进行更新操作,开发人员角色可能只有读取权限。
    • 命名空间隔离防护:Secret 是命名空间(Namespace)范围内的资源。不同命名空间中的 Secret 相互隔离,这提供了天然的访问屏障。例如,开发环境的 Secret 存放在开发命名空间,生产环境的 Secret 存放在生产命名空间,默认情况下,开发环境的用户无法访问生产命名空间的 Secret,有效防止了跨环境的非授权访问。
  • 传输安全
    • TLS 加密传输:在集群内部,Secret 数据在传输过程中可以通过 TLS 进行加密。当 API Server 与节点之间或者不同组件之间传输 Secret 相关的数据时,TLS 通道确保数据在网络上以加密的形式传输。这防止了数据在传输过程中被中间人窃取或者篡改,保证了数据从存储位置到使用位置的安全性。
  • 使用安全措施
    • 容器内权限管理:当 Secret 在容器中作为环境变量或者挂载文件使用时,Kubernetes 会谨慎处理。如果是挂载文件,容器内的应用程序可以被配置为以只读权限访问这些文件,避免了文件内容被意外修改。对于作为环境变量注入的 Secret 数据,容器内的进程只能在其运行权限范围内使用这些变量,减少了数据泄露风险。
    • 更新谨慎处理:更新 Secret 时,Kubernetes 采取谨慎的策略。已经运行的容器不会自动获取更新后的 Secret 内容,这是为了避免配置突然变化导致应用程序异常。这种机制确保了 Secret 更新过程的可控性,防止因配置更新导致的潜在安全漏洞。只有在经过适当的操作(如重新部署容器或者采用支持热更新且经过安全验证的方式)后,容器才会获取新的 Secret 内容。

Secret 的类型

内置类型 用法
Opaque 用户定义的任意数据
kubernetes.io/service-account-token 服务账号令牌
kubernetes.io/dockercfg ~/.dockercfg 文件的序列化形式
kubernetes.io/dockerconfigjson ~/.docker/config.json 文件的序列化形式
kubernetes.io/basic-auth 用于基本身份认证的凭据
kubernetes.io/ssh-auth 用于 SSH 身份认证的凭据
kubernetes.io/tls 用于 TLS 客户端或者服务器端的数据

这里选取Opaque、service-account-token、dockerconfigjson类型作案例演示。

Base64编码/解码

  • 命令行
复制代码
# 编码
[root@k8s-master01 ~]# echo -n "admin" | base64
YWRtaW4=
​
# 解码
[root@k8s-master01 ~]# echo -n "YWRtaW4=" | base64 -d
admin
​

Opaque Secret

创建Secret

Opaque 类型的数据是一个 map 类型,要求value是 base64编码格式,比如创建一个用户名为 admin,密码为 admin321 的 Secret 对象,首先将用户名和密码做 base64 编码

复制代码
$ echo -n "admin" | base64
YWRtaW4=
​
$ echo -n "admin321" | base64
YWRtaW4zMjE=

然后用base64编码过后的数据来编写一个 YAML文件:(secret-demo.yaml)

创建yaml文件

复制代码
# 目录准备
[root@k8s-master01 test]# mkdir secrettest
[root@k8s-master01 test]# cd secrettest/
​
# 创建yaml文件
[root@k8s-master01 secrettest]# vi secret-demo.yaml

内容如下

复制代码
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: YWRtaW4zMjE=

使用 kubectl命令来创建了:

复制代码
[root@k8s-master01 secrettest]# kubectl create -f secret-demo.yaml
secret/mysecret created

利用 get secret命令查看:

复制代码
[root@k8s-master01 secrettest]# kubectl get secret
NAME       TYPE     DATA   AGE
mysecret   Opaque   2      8s

使用 describe命令,查看详情:

复制代码
[root@k8s-master01 secrettest]# kubectl get secret
NAME       TYPE     DATA   AGE
mysecret   Opaque   2      8s
[root@k8s-master01 secrettest]# kubectl describe secret mysecret
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  <none>
​
Type:  Opaque
​
Data
====
password:  8 bytes
username:  5 bytes

可以看到利用 describe命令查看到的 Data没有直接显示出来,如果想看到 Data里面的详细信息,可以输出成 YAML文件进行查看:

复制代码
[root@k8s-master01 secrettest]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  password: YWRtaW4zMjE=
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2024-11-28T15:58:49Z"
  name: mysecret
  namespace: default
  resourceVersion: "563446"
  uid: 092ffdfc-8ba7-4ac5-aae2-2787e0fe9cb7
type: Opaque

使用Secret

创建好 Secret对象后,有两种方式来使用它:

  • 以环境变量的形式

  • 以Volume的形式挂载

环境变量

创建yaml文件

复制代码
vi secret1-pod.yaml

内容如下

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: secret1-pod
spec:
  containers:
  - name: secret1
    image: busybox
    command: [ "/bin/sh", "-c", "env" ]
    env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: username
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: password

创建pod

复制代码
[root@k8s-master01 secrettest]# kubectl create -f secret1-pod.yaml
pod/secret1-pod created

查看pod

复制代码
[root@k8s-master01 secrettest]# kubectl get pod
NAME          READY   STATUS              RESTARTS   AGE
secret1-pod   0/1     ContainerCreating   0          35s
​
[root@k8s-master01 secrettest]# kubectl get pod
NAME          READY   STATUS      RESTARTS   AGE
secret1-pod   0/1     Completed   0          56s
​

等到pod的状态为Completed,查看 Pod的日志输出:

复制代码
[root@k8s-master01 secrettest]# kubectl logs secret1-pod
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.0.0.1:443
HOSTNAME=secret1-pod
SHLVL=1
HOME=/root
USERNAME=admin
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
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443
KUBERNETES_SERVICE_HOST=10.0.0.1
PWD=/
PASSWORD=admin321
​

可以看到有 USERNAME 和 PASSWORD 两个环境变量输出出来。

Volume 挂载

创建yaml文件

复制代码
[root@k8s-master01 secrettest]# vi secret2-pod.yaml

内容如下

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: secret2-pod
spec:
  containers:
  - name: secret2
    image: busybox
    command: ["/bin/sh", "-c", "ls /etc/secrets"]
    volumeMounts:
    - name: secrets
      mountPath: /etc/secrets
  volumes:
  - name: secrets
    secret:
     secretName: mysecret

创建 Pod:

复制代码
[root@k8s-master01 secrettest]# kubectl create -f secret2-pod.yaml 
pod/secret2-pod created

查看pod

复制代码
[root@k8s-master01 secrettest]# kubectl get pod
NAME          READY   STATUS             RESTARTS      AGE
secret1-pod   0/1     CrashLoopBackOff   4 (40s ago)   4m29s
secret2-pod   0/1     Completed          0             36s
​

查看输出日志:

复制代码
[root@k8s-master01 secrettest]# kubectl logs secret2-pod
password
username

可以看到 secret把两个key挂载成了两个对应的文件。

dockerconfigjson Secret

创建docker registry认证的 Secret,直接使用 kubectl create命令创建,如下:

复制代码
[root@k8s-master01 secrettest]# kubectl create secret docker-registry myregistry --docker-server=DOCKER_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret/myregistry created

然后查看 Secret列表:

复制代码
[root@k8s-master01 secrettest]# kubectl get secret
NAME         TYPE                             DATA   AGE
myregistry   kubernetes.io/dockerconfigjson   1      10s
mysecret     Opaque                           2      11m
​

注意看上面的 TYPE类型,myregistry是不是对应的 kubernetes.io/dockerconfigjson,使用 describe命令来查看详细信息:

复制代码
[root@k8s-master01 secrettest]# kubectl describe secret myregistry
Name:         myregistry
Namespace:    default
Labels:       <none>
Annotations:  <none>
​
Type:  kubernetes.io/dockerconfigjson
​
Data
====
.dockerconfigjson:  152 bytes
​

看到 Data区域没有直接展示出来,如果想查看的话可以使用get命令 -o yaml来输出展示出来:

复制代码
[root@k8s-master01 secrettest]# kubectl get secret myregistry -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJET0NLRVJfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0=
kind: Secret
metadata:
  creationTimestamp: "2024-11-28T16:10:35Z"
  name: myregistry
  namespace: default
  resourceVersion: "564657"
  uid: 0c379366-e94e-4fa0-9027-28a040d24ecf
type: kubernetes.io/dockerconfigjson
​

把上面的 data.dockerconfigjson下面的数据做一个 base64解码,可以查看docker registry认证信息

复制代码
[root@k8s-master01 secrettest]# echo eyJhdXRocyI6eyJET0NLRVJfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0= | base64 -d
{"auths":{"DOCKER_SERVER":{"username":"DOCKER_USER","password":"DOCKER_PASSWORD","email":"DOCKER_EMAIL","auth":"RE9DS0VSX1VTRVI6RE9DS0VSX1BBU1NXT1JE"}}} 
​

如果需要拉取私有仓库中的 docker镜像的话就需要使用到上面的 myregistry这个 Secret

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
  - name: foo
    image: 192.168.1.100:5000/test:v1
  imagePullSecrets:
  - name: myregistrykey

需要拉取私有仓库镜像 192.168.1.100:5000/test:v1,就需要针对该私有仓库来创建一个如上的 Secret,然后在 Pod的 YAML 文件中指定 imagePullSecrets

service-account-token Secret

service-account-token,用于被 serviceaccount引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。

Pod 如果使用了 serviceaccount,对应的secret会自动挂载到Pod的 /run/secrets/kubernetes.io/serviceaccount目录中。

使用一个 nginx镜像来验证一下

复制代码
[root@k8s-master01 secrettest]# kubectl run secret-pod3 --image nginx:1.14.2
pod/secret-pod3 created
​
[root@k8s-master01 secrettest]# kubectl get pods
NAME          READY   STATUS             RESTARTS        AGE
secret-pod3   1/1     Running            0               12s
secret1-pod   0/1     CrashLoopBackOff   6 (4m53s ago)   13m
secret2-pod   0/1     CrashLoopBackOff   6 (74s ago)     9m50s
​
[root@k8s-master01 secrettest]# kubectl exec secret-pod3 -- ls /run/secrets/kubernetes.io/serviceaccount
ca.crt
namespace
token
​
[root@k8s-master01 secrettest]# kubectl exec secret-pod3 -- cat /run/secrets/kubernetes.io/serviceaccount/token
eyJhbGciOiJSUzI1NiIsImtpZCI6Ii1MZ29NaWJ3R0lpQ1hCSTB4bzQzbkp5V0hiXzJsODA2M0lKakRPRkZ2eEEifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzY0MzQ2NjAyLCJpYXQiOjE3MzI4MTA2MDIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNDRjYWMwNTktYjQzYi00OTY5LThjNDUtNDBhN2M4NWJhY2QxIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwibm9kZSI6eyJuYW1lIjoiazhzLW5vZGUwMSIsInVpZCI6ImQxZDU3ZTgwLWVlYjUtNDRjOC1hZDk4LWYxZjllNzk4MWQ4ZSJ9LCJwb2QiOnsibmFtZSI6InNlY3JldC1wb2QzIiwidWlkIjoiMjRhYmRhYWEtZDhjMC00ODkzLTk4ZTQtNWQyZjM5M2YwN2NkIn0sInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJkZWZhdWx0IiwidWlkIjoiYzBhYjc4ZTAtZDZkMC00NWFmLTlkNTQtOTFhMmI3MGZjOTdkIn0sIndhcm5hZnRlciI6MTczMjgxNDIwOX0sIm5iZiI6MTczMjgxMDYwMiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.GPtgJy4-o3-l2ZmIsc4yY2tdjpTlofS1uOoGaAFoDAjtZ0Xh0ZvRxD6-Ae8NHgLv9Wmu2jY4jiE54-C56R_7N7iDby4zzwa9DuMtytIDk4ZMv85X7GcoBd7z5kfvWU3mMIVZP8dKYopblNYTQX80Homv-HKX-vD1fRasiF13xGmxCWkcxcCM2pZamXDJ2_YZcZ-_buGvZK5Ejfmfm51lmUzICFbcWWd9ZKTx5W5PnlCfUgaCsfq7ZBVz_NjUP9Ufw9a8qGc9in9iGnrOdTetcn1-UW9oqXeVoFUxRAYjYXJR-22iwlCKme5uvtr63r2WPEn-b_-j_tWzTvV_T_BEmQ
相关推荐
chuanauc5 小时前
Kubernets K8s 学习
java·学习·kubernetes
小张是铁粉5 小时前
docker学习二天之镜像操作与容器操作
学习·docker·容器
烟雨书信5 小时前
Docker文件操作、数据卷、挂载
运维·docker·容器
IT成长日记5 小时前
【Docker基础】Docker数据卷管理:docker volume prune及其参数详解
运维·docker·容器·volume·prune
这儿有一堆花5 小时前
Docker编译环境搭建与开发实战指南
运维·docker·容器
LuckyLay5 小时前
Compose 高级用法详解——AI教你学Docker
运维·docker·容器
Uluoyu5 小时前
redisSearch docker安装
运维·redis·docker·容器
IT成长日记9 小时前
【Docker基础】Docker数据持久化与卷(Volume)介绍
运维·docker·容器·数据持久化·volume·
疯子的模样14 小时前
Docker 安装 Neo4j 保姆级教程
docker·容器·neo4j
虚伪的空想家14 小时前
rook-ceph配置dashboard代理无法访问
ceph·云原生·k8s·存储·rook