【云原生】Secret敏感信息存储

Secret敏感信息存储

文章目录

介绍

  • Secret是一种包含少量敏感信息例如密码、令牌或密钥的对象。这样的信息可能会被放在Pod规约种或者镜像中。使用Secret意味着你不需要再应用程序代码中包含机制数据。
  • 由于创建Secret可以独立于使用它们的Pod,因此在创建、查看和编辑Pod的工作流程中暴露Secret(及其数据)的风险较小。Kubernetes和在集群中运行的应用程序也可以对Secret采取额外的预防措施,例如避免讲敏感数据写入非易失性存储。
  • Secret类似于ConfigMap但专门用来保存机密数据。

一、Secret

1.1、Secret名称与数据的约束

  • Secret对象的名称必须是合法的DNS子域名。
  • 在为创建Secret编写配置文件时,你可以设置data与/或stringData字段。data和stringData字段都是可选的。data字段中国所有键值都必须是base54编码的字符串。如果不希望指定这种base64字符串的转换操作,你可以选择设置stringData字段,其中可以使用任何字符串作为其取值。
  • data和srtingData中的键名只能包含字母、数据、-、_或.字符。stringData字段中的所有键值对都会在内部被合并到data字段中。如果某个主键同时出现在data和stringData字段中,stringData所指定的键值具有高优先级。

1.2、尺寸限制

  • 每个Secret的尺寸最多为1MB。驰加这一限制是为了避免用户创建非常大的Secret,进而导致API服务器和kubelet内存耗尽。不过创建很多小的Secret也可能耗尽内存。你可以使用资源配额来约束每个名称空间中Secret(后其他资源)的个数。

1.3、编辑Secret

  • 你可以编辑一个已有的Secret。除非它是不可变更的。

1.4、可选的Secret

  • 当你在Pod中引用Secret时,你可以将该Secret标记为可选,就像下面的例子中所展示的那样。如果可选的Secret不存在,Kubernetes将忽略它。然后直接创建你要想的资源。
yaml 复制代码
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
      # optional字段设置为true表示这是一个可选的Secret。
      optional: true

二、Secret创建

  • 本文展示如何安全地将敏感数据(如密码和加密密钥)注入到Pod中。

2.1、将Secret数据转换为base-64形式

  • 假设用户想要两条Secret数据:用户名my-app和密码39528$vdg7Jb。首先使用base64编码将用户名和密码转换为base-64形式。下面是一个使用常用的base程序的示例:
  • 以下的base-64的回显结果的形式的用户名为bXktYXBw,base-64形式的密码为Mzk1MjgkdmRnN0pi。
bash 复制代码
# 用户名base64
[root@master ~]# echo -n 'my-app' | base64
bXktYXBw


# 密码base64
[root@master ~]# echo -n '39528$vdg7Jb' | base64
Mzk1MjgkdmRnN0pi

2.2、创建Secret

  • 这是一个配置文件,可以用来创建存储有用户名和密码的Secret:
bash 复制代码
[root@master ~]# vim secret.yaml
apiVersion: "v1"
kind: Secret
metadata:
  name: test-secret
type: Opaque
data:
  # 此处的键的值是单行内容
  username: bXktYXBw
  password: Mzk1MjgkdmRnN0pi
bash 复制代码
# 创建Secret
[root@master ~]# kubectl apply -f secret.yaml 
bash 复制代码
# 查看Secret相关信息
[root@master ~]# kubectl get secrets test-secret 
NAME          TYPE     DATA   AGE
test-secret   Opaque   2      39s


# 回显字段解释
NAME:Secret存储的名称
TYPE:Secret的类型
DATA:描述Secret存储中有几个数据,一个键表示一个数据
AGE:表示Secret被创建的时间
bash 复制代码
# 查看Secret相关的更多详细信息
# 仔细观察可以发现,我们定义的值被加密了
[root@master ~]# kubectl describe secrets test-secret 
Name:         test-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  12 bytes
username:  6 bytes

2.3、直接用kubectl创建Secret

  • 如果你希望略过Base64编码的步骤,你也可以使用kubectl create secret的命令直接创建Secret,例如:
  • 这是一种更为方便的方法。前面展示的详细分解步骤有助于了解究竟发生了什么事情。
  • 你也可以使用前面相同的命令去查询这个secret。(注意名字)
bash 复制代码
[root@master ~]# kubectl create secret generic secret --from-literal='username=my-app' --from-literal='password=password=39528$vdg7Jb'

三、引用Secret

  • 注意:以下的所有引用都可能引用刚刚创建的Secret,请先提前准备好Secret存储。

3.1、创建一个可以通过卷访问Secret数据的Pod

  • 这里是一个可以用来创建Pod的配置文件:
bash 复制代码
[root@master ~]# vim secret-pod.yaml
apiVersion: "v1"
kind: Pod
metadata:
  name: secret-test-pod
spec:
  restartPolicy: Always
  containers:
    - name: test-container
      image: nginx:latest
      imagePullPolicy: IfNotPresent
      volumeMounts:
        # name 必须与下面的卷名匹配
        - name: secret-volume
          mountPath: "/etc/secret-volume"
          readOnly: true 

  # Secret 数据通过一个卷暴露给该Pod中的容器
  volumes:
    - name: secret-volume
      # 这个卷将会从下面的test-secret中取值
      secret:
        secretName: test-secret
bash 复制代码
# 创建Pod
[root@master ~]# kubectl apply -f secret-pod.yaml


# 确定Pod正在运行
[root@master ~]# kubectl get pod
NAME              READY   STATUS    RESTARTS   AGE
secret-test-pod   1/1     Running   0          34s
bash 复制代码
# Secret数据卷通过挂载在/etc/secret-volume目录下的卷暴露在容器中
# 在shell中,列举/etc/secret-volume目录下的文件
# 使用以下命令可以看到两个文件,每个对应一个Secret数据条目
[root@master ~]# kubectl exec -it secret-test-pod -- ls /etc/secret-volume
password  username
bash 复制代码
# Secret data映射中的每个键都成为被挂载目录下的文件名
# 显示username和password文件的内容
[root@master ~]# kubectl exec -it secret-test-pod -- cat /etc/secret-volume/username
my-app


[root@master ~]# kubectl exec -it secret-test-pod -- cat /etc/secret-volume/password
39528$vdg7Jb

3.2、映射Secret键到特定的文件路径

  • 你还可以控制卷内Secret键的映射路径。使用.spec.volumes[].secret.items字段来改变每个键的目标路径
bash 复制代码
# 如果你使用.spec.volumes[].secret.items明确地列出键,请考虑以下事情
# 只有在items字段中指定的键才会被映射到挂载目录下
# 要使用Secret中全部的键,那么全部的键都必须列在items字段中
# 所有列出的键必须存在于相应的Secret中,否则该卷不会被创建


[root@master ~]# vim secret-mypod.yaml
apiVersion: "v1"
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true

  volumes:
  - name: foo
    secret:
      secretName: test-secret
      items:
      # 来自test-secret的键username可以在路径为/etc/foo/my-group/my-username下供容器使用,而不是路径/etc/foo/username
      - key: username
        path: "my-group/my-username"
      - key: password
        path: "1/2/3/4/password.conf"
bash 复制代码
# 创建Pod
[root@master ~]# kubectl apply -f secret-mypod.yaml


# 确定Pod正在运行
[root@master ~]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
mypod   1/1     Running   0          107s
bash 复制代码
# 如果以下命令验证效果
# 可以很明显的看出,我们在使用Secret的时候是可以选择我们的配置文件放在什么目录下,但是需要注意的是父目录永远是挂载Pod中的目录
[root@master ~]# kubectl exec -it mypod -- ls /etc/foo/my-group/
my-username


[root@master ~]# kubectl exec -it mypod -- ls /etc/foo/1/2/3/4/
password.conf

3.3、使用Secret数据定义容器变量

  • 在你的容器中,你可以以环境变量的方式使用Secret中的数据。
  • 如果容器已经使用了在环境变量中的Secret,除非容器重新启动,否则容器将无法感知到Secret的更新。有第三方解决方案可以在Secret该表时触发容器重启。
bash 复制代码
[root@master ~]# vim secret-env.yaml
apiVersion: "v1"
kind: Pod
metadata:
  name: env-single-secret
spec:
  containers:
  - name: envars-test-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    env:
    # 定义一个变量名为 SECRET_USERNAME
    - name: SECRET_USERNAME
      valueFrom:
        # 新变量的值将会从test-secret存储中的username键取值
        secretKeyRef: 
          name: test-secret
          key: username
bash 复制代码
# 创建Pod
[root@master ~]# kubectl apply -f secret-env.yaml


# 确定Pod正在运行
[root@master ~]# kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
env-single-secret   1/1     Running   0          22s
bash 复制代码
# 在Shell中,显示容器环境变量SECRET_USERNAME的内容
[root@master ~]# kubectl exec -it env-single-secret -- /bin/sh -c 'echo $SECRET_USERNAME'
my-app

3.4、使用来自多个Secret的数据定义环境变量

  • 使用命令行创建多个Secret
bash 复制代码
[root@master ~]# kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'


[root@master ~]# kubectl create secret generic db-user --from-literal=db-username='db-admin'
  • 在Pod规约中定义环境变量
bash 复制代码
[root@master ~]# vim envars-secret.yaml
apiVersion: "v1"
kind: Pod
metadata:
  name: envvars-multiple-secrets
spec:
  containers:
  - name: envars-test-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    env:
    - name: BACKEND_USERNAME
      valueFrom:
        secretKeyRef:
          name: backend-user
          key: backend-username
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: db-user
          key: db-username
bash 复制代码
# 创建Pod
[root@master ~]# kubectl apply -f envars-secret.yaml


# 确定Pod正在运行
[root@master ~]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
envvars-multiple-secrets   1/1     Running   0          15s
bash 复制代码
# 在shell中,显示容器环境变量的内容
[root@master ~]# kubectl exec -i -t envvars-multiple-secrets -- /bin/sh -c 'env | grep _USERNAME'
DB_USERNAME=db-admin
BACKEND_USERNAME=backend-admin

3.5、将Secret中的所有键值对定义为环境变量

  • 说明:此功能在Kubernetes 1.6版本之后可用
bash 复制代码
# 使用envFrom来将Secret中的所有数据定义为环境变量。Secret中的键名成为容器中的环境变量名
[root@master ~]# vim suoyou-env.yaml
apiVersion: "v1"
kind: Pod
metadata:
  name: envfrom-secret
spec:
  containers:
  - name: envars-test-container
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    envFrom:
    - secretRef:
        name: test-secret
bash 复制代码
# 创建Pod
[root@master ~]# kubectl apply -f suoyou-env.yaml


# 确定Pod正在运行
[root@master ~]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
envfrom-secret             1/1     Running   0          25s
bash 复制代码
# 在Shell中,显示环境变量username和password的内容
[root@master ~]# kubectl exec -i -t envfrom-secret -- /bin/sh -c 'echo "username: $username\npassword: $password\n"'
username: my-app
password: 39528$vdg7Jb
相关推荐
知已难寻6 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
阿里云云原生11 小时前
生产更可信,订阅更耐用丨Higress 社区进展报告
云原生
阿里云云原生12 小时前
如何用 STAROps Elasticsearch 智能助手看穿“搜索变慢”
云原生
kuroomi16 小时前
Git入门
git·kubernetes
雾时之林16 小时前
国内Docker 镜像加速器配置
云原生·eureka
我是koten1 天前
【运维杂谈】K8s遇到Terminating的名称空间删除不了怎么办?(解决方案亲测有效)
linux·运维·服务器·云原生·kubernetes·k8s·名称空间
RuoyiOffice1 天前
KubeSphere 容器云实践:从管理 K8s 到建设企业 PaaS,还需要哪些能力
spring boot·kubernetes·kubesphere·jenkins·paas·微服务部署·ruoyi office
风吹稻子1 天前
etcd备份与恢复:删了 etcd.yaml,容器为什么还在跑?——一次 K8s 控制面死锁排查实录
kubernetes
weirong1 天前
Operator 的测试该写到哪一层?139 个用例之后我划的三条线
kubernetes
阿里云云原生2 天前
稳定复现超 70% 的缺陷,报警到自动修复的 Agent 流水线实践
云原生