Kubernetes集群服务发现与负载均衡

Kubernetes服务发现和负载均衡是Kubernetes网络模型中的核心组件,它们确保了应用在集群中的可访问性和高可用性。

主要方面

服务发现(Service Discovery)

服务发现是Kubernetes中自动检测和定位服务的机制。在Kubernetes中,服务发现主要通过以下方式实现:

  1. DNS服务发现:通过CoreDNS为每个Service提供DNS记录
  2. 环境变量注入:在Pod创建时自动注入已存在的Service信息到环境变量中
  3. API Server查询:直接查询API Server获取Service和Endpoints信息

负载均衡(Load Balancing)

Kubernetes提供了多种负载均衡机制来分发流量到后端Pod:

  1. ClusterIP:集群内部虚拟IP负载均衡
  2. NodePort:通过节点端口暴露服务
  3. LoadBalancer:云提供商的负载均衡器
  4. ExternalName:通过CNAME记录将服务映射到外部名称

实施配置

Service资源配置

创建一个基本的Service配置示例:

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

Headless Service配置

当不需要负载均衡或单一服务IP时,可以创建Headless Service:

apiVersion: v1
kind: Service
metadata:
  name: my-headless-service
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

ExternalName Service配置

将服务映射到外部系统:

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

NodePort Service配置

通过节点端口暴露服务:

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

主要架构组件

CoreDNS

CoreDNS是Kubernetes默认的DNS服务器,负责服务发现。它通过kubernetes插件监听Kubernetes API,为Service和Pod创建DNS记录。

核心配置示例:

cluster.local {
    kubernetes {
        pods verified
        fallthrough in-addr.arpa ip6.arpa
    }
    cache 30
    reload
}

kube-proxy

kube-proxy运行在每个节点上,负责实现Kubernetes Service的网络代理和负载均衡功能。它支持三种模式:

  1. iptables模式:使用iptables规则进行流量转发
  2. IPVS模式:使用Linux IP Virtual Server进行负载均衡
  3. 用户空间模式:较老的实现方式,性能较差

Endpoints Controller

Endpoints Controller是Kubernetes控制平面的一部分,负责维护Service和Pod之间的关联关系。当Service的selector匹配到Pod时,Endpoints Controller会自动创建或更新Endpoints对象。

Endpoints对象

Endpoints对象存储了Service后端Pod的实际网络地址信息:

apiVersion: v1
kind: Endpoints
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 10.244.0.5
        nodeName: node-1
      - ip: 10.244.1.6
        nodeName: node-2
    ports:
      - port: 8080
        protocol: TCP

应用场景

内部服务通信

最常见的应用场景是集群内服务之间的通信。通过Service,应用可以使用稳定的DNS名称访问其他服务,而不需要关心后端Pod的具体IP地址。

# 在集群内的Pod中访问其他服务
curl http://my-app-service.namespace.svc.cluster.local

外部访问应用

通过NodePort或LoadBalancer类型的Service,外部客户端可以访问集群内的应用:

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

服务发现与微服务

在微服务架构中,服务发现机制使得服务能够动态地发现和调用其他服务:

// Go应用中通过服务名称调用其他服务
resp, err := http.Get("http://user-service/api/users")

蓝绿部署和金丝雀发布

通过配置不同的Service和Deployment,可以实现蓝绿部署和金丝雀发布:

# 稳定版本服务
apiVersion: v1
kind: Service
metadata:
  name: app-stable
spec:
  selector:
    app: my-app
    version: v1.0
  # ...

---
# 金丝雀版本服务
apiVersion: v1
kind: Service
metadata:
  name: app-canary
spec:
  selector:
    app: my-app
    version: v2.0
  # ...

跨集群服务访问

通过ExternalName类型的Service,可以访问集群外部的服务:

apiVersion: v1
kind: Service
metadata:
  name: external-database
spec:
  type: ExternalName
  externalName: database.company.internal

高级配置选项

会话亲和性(Session Affinity)

保持客户端请求始终路由到同一个Pod:

apiVersion: v1
kind: Service
metadata:
  name: session-affinity-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

外部流量策略(External Traffic Policy)

控制外部流量如何处理:

apiVersion: v1
kind: Service
metadata:
  name: external-policy-service
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080
  type: LoadBalancer
  externalTrafficPolicy: Local

健康检查配置

配置服务的健康检查端点:

apiVersion: v1
kind: Service
metadata:
  name: health-check-service
  annotations:
    service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  publishNotReadyAddresses: true

故障排除

DNS解析问题

检查CoreDNS是否正常运行:

kubectl get pods -n kube-system -l k8s-app=kube-dns

测试服务DNS解析:

kubectl run -it --rm debug --image=busybox -- nslookup my-service

Service访问问题

检查Service和Endpoints:

kubectl get service my-service
kubectl get endpoints my-service

检查kube-proxy状态:

kubectl get pods -n kube-system -l k8s-app=kube-proxy

最佳实践

  1. 合理使用Service类型:根据访问需求选择合适的Service类型
  2. 配置适当的会话亲和性:根据应用需求配置sessionAffinity
  3. 使用命名空间隔离:通过命名空间组织和隔离服务
  4. 监控和告警:监控Service和Endpoints状态,设置适当的告警
  5. 安全配置:使用网络策略(NetworkPolicy)限制服务访问

通过合理的配置和管理,Kubernetes的服务发现和负载均衡机制可以为应用提供稳定、高可用的网络访问能力。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐