跳到主要内容

Service 与网络

Service 为一组 Pod 提供稳定的网络访问入口,是 Kubernetes 实现服务发现和负载均衡的核心资源。

什么是 Service?

Service 是一个抽象层,为一组 Pod 提供稳定的 IP 地址和 DNS 名称,屏蔽了 Pod 的动态性。

Service 类型

1. ClusterIP(默认)

仅在集群内部可访问:

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
# 访问 Service
# 在集群内通过 DNS 或 IP 访问
curl http://my-service.default.svc.cluster.local
curl http://10.0.0.100:80

2. NodePort

在每个节点的固定端口上暴露服务:

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 指定端口(30000-32767)
protocol: TCP
name: http
# 访问 Service
curl http://<node-ip>:30080

3. LoadBalancer

使用云提供商的负载均衡器:

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
protocol: TCP

4. ExternalName

映射到外部域名:

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ExternalName
externalName: my.external.domain

Service 端点

Service 自动维护 EndpointSlice,追踪后端 Pod:

apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 10.1.0.1
targetRef:
kind: Pod
name: pod-1
- ip: 10.1.0.2
targetRef:
kind: Pod
name: pod-2
ports:
- port: 80
protocol: TCP

服务发现

DNS 机制

Kubernetes 提供集群内 DNS 自动解析:

# Service DNS 格式
# <service-name>.<namespace>.svc.cluster.local

# 简写(同一命名空间)
curl http://my-service

# 跨命名空间
curl http://my-service.other-namespace.svc.cluster.local

无头服务(Headless Service)

不分配 ClusterIP,直接解析 Pod IP:

apiVersion: v1
kind: Service
metadata:
name: headless-service
spec:
clusterIP: None # 关键:设置为 None
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
# DNS 解析返回所有 Pod IP
nslookup headless-service.default.svc.cluster.local

Ingress

Ingress 是 HTTP/HTTPS 路由的入口:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80

Ingress 配置示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
# SSL 重定向
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# 启用 CORS
nginx.ingress.kubernetes.io/enable-cors: "true"
spec:
tls:
- hosts:
- myapp.example.com
secretName: my-tls-secret
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80

NetworkPolicy

NetworkPolicy 用于控制 Pod 间的网络流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-network-policy
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: web
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432

常用场景

# 1. 拒绝所有入站流量(默认拒绝)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
spec:
podSelector: {}
policyTypes:
- Ingress

# 2. 允许同一命名空间内的流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
spec:
podSelector: {}
ingress:
- from:
- podSelector: {}

# 3. 允许特定标签的流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend

DNS 服务

CoreDNS 配置

apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
}

网络调试命令

# 查看 Service
kubectl get svc

# 查看 Endpoint
kubectl get endpoints

# 查看 Ingress
kubectl get ingress

# 查看 NetworkPolicy
kubectl get networkpolicy

# 描述 Service
kubectl describe svc my-service

# 测试 DNS 解析
kubectl exec -it busybox -- nslookup my-service

# 端口转发测试
kubectl port-forward svc/my-service 8080:80

最佳实践

1. 使用合适的 Service 类型

# 生产环境推荐:ClusterIP + Ingress
spec:
type: ClusterIP

2. 为 Service 添加标签

metadata:
labels:
app: my-app
tier: backend

3. 使用健康检查

确保 Pod 的就绪探针正常工作,Service 只会将流量路由到就绪的 Pod。

4. 使用 NetworkPolicy

# 限制 Pod 间访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress

服务网格(Service Mesh)

Istio 简介

Istio 是流行的服务网格解决方案,提供:

  • mTLS 加密
  • 流量管理
  • 可观测性
  • 安全策略
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-service
spec:
hosts:
- my-service
http:
- route:
- destination:
host: my-service
subset: v1
weight: 90
- destination:
host: my-service
subset: v2
weight: 10

小结

本章我们学习了:

  1. Service 概念:稳定的网络入口
  2. Service 类型:ClusterIP、NodePort、LoadBalancer、ExternalName
  3. 服务发现:DNS 解析和无头服务
  4. Ingress:HTTP/HTTPS 路由
  5. NetworkPolicy:网络策略控制
  6. 网络调试:常用命令和工具

练习

  1. 创建一个 NodePort 类型的 Service
  2. 配置 Ingress 实现基于路径的路由
  3. 创建 NetworkPolicy 限制 Pod 访问
  4. 使用 kubectl 调试服务连接

准备好继续学习了吗?点击下一章了解存储管理!