先确定你的部署方式

你要先决定:

  • 方案 A:单机 Kubernetes
    • 只有一台树莓派,先搭一个单节点集群学习。
  • 方案 B:多机 Kubernetes
    • 比如:
      • 1 台 master/control-plane
      • 1~N 台 worker

下面是 最通用的 kubeadm 方式 ,默认:

  • 系统:Raspberry Pi OS 64-bit / Ubuntu Server 64-bit
  • 架构:arm64
  • 容器运行时:containerd
  • 网络插件:Flannel
  • Kubernetes:v1.29 系列

准备工作:每台树莓派都要做

如果你以后要做多节点,这一部分所有节点都要执行。如果你只有一台,也一样执行。

第 1 步:查看系统信息

先执行:

1
2
3
uname -m
cat /etc/os-release
hostname -I

需要重点看:uname -m 是否是 aarch64,并记住当前树莓派 IP

第 2 步:更新系统

1
2
sudo apt update
sudo apt upgrade -y

安装常用工具:

1
sudo apt install -y curl wget vim git net-tools htop ca-certificates gnupg lsb-release apt-transport-https

第 3 步:设置主机名

如果你只有一台机器,可以命名为:

1
sudo hostnamectl set-hostname rpi-master

如果是多台:

  • master:rpi-master
  • worker1:rpi-node1
  • worker2:rpi-node2

查看:

1
hostname

第 4 步:配置 hosts

编辑:

1
sudo nano /etc/hosts

如果你是单节点,至少保留本机解析。
如果是多节点,建议写成这样:

1
2
3
192.168.1.10 rpi-master
192.168.1.11 rpi-node1
192.168.1.12 rpi-node2

把 IP 换成你自己的。

关闭 swap

Kubernetes 要求关闭 swap。先临时关闭:

1
sudo swapoff -a

再永久关闭:

1
sudo sed -i '/ swap / s/^/#/' /etc/fstab

检查:

1
free -h

确认 Swap 一栏是 0。

开启内核模块和网络转发

这是 Kubernetes 网络能正常工作的关键。

第 1 步:加载内核模块

执行:

1
2
3
4
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

然后加载:

1
2
sudo modprobe overlay
sudo modprobe br_netfilter

第 2 步:设置内核参数

执行:

1
2
3
4
5
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

应用配置:

1
sudo sysctl --system

验证:

1
sysctl net.ipv4.ip_forward

应该输出:

1
net.ipv4.ip_forward = 1

配置树莓派 cgroup

这一步非常重要,否则 kubelet 容易出问题。树莓派系统一般需要手工加启动参数。

第 1 步:编辑启动参数

先判断文件在哪,常见是:

1
/boot/firmware/cmdline.txt

也有可能是:

1
/boot/cmdline.txt

你可以先试:

1
2
ls /boot/firmware/cmdline.txt
ls /boot/cmdline.txt

编辑对应文件,例如:

1
sudo nano /boot/firmware/cmdline.txt

注意:这个文件通常只有一整行,不要换行。在这一行末尾追加:

1
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

例如原来是:

1
console=serial0,115200 console=tty1 root=PARTUUID=xxxx rootfstype=ext4 fsck.repair=yes rootwait

改成:

1
console=serial0,115200 console=tty1 root=PARTUUID=xxxx rootfstype=ext4 fsck.repair=yes rootwait cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

第 2 步:重启

1
sudo reboot

重启后检查:

1
cat /proc/cgroups

安装并配置 containerd

即使你有 Docker,也建议明确配置 containerd

第 1 步:安装 containerd

1
2
sudo apt update
sudo apt install -y containerd

第 2 步:生成默认配置

1
2
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null

第 3 步:修改 cgroup 驱动

编辑配置:

1
sudo nano /etc/containerd/config.toml

找到这一行:

1
SystemdCgroup = false

改成:

1
SystemdCgroup = true

第 4 步:重启并设置开机启动

1
2
sudo systemctl restart containerd
sudo systemctl enable containerd

检查:

1
sudo systemctl status containerd

如果看到 active (running) 就正常。

安装 Kubernetes 组件

安装:kubelet,kubeadm,kubectl

第 1 步:添加 Kubernetes 官方仓库

安装依赖:

1
2
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gpg

添加 key:

1
2
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

添加源:

1
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

第 2 步:安装组件

1
2
3
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

查看版本:

1
2
3
kubeadm version
kubectl version --client
kubelet --version

配置 Docker 与 containerd 关系

如果你只是拿 Docker 平时自己用,可以保留。但 Kubernetes 主要走 containerd。建议检查 containerd socket:

1
ls /run/containerd/containerd.sock

如果存在,一般就没问题。

拉取 Kubernetes 镜像

先看 kubeadm 需要哪些镜像:

1
kubeadm config images list

然后拉取:

1
sudo kubeadm config images pull --cri-socket unix:///run/containerd/containerd.sock

如果下载慢或者失败,需要换国内镜像。对应的命令如下所示:

1
sudo kubeadm config images pull --cri-socket unix:///run/containerd/containerd.sock --image-repository registry.aliyuncs.com/google_containers

初始化 Kubernetes 控制平面

如果你现在只有一台树莓派,这一步就是最关键的一步。先查看本机 IP:

1
hostname -I

假设你的树莓派 IP 是:

1
192.168.1.10

执行初始化:

1
2
3
4
sudo kubeadm init \
--apiserver-advertise-address=192.168.1.10 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket unix:///run/containerd/containerd.sock

说明:

  • --apiserver-advertise-address:你的 master IP
  • --pod-network-cidr=10.244.0.0/16:给 Flannel 用
  • --cri-socket:指定 containerd

初始化可能要几分钟。成功后你会看到类似:

1
Your Kubernetes control-plane has initialized successfully!

并且下面会给你一段 kubeadm join ... 命令。一定复制保存,后续 worker 节点加入要用。如果拉取失败,可以采用国内镜像,对应命令如下:

1
2
3
4
5
sudo kubeadm init \
--apiserver-advertise-address=192.168.1.10 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket unix:///run/containerd/containerd.sock \
--image-repository registry.aliyuncs.com/google_containers

同时需要编辑配置文件:

1
sudo nano /etc/containerd/config.toml

将其中的sandbox_image = "..."改成sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.10.2",接着重启 containerd 和 kubelet:

1
2
sudo systemctl restart containerd
sudo systemctl restart kubelet

检查:

1
2
sudo systemctl status containerd --no-pager
sudo systemctl status kubelet --no-pager

配置 kubectl

初始化成功后,执行下面命令,让当前用户能直接用 kubectl

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

测试:

1
kubectl get nodes

这时大概率会看到节点是:

1
NotReady

这是正常的,因为你还没装网络插件。

安装 CNI 网络插件(Flannel)

执行:

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

然后查看:

1
kubectl get pods -A

等几十秒到几分钟,再查看:

1
kubectl get nodes

如果正常,节点会变成:

1
Ready

如果你只有一台树莓派:允许 master 运行业务 Pod

默认 control-plane 节点有污点,不让普通 Pod 调度上去。单机学习环境可以去掉:

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

然后再看:

1
kubectl get nodes

这样你的单机节点既是 master,也能跑应用。

部署一个测试应用

先部署 nginx:

1
kubectl create deployment nginx --image=nginx

暴露服务:

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

查看 Pod:

1
kubectl get pods -o wide

查看 Service:

1
kubectl get svc

你会看到类似:

1
nginx   NodePort   10.x.x.x   <none>   80:3xxxx/TCP

然后访问:

1
http://你的树莓派IP:3xxxx

比如:

1
http://192.168.1.10:31234

如果能打开 nginx 欢迎页,说明整个 Kubernetes 已经跑起来了。

如果你有多台树莓派:worker 加入集群

在其他树莓派上,重复前面的步骤:

  • 更新系统
  • 关闭 swap
  • 配置 cgroup
  • 安装 containerd
  • 安装 kubelet kubeadm kubectl

但不要执行 kubeadm init,而是在 worker 节点执行 master 初始化后给你的 join 命令,例如:

1
2
3
4
sudo kubeadm join 192.168.1.10:6443 \
--token abcdef.1234567890abcdef \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
--cri-socket unix:///run/containerd/containerd.sock

回到 master 查看:

1
kubectl get nodes -o wide

如果成功,你会看到:

  • rpi-master Ready
  • rpi-node1 Ready
  • rpi-node2 Ready

常用管理命令

查看节点

1
kubectl get nodes -o wide

查看所有 Pod

1
kubectl get pods -A

查看服务

1
kubectl get svc -A

查看 deployment

1
kubectl get deployment -A

查看详细信息

1
2
kubectl describe node rpi-master
kubectl describe pod <pod名> -n <命名空间>

查看日志

1
kubectl logs <pod名>

如果 Pod 有多个容器:

1
kubectl logs <pod名> -c <容器名>

开机启动

一般以下服务都应自动启动:

containerd

1
sudo systemctl enable containerd

kubelet

1
sudo systemctl enable kubelet

检查:

1
2
systemctl is-enabled containerd
systemctl is-enabled kubelet

如果你想确认 Kubernetes 是否真的可用

执行:

1
2
3
kubectl create deployment hello --image=nginx
kubectl expose deployment hello --port=80 --type=NodePort
kubectl get pods,svc

删除测试:

1
2
kubectl delete svc hello
kubectl delete deployment hello

常见问题排查

问题 1:kubeadm init 失败

看 kubelet 日志:

1
sudo journalctl -u kubelet -f

常见原因:

  • swap 没关
  • cgroup 参数没加
  • containerd 没启动
  • SystemdCgroup = true 没配

问题 2:节点一直 NotReady

通常是网络插件没装好。

查看:

1
kubectl get pods -A

重点看:

  • kube-flannel
  • coredns

如果 flannel 没起来,节点通常不会 Ready。

问题 3:镜像拉取失败

先看需要拉哪些镜像:

1
kubeadm config images list

再手工拉:

1
sudo kubeadm config images pull --cri-socket unix:///run/containerd/containerd.sock

问题 4:端口访问不到 NodePort

检查:

1
2
kubectl get svc
sudo ss -lntp

确认:

  • 服务类型是 NodePort
  • 防火墙没拦截
  • 访问的是树莓派真实 IP

从零开始的最简命令版

如果你只想先在 一台树莓派 快速跑起来,可以按下面顺序直接做。

1)基础配置

1
2
3
4
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget vim git net-tools htop ca-certificates gnupg lsb-release apt-transport-https
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

2)模块和内核参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

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

3)编辑 /boot/firmware/cmdline.txt/boot/cmdline.txt

末尾加:

1
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

然后:

1
sudo reboot

4)安装 containerd

1
2
3
4
5
6
7
sudo apt update
sudo apt install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

5)安装 Kubernetes

1
2
3
4
5
6
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/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.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

6)初始化

把下面 IP 改成你自己的:

1
2
3
4
sudo kubeadm init \
--apiserver-advertise-address=192.168.1.10 \
--pod-network-cidr=10.244.0.0/16 \
--cri-socket unix:///run/containerd/containerd.sock

7)配置 kubectl

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

8)安装 flannel

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

9)单机允许调度

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

10)验证

1
2
3
4
5
kubectl get nodes
kubectl get pods -A
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc