k8s学习-容器基础

网友投稿 260 2022-09-10

k8s学习-容器基础

容器镜像

在 Kubernetes 的 Pod 中使用容器镜像之前,必须将其推送到一个镜像仓库(或者使用仓库中已经有的容器镜像)。在 Kubernetes 的 Pod 定义中定义容器时,必须指定容器所使用的镜像,容器中的 image​ 字段支持与 docker 命令一样的语法,包括私有镜像仓库和标签。

例如:my-registry.example.com:5000/example/web-example:v1.0.1 由如下几个部分组成:

my-registry.example.com: registry地址:5000 端口​/example/ repository 名字​web-example image名字​v1.0.1 image标签

使用 hub.dokcer.com​ Registry 中的镜像,可以省略 registry 地址和 registry 端口。例如:nginx:latest,eipwork/kuboard

更新镜像

Kubernetes中,默认的镜像抓取策略是 IfNotPresent,使用此策略,kubelet在发现本机有镜像的情况下,不会向镜像仓库抓取镜像。如果您期望每次启动 Pod 时,都强制从镜像仓库抓取镜像,可以尝试如下方式:

设置 container 中的imagePullPolicy 为Always省略imagePullPolicy 字段,并使用:latest tag 的镜像省略imagePullPolicy 字段和镜像的 tag激活AlwaysPullImages (opens new window)管理控制器

容器的环境变量

Kubernetes为容器提供了一系列重要的资源:

由镜像、一个或多个数据卷合并组成的文件系统容器自身的信息集群中其他重要对象的信息

​​容器的信息

在容器中执行 hostname​ 命令或者在libc 中执行 gethostname (opens new window)函调用,获得的是容器所在 Pod 的名字。

Pod 的名字,以及 Pod 所在名称空间可以通过 downward API (opens new window)注入到容器的环境变量里。

用户也可以为容器自定义环境变量。

集群的信息

在容器创建时,集群中所有的 Service 的连接信息将以环境变量的形式注入到容器中。例如,已创建了一个名为 Foo 的 Service,此时再创建任何容器时,该容器将包含如下环境变量:

FOO_SERVICE_HOST=FOO_SERVICE_PORT=

Runtime Class

使用 RuntimeClass 这一特性可以为容器选择运行时的容器引擎。

可以通过 RuntimeClass,使不同的 Pod 使用不同的容器引擎,以在性能和安全之间取得平衡。例如,如果某些工作负载需要非常高的信息安全保证,您可能想要将其 Pod 运行在那种使用硬件虚拟化的容器引擎上;同时,将其他的 Pod 运行在另外一种容器引擎上,以获得更高的性能。

也可以通过 RuntimeClass 配置,使不同的 Pod 使用相同的容器引擎和不同的容器引擎配置参数

节点上配置cri

需通过RuntimeClass进行配置,是依赖于 Container Runtime Interface(CRI)的具体实现的。

配置 CRI 时,请留意其 handler 名称(该名称是有 字符/数字 和 - 组成的字符串),RuntimeClass中将引用该名称。

dockershimKubernetes 内建的 dockershim CRI 不支持 RuntimeClasscontainerd

通过 containerd 的配置文件 /etc/containerd/config.toml 配置其 Runtime handler

cri-o

通过 cri-o 的配置文件 /etc/crio/crio.conf 配置 Runtime handler。

RuntimeClass 目前只有两个主要的字段:

RuntimeClass name(metadata.name)handler (handler)

apiVersion: node.k8s.io/v1beta1kind: RuntimeClassmetadata: name: myclass # RuntimeClass 没有名称空间handler: myconfiguration # 对应 CRI 配置的 handler 名称

使用

为集群完成 RuntimeClass 的配置后,使用的时候会非常简单。在 Pod 的定义中指定 runtimeClassName 即可

apiVersion: v1kind: Podmetadata: name: mypodspec: runtimeClassName: myclass # ...

kubelet 将依据这个字段使用指定的 RuntimeClass 来运行该 Pod。如果指定的 RuntimeClass 不存在,或者 CRI 不能运行对应的 handler 配置,则 Pod 将进入 Failed​ 这个终止 阶段。此时可通过 Pod 中的 Event(事件)来查看具体的出错信息。

如果 Pod 中未指定 runtimeClassName,kubelet 将使用默认的 RuntimeHandler 运行 Pod,其效果等价于 RuntimeClass 这个特性被禁用的情况。

容器的生命周期

Kubernetes 中,也为容器提供了对应的生命周期钩子函数,使得容器可以获知其所在运行环境对其进行管理的生命周期事件,以便容器可以响应该事件,并执行对应的代码

容器钩子

Kubernetes中为容器提供了两个 hook(钩子函数):

PostStart此钩子函数在容器创建后将立刻执行。但是,并不能保证该钩子函数在容器的ENTRYPOINT 之前执行。该钩子函数没有输入参数。PreStop此钩子函数在容器被 terminate(终止)之前执行,例如:

通过接口调用删除容器所在 Pod某些管理事件的发生:健康检查失败、资源紧缺等

如果容器已经被关闭或者进入了 completed 状态,preStop 钩子函数的调用将失败。该函数的执行是同步的,即,kubernetes 将在该函数完成执行之后才删除容器。该钩子函数没有输入参数。

Hook handler的实现

容器只要实现并注册 hook handler 便可以使用钩子函数。Kubernetes 中,容器可以实现两种类型的 hook handler:

Exec - 在容器的名称空进和 cgroups 中执行一个指定的命令,例如 pre-stop.sh。该命令所消耗的 CPU、内存等资源,将计入容器可以使用的资源限制。HTTP - 向容器的指定端口发送一个 HTTP 请求

Hook handler的执行

当容器的生命周期事件发生时,Kubernetes 在容器中执行该钩子函数注册的 handler。

对于 Pod 而言,hook handler 的调用是同步的。即,如果是 PostStart hook,容器的 ENTRYPOINT 和 hook 是同时出发的,然而如果 hook 执行的时间过长或者挂起了,容器将不能进入到 Running 状态。

PreStop hook 的行为与此相似。如果 hook 在执行过程中挂起了,Pod phase 将停留在 Terminating 的状态,并且在 terminationGracePeriodSeconds 超时之后,Pod被删除。如果 PostStart 或者 PreStop hook 执行失败,则 Kubernetes 将 kill(杀掉)该容器。

Hook触发的保证

Hook 将至少被触发一次,即,当指定事件 PostStart 或 PreStop 发生时,hook 有可能被多次触发。hook handler 的实现需要保证即使多次触发,执行也不会出错。

通常来说,hook 实际值被触发一次。例如:如果 HTTP hook 的服务端已经停机,或者因为网络的问题不能接收到请求,请求将不会被再次发送。在极少数的情况下, 触发两次 hook 的事情会发生。例如,如果 kueblet 在触发 hook 的过程中重启了,该 hook 将在 Kubelet 重启后被再次触发。

调试 hook handler

Hook handler 的日志并没有在 Pod 的 events 中发布。如果 handler 因为某些原因失败了,kubernetes 将广播一个事件 PostStart hook 发送 FailedPreStopHook 事件。 可以执行命令 kubectl describe pod $(pod_name) 以查看这些事件

容器的生命周期事件处理

Kubernetes 中支持容器的 postStart 和 preStop 事件,本文阐述了如何向容器添加生命周期事件处理程序(handler)。

postStart 容器启动时,Kubernetes 立刻发送 postStart 事件,但不确保对应的 handler 是否能在容器的EntryPoint 之前执行preStop 容器停止前,Kubernetes 发送 preStop 事件

定义postStart和preStop处理程序

创建一个包含单一容器的 Pod,并为该容器关联 postStart 和 preStop 处理程序(handler)。Pod 的yaml文件定义如下:

apiVersion: v1kind: Podmetadata: name: lifecycle-demospec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] preStop: exec: command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]

postStart 命令向usr/share/message 文件写入了一行文字preStop 命令优雅地关闭了 nginx

#创建podkubectl apply -f get pod lifecycle-demo#进入荣光一的命令行终端kubectl exec -it lifecycle-demo -- /bin/bash

Kubernetes 在容器启动后立刻发送 postStart 事件,但是并不能确保 postStart 事件处理程序在容器的 EntryPoint 之前执行。postStart 事件处理程序相对于容器中的进程来说是异步的(同时执行),然而,Kubernetes 在管理容器时,将一直等到 postStart 事件处理程序结束之后,才会将容器的状态标记为 Running。

Kubernetes 在决定关闭容器时,立刻发送 preStop 事件,并且,将一直等到 preStop 事件处理程序结束或者 Pod 的 --grace-period 超时,才删除容器

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:聚焦行业,赋能客户 | 博云容器云产品族五大行业解决方案发布
下一篇:SocialBeta:SK-II 进军动画,有《爱,死亡和机器人》那味了!
相关文章

 发表评论

暂时没有评论,来抢沙发吧~