1413 words
7 minutes
kubernetes-service
1.NodePort
- 通过NodePort类型的Service,可以将Pod暴露到集群外部,通过Node的IP和NodePort访问Pod
- 服务于多个Node的集群,可以通过任何Node的IP和NodePort访问Pod
- NodePort端口范围:30000-32767
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 80 # default 与 port一致
nodePort: 30080 # optional, 30000-32767
selector: # link with pod definition metadata.labels
app: my-app
2.ClusterIP
- ClusterIP类型的Service,只能在集群内部访问,通过ClusterIP访问Pod, eg.前后端交流, 数据库访问
- ClusterIP类型的Service,可以通过其他Service访问
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP # default
ports:
- port: 80 # svc 暴露端口
targetPort: 80 # 目标pod端口
selector: # link with pod definition metadata.labels
app: my-app
3.LoadBalancer
- LoadBalancer类型的Service,可以将Pod暴露到集群外部,通过外部负载均衡器访问Pod, 如果在不支持的环境创建,会被默认为NodePort类型的Service
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: my-app
1. Service 简介
在 Kubernetes(K8s)中,Service(服务)用于提供稳定的网络访问,即使 Pod 副本数量变化,其访问入口(Service 的 Cluster IP 或外部 IP)仍然保持不变。
Service 的主要目标:
- 提供稳定访问:Pod 可能会重启、扩缩容,但 Service 提供一个固定的网络入口。
- 负载均衡:自动将流量分发到后端的多个 Pod。
- 服务发现:通过 Kubernetes DNS 解析 Service 名称,使应用间通信更容易。
2. Service 工作原理
Service 通过 Labels 选择后端 Pod,并使用 kube-proxy 进行流量转发。流量调度可基于 iptables 或 IPVS 规则实现。
Service 的基本工作流程如下:
- 创建 Service:定义一个 Service,指定选择的 Pod(通过
selector
)。 - Kube-proxy 监听:
kube-proxy
监听 API Server 变化,更新 iptables/IPVS 规则。 - Pod 访问 Service:应用通过 Service 名称访问时,流量会被负载均衡到后端 Pod。
示意图:
+--------------------+ +--------------------+
| Service (VIP) | ---> | Pod 1 (Backend) |
| 10.96.0.1 | | |
| my-service | ---> | Pod 2 (Backend) |
| selector: app=X | | |
+--------------------+ +--------------------+
3. Service 的核心组件
- kube-proxy
- 监听 Kubernetes API Server,维护 iptables/IPVS 规则,将 Service IP 映射到后端 Pod。
- Endpoints
- Service 会自动创建
Endpoints
对象,存储可用 Pod 的 IP 和端口。 - 可通过
kubectl get endpoints
查看。
- Service 会自动创建
- Kubernetes DNS
- 通过 CoreDNS 解析 Service 名称,使 Pod 之间能通过
my-service.default.svc.cluster.local
访问。
- 通过 CoreDNS 解析 Service 名称,使 Pod 之间能通过
4. Service 类型
类型 | 说明 | 访问方式 |
---|---|---|
ClusterIP(默认) | 仅在集群内部可访问 | curl http://<service-name> |
NodePort | 通过集群节点 IP 和指定端口访问 | http://<NodeIP>:<NodePort> |
LoadBalancer | 在云平台创建外部负载均衡 | http://<External-IP> |
ExternalName | 代理请求到外部 DNS | http://<External-Domain> |
Headless | 无 ClusterIP,直接解析到 Pod IP | http://pod-ip:port |
5. Service 配置示例
(1)ClusterIP(默认类型,内部访问)
- 适用于集群内部 Pod 之间的通信: ![[Pasted image 20250309153854.png]]
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80 # Service 端口
targetPort: 8080 # Pod 端口
验证 Service:
kubectl get svc my-service kubectl get endpoints my-service
(2)NodePort(暴露到集群外部)
![[Pasted image 20250309153814.png]]
- 适用于集群外部访问,Kubernetes 自动分配
30000-32767
端口:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30080 # 可手动指定端口(可选)
访问方式:
curl http://<NodeIP>:30080
(3)LoadBalancer(云平台自动创建外部负载均衡)
- 适用于 AWS、GCP、Azure 等云环境:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
访问方式:
curl http://<External-IP>
(4)ExternalName(代理外部服务)
- 适用于 Kubernetes 内部访问外部服务,如
example.com
:
apiVersion: v1
kind: Service
metadata:
name: my-external-service
spec:
type: ExternalName
externalName: example.com
访问方式:
curl http://my-external-service
(5)Headless Service(无 ClusterIP,直接访问 Pod)
被创建后并不会被分配一个 VIP,而是会以 DNS 记录的方式暴露出它所代理的 Pod: <pod-name>.<svc-name>.<namespace>.svc.cluster.local
- 适用于 StatefulSet 或 DNS 直接解析:
apiVersion: v1
kind: Service
metadata:
name: headless-service
spec:
clusterIP: None
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
访问方式:
nslookup headless-service
6. Service 关键参数
参数 | 说明 |
---|---|
selector | 选择匹配的 Pod |
ports.port | Service 监听的端口 |
ports.targetPort | Pod 的应用端口 |
type | Service 类型(ClusterIP、NodePort、LoadBalancer、ExternalName) |
sessionAffinity | ClientIP 方式保持会话 |
7. Service 进阶
Session Affinity(会话保持)
- 默认情况下,Service 负载均衡到不同 Pod,可以开启 基于 IP 的粘性会话:
- 将同一客户端的请求始终路由到同一个 Pod
- 工作原理: Kubernetes Service 会记录客户端 IP 与后端 Pod 的对应关系,并将来自同一 IP 的请求始终路由到该 Pod。
spec: sessionAffinity: ClientIP
Health Check(健康检查)
- 通过
readinessProbe
确保 Service 仅发送流量到健康 Pod: readinessProbe
用于检测 Pod 是否准备好接收流量。只有通过readinessProbe
检查的 Pod 才会被添加到 Service 的后端 Endpoint 列表中。- 重要性: 确保 Service 只将流量发送到运行正常的 Pod,避免将流量发送到尚未启动或运行异常的 Pod。
readinessProbe: #service会定期的通过HTTP的GET方法,去访问POD的8080端口的/health路径,如果返回的状态码是200,则表明这个POD是健康的 httpGet: path: /health port: 8080
- 通过
与 Ingress 结合
- 用于管理外部流量到集群内部 Service 的路由
- 关系:
- Ingress 通过 Service 将外部流量路由到后端的 Pod。
- Service 负责在 Pod 之间进行负载均衡,而 Ingress 负责根据主机名、路径等信息将流量路由到不同的 Service。
- Ingress 通过 Service 将外部流量路由到内部 Pod:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: rules: - host: my-app.example.com #定义了当请求路径以 / 开头时,将流量转发到名为 my-service 的 Service 的 80 端口。 http: paths: - path: / pathType: Prefix backend: service: name: my-service port: number: 80
8. Service Debug & 排查
检查 Service 是否创建成功
kubectl get svc my-service
查看 Service 对应的 Endpoints
kubectl get endpoints my-service
查看 Pod 是否能访问 Service
kubectl exec -it <pod-name> -- curl http://my-service:80
检查 kube-proxy 规则
iptables -t nat -L -n | grep my-service
kubernetes-service
https://fuwari.vercel.app/posts/kubernetes-service/kubernetes-service/