截止目前k8s1.18,k8s已经支持标准容器,sidecar容器,init 容器,ephemeral 容器 4种类型的containers。本文咱们详细介绍一下这4种容器的特性已经使用场景。nginx
临时容器与其余容器的不一样之处在于,它们缺乏对资源或执行的保证,而且永远不会自动重启,所以不适用于构建应用程序。临时容器使用与常规容器相同的 ContainerSpec
段进行描述,但许多字段是不相容且不容许的。git
ports
,livenessProbe
,readinessProbe
这样的字段是不容许的。resources
配置是不容许的。临时容器是使用 API 中的一种特殊的 ephemeralcontainers
处理器进行建立的,而不是直接添加到 pod.spec
段,所以没法使用 kubectl edit
来添加一个临时容器。docker
与常规容器同样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。shell
为何咱们须要Ephemeral 容器?数据库
咱们知道容器的优势是它们经过使用不变方法提供全部必需的依赖项来运行隔离的进程。经过仅将所需的依赖项添加到镜像中,容器能够下降攻击面并提供更快的启动和部署。使用“distroless”方法构建容器镜像(基于scratch),经过仅包含已编译的应用程序二进制文件,将容器镜像提高到了一个新的水平。与普通的容器镜像不一样,它们不基于任何种类的Linux发行版,所以不包含任何其余可经过kubectl exec执行以进行故障排除的二进制文件和工具。这就决定了该容器有助于提供安全可靠的运行时环境,但也很难在问题发生时进行调试。json
在这种状况下,临时容器发挥做用。它们实现了调试容器附加到主进程的功能,而后你能够用于调试任何类型的问题。调试容器能够基于任何镜像,所以能够根据您的需求进行定制。您能够构建本身的调试镜像,其中包含特殊的调试二进制文件或仅包含curl,OpenSSL和MongoDB客户端之类的工具。可是,您也能够选择Linux发行版(如Ubuntu)或仅运行Busybox镜像,这两个镜像都已经包含了许多有用的工具。api
如何使用临时容器?安全
临时容器是alpha功能,所以默认状况下处于禁用状态。您将须要激活如下功能门才能使用它们:服务器
本节中的示例演示了临时容器如何出如今 API 中。 一般,您可使用 kubectl
插件进行故障排查,从而自动化执行这些步骤。网络
临时容器是使用 Pod 的 ephemeralcontainers
子资源建立的,可使用 kubectl --raw
命令进行显示。首先描述临时容器被添加为一个 EphemeralContainers
列表:
{ "apiVersion": "v1", "kind": "EphemeralContainers", "metadata": { "name": "example-pod" }, "ephemeralContainers": [{ "command": [ "sh" ], "image": "busybox", "imagePullPolicy": "IfNotPresent", "name": "debugger", "stdin": true, "tty": true, "terminationMessagePolicy": "File" }] }
使用以下命令更新已运行的临时容器 example-pod
:
kubectl replace --raw /api/v1/namespaces/default/pods/example-pod/ephemeralcontainers -f ec.json
这将返回临时容器的新列表:
{ "kind":"EphemeralContainers", "apiVersion":"v1", "metadata":{ "name":"example-pod", "namespace":"default", "selfLink":"/api/v1/namespaces/default/pods/example-pod/ephemeralcontainers", "uid":"a14a6d9b-62f2-4119-9d8e-e2ed6bc3a47c", "resourceVersion":"15886", "creationTimestamp":"2019-08-29T06:41:42Z" }, "ephemeralContainers":[ { "name":"debugger", "image":"busybox", "command":[ "sh" ], "resources":{ }, "terminationMessagePolicy":"File", "imagePullPolicy":"IfNotPresent", "stdin":true, "tty":true } ] }
可使用如下命令查看新建立的临时容器的状态:
kubectl describe pod example-pod ... Ephemeral Containers: debugger: Container ID: docker://cf81908f149e7e9213d3c3644eda55c72efaff67652a2685c1146f0ce151e80f Image: busybox Image ID: docker-pullable://busybox@sha256:9f1003c480699be56815db0f8146ad2e22efea85129b5b5983d0e0fb52d9ab70 Port: <none> Host Port: <none> Command: sh State: Running Started: Thu, 29 Aug 2019 06:42:21 +0000 Ready: False Restart Count: 0 Environment: <none> Mounts: <none> ...
可使用如下命令链接到新的临时容器:
kubectl attach -it example-pod -c debugger
若是启用了进程命名空间共享,则能够查看该 Pod 全部容器中的进程。 例如,运行上述 attach
操做后,在调试器容器中运行 ps
操做:
# 在 "debugger" 临时容器内中运行此 shell 命令 ps auxww
运行命令后,输出相似于:
PID USER TIME COMMAND 1 root 0:00 /pause 6 root 0:00 nginx: master process nginx -g daemon off; 11 101 0:00 nginx: worker process 12 101 0:00 nginx: worker process 13 101 0:00 nginx: worker process 14 101 0:00 nginx: worker process 15 101 0:00 nginx: worker process 16 101 0:00 nginx: worker process 17 101 0:00 nginx: worker process 18 101 0:00 nginx: worker process 19 root 0:00 /pause 24 root 0:00 sh 29 root 0:00 ps auxww
在Kubernetes中,init容器是在同一Pod中的其余容器以前开始并执行的容器。它旨在为Pod上托管的主应用程序执行初始化逻辑。例如,建立必要的用户账户,执行数据库迁移,建立数据库结构等。
建立initcontainer时应考虑一些注意事项:
正如咱们刚刚讨论的那样,init容器老是比同一个Pod上的其余应用程序容器先启动。结果,调度程序对init容器的资源和限制赋予了更高的优先级。必须仔细考虑这种行为,由于这可能会致使不良后果。例如,若是您有一个初始化容器和一个应用程序容器,而且将初始化容器的资源和限制设置为高于应用程序容器的资源和限制,那么只有在有一个可用节点知足初始化的状况下,才调度整个Pod容器要求。换句话说,即便有一个未使用的节点能够在其中运行应用程序容器,但若是初始化容器具备该节点能够处理的更高资源先决条件,则Pod也不会部署到该节点。所以,在定义初始化容器的请求和限制时,您应尽量严格。最佳作法是,除非绝对必要,不然请勿将这些参数设置为高于应用程序容器的值。
在k8s1.18 以前,这两种容器从k8s管理的角度来看,并无什么区别。只不过人为从功能上作了区分。
使用sidecar容器(模块化)具备的优势
对于Sidecar容器通常来讲主要体如今如下4种角色:
代理
。例如如今Istio中的Envoy。经过这种Sidercar 模式,代理能够拦截进出主容器的流量从而Istio能够提取有关流量行为的大量信号做为属性。 Istio可使用这些属性来执行策略决策,并将其发送到监视系统以提供有关整个网格行为的信息。
Sidecar代理模型还容许您将Istio功能添加到现有部署中,而无需从新构造或重写代码。
适配器
。适配器容器对输出进行标准化。考虑监视N个不一样应用程序的任务。可使用不一样的导出监视数据的方式来构建每一个应用程序。 (例如JMX,StatsD,特定于应用程序的统计信息),但每一个监控系统都但愿其收集的监控数据具备一致且统一的数据模型。经过使用复合容器的适配器模式,您能够经过建立Pod来未来自不一样系统的异构监视数据转换为一个统一的表示形式,该Pod将应用程序容器与知道如何进行转换的适配器分组在一块儿。一样,因为这些Pod共享名称空间和文件系统,所以这两个容器的协调很是简单明了。加强主容器功能
。Sidecar容器扩展并加强了“主”容器,它们可使用现有的容器并使它们变得更好。例如,考虑一个运行Nginx Web服务器的容器。添加另外一个将文件系统与git存储库同步的容器,在这些容器之间共享文件系统,而且您已经构建了Git Push-to-deploy。可是您已经以模块化的方式完成了此工做,其中git同步器能够由不一样的团队构建,而且能够在许多不一样的Web服务器(Apache,Python,Tomcat等)上重复使用。因为这种模块化,您只需编写和测试git同步器一次,便可在众多应用程序中重复使用它。并且,若是有人编写它,您甚至不须要这样作。实现辅助功能
。这种场景通常出如今DevOps中。好比将收集日志的组件以Sidecar的方式部署,实现收集日志的用途,或是部署一个Sidecar组件从配置中心监听配置变化,实时更新本地配置。生命周期
Sidecar容器的全部问题都与容器生命周期相关性有关。因为Pod中的常规容器之间没有区别,所以没法控制哪一个容器首先启动或最后终止,可是先正确运行Sidecar容器一般是应用程序容器正确运行的要求。
从1.18版本开始,K8S内置的Sidecar功能将确保Sidecar容器在正常业务流程开始以前就启动并运行,即经过更改pod的启动生命周期,在init容器完成后启动sidecar容器,在sidecar容器就绪后启动业务容器,从启动流程上保证顺序性。
经过更改Pod规范中的container.lifecycle.type
将容器标记为Sidecar类型:Sidecar
,默认为Standard
,以下:
apiVersion: v1 kind: Pod metadata: name: bookings-v1-b54bc7c9c-v42f6 labels: app: demoapp spec: containers: - name: bookings image: banzaicloud/allspark:0.1.1 ... - name: istio-proxy image: docker.io/istio/proxyv2:1.4.3 lifecycle: type: Sidecar ...
本文简单介绍了标准容器,sidecar容器,init 容器,ephemeral 容器 4种类型的containers。随着kubernetes日益普及,咱们须要充分掌握着几种类型容器原理和使用方法,才能更好地服务业务。
此外Sidecar容器将会成为将来软件交付的一种新的方式,参照Dapr等,不一样的团队提供本身的功能容器,而后选择性注入Sidecar到主业务容器,实现解耦。