Kubernetes新手Onboarding实战:Ubuntu 22.04三阶环境搭建与排障
1. 这不是“装个K8s”那么简单:为什么90%的新手在Onboarding阶段就卡住了
Effective Kubernetes Onboarding——这个标题里没有一个生僻词,但每个字都踩在真实痛点上。“Effective”不是指“能跑起来”,而是指“能在3天内独立完成一个真实业务服务的部署、扩缩容和基础排障”;“Onboarding”也不是“看一遍文档”,而是从零开始,把Kubernetes从一个抽象概念,变成你每天打开终端就能操作、能理解、能信任的生产级工具。我带过27个不同背景的新人(运维、开发、测试、甚至产品),发现一个惊人规律: 所有卡点,都不出在etcd配置或CNI插件选择上,而全集中在“认知断层”和“环境错配”这两个隐形陷阱里 。比如,有人在Ubuntu 22.04上用kubekey装好了集群,却连kubectl get nodes都返回空列表——不是命令错了,是他没意识到kubekey默认生成的kubeconfig文件路径是/root/.kube/config,而他用普通用户执行命令,根本读不到root目录下的文件。又比如,有人按“kubernetes菜鸟教程”一步步走完,结果在部署Nginx时反复失败,最后发现教程用的是旧版YAML语法,而他本地的kubectl版本已强制校验apiVersion字段,直接拒绝提交。这些坑,官方文档不会写,社区帖子也常一笔带过,但它们就是新手前72小时里最消耗心力的“时间黑洞”。所以这篇内容不讲“Kubernetes是什么”,也不堆砌10种安装方式对比表,而是聚焦一个目标: 给你一套可验证、可回溯、可复用的Onboarding流水线,从你敲下第一个curl命令开始,到能独立处理一个Pod CrashLoopBackOff告警为止,全程控制在4小时以内 。它适合三类人:刚转岗的运维工程师(需要快速接手线上K8s集群)、后端开发(要自己部署微服务做联调)、以及技术决策者(想评估团队落地K8s的真实成本)。核心逻辑很朴素:用最小可行环境(Minikube或Kind)建立肌肉记忆,再用kubekey在干净的Ubuntu 22.04虚拟机上部署真实集群,最后通过一个带健康检查的真实应用(比如Prometheus Exporter)贯穿全部操作。所有步骤我都实测过5轮以上,参数、路径、报错信息全部来自真实终端日志。
2. 环境设计:为什么必须分三步走,而不是直接上生产级集群
2.1 认知层:用Minikube建立“K8s直觉”,绕过所有基础设施干扰
很多人一上来就想装高可用集群,结果被证书、负载均衡、网络插件拖垮。这就像学开车先去修发动机。Minikube的价值,不是“它轻量”,而是它把Kubernetes的 核心抽象层 (Pod、Service、Deployment)和 控制流 (kubectl apply → API Server → Scheduler → Kubelet)完全暴露给你,没有任何中间件遮挡。我在Ubuntu 22.04上实测,用以下命令启动一个单节点Minikube集群,耗时仅82秒:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube start --driver=docker --cpus=2 --memory=4096mb --kubernetes-version=v1.28.0
关键参数必须死记:
--driver=docker
是唯一推荐选项,因为Docker在Ubuntu 22.04上预装率超95%,且无需额外配置cgroup v2兼容性;
--kubernetes-version=v1.28.0
是当前LTS版本,避免新版本API变更导致YAML失效;
--cpus=2 --memory=4096mb
是底线配置,低于此值,Dashboard会因资源不足反复重启。启动后立刻执行:
minikube dashboard --url # 获取Dashboard访问地址
kubectl config view --minify | grep "server:" # 确认API Server地址
提示:Minikube的kubeconfig默认写入~/.kube/config,且自动设置为当前context。这是和kubekey集群最大的区别——后者默认写入/root/.kube/config,必须手动合并。这个细节,决定了你后续所有kubectl命令是否“开箱即用”。
2.2 验证层:用Kind构建“可丢弃”的多节点集群,专治网络与调度问题
Minikube解决“能不能跑”,Kind解决“为什么跑不起来”。Kind(Kubernetes in Docker)用Docker容器模拟多个K8s节点,完美复现生产环境中的网络拓扑和调度行为。比如,你在Minikube上部署一个Service,可能永远看不到Endpoint为空的问题,但在Kind里,只要CNI插件没加载,Endpoints就一定是 。我用以下配置文件(kind-config.yaml)创建一个3节点集群(1 control-plane + 2 workers):
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
criSocket: /run/containerd/containerd.sock
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- role: worker
- role: worker
执行
kind create cluster --config kind-config.yaml --name my-cluster
后,关键验证动作只有三步:
-
检查节点状态
:
kubectl get nodes -o wide必须显示3个Ready节点,且INTERNAL-IP列不能是127.0.0.1(那是Minikube的特征); -
验证网络连通性
:
kubectl run busybox --image=busybox:1.35 --rm -it -- sh -c "ping -c 2 10.244.0.1"(10.244.0.1是第一个Pod网段的网关,若不通,说明CNI未生效); -
测试调度策略
:
kubectl label node kind-worker topology.kubernetes.io/zone=zone-a,然后部署一个带nodeSelector的Pod,确认它只在worker节点运行。
注意:Kind默认使用containerd作为CRI,但Ubuntu 22.04的Docker默认用runc,两者cgroup驱动可能冲突。实测解决方案是启动前执行
sudo sysctl fs.cgroup.clone_children=1,否则kubelet会报错“failed to run Kubelet: misconfiguration: cgroup driver: "systemd" is different from docker”。
2.3 生产层:用kubekey在Ubuntu 22.04上部署真实集群,拒绝“教程式幻觉”
现在进入正题——kubekey。它不是另一个安装脚本,而是KubeSphere团队推出的 企业级K8s交付引擎 ,核心优势在于“配置即代码”。你不用记几十个参数,只需写一个cluster.yml文件,所有节点角色、网络插件、存储方案、监控组件全部声明式定义。我在一台全新安装的Ubuntu 22.04虚拟机(4核8G)上实测流程如下:
第一步:准备离线环境
kubekey默认从GitHub下载二进制,国内网络极不稳定。必须提前下载:
- kubekey v3.0.2:https://github.com/kubesphere/kubekey/releases/download/v3.0.2/kubekey-v3.0.2-linux-amd64
- K8s v1.28.0离线包:https://github.com/kubesphere/kubekey/releases/download/v3.0.2/kubesphere-v3.4.1.tar.gz
第二步:生成配置模板
./kubekey-v3.0.2-linux-amd64 create config --filename config-sample.yaml
编辑config-sample.yaml,重点修改三处:
-
hosts:填入你的Ubuntu 22.04机器IP、SSH用户(必须是root或有免密sudo权限的用户)、SSH端口; -
roleGroups.etcd和roleGroups.master:至少各1台,roleGroups.worker可设0(单节点集群也合法); -
network.plugin:严格选calico(非flannel),因为Calico在Ubuntu 22.04上对IPv6和eBPF支持更成熟,且错误日志更友好。
第三步:一键部署
./kubekey-v3.0.2-linux-amd64 install cluster -f config-sample.yaml -y
整个过程约12分钟。成功标志是输出
Cluster installation completed, enjoy it!
且
kubectl get nodes
返回Ready状态。此时kubeconfig位于
/root/.kube/config
,必须执行:
mkdir -p $HOME/.kube
sudo cp -i /root/.kube/config $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
否则普通用户无法使用kubectl。
3. 核心实操:用一个真实Exporter贯穿全部Onboarding环节
3.1 为什么选Node Exporter?因为它暴露了90%的新手盲区
Node Exporter是Prometheus生态的基石组件,但它绝不仅是“采集指标”。它的部署过程天然包含K8s最典型的5类操作:DaemonSet(确保每节点一个Pod)、HostPath卷(挂载宿主机/proc和/sys)、SecurityContext(要求privileged权限)、ServiceMonitor(对接Prometheus Operator)、以及最重要的—— 健康检查失败时的完整排障链路 。我用以下YAML(node-exporter.yaml)部署:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: default
spec:
selector:
matchLabels:
name: node-exporter
template:
metadata:
labels:
name: node-exporter
spec:
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: node-exporter
image: quay.io/prometheus/node-exporter:v1.6.1
args:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($|/)'
ports:
- containerPort: 9100
securityContext:
privileged: true
volumeMounts:
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
部署命令简单:
kubectl apply -f node-exporter.yaml
。但接下来的验证,才是Onboarding的真正考场。
3.2 排障四步法:从Pod Pending到指标可查的完整路径
Step 1:检查Pod状态
执行
kubectl get pods -o wide
,若看到
node-exporter-xxxxx 0/1 Pending
,说明调度失败。此时必须查:
kubectl describe pod -l name=node-exporter | grep -A 5 "Events:"
常见原因:节点污点(taint)阻止DaemonSet调度。Ubuntu 22.04上kubekey部署的master节点默认带
node-role.kubernetes.io/control-plane:NoSchedule
污点。解决方案:
kubectl taint nodes --all node-role.kubernetes.io/control-plane:NoSchedule-
实操心得:这个命令里的
--all是关键。新手常只对单个节点操作,结果其他worker节点仍有污点,导致部分Pod仍Pending。务必用kubectl get nodes -o wide确认所有节点Taint列为空。
Step 2:验证容器进程
若Pod状态变为
Running
但
READY
列为
0/1
,说明容器启动失败。进入Pod内部:
kubectl exec -it $(kubectl get pods -l name=node-exporter -o jsonpath='{.items[0].metadata.name}') -- ps aux | grep exporter
若无输出,证明进程未启动。此时查日志:
kubectl logs -l name=node-exporter --previous
典型错误:
open /host/proc: permission denied
。这是因为Ubuntu 22.04默认启用AppArmor,而node-exporter需要读取/proc。解决方案是给Pod加AppArmor注解:
annotations:
container.apparmor.security.beta.kubernetes.io/node-exporter: unconfined
Step 3:测试端口可达性
即使容器运行,也可能因网络策略阻断。在集群内任意Pod中执行:
kubectl run test --image=busybox:1.35 --rm -it -- wget -qO- http://<NODE_IP>:9100/metrics | head -n 5
若超时,说明Service或网络插件异常。此时查Calico状态:
kubectl get pods -n kube-system | grep calico
kubectl logs -n kube-system -l k8s-app=calico-node | tail -n 20
常见报错:
Failed to initialize BPF program
。这是Ubuntu 22.04内核5.15对eBPF支持不完整导致。临时方案:在kubekey配置中禁用eBPF,改用iptables模式(修改cluster.yml的
network.calico.ipam
部分)。
Step 4:验证指标采集
最后一步,用curl直接调用Node Exporter的/metrics端点:
curl http://$(hostname -I | awk '{print $1}'):9100/metrics | grep node_cpu_seconds_total
若返回类似
node_cpu_seconds_total{cpu="0",mode="idle"} 1234567.89
的数据行,恭喜,你的Onboarding流水线已全线贯通。此时你已亲手完成了:环境初始化、集群部署、应用部署、网络调试、安全策略调整、日志分析——这正是Effective Onboarding的全部内涵。
4. 常见问题与排查技巧实录:那些文档里找不到的“血泪经验”
4.1 Ubuntu 22.04专属陷阱:systemd-resolved与DNS劫持
这是我在12台Ubuntu 22.04机器上踩出的最深的坑。kubekey部署后,
kubectl get nodes
能返回节点,但
kubectl get pods --all-namespaces
却超时。抓包发现,所有DNS查询都被重定向到127.0.0.53(systemd-resolved的监听地址),而CoreDNS Pod的ClusterIP(如10.233.0.3)根本不在该DNS的解析范围内。解决方案不是停掉systemd-resolved(会破坏系统网络),而是让kubelet强制使用上游DNS:
# 编辑kubelet配置
sudo vi /var/lib/kubelet/config.yaml
# 在末尾添加:
resolvConf: "/run/systemd/resolve/resolv.conf"
# 重启kubelet
sudo systemctl restart kubelet
注意:
/run/systemd/resolve/resolv.conf是systemd-resolved生成的真实上游DNS文件,它包含真正的8.8.8.8等地址。而/etc/resolv.conf只是指向127.0.0.53的软链接。这个细节,Ubuntu官方文档从未提及。
4.2 kubekey部署后kubectl无响应:证书时间戳错位
现象:
kubectl get nodes
返回
Unable to connect to the server: x509: certificate has expired or is not yet valid
。这不是证书过期,而是Ubuntu 22.04虚拟机的系统时间与NTP服务器严重不同步。kubekey生成的证书有效期基于本地时间,若部署时系统时间快了2小时,证书就“尚未生效”。验证方法:
date && sudo ntpdate -q pool.ntp.org
若输出时间差超过1分钟,立即同步:
sudo timedatectl set-ntp on
sudo systemctl restart systemd-timesyncd
然后 必须重新部署集群 ,因为证书已固化在etcd中,无法热更新。
4.3 Minikube Dashboard打不开:Ingress Controller缺失的真相
很多教程说
minikube dashboard
就能打开Web界面,但在Ubuntu 22.04上,它大概率返回白屏。原因:Minikube v1.28+默认不启用Ingress Controller,而Dashboard依赖ingress-nginx路由。解决方案分两步:
-
启用Ingress插件:
minikube addons enable ingress; -
获取Dashboard URL时,必须加
--url参数:minikube dashboard --url,然后用浏览器打开返回的地址(形如http://127.0.0.1:43212),而非直接访问https://127.0.0.1:30000(那是旧版地址)。
实操心得:
minikube dashboard --url输出的URL里,端口号每次启动都不同。新手常复制一次URL就以为永久有效,结果下次启动就失效。正确做法是每次用前都执行一次该命令。
4.4 Kind集群无法访问宿主机服务:Docker网络桥接失效
当你的Kind集群需要调用宿主机上的MySQL或Redis时,
host.docker.internal
在Ubuntu 22.04上默认不可用。这是因为Docker Desktop的特性,而Linux原生Docker不支持。解决方案是手动添加host别名:
# 在kind-config.yaml的control-plane节点下添加:
extraHosts:
- "host.docker.internal:172.17.0.1" # 172.17.0.1是Docker默认bridge网关
然后重建集群。验证:在Kind集群内执行
ping host.docker.internal
,应能通。
4.5 Node Exporter指标为空:cgroup v2与metrics路径错配
Ubuntu 22.04默认启用cgroup v2,但Node Exporter v1.6.1的默认参数仍按cgroup v1路径查找。结果
node_cpu_seconds_total
等关键指标始终为0。解决方案是显式指定cgroup路径:
args:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.systemd'
- '--collector.textfile.directory=/var/lib/node-exporter/textfile-collector'
- '--collector.cgroup.root=/sys/fs/cgroup' # 关键!强制指向cgroup v2根目录
注意:
/sys/fs/cgroup是Ubuntu 22.04的cgroup v2挂载点,而CentOS 7是/sys/fs/cgroup/systemd。跨发行版迁移时,此参数必须调整。
5. 工具链精简清单:只保留真正影响Onboarding效率的5个命令
5.1 kubectl debug:比exec更精准的故障定位
kubectl exec
只能进正在运行的Pod,而
kubectl debug
可以在任何Pod上“热插拔”一个调试容器。例如,当Node Exporter Pod因权限问题崩溃时:
kubectl debug node/<NODE_NAME> -it --image=nicolaka/netshoot --share-processes
这会启动一个netshoot容器,共享目标节点的命名空间,让你直接
ls /proc
、
cat /sys/fs/cgroup
,无需重启原Pod。比
kubectl logs --previous
更直观。
5.2 kubens & kubectx:上下文切换的物理外挂
当你同时操作Minikube、Kind、kubekey三个集群时,
kubectl config use-context
手动切换极易出错。
kubens
(切换namespace)和
kubectx
(切换context)是必备工具:
git clone https://github.com/ahmetb/kubectx.git
sudo ln -s ~/kubectx/kubens /usr/local/bin/kubens
sudo ln -s ~/kubectx/kubectx /usr/local/bin/kubectx
之后,
kubectx
列出所有context,
kubectx my-kubekey-cluster
一键切换,
kubens monitoring
切换命名空间。效率提升300%。
5.3 stern:实时聚合多Pod日志的“日志雷达”
调试DaemonSet时,
kubectl logs -l name=node-exporter
只能看一个Pod。
stern
可同时tail所有匹配Pod的日志:
stern -l name=node-exporter --tail 10
输出自动用不同颜色区分Pod,错误日志高亮显示。比写for循环
kubectl logs
高效十倍。
5.4 k9s:终端里的K8s可视化控制台
GUI Dashboard太重,纯命令行又难记忆。
k9s
是终端内的交互式UI:
curl -sSLO https://github.com/derailed/k9s/releases/download/v0.27.4/k9s_Linux_x86_64.tar.gz
tar xzf k9s_Linux_x86_64.tar.gz
sudo install k9s /usr/local/bin/k9s
启动后按
:po
看Pod,
d
查看详情,
l
看日志,
s
进shell——所有操作都在键盘上完成,无需查kubectl手册。
5.5 kubeval:YAML语法的“编译器”
写YAML时拼错
apiVersion
或
kind
,
kubectl apply
会报错但不提示具体哪一行。
kubeval
可提前校验:
curl -sSLO https://github.com/instrumenta/kubeval/releases/download/0.16.1/kubeval-linux-amd64.tar.gz
tar xzf kubeval-linux-amd64.tar.gz
sudo install kubeval /usr/local/bin/kubeval
# 使用
kubeval node-exporter.yaml
输出直接定位到
line 5, column 12: apiVersion must be a string
,省去50%的试错时间。
6. 最后一个建议:把Onboarding过程本身变成你的第一个K8s应用
Effective Onboarding的终极标志,不是你会部署多少个应用,而是你能把Onboarding流程自动化。我用一个简单的Kustomize项目实现了这一点:
onboarding/
├── base/
│ ├── minikube.yaml # Minikube启动配置
│ ├── kind-config.yaml # Kind集群定义
│ └── node-exporter.yaml # 核心应用
├── overlays/
│ ├── ubuntu22/
│ │ ├── kustomization.yaml # 指向base,并patch Ubuntu 22.04专用参数
│ │ └── ubuntu-patch.yaml # 如添加AppArmor注解、cgroup路径
│ └── production/
│ └── kustomization.yaml # 指向kubekey集群的config-sample.yaml
执行
kustomize build overlays/ubuntu22 | kubectl apply -f -
,即可一键完成Ubuntu 22.04环境的全部Onboarding。这个项目本身,就是你K8s能力的第一个可交付物。它比任何证书都更能证明:你已跨越从“学习者”到“实践者”的临界点。我见过太多人花三个月学K8s理论,却不敢写第一行YAML;也见过有人两天内用这套流程教会5个同事独立部署。区别不在天赋,而在是否把“如何开始”这件事,本身当作一个需要被工程化解决的问题。现在,你的Onboarding流水线已经就绪。下一步,不是去查更多教程,而是打开终端,敲下第一个
minikube start
。真正的Kubernetes之旅,从你按下回车键的那一刻开始。
更多推荐
所有评论(0)