在kubernetes中,如何访问configmap中的环境变量?

时间:2020-10-14 17:27:04

标签: kubernetes kubernetes-helm kubernetes-pod

我有用例将pod名称附加到“ jdbc_db_url ”属性中。该文件位于“ common-configmap.config ”文件中。为了实现这一目标,我遵循了以下步骤,但很遗憾无法实现。

步骤1: common-configmap.config

# Database Properties
jdbc_auto_commit=false

jdbc_postgresql_driverClassName=org.postgresql.Driver
jdbc_db_url=jdbc:postgresql://dev.postgres.database.azure.com/dbname?ApplicationName=${POD_NAME}

步骤2: 使用以下命令将configmap部署到集群中

kubectl create configmap common-configmap --from-env-file /app/conf/common-configmap.config -n default

第3步: 使用以下清单文件创建“ myapp”容器和服务

部署清单文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    meta.helm.sh/release-name: master
    meta.helm.sh/release-namespace: default
  generation: 1
  labels:
    app.kubernetes.io/instance: master
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: myapp
    app.kubernetes.io/version: 4.0.0
    helm.sh/chart: myapp-4.0.0
  name: myapp
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 5
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: master
      app.kubernetes.io/name: myapp
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
      labels:
        app.kubernetes.io/instance: master
        app.kubernetes.io/name: myapp
    spec:
      containers:
      - env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        envFrom:
        - configMapRef:
            name: myapp-configmap
        - configMapRef:
            name: common-configmap
        image: docker.com/myapp:4.0.0
        imagePullPolicy: Always
        name: myapp
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always

服务清单文件:

apiVersion: v1
kind: Service
metadata:
  annotations:
    meta.helm.sh/release-name: master
    meta.helm.sh/release-namespace: default
  labels:
    app.kubernetes.io/instance: master
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: myapp
    app.kubernetes.io/version: 4.0.0
    helm.sh/chart: myapp-4.0.0
  name: myapp
  namespace: default
spec:
  ports:
 - name: http
    port: 8080
    protocol: TCP
    targetPort: http
  selector:
    app.kubernetes.io/instance: master
    app.kubernetes.io/name: myapp
  sessionAffinity: None
  type: ClusterIP

验证结果,然后进入运行外壳的容器并打印环境变量:

kubectl exec --stdin --tty myapp-d5db776b9-h25q5 -c myapp -- /bin/sh

实际结果:

# printenv

jdbc_auto_commit=false
jdbc_postgresql_driverClassName=org.postgresql.Driver
jdbc_db_url=jdbc:postgresql://dev.postgres.database.azure.com/dbname?ApplicationName=${POD_NAME}

预期结果:

jdbc_auto_commit=false
jdbc_postgresql_driverClassName=org.postgresql.Driver
jdbc_db_url=jdbc:postgresql://dev.postgres.database.azure.com/dbname?ApplicationName=myapp-d5db776b9-h25q5
  • 我如何在配置映射中替换环境变量,同时 部署/容器运行时?或还有其他方法 通过/替换 JDBC_URL

    中的 pod_name
  • 我可以知道,在这种情况下我做了什么错事?

预先感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您可以使用init容器与主容器之间共享emptyDir类型的共享容器来完成此操作。

首先,编辑部署以添加一个emptyDir卷和一个初始化容器,并将该卷安装到两个容器中:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    meta.helm.sh/release-name: master
    meta.helm.sh/release-namespace: default
  generation: 1
  labels:
    app.kubernetes.io/instance: master
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: myapp
    app.kubernetes.io/version: 4.0.0
    helm.sh/chart: myapp-4.0.0
  name: myapp
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 5
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: master
      app.kubernetes.io/name: myapp
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
      labels:
        app.kubernetes.io/instance: master
        app.kubernetes.io/name: myapp
    spec:
      volumes: # emptyDir volume for the entire pod
        - name: config-volume
          emptyDir: {}
      initContainers: # an init container that will compile the env var with the pod name
      - name: config-compiler
        image: bash
        volumeMounts:
        - name: config-compiler
          mountPath: /configs
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        envFrom:
        - configMapRef:
            name: common-configmap
        command: 
        - bash
        - -c
        - 'echo $jdbc_db_url | sed "s/POD_NAME/${POD_NAME}/" > /configs/compiled.env'
      containers:
      - volumeMounts:
        - name: config-compiler
          mountPath: /configs
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        envFrom:
        - configMapRef:
            name: myapp-configmap
        - configMapRef:
            name: common-configmap
        image: docker.com/myapp:4.0.0
        imagePullPolicy: Always
        name: myapp
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always

然后,您需要确保您的实际Pod正在读取env vars文件-您可以通过编辑入口点脚本以添加如下一行来做到这一点:

source /configs/compiled.env

或将广告连播的命令编辑为类似的内容:

command: [ 'source', '/configs/compiled.env;', 'previous-command' ]

以上两种方法都有点漏洞-因此,我建议您做的是查看应用程序默认读取的配置文件,并使您的编译脚本与之匹配。

例如,如果您的应用程序从/etc/myapp/confs.d/files.env读取-将空目录挂载到/etc/myapp/confs.d并将init容器写入files.env,并按照应用程序期望的格式进行操作(例如,如果它是ini文件而不是env文件,请对其进行编译,使其与该格式匹配)

显然,还有比sed更好的方法来编译配置文件-但是,如果您希望(并且负担得起)使事情简短,则可以选择

答案 1 :(得分:0)

一种简单的方法是在部署中使用一个简单的命令,假设JDBC_URL值仅在示例容器中使用。否则,您可以在自定义基础映像(如果有)或init容器中具有类似的逻辑。

pip install pipwin
pipwin install pygame

请注意我插入的代码段:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    meta.helm.sh/release-name: master
    meta.helm.sh/release-namespace: default
  generation: 1
  labels:
    app.kubernetes.io/instance: master
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: myapp
    app.kubernetes.io/version: 4.0.0
    helm.sh/chart: myapp-4.0.0
  name: myapp
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 5
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: master
      app.kubernetes.io/name: myapp
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
      labels:
        app.kubernetes.io/instance: master
        app.kubernetes.io/name: myapp
    spec:
      containers:
      - env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        envFrom:
        - configMapRef:
            name: myapp-configmap
        - configMapRef:
            name: common-configmap
        image: docker.com/myapp:4.0.0
        imagePullPolicy: Always
        name: myapp
        command: 
        - bash
        - -c
        - export JDBC_URL=$(echo $JDBC_URL | sed "s/POD_NAME/${POD_NAME}/1")
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always