概念解析

Service是Kubernetes中的核心概念之一,它為一組Pod提供穩定的網絡端點。由於Pod是臨時的且IP地址會變化,Service為客户端提供了一種穩定的方式來訪問應用程序。

核心概念

  1. 穩定的網絡端點:Service為一組Pod提供固定的IP地址和DNS名稱
  2. 負載均衡:自動在後端Pod之間分發流量
  3. 服務發現:通過DNS或環境變量發現服務
  4. 標籤選擇:通過標籤選擇器確定後端Pod

Service的工作原理

  1. Service通過標籤選擇器選擇一組Pod
  2. Endpoint Controller為Service創建Endpoints對象,包含所有匹配Pod的IP地址
  3. kube-proxy監視Service和Endpoints的變化,在每個節點上配置iptables或ipvs規則
  4. 當流量到達Service的ClusterIP時,kube-proxy將流量轉發到後端Pod

核心特性

  1. 多種服務類型:ClusterIP、NodePort、LoadBalancer、ExternalName
  2. 負載均衡:支持輪詢、隨機等多種負載均衡算法
  3. 會話親和性:支持基於客户端IP的會話親和性
  4. 多端口支持:單個Service可以暴露多個端口
  5. 服務發現:通過DNS或環境變量自動發現服務
  6. Headless Service:為有狀態應用提供特殊服務類型

實踐教程

創建ClusterIP Service

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

創建NodePort Service

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

創建LoadBalancer Service

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

服務發現示例

# 通過DNS訪問服務
curl http://my-service.namespace.svc.cluster.local

# 查看服務環境變量(在Pod內部)
env | grep SERVICE

# 查看Endpoints
kubectl get endpoints my-service

真實案例

案例:微服務架構中的服務通信

在一個典型的微服務架構中,前端應用需要與用户服務、訂單服務、支付服務等多個後端服務通信。通過Service可以實現服務間的穩定通信:

# 用户服務
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: mycompany/user-service:1.0
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
---
# 訂單服務
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
      - name: order-service
        image: mycompany/order-service:1.0
        ports:
        - containerPort: 8080
        env:
        - name: USER_SERVICE_URL
          value: "http://user-service"  # 通過Service名稱訪問
---
apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  selector:
    app: order-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

在訂單服務中,可以通過http://user-service直接訪問用户服務,無需關心具體的Pod IP地址。

配置詳解

多端口Service

apiVersion: v1
kind: Service
metadata:
  name: multi-port-service
spec:
  selector:
    app: MyApp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 9376
  - name: https
    protocol: TCP
    port: 443
    targetPort: 9377

Headless Service

apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  clusterIP: None
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

帶會話親和性的Service

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

ExternalName Service

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

故障排除

常見問題及解決方案

  1. 服務無法訪問

    # 檢查Service配置
    kubectl describe service <service-name>
    
    # 檢查Endpoints
    kubectl get endpoints <service-name>
    
    # 檢查Pod標籤是否匹配
    kubectl get pods --show-labels
    
  2. DNS解析失敗

    # 在Pod中測試DNS解析
    kubectl exec -it <pod-name> -- nslookup <service-name>
    
    # 檢查CoreDNS狀態
    kubectl get pods -n kube-system -l k8s-app=kube-dns
    
  3. 負載均衡不工作

    # 檢查Endpoints數量
    kubectl get endpoints <service-name>
    
    # 檢查Pod狀態
    kubectl get pods -l <selector-labels>
    
  4. NodePort無法訪問

    # 檢查NodePort範圍
    kubectl get service <service-name> -o wide
    
    # 檢查防火牆規則
    # 檢查節點網絡連通性
    

最佳實踐

  1. 命名規範

    • 使用有意義的服務名稱
    • 遵循DNS命名規範
  2. 標籤管理

    • 為Service和Pod使用一致的標籤
    • 使用版本標籤區分不同版本的服務
  3. 端口管理

    • 明確指定targetPort
    • 為多端口服務使用有意義的端口名稱
  4. 服務類型選擇

    • 內部服務使用ClusterIP
    • 外部訪問使用NodePort或LoadBalancer
    • 外部服務使用ExternalName
  5. 健康檢查

    • 配置合適的readiness探針確保服務可用性
    • 監控服務狀態
  6. 安全考慮

    • 限制不必要的外部訪問
    • 使用網絡策略控制服務間通信

安全考慮

網絡策略限制服務訪問

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow
spec:
  podSelector:
    matchLabels:
      app: api
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

使用TLS加密服務通信

apiVersion: v1
kind: Service
metadata:
  name: secure-service
spec:
  selector:
    app: secure-app
  ports:
  - name: https
    protocol: TCP
    port: 443
    targetPort: 8443

配合相應的證書配置,確保服務間通信的安全性。

命令速查

命令 描述
kubectl get services 查看Service列表
kubectl describe service <name> 查看Service詳細信息
kubectl get endpoints <name> 查看Service的Endpoints
kubectl apply -f <service.yaml> 創建或更新Service
kubectl delete service <name> 刪除Service
kubectl expose deployment <name> --port=<port> 為Deployment創建Service
kubectl get svc 查看Service簡寫命令
kubectl patch service <name> -p '{"spec":{"type":"NodePort"}}' 修改Service類型
kubectl get services -o wide 查看Service詳細信息
kubectl exec -it <pod-name> -- nslookup <service-name> 在Pod中測試DNS解析

總結

Service是Kubernetes中實現服務發現和負載均衡的核心組件。通過本文檔的學習,你應該能夠:

  • 理解Service的概念和工作機制
  • 創建不同類型的Service
  • 配置服務發現和負載均衡
  • 排查常見的Service問題
  • 遵循Service的最佳實踐和安全考慮

在下一文檔中,我們將學習Ingress控制器,它是管理外部訪問集羣服務的重要組件。