You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu环境下runit如何读取K8s注入的容器环境变量?

问题描述

我们在用于K8s部署的Docker镜像中使用runit /etc/service/,/etc/service路径下包含/etc/service/acme/run脚本,该脚本通过Dockerfile如下配置复制:

COPY --link=true --chmod=755 scripts/acme_server.sh /etc/service/acme/run

acme_server.sh脚本内容示例如下:

#!/bin/bash
set -x 
exec 2>&1
export PATH="/opt/app_venv/bin:${PATH}"

EV_ACME_REPOSITORY=`echo $ACME_REPOSITORY`
if [[  -z "$EV_ACME_REPOSITORY" ]]
then
    ln -s /app/ACME_repository /ACME
iACME_PATH=${EV_ACME_REPOSITORY:-"/app/acme_repository"}
/opt/unicornserver/bin/unicornserver --exit-on-error=false --acme-repository="${iACME_PATH}"

K8s部署配置中已设置环境变量:

env:
  - name: ACME_REPOSITORY
    value: "/var/www/acme/repository"

登录Pod后,通过env、printenv或echo $ACME_REPOSITORY均能看到该变量值,但runit启动的脚本未获取到ACME_REPOSITORY的值,最终使用了默认的错误路径,日志如下:

2023-05-15_04:45:09.65401 + EV_ACME_REPOSITORY=
2023-05-15_04:45:09.65401 + [[ -z '' ]]
2023-05-15_04:45:09.65402 + ln -s /app/ACME_repository /ACME
2023-05-15_04:45:09.65409 + iACME_PATH=/app/ACME_repository
2023-05-15_04:45:09.65410 + /opt/unicornserver/bin/unicornserver --exit-on-error=false --acme-repository=/app/ACME_repository

如何让runit启动的脚本正确获取到该环境变量的值?

解决方法

runit默认不会自动继承容器的全局环境变量到其管理的服务进程中,以下是几种可行的解决方式:

方法1:在run脚本中手动导入环境变量

直接在acme_server.sh开头添加环境变量导入逻辑,可从容器init进程的环境变量文件/proc/1/environ中读取:

#!/bin/bash
set -x 
exec 2>&1

# 从容器init进程导入环境变量
while IFS='=' read -r key value; do
  export "$key=$value"
done < <(tr '\0' '\n' < /proc/1/environ)

export PATH="/opt/app_venv/bin:${PATH}"

EV_ACME_REPOSITORY="$ACME_REPOSITORY"
if [[  -z "$EV_ACME_REPOSITORY" ]]
then
    ln -s /app/ACME_repository /ACME
fi
iACME_PATH=${EV_ACME_REPOSITORY:-"/app/acme_repository"}
/opt/unicornserver/bin/unicornserver --exit-on-error=false --acme-repository="${iACME_PATH}"

如果你的镜像会将环境变量写入/etc/environment,也可以用更简洁的方式导入:

if [ -f /etc/environment ]; then
  source /etc/environment
fi

方法2:使用runit自带的envdir工具传递变量

runit的envdir工具可以从指定目录加载环境变量(目录下文件名对应变量名,文件内容对应变量值):

  1. 在Dockerfile中创建环境变量存储目录:
RUN mkdir -p /etc/env.d/acme
  1. 修改K8s部署配置,通过init容器将环境变量写入该目录:
env:
  - name: ACME_REPOSITORY
    value: "/var/www/acme/repository"
volumeMounts:
  - name: acme-env
    mountPath: /etc/env.d/acme
volumes:
  - name: acme-env
    emptyDir: {}
initContainers:
  - name: set-acme-env
    image: busybox
    command: ['sh', '-c', 'echo "$ACME_REPOSITORY" > /etc/env.d/acme/ACME_REPOSITORY']
    env:
      - name: ACME_REPOSITORY
        value: "/var/www/acme/repository"
    volumeMounts:
      - name: acme-env
        mountPath: /etc/env.d/acme
  1. 修改acme_server.sh,通过envdir加载变量后启动服务:
#!/bin/bash
set -x 
exec 2>&1

exec envdir /etc/env.d/acme /opt/unicornserver/bin/unicornserver --exit-on-error=false --acme-repository="${ACME_REPOSITORY:-/app/acme_repository}"

方法3:修改runit启动命令,全局传递环境变量

如果runit是容器的ENTRYPOINT/CMD,可在启动runit前先导入所有环境变量,让所有runit管理的服务都能继承:
修改Dockerfile的CMD:

CMD ["/bin/sh", "-c", "export $(cat /proc/1/environ | tr '\\0' '\\n' | xargs) && runsvdir /etc/service"]

这种方式无需修改单个服务的run脚本,一次性解决所有服务的环境变量继承问题。

内容的提问来源于stack exchange,提问作者hare krshn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 04:22:54