博客 / 詳情

返回

k8s~deployment和service如何找到pod

deployment關聯到pod

spec.selector.matchLabels.deployment: hello

作用:

這是選擇器(Selector),用於告訴Deployment:

  • 識別哪些Pod屬於這個Deployment管理
  • 它會匹配集羣中已有的Pod標籤
  • 一個Deployment只能管理與自己selector匹配的Pod

關鍵點:

  • 用於查找和選擇現有的Pod
  • 決定Deployment的管理範圍
  • 一旦設置後不能修改(除非刪除整個Deployment重新創建)

spec.template.metadata.labels.deployment: hello

作用:

這是模板標籤(Template Labels),用於:

  • 定義新創建Pod的標籤
  • 當Deployment創建新Pod副本時,會給每個Pod打上這個標籤
  • 確保新Pod能夠被上面的selector選中

關鍵點:

  • 用於給新Pod打標籤
  • 決定新Pod的身份標識
  • 可以修改(觸發滾動更新)

兩者關係圖示

Deployment
├── selector.matchLabels: deployment=hello    ← 查找標準("我要管理哪些Pod?")
│
└── template
    └── metadata.labels: deployment=hello    ← 創建標準("我創建的Pod長這樣")
        │
        └── Pod1 (deployment=hello)          ← 被selector匹配到
        └── Pod2 (deployment=hello)          ← 被selector匹配到

為什麼需要兩者匹配?

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      deployment: hello  # ← 查找標籤為deployment=hello的Pod
  template:
    metadata:
      labels:
        deployment: hello  # ← 創建Pod時給它打上deployment=hello標籤
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2

如果不匹配會發生什麼?

假設:

  • selector匹配 deployment: hello
  • 但template標籤是 app: hello

結果:

  1. Deployment創建Pod時打上 app: hello 標籤
  2. Deployment的selector查找 deployment: hello 的Pod
  3. 找不到自己創建的Pod
  4. 無限創建新Pod(因為永遠達不到期望的副本數)
  5. 出現錯誤:"selector does not match template labels"

實際應用場景

1. 版本管理

selector:
  matchLabels:
    app: myapp  # 匹配所有myapp的Pod,無論版本

template:
  metadata:
    labels:
      app: myapp
      version: v1.2.3  # 創建特定版本的Pod

2. 多Deployment共享Pod

# Deployment A
selector:
  matchLabels:
    app: myapp
    tier: frontend

# Deployment B(也可以管理同樣的Pod)
selector:
  matchLabels:
    app: myapp
    managed-by: deployment-b

3. 金絲雀發佈

# 主Deployment
selector:
  matchLabels:
    app: myapp
    track: stable

# 金絲雀Deployment
selector:
  matchLabels:
    app: myapp
    track: canary

最佳實踐

  1. 始終保持一致:selector的標籤必須包含在template的標籤中
  2. 使用複合標籤:不要只用一個標籤,通常用2-3個標籤組合
  3. 避免修改selector:修改會導致Deployment無法管理現有Pod
  4. 使用有意義的標籤
labels:
  app: shopping-cart
  component: payment
  environment: production
  version: v2.1.0

總結對比

特性 selector.matchLabels template.metadata.labels
作用 選擇管理哪些Pod 定義新Pod的標籤
方向 從Pod到Deployment 從Deployment到Pod
可修改 不可修改(創建後) 可修改(觸發更新)
匹配關係 必須⊆ template的標籤 必須⊇ selector的標籤

簡單記憶:selector是"我要找誰",template是"我造的人長什麼樣"。Deployment用selector找到自己該管的人,然後用template製造新人。

service路由到pod

完全正確!你的理解非常準確。

Service Selector 的作用

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  selector:
    deployment: hello  # ← 這是選擇Pod的標籤,不是選擇Deployment!
  ports:
  - port: 80
    targetPort: 8080

Service的selector直接關聯到Pod,而不是Deployment,這是Kubernetes服務發現的核心機制。

詳細解釋

工作原理圖示

┌─────────────┐   管理    ┌─────────────┐   標籤匹配   ┌─────────────┐
│ Deployment  │──────────▶│     Pod     │◀────────────│   Service   │
│             │ 創建Pod  │ (deployment:hello) │ 流量轉發 │             │
└─────────────┘          └─────────────┘             └─────────────┘
      │                          ▲                          │
      │  設置Pod標籤             │                   通過標籤選擇Pod
      └──────────────────────────┘                          │
                                                          流量
                                                            ▼
                                                       客户端請求

關鍵區別

對象 選擇目標 選擇依據 作用
Deployment Selector Pod matchLabels 管理Pod的生命週期(創建、更新、刪除)
Service Selector Pod selector 將流量路由到匹配的Pod

完整示例

# 1. Deployment創建Pod並打標籤
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deployment
spec:
  selector:
    matchLabels:
      app: hello-app  # 管理標籤匹配的Pod
  template:
    metadata:
      labels:
        app: hello-app      # Service會匹配這個
        version: v1         # Service也會匹配這個(如果selector包含)
        environment: prod   # 額外標籤,Service不關心
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2

---
# 2. Service通過標籤選擇Pod
apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  selector:
    app: hello-app      # 選擇具有app=hello-app標籤的Pod
    # version: v1       # 也可以同時匹配多個標籤
  ports:
  - port: 80
    targetPort: 80

實際應用中的常見模式

模式1:一對一關聯

# Deployment
template.metadata.labels:
  app: frontend
  component: web

# Service
selector:
  app: frontend
  component: web
# 精確匹配特定應用的特定組件

模式2:一對多關聯

# 多個Deployment創建相同標籤的Pod
# Deployment A
template.metadata.labels:
  app: backend
  tier: api

# Deployment B(另一個版本的API)
template.metadata.labels:
  app: backend
  tier: api

# 單個Service負載均衡到所有匹配的Pod
# Service
selector:
  app: backend
  tier: api
# 流量會同時分發到兩個Deployment創建的Pod

模式3:流量分片

# 金絲雀部署場景
# 穩定版Deployment
template.metadata.labels:
  app: shopping-cart
  track: stable

# 金絲雀Deployment
template.metadata.labels:
  app: shopping-cart
  track: canary

# Service A(穩定流量)
selector:
  app: shopping-cart
  track: stable

# Service B(測試流量)
selector:
  app: shopping-cart
  track: canary

重要特性

1. 動態發現

# 當新Pod啓動並匹配Service的selector時
# Service會自動將其添加到端點列表
kubectl get endpoints hello-service

# 輸出示例:
# NAME             ENDPOINTS                                  AGE
# hello-service    10.244.1.5:80,10.244.2.3:80,10.244.2.4:80   10m
#                                     ↑
#                Service自動發現的所有匹配Pod的IP

2. 標籤變化的影響

# 如果Pod的標籤變化,不再匹配Service的selector
# Service會自動將其從端點列表中移除
原始Pod標籤: app=frontend, version=v1
Service selector: app=frontend, version=v1

# 如果Pod標籤變為: app=frontend, version=v2
# Pod將不再接收來自該Service的流量

3. 無selector的Service

# Service也可以沒有selector,手動指定端點
apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  ports:
  - port: 80
# 沒有selector,需要手動創建Endpoints對象

驗證方法

# 1. 查看Pod標籤
kubectl get pods --show-labels

# 2. 查看Service的selector
kubectl describe service hello-service | grep Selector

# 3. 查看Service關聯的端點
kubectl get endpoints hello-service

# 4. 測試連接
kubectl run test-$RANDOM --rm -i --image=busybox --restart=Never -- \
  wget -qO- hello-service

常見誤區澄清

  1. ❌ Service選擇Deployment

    • ✅ Service只選擇Pod,與Deployment無關
  2. ❌ 修改Deployment會影響Service

    • ✅ 只有Pod的標籤變化才會影響Service
  3. ❌ Service和Deployment必須同名

    • ✅ 它們可以任意命名,只需標籤匹配
  4. ❌ 一個Service只能關聯一個Deployment

    • ✅ 一個Service可以關聯多個Deployment創建的Pod

總結

  • Service selector → Pod標籤:Service直接選擇Pod,不關心Pod由誰創建
  • 標籤匹配機制:Service的selector必須完全匹配Pod的標籤(所有key-value都對上)
  • 動態更新:Pod標籤變化時,Service的端點列表自動更新
  • 多對多關係:多個Service可以選擇同一組Pod,一個Pod可以被多個Service選擇

記住這個簡單規則:Service通過標籤找Pod,不關心Deployment的存在。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.