【问题标题】:How to properly set bearer API token as an environment variable in K8 pod如何在 K8 pod 中正确设置不记名 API 令牌作为环境变量
【发布时间】:2021-07-14 17:10:32
【问题描述】:

我有一个大问题,我会尽量简短地解释。我正在端点上运行 cronjob,并希望将该过程容器化。端点需要设置一些环境变量,并且显然是 TOKEN 身份验证,这基本上是我可以 curl POST 或 GET 从 API 获取我想要的内容之前的登录。棘手的部分是 TOKEN 永远不会相同,这意味着我需要运行 curl 命令才能在 pod 运行时获取它。为了确保这些环境变量在运行时存在,我在 cronjob args 字段中注入了一个命令以使其保持运行。当我 ssh 到 pod 时,我所有的 env var 都在那里 ;) 但是 TOKEN :( 。当我从 pod 内部运行 ./run.sh 时,什么也没有发生,这就是令牌未列在 printenv 中的原因。但是,当我从 pod 内部手动运行 command 1 然后 command 2 时,它工作正常。我很困惑,如果可以请帮助我。而不是在 docker 级别在 cmd 中将我的命令作为 bash 运行,我已经看到我可以使用多行块标量从我的 cronjob.yaml 中的run.sh 解析command 1 和command 2,但还没有想到 yaml 格式是多么痛苦。下面是我的代码更多细节:

docker-entrypoint.sh --> 移除

#! /bin/sh
export AWS_REGION=$AWS_REGION
export API_VS_HD=$API_VS_HD
export CONTROLLER_IP=$CONTROLLER_IP
export PASSWORD=$PASSWORD
export UUID=$UUID

Dockerfile

FROM harbor/ops5/private/:device-purge/python38:3.8

# Use root user for packages installation
USER root

# Install packages
RUN yum update -y && yum upgrade -y

# Install curl
RUN yum install curl -y \
    && curl --version

# Install zip/unzip/gunzip
RUN yum install zip unzip -y \
    && yum install gzip -y

# Install wget 
RUN yum install wget -y

# Install jq
RUN wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
RUN chmod +x ./jq
RUN cp jq /usr/bin

# Install aws cli
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
RUN unzip awscliv2.zip
RUN ./aws/install

# Set working directory
WORKDIR /home/app

# Add user
RUN groupadd --system user && adduser --system user --no-create-home --gid user
RUN chown -R user:user /home/app && chmod -R 777 /home/app

# Copy app
COPY ./run.sh /home/app 
RUN chmod +x /home/app/run.sh

# Switch to non-root user
USER user

# Run service
CMD ["sh", "-c", "./run.sh"]

run.sh

# Command 1
export TOKEN=`curl -H "Content-Type: application/json" -H "${API_VS_HD}" --request POST --data "{\"providerName\":\"local\",\"username\":\"admin\",\"password\":\"$PASSWORD\",\"deviceId\":\"$UUID\"}" https://$CONTROLLER_IP:444/admin/login --insecure | jq -r '.token'`

# Sleep 
sleep 3

# Command 2
curl -k -H "Content-Type: application/json" \
         -H "$API_VS_HD" \
         -H "Authorization: Bearer $TOKEN" \
         -X GET \
         https://$CONTROLLER_IP:444/admin/license/users

cronjob.yaml

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: device-cron-job
  namespace: device-purge
spec:
  schedule: "*/2 * * * *" # test
  jobTemplate:
    spec:
      template:
        spec:
          imagePullSecrets:
          - name: cron
          containers:
          - name: device-cron-pod
            image: harbor/ops5/private/:device-purge
            env:
            - name: AWS_REGION
              value: "us-east-1"
            - name: API_VS_HD
              value: "Accept:application/vnd.appgate.peer-v13+json"
            - name: CONTROLLER_IP
              value: "52.61.245.214"
            - name: UUID
              value: "d2b78ec2-####-###-###-#########"
            - name: PASSWORD
              valueFrom:
                secretKeyRef: 
                  name: password
                  key: password
            imagePullPolicy: Always
          restartPolicy: OnFailure
      backoffLimit: 3

【问题讨论】:

    标签: bash docker api kubernetes yaml


    【解决方案1】:

    run.sh 永远不会被调用。 docker-entrypoint.sh 需要通过在底部添加 exec $@ 来执行 run.sh。但是无论如何你并不真的需要入口点,这些环境变量已经被 docker 导出到你的环境中。我也不确定您为什么在 yaml 规范中指定 command 和 args,但我会摆脱这些。

    当您以这种形式提供ENTRYPOINT 和CMD 命令时,CMD 参数将传递给入口点文件,然后入口点文件负责执行必要的过程。您可以查看文档here。

    【讨论】:

      【解决方案2】:

      您的自定义入口点似乎阻止 run.sh 运行,并且脚本本身没有指定解释器。

      你可以试试:

      #Switch back to default entrypoint
      ENTRYPOINT ["/bin/sh"]
      
      #Actually run run.sh
      # NOTE THE INITIAL dot (.) after "-c"
      CMD ["-c",". docker-entrypoint.sh && ./run.sh"]
      

      并删除 k8s CronJob command 和关联的 args(您也可以在 CronJob yaml 中实现相同的目的,但我更喜欢让容器准备好完成它们的工作,而不是在 k8s 级别指定 CMD。

      您还可以让/bin/sh 更容易运行run.sh,方法是在第一行说明如何运行它并在那里导入环境变量(我猜这就是为什么当你输入./run.sh 时它不运行的原因):

      #!/bin/sh
      
      # Note the initial dot '.'
      . docker-entrypoint.sh
      
      # Command 1
      [...]
      
      # Command 2
      [...]
      

      另一个建议是在 k8s CronJob yaml 级别定义docker-entrypoint.sh 中定义的环境变量。这被认为是在 k8s pod 中定义环境变量的最佳实践。变量值敏感时可以使用k8s secrets。

      【讨论】:

      • 感谢两位的反馈。为了使它工作,我删除了docker-entrypoint,并将CMD中的命令作为默认可执行文件运行,然后从cron yaml中删除了args和command。上帝保佑你们俩 ;).. 我还更新了我上面使用的最终代码,供任何感兴趣的人使用。
      • 嘿@kddiji,很高兴它有帮助!如果答案对您有用,您会考虑点赞吗?
      猜你喜欢
      • 2018-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2013-07-17
      • 1970-01-01
      • 2021-02-18
      相关资源
      最近更新 更多