kubeadm部署Kubernetes

在当今的云原生时代,Kubernetes(简称 K8s)已不再仅仅是一个容器编排工具,它是现代应用架构的基石,是连接开发效率与运维稳定性的桥梁。然而,对于许多初学者而言,K8s 陡峭的学习曲线和复杂的组件依赖往往让人望而却步。尤其是当面对”节点未就绪”、”镜像拉取失败”或”网络插件冲突”等常见陷阱时,一次次的初始化失败极易消磨学习的热情。

本指南并非一份枯燥的命令罗列,而是一次真实的、基于 2C4G 低配云服务器的全流程实战记录。我们摒弃了理想化的实验室环境,直面国内网络访问受限、系统资源紧张以及 Docker 与 Kubelet 配置冲突等现实挑战。

第一步:系统初始化(必须执行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 关闭 Swap
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

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

# 3. 设置 sysctl
cat <<EOF | sudo tee /etc/sysctl.d/k99-kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system

# 4. 安装依赖
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release conntrack

第二步:安装 Docker(如果已安装可跳过)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 添加 Docker GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg

# 添加 Docker 源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 启动并启用
sudo systemctl enable docker
sudo systemctl start docker

# 将当前用户加入 docker 组(避免每次输 sudo)
sudo usermod -aG docker $USER

第三步:安装 cri-dockerd(关键步骤!)

这是让 K8s 兼容 Docker 的核心组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 下载 cri-dockerd 二进制文件(以 amd64 为例,如果是 arm64 请改链接)
VERSION="0.3.12"
ARCH="amd64"
wget https://github.com/Mirantis/cri-dockerd/releases/download/v${VERSION}/cri-dockerd-${VERSION}.${ARCH}.tgz
tar -xvf cri-dockerd-${VERSION}.${ARCH}.tgz
sudo mv cri-dockerd/cri-dockerd /usr/local/bin/

# 2. 安装 systemd 服务文件
wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service
wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket

sudo mv cri-docker.service cri-docker.socket /etc/systemd/system/

# 3. 修改 service 文件,指定 socket 路径
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

# 4. 启动 cri-dockerd
sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket

第四步:安装 Kubeadm, Kubelet, Kubectl

我们使用阿里云源加速。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 添加阿里云 GPG 密钥
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -

# 2. 添加阿里云源
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

# 3. 安装指定版本(推荐 1.28,稳定且兼容性好)
sudo apt-get update
sudo apt-get install -y kubelet=1.28.2-00 kubeadm=1.28.2-00 kubectl=1.28.2-00

# 4. 锁定版本
sudo apt-mark hold kubelet kubeadm kubectl

# 5. 启用 kubelet
sudo systemctl enable kubelet

第五步:初始化集群(Init)

初始化之前我们需要手动从阿里云拉取 pause 镜像,并将其重命名为 Kubelet 期望的名字。

1
2
3
4
5
# 1. 从阿里云拉取 pause 镜像(版本 3.9 对应 K8s 1.28)
sudo docker pull registry.aliyuncs.com/google_containers/pause:3.9

# 2. 将其标记为 Kubelet 默认寻找的名字
sudo docker tag registry.aliyuncs.com/google_containers/pause:3.9 registry.k8s.io/pause:3.9

然后初始化,注意这里我们要显式指定 --cri-socket 指向 cri-dockerd。

1
2
3
4
5
sudo kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers \
--cri-socket=unix:///var/run/cri-dockerd.sock \
--ignore-preflight-errors=NumCPU,Mem
  • --cri-socket: 告诉 kubeadm 使用 cri-dockerd 而不是 containerd。
  • --ignore-preflight-errors=NumCPU,Mem: 忽略 2C4G 的资源检查报错。

等待初始化完成,看到 Your Kubernetes control-plane has initialized successfully! 后,执行提示中的命令:

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

第六步:安装网络插件(Calico)

Calico 是生产环境的事实标准,功能更强(支持网络策略)。

1
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml

如果下载慢,可以使用这个国内镜像地址:

1
kubectl apply -f https://ghproxy.net/https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml

等待 Pod 启动,Calico 需要一点时间来拉取镜像并启动。执行以下命令观察状态:

1
watch kubectl get pods -n kube-system

当所有 Pod 的状态都变为 Running 时,按 Ctrl+C 退出。

再次检查节点状态:

1
kubectl get nodes

此时,节点状态应该从 NotReady 变为 Ready。

第七步:移除 Master 污点(单节点必备)

默认 Master 不跑业务,我们需要强制让它跑。

1
kubectl taint nodes --all node-role.kubernetes.io/control-plane-

接下来做什么?

你可以尝试部署一个 Nginx 来测试网络是否通畅。

创建 Deployment

执行以下命令,K8s 会从 Docker Hub 拉取 nginx:alpine 镜像并启动一个 Pod:

1
kubectl create deployment my-nginx --image=nginx:alpine --port=80
  • my-nginx: 你给这个应用起的名字。
  • --image=nginx:alpine: 使用的镜像。
  • --port=80: 告诉 K8s 这个容器监听 80 端口。

检查 Pod 状态

执行以下命令查看 Pod 是否运行成功:

1
kubectl get pods
  • STATUS: Running 表示容器已经成功启动。
  • READY: 1/1 表示容器已准备好接收流量。
  • 如果状态是 ContainerCreating,请稍等几秒再查,因为第一次需要拉取镜像。

暴露服务(让外部能访问)

默认情况下,Pod 只能在集群内部访问。为了让你的浏览器能访问它,我们需要创建一个 Service,并将其类型设置为 NodePort:

1
kubectl expose deployment my-nginx --type=NodePort --port=80

获取访问地址

执行以下命令查看服务分配的端口:

1
kubectl get svc my-nginx

注意看 PORT(S) 列:80:32124/TCP。

  • 80 是容器内部端口。
  • 32124 是映射到你服务器上的节点端口(你的数字可能不同,请以实际输出为准)。

浏览器访问

打开浏览器,访问:

1
http://<你的服务器公网IP>:<节点端口>

例如:http://1.2.3.4:32124

如果你看到了 “Welcome to nginx!” 的页面,恭喜你!你已经成功用 Kubernetes 部署并暴露了一个应用!

删除 Nginx

要删除刚才部署的 Nginx,你需要同时删除 Deployment(负责管理容器)和 Service(负责暴露端口)。

1
2
3
4
5
# 1. 删除 Deployment(这会自动删除对应的 Pod)
kubectl delete deployment my-nginx

# 2. 删除 Service(释放节点端口)
kubectl delete svc my-nginx

验证是否删除干净

执行以下命令,确保列表中没有残留:

1
kubectl get all

如果输出中不再显示 my-nginx 相关的行,说明已经彻底清理完毕。你的集群又恢复到初始的干净状态了!