惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
C
Cybersecurity and Infrastructure Security Agency CISA
N
News and Events Feed by Topic
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
Scott Helme
Scott Helme
P
Palo Alto Networks Blog
S
Schneier on Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
量子位
G
Google Developers Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog RSS Feed
NISL@THU
NISL@THU
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
AWS News Blog
AWS News Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
Security Archives - TechRepublic
Security Archives - TechRepublic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Secure Thoughts
Cloudbric
Cloudbric
aimingoo的专栏
aimingoo的专栏
L
Lohrmann on Cybersecurity
TaoSecurity Blog
TaoSecurity Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Hacker News: Ask HN
Hacker News: Ask HN
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
P
Proofpoint News Feed
V
V2EX
Martin Fowler
Martin Fowler
C
CERT Recently Published Vulnerability Notes
Attack and Defense Labs
Attack and Defense Labs
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
SecWiki News
SecWiki News
罗磊的独立博客
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
The Last Watchdog
The Last Watchdog

博客园_首页

Linux实操--组管理、权限管理和定时任务 Java + EasyExcel 实现单个接口导出多个Excel Mem0 源码解析系列(二):提示词工程的深度剖析 Openclaw TaskFlow究竟是什么?和普通Skill技能有什么区别 博文阅读密码验证 - 博客园 嘉立创开源:应该是全网MicroPython教程最多的开发板 Hermes Agent 集成实践:从协议到生产 2026年AI编程工具横评:Cursor、Codex、Claude Code、Zed、Windsurf Java程序员必看的RAG入门教程 手机上的全能智能体,Auto小二正式开源 2026 AI效率神器:Superpowers + Claude Code 保姆级教程 本地大模型部署全攻略:从 0 到 1 玩转 Ollama 【从0到1构建一个ClaudeAgent】内存管理-上下文压缩 .NET 高级开发 | 设计、实现一个事件总线框架 电子小白入门之NE555 3. WorkBuddy:隐藏玩法,一键召唤专家,让 AI 以"专家身份"给你干活 和AI一起搞事情#3:Claude Teammate 游戏开发翻车实录 【OpenClaw】通过 Nanobot 源码学习架构---(7)Memory C# .NET 周刊|2026年3月3期 深度学习进阶(七)Data-efficient Image Transformer CLI+Skill搭建浏览器AI自动化框架,告别一切重复枯燥任务 告别Token账单无底洞:OpenClaw本地部署,重塑企业数据主权的唯一解 FastAPI+Vue:文件分片上传+秒传+断点续传,这坑我帮你踩平了! SBTI 爆火后,我做了个程序员版的 CBTI。。已开源 + 附开发过程 多模态检索开始进入工程期:用 Sentence Transformers 搭建可落地的 Multimodal RAG 100多行代码实现一个最简单的Agent(用ReAct) Claude Code 通关手册(八):推荐 5 个 Hooks,代码质量提升 3 倍 老板:“有人截图了!”。安全部门:“收到,马上查暗水印!” - why技术 技术之外,皆是人间 C#/.NET/.NET Core技术前沿周刊 | 第 69 期(2026年4.01-4.12) Snack JSONPath 项目架构分析 Claude Code Buddy 小析:一个非核心功能,如何体现产品的细节完成度 AI新时代下的图床管理方案-Cloudflare图床+MCP+Skills方案指南 化繁为简:顺丰速运App如何通过 HarmonyOS SDK实现专业级空间测量 从零实现富文本编辑器#13-React非编辑节点的内容渲染 AI开发-python-langchain框架(3-23-OpenAI Functions风格Tool Calling智能助手) .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut PbootCMS 网站内容数量多导致访问慢?这些实用优化方案帮你提速! - 家兴网络技术工作室 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 网站漏洞怎么发现并修复?一篇实用指南(附完整流程) - 家兴网络技术工作室 开了 TUN 模式还是直连?90% 的人都踩过这个坑 Github日报|2026年04月12日 - AI一族 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术 Etsy 把 1000 个 MySQL 分片迁进 Vitess:425TB 数据背后的真正问题不是性能,而是运维规模 MicroPython LVGL基础知识和概念:底层渲染与性能优化 - FreakStudio 数据库草图算法 Python 潮流周刊#146:CPython 引入 Rust 的进展 - 豌豆花下猫 最小生成树 - mofei1116 红日靶场七:从外网入口、容器逃逸到 AD 接管的完整利用链复盘 - YouDiscovered1t 分享四款开源且实用的 Kafka 管理工具 - 追逐时光者 vLLM 权重加载机制全解析:从挑战到理想架构 LCT 学习笔记 - ACehomoxue Avalonia UI 12.0.0 正式发布:架构演进和性能飞跃 - 张善友 当 AI Agent 把调用链拉长,延迟开始成为一门生意 conhost.exe 无法显示 U+2717 - 145a 太秀了,我把自己蒸馏成了 Skill!已开源 - 程序员鱼皮 ASP.NET Core 内存缓存实战:一篇搞懂该怎么配、怎么避坑 基于 Ghostty 带有分割标签页和为 Claude 编程设计的通知终端 - BugShare AI 焊死入口:教育的“操作系统级”重塑 - 郝hai 初级Java开发工程师使用sql脚本编写代码的过程是简单而且不糊涂 - CoderOilStation Claude Code通关手册(六):MCP协议完全指南 - 暮色之狐 边框灯光环绕动画特效实现指南 - Newbe36524 开源:子木蒸馏版的 SEO 审计工具 seo-audit-skill v1.0 我所理解的Python元模型 【从0到1构建一个ClaudeAgent】规划与协调-TodoWrite - 程序员Seven Claude 和 Codex 在审计 Skill 上性能差异探究 - ACai_sec AScript如何实现中文脚本引擎 - rockey627 【渗透测试】HTB Season10 Garfield 全过程wp - dynasty_chenzi Android 开发者为什么必须掌握 AI 能力?端侧视角下的技术变革 树状数组正确性证明 - AC-wyr 你的 AI 焦虑,可能比 AI 本身更危险——ATM 机没有消灭银行柜员,但恐慌消灭了你的判断力 - 我没有三颗心脏 一个拉胯的分库分表方案有多绝望?整个部门都在救火! - 冰河团队 动态规划入门必学之走方格问题 - Ofnoname PostgREST 与 PostgreSQL 角色权限配置全解析(生产级实践) - SheepDog1998 使用 UEFI 图形输出协议 GOP 在屏幕上显示图像的方法 - 阿源- Claude Code通关手册(五):组建你的AI专家团队,子代理系统 - 暮色之狐 一个程序员到架构师的催婚路之感悟(整整10年后的催婚相亲感悟) - MisterLip 用 Agent Skill 自动生成工作周报 - 赵康
我在 Debian 11 上把 K8s 单机搭起来了,过程没你想的那么顺(/opt 目录版)
陌陌卡上 · 2026-04-13 · via 博客园_首页

前言

这事儿得从前天晚上说起。我手头有一台 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集群的还是蛮多的。