<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>fault | 伪架构师</title>
    <link>/tags/fault/</link>
      <atom:link href="/tags/fault/index.xml" rel="self" type="application/rss+xml" />
    <description>fault</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Wed, 20 Dec 2017 01:58:49 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>fault</title>
      <link>/tags/fault/</link>
    </image>
    
    <item>
      <title>Node 重伤之后</title>
      <link>/post/node-downtime/</link>
      <pubDate>Wed, 20 Dec 2017 01:58:49 +0800</pubDate>
      <guid>/post/node-downtime/</guid>
      <description>

&lt;p&gt;很多人都知道 Kubernetes 能自动维护失效 Pod、防止服务中断、剔除故障节点 BLABLA 的一堆高大上功能。但节点故障之后，会对运行在故障节点上的容器、以及依赖容器的服务造成什么影响，是应该了解的，这样才能有针对性的进行监控设置、部署安排、故障处理等工作。&lt;/p&gt;

&lt;p&gt;水平有限，这里不谈原理，只说说症状和一些相关的调整。&lt;/p&gt;

&lt;h2 id=&#34;测试环境&#34;&gt;测试环境&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes 1.7.10，三节点，其中 Master 节点被 Taint.

&lt;ul&gt;
&lt;li&gt;10.211.55.11(Master)&lt;/li&gt;
&lt;li&gt;10.211.55.12&lt;/li&gt;
&lt;li&gt;10.211.55.13&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;CentOS 7&lt;/li&gt;
&lt;li&gt;Docker 1.12.3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;实验设计&#34;&gt;实验设计&lt;/h2&gt;

&lt;p&gt;Docker、Kubelet 以及 Kube-Proxy 是 Node 的标准组件，我们准备一个 2 Replicas 的 Deployment 作为测试目标，使用 NodePort 方式暴露 HTTP 端口。具体代码见附录。&lt;/p&gt;

&lt;p&gt;使用 &lt;code&gt;systemctl&lt;/code&gt; 关停目标服务，使用 &lt;code&gt;watch -n5 kubectl get pods,nodes,deploy&lt;/code&gt; 以及 &lt;code&gt;watch -n5 kubectl &amp;quot;describe svc httpbin | grep -i endp&amp;quot;&lt;/code&gt; 命令持续检查相关工作负载的情况。同时可以使用 &lt;code&gt;curl&lt;/code&gt; 命令检查服务是否存活。&lt;/p&gt;

&lt;h2 id=&#34;kube-proxy&#34;&gt;Kube-Proxy&lt;/h2&gt;

&lt;p&gt;选择登录一个节点，例如 &lt;code&gt;10.211.55.12&lt;/code&gt;，使用 &lt;code&gt;kubectl stop kube-proxy&lt;/code&gt; 关闭之后可以看到，各个 &lt;code&gt;kubectl get&lt;/code&gt; 命令返回结果都正常，似乎未受影响；然而使用 &lt;code&gt;curl&lt;/code&gt; 进行逐个节点的 NodePort 进行验证的时候，会发现停掉 Proxy 的地址是无法提供服务的。&lt;/p&gt;

&lt;h3 id=&#34;监控&#34;&gt;监控&lt;/h3&gt;

&lt;p&gt;除了监控进程/服务之外，Kube-Proxy 还提供了几个可以用于监控的参数&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--healthz-bind-address&lt;/code&gt;：健康检测地址和端口，缺省为 0.0.0.0:10256&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--healthz-port&lt;/code&gt;：健康检测端口，缺省 10256，设置为 0 则关闭。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl http://127.0.0.1:10256/healthz | jq&lt;/code&gt; 会看到返回的健康数据：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;lastUpdated&amp;quot;: &amp;quot;2017-12-19 16:05:27.333531431 +0800 CST&amp;quot;,
  &amp;quot;currentTime&amp;quot;: &amp;quot;2017-12-19 16:05:33.73732624 +0800 CST&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;mdash; &lt;code&gt;--metrics-bind-address&lt;/code&gt; 用于提供监控指标的地址和端口，缺省为 127.0.0.1:10249，返回内容可用于 Prometheus。例如：&lt;code&gt;curl -s  http://127.0.0.1:10249/metrics  | more&lt;/code&gt;会看到：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;......
# HELP http_request_size_bytes The HTTP request sizes in bytes.
# TYPE http_request_size_bytes summary
http_request_size_bytes{handler=&amp;quot;prometheus&amp;quot;,quantile=&amp;quot;0.5&amp;quot;} 64
http_request_size_bytes{handler=&amp;quot;prometheus&amp;quot;,quantile=&amp;quot;0.9&amp;quot;} 64
http_request_size_bytes{handler=&amp;quot;prometheus&amp;quot;,quantile=&amp;quot;0.99&amp;quot;} 64
http_request_size_bytes_sum{handler=&amp;quot;prometheus&amp;quot;} 192
http_request_size_bytes_count{handler=&amp;quot;prometheus&amp;quot;} 3
......
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;kubelet&#34;&gt;Kubelet&lt;/h2&gt;

&lt;p&gt;Kubelet 情况比 kube-proxy 复杂一些。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;首先使用&lt;code&gt;kubectl get po -o wide&lt;/code&gt;，确认 Pod 所在节点。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;systemctl stop kubelet&lt;/code&gt;停止 kubelet 服务。&lt;/li&gt;
&lt;li&gt;观察&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;首先我们会看到，经过约半分钟以后，该节点变为&lt;code&gt;NotReady&lt;/code&gt;状态。Deploy 对象的 Available 字段数字会减 1，服务的&lt;code&gt;Endpoints&lt;/code&gt;列表减少一个。；但是 Pod 状态保持在&lt;code&gt;Running&lt;/code&gt;，&lt;/p&gt;

&lt;p&gt;五分钟左右，Pod 进入&lt;code&gt;Unknown&lt;/code&gt;状态，开始尝试启动新 Pod。&lt;/p&gt;

&lt;h3 id=&#34;存活检测和就绪检测&#34;&gt;存活检测和就绪检测&lt;/h3&gt;

&lt;p&gt;测试中我们使用的 yaml 中并没有设置这两个内容，事实上，这两个检测是由 kubelet 执行的，对上述行为并无影响。&lt;/p&gt;

&lt;h3 id=&#34;参数调整&#34;&gt;参数调整&lt;/h3&gt;

&lt;p&gt;真正影响上面的行为的是&lt;code&gt;kube-controller-manager&lt;/code&gt;的两个参数：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--pod-eviction-timeout&lt;/code&gt;：缺省为 5m，五分钟，在 Pod 驱逐行为的超时时间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--node-monitor-grace-period&lt;/code&gt;：缺省为 40s，也就是 40 秒，无响应 Node 在标记为 NotReady 之前的等候时间。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;监控-1&#34;&gt;监控&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--healthz-bind-address&lt;/code&gt;：健康监测地址，缺省为&lt;code&gt;127.0.0.1&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--healthz-port&lt;/code&gt;：健康检测端口，缺省为 10248。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;curl 访问该地址，会得到响应：&lt;code&gt;ok&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;另外如果使用&lt;code&gt;kube-metrics exporter&lt;/code&gt;进行集群监控，可以关注 RC、Deploy 等对象的可用实例数量。&lt;/p&gt;

&lt;h2 id=&#34;docker&#34;&gt;Docker&lt;/h2&gt;

&lt;p&gt;Docker 的情况其实跟 Kubelet 类似，但是结果会更严重：在 Endpoint 被排除之前，路由到故障节点的流量会发生故障。&lt;/p&gt;

&lt;h2 id=&#34;测试之外&#34;&gt;测试之外&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;多 Pod 不仅对性能有好处，在极端情况下能降低故障节点对服务整体效果的影响。&lt;/li&gt;
&lt;li&gt;建议采用节点互斥的方式进行部署。&lt;/li&gt;
&lt;li&gt;对关键组件的监控，应该建立从进程到指标的多级监控，减小服务故障的时间窗口。&lt;/li&gt;
&lt;li&gt;Pod 的存活和健康监测，对于容器内的应用是有效的，应该推荐。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;附录&#34;&gt;附录&lt;/h2&gt;

&lt;h3 id=&#34;workload-yaml&#34;&gt;workload.yaml&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;
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
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
  </channel>
</rss>
