• 【云原生 | Kubernetes 系列】K8s 实战 管理 Secret 详解



    前言

    在这里插入图片描述

    Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 用户可以创建 Secret,同时系统也创建了一些 Secret。


    一、使用 kubectl 管理 Secret

    1.1、创建 Secret

    一个 Secret 可以包含 Pod 访问数据库所需的用户凭证。 例如,由用户名和密码组成的数据库连接字符串。 你可以在本地计算机上,将用户名存储在文件 ./username.txt 中,将密码存储在文件 ./password.txt 中。

    echo -n 'admin' > ./username.txt
    echo -n '1f2d1e2e67df' > ./password.txt
    
    • 1
    • 2

    在这些命令中,-n 标志确保生成的文件在文本末尾不包含额外的换行符。 这一点很重要,因为当 kubectl 读取文件并将内容编码为 base64 字符串时,多余的换行符也会被编码。

    kubectl create secret 命令将这些文件打包成一个 Secret 并在 API 服务器上创建对象。

    $ kubectl create secret generic db-user-pass \
      --from-file=./username.txt \
      --from-file=./password.txt
    
    • 1
    • 2
    • 3

    输出类似于:

    secret/db-user-pass created
    
    • 1

    默认密钥名称是文件名。 可以使用 --from-file=[key=]source 来设置密钥名称。

    例如:

    $ kubectl create secret generic db-user-pass \
      --from-file=username=./username.txt \
      --from-file=password=./password.txt
    
    • 1
    • 2
    • 3

    不需要对文件中包含的密码字符串中的特殊字符进行转义

    还可以使用 --from-literal==> 标签提供 Secret 数据。 可以多次使用此标签,提供多个键值对。
    需要注意,特殊字符(例如:$,\,*,= 和 !)由你的 shell 解释执行,而且需要转义。

    在大多数 shell 中,转义密码最简便的方法是用单引号括起来。 比如,如果你的密码是 S!B\*d$zDsb=, 可以像下面一样执行命令:

    $ kubectl create secret generic db-user-pass \
      --from-literal=username=devuser \
      --from-literal=password='S!B\*d$zDsb='
    
    • 1
    • 2
    • 3

    1.2、验证 Secret

    检查 secret 是否已创建:

    $ kubectl get secrets
    
    • 1

    输出类似于:

    NAME                  TYPE                                  DATA      AGE
    db-user-pass          Opaque                                2         51s
    
    • 1
    • 2

    你可以查看 Secret 的描述:

    $ kubectl describe secrets/db-user-pass
    
    • 1

    输出类似于:

    Name:            db-user-pass
    Namespace:       default
    Labels:          >
    Annotations:     >
    
    Type:            Opaque
    
    Data
    ====
    password:    12 bytes
    username:    5 bytes
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    kubectl getkubectl describe 命令默认不显示 Secret 的内容。 这是为了防止 Secret 被意外暴露或存储在终端日志中。

    1.3、解码 Secret

    要查看创建的 Secret 的内容,运行以下命令:

    $ kubectl get secret db-user-pass -o jsonpath='{.data}'
    
    • 1

    这里会输出你的账号和密码,我就不贴了。

    现在你可以解码 password 的数据:

    # 这是一个用于文档说明的示例。
    # 如果你这样做,数据 'MWYyZDFlMmU2N2Rm' 可以存储在你的 shell 历史中。
    # 可以进入你电脑的人可以找到那个记住的命令并可以在你不知情的情况下 base-64 解码这个 Secret。
    # 通常最好将这些步骤结合起来,如页面后面所示。
    echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
    
    • 1
    • 2
    • 3
    • 4
    • 5

    输出类似于:

    1f2d1e2e67df
    
    • 1

    为了避免在 shell 历史记录中存储 Secret 的编码值,可以执行如下命令:

    $ kubectl get secret db-user-pass -o jsonpath='{.data.password}' | base64 --decode
    
    • 1

    输出应与上述类似。

    1.4、清理

    删除创建的 Secret:

    $ kubectl delete secret db-user-pass
    
    • 1

    二、使用配置文件管理 Secret

    2.1、创建 Secret

    你可以先用 JSON 或 YAML 格式在一个清单文件中定义 Secret 对象,然后创建该对象。 Secret 资源包含 2 个键值对:data 和 stringData。 data 字段用来存储 base64 编码的任意数据。 提供 stringData 字段是为了方便,它允许 Secret 使用未编码的字符串。 data 和 stringData 的键必须由字母、数字、-、_ 或 . 组成。

    我来使用 data 字段在 Secret 中存储两个字符串:

    1. 将这些字符串转换为 base64:
    echo -n 'admin' | base64
    echo -n '1f2d1e2e67df' | base64
    
    • 1
    • 2

    输出类似于:

    YWRtaW4=
    MWYyZDFlMmU2N2Rm
    
    • 1
    • 2
    1. 创建清单:
    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    type: Opaque
    data:
      username: YWRtaW4=
      password: MWYyZDFlMmU2N2Rm
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Secret 对象的名称必须是有效的 DNS 子域名。

    1. 使用 kubectl apply 创建 Secret:
    $ kubectl apply -f ./secret.yaml
    
    • 1

    输出类似于:

    secret/mysecret created
    
    • 1

    2.2、创建 Secret 时提供未编码的数据

    对于某些场景,你可能希望使用 stringData 字段。 这个字段可以将一个非 base64 编码的字符串直接放入 Secret 中, 当创建或更新该 Secret 时,此字段将被编码。

    上述用例的实际场景可能是这样:当你部署应用时,使用 Secret 存储配置文件, 你希望在部署过程中,填入部分内容到该配置文件。

    如果你的应用程序使用以下配置文件:

    apiUrl: "https://my.api.com/api/v1"
    username: ""
    password: ""
    
    • 1
    • 2
    • 3

    你可以使用以下定义将其存储在 Secret 中:

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    type: Opaque
    stringData:
      config.yaml: |
        apiUrl: "https://my.api.com/api/v1"
        username: 
        password:    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    当你检索 Secret 数据时,此命令将返回编码的值,并不是你在 stringData 中提供的纯文本值。

    运行以下命令:

    $ kubectl get secret mysecret -o yaml
    
    • 1

    输出类似于:

    apiVersion: v1
    data:
      config.yaml: YXBpVXJsOiAiaHR0cHM6Ly9teS5hcGkuY29tL2FwaS92MSIKdXNlcm5hbWU6IHt7dXNlcm5hbWV9fQpwYXNzd29yZDoge3twYXNzd29yZH19
    kind: Secret
    metadata:
      creationTimestamp: 2018-11-15T20:40:59Z
      name: mysecret
      namespace: default
      resourceVersion: "7225"
      uid: c280ad2e-e916-11e8-98f2-025000000001
    type:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.3、同时指定 data 和 stringData

    如果在 data 和 stringData 中设置了同一个字段,则使用来自 stringData 中的值。

    可以定义以下 Secret:

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    type: Opaque
    data:
      username: YWRtaW4=
    stringData:
      username: administrator
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    所创建的 Secret 对象如下:

    apiVersion: v1
    data:
      username: YWRtaW5pc3RyYXRvcg==
    kind: Secret
    metadata:
      creationTimestamp: 2018-11-15T20:46:46Z
      name: mysecret
      namespace: default
      resourceVersion: "7579"
      uid: 91460ecb-e917-11e8-98f2-025000000001
    type: Opaque
    YWRtaW5pc3RyYXRvcg== 解码成 administrator。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.4、清理

    删除你创建的 Secret:

    $ kubectl delete secret mysecret
    
    • 1

    三、使用 Kustomize 管理 Secret

    从 kubernetes v1.14 开始,kubectl 支持使用 Kustomize 管理对象。 Kustomize 提供了资源生成器(Generators)来创建 Secret 和 ConfigMap。 Kustomize 生成器应该在某个目录的 kustomization.yaml 文件中指定。 生成 Secret 后,你可以使用 kubectl apply 在 API 服务器上创建该 Secret。

    3.1、创建 Kustomization 文件

    你可以在 kustomization.yaml 中定义 secreteGenerator 字段,并在定义中引用其它本地文件生成 Secret。 例如:下面的 kustomization 文件 引用了 ./username.txt./password.txt 文件:

    secretGenerator:
    - name: db-user-pass
      files:
      - username.txt
      - password.txt
    
    • 1
    • 2
    • 3
    • 4
    • 5

    你也可以在 kustomization.yaml 文件中指定一些字面量定义 secretGenerator 字段。 例如:下面的 kustomization.yaml 文件中包含了 username 和 password 两个字面量:

    secretGenerator:
    - name: db-user-pass
      literals:
      - username=admin
      - password=1f2d1e2e67df
    
    • 1
    • 2
    • 3
    • 4
    • 5

    你也可以使用 .env 文件在 kustomization.yaml 中定义 secretGenerator。 例如:下面的 kustomization.yaml 文件从 .env.secret 文件获取数据。

    secretGenerator:
    - name: db-user-pass
      envs:
      - .env.secret
    
    • 1
    • 2
    • 3
    • 4

    注意,上面两种情况,你都不需要使用 base64 编码。

    3.2、创建 Secret

    在包含 kustomization.yaml 文件的目录下使用 kubectl apply 命令创建 Secret。

    $ kubectl apply -k .
    
    • 1

    输出类似于:

    secret/db-user-pass-96mffmfh4k created
    
    • 1

    请注意,生成 Secret 时,Secret 的名称最终是由 name 字段和数据的哈希值拼接而成。 这将保证每次修改数据时生成一个新的 Secret。

    3.3、检查创建的 Secret

    你可以检查刚才创建的 Secret:

    $ kubectl get secrets
    
    • 1

    输出类似于:

    NAME                             TYPE                                  DATA      AGE
    db-user-pass-96mffmfh4k          Opaque                                2         51s
    
    • 1
    • 2

    你可以看到 Secret 的描述:

    $ kubectl describe secrets/db-user-pass-96mffmfh4k
    
    • 1

    输出类似于:

    Name:            db-user-pass-96mffmfh4k
    Namespace:       default
    Labels:          >
    Annotations:     >
    
    Type:            Opaque
    
    Data
    ====
    password.txt:    12 bytes
    username.txt:    5 bytes
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    kubectl getkubectl describe 命令默认不显示 Secret 的内容。 这是为了防止 Secret 被意外暴露给旁观者或存储在终端日志中。

    3.5、清理

    删除你创建的 Secret:

    $ kubectl delete secret db-user-pass-96mffmfh4k
    
    • 1

    总结

    通过 API 创建的 Pod 时,不会检查应用的 secret 是否存在。一旦 Pod 被调度,kubelet 就会尝试获取该 secret 的值。如果获取不到该 secret,或者暂时无法与 API server 建立连接,kubelet 将会定期重试。Kubelet 将会报告关于 pod 的事件,并解释它无法启动的原因。一旦获取的 secret,kubelet将创建并装载一个包含它的卷。在安装所有pod的卷之前,都不会启动 pod 的容器。

  • 相关阅读:
    MiddleWare ❀ Zookeeper基础概述
    DotNetCore环境离线CentOS安装
    Mysql 死锁和死锁的解决方案
    自我总结项目中遇到的困难(vue篇)
    【办公类-40-02】20240311 python模仿PPT相册功能批量插入照片,更改背景颜色 (家长会系列二)
    按照C++语言程序结构组成数字电路进行计算的计算机
    PCIe系列专题之五:PCIe总线电源管理
    什么是单子?Java 开发人员的基本理论
    CefSharp自定义缓存实现
    CCF计算机资格认证模拟题202212-1现值计算
  • 原文地址:https://blog.csdn.net/u010755471/article/details/126508811