K8s系列第五篇:K8s 服务访问:Service 全解析(ClusterIP/NodePort/LoadBalancer)
前言在上一篇文章中我们详细学习了Deployment的核心用法——通过Deployment可以自动化管理Pod实现Pod的扩缩容、滚动更新和版本回滚确保应用的高可用运行。但此时又出现了一个新的关键问题Pod的IP是动态变化的。比如Deployment自动重建Pod如Pod故障、节点故障时新Pod会被分配一个全新的IP地址扩缩容时新增的Pod也会有新的IP滚动更新时旧Pod删除、新Pod创建IP也会随之变化。如果直接通过Pod IP访问应用一旦Pod IP变化访问就会失败这在生产环境中是完全不可接受的。而Service的出现就是为了解决“Pod IP动态变化”的访问难题。Service是K8s中负责服务发现和负载均衡的核心组件它会为一组具有相同标签的Pod分配一个固定的“服务IP”ClusterIP无论Pod如何变化IP变更、新增、删除通过这个固定的服务IP都能稳定访问到后端的Pod同时还能实现Pod之间的负载均衡。本文专门针对小白从“为什么要用Service、Service核心概念、三种常用Service类型ClusterIP/NodePort/LoadBalancer的配置与实战、Service与Deployment的关联”四个维度手把手教你掌握Service全程实操、命令可复制、yaml可直接复用还会补充常见问题排错和企业级最佳实践帮你彻底打通K8s服务访问的关键环节实现从“部署应用”到“访问应用”的闭环。前置要求已搭建好K8s集群掌握Pod、Deployment的基本概念和kubectl常用命令参考第二、三、四篇教程已部署好Nginx Deployment可参考第四篇实战步骤无需额外准备其他环境。一、先搞懂为什么要用Service核心痛点优势在学习Service之前我们先明确核心痛点和Service的核心优势小白务必理解——Service不是多余的组件而是K8s集群中“不可或缺的服务访问入口”。1.1 核心痛点Pod IP动态变化无法稳定访问直接访问Pod的三大致命问题也是Service要解决的核心痛点Pod IP动态变化Pod的生命周期是短暂的无论是Deployment自动重建、扩缩容还是滚动更新Pod都会被重新创建新Pod的IP会发生变化旧IP会失效直接通过IP访问会频繁失败。无负载均衡如果有多个Pod如Deployment的多副本直接访问Pod IP只能访问到单个Pod无法将请求均匀分发到所有Pod会导致单个Pod负载过高其他Pod闲置无法充分利用资源。集群内外访问隔离Pod IP属于集群内部私有IP只能在K8s集群内部如其他Pod访问外部客户端如本地电脑、手机无法直接访问Pod无法对外提供服务。1.2 Service的核心优势Service通过以下3点完美解决上述痛点成为K8s服务访问的核心入口固定访问入口Service会分配一个固定的“服务IP”ClusterIP这个IP在Service的生命周期内不会变化无论后端Pod如何变化通过这个固定IP就能稳定访问到后端Pod。内置负载均衡Service会自动识别所有具有相同标签的Pod将客户端的请求均匀分发到这些Pod上实现负载均衡避免单个Pod负载过高提升应用的并发处理能力。支持集群内外访问不同类型的ServiceNodePort/LoadBalancer支持外部客户端访问解决“集群内Pod可访问、外部无法访问”的问题实现应用对外提供服务。1.3 Service和Pod、Deployment的关系重点区分很多小白会混淆Service、Pod、Deployment的关系这里用一句通俗的话总结Deployment管理Pod的生命周期Service管理Pod的访问入口。核心逻辑三者协同工作流程Deployment通过Pod模板创建多个Pod并维护Pod的副本数确保Pod正常运行Service通过“标签选择器”匹配到Deployment管理的所有Pod这些Pod具有相同的标签Service分配一个固定的ClusterIP对外提供访问入口客户端通过ClusterIP访问ServiceService将请求负载均衡到后端的Pod上。简单理解Deployment → 管理Pod运行应用Service → 给Pod“穿一件固定的访问外套”无论Pod如何变化外套ClusterIP不变客户端只需要访问外套就能找到里面的Pod。二、Service核心概念小白必懂学习Service之前先掌握几个核心概念后续实战会频繁用到无需死记硬背理解作用即可标签选择器selectorService的核心配置用于匹配后端的Pod必须和Pod的labels完全一致和Deployment的selector逻辑一致。比如Service的selector是app: nginx-pod那么所有标签为app: nginx-pod的Pod都会被该Service管理。ClusterIP集群内部IPService默认分配的IP地址属于K8s集群内部的私有IP只能在集群内部如其他Pod、Master节点访问无法被集群外部访问是Service最基础的访问方式。端口映射portsService需要配置“端口映射”将Service的端口映射到Pod的端口容器端口客户端访问Service的端口请求会被转发到Pod的对应端口。核心包含三个端口小白重点区分portService的端口集群内部访问Service时使用的端口可自定义如80targetPortPod的容器端口后端应用实际运行的端口如Nginx的80端口nodePort可选NodePort类型Service的端口用于集群外部访问会在所有Node节点上开放一个端口外部客户端通过“NodeIP:nodePort”访问Service。Service类型typeService有4种类型小白重点掌握前3种第4种ExternalName很少用了解即可ClusterIP默认类型只能在集群内部访问分配固定的ClusterIPNodePort在每个Node节点上开放一个固定端口外部客户端通过“NodeIP:nodePort”访问适合测试环境LoadBalancer结合云服务商的负载均衡器如阿里云SLB、腾讯云CLB自动分配一个公网IP外部客户端通过该公网IP访问适合生产环境ExternalName将Service映射到集群外部的域名如www.baidu.com无需后端Pod适合访问集群外部服务。三、Service核心配置yaml详解重中之重和Pod、Deployment一样Service的部署也分为“命令行方式”测试用和“yaml配置文件方式”生产用生产环境优先使用yaml方式规范、可复用、可版本控制。下面先给出三种常用Service类型ClusterIP/NodePort/LoadBalancer的完整yaml模板可直接复制复用再逐字段详解重点记“必配字段”和“不同类型的差异”。3.1 通用yaml核心字段所有类型都包含无论哪种Service类型都包含以下核心字段小白先掌握这些通用字段apiVersion: v1# API版本Service的API版本固定为v1kind: Service# 资源类型这里是Servicemetadata:# 元数据描述Service的基本信息name: nginx-svc# Service的名称必须唯一labels:# 标签用于标识Service可选app: nginx-svc spec:# 规格核心配置selector:# 标签选择器匹配后端Pod必须和Pod的labels一致app: nginx-pod# 匹配标签为app: nginx-pod的Podports:# 端口映射数组形式可配置多个端口- port:80# Service的端口集群内部访问用targetPort:80# Pod的容器端口后端应用端口protocol: TCP# 协议TCP/UDP默认TCPtype: ClusterIP# Service类型默认是ClusterIP3.2 三种常用Service类型yaml模板可直接复制重点区分三种类型的差异核心差异在“type”字段和“nodePort”字段仅NodePort类型需要。3.2.1 ClusterIP类型默认集群内部访问最常用的类型适合集群内部Pod之间的访问如后端服务访问数据库服务无法被集群外部访问apiVersion: v1 kind: Service metadata: name: nginx-svc-clusterip labels: app: nginx-svc-clusterip spec: selector: app: nginx-pod ports: - port:80targetPort:80protocol: TCP type: ClusterIP# 类型为ClusterIP默认可省略3.2.2 NodePort类型集群外部访问测试用适合测试环境外部客户端通过“NodeIP:nodePort”访问nodePort范围是30000-32767K8s默认范围不可超出apiVersion: v1 kind: Service metadata: name: nginx-svc-nodeport labels: app: nginx-svc-nodeport spec: selector: app: nginx-pod ports: - port:80targetPort:80nodePort:30080# NodePort端口30000-32767之间protocol: TCP type: NodePort# 类型为NodePort3.2.3 LoadBalancer类型集群外部访问生产用适合生产环境需要结合云服务商的负载均衡器如阿里云、腾讯云会自动分配一个公网IP外部客户端通过该公网IP访问无需配置nodePortapiVersion: v1 kind: Service metadata: name: nginx-svc-loadbalancer labels: app: nginx-svc-loadbalancer spec: selector: app: nginx-pod ports: - port:80targetPort:80protocol: TCP type: LoadBalancer# 类型为LoadBalancer3.3 yaml核心字段详解小白必记apiVersion: v1必配字段Service属于“核心资源”API版本固定为v1和Pod的apiVersion一致。kind: Service必配字段指定资源类型为Service区别于Podkind: Pod和Deploymentkind: Deployment。**metadata元数据**和Pod、Deployment的metadata结构一致核心子字段nameService名称唯一、labels标签自定义可选可选字段namespace命名空间。spec规格核心中的核心Service的核心配置所有关键功能匹配Pod、端口映射、访问类型都在这里配置核心子字段selector标签选择器必配字段用于匹配后端的Pod必须和Pod的labels完全一致否则Service无法找到Pod。比如Pod的标签是app: nginx-podService的selector也必须是app: nginx-pod。ports端口映射必配字段数组形式可配置多个端口映射核心子字段portService的端口集群内部访问Service时使用的端口可自定义如80、8080无需和targetPort一致但建议保持一致便于记忆。targetPort必配字段Pod的容器端口后端应用实际运行的端口如Nginx的80端口、Tomcat的8080端口Service会将请求转发到这个端口。nodePort可选字段仅NodePort类型需要配置范围是30000-32767K8s会在所有Node节点上开放这个端口外部客户端通过“NodeIP:nodePort”访问。protocol可选字段协议类型默认是TCP可根据需求改为UDP如DNS服务。typeService类型必配字段默认是ClusterIP可根据需求改为NodePort或LoadBalancer三种类型的差异前面已经详细讲解。四、Service完整实战三种类型全覆盖结合前面的yaml模板我们进行全程实操覆盖三种常用Service类型的部署、访问和删除所有命令可直接复制小白跟着做就能完成全程在Master节点执行。前置准备确保已部署好Nginx Deployment参考第四篇实战Deployment名称为nginx-deployPod标签为app: nginx-pod副本数3个可通过以下命令确认# 查看Deployment状态kubectl get deployment nginx-deploy# 查看Pod状态确认Pod标签为app: nginx-pod状态为Runningkubectl get pods-lappnginx-pod-owide4.1 实战1部署ClusterIP类型Service集群内部访问ClusterIP是默认类型只能在集群内部访问适合集群内Pod之间的通信如后端服务访问数据库。步骤1创建yaml文件nginx-svc-clusterip.yamlvinginx-svc-clusterip.yaml粘贴ClusterIP类型的yaml模板保存退出Esc → :wq。步骤2部署Service# 用yaml文件部署Servicekubectl apply-fnginx-svc-clusterip.yaml# 查看Service状态确认部署成功kubectl get svc# svc是service的缩写可简写# 查看Service的详细信息包含ClusterIP、标签选择器、端口映射等kubectl describe svc nginx-svc-clusterip关键说明kubectl get svc 输出中TYPE为ClusterIPCLUSTER-IP为分配的固定IP如10.96.xx.xxPORT(S)为80:443/TCP443是K8s默认的端口映射可忽略。ClusterIP只能在集群内部访问我们可以通过集群内的Pod如创建一个临时Pod测试访问步骤3测试集群内部访问# 创建一个临时的busybox Pod用于测试访问kubectl run busybox-test--imagebusybox:1.35--rm-it-- /bin/sh# 在临时Pod内部访问Service的ClusterIP替换为自己的ClusterIPwget-O-10.96.xx.xx:80# 输出Nginx的首页内容说明访问成功# 退出临时Pod退出后Pod会自动删除exit4.2 实战2部署NodePort类型Service集群外部访问测试用NodePort类型适合测试环境外部客户端如本地电脑可通过“NodeIP:nodePort”访问Service进而访问后端Pod。步骤1创建yaml文件nginx-svc-nodeport.yamlvinginx-svc-nodeport.yaml粘贴NodePort类型的yaml模板nodePort设为30080保存退出。步骤2部署Service# 部署NodePort类型Servicekubectl apply-fnginx-svc-nodeport.yaml# 查看Service状态确认TYPE为NodePortPORT(S)为80:30080/TCPkubectl get svc nginx-svc-nodeport步骤3测试集群外部访问第一步获取Node节点的IP集群中任意一个Node节点的IP都可以# 查看Node节点IPkubectl get nodes-owide第二步外部客户端本地电脑访问“NodeIP:30080”如192.168.xx.xx:30080打开浏览器访问该地址能看到Nginx的首页说明访问成功。注意如果是云服务器如阿里云ECS需要在安全组中开放30080端口否则外部无法访问。4.3 实战3部署LoadBalancer类型Service集群外部访问生产用LoadBalancer类型适合生产环境需要结合云服务商的负载均衡器如阿里云SLB、腾讯云CLB部署后会自动分配一个公网IP外部客户端通过该公网IP访问无需配置nodePort。注意该类型在本地虚拟机集群如VMware中无法正常使用没有云服务商的负载均衡器仅在云服务器集群如阿里云EKS、腾讯云TKE中可用。步骤1创建yaml文件nginx-svc-loadbalancer.yamlvinginx-svc-loadbalancer.yaml粘贴LoadBalancer类型的yaml模板保存退出。步骤2部署Service# 部署LoadBalancer类型Servicekubectl apply-fnginx-svc-loadbalancer.yaml# 查看Service状态等待EXTERNAL-IP分配分配完成后显示公网IPkubectl get svc nginx-svc-loadbalancer步骤3测试集群外部访问外部客户端本地电脑直接访问Service的EXTERNAL-IP公网IP端口为80如http://公网IP:80能看到Nginx的首页说明访问成功。4.4 实战4Service与Deployment的联动关键Service会自动关联具有相同标签的Pod当Deployment扩缩容、滚动更新时Service会自动识别新的Pod、剔除失效的Pod无需手动修改Service配置这是Service的核心优势之一。步骤1扩缩容Deployment将副本数从3扩到5kubectl scale deployment nginx-deploy--replicas5# 查看Pod状态确认有5个Podkubectl get pods-lappnginx-pod步骤2查看Service的后端Pod确认Service已关联新的Pod# 查看Service关联的PodENDPOINTS字段会显示所有Pod的IP和端口kubectl describe svc nginx-svc-clusterip|grepEndpoints步骤3测试访问无论Pod如何变化Service的访问入口不变# 再次通过临时Pod访问Service依然能正常访问kubectl run busybox-test--imagebusybox:1.35--rm-it-- /bin/shwget-O-10.96.xx.xx:80exit4.5 实战5删除Service测试完成后删除Service时只会删除Service本身不会删除后端的Pod和Deployment后端Pod依然正常运行只是无法通过该Service访问。# 按名称删除三种类型的Servicekubectl delete svc nginx-svc-clusterip kubectl delete svc nginx-svc-nodeport kubectl delete svc nginx-svc-loadbalancer# 查看结果确认Service已删除kubectl get svc五、Service常用操作命令高频汇总可直接复制整理了Service日常操作的高频命令分类汇总方便小白查询和使用和Pod、Deployment的命令逻辑一致容易记忆5.1 部署与查看命令# 1. 用yaml部署Servicekubectl apply-f文件名.yaml# 2. 查看所有Service简写svckubectl get svc# 3. 查看指定Service的详细信息kubectl describe svc Service名称# 4. 查看Service的yaml配置kubectl get svc Service名称-oyaml# 5. 查看Service关联的Pod通过标签筛选kubectl get pods-lappnginx-pod# 替换为自己的Pod标签5.2 更新与删除命令# 1. 更新Service配置修改yaml后执行kubectl apply-f文件名.yaml# 2. 命令行修改Service类型如将ClusterIP改为NodePortkubectl patch svc Service名称-p{spec:{type:NodePort,ports:[{port:80,targetPort:80,nodePort:30081}]}}# 3. 删除指定Servicekubectl delete svc Service名称# 4. 通过yaml文件删除Servicekubectl delete-f文件名.yaml5.3 访问测试命令# 1. 集群内部测试访问通过临时Podkubectl run busybox-test--imagebusybox:1.35--rm-it-- /bin/shwget-O- ClusterIP:port# 替换为自己的ClusterIP和Service端口# 2. 查看Service的Endpoints确认关联的Podkubectl describe svc Service名称|grepEndpoints六、常见问题排错小白必看**问题1部署Service后无法访问后端PodService的Endpoints为空**原因Service的selector和Pod的labels不匹配导致Service无法找到Pod或Pod未正常运行状态不是Running。解决1. 检查Service的selector和Pod的labels确保完全一致kubectl get svc Service名称 -o yaml 查看selectorkubectl get pods -l appxxx 查看Pod标签2. 检查Pod状态确保Pod处于Running状态kubectl get pods -l appxxx。**问题2NodePort类型Service外部无法访问浏览器访问NodeIP:nodePort失败**原因1. NodeIP错误使用了Master节点的IP而非Node节点的IP2. nodePort超出30000-32767范围3. 防火墙/安全组未开放nodePort端口4. Pod未正常运行。解决1. 确认Node节点IPkubectl get nodes -o wide2. 检查nodePort范围修改为30000-32767之间3. 开放防火墙/安全组端口如阿里云安全组开放30080端口4. 检查Pod状态。问题3LoadBalancer类型ServiceEXTERNAL-IP一直显示pending原因该类型需要结合云服务商的负载均衡器本地虚拟机集群如VMware不支持或云服务器集群未配置负载均衡器权限。解决本地测试用NodePort类型生产环境使用云服务器集群如阿里云EKS并确保账号有负载均衡器权限。**问题4访问Service时出现“Connection refused”连接拒绝**原因1. Pod的容器端口targetPort配置错误如Nginx的端口是80却配置为80802. 容器内部应用未正常启动如Nginx未启动。解决1. 检查Service的targetPort确保和Pod的容器端口一致2. 查看Pod日志确认应用正常启动kubectl logs Pod名称。问题5Service的ClusterIP无法访问原因ClusterIP是集群内部私有IP只能在集群内部访问外部客户端无法直接访问或集群网络插件Flannel/Calico异常。解决1. 在集群内部通过临时Pod测试访问2. 检查网络插件状态kubectl get pods -n kube-system确保网络插件正常运行。七、企业级最佳实践小白进阶结合生产环境的实际需求补充3个Service的最佳实践小白可以直接应用到自己的部署中Service类型选择测试环境用NodePort类型生产环境用LoadBalancer类型云服务器集群集群内部Pod之间的通信用ClusterIP类型无需暴露到外部。端口规范port和targetPort建议保持一致如都用80、8080便于记忆和维护NodePort端口建议从30000开始按应用类型分配如Nginx用30080Tomcat用30808避免端口冲突。标签规范Service的selector和Pod的labels要规范命名如app: nginx-pod、app: mysql-pod避免标签混乱导致Service无法匹配PodDeployment和Service的标签建议关联如Deployment的标签是app: nginx-deployService的标签是app: nginx-svc便于管理。生产环境安全生产环境中避免使用NodePort类型端口暴露过多不安全优先使用LoadBalancer类型并配置安全组限制外部访问来源集群内部通信ClusterIP可结合NetworkPolicy网络策略限制Pod之间的访问提升安全性。八、总结及下一篇预告本文详细讲解了Service的核心知识点和完整实战从“为什么要用Service”到“核心概念、yaml配置”再到“三种常用Service类型的部署与访问”覆盖了小白入门Service的所有关键内容也补充了常见问题排错和企业级最佳实践帮你彻底解决“Pod IP动态变化无法稳定访问”的难题。重点记住3点Service的核心作用是“固定访问入口负载均衡”解决Pod IP动态变化的访问问题是K8s服务访问的核心组件三种常用Service类型的区别ClusterIP集群内部访问、NodePort测试用外部访问、LoadBalancer生产用外部访问需云服务商支持Service通过“标签选择器”关联Pod和Deployment协同工作Pod变化时Service无需手动配置自动关联新Pod、剔除失效Pod。下一篇文章我们将学习K8s的存储机制——《K8s 存储管理Volume 与 PersistentVolume 全实战》带你解决“Pod删除后数据丢失”的问题实现数据持久化存储敬请关注最后如果你觉得这篇文章对你有帮助欢迎点赞、收藏、关注后续会持续更新K8s系列实战文章从入门到精通带你轻松搞定K8s
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2426772.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!