前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在容器中获取配置及上下文信息 -- Projected Volumes

在容器中获取配置及上下文信息 -- Projected Volumes

作者头像
用户3147702
发布2022-06-27 17:04:12
9870
发布2022-06-27 17:04:12
举报
文章被收录于专栏:小脑斧科技博客

1. 引言

上一篇文章中,我们详细介绍了 Kubernetes 中的 Pod:

详解 Kubernetes 中的 Pod

在实际的线上场景中,我们并不能在配置 Pod 的 yaml 里描述所有需要的信息,因为总有一些信息或因为其保密性,或因为其动态变化性,是不能够放在配置文件里的,那么,这类信息要怎么加入到我们的 Pod 配置体系中呢?

这就需要一种特殊的 Volume -- 投射数据卷,Projected Volume。本文我们就来详细介绍投射数据卷的用法。

2. 投射数据卷

之所以被称作“投射数据卷”,是因为这些数据是提前定义好,或者动态拉取,然后投射进 Kubernetes 的容器中的,它们有三种:

  1. Secret
  2. ConfigMap
  3. DownwardAPI

需要注意的是:

  1. Pod 只能使用同一个命名空间中的 Projected Volume;
  2. Pod 要使用的 Projected Volume 必须在 Pod 启动前就已经存在;
  3. 虽然 Projected Volume 基本上都有挂载为 volume 和作为环境变量两种使用方式,但作为环境变量的方式不会随着 volume 数据本身的更新而更新,所以对于需要感知 Projected Volume 数据变化的场景,还是推荐挂载为 volume 来进行使用。

下面,我们来一一介绍。

3. Secret

Secret Volume 的作用是帮你把想要访问的加密数据存放到 etcd 中,这样,Pod 中的容器就可以通过挂载相应 Volume 的方式访问到这些加密信息了。

3.1 Secret Volume 的创建

有两种方式可以创建 Secret Volume:

  1. 通过命令的方式;
  2. 通过 yaml 配置文件的方式。

3.1.1 通过命令创建 Secret Volume

首先,我们需要两个文件,分别用来存储用户名和密码:

$ echo "admin" > username.txt $ echo "UjtLdUtzWOnfcIh8" > password.txt

然后,执行 kubectl create 命令就可以完成 Secret Volume 的创建:

$ kubectl create secret generic user --from-file=./username.txt $ kubectl create secret generic pass --from-file=./password.txt

3.1.2 通过配置文件创建 Secret Volume

编写配置文件:

代码语言:javascript
复制
apiVersion: v1
kind: Secret
metadata:
  name: secret-volume
type: Opaque
data:
  user: YWRtaW4=
  pass: VWp0TGRVdHpXT25mY0loOAo=
  • 需要注意的是,在配置文件中,所有数据中的值都需要进行 base64 转码处理。

同样,通过 kubectl create 命令,就可以完成 Secret Volume 的创建了:

$ kubectl create -f secret-volume.yaml

3.1.3 Secret Volume 的查询

通过 kubectl get 命令可以进行 secret 的查询:

$ kubectl get secretes

事实上,这样查询出来的明文结果是具有很大的风险的,在真实的线上环境中,我们还需要开启 Secret 加密插件,进一步保障数据的保密性。

3.2 Secret Volume 的实际使用

Secret Volume 虽然是一种用来保存加密信息的特殊的 Volume,但他的使用和其他 Volume 并没有明显区别。

例如,下面是一个 Pod 的定义:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: test-projected-volume 
spec:
  containers:
  - name: test-secret-volume
    image: busybox
    args:
    - sleep
    - "86400"
    volumeMounts:
    - name: mysql-cred
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: mysql-cred
    projected:
      sources:
      - secret:
          name: user
      - secret:
          name: pass

我们通过 exec 命令进入到这个容器,通过查看挂载的目录就可以看到相应的内容了:

$ kubectl exec -it test-projected-volume -- /bin/sh $ cat /projected-volume/user root

4. ConfigMap

ConfigMap 与 Secret 非常类似,也是通过用键值对的方式来保存数据的 Volume,区别在于 ConfigMap 并非用来保存加密数据的,他是用来保存配置信息的。

4.1 ConfigMap 的配置

与 Secret 一样,ConfigMap 也有两种配置方法:

  1. 通过 properties 文件配置;
  2. 通过 yaml 文件配置。

4.1.1 通过 properties 文件配置

首先,我们先定义 properties 文件:

代码语言:javascript
复制
color.good=purple
color.bad=yellow
allow.textmod=true

执行 kubectl create 命令即可完成 ConfigMap 的创建:

$ kubectl create configmap ui-config --from-file=ui.properties

4.1.2 通过 yaml 文件配置

编写配置文件:

代码语言:javascript
复制
apiVersion: v1
kind: ConfigMap
metadata:
 name: ui-config
data:
 color.good: purple
 color.bad: yellow

执行 kubectl create 命令即可完成 ConfigMap 的创建:

$ kubectl create -f config.yaml

4.1.3 查询 ConfigMap

通过 kubectl describe 命令就可以实现 ConfigMap 的查询了:

$ kubectl describe configmap ui-config

4.2 使用 ConfigMap

接下来我们来介绍两种可以在 Pod 中使用 ConfigMap 的方式:

  1. 配置到容器的环境变量;
  2. 使用 Volume 将 ConfigMap 作为文件或目录挂载。

除此以外,还可以编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap,这种方式后续再进行介绍,敬请期待。

  • 在使用 envFrom 时,会自动忽略无效的键。

4.2.1 将 ConfigMap 配置到容器的环境变量

  • 配置环境变量
代码语言:javascript
复制
# test-pod-configmap.yaml
apiVersion: v1
kind: Pod
metadata:
 name: test-pod-configmap
spec:
 containers:
  - name: test-busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    args:
    - sleep
    - "86400"
    env:
    - name: KEY1
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.good
    - name: KEY2
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.bad
  • 配置容器启动参数

通常,我们会想要用 ConfigMap 来设置容器启动时的命令行参数,尽管这是 Kubernetes 不支持的,但它支持通过环境变量来配置启动参数,我们就可以如法炮制了:

代码语言:javascript
复制
# test-pod-configmap-cmd
apiVersion: v1
kind: Pod
metadata:
 name: test-pod-configmap-cmd
spec:
 containers:
  - name: test-busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    command: [ "/bin/sh","-c","echo $(KEY1) $(KEY2)"]
    env:
    - name: KEY1
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.good
    - name: KEY2
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.bad
 restartPolicy: Never

4.2.2 将 ConfigMap 挂载到容器中

同样,我们也可以将 ConfigMap 作为普通的 volume 挂载到容器中:

代码语言:javascript
复制
# test-pod-projected-configmap-volume.yaml
apiVersion: v1
kind: Pod
metadata:
 name: test-pod-projected-configmap-volume
spec:
 containers:
 - name: test-pod-busybox
   image: busybox
   imagePullPolicy: IfNotPresent
   args:
   - sleep
   - "86400"
   volumeMounts:
   - name: config-volume
     mountPath: "/projected-volume"
     readOnly: true
 volumes:
 - name: config-volume
   projected:
    sources:
    - configMap:
       name: ui-config

5. Downward API

在我们配置一个 Pod 时,我们把许许多多的信息编写在了配置文件上,但有时候,我们需要在容器中获取当前 Pod 的这些配置信息,我们又该怎么做呢?

Kubernetes 提供了 Downward API,来让我们能够实现这一功能。

5.1 Downward API 的使用

例如:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: test-downwardapi-volume
  labels:
    zone: us-est-coast
    cluster: test-cluster1
    rack: rack-22
spec:
  containers:
    - name: client-container
      image: k8s.gcr.io/busybox
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
            echo -en '\n\n'; cat /etc/podinfo/labels; fi;
          sleep 5;
        done;
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
          readOnly: false
  volumes:
    - name: podinfo
      projected:
        sources:
        - downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels

在这个 pod 的定义中,我们定义了一个 downwardAPI 类型的 projected volume 并且挂载到了容器中,而这个容器的功能,就是循环打印挂载的 projected volume 中的文件内容。

于是我们看到打印出了我们为这个 pod 定义的 labels:

$ kubectl logs test-downwardapi-volume cluster="test-cluster1" rack="rack-22" zone="us-est-coast"

5.2 支持的 Downward API 列表

目前,Downward API 支持的字段已经非常丰富了,他分为两个部分:

1. 使用 fieldRef 声明和使用

  1. spec.nodeName - 宿主机名字
  2. status.hostIP - 宿主机IP
  3. metadata.name - Pod的名字
  4. metadata.namespace - Pod的Namespace
  5. status.podIP - Pod的IP
  6. spec.serviceAccountName - Pod的Service Account的名字
  7. metadata.uid - Pod的UID
  8. metadata.labels['<KEY>'] - 指定<KEY>的Label值
  9. metadata.annotations['<KEY>'] - 指定<KEY>的Annotation值
  10. metadata.labels - Pod的所有Label
  11. metadata.annotations - Pod的所有Annotation
  12. 使用 resourceFieldRef 声明和使用.

2. 7. Projected Volume

1. 引言

上一篇文章中,我们详细介绍了 Kubernetes 中的 Pod:

<a id="10183740"></a>

在实际的线上场景中,我们并不能在配置 Pod 的 yaml 里描述所有需要的信息,因为总有一些信息或因为其保密性,或因为其动态变化性,是不能够放在配置文件里的,那么,这类信息要怎么加入到我们的 Pod 配置体系中呢?

这就需要一种特殊的 Volume -- 投射数据卷,Projected Volume。本文我们就来详细介绍投射数据卷的用法。

2. 投射数据卷

之所以被称作“投射数据卷”,是因为这些数据是提前定义好,或者动态拉取,然后投射进 Kubernetes 的容器中的,它们有四种:

  1. Secret
  2. ConfigMap
  3. DownwardAPI
  4. ServiceAccountToken

需要注意的是,Pod 只能使用同一个命名空间中的 Projected Volume。

下面,我们来一一介绍。

3. Secret

Secret Volume 的作用是帮你把想要访问的加密数据存放到 etcd 中,这样,Pod 中的容器就可以通过挂载相应 Volume 的方式访问到这些加密信息了。

3.1 Secret Volume 的创建

有两种方式可以创建 Secret Volume:

  1. 通过命令的方式;
  2. 通过 yaml 配置文件的方式。

3.1.1 通过命令创建 Secret Volume

首先,我们需要两个文件,分别用来存储用户名和密码:

$ echo "admin" > username.txt $ echo "UjtLdUtzWOnfcIh8" > password.txt

然后,执行 kubectl create 命令就可以完成 Secret Volume 的创建:

$ kubectl create secret generic user --from-file=./username.txt $ kubectl create secret generic pass --from-file=./password.txt

3.1.2 通过配置文件创建 Secret Volume

编写配置文件:

代码语言:javascript
复制
apiVersion: v1
kind: Secret
metadata:
  name: secret-volume
type: Opaque
data:
  user: YWRtaW4=
  pass: VWp0TGRVdHpXT25mY0loOAo=
  • 需要注意的是,在配置文件中,所有数据中的值都需要进行 base64 转码处理。

同样,通过 kubectl create 命令,就可以完成 Secret Volume 的创建了:

$ kubectl create -f secret-volume.yaml

3.1.3 Secret Volume 的查询

通过 kubectl get 命令可以进行 secret 的查询:

$ kubectl get secretes

事实上,这样查询出来的明文结果是具有很大的风险的,在真实的线上环境中,我们还需要开启 Secret 加密插件,进一步保障数据的保密性。

3.2 Secret Volume 的实际使用

Secret Volume 虽然是一种用来保存加密信息的特殊的 Volume,但他的使用和其他 Volume 并没有明显区别。

例如,下面是一个 Pod 的定义:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: test-projected-volume 
spec:
  containers:
  - name: test-secret-volume
    image: busybox
    args:
    - sleep
    - "86400"
    volumeMounts:
    - name: mysql-cred
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: mysql-cred
    projected:
      sources:
      - secret:
          name: user
      - secret:
          name: pass

我们通过 exec 命令进入到这个容器,通过查看挂载的目录就可以看到相应的内容了:

$ kubectl exec -it test-projected-volume -- /bin/sh $ cat /projected-volume/user root

4. ConfigMap

ConfigMap 与 Secret 非常类似,也是通过用键值对的方式来保存数据的 Volume,区别在于 ConfigMap 并非用来保存加密数据的,他是用来保存配置信息的。

4.1 ConfigMap 的配置

与 Secret 一样,ConfigMap 也有两种配置方法:

  1. 通过 properties 文件配置;
  2. 通过 yaml 文件配置。

4.1.1 通过 properties 文件配置

首先,我们先定义 properties 文件:

代码语言:javascript
复制
color.good=purple
color.bad=yellow
allow.textmod=true

执行 kubectl create 命令即可完成 ConfigMap 的创建:

$ kubectl create configmap ui-config --from-file=ui.properties

4.1.2 通过 yaml 文件配置

编写配置文件:

代码语言:javascript
复制
apiVersion: v1
kind: ConfigMap
metadata:
 name: ui-config
data:
 color.good: purple
 color.bad: yellow

执行 kubectl create 命令即可完成 ConfigMap 的创建:

$ kubectl create -f config.yaml

4.1.3 查询 ConfigMap

通过 kubectl describe 命令就可以实现 ConfigMap 的查询了:

$ kubectl describe configmap ui-config

4.2 使用 ConfigMap

接下来我们来介绍两种可以在 Pod 中使用 ConfigMap 的方式:

  1. 配置到容器的环境变量;
  2. 使用 Volume 将 ConfigMap 作为文件或目录挂载。

除此以外,还可以编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap,这种方式后续再进行介绍,敬请期待。

  • 需要注意的是,ConfigMap 必须在Pod使用它之前创建。
  • 在使用 envFrom 时,会自动忽略无效的键。

4.2.1 将 ConfigMap 配置到容器的环境变量

  • 配置环境变量
代码语言:javascript
复制
# test-pod-configmap.yaml
apiVersion: v1
kind: Pod
metadata:
 name: test-pod-configmap
spec:
 containers:
  - name: test-busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    args:
    - sleep
    - "86400"
    env:
    - name: KEY1
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.good
    - name: KEY2
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.bad
  • 配置容器启动参数

通常,我们会想要用 ConfigMap 来设置容器启动时的命令行参数,尽管这是 Kubernetes 不支持的,但它支持通过环境变量来配置启动参数,我们就可以如法炮制了:

代码语言:javascript
复制
# test-pod-configmap-cmd
apiVersion: v1
kind: Pod
metadata:
 name: test-pod-configmap-cmd
spec:
 containers:
  - name: test-busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    command: [ "/bin/sh","-c","echo $(KEY1) $(KEY2)"]
    env:
    - name: KEY1
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.good
    - name: KEY2
      valueFrom:
       configMapKeyRef:
        name: ui-config
        key: color.bad
 restartPolicy: Never

4.2.2 将 ConfigMap 挂载到容器中

同样,我们也可以将 ConfigMap 作为普通的 volume 挂载到容器中:

代码语言:javascript
复制
# test-pod-projected-configmap-volume.yaml
apiVersion: v1
kind: Pod
metadata:
 name: test-pod-projected-configmap-volume
spec:
 containers:
 - name: test-pod-busybox
   image: busybox
   imagePullPolicy: IfNotPresent
   args:
   - sleep
   - "86400"
   volumeMounts:
   - name: config-volume
     mountPath: "/projected-volume"
     readOnly: true
 volumes:
 - name: config-volume
   projected:
    sources:
    - configMap:
       name: ui-config

5. Downward API

在我们配置一个 Pod 时,我们把许许多多的信息编写在了配置文件上,但有时候,我们需要在容器中获取当前 Pod 的这些配置信息,我们又该怎么做呢?

Kubernetes 提供了 Downward API,来让我们能够实现这一功能。

5.1 Downward API 的使用

例如:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: test-downwardapi-volume
  labels:
    zone: us-est-coast
    cluster: test-cluster1
    rack: rack-22
spec:
  containers:
    - name: client-container
      image: k8s.gcr.io/busybox
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
            echo -en '\n\n'; cat /etc/podinfo/labels; fi;
          sleep 5;
        done;
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
          readOnly: false
  volumes:
    - name: podinfo
      projected:
        sources:
        - downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels

在这个 pod 的定义中,我们定义了一个 downwardAPI 类型的 projected volume 并且挂载到了容器中,而这个容器的功能,就是循环打印挂载的 projected volume 中的文件内容。

于是我们看到打印出了我们为这个 pod 定义的 labels:

$ kubectl logs test-downwardapi-volume cluster="test-cluster1" rack="rack-22" zone="us-est-coast"

5.2 支持的 Downward API 列表

目前,Downward API 支持的字段已经非常丰富了,他分为两个部分:

1. 使用 fieldRef 声明和使用

  1. spec.nodeName - 宿主机名字
  2. status.hostIP - 宿主机 IP
  3. metadata.name - Pod 的名字
  4. metadata.namespace - Pod 的 Namespace
  5. status.podIP - Pod 的 IP
  6. spec.serviceAccountName - Pod 的 Service Account的名字
  7. metadata.uid - Pod 的 UID
  8. metadata.labels['<KEY>'] - 指定 <KEY> 的Label值
  9. metadata.annotations['<KEY>'] - 指定 <KEY> 的Annotation值
  10. metadata.labels - Pod 的所有 Label
  11. metadata.annotations - Pod 的所有 Annotation

2. 使用 resourceFieldRef 声明和使用

  1. limits.cpu -- 容器的 CPU 限额
  2. requests.cpu -- 容器的 CPU 需求
  3. limits.memory -- 容器的内存限额
  4. requests.memory -- 容器的内存需求
  5. limits.ephemeral-storage -- 容器的存储空间限额
  6. requests.ephemeral-storage -- 容器的存储空间需求

例如:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-resourcefieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox:1.24
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_CPU_REQUEST MY_CPU_LIMIT;
          printenv MY_MEM_REQUEST MY_MEM_LIMIT;
          sleep 10;
        done;
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      env:
        - name: MY_CPU_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.memory
  restartPolicy: Never
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. 投射数据卷
  • 3. Secret
    • 3.1 Secret Volume 的创建
      • 3.1.1 通过命令创建 Secret Volume
      • 3.1.2 通过配置文件创建 Secret Volume
      • 3.1.3 Secret Volume 的查询
    • 3.2 Secret Volume 的实际使用
    • 4. ConfigMap
      • 4.1 ConfigMap 的配置
        • 4.1.1 通过 properties 文件配置
        • 4.1.2 通过 yaml 文件配置
        • 4.1.3 查询 ConfigMap
      • 4.2 使用 ConfigMap
        • 4.2.1 将 ConfigMap 配置到容器的环境变量
        • 4.2.2 将 ConfigMap 挂载到容器中
    • 5. Downward API
      • 5.1 Downward API 的使用
        • 5.2 支持的 Downward API 列表
          • 1. 使用 fieldRef 声明和使用
          • 2. 7. Projected Volume
      • 1. 引言
      • 2. 投射数据卷
      • 3. Secret
        • 3.1 Secret Volume 的创建
          • 3.1.1 通过命令创建 Secret Volume
          • 3.1.2 通过配置文件创建 Secret Volume
          • 3.1.3 Secret Volume 的查询
        • 3.2 Secret Volume 的实际使用
        • 4. ConfigMap
          • 4.1 ConfigMap 的配置
            • 4.1.1 通过 properties 文件配置
            • 4.1.2 通过 yaml 文件配置
            • 4.1.3 查询 ConfigMap
          • 4.2 使用 ConfigMap
            • 4.2.1 将 ConfigMap 配置到容器的环境变量
            • 4.2.2 将 ConfigMap 挂载到容器中
        • 5. Downward API
          • 5.1 Downward API 的使用
            • 5.2 支持的 Downward API 列表
              • 1. 使用 fieldRef 声明和使用
              • 2. 使用 resourceFieldRef 声明和使用
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档