Kubernetes pod/deployment 在将参数传递给容器时?
Kubernetes pod/deployment while passing args to container?
我是 docker/k8s 世界的新手...有人问我是否可以使用 args 部署容器来修改行为(通常如果应用程序在 "master" 或 "slave" 版本),我这样做了。也许不是最佳解决方案,但它有效:
这是一个简单的验证测试。我制作了一个带有脚本的自定义图像:
role.sh:
#!/bin/sh
ROLE=
echo "You are running "$ROLE" version of your app"
Docker 文件:
FROM centos:7.4.1708
COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE=""
ARG ROLE
ENTRYPOINT ["role.sh"]
CMD ["${ROLE}"]
如果我使用以下命令以 docker 启动此容器:
docker run -dit --name test docker.local:5000/test master
我最终得到以下日志,这正是我要找的:
You are running master version of your app
现在我想在 k8s 上有相同的行为,使用 yaml 文件。我尝试了几种方法,但 none 奏效了。
YAML 文件:
apiVersion: v1
kind: Pod
metadata:
name: master-pod
labels:
app: test-master
spec:
containers:
- name: test-master-container
image: docker.local:5000/test
command: ["role.sh"]
args: ["master"]
我看到了很多不同的方法来做到这一点,我必须说我仍然不明白 ARG 和 ENV 之间的区别。
我也试过
- name: test-master-container
image: docker.local:5000/test
env:
- name: ROLE
value: master
和
- name: test-master-container
image: docker.local:5000/test
args:
- master
但是其中 none 有效,我的 pods 总是处于 CrashLoopBackOff 状态。
预先感谢您的帮助!
在具体领域方面:
- Kubernetes的
command:
符合Docker的"entrypoint"概念,这里指定的就是运行作为容器的主进程。如果您的 Docker 文件已经具有正确的 ENTRYPOINT
,则无需在 pod 规范中指定 command:
。
- Kubernetes 的
args:
匹配 Docker 的 "command" 概念,这里指定的任何内容都作为命令行参数传递给入口点。
- Docker 和 Kubernetes 中的环境变量都有它们通常的 Unix 语义。
- Dockerfile
ARG
指定图像的 build-time 配置设置。 expansion rules and interaction with environment variables 有点奇怪。根据我的经验,这有几个有用的用例 ("which JVM version do I actually want to build against?"),但是 每个从图像构建的 容器将具有相同的继承 ARG
值;这不是 运行-time 配置的好机制。
- 对于可以在 Docker 文件中或在 运行 时间设置的各种东西(
ENV
变量,EXPOSE
d 端口,默认 CMD
,尤其是 VOLUME
) 没有特别需要在 Docker 文件中 "declare" 它们,以便能够在 运行 时间设置它们。
有几种或多或少等效的方法可以完成您所描述的事情。 (为了简洁起见,我将使用 docker run
语法。)可能最灵活的方法是将 ROLE
设置为环境变量;当您 运行 入口点脚本时,您可以假设 $ROLE
有一个值,但值得检查。
#!/bin/sh
# --> I expect $ROLE to be set
# --> Pass some command to run as additional arguments
if [ -z "$ROLE" ]; then
echo "Please set a ROLE environment variable" >&2
exit 1
fi
echo "You are running $ROLE version of your app"
exec "$@"
docker run --rm -e ROLE=some_role docker.local:5000/test /bin/true
在这种情况下,您可以根据需要在 Docker 文件中指定默认值 ROLE
。
FROM centos:7.4.1708
COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE="default_role"
ENTRYPOINT ["role.sh"]
第二种方法是将角色作为命令行参数:
#!/bin/sh
# --> pass a role name, then a command, as parameters
ROLE=""
if [ -z "$ROLE" ]; then
echo "Please pass a role as a command-line option" >&2
exit 1
fi
echo "You are running $ROLE version of your app"
shift # drops first parameter
export ROLE # makes it an environment variable
exec "$@"
docker run --rm docker.local:5000/test some_role /bin/true
我可能更喜欢环境变量路径,因为它更容易提供多个不相关的选项,并且不会在 "command" 部分混合使用 "settings" 和 "the command" Docker 调用。
至于为什么你的 pod 是 "crashing":Kubernetes 通常期望 pods 是 long-运行ning,所以如果你写一个只打印一些东西然后退出的容器,Kubernetes将重新启动它,当它没有保持运行时,它将 总是 结束在 CrashLoopBackOff
状态。对于您现在正在尝试做的事情,请不要担心它并查看 pod 的 kubectl logs
。如果这让您感到困扰,请考虑设置 pod 规范的 restart policy。
为了回答您的具体情况,考虑到您声明它们的方式,您的 ARG 或 ENV 似乎都没有效果。
您的工作流程应该是:
- 编写您的 Dockerfile(就像您所做的那样,好的)
- build 你的容器(你没有提供你使用的构建命令,但鉴于你的 ARG 声明,我假设你必须在那里传递一个值)
- 运行 您的容器(
docker run
或在 kubernetes pod/deployment/etc 中)
你的 ENV ROLE=""
意味着在构建期间你应该有一个空变量 $ROLE 你可以在整个 Dockerfile 中使用它并且它将在 运行ning 的环境中以相同的名称可用容器(大概是一个空字符串)。
你的 ARG ROLE
意味着你需要将一个 ROLE 传递给你的 docker build
命令,它将在构建期间的整个 Dockerfile 中可用,大概会覆盖你之前声明的 ENV,但除了构建过程。
就您的 运行ning 脚本而言,唯一重要的角色是 ROLE=
,例如。变量 $ROLE 取第一个参数的值。这意味着在你的 kubernetes yml 中指定一个 env RULE 是没有意义的,因为当你的脚本 运行s 时,它会用你的脚本的第一个参数覆盖 RULE,即使有 none (导致空价值)。
这个规范看起来是正确的,别忘了你可以用 args: ["$(ROLE)"]
之类的东西替换 args: ["master"]
(例如:它会期望在执行你的 kubectl 的机器上设置一个 ROLE env var。
apiVersion: v1
kind: Pod
metadata:
name: master-pod
labels:
app: test-master
spec:
containers:
- name: test-master-container
image: docker.local:5000/test
command: ["role.sh"]
args: ["master"]
我是 docker/k8s 世界的新手...有人问我是否可以使用 args 部署容器来修改行为(通常如果应用程序在 "master" 或 "slave" 版本),我这样做了。也许不是最佳解决方案,但它有效:
这是一个简单的验证测试。我制作了一个带有脚本的自定义图像: role.sh:
#!/bin/sh
ROLE=
echo "You are running "$ROLE" version of your app"
Docker 文件:
FROM centos:7.4.1708
COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE=""
ARG ROLE
ENTRYPOINT ["role.sh"]
CMD ["${ROLE}"]
如果我使用以下命令以 docker 启动此容器:
docker run -dit --name test docker.local:5000/test master
我最终得到以下日志,这正是我要找的:
You are running master version of your app
现在我想在 k8s 上有相同的行为,使用 yaml 文件。我尝试了几种方法,但 none 奏效了。
YAML 文件:
apiVersion: v1
kind: Pod
metadata:
name: master-pod
labels:
app: test-master
spec:
containers:
- name: test-master-container
image: docker.local:5000/test
command: ["role.sh"]
args: ["master"]
我看到了很多不同的方法来做到这一点,我必须说我仍然不明白 ARG 和 ENV 之间的区别。
我也试过
- name: test-master-container
image: docker.local:5000/test
env:
- name: ROLE
value: master
和
- name: test-master-container
image: docker.local:5000/test
args:
- master
但是其中 none 有效,我的 pods 总是处于 CrashLoopBackOff 状态。 预先感谢您的帮助!
在具体领域方面:
- Kubernetes的
command:
符合Docker的"entrypoint"概念,这里指定的就是运行作为容器的主进程。如果您的 Docker 文件已经具有正确的ENTRYPOINT
,则无需在 pod 规范中指定command:
。 - Kubernetes 的
args:
匹配 Docker 的 "command" 概念,这里指定的任何内容都作为命令行参数传递给入口点。 - Docker 和 Kubernetes 中的环境变量都有它们通常的 Unix 语义。
- Dockerfile
ARG
指定图像的 build-time 配置设置。 expansion rules and interaction with environment variables 有点奇怪。根据我的经验,这有几个有用的用例 ("which JVM version do I actually want to build against?"),但是 每个从图像构建的 容器将具有相同的继承ARG
值;这不是 运行-time 配置的好机制。 - 对于可以在 Docker 文件中或在 运行 时间设置的各种东西(
ENV
变量,EXPOSE
d 端口,默认CMD
,尤其是VOLUME
) 没有特别需要在 Docker 文件中 "declare" 它们,以便能够在 运行 时间设置它们。
有几种或多或少等效的方法可以完成您所描述的事情。 (为了简洁起见,我将使用 docker run
语法。)可能最灵活的方法是将 ROLE
设置为环境变量;当您 运行 入口点脚本时,您可以假设 $ROLE
有一个值,但值得检查。
#!/bin/sh
# --> I expect $ROLE to be set
# --> Pass some command to run as additional arguments
if [ -z "$ROLE" ]; then
echo "Please set a ROLE environment variable" >&2
exit 1
fi
echo "You are running $ROLE version of your app"
exec "$@"
docker run --rm -e ROLE=some_role docker.local:5000/test /bin/true
在这种情况下,您可以根据需要在 Docker 文件中指定默认值 ROLE
。
FROM centos:7.4.1708
COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE="default_role"
ENTRYPOINT ["role.sh"]
第二种方法是将角色作为命令行参数:
#!/bin/sh
# --> pass a role name, then a command, as parameters
ROLE=""
if [ -z "$ROLE" ]; then
echo "Please pass a role as a command-line option" >&2
exit 1
fi
echo "You are running $ROLE version of your app"
shift # drops first parameter
export ROLE # makes it an environment variable
exec "$@"
docker run --rm docker.local:5000/test some_role /bin/true
我可能更喜欢环境变量路径,因为它更容易提供多个不相关的选项,并且不会在 "command" 部分混合使用 "settings" 和 "the command" Docker 调用。
至于为什么你的 pod 是 "crashing":Kubernetes 通常期望 pods 是 long-运行ning,所以如果你写一个只打印一些东西然后退出的容器,Kubernetes将重新启动它,当它没有保持运行时,它将 总是 结束在 CrashLoopBackOff
状态。对于您现在正在尝试做的事情,请不要担心它并查看 pod 的 kubectl logs
。如果这让您感到困扰,请考虑设置 pod 规范的 restart policy。
为了回答您的具体情况,考虑到您声明它们的方式,您的 ARG 或 ENV 似乎都没有效果。
您的工作流程应该是:
- 编写您的 Dockerfile(就像您所做的那样,好的)
- build 你的容器(你没有提供你使用的构建命令,但鉴于你的 ARG 声明,我假设你必须在那里传递一个值)
- 运行 您的容器(
docker run
或在 kubernetes pod/deployment/etc 中)
你的 ENV ROLE=""
意味着在构建期间你应该有一个空变量 $ROLE 你可以在整个 Dockerfile 中使用它并且它将在 运行ning 的环境中以相同的名称可用容器(大概是一个空字符串)。
你的 ARG ROLE
意味着你需要将一个 ROLE 传递给你的 docker build
命令,它将在构建期间的整个 Dockerfile 中可用,大概会覆盖你之前声明的 ENV,但除了构建过程。
就您的 运行ning 脚本而言,唯一重要的角色是 ROLE=
,例如。变量 $ROLE 取第一个参数的值。这意味着在你的 kubernetes yml 中指定一个 env RULE 是没有意义的,因为当你的脚本 运行s 时,它会用你的脚本的第一个参数覆盖 RULE,即使有 none (导致空价值)。
这个规范看起来是正确的,别忘了你可以用 args: ["$(ROLE)"]
之类的东西替换 args: ["master"]
(例如:它会期望在执行你的 kubectl 的机器上设置一个 ROLE env var。
apiVersion: v1
kind: Pod
metadata:
name: master-pod
labels:
app: test-master
spec:
containers:
- name: test-master-container
image: docker.local:5000/test
command: ["role.sh"]
args: ["master"]