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

Secret敏感信息存储

文章目录

介绍

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

一、Secret

1.1、Secret名称与数据的约束

  • Secret对象的名称必须是合法的DNS子域名。
  • 在为创建Secret编写配置文件时,你可以设置data与/或stringData字段。datastringData字段都是可选的。data字段中国所有键值都必须是base54编码的字符串。如果不希望指定这种base64字符串的转换操作,你可以选择设置stringData字段,其中可以使用任何字符串作为其取值。
  • datasrtingData中的键名只能包含字母、数据、-_.字符。stringData字段中的所有键值对都会在内部被合并到data字段中。如果某个主键同时出现在datastringData字段中,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
相关推荐
HoweWWW3 小时前
k8s 微服务 ingress-nginx 金丝雀发布
微服务·容器·kubernetes
向往风的男子3 小时前
【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(三十一)
学习·容器·kubernetes
HoweWWW3 小时前
k8s中的存储
linux·容器·kubernetes
djgxfc4 小时前
Docker概述
spring cloud·云原生·eureka
苏supper4 小时前
k8s的NodeIP、PodIP、ClusterIP、ExternalIP
kubernetes
研究司马懿5 小时前
【云原生监控】Prometheus之PushGateway
云原生·prometheus·云原生监控·企业级监控系统·promesql
东边的那根草~15 小时前
2024年9月12日(k8s环境及测试 常用命令)
docker·容器·kubernetes
方圆师兄15 小时前
k8s 常见问题梳理
java·kubernetes
ly143567861915 小时前
93、k8s之hpa+helm
云原生·容器·kubernetes
Hai99021817 小时前
k8s用StatefulSet部署redis
redis·kubernetes