【云原生】k8s之pod基础(下)
pod的知识点下要了解重启策略
一、pod的镜像拉取策略
1. 镜像拉取说明
当你在创建容器时会针对指定的镜像来进行容器的创建,所以pod的创建是以镜像为基础。当你在拉取镜向不指定仓库的主机名,Kubernetes 认为你在使用 Docker 公共仓库。
在镜像名称之后,你可以添加一个标签(Tag)(与使用 docker 或 podman 等命令时的方式相同)。 使用标签能让你辨识同一镜像序列中的不同版本。
镜像标签可以包含小写字母、大写字母、数字、下划线()、句点(.)和连字符(-)。 关于在镜像标签中何处可以使用分隔字符(、- 和 .)还有一些额外的规则。 如果你不指定标签,Kubernetes 认为你想使用标签latest
镜像拉取的策略
首先在资源式声明中存在着imagePullPolicy的字段,它的value决定着k8s创建容器时拉取镜像的方式策略。【此字段所在位置也说明了在声明式yaml中,imagePullPolicy是包含containers中】
kubectl explain pod.spec.containers.imagePullPolicy
如图所示,这三种便是k8s拉取镜像的三种策略:
IfNotPresent
只有当镜像在本地不存在时才会拉取。(先对本地进行排查,本地有该镜像直接使用,本地没有该镜像则选择在仓库中拉取)
Always
总是从仓库拉取镜像,无论本地是否存在镜像(即使本地中存在我们所指定的相关镜像,该策略也会先从仓库中拉取进行应用)
Never
Kubelet 不会尝试获取镜像。如果镜像已经以某种方式存在本地, kubelet 会尝试启动容器;否则,会启动失败。(如果本地不存在,并不会在仓库中拉取,直接报错)
注意:如果没有显式设定的话, Pod 中所有容器的默认镜像拉取策略是IfNotPresent。但是也存在着默认策略选择Always的情况。
此:
在生产环境中部署容器时,你应该避免使用 :latest 标签,因为这使得正在运行的镜像的版本难以追踪,并且难以正确地回滚。(难以追溯版本,且latest一直会不断迭代更新,给版本维护照成困扰)
镜像拉取策略的设置操作
(1)Never策略的使用
kubectl run app-test --image=httpd --dry-run=client -o yaml > demo1.yaml
vim demo1.yaml
(2)IfNotPresent策略在本地无镜像的情况下使用
vim demo1.yaml
#查看详细的pod信息,其中也有日志的作用
kubectl describe pod app-test
(3)Always策略
2.pod的启动命令说明
在k8s的容器中也存在着和docker-compose类似的shell启动命令字段,用于pod容器启动后执行命令的操作。
该字段存在containers中:
kubectl explain pod.spec.containers
command,用于在 pod 中的容器初始化完毕之后运行一个命令
command: ["/bin/sh","-c","touch /tmp/hello.txt"]
"/bin/sh","-c", 使用sh执行命令
touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件
该字段还可以运用args进行编写(起到同样的效果):
args:
- /bin/bash
- touch /tmp/hello.txt
除了 command 参数外,还有一个 args 参数
command 已经可以完成启动命令和传递参数的功能,为什么这里还要提供一个 args 选项,用于传递参数呢?这其实跟 docker 有点关系,kubernetes 中的 command、args 两项其实是实现覆盖 Dockerfile 中 ENTRYPOINT 的功能。
1)如果 command 和 args 均没有写,那么用 Dockerfile 的配置。
2)如果 command 写了,但 args 没有写,那么 Dockerfile 默认的配置会被忽略,执行输入的 command
3)如果 command 没写,但 args 写了,那么 Dockerfile 中配置的 ENTRYPOINT 的命令会被执行,使用当前 args 的参数
4)如果 command 和 args 都写了,那么 Dockerfile 的配置被忽略,执行 command 并追加上 args 参数
二、Pod 容器的重启策略
k8s中重启策略适用于pod对象中的所有容器,首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长为10s,20s,40s,80s,160s,300s, 300s是最大延迟时长
kubectl explain pod.spec.restartPolicy
1.pod的状态说明
(1)Pod 一直处于Pending状态
Pending状态意味着Pod的YAML文件已经提交给Kubernetes,API对象已经被创建并保存在Etcd当中。但是,这个Pod里有些容器因为某种原因而不能被顺利创建。比如,调度不成功(可以通过kubectl describe pod命令查看到当前Pod的事件,进而判断为什么没有调度)。
可能原因:资源不足(集群内所有的Node都不满足该Pod请求的CPU、内存、GPU等资源); HostPort 已被占用(通常推荐使用Service对外开放服务端口)。
(2)Pod一直处于Waiting 或 ContainerCreating状态
首先还是通过 kubectl describe pod命令查看当前Pod的事件。可能的原因有:
1)镜像拉取失败,比如镜像地址配置错误、拉取不了国外镜像源(gcr.io)、私有镜像密钥配置错误、镜像太大导致拉取超时 (可以适当调整kubelet的-image-pull-progress-deadline和-runtime-request-timeout选项)等。
2)CNI网络错误,一般需要检查CNI网络插件的配置,比如:无法配置Pod 网络、无法分配IP地址。
3)容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数
4)Failed create pod sandbox,查看kubelet日志,原因可能是磁盘坏道(input/output error)。
(3)Pod 一直处于ImagePullBackOff状态
通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。
(4)Pod 一直处于CrashLoopBackOff状态
此状态说明容器曾经启动了,但又异常退出。这时可以先查看一下容器的日志。
通过命令kubectl logs 和kubectl logs --previous 可以发下一些容器退出的原因,比如:容器进程退出、健康检查失败退出;此时如果还未发现线索,还而已到容器内执行命令(kubectl exec cassandra - cat /var.log/cassandra/system.loq)来进一步查看退出原因;如果还是没有线索,那就需要SSH登录该Pod所在的Node上,查看Kubelet或者Docker的日志进一步排查。
(5) Pod处于Error状态
通常处于Error状态说明Pod启动过程中发生了错误。
常见的原因:依赖的ConfigMap、Secret或PV等不存在;请求的资源超过了管理员设置的限制,比如超过了LimitRange等;违反集群的安全策略,比如违反了PodSecurityPolicy.等;容器无法操作集群内的资源,比如开启RDAC后,需要为ServiceAccount配置角色绑定。
(6) Pod 处于Terminating或 Unknown状态
从v1.5开始,Kubernetes不会因为Node失联而删除其上正在运行的Pod,而是将其标记为Terminating 或 Unknown 状态。想要删除这些状态的Pod有三种方法:
1)从集群中删除Node。使用公有云时,kube-controller-manager会在VM删除后自动删除对应的Node。而在物理机部署的集群中,需要管理员手动删除Node(kubectl delete node)。
2)Node恢复正常。kubelet会重新跟kube-apiserver通信确认这些Pod的期待状态,进而再决定删除或者继续运行这些Pod。用户强制删除,用户可以执行(kubectl delete pods pod-name --grace-period=0 --force)强制删除Pod。除非明确知道Pod的确处于停止状态(比如Node所在VM或物理机已经关机),否则不建议使用该方法。特别是StatefulSet 管理的Pod,强制删除容易导致脑裂或数据丢失等问题。
3)Pod行为异常,这里所说的行为异常是指Pod没有按预期的行为执行,比如没有运行podSpec 里面设置的命令行参数。这一般是podSpec yaml文件内容有误,可以尝试使用 --validate 参数重建容器,比如(kubectl delete pod mypod 和 kubectl create --validate -f mypod.yaml);也可以查看创建后的podSpec是否是对的,比如(kubectl get pod mypod -o yaml);修改静态Pod的Manifest后未自动重建,kubelet 使用inotify 机制检测 /etc/kubernetes/manifests 目录(可通过 kubelet 的 -pod-manifest-path 选项指定)中静态Pod的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发现修改静态Pod的 Manifest后未自动创建新 Pod的情景,此时已过简单的修复方法是重启 Kubelet。
Unknown 这个异常状态意味着Pod的状态不能持续地被 kubelet汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。
(7)pod从创建到成功或失败的事件
PodScheduled
pod正处于调度中,刚开始调度的时候,hostip还没绑定上,持续调度之后,有合适的节点就会绑定hostip,然后更新etcd数据
Initialized
pod中的所有初始化容器已经初启动完毕
Ready
pod中的容器可以提供服务了
Unschedulable
不能调度,没有合适的节点
2.
总结
更多推荐
所有评论(0)