Deployment必须包含资源对象
作者:互联网
- Deployment 是一个控制器,能够用来控制 pod 数量跟期望数量一致,配置 pod 的发布方式 Deployment 会按照给定策略进行发布指定 pod,保证在更新过程中不可用数量在限定范围内.
-
Deployment 控制 ReplicatSet, ReplicateSet控制 pod 副本的数量,pod 所属于 Replicaset,同一个 Replicaset 下的 pod 都是一样的
-
ReplicaSet 管理多个 Pod 副本,当有一个副本出现故障时,会不断的重启,重启的时间间隔以指数级增长,直到 5 分钟,不会自动转移。你或许会很奇怪,为什么 Pod 不会自动移除或者重新调度,这是因为 ReplicaSet 并不关心 Pod 是否处于正常运行状态,它只关心期望的副本数量和当前的副本数量是否一致。
-
一个 Pod 中可以包含多个容器,如果想查看其中单个 Container 容器,可以使用
kubectl logs client-pod -c client-container
。 -
如果一个容器依赖与另外一个容器,使用 initContainer 来延迟 Pod 主容器的启动。同时 initContainer 是顺序启动容器。但更建议你添加 Readisness 就绪探针来探测服务是否正常启动,如果这个服务没有准备好,那么 Kubernetes 就会阻止这个服务成为服务端点。
-
volumeMount 数据卷挂载,通常我们会通过定义 pv pvc 把容器内部数据挂载持久性存储卷或者宿主机特定目录。不过我就曾经发现有人把配置和证书等信息放置持久存储卷到特定目录,然后 mount 到容器内部。从管理和使用的角度不建议使用这种方式,更推荐使用 ConfigMap 和Secret。
存活探针(livenessprobe)和就绪探针(readinessprobe),语法相似,但功能不同,存活探针主要是用于检测服务是否正常启动,如果不正常,则重建 pod,直到正常为止,使用过程中要注意初始化延迟时间,如果设置时间太短,可能会导致 Pod 创建进入死循环,影响服务正常启动。
就绪探针主要是用于服务是否能够正常对外提供服务,如果不正常则从端点服务列表中移除,直到正常为止。
探针这个功能是 Kubernetes 中很接地气的一个设计,分布式系统很棘手的一个问题就是服务数量众多,存在一定量的僵尸服务,常规的做法通过侵入式设计,在服务中添加接口,循环检测,发现问题消息通知,在这种机制下消息往往不能得到及时解决。探针属于监控领域的一部分,要想检测服务是否正常,编排文件必须包含探针。
preStop 和 postStart 是容器生命周期的钩子,它跟存活和就绪探针类似,是在容器内部执行一个命令或者请求,但是这个钩子是和容器主进程并行执行的,postStart 在容器创建成功后立即执行,主要用于资源的部署和环境的准备,比如把某个文件复制到特定目录。
preStop 容器终止前的任务,主要用于优雅的关闭应用程序或者通知第三方服务等操作, 停止前钩子非常重要,编排文件中应该包含。看完了两个生命周期钩子函数,我们也说了停止前钩子非常重要,为什么呢?下面先简单介绍下一个 pod 被删除后发生了什么?
1.apiServer 发出 http delete 请求后,apiserver 不会直接删除 Pod 而是给 Pod 设置一个删除时间,拥有删除时间的 Pod 就开始停止了。
2.kublet 检测到有需要停止的 Pod ,kublet 会给每个容器一定时间来优雅的停止 Pod,这个时间叫做终止宽限期,这个时间每个 Pod 可以单独配置。终止进程开始之后,计时器开始倒计时,然后执行以下操作:
- 执行停止前钩子(如果配置了的话),然后等待执行完毕
- 向容器主进程发送sigterm信号
- 等待容器优雅的关闭或者等待终止宽限期超时
- 如果容器主进程没有优雅地关闭,那么使用sigkill强制终止进程。即使此时停止前钩子没有执行完成。
如果仔细思考这个过程中,你会发现会有几个问题?
- 停止前钩子没有执行完成怎么办,比如现在运行的有状态服务是数据库,数据库所在 Pod 缩容之后,需要进行数据转移。现在使用了停止前钩子进行数据转移。这个时候更建议使用 DaemonSet 定时任务专门处理此类问题,不要过度依赖停止前钩子函数,因为它无法预料到 Pod 生命周期何时结束。
- Pod 关闭时客户端连接断开怎么办,因为移除 iptable 规则的时间很可能比删除 Pod 时间要慢,这就导致之后外部请求到内部 Pod 发生 Connection refused,这种场景很难被解决,但是可以从一定程度上去避免,比如在停止前钩子,延迟 5-10s 关闭时间,尽可能多处理一定量请求,具体时间根据场景进行控制。
Kubernetes 通过 cgroup 进行资源限制,主要是通过设置 CPU 和内存请求资源和限制物理资源使用,由高到底分为 Guranteed、Burstable、Besteffort 三种资源限制级别。在生产环境中必须设置服务所需资源,可以考虑结合 limitrange 对命名空间所需资源限制,内部分别设置各个 Pod 所需资源,防止出现服务被驱逐;具体根据服务所需资源进行设置,如果 req 设置太大会导致资源浪费,太小会导致 OOMkilld,requests 建议使用历史峰值 * 1.2(系数)。如果线上环境存在突发流量,可以考虑结合 Kubernetes HPA 根据服务资源占用情况进行动态扩缩容。
经常看到有开发人员为镜像设置 latest 标签,简单,不用推送过多镜像,但是这样存在一定的隐患, 常见的就是当你 ImagesPullPolicy 设置为 IfNotPreset,推送镜像到远端,执行 yaml 文件不生效,那是因为 Kubernetes 发现版本没有变化没有去远端拉取,你不得不把拉取策略修改为 Always,这样一样,每当多产生一个 Pod 都会去联系镜像中心,拖慢了服务运行速度,严重情况下,网络出现问题就会导致整个服务无法正常启动。
另一个严重问题是一直使用同一个镜像标签,当服务出现问题时,导致无法回退到之前的版本。所以每当镜像发生变化时,要使用和之前不一样的标签。
对于一些日志收集或者有状态服务中,可能存在需要获取 pod 名称或者其它信息的需求,可以通过使用 env 对象获取资源对象,不仅如此,当我们需要调试服务的时候通过动态环境注入的方式,很方便的帮助我们进行服务调试,而不用执行重新打镜像操作,比如 java 服务出现内存溢出,可以通过注入如下信息:
在本地、虚拟机或者物理机部署时服务正常运行,换做容器运行各种崩溃,其实出现崩溃并不可怕,关键是分析为什么崩溃。Pod 在运行过程中会经历如下几个状态 Pending、Running、Succeeded、Faild、UnKnown 等。
-
首先出现问题后注意使用 kubectl describe deployment 查看 deployment 状态, 如果 deployment 一切正常、开始查看 kubectl describe replicaset,如果这两个控制器不正常,查看原因,一般 events 中会有提示。
-
如果一切正常,kubectl describe pod 查看 pod 运行状况,如果看不出问题所在,那么执行 kubectl logs pod 当然你的日志可能没有输出到控制台,你可以到你挂载日志所在宿主机或者日志收集中心查看日志。(前提是你的所有日志文件都已经 mount 到宿主机)
-
如果通过日志仍然无法看出问题或者根据异常信息不能分析出问题所在,其实可以通过 kubectl cp values.yaml pod-9fbfdbf89-rcwhc:/home/(把本地文件拷贝到 pod)也可以通过 kubectl cp pod-deployment-9fbfdbf89-rcwhc:home/values.yaml values.yaml(把镜像内部复制到宿主机)把一些你认为能够排除问题的工具复制到 Pod 内部进行协助问题排除。
-
最后如果仍然无法找到问题,那么你可以考虑运行一个没有问题的进程,最简单的就是创建一个普通的 centos 容器进行实现,通过如下命令,保证容器启动时拥有一个前台进程 command: ["/bin/bash","-c","while true; do sleep 1000; done"] 然后把有问题的服务 mount 进去,手动执行。
标签:容器,服务,包含,对象,钩子,探针,Deployment,Pod,pod 来源: https://www.cnblogs.com/sanduzxcvbnm/p/16173164.html