LXC 搭建 K8s 集群计划通
posts/deploy-kubernetes-cluster-on-lxc最近尝试了一种比较轻量的 k8s 集群搭建方式。在单机 Arch Linux Host(kernel 7.1.7-arch1-1)上通过 LXC 创建多个容器节点,然后在这些 LXC 容器内部运行 k8s。这种方式相比直接使用虚拟机资源占用更低且创建节点速度更快(4个节点+宿主机内存占用仅为2GB)。
整体架构如下:
Host Linux
|
lxcbr0 Bridge
|
+------------+------------+------------+
| | | |
LXC Node1 LXC Node2 LXC Node3 LXC Node4
| | | |
kubelet kubelet kubelet kubelet
| | | |
k8s Cluster
环境准备
Host 安装基础组件
sudo pacman -S lxc lxcfs dnsmasq
其中:
lxc提供 Linux Container 管理能力lxcfs提供容器内部更准确的/proc信息dnsmasq为 LXC 网络提供 DHCP/DNS 服务
配置 LXC 网络
LXC 默认可以通过 lxc-net 创建 NAT 网络。编辑 /etc/default/lxc-net:
USE_LXC_BRIDGE="true"
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.3.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.3.0/24"
这里创建一个 10.0.3.0/24 网段,Host 地址为 10.0.3.1,后续 k8s 节点会使用 10.0.3.x 地址。
启动网络服务:
sudo systemctl enable --now lxc-net
检查:
ip addr show lxcbr0
应该可以看到:
4: lxcbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 10:66:6a:00:00:00 brd ff:ff:ff:ff:ff:ff
inet 10.0.3.1/24 brd 10.0.3.255 scope global lxcbr0
valid_lft forever preferred_lft forever
创建 LXC 节点
使用官方 download template 创建 Arch Linux 容器。一共需要 4 个节点,重复以下命令依次创建 arch-lxc-1 ~ arch-lxc-4。下面以 arch-lxc-1 为例:
sudo lxc-create \
-n arch-lxc-1 \
-t download \
-- \
-d archlinux \
-r current \
-a amd64
参数说明:
| 参数 | 说明 |
|---|---|
-n | 容器名称 |
-t download | 使用下载模板 |
-d | Linux 发行版 |
-r | Release |
-a | CPU 架构 |
启动,这里的-d 表示 daemon 模式运行:
sudo lxc-start arch-lxc-1 -d
进入容器:
sudo lxc-attach arch-lxc-1
能进去的话就说明容器没什么问题了。
为 k8s 修改 LXC 配置
k8s 默认需要访问 cgroup、proc、sys、/dev/kmsg等,而普通 LXC 容器默认限制较多,需要调整。
以下配置需要对所有 4 个 LXC 节点 (
arch-lxc-1~arch-lxc-4) 各执行一次,下面以arch-lxc-1为例。
编辑 /var/lib/lxc/arch-lxc-1/config,加入:
# 嵌套容器与特权设备访问
lxc.include = /usr/share/lxc/config/nesting.conf
lxc.apparmor.profile = unconfined
lxc.cgroup2.devices.allow = a
lxc.mount.auto = proc:mixed sys:rw cgroup:rw
# k8s 额外需要
features = nesting=1,keyctl=1
lxc.mount.entry = /dev/kmsg dev/kmsg none bind,create=file
lxc.mount.entry = proc proc proc rw,nosuid,nodev,noexec,relatime 0 0
重启容器:
lxc-stop arch-lxc-1
lxc-start arch-lxc-1
Host 开启 k8s 必需 Kernel Module
k8s 网络需要 overlay filesystem 和 bridge netfilter。需要在 Host 上加载:
sudo modprobe overlay
sudo modprobe br_netfilter
设置开机加载 /etc/modules-load.d/k8s.conf:
overlay
br_netfilter
LXC 安装 containerd
以下操作需要在每个 LXC 节点内重复执行。
进入 LXC 节点:
sudo lxc-attach arch-lxc-1
官方 download template 拉下来的容器 keyring 可能过期,先同步一下:
pacman -Sy
安装 containerd:
pacman -S containerd
启动:
systemctl enable --now containerd
生成默认配置:
mkdir /etc/containerd
containerd config default \
| tee /etc/containerd/config.toml
k8s 推荐使用 systemd cgroup,修改 /etc/containerd/config.toml:
sed -i \
's/SystemdCgroup = false/SystemdCgroup = true/' \
/etc/containerd/config.toml
重启:
systemctl restart containerd
测试:
ctr version
正常情况下可以看到 containerd client/server 信息。
Client:
Version: v2.3.3
Revision: aad11006b869517fcd3009450b6f82da282e1a9b.m
Go version: go1.26.5-X:nodwarf5
Server:
Version: v2.3.3
Revision: aad11006b869517fcd3009450b6f82da282e1a9b.m
UUID: 418cba5e-e128-4af5-ae41-f91cea65ea19
安装 k8s 组件
以下操作需要在每个 LXC 节点内重复执行。
pacman -S kubeadm kubelet
此处不要
enable kubelet,kubeadm init 之前启动会立即报错,master init 成功后再启用即可。
配置 k8s 网络参数
以下操作需要在每个 LXC 节点内重复执行。
创建 /etc/sysctl.d/k8s.conf:
sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
EOF
加载:
sudo sysctl --system
检查各节点 IP,master 节点的 IP(例如 10.0.3.49)后面 kubeadm init 要用:
ip addr
初始化 k8s Master
使用 kubeadm:
sudo kubeadm init \
--apiserver-advertise-address=10.0.3.49 \
--pod-network-cidr=192.168.0.0/16
参数说明:
apiserver-advertise-address:指定 k8s API Server 对外监听地址。这里使用 LXC 网络地址10.0.3.49。pod-network-cidr:指定 Pod 网络范围,例如192.168.0.0/16,后续安装 CNI 时需要保持一致。
这个初始化需要一段时间,几分钟后看到以下输出:
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
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.0.3.49:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
init 成功后启用 kubelet:
sudo systemctl enable --now kubelet
把 KUBECONFIG 持久化到 /etc/environment:
echo 'KUBECONFIG=/etc/kubernetes/admin.conf' | sudo tee -a /etc/environment
接着部署 Calico CNI(pod 网络需要):
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.2/manifests/calico.yaml
稍等片刻后,把 init 末尾的 kubeadm join 命令在另外三个容器内执行一遍即可。
三个 worker join 后也需要 enable kubelet,确保重启后自启:
sudo systemctl enable kubelet
所有节点加入后验证集群:
kubectl get nodes
四个节点均为 Ready:
NAME STATUS ROLES AGE VERSION
arch-lxc-1 Ready control-plane 23h v1.36.3
arch-lxc-2 Ready <none> 23h v1.36.3
arch-lxc-3 Ready <none> 23h v1.36.3
arch-lxc-4 Ready <none> 23h v1.36.3
总结
整体流程:Host 装 LXC + 配网 → 拉 4 个 Arch 容器 → 改 LXC config 让其支持 k8s → 节点内装 containerd + kubeadm/kubelet + 调 sysctl → master init → 部署 Calico CNI → worker join → kubectl get nodes 验证。
LXC 运行 k8s 是一个非常适合学习 k8s 原理的方案。
相比 Docker-in-Docker:
- LXC 提供更完整的 Linux 环境
- kubelet/containerd 可以按照接近真实服务器的方式运行
- 节点创建速度非常快
但是也需要处理 cgroup、AppArmor、proc mount、kernel module 等问题。