首页 > 基础资料 博客日记

我在 Debian 11 上把 K8s 单机搭起来了,过程没你想的那么顺(/opt 目录版)

2026-04-13 19:00:02基础资料围观1

本篇文章分享我在 Debian 11 上把 K8s 单机搭起来了,过程没你想的那么顺(/opt 目录版),对你有帮助的话记得收藏一下,看极客资料网收获更多编程知识

前言

这事儿得从前天晚上说起。我手头有一台 Debian 11 的虚拟机,想着搭个 K8s 单节点环境平时做实验用。网上教程一搜一大把,可真跟着做的时候才发现,十个教程九个坑,还有一个写了一半就不见了。

踩了两天坑之后,我终于把这套流程捋顺了,而且还特意把所有数据目录都挪到了 /opt 下面——因为系统盘就剩 20G,不挪地方早晚要崩。我把整个过程记了下来,既给自己留个底,也给遇到同样问题的朋友省点时间。这篇文章不是流水账,里面夹了不少我的真实感受,比如“呵呵,这我没想到”的那种瞬间,你懂的。

强烈建议搭配AI食用(当然,也别把AI太当一回事~)


环境与思路

项目 我的实际配置
主机名 k8s-master
IP 192.168.1.10(改成你自己的)
系统 Debian 11
数据目录 /opt(所有容器、kubelet 数据都放这)
Kubernetes v1.31
容器运行时 containerd
网络插件 Flannel

重点:IP 和主机名后面会反复用到,千万别写错了。我第一遍就是 hosts 文件里多打了一个空格,结果 kubeadm init 直接报错退出了,排查了半小时,只能说“没办法,自己手贱”。


一、把主机名和 hosts 收拾干净

这是第一步,也是最容易翻车的一步。很多人上来就装软件,结果后面 service 启动不了还不知道为什么。

sudo hostnamectl set-hostname k8s-master

然后编辑 /etc/hosts

sudo nano /etc/hosts

内容改成这样(注意 IP 换成你自己的):

127.0.0.1       localhost
127.0.1.1       k8s-master

192.168.1.10    k8s-master

验证一下解析:

hostname
hostname -i

必须返回你的真实 IP,否则 kubelet 会找不到北。


二、系统初始化,顺手装些常用工具

这步没啥好说的,纯体力活:

sudo apt update
sudo apt upgrade -y
sudo apt install -y curl vim wget net-tools gnupg lsb-release

早知道后面要频繁 curl,我第一个就该装它。


三、iptables 切换成 legacy 模式——Debian 11 绕不过的坎

Deiban 11 默认用的是 nftables,而 K8s 的一些组件(尤其是 kube-proxy)跟 legacy 模式更搭。不切换的话,后面网络会有各种莫名其妙的问题。我一开始没当回事,结果 Pod 之间死活不通,查了半天日志才发现是这里。

sudo apt install -y iptables arptables ebtables

sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo update-alternatives --set arptables /usr/sbin/arptables-legacy
sudo update-alternatives --set ebtables /usr/sbin/ebtables-legacy

检查一下:

iptables --version

看到 (legacy) 字样就对了。呵呵,这步不做后面有你哭的时候。


四、关掉 Swap,不然 kubelet 会抗议

Kubernetes 很固执,它认为 swap 会影响性能,所以只要检测到 swap 开着,kubelet 就直接罢工。

sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

free -m 看一眼,Swap 那行全是 0 就对了。


五、加载内核模块

两个模块必须提前加载:overlaybr_netfilter,一个是给容器文件系统用的,一个是给网络桥接用的。

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

sudo modprobe overlay
sudo modprobe br_netfilter

六、调整 sysctl 参数

这几个参数允许 iptables 正确看到桥接流量,并且开启内核转发。

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

七、对个时

分布式系统对时间很敏感,差太多的话证书验证都会失败。装个 chrony 省心:

sudo apt install -y chrony
sudo systemctl enable chrony
sudo systemctl start chrony
timedatectl

看到 System clock synchronized: yes 就放心了。


八、创建 /opt 下的数据目录

这是为了把数据从系统盘挪出来,毕竟根分区空间金贵。

sudo mkdir -p /opt/containerd
sudo mkdir -p /opt/kubelet
sudo mkdir -p /opt/etcd
sudo mkdir -p /opt/cni
sudo mkdir -p /opt/log

其实 etcd 在单机下默认放 /var/lib/etcd,但我们可以后面通过配置改掉,或者直接软链接,这个按需来。我这里先建着,后面 kubeadm init 的时候会用到 /opt/etcd


九、安装 containerd(用 Docker 官方源)

用 Docker 的官方 containerd 包,版本比较新,兼容性也好。

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg

echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list

sudo apt update
sudo apt install -y containerd.io

然后生成默认配置并修改两个地方:数据根目录SystemdCgroup

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

编辑配置文件:

sudo nano /etc/containerd/config.toml

找到 root 字段改成 /opt/containerd,找到 SystemdCgroup 改成 true

root = "/opt/containerd"
state = "/run/containerd"

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

重启并设置开机自启:

sudo systemctl restart containerd
sudo systemctl enable containerd

十、安装 Kubernetes 组件

添加官方源,然后装 kubelet、kubeadm、kubectl,并锁定版本防止被意外升级。

sudo mkdir -p /etc/apt/keyrings

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/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.31/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

十一、把 kubelet 的数据目录也改到 /opt

默认 kubelet 会把数据存在 /var/lib/kubelet,这跟我们的规划不符。通过 systemd 的 drop-in 文件来覆盖启动参数。

sudo mkdir -p /etc/systemd/system/kubelet.service.d

创建配置文件:

cat <<EOF | sudo tee /etc/systemd/system/kubelet.service.d/10-kubelet.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--root-dir=/opt/kubelet"
EOF

重载并重启 kubelet:

sudo systemctl daemon-reload
sudo systemctl restart kubelet

这一步在 init 之前做最合适,因为 init 的时候 kubelet 会开始写数据,如果不提前改目录,就会写到 /var/lib 下面去,后面再挪就麻烦了。早知道我第一遍就该这么干


十二、kubeadm init——最紧张的一步

终于要初始化集群了。先装几个必要的网络工具包(kubeadm 依赖它们):

sudo apt update
sudo apt install -y conntrack ebtables ethtool socat iproute2

然后执行 init。注意把 --apiserver-advertise-address 换成你自己的 IP,--pod-network-cidr 使用 10.244.0.0/16 是为了和 Flannel 默认网段匹配。

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.png

如果一切顺利,最后会输出一段 kubeadm join ... 的命令,一定保存下来!虽然我们是单节点用不上 join,但万一以后想加节点呢?

如果失败了怎么办?我就失败过一次,因为之前残留了一些配置。这时候需要彻底清理:

sudo kubeadm reset -f
sudo rm -rf /var/lib/etcd
sudo rm -rf /etc/kubernetes/manifests/*

然后再重新 init。这个过程就像重启电脑,没什么大不了,就是多等几分钟。


十三、配置 kubectl 让普通用户也能用

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

测试一下:

kubectl get nodes

这时候节点状态应该是 NotReady,因为网络插件还没装。别慌,这是正常的。

image.png


十四、安装 Flannel 网络插件

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

等个一两分钟,再 kubectl get nodes,状态就变成 Ready 了。我第一次看到这个结果的时候长舒一口气——总算没白折腾。

image.png


十五、允许 Master 节点调度 Pod(单机必做)

默认情况下,Master 节点是打了污点(taint)的,不允许普通 Pod 运行。我们既然是单机,就得去掉它:

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

验证一下污点没了:

kubectl describe node | grep -i taint

十六、跑个 Nginx 测试一下

kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc nginx

记下那个 30000+ 的端口,浏览器访问 http://你的服务器IP:端口,看到 Nginx 欢迎页就说明集群完全可用了。

测试完可以把这俩资源删掉,免得占用端口:

kubectl delete deployment nginx
kubectl delete service nginx

十七、最终的数据目录结构

检查一下我们的劳动成果:

ls /opt/containerd
ls /opt/kubelet

应该能看到 containerd 的元数据、kubelet 的 pod 目录都乖乖躺在这里。没白费功夫。


十八、完整的安装顺序——很多人失败就是因为跳步

如果你是按我的步骤从头做下来的,顺序应该是这样的:

  1. 修改 hostname + hosts
  2. apt update && upgrade
  3. iptables 切换 legacy
  4. 关闭 swap
  5. 加载内核模块
  6. 设置 sysctl
  7. 时间同步
  8. 安装 containerd 并配置
  9. 安装 kubeadm/kubelet/kubectl
  10. 修改 kubelet 数据目录
  11. kubeadm init
  12. 配置 kubectl
  13. 安装 Flannel
  14. 去除 Master 污点
  15. 测试部署

Kubernetes 安装失败,90% 都是顺序错了,或者是某一步没生效就急着往下走。没办法,这玩意就是环环相扣,少一个螺丝都不行。


进阶:想让这套环境更好用?聊聊 Kite 和其他组件

你可能会问,接下来我该装什么?我见过不少新手搭完集群就迷茫了。其实 Kubernetes 本身只提供基础能力,后面要加的东西都是“选装包”。下面我结合自己的使用习惯和你提到的 Kite 说说怎么选。

这些组件到底要不要装?

组件 是否必须 我的建议
Helm 非必须,但强烈推荐 K8s 的应用商店,后面装 Kite 也会用到,先装上吧。
Ingress Nginx 非必须 如果你想用域名访问集群里的服务(比如 Kite 控制台),就需要;单机 IP 访问可以暂时不装。
Kubernetes Dashboard 非必须 Kite 完全可以替代它,界面好看功能还多,没必要装两个。
Metrics Server 非必须 想让 Kite 或 kubectl top 看到 CPU/内存曲线,就必须装,否则图表是空的。
Prometheus + Grafana 非必须 Kite 已经内置了基础监控图表,除非你需要长期存储和高级告警,否则先放一放。
StorageClass 非必须 跑无状态应用用不到,等你想玩数据库了再说。单机测试用 hostPath 就行。

Kite 能覆盖哪些?

根据官方介绍,Kite 自带:

  • 资源管理界面(替代 Dashboard)
  • 实时 CPU/内存/网络图表(需要 Metrics Server 提供数据)
  • Web 终端(直接进容器操作)
  • 日志查看、YAML 编辑
  • 多集群切换

所以我个人觉得,对于单机实验环境,装个 Kite 就够你玩的了

我推荐的后续安装顺序

1. 安装 Helm

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

2. 安装 Metrics Server

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

注意:在某些自签证书的环境下,Metrics Server 可能需要添加 --kubelet-insecure-tls 参数才能正常工作。如果装完 Kite 看不到监控数据,记得去检查一下 Metrics Server 的日志。

3. 用 Helm 部署 Kite

helm repo add kite https://kite-org.github.io/kite/
helm repo update
helm install kite kite/kite -n kube-system

4. 访问 Kite

默认 Kite 的 Service 是 ClusterIP 类型,只能集群内部访问。最简单暴力的方式是用 kubectl port-forward

nohup kubectl port-forward -n kube-system svc/kite 8080:8080 &

然后浏览器打开 http://你的服务器IP:8080 就行。

云服务器访问不了怎么办?

如果你用的是云服务器,port-forward 默认只监听 127.0.0.1,外网是打不开的。这时候有两个办法:

办法一:改用 NodePort

kubectl patch svc kite -n kube-system -p '{"spec":{"type":"NodePort"}}'
kubectl get svc -n kube-system kite

会看到一个类似 8080:31234 的端口映射,去云控制台的安全组里开放那个 31234 端口,然后公网访问 http://公网IP:31234 即可。

办法二:配置 Nginx 反向代理

在宿主机上装个 Nginx,把域名流量转发到 127.0.0.1:8080,再加个 SSL 证书,体验和线上服务一样。具体配置不展开,网上大把教程。


写在最后

这篇文章算是我这几天折腾 Debian 11 + K8s 的一个完整记录。过程中无数次想砸键盘,但最后看到 Nginx 页面和 Kite 仪表板的那一刻,又觉得挺值的。如果你也正在啃这块硬骨头,希望这篇笔记能帮你少走弯路。

要是你在哪一步卡住了,或者发现有更好的优化方法,欢迎在评论区交流——毕竟 K8s 的世界里,谁还不是一边踩坑一边成长呢?

PS:单机版k8s纯手搓也就图一乐,市面上快速搭建k8s集群的还是蛮多的。


文章来源:https://www.cnblogs.com/liwangwang/p/19861383
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云