Init 容器

该特性在 1.6 版本已经退出 beta 版本。Init 容器可以在 PodSpec 中同应用程序的 containers 数组一起来指定。 beta 注解的值将仍需保留,并覆盖 PodSpec 字段值。

本文讲解 Init 容器的基本概念,它是一种专用的容器,在应用程序容器启动之前运行,并包括一些应用镜像中不存在的实用工具和安装脚本。

理解 Init 容器

Pod 能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的 Init 容器。

Init 容器与普通的容器非常像,除了如下两点:

  • Init 容器总是运行到成功完成为止。
  • 每个 Init 容器都必须在下一个 Init 容器启动之前成功完成。

如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 为 Never,它不会重新启动。

指定容器为 Init 容器,在 PodSpec 中添加 initContainers 字段,以 v1.Container 类型对象的 JSON 数组的形式,还有 app 的 containers 数组。 Init 容器的状态在 status.initContainerStatuses 字段中以容器状态数组的格式返回(类似 status.containerStatuses 字段)。

与普通容器的不同之处

Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。 然而,Init 容器对资源请求和限制的处理稍有不同,在下面 资源 处有说明。 而且 Init 容器不支持 Readiness Probe,因为它们必须在 Pod 就绪之前运行完成。

如果为一个 Pod 指定了多个 Init 容器,那些容器会按顺序一次运行一个。 每个 Init 容器必须运行成功,下一个才能够运行。 当所有的 Init 容器运行完成时,Kubernetes 初始化 Pod 并像平常一样运行应用容器。

Init 容器能做什么?

因为 Init 容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:

  • 它们可以包含并运行实用工具,但是出于安全考虑,是不建议在应用程序容器镜像中包含这些实用工具的。
  • 它们可以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像中。例如,创建镜像没必要 FROM 另一个镜像,只需要在安装过程中使用类似 sed、 awk、 python 或 dig 这样的工具。
  • 应用程序镜像可以分离出创建和部署的角色,而没有必要联合它们构建一个单独的镜像。
  • Init 容器使用 Linux Namespace,所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问 Secret 的权限,而应用程序容器则不能。
  • 它们必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以 Init 容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件。

示例

下面是一些如何使用 Init 容器的想法:

  • 等待一个 Service 创建完成,通过类似如下 shell 命令:
      for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; exit 1
    
  • 将 Pod 注册到远程服务器,通过在命令中调用 API,类似如下:
      curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
    
  • 在启动应用容器之前等一段时间,使用类似 sleep 60 的命令。
  • 克隆 Git 仓库到数据卷。
  • 将配置值放到配置文件中,运行模板工具为主应用容器动态地生成配置文件。例如,在配置文件中存放 POD_IP 值,并使用 Jinja 生成主应用配置文件。

更多详细用法示例,可以在 StatefulSet 文档 和 生产环境 Pod 指南 中找到。

使用 Init 容器

下面是 Kubernetes 1.5 版本 yaml 文件,展示了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 myservice 启动,第二个等待 mydb 启动。 一旦这两个 Service 都启动完成,Pod 将开始启动。

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
  annotations:
    pod.beta.kubernetes.io/init-containers: '[
        {
            "name": "init-myservice",
            "image": "busybox",
            "command": ["sh", "-c", "until nslookup myservice; do echo waiting for myservice; sleep 2; done;"]
        },
        {
            "name": "init-mydb",
            "image": "busybox",
            "command": ["sh", "-c", "until nslookup mydb; do echo waiting for mydb; sleep 2; done;"]
        }
    ]'
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']

这是 Kubernetes 1.6 版本的新语法,尽管老的 annotation 语法仍然可以使用。我们已经把 Init 容器的声明移到 spec 中:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

1.5 版本的语法在 1.6 版本仍然可以使用,但是我们推荐使用 1.6 版本的新语法。 在 Kubernetes 1.6 版本中,Init 容器在 API 中新建了一个字段。 虽然期望使用 beta 版本的 annotation,但在未来发行版将会被废弃掉。

下面的 yaml 文件展示了 mydb 和 myservice 两个 Service:

kind: Service
apiVersion: v1
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

这个 Pod 可以使用下面的命令进行启动和调试:

$ kubectl create -f myapp.yaml
pod "myapp-pod" created
$ kubectl get -f myapp.yaml
NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m
$ kubectl describe -f myapp.yaml 
Name:          myapp-pod
Namespace:     default
[...]
Labels:        app=myapp
Status:        Pending
[...]
Init Containers:
  init-myservice:
[...]
    State:         Running
[...]
  init-mydb:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Containers:
  myapp-container:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Events:
  FirstSeen    LastSeen    Count    From                      SubObjectPath                           Type          Reason        Message
  ---------    --------    -----    ----                      -------------                           --------      ------        -------
  16s          16s         1        {default-scheduler }                                              Normal        Scheduled     Successfully assigned myapp-pod to 172.17.4.201
  16s          16s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Pulling       pulling image "busybox"
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Pulled        Successfully pulled image "busybox"
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Created       Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Started       Started container with docker id 5ced34a04634
$ kubectl logs myapp-pod -c init-myservice # Inspect the first init container
$ kubectl logs myapp-pod -c init-mydb      # Inspect the second init container

一旦我们启动了 mydb 和 myservice 这两个 Service,我们能够看到 Init 容器完成,并且 myapp-pod 被创建:

$ kubectl create -f services.yaml
service "myservice" created
service "mydb" created
$ kubectl get -f myapp.yaml
NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

这个例子非常简单,但是应该能够为我们创建自己的 Init 容器提供一些启发。

具体行为

在 Pod 启动过程中,Init 容器会按顺序在网络和数据卷初始化之后启动。 每个容器必须在下一个容器启动之前成功退出。 如果由于运行时或失败退出,导致容器启动失败,它会根据 Pod 的 restartPolicy 指定的策略进行重试。 然而,如果 Pod 的 restartPolicy 设置为 Always,Init 容器失败时会使用 RestartPolicy策略。

在所有的 Init 容器没有成功之前,Pod 将不会变成 Ready 状态。 Init 容器的端口将不会在 Service 中进行聚集。 正在初始化中的 Pod 处于 Pending 状态,但应该会将条件 Initializing 设置为 true。

如果 Pod 重启,所有 Init 容器必须重新执行。

对 Init 容器 spec 的修改,被限制在容器 image 字段中。 更改 Init 容器的 image 字段,等价于重启该 Pod。

因为 Init 容器可能会被重启、重试或者重新执行,所以 Init 容器的代码应该是幂等的。 特别地,被写到 EmptyDirs 中文件的代码,应该对输出文件可能已经存在做好准备。

Init 容器具有应用容器的所有字段。 除了 readinessProbe,因为 Init 容器无法定义不同于完成(completion)的就绪(readiness)的之外的其他状态。 这会在验证过程中强制执行。

在 Pod 上使用 activeDeadlineSeconds,在容器上使用 livenessProbe,这样能够避免 Init 容器一直失败。 这就为 Init 容器活跃设置了一个期限。

在 Pod 中的每个 app 和 Init 容器的名称必须唯一;与任何其它容器共享同一个名称,会在验证时抛出错误。

资源

为 Init 容器指定顺序和执行逻辑,下面对资源使用的规则将被应用:

  • 在所有 Init 容器上定义的,任何特殊资源请求或限制的最大值,是 有效初始请求/限制
  • Pod 对资源的有效请求/限制要高于:
    • 所有应用容器对某个资源的请求/限制之和
    • 对某个资源的有效初始请求/限制
  • 基于有效请求/限制完成调度,这意味着 Init 容器能够为初始化预留资源,这些资源在 Pod 生命周期过程中并没有被使用。
  • Pod 的 有效 QoS 层,是 Init 容器和应用容器相同的 QoS 层。

基于有效 Pod 请求和限制来应用配额和限制。 Pod 级别的 cgroups 是基于有效 Pod 请求和限制,和调度器相同。

Pod 重启的原因

Pod 能够重启,会导致 Init 容器重新执行,主要有如下几个原因:

  • 用户更新 PodSpec 导致 Init 容器镜像发生改变。应用容器镜像的变更只会重启应用容器。
  • Pod 基础设施容器被重启。这不多见,但某些具有 root 权限可访问 Node 的人可能会这样做。
  • 当 restartPolicy 设置为 Always,Pod 中所有容器会终止,强制重启,由于垃圾收集导致 Init 容器完成的记录丢失。

支持与兼容性

Apiserver 版本为 1.6 或更高版本的集群,通过使用 spec.initContainers 字段来支持 Init 容器。 之前的版本可以使用 alpha 和 beta 注解支持 Init 容器。 spec.initContainers 字段也被加入到 alpha 和 beta 注解中,所以 Kubernetes 1.3.0 版本或更高版本可以执行 Init 容器,并且 1.6 版本的 apiserver 能够安全的回退到 1.5.x 版本,而不会使存在的已创建 Pod 失去 Init 容器的功能。

原文地址:https://k8smeetup.github.io/docs/concepts/workloads/pods/init-containers/

译者:shirdrn

K8S中文社区微信公众号

Kubernetes kubectl 命令表

kubectl命令列表

K8S中文社区微信公众号

Kubernetes kubectl set subject 命令详解

kubectl set subject

更新RoleBinding / ClusterRoleBinding中User、Group 或 ServiceAccount。

语法

$ subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]

示例

更新一个ClusterRoleBinding 的 serviceaccount1

kubectl set subject clusterrolebinding admin --serviceaccount=namespace:serviceaccount1

更新RoleBinding的user1,user2和group1

kubectl set subject rolebinding admin --user=user1 --user=user2 --group=group1

Flags

Name Shorthand Default Usage
all false select all resources in the namespace of the specified resource types
allow-missing-template-keys true If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.
dry-run false If true, only print the object that would be sent, without sending it.
filename f [] Filename, directory, or URL to files the resource to update the subjects
group [] groups to bind to the role
local false If true, set resources will NOT contact api-server but run locally.
no-headers false When using the default or custom-column output format, don't print headers (default print headers).
output o Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].
output-version DEPRECATED: To use a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').
recursive R false Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.
selector l Selector (label query) to filter on, supports '=', '==', and '!='.
serviceaccount [] service accounts to bind to the role
show-all a false When printing, show all resources (default hide terminated pods.)
show-labels false When printing, show all labels as the last column (default hide labels column)
sort-by If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
template Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
user [] usernames to bind to the role
K8S中文社区微信公众号

Kubernetes kubectl set selector 命令详解

kubectl set selector

设置资源的selector(选择器)。如果在调用"set selecto"命令之前已经存在选择器,则新创建的选择器将覆盖原来的选择器。

selector必须以字母或数字开头,最多包含63个字符,可使用:字母、数字、连字符" - " 、点"."和下划线" _ "。如果指定了--resource-version,则更新将使用此资源版本,否则将使用现有的资源版本。注意:目前selector命令只能用于Service对象。

语法

$ selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]

示例

在创建deployment/service对之前设置labels和selector。

kubectl create service clusterip my-svc --clusterip="None" -o yaml --dry-run | kubectl set selector --local -f - 'environment=qa' -o yaml | kubectl create -f -
kubectl create deployment my-dep -o yaml --dry-run | kubectl label --local -f - environment=qa -o yaml | kubectl create -f -

Flags

Name Shorthand Default Usage
all false Select all resources in the namespace of the specified resource types
allow-missing-template-keys true If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.
dry-run false If true, only print the object that would be sent, without sending it.
filename f [] Filename, directory, or URL to files the resource to update the selectors
local false If true, set selector will NOT contact api-server but run locally.
no-headers false When using the default or custom-column output format, don't print headers (default print headers).
output o Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].
output-version DEPRECATED: To use a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').
record false Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.
recursive R false Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.
resource-version If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.
show-all a false When printing, show all resources (default hide terminated pods.)
show-labels false When printing, show all labels as the last column (default hide labels column)
sort-by If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
template Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
K8S中文社区微信公众号

Kubernetes kubectl set resources 命令详解

kubectl set resources

资源对象中的Pod可以指定计算资源需求(CPU-单位m、内存-单位Mi),即使用的最小资源请求(Requests),限制(Limits)的最大资源需求,Pod将保证使用在设置的资源数量范围。

  • Requests:计算资源最小数量。
  • Limits:资源最大允许数量。

对于每个Pod资源,如果指定了Limits(限制)值,并省略了Requests(请求),则Requests默认为Limits的值。

可用资源对象包括(支持大小写):replicationcontroller、deployment、daemonset、job、replicaset。

语法

$ resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=REQUESTS]

示例

将deployment的nginx容器cpu限制为“200m”,将内存设置为“512Mi”

kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi

为nginx中的所有容器设置 Requests和Limits

kubectl set resources deployment nginx --limits=cpu=200m,memory=512Mi --requests=cpu=100m,memory=256Mi

删除nginx中容器的计算资源值

kubectl set resources deployment nginx --limits=cpu=0,memory=0 --requests=cpu=0,memory=0

打印从本地更新nginx容器限制的结果(以yaml格式),而不会触发服务器

打印结果(以yaml格式),在不影响服务器的情况下,从本地更新nginx容器限制

kubectl set resources -f path/to/file.yaml --limits=cpu=200m,memory=512Mi --local -o yaml

Flags

Name Shorthand Default Usage
all false select all resources in the namespace of the specified resource types
allow-missing-template-keys true If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.
containers c * The names of containers in the selected pod templates to change, all containers are selected by default - may use wildcards
dry-run false If true, only print the object that would be sent, without sending it.
filename f [] Filename, directory, or URL to files identifying the resource to get from a server.
limits The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.
local false If true, set resources will NOT contact api-server but run locally.
no-headers false When using the default or custom-column output format, don't print headers (default print headers).
output o Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].
output-version DEPRECATED: To use a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').
record false Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.
recursive R false Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.
requests The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.
selector l Selector (label query) to filter on, supports '=', '==', and '!='.
show-all a false When printing, show all resources (default hide terminated pods.)
show-labels false When printing, show all labels as the last column (default hide labels column)
sort-by If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
template Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
K8S中文社区微信公众号

Kubernetes kubectl set image 命令详解

kubectl set image

更新现有的资源对象的容器镜像。

可使用资源对象包括(不区分大小写):

pod (po)、replicationcontroller (rc)、deployment (deploy)、daemonset (ds)、job、replicaset (rs)

语法

$ image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N

示例

将deployment中的nginx容器镜像设置为“nginx:1.9.1”。

kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1

所有deployment和rc的nginx容器镜像更新为“nginx:1.9.1”

kubectl set image deployments,rc nginx=nginx:1.9.1 --all

将daemonset abc的所有容器镜像更新为“nginx:1.9.1”

kubectl set image daemonset abc *=nginx:1.9.1

从本地文件中更新nginx容器镜像

kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 --local -o yaml

Flags

Name Shorthand Default Usage
all false select all resources in the namespace of the specified resource types
allow-missing-template-keys true If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.
dry-run false If true, only print the object that would be sent, without sending it.
filename f [] Filename, directory, or URL to files identifying the resource to get from a server.
local false If true, set image will NOT contact api-server but run locally.
no-headers false When using the default or custom-column output format, don't print headers (default print headers).
output o Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].
output-version DEPRECATED: To use a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').
record false Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.
recursive R false Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.
selector l Selector (label query) to filter on, supports '=', '==', and '!='.
show-all a false When printing, show all resources (default hide terminated pods.)
show-labels false When printing, show all labels as the last column (default hide labels column)
sort-by If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
template Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
K8S中文社区微信公众号