Kubernetes 集群管理经(教)验(训)
2020-02-26 更新:本文再更新,请移步 Kubernetes集群管理经验
节点问题
删除节点的正确步骤
1
2
3
4
5
# SchedulingDisabled,确保新的容器不会调度到该节点
kubectl cordon $node
# 驱逐除了ds以外所有的pod
kubectl drain $node --ignore-daemonsets
kubectl delete $node
维护节点的正确步骤
1
2
3
4
5
6
# SchedulingDisabled,确保新的容器不会调度到该节点
kubectl cordon $node
# 驱逐除了ds以外所有的pod
kubectl drain $node --ignore-daemonsets --delete-local-data
# 维护完成,恢复其正常状态
kubectl uncordon $node
–delete-local-data 是忽略 emptyDir这类的临时存储的意思
ImageGCFailed
kubelet 可以清除未使用的容器和镜像。kubelet 在每分钟和每五分钟分别回收容器和镜像。
但是 kubelet 的垃圾回收有个问题,它只能回收那些未使用的镜像,有点像 docker system prune,然而观察发现,那些死掉的容器不是最大的问题,正在运行的容器才是更大的问题.如果ImageGCFailed一直发生,而容器使用的ephemeral-storage/hostpath(宿主目录)越发增多,最终将会导致更严重的DiskPressure问题,波及节点上所有容器.
建议:
- 高配机器(4核32G以上)的docker目录配置100G SSD以上空间
- 配置ResourceQuota限制整体资源限额
- 容器端禁用ephemeral-storage(本地文件写入),或者使用spec.containers[].resources.limits.ephemeral-storage限制,控制宿主目录写入
节点出现磁盘压力(DiskPressure)
1
--eviction-hard=imagefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<5%
kubelet在启动时指定了磁盘压力,以阿里云为例,imagefs.available<15%意思是说容器的读写层少于15%的时候,节点会被驱逐.节点被驱逐的后果就是产生DiskPressure这种状况,并且节点上再也不能运行任何镜像,直至磁盘问题得到解决.如果节点上容器使用了宿主目录,这个问题将会是致命的.因为你不能把目录删除掉,但是真是这些宿主机的目录堆积,导致了节点被驱逐.
所以,平时要养好良好习惯,容器里面别瞎写东西(容器里面写文件会占用ephemeral-storage,ephemeral-storage过多pod会被驱逐),多使用无状态型容器,谨慎选择存储方式,尽量别用hostpath这种存储
出现状况时,真的有种欲哭无泪的感觉.
1
2
3
4
5
6
7
8
9
10
11
12
13
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FreeDiskSpaceFailed 23m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 5182058496 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning ImageGCFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Warning ImageGCFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Normal NodeHasNoDiskPressure 10m (x5 over 47d) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasNoDiskPressure
Normal Starting 10m kube-proxy, node.xxxx1 Starting kube-proxy.
Normal NodeHasDiskPressure 10m (x4 over 42m) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasDiskPressure
Warning EvictionThresholdMet 8m29s (x19 over 42m) kubelet, node.xxxx1 Attempting to reclaim ephemeral-storage
Warning ImageGCFailed 3m4s kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4920913920 bytes, but freed 0 bytes
ImageGCFailed 是很坑爹的状态,出现这个状态时,表示 kubelet 尝试回收磁盘失败,这时得考虑是否要手动上机修复了.
建议:
- 镜像数量在200以上时,采购100G SSD存镜像
- 少用临时存储(empty-dir,hostpath之类的)
参考链接:
节点CPU彪高
有可能是节点在进行GC(container GC/image GC),用describe node查查.我有次遇到这种状况,最后节点上的容器少了很多,也是有点郁闷
1
2
3
4
Events:
Type Reason Age From Message
---- ------ ---- ----
Warning ImageGCFailed 45m kubelet, cn-shenzhen.xxxx failed to get image stats: rpc error: code = DeadlineExceeded desc = context deadline exceeded
参考:
节点失联(unknown)
1
2
3
4
5
6
Ready False Fri, 28 Jun 2019 10:19:21 +0800 Thu, 27 Jun 2019 07:07:38 +0800 KubeletNotReady PLEG is not healthy: pleg was last seen active 27h14m51.413818128s ago; threshold is 3m0s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ContainerGCFailed 5s (x543 over 27h) kubelet, cn-shenzhen.xxxx rpc error: code = DeadlineExceeded desc = context deadline exceeded
ssh登录主机后发现,docker服务虽然还在运行,但docker ps卡住了.于是我顺便升级了内核到5.1,然后重启.
后来发现是有个人上了一个问题镜像,无论在哪节点运行,都会把节点搞瘫,也是醉了。
unknown 是非常严重的问题,必须要予以重视.节点出现 unknown ,kubernetes master 自身不知道节点上面的容器是死是活,假如有一个非常重要的容器在 unknown 节点上面运行,而且他刚好又挂了,kubernetes是不会自动帮你另启一个容器的,这点要注意.
参考链接:
Node flapping between Ready/NotReady with PLEG issues 深度解析Kubernetes Pod Disruption Budgets(PDB)
SystemOOM
SystemOOM 并不一定是机器内存用完了.有一种情况是docker 在控制容器的内存导致的.
默认情况下Docker的存放位置为:/var/lib/docker/containers/$id
这个目录下面有个重要的文件: hostconfig.json,截取部分大概长这样:
1
2
3
4
5
6
7
8
9
"MemorySwappiness": -1,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0
}
"OomKillDisable": false, 禁止了 docker 服务通过杀进程/重启的方式去和谐使用资源超限的容器,而是以其他的方式去制裁(具体的可以看这里)
docker daemon 卡住
这种状况我出现过一次,原因是某个容器有毛病,坑了整个节点.
出现这个问题要尽快解决,因为节点上面所有的 pod 都会变成 unknown .
1
2
3
systemctl daemon-reexec
systemctl restart docker(可选视情况定)
systemctl restart kubelet
严重时只能重启节点,停止涉事容器.
建议: 对于容器的liveness/readiness 使用tcp/httpget的方式,避免 高频率使用exec
pod
pod频繁重启
原因有多种,不可一概而论
有一种情况是,deploy配置了健康检查,节点运行正常,但是因为节点负载过高导致了健康检查失败(load15长期大于2以上),频繁Backoff.我调高了不健康阈值之后,降低节点负载之后,问题解决
1
2
3
4
5
6
7
8
9
10
livenessProbe:
# 不健康阈值
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
资源达到limit设置值
调高limit或者检查应用
Readiness/Liveness connection refused
Readiness检查失败的也会重启,但是Readiness检查失败不一定是应用的问题,如果节点本身负载过重,也是会出现connection refused或者timeout
这个问题要上节点排查
pod被驱逐(Evicted)
- 节点加了污点导致pod被驱逐
- ephemeral-storage超过限制被驱逐
- EmptyDir 的使用量超过了他的 SizeLimit,那么这个 pod 将会被驱逐
- Container 的使用量(log,如果没有 overlay 分区,则包括 imagefs)超过了他的 limit,则这个 pod 会被驱逐
- Pod 对本地临时存储总的使用量(所有 emptydir 和 container)超过了 pod 中所有container 的 limit 之和,则 pod 被驱逐
ephemeral-storage是一个pod用的临时存储.
1
2
3
4
5
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "3Gi"
节点被驱逐后通过get po还是能看到,用describe命令,可以看到被驱逐的历史原因
Message: The node was low on resource: ephemeral-storage. Container codis-proxy was using 10619440Ki, which exceeds its request of 0.
参考:
kubectl exec 进入容器失败
这种问题我在搭建codis-server的时候遇到过,当时没有配置就绪以及健康检查.但获取pod描述的时候,显示running.其实这个时候容器以及不正常了.
1
2
3
~ kex codis-server-3 sh
rpc error: code = 2 desc = containerd: container not found
command terminated with exit code 126
解决办法:删了这个pod,配置livenessProbe
pod的virtual host name
Deployment衍生的pod,virtual host name就是pod name.
StatefulSet衍生的pod,virtual host name是<pod name>.<svc name>.<namespace>.svc.cluster.local.相比Deployment显得更有规律一些.而且支持其他pod访问
pod接连Crashbackoff
Crashbackoff有多种原因.
沙箱创建(FailedCreateSandBox)失败,多半是cni网络插件的问题
镜像拉取,有中国特色社会主义的问题,可能太大了,拉取较慢
也有一种可能是容器并发过高,流量雪崩导致.
比如,现在有3个容器abc,a突然遇到流量洪峰导致内部奔溃,继而Crashbackoff,那么a就会被service剔除出去,剩下的bc也承载不了那么多流量,接连崩溃,最终网站不可访问.这种情况,多见于高并发网站+低效率web容器.
在不改变代码的情况下,最优解是增加副本数,并且加上hpa,实现动态伸缩容.
DNS 效率低下
容器内打开nscd(域名缓存服务),可大幅提升解析性能
严禁生产环境使用alpine作为基础镜像(会导致dns解析请求异常)
deploy
MinimumReplicationUnavailable
如果deploy配置了SecurityContext,但是api-server拒绝了,就会出现这个情况,在api-server的容器里面,去掉SecurityContextDeny这个启动参数.
具体见Using Admission Controllers
service
建了一个服务,但是没有对应的po,会出现什么情况?
请求时一直不会有响应,直到request timeout
参考
service connection refuse
原因可能有
- pod没有设置readinessProbe,请求到未就绪的pod
- kube-proxy宕机了(kube-proxy负责转发请求)
- 网络过载
service没有负载均衡
检查一下是否用了headless service.headless service是不会自动负载均衡的…
1
2
3
4
5
kind: Service
spec:
# clusterIP: None的即为`headless service`
type: ClusterIP
clusterIP: None
具体表现service没有自己的虚拟IP,nslookup会出现所有pod的ip.但是ping的时候只会出现第一个pod的ip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.31.10.94 172-31-10-94.consul.default.svc.cluster.local
Address 2: 172.31.10.95 172-31-10-95.consul.default.svc.cluster.local
Address 3: 172.31.11.176 172-31-11-176.consul.default.svc.cluster.local
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.973 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.170 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.170/0.571/0.973 ms
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.206 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.178 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.178/0.192/0.206 ms
普通的type: ClusterIP service,nslookup会出现该服务自己的IP
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.30.15.52 consul.default.svc.cluster.local
ReplicationController不更新
ReplicationController不是用apply去更新的,而是kubectl rolling-update,但是这个指令也废除了,取而代之的是kubectl rollout.所以应该使用kubectl rollout作为更新手段,或者懒一点,apply file之后,delete po.
尽量使用deploy吧.
StatefulSet
pod 更新失败
StatefulSet是逐一更新的,观察一下是否有Crashbackoff的容器,有可能是这个容器导致更新卡住了,删掉即可.
unknown pod
如果 StatefulSet 绑定 pod 状态变成 unknown ,这个时候是非常坑爹的,StatefulSet不会帮你重建pod.
这时会导致外部请求一直失败.
综合建议,不用 StatefulSet ,改用 operator 模式替换它.
kube-apiserver
kube-apiserver 是一组运行在 master 上面的特殊容器。以 阿里云 kubernetes 为例 (kubeadm创建的 kubernetes 同理)
在 /etc/kubernetes/manifests/ 下面定义了三个文件
- kube-apiserver.yaml
- kube-controller-manager.yaml
- kube-scheduler.yaml
master 节点会自动监视这个目录里面文件的变化,视情况自动重启。
所以修改 api server 的设置只需要修改kube-apiserver.yaml,保存退出,相应的容器就会重启。同理,如果你改错了配置,api server 就会启动失败,修改之前务必仔细看清楚文档
阿里云Kubernetes问题
修改默认ingress
新建一个指向ingress的负载均衡型svc,然后修改一下kube-system下nginx-ingress-controller启动参数.
1
2
3
4
5
6
7
8
- args:
- /nginx-ingress-controller
- '--configmap=$(POD_NAMESPACE)/nginx-configuration'
- '--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services'
- '--udp-services-configmap=$(POD_NAMESPACE)/udp-services'
- '--annotations-prefix=nginx.ingress.kubernetes.io'
- '--publish-service=$(POD_NAMESPACE)/<自定义svc>'
- '--v=2'
LoadBalancer服务一直没有IP
具体表现是EXTERNAL-IP一直显示pending.
1
2
3
~ kg svc consul-web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
consul-web LoadBalancer 172.30.13.122 <pending> 443:32082/TCP 5m
这问题跟Alibaba Cloud Provider这个组件有关,cloud-controller-manager有3个组件,他们需要内部选主,可能哪里出错了,当时我把其中一个出问题的pod删了,就好了.
清理Statefulset动态PVC
目前阿里云Statefulset动态PVC用的是nas。
- 对于这种存储,需要先把容器副本将为0,或者整个
Statefulset删除。 - 删除PVC
- 把nas挂载到任意一台服务器上面,然后删除pvc对应nas的目录。
升级到v1.12.6-aliyun.1之后节点可分配内存变少
该版本每个节点保留了1Gi,相当于整个集群少了N GB(N为节点数)供Pod分配.
如果节点是4G的,Pod请求3G,极其容易被驱逐.
建议提高节点规格.
1
Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.6-aliyun.1", GitCommit:"8cb561c", GitTreeState:"", BuildDate:"2019-04-22T11:34:20Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"}
新加节点出现NetworkUnavailable
RouteController failed to create a route
看一下kubernetes events,是否出现了
1
timed out waiting for the condition -> WaitCreate: ceate route for table vtb-wz9cpnsbt11hlelpoq2zh error, Aliyun API Error: RequestId: 7006BF4E-000B-4E12-89F2-F0149D6688E4 Status Code: 400 Code: QuotaExceeded Message: Route entry quota exceeded in this route table
出现这个问题是因为达到了VPC的自定义路由条目限制,默认是48,需要提高vpc_quota_route_entrys_num的配额
访问LoadBalancer svc随机出现流量转发异常
见 [bug]阿里云kubernetes版不检查loadbalancer service port,导致流量被异常转发 简单的说,同SLB不能有相同的svc端口,不然会瞎转发。
官方说法:
复用同一个SLB的多个Service不能有相同的前端监听端口,否则会造成端口冲突。
控制台显示的节点内存使用率总是偏大
原因在于他们控制台用的是usage_in_bytes(cache+buffer),所以会比云监控看到的数字大
Ingress Controller 玄学优化
修改 kube-system 下面名为 nginx-configuration 的configmap
1
2
3
4
5
6
7
8
9
10
11
proxy-connect-timeout: "75"
proxy-read-timeout: "75"
proxy-send-timeout: "75"
upstream-keepalive-connections: "300"
upstream-keepalive-timeout: "300"
upstream-keepalive-requests: "1000"
keep-alive-requests: "1000"
keep-alive: "300"
disable-access-log: "true"
client-header-timeout: "75"
worker-processes: "16"
注意,是一个项对应一个配置,而不是一个文件. 格式大概这样
1
2
3
4
5
6
7
8
9
➜ ~ kg cm nginx-configuration -o yaml
apiVersion: v1
data:
disable-access-log: "true"
keep-alive: "300"
keep-alive-requests: "1000"
proxy-body-size: 20m
worker-processes: "16"
......
pid 问题
1
Message: **Liveness probe failed: rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:262: starting container process caused "process_linux.go:86: adding pid 30968 to cgroups caused \"failed to write 30968 to cgroup.procs: write /sys/fs/cgroup/cpu,cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podfe4cc065_cc58_11e9_bf64_00163e08cd06.slice/docker-0447a362d2cf4719ae2a4f5ad0f96f702aacf8ee38d1c73b445ce41bdaa8d24a.scope/cgroup.procs: invalid argument\""
阿里云初始化节点用的 centos 版本老旧,内核是3.1, Centos7.4的内核3.10还没有支持cgroup对于pid/fd限制,所以会出现这类问题.
建议:
OSS PVC FailedMount
可以通过PV制定access key,access secret +PVC的方式使用OSS.某天某个deploy遇到 FailedMount 的问题,联系到阿里云的开发工程师,说是 flexvolume 在初次运行的节点上面运行会有问题,要让他”重新注册”
影响到的版本: registry-vpc.cn-shenzhen.aliyuncs.com/acs/flexvolume:v1.12.6.16-1f4c6cb-aliyun
解决方案:
1
touch /usr/libexec/kubernetes/kubelet-plugins/volume/exec/alicloud~oss/debug
参考(应用调度相关):
Kubernetes Cluster Management Experience (Lessons)
2020-02-26 Update: This article has been updated again, please go to Kubernetes Cluster Management Experience
Node Issues
Correct Steps to Delete a Node
1
2
3
4
5
# SchedulingDisabled, ensure new containers won't be scheduled to this node
kubectl cordon $node
# Evict all pods except daemonsets
kubectl drain $node --ignore-daemonsets
kubectl delete $node
Correct Steps to Maintain a Node
1
2
3
4
5
6
# SchedulingDisabled, ensure new containers won't be scheduled to this node
kubectl cordon $node
# Evict all pods except daemonsets
kubectl drain $node --ignore-daemonsets --delete-local-data
# After maintenance is complete, restore its normal state
kubectl uncordon $node
–delete-local-data means ignoring temporary storage like emptyDir
ImageGCFailed
kubelet can clean up unused containers and images. kubelet recycles containers and images every minute and every five minutes respectively.
But kubelet’s garbage collection has a problem: it can only recycle unused images, somewhat like docker system prune. However, observation shows that dead containers are not the biggest problem; running containers are the bigger problem. If ImageGCFailed keeps occurring, and container usage of ephemeral-storage/hostpath (host directories) keeps increasing, it will eventually lead to more serious DiskPressure problems, affecting all containers on the node.
Recommendations:
- For high-spec machines (4 cores 32G and above), configure 100G+ SSD space for the docker directory
- Configure ResourceQuota to limit overall resource quotas
- Disable ephemeral-storage (local file writes) on the container side, or use spec.containers[].resources.limits.ephemeral-storage to limit and control host directory writes
Node Disk Pressure (DiskPressure)
1
--eviction-hard=imagefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<5%
kubelet specifies disk pressure at startup. Taking Alibaba Cloud as an example, imagefs.available<15% means when the container’s read-write layer is less than 15%, the node will be evicted. The consequence of node eviction is the occurrence of DiskPressure, and the node can no longer run any images until the disk problem is resolved. If containers on the node use host directories, this problem will be fatal. Because you can’t delete the directories, but it’s really the accumulation of these host directories that caused the node to be evicted.
So, develop good habits: don’t write things randomly in containers (writing files in containers will occupy ephemeral-storage, too much ephemeral-storage will cause pods to be evicted), use stateless containers more, choose storage methods carefully, try not to use hostpath storage.
When this happens, it really feels like wanting to cry but having no tears.
1
2
3
4
5
6
7
8
9
10
11
12
13
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FreeDiskSpaceFailed 23m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 5182058496 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning ImageGCFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Warning ImageGCFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Normal NodeHasNoDiskPressure 10m (x5 over 47d) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasNoDiskPressure
Normal Starting 10m kube-proxy, node.xxxx1 Starting kube-proxy.
Normal NodeHasDiskPressure 10m (x4 over 42m) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasDiskPressure
Warning EvictionThresholdMet 8m29s (x19 over 42m) kubelet, node.xxxx1 Attempting to reclaim ephemeral-storage
Warning ImageGCFailed 3m4s kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4920913920 bytes, but freed 0 bytes
ImageGCFailed is a very problematic state. When this state appears, it means kubelet tried to reclaim disk but failed. At this point, consider whether to manually go on the machine to fix it.
Recommendations:
- When the number of images is above 200, purchase 100G SSD to store images
- Use less temporary storage (empty-dir, hostpath, etc.)
Reference links:
Node CPU Spikes
It’s possible the node is performing GC (container GC/image GC). Check with describe node. I encountered this situation once, and in the end, there were many fewer containers on the node, which was a bit frustrating.
1
2
3
4
Events:
Type Reason Age From Message
---- ------ ---- ----
Warning ImageGCFailed 45m kubelet, cn-shenzhen.xxxx failed to get image stats: rpc error: code = DeadlineExceeded desc = context deadline exceeded
Reference:
kubelet Source Code Analysis: Garbage Collect
Node Disconnection (unknown)
1
2
3
4
5
6
Ready False Fri, 28 Jun 2019 10:19:21 +0800 Thu, 27 Jun 2019 07:07:38 +0800 KubeletNotReady PLEG is not healthy: pleg was last seen active 27h14m51.413818128s ago; threshold is 3m0s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ContainerGCFailed 5s (x543 over 27h) kubelet, cn-shenzhen.xxxx rpc error: code = DeadlineExceeded desc = context deadline exceeded
After SSHing into the host, I found that although the docker service was still running, docker ps was stuck. So I upgraded the kernel to 5.1 and restarted.
Later it was discovered that someone deployed a problematic image that would crash any node it ran on, no matter which node. That was frustrating.
unknown is a very serious problem and must be taken seriously. When a node becomes unknown, the kubernetes master itself doesn’t know whether containers on the node are alive or dead. If there’s a very important container running on an unknown node, and it happens to crash, kubernetes won’t automatically start another container for you. This is something to note.
Reference links:
Node flapping between Ready/NotReady with PLEG issues In-depth Analysis of Kubernetes Pod Disruption Budgets (PDB)
SystemOOM
SystemOOM doesn’t necessarily mean the machine’s memory is exhausted. One situation is docker controlling container memory.
By default, Docker’s storage location is: /var/lib/docker/containers/$id
There’s an important file in this directory: hostconfig.json, a partial excerpt looks like this:
1
2
3
4
5
6
7
8
9
"MemorySwappiness": -1,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0
}
"OomKillDisable": false, prevents the docker service from harmonizing containers that exceed resource limits by killing processes/restarting, but instead sanctions them in other ways (details can be seen here)
docker daemon stuck
I encountered this situation once. The reason was a problematic container that affected the entire node.
This problem needs to be resolved quickly, because all pods on the node will become unknown.
1
2
3
systemctl daemon-reexec
systemctl restart docker (optional, depending on situation)
systemctl restart kubelet
In severe cases, only restarting the node and stopping the involved container works.
Recommendation: For container liveness/readiness, use tcp/httpget methods, avoid high-frequency use of exec
pod
pod Frequent Restarts
There are many reasons, cannot generalize
One situation is: deploy configured health checks, node runs normally, but because node load is too high, health checks fail (load15 consistently above 2), frequent Backoff. After I raised the unhealthy threshold and reduced node load, the problem was resolved.
1
2
3
4
5
6
7
8
9
10
livenessProbe:
# Unhealthy threshold
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
Resources Reached Limit Setting
Raise limit or check application
Readiness/Liveness connection refused
Readiness check failures will also restart, but Readiness check failure isn’t necessarily an application problem. If the node itself is overloaded, connection refused or timeout can also occur.
This problem needs to be investigated on the node.
pod Evicted
- Node added taint causing pod to be evicted
- ephemeral-storage exceeded limit and was evicted
- If EmptyDir usage exceeds its SizeLimit, then this pod will be evicted
- If Container usage (log, and if there’s no overlay partition, includes imagefs) exceeds its limit, then this pod will be evicted
- If Pod’s total usage of local temporary storage (all emptydir and container) exceeds the sum of all container limits in the pod, then the pod is evicted
ephemeral-storage is temporary storage used by a pod.
1
2
3
4
5
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "3Gi"
After a node is evicted, you can still see it through get po. Use the describe command to see the historical reason for eviction.
Message: The node was low on resource: ephemeral-storage. Container codis-proxy was using 10619440Ki, which exceeds its request of 0.
References:
kubectl exec Entering Container Failed
I encountered this problem when setting up codis-server. At that time, readiness and health checks were not configured. But when getting pod description, it showed running. Actually, at this point, the container was already abnormal.
1
2
3
~ kex codis-server-3 sh
rpc error: code = 2 desc = containerd: container not found
command terminated with exit code 126
Solution: Delete this pod, configure livenessProbe
pod’s virtual host name
For pods derived from Deployment, virtual host name is pod name.
For pods derived from StatefulSet, virtual host name is <pod name>.<svc name>.<namespace>.svc.cluster.local. Compared to Deployment, it’s more regular. And it supports access from other pods.
pod Consecutive Crashbackoff
Crashbackoff has many causes.
Sandbox creation (FailedCreateSandBox) failure is mostly a CNI network plugin problem.
Image pulling has issues with Chinese characteristics, may be too large, pulling is slow.
There’s also a possibility that container concurrency is too high, causing traffic avalanche.
For example, there are now 3 containers abc. a suddenly encounters a traffic spike causing internal crash, then Crashbackoff, so a will be removed by service. The remaining bc can’t handle that much traffic, crash consecutively, and finally the website becomes inaccessible. This situation is common in high-concurrency websites + low-efficiency web containers.
Without changing code, the optimal solution is to increase replica count and add HPA to achieve dynamic scaling.
DNS Inefficiency
Enable nscd (domain name caching service) inside containers to significantly improve resolution performance.
Strictly prohibit using alpine as base image in production (will cause DNS resolution request abnormalities)
deploy
MinimumReplicationUnavailable
If deploy configured SecurityContext, but api-server rejected it, this situation will occur. In the api-server container, remove the SecurityContextDeny startup parameter.
See Using Admission Controllers
service
Created a Service, But No Corresponding po, What Happens?
Requests will have no response until request timeout
Reference
service connection refuse
Possible reasons:
- pod didn’t set readinessProbe, requests go to unready pods
- kube-proxy is down (kube-proxy is responsible for forwarding requests)
- Network overload
service No Load Balancing
Check if headless service is used. headless service does not automatically load balance…
1
2
3
4
5
kind: Service
spec:
# clusterIP: None is `headless service`
type: ClusterIP
clusterIP: None
Specific behavior: service has no virtual IP of its own, nslookup will show all pod IPs. But when pinging, only the first pod’s IP appears.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.31.10.94 172-31-10-94.consul.default.svc.cluster.local
Address 2: 172.31.10.95 172-31-10-95.consul.default.svc.cluster.local
Address 3: 172.31.11.176 172-31-11-176.consul.default.svc.cluster.local
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.973 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.170 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.170/0.571/0.973 ms
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.206 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.178 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.178/0.192/0.206 ms
For normal type: ClusterIP service, nslookup will show the service’s own IP
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.30.15.52 consul.default.svc.cluster.local
ReplicationController Not Updating
ReplicationController is not updated with apply, but with kubectl rolling-update. However, this command is also deprecated, replaced by kubectl rollout. So should use kubectl rollout as the update method, or be lazy, apply file then delete po.
Try to use deploy instead.
StatefulSet
pod Update Failed
StatefulSet updates one by one. Observe if there are containers in Crashbackoff. It’s possible this container caused the update to get stuck. Delete it.
unknown pod
If a StatefulSet bound pod’s status becomes unknown, this is very problematic. StatefulSet won’t help you recreate the pod.
This will cause external requests to keep failing.
Comprehensive recommendation: don’t use StatefulSet, replace it with operator pattern.
kube-apiserver
kube-apiserver is a set of special containers running on master. Taking Alibaba Cloud kubernetes as an example (same for kubernetes created with kubeadm)
Three files are defined under /etc/kubernetes/manifests/
- kube-apiserver.yaml
- kube-controller-manager.yaml
- kube-scheduler.yaml
The master node will automatically monitor changes to files in this directory and automatically restart as needed.
So to modify api server settings, just modify kube-apiserver.yaml, save and exit, and the corresponding container will restart. Similarly, if you modify the configuration incorrectly, api server will fail to start. Before modifying, be sure to carefully read the documentation
Alibaba Cloud Kubernetes Issues
Modify Default Ingress
Create a new load balancer type svc pointing to ingress, then modify the startup parameters of nginx-ingress-controller under kube-system.
1
2
3
4
5
6
7
8
- args:
- /nginx-ingress-controller
- '--configmap=$(POD_NAMESPACE)/nginx-configuration'
- '--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services'
- '--udp-services-configmap=$(POD_NAMESPACE)/udp-services'
- '--annotations-prefix=nginx.ingress.kubernetes.io'
- '--publish-service=$(POD_NAMESPACE)/<custom svc>'
- '--v=2'
LoadBalancer Service Has No IP
Specific behavior is EXTERNAL-IP always shows pending.
1
2
3
~ kg svc consul-web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
consul-web LoadBalancer 172.30.13.122 <pending> 443:32082/TCP 5m
This problem is related to the Alibaba Cloud Provider component. cloud-controller-manager has 3 components. They need internal leader election. Something may have gone wrong. At that time, I deleted one of the problematic pods, and it was fixed.
Clean Statefulset Dynamic PVC
Currently, Alibaba Cloud Statefulset dynamic PVC uses nas.
- For this type of storage, first scale container replicas to 0, or delete the entire
Statefulset. - Delete PVC
- Mount nas to any server, then delete the pvc corresponding nas directory.
After Upgrading to v1.12.6-aliyun.1, Node Allocatable Memory Decreased
This version reserves 1Gi per node, equivalent to the entire cluster having N GB less (N is the number of nodes) for Pod allocation.
If a node is 4G and a Pod requests 3G, it’s extremely easy to be evicted.
Recommendation: Increase node specifications.
1
Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.6-aliyun.1", GitCommit:"8cb561c", GitTreeState:"", BuildDate:"2019-04-22T11:34:20Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"}
New Node Shows NetworkUnavailable
RouteController failed to create a route
Check kubernetes events to see if this appears:
1
timed out waiting for the condition -> WaitCreate: ceate route for table vtb-wz9cpnsbt11hlelpoq2zh error, Aliyun API Error: RequestId: 7006BF4E-000B-4E12-89F2-F0149D6688E4 Status Code: 400 Code: QuotaExceeded Message: Route entry quota exceeded in this route table
This problem occurs because the VPC custom route entry limit was reached. Default is 48. Need to increase the quota for vpc_quota_route_entrys_num.
Accessing LoadBalancer svc Randomly Shows Traffic Forwarding Abnormalities
See [bug] Alibaba Cloud kubernetes version doesn’t check loadbalancer service port, causing traffic to be abnormally forwarded Simply put, the same SLB cannot have the same svc port, otherwise it will forward blindly.
Official statement:
Multiple Services reusing the same SLB cannot have the same frontend listening port, otherwise it will cause port conflicts.
Console Shows Node Memory Usage Always Too High
Docker Container Memory Monitoring
The reason is their console uses usage_in_bytes(cache+buffer), so it will be larger than the numbers seen in cloud monitoring.
Ingress Controller Mystical Optimization
Modify the configmap named nginx-configuration under kube-system
1
2
3
4
5
6
7
8
9
10
11
proxy-connect-timeout: "75"
proxy-read-timeout: "75"
proxy-send-timeout: "75"
upstream-keepalive-connections: "300"
upstream-keepalive-timeout: "300"
upstream-keepalive-requests: "1000"
keep-alive-requests: "1000"
keep-alive: "300"
disable-access-log: "true"
client-header-timeout: "75"
worker-processes: "16"
Note: one item corresponds to one configuration, not one file. Format is roughly like this:
1
2
3
4
5
6
7
8
9
➜ ~ kg cm nginx-configuration -o yaml
apiVersion: v1
data:
disable-access-log: "true"
keep-alive: "300"
keep-alive-requests: "1000"
proxy-body-size: 20m
worker-processes: "16"
......
pid Problem
1
Message: **Liveness probe failed: rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:262: starting container process caused "process_linux.go:86: adding pid 30968 to cgroups caused \"failed to write 30968 to cgroup.procs: write /sys/fs/cgroup/cpu,cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podfe4cc065_cc58_11e9_bf64_00163e08cd06.slice/docker-0447a362d2cf4719ae2a4f5ad0f96f702aacf8ee38d1c73b445ce41bdaa8d24a.scope/cgroup.procs: invalid argument\""
Alibaba Cloud initialization nodes use an old centos version, kernel is 3.1. Centos7.4’s kernel 3.10 doesn’t support cgroup limits for pid/fd yet, so this type of problem occurs.
Recommendations:
- Manually maintain nodes, upgrade to 5.x kernel (currently some nodes have been upgraded to 5.x, but docker version is still 17.6.2, continuing to observe~)
- Install NPD + eventer, use event mechanism to alert administrators for manual maintenance
OSS PVC FailedMount
OSS can be used through PV specifying access key, access secret + PVC. One day, a deploy encountered a FailedMount problem. Contacted Alibaba Cloud development engineers, who said flexvolume will have problems running on nodes running for the first time, need to let it “re-register”
Affected version: registry-vpc.cn-shenzhen.aliyuncs.com/acs/flexvolume:v1.12.6.16-1f4c6cb-aliyun
Solution:
1
touch /usr/libexec/kubernetes/kubelet-plugins/volume/exec/alicloud~oss/debug
References (application scheduling related):
Kubernetesクラスター管理の経験(教訓)
2020-02-26更新:この記事は再更新されました。 Kubernetesクラスター管理の経験に移動してください
ノードの問題
ノードを削除する正しい手順
1
2
3
4
5
# SchedulingDisabled、新しいコンテナがこのノードにスケジュールされないようにする
kubectl cordon $node
# daemonsets以外のすべてのpodを追い出す
kubectl drain $node --ignore-daemonsets
kubectl delete $node
ノードをメンテナンスする正しい手順
1
2
3
4
5
6
# SchedulingDisabled、新しいコンテナがこのノードにスケジュールされないようにする
kubectl cordon $node
# daemonsets以外のすべてのpodを追い出す
kubectl drain $node --ignore-daemonsets --delete-local-data
# メンテナンスが完了したら、正常な状態に復元する
kubectl uncordon $node
–delete-local-dataはemptyDirのような一時ストレージを無視することを意味します
ImageGCFailed
kubeletは未使用のコンテナとイメージをクリーンアップできます。kubeletは毎分と5分ごとにコンテナとイメージをそれぞれ回収します。
しかし、kubeletのガベージコレクションには問題があります。未使用のイメージのみを回収でき、docker system pruneに似ています。しかし、観察により、死んだコンテナが最大の問題ではなく、実行中のコンテナがより大きな問題であることがわかりました。ImageGCFailedが継続的に発生し、コンテナのephemeral-storage/hostpath(ホストディレクトリ)の使用量が増加し続けると、最終的により深刻なDiskPressure問題につながり、ノード上のすべてのコンテナに影響します。
推奨事項:
- 高スペックマシン(4コア32G以上)の場合、dockerディレクトリに100G以上のSSDスペースを設定する
- ResourceQuotaを設定して、全体的なリソースクォータを制限する
- コンテナ側でephemeral-storage(ローカルファイル書き込み)を無効にするか、spec.containers[].resources.limits.ephemeral-storageを使用してホストディレクトリへの書き込みを制限および制御する
ノードのディスク圧力(DiskPressure)
1
--eviction-hard=imagefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<5%
kubeletは起動時にディスク圧力を指定します。阿里云を例にとると、imagefs.available<15%は、コンテナの読み書き層が15%未満の場合、ノードが追い出されることを意味します。ノードの追い出しの結果は、DiskPressureの発生であり、ディスク問題が解決されるまで、ノードはもうイメージを実行できません。ノード上のコンテナがホストディレクトリを使用している場合、この問題は致命的になります。ディレクトリを削除することはできませんが、これらのホストディレクトリの蓄積がノードの追い出しを引き起こしました。
したがって、良い習慣を身につけてください。コンテナ内にランダムに書き込まない(コンテナ内にファイルを書き込むとephemeral-storageが占有され、ephemeral-storageが多すぎるとpodが追い出されます)、ステートレスコンテナをより多く使用し、ストレージ方法を慎重に選択し、hostpathストレージを使用しないようにしてください。
これが発生すると、本当に泣きたくても涙が出ない気持ちになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FreeDiskSpaceFailed 23m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 5182058496 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning ImageGCFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Warning ImageGCFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Normal NodeHasNoDiskPressure 10m (x5 over 47d) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasNoDiskPressure
Normal Starting 10m kube-proxy, node.xxxx1 Starting kube-proxy.
Normal NodeHasDiskPressure 10m (x4 over 42m) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasDiskPressure
Warning EvictionThresholdMet 8m29s (x19 over 42m) kubelet, node.xxxx1 Attempting to reclaim ephemeral-storage
Warning ImageGCFailed 3m4s kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4920913920 bytes, but freed 0 bytes
ImageGCFailedは非常に問題のある状態です。この状態が表示されると、kubeletがディスクを回収しようとしたが失敗したことを意味します。この時点で、マシンに手動で修正する必要があるかどうかを検討してください。
推奨事項:
- イメージ数が200を超える場合、100G SSDを購入してイメージを保存する
- 一時ストレージ(empty-dir、hostpathなど)を少なく使用する
参考リンク:
ノードCPUの急上昇
ノードがGC(コンテナGC/イメージGC)を実行している可能性があります。describe nodeで確認してください。この状況に一度遭遇し、最終的にノード上のコンテナが大幅に減少し、少しイライラしました。
1
2
3
4
Events:
Type Reason Age From Message
---- ------ ---- ----
Warning ImageGCFailed 45m kubelet, cn-shenzhen.xxxx failed to get image stats: rpc error: code = DeadlineExceeded desc = context deadline exceeded
参考:
ノードの切断(unknown)
1
2
3
4
5
6
Ready False Fri, 28 Jun 2019 10:19:21 +0800 Thu, 27 Jun 2019 07:07:38 +0800 KubeletNotReady PLEG is not healthy: pleg was last seen active 27h14m51.413818128s ago; threshold is 3m0s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ContainerGCFailed 5s (x543 over 27h) kubelet, cn-shenzhen.xxxx rpc error: code = DeadlineExceeded desc = context deadline exceeded
ホストにSSHでログインした後、dockerサービスはまだ実行されていましたが、docker psが固まっていました。そこで、カーネルを5.1にアップグレードして再起動しました。
後で、誰かが問題のあるイメージをデプロイし、どのノードで実行してもノードをクラッシュさせることがわかりました。それはイライラしました。
unknownは非常に深刻な問題であり、真剣に取り組む必要があります。ノードがunknownになると、kubernetes master自体はノード上のコンテナが生きているか死んでいるかを知りません。unknownノード上で非常に重要なコンテナが実行されており、たまたまクラッシュした場合、kubernetesは自動的に別のコンテナを起動しません。これは注意すべき点です。
参考リンク:
PLEGの問題でReady/NotReadyの間でフラッピングするノード Kubernetes Pod Disruption Budgets(PDB)の詳細分析
SystemOOM
SystemOOMは必ずしもマシンのメモリが使い果たされたことを意味するわけではありません。dockerがコンテナのメモリを制御している場合があります。
デフォルトでは、Dockerの保存場所は次のとおりです:/var/lib/docker/containers/$id
このディレクトリには重要なファイルがあります:hostconfig.json。部分的な抜粋は次のようになります:
1
2
3
4
5
6
7
8
9
"MemorySwappiness": -1,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0
}
"OomKillDisable": false,は、dockerサービスがリソース制限を超えるコンテナをプロセスを殺す/再起動することで調和することを防ぎ、代わりに他の方法で制裁します(詳細はここを参照)
docker daemonの固まり
この状況に一度遭遇しました。理由は、問題のあるコンテナがノード全体に影響を与えたことです。
この問題は迅速に解決する必要があります。ノード上のすべてのpodがunknownになるためです。
1
2
3
systemctl daemon-reexec
systemctl restart docker(状況に応じてオプション)
systemctl restart kubelet
深刻な場合は、ノードを再起動し、関連するコンテナを停止するしかありません。
推奨事項:コンテナのliveness/readinessにはtcp/httpget方式を使用し、execの高頻度使用を避ける
pod
podの頻繁な再起動
多くの理由があり、一概には言えません
1つの状況は、deployがヘルスチェックを設定し、ノードが正常に実行されているが、ノードの負荷が高すぎてヘルスチェックが失敗した(load15が2以上で長期間)、頻繁なBackoffです。不健全なしきい値を上げ、ノードの負荷を下げた後、問題が解決しました。
1
2
3
4
5
6
7
8
9
10
livenessProbe:
# 不健全なしきい値
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
リソースがlimit設定値に達した
limitを上げるか、アプリケーションを確認する
Readiness/Liveness connection refused
Readinessチェックの失敗も再起動しますが、Readinessチェックの失敗が必ずしもアプリケーションの問題であるとは限りません。ノード自体が過負荷の場合、connection refusedまたはtimeoutも発生する可能性があります。
この問題はノードで調査する必要があります。
podの追放(Evicted)
- ノードにtaintが追加され、podが追放された
- ephemeral-storageが制限を超えて追放された
- EmptyDirの使用量がSizeLimitを超える場合、このpodは追放されます
- Containerの使用量(ログ、overlayパーティションがない場合はimagefsを含む)がlimitを超える場合、このpodは追放されます
- Podのローカル一時ストレージの総使用量(すべてのemptydirとcontainer)がpod内のすべてのcontainerのlimitの合計を超える場合、podは追放されます
ephemeral-storageはpodが使用する一時ストレージです。
1
2
3
4
5
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "3Gi"
ノードが追放された後、get poでまだ見ることができます。describeコマンドを使用して、追放の履歴的な理由を確認できます。
Message: The node was low on resource: ephemeral-storage. Container codis-proxy was using 10619440Ki, which exceeds its request of 0.
参考:
kubectl execコンテナへの進入失敗
codis-serverをセットアップしているときにこの問題に遭遇しました。その時、readinessとヘルスチェックが設定されていませんでした。しかし、podの説明を取得すると、runningと表示されました。実際、この時点で、コンテナはすでに異常でした。
1
2
3
~ kex codis-server-3 sh
rpc error: code = 2 desc = containerd: container not found
command terminated with exit code 126
解決策:このpodを削除し、livenessProbeを設定する
podの仮想ホスト名
Deploymentから派生したpodの場合、virtual host nameはpod nameです。
StatefulSetから派生したpodの場合、virtual host nameは<pod name>.<svc name>.<namespace>.svc.cluster.localです。Deploymentと比較して、より規則的です。また、他のpodからのアクセスをサポートします。
podの連続Crashbackoff
Crashbackoffには多くの原因があります。
サンドボックスの作成(FailedCreateSandBox)の失敗は、主にcniネットワークプラグインの問題です。
イメージのプルには中国の特色のある問題があり、大きすぎる可能性があり、プルが遅いです。
コンテナの同時実行が高すぎて、トラフィックの雪崩を引き起こしている可能性もあります。
たとえば、現在3つのコンテナabcがあります。aが突然トラフィックの急増に遭遇し、内部クラッシュを引き起こし、その後Crashbackoffになり、aはserviceによって削除されます。残りのbcはそれほど多くのトラフィックを処理できず、連続してクラッシュし、最終的にウェブサイトがアクセス不能になります。この状況は、高同時実行ウェブサイト+低効率のWebコンテナでよく見られます。
コードを変更せずに、最適な解決策は、レプリカ数を増やし、HPAを追加して動的スケーリングを実現することです。
DNSの非効率性
コンテナ内でnscd(ドメイン名キャッシュサービス)を有効にすると、解決パフォーマンスが大幅に向上します。
本番環境でalpineをベースイメージとして使用することは厳禁です(DNS解決リクエストの異常を引き起こします)
deploy
MinimumReplicationUnavailable
deployがSecurityContextを設定したが、api-serverが拒否した場合、この状況が発生します。api-serverコンテナ内で、SecurityContextDeny起動パラメータを削除します。
Using Admission Controllersを参照
service
サービスを作成したが、対応するpoがない場合、何が起こるか?
リクエストはrequest timeoutまで応答がありません
参考
service connection refuse
考えられる理由:
- podがreadinessProbeを設定していない、リクエストが準備ができていないpodに送信される
- kube-proxyがダウンしている(kube-proxyはリクエストの転送を担当)
- ネットワークの過負荷
serviceに負荷分散がない
headless serviceが使用されているかどうかを確認してください。headless serviceは自動的に負荷分散しません…
1
2
3
4
5
kind: Service
spec:
# clusterIP: Noneが`headless service`です
type: ClusterIP
clusterIP: None
具体的な動作:serviceには独自の仮想IPがなく、nslookupはすべてのpodのIPを表示します。しかし、pingするときは、最初のpodのIPのみが表示されます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.31.10.94 172-31-10-94.consul.default.svc.cluster.local
Address 2: 172.31.10.95 172-31-10-95.consul.default.svc.cluster.local
Address 3: 172.31.11.176 172-31-11-176.consul.default.svc.cluster.local
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.973 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.170 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.170/0.571/0.973 ms
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.206 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.178 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.178/0.192/0.206 ms
通常のtype: ClusterIP serviceの場合、nslookupはサービス自身のIPを表示します
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.30.15.52 consul.default.svc.cluster.local
ReplicationControllerが更新されない
ReplicationControllerはapplyで更新されるのではなく、kubectl rolling-updateで更新されます。しかし、このコマンドも廃止され、kubectl rolloutに置き換えられました。したがって、kubectl rolloutを更新手段として使用するか、怠惰に、apply fileの後にdelete poを実行する必要があります。
できるだけdeployを使用してください。
StatefulSet
podの更新失敗
StatefulSetは1つずつ更新されます。Crashbackoffのコンテナがあるかどうかを観察してください。このコンテナが更新を停止させた可能性があります。削除してください。
unknown pod
StatefulSetがバインドするpodの状態がunknownになった場合、これは非常に問題があります。StatefulSetはpodを再作成しません。
これにより、外部リクエストが継続的に失敗します。
総合的な推奨事項:StatefulSetを使用せず、operatorパターンに置き換えてください。
kube-apiserver
kube-apiserverはmaster上で実行される特殊なコンテナのセットです。阿里云kubernetesを例にとると(kubeadmで作成されたkubernetesも同様)
/etc/kubernetes/manifests/の下に3つのファイルが定義されています
- kube-apiserver.yaml
- kube-controller-manager.yaml
- kube-scheduler.yaml
masterノードはこのディレクトリ内のファイルの変更を自動的に監視し、必要に応じて自動的に再起動します。
したがって、api serverの設定を変更するには、kube-apiserver.yamlを変更し、保存して終了するだけで、対応するコンテナが再起動します。同様に、設定を間違えて変更すると、api serverは起動に失敗します。変更する前に、必ずドキュメントを注意深く読んでください。
阿里云Kubernetesの問題
デフォルトingressの変更
ingressを指す新しいロードバランサー型svcを作成し、kube-systemの下のnginx-ingress-controllerの起動パラメータを変更します。
1
2
3
4
5
6
7
8
- args:
- /nginx-ingress-controller
- '--configmap=$(POD_NAMESPACE)/nginx-configuration'
- '--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services'
- '--udp-services-configmap=$(POD_NAMESPACE)/udp-services'
- '--annotations-prefix=nginx.ingress.kubernetes.io'
- '--publish-service=$(POD_NAMESPACE)/<カスタムsvc>'
- '--v=2'
LoadBalancerサービスにIPがない
具体的な動作は、EXTERNAL-IPが常にpendingと表示されることです。
1
2
3
~ kg svc consul-web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
consul-web LoadBalancer 172.30.13.122 <pending> 443:32082/TCP 5m
この問題はAlibaba Cloud Providerコンポーネントに関連しています。cloud-controller-managerには3つのコンポーネントがあり、内部でリーダー選出が必要です。どこかでエラーが発生した可能性があります。その時、問題のあるpodの1つを削除したところ、修正されました。
Statefulset動的PVCのクリーンアップ
現在、阿里云Statefulset動的PVCはnasを使用しています。
- このタイプのストレージの場合、まずコンテナのレプリカを0にするか、
Statefulset全体を削除する必要があります。 - PVCを削除する
- nasを任意のサーバーにマウントし、pvcに対応するnasディレクトリを削除する
v1.12.6-aliyun.1にアップグレード後、ノードの割り当て可能メモリが減少
このバージョンは各ノードに1Giを予約し、クラスター全体でN GB(Nはノード数)少なくなり、Podの割り当てに使用できます。
ノードが4Gで、Podが3Gをリクエストする場合、非常に追放されやすくなります。
推奨事項:ノードの仕様を向上させる。
1
Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.6-aliyun.1", GitCommit:"8cb561c", GitTreeState:"", BuildDate:"2019-04-22T11:34:20Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"}
新しいノードにNetworkUnavailableが表示される
RouteController failed to create a route
kubernetes eventsを確認し、以下が表示されているかどうかを確認してください:
1
timed out waiting for the condition -> WaitCreate: ceate route for table vtb-wz9cpnsbt11hlelpoq2zh error, Aliyun API Error: RequestId: 7006BF4E-000B-4E12-89F2-F0149D6688E4 Status Code: 400 Code: QuotaExceeded Message: Route entry quota exceeded in this route table
この問題はVPCのカスタムルートエントリ制限に達したために発生します。デフォルトは48です。vpc_quota_route_entrys_numのクォータを増やす必要があります。
LoadBalancer svcへのアクセスでランダムにトラフィック転送の異常が発生
参照 [bug]阿里云kubernetes版がloadbalancer service portをチェックせず、トラフィックが異常に転送される 簡単に言えば、同じSLBに同じsvcポートを持つことはできません。そうしないと、盲目に転送されます。
公式声明:
同じSLBを再利用する複数のServiceは、同じフロントエンドリスニングポートを持つことはできません。そうしないと、ポートの競合が発生します。
コンソールに表示されるノードのメモリ使用率が常に大きい
理由は、コンソールがusage_in_bytes(cache+buffer)を使用しているため、クラウド監視で見られる数値よりも大きくなることです。
Ingress Controllerの神秘的な最適化
kube-systemの下のnginx-configurationという名前のconfigmapを変更する
1
2
3
4
5
6
7
8
9
10
11
proxy-connect-timeout: "75"
proxy-read-timeout: "75"
proxy-send-timeout: "75"
upstream-keepalive-connections: "300"
upstream-keepalive-timeout: "300"
upstream-keepalive-requests: "1000"
keep-alive-requests: "1000"
keep-alive: "300"
disable-access-log: "true"
client-header-timeout: "75"
worker-processes: "16"
注意:1つの項目が1つの設定に対応し、1つのファイルではありません。フォーマットはおおよそ次のとおりです:
1
2
3
4
5
6
7
8
9
➜ ~ kg cm nginx-configuration -o yaml
apiVersion: v1
data:
disable-access-log: "true"
keep-alive: "300"
keep-alive-requests: "1000"
proxy-body-size: 20m
worker-processes: "16"
......
pidの問題
1
Message: **Liveness probe failed: rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:262: starting container process caused "process_linux.go:86: adding pid 30968 to cgroups caused \"failed to write 30968 to cgroup.procs: write /sys/fs/cgroup/cpu,cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podfe4cc065_cc58_11e9_bf64_00163e08cd06.slice/docker-0447a362d2cf4719ae2a4f5ad0f96f702aacf8ee38d1c73b445ce41bdaa8d24a.scope/cgroup.procs: invalid argument\""
阿里云の初期化ノードで使用されるcentosバージョンは古く、カーネルは3.1です。Centos7.4のカーネル3.10はまだpid/fdのcgroup制限をサポートしていないため、このタイプの問題が発生します。
推奨事項:
- ノードを手動でメンテナンスし、5.xカーネルにアップグレードする(現在、一部のノードが5.xにアップグレードされていますが、dockerバージョンはまだ17.6.2です。継続的に観察中〜)
- NPD + eventerをインストールし、イベントメカニズムを利用して管理者に手動メンテナンスを促す
OSS PVC FailedMount
PVでaccess key、access secret + PVCを指定することでOSSを使用できます。ある日、あるdeployがFailedMountの問題に遭遇し、阿里云の開発エンジニアに連絡したところ、flexvolumeが初回実行のノードで実行すると問題が発生し、「再登録」させる必要があるとのことでした。
影響を受けるバージョン:registry-vpc.cn-shenzhen.aliyuncs.com/acs/flexvolume:v1.12.6.16-1f4c6cb-aliyun
解決策:
1
touch /usr/libexec/kubernetes/kubelet-plugins/volume/exec/alicloud~oss/debug
参考(アプリケーションスケジューリング関連):
Опыт (уроки) управления кластером Kubernetes
2020-02-26 Обновление: Эта статья снова обновлена, пожалуйста, перейдите к Опыт управления кластером Kubernetes
Проблемы узлов
Правильные шаги для удаления узла
1
2
3
4
5
# SchedulingDisabled, убедитесь, что новые контейнеры не будут запланированы на этот узел
kubectl cordon $node
# Вытеснить все поды, кроме daemonsets
kubectl drain $node --ignore-daemonsets
kubectl delete $node
Правильные шаги для обслуживания узла
1
2
3
4
5
6
# SchedulingDisabled, убедитесь, что новые контейнеры не будут запланированы на этот узел
kubectl cordon $node
# Вытеснить все поды, кроме daemonsets
kubectl drain $node --ignore-daemonsets --delete-local-data
# После завершения обслуживания восстановите его нормальное состояние
kubectl uncordon $node
–delete-local-data означает игнорирование временного хранилища, такого как emptyDir
ImageGCFailed
kubelet может очистить неиспользуемые контейнеры и образы. kubelet перерабатывает контейнеры и образы каждую минуту и каждые пять минут соответственно.
Но у сборки мусора kubelet есть проблема: она может перерабатывать только неиспользуемые образы, что-то вроде docker system prune. Однако наблюдения показывают, что мертвые контейнеры — не самая большая проблема; запущенные контейнеры — большая проблема. Если ImageGCFailed продолжает происходить, а использование контейнерами ephemeral-storage/hostpath (хост-каталоги) продолжает увеличиваться, это в конечном итоге приведет к более серьезным проблемам DiskPressure, затрагивающим все контейнеры на узле.
Рекомендации:
- Для машин с высокими характеристиками (4 ядра 32G и выше) настройте 100G+ SSD пространства для каталога docker
- Настройте ResourceQuota для ограничения общих квот ресурсов
- Отключите ephemeral-storage (запись локальных файлов) на стороне контейнера или используйте spec.containers[].resources.limits.ephemeral-storage для ограничения и контроля записи в хост-каталоги
Давление диска узла (DiskPressure)
1
--eviction-hard=imagefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<5%
kubelet указывает давление диска при запуске. В качестве примера возьмем Alibaba Cloud: imagefs.available<15% означает, что когда слой чтения-записи контейнера меньше 15%, узел будет вытеснен. Последствием вытеснения узла является возникновение DiskPressure, и узел больше не может запускать какие-либо образы, пока проблема с диском не будет решена. Если контейнеры на узле используют хост-каталоги, эта проблема будет фатальной. Потому что вы не можете удалить каталоги, но именно накопление этих хост-каталогов привело к вытеснению узла.
Поэтому выработайте хорошие привычки: не пишите вещи случайно в контейнерах (запись файлов в контейнерах будет занимать ephemeral-storage, слишком много ephemeral-storage приведет к вытеснению подов), используйте больше stateless-контейнеров, тщательно выбирайте способы хранения, старайтесь не использовать хранилище hostpath.
Когда это происходит, действительно чувствуешь, что хочешь плакать, но нет слез.
1
2
3
4
5
6
7
8
9
10
11
12
13
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FreeDiskSpaceFailed 23m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 5182058496 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning ImageGCFailed 18m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 6089891840 bytes, but freed 0 bytes
Warning FreeDiskSpaceFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Warning ImageGCFailed 13m kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4953321472 bytes, but freed 0 bytes
Normal NodeHasNoDiskPressure 10m (x5 over 47d) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasNoDiskPressure
Normal Starting 10m kube-proxy, node.xxxx1 Starting kube-proxy.
Normal NodeHasDiskPressure 10m (x4 over 42m) kubelet, node.xxxx1 Node node.xxxx1 status is now: NodeHasDiskPressure
Warning EvictionThresholdMet 8m29s (x19 over 42m) kubelet, node.xxxx1 Attempting to reclaim ephemeral-storage
Warning ImageGCFailed 3m4s kubelet, node.xxxx1 failed to garbage collect required amount of images. Wanted to free 4920913920 bytes, but freed 0 bytes
ImageGCFailed — очень проблемное состояние. Когда появляется это состояние, это означает, что kubelet попытался освободить диск, но не смог. На этом этапе рассмотрите возможность ручного исправления на машине.
Рекомендации:
- Когда количество образов превышает 200, приобретите 100G SSD для хранения образов
- Используйте меньше временного хранилища (empty-dir, hostpath и т.д.)
Ссылки:
Высокое использование CPU узла
Возможно, узел выполняет GC (GC контейнера/GC образа). Проверьте с помощью describe node. Я столкнулся с этой ситуацией один раз, и в итоге контейнеров на узле стало намного меньше, что было немного расстраивающим.
1
2
3
4
Events:
Type Reason Age From Message
---- ------ ---- ----
Warning ImageGCFailed 45m kubelet, cn-shenzhen.xxxx failed to get image stats: rpc error: code = DeadlineExceeded desc = context deadline exceeded
Ссылка:
Анализ исходного кода kubelet: Сборка мусора
Отключение узла (unknown)
1
2
3
4
5
6
Ready False Fri, 28 Jun 2019 10:19:21 +0800 Thu, 27 Jun 2019 07:07:38 +0800 KubeletNotReady PLEG is not healthy: pleg was last seen active 27h14m51.413818128s ago; threshold is 3m0s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ContainerGCFailed 5s (x543 over 27h) kubelet, cn-shenzhen.xxxx rpc error: code = DeadlineExceeded desc = context deadline exceeded
После SSH-входа на хост я обнаружил, что хотя служба docker все еще работает, docker ps зависла. Поэтому я обновил ядро до 5.1 и перезапустил.
Позже выяснилось, что кто-то развернул проблемный образ, который крашил любой узел, на котором он запускался, независимо от узла. Это было расстраивающим.
unknown — очень серьезная проблема, и к ней нужно относиться серьезно. Когда узел становится unknown, сам kubernetes master не знает, живы ли контейнеры на узле или мертвы. Если на unknown-узле работает очень важный контейнер, и он случайно упал, kubernetes не запустит для вас другой контейнер автоматически. Это нужно отметить.
Ссылки:
Узел мечется между Ready/NotReady с проблемами PLEG Глубокий анализ Pod Disruption Budgets (PDB) Kubernetes
SystemOOM
SystemOOM не обязательно означает, что память машины исчерпана. Одна ситуация — это docker, контролирующий память контейнера.
По умолчанию место хранения Docker: /var/lib/docker/containers/$id
В этом каталоге есть важный файл: hostconfig.json, частичный отрывок выглядит так:
1
2
3
4
5
6
7
8
9
"MemorySwappiness": -1,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0
}
"OomKillDisable": false, предотвращает гармонизацию службой docker контейнеров, превышающих лимиты ресурсов, путем убийства процессов/перезапуска, а вместо этого санкционирует их другими способами (подробности можно увидеть здесь)
docker daemon зависла
Я столкнулся с этой ситуацией один раз. Причина была в проблемном контейнере, который повлиял на весь узел.
Эту проблему нужно решить быстро, потому что все поды на узле станут unknown.
1
2
3
systemctl daemon-reexec
systemctl restart docker (опционально, в зависимости от ситуации)
systemctl restart kubelet
В тяжелых случаях работает только перезапуск узла и остановка задействованного контейнера.
Рекомендация: Для liveness/readiness контейнера используйте методы tcp/httpget, избегайте частого использования exec
pod
Частые перезапуски pod
Есть много причин, нельзя обобщать
Одна ситуация: deploy настроил проверки работоспособности, узел работает нормально, но из-за слишком высокой нагрузки узла проверки работоспособности не проходят (load15 постоянно выше 2), частые Backoff. После того, как я повысил порог нездоровья и снизил нагрузку узла, проблема была решена.
1
2
3
4
5
6
7
8
9
10
livenessProbe:
# Порог нездоровья
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
Ресурсы достигли установленного лимита
Повысьте лимит или проверьте приложение
Readiness/Liveness connection refused
Неудачные проверки Readiness также перезапустят, но неудача проверки Readiness не обязательно является проблемой приложения. Если сам узел перегружен, также может возникнуть connection refused или timeout.
Эту проблему нужно исследовать на узле.
pod вытеснен (Evicted)
- Узел добавил taint, вызвав вытеснение pod
- ephemeral-storage превысил лимит и был вытеснен
- Если использование EmptyDir превышает его SizeLimit, то этот pod будет вытеснен
- Если использование Container (лог, и если нет раздела overlay, включает imagefs) превышает его лимит, то этот pod будет вытеснен
- Если общее использование локального временного хранилища Pod (все emptydir и container) превышает сумму всех лимитов контейнеров в pod, то pod вытесняется
ephemeral-storage — это временное хранилище, используемое pod.
1
2
3
4
5
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "3Gi"
После вытеснения узла вы все еще можете видеть его через get po. Используйте команду describe, чтобы увидеть историческую причину вытеснения.
Message: The node was low on resource: ephemeral-storage. Container codis-proxy was using 10619440Ki, which exceeds its request of 0.
Ссылки:
kubectl exec вход в контейнер не удался
Я столкнулся с этой проблемой при настройке codis-server. В то время готовность и проверки работоспособности не были настроены. Но при получении описания pod оно показывало running. На самом деле, в этот момент контейнер уже был ненормальным.
1
2
3
~ kex codis-server-3 sh
rpc error: code = 2 desc = containerd: container not found
command terminated with exit code 126
Решение: Удалите этот pod, настройте livenessProbe
виртуальное имя хоста pod
Для подов, производных от Deployment, virtual host name — это pod name.
Для подов, производных от StatefulSet, virtual host name — это <pod name>.<svc name>.<namespace>.svc.cluster.local. По сравнению с Deployment, это более регулярно. И поддерживает доступ от других подов.
последовательные Crashbackoff pod
Crashbackoff имеет много причин.
Неудача создания песочницы (FailedCreateSandBox) в основном является проблемой плагина сети CNI.
Вытягивание образа имеет проблемы с китайской спецификой, может быть слишком большим, вытягивание медленное.
Также есть возможность, что параллелизм контейнера слишком высок, вызывая лавину трафика.
Например, теперь есть 3 контейнера abc. a внезапно столкнулся со всплеском трафика, вызвав внутренний сбой, затем Crashbackoff, поэтому a будет удален service. Оставшиеся bc не могут обработать столько трафика, последовательно падают, и в конечном итоге веб-сайт становится недоступным. Эта ситуация часто встречается в высококонкурентных веб-сайтах + неэффективных веб-контейнерах.
Без изменения кода оптимальное решение — увеличить количество реплик и добавить HPA для достижения динамического масштабирования.
Неэффективность DNS
Включите nscd (службу кэширования доменных имен) внутри контейнеров, чтобы значительно повысить производительность разрешения.
Строго запрещено использовать alpine в качестве базового образа в production (вызовет аномалии запросов разрешения DNS)
deploy
MinimumReplicationUnavailable
Если deploy настроил SecurityContext, но api-server отклонил его, возникнет эта ситуация. В контейнере api-server удалите параметр запуска SecurityContextDeny.
См. Использование контроллеров допуска
service
Создана служба, но нет соответствующего po, что произойдет?
Запросы не будут иметь ответа до истечения времени ожидания запроса
Ссылка
service connection refuse
Возможные причины:
- pod не установил readinessProbe, запросы идут на неготовые поды
- kube-proxy не работает (kube-proxy отвечает за пересылку запросов)
- Перегрузка сети
service нет балансировки нагрузки
Проверьте, используется ли headless service. headless service не балансирует нагрузку автоматически…
1
2
3
4
5
kind: Service
spec:
# clusterIP: None — это `headless service`
type: ClusterIP
clusterIP: None
Конкретное поведение: у службы нет собственного виртуального IP, nslookup покажет все IP подов. Но при ping будет появляться только IP первого пода.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.31.10.94 172-31-10-94.consul.default.svc.cluster.local
Address 2: 172.31.10.95 172-31-10-95.consul.default.svc.cluster.local
Address 3: 172.31.11.176 172-31-11-176.consul.default.svc.cluster.local
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.973 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.170 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.170/0.571/0.973 ms
/ # ping consul
PING consul (172.31.10.94): 56 data bytes
64 bytes from 172.31.10.94: seq=0 ttl=62 time=0.206 ms
64 bytes from 172.31.10.94: seq=1 ttl=62 time=0.178 ms
^C
--- consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.178/0.192/0.206 ms
Для обычного типа: ClusterIP service, nslookup покажет собственный IP службы
/ # nslookup consul
nslookup: can't resolve '(null)': Name does not resolve
Name: consul
Address 1: 172.30.15.52 consul.default.svc.cluster.local
ReplicationController не обновляется
ReplicationController не обновляется с помощью apply, а с помощью kubectl rolling-update. Однако эта команда также устарела, заменена на kubectl rollout. Поэтому следует использовать kubectl rollout в качестве метода обновления, или быть ленивым, применить файл, затем удалить po.
Старайтесь использовать deploy вместо этого.
StatefulSet
обновление pod не удалось
StatefulSet обновляется по одному. Наблюдайте, есть ли контейнеры в Crashbackoff. Возможно, этот контейнер вызвал зависание обновления. Удалите его.
unknown pod
Если статус привязанного к StatefulSet pod становится unknown, это очень проблематично. StatefulSet не поможет вам пересоздать pod.
Это приведет к постоянным сбоям внешних запросов.
Комплексная рекомендация: не используйте StatefulSet, замените его паттерном operator.
kube-apiserver
kube-apiserver — это набор специальных контейнеров, работающих на master. В качестве примера возьмем kubernetes Alibaba Cloud (то же самое для kubernetes, созданного с помощью kubeadm)
Три файла определены под /etc/kubernetes/manifests/
- kube-apiserver.yaml
- kube-controller-manager.yaml
- kube-scheduler.yaml
Узел master будет автоматически отслеживать изменения файлов в этом каталоге и автоматически перезапускаться по мере необходимости.
Поэтому для изменения настроек api server просто измените kube-apiserver.yaml, сохраните и выйдите, и соответствующий контейнер перезапустится. Аналогично, если вы неправильно измените конфигурацию, api server не запустится. Перед изменением обязательно внимательно прочитайте документацию
Проблемы Kubernetes Alibaba Cloud
Изменить Ingress по умолчанию
Создайте новый svc типа балансировщика нагрузки, указывающий на ingress, затем измените параметры запуска nginx-ingress-controller под kube-system.
1
2
3
4
5
6
7
8
- args:
- /nginx-ingress-controller
- '--configmap=$(POD_NAMESPACE)/nginx-configuration'
- '--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services'
- '--udp-services-configmap=$(POD_NAMESPACE)/udp-services'
- '--annotations-prefix=nginx.ingress.kubernetes.io'
- '--publish-service=$(POD_NAMESPACE)/<пользовательский svc>'
- '--v=2'
У службы LoadBalancer нет IP
Конкретное поведение: EXTERNAL-IP всегда показывает pending.
1
2
3
~ kg svc consul-web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
consul-web LoadBalancer 172.30.13.122 <pending> 443:32082/TCP 5m
Эта проблема связана с компонентом Alibaba Cloud Provider. cloud-controller-manager имеет 3 компонента. Им нужно внутреннее избрание лидера. Возможно, что-то пошло не так. В то время я удалил один из проблемных pods, и это было исправлено.
Очистка динамического PVC Statefulset
В настоящее время динамический PVC Statefulset Alibaba Cloud использует nas.
- Для этого типа хранилища сначала масштабируйте реплики контейнера до 0 или удалите весь
Statefulset. - Удалите PVC
- Подключите nas к любому серверу, затем удалите соответствующий каталог nas pvc.
После обновления до v1.12.6-aliyun.1 выделяемая память узла уменьшилась
Эта версия резервирует 1Gi на узел, что эквивалентно тому, что весь кластер имеет на N GB меньше (N — количество узлов) для выделения Pod.
Если узел 4G, а Pod запрашивает 3G, его очень легко вытеснить.
Рекомендация: Увеличьте спецификации узла.
1
Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.6-aliyun.1", GitCommit:"8cb561c", GitTreeState:"", BuildDate:"2019-04-22T11:34:20Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"}
Новый узел показывает NetworkUnavailable
RouteController failed to create a route
Проверьте события kubernetes, чтобы увидеть, появляется ли это:
1
timed out waiting for the condition -> WaitCreate: ceate route for table vtb-wz9cpnsbt11hlelpoq2zh error, Aliyun API Error: RequestId: 7006BF4E-000B-4E12-89F2-F0149D6688E4 Status Code: 400 Code: QuotaExceeded Message: Route entry quota exceeded in this route table
Эта проблема возникает из-за достижения лимита пользовательских записей маршрута VPC. По умолчанию 48. Нужно увеличить квоту для vpc_quota_route_entrys_num.
Доступ к LoadBalancer svc случайно показывает аномалии пересылки трафика
См. [bug] Версия kubernetes Alibaba Cloud не проверяет порт службы loadbalancer, вызывая аномальную пересылку трафика Проще говоря, один и тот же SLB не может иметь тот же порт svc, иначе он будет пересылать вслепую.
Официальное заявление:
Несколько служб, повторно использующих один и тот же SLB, не могут иметь один и тот же порт прослушивания на передней панели, иначе это вызовет конфликт портов.
Консоль показывает использование памяти узла всегда слишком высоким
Мониторинг памяти контейнера Docker
Причина в том, что их консоль использует usage_in_bytes (cache+buffer), поэтому она будет больше, чем числа, видимые в облачном мониторинге.
Мистическая оптимизация Ingress Controller
Измените configmap с именем nginx-configuration под kube-system
1
2
3
4
5
6
7
8
9
10
11
proxy-connect-timeout: "75"
proxy-read-timeout: "75"
proxy-send-timeout: "75"
upstream-keepalive-connections: "300"
upstream-keepalive-timeout: "300"
upstream-keepalive-requests: "1000"
keep-alive-requests: "1000"
keep-alive: "300"
disable-access-log: "true"
client-header-timeout: "75"
worker-processes: "16"
Примечание: один элемент соответствует одной конфигурации, а не одному файлу. Формат примерно такой:
1
2
3
4
5
6
7
8
9
➜ ~ kg cm nginx-configuration -o yaml
apiVersion: v1
data:
disable-access-log: "true"
keep-alive: "300"
keep-alive-requests: "1000"
proxy-body-size: 20m
worker-processes: "16"
......
проблема pid
1
Message: **Liveness probe failed: rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:262: starting container process caused "process_linux.go:86: adding pid 30968 to cgroups caused \"failed to write 30968 to cgroup.procs: write /sys/fs/cgroup/cpu,cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podfe4cc065_cc58_11e9_bf64_00163e08cd06.slice/docker-0447a362d2cf4719ae2a4f5ad0f96f702aacf8ee38d1c73b445ce41bdaa8d24a.scope/cgroup.procs: invalid argument\""
Узлы инициализации Alibaba Cloud используют старую версию centos, ядро 3.1. Ядро 3.10 Centos7.4 еще не поддерживает ограничения cgroup для pid/fd, поэтому возникает этот тип проблемы.
Рекомендации:
- Вручную обслуживайте узлы, обновите до ядра 5.x (в настоящее время некоторые узлы были обновлены до 5.x, но версия docker все еще 17.6.2, продолжаю наблюдать~)
- Установите NPD + eventer, используйте механизм событий для предупреждения администраторов о ручном обслуживании
OSS PVC FailedMount
OSS можно использовать через PV, указывающий access key, access secret + PVC. Один день deploy столкнулся с проблемой FailedMount. Связался с инженерами разработки Alibaba Cloud, которые сказали, что flexvolume будет иметь проблемы при запуске на узлах, запускающихся впервые, нужно дать ему “перерегистрироваться”
Затронутая версия: registry-vpc.cn-shenzhen.aliyuncs.com/acs/flexvolume:v1.12.6.16-1f4c6cb-aliyun
Решение:
1
touch /usr/libexec/kubernetes/kubelet-plugins/volume/exec/alicloud~oss/debug
Ссылки (связанные с планированием приложений):
- Проверки работоспособности Kubernetes и обработка зависимостей служб
- Как kubernetes решает зависимости служб?
- Путь Kubernetes 1 - Заблуждения об ограничениях ресурсов приложения Java
- Управление политиками управления CPU на узле
- Резервирование вычислительных ресурсов для системных демонов
- Настройка обработки нехватки ресурсов