1.如何设置升级部署过程中优雅的切换流量;
其实不管你是否采用deployment的滚动升级方式,如果在旧应用没有做相关的配置,在并发量大的情况下,流量切换过程中还是会可能出现502、504之类的错误:
- 502:应用程序在收到 SIGTERM 信号后直接终止了运行,导致部分还没有被处理完的请求直接中断,代理层返回 502 表示这种情况
- 504:Service Endpoints 移除不够及时,在 Pod 已经被终止后,仍然有个别请求被路由到了该 Pod,得不到响应导致 504
pod的Terminating过程:
1.1 pod被设置成terminating,几乎同时该 Pod 被从所有关联的 Service Endpoints 中移除;此时,Pod 停止获得新的流量,但在 Pod 中运行的容器不会受到影响;
1.2 执行preStop 钩子(如果设置有),发生在stop动作之前;preStop Hook 支持 bash 脚本、TCP 或 HTTP 请求
1.3 执行完preStop 钩子,SIGTERM 信号被发送给 Pod 中的所有容器
1.4 等待指定的时间:terminationGracePeriodSeconds(可配置) 字段用于控制等待时间,默认值为 30 秒。该步骤与 preStop Hook 同时执行,因此 terminationGracePeriodSeconds 需要大于 preStop 的时间,否则会出现 preStop 未执行完毕,pod 就被 kill 的情况;(需要注意的是,这个优雅退出的等待计时是与 preStop 同步开始的!而且它也不会等待 preStop 结束)
1.5 发送 SIGKILL 信号:等待指定时间后,向 pod 中的容器发送 SIGKILL 信号,删除 pod;
解决方案:
1.6 pod 配置就绪检测,等待业务代码初始化完毕后后再将 node 加入到 SLB 后端;
livenessProbe 为存活检测,如果失败次数到达阈值(failureThreshold)后,pod 会重启;
readinessProbe 为就绪检查,只有就绪检查通过后,pod 才会被加入到 Endpoint 中。容器服务 监控到 Endpoint 变化后才会将 node 挂载到 slb 后端;
preStop 时间建议设置为业务处理完所有剩余请求所需的时间;
terminationGracePeriodSeconds 时间建议设置为 preStop 的时间再加 30 秒以上;
1.7 为 pod 配置 preStop Hook,使 Pod 收到 SIGTERM 时 sleep 一段时间而不是立刻停止工作,从而确保从 SLB 转发的流量还可以继续被 Pod 处理
containers:
- name: my-app
# 添加下面这部分
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- "while [ $(netstat -plunt | grep tcp | wc -l | xargs) -ne 0 ]; do sleep 1; done"
2.磁盘爆满
2.1 影响表现
docker运行时出错, tainerCreating 或者terminating状态;pod无法重启;(很大可能由于kubelet的gc参数以及驱逐相关参数配置错误)
解决方案:
- 清理docker日志(使用 cat /dev/null >)
- 驱逐pod
- 重启docker
- 解除污点
3. pod退出状态码
pod正常退出状态码为0,非正常退出状态码为1-255,其中129-255属于外界原因导致pod的异常退出,1到128为程序自身原因导致pod退出,137为常见的非正常状态码,由于 Pod 中容器内存达到了其资源限制或者宿主机资源已经不够用;
4.Qos limit request的配置
默认情况下, Kubernetes 集群上的容器运行使用的计算资源没有限制!
如果pod没有配置limit或者request,默认值为命名空间下 LimitRange定义的资源大小,LimitRange 的验证仅在 Pod 准入阶段进行,不对正在运行的 Pod 进行验证;
在java项目中没有给jvm指定内存大小的情况下,机器物理内存很大时,jvm默认占用的内存Xms超出了k8s分配给pod的内存,导致pod内存溢出,从而k8s不断重启pod;也可能是运行过程中,jvm不断申请内存直到最大堆内存Xmx,Xmx超出了k8s分配给pod的内存,从而k8s自动重启pod。(jvm 是不知道自己在Docker容器中运行的,jvm识别的是物理主机的内存,而不是k8s给pod分配的内存或docker容器的内存)(如果设置了 limit 没有设置 request,那么k8s 默认会把 request 设置为与 limit 同等值)
QoS 等级分为:
Guaranteed: limits=requests (最高优先级)
当集群部署应用时,对应高要求的业务,应该把 pod 设置为 Guaranteed;
Burstable: limits!=requests (次高优先级)
一些非核心,并且资源不长期占用的应用;
BestEffort: 未配置limits、requests (最低优先级)
不建议 POD 为 BestEffort 类型,因为容易直接导致在节点资源紧张时候,仍有大量 pod 被调度运行
5.HPA与VPA
- VPA不能与HPA(Horizontal Pod Autoscaler )一起使用(有前提条件)
- VPA适用于Pod比如使用副本控制器,例如属于Deployment或者StatefulSet
- HPA非常适合扩展无状态应用程序,但也适合有状态应用
- Cluster Autoscaler是node节点集群级别的伸缩容
6.Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止;
pod启动的参数,如果在配置文件中设置了容器启动时要执行的命令及其参数,那么容器镜像中自带的命令与参数将会被覆盖而不再执行。如果配置文件中只是设置了参数,却没有设置其对应的命令,那么容器镜像中自带的命令会使用该新参数作为其执行时的参数;
# k8s常用技巧
pod重启的几大方法:
kubectl replace --force -f xxx.yaml
kubectl scale deployment {pod} --replicas=0 -n {namespace}
kubectl scale deployment {pod} --replicas=1 -n {namespace}
kubectl delete replicaset {rs_name} -n {namespace}
kubectl get pod {podname} -n {namespace} -o yaml | kubectl replace --force -f -
kubectl rollout restart deployment {pod} -n {namespace}
删除指定命名空间下的所有资源:
kubectl delete all --all -n {Namespace}
如果需要删除deployment下的pod,需要先删除deployment
kubectl delete deployment DEPLOYMENT_NAME -n NAMESPACE_NAME
kubectl delete pod --all
要允许从源 Pod 到目的 Pod 的连接,源 Pod 的出口策略和目的 Pod 的入口策略都需要允许连接。 如果任何一方不允许连接,建立连接将会失败;
针对容器化应用,最简单且最广泛采用的日志记录方式就是写入标准输出和标准错误流;
默认情况下,如果容器重启,kubelet 会保留被终止的容器日志。 如果 Pod 在工作节点被驱逐,该 Pod 中所有的容器也会被驱逐,包括容器日志;
7.应用configmap使用四种方式:
在容器命令和参数内
容器的环境变量
在只读卷里面添加一个文件,让应用来读取
编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
8.外网域名时而解析正常。时而解析出错;
coredns挂载了宿主机的/etc/resolv.conf;里面配置了内网使用的域名;
9.istio的sidecar无法从istiod获取配置信息;
envoy进程可以访问sevice ip,但是service无法连接通pod;proxy的转发规则出问题;由于采取ipvs模式
附加pod错误信息:
imagepullbackoff
imageinspecterror
errimagespull
errimagesneverpull
registryunavailable
invalidimagesname
浙公网安备 33010602011771号