简介

Kubernetes 是当今最流行的开源容器管理平台,是大名鼎鼎的 Google Borg 的开源版本。因为它的名字有点长,所以一般被称作k8s(因为k和s之间有8个字母,没错就是这么随便)

但尽管k8s如此重要,不少人在部署k8s集群这一步就被直接劝退了。原因有:

  • 网络问题:K8S 是 Google 开发的,官方最新镜像都在墙外,安装时下载不了镜像。
  • 机器问题:K8S 运行的组件非常多,对于机器本身有要求,配置不能低,如果要搭建集群,还需要多台机器,是笔不小的开销。
  • 运维问题:K8S 的部署安装和维护,涉及到不少 Linux 及网络相关的内容,需要有一定的运维能力。
  • 单机可用的minikube虽然易用,但功能不够完善。

其实我自己在部署Kubernetes时也遇到了很多坑,最后非常艰难地完成了部署。不过如今已经有很多的安装工具,甚至有一键安装及图形化界面安装工具。本文使用官方推荐的kubeadm工具部署集群。

Kubernetes官方文档:https://kubernetes.io/zh-cn/
Kubernetes架构图:
file

安装

准备工作

本次部署的集群为多节点集群,有一个master和两个node节点。(我们仅仅是学习之用,没有集群稳定安全性考虑,这里就不需要浪费资源去搞高可用。)

部署版本为目前的最新版1.25.0

Docker Engine没有实现CRI,而这是容器运行时在Kubernetes中工作所需要的。为此,必须安装一个额外的服务cri-dockerdcri-dockerd是一个基于传统的内置Docker引擎支持的项目,它在1.24版本从kubelet中移除。Kubernetes推荐使用containerd代替cri-dockerd,但本文仍使用cri-dockerd进行部署,后期再考虑升级。官方CRI文档

部署环境为三台VMware Workstation虚拟机,操作系统为Ubuntu 22.04.1 LTS,加入同一虚拟网络。

鉴于我使用国内镜像站部署后一直报错,本文在部署过程中使用Google官方镜像站下载镜像文件,因此请保证你能让虚拟机访问外网。使用Clash的用户可以参考Clash for Windows教程:配置TUN/TAP虚拟网卡

本文所有操作请使用root用户执行。

因为是在虚拟机内操作,为了防止误操作,请多使用VMware的快照功能。

1 配置虚拟机网络

本段内容需要在所有节点执行。
安装虚拟机的部分不再赘述。安装完一台后克隆两台,随后在虚拟机设置-网络适配器-高级中分别重新生成mac地址即可(mac地址不能重复)。

之后点击编辑-虚拟网络编辑器,添加一个网络,选择NAT模式,配置好子网和网关,如图:
file
file

配置三台虚拟机的网络适配器的网络连接为此网络:
file

这一步是为了将虚拟机置于同一网络内,让它们能互相访问,同时NAT使它们能够访问到广域网。

DHCP为虚拟机分配的IP会变化,对于K8S集群环境来说,管理网络的IP应该是固定的,否则会造成通信的混乱,所以需要配置静态IP。

开启这三台虚拟机,分别编辑/etc/netplan/00-installer-config.yaml(可能文件名不一样),修改为以下内容:
file
注意不要把三台虚拟机的IP配一样了。

编辑完之后对三台机器使用如下命令使配置生效:

netplan apply

由于IP发生了变化,SSH连接会断开,再次连接即可。

2 基础环境

本段内容需要在所有节点执行。

关闭swap

在旧版的k8s中kubelet都要求关闭swap,但最新版的kubelet其实已经支持swap,因此这一步其实可以不做。但在生产环境还是建议关闭swap,毕竟如果任务运行到了swap上,性能会大打折扣。

# 临时关闭swap
swapoff -a
# 编辑/etc/fstab,注释掉swap那行,持久化生效
vim /etc/fstab

修改主机名并添加hosts解析

这一步是为了增加节点辨识度。这一步可以不做,但建议还是做一下。
为所有节点使用如下命令设置主机名:

# 将name改为你希望的名称,如master、node1等
hostnamectl set-hostname name

编辑/etc/hosts,依次加入各个节点的IP和主机名,如图:
file

修改时区

timedatectl set-timezone Asia/Shanghai

修改后,如果想使得系统日志的时间戳也立即生效,重启rsyslog:

systemctl restart rsyslog

设置内核参数

首先确认你的系统已经加载了br_netfilter模块。默认是没有该模块的,需要你先安装bridge-utils。然后再使用modprobe加载一下,lsmod就能看到br_netfilter模块,此时再确认一下内核参数net.bridge.bridge-nf-call-iptables是否为1

# 首先更新源
apt update
apt install -y bridge-utils
modprobe br_netfilter
lsmod | grep br_netfilter
sysctl -a | grep bridge

file
在Ubuntu新版本上,这个值就是1。如果你的系统上不一致,使用下面的命令来修改:

cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

3 基础软件

本段内容需要在所有节点执行。

安装Docker

目前新版的Ubuntu已经有提供Docker的安装包,直接安装即可。

apt install docker.io
systemctl start docker
systemctl enable docker

安装cri-dockerd

wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.5/cri-dockerd_0.2.5.3-0.ubuntu-bionic_amd64.deb
dpkg -i cri-dockerd_0.2.5.3-0.ubuntu-bionic_amd64.deb

安装kubeadm、kubelet和kubectl

本段内容来自官方文档。需要虚拟机能够访问外网。

# 安装使用 Kubernetes apt 仓库所需要的包
apt install -y apt-transport-https ca-certificates curl
# 下载 Google Cloud 公开签名秘钥
curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
# 添加 Kubernetes apt 仓库
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 更新 apt 包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本
apt update
apt install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl

kubelet现在每隔几秒就会重启,目前这是正常现象,因为它陷入了一个等待kubeadm指令的死循环。

4 使用kubeadm创建集群

本段内容需要在master和node节点执行不同的操作。

使用如下命令初始化master节点。需要虚拟机能够访问外网。

sudo kubeadm init \
    --pod-network-cidr 172.16.0.0/16 \ # Pod子网
    --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \ # 国内镜像仓库
    --token-ttl 0 \ # Token失效时间,0为永不失效
    --cri-socket unix:///var/run/cri-dockerd.sock # 容器运行时端点

执行完成后会提醒你做三件事:
file

  1. 配置环境变量
    在master上操作以便你能正常使用kubectl进行集群的操作。
    对于常规用户如下:

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

    对于root用户命令如下:

    export KUBECONFIG=/etc/kubernetes/admin.conf
  2. 将节点加入集群
    在两台node节点运行以下命令将其加入集群。

    # 注意这里是示例,以你的控制台显示的命令为准
    kubeadm join 172.20.20.200:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:4e4a7d0e848ae6c047d163fbe07f0e6975d71cc156d7705649241a59bbecaa04

    完成之后,再到master上查看node,若可以看到node说明成功将worker加入集群中了。
    file

  3. 部署网络插件
    上面我们已经部署好了K8S集群,但是由于还没有安装网络插件,因此整个集群实际上还是不能工作的,通过kubectl get nodes可以看到虽然已经有两个节点,但Status却都还是NotReady。
    K8S的网络插件有很多,常见的有flannel、calico、cilium、kube-ovn等等。Calico 是比较主流的选择,因此这里选择Calico进行安装。
    在集群上运行以下命令安装Calico:

    kubectl apply -f "https://docs.projectcalico.org/manifests/calico.yaml"

    等待几分钟,网络插件安装成功运行之后,再次查看Node,其状态会更新为ready。
    file

验收集群

如果可以在K8S集群里成功创建一个Pod,那就说明这个集群是健康的、可用的。
使用如下命令就可以创建一个最简单的nginx pod:

kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml

simple.pod的yaml简单内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

执行后,通过kubectl get pod可以观察到状态的变化:
file
通过加-o wide可以查看pod的ip,再使用curl,就可以访问这个nginx服务。
file


至此,我们创建了第一个pod的集群搭建完成。

恭喜你,已经完成了你学习K8S最艰难的一步——环境搭建。


参考:
图解 K8S(01):基于 Ubuntu 20.04 部署 1.23版K8S 集群 - 王炳明
安装 kubeadm - Kubernetes文档