部署一套完整的Kubernetes高可用集群(二进制,v1.18版)
<h2 id="heading">一、前置知识点</h2><h3 id="11-kubernetes">1.1 生产环境可部署Kubernetes集群的两种方式</h3>
<p>目前生产部署Kubernetes集群主要有两种方式:</p>
<ul>
<li>kubeadm</li>
</ul>
<p>Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。</p>
<p>官方地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/</p>
<ul>
<li>二进制包</li>
</ul>
<p>从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。</p>
<p>Kubeadm降低部署门槛,但屏蔽了很多细节,遇到问题很难排查。如果想更容易可控,推荐使用二进制包部署Kubernetes集群,虽然手动部署麻烦点,期间可以学习很多工作原理,也利于后期维护。</p>
<h3 id="12-">1.2 安装要求</h3>
<p>在开始之前,部署Kubernetes集群机器需要满足以下几个条件:</p>
<ul>
<li>一台或多台机器,操作系统 CentOS7.x-86_x64</li>
<li>硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多</li>
<li>可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点</li>
<li>禁止swap分区</li>
</ul>
<h3 id="13-">1.3 准备环境</h3>
<p>软件环境:</p>
<table>
<thead>
<tr><th><strong>软件</strong></th><th><strong>版本</strong></th></tr>
</thead>
<tbody>
<tr>
<td>操作系统</td>
<td>CentOS7.8_x64 (mini)</td>
</tr>
<tr>
<td>Docker</td>
<td>19-ce</td>
</tr>
<tr>
<td>Kubernetes</td>
<td>1.18</td>
</tr>
</tbody>
</table>
<p>服务器整体规划:</p>
<table>
<thead>
<tr><th><strong>角色</strong></th><th><strong>IP</strong></th><th><strong>组件</strong></th></tr>
</thead>
<tbody>
<tr>
<td>k8s-master1</td>
<td>192.168.31.71</td>
<td>kube-apiserver,kube-controller-manager,kube-scheduler,etcd</td>
</tr>
<tr>
<td>k8s-master2</td>
<td>192.168.31.74</td>
<td>kube-apiserver,kube-controller-manager,kube-scheduler</td>
</tr>
<tr>
<td>k8s-node1</td>
<td>192.168.31.72</td>
<td>kubelet,kube-proxy,docker etcd</td>
</tr>
<tr>
<td>k8s-node2</td>
<td>192.168.31.73</td>
<td>kubelet,kube-proxy,docker,etcd</td>
</tr>
<tr>
<td>Load Balancer(Master)</td>
<td>192.168.31.81 ,192.168.31.88 (VIP)</td>
<td>Nginx L4</td>
</tr>
<tr>
<td>Load Balancer(Backup)</td>
<td>192.168.31. 82</td>
<td>Nginx L4</td>
</tr>
</tbody>
</table>
<p> </p>
<p>须知:考虑到有些朋友电脑配置较低,这么多虚拟机跑不动,所以这一套高可用集群分两部分实施,先部署一套单Master架构(192.168.31.71/72/73),再扩容为多Master架构(上述规划),顺便熟悉下Master扩容流程。</p>
<p>单Master架构图:</p>
<p><img src="https://img2020.cnblogs.com/blog/991704/202007/991704-20200721175907693-1828012284.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p>单Master服务器规划:</p>
<table>
<thead>
<tr><th><strong>角色</strong></th><th><strong>IP</strong></th><th><strong>组件</strong></th></tr>
</thead>
<tbody>
<tr>
<td>k8s-master</td>
<td>192.168.31.71</td>
<td>kube-apiserver,kube-controller-manager,kube-scheduler,etcd</td>
</tr>
<tr>
<td>k8s-node1</td>
<td>192.168.31.72</td>
<td>kubelet,kube-proxy,docker etcd</td>
</tr>
<tr>
<td>k8s-node2</td>
<td>192.168.31.73</td>
<td>kubelet,kube-proxy,docker,etcd</td>
</tr>
</tbody>
</table>
<p> </p>
<h3 id="14-">1.4 操作系统初始化配置</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"># 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭selinux
sed </span>-i <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">s/enforcing/disabled/</span><span style="color: rgba(128, 0, 0, 1)">'</span> /etc/selinux/<span style="color: rgba(0, 0, 0, 1)">config# 永久
setenforce </span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"># 临时
# 关闭swap
swapoff </span>-<span style="color: rgba(0, 0, 0, 1)">a# 临时
sed </span>-ri <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">s/.*swap.*/#&/</span><span style="color: rgba(128, 0, 0, 1)">'</span> /etc/<span style="color: rgba(0, 0, 0, 1)">fstab # 永久
# 根据规划设置主机名
hostnamectl </span><span style="color: rgba(0, 0, 255, 1)">set</span>-hostname <hostname><span style="color: rgba(0, 0, 0, 1)">
# 在master添加hosts
cat </span>>> /etc/hosts <<<span style="color: rgba(0, 0, 0, 1)"> EOF
</span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.71</span> k8s-<span style="color: rgba(0, 0, 0, 1)">master
</span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.72</span> k8s-<span style="color: rgba(0, 0, 0, 1)">node1
</span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.73</span> k8s-<span style="color: rgba(0, 0, 0, 1)">node2
EOF
# 将桥接的IPv4流量传递到iptables的链
cat </span>> /etc/sysctl.d/k8s.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
net.bridge.bridge</span>-nf-call-ip6tables = <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
net.bridge.bridge</span>-nf-call-iptables = <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
EOF
sysctl </span>--<span style="color: rgba(0, 0, 0, 1)">system# 生效
# 时间同步
yum install ntpdate </span>-<span style="color: rgba(0, 0, 0, 1)">y
ntpdate time.windows.com</span></pre>
</div>
<h2 id="etcd">二、部署Etcd集群</h2>
<p>Etcd 是一个分布式键值存储系统,Kubernetes使用Etcd进行数据存储,所以先准备一个Etcd数据库,为解决Etcd单点故障,应采用集群方式部署,这里使用3台组建集群,可容忍1台机器故障,当然,你也可以使用5台组建集群,可容忍2台机器故障。</p>
<table>
<thead>
<tr><th><strong>节点名称</strong></th><th><strong>IP</strong></th></tr>
</thead>
<tbody>
<tr>
<td>etcd-1</td>
<td>192.168.31.71</td>
</tr>
<tr>
<td>etcd-2</td>
<td>192.168.31.72</td>
</tr>
<tr>
<td>etcd-3</td>
<td>192.168.31.73</td>
</tr>
</tbody>
</table>
<p>注:为了节省机器,这里与K8s节点机器复用。也可以独立于k8s集群之外部署,只要apiserver能连接到就行。</p>
<h3 id="21-cfssl">2.1 准备cfssl证书生成工具</h3>
<p>cfssl是一个开源的证书管理工具,使用json文件生成证书,相比openssl更方便使用。</p>
<p>找任意一台服务器操作,这里用Master节点。</p>
<div class="cnblogs_code">
<pre>wget https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">pkg.cfssl.org/R1.2/cfssl_linux-amd64</span>
wget https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">pkg.cfssl.org/R1.2/cfssljson_linux-amd64</span>
wget https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64</span>
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-<span style="color: rgba(0, 0, 0, 1)">amd64
mv cfssl_linux</span>-amd64 /usr/local/bin/<span style="color: rgba(0, 0, 0, 1)">cfssl
mv cfssljson_linux</span>-amd64 /usr/local/bin/<span style="color: rgba(0, 0, 0, 1)">cfssljson
mv cfssl</span>-certinfo_linux-amd64 /usr/bin/cfssl-certinfo</pre>
</div>
<h3 id="22-etcd">2.2 生成Etcd证书</h3>
<h4 id="1-ca">1. 自签证书颁发机构(CA)</h4>
<p>创建工作目录:</p>
<div class="cnblogs_code">
<pre>mkdir -p ~/TLS/<span style="color: rgba(0, 0, 0, 1)">{etcd,k8s}
cd TLS</span>/etcd</pre>
</div>
<p>自签CA:</p>
<div class="cnblogs_code">
<pre>cat > ca-config.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">signing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">default</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">expiry</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">87600h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">profiles</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">www</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">expiry</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">87600h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">usages</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">signing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key encipherment</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">server auth</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">client auth</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
]
}
}
}
}
EOF
cat </span>> ca-csr.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd CA</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">algo</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rsa</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">size</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">2048</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">names</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">L</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Beijing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ST</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Beijing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
]
}
EOF</span></pre>
</div>
<p>生成证书:</p>
<div class="cnblogs_code">
<pre>cfssl gencert -initca ca-csr.json | cfssljson -bare ca -<span style="color: rgba(0, 0, 0, 1)">
ls </span>*<span style="color: rgba(0, 0, 0, 1)">pem
ca</span>-key.pemca.pem</pre>
</div>
<h4 id="2-caetcd-https">2. 使用自签CA签发Etcd HTTPS证书</h4>
<p>创建证书申请文件:</p>
<div class="cnblogs_code">
<pre>cat > server-csr.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hosts</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.71</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.72</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.73</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">algo</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rsa</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">size</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">2048</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">names</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">L</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BeiJing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ST</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BeiJing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
]
}
EOF</span></pre>
</div>
<blockquote>
<p>注:上述文件hosts字段中IP为所有etcd节点的集群内部通信IP,一个都不能少!为了方便后期扩容可以多写几个预留的IP。</p>
</blockquote>
<p>生成证书:</p>
<div class="cnblogs_code">
<pre>cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -<span style="color: rgba(0, 0, 0, 1)">bare server
ls server</span>*<span style="color: rgba(0, 0, 0, 1)">pem
server</span>-key.pemserver.pem</pre>
</div>
<h3 id="23-github">2.3 从Github下载二进制文件</h3>
<p>下载地址:https://github.com/etcd-io/etcd/releases/download/v3.4.9/etcd-v3.4.9-linux-amd64.tar.gz</p>
<h3 id="24-etcd">2.4 部署Etcd集群</h3>
<p>以下在节点1上操作,为简化操作,待会将节点1生成的所有文件拷贝到节点2和节点3.</p>
<h4 id="1-">1. 创建工作目录并解压二进制包</h4>
<div class="cnblogs_code">
<pre>mkdir /opt/etcd/{bin,cfg,ssl} -<span style="color: rgba(0, 0, 0, 1)">p
tar zxvf etcd</span>-v3.<span style="color: rgba(128, 0, 128, 1)">4.9</span>-linux-<span style="color: rgba(0, 0, 0, 1)">amd64.tar.gz
mv etcd</span>-v3.<span style="color: rgba(128, 0, 128, 1)">4.9</span>-linux-amd64/{etcd,etcdctl} /opt/etcd/bin/</pre>
</div>
<h4 id="2-etcd">2. 创建etcd配置文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/etcd/cfg/etcd.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
#
ETCD_NAME</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd-1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_DATA_DIR</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/var/lib/etcd/default.etcd</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_LISTEN_PEER_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2380</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_LISTEN_CLIENT_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2379</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
#
ETCD_INITIAL_ADVERTISE_PEER_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2380</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_ADVERTISE_CLIENT_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2379</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_INITIAL_CLUSTER</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd-1=https://192.168.31.71:2380,etcd-2=https://192.168.31.72:2380,etcd-3=https://192.168.31.73:2380</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_INITIAL_CLUSTER_TOKEN</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd-cluster</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_INITIAL_CLUSTER_STATE</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">new</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
EOF</span></pre>
</div>
<ul>
<li>ETCD_NAME:节点名称,集群中唯一</li>
<li>ETCD_DATA_DIR:数据目录</li>
<li>ETCD_LISTEN_PEER_URLS:集群通信监听地址</li>
<li>ETCD_LISTEN_CLIENT_URLS:客户端访问监听地址</li>
<li>ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址</li>
<li>ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址</li>
<li>ETCD_INITIAL_CLUSTER:集群节点地址</li>
<li>ETCD_INITIAL_CLUSTER_TOKEN:集群Token</li>
<li>ETCD_INITIAL_CLUSTER_STATE:加入集群的当前状态,new是新集群,existing表示加入已有集群</li>
</ul>
<h4 id="3-systemdetcd">3. systemd管理etcd</h4>
<div class="cnblogs_code">
<pre>cat > /usr/lib/systemd/system/etcd.service <<<span style="color: rgba(0, 0, 0, 1)"> EOF
Description</span>=<span style="color: rgba(0, 0, 0, 1)">Etcd Server
After</span>=<span style="color: rgba(0, 0, 0, 1)">network.target
After</span>=network-<span style="color: rgba(0, 0, 0, 1)">online.target
Wants</span>=network-<span style="color: rgba(0, 0, 0, 1)">online.target
Type</span>=<span style="color: rgba(0, 0, 0, 1)">notify
EnvironmentFile</span>=/opt/etcd/cfg/<span style="color: rgba(0, 0, 0, 1)">etcd.conf
ExecStart</span>=/opt/etcd/bin/<span style="color: rgba(0, 0, 0, 1)">etcd \
</span>--cert-file=/opt/etcd/ssl/<span style="color: rgba(0, 0, 0, 1)">server.pem \
</span>--key-file=/opt/etcd/ssl/server-<span style="color: rgba(0, 0, 0, 1)">key.pem \
</span>--peer-cert-file=/opt/etcd/ssl/<span style="color: rgba(0, 0, 0, 1)">server.pem \
</span>--peer-key-file=/opt/etcd/ssl/server-<span style="color: rgba(0, 0, 0, 1)">key.pem \
</span>--trusted-ca-file=/opt/etcd/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \
</span>--peer-trusted-ca-file=/opt/etcd/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \
</span>--logger=<span style="color: rgba(0, 0, 0, 1)">zap
Restart</span>=on-<span style="color: rgba(0, 0, 0, 1)">failure
LimitNOFILE</span>=<span style="color: rgba(128, 0, 128, 1)">65536</span><span style="color: rgba(0, 0, 0, 1)">
WantedBy</span>=multi-<span style="color: rgba(0, 0, 0, 1)">user.target
EOF</span></pre>
</div>
<h4 id="4-">4. 拷贝刚才生成的证书</h4>
<p>把刚才生成的证书拷贝到配置文件中的路径:</p>
<div class="cnblogs_code">
<pre>cp ~/TLS/etcd/ca*pem ~/TLS/etcd/server*pem /opt/etcd/ssl/</pre>
</div>
<h4 id="5-">5. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start etcd
systemctl enable etcd</span></pre>
</div>
<h4 id="6-123">6. 将上面节点1所有生成的文件拷贝到节点2和节点3</h4>
<div class="cnblogs_code">
<pre>scp -r /opt/etcd/ root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.72</span>:/opt/<span style="color: rgba(0, 0, 0, 1)">
scp </span>/usr/lib/systemd/system/etcd.service root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.72</span>:/usr/lib/systemd/system/<span style="color: rgba(0, 0, 0, 1)">
scp </span>-r /opt/etcd/ root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.73</span>:/opt/<span style="color: rgba(0, 0, 0, 1)">
scp </span>/usr/lib/systemd/system/etcd.service root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.73</span>:/usr/lib/systemd/system/</pre>
</div>
<p>然后在节点2和节点3分别修改etcd.conf配置文件中的节点名称和当前服务器IP:</p>
<div class="cnblogs_code">
<pre>vi /opt/etcd/cfg/<span style="color: rgba(0, 0, 0, 1)">etcd.conf
#
ETCD_NAME</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd-1</span><span style="color: rgba(128, 0, 0, 1)">"</span> # 修改此处,节点2改为etcd-<span style="color: rgba(128, 0, 128, 1)">2</span>,节点3改为etcd-<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_DATA_DIR</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/var/lib/etcd/default.etcd</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_LISTEN_PEER_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2380</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> # 修改此处为当前服务器IP
ETCD_LISTEN_CLIENT_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2379</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> # 修改此处为当前服务器IP
#
ETCD_INITIAL_ADVERTISE_PEER_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2380</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> # 修改此处为当前服务器IP
ETCD_ADVERTISE_CLIENT_URLS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2379</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> # 修改此处为当前服务器IP
ETCD_INITIAL_CLUSTER</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd-1=https://192.168.31.71:2380,etcd-2=https://192.168.31.72:2380,etcd-3=https://192.168.31.73:2380</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_INITIAL_CLUSTER_TOKEN</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">etcd-cluster</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
ETCD_INITIAL_CLUSTER_STATE</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">new</span><span style="color: rgba(128, 0, 0, 1)">"</span></pre>
</div>
<p>最后启动etcd并设置开机启动,同上。</p>
<h4 id="7-">7. 查看集群状态</h4>
<div class="cnblogs_code">
<pre>ETCDCTL_API=<span style="color: rgba(128, 0, 128, 1)">3</span> /opt/etcd/bin/etcdctl --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem --endpoints=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:2379,https://192.168.31.72:2379,https://192.168.31.73:2379</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> endpoint health
https:</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">192.168.31.71:2379 is healthy: successfully committed proposal: took = 8.154404ms</span>
https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">192.168.31.73:2379 is healthy: successfully committed proposal: took = 9.044117ms</span>
https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">192.168.31.72:2379 is healthy: successfully committed proposal: took = 10.000825ms</span></pre>
</div>
<p>如果输出上面信息,就说明集群部署成功。如果有问题第一步先看日志:/var/log/message 或 journalctl -u etcd</p>
<h2 id="docker">三、安装Docker</h2>
<p>下载地址:https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz</p>
<p>以下在所有节点操作。这里采用二进制安装,用yum安装也一样。</p>
<h3 id="31-">3.1 解压二进制包</h3>
<div class="cnblogs_code">
<pre>tar zxvf docker-<span style="color: rgba(128, 0, 128, 1)">19.03</span>.<span style="color: rgba(128, 0, 128, 1)">9</span><span style="color: rgba(0, 0, 0, 1)">.tgz
mv docker</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> /usr/bin</span></pre>
</div>
<h3 id="32-systemddocker">3.2 systemd管理docker</h3>
<div class="cnblogs_code">
<pre>cat > /usr/lib/systemd/system/docker.service <<<span style="color: rgba(0, 0, 0, 1)"> EOF
Description</span>=<span style="color: rgba(0, 0, 0, 1)">Docker Application Container Engine
Documentation</span>=https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">docs.docker.com</span>
After=network-<span style="color: rgba(0, 0, 0, 1)">online.target firewalld.service
Wants</span>=network-<span style="color: rgba(0, 0, 0, 1)">online.target
Type</span>=<span style="color: rgba(0, 0, 0, 1)">notify
ExecStart</span>=/usr/bin/<span style="color: rgba(0, 0, 0, 1)">dockerd
ExecReload</span>=/bin/kill -<span style="color: rgba(0, 0, 0, 1)">s HUP $MAINPID
LimitNOFILE</span>=<span style="color: rgba(0, 0, 0, 1)">infinity
LimitNPROC</span>=<span style="color: rgba(0, 0, 0, 1)">infinity
LimitCORE</span>=<span style="color: rgba(0, 0, 0, 1)">infinity
TimeoutStartSec</span>=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
Delegate</span>=<span style="color: rgba(0, 0, 0, 1)">yes
KillMode</span>=<span style="color: rgba(0, 0, 0, 1)">process
Restart</span>=on-<span style="color: rgba(0, 0, 0, 1)">failure
StartLimitBurst</span>=<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">
StartLimitInterval</span>=<span style="color: rgba(0, 0, 0, 1)">60s
WantedBy</span>=multi-<span style="color: rgba(0, 0, 0, 1)">user.target
EOF</span></pre>
</div>
<h3 id="33-">3.3 创建配置文件</h3>
<div class="cnblogs_code">
<pre>mkdir /etc/<span style="color: rgba(0, 0, 0, 1)">docker
cat </span>> /etc/docker/daemon.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">registry-mirrors</span><span style="color: rgba(128, 0, 0, 1)">"</span>: [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://b9pmyelo.mirror.aliyuncs.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">log-driver</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">json-file</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">log-opts</span><span style="color: rgba(128, 0, 0, 1)">"</span>: {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">max-size</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">500m</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">max-file</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}
}
EOF</span></pre>
</div>
<ul>
<li>registry-mirrors 阿里云镜像加速器</li>
</ul>
<h3 id="34-">3.4 启动并设置开机启动</h3>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start docker
systemctl enable docker</span></pre>
</div>
<h2 id="master-node">四、部署Master Node</h2>
<blockquote>
<p>如果你在学习中遇到问题或者文档有误可联系阿良~ 微信: init1024</p>
</blockquote>
<h3 id="41-kubeapiserver">4.1 生成kube-apiserver证书</h3>
<h4 id="1-ca1">1. 自签证书颁发机构(CA)</h4>
<div class="cnblogs_code">
<pre>cat > ca-config.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">signing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">default</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">expiry</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">87600h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">profiles</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">expiry</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">87600h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">usages</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">signing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key encipherment</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">server auth</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">client auth</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
]
}
}
}
}
EOF
cat </span>> ca-csr.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">algo</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rsa</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">size</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">2048</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">names</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">L</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Beijing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ST</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Beijing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">O</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">k8s</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OU</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">System</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
]
}
EOF</span></pre>
</div>
<p>生成证书:</p>
<div class="cnblogs_code">
<pre>cfssl gencert -initca ca-csr.json | cfssljson -bare ca -<span style="color: rgba(0, 0, 0, 1)">
ls </span>*<span style="color: rgba(0, 0, 0, 1)">pem
ca</span>-key.pemca.pem</pre>
</div>
<h4 id="2-cakubeapiserver-https">2. 使用自签CA签发kube-apiserver HTTPS证书</h4>
<p>创建证书申请文件:</p>
<div class="cnblogs_code">
<pre>cd TLS/<span style="color: rgba(0, 0, 0, 1)">k8s
cat </span>> server-csr.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hosts</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10.0.0.1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">127.0.0.1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.71</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.72</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.73</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.74</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.81</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.82</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">192.168.31.88</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes.default</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes.default.svc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes.default.svc.cluster</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubernetes.default.svc.cluster.local</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">algo</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rsa</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">size</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">2048</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">names</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">L</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BeiJing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ST</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BeiJing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">O</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">k8s</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OU</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">System</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
]
}
EOF</span></pre>
</div>
<blockquote>
<p>注:上述文件hosts字段中IP为所有Master/LB/VIP IP,一个都不能少!为了方便后期扩容可以多写几个预留的IP。</p>
</blockquote>
<p>生成证书:</p>
<div class="cnblogs_code">
<pre>cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -<span style="color: rgba(0, 0, 0, 1)">bare server
ls server</span>*<span style="color: rgba(0, 0, 0, 1)">pem
server</span>-key.pemserver.pem</pre>
</div>
<h3 id="42-github">4.2 从Github下载二进制文件</h3>
<p>下载地址: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.18.md#v1183</p>
<blockquote>
<p>注:打开链接你会发现里面有很多包,下载一个server包就够了,包含了Master和Worker Node二进制文件。</p>
</blockquote>
<h3 id="43-">4.3 解压二进制包</h3>
<div class="cnblogs_code">
<pre>mkdir -p /opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">{bin,cfg,ssl,logs}
tar zxvf kubernetes</span>-server-linux-<span style="color: rgba(0, 0, 0, 1)">amd64.tar.gz
cd kubernetes</span>/server/<span style="color: rgba(0, 0, 0, 1)">bin
cp kube</span>-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">bin
cp kubectl </span>/usr/bin/</pre>
</div>
<h3 id="44-kubeapiserver">4.4 部署kube-apiserver</h3>
<h4 id="1-1">1. 创建配置文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/kube-apiserver.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
KUBE_APISERVER_OPTS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--logtostderr=false \\</span>
--v=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--log-dir=/opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">logs \\
</span>--etcd-servers=https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">192.168.31.71:2379,</span><span style="color: rgba(0, 128, 0, 1); text-decoration: underline">https://192.168.31.72</span><span style="color: rgba(0, 128, 0, 1)">:2379,</span><span style="color: rgba(0, 128, 0, 1); text-decoration: underline">https://192.168.31.73</span><span style="color: rgba(0, 128, 0, 1)">:2379 \\</span>
--bind-address=<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.71</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--secure-port=<span style="color: rgba(128, 0, 128, 1)">6443</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--advertise-address=<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.71</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--allow-privileged=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--service-cluster-ip-range=<span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span>/<span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--enable-admission-plugins=<span style="color: rgba(0, 0, 0, 1)">NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \\
</span>--authorization-mode=<span style="color: rgba(0, 0, 0, 1)">RBAC,Node \\
</span>--enable-bootstrap-token-auth=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--token-auth-file=/opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">token.csv \\
</span>--service-node-port-range=<span style="color: rgba(128, 0, 128, 1)">30000</span>-<span style="color: rgba(128, 0, 128, 1)">32767</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--kubelet-client-certificate=/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">server.pem \\
</span>--kubelet-client-key=/opt/kubernetes/ssl/server-<span style="color: rgba(0, 0, 0, 1)">key.pem \\
</span>--tls-cert-file=/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">server.pem\\
</span>--tls-<span style="color: rgba(0, 0, 255, 1)">private</span>-key-file=/opt/kubernetes/ssl/server-<span style="color: rgba(0, 0, 0, 1)">key.pem \\
</span>--client-ca-file=/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \\
</span>--service-account-key-file=/opt/kubernetes/ssl/ca-<span style="color: rgba(0, 0, 0, 1)">key.pem \\
</span>--etcd-cafile=/opt/etcd/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \\
</span>--etcd-certfile=/opt/etcd/ssl/<span style="color: rgba(0, 0, 0, 1)">server.pem \\
</span>--etcd-keyfile=/opt/etcd/ssl/server-<span style="color: rgba(0, 0, 0, 1)">key.pem \\
</span>--audit-log-maxage=<span style="color: rgba(128, 0, 128, 1)">30</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--audit-log-maxbackup=<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--audit-log-maxsize=<span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--audit-log-path=/opt/kubernetes/logs/k8s-audit.log<span style="color: rgba(128, 0, 0, 1)">"
</span>EOF</pre>
</div>
<blockquote>
<p>注:上面两个\ \ 第一个是转义符,第二个是换行符,使用转义符是为了使用EOF保留换行符。</p>
</blockquote>
<ul>
<li>–logtostderr:启用日志</li>
<li>—v:日志等级</li>
<li>–log-dir:日志目录</li>
<li>–etcd-servers:etcd集群地址</li>
<li>–bind-address:监听地址</li>
<li>–secure-port:https安全端口</li>
<li>–advertise-address:集群通告地址</li>
<li>–allow-privileged:启用授权</li>
<li>–service-cluster-ip-range:Service虚拟IP地址段</li>
<li>–enable-admission-plugins:准入控制模块</li>
<li>–authorization-mode:认证授权,启用RBAC授权和节点自管理</li>
<li>–enable-bootstrap-token-auth:启用TLS bootstrap机制</li>
<li>–token-auth-file:bootstrap token文件</li>
<li>–service-node-port-range:Service nodeport类型默认分配端口范围</li>
<li>–kubelet-client-xxx:apiserver访问kubelet客户端证书</li>
<li>–tls-xxx-file:apiserver https证书</li>
<li>–etcd-xxxfile:连接Etcd集群证书</li>
<li>–audit-log-xxx:审计日志</li>
</ul>
<h4 id="2-">2. 拷贝刚才生成的证书</h4>
<p>把刚才生成的证书拷贝到配置文件中的路径:</p>
<div class="cnblogs_code">
<pre>cp ~/TLS/k8s/ca*pem ~/TLS/k8s/server*pem /opt/kubernetes/ssl/</pre>
</div>
<h4 id="3--tls-bootstrapping-">3. 启用 TLS Bootstrapping 机制</h4>
<p>TLS Bootstraping:Master apiserver启用TLS认证后,Node节点kubelet和kube-proxy要与kube-apiserver进行通信,必须使用CA签发的有效证书才可以,当Node节点很多时,这种客户端证书颁发需要大量工作,同样也会增加集群扩展复杂度。为了简化流程,Kubernetes引入了TLS bootstraping机制来自动颁发客户端证书,kubelet会以一个低权限用户自动向apiserver申请证书,kubelet的证书由apiserver动态签署。所以强烈建议在Node上使用这种方式,目前主要用于kubelet,kube-proxy还是由我们统一颁发一个证书。</p>
<p>TLS bootstraping 工作流程:</p>
<p><img src="https://img2020.cnblogs.com/blog/991704/202007/991704-20200721180905841-1895505349.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> 创建上述配置文件中token文件:</p>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/token.csv <<<span style="color: rgba(0, 0, 0, 1)"> EOF
c47ffb939f5ca36231d9e3121a252940,kubelet</span>-bootstrap,<span style="color: rgba(128, 0, 128, 1)">10001</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">system:node-bootstrapper</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
EOF</span></pre>
</div>
<p>格式:token,用户名,UID,用户组</p>
<p>token也可自行生成替换:</p>
<div class="cnblogs_code">
<pre>head -c <span style="color: rgba(128, 0, 128, 1)">16</span> /dev/urandom | od -An -t x | tr -d <span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(128, 0, 0, 1)">'</span></pre>
</div>
<h4 id="4-systemdapiserver">4. systemd管理apiserver</h4>
<div class="cnblogs_code">
<pre>cat > /usr/lib/systemd/system/kube-apiserver.service <<<span style="color: rgba(0, 0, 0, 1)"> EOF
Description</span>=<span style="color: rgba(0, 0, 0, 1)">Kubernetes API Server
Documentation</span>=https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">github.com/kubernetes/kubernetes</span>
<span style="color: rgba(0, 0, 0, 1)">
EnvironmentFile</span>=/opt/kubernetes/cfg/kube-<span style="color: rgba(0, 0, 0, 1)">apiserver.conf
ExecStart</span>=/opt/kubernetes/bin/kube-<span style="color: rgba(0, 0, 0, 1)">apiserver \$KUBE_APISERVER_OPTS
Restart</span>=on-<span style="color: rgba(0, 0, 0, 1)">failure
WantedBy</span>=multi-<span style="color: rgba(0, 0, 0, 1)">user.target
EOF</span></pre>
</div>
<h4 id="5-1">5. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start kube</span>-<span style="color: rgba(0, 0, 0, 1)">apiserver
systemctl enable kube</span>-apiserver</pre>
</div>
<h4 id="6-kubeletbootstrap">6. 授权kubelet-bootstrap用户允许请求证书</h4>
<div class="cnblogs_code">
<pre>kubectl create clusterrolebinding kubelet-<span style="color: rgba(0, 0, 0, 1)">bootstrap \
</span>--clusterrole=system:node-<span style="color: rgba(0, 0, 0, 1)">bootstrapper \
</span>--user=kubelet-bootstrap</pre>
</div>
<h3 id="45-kubecontrollermanager">4.5 部署kube-controller-manager</h3>
<h4 id="1-2">1. 创建配置文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/kube-controller-manager.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
KUBE_CONTROLLER_MANAGER_OPTS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--logtostderr=false \\</span>
--v=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--log-dir=/opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">logs \\
</span>--leader-elect=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--master=<span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">8080</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--bind-address=<span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--allocate-node-cidrs=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--cluster-cidr=<span style="color: rgba(128, 0, 128, 1)">10.244</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span>/<span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--service-cluster-ip-range=<span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span>/<span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--cluster-signing-cert-file=/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \\
</span>--cluster-signing-key-file=/opt/kubernetes/ssl/ca-<span style="color: rgba(0, 0, 0, 1)">key.pem\\
</span>--root-ca-file=/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \\
</span>--service-account-<span style="color: rgba(0, 0, 255, 1)">private</span>-key-file=/opt/kubernetes/ssl/ca-<span style="color: rgba(0, 0, 0, 1)">key.pem \\
</span>--experimental-cluster-signing-duration=87600h0m0s<span style="color: rgba(128, 0, 0, 1)">"
</span>EOF</pre>
</div>
<ul>
<li>–master:通过本地非安全本地端口8080连接apiserver。</li>
<li>–leader-elect:当该组件启动多个时,自动选举(HA)</li>
<li>–cluster-signing-cert-file/–cluster-signing-key-file:自动为kubelet颁发证书的CA,与apiserver保持一致</li>
</ul>
<h4 id="2-systemdcontrollermanager">2. systemd管理controller-manager</h4>
<div class="cnblogs_code">
<pre>cat > /usr/lib/systemd/system/kube-controller-manager.service <<<span style="color: rgba(0, 0, 0, 1)"> EOF
Description</span>=<span style="color: rgba(0, 0, 0, 1)">Kubernetes Controller Manager
Documentation</span>=https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">github.com/kubernetes/kubernetes</span>
<span style="color: rgba(0, 0, 0, 1)">
EnvironmentFile</span>=/opt/kubernetes/cfg/kube-controller-<span style="color: rgba(0, 0, 0, 1)">manager.conf
ExecStart</span>=/opt/kubernetes/bin/kube-controller-<span style="color: rgba(0, 0, 0, 1)">manager \$KUBE_CONTROLLER_MANAGER_OPTS
Restart</span>=on-<span style="color: rgba(0, 0, 0, 1)">failure
WantedBy</span>=multi-<span style="color: rgba(0, 0, 0, 1)">user.target
EOF</span></pre>
</div>
<h4 id="3-">3. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start kube</span>-controller-<span style="color: rgba(0, 0, 0, 1)">manager
systemctl enable kube</span>-controller-manager</pre>
</div>
<h3 id="46-kubescheduler">4.6 部署kube-scheduler</h3>
<h4 id="1-3">1. 创建配置文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/kube-scheduler.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
KUBE_SCHEDULER_OPTS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--logtostderr=false \</span>
--v=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--log-dir=/opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">logs \
</span>--leader-<span style="color: rgba(0, 0, 0, 1)">elect \
</span>--master=<span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">8080</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--bind-address=<span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span><span style="color: rgba(128, 0, 0, 1)">"
</span>EOF</pre>
</div>
<ul>
<li>–master:通过本地非安全本地端口8080连接apiserver。</li>
<li>–leader-elect:当该组件启动多个时,自动选举(HA)</li>
</ul>
<h4 id="2-systemdscheduler">2. systemd管理scheduler</h4>
<div class="cnblogs_code">
<pre>cat > /usr/lib/systemd/system/kube-scheduler.service <<<span style="color: rgba(0, 0, 0, 1)"> EOF
Description</span>=<span style="color: rgba(0, 0, 0, 1)">Kubernetes Scheduler
Documentation</span>=https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">github.com/kubernetes/kubernetes</span>
<span style="color: rgba(0, 0, 0, 1)">
EnvironmentFile</span>=/opt/kubernetes/cfg/kube-<span style="color: rgba(0, 0, 0, 1)">scheduler.conf
ExecStart</span>=/opt/kubernetes/bin/kube-<span style="color: rgba(0, 0, 0, 1)">scheduler \$KUBE_SCHEDULER_OPTS
Restart</span>=on-<span style="color: rgba(0, 0, 0, 1)">failure
WantedBy</span>=multi-<span style="color: rgba(0, 0, 0, 1)">user.target
EOF</span></pre>
</div>
<h4 id="3-1">3. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start kube</span>-<span style="color: rgba(0, 0, 0, 1)">scheduler
systemctl enable kube</span>-scheduler</pre>
</div>
<h4 id="4-1">4. 查看集群状态</h4>
<p>所有组件都已经启动成功,通过kubectl工具查看当前集群组件状态:</p>
<div class="cnblogs_code">
<pre>kubectl <span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller</span>-<span style="color: rgba(0, 0, 0, 1)">manager Healthy ok
etcd</span>-<span style="color: rgba(128, 0, 128, 1)">2</span> Healthy {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">health</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}
etcd</span>-<span style="color: rgba(128, 0, 128, 1)">1</span> Healthy {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">health</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}
etcd</span>-<span style="color: rgba(128, 0, 128, 1)">0</span> Healthy {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">health</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span>}</pre>
</div>
<p>如上输出说明Master节点组件运行正常。</p>
<h2 id="worker-node">五、部署Worker Node</h2>
<blockquote>
<p>如果你在学习中遇到问题或者文档有误可联系阿良~ 微信: init1024</p>
</blockquote>
<p>下面还是在Master Node上操作,即同时作为Worker Node</p>
<h3 id="51-">5.1 创建工作目录并拷贝二进制文件</h3>
<p>在所有worker node创建工作目录:</p>
<div class="cnblogs_code">
<pre>mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs} </pre>
</div>
<p>从master节点拷贝:</p>
<div class="cnblogs_code">
<pre>cd kubernetes/server/<span style="color: rgba(0, 0, 0, 1)">bin
cp kubelet kube</span>-proxy /opt/kubernetes/bin # 本地拷贝</pre>
</div>
<h3 id="52-kubelet">5.2 部署kubelet</h3>
<h4 id="1-4">1. 创建配置文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/kubelet.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
KUBELET_OPTS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--logtostderr=false \\</span>
--v=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--log-dir=/opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">logs \\
</span>--hostname-<span style="color: rgba(0, 0, 255, 1)">override</span>=k8s-<span style="color: rgba(0, 0, 0, 1)">master \\
</span>--network-plugin=<span style="color: rgba(0, 0, 0, 1)">cni \\
</span>--kubeconfig=/opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">kubelet.kubeconfig \\
</span>--bootstrap-kubeconfig=/opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">bootstrap.kubeconfig \\
</span>--config=/opt/kubernetes/cfg/kubelet-<span style="color: rgba(0, 0, 0, 1)">config.yml \\
</span>--cert-dir=/opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">ssl \\
</span>--pod-infra-container-image=lizhenliang/pause-amd64:<span style="color: rgba(128, 0, 128, 1)">3.0</span><span style="color: rgba(128, 0, 0, 1)">"
</span>EOF</pre>
</div>
<ul>
<li>–hostname-override:显示名称,集群中唯一</li>
<li>–network-plugin:启用CNI</li>
<li>–kubeconfig:空路径,会自动生成,后面用于连接apiserver</li>
<li>–bootstrap-kubeconfig:首次启动向apiserver申请证书</li>
<li>–config:配置参数文件</li>
<li>–cert-dir:kubelet证书生成目录</li>
<li>–pod-infra-container-image:管理Pod网络容器的镜像</li>
</ul>
<h4 id="2-1">2. 配置参数文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/kubelet-config.yml <<<span style="color: rgba(0, 0, 0, 1)"> EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io</span>/<span style="color: rgba(0, 0, 0, 1)">v1beta1
address: </span><span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span><span style="color: rgba(0, 0, 0, 1)">
port: </span><span style="color: rgba(128, 0, 128, 1)">10250</span><span style="color: rgba(0, 0, 0, 1)">
readOnlyPort: </span><span style="color: rgba(128, 0, 128, 1)">10255</span><span style="color: rgba(0, 0, 0, 1)">
cgroupDriver: cgroupfs
clusterDNS:
</span>- <span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.2</span><span style="color: rgba(0, 0, 0, 1)">
clusterDomain: cluster.local
failSwapOn: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
authentication:
anonymous:
enabled: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
webhook:
cacheTTL: 2m0s
enabled: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
x509:
clientCAFile: </span>/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: 5m0s
cacheUnauthorizedTTL: 30s
evictionHard:
imagefs.available: </span><span style="color: rgba(128, 0, 128, 1)">15</span>%<span style="color: rgba(0, 0, 0, 1)">
memory.available: 100Mi
nodefs.available: </span><span style="color: rgba(128, 0, 128, 1)">10</span>%<span style="color: rgba(0, 0, 0, 1)">
nodefs.inodesFree: </span><span style="color: rgba(128, 0, 128, 1)">5</span>%<span style="color: rgba(0, 0, 0, 1)">
maxOpenFiles: </span><span style="color: rgba(128, 0, 128, 1)">1000000</span><span style="color: rgba(0, 0, 0, 1)">
maxPods: </span><span style="color: rgba(128, 0, 128, 1)">110</span><span style="color: rgba(0, 0, 0, 1)">
EOF</span></pre>
</div>
<h4 id="3-bootstrapkubeconfig">3. 生成bootstrap.kubeconfig文件</h4>
<div class="cnblogs_code">
<pre>KUBE_APISERVER=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:6443</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> # apiserver IP:PORT
TOKEN</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">c47ffb939f5ca36231d9e3121a252940</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> # 与token.csv里保持一致
# 生成 kubelet bootstrap kubeconfig 配置文件
kubectl config </span><span style="color: rgba(0, 0, 255, 1)">set</span>-<span style="color: rgba(0, 0, 0, 1)">cluster kubernetes \
</span>--certificate-authority=/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \
</span>--embed-certs=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--server=<span style="color: rgba(0, 0, 0, 1)">${KUBE_APISERVER} \
</span>--kubeconfig=<span style="color: rgba(0, 0, 0, 1)">bootstrap.kubeconfig
kubectl config </span><span style="color: rgba(0, 0, 255, 1)">set</span>-credentials <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubelet-bootstrap</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--token=<span style="color: rgba(0, 0, 0, 1)">${TOKEN} \
</span>--kubeconfig=<span style="color: rgba(0, 0, 0, 1)">bootstrap.kubeconfig
kubectl config </span><span style="color: rgba(0, 0, 255, 1)">set</span>-context <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--cluster=<span style="color: rgba(0, 0, 0, 1)">kubernetes \
</span>--user=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">kubelet-bootstrap</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--kubeconfig=<span style="color: rgba(0, 0, 0, 1)">bootstrap.kubeconfig
kubectl config use</span>-context <span style="color: rgba(0, 0, 255, 1)">default</span> --kubeconfig=bootstrap.kubeconfig</pre>
</div>
<p>拷贝到配置文件路径:</p>
<div class="cnblogs_code">
<pre>cp bootstrap.kubeconfig /opt/kubernetes/cfg</pre>
</div>
<h4 id="4-systemdkubelet">4. systemd管理kubelet</h4>
<div class="cnblogs_code">
<pre>cat > /usr/lib/systemd/system/kubelet.service <<<span style="color: rgba(0, 0, 0, 1)"> EOF
Description</span>=<span style="color: rgba(0, 0, 0, 1)">Kubernetes Kubelet
After</span>=<span style="color: rgba(0, 0, 0, 1)">docker.service
EnvironmentFile</span>=/opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">kubelet.conf
ExecStart</span>=/opt/kubernetes/bin/<span style="color: rgba(0, 0, 0, 1)">kubelet \$KUBELET_OPTS
Restart</span>=on-<span style="color: rgba(0, 0, 0, 1)">failure
LimitNOFILE</span>=<span style="color: rgba(128, 0, 128, 1)">65536</span><span style="color: rgba(0, 0, 0, 1)">
WantedBy</span>=multi-<span style="color: rgba(0, 0, 0, 1)">user.target
EOF</span></pre>
</div>
<h4 id="5-2">5. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start kubelet
systemctl enable kubelet</span></pre>
</div>
<h3 id="53-kubelet">5.3 批准kubelet证书申请并加入集群</h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"># 查看kubelet证书请求
kubectl </span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node</span>-csr-uCEGPOIiDdlLODKts8J658HrFq9CZ--K6M4G7bjhk8A 6m3s kubernetes.io/kube-apiserver-client-kubelet kubelet-<span style="color: rgba(0, 0, 0, 1)">bootstrap Pending
# 批准申请
kubectl certificate approve node</span>-csr-uCEGPOIiDdlLODKts8J658HrFq9CZ--<span style="color: rgba(0, 0, 0, 1)">K6M4G7bjhk8A
# 查看节点
kubectl </span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> node
NAME STATUS ROLES AGE VERSION
k8s</span>-master NotReady <none> 7s v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span></pre>
</div>
<blockquote>
<p>注:由于网络插件还没有部署,节点会没有准备就绪 NotReady</p>
</blockquote>
<h3 id="54-kubeproxy">5.4 部署kube-proxy</h3>
<h4 id="1-5">1. 创建配置文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/kube-proxy.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
KUBE_PROXY_OPTS</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">--logtostderr=false \\</span>
--v=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)"> \\
</span>--log-dir=/opt/kubernetes/<span style="color: rgba(0, 0, 0, 1)">logs \\
</span>--config=/opt/kubernetes/cfg/kube-proxy-config.yml<span style="color: rgba(128, 0, 0, 1)">"
</span>EOF</pre>
</div>
<h4 id="2-2">2. 配置参数文件</h4>
<div class="cnblogs_code">
<pre>cat > /opt/kubernetes/cfg/kube-proxy-config.yml <<<span style="color: rgba(0, 0, 0, 1)"> EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io</span>/<span style="color: rgba(0, 0, 0, 1)">v1alpha1
bindAddress: </span><span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span><span style="color: rgba(0, 0, 0, 1)">
metricsBindAddress: </span><span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span>:<span style="color: rgba(128, 0, 128, 1)">10249</span><span style="color: rgba(0, 0, 0, 1)">
clientConnection:
kubeconfig: </span>/opt/kubernetes/cfg/kube-<span style="color: rgba(0, 0, 0, 1)">proxy.kubeconfig
hostnameOverride: k8s</span>-<span style="color: rgba(0, 0, 0, 1)">master
clusterCIDR: </span><span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span>/<span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)">
EOF</span></pre>
</div>
<h4 id="3-kubeproxykubeconfig">3. 生成kube-proxy.kubeconfig文件</h4>
<p>生成kube-proxy证书:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"># 切换工作目录
cd TLS</span>/<span style="color: rgba(0, 0, 0, 1)">k8s
# 创建证书请求文件
cat </span>> kube-proxy-csr.json <<<span style="color: rgba(0, 0, 0, 1)"> EOF
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">system:kube-proxy</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hosts</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [],
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">key</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">algo</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rsa</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">size</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 128, 1)">2048</span><span style="color: rgba(0, 0, 0, 1)">
},
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">names</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">: [
{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CN</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">L</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BeiJing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ST</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BeiJing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">O</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">k8s</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OU</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">System</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
]
}
EOF
# 生成证书
cfssl gencert </span>-ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-<span style="color: rgba(0, 0, 0, 1)">proxy
ls kube</span>-proxy*<span style="color: rgba(0, 0, 0, 1)">pem
kube</span>-proxy-key.pemkube-proxy.pem</pre>
</div>
<p>生成kubeconfig文件:</p>
<div class="cnblogs_code">
<pre>KUBE_APISERVER=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://192.168.31.71:6443</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
kubectl config </span><span style="color: rgba(0, 0, 255, 1)">set</span>-<span style="color: rgba(0, 0, 0, 1)">cluster kubernetes \
</span>--certificate-authority=/opt/kubernetes/ssl/<span style="color: rgba(0, 0, 0, 1)">ca.pem \
</span>--embed-certs=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--server=<span style="color: rgba(0, 0, 0, 1)">${KUBE_APISERVER} \
</span>--kubeconfig=kube-<span style="color: rgba(0, 0, 0, 1)">proxy.kubeconfig
kubectl config </span><span style="color: rgba(0, 0, 255, 1)">set</span>-credentials kube-<span style="color: rgba(0, 0, 0, 1)">proxy \
</span>--client-certificate=./kube-<span style="color: rgba(0, 0, 0, 1)">proxy.pem \
</span>--client-key=./kube-proxy-<span style="color: rgba(0, 0, 0, 1)">key.pem \
</span>--embed-certs=<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--kubeconfig=kube-<span style="color: rgba(0, 0, 0, 1)">proxy.kubeconfig
kubectl config </span><span style="color: rgba(0, 0, 255, 1)">set</span>-context <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--cluster=<span style="color: rgba(0, 0, 0, 1)">kubernetes \
</span>--user=kube-<span style="color: rgba(0, 0, 0, 1)">proxy \
</span>--kubeconfig=kube-<span style="color: rgba(0, 0, 0, 1)">proxy.kubeconfig
kubectl config use</span>-context <span style="color: rgba(0, 0, 255, 1)">default</span> --kubeconfig=kube-proxy.kubeconfig</pre>
</div>
<p>拷贝到配置文件指定路径:</p>
<div class="cnblogs_code">
<pre>cp kube-proxy.kubeconfig /opt/kubernetes/cfg/</pre>
</div>
<h4 id="4-systemdkubeproxy">4. systemd管理kube-proxy</h4>
<div class="cnblogs_code">
<pre>cat > /usr/lib/systemd/system/kube-proxy.service <<<span style="color: rgba(0, 0, 0, 1)"> EOF
Description</span>=<span style="color: rgba(0, 0, 0, 1)">Kubernetes Proxy
After</span>=<span style="color: rgba(0, 0, 0, 1)">network.target
EnvironmentFile</span>=/opt/kubernetes/cfg/kube-<span style="color: rgba(0, 0, 0, 1)">proxy.conf
ExecStart</span>=/opt/kubernetes/bin/kube-<span style="color: rgba(0, 0, 0, 1)">proxy \$KUBE_PROXY_OPTS
Restart</span>=on-<span style="color: rgba(0, 0, 0, 1)">failure
LimitNOFILE</span>=<span style="color: rgba(128, 0, 128, 1)">65536</span><span style="color: rgba(0, 0, 0, 1)">
WantedBy</span>=multi-<span style="color: rgba(0, 0, 0, 1)">user.target
EOF</span></pre>
</div>
<h4 id="5-3">5. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start kube</span>-<span style="color: rgba(0, 0, 0, 1)">proxy
systemctl enable kube</span>-proxy</pre>
</div>
<h3 id="55-cni">5.5 部署CNI网络</h3>
<p>先准备好CNI二进制文件:</p>
<p>下载地址:https://github.com/containernetworking/plugins/releases/download/v0.8.6/cni-plugins-linux-amd64-v0.8.6.tgz</p>
<p>解压二进制包并移动到默认工作目录:</p>
<div class="cnblogs_code">
<pre>mkdir /opt/cni/<span style="color: rgba(0, 0, 0, 1)">bin
tar zxvf cni</span>-plugins-linux-amd64-v0.<span style="color: rgba(128, 0, 128, 1)">8.6</span>.tgz -C /opt/cni/bin</pre>
</div>
<p>部署CNI网络:</p>
<div class="cnblogs_code">
<pre>wget https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml</span>
sed -i -r <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">s#quay.io/coreos/flannel:.*-amd64#lizhenliang/flannel:v0.12.0-amd64#g</span><span style="color: rgba(128, 0, 0, 1)">"</span> kube-flannel.yml</pre>
</div>
<p>默认镜像地址无法访问,修改为docker hub镜像仓库。</p>
<div class="cnblogs_code">
<pre>kubectl apply -f kube-<span style="color: rgba(0, 0, 0, 1)">flannel.yml
kubectl </span><span style="color: rgba(0, 0, 255, 1)">get</span> pods -n kube-<span style="color: rgba(0, 0, 0, 1)">system
NAME READY STATUS RESTARTS AGE
kube</span>-flannel-ds-amd64-2pc95 <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> 72s
kubectl </span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> node
NAME STATUS ROLES AGE VERSION
k8s</span>-master Ready <none> 41m v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span></pre>
</div>
<p>部署好网络插件,Node准备就绪。</p>
<h3 id="56-apiserverkubelet">5.6 授权apiserver访问kubelet</h3>
<div class="cnblogs_code">
<pre>cat > apiserver-to-kubelet-rbac.yaml <<<span style="color: rgba(0, 0, 0, 1)"> EOF
apiVersion: rbac.authorization.k8s.io</span>/<span style="color: rgba(0, 0, 0, 1)">v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io</span>/autoupdate: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
labels:
kubernetes.io</span>/bootstrapping: rbac-<span style="color: rgba(0, 0, 0, 1)">defaults
name: system:kube</span>-apiserver-to-<span style="color: rgba(0, 0, 0, 1)">kubelet
rules:
</span>-<span style="color: rgba(0, 0, 0, 1)"> apiGroups:
</span>- <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">
resources:
</span>- nodes/<span style="color: rgba(0, 0, 0, 1)">proxy
</span>- nodes/<span style="color: rgba(0, 0, 0, 1)">stats
</span>- nodes/<span style="color: rgba(0, 0, 0, 1)">log
</span>- nodes/<span style="color: rgba(0, 0, 0, 1)">spec
</span>- nodes/<span style="color: rgba(0, 0, 0, 1)">metrics
</span>- pods/<span style="color: rgba(0, 0, 0, 1)">log
verbs:
</span>- <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*</span><span style="color: rgba(128, 0, 0, 1)">"</span>
---<span style="color: rgba(0, 0, 0, 1)">
apiVersion: rbac.authorization.k8s.io</span>/<span style="color: rgba(0, 0, 0, 1)">v1
kind: ClusterRoleBinding
metadata:
name: system:kube</span>-<span style="color: rgba(0, 0, 0, 1)">apiserver
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span>: <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube</span>-apiserver-to-<span style="color: rgba(0, 0, 0, 1)">kubelet
subjects:
</span>-<span style="color: rgba(0, 0, 0, 1)"> apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes
EOF
kubectl apply </span>-f apiserver-to-kubelet-rbac.yaml</pre>
</div>
<h3 id="57-worker-node">5.7 新增加Worker Node</h3>
<h4 id="1-node">1. 拷贝已部署好的Node相关文件到新节点</h4>
<p>在Master节点将Worker Node涉及文件拷贝到新节点192.168.31.72/73</p>
<div class="cnblogs_code">
<pre>scp /opt/kubernetes root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.72</span>:/opt/<span style="color: rgba(0, 0, 0, 1)">
scp </span>-r /usr/lib/systemd/system/{kubelet,kube-proxy}.service root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.72</span>:/usr/lib/systemd/<span style="color: rgba(0, 0, 0, 1)">system
scp </span>-r /opt/cni/ root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.72</span>:/opt/<span style="color: rgba(0, 0, 0, 1)">
scp </span>/opt/kubernetes/ssl/ca.pem root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.72</span>:/opt/kubernetes/ssl</pre>
</div>
<h4 id="2-kubeletkubeconfig">2. 删除kubelet证书和kubeconfig文件</h4>
<div class="cnblogs_code">
<pre>rm /opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">kubelet.kubeconfig
rm </span>-f /opt/kubernetes/ssl/kubelet*</pre>
</div>
<blockquote>
<p>注:这几个文件是证书申请审批后自动生成的,每个Node不同,必须删除重新生成。</p>
</blockquote>
<h4 id="3-2">3. 修改主机名</h4>
<div class="cnblogs_code">
<pre>vi /opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">kubelet.conf
</span>--hostname-<span style="color: rgba(0, 0, 255, 1)">override</span>=k8s-<span style="color: rgba(0, 0, 0, 1)">node1
vi </span>/opt/kubernetes/cfg/kube-proxy-<span style="color: rgba(0, 0, 0, 1)">config.yml
hostnameOverride: k8s</span>-node1</pre>
</div>
<h4 id="4-2">4. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start kubelet
systemctl enable kubelet
systemctl start kube</span>-<span style="color: rgba(0, 0, 0, 1)">proxy
systemctl enable kube</span>-proxy</pre>
</div>
<h4 id="5-masternode-kubelet">5. 在Master上批准新Node kubelet证书申请</h4>
<div class="cnblogs_code">
<pre>kubectl <span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node</span>-csr-4zTjsaVSrhuyhIGqsefxzVoZDCNKei-aE2jyTP81Uro 89s kubernetes.io/kube-apiserver-client-kubelet kubelet-<span style="color: rgba(0, 0, 0, 1)">bootstrap Pending
kubectl certificate approve node</span>-csr-4zTjsaVSrhuyhIGqsefxzVoZDCNKei-aE2jyTP81Uro</pre>
</div>
<h4 id="6-node">6. 查看Node状态</h4>
<div class="cnblogs_code">
<pre>kubectl <span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> node
NAME STATUS ROLES AGE VERSION
k8s</span>-master Ready <none> 65m v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-node1 Ready <none> 12m v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-node2 Ready <none> 81s v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span></pre>
</div>
<p>Node2(192.168.31.73 )节点同上。记得修改主机名!</p>
<h2 id="dashboardcoredns">六、部署Dashboard和CoreDNS</h2>
<h3 id="61-dashboard">6.1 部署Dashboard</h3>
<div class="cnblogs_code">
<pre>$ wget https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml</span></pre>
</div>
<p>默认Dashboard只能集群内部访问,修改Service为NodePort类型,暴露到外部:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">vi recommended.yaml
kind: Service
apiVersion: v1
metadata:
labels:
k8s</span>-app: kubernetes-<span style="color: rgba(0, 0, 0, 1)">dashboard
name: kubernetes</span>-<span style="color: rgba(0, 0, 0, 1)">dashboard
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span>: kubernetes-<span style="color: rgba(0, 0, 0, 1)">dashboard
spec:
ports:
</span>- port: <span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)">
targetPort: </span><span style="color: rgba(128, 0, 128, 1)">8443</span><span style="color: rgba(0, 0, 0, 1)">
nodePort: </span><span style="color: rgba(128, 0, 128, 1)">30001</span><span style="color: rgba(0, 0, 0, 1)">
type: NodePort
selector:
k8s</span>-app: kubernetes-<span style="color: rgba(0, 0, 0, 1)">dashboard
kubectl apply </span>-f recommended.yaml</pre>
</div>
<div class="cnblogs_code">
<pre>kubectl <span style="color: rgba(0, 0, 255, 1)">get</span> pods,svc -n kubernetes-<span style="color: rgba(0, 0, 0, 1)">dashboard
NAME READY STATUS RESTARTS AGE
pod</span>/dashboard-metrics-scraper-694557449d-z8gfb <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> 2m18s
pod</span>/kubernetes-dashboard-9774cc786-q2gsx <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> 2m19s
NAME TYPE CLUSTER</span>-IP EXTERNAL-<span style="color: rgba(0, 0, 0, 1)">IP PORT(S) AGE
service</span>/dashboard-metrics-scraper ClusterIP <span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.141</span> <none> <span style="color: rgba(128, 0, 128, 1)">8000</span>/<span style="color: rgba(0, 0, 0, 1)">TCP 2m19s
service</span>/kubernetes-dashboard NodePort <span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.239</span> <none> <span style="color: rgba(128, 0, 128, 1)">443</span>:<span style="color: rgba(128, 0, 128, 1)">30001</span>/TCP 2m19s</pre>
</div>
<p>访问地址:https://NodeIP:30001</p>
<p>创建service account并绑定默认cluster-admin管理员集群角色:</p>
<div class="cnblogs_code">
<pre>kubectl create serviceaccount dashboard-admin -n kube-<span style="color: rgba(0, 0, 0, 1)">system
kubectl create clusterrolebinding dashboard</span>-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-<span style="color: rgba(0, 0, 0, 1)">admin
kubectl describe secrets </span>-n kube-system $(kubectl -n kube-system <span style="color: rgba(0, 0, 255, 1)">get</span> secret | awk <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/dashboard-admin/{print $1}</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
</div>
<p>使用输出的token登录Dashboard。</p>
<p><img src="https://img2020.cnblogs.com/blog/991704/202007/991704-20200721182237448-2025048402.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> <img src="https://img2020.cnblogs.com/blog/991704/202007/991704-20200721182245516-270140406.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> </p>
<h3 id="62-coredns">6.2 部署CoreDNS</h3>
<p>CoreDNS用于集群内部Service名称解析。</p>
<div class="cnblogs_code">
<pre>kubectl apply -<span style="color: rgba(0, 0, 0, 1)">f coredns.yaml
kubectl </span><span style="color: rgba(0, 0, 255, 1)">get</span> pods -n kube-<span style="color: rgba(0, 0, 0, 1)">system
NAME READY STATUS RESTARTS AGE
coredns</span>-5ffbfd976d-j6shb <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> 32s
kube</span>-flannel-ds-amd64-2pc95 <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> 38m
kube</span>-flannel-ds-amd64-7qhdx <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> 15m
kube</span>-flannel-ds-amd64-99cr8 <span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">1</span> Running <span style="color: rgba(128, 0, 128, 1)">0</span> 26m</pre>
</div>
<p>DNS解析测试:</p>
<div class="cnblogs_code">
<pre>kubectl run -it --rm dns-test --image=busybox:<span style="color: rgba(128, 0, 128, 1)">1.28</span>.<span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)"> sh
If you don</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">t see a command prompt, try pressing enter.</span>
/<span style="color: rgba(0, 0, 0, 1)"> # nslookup kubernetes
Server: </span><span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.2</span><span style="color: rgba(0, 0, 0, 1)">
Address </span><span style="color: rgba(128, 0, 128, 1)">1</span>: <span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.2</span> kube-dns.kube-<span style="color: rgba(0, 0, 0, 1)">system.svc.cluster.local
Name: kubernetes
Address </span><span style="color: rgba(128, 0, 128, 1)">1</span>: <span style="color: rgba(128, 0, 128, 1)">10.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span> kubernetes.<span style="color: rgba(0, 0, 255, 1)">default</span>.svc.cluster.local</pre>
</div>
<p>解析没问题。</p>
<h2 id="master">七、高可用架构(扩容多Master架构)</h2>
<p>Kubernetes作为容器集群系统,通过健康检查+重启策略实现了Pod故障自我修复能力,通过调度算法实现将Pod分布式部署,并保持预期副本数,根据Node失效状态自动在其他Node拉起Pod,实现了应用层的高可用性。</p>
<p>针对Kubernetes集群,高可用性还应包含以下两个层面的考虑:Etcd数据库的高可用性和Kubernetes Master组件的高可用性。 而Etcd我们已经采用3个节点组建集群实现高可用,本节将对Master节点高可用进行说明和实施。</p>
<p>Master节点扮演着总控中心的角色,通过不断与工作节点上的Kubelet和kube-proxy进行通信来维护整个集群的健康工作状态。如果Master节点故障,将无法使用kubectl工具或者API做任何集群管理。</p>
<p>Master节点主要有三个服务kube-apiserver、kube-controller-manager和kube-scheduler,其中kube-controller-manager和kube-scheduler组件自身通过选择机制已经实现了高可用,所以Master高可用主要针对kube-apiserver组件,而该组件是以HTTP API提供服务,因此对他高可用与Web服务器类似,增加负载均衡器对其负载均衡即可,并且可水平扩容。</p>
<p>多Master架构图:</p>
<p><img src="https://img2020.cnblogs.com/blog/991704/202007/991704-20200721182337381-1239926526.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> </p>
<h3 id="71-docker">7.1 安装Docker</h3>
<p>同上,不再赘述。</p>
<h3 id="72-master2-node1921683174">7.2 部署Master2 Node(192.168.31.74)</h3>
<p>Master2 与已部署的Master1所有操作一致。所以我们只需将Master1所有K8s文件拷贝过来,再修改下服务器IP和主机名启动即可。</p>
<h4 id="1-etcd">1. 创建etcd证书目录</h4>
<p>在Master2创建etcd证书目录:</p>
<div class="cnblogs_code">
<pre>mkdir -p /opt/etcd/ssl</pre>
</div>
<h4 id="2-master1">2. 拷贝文件(Master1操作)</h4>
<p>拷贝Master1上所有K8s文件和etcd证书到Master2:</p>
<div class="cnblogs_code">
<pre>scp -r /opt/kubernetes root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span>:/<span style="color: rgba(0, 0, 0, 1)">opt
scp </span>-r /opt/cni/ root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span>:/<span style="color: rgba(0, 0, 0, 1)">opt
scp </span>-r /opt/etcd/ssl root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span>:/opt/<span style="color: rgba(0, 0, 0, 1)">etcd
scp </span>/usr/lib/systemd/system/kube* root@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span>:/usr/lib/systemd/<span style="color: rgba(0, 0, 0, 1)">system
scp </span>/usr/bin/kubectlroot@<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span>:/usr/bin</pre>
</div>
<h4 id="3-3">3. 删除证书文件</h4>
<p>删除kubelet证书和kubeconfig文件:</p>
<div class="cnblogs_code">
<pre>rm -f /opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">kubelet.kubeconfig
rm </span>-f /opt/kubernetes/ssl/kubelet*</pre>
</div>
<h4 id="4-ip">4. 修改配置文件IP和主机名</h4>
<p>修改apiserver、kubelet和kube-proxy配置文件为本地IP:</p>
<div class="cnblogs_code">
<pre>vi /opt/kubernetes/cfg/kube-<span style="color: rgba(0, 0, 0, 1)">apiserver.conf
...
</span>--bind-address=<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span><span style="color: rgba(0, 0, 0, 1)"> \
</span>--advertise-address=<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span><span style="color: rgba(0, 0, 0, 1)"> \
...
vi </span>/opt/kubernetes/cfg/<span style="color: rgba(0, 0, 0, 1)">kubelet.conf
</span>--hostname-<span style="color: rgba(0, 0, 255, 1)">override</span>=k8s-<span style="color: rgba(0, 0, 0, 1)">master2
vi </span>/opt/kubernetes/cfg/kube-proxy-<span style="color: rgba(0, 0, 0, 1)">config.yml
hostnameOverride: k8s</span>-master2</pre>
</div>
<h4 id="5-4">5. 启动设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start kube</span>-<span style="color: rgba(0, 0, 0, 1)">apiserver
systemctl start kube</span>-controller-<span style="color: rgba(0, 0, 0, 1)">manager
systemctl start kube</span>-<span style="color: rgba(0, 0, 0, 1)">scheduler
systemctl start kubelet
systemctl start kube</span>-<span style="color: rgba(0, 0, 0, 1)">proxy
systemctl enable kube</span>-<span style="color: rgba(0, 0, 0, 1)">apiserver
systemctl enable kube</span>-controller-<span style="color: rgba(0, 0, 0, 1)">manager
systemctl enable kube</span>-<span style="color: rgba(0, 0, 0, 1)">scheduler
systemctl enable kubelet
systemctl enable kube</span>-proxy</pre>
</div>
<h4 id="6-">6. 查看集群状态</h4>
<div class="cnblogs_code">
<pre>kubectl <span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller</span>-<span style="color: rgba(0, 0, 0, 1)">manager Healthy ok
etcd</span>-<span style="color: rgba(128, 0, 128, 1)">1</span> Healthy {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">health</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}
etcd</span>-<span style="color: rgba(128, 0, 128, 1)">2</span> Healthy {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">health</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">}
etcd</span>-<span style="color: rgba(128, 0, 128, 1)">0</span> Healthy {<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">health</span><span style="color: rgba(128, 0, 0, 1)">"</span>:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span>}</pre>
</div>
<h4 id="7-kubelet">7. 批准kubelet证书申请</h4>
<div class="cnblogs_code">
<pre>kubectl <span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node</span>-csr-JYNknakEa_YpHz797oKaN-ZTk43nD51Zc9CJkBLcASU 85m kubernetes.io/kube-apiserver-client-kubelet kubelet-<span style="color: rgba(0, 0, 0, 1)">bootstrap Pending
kubectl certificate approve node</span>-csr-JYNknakEa_YpHz797oKaN-<span style="color: rgba(0, 0, 0, 1)">ZTk43nD51Zc9CJkBLcASU
kubectl </span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> node
NAME STATUS ROLES AGE VERSION
k8s</span>-master Ready <none> 34h v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-master2 Ready <none> 83m v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-node1 Ready <none> 33h v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-node2 Ready <none> 33h v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span></pre>
</div>
<blockquote>
<p>如果你在学习中遇到问题或者文档有误可联系阿良~ 微信: init1024</p>
</blockquote>
<h3 id="73-nginx">7.3 部署Nginx负载均衡器</h3>
<p>kube-apiserver高可用架构图:</p>
<p><img src="https://img2020.cnblogs.com/blog/991704/202007/991704-20200721182612816-1202135604.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<ul>
<li>Nginx是一个主流Web服务和反向代理服务器,这里用四层实现对apiserver实现负载均衡。</li>
<li>Keepalived是一个主流高可用软件,基于VIP绑定实现服务器双机热备,在上述拓扑中,Keepalived主要根据Nginx运行状态判断是否需要故障转移(偏移VIP),例如当Nginx主节点挂掉,VIP会自动绑定在Nginx备节点,从而保证VIP一直可用,实现Nginx高可用。</li>
</ul>
<h4 id="1-6">1. 安装软件包(主/备)</h4>
<div class="cnblogs_code">
<pre>yum install epel-release -<span style="color: rgba(0, 0, 0, 1)">y
yum install nginx keepalived </span>-y</pre>
</div>
<h4 id="2-nginx">2. Nginx配置文件(主/备一样)</h4>
<div class="cnblogs_code">
<pre>cat > /etc/nginx/nginx.conf << <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EOF</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
user nginx;
worker_processes auto;
error_log </span>/<span style="color: rgba(0, 0, 255, 1)">var</span>/log/nginx/<span style="color: rgba(0, 0, 0, 1)">error.log;
pid </span>/run/<span style="color: rgba(0, 0, 0, 1)">nginx.pid;
include </span>/usr/share/nginx/modules<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">.conf;
events {
worker_connections 1024;
}
# 四层负载均衡,为两台Master apiserver组件提供负载均衡
stream {
log_formatmain'$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
access_log/var/log/nginx/k8s-access.logmain;
upstream k8s-apiserver {
server 192.168.31.71:6443; # Master1 APISERVER IP:PORT
server 192.168.31.74:6443; # Master2 APISERVER IP:PORT
}
server {
listen 6443;
proxy_pass k8s-apiserver;
}
}
http {
log_formatmain'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log/var/log/nginx/access.logmain;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80 default_server;
server_name_;
location / {
}
}
}
EOF</span></pre>
</div>
<h4 id="3-keepalivednginx-master">3. keepalived配置文件(Nginx Master)</h4>
<div class="cnblogs_code">
<pre>cat > /etc/keepalived/keepalived.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server </span><span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span><span style="color: rgba(0, 0, 0, 1)">
smtp_connect_timeout </span><span style="color: rgba(128, 0, 128, 1)">30</span><span style="color: rgba(0, 0, 0, 1)">
router_id NGINX_MASTER
}
vrrp_script check_nginx {
script </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/etc/keepalived/check_nginx.sh</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
vrrp_instance VI_1 {
state MASTER
</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> ens33
virtual_router_id </span><span style="color: rgba(128, 0, 128, 1)">51</span><span style="color: rgba(0, 0, 0, 1)"> # VRRP 路由 ID实例,每个实例是唯一的
priority </span><span style="color: rgba(128, 0, 128, 1)">100</span> # 优先级,备服务器设置 <span style="color: rgba(128, 0, 128, 1)">90</span><span style="color: rgba(0, 0, 0, 1)">
advert_int </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)"> # 指定VRRP 心跳包通告间隔时间,默认1秒
authentication {
auth_type PASS
auth_pass </span><span style="color: rgba(128, 0, 128, 1)">1111</span><span style="color: rgba(0, 0, 0, 1)">
}
# 虚拟IP
virtual_ipaddress {
</span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.88</span>/<span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)">
}
track_script {
check_nginx
}
}
EOF</span></pre>
</div>
<ul>
<li>
<p>vrrp_script:指定检查nginx工作状态脚本(根据nginx状态判断是否故障转移)</p>
</li>
<li>
<p>virtual_ipaddress:虚拟IP(VIP)</p>
</li>
</ul>
<p>检查nginx状态脚本:</p>
<div class="cnblogs_code">
<pre>cat > /etc/keepalived/check_nginx.sh<< <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EOF</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
#</span>!/bin/<span style="color: rgba(0, 0, 0, 1)">bash
count</span>=$(ps -ef |grep nginx |egrep -cv <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">grep|$$</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">$count</span><span style="color: rgba(128, 0, 0, 1)">"</span> -eq <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> ];then
exit </span><span style="color: rgba(128, 0, 128, 1)">1</span>
<span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
exit </span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
fi
EOF
chmod </span>+x /etc/keepalived/check_nginx.sh</pre>
</div>
<h4 id="4-keepalivednginx-backup">4. keepalived配置文件(Nginx Backup)</h4>
<div class="cnblogs_code">
<pre>cat > /etc/keepalived/keepalived.conf <<<span style="color: rgba(0, 0, 0, 1)"> EOF
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server </span><span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span><span style="color: rgba(0, 0, 0, 1)">
smtp_connect_timeout </span><span style="color: rgba(128, 0, 128, 1)">30</span><span style="color: rgba(0, 0, 0, 1)">
router_id NGINX_BACKUP
}
vrrp_script check_nginx {
script </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/etc/keepalived/check_nginx.sh</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}
vrrp_instance VI_1 {
state BACKUP
</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> ens33
virtual_router_id </span><span style="color: rgba(128, 0, 128, 1)">51</span><span style="color: rgba(0, 0, 0, 1)"> # VRRP 路由 ID实例,每个实例是唯一的
priority </span><span style="color: rgba(128, 0, 128, 1)">90</span><span style="color: rgba(0, 0, 0, 1)">
advert_int </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
authentication {
auth_type PASS
auth_pass </span><span style="color: rgba(128, 0, 128, 1)">1111</span><span style="color: rgba(0, 0, 0, 1)">
}
virtual_ipaddress {
</span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.88</span>/<span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)">
}
track_script {
check_nginx
}
}
EOF</span></pre>
</div>
<p>上述配置文件中检查nginx运行状态脚本:</p>
<div class="cnblogs_code">
<pre>cat > /etc/keepalived/check_nginx.sh<< <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">EOF</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
#</span>!/bin/<span style="color: rgba(0, 0, 0, 1)">bash
count</span>=$(ps -ef |grep nginx |egrep -cv <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">grep|$$</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> [ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">$count</span><span style="color: rgba(128, 0, 0, 1)">"</span> -eq <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> ];then
exit </span><span style="color: rgba(128, 0, 128, 1)">1</span>
<span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
exit </span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
fi
EOF
chmod </span>+x /etc/keepalived/check_nginx.sh</pre>
</div>
<blockquote>
<p>注:keepalived根据脚本返回状态码(0为工作正常,非0不正常)判断是否故障转移。</p>
</blockquote>
<h4 id="5-5">5. 启动并设置开机启动</h4>
<div class="cnblogs_code">
<pre>systemctl daemon-<span style="color: rgba(0, 0, 0, 1)">reload
systemctl start nginx
systemctl start keepalived
systemctl enable nginx
systemctl enable keepalived</span></pre>
</div>
<h4 id="6-keepalived">6. 查看keepalived工作状态</h4>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">ip a
</span><span style="color: rgba(128, 0, 128, 1)">1</span>: lo: <LOOPBACK,UP,LOWER_UP> mtu <span style="color: rgba(128, 0, 128, 1)">65536</span> qdisc noqueue state UNKNOWN group <span style="color: rgba(0, 0, 255, 1)">default</span> qlen <span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">
link</span>/loopback <span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span> brd <span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span>:<span style="color: rgba(128, 0, 128, 1)">00</span><span style="color: rgba(0, 0, 0, 1)">
inet </span><span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>/<span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)"> scope host lo
valid_lft forever preferred_lft forever
inet6 ::</span><span style="color: rgba(128, 0, 128, 1)">1</span>/<span style="color: rgba(128, 0, 128, 1)">128</span><span style="color: rgba(0, 0, 0, 1)"> scope host
valid_lft forever preferred_lft forever
</span><span style="color: rgba(128, 0, 128, 1)">2</span>: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu <span style="color: rgba(128, 0, 128, 1)">1500</span> qdisc pfifo_fast state UP group <span style="color: rgba(0, 0, 255, 1)">default</span> qlen <span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">
link</span>/ether <span style="color: rgba(128, 0, 128, 1)">00</span>:0c:<span style="color: rgba(128, 0, 128, 1)">29</span>:<span style="color: rgba(128, 0, 128, 1)">04</span><span style="color: rgba(0, 0, 0, 1)">:f7:2c brd ff:ff:ff:ff:ff:ff
inet </span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.80</span>/<span style="color: rgba(128, 0, 128, 1)">24</span> brd <span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.255</span> scope <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)"> noprefixroute ens33
valid_lft forever preferred_lft forever
inet </span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.88</span>/<span style="color: rgba(128, 0, 128, 1)">24</span> scope <span style="color: rgba(0, 0, 255, 1)">global</span><span style="color: rgba(0, 0, 0, 1)"> secondary ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe04:f72c</span>/<span style="color: rgba(128, 0, 128, 1)">64</span><span style="color: rgba(0, 0, 0, 1)"> scope link
valid_lft forever preferred_lft forever</span></pre>
</div>
<p>可以看到,在ens33网卡绑定了192.168.31.88 虚拟IP,说明工作正常。</p>
<h4 id="7-nginxkeepalived">7. Nginx+Keepalived高可用测试</h4>
<p>关闭主节点Nginx,测试VIP是否漂移到备节点服务器。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">在Nginx Master执行 pkill nginx
在Nginx Backup,ip addr命令查看已成功绑定VIP。</span></pre>
</div>
<h4 id="8-">8. 访问负载均衡器测试</h4>
<p>找K8s集群中任意一个节点,使用curl查看K8s版本测试,使用VIP访问:</p>
<div class="cnblogs_code">
<pre>curl -k https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">192.168.31.88:6443/version</span>
<span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">major</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">minor</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">18</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gitVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">v1.18.3</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gitCommit</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2e7996e3e2712684bc73f0dec0200d64eec7fe40</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gitTreeState</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">clean</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">buildDate</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2020-05-20T12:43:34Z</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">goVersion</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">go1.13.9</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">compiler</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">gc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">platform</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">linux/amd64</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>可以正确获取到K8s版本信息,说明负载均衡器搭建正常。该请求数据流程:curl -> vip(nginx) -> apiserver</p>
<p>通过查看Nginx日志也可以看到转发apiserver IP:</p>
<div class="cnblogs_code">
<pre>tail /<span style="color: rgba(0, 0, 255, 1)">var</span>/log/nginx/k8s-access.log -<span style="color: rgba(0, 0, 0, 1)">f
</span><span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.81</span> <span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.71</span>:<span style="color: rgba(128, 0, 128, 1)">6443</span> - [<span style="color: rgba(128, 0, 128, 1)">30</span>/May/<span style="color: rgba(128, 0, 128, 1)">2020</span>:<span style="color: rgba(128, 0, 128, 1)">11</span>:<span style="color: rgba(128, 0, 128, 1)">15</span>:<span style="color: rgba(128, 0, 128, 1)">10</span> +<span style="color: rgba(128, 0, 128, 1)">0800</span>] <span style="color: rgba(128, 0, 128, 1)">200</span> <span style="color: rgba(128, 0, 128, 1)">422</span>
<span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.81</span> <span style="color: rgba(128, 0, 128, 1)">192.168</span>.<span style="color: rgba(128, 0, 128, 1)">31.74</span>:<span style="color: rgba(128, 0, 128, 1)">6443</span> - [<span style="color: rgba(128, 0, 128, 1)">30</span>/May/<span style="color: rgba(128, 0, 128, 1)">2020</span>:<span style="color: rgba(128, 0, 128, 1)">11</span>:<span style="color: rgba(128, 0, 128, 1)">15</span>:<span style="color: rgba(128, 0, 128, 1)">26</span> +<span style="color: rgba(128, 0, 128, 1)">0800</span>] <span style="color: rgba(128, 0, 128, 1)">200</span> <span style="color: rgba(128, 0, 128, 1)">422</span></pre>
</div>
<p>到此还没结束,还有下面最关键的一步。</p>
<h3 id="74-worker-nodelb-vip">7.4 修改所有Worker Node连接LB VIP</h3>
<p>试想下,虽然我们增加了Master2和负载均衡器,但是我们是从单Master架构扩容的,也就是说目前所有的Node组件连接都还是Master1,如果不改为连接VIP走负载均衡器,那么Master还是单点故障。</p>
<p>因此接下来就是要改所有Node组件配置文件,由原来192.168.31.71修改为192.168.31.88(VIP):</p>
<table>
<thead>
<tr><th><strong>角色</strong></th><th><strong>IP</strong></th></tr>
</thead>
<tbody>
<tr>
<td>k8s-master1</td>
<td>192.168.31.71</td>
</tr>
<tr>
<td>k8s-master2</td>
<td>192.168.31.74</td>
</tr>
<tr>
<td>k8s-node1</td>
<td>192.168.31.72</td>
</tr>
<tr>
<td>k8s-node2</td>
<td>192.168.31.73</td>
</tr>
</tbody>
</table>
<p>也就是通过kubectl get node命令查看到的节点。</p>
<p>在上述所有Worker Node执行:</p>
<div class="cnblogs_code">
<pre>sed -i <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">s#192.168.31.71:6443#192.168.31.88:6443#</span><span style="color: rgba(128, 0, 0, 1)">'</span> /opt/kubernetes/cfg<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
systemctl restart kubelet
systemctl restart kube-proxy</span></pre>
</div>
<p>检查节点状态:</p>
<div class="cnblogs_code">
<pre>kubectl <span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)"> node
NAME STATUS ROLES AGE VERSION
k8s</span>-master Ready <none> 34h v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-master2 Ready <none> 101m v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-node1 Ready <none> 33h v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span><span style="color: rgba(0, 0, 0, 1)">
k8s</span>-node2 Ready <none> 33h v1.<span style="color: rgba(128, 0, 128, 1)">18.3</span></pre>
</div>
<p>至此,一套完整的 Kubernetes 高可用集群就部署完成了!</p>
<p>PS:如果你是在公有云上,一般都不支持keepalived,那么你可以直接用它们的负载均衡器产品(内网就行,还免费~),架构与上面一样,直接负载均衡多台Master kube-apiserver即可!</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<div>作者:一个大西瓜</div>
<div>出处:https://www.cnblogs.com/wyt007/
</div>
<p>-------------------------------------------</p>
<p>个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!</p>
<p>如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个<span>“推荐”</span>哦,博主在此感谢!</p>
<p></p>
<p>万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!</p>
<div align="left">
<img src="https://www.cnblogs.com/images/cnblogs_com/wyt007/1375409/t_alipay.bmp">
<img src="https://www.cnblogs.com/images/cnblogs_com/wyt007/1375409/t_wxpay.bmp">
</div><br><br>
来源:https://www.cnblogs.com/wyt007/p/13356734.html
頁:
[1]