Node 重伤之后
很多人都知道 Kubernetes 能自动维护失效 Pod、防止服务中断、剔除故障节点 BLABLA 的一堆高大上功能。但节点故障之后,会对运行在故障节点上的容器、以及依赖容器的服务造成什么影响,是应该了解的,这样才能有针对性的进行监控设置、部署安排、故障处理等工作。
水平有限,这里不谈原理,只说说症状和一些相关的调整。
测试环境
- Kubernetes 1.7.10,三节点,其中 Master 节点被 Taint.
- 10.211.55.11(Master)
- 10.211.55.12
- 10.211.55.13
- CentOS 7
- Docker 1.12.3
实验设计
Docker、Kubelet 以及 Kube-Proxy 是 Node 的标准组件,我们准备一个 2 Replicas 的 Deployment 作为测试目标,使用 NodePort 方式暴露 HTTP 端口。具体代码见附录。
使用 systemctl
关停目标服务,使用 watch -n5 kubectl get pods,nodes,deploy
以及 watch -n5 kubectl "describe svc httpbin | grep -i endp"
命令持续检查相关工作负载的情况。同时可以使用 curl
命令检查服务是否存活。
Kube-Proxy
选择登录一个节点,例如 10.211.55.12
,使用 kubectl stop kube-proxy
关闭之后可以看到,各个 kubectl get
命令返回结果都正常,似乎未受影响;然而使用 curl
进行逐个节点的 NodePort 进行验证的时候,会发现停掉 Proxy 的地址是无法提供服务的。
监控
除了监控进程/服务之外,Kube-Proxy 还提供了几个可以用于监控的参数
--healthz-bind-address
:健康检测地址和端口,缺省为 0.0.0.0:10256--healthz-port
:健康检测端口,缺省 10256,设置为 0 则关闭。
curl http://127.0.0.1:10256/healthz | jq
会看到返回的健康数据:
{
"lastUpdated": "2017-12-19 16:05:27.333531431 +0800 CST",
"currentTime": "2017-12-19 16:05:33.73732624 +0800 CST"
}
— --metrics-bind-address
用于提供监控指标的地址和端口,缺省为 127.0.0.1:10249,返回内容可用于 Prometheus。例如:curl -s http://127.0.0.1:10249/metrics | more
会看到:
......
# HELP http_request_size_bytes The HTTP request sizes in bytes.
# TYPE http_request_size_bytes summary
http_request_size_bytes{handler="prometheus",quantile="0.5"} 64
http_request_size_bytes{handler="prometheus",quantile="0.9"} 64
http_request_size_bytes{handler="prometheus",quantile="0.99"} 64
http_request_size_bytes_sum{handler="prometheus"} 192
http_request_size_bytes_count{handler="prometheus"} 3
......
Kubelet
Kubelet 情况比 kube-proxy 复杂一些。
- 首先使用
kubectl get po -o wide
,确认 Pod 所在节点。 - 使用
systemctl stop kubelet
停止 kubelet 服务。 - 观察
首先我们会看到,经过约半分钟以后,该节点变为NotReady
状态。Deploy 对象的 Available 字段数字会减 1,服务的Endpoints
列表减少一个。;但是 Pod 状态保持在Running
,
五分钟左右,Pod 进入Unknown
状态,开始尝试启动新 Pod。
存活检测和就绪检测
测试中我们使用的 yaml 中并没有设置这两个内容,事实上,这两个检测是由 kubelet 执行的,对上述行为并无影响。
参数调整
真正影响上面的行为的是kube-controller-manager
的两个参数:
--pod-eviction-timeout
:缺省为 5m,五分钟,在 Pod 驱逐行为的超时时间。--node-monitor-grace-period
:缺省为 40s,也就是 40 秒,无响应 Node 在标记为 NotReady 之前的等候时间。
监控
--healthz-bind-address
:健康监测地址,缺省为127.0.0.1
。--healthz-port
:健康检测端口,缺省为 10248。
curl 访问该地址,会得到响应:ok
。
另外如果使用kube-metrics exporter
进行集群监控,可以关注 RC、Deploy 等对象的可用实例数量。
Docker
Docker 的情况其实跟 Kubelet 类似,但是结果会更严重:在 Endpoint 被排除之前,路由到故障节点的流量会发生故障。
测试之外
- 多 Pod 不仅对性能有好处,在极端情况下能降低故障节点对服务整体效果的影响。
- 建议采用节点互斥的方式进行部署。
- 对关键组件的监控,应该建立从进程到指标的多级监控,减小服务故障的时间窗口。
- Pod 的存活和健康监测,对于容器内的应用是有效的,应该推荐。
附录
workload.yaml
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: http
port: 80
nodePort: 30080
selector:
app: httpbin
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpbin-v1
spec:
replicas: 1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
containers:
- image: httpd
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80