公司动态
Kubernetes 上手实战(2):本地搭建 K8s 学习环境
上一篇建立了 Pod、Deployment、Service 与调谐循环的心智模型。本篇把这些概念落到一套可重复创建、可彻底销毁的本地环境用 Docker 承载节点、kind 创建集群、kubectl 操作 API并实际部署 web 应用。一、痛点学习环境也需要可复现本地 Kubernetes 方案很多。Docker Desktop 集成度高适合希望少维护的桌面用户minikube 支持虚拟机、容器等多种驱动附加组件丰富kind 把 Kubernetes 节点运行在 Docker 容器中创建快、配置文件清晰尤其适合教学和 CI。本系列选 kind不代表它适合承载生产业务而是因为环境能写成代码、失败后可低成本重建。先安装 Docker、kind 和 kubectl并分别检查版本。kubectl 客户端与服务器允许有限版本偏差长期使用应参考官方版本偏差策略。不要从来路不明的网盘下载二进制按官方安装页选择操作系统和架构并校验校验和。Docker 需要至少约 4GB 可用内存若镜像频繁被系统杀死应先提高资源额度。kubectl 通过 kubeconfig 确定集群地址、证书和身份。一个配置可保存多个 cluster、user 与 contextcontext 是三者加默认 namespace 的组合。多数“命令打错集群”并非 Kubernetes 故障而是当前 context 不正确。每次执行删除或修改前都应先打印 current-context。二、原理节点容器与端口映射kind 的节点看起来像 Docker 容器但内部运行 kubelet、容器运行时和控制平面组件。业务 Pod 由节点内的 containerd 启动不等同于宿主机 Docker 容器。宿主机端口也不会自动进入集群extraPortMappings显式把宿主机 8080 映射到节点 30080便于稍后验证 NodePort。下面保存为kind.yaml。一个控制平面加两个工作节点足够观察调度与节点故障固定节点镜像版本能避免今天创建和下月创建得到不同 Kubernetes 版本。若官方已更新镜像可替换为当前受支持的精确标签但团队应把这个变化作为受审查的依赖升级。kind:ClusterapiVersion:kind.x-k8s.io/v1alpha4name:k8s-labnodes:-role:control-planeextraPortMappings:-containerPort:30080hostPort:8080protocol:TCP-role:workerlabels:learning.k8s.io/zone:a-role:workerlabels:learning.k8s.io/zone:bnetworking:ipFamily:ipv4apiServerAddress:127.0.0.1apiServerPort:6443kubeadmConfigPatches:-|kind: ClusterConfiguration apiServer: extraArgs: enable-admission-plugins: NodeRestriction创建脚本在任何步骤失败时立即退出并核对 context、节点和系统 Pod。它还建立独立 namespace减少与其他实验互相污染。重复运行时若集群已存在脚本不会默默覆盖而会提示先决定复用还是删除。#!/usr/bin/env bashset-euopipefailcluster_namek8s-labcontext_namekind-${cluster_name}command-vdocker/dev/nullcommand-vkind/dev/nullcommand-vkubectl/dev/nulldockerinfo/dev/nullifkind get clusters|grep-qx${cluster_name};thenechocluster already exists:${cluster_name}elsekind create cluster--configkind.yaml--wait120sfikubectl config use-context${context_name}test$(kubectl config current-context)${context_name}kubectlwait--forconditionReady nodes--all--timeout120s kubectl get nodes-owide kubectl get pods-nkube-system kubectl create namespace lab --dry-runclient-oyaml|kubectl apply-f- kubectl config set-context--current--namespacelab kubectl auth can-i create deployments.apps脚本应输出三个 Ready 节点kube-system 中 CoreDNS、kube-proxy 等 Pod 正常并在最后返回yes。若节点 NotReady先运行docker ps与kind export logs ./kind-logs --name k8s-lab不要反复重建掩盖根因。三、实现部署并从宿主机访问复用上一篇的 Deployment但为 Service 指定type: NodePort和nodePort: 30080。应用清单后执行kubectl rollout status deployment/web再访问http://127.0.0.1:8080。请求路径为宿主机 8080、控制平面节点 30080、Service、EndpointSlice、Pod 80明确链路后任一层不通都有可检查对象。可先用kubectl create deployment web --imagenginx:1.27-alpine --dry-runclient -o yaml学习生成但最终清单要写入文件。命令生成的内容通常缺少标签规范、探针与资源配置它是脚手架而非生产答案。访问失败时依次检查docker port k8s-lab-control-plane、Service 端口、EndpointSlice 和 Pod Ready 状态。用kubectl run curl --imagecurlimages/curl:8.10.1 --rm -it --restartNever -- http://web可以从集群内部验证 DNS 和 Service。如果内部成功、宿主机失败问题就在端口映射或 NodePort如果 DNS 失败检查 CoreDNS如果有 Service 却无端点检查标签与 readiness。这种二分法以后同样适用于云集群。四、踩坑版本、镜像和上下文Apple Silicon 或 ARM Linux 应选多架构镜像自己构建的单架构业务镜像则可能出现exec format error。本地镜像不会自动出现在 kind 节点需执行kind load docker-image image --name k8s-lab并使用非latest标签及合适的imagePullPolicy。真实仓库镜像则由节点通过 registry 拉取。企业代理环境常见问题是宿主机能联网而节点容器不能拉镜像。应为 Docker daemon 正确设置代理、内部 CA 与镜像仓库而不是关闭 TLS 验证。端口 8080 或 6443 被占用时应明确修改配置中的 hostPort 或 apiServerPort不能随机试错后忘记记录。删除集群是破坏操作先确认目标kind get clusters再执行kind delete cluster --name k8s-lab。它不会删除源码但会删除该集群内所有对象和数据。学习中的重要清单必须放在宿主机 Git 仓库而非只保留在 etcd 或临时容器里。五、验证形成可重建基线一套合格环境应满足四项工具版本可打印当前 context 明确是kind-k8s-lab全部节点 Ready删除并依据配置重建后应用仍能由清单恢复。把创建脚本加入仓库团队成员和 CI 才能复用同一基线。实验结束可以导出诊断信息再删除集群并重新运行脚本。若第二次结果一致说明环境没有依赖隐藏的手工步骤。生产环境当然不能用 kind 代替托管集群但这里训练出的版本固定、上下文确认、分层验证和可销毁思维会直接迁移过去。下一篇将继续使用labnamespace把 web 从最小清单扩展为带滚动发布策略、资源约束和回滚验证的 Deployment并深入 Pod 生命周期。还可以做一次“陌生机器演练”让同事仅依据仓库中的版本说明、kind 配置和创建脚本操作禁止口头补充步骤。如果对方需要手工改节点、复制隐藏文件或猜测代理设置就把缺失条件写回文档和预检。为镜像下载失败、端口冲突、资源不足分别记录症状与解决办法并区分可自动修复和必须人工决定的情形。这个练习能提前暴露只在作者电脑成立的隐含前提。环境基线还应保存创建时间、Kubernetes 版本、节点镜像摘要、工具版本和宿主架构。升级其中一项后重新运行节点就绪、集群内访问、宿主端口访问和销毁重建四项测试。若团队需要同时维护多个实验应为集群名、端口和配置设明确规则避免共享默认上下文。至此得到的不只是一个能用的集群而是一套可移交的环境契约。在真正创建集群前可先用标准库检查端口和节点计划避免把明显冲突留给 kind。第一个程序验证节点角色、主机端口范围及唯一性修改数据即可迁移到团队自己的本地集群配置生成器。nodes[{name:control-plane,role:control-plane,host_port:8080},{name:worker-a,role:worker,host_port:None},{name:worker-b,role:worker,host_port:None},]errors:list[str][]ports:set[int]set()roles[node[role]fornodeinnodes]ifroles.count(control-plane)!1:errors.append(exactly one control-plane is required)ifroles.count(worker)1:errors.append(at least one worker is required)fornodeinnodes:portnode[host_port]ifportisNone:continueifnot1024port65535:errors.append(finvalid port:{port})ifportinports:errors.append(fduplicate port:{port})ports.add(port)print(fnodes{len(nodes)}workers{roles.count(worker)})print(fmapped_ports{sorted(ports)})print(validation(PASSifnoterrorselseFAIL))运行输出nodes3 workers2 mapped_ports[8080] validationPASS第二个程序把 context 保护写成可测试函数。生产脚本同样应在修改前比较允许值而不是只把当前 context 打印出来后依赖操作者肉眼判断。fromdataclassesimportdataclassdataclass(frozenTrue)classKubectlTarget:context:strnamespace:strdefauthorize(target:KubectlTarget,allowed:set[KubectlTarget])-str:iftargetnotinallowed:returnDENYiftarget.namespacein{default,kube-system}:returnDENYreturnALLOWallowed{KubectlTarget(kind-k8s-lab,lab),KubectlTarget(kind-k8s-lab,debug-lab),}attempts[KubectlTarget(kind-k8s-lab,lab),KubectlTarget(company-production,lab),]forattemptinattempts:decisionauthorize(attempt,allowed)print(f{attempt.context}/{attempt.namespace}{decision})运行输出kind-k8s-lab/labALLOW company-production/labDENY参考来源kind Quick Startkind ConfigurationInstall and Set Up kubectlOrganizing Cluster Access Using kubeconfig 觉得有用就点个赞 收藏方便回头查阅有疑问直接在评论区留言我看到都会回。 本文属于《Kubernetes 上手实战》系列持续更新关注不迷路。 文章里的代码都能直接跑。想要可直接 clone 的完整工程 配套部署脚本 / 踩坑清单评论一声或发邮件到cj2664qq.com我免费发你。如果你正好在做类似系统、或有工程化难题想找人做也欢迎邮件聊一句——我按实际情况评估能落地的就接单或出方案。评论和邮件都能直接找到我不用跳别的平台。