You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过GitLab CI/CD变量参数化Pod模板文件(airflow_template.yaml)并替换指定Airflow环境变量?

搞定GitLab CI/CD里Airflow模板变量不生效的问题

嘿,我看你碰到的问题是airflow_template.yaml里的$DEV_AIRFLOW_CONTAINER_REPO$DEV_AIRFLOW_LOG_FOLDER这两个变量,没法被GitLab CI/CD的环境变量自动替换对吧?其实核心原因很简单:这个yaml文件本身不会被shell或者CI流程自动解析,那些$开头的字符串就是纯文本,得你主动在部署或构建阶段处理模板,把变量换成实际值才行。

下面给你几个适配你项目结构的靠谱方案,从简单到优雅都有:

方案1:用envsubst批量替换模板变量

envsubst是GNU工具集里的小工具,能自动把文件里的环境变量引用替换成实际值,刚好适配这种模板场景。

修改deploy_to_dev阶段的脚本

在部署前先处理模板文件,把变量替换好:

deploy_to_dev:
  stage: deploy_to_dev
  image: $CI_REGISTRY_IMAGE:kube-image
  script:
    - echo $DEV_CREDENTIALS > service_account.json && cat service_account.json | docker login -u _json_key --password-stdin https://gcr.io
    - echo "当前日志目录变量值: $DEV_AIRFLOW_LOG_FOLDER"
    # 把CI变量导出到当前shell环境,让envsubst能读到
    - export DEV_AIRFLOW_CONTAINER_REPO="${DEV_AIRFLOW_CONTAINER_REPO}"
    - export DEV_AIRFLOW_LOG_FOLDER="${DEV_AIRFLOW_LOG_FOLDER}"
    # 替换模板变量,生成可用的yaml文件
    - envsubst < dataops/docker/base/airflow_template.yaml > dataops/docker/base/airflow.yaml
    # 后续的集群认证和Helm部署命令
    - gcloud auth activate-service-account $DEV_SERVICE_ACCOUNT --key-file=./service_account.json --project=$DEV_PROJECT_NAME
    - gcloud container clusters get-credentials $DEV_GKE_CLUSTER --region $REGION
    - echo $DEV_DB_CONN > dataops/helm/airflow-loadbalancer/files/secrets/airflow/AIRFLOW__CORE__SQL_ALCHEMY_CONN
    - cd dataops/helm/
    - helm upgrade airflow-dev airflow-loadbalancer/ --install --atomic --set dags_image.tag=$CI_COMMIT_SHORT_SHA
  only:
    refs:
      - develop

注意:如果你的kube-image镜像里没有envsubst,得先安装它——比如Debian/Ubuntu系镜像可以加一句apt-get update && apt-get install -y gettext-base

方案2:把Airflow模板集成到Helm(更推荐)

既然你已经在用Helm部署,把airflow_template.yaml的逻辑迁移到Helm的templates目录下,用Helm的变量系统管理会更优雅,还能完美适配多环境。

步骤1:迁移模板到Helm

dataops/docker/base/airflow_template.yaml的内容复制到dataops/helm/templates/airflow-worker-pod-template.yaml,然后把变量改成Helm模板语法:

apiVersion: v1
kind: Pod
metadata:
  labels: {}
spec:
  containers:
    - args: []
      command: []
      env:
        - name: AIRFLOW__KUBERNETES__WORKER_CONTAINER_REPOSITORY
          value: {{ .Values.airflow.workerContainerRepo }}
        - name: AIRFLOW__LOGGING__REMOTE_BASE_LOG_FOLDER
          value: {{ .Values.airflow.remoteBaseLogFolder }}
      envFrom: []
      imagePullPolicy: Always
      name: base
      ports: []
      volumeMounts:
        - mountPath: /usr/local/airflow/logs
          name: airflow-logs
  hostNetwork: false
  imagePullSecrets: []
  initContainers: []
  nodeSelector: {}
  restartPolicy: Never
  securityContext:
    runAsUser: 1000
  serviceAccountName: default
  volumes:
    - emptyDir: {}
      name: airflow-logs

步骤2:在Helm的values.yaml加默认值

打开dataops/helm/values.yaml,添加默认配置:

airflow:
  workerContainerRepo: "default-repo"
  remoteBaseLogFolder: "default-log-folder"

步骤3:CI里通过Helm传递变量

修改deploy_to_dev的Helm命令,直接把CI变量传进去:

deploy_to_dev:
  stage: deploy_to_dev
  image: $CI_REGISTRY_IMAGE:kube-image
  script:
    - echo $DEV_CREDENTIALS > service_account.json && cat service_account.json | docker login -u _json_key --password-stdin https://gcr.io
    - gcloud auth activate-service-account $DEV_SERVICE_ACCOUNT --key-file=./service_account.json --project=$DEV_PROJECT_NAME
    - gcloud container clusters get-credentials $DEV_GKE_CLUSTER --region $REGION
    - echo $DEV_DB_CONN > dataops/helm/airflow-loadbalancer/files/secrets/airflow/AIRFLOW__CORE__SQL_ALCHEMY_CONN
    - cd dataops/helm/
    - helm upgrade airflow-dev airflow-loadbalancer/ --install --atomic \
        --set dags_image.tag=$CI_COMMIT_SHORT_SHA \
        --set airflow.workerContainerRepo=$DEV_AIRFLOW_CONTAINER_REPO \
        --set airflow.remoteBaseLogFolder=$DEV_AIRFLOW_LOG_FOLDER
  only:
    refs:
      - develop

这种方式的好处太多了:

  • 天然支持dev/prod多环境变量隔离
  • 可以用values文件维护默认值,CI只需要传递差异值
  • 不用额外处理模板文件,Helm会自动帮你渲染

方案3:用sed逐个替换变量

如果不想加新工具,用sed直接替换字符串也能搞定,适合变量少、值不复杂的场景:

deploy_to_dev:
  stage: deploy_to_dev
  image: $CI_REGISTRY_IMAGE:kube-image
  script:
    - echo $DEV_CREDENTIALS > service_account.json && cat service_account.json | docker login -u _json_key --password-stdin https://gcr.io
    # 逐个替换模板里的变量
    - sed -i "s/\$DEV_AIRFLOW_CONTAINER_REPO/$DEV_AIRFLOW_CONTAINER_REPO/g" dataops/docker/base/airflow_template.yaml
    - sed -i "s/\$DEV_AIRFLOW_LOG_FOLDER/$DEV_AIRFLOW_LOG_FOLDER/g" dataops/docker/base/airflow_template.yaml
    # 后续的集群认证和部署命令...

注意:如果变量值里有特殊字符(比如/&),得先转义,不然sed会报错。

为啥原来的方式没生效?

你之前只是把变量导出到shell环境,但airflow_template.yaml文件根本没被任何工具解析——里面的$DEV_AIRFLOW_*就是普通字符串,不会自动变成环境变量的值。必须主动用工具(envsubst/Helm/sed)来完成替换操作才行。

内容的提问来源于stack exchange,提问作者Sandeep Singh

火山引擎 最新活动