如何获得部署配置的操作员最佳实践 ConfigMap中的环境变量 Secret中的环境变量

问题描述

我正在研究operator-sdk,在控制器中,我们经常需要创建一个Deployment对象,并且Deployment资源具有很多配置项,例如环境变量或端口定义或其他如下配置。我想知道获取这些值的最佳方法是什么,我不想对它们进行硬编码,例如,variable_a或variable_b。

可能您可以将它们作为规范放入CRD中,然后将其传递给Operator Controller。或者,您可以将它们放入configmap中,然后将configmap名称传递给Operator Controller,Operator Controller可以访问configmap来获取它们;或者,您可以放入模板文件,然后在操作员控制器中,控制器必须读取该模板文件。

处理这种情况的最佳方法或最佳做法是什么?感谢您分享您的想法或观点。

    deployment := &appsv1.Deployment{
        ObjectMeta: metav1.ObjectMeta{
            Name:      m.Name,Namespace: m.Namespace,Labels:    ls,},Spec: appsv1.DeploymentSpec{
            Replicas: &replicas,Selector: &metav1.LabelSelector{
                MatchLabels: ls,Template: corev1.PodTemplateSpec{
                ObjectMeta: metav1.ObjectMeta{
                    Labels: ls,Spec: corev1.PodSpec{
                    Containers: []corev1.Container{{
                        Image: "....",Name: m.Name,Ports: []corev1.ContainerPort{{
                            ContainerPort: port_a,Name:          "tcpport",}},Env: []corev1.EnvVar{
                            {
                                Name:  "aaaa",Value: variable_a,{
                                Name:  "bbbb",Value: variable_b,

解决方法

使用环境变量

应用程序将数据作为环境变量获取会很方便。

ConfigMap中的环境变量

对于非敏感数据,可以将变量存储在ConfigMap中,然后使用ConfigMap数据定义容器环境变量。

Example from Kubernetes docs

首先创建ConfigMap。文件configmaps.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO

创建ConfigMap:

kubectl create -f ./configmaps.yaml

然后在Pod规范pod-multiple-configmap-env-variable.yaml中定义环境变量:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh","-c","env" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: env-config
              key: log_level
  restartPolicy: Never

创建Pod

kubectl create -f ./pod-multiple-configmap-env-variable.yaml

现在,您可以在控制器中读取以下环境变量SPECIAL_LEVEL_KEY(将从special.how special-config中获得ConfigMap的值)和LOG_LEVEL(将从log_level env-config给您ConfigMap的价值):

例如:

specialLevelKey := os.Getenv("SPECIAL_LEVEL_KEY")
logLevel := os.Getenv("LOG_LEVEL")

fmt.Println("SPECIAL_LEVEL_KEY:",specialLevelKey)
fmt.Println("LOG_LEVEL:",logLevel)

Secret中的环境变量

如果您的数据敏感,则可以将其存储在Secret中,然后将Secret用作环境变量。

To create a Secret manually

您首先需要使用base64对字符串进行编码。

# encode username
$ echo -n 'admin' | base64
YWRtaW4=

# encode password
$ echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm

然后使用上述数据创建一个Secret

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

使用Secret创建一个kubectl apply

$ kubectl apply -f ./secret.yaml

请注意,还有其他方法可以创建一个秘密,选择最适合您的秘密:

现在您可以use this created Secret for environment variables了。

要在Pod中的环境变量中使用机密信息:

  1. 创建一个秘密或使用现有的秘密。多个Pod可以引用相同的秘密。
  2. 在每个您希望使用密钥值的容器中修改Pod定义,以便为您希望使用的每个密钥添加环境变量。使用秘密密钥的环境变量应在env[].valueFrom.secretKeyRef中填充秘密的名称和密钥。
  3. 修改图像和/或命令行,以便程序在指定的环境变量中查找值。

这是Kubernetes文档中的一个Pod示例,展示了如何对环境变量使用Secret

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
  restartPolicy: Never

最后,如文档所述:

在一个在环境变量中使用秘密的容器中,秘密密钥显示为包含秘密数据的base64解码值的普通环境变量。

现在,您可以在控制器中读取以下环境变量SECRET_USERNAME(将从username mysecret中获得Secret的值)和SECRET_PASSWORD(将从password mysecret给您Secret的价值):

例如:

username := os.Getenv("SECRET_USERNAME")
password := os.Getenv("SECRET_PASSWORD")

使用卷

您还可以将ConfigMapSecret都作为卷安装到您的Pod。

Populate a Volume with data stored in a ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh","ls /etc/config/" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        # Provide the name of the ConfigMap containing the files you want
        # to add to the container
        name: special-config
  restartPolicy: Never

Using Secrets as files from a Pod

要在Pod中的某个卷中使用秘密:

  1. 创建一个秘密或使用现有的秘密。多个Pod可以引用相同的秘密。
  2. 修改您的Pod定义以在.spec.volumes []下添加一个体积。将该卷命名为任何名称,并具有一个.spec.volumes []。secret.secretName字段,该字段等于Secret对象的名称。
  3. 向每个需要机密的容器添加.spec.containers[].volumeMounts[]。将.spec.containers[].volumeMounts[].readOnly = true.spec.containers[].volumeMounts[].mountPath指定为您要显示机密的未使用目录名称。 修改您的图像或命令行,以便程序在该目录中查找文件。秘密data映射中的每个密钥都变成mountPath下的文件名。

Pod装入卷中的Secret的示例:

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...