本文介绍了在将args传递到容器时,Kubernetes的pod/部署?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是docker/k8s世界的新手...有人问我是否可以使用args部署容器来修改行为(通常是应用程序在主"版本还是从"版本中工作),我做过.也许不是最佳解决方案,但它可以起作用:

I'm new to docker/k8s world... I was asked if I could deploy a container using args to modify the behavior (typically if the app is working in "master" or "slave" version), which I did. Maybe not the optimal solution but it works:

这是验证的简单测试.我用一个脚本创建了一个自定义图像:role.sh:

This is a simple test to verify. I made a custom image with a script inside:role.sh:

#!/bin/sh
ROLE=$1
echo "You are running "$ROLE" version of your app"

Dockerfile:

Dockerfile:

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启动此容器:

If I start this container with docker using the following command:

docker run -dit --name test docker.local:5000/test master

我最终得到以下日志,这正是我要查找的日志:

I end up with the following log, which is exactly what I am looking for:

You are running master version of your app

现在,我希望使用yaml文件在k8s上具有相同的行为.我尝试了几种方法,但是没有用.

Now I want to have the same behavior on k8s, using a yaml file. I tried several ways but none worked.

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之间的区别.

I saw so many different ways to do this and I must say that I still don't get the difference between ARG and 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

但是这些都不起作用,我的吊舱始终处于CrashLoopBackOff状态.预先感谢您的帮助!

but none of these worked, my pods are always in CrashLoopBackOff state..Thanks in advance for your help!

推荐答案

在特定字段方面:

  • Kubernetes的command:与Docker的入口点"概念匹配,并且此处指定的内容均作为容器的主要过程运行.如果您的Dockerfile已经具有正确的ENTRYPOINT,则无需在pod规范中指定command:.
  • Kubernetes的args:与Docker的命令"概念匹配,此处指定的任何内容均作为命令行参数传递给入口点.
  • Docker和Kubernetes中的环境变量具有其通常的Unix语义.
  • Dockerfile ARG指定映像的构建时间配置设置. 扩展规则以及与环境变量的交互有点奇怪.以我的经验,这有几个有用的用例(我实际上要针对哪个JVM版本构建?"),但是从图像构建的每个容器将具有相同的继承的ARG值;这不是运行时配置的好机制.
  • 对于可以在Dockerfile或运行时中设置的各种内容(ENV变量,EXPOSE d端口,默认的CMD,尤其是VOLUME),不需要特别在其中声明它们. Dockerfile以便能够在运行时进行设置.
  • Kubernetes's command: matches Docker's "entrypoint" concept, and whatever is specified here is run as the main process of the container. You don't need to specify a command: in a pod spec if your Dockerfile has a correct ENTRYPOINT already.
  • Kubernetes's args: matches Docker's "command" concept, and whatever is specified here is passed as command-line arguments to the entrypoint.
  • Environment variables in both Docker and Kubernetes have their usual Unix semantics.
  • Dockerfile ARG specifies a build-time configuration setting for an image. The expansion rules and interaction with environment variables are a little odd. In my experience this has a couple of useful use cases ("which JVM version do I actually want to build against?"), but every container built from an image will have the same inherited ARG value; it's not a good mechanism for run-time configuration.
  • For various things that could be set in either the Dockerfile or at runtime (ENV variables, EXPOSEd ports, a default CMD, especially VOLUME) there's no particular need to "declare" them in the Dockerfile to be able to set them at run time.

有两种或多或少的等效方法可以完成您所描述的事情. (为了简洁起见,我将使用docker run语法.)可能最灵活的方法是将ROLE设置为环境变量;否则,将其设置为环境变量.当您运行入口点脚本时,可以假定$ROLE具有值,但是值得检查.

There are a couple of more-or-less equivalent ways to do what you're describing. (I will use docker run syntax for the sake of compactness.) Probably the most flexible way is to have ROLE set as an environment variable; when you run the entrypoint script you can assume $ROLE has a value, but it's worth checking.

#!/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

在这种情况下,您可以根据需要在Dockerfile中指定默认的ROLE.

In this case you can specify a default ROLE in the Dockerfile if you want to.

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"]

第二条路径是将角色用作命令行参数:

A second path is to take the role as a command-line parameter:

#!/bin/sh
# --> pass a role name, then a command, as parameters
ROLE="$1"
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

我可能更喜欢环境变量路径,因为它更容易提供多个不相关的选项,并且不会在Docker调用的命令"部分中混合设置"和命令".

I would probably prefer the environment-variable path both for it being a little easier to supply multiple unrelated options and to not mix "settings" and "the command" in the "command" part of the Docker invocation.

关于您的Pod为何崩溃"的原因:Kubernetes通常期望Pod可以长时间运行,因此,如果您编写一个只打印某些内容并退出的容器,Kubernetes会重新启动它,并且当它没有停顿时,它将始终以CrashLoopBackOff状态结束.对于您现在要尝试执行的操作,不必担心,请查看pod的kubectl logs.如果麻烦的话,可以考虑设置pod规范的重启策略你.

As to why your pod is "crashing": Kubernetes generally expects pods to be long-running, so if you write a container that just prints something and exits, Kubernetes will restart it, and when it doesn't stay up, it will always wind up in CrashLoopBackOff state. For what you're trying to do right now, don't worry about it and look at the kubectl logs of the pod. Consider setting the pod spec's restart policy if this bothers you.

这篇关于在将args传递到容器时,Kubernetes的pod/部署?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-01 13:56