3

我在做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,
                            },
4

1 回答 1

1

使用环境变量

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

环境变量来自ConfigMap

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

来自 Kubernetes 文档的示例

创建第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

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

Secret手动创建:

您首先需要使用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

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

现在你可以使用这个Secret为环境变量创建的。

要在 Pod 的环境变量中使用密钥:

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

这是PodKubernetes 文档中的一个示例,展示了如何使用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 中。

使用存储在 ConfigMap 中的数据填充卷

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "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

使用 Secrets 作为来自 Pod 的文件

要在 Pod 的卷中使用 Secret:

  1. 创建一个秘密或使用现有的秘密。多个 Pod 可以引用同一个 secret。
  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在卷中安装 a的示例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
于 2020-09-03T09:16:48.783 回答