Kubernetes的Service详解
一、Service介绍


Service 是 Kubernetes 中用于定义一组 Pod 的逻辑集合及其访问策略的抽象。主要解决以下问题:
-
服务发现:动态 Pod 环境下,如何找到其他服务。
-
负载均衡:将流量均匀分发到多个 Pod 实例。
-
解耦访问:客户端无需关心 Pod 的具体 IP 或节点位置。
-
稳定访问端点:Pod 可能频繁重建,Service 提供固定访问入口(ClusterIP/DNS)。
二、Service的核心原理
1、kube-proxy:负责实现 Service 的流量转发,支持以下模式:
-
iptables(默认):通过 iptables 规则转发流量。
-
IPVS:高性能模式,基于内核的 IPVS 负载均衡。
-
userspace(已弃用):用户空间代理。
2、Endpoints:Service 通过标签选择器(Selector)动态维护后端 Pod 的 IP 列表(Endpoints 对象)。
3、EndpointSlice:替代 Endpoints 的扩展机制,支持更大规模的服务(分片存储 Endpoint 信息)。
三、Service常见的三种类型
Service的资源清单文件:
kind: Service # 资源类型
apiVersion: v1 # 资源版本
metadata: # 元数据
name: service # 资源名称
namespace: dev # 命名空间
spec: # 描述
selector: # 标签选择器,用于确定当前service代理哪些pod
app: nginx
type: # Service类型,指定service的访问方式
clusterIP: # 虚拟服务的ip地址
sessionAffinity: # session亲和性,支持ClientIP、None两个选项
ports: # 端口信息
- protocol: TCP
port: 3017 # service端口
targetPort: 5003 # pod端口
nodePort: 31122 # 主机端口
实验环境准备:
创建一个deployment.yaml文件,内容如下:
[root@k8s-master test]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pc-deployment
namespace: dev
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
#创建
[root@k8s-master test]# kubectl create -f deployment.yaml
#查看详情
[root@k8s-master test]# # kubectl get pods -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pc-deployment-575f6f4ff-7p8hs 1/1 Running 0 36m 100.125.152.6 k8s-node02 <none> <none>
pc-deployment-575f6f4ff-lhqj4 1/1 Running 0 36m 100.97.125.7 k8s-node01 <none> <none>
pc-deployment-575f6f4ff-mvnrp 1/1 Running 0 36m 100.97.125.8 k8s-node01 <none> <none>
#为了后面的测试,修改三台nginx的index.html页面(三台修改的IP地址不一样)
kubectl exec -it pc-deployment-575f6f4ff-7p8hs -n dev /bin/sh
# echo "`hostname`" > /usr/share/nginx/html/index.html
修改完毕,访问测试:
1、ClusterIP
默认类型,为集群内部提供访问的虚拟 IP(仅在集群内可访问)
Kubernetes 中 Deployment 仅管理 Pod 副本,需通过 Service 暴露 Pod 服务,否则外部无法访问。
如果写yaml不太熟练的话,可以执行以下命令导入一个文件中:
[root@k8s-master test]# kubectl create service clusterip nginx-svc1 --tcp=80:80 -n dev --dry-run=client -o yaml > service-clusterip.yaml
[root@k8s-master test]# cat service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: service-clusterip
namespace: dev
spec:
selector:
app: nginx-pod
clusterIP: 10.96.1.100 # service的ip地址,如果不写(删掉),就会默认生成一个IP地址
type: ClusterIP
ports:
- port: 80 # Service端口
targetPort: 80 # pod端口
# 创建 service[root@k8s-master test]# kubectl create -f service-clusterip.yamlservice / service-clusterip created# 查看 service[root@k8s-master test]# kubectl get svc -n dev -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service-clusterip ClusterIP 10.96.1.100 <none> 80/TCP 2s app=nginx-pod
2、NodePort
在 ClusterIP 基础上,在每个节点上开放一个静态端口(NodeIP:NodePort)
[root@k8s-master test]# cat service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: service-nodeport
namespace: dev
spec:
selector:
app: nginx-pod
type: NodePort
ports:
- port: 80 # Service端口
nodePort: 30002
targetPort: 80 # pod端口
# 创建service
[root@master ~]# kubectl create -f service-nodeport.yaml
service/service-nodeport created
# 查看service
[root@master ~]# kubectl get svc -n dev -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service-headliness ClusterIP None <none> 80/TCP 9m10s app=nginx-pod
service-nodeport NodePort 10.96.1.99 <none> 80:30002/TCP 18s app=nginx-pod
# 接下来可以通过电脑主机的浏览器去访问集群中任意一个nodeip的30002端口,即可访问到pod
3、LoadBalancer
通过云提供商的负载均衡器(如 AWS ELB、GCP LB)暴露服务到外部。
LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
不分配 ClusterIP,直接访问 Pod 的 IP 或通过 DNS 解析,客户端需要自行实现负载均衡。
三款开源 Kubernetes 负载均衡器: MetalLB vs PureLB vs OpenELB
apiVersion: v1
kind: Service
metadata:
name: my-loadbalancer-service
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
externalTrafficPolicy: Local # 保留客户端源 IP(默认是 Cluster)