目标 :安装一主二从集群
途径:采用 vmware,ubuntu,2核,2G内存,50G硬盘
一、vmware安装:
1、为了避免大一安装vmware导致电脑格式化 并重置的悲剧,所以安装时,直接默认选项,并安置到C盘。
2、镜像文件 ISO:https://old-releases.ubuntu.com/releases/,直接在官网下载24.04版本,放到E盘下的resource文件夹中。
3、在虚拟网络编辑器里,创建两个网络格式:VMnet0(自动桥接模式)、VMnet8(NAT模式),
4、针对VMnet8,选择NAT模式 ,让虚拟机把宿主机当作中转翻墙去上网,IP可由内部自定义。
5、选择NAT模式后(网络地址转接),不要让DHCP协议自动分发IP,而是采用静态IP,确保可以搭建集群。不建议 选择 自动桥接模式,他是自动分配IP,IP分配不稳定。
6、我为 vmware 中的 VMnet8网络 分配的子网IP为 192.168.100.0、子网掩码为 255.255.255.0。
其实,vm 的 NAT 功能,在这里就相当于一个路由,负责监听 如下的固定网段。
go
VMnet8 (虚拟网段) ──> IP池:192.168.100.0/24
│
├── Master1 (主动设计静态 IP 192.168.100.111)
├── Node1 (主动设计静态 IP 192.168.100.112)
└── Node2 (主动设计静态 IP 192.168.100.113)
7、一主:Master
进入 etc/netplan/ 中,
并创建yaml文件:99-k8s-static.yaml,并写入:
切记yaml文件的格式,一定要对齐,否则会解析出错
yaml
network: # Netplan 网络配置的根节点
version: 2 # Netplan 配置版本,固定写 2
renderer: networkd # 使用 systemd-networkd 管理网络,适合 Ubuntu Server
ethernets: # 配置以太网网卡
ens33: # 网卡名称,你当前虚拟机的网卡叫 ens33
dhcp4: no # 关闭 DHCP,表示不自动获取 IP,改为手动静态 IP
addresses: # 配置静态 IP 地址
- 192.168.100.111/24 # 当前虚拟机的 IP,/24 等于子网掩码 255.255.255.0
gateway4: 192.168.100.2 # 默认网关,指向 VMware NAT 网关
nameservers: # DNS 服务器配置
addresses: # DNS 地址列表
- 8.8.8.8 # Google DNS,用于解析域名
- 223.5.5.5 # 阿里 DNS,用于解析域名
分配权限:sudo chmod 600 /etc/netplan/99-k8s-static.yaml
之后执行:sudo netplan apply,确保执行并应用
8、二从:Node1、Node2
这两个只需要改变 addresses 即可。
node1 - 192.168.100.112/24
node2 - 192.168.100.113/24
9、隐私设计:
主name:zhumo,密码:w1***53
从1name:***, 密码:1***6
从2name:***, 密码:1***7
10、我采用的是 WindTerm 进行的远程连接。所以需要本地vmware中的虚拟机,打开openssh这中对外连接,否则ping通过了,也无法通过ssh通道连接上。
二、环境搭建-环境初始化(一主多从)
注:若用 WindTerm 这种配置进行操作,会非常方便。因为 vmware 无法粘贴复制,会显示的很局促。
1、检查 Ubuntu 版本
尽量保证各个版本之间一致,可以避免兼容性问题。可以少踩坑。
cat /etc/os-release
2、配置主机名
注:配置主机名,为每个服务器起个名字,之后的k8s就是靠这个,进行识别的。
分别在三台机器执行。
master 执行:
sudo hostnamectl set-hostname master-k8s
node1 执行:
sudo hostnamectl set-hostname node1-k8s
node2 执行:
sudo hostnamectl set-hostname node2-k8s
查看是否成功:
hostname
3、配置 hosts 解析
三台机器都执行:
sudo vim /etc/hosts
添加:
192.168.100.111 master-k8s
192.168.100.112 node1-k8s
192.168.100.113 node2-k8s
保存后测试:
ping master-k8s
ping node1-k8s
ping node2-k8s
只要能 ping 通,说明主机名解析正常。
之后,各个服务器之间,就可以靠着名字,相互通信了。
当然,其实就是个域名解析而已。
4、时间同步
Ubuntu 24.04 默认一般用 systemd-timesyncd,不一定要装 chrony。
先查看:
timedatectl
开启时间同步:
sudo timedatectl set-ntp true
查看状态:
timedatectl status
你重点看这一行:
System clock synchronized: yes
如果是 yes,就可以。
各个集群之间,需要统一时区。
5、关闭防火墙
Ubuntu 一般是 ufw。
查看状态:
sudo ufw status
关闭:
sudo ufw disable
再次查看:
sudo ufw status
看到这个就行:
Status: inactive
k8s和容器网络会管理大量的 iptables/nftables 规则,我现在的学习初期阶段,关闭防火墙可以有效避免被网络拦截。
6、关闭 swap
必须要执行,不执行,后面初始化master的时候,会报错。因为kubelet默认不允许开启swap。
在 master-k8s、node1-k8s、node2-k8s 都执行:
sudo swapoff -a
这句是临时关闭 swap,马上生效。
然后永久关闭 swap:
sudo sed -i.bak '/ swap / s/^/#/' /etc/fstab
7、加载内核模块
三台机器都执行:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
立即加载:
sudo modprobe overlay
sudo modprobe br_netfilter
查看是否加载成功:
lsmod | grep br_netfilter
lsmod | grep overlay
overlay 是容器文件系统所需要的,br_netfilter 是让 Linux 网桥流量可以被 iptables/nftables 处理。
8、配置 Linux 内核网络参数
三台机器都执行:
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
让配置立即生效:
sudo sysctl --system
检查:
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables
sysctl net.ipv4.ip_forward
应该看到:
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
K8s 的 Pod 网络本质上需要跨节点转发流量,所以必须开启 ip_forward 和网桥流量处理。
9、配置 IPVS,可选但推荐
kubernetes 中的 service 转发有几种模式,长江的是 iptables 和 ipvs
其中,ipvs 性能更高些。
现在初学可以先配上,不吃亏。
安装工具:
sudo apt update
sudo apt install -y ipset ipvsadm
创建模块加载文件:
cat <<EOF | sudo tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF
立即加载:
sudo modprobe ip_vs
sudo modprobe ip_vs_rr
sudo modprobe ip_vs_wrr
sudo modprobe ip_vs_sh
sudo modprobe nf_conntrack
查看:
lsmod | grep -e ip_vs -e nf_conntrack
IPVS 是 Linux 内核里的高性能负载均衡能力,K8s 的 Service 可以用它做流量转发。
10、安装基础工具
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gpg vim net-tools lrzsz
工具作用:
curl:下载配置和密钥
gpg:验证软件源签名
vim:编辑配置文件
net-tools:提供 ifconfig、netstat 等命令
ca-certificates:HTTPS 证书
apt-transport-https:让 apt 支持 HTTPS 源
提前把工具准备好,后期可能需要用
11、检查网络 IP
大致就是用 ip addr 测网卡
用 ping baidu.com 测联通性
12、重启机器
sudo reboot
重启,确保配置生效。
三、环境搭建-集群安装
我当前的环境配置:
系统:Ubuntu 24.04
环境:VMware 三台虚拟机
master-k8s:192.168.100.111
node1-k8s: 192.168.100.112
node2-k8s: 192.168.100.113
容器运行时:containerd
Kubernetes:v1.36 系列
网络插件:Flannel
国内环境:软件包走中科大/清华镜像,K8s 镜像走阿里云/DaoCloud 镜像方案
1、安装 containerd
1.1 三台机器都执行
sudo apt update
sudo apt install -y containerd
检查版本:
containerd --version
其中,containerd 是 Kubernetes 真正用来拉镜像、创建容器、启动容器的组件。
它大致是如此起作用的:
kubectl 发送命令
↓
kube-apiserver 接收命令
↓
kubelet 在节点上执行
↓
containerd 真正启动容器
sudo apt update 表示更新 Ubuntu 的软件包索引。
sudo:用管理员权限执行
apt:Ubuntu 的软件包管理工具
install:安装软件
-y:自动回答 yes
containerd:要安装的软件名
1.2 生成 containerd 配置文件
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
将containerd的默认配置信息,通过管道写入 config.toml中,方便后续修改配置,而不是一直用containerd这种默认方式。
tee 是将内容写入指定文件。
> 代表不用将输入内容输出,写入一个空文件就行。防止内容太多,而导致刷屏。
1.3 修改 containerd 的 cgroup 为 systemd
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml # 替换管理进程的方式,保证各个节点一致
grep -n "SystemdCgroup" /etc/containerd/config.toml # 查看修改是否正确
sed:替换操作
i:直接修改文件
s/旧内容/新内容/:替换方式
1.4 国内环境:修改 pause 镜像地址
替换一波,k8s.io 在中国内网络太慢。
sudo sed -i "s#sandbox = 'registry.k8s.io/pause:3.10.1'#sandbox = 'registry.aliyuncs.com/google_containers/pause:3.10'#" /etc/containerd/config.toml
grep -nE "pinned_images|sandbox|pause" /etc/containerd/config.toml
应该会输出:
sandbox = 'registry.aliyuncs.com/google_containers/pause:3.10'
代表替换成功。
pause其实是,必不可少的。
Pod
├── pause 容器:负责 Pod 的基础网络环境
├── nginx 容器:负责运行网站
└── log-agent 容器:负责收集 nginx 日志
然后重启一波,才生效:
sudo systemctl restart containerd
sudo systemctl enable containerd
2、安装 kubeadm、kubelet、kubectl
2.1 三台机器都执行:添加 Kubernetes 国内软件源
我用的是中科大 Kubernetes 镜像源。
三台机器都执行:
K8S_MINOR=v1.36
创建 keyring 目录:
sudo mkdir -p -m 755 /etc/apt/keyrings
导入 Kubernetes GPG key:
curl -fsSL https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/deb/Release.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
添加中科大 Kubernetes 源:
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.ustc.edu.cn/kubernetes/core:/stable:/${K8S_MINOR}/deb/ /" \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
更新软件源:
sudo apt update
如果失败的化,可以换成其他源。
2.2 安装 kubelet / kubeadm / kubectl
三台机器都执行:
sudo apt install -y kubelet kubeadm kubectl
在锁定版本:
sudo apt-mark hold kubelet kubeadm kubectl
查看版本:
kubeadm version
kubectl version --client
启动 kubelet:
sudo systemctl enable --now kubelet
这三个组件要分清楚:
kubeadm:用来初始化集群、加入节点
kubelet:每台机器上的节点代理,真正负责管理 Pod
kubectl:你操作 Kubernetes 的命令行工具
安装后先 hold 是为了防止系统自动升级它们。Kubernetes 升级需要按控制面、节点、kubelet 的顺序来,所以不能随便被 apt upgrade 升级。
并且,官方安装文档也要求安装后锁定 kubelet kubeadm kubectl。
2.3 配置 crictl,方便排查 containerd
三台机器都执行:
cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
测试:
sudo crictl info
如果能输出一大段 JSON 信息,说明 crictl 能连上 containerd。
安装:
sudo apt install -y cri-tools
看版本:
crictl --version
测信息:
sudo crictl info
crictl 其实就是为了看,containerd这种容器运行时的内部信息,方便排错。
如果以后pod容器跑不起来了,可以:
sudo crictl ps -a
sudo crictl images
sudo crictl logs 容器ID
3、初始化 master
下面只在 master-k8s 执行。
3.1 确认 master IP
ip addr show ens33
确认你看到:
```cmd
192.168.100.111
3.2 创建 kubeadm 初始化配置文件
只在 master 执行:
cmd
K8S_VERSION=$(kubeadm version -o short)
echo $K8S_VERSION
然后创建配置文件:
cat <<EOF | sudo tee /root/kubeadm-init.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.100.111
bindPort: 6443
nodeRegistration:
criSocket: unix:///run/containerd/containerd.sock
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: ${K8S_VERSION}
imageRepository: registry.aliyuncs.com/google_containers
networking:
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
dnsDomain: cluster.local
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
EOF
检查配置文件:
cat /root/kubeadm-init.yaml
3.3 预拉取 Kubernetes 镜像
只在 master 执行:
sudo kubeadm config images list --config /root/kubeadm-init.yaml
然后拉取:
sudo kubeadm config images pull --config /root/kubeadm-init.yaml
主要是测试网络连通性的。
3.4 初始化 master
只在 master 执行:
sudo kubeadm init --config /root/kubeadm-init.yaml
成功后,你会看到类似:
Your Kubernetes control-plane has initialized successfully!
并且最后会输出一段 kubeadm join ... 命令。
一定要保存这段命令,后面 node1 / node2 要用。
kubeadm join 192.168.100.111:6443 --token ctp40n.gpp714i8mtchfjcb \
--discovery-token-ca-cert-hash sha256:e24ee795ce05f9a88cb4a22f9f7714b5ed4897c1a31957e160362f445e0e769d
一般,生效周期是24小时,之后就会失效,
kubeadm token create --print-join-command
可以采用这个,进行重新生成。
这一步的意义:
kubeadm init 会把 master 控制面搭起来。它会做预检、生成证书、生成 kubeconfig、创建 etcd、kube-apiserver、kube-controller-manager、kube-scheduler 等静态 Pod,并生成 worker 节点加入集群用的 token。官方文档也明确说明 kubeadm init 是初始化 Kubernetes control plane node 的命令。
一句话理解:
kubeadm init = 把 master 节点初始化成 Kubernetes 控制中心。
3.5 配置 kubectl
只在 master 执行:
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
此时你可能看到:
master-k8s NotReady
这是正常的,因为网络插件还没装。
这一步的意义
kubectl 需要知道连接哪个 Kubernetes API Server,也需要证书权限。/etc/kubernetes/admin.conf 就是 master 初始化后生成的管理员配置文件。
4、安装 Flannel 网络插件
下面只在 master 执行。
4.1 下载 Flannel 配置
curl -L -o kube-flannel.yml https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
4.2 国内环境:替换 Flannel 镜像源
Flannel 官方 YAML 当前使用 ghcr.io/flannel-io/... 镜像,国内可能拉不下来。Flannel 官方说明它是一个给 Kubernetes 使用的三层网络方案,并且会在每个节点上运行 flanneld 来分配和管理 Pod 子网。
先查看镜像:
grep "image:" kube-flannel.yml
如果里面是:
ghcr.io/flannel-io/...
可以替换成 DaoCloud 的 GHCR 镜像代理:
sed -i 's#ghcr.io/#ghcr.m.daocloud.io/#g' kube-flannel.yml
再检查:
grep "image:" kube-flannel.yml
应该变成类似:
ghcr.m.daocloud.io/flannel-io/flannel
ghcr.m.daocloud.io/flannel-io/flannel-cni-plugin
4.3 安装 Flannel
kubectl apply -f kube-flannel.yml
观察:
kubectl get pods -n kube-flannel -w
如果你的 Flannel Pod 在 kube-system,就用:
kubectl get pods -n kube-system -w
等它变成:
Running
然后检查节点:
kubectl get nodes
master 应该慢慢从:
NotReady
变成:
Ready
这一步的意义:
Kubernetes 本身不负责打通 Pod 网络。CNI 插件负责让不同节点上的 Pod 可以通信。
现在选 Flannel,是因为它简单,适合初学。它会在每个节点上跑一个网络代理,负责给每个节点分配 Pod 子网,并用 VXLAN 等方式转发跨节点 Pod 流量。
5、node1 / node2 加入集群
下面在 node1-k8s 和 node2-k8s 执行。
5.1 使用 master 输出的 join 命令
master 初始化成功后,会输出类似:
kubeadm join 192.168.100.111:6443 --token xxxxxx.xxxxxxxxxxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxx
你在 node1 和 node2 上执行时,前面加 sudo:
sudo kubeadm join 192.168.100.111:6443 --token xxxxxx.xxxxxxxxxxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxx \
--cri-socket unix:///run/containerd/containerd.sock
5.2 如果 join 命令丢了
在 master 上重新生成:
kubeadm token create --print-join-command
然后复制到 node1 / node2 执行。
这一步的意义
kubeadm join 的作用是让 worker 节点加入 master 管理的集群。
它会做几件事:
- 连接 master 的 6443 端口
- 用 token 做第一次认证
- 校验 CA 证书 hash,防止连到假的 master
- 注册 kubelet
- 让这个节点成为 Kubernetes Node
6、最终验证,查看节点
kubectl get nodes -o wide
你最终要看到类似:
NAME STATUS ROLES INTERNAL-IP
master-k8s Ready control-plane 192.168.100.111
node1-k8s Ready <none> 192.168.100.112
node2-k8s Ready <none> 192.168.100.113
7、部署nginx测试
国内环境下,nginx:latest 可能因为 Docker Hub 网络问题拉不下来。这里用 DaoCloud 镜像代理:
kubectl create deployment nginx --image=docker.m.daocloud.io/library/nginx:latest --replicas=3
查看 Pod:
kubectl get pods -o wide
```
暴露服务:
```
kubectl expose deployment nginx --port=80 --type=NodePort
```
查看 Service:
```
kubectl get svc
```
你会看到类似:
```
nginx NodePort 10.96.xxx.xxx <none> 80:30xxx/TCP
```
然后在宿主机浏览器访问:
```
http://192.168.100.111:30xxx
http://192.168.100.112:30xxx
http://192.168.100.113:30xxx
```
能看到 nginx 页面,就说明集群基本成功。