generic

这里将分作两部分讨论,第一部分是将数据传入generic类型的Secret,即创建Secret,第二部分是将数据从Secret中传入容器中(以环境变量的方式、以文件的形式)。

该类型的Secret的secret.type=Opaque

配置传入Secret

数据传入Secret的过程,即创建Secret的过程,在创建时,可以将需要传给Pod中容器的信息以键/值对的形式写入Secret中。

创建Secret与ConfigMap同样有两种方式:

  1. 使用指令创建(优选);

  2. 使用配置文件创建;

使用命令创建

在使用kubectl create secret generic创建generic类型的Secret时,可以通过不同的参数,以不同的方式向其中写入数据:

  1. --from-literal:最普通的写入方式,值为简单的字面量:

    例如,创建一个名为mysecret的Secret,其包含username=adminpassword=123456两个条目:

     kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123456
  2. --from-env-file:后面跟的是文件名,文件中存放的是键/值对形式的条目,它们会被批量传入Secret中:

     # 先通过key=value的方式创建环境变量的文件
     cat << EOF > env.txt
     > username=admin
     > password=123456
     > EOF
     # 使用k8s命令创建
     kubectl create secret generic mysecret --from-env-file=env.txt
  3. --from-file:将文件内容作为值写入:

    例如,创建一个名为mysecret的generic类型的Secret,其包含的文件内容为username.conf中的内容,其username.conf(因为不自定义的关系,所以默认与文件名一致):

     kubectl create secret generic mysecret --from-file=username.conf

    当然,也可以手动指定键。例如,指定键名为username

     kubectl create configmap myconfigmap --from-file=username=username.conf

Tips: --from-file后面除了跟单个文件名外,同样可以跟目录名,其会将该目录下所有文件名合法的文件都传入Secret中,即批量传入多个条目,但是这种情况下,无法单独指定键名。

使用配置文件创建

Secret的配置文件非常简单,需要写入的数据都被存放在了secret.data中,下面展示一个案例:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret    # 该Secret的名字
type: Opaque    # Secret的默认类型,可以不指定
stringData:
  foo: bar    # stringData中存放非二进制数据,可以不用手动Base64编码,但是在创建后,会自动编码
data:
  username: YWRtaW4=    # 敏感数据需手动base64编码,使用echo -n admin | base64得到,使用base64 --decode可以反编码
  password: MTIzNDU2    # password是文件名,在容器中,内容会自动反编码再存入文件

Tips: 在Secret的配置文件中

  1. secret.data中写入键/值对时,值需要经过Base64编码后再放入配置文件中;

  2. secret.stringData中写入键/值对时,可以不经过Base64编码,就可以将值放入配置文件中;

从Secret中读取数据

Pod中的容器想要从Secret中读取数据,与ConfigMap类似,同样有两种方式:

  1. 读取为环境变量(不推荐):分为读取单个条目和读取所有条目两种方式;

  2. 读取为文件:将Secret以卷的方式挂载,进而从中读取数据;

读取为环境变量

从ConfigMap读取配置为环境变量类似,可以从Secret中读取数据作为环境变量,可以读取单个条目,或者一次性读取所有条目。

读取单个条目

读取单个条目,是通过Pod的配置文件中的spec.env.valueFrom.secretKeyRef进行配置,从而从Secret中读取指定的条目,作为环境变量。

例如,为容器创建一个键为FOO_SECRET的环境变量,其值引用的是名为fortune-https的Secret中的键为foo的条目的值:

env:    # 配置容器的环境变量
- name: FOO_SECRET    # 环境变量的Key
  valueFrom:    # 配置环境变量的Value
    secretKeyRef:    # 从Secret中读取数据
      name: fortune-https    # Secret的名字
      key: foo    # (必须)Secret中的条目的key,将key为foo的条目的value,作为容器的Key为FOO_SECRET的环境变量的Value

读取所有条目

读取所有条目,是通过Pod的配置文件中的spec.containers.envFrom.secretRef进行配置,从而从Secret中读取所有的条目,作为环境变量。

如果Secret中某键名不符合环境变量的键名格式,那么在创建环境变量时,会自动忽略对应的条目。

例如,容器从名为fortune-https的Secret中读取所有条目作为环境变量:

envFrom:    # 配置容器的环境变量
- secretRef:    # 从Secret中读取数据
  name: fortune-https    # Secret的名字

通过指定spec.containers.envFrom.prefix可以为读入的所有环境变量添加前缀,比如Secret中包含键为FOOBAR的两个条目,那么可以通过下面这种方式添加前缀CONFIG_,令读入容器中的环境变量变成CONFIG_FOOCONFIG_BAR

envFrom:
- prefix: CONFIG_    # 为读入的环境变量添加前缀CONFIG_
  configMapKeyRef:
    name: fortune-config

读取为文件

从ConfigMap读取配置为文件类似,Secret中的条目可以被容器以文件的形式读入,这种情况下,需要将Secret作为卷挂载至Pod中的容器中。

在挂载至容器后,默认情况下,容器会将Secret中的条目的作为文件名,将条目的作为文件内容,且在读取内容时会自动将其Base64解码。

因为Secret中具有多个条目,因此可以通过在pod.spec.volumes.secret.items中进行指定单独挂载的文件。

挂载所有文件

将Secret作为卷挂载,需要下面两步:

  1. 定义卷:在spec.volumes.secret中指定secretName为预先创建好的Secret资源的名字,即与Secret资源相关联;

  2. 挂载卷:在Pod的spec.containers.volumeMounts中指定挂载点和挂载的卷名;

下面举一个例子,在容器的/etc/nginx/certs/下挂载一个名为certs的Secret卷,该卷与名为fortune-https的Secret相关联,容器会将该Secret中的所有条目,以条目的键为文件名,值的Base64解码作为文件内容,在挂载点中创建这些文件:

apiVersion: v1
kind: Pod
metadata:
  name: fortune-https
spec:
  containers:
  - image: nginx:alpine
    name: web-server
    volumeMounts:    # 定义挂载点
    - name: certs    # (必须)挂载的卷名
      mountPath: /etc/nginx/certs/    # (必须)容器中的挂载点,该目录下的原文件都会被隐藏
      readOnly: true
    ports:
    - containerPort: 80
    - containerPort: 443
  volumes:    # 定义卷
  - name: certs    # (必须)卷名
    secret:    # 创建的是Secret卷
      secretName: fortune-https    # 需要挂载的Secret的名字
      defaultMode: 0660    # 为挂载的文件设置权限,默认是0644,取值范围为0~0777

挂载指定文件

同样,挂载卷的方式可以只挂载部分文件,而不是将Secret中的所有文件都挂载进Pod。有两种方法可以实现:

  1. 利用pod.spec.volumeMounts.subPath将卷中的指定文件挂载至容器中,具体方法可以参考这章节;

    优点:挂载点中原本存在的文件不会被隐藏;

    缺点:应用于Secret卷时,被挂载的文件不会随着Secret中条目的更新而更新;

  2. 利用spec.volumes.secret.items定义卷时,指定需要被挂载至卷中的条目;

    优点:被挂载的文件会随着Secret中条目的更新而更新,更新原理与ConfigMap的同步更新一样

    缺点:挂载点中原本存在的文件会被隐藏;

这里针对第二种方法进行详细介绍。

下面举一个例子,在容器的/etc/nginx/certs/下挂载一个名为certs的Secret卷,该卷与名为fortune-https的Secret相关联,容器会将该Secret中的键为username.conf的条目,更名为username,将条目的值Base64解码后,在挂载点中创建该文件:

apiVersion: v1
kind: Pod
metadata:
  name: fortune-https
spec:
  containers:
  - image: nginx:alpine
    name: web-server
    volumeMounts:    # 定义挂载点
    - name: certs    # (必须)挂载的卷名
      mountPath: /etc/nginx/certs/    # (必须)容器中的挂载点,该目录下的源文件都会被隐藏
      readOnly: true
    ports:
    - containerPort: 80
    - containerPort: 443
  volumes:    # 定义卷
  - name: certs    # (必须)卷名
    secret:    # 创建的是Secret卷
      name: fortune-https    # 需要挂载的ConfigMap的名字
      items:    # 仅挂载ConfigMap中的部分条目
      - key: username.conf    # (必须)Secret中条目的键名
        path: username    # (必须)挂载至容器中挂载点的相对路径
        mode: 0660    # 为挂载的文件设置权限,默认是0644,取值范围为0~0777

Last updated

Was this helpful?