ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Kubernetes核心架构与实战入门:从容器编排到集群管理

Kubernetes核心架构与实战入门:从容器编排到集群管理 1. 从“容器”到“集群”为什么我们需要Kubernetes如果你已经玩过Docker把应用打包成一个镜像然后在自己的电脑或者一台服务器上跑起来感觉一切尽在掌握。那么当你第一次听说Kubernetes简称K8s时可能会有点懵这不就是个管理容器的工具吗我手动docker run不也一样能跑没错对于一两个容器手动管理完全没问题。但想象一下这个场景你开发了一个火爆的电商应用它由前端、后端API、数据库、缓存、消息队列等十几个微服务组成每个服务都可能需要多个实例来应对高并发。现在你需要部署与更新手动在几十上百台服务器上启动、停止、更新每一个容器实例确保版本一致服务不中断。故障自愈半夜三点某个容器因为内存泄漏崩溃了你需要立刻被报警叫醒然后登录服务器手动重启它。弹性伸缩促销活动时流量暴涨你需要快速增加容器实例活动结束后又需要及时回收资源以节省成本。服务发现与负载均衡新增的容器实例如何被其他服务发现并访问流量如何均匀地分发到所有健康的实例上资源调度如何把数百个容器合理地安排到数十台服务器上既避免某些服务器过载又充分利用所有资源面对这些问题手动操作不仅效率低下而且极易出错基本不具备可操作性。这时你就需要一个“容器编排系统”。你可以把Kubernetes想象成一个高度自动化的数据中心操作系统或者一个容器集群的“大脑”。它接管了底层硬件服务器或称节点将CPU、内存、存储、网络等资源抽象成一个巨大的资源池。你只需要告诉这个“大脑”你想要运行什么应用以容器为单位、需要多少份副本、需要多少资源、如何对外提供服务它就会自动帮你完成调度、部署、监控、扩缩容、故障恢复等一系列复杂操作。简单来说Docker解决了“应用如何打包和运行”的问题而Kubernetes解决了“如何大规模、高可靠、自动化地运行和管理成千上万个应用容器”的问题。它是云原生时代的基石无论是自建数据中心还是使用公有云掌握K8s都已成为后端、运维、乃至全栈工程师的必备技能。这篇文章我将从一个过来人的角度带你穿透那些复杂的概念直击K8s最核心、最基础的工作原理和操作逻辑让你能亲手搭建一个最小化的环境并运行起你的第一个应用。2. 核心架构拆解Master与Node是如何协同工作的很多初学者被K8s一堆组件名词吓退其实它的架构思想非常清晰遵循经典的“控制平面-数据平面”分离设计。理解了这张蓝图再看具体组件就豁然开朗了。2.1 控制平面集群的“决策大脑”控制平面Control Plane也叫Master节点是集群的指挥中心负责管理和调度。在生产环境中为了保证高可用控制平面的组件通常是多副本部署的。对于我们学习和测试可以先将它们理解为一套协同工作的服务。kube-apiserver 唯一的入口与“前台”这是整个K8s集群的“总机”和“网关”。所有内部组件如调度器与外部用户如你通过kubectl发出的命令与集群的交互都必须通过API Server。它接收RESTful请求验证其合法性然后更新存储在etcd中的数据并触发相应的后续操作。记住操作K8s本质上就是在和API Server对话。etcd 集群的“记忆中枢”一个高可用的键值对数据库。K8s集群的所有状态数据例如有哪些节点、创建了哪些Pod、Service如何配置都持久化地保存在这里。API Server是唯一能直接读写etcd的组件其他组件通过监听API Server来感知集群状态的变化。你可以把它理解为集群的“唯一事实来源”。kube-scheduler 精明的“调度器”它的职责很简单为新创建的、还没有被分配到具体节点上的Pod选择一个最合适的Node来运行。这个选择不是随机的调度器会综合考虑节点的资源余量CPU、内存、数据位置、软硬件约束、亲和性与反亲和性策略等一系列复杂因素做出最优的调度决策。决策完成后它通过API Server更新Pod与Node的绑定关系。kube-controller-manager 勤劳的“控制循环”它不是单个进程而是一系列控制器Controller的集合。每个控制器都是一个独立的“调节回路”持续地监控着集群的某种状态通过API Server并努力将其调整到与用户声明的“期望状态”一致。节点控制器Node Controller负责监控Node的健康状态。当节点失联时负责标记其状态并触发其上Pod的重新调度。副本控制器ReplicaSet Controller确保任何时候都有指定数量的Pod副本在运行。如果少了就创建新的如果多了就删除多余的。端点控制器Endpoints Controller维护Service与Pod之间的关联关系即Endpoints对象。服务账户和令牌控制器Service Account Token Controllers为新的命名空间创建默认的服务账户和API访问令牌。cloud-controller-manager 与云厂商的“对接器”这是一个可选组件当你的K8s集群运行在AWS、Azure、GCP等公有云上时才需要。它将那些与特定云平台相关的控制逻辑如负载均衡器配置、存储卷创建、节点生命周期管理从kube-controller-manager中剥离出来让K8s核心代码更通用云厂商只需实现这个接口即可。2.2 数据平面干活的“工人节点”数据平面由一群Node也叫Worker Node或Minion组成它们是容器实际运行的地方。kubelet 节点上的“监工”每个Node上都必须运行的“节点代理”。它负责接收来自API Server的指令比如“请在这个节点上运行一个Pod”。管理本节点上Pod的生命周期包括创建、启动、停止、删除容器。定期向API Server汇报本节点的状态如资源使用情况、Pod运行状态。kube-proxy 网络流量的“交通警察”运行在每个Node上的网络代理负责实现K8s Service概念的一部分。它通过维护节点上的网络规则如iptables或ipvs规则来实现Pod之间的网络通信、负载均衡以及将发送到Service虚拟IP的流量转发到后端正确的Pod上。容器运行时 真正的“执行者”负责运行容器的软件最常用的是Docker也可以是containerd、CRI-O等任何实现了K8s容器运行时接口CRI的程序。kubelet通过CRI与容器运行时交互指示它下载镜像、启动或停止容器。Pod 最小的调度与部署单元这是K8s中最核心、也最容易让人困惑的概念。Pod不是容器而是一个或多个容器的“逻辑主机”。一个Pod内的所有容器共享相同的网络命名空间拥有同一个IP地址、存储卷和一些其他资源。它们就像被部署在同一台物理机或虚拟机上的紧密协作的进程组。为什么这么设计因为有些应用需要紧密协作比如一个Web容器和一个日志收集sidecar容器它们需要共享本地磁盘和网络放在同一个Pod里是最自然的选择。K8s调度的是Pod而不是直接的容器。3. 核心对象模型用“声明式”语言告诉K8s你想要什么K8s不希望你用一串命令去指挥它“先做这个再做那个”命令式。它希望你用YAML或JSON文件声明你最终期望的系统状态是什么样子声明式。然后它的各个控制器会不断地工作驱动现实世界向这个声明的状态无限逼近。这些声明就是通过创建一系列“对象”来实现的。以下是你必须掌握的四大核心对象。3.1 Pod工作负载的基石如前所述Pod是原子单元。一个简单的Pod定义文件pod.yaml如下所示apiVersion: v1 # 对象使用的API版本 kind: Pod # 对象的类型这里是Pod metadata: # 对象的元数据 name: my-simple-pod # Pod的名字在命名空间内必须唯一 labels: # 标签是用于识别和选择对象的键值对 app: myapp tier: frontend spec: # 对象的“规格”即你期望的状态 containers: # Pod中包含的容器列表 - name: nginx-container # 容器名称 image: nginx:1.21 # 容器镜像 ports: - containerPort: 80 # 容器监听的端口 resources: # 资源请求与限制 requests: memory: 64Mi cpu: 250m limits: memory: 128Mi cpu: 500m关键点解析labels这是K8s中最重要的组织概念之一。你可以给任何对象打上标签如appmyapp,envprod然后通过“标签选择器”来批量选择和管理它们。Service就是通过标签来找到它要代理的Pod的。resources这是保证集群稳定性的关键。requests是调度依据K8s保证Pod能被调度到至少有这么多资源的节点上limits是硬性上限容器使用资源不能超过此限制否则会被限制或杀死。实操心得我们几乎从不直接创建独立的Pod因为Pod本身没有自愈能力——如果它所在的节点宕机了这个Pod就消失了不会自动在其他节点重建。直接管理Pod就像管理一群没有纪律的散兵。我们使用更高级的对象来管理Pod。3.2 DeploymentPod的“管理器”与“复制器”Deployment是管理Pod副本集ReplicaSet的更高层抽象。它是我们部署无状态应用如Web服务器、API服务最常用的对象。apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx-deployment spec: replicas: 3 # 期望的Pod副本数这是核心 selector: # 标签选择器用于匹配由本Deployment管理的Pod matchLabels: app: nginx template: # Pod模板用于创建新的Pod metadata: labels: app: nginx # 这个标签必须与上面的selector匹配 spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80Deployment为你做了什么多副本与自愈通过replicas: 3它确保始终有3个名为nginx的Pod在运行。如果某个Pod挂了Deployment会立刻创建一个新的来替换。滚动更新这是Deployment的杀手级功能。当你想更新镜像版本如从nginx:1.21升级到nginx:1.22时你不需要手动删除旧Pod再创建新Pod。只需修改YAML文件中的image字段然后执行kubectl apply。Deployment会自动地、逐步地用新Pod替换旧Pod例如先启动一个新Pod等它健康后再删除一个旧Pod确保在整个更新过程中服务始终有可用的副本实现零停机部署。版本回滚如果新版本有问题一条命令kubectl rollout undo deployment/my-nginx-deployment就能立刻回滚到上一个稳定版本。3.3 Service稳定的网络端点Pod是脆弱的、临时的——它们可能因为故障、更新、扩缩容而被销毁和重建每次重建都会获得一个新的IP地址。客户端不可能去追踪这些动态变化的IP。Service就是为了解决这个问题而生的。Service的核心作用为一组功能相同的Pod通常由Deployment管理提供一个稳定的、统一的访问入口虚拟IP地址和DNS名称和负载均衡。apiVersion: v1 kind: Service metadata: name: my-nginx-service spec: selector: # 关键通过标签选择器找到要代理的Pod app: nginx ports: - port: 80 # Service对外暴露的端口 targetPort: 80 # Pod内容器监听的端口 type: ClusterIP # Service类型这是默认值Service类型详解ClusterIP默认在集群内部提供一个虚拟IP只有集群内的其他Pod或服务可以访问。这是微服务间内部通信的主要方式。NodePort在ClusterIP的基础上在每个Node上打开一个静态端口范围30000-32767。这样通过任意Node的IP:NodePort就能从集群外部访问服务。适合开发测试生产环境一般不用。LoadBalancer在NodePort的基础上利用云服务商AWS、GCP等的负载均衡器创建一个外部负载均衡器并将流量引导到Service。这是在生产环境将服务暴露到公网的常用方式在云上。ExternalName将Service映射到一个外部DNS名用于将集群内服务指向集群外的服务。服务发现在集群内部你可以直接通过Service的名字如my-nginx-service来访问它。K8s内置的DNS服务CoreDNS会自动将这个名称解析为Service的ClusterIP。所以一个Pod要访问my-nginx-service只需请求http://my-nginx-service即可无需关心后端有多少个Pod、它们的IP是什么。3.4 ConfigMap与Secret配置与敏感信息管理将配置硬编码在容器镜像里是糟糕的做法。K8s提供了ConfigMap和Secret来将配置信息与容器镜像解耦。ConfigMap用于存储非敏感的配置数据如环境变量、配置文件内容。apiVersion: v1 kind: ConfigMap metadata: name: app-config data: log-level: INFO config.properties: | server.port8080 cache.enabledtrue你可以在Pod定义中将ConfigMap的数据以环境变量或文件卷Volume的形式挂载到容器内。Secret用于存储敏感信息如密码、OAuth令牌、SSH密钥。用法与ConfigMap类似但数据会以Base64编码存储仅是一种简单的编码并非加密。在生产环境中应考虑结合Vault等外部密钥管理工具或使用加密的Secret需要配置。apiVersion: v1 kind: Secret metadata: name: db-secret type: Opaque data: username: YWRtaW4 # admin的base64编码 password: cGFzc3dvcmQ # password的base64编码4. 实战入门亲手搭建Minikube并部署第一个应用理论说再多不如动手做一遍。对于学习和开发最推荐的工具是Minikube。它可以在你的本地电脑Windows, macOS, Linux上快速创建一个单节点的K8s集群包含了K8s的所有核心功能。4.1 环境准备与安装安装容器运行时Minikube支持多种驱动。最简单的是Docker。请先根据你的操作系统安装 Docker Desktop 或Docker Engine。安装kubectl这是命令行工具用于与任何K8s集群包括Minikube通信。macOS (使用Homebrew):brew install kubectlLinux: 可以从官方下载二进制文件或使用包管理器。例如Ubuntu:sudo apt-get update sudo apt-get install -y kubectlWindows (使用Chocolatey):choco install kubernetes-cli安装后运行kubectl version --client验证。安装MinikubemacOS (使用Homebrew):brew install minikubeLinux:curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikubeWindows (使用Chocolatey):choco install minikube4.2 启动集群与初探Dashboard启动Minikube集群使用Docker驱动minikube start --driverdocker这个命令会下载必要的镜像并在Docker中启动一个虚拟机或容器来运行单节点的K8s集群。首次启动需要几分钟。验证集群状态kubectl cluster-info minikube status看到控制平面和核心服务运行正常即可。一个极其有用的命令minikube tunnel当你创建LoadBalancer类型的Service时在云上会自动分配一个外部IP。但在Minikube本地这个外部IP会一直处于Pending状态。运行minikube tunnel需要管理员权限并在另一个终端保持运行可以解决这个问题它会为这些Service分配一个本地可达的IP。可选开启Web Dashboardminikube dashboard这条命令会自动打开浏览器显示K8s的官方仪表盘。你可以在这里以图形化的方式查看集群资源、Pod、Service等所有对象非常适合初学者直观理解集群状态。4.3 部署一个完整的应用Nginx Service现在我们将之前学到的概念串联起来部署一个可通过浏览器访问的Nginx。创建Deployment将下面的内容保存为deployment.yaml。apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80创建Service将下面的内容保存为service.yaml。apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 # Service端口 targetPort: 80 # 容器端口 type: LoadBalancer # 准备对外暴露应用配置kubectl apply -f deployment.yaml kubectl apply -f service.yamlkubectl apply是声明式操作的典范。它会创建或更新资源使其符合YAML文件中描述的状态。查看部署结果# 查看Deployment状态 kubectl get deployments # 查看由Deployment创建的Pod kubectl get pods # 查看Service注意EXTERNAL-IP列 kubectl get service nginx-service稍等片刻Pod状态会变为Running。对于Service由于我们使用了LoadBalancer类型且运行了minikube tunnelEXTERNAL-IP列会显示一个IP如10.96.0.0或类似。访问应用 使用上一步获取的EXTERNAL-IP在浏览器中访问http://EXTERNAL-IP你应该能看到Nginx的欢迎页面。体验滚动更新 让我们把Nginx从1.21升级到1.22。kubectl set image deployment/nginx-deployment nginxnginx:1.22 --record使用kubectl rollout status deployment/nginx-deployment观察更新过程。你会看到K8s逐步创建新的Pod1.22版本并终止旧的Pod1.21版本期间服务始终可用。清理资源kubectl delete -f service.yaml -f deployment.yaml # 或者删除所有本命名空间的资源 kubectl delete all --all5. 避坑指南与核心操作命令速查刚开始接触K8s你一定会被它的复杂性绊倒几次。这里分享几个我早期踩过的坑和对应的排查思路以及最常用的命令。5.1 常见问题与排查链路问题一Pod一直处于Pending状态。排查思路kubectl describe pod pod-name这是最重要的排错命令。查看Events部分通常会直接告诉你原因例如“Insufficient cpu/memory”节点资源不足或“didn‘t find available persistent volumes”存储卷问题。kubectl get nodes和kubectl describe node node-name检查节点状态和资源分配情况。节点是否ReadyCPU和内存是否真的不足检查Pod定义中的resources.requests是否设置得过高超过了节点容量。问题二Pod处于CrashLoopBackOff或Error状态。排查思路kubectl logs pod-name查看容器应用本身的日志这是第一现场。如果Pod内有多个容器用-c container-name指定。kubectl logs pod-name --previous如果容器已经重启查看上一次崩溃前的日志。kubectl describe pod pod-name查看事件看是否是镜像拉取失败ImagePullBackOff、启动命令执行失败等原因。进入容器内部调试如果容器还能启动kubectl exec -it pod-name -- /bin/sh检查配置文件、环境变量等。问题三Service无法访问或者访问不到后端Pod。排查思路检查Service的Selector标签kubectl describe service service-name查看Selector字段。然后kubectl get pods --show-labels确认Pod的标签是否与Service的Selector完全匹配。这是最常见的原因检查Pod是否就绪Pod除了Running还需要通过“就绪探针”Readiness Probe检测。kubectl get pods看READY列是否为1/1。检查EndpointsService通过Endpoints对象关联Pod。kubectl get endpoints service-name。如果这里为空说明Service没有找到匹配的Pod。从集群内部另一个Pod进行测试kubectl run curl-test --imageradial/busyboxplus:curl -it --rm -- /bin/sh进入临时Pod后执行curl http://service-name看能否通。5.2 必备的kubectl命令清单以下命令请务必熟练它们是你与K8s交互的主要方式。命令作用常用示例基础查询kubectl get列出资源kubectl get pods,kubectl get svc,deploykubectl describe查看资源详细信息用于排错kubectl describe pod namekubectl explain查看资源字段说明写YAML时的神器kubectl explain pod.spec.containers应用部署kubectl apply -f声明式创建/更新资源kubectl apply -f deployment.yamlkubectl create命令式创建资源不常用kubectl create deployment nginx --imagenginxkubectl delete删除资源kubectl delete -f file.yaml或kubectl delete pod name交互与调试kubectl logs查看Pod日志kubectl logs pod-name -f(-f持续输出)kubectl exec在Pod中执行命令kubectl exec -it pod-name -- /bin/bashkubectl port-forward将本地端口转发到Pod临时访问kubectl port-forward pod/name 8080:80部署管理kubectl rollout管理滚动更新kubectl rollout status deployment/namekubectl rollout undo deployment/namekubectl scale扩缩容kubectl scale deployment/name --replicas5配置管理kubectl edit直接编辑资源kubectl edit deployment/name慎用kubectl label给资源打标签kubectl label pod name envprod核心技巧善用--help和-o输出格式。例如kubectl get pods -o wide显示更宽的信息如节点IPkubectl get pods -o yaml以YAML格式输出方便复制和修改。kubectl api-resources可以列出所有可操作的资源类型。6. 学习路径建议从菜鸟到熟练工K8s生态庞大一口吃不成胖子。我建议按照以下路径循序渐进每一步都动手实践夯实核心概念本文所讲的Pod, Deployment, Service, ConfigMap/Secret是基石必须理解透彻。在Minikube上反复练习它们的创建、关联和访问。深入存储与配置学习PersistentVolume (PV)和PersistentVolumeClaim (PVC)理解如何为有状态应用如数据库提供持久化存储。掌握应用发布深入研究Deployment的滚动更新策略strategy、就绪与存活探针readinessProbe,livenessProbe。这是保证应用高可用的关键。学习有状态应用了解StatefulSet它用于部署像MySQL、Redis、ZooKeeper这类需要稳定网络标识和持久化存储的应用。探索网络与安全理解NetworkPolicy网络策略来控制Pod间的网络流量。学习ServiceAccount,Role,RoleBinding来实现基于角色的访问控制RBAC。接触包管理工具当应用越来越复杂几十个YAML文件手动管理就力不从心了。这时需要学习Helm它是K8s的包管理器通过“Chart”来打包、分发和安装复杂的应用。走向生产环境了解Ingress比Service更强大的7层流量入口、HPAHorizontal Pod Autoscaler基于CPU等指标自动扩缩容、资源配额ResourceQuota、以及如何配置日志收集如EFK栈和监控如Prometheus Grafana。学习过程中最大的心得就是“不要怕多动手”。遇到错误仔细阅读kubectl describe和kubectl logs的输出大部分问题都能找到线索。官方文档kubernetes.io/zh/docs/是你最好的朋友虽然初期可能觉得晦涩但它的准确性和完整性无可替代。从在Minikube上运行第一个Pod开始逐步构建起你自己的知识体系你会发现这个强大的系统正在将你从繁琐的运维工作中解放出来让你能更专注于应用本身的价值。
返回列表