Kubernetes Service 與網路設定

在 Kubernetes 叢集中,Pod 是短暫且動態的,它們的 IP 位址可能隨時改變。為了提供穩定的網路存取方式,Kubernetes 引入了 Service 的概念。本文將介紹 Service 的類型、建立方式、DNS 解析機制以及 Endpoint 的運作原理。

Service 類型

Kubernetes 提供了四種主要的 Service 類型,每種類型都有其特定的使用場景。

ClusterIP

ClusterIP 是 Kubernetes 中最基本也是預設的 Service 類型。它會為 Service 分配一個叢集內部的虛擬 IP 位址,只有叢集內部的 Pod 可以存取這個 Service。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: Service
metadata:
  name: my-clusterip-service
spec:
  type: ClusterIP
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

使用場景:

  • 內部微服務之間的通訊
  • 資料庫服務(如 MySQL、PostgreSQL)
  • 快取服務(如 Redis、Memcached)

NodePort

NodePort 類型的 Service 會在每個節點上開放一個固定的連接埠(範圍為 30000-32767),外部流量可以透過 <NodeIP>:<NodePort> 存取服務。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30080

使用場景:

  • 開發和測試環境
  • 不需要負載平衡器的小型部署
  • 直接存取特定節點的服務

LoadBalancer

LoadBalancer 類型的 Service 會向雲端供應商請求一個外部負載平衡器,自動將流量分發到後端的 Pod。這種類型通常用於生產環境中需要對外暴露的服務。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

使用場景:

  • 生產環境的對外服務
  • 需要高可用性的應用程式
  • 雲端環境(AWS、GCP、Azure)中的服務暴露

ExternalName

ExternalName 是一種特殊的 Service 類型,它不會建立任何代理或轉發規則,而是透過 DNS CNAME 記錄將服務名稱對應到外部的 DNS 名稱。

1
2
3
4
5
6
7
apiVersion: v1
kind: Service
metadata:
  name: my-external-service
spec:
  type: ExternalName
  externalName: external.example.com

建立 Service

使用 kubectl 命令建立

最簡單的方式是使用 kubectl expose 命令:

1
2
3
4
5
# 為 Deployment 建立 Service
kubectl expose deployment my-deployment --port=80 --target-port=8080

# 指定 Service 類型
kubectl expose deployment my-deployment --port=80 --target-port=8080 --type=NodePort

使用 YAML 檔案建立

建立一個完整的 Service YAML 檔案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: Service
metadata:
  name: web-service
  namespace: default
  labels:
    app: web
spec:
  type: ClusterIP
  selector:
    app: web
    tier: frontend
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080
    - name: https
      protocol: TCP
      port: 443
      targetPort: 8443
  sessionAffinity: None

然後套用設定:

1
kubectl apply -f service.yaml

驗證 Service 狀態

1
2
3
4
5
6
7
8
# 列出所有 Service
kubectl get services

# 查看 Service 詳細資訊
kubectl describe service web-service

# 查看 Service 的 YAML 定義
kubectl get service web-service -o yaml

DNS 解析

Kubernetes 叢集內建 DNS 服務(通常是 CoreDNS),為每個 Service 自動建立 DNS 記錄。

DNS 命名規則

Service 的完整 DNS 名稱格式為:

1
<service-name>.<namespace>.svc.cluster.local

例如,在 default 命名空間中名為 web-service 的 Service,其完整 DNS 名稱為:

1
web-service.default.svc.cluster.local

DNS 解析範例

在同一個命名空間內,可以直接使用 Service 名稱:

1
2
3
4
5
6
7
8
# 同一命名空間內
curl http://web-service

# 跨命名空間存取
curl http://web-service.other-namespace

# 完整 DNS 名稱
curl http://web-service.other-namespace.svc.cluster.local

測試 DNS 解析

可以使用 nslookupdig 命令測試 DNS 解析:

1
2
3
4
5
# 建立一個測試 Pod
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- nslookup web-service

# 使用 dig 命令
kubectl run dns-test --image=tutum/dnsutils --rm -it --restart=Never -- dig web-service.default.svc.cluster.local

Headless Service

當不需要負載平衡和單一 Service IP 時,可以建立 Headless Service(將 clusterIP 設為 None)。DNS 查詢會直接返回所有後端 Pod 的 IP 位址。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

Endpoint

Endpoint 是 Kubernetes 中用來追蹤 Service 後端 Pod IP 位址的資源。當 Pod 被建立或刪除時,Endpoint 會自動更新。

查看 Endpoint

1
2
3
4
5
6
7
8
# 列出所有 Endpoint
kubectl get endpoints

# 查看特定 Service 的 Endpoint
kubectl get endpoints web-service

# 詳細資訊
kubectl describe endpoints web-service

輸出範例:

1
2
NAME          ENDPOINTS                                   AGE
web-service   10.244.1.5:8080,10.244.2.3:8080            5m

Endpoint 的運作原理

  1. 選擇器匹配:Service 透過 selector 選擇符合標籤的 Pod
  2. 自動更新:Endpoint Controller 會監控 Pod 的狀態變化
  3. 健康檢查:只有通過 readiness probe 的 Pod 才會被加入 Endpoint

手動管理 Endpoint

在某些情況下,您可能需要手動建立 Endpoint,例如指向叢集外部的服務:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 建立無選擇器的 Service
apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  ports:
    - port: 3306
      targetPort: 3306
---
# 手動建立 Endpoint
apiVersion: v1
kind: Endpoints
metadata:
  name: external-db
subsets:
  - addresses:
      - ip: 192.168.1.100
      - ip: 192.168.1.101
    ports:
      - port: 3306

EndpointSlice

在 Kubernetes 1.21 之後,EndpointSlice 成為預設的 Endpoint 管理方式。它提供更好的擴展性,特別是在大型叢集中。

1
2
3
4
5
# 查看 EndpointSlice
kubectl get endpointslices

# 查看特定 Service 的 EndpointSlice
kubectl get endpointslices -l kubernetes.io/service-name=web-service

總結

Kubernetes Service 是建立穩定網路存取的核心元件:

類型存取範圍使用場景
ClusterIP叢集內部內部微服務通訊
NodePort節點 IP + 連接埠開發測試環境
LoadBalancer外部負載平衡器生產環境對外服務
ExternalNameDNS CNAME存取外部服務

透過 Service、DNS 解析和 Endpoint 的協作,Kubernetes 提供了強大且靈活的服務發現與網路通訊機制,讓應用程式能夠在動態的容器環境中保持穩定運作。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy