<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>kubelet | 伪架构师</title>
    <link>/tags/kubelet/</link>
      <atom:link href="/tags/kubelet/index.xml" rel="self" type="application/rss+xml" />
    <description>kubelet</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Wed, 27 Feb 2019 21:30:31 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>kubelet</title>
      <link>/tags/kubelet/</link>
    </image>
    
    <item>
      <title>从 Metric Server 到 Kubelet 服务证书</title>
      <link>/post/from-metric-server/</link>
      <pubDate>Wed, 27 Feb 2019 21:30:31 +0800</pubDate>
      <guid>/post/from-metric-server/</guid>
      <description>&lt;p&gt;很少用 Kubeadm，一直用自有 CA 签发证书，所以 TLS Bootstrap 也极少接触，然后乐子就来了。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ git clone https://github.com/kubernetes-incubator/metrics-server.git
$ cd metrics-server/deploy/1.8+
$ kubectl apply -f .
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;使用 &lt;code&gt;kubectl top nodes&lt;/code&gt;，返回的永远都是 &lt;code&gt;error: metrics not available yet&lt;/code&gt;。&lt;code&gt;kubectl logs metrics-server-fc6d4999b-58xtc&lt;/code&gt; 查看日志，其中大量的：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;unable to fetch metrics from Kubelet node-standard-3 (node-standard-3): Get https://node-standard-3:10250/stats/summary/: x509: certificate signed by unknown authority]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;检查一下，很明显，kubelet 提供的 https 服务使用了未经认可的 CA：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ openssl s_client -showcerts -connect node-standard-3:10250
...
    Verify return code: 19 (self signed certificate in certificate chain)
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Metric Server 支持一个参数 &lt;code&gt;--kubelet-insecure-tls&lt;/code&gt;，可以跳过这一检查，然而官方也明确说了，这种方式不推荐生产使用。&lt;/p&gt;

&lt;p&gt;这时候我又想到个问题，那 API Server 是怎么访问 Kubelet 的？最后我看到，API Server 中有一行注释：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// Proxying to pods and services is IP-based... don&#39;t expect to be able to verify the hostname
proxyTLSClientConfig := &amp;amp;tls.Config{InsecureSkipVerify: true}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;那么问题来了，如何让 Kubelet 具备一个“正式”的证书，让各种组件可以放心的使用 TLS 进行访问呢？查阅资料发现，目前的 kubeadm 流程中，kubelet 的 Bootstrap 因为节点动态的原因，已经不再自动完成 Kubelet 服务端点的证书签发了，使用统一 CA 自行签署，或者恢复 Bootstrap 中的服务证书申请流程，也就能完成任务了。&lt;/p&gt;

&lt;p&gt;Kubelet 的 &lt;code&gt;config.yaml&lt;/code&gt; 中加入一行：&lt;code&gt;serverTLSBootstrap: true&lt;/code&gt;，即可启动这一过程。重启 Kubelet，会发现出现了新的 CSR：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl get csr
NAME        AGE     REQUESTOR                     CONDITION
csr-f29hk   5s      system:node:node-standard-2   Pending
csr-n9pvr   3m31s   system:node:node-standard-3   Pending
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果使用 &lt;code&gt;base64 -d&lt;/code&gt; 对 csr 的 request 字段做解码，并查看其请求内容的话，会发现：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ openssl req -in csr.pem -noout -text
...
X509v3 Subject Alternative Name:
                DNS:node-standard-2, IP Address:10.211.55.28
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;证书请求中已经带有了 SAN 记录。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl certificate approve csr-n9pvr
certificatesigningrequest.certificates.k8s.io/csr-n9pvr approved
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;通过之后，Kubelet 就有了使用 API Server 的 CA 签发的证书了。&lt;/p&gt;

&lt;p&gt;稍等片刻，再次执行 &lt;code&gt;kubectl top nodes&lt;/code&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl top nodes
NAME              CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
node-standard-1   213m         10%    1220Mi          70%
node-standard-2   71m          3%     361Mi           20%
node-standard-3   61m          3%     355Mi           20%
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
  </channel>
</rss>
