Featured image of post 我的虚拟化星球核心启动:Kubernetes 集群搭建实录

我的虚拟化星球核心启动:Kubernetes 集群搭建实录

在 Ubuntu 虚拟机中,用 kubeadm 搭建 Kubernetes 1.33 集群,安装 Flannel 网络插件、Dashboard、并通过宿主机的 FRP 实现端口转发

我用 kubeadm 在虚拟机中搭好了一个可用的 Kubernetes 集群,它现在撑起了我家庭云的“大脑”。 这篇文章记录整个过程,踩坑不少,也收获很多。


🧱 我的集群结构

  • 系统环境:Ubuntu Server 22.04(运行在 KVM 虚拟机中)
  • 控制节点:k8s-master(2 核 4G,初步实验用)
  • 工作节点:后续通过 kubeadm join 加入
  • 网络插件:Flannel
  • 容器运行时:Containerd
  • 组件:Helm、Kubernetes Dashboard
  • 宿主机通过 FRP 实现端口转发(如 Dashboard)

🚧 环境准备:内核 & 模块配置

Kubernetes 需要开启 IP 转发,并加载 overlay 和 br_netfilter 模块:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 启用 IP 转发
cat << EOF | tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

# 加载必要内核模块
cat << EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

🐳 安装 Containerd

我使用的是 containerd v1.7.27:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
wget https://github.com/containerd/containerd/releases/download/v1.7.27/containerd-1.7.27-linux-amd64.tar.gz
sudo tar Cxzvf /usr/local containerd-1.7.27-linux-amd64.tar.gz

# 获取并注册 containerd 的 systemd 服务
sudo mkdir -p /usr/local/lib/systemd/system 
sudo curl -o /usr/local/lib/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service

# 启动 containerd
sudo systemctl daemon-reload
sudo systemctl enable --now containerd

安装成功后用 sudo systemctl status containerd 验证运行状态。


🔐 安装 runc & CNI 插件

1
2
3
4
5
6
7
8
9
# 安装 runc
wget https://github.com/opencontainers/runc/releases/download/v1.2.6/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc

# 安装 CNI 插件

wget https://github.com/containernetworking/plugins/releases/download/v1.7.1/cni-plugins-linux-amd64-v1.7.1.tgz
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.7.1.tgz

⚙️ 配置 Containerd

1
2
sudo mkdir -p /etc/containerd/
sudo bash -c 'containerd config default > /etc/containerd/config.toml'

编辑 /etc/containerd/config.toml

  • 设置 SystemdCgroup = true
  • 设置 sandbox 镜像为kubernetes 版本对应的 pause 版本
1
2
3
4
5
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.k8s.io/pause:3.10"

保存后重启:

1
sudo systemctl restart containerd

🔧 安装 kubeadm / kubelet / kubectl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
sudo swapoff -a

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/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.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

配置 kubelet 使用 systemd cgroup:

1
2
echo 'KUBELET_EXTRA_ARGS=--cgroup-driver=systemd' | sudo tee /etc/default/kubelet
sudo systemctl enable --now kubelet

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


🏷️ 设置主机名与 hosts 文件

在部署 Kubernetes 前,为了方便集群通信,统一为每台虚拟机设置了主机名,并配置了 /etc/hosts,避免因 DNS 失败导致通信异常。

✅ 修改主机名

k8s-master 为例:

1
sudo hostnamectl set-hostname k8s-master

其他节点按需设置为 k8s-worker1k8s-worker2k8s-worker3

✅ 编辑 /etc/hosts

在每台节点的 /etc/hosts 文件中添加以下内容:

1
2
3
4
192.168.122.169 k8s-master
192.168.122.170 k8s-worker1
192.168.122.171 k8s-worker2
192.168.122.172 k8s-worker3

确保所有节点都能通过主机名互相通信。


🚀 初始化集群(主节点)

查看本机 IP:

1
2
ip route show | grep default
# 举例:default via 192.168.122.1 dev enp1s0 proto dhcp src 192.168.122.169 metric 100 

执行初始化命令:

1
2
3
4
5
6
sudo kubeadm init \
  --control-plane-endpoint=k8s-master \
  --apiserver-advertise-address=192.168.122.169 \
  --pod-network-cidr=10.244.0.0/16 \
  --service-cidr=10.96.0.0/12
 

这里的k8s-master是虚拟机的主机名,--apiserver-advertise-address 是虚拟机 IP 地址。

完成后执行以下操作:

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

🌐 安装 Flannel 网络插件

1
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

安装 Pod 网络后,你可以通过在 kubectl get pods --all-namespaces 输出中检查 CoreDNS Pod 是否 Running 来确认其是否正常运行。 一旦 CoreDNS Pod 启用并运行,你就可以继续加入节点。

如果你的网络无法正常工作或 CoreDNS 不在 Running 状态,请查看 kubeadm 的故障排除指南。

通过以下命令查看 Flannel Pod 的日志:

1
kubectl logs -n kube-flannel kube-flannel-ds-2s5dr

如果出现 Failed to check br_netfilter 报错,请检查你的虚拟机是否加载了对应模块(见文首)。


🤝 Worker 节点加入集群

在完成主节点初始化后,kubeadm 会生成一条 join 命令,用于将工作节点加入集群。

在每台 Worker 节点上执行:

1
2
sudo kubeadm join k8s-master:6443 --token x3n5o4.innk28m148gig4rf \
  --discovery-token-ca-cert-hash sha256:1b5fe8185016ecf8d75f8d9d7753637a6cb1406ac16b41c17e3b10c8dcbc0e98

加入成功后,在 Master 节点查看节点状态:

1
kubectl get nodes

输出示例:

1
2
3
4
5
NAME           STATUS   ROLES           AGE     VERSION
k8s-master     Ready    control-plane   10m     v1.33.0
k8s-worker1    Ready    <none>          2m      v1.33.0
k8s-worker2    Ready    <none>          2m      v1.33.0
k8s-worker3    Ready    <none>          2m      v1.33.0

k8s-pods-nodes.png


🧰 安装 Helm、Dashboard (主节点)

安装 Helm

1
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

安装 Kubernetes Dashboard

1
2
3
4
# Add kubernetes-dashboard repository
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
# Deploy a Helm Release named "kubernetes-dashboard" using the kubernetes-dashboard chart
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard

端口转发:

1
kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-proxy 8443:443 --address=0.0.0.0

📡 宿主机转发端口到虚拟机

我使用 frps + frpc 实现了从公网访问虚拟机服务。

例如,将宿主机的 8443 端口转发到虚拟机的 Dashboard:

1
2
3
4
5
6
[[proxies]]
name = "kubernetes-dashboard"
type = "tcp"
localIP = "192.168.122.169"
localPort = 8443
remotePort = 8443

k8s-dashboard.png


🔍 常用命令收集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 管理容器(类似 docker ps)
sudo crictl ps

# 查看节点
kubectl get nodes

# 查看 Pod
kubectl get pods -A

# 查看日志
kubectl logs -n kube-system kube-controller-manager-xxx

📌 小结

虽然是从头部署,但整个流程清晰明确,只要细节不马虎,完全可以在家用虚拟机环境中跑一个 Kubernetes 练手集群。

下一步,我会尝试用这个集群跑起我的个人博客,并通过 Drone 实现 GitOps 风格的持续部署。

使用 Hugo 构建
主题 StackJimmy 设计