谁再说搞不懂 k8s 四种 Service 类型!就把这个给他甩过去。
Kubernetes(简称k8s) 是一个开源的容器编排平台,用于自动化应用程序的部署、扩展和管理。它最初由谷歌设计,并基于谷歌内部多年运行容器化工作负载的经验(即Borg系统)开发而成,后来捐赠给云原生计算基金会(CNCF)进行维护和推广。Kubernetes 已经成为容器编排领域的事实标准,广泛应用于云原生应用开发和微服务架构中。
在 Kubernetes 中,Service 是一种抽象概念,用于将一组运行在 Pods 上的应用程序暴露为网络服务。Kubernetes 提供了四种主要的 Service 类型,每种类型适用于不同的使用场景。
k8s 四种 Service 类型:ClusterIP、NodePort、LoadBalancer、ExternalName,今天一次性给你们讲清楚。
ClusterIP
它是 Kubernetes Service的默认类型,也就是说如果不指定 type
,Kubernetes 会默认创建 ClusterIP
类型的 Service。
仅在集群内部可访问,提供一个集群内部的虚拟 IP 地址(ClusterIP)。适用于集群内部的服务发现和通信,例如微服务之间的调用。
简单易用,默认类型,无需额外配置。它提供稳定的虚拟 IP 和 DNS 名称,便于服务发现。且负载均衡和故障转移由 Kubernetes 自动处理。
工作原理
- 虚拟 IP 分配:当创建一个 ClusterIP Service 时,Kubernetes 会为其分配一个虚拟 IP(ClusterIP),这个 IP 来自集群的 Service CIDR 范围(例如
10.96.0.0/12
)。 - Endpoints 管理:Service 通过
selector
字段选择一组 Pod 作为后端。Kubernetes 会自动创建与 Service 同名的 Endpoints 对象,其中包含所有匹配selector
的 Pod 的 IP 和端口。如果 Pod 发生变化(例如扩容或重启),Endpoints 会自动更新。 - 流量转发:每个节点上的
kube-proxy
组件会监听 Service 和 Endpoints 的变化,并在节点上配置 iptables 或 IPVS 规则,将流量从 ClusterIP 转发到后端 Pod。
使用场景
- 微服务架构:在微服务架构中,服务之间通过 ClusterIP 进行内部通信。例如,前端服务通过 ClusterIP 访问后端 API 服务。
- 数据库服务:数据库服务(如 MySQL、PostgreSQL)通常只在集群内部暴露,使用 ClusterIP 可以确保外部无法直接访问。
- 监控和日志系统:监控系统(如 Prometheus)、日志系统(如 Elasticsearch)等,通常只在集群内部使用。
配置 ClusterIP 服务
使用 YAML 文件配置 ClusterIP 服务
编写 Service 定义文件:
- 指定
type: ClusterIP
(默认值,可省略)。 - 配置
selector
以匹配目标 Pod 的标签。 - 定义
ports
,包括port
(Service 的端口)和targetPort
(Pod 的端口)。
应用 YAML 文件
kubectl apply -f your-service.yaml
示例 YAML 文件
apiVersion: v1
kind:Service
metadata:
name:my-clusterip-service
spec:
type:ClusterIP#可省略,默认就是 ClusterIP
selector:
app:my-app#匹配 Pod 的标签
ports:
-protocol:TCP
port:80 #Service 的端口,集群内的其他 Pod 通过该端口访问服务。
targetPort:8080#Pod 的端口,Service 将流量转发到该端口。
使用 kubectl 命令行工具配置 ClusterIP 服务
创建 Service
kubectl expose deployment my-deployment \
--type=ClusterIP \
--name=my-clusterip-service \
--port=80 \
--target-port=8080
验证 Service
kubectl get svc my-clusterip-service
验证 ClusterIP 服务
获取 ClusterIP 地址:
kubectl get svc my-clusterip-service
输出示例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-clusterip-service ClusterIP 10.96.123.45 <none> 80/TCP 10s
从集群内部访问服务
假设有一个 Pod 运行在集群中,可以通过 ClusterIP
地址访问服务:
curl http://10.96.123.45:80
检查 Service 详情
kubectl describe svc my-clusterip-service
高级特性
指定 ClusterIP
如果需要手动指定 ClusterIP
,可以在 YAML 文件中添加 clusterIP
字段:
apiVersion: v1
kind:Service
metadata:
name:my-clusterip-service
spec:
type:ClusterIP
clusterIP:10.96.0.100#手动指定 ClusterIP
selector:
app:my-app
ports:
-protocol:TCP
port:80
targetPort:8080
注意:指定的 ClusterIP
必须在 Kubernetes 配置的地址范围内,且不能与其他服务冲突。
多端口支持
Service 可以暴露多个端口,每个端口可以映射到后端 Pod 的不同端口。
spec:
ports:
-name:http
protocol:TCP
port:80
targetPort:8080
-name:https
protocol:TCP
port:443
targetPort:8443
NodePort
Kubernetes Service 的 NodePort 类型 是一种用于将服务暴露到集群外部的 Service 类型。在每个节点上开放一个静态端口(NodePort),允许通过 <NodeIP>:<NodePort>
的方式从集群外部访问服务。NodePort
会在 ClusterIP
的基础上额外暴露一个端口。
NodePort
的端口范围默认是 30000-32767,也可以通过手工配置调整。由于每个服务占用一个节点端口,会导致端口资源有限,手动管理端口可能会导致冲突。总体性能和可用性不如 LoadBalancer。
工作原理
- NodePort 分配:当创建一个 NodePort Service 时,Kubernetes 会为其分配一个 ClusterIP,并在每个节点上开放一个静态端口(NodePort)。NodePort 的默认范围是
30000-32767
,但可以手动指定。 - 流量转发:每个节点上的
kube-proxy
组件会监听 Service 和 Endpoints 的变化,并通过 iptables 或 IPVS 规则将流量从 NodePort 转发到后端 Pod。 - 负载均衡:NodePort 会根据后端 Pod 的数量和状态,将流量均匀分配到可用的 Pod。
使用场景
- 开发和测试环境:NodePort 可以快速暴露服务,方便外部访问和调试。
- 小型生产环境:在没有负载均衡器的情况下,可以使用 NodePort 暴露服务。
- 直接访问节点:某些场景下,可能需要直接通过节点的 IP 地址访问服务,例如某些网络设备或旧系统。
- 云环境:NodePort 通常与 LoadBalancer 结合使用,LoadBalancer 会将外部流量导入 NodePort。
配置 NodePort 服务
在 Kubernetes 中,配置 NodePort 类型的服务可以通过 YAML 文件或 kubectl 命令行工具完成。
使用 YAML 文件配置 NodePort 服务
编写 Service 定义文件:
- 指定
type: NodePort
。 - 配置
selector
以匹配目标 Pod 的标签。 - 定义
ports
,包括targetPort
(Pod 的端口)和nodePort
。
应用 YAML 文件:
kubectl apply -f your-service.yaml
示例 YAML 文件
apiVersion: v1
kind:Service
metadata:
name:my-nodeport-service
spec:
type:NodePort#指定服务类型为 NodePort
selector: #用于匹配目标 Pod 的标签
app:my-app#匹配 Pod 的标签
ports:
-protocol:TCP
port:80 #Service 的端口,客户端通过该端口访问服务
targetPort:8080#Pod 的端口,Service 将流量转发到该端口
nodePort:30007#可选,指定节点端口(范围 30000-32767)
使用 kubectl 命令行工具配置 NodePort 服务
创建 Service:
kubectl expose deployment my-deployment \
--type=NodePort \
--name=my-nodeport-service \
--port=80 \
--target-port=8080 \
--node-port=30007
参数详解
expose deployment:#基于现有的 Deployment 创建 Service。
--type=NodePort:#指定服务类型为 NodePort。
--name:#指定 Service 的名称。
--port:#Service 的端口。
--target-port:#Pod 的端口。
--node-port:#指定节点端口(可选)。
验证 Service:
kubectl get svc my-nodeport-service
验证 NodePort 服务
获取节点 IP 地址:
kubectl get nodes -o wide
访问服务:使用节点 IP 和 NodePort 访问服务。
http://<Node-IP>:30007
检查 Service 详情:
kubectl describe svc my-nodeport-service
LoadBalancer
Kubernetes Service 的 LoadBalancer 类型 是一种用于将服务暴露到集群外部的 Service 类型,在 NodePort
的基础上,通过云服务商(如 AWS、GCP、Azure)的负载均衡器(Load Balancer)将外部流量导入到服务。提供一个外部可访问的 IP 地址,通常用于生产环境。
裸机环境或本地 Kubernetes 集群(如 Minikube)通常无法使用。
在支持 LoadBalancer 的云环境中,Kubernetes 会自动创建和管理负载均衡器,无需手动配置。
工作原理
- Service 创建:当创建一个 LoadBalancer 类型的 Service 时,Kubernetes 会根据云提供商的支持,自动创建一个负载均衡器。
- 外部 IP 分配:云提供商会为负载均衡器分配一个外部 IP 地址,该地址会关联到 Service。
- 流量转发:负载均衡器会将外部流量转发到 Service 的 ClusterIP,再由 kube-proxy 或 IPVS 将流量分发到后端的 Pod。
- 健康检查:负载均衡器会定期检查后端 Pod 的健康状态,确保流量只转发到健康的 Pod。
使用场景
- 云环境:在支持 LoadBalancer 的云提供商(如 AWS、GCP、Azure)中,LoadBalancer 类型 Service 是暴露服务的推荐方式。
- 需要外部访问的服务:例如 Web 应用、API 网关等,需要从集群外部访问的服务。
- 高可用性需求:需要负载均衡和高可用性的服务。
配置 LoadBalancer 类型服务
创建 LoadBalancer
类型的 Service。
以下是一个简单的 LoadBalancer
服务配置示例:
apiVersion: v1
kind:Service
metadata:
name:my-service
spec:
type:LoadBalancer#指定服务类型为 LoadBalancer
selector: #选择要暴露的 Pod,标签 app: my-app 用于匹配目标 Pod
app:my-app
ports:
-protocol:TCP
port:80 #服务暴露的端口(外部访问的端口)
targetPort:8080#Pod 中应用监听的端口
应用配置
将上述配置保存为 service.yaml
文件,然后使用 kubectl
命令应用配置:
kubectl apply -f service.yaml
检查服务状态
应用配置后,Kubernetes 会请求云服务提供商创建一个外部负载均衡器,并分配一个外部 IP 地址。可以通过以下命令查看服务状态:
kubectl get svc my-service
输出示例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service LoadBalancer 10.96.0.1 203.0.113.1 80:30007/TCP 10s
EXTERNAL-IP #表示负载均衡器的外部 IP 地址,外部用户可以通过该地址访问服务。
PORT(S) #显示服务端口和映射的节点端口。
访问服务
一旦 EXTERNAL-IP
可用,外部用户可以通过以下方式访问服务:
http://<EXTERNAL-IP>:80
例如,如果 EXTERNAL-IP
是 203.0.113.1
,则访问地址为:
http://203.0.113.1
配置注意事项
- 云服务提供商支持:
LoadBalancer
类型服务依赖于云服务提供商的负载均衡器。如果在本地或不支持LoadBalancer
的环境中运行(如 Minikube),可以使用NodePort
或Ingress
,或者安装 MetalLB 等解决方案。 - 安全组和防火墙规则:确保云服务提供商的安全组或防火墙规则允许外部流量访问负载均衡器的端口(如 80 或 443)。
- DNS 配置:可以将
EXTERNAL-IP
映射到一个域名,方便用户访问。 - 健康检查:云服务提供商通常会自动配置健康检查,确保流量只转发到健康的 Pod。如果需要自定义健康检查,可以参考云服务提供商的文档。
示例:暴露 HTTPS 服务
如果需要暴露 HTTPS 服务,可以修改 Service 配置并使用 Ingress
控制器管理 SSL 证书。例如:
apiVersion: v1
kind:Service
metadata:
name:my-https-service
spec:
type:LoadBalancer
selector:
app:my-app
ports:
-protocol:TCP
port:443
targetPort:8443
然后使用 Ingress
控制器(如 NGINX Ingress 或 Traefik)管理 SSL 证书和域名。
本地环境使用 MetalLB
如果在本地环境(如 Minikube 或裸机 Kubernetes 集群)中运行,可以使用 MetalLB) 模拟 LoadBalancer
类型服务。
安装 MetalLB:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.13/config/manifests/metallb-native.yaml
配置 IP 地址池:创建一个 ConfigMap
来定义 MetalLB 可分配的 IP 地址范围:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: my-ip-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.240-192.168.1.250
应用配置:
kubectl apply -f metallb-config.yaml
ExternalName
Kubernetes Service 的 ExternalName 类型是一种特殊的 Service 类型,用于将集群内部的服务映射到集群外部的 DNS 名称,而不是将流量路由到集群内的 Pod。
简单易用,无需创建实际的 Service 或 Pod,隐藏外部服务的复杂性,提供统一的 DNS 访问方式。仅支持 DNS 名称,无法映射到 IP 地址。也不提供负载均衡或故障转移。
工作原理
- DNS 映射:
ExternalName
类型的 Service 通过 DNS 解析将请求转发到指定的外部域名。 - 无代理或负载均衡:与
ClusterIP
、NodePort
或LoadBalancer
类型不同,ExternalName
不会创建代理或负载均衡器,也不会分配集群 IP。 - 简单配置:只需指定
externalName
字段,Kubernetes 会自动将 Service 的 DNS 名称解析为指定的外部域名。
使用场景
- 访问外部服务:例如,访问外部数据库(如 MySQL、PostgreSQL)、消息队列(如 RabbitMQ)或第三方 API。
- 服务迁移:在将服务从外部迁移到 Kubernetes 集群时,可以先使用
ExternalName
类型 Service 进行过渡。 - 简化服务发现:通过 Kubernetes 的 DNS 服务发现机制,客户端可以像访问集群内服务一样访问外部服务。
示例配置
以下是一个 ExternalName
类型 Service 的示例:
apiVersion: v1
kind:Service
metadata:
name:external-db#访问方式
spec:
type:ExternalName
externalName:my-external-db.example.com#指定外部服务的 DNS 名称
curl http://external-db:5432
总结
Service 类型 | 访问方式 | 适用场景 |
---|---|---|
ClusterIP | 仅集群内部 | 内部服务通信 |
NodePort | 集群外部通过 <NodeIP>:<NodePort> | 开发和测试环境 |
LoadBalancer | 集群外部通过负载均衡器 IP | 生产环境,需要外部负载均衡 |
ExternalName | 通过 DNS CNAME 映射到外部服务 | 访问集群外部服务 |
在 Kubernetes 中,四种 Service 类型(ClusterIP、NodePort、LoadBalancer、ExternalName)没有绝对的“好用类型”,而是根据具体o业务场景需求来选择最合适的类型。