从 K8s .yaml 文件执行命令的最佳实践

P i*_*P i 1 command yaml kubernetes

我的 .yaml 看起来像这样:

apiVersion: batch/v1
kind: Job
metadata:
  name: foo
  namespace: bar
spec:
  template:
    spec:
      imagePullSecrets:
        - name: $DOCKERHUB_REGISTRY_SECRET
      containers:
        - name: django
          image: $DOCKERHUB_USER/$DOCKERHUB_IMAGENAME:$VERSION
          command: [ 'python manage.py makemigrations' ]
          :
Run Code Online (Sandbox Code Playgroud)

不过,我看到了很多替代方案command

          command: [ 'python', 'manage.py', 'makemigrations' ]
Run Code Online (Sandbox Code Playgroud)
          command: [ '/bin/sh -c', 'python', 'manage.py', 'makemigrations' ]
Run Code Online (Sandbox Code Playgroud)
          command: [ '/bin/sh', '-c' ]
          args: [ 'python', 'manage.py', 'makemigrations' ]
Run Code Online (Sandbox Code Playgroud)
          command: [ 'python' ]
          args: [ 'manage.py', 'makemigrations' ]
Run Code Online (Sandbox Code Playgroud)

ETC。

从美学上来说,我更喜欢最后一种方法,因为它清楚地将命令与参数分开。

但我想检查一下:这些版本之间有什么细微的区别吗?是否存在任何令人信服的逻辑来支持其中一个而不是其他?

Fri*_*rdt 5

K8s文档很详细,但对于这一点并没有很固执。此外,首先必须了解底层容器运行时(例如Docker)的行为。

作为一个好的做法,我建议遵循以下规则:

  • 如果可能,请使用图像默认值。如果您的 Docker 镜像已预先配置了合理的ENTRYPOINT,则无需command在 K8s 配置中定义 a 。如果您的映像已正确预配置,则/bin/sh几乎总是不需要在 K8s 配置中进行定义。

尽管如此,如果您必须覆盖图像默认值,我只会考虑两种常规模式

  • Shell 模式,您command只提供一个 shell 和args实际的可执行文件及其参数。这使您的配置易于阅读,并且使args使用命令链变得复杂。

    command: [ '/bin/sh', '-c' ]
    args: [ 'python manage.py makemigrations' ]
    
    Run Code Online (Sandbox Code Playgroud)
  • Exec 模式,您在其中command提供可执行文件以及args该可执行文件的参数。这遵循将配置分为两部分的架构思想,其中图像的用户通常只需修改args.

    command: [ 'python' ]
    args: [ 'manage.py', 'makemigrations']
    
    Run Code Online (Sandbox Code Playgroud)

请注意,K8s 不允许类似shell 的模式command,例如以下不是有效的配置:

  command: [ '/bin/sh -c' ] << NOT VALID
  args: [ 'python', 'manage.py',  'makemigrations' ]
Run Code Online (Sandbox Code Playgroud)