LOADING

加载过慢请开启缓存 浏览器默认开启

记一次Kubernetes完整集群的搭建(1)

写在前面

太好了孩子们 这次基本全都是命令行操作 我不用截图了

以下几乎全是命令 几乎一张图片没有 如果你想做为参考的话请仔细阅读每一行

起因

昨天我在折腾Authentik认证服务的时候 一直在思考用什么反代服务

常见的可以用Nginx Proxy Manager,Caddy,Traefik

这里面我觉得比较好用的是Traefik,但是即使是Traefik想要自动申请证书之类的你也需要在docker compose里写一堆lable去定义

再加上我的服务越来越多 之前都是宝塔和1Panel混着用来管理docker

这太不健康了

我认为是时候开始大一统了

那么随着Docker慢慢被大企业抛弃 Kubernetes(以下简称K8s)越来越流行了

模块化 资源分配 负载均衡 统一管理 故障迁移 分布存储等等

事实上Docker你分开用一堆模块也可以做到这些东西

但是K8s是一整套解决方案 刚好我也想学习一下

让我们来搭建一个完整的K8s集群吧

为什么不用K3s 因为目的不只是为了方便 我认为学习K8s的组件也是很有必要的

折腾开始

大部分都可以参考K8s的官方文档 写的很详细,介绍了很多概念以及在生产环境中要学习的东西

我个人觉得学习的话收益还是很大的

而且还有中文 美滋滋

地址在这里https://kubernetes.io/zh-cn/docs/home/

1.1 主机配置说明

我首先搭建了三台相同的Ubuntu Server,我的打算是1Master 2Node

配置如下

配置 CPU RAM 硬盘 IP地址
Master 4Core 4G 40G 192.168.0.100/24
Worker01 4Core 8G 128G 192.168.0.101/24
Worker02 4Core 8G 128G 192.168.0.102/24

我是ESXi虚拟机 实在不够用可以扩容 而且我可能会打算部署分布存储 所以先这样配置

1.2 主机配置

1.2.1 主机名配置

我们用xShell连接上三台机器 全部切换到root

为了方便我们先分别设定一下三台机器的主机名字

master节点

hostnamectl set-hostname k8s-master01

Worker1

hostnamectl set-hostname k8s-worker01

Worker2

hostnamectl set-hostname k8s-worker02

然后上面菜单栏————查看————撰写————撰写栏

打开它 然后左下角有一个将命令发送到全部会话

这样我们可以统一执行一些命令

1.2.2 统一时区与时间

!!以下命令所有机器都要执行!!

apt update
apt upgrade -y #更新软件包
timedatectl set-timezone Asia/Shanghai # 统一时间

为了统一时间 防止时间偏移 我们可以定期让三台机器自动同步时间

这边用的最小化安装 还得安装一下cron

apt install cron -y 
systemctl enable cron
systemctl start cron
apt install ntpdate -y
ntpdate ntp.aliyun.com
crontab -e

选择2 我们用vim编辑

我们想让他在每天 5点自动更新 那就写

0 5 * * * ntpdate ntp.aliyun.com

然后:wq保存

1.2.3 配置内核转发 网桥过滤

Ubuntu默认是不开启这个的 为了便于集群之间的通信 还有一些Pod的特殊需求 这个肯定是要打开的

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

然后给内核导入overlay br_netfilter这两个模块 这两个是K8s的必要模块

modprobe overlay
modprobe br_netfilter
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sysctl --system

然后既然是新搭建的,我们可以给kube-proxy用新的ipvs模式 性能更好

需要安装ipset和ipvsadm

apt install ipset ipvsadm -y
#让其自动加载
cat << EOF | tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF
# 立即加载模块
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack

1.2.4 关闭swap分区

K8s可以强行兼容swap分区 但是官方文档建议是关闭

因为K8s运行中显然需要的是真实的内存和CPU 为了防止出现奇奇怪怪的问题 关掉它

swapoff -a
vim /etc/fstab

找到最下面一行带有swap关键字的 前面加个#给他注释掉

!!以上命令所有机器都要执行!!

完成之后机器的基本配置算是完成了

2.1 容器运行时的安装

K8s弃用了Docker作为容器运行时 转而使用Containerd

事实上这就是Docker的底层

依旧所有机器都要运行:

wget https://github.com/containerd/containerd/releases/download/v2.1.4/containerd-2.1.4-linux-amd64.tar.gz

下不来可以配置一下proxy

这里的地址可以自己去Github下载最新的release

然后解压出来

tar Cxzvf /usr/local containerd-2.1.4-linux-amd64.tar.gz 
which containerd #检查是否成功

然后旧版本的cri懒人包没了 我们需要手动安装runc和CNI

wget https://github.com/opencontainers/runc/releases/download/v1.3.2/runc.amd64
wget https://github.com/containernetworking/plugins/releases/download/v1.8.0/cni-plugins-linux-amd64-v1.8.0.tgz
install -m 755 runc.amd64 /usr/local/sbin/runc
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.8.0.tgz

然后生成containerd的基础配置文件

mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml


#sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

网上提到的systemd cgroup在新版Containerd中默认使用 我们等下可以验证

然后差点忘了我们手动安装的要注册一下才能用systemctl去调用

wget -O /etc/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
systemctl daemon-reload
systemctl restart containerd
systemctl enable containerd

跑起来之后我们ls /var/run/containerd/看看 有一个.sock结尾就是ok了

3.1 正式开始部署K8s

# 下载K8s仓库的公钥
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt update
# 查看版本
apt-cache madison kubeadm

我这里版本最新是1.34.1-1.1

直接安装

apt install kubeadm=1.34.1-1.1 kubelet=1.34.1-1.1 kubectl=1.34.1-1.1
apt-mark hold kubelet kubeadm kubectl # 锁定版本防止自动更新炸刚

3.2 配置kubelet

先配置kubelet的cgroup驱动

vim /etc/default/kubelet 

在后面加上”–cgroup-driver=systemd”

kubelet负责集群中Pod的生命周期管理,所以我们需要开机自启动 否则集群会炸

systemctl enable kubelet 

3.3 集群初始化

3.3.1 生成初始配置文件

请注意:以下命令只需要在Master节点中执行

kubeadm config print init-defaults > kubeadm-config.yaml

配置文件太长了我直接贴出来

apiVersion: kubeadm.k8s.io/v1beta4
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.0.100 #改这里
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  imagePullSerial: true
  name: k8s-master01 #改这里
  taints: null
timeouts:
  controlPlaneComponentHealthCheck: 4m0s
  discovery: 5m0s
  etcdAPICall: 2m0s
  kubeletHealthCheck: 4m0s
  kubernetesAPICall: 1m0s
  tlsBootstrap: 5m0s
  upgradeManifests: 5m0s
---
kind: ClusterConfiguration
kubernetesVersion: 1.34.0
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
  podSubnet: 10.244.0.0/16 #改这里
proxy: {}
scheduler: {}

3.3.2 获取镜像

然后Pull相关镜像

kubeadm config images pull

这里官方镜像是完全不可达的 由于Containerd默认不走系统设置的proxy变量 这里要么用镜像源要么就软路由给整个节点起飞走

下完之后就可以初始化集群了

3.3.3 正式初始化集群

kubeadm init --config kubeadm-config.yaml --upload-certs --v=9
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

当你看到这一坨 意味着控制平面搭建成功了

然后把它上面给的三行命令复制粘贴到控制台

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

然后

kubectl get nodes

如果得到这样的输出

NAME           STATUS     ROLES           AGE     VERSION
k8s-master01   NotReady   control-plane   3m30s   v1.34.1

完事了

然后记得上面他给了一行让worker加入的命令 复制他粘贴到Workernodes 前期配置没有问题的话顺利加入肯定也没问题

重新get nodes之后能看到

NAME           STATUS     ROLES           AGE     VERSION
k8s-master01   NotReady   control-plane   8m39s   v1.34.1
k8s-worker01   NotReady   <none>          8s      v1.34.1
k8s-worker02   NotReady   <none>          8s      v1.34.1

我们可以看到Status还是NotReady,怎么回事呢

我们可以看到pods里面的coredns 还属于pending状态 他作为核心pod之一还没有调度到节点里去

我们的节点还没有调度IP 所以我们需要网络插件CNI

4.1 网络插件

4.1.1 选择

常见的话有三个 Flannel Calico Cilium

复杂程度都是递增的

事实上的话Calico已经足够极其庞大的集群使用了

Cilium则是用于多集群 而且他会复杂非常多 我们暂时不考虑

为了练手 我这里还是选择Calico

4.1.2 Calico的安装

如果用Opertor安装的话其实很简单 只是还是网络环境的问题

如果之前你能成功init我相信是没问题的 我们偷懒用Operator就好

进入Tigera的文档https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises找到安装的命令

在Master节点上执行:

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/tigera-operator.yaml
wget https://raw.githubusercontent.com/projectcalico/calico/v3.30.3/manifests/custom-resources.yaml
vim custom-resources.yaml

自定义一下Calico的配置 我们要改的就是默认的那个网段

apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    ipPools:
    - name: default-ipv4-ippool
      blockSize: 26
      cidr: 10.244.0.0/16  # 这里
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()

---
apiVersion: operator.tigera.io/v1

改完保存然后

kubectl create -f custom-resources.yaml

完事之后Calico就开始初始化了

watch kubectl get pods -n calico-system

看里面的组件确保全部Running

这时候我们在看看nodes状态

root@k8s-master01:/home/cainong# kubectl get nodes
NAME           STATUS   ROLES           AGE   VERSION
k8s-master01   Ready    control-plane   83m   v1.34.1
k8s-worker01   Ready    <none>          74m   v1.34.1
k8s-worker02   Ready    <none>          74m   v1.34.1

完事 至此K8s已经完全启动了 撒花撒花

还没完全结束 我们还有Ingress Dashboard没有配置 我是不可能手敲命令行手写yml的

而且我们还要慢慢迁移之前的docker服务 以及Longhorn的配置

这是下一个坑