☰
Kubernetes离线手动搭建实战:从环境准备到Calico网络联调
2026/10/20 13:14:49 网站建设 项目流程

1. 整体思路与部署架构选型

1.1 为什么选择离线手动搭建

先聊一个大家都会遇到的问题:学习K8S到底应该从哪里入手?很多人第一反应是装个minikube或者kind,一条命令拉起来,kubectl get nodes能看到一个Ready的节点,就觉得"我会K8S了"。但等真正上了生产,出了问题才发现自己完全不知道集群内部是怎么运转的。这就跟开车一样,你在驾校开自动挡和上了路开手动挡完全是两码事。K8S这个东西,如果不去手动搭建一次,你就永远停留在"会用工具"的层面,没有真正理解"工具"本身。

我这次选择离线手动搭建,其实是被环境"逼"出来的。某公司的内网服务器完全不能访问外网,但又需要一套K8S环境来做容器化部署的测试和验证。最开始我也想过曲线救国:在一台能上网的机器上装好所有镜像,然后打包带进内网。后来发现这个思路本身就是K8S离线部署的标配玩法。索性就把整个过程完整走了一遍,顺便把之前的很多知识盲区补上了。

手动搭建的好处在哪里?首先是你能真正搞清楚每个组件是干什么的。etcd存什么数据、kube-apiserver怎么和etcd交互、kube-scheduler怎么调度Pod、kubelet怎么和容器运行时通信。这些东西在自动化的安装工具里全都是黑盒,你只知道装完就能用,但出了问题就抓瞎。其次是手动搭建的过程中,你会被迫理解证书体系、网络插件的选择、Pod网段和Service网段的规划,这些才是K8S运维的核心能力。

1.2 核心组件与架构设计

在动手之前,先把K8S的架构理清楚。我这次搭建的是最经典的单Master双Worker架构,三个节点分别是master01、worker01、worker02。为什么不用高可用?因为这是做学习和验证用的环境,单Master足够覆盖绝大部分测试场景。如果以后要上生产,再做HA,原理是一样的,只是多了负载均衡这一层。

K8S的核心组件可以分成两个部分:控制平面和节点平面。控制平面包含kube-apiserver、kube-controller-manager、kube-scheduler、etcd四个组件,节点平面包含kubelet、kube-proxy和容器运行时。

组件角色一览:

组件职责关键点
etcd集群状态存储所有数据的唯一来源,坏了集群就瞎了
kube-apiserver所有请求的入口唯一能直接访问etcd的组件
kube-controller-manager维持期望状态节点控制器、副本控制器等一堆控制器
kube-scheduler决定Pod跑在哪个节点根据资源和约束做调度决策
kubelet节点上的“眼睛和手”负责Pod的生命周期管理
kube-proxyService流量转发实现负载均衡和服务发现

这里最需要理解的是kube-apiserver的地位。所有的组件——kubelet、kube-scheduler、kube-controller-manager、kubectl——要读写集群状态,都必须经过kube-apiserver。它就像整个集群的“总闸门”,所有请求进来先经过认证、授权、准入控制三道关卡,然后才会真正写入etcd。理解了这一点,你就知道为什么在排查问题的时候,第一步总是看kube-apiserver是否正常。

1.3 版本选型与配套组件

版本选型这个问题,网上说法很多,但我给的建议很简单:选一个经过时间验证的稳定版本。我这次用的是1.23.17,为什么选这个版本?因为1.24开始,K8S把Dockershim移除了,如果你还习惯用Docker作为容器运行时,就需要额外安装CRI-Dockerd这个适配层。而1.23及之前的版本,Docker还是"原生支持"的,对初学者来说少了一道折腾。当然如果你已经适应containerd作为运行时,用更新的版本也没问题,只是我这次为了减少变量,选择了更稳妥的1.23。

配套组件版本也是一个萝卜一个坑:

组件版本说明
Kubernetesv1.23.17主版本
etcdv3.5.6存储集群数据
containerdv1.6.19容器运行时,替代Docker
crictlv1.24.0命令行调试工具
calicov3.25.0CNI网络插件

这里多说一句为什么要用containerd而不是Docker。刚开始我其实想用Docker,毕竟熟悉嘛。但研究了一下发现,在当前这个阶段,containerd才是更"正统"的容器运行时。K8S通过CRI(Container Runtime Interface)和containerd直接交互,中间少了一个Docker的转换层,更稳定也更高效。而且后面如果想把集群升级到更新版本,用containerd可以省掉很多麻烦。

2. 离线环境的准备与前置条件

2.1 离线安装包的准备策略

离线安装最大的难点不是"装",而是"怎么把需要的东西都提前准备好"。

首先明确需要准备的几个包:K8S的三个核心组件包——kubelet、kubeadm、kubectl,而且必须指定版本。这三个东西在K8S官方的yum仓库或者apt仓库里都有,关键是要在能联网的机器上先下载好。我用的是yum方式,所以需要下载kubelet-1.23.17、kubeadm-1.23.17、kubectl-1.23.17这三个rpm包,以及它们的一堆依赖。

然后就是容器运行时。我选了containerd,需要下载containerd.io这个包。这里必须提醒一下:containerd的版本和K8S版本要兼容,1.6.x的containerd配合1.23.x的K8S是经过验证的组合。

接下来是镜像。K8S集群跑起来需要一堆镜像:kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、etcd、pause、coredns,还有网络插件calico需要的几个镜像。这一块是离线部署的重头戏,也是最容易出问题的地方。

提示:镜像的获取有一个小技巧,通过kubeadm config images list可以列出指定版本K8S需要的全部镜像清单,然后逐个拉取、打包、拷贝。这一步必须在能联网的机器上提前完成。

2.2 服务器基础环境配置

三台服务器的操作系统我用的都是CentOS 7.9,配置是4核8G、100G磁盘。这个配置跑一个测试集群完全够了,但如果想让集群运行得更从容,建议Master节点给到8核16G,毕竟etcd和kube-apiserver都是吃内存的主儿。

系统层面的准备工作集中在三个方面:主机名、IP和防火墙。

主机规划:

主机名IP地址角色
master01192.168.1.101控制平面节点
worker01192.168.1.102工作节点
worker02192.168.1.103工作节点

设置主机名很简单,hostnamectl set-hostname master01,然后三台机器的/etc/hosts都要加上三行映射关系。这一步很多人会忽略,但非常重要——K8S组件之间通信依赖主机名解析,如果你不配hosts,后面kubeadm init的时候就会报"hostname not found"的错误。

然后就是关闭防火墙。很多人对"关闭防火墙"这件事有心理障碍,觉得不安全。这里要说明一下:在K8S集群内部,组件之间需要大量端口互通,你要是开着firewalld,就得额外配置一堆端口放行规则,把K8S的端口清单一个个加进去。对于学习和测试环境,直接systemctl stop firewalld加systemctl disable firewalld是最省事的。生产环境当然不能这么干,需要按端口白名单严格配置,这是后话。

SELinux也要关掉。这个说法可能有人不认同,但我的经验是:在CentOS 7上用K8S,关SELinux能省掉80%的疑难杂症。设置setenforce 0,然后修改/etc/selinux/config把SELINUX=enforcing改成permissive。网上也有不关SELinux硬上的,但那是给追求极致安全的强迫症准备的,不适合我们这种要快速落地场景。

2.3 内核参数与系统调优

这一块是很多人容易忽略的。K8S对系统的要求不只是"能跑",还需要一些内核参数的配合。核心是开启iptables对桥接流量的处理能力。

cat > /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 vm.swappiness = 0 EOF sysctl --system

逐条解释一下。bridge-nf-call-iptables表示让iptables能够处理经过Linux网桥的流量。这是K8S网络能不能正常工作的关键:Pod之间的通信要经过CNI网桥,如果这个参数没开,流量就无法被netfilter正确过滤和转发。ip_forward是开启IP转发,这个几乎是所有容器网络方案的硬性前提。vm.swappiness=0说得直白点就是尽量别用swap,因为容器场景下内存被swap出去会导致性能急剧下降,而且K8S在计算节点内存资源时,默认是不考虑swap的。

还有一个容易被忽视的点:需要加载br_netfilter模块。虽然在CentOS 7.9上默认会加载,但稳妥起见还是提前确认一下:

modprobe br_netfilter lsmod | grep br_netfilter

3. 容器运行时与K8S组件安装

3.1 手动安装containerd

containerd的安装方式其实很简单,就是一个rpm包。但在装完之后,有两件重要的事情要做:一是配置cgroup驱动,二是配置系统服务。

containerd默认的cgroup驱动是systemd还是cgroupfs?这里有一个历史问题。K8S从1.21版本开始,kubelet默认使用systemd作为cgroup驱动,而containerd默认用cgroupfs。这俩如果不一致,就会出现一个让人很困惑的现象:kubelet起来之后报"failed to run Kubelet: failed to validate kubelet flags"或者cgroup相关的错误。解决办法是修改containerd的配置文件,让它也用systemd。

containerd的默认配置文件可以通过containerd config default > /etc/containerd/config.toml生成,然后修改两个地方。一个是SystemdCgroup,把它从false改成true;另一个是sandbox_image,这是Pause镜像的地址。

sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml sed -i 's#sandbox_image = "registry.k8s.io/pause.*#sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6"#' /etc/containerd/config.toml

这里要补充说一下sandbox_image这个参数的含义。Pause容器是每个Pod里的"根容器",它不干任何正事,就是占个位置,负责创建和维护Pod的网络命名空间,Pod里其他容器才能共享网络。如果Pause镜像拉不下来,整个Pod就创建不起来。所以在离线环境里,这一步提前在配置里指定好镜像源位置,能避免很多麻烦。

3.2 K8S核心组件包的安装

在安装之前,先把chache的/etc/yum.repos.d/kubernetes.repo配置好。但离线环境是访问不了这个仓库的,所以正确姿势是:在联网机器上把rpm包下载好,然后拷贝到三台服务器上,用yum install -y ./kubelet-1.23.17.rpm ./kubeadm-1.23.17.rpm ./kubectl-1.23.17.rpm本地安装。

如果遇到依赖问题,比如某个so文件缺失,我的建议是直接使用yum install --downloadonly方式把依赖也一并拉下来。

装完之后把kubelet、kubeadm、kubectl加开机自启并启动:

systemctl enable kubelet && systemctl start kubelet

注意一点:现在kubelet会起得很早,它会因为找不到集群而疯狂报错,刷一堆"failed to connect to API server"的日志。这是正常的,不用慌。kubelet本身就是个不断重试的"打不死的小强",等kubeadm init完成之后它自然就正常了。

3.3 镜像的导入与校验

离线环境最大的坎儿就是镜像。K8S核心组件加上Calico网络插件,总共需要大概十四五个镜像,每一个都必须提前准备好。

具体流程是这样:在联网机器上,先拉取所有需要的镜像,然后通过docker save -o k8s-images.tar或者ctr -n k8s.io images export把镜像打包成一个tar文件,拷贝到内网服务器后再导入。

如果你用的是containerd,导入命令是:

ctr -n k8s.io images import k8s-images.tar

注意-n k8s.io这个命名空间参数,这是K8S专用的镜像命名空间,如果不指定默认是default,导进去的镜像在K8S里根本看不到。

之前提到的kubeadm config images list是获取镜像清单的快捷方式。列出后逐个拉取即可,如下是1.23.17核心组件需要的镜像列表:

registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.23.17 registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.23.17 registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.23.17 registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.23.17 registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6 registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.6-0 registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.6

Calico需要的镜像相对独立,后面网络配置部分再单独说。

4. 证书体系与控制平面初始化

4.1 手动生成PKI证书

K8S的证书体系是整个集群安全的基础,众多组件之间通信全靠TLS双向认证。手动搭建的好处是在这个环节你会被迫搞清楚谁给谁签发证书,以及每个证书的用途。

大体的证书逻辑是:有一个集群的CA根证书,然后给apiserver签发一个服务端证书,给etcd签发证书,给每个节点的kubelet签发客户端证书。K8S集群里的所有组件都信任这个根CA,只要持有根CA签发的证书,就能互相认证。

证书要放在/etc/kubernetes/pki目录下。核心的证书文件如下:

证书文件用途说明
ca.crt, ca.key集群根CA所有证书的信任根
apiserver.crt, apiserver.keyAPI Server服务端证书需要包含MasterIP和Service网段
apiserver-kubelet-client.crt连接kubelet的客户端证书API Server访问kubelet时使用
front-proxy-ca.crt聚合层CA扩展API Server时使用
etcd/ca.crtetcd集群CAetcd组件专用

其实手动生成这些证书并不算太复杂,关键在于别把SAN(Subject Alternative Name)搞错。apiserver的证书SAN必须包含所有可能访问apiserver的地址,包括Master节点的IP、集群的Service网段第一个地址(通常是10.96.0.1)、还有"kubernetes"和"kubernetes.default"这些内置域名。漏掉任何一个,后面都会出现诡异的证书校验失败。

4.2 kubeadm init的执行与参数解析

说起来,手动搭建K8S其实很少有人真的去逐个证书手动用openssl生成,更多是用kubeadm init来"半自动"完成。这里的"手动"指的是不用自动化脚本来做,而不是说连kubeadm都不用。你依然需要自己规划IP、网段、镜像仓库,只是证书、配置文件的生成这一步kubeadm帮我们完成了大部分工作。

执行初始化:

kubeadm init \ --apiserver-advertise-address=192.168.1.101 \ --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers \ --kubernetes-version=v1.23.17 \ --service-cidr=10.96.0.0/12 \ --pod-network-cidr=10.244.0.0/16

逐个参数拆解一下。apiserver-advertise-address指定apiserver对外广播的地址,必须填Master节点的内网IP,不然其他节点找不到它。image-repository是镜像仓库地址,因为离线环境我们已经手动导入镜像了,这里其实不拉取,但这个地址会被写入kubeadm的配置里,后面token验证的时候还会用到。service-cidr是Service的虚拟IP网段,pod-network-cidr是Pod的IP网段,这两个地址池不能和物理机网段冲突,相互之间也不能重叠。我这次选的10.244.0.0/16是Calico默认推荐的Pod网段,10.96.0.0/12是K8S默认的Service网段。

提示:Pod网段和Service网段一旦确定,后期修改极麻烦,会牵涉到CNI配置和CoreDNS配置。集群一经初始化,这两个网段基本就锁死了。所以动手之前一定想清楚。

成功初始化之后,kubeadm会在末尾输出一串关键信息,包括:加入集群的token和证书校验哈希值、kubectl的config文件位置。务必截图保存,后面两个Worker节点加入集群就靠它了。

4.3 部署CoreDNS扩展组件

CoreDNS是K8S集群内部DNS服务,负责Service名的解析。如果你不在集群里部署CoreDNS,Pod之间就不能通过Service名访问彼此,只能靠IP,这在微服务架构中是不可接受的。

部署CoreDNS其实很简单,因为kubeadm会在init完成后自动部署,但前提是网络插件已经就绪。在没有CNI的情况下,CoreDNS会一直处于Pending状态。所以正确的顺序是先部署网络插件,再等CoreDNS正常。

在初始化之后检查:

kubectl get pods -n kube-system

如果看到coredns的Pod是Pending,不用着急,这是正常的。后面部署好Calico之后,它会自动从Pending变成Running。

5. 网络插件的部署与集群联调

5.1 Calico的离线部署

集群的网络方案我选了Calico,它的优势在于支持多种网络模式,性能在CNI插件里属于第一梯队,而且配置灵活,既能做纯三层的BGP网络,也能用Overlay模式。

离线部署Calico的流程是:先把calico.yaml配置文件拿下来,然后把配置里镜像地址改成本地已经导入的镜像地址,再kubectl apply -f calico.yaml。

在配置Calico之前,有一个重要的参数要确认:CALICO_IPV4POOL_CIDR。这个参数是Calico里面Pod地址池的配置,必须和之前kubeadm init时设置的pod-network-cidr一致。比如我之前设置的Pod网段是10.244.0.0/16,那么calico.yaml里的CALICO_IPV4POOL_CIDR也要改成10.244.0.0/16,集群的网络才能正常通信。

注意:Calico部署的先后顺序虽然可以在kubeadm init之前或之后,但有一个大原则是必须在kubelet和kube-proxy工作正常之后、CoreDNS调度之前完成。因为在没有任何CNI插件的情况下,K8S是没有能力为Pod分配IP的,所有Pod都只能卡在ContainerCreating状态。

5.2 Worker节点加入集群

Worker节点的加入是整个过程中最流畅也最容易出错的环节。kubeadm init结束时的输出里有完整的join命令模板,把token和ca-cert-hash替换成自己环境的实际值即可:

kubeadm join 192.168.1.101:6443 \ --token l5d3qn.abcdef1234567890 \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

这个命令在worker01和worker02上各执行一次。执行成功之后,Master节点上验证:

kubectl get nodes

正常情况下会看到三个节点处于NotReady状态。为什么是NotReady?因为kubelet虽然起来了,但它并不会主动告诉apiserver"我准备好了",要由kubelet上报自己的资源信息和状态,由controller-manager给它打上Ready标签。如果节点上网络插件还没就绪,或者kubelet上报有问题,节点就会一直停留在NotReady。

如果join的时候提示token过期或者证书校验失败,不要慌。直接用下面的命令在Master节点上重新生成:

kubeadm token create --print-join-command

这条命令会输出一个新的join命令,直接复制就行。

5.3 网络状态验证与联通性测试

集群初始化的最后一步,是验证网络是否真的通了。我的验证方法是三板斧:看节点状态、看系统Pod状态、跑一个测试Deployment。

第一步,kubectl get nodes,看到三个节点都是Ready,说明节点层面的网络配置正确了。

第二步,kubectl get pods -n kube-system,看到所有Pod都是Running,包括calico-kube-controllers和calico-node。

第三步,创建测试用Pod,验证跨节点网络互通:

kubectl run test-nginx --image=nginx

如果这个Pod能进入Running状态,说明整个网络链路已经打通了。再进一步做一次跨节点连通性测试:

kubectl exec -it test-nginx -- curl <pod_ip>

能通,说明Calico的路由规则已经生效,Pod之间的三层网络没有问题了。

6. 实战坑点与排查经验

6.1 版本不匹配问题

在手动搭建过程中,版本不匹配是最折磨人的一类问题。这里分享一个我踩过的具体案例。

某次初始化的时候,kubeadm init报了一个"error execution phase preflight: unable to fetch the kubeadm-config ConfigMap"的错误。排查了很久,最后发现是kubeadm和kubelet的版本不一致。kubeadm是1.23.17,但kubelet被yum自动升级到了1.24。版本不同导致kubeadm生成的配置和kubelet实际行为不一致,最终卡在preflight检查。

这个问题常规文档不太会提,因为它和"正常安装流程"没关系,纯粹是离线环境里手忙脚乱搞出来的版本错乱。排查思路是:

kubeadm version kubelet --version kubectl version

三个版本必须完全一致,差一个minor版本都不行。解决方法是把kubelet降级到和kubeadm一致的版本:

yum install -y kubelet-1.23.17 --nogpgcheck systemctl restart kubelet

6.2 镜像拉取失败与命名空间陷阱

离线环境里镜像拉取失败是另一个高频问题。这里的坑点往往不在"拉取"本身,而在于镜像导入的命名空间不对。

之前提过,K8S使用的是containerd的k8s.io命名空间。如果你导入镜像时用了默认命名空间ctr images import而不是ctr -n k8s.io images import,kubelet在拉取镜像时会报"image not found",但实际上镜像已经在本地了。这个问题我至少遇到过三次,每次都是因为命令少写了-n k8s.io参数。

还有一个容易忽略的点:如果K8S组件使用默认的registry.k8s.io仓库,而你导入镜像时用的是阿里云仓库路径,也会导致镜像找不到。一定要保证镜像仓库地址一致。比如配置里写着registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6,那么导入的镜像也必须是这个完整路径。

6.3 节点NotReady的排查路径

节点一直NotReady是最让人头疼的问题,因为它可能由多个原因导致。我的排查路径有一个固定的优先顺序:

第一步,看kubelet状态:systemctl status kubelet,看有没有报错。如果是证书相关错误,去检查/etc/kubernetes/kubelet.conf是否存在且权限是否正确。

第二步,看节点上的容器运行时:crictl ps,如果这个命令报错,说明crictl连接不上containerd,检查/run/containerd/containerd.sock是否存在、crictl的runtime-endpoint配置是否正确。

第三步,看CNI插件是否就绪:ls /opt/cni/bin/,如果没有calico相关的可执行文件,说明CNI还在启动中或安装不完整。

第四步,看apiserver上的节点事件:kubectl describe node worker01,这里能看到具体的时间线,比如哪个探针失败、什么原因导致的NotReady。

这套排查路径在我手动搭建过程中多次验证过,效率很高。你不需要一开始就去翻日志,按照这个顺序一步步排除,基本十分钟内能定位到根因。

6.4 常见问题速查表

把这次手动搭建过程中遇到的坑整理成了一个速查表,方便大家对照:

现象可能原因解决方案
kubeadm init失败:port 6443 already in use端口被占用ss -lntp查端口占用的进程,释放端口
节点一直NotReadyCNI未就绪或kubelet异常先看CNI状态,再看kubelet日志
镜像报not found导入命名空间不对用ctr -n k8s.io images import重新导入
CoreDNS一直Pending网络插件没跑起来确认Calico部署成功后再观察
kubectl无法连接apiserverkubeconfig配置错误检查~/.kube/config的server字段和证书路径
跨节点Pod网络不通Calico配置的Pod网段不一致核对CALICO_IPV4POOL_CIDR和kubeadm的pod-network-cidr
kubelet疯狂重启版本不一致或缺少依赖核对kubelet/kubeadm/kubectl版本,检查依赖库

7. 常用运维命令与集群日常管理

7.1 节点与Pod的日常操作

集群搭好之后,日常管理主要是通过kubectl完成。这里把我常用的命令整理一下,都是一些高频操作。

查看节点状态:

kubectl get nodes -o wide

查看集群里所有命名空间的Pod:

kubectl get pods -A -o wide

查看某个Pod的详细信息和事件:

kubectl describe pod <pod-name> -n <namespace>

查看Pod日志:

kubectl logs -f <pod-name> -n <namespace> --tail=200

进入Pod内执行命令:

kubectl exec -it <pod-name> -n <namespace> -- /bin/bash

这些命令是基础中的基础,但恰恰是日常最常用的部分。建议大家把这些命令的-o wide参数用起来,它能直接显示Pod跑在哪个节点、IP是什么,排查问题的时候非常高效。

7.2 证书过期与更新策略

K8S的证书有效期默认是一年。这个时间说长不长,说短不短,很多集群跑着跑着突然出现一堆奇怪的报错,一查才发现是证书过期了。

如果是kubeadm部署的集群,更新证书比较简单:

kubeadm certs renew all

执行完之后重启相关组件:

systemctl restart kubelet

对于自签的apiserver证书,更新之后需要重启kube-apiserver。但要注意,kube-apiserver是静态Pod,修改/etc/kubernetes/manifests/kube-apiserver.yaml之后会自动重启,不需要手动干预。

7.3 节点维护与移除

有时候需要把某个节点摘下来做维护,这时候要让K8S把Pod都赶走:

kubectl drain worker02 --ignore-daemonsets --delete-emptydir-data

维护完成后让节点重新参与调度:

kubectl uncordon worker02

如果要彻底移除一个节点,顺序是:先drain、再删除节点、然后在该节点上执行kubeadm reset清空本地数据。

这两个命令在运维中必不可少,特别是当某个Worker节点要换硬件的时候,drain + uncordon的组合能让业务无感知地完成迁移。

8. 手动搭建的经验总结与后续扩展

这次离线手动搭建K8S集群,前后花了两天时间。第一天准备环境、拉镜像、踩版本坑,第二天正式部署然后反复调试网络。整个过程走完之后,我对K8S的理解和在"一条命令装好"时代形成的认知完全不一样了。你开始明白每个组件为什么要这么设计,哪些参数是牵一发动全身的,哪些错误信息背后真正的原因是什么。

如果让我给准备入门的同学一个建议:即便你以后用开源的集群管理平台做生产部署,也一定要找一套离线环境手动把集群搭一遍。因为你在手动搭建过程中积累的底层认知,会在未来每一次集群故障排查中变成你的直觉。

关于后续扩展,我打算在搭建好的集群上做三件事。第一件事是部署一套完整的微服务Demo,把Ingress、ConfigMap、Secret、PV/PVC这些核心资源都用起来,看看它们在真实业务中的应用方式。第二件事是尝试把集群升级到更新的版本,练练兵,毕竟版本升级在生产中是个高频话题。第三件事是试一下集群监控那套体系,看看从零开始构建可观测性的完整路径。

这一趟下来,我现在碰到网络问题第一反应不是去看什么知名博主写的"十种排查方法",而是自己从Pod网段、Service网段、Calico的路由规则这几个维度去推,反而解决问题更快一些。这就是手动搭建带来的底层能力,也是我愿意把这套流程完整记录下来的原因。希望这篇实践记录能给同样准备手动搭建K8S集群的同学一点参考,少走一些我曾经踩过的弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询