在 Kubernetes(简称 K8s)的生态体系中,Service 扮演着至关重要的角色,它是保障集群内服务间通信、实现服务对外暴露以及进行负载均衡的核心组件。无论是微服务架构下众多服务的相互协作,还是将应用服务开放给外部用户访问,都离不开对 Kubernetes Service 的合理运用与精细管理。本文将围绕 Kubernetes Service 管理的丰富内容,从 ClusterIP、NodePort 到 Ingress,再到 Web 管理插件及服务账号权限等方面,进行全方位、深层次的解析,助力你透彻掌握 Kubernetes Service 管理的精髓。
一、ClusterIP:集群内部服务通信的基石
(一)ClusterIP 基础认知
ClusterIP 是 Kubernetes Service 默认的服务类型,它为服务分配一个仅能在集群内部访问的虚拟 IP 地址(即 ClusterIP) 。这个 IP 地址是 Kubernetes 集群内部服务发现和通信的关键,使得集群内的其他 Pod 可以通过该固定 IP 来访问对应服务,无需关心后端提供服务的 Pod 具体是哪些、如何动态变化,极大简化了服务间调用的复杂度。
(二)创建服务(以 Nginx 服务为例)
apiVersion: v1
kind: Service
metadata:
name: nginx-clusterip-service
spec:
type: ClusterIP
selector:
app: nginx
ports:
- protocol: TCP
port: 80 # 服务暴露在ClusterIP上的端口
targetPort: 80 # 后端Pod监听的端口
通过kubectl apply -f nginx-clusterip-service.yaml
命令即可创建该 Service。Kubernetes 会基于selector
(这里匹配标签app: nginx
的 Pod ),将对该 ClusterIP 服务的请求转发到对应的后端 Pod 上,实现集群内服务的调用。
(三)解析域名:便捷的服务访问方式
Kubernetes 为每个 Service 自动创建对应的 DNS 记录,格式通常为<service - name>.<namespace>.svc.cluster.local
。比如上述nginx-clusterip-service
服务,如果在default
命名空间下,其域名就是nginx-clusterip-service.default.svc.cluster.local
。集群内的 Pod 可以直接通过这个域名访问服务,无需记忆 ClusterIP,Kubernetes 的 DNS 插件(如 CoreDNS )会负责域名解析工作,将域名转换为对应的 ClusterIP,让服务间通信更加灵活、便捷。
(四)创建后端应用与负载均衡
- 创建后端应用(Nginx Pod 示例)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.6
ports:
- containerPort: 80
使用kubectl apply -f nginx-deployment.yaml
创建 Deployment,会生成 3 个带有app: nginx
标签的 Pod ,作为nginx-clusterip-service
服务的后端应用。
2. 负载均衡机制
当多个 Pod 作为后端为 ClusterIP 服务提供支持时,Kubernetes 的 kube - proxy 组件会在集群节点上实现负载均衡。kube - proxy 通过一种或多种调度算法(如轮询等,可配置),将客户端对 Service 的请求均匀地分发到各个后端 Pod 上,充分利用多个 Pod 的计算资源,提高服务的整体处理能力和响应效率,保障服务稳定、高效运行。
(五)固定 IP 服务与端口别名
1.固定 IP 服务
ClusterIP 服务的 IP 是由 Kubernetes 集群自动分配的,但在一些特定场景下,可能需要固定 Service 的 IP。不过 Kubernetes 本身并不直接支持手动指定 ClusterIP(除非在创建 Service 时,集群内该 IP 未被占用且符合 IP 规划 ),一般可通过在创建 Service 的 YAML 文件中显式设置clusterIP
字段来尝试指定,如下:
apiVersion: v1
kind: Service
metadata:
name: nginx-clusterip-fixed-service
spec:
type: ClusterIP
clusterIP: 10.96.0.100 # 需确保该IP在集群Service IP范围内且未被占用
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
2.端口别名
可以通过在 Service 的ports
定义中,为port
(服务端口)和targetPort
(Pod 端口)设置更具语义的名称,方便理解和维护,例如:
ports:
- protocol: TCP
name: http - service - port # 服务端口别名
port: 80
targetPort: http - pod - port # Pod端口别名,需在Pod定义的容器端口中对应
不过targetPort
的别名需要后端 Pod 的容器端口定义中实际存在,比如 Pod 的容器端口定义:
containers:
- name: nginx
image: nginx:1.21.6
ports:
- containerPort: 80
name: http - pod - port
(六)服务排错
- 检查 Service 状态
使用kubectl get services
查看 Service 的基本信息,包括 ClusterIP、端口、是否关联到 Pod(通过ENDPOINTS
字段判断,若ENDPOINTS
为空,说明selector
可能配置错误,未匹配到 Pod )。例如kubectl get services nginx-clusterip-service
- 检查 Endpoints
Endpoints 是 Kubernetes 用来记录 Service 对应后端 Pod 的资源,通过kubectl get endpoints <service - name>
查看,如kubectl get endpoints nginx-clusterip-service
,正常情况下应显示与 Serviceselector
匹配的 Pod 的 IP 和端口信息。若没有,需检查 Deployment 的selector
和 Service 的selector
是否一致。 - 测试服务访问
在集群内的某个 Pod 中(可通过kubectl run -it --rm test - pod --image=busybox
创建临时测试 Pod ),使用wget
或curl
命令访问 Service 的 ClusterIP 或域名,测试是否能正常获取响应,如curl http://nginx-clusterip-service.default.svc.cluster.local
,根据返回结果判断服务是否可访问,排查网络策略、防火墙规则等可能影响通信的因素。
二、NodePort:对外发布服务的常用方式
(一)对外发布服务原理与配置
NodePort 类型的 Service 会在集群的每个节点上开放一个指定的端口(nodePort
字段指定,范围一般是 30000 - 32767 ),外部用户可以通过<节点IP>:<nodePort>
的方式访问集群内的服务。它是在 ClusterIP 的基础上,将服务暴露到集群节点的网络接口上,实现对外访问。
以下是 NodePort Service 的 YAML 示例:
apiVersion: v1
kind: Service
metadata:
name: nginx - nodeport - service
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80 # 集群内Service的端口
targetPort: 80 # 后端Pod端口
nodePort: 30080 # 节点上开放的端口,需在30000 - 32767之间且未被占用
创建后,通过kubectl apply -f nginx - nodeport - service.yaml
,外部就可以使用任意集群节点的 IP 加上 30080 端口访问 Nginx 服务了,比如集群节点 IP 为192.168.1.100
,则访问地址是http://192.168.1.100:30080
。
(二)适用场景与优缺点
- 适用场景
适用于一些简单的对外服务暴露需求,比如在测试环境中,快速将服务开放给外部测试人员访问;或者服务调用方是固定的 IP 地址,且可以直接通过节点 IP + 端口的方式访问的场景。 - 优点
配置简单直接,能够快速实现服务对外暴露;不需要额外的 ingress 控制器等复杂组件,依赖 Kubernetes 自身的 kube - proxy 和节点网络即可工作。 - 缺点
每个 NodePort 服务会占用节点上的一个端口,端口资源有限(30000 - 32767 ),大量服务对外暴露时容易出现端口冲突;且服务访问地址是节点 IP + 端口,当节点 IP 发生变化(如节点故障替换)时,访问地址需要相应调整,不够灵活和友好。
三、Ingress:精细管控对外服务暴露
(一)Ingress 概念与作用
Ingress 是 Kubernetes 中用于管理外部对集群内服务访问的 API 资源,它本身并不直接提供服务暴露功能,而是需要结合 Ingress 控制器(如 Nginx Ingress Controller、Traefik 等 )来实现。Ingress 可以根据不同的域名、路径等规则,将外部的 HTTP/HTTPS 请求转发到集群内对应的 Service 上,实现更精细、灵活的服务路由和对外暴露,像一个智能的 “流量网关”,统一管理集群的对外服务入口。
(二)安装控制器(以 Nginx Ingress Controller 为例)
1.使用 Helm 安装(推荐,简单高效)
首先确保集群已安装 Helm,然后添加 Nginx Ingress Controller 的 Helm 仓库:
bash
helm repo add ingress - nginx https://kubernetes.github.io/ingress - nginx
helm repo update
接着安装 Ingress Controller:
bash
helm install nginx - ingress ingress - nginx/ingress - nginx --namespace ingress - nginx --create - namespace
2.手动安装(了解流程,适合定制化场景)
从 GitHub 下载 Nginx Ingress Controller 的部署文件(https://github.com/kubernetes/ingress - nginx/tree/main/deploy/static/provider/cloud ),根据集群环境修改相关配置(如镜像地址、资源限制等 ),然后使用kubectl apply -f
命令依次部署所需的资源,包括 Deployment、Service(一般是 LoadBalancer 类型或 NodePort 类型,根据实际需求 )、ServiceAccount 等,确保 Ingress Controller 正常运行。
(三)验证后端服务
在使用 Ingress 对外发布服务前,需要确保后端的 Service 和 Pod 正常工作。可以按照前面 ClusterIP 或 NodePort 服务的创建方式,先创建好提供实际功能的 Service 和对应的后端应用 Pod,然后通过集群内访问的方式(如使用 ClusterIP 访问 Service )验证服务是否能正常响应,保证后端服务自身无问题,为 Ingress 转发请求打好基础。
(四)对外发布服务(Ingress 规则配置示例)
假设要将前面的 Nginx 服务通过 Ingress 以nginx.example.com
域名、/nginx
路径对外发布,Ingress 规则 YAML 如下:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx - ingress - rule
annotations:
nginx.ingress.kubernetes.io/rewrite - target: / # 路径重写,将/nginx路径重写为/,方便后端服务处理
spec:
rules:
- host: nginx.example.com
http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: nginx - clusterip - service # 关联的ClusterIP服务
port:
number: 80
创建该 Ingress 规则(kubectl apply -f nginx - ingress - rule.yaml
)后,确保 Ingress 控制器正常运行且能获取到该规则,外部用户就可以通过http://nginx.example.com/nginx
(需配置本地 DNS 或使用 Hosts 文件将nginx.example.com
解析到 Ingress 控制器所在节点的 IP )访问到集群内的 Nginx 服务了。Ingress 控制器会根据规则,将请求转发到对应的 Service,再由 Service 转发到后端 Pod 处理。
四、Web 管理插件:Dashboard 助力可视化管理
(一)安装 Dashboard
- 部署 Dashboard 资源
从 Kubernetes 官方获取 Dashboard 的部署文件(https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml ),使用kubectl apply -f recommended.yaml
命令部署 Dashboard 相关的资源,包括 Deployment、Service 等。默认情况下,Dashboard 的 Service 是 ClusterIP 类型,只能在集群内访问。 - 暴露 Dashboard 服务(可选,如需外部访问)
如果需要从外部访问 Dashboard,可以将其 Service 类型修改为 NodePort 或 LoadBalancer。例如,修改 Service 的 YAML:
yaml
apiVersion: v1
kind: Service
metadata:
name: kubernetes - dashboard
namespace: kubernetes - dashboard
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30443 # 自定义节点端口
selector:
k8s - app: kubernetes - dashboard
然后kubectl apply -f
更新 Service,之后就可以通过https://<节点IP>:30443
访问 Dashboard(注意是 HTTPS 协议,需要处理证书相关问题,可使用自签名证书或配置正确的 CA 证书 )。
(二)发布服务与管理
- 登录 Dashboard
获取登录令牌,一般可以通过创建一个具有管理员权限的 ServiceAccount 并绑定 ClusterRole 来获取。示例如下:
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin - user
namespace: kubernetes - dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin - user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster - admin
subjects:
- kind: ServiceAccount
name: admin - user
namespace: kubernetes - dashboard
创建后,使用kubectl -n kubernetes - dashboard get secret $(kubectl -n kubernetes - dashboard get sa/admin - user -o jsonpath="{.secrets[0].name}") -o go - template="{{.data.token | base64decode}}"
命令获取令牌,然后在 Dashboard 登录页面输入令牌登录。
2. 管理服务
登录 Dashboard 后,可以直观地查看集群内所有的 Service 资源,包括 Service 的类型、ClusterIP、关联的 Pod 等信息;也可以通过 Dashboard 创建、编辑、删除 Service,图形化的操作界面对于不熟悉命令行的用户非常友好,方便进行日常的服务管理和监控。
五、服务账号与权限:保障集群安全访问
(一)创建服务账号
服务账号(ServiceAccount)是 Kubernetes 中用于标识运行在 Pod 内的进程的身份,可通过 YAML 文件创建,示例:
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: my - service - account
namespace: default
使用kubectl apply -f my - service - account.yaml
创建后,该服务账号就可以被 Pod 引用,作为 Pod 内进程访问 Kubernetes API 或其他资源的身份标识。
(二)获取用户 token
创建服务账号后,Kubernetes 会自动为其生成一个 Secret 来存储令牌(token)。可以通过以下命令获取:
bash
kubectl get secret $(kubectl get serviceaccount my - service - account -o jsonpath="{.secrets[0].name}") -o go - template="{{.data.token | base64decode}}"
这个令牌可以用于 Pod 内的应用程序访问 Kubernetes API 时进行身份认证,比如在 Pod 中运行的服务需要调用 Kubernetes API 获取集群内其他资源信息时,就可以使用该令牌进行认证。
(三)角色与鉴权
1.角色(Role)与集群角色(ClusterRole)
Role 是用于在某个命名空间内定义权限规则的资源,ClusterRole 则是在整个集群范围内定义权限规则。例如,创建一个在default
命名空间内具有查看 Pod 和 Service 权限的 Role:
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod - service - viewer
namespace: default
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list", "watch"]
ClusterRole 示例(具有查看所有命名空间 Pod 和 Service 的权限 ):
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster - pod - service - viewer
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list", "watch"]
2.角色绑定(RoleBinding)与集群角色绑定(ClusterRoleBinding)
RoleBinding 用于将 Role 绑定到用户、服务账号等主体,使其在对应的命名空间内拥有 Role 定义的权限。例如,将上面的pod - service - viewer
Role 绑定到my - service - account
服务账号:
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my - service - account - bind
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name