肥彭 發表於 2023-8-16 01:39:00

Ubuntu 安装部署Kubernetes(k8s)集群

<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>一.系统环境</li><li>二.前言</li><li>三.Kubernetes<ul><li>3.1 概述</li><li>3.2 Kubernetes 组件<ul><li>3.2.1 控制平面组件</li><li>3.2.2 Node组件</li></ul></li></ul></li><li>四.配置节点的基本环境</li><li>五.节点安装docker,并进行相关配置</li><li>六.安装kubelet,kubeadm,kubectl</li><li>七.kubeadm初始化</li><li>八.添加worker节点到k8s集群</li><li>九.部署CNI网络插件calico</li><li>十.配置kubectl命令tab键自动补全</li><li>十一.总结</li></ul></div><p></p>
<h1 id="一系统环境">一.系统环境</h1>
<p>本文主要基于Kubernetes1.22.2和Linux操作系统Ubuntu 18.04。</p>
<table>
<thead>
<tr>
<th>服务器版本</th>
<th>docker软件版本</th>
<th>Kubernetes(k8s)集群版本</th>
<th>CPU架构</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ubuntu 18.04.5 LTS</td>
<td>Docker version 20.10.14</td>
<td>v1.22.2</td>
<td>x86_64</td>
</tr>
</tbody>
</table>
<p>Kubernetes集群架构:k8scludes1作为master节点,k8scludes2,k8scludes3作为worker节点。</p>
<table>
<thead>
<tr>
<th>服务器</th>
<th>操作系统版本</th>
<th>CPU架构</th>
<th>进程</th>
<th>功能描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>k8scludes1/192.168.110.128</td>
<td>Ubuntu 18.04.5 LTS</td>
<td>x86_64</td>
<td>docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico</td>
<td>k8s master节点</td>
</tr>
<tr>
<td>k8scludes2/192.168.110.129</td>
<td>Ubuntu 18.04.5 LTS</td>
<td>x86_64</td>
<td>docker,kubelet,kube-proxy,calico</td>
<td>k8s worker节点</td>
</tr>
<tr>
<td>k8scludes3/192.168.110.130</td>
<td>Ubuntu 18.04.5 LTS</td>
<td>x86_64</td>
<td>docker,kubelet,kube-proxy,calico</td>
<td>k8s worker节点</td>
</tr>
</tbody>
</table>
<h1 id="二前言">二.前言</h1>
<p>下图描述了软件部署方式的变迁:<strong>传统部署时代</strong>,<strong>虚拟化部署时代</strong>,<strong>容器部署时代</strong>。</p>
<p><img src="https://typorablogimage.oss-cn-hangzhou.aliyuncs.com/image-20220909014039574.png"></p>
<p><strong>传统部署时代</strong>:</p>
<p>早期,各个组织是在物理服务器上运行应用程序。 由于无法限制在物理服务器中运行的应用程序资源使用,因此会导致资源分配问题。 例如,如果在同一台物理服务器上运行多个应用程序, 则可能会出现一个应用程序占用大部分资源的情况,而导致其他应用程序的性能下降。 一种解决方案是将每个应用程序都运行在不同的物理服务器上, 但是当某个应用程式资源利用率不高时,剩余资源无法被分配给其他应用程式, 而且维护许多物理服务器的成本很高。</p>
<p><strong>虚拟化部署时代</strong>:</p>
<p>因此,虚拟化技术被引入了。虚拟化技术允许你在单个物理服务器的 CPU 上运行多台虚拟机(VM)。 虚拟化能使应用程序在不同 VM 之间被彼此隔离,且能提供一定程度的安全性, 因为一个应用程序的信息不能被另一应用程序随意访问。</p>
<p>虚拟化技术能够更好地利用物理服务器的资源,并且因为可轻松地添加或更新应用程序, 而因此可以具有更高的可扩缩性,以及降低硬件成本等等的好处。 通过虚拟化,你可以将一组物理资源呈现为可丢弃的虚拟机集群。</p>
<p>每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。</p>
<p><strong>容器部署时代</strong>:</p>
<p>容器类似于 VM,但是更宽松的隔离特性,使容器之间可以共享操作系统(OS)。 因此,容器比起 VM 被认为是更轻量级的。且与 VM 类似,每个容器都具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植。</p>
<p>容器因具有许多优势而变得流行起来,例如:</p>
<ul>
<li>敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。</li>
<li>持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性), 提供可靠且频繁的容器镜像构建和部署。</li>
<li>关注开发与运维的分离:在构建、发布时创建应用程序容器镜像,而不是在部署时, 从而将应用程序与基础架构分离。</li>
<li>可观察性:不仅可以显示 OS 级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。</li>
<li>跨开发、测试和生产的环境一致性:在笔记本计算机上也可以和在云中运行一样的应用程序。</li>
<li>跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。</li>
<li>以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。</li>
<li>松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。</li>
<li>资源隔离:可预测的应用程序性能。</li>
<li>资源利用:高效率和高密度。</li>
</ul>
<p>在这篇博客中,我们将详细介绍如何在Ubuntu 18.04上安装和部署Kubernetes 1.22.2集群。我们将使用kubeadm工具,这是Kubernetes官方推荐的用于快速部署Kubernetes集群的工具。</p>
<p>如果您的平台在Centos系统上,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Centos7 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/16686769.html。</p>
<p>如果您对Ubuntu系统不熟悉,Ubuntu系统的详细操作,请查看博客《centos系统和Ubuntu系统命令区别以及常见操作》。</p>
<h1 id="三kubernetes">三.Kubernetes</h1>
<h2 id="31-概述">3.1 概述</h2>
<p>Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态,其服务、支持和工具的使用范围相当广泛。</p>
<p>Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系。 Google 在 2014 年开源了 Kubernetes 项目。 Kubernetes 建立在 Google 大规模运行生产工作负载十几年经验的基础上, 结合了社区中最优秀的想法和实践。</p>
<p>Kubernetes 为你提供的功能如下:</p>
<ol>
<li><strong>服务发现和负载均衡</strong>:Kubernetes 可以使用 DNS 名称或自己的 IP 地址来曝露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。</li>
<li><strong>存储编排</strong>:Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。</li>
<li><strong>自动部署和回滚</strong>:你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。</li>
<li><strong>自动完成装箱计算</strong>:你为 Kubernetes 提供许多节点组成的集群,在这个集群上运行容器化的任务。 你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。 Kubernetes 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。</li>
<li><strong>自我修复</strong>:Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。</li>
<li><strong>密钥与配置管理</strong>:Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。</li>
</ol>
<h2 id="32-kubernetes-组件">3.2 Kubernetes 组件</h2>
<p>Kubernetes 集群架构如下:</p>
<img src="https://typorablogimage.oss-cn-hangzhou.aliyuncs.com/image-20220911185505198.png">
<p>Kubernetes 集群组件如下:</p>
<p><img src="https://typorablogimage.oss-cn-hangzhou.aliyuncs.com/image-20220909015606030.png"></p>
<p><strong>Kubernetes有两种节点类型:master节点,worker节点</strong>。master节点又称为控制平面(Control Plane)。控制平面有很多组件,控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足部署的 replicas 字段时, 要启动新的 pod)。</p>
<p>控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。</p>
<h3 id="321-控制平面组件">3.2.1 控制平面组件</h3>
<p><strong>控制平面组件如下</strong>:</p>
<ol>
<li><strong>kube-apiserver</strong>:API 服务器是 Kubernetes 控制平面的组件, 该组件负责公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。<br>
Kubernetes API 服务器的主要实现是 kube-apiserver。 kube-apiserver 设计上考虑了水平扩缩,也就是说,它可通过部署多个实例来进行扩缩。 你可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量。</li>
<li><strong>etcd</strong>:etcd 是兼顾一致性与高可用性的键值对数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。你的 Kubernetes 集群的 etcd 数据库通常需要有个备份计划。</li>
<li><strong>kube-scheduler</strong>:kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。调度决策考虑的因素包括单个 Pod 及 Pods 集合的资源需求、软硬件及策略约束、 亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。</li>
<li><strong>kube-controller-manager</strong>:kube-controller-manager 是控制平面的组件, 负责运行控制器进程。从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。<br>
这些控制器包括:<br>
节点控制器(Node Controller):负责在节点出现故障时进行通知和响应<br>
任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成<br>
端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入 Service 与 Pod)<br>
服务帐户和令牌控制器(Service Account &amp; Token Controllers):为新的命名空间创建默认帐户和 API 访问令牌</li>
<li><strong>cloud-controller-manager</strong>:一个 Kubernetes 控制平面组件, 嵌入了特定于云平台的控制逻辑。 云控制器管理器(Cloud Controller Manager)允许你将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。cloud-controller-manager 仅运行特定于云平台的控制器。 因此如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部署的集群不需要有云控制器管理器。<br>
与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的控制回路组合到同一个可执行文件中, 供你以同一进程的方式运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。<br>
下面的控制器都包含对云平台驱动的依赖:<br>
节点控制器(Node Controller):用于在节点终止响应后检查云提供商以确定节点是否已被删除<br>
路由控制器(Route Controller):用于在底层云基础架构中设置路由<br>
服务控制器(Service Controller):用于创建、更新和删除云提供商负载均衡器</li>
</ol>
<h3 id="322-node组件">3.2.2 Node组件</h3>
<p>节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。</p>
<p><strong>node组件如下</strong>:</p>
<ol>
<li>kubelet:kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。kubelet 接收一组通过各类机制提供给它的 PodSpecs, 确保这些 PodSpecs 中描述的容器处于运行状态且健康。 kubelet 不会管理不是由 Kubernetes 创建的容器。</li>
<li>kube-proxy:kube-proxy 是集群中每个节点(node)所上运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。</li>
</ol>
<h1 id="四配置节点的基本环境">四.配置节点的基本环境</h1>
<p>先配置节点的基本环境,3个节点都要同时设置,在此以k8scludes1作为示例。</p>
<p>查看Ubuntu系统版本。</p>
<pre><code class="language-shell">root@localhost:~# lsb_release -a
No LSB modules are available.
Distributor ID:        Ubuntu
Description:        Ubuntu 18.04.5 LTS
Release:        18.04
Codename:        bionic
</code></pre>
<p>首先设置主机名。</p>
<pre><code class="language-shell">root@localhost:~# vim /etc/hostname

root@localhost:~# cat /etc/hostname
k8scludes1
</code></pre>
<p>配置节点静态IP地址(可选)。</p>
<pre><code class="language-yaml">root@localhost:~# vim /etc/netplan/01-netcfg.yaml

root@localhost:~# cat /etc/netplan/01-netcfg.yaml
network:
version: 2
renderer: networkd
ethernets:
    ens32:
      dhcp4: no
      addresses:
      gateway4: 192.168.110.2
      nameservers:
      addresses:
</code></pre>
<p>使配置生效。</p>
<pre><code class="language-shell">root@localhost:~# netplan apply
</code></pre>
<p>测试机器是否可以访问网络。</p>
<pre><code class="language-shell">root@localhost:~# ping www.baidu.com
PING www.baidu.com (14.215.177.39) 56(84) bytes of data.
64 bytes from www.baidu.com (14.215.177.39): icmp_seq=1 ttl=128 time=48.0 ms
64 bytes from www.baidu.com (14.215.177.39): icmp_seq=2 ttl=128 time=52.9 ms
64 bytes from www.baidu.com (14.215.177.39): icmp_seq=3 ttl=128 time=39.8 ms
^C
--- www.baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2009ms
rtt min/avg/max/mdev = 39.843/46.940/52.968/5.417 ms
</code></pre>
<p>配置IP地址和主机名映射。</p>
<pre><code class="language-shell">root@localhost:~# ifconfig
ens32: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;mtu 1500
      inet 192.168.110.128netmask 255.255.255.0broadcast 192.168.110.255
      inet6 fe80::20c:29ff:fe92:3462prefixlen 64scopeid 0x20&lt;link&gt;
      ether 00:0c:29:92:34:62txqueuelen 1000(Ethernet)
      RX packets 3600bytes 909889 (909.8 KB)
      RX errors 0dropped 0overruns 0frame 0
      TX packets 2327bytes 225443 (225.4 KB)
      TX errors 0dropped 0 overruns 0carrier 0collisions 0

lo: flags=73&lt;UP,LOOPBACK,RUNNING&gt;mtu 65536
      inet 127.0.0.1netmask 255.0.0.0
      inet6 ::1prefixlen 128scopeid 0x10&lt;host&gt;
      looptxqueuelen 1000(Local Loopback)
      RX packets 54bytes 6421 (6.4 KB)
      RX errors 0dropped 0overruns 0frame 0
      TX packets 54bytes 6421 (6.4 KB)
      TX errors 0dropped 0 overruns 0carrier 0collisions 0

root@localhost:~# vim /etc/hosts

root@localhost:~# cat /etc/hosts
127.0.0.1        localhost
127.0.1.1        tom
192.168.110.128 k8scludes1
192.168.110.129 k8scludes2
192.168.110.130 k8scludes3

# The following lines are desirable for IPv6 capable hosts
::1   localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
</code></pre>
<p>重启机器之后,主机名变为k8scludes1,另外两台机器也进行相同操作。</p>
<p>k8scludes1可以ping通其他两个节点则成功。</p>
<pre><code class="language-shell">root@k8scludes1:~# ping k8scludes1
PING k8scludes1 (192.168.110.128) 56(84) bytes of data.
64 bytes from k8scludes1 (192.168.110.128): icmp_seq=1 ttl=64 time=0.014 ms
64 bytes from k8scludes1 (192.168.110.128): icmp_seq=2 ttl=64 time=0.040 ms
64 bytes from k8scludes1 (192.168.110.128): icmp_seq=3 ttl=64 time=0.058 ms
^C
--- k8scludes1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2048ms
rtt min/avg/max/mdev = 0.014/0.037/0.058/0.018 ms

root@k8scludes1:~# ping k8scludes2
PING k8scludes2 (192.168.110.129) 56(84) bytes of data.
64 bytes from k8scludes2 (192.168.110.129): icmp_seq=1 ttl=64 time=0.465 ms
64 bytes from k8scludes2 (192.168.110.129): icmp_seq=2 ttl=64 time=2.98 ms
64 bytes from k8scludes2 (192.168.110.129): icmp_seq=3 ttl=64 time=2.34 ms
^C
--- k8scludes2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2048ms
rtt min/avg/max/mdev = 0.465/1.932/2.983/1.069 ms

root@k8scludes1:~# ping k8scludes3
PING k8scludes3 (192.168.110.130) 56(84) bytes of data.
64 bytes from k8scludes3 (192.168.110.130): icmp_seq=1 ttl=64 time=0.450 ms
64 bytes from k8scludes3 (192.168.110.130): icmp_seq=2 ttl=64 time=3.71 ms
^C
--- k8scludes3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1022ms
rtt min/avg/max/mdev = 0.450/2.083/3.717/1.634 ms
</code></pre>
<p>配置Ubuntu软件源,软件源如下,最后三行是k8s源。</p>
<pre><code class="language-shell">root@localhost:~# cat /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
deb https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable
# deb-src https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable
</code></pre>
<p>apt-key.gpg是k8s的deb源公钥,加载k8s的deb源公钥命令为:apt-key add apt-key.gpg,下载并加载k8s的deb源公钥命令为:curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - ; apt-get update,但是谷歌的网址访问不了,我们直接去网上下载apt-key.gpg文件。</p>
<pre><code class="language-shell">#apt-key.gpg文件下载好了
root@localhost:~# ls
apt-key.gpg
</code></pre>
<p>加载k8s的deb源公钥。</p>
<pre><code class="language-shell">root@localhost:~# cat apt-key.gpg | apt-key add -
OK
</code></pre>
<p>更新软件源。</p>
<pre><code class="language-shell">root@localhost:~# apt-get update
Hit:1 http://mirrors.aliyun.com/ubuntu bionic InRelease
Hit:2 http://mirrors.aliyun.com/ubuntu bionic-security InRelease                                                                     
Hit:3 http://mirrors.aliyun.com/ubuntu bionic-updates InRelease                                                                     
Get:4 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial InRelease                   
Hit:5 http://mirrors.aliyun.com/ubuntu bionic-proposed InRelease                                       
Hit:6 http://mirrors.aliyun.com/ubuntu bionic-backports InRelease                                                                     
Hit:7 https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic InRelease   
Ign:8 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
Get:8 https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
Fetched 54.7 kB in 2s (33.3 kB/s)
Reading package lists... Done
</code></pre>
<p>关闭防火墙。</p>
<pre><code class="language-shell">root@k8scludes1:~# ufw disable
Firewall stopped and disabled on system startup
</code></pre>
<p>Linux swapoff命令用于关闭系统交换分区(swap area)。</p>
<p><strong>注意</strong>:如果不关闭swap,就会在kubeadm初始化Kubernetes的时候报错:“: running with swap on is not supported. Please disable swap”。</p>
<pre><code class="language-shell">root@k8scludes1:~# swapoff -a ;sed -i '/swap/d' /etc/fstab

root@k8scludes1:~# cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# &lt;file system&gt; &lt;mount point&gt;   &lt;type&gt;&lt;options&gt;       &lt;dump&gt;&lt;pass&gt;
/dev/mapper/tom--vg-root /               ext4    errors=remount-ro 0       1
</code></pre>
<p>此时基本环境就配置完毕了。</p>
<h1 id="五节点安装docker并进行相关配置">五.节点安装docker,并进行相关配置</h1>
<p>k8s是容器编排工具,需要容器管理工具,所以三个节点同时安装docker,还是以k8scludes1为例。</p>
<p>安装docker。</p>
<pre><code class="language-shell">root@k8scludes1:~# apt-get install docker-ce
Reading package lists... Done
Building dependency tree      
Reading state information... Done
The following additional packages will be installed:
containerd.io dbus-user-session docker-ce-cli docker-ce-rootless-extras docker-scan-plugin libltdl7 pigz
......
Processing triggers for libc-bin (2.27-3ubuntu1.2) ...
</code></pre>
<p>查看docker安装包。</p>
<pre><code class="language-shell">root@k8scludes        1:~# dpkg -l | grep docker
iidocker-ce                              5:20.10.14~3-0~ubuntu-bionic                  amd64      Docker: the open-source application container engine
iidocker-ce-cli                        5:20.10.14~3-0~ubuntu-bionic                  amd64      Docker CLI: the open-source application container engine
iidocker-ce-rootless-extras            5:20.10.14~3-0~ubuntu-bionic                  amd64      Rootless support for Docker.
iidocker-scan-plugin                     0.17.0~ubuntu-bionic                            amd64      Docker scan cli plugin.
</code></pre>
<p>设置docker开机自启动并现在启动docker。</p>
<pre><code class="language-shell">root@k8scludes1:~# systemctl enable docker --now
Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable docker
</code></pre>
<p>查看docker状态。</p>
<pre><code class="language-shell">root@k8scludes1:~# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2022-04-16 21:39:46 CST; 3min 21s ago
   Docs: https://docs.docker.com
Main PID: 1822 (dockerd)
    Tasks: 9
   CGroup: /system.slice/docker.service
         └─1822 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
</code></pre>
<p>查看docker版本。</p>
<pre><code class="language-shell">root@k8scludes1:~# docker --version
Docker version 20.10.14, build a224086
</code></pre>
<p>注意kubernetes V1.22.2版本及其以后,要求容器的cgroup driver 为systemd,但是docker默认的cgroup driver 是cgroupfs,kubernetes 1.21版本及其之前,是不需要修改cgroup driver的。</p>
<p>可以使用docker info | grep -i cgroup查看cgroup driver。</p>
<pre><code class="language-shell">root@k8scludes1:~# docker info | grep -i cgroup
WARNING: No swap limit support
Cgroup Driver: cgroupfs
Cgroup Version: 1
</code></pre>
<p>配置docker镜像加速器,并设置docker的cgroup driver 为systemd。</p>
<pre><code class="language-shell">root@k8scludes1:~# cat &gt; /etc/docker/daemon.json &lt;&lt;EOF
&gt; {
&gt; "registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"],
&gt; "exec-opts": ["native.cgroupdriver=systemd"]
&gt; }
&gt; EOF

root@k8scludes1:~# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
</code></pre>
<p>重启docker。</p>
<pre><code class="language-shell">root@k8scludes1:~# systemctl restart docker

root@k8scludes1:~# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2022-04-16 21:51:29 CST; 8s ago
   Docs: https://docs.docker.com
Main PID: 3541 (dockerd)
    Tasks: 9
   CGroup: /system.slice/docker.service
         └─3541 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
</code></pre>
<p>这时Cgroup Driver就变为systemd了。</p>
<pre><code class="language-shell">root@k8scludes1:~# docker info | grep -i cgroup
Cgroup Driver: systemd
Cgroup Version: 1
WARNING: No swap limit support
</code></pre>
<p>设置iptables不对bridge的数据进行处理,启用IP路由转发功能。</p>
<pre><code class="language-shell">root@k8scludes1:~# cat &lt;&lt;EOF&gt; /etc/sysctl.d/k8s.conf
&gt; net.bridge.bridge-nf-call-ip6tables = 1
&gt; net.bridge.bridge-nf-call-iptables = 1
&gt; net.ipv4.ip_forward = 1
&gt; EOF
</code></pre>
<p>使配置生效。</p>
<pre><code class="language-shell">root@k8scludes1:~# sysctl -p /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
</code></pre>
<h1 id="六安装kubeletkubeadmkubectl">六.安装kubelet,kubeadm,kubectl</h1>
<p>三个节点都安装kubelet,kubeadm,kubectl,以k8scludes1为例:</p>
<ul>
<li>Kubelet 是 kubernetes 工作节点上的一个代理组件,运行在每个节点上</li>
<li>Kubeadm 是一个快捷搭建kubernetes(k8s)的安装工具,它提供了 kubeadm init 以及 kubeadm join 这两个命令来快速创建 kubernetes 集群,kubeadm 通过执行必要的操作来启动和运行一个最小可用的集群</li>
<li>kubectl是Kubernetes集群的命令行工具,通过kubectl能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。</li>
</ul>
<pre><code class="language-shell">root@k8scludes1:~# apt-get -y install kubelet=1.22.2-00 kubeadm=1.22.2-00 kubectl=1.22.2-00
Reading package lists... Done
Building dependency tree      
Reading state information... Done
The following additional packages will be installed:
conntrack cri-tools kubernetes-cni socat
......
Unpacking kubeadm (1.22.2-00) ...
Setting up conntrack (1:1.4.4+snapshot20161117-6ubuntu2) ...
Setting up kubernetes-cni (0.8.7-00) ...
Setting up cri-tools (1.23.0-00) ...
Setting up socat (1.7.3.2-2ubuntu2) ...
Setting up kubelet (1.22.2-00) ...
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /lib/systemd/system/kubelet.service.
Setting up kubectl (1.22.2-00) ...
Setting up kubeadm (1.22.2-00) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
</code></pre>
<p>设置kubelet开机自启动并现在启动kubelet。</p>
<pre><code class="language-shell">root@k8scludes1:~# systemctl enable kubelet --now
</code></pre>
<p>kubelet现在是启动不了的。</p>
<pre><code class="language-shell">root@k8scludes1:~# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/kubelet.service.d
         └─10-kubeadm.conf
   Active: activating (auto-restart) (Result: exit-code) since Sat 2022-04-16 22:07:09 CST; 7s ago
   Docs: https://kubernetes.io/docs/home/
Process: 5282 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=1/FAILURE)
Main PID: 5282 (code=exited, status=1/FAILURE)
</code></pre>
<h1 id="七kubeadm初始化">七.kubeadm初始化</h1>
<p>更新软件源。</p>
<pre><code class="language-shell">root@k8scludes1:~# apt update
</code></pre>
<p>查看可得的kubeadm软件包版本。</p>
<pre><code class="language-shell">root@k8scludes1:~# apt-cache madison kubeadm | grep 1.22
   kubeadm |1.22.8-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.7-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.6-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.5-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.4-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.3-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.2-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.1-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |1.22.0-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
</code></pre>
<p>kubeadm init:在主节点k8scludes1上初始化 Kubernetes 控制平面节点。</p>
<ul>
<li>--image-repository registry.aliyuncs.com/google_containers:表示使用阿里云镜像仓库,不然有些镜像下载不下来 ;</li>
<li>--kubernetes-version=v1.22.2:指定kubernetes的版本;</li>
<li>--pod-network-cidr=10.244.0.0/16:指定pod的网段 ;</li>
<li>coredns是一个用go语言编写的开源的DNS服务。</li>
</ul>
<pre><code class="language-shell">root@k8scludes1:~# kubeadm init --image-repository registry.aliyuncs.com/google_containers --kubernetes-version=v1.22.2 --pod-network-cidr=10.244.0.0/16

Using Kubernetes version: v1.22.2
Running pre-flight checks
......
Creating the "cluster-info" ConfigMap in the "kube-public" namespace
Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
Applied essential addon: CoreDNS
Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f .yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.110.128:6443 --token ju8p1y.8gjm5q00l6u5y1rp \
      --discovery-token-ca-cert-hash sha256:3f401b6187ed44ff8f4b50aa6453cf3eacc3b86d6a72e3bf2caba02556cb918e
</code></pre>
<p>进行kubeadm初始化的时候会去下载各种镜像,可以使用docker images查看。</p>
<pre><code class="language-shell">root@k8scludes1:~# docker images
REPOSITORY                                                      TAG       IMAGE ID       CREATED         SIZE
registry.aliyuncs.com/google_containers/kube-apiserver            v1.22.2   e64579b7d886   7 months ago    128MB
registry.aliyuncs.com/google_containers/kube-controller-manager   v1.22.2   5425bcbd23c5   7 months ago    122MB
registry.aliyuncs.com/google_containers/kube-proxy                v1.22.2   873127efbc8a   7 months ago    104MB
registry.aliyuncs.com/google_containers/kube-scheduler            v1.22.2   b51ddc1014b0   7 months ago    52.7MB
registry.aliyuncs.com/google_containers/etcd                      3.5.0-0   004811815584   10 months ago   295MB
registry.aliyuncs.com/google_containers/coredns                   v1.8.4    8d147537fb7d   10 months ago   47.6MB
registry.aliyuncs.com/google_containers/pause                     3.5       ed210e3e4a5b   13 months ago   683kB
</code></pre>
<p>根据提示创建目录和配置文件。</p>
<pre><code class="language-shell">root@k8scludes1:~# mkdir -p $HOME/.kube

root@k8scludes1:~# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

root@k8scludes1:~# sudo chown $(id -u):$(id -g) $HOME/.kube/config
</code></pre>
<p>现在已经可以看到master节点了。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubectl get node
NAME         STATUS   ROLES                  AGE    VERSION
k8scludes1   NotReady   control-plane,master   178m   v1.22.2
</code></pre>
<h1 id="八添加worker节点到k8s集群">八.添加worker节点到k8s集群</h1>
<p>接下来把另外的两个worker节点也加入到k8s集群。</p>
<p>kubeadm init的时候输出了如下这句。</p>
<pre><code class="language-shell">kubeadm join 192.168.110.128:6443 --token ju8p1y.8gjm5q00l6u5y1rp \
      --discovery-token-ca-cert-hash sha256:3f401b6187ed44ff8f4b50aa6453cf3eacc3b86d6a72e3bf2caba02556cb918e
</code></pre>
<p>在另外两个worker节点执行这一命令就可以把节点加入到k8s集群里。</p>
<p>如果加入集群的token忘了,可以使用如下的命令获取最新的加入命令token。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubeadm token create --print-join-command
kubeadm join 192.168.110.128:6443 --token 4xk96a.qizykuirhn8ccvcw --discovery-token-ca-cert-hash sha256:3f401b6187ed44ff8f4b50aa6453cf3eacc3b86d6a72e3bf2caba02556cb918e
</code></pre>
<p>在k8scludes2执行加入集群的token命令。</p>
<pre><code class="language-shell">root@k8scludes2:~# kubeadm join 192.168.110.128:6443 --token 4xk96a.qizykuirhn8ccvcw --discovery-token-ca-cert-hash sha256:3f401b6187ed44ff8f4b50aa6453cf3eacc3b86d6a72e3bf2caba02556cb918e
Running pre-flight checks
Reading configuration from the cluster...
FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
Starting the kubelet
Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
</code></pre>
<p>可以发现worker节点加入到k8s集群后多了两个镜像。</p>
<pre><code class="language-shell">root@k8scludes2:~# docker images
REPOSITORY                                    TAG       IMAGE ID       CREATED         SIZE
registry.aliyuncs.com/google_containers/pause   3.5       ed210e3e4a5b   13 months ago   683kB
registry.aliyuncs.com/google_containers/kube-proxy   v1.22.2   873127efbc8a   7 months ago    104MB
</code></pre>
<p>在k8scludes3执行加入集群的token命令。</p>
<pre><code class="language-shell">root@k8scludes3:~# kubeadm join 192.168.110.128:6443 --token 4xk96a.qizykuirhn8ccvcw --discovery-token-ca-cert-hash sha256:3f401b6187ed44ff8f4b50aa6453cf3eacc3b86d6a72e3bf2caba02556cb918e
Running pre-flight checks
Reading configuration from the cluster...
FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
Starting the kubelet
Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
</code></pre>
<p>可以发现worker节点加入到k8s集群后多了两个镜像。</p>
<pre><code class="language-shell">root@k8scludes3:~# docker images
REPOSITORY                                           TAG       IMAGE ID       CREATED         SIZE
registry.aliyuncs.com/google_containers/kube-proxy   v1.22.2   873127efbc8a   7 months ago    104MB
registry.aliyuncs.com/google_containers/pause      3.5       ed210e3e4a5b   13 months ago   683kB
</code></pre>
<p>在k8scludes1查看节点状态,可以看到两个worker节点都加入到了k8s集群。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubectl get nodes
NAME         STATUS   ROLES                  AGE    VERSION
k8scludes1   NotReady   control-plane,master   3h2m   v1.22.2
k8scludes2   NotReady   &lt;none&gt;               60s    v1.22.2
k8scludes3   NotReady   &lt;none&gt;               57s    v1.22.2
</code></pre>
<h1 id="九部署cni网络插件calico">九.部署CNI网络插件calico</h1>
<p>虽然现在kubernetes集群已经有1个master节点,2个worker节点,但是此时三个节点的状态都是NotReady的,<strong>原因是没有CNI网络插件</strong>,为了节点间的通信,需要安装cni网络插件,<strong>常用的cni网络插件有calico和flannel,两者区别为:flannel不支持复杂的网络策略,calico支持网络策略,因为今后还要配置kubernetes网络策略networkpolicy,所以本文选用的cni网络插件为calico!</strong></p>
<p>现在去官网下载calico.yaml文件:</p>
<p>官网:https://projectcalico.docs.tigera.io/about/about-calico</p>
<p><img src="https://typorablogimage.oss-cn-hangzhou.aliyuncs.com/image-20220911190918361.png"></p>
<p>搜索框里直接搜索calico.yaml。</p>
<p><img src="https://typorablogimage.oss-cn-hangzhou.aliyuncs.com/image-20220911190949598.png"></p>
<p>找到下载calico.yaml的命令。</p>
<p><img src="https://typorablogimage.oss-cn-hangzhou.aliyuncs.com/image-20220911191022325.png"></p>
<p>下载calico.yaml文件。</p>
<pre><code class="language-shell">root@k8scludes1:~# curl https://docs.projectcalico.org/manifests/calico.yaml -O
% Total    % Received % XferdAverage Speed   Time    Time   TimeCurrent
                                 DloadUpload   Total   Spent    LeftSpeed
100212k100212k    0   0   8736      00:00:240:00:24 --:--:-- 18568

root@k8scludes1:~# ls
aa.txtapt-key.gpgcalico.yamlset.sh
</code></pre>
<p>查看需要下载的calico镜像。</p>
<pre><code class="language-shell">root@k8scludes1:~# grep image calico.yaml
          image: docker.io/calico/cni:v3.22.2
          image: docker.io/calico/cni:v3.22.2
          image: docker.io/calico/pod2daemon-flexvol:v3.22.2
          image: docker.io/calico/node:v3.22.2
          image: docker.io/calico/kube-controllers:v3.22.2
</code></pre>
<p>这四个镜像需要在所有节点都下载,以k8scloudes1为例。</p>
<pre><code class="language-shell">root@k8scludes1:~# docker pull docker.io/calico/cni:v3.22.2

root@k8scludes1:~# docker pull docker.io/calico/pod2daemon-flexvol:v3.22.2

root@k8scludes1:~# docker pull docker.io/calico/node:v3.22.2

root@k8scludes1:~# docker pull docker.io/calico/kube-controllers:v3.22.2
</code></pre>
<p>此时三个节点都有calico镜像了。</p>
<pre><code class="language-shell">root@k8scludes1:~# docker images | grep calico
calico/kube-controllers                                           v3.22.2   a1a88662416b   2 days ago      132MB
calico/cni                                                      v3.22.2   be7dfc21ba2e   2 days ago      236MB
calico/pod2daemon-flexvol                                       v3.22.2   d6660bf471e1   2 days ago      19.7MB
calico/node                                                       v3.22.2   fd1608dbbc19   2 days ago      198MB

root@k8scludes2:~# docker images | grep calico
calico/kube-controllers                         v3.22.2   a1a88662416b   2 days ago      132MB
calico/cni                                    v3.22.2   be7dfc21ba2e   2 days ago      236MB
calico/pod2daemon-flexvol                     v3.22.2   d6660bf471e1   2 days ago      19.7MB
calico/node                                     v3.22.2   fd1608dbbc19   2 days ago      198MB

root@k8scludes3:~# docker images | grep calico
calico/kube-controllers                              v3.22.2   a1a88662416b   2 days ago      132MB
calico/cni                                           v3.22.2   be7dfc21ba2e   2 days ago      236MB
calico/pod2daemon-flexvol                            v3.22.2   d6660bf471e1   2 days ago      19.7MB
calico/node                                          v3.22.2   fd1608dbbc19   2 days ago      198MB
</code></pre>
<p>修改calico.yaml 文件,CALICO_IPV4POOL_CIDR的IP段要和kubeadm初始化时候的pod网段一致,注意格式要对齐,不然会报错。</p>
<pre><code class="language-shell">root@k8scludes1:~# vim calico.yaml

root@k8scludes1:~# cat calico.yaml | egrep "CALICO_IPV4POOL_CIDR|"10.244""
            - name: CALICO_IPV4POOL_CIDR
            value: "10.244.0.0/16"
</code></pre>
<p>不直观的话看图片:修改calico.yaml 文件。</p>
<p><img src="https://typorablogimage.oss-cn-hangzhou.aliyuncs.com/image-20220911191155083.png"></p>
<p>应用calico.yaml文件。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubectl apply -f calico.yaml
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
......
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
Warning: policy/v1beta1 PodDisruptionBudget is deprecated in v1.21+, unavailable in v1.25+; use policy/v1 PodDisruptionBudget
poddisruptionbudget.policy/calico-kube-controllers created
</code></pre>
<p>查看calico pod。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubectl get pod -A | grep calico
kube-system   calico-kube-controllers-65898446b5-gtsz6   1/1   Running             0          58s
kube-system   calico-node-d6564                        1/1   Running             0          59s
kube-system   calico-node-jgvjb                        0/1   Running             0          59s
kube-system   calico-node-snkxp                        1/1   Running             0          59s
</code></pre>
<p>此时发现三个节点都是Ready状态了。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubectl get node
NAME         STATUS   ROLES                  AGE   VERSION
k8scludes1   Ready    control-plane,master   3h44m   v1.22.2
k8scludes2   Ready    &lt;none&gt;               42m   v1.22.2
k8scludes3   Ready    &lt;none&gt;               42m   v1.22.2
</code></pre>
<h1 id="十配置kubectl命令tab键自动补全">十.配置kubectl命令tab键自动补全</h1>
<p>查看kubectl自动补全命令。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubectl --help | grep bash
completion    Output shell completion code for the specified shell (bash or zsh)
</code></pre>
<p>添加source &lt;(kubectl completion bash)到/etc/profile,并使配置生效。</p>
<pre><code class="language-shell">root@k8scludes1:~# vim /etc/profile

root@k8scludes1:~# cat /etc/profile | head -3
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
source &lt;(kubectl completion bash)

root@k8scludes1:~# source /etc/profile
</code></pre>
<p>此时即可kubectl命令tab键自动补全。</p>
<pre><code class="language-shell">root@k8scludes1:~# kubectl get nodes
NAME         STATUS   ROLES                  AGE   VERSION
k8scludes1   Ready    control-plane,master   3h46m   v1.22.2
k8scludes2   Ready    &lt;none&gt;               45m   v1.22.2
k8scludes3   Ready    &lt;none&gt;               45m   v1.22.2
</code></pre>
<h1 id="十一总结">十一.总结</h1>
<p>至此,我们已经成功在Ubuntu 18.04上安装并部署了Kubernetes 1.22.2集群。你现在可以开始创建和管理你的Kubernetes资源了。</p>


</div>
<div id="MySignature" role="contentinfo">
    致力于一条龙式的为您解决问题<br><br>
来源:https://www.cnblogs.com/renshengdezheli/p/17632858.html
頁: [1]
查看完整版本: Ubuntu 安装部署Kubernetes(k8s)集群