Kubernetes 提供了完善的機制來管理應用程式的版本控制、釋出和佈署。透過 Deployment 物件,可以定義應用程式的佈署策略,例如滾動更新或重建,並精確控制更新過程中 Pod 的數量和可用性。配合語義化版本控制,可以清晰地標記應用程式的版本,方便管理和回復。對於更複雜的應用程式,Helm 作為 Kubernetes 的套件管理器,可以簡化應用程式的佈署和管理,並透過 Chart 的方式封裝應用程式的所有元件,實作更便捷的版本控制和釋出。在全球化佈署場景下,需要考慮影像登入檔的全球分佈、佈署引數化以及全球流量負載平衡等議題,才能確保應用程式在全球範圍內的可靠性和高效性。
版本控制、釋出與佈署
傳統的單體式應用程式常因過於龐大而難以升級、版本控制或修改,以滿足業務需求。為瞭解決這些問題,開發團隊開始採用敏捷開發實踐和微服務架構。容器技術的採用提高了系統的隔離性和可組合性,但仍需要高水準的人工自動化和系統管理。服務協調工具如Kubernetes和Docker Swarm簡化了應用程式的版本控制、釋出和佈署過程。
版本控制
在微服務架構中,語義版本控制(Semantic Versioning)被廣泛採用。語義版本控制使用三部分版本號:主版本、次版本和修補版本(例如1.2.3)。修補版本代表包含錯誤修復或非常小的變更,且不改變API。次版本代表包含新的API變更,但與前一版本保持向後相容。主版本代表破壞性的變更,通常與前一版本不相容。
版本控制範例
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 3
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
version: "1.2.3" # 使用語義版本控制標記版本
spec:
containers:
- name: example-container
image: example/image:1.2.3 # 映象版本與 Deployment 版本一致
內容解密:
apiVersion和kind定義了 Kubernetes 資源的型別和版本。metadata.name指定了 Deployment 的名稱。spec.replicas定義了所需的副本數量。spec.selector.matchLabels和spec.template.metadata.labels確保 Deployment 正確管理對應的 Pod。version標籤使用了語義版本控制,便於管理和識別不同版本的應用。
釋出
Kubernetes 本身沒有內建的釋出控制器,但可以透過 Deployment 的 metadata.labels 和 pod.spec.template.metadata.label 來實作釋出控制。Helm 是 Kubernetes 的包管理工具,它引入了釋出(Release)的概念,用於區分同一份 Helm Chart 在叢集中的不同執行例項。
釋出名稱的運用
釋出名稱(如 stable 或 canary)可以用於操作控制,特別是在結合服務網格(Service Mesh)進行精細路由決策時。大型的組織可能會採用環狀架構(Ring Architecture),使用 ring-0、ring-1 等名稱來進行分層釋出。
佈署與滾動更新
在 Kubernetes 中,Deployment 控制器用於管理應用的滾動更新。滾動更新策略允許逐步替換舊版本的 Pod,而不會中斷服務。Kubernetes 支援兩種更新策略:rollingUpdate 和 recreate。
滾動更新範例
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example-container
image: example/image:latest
內容解密:
spec.strategy.type設定為RollingUpdate以啟用滾動更新。rollingUpdate.maxUnavailable指定了在更新過程中允許的最大不可用 Pod 數量。rollingUpdate.maxSurge指定了在更新過程中允許的最大額外 Pod 數量。- 這樣的組態確保了在更新過程中,至少有兩個 Pod 處於可用狀態,並且總 Pod 數量不會超過預期數量的上限。
版本控制、釋出與滾動更新策略
在 Kubernetes 中,版本控制、釋出與滾動更新是確保應用程式平穩運作的關鍵要素。不同的工作負載需要不同的佈署策略,以確保服務的持續可用性。
重建(Recreate)策略
對於某些可以容忍完全中斷的工作負載,重建策略是一種有效的選擇。在此策略中,Deployment 控制器會建立一個新的 ReplicaSet,並在上線新 Pod 之前刪除舊的 ReplicaSet。這種策略適用於根據佇列的系統,因為在新 Pod 上線之前,訊息會在佇列中等待,待新 Pod 上線後再繼續處理。
滾動更新(RollingUpdate)策略
滾動更新是一種更常見的佈署策略,它允許在不中斷服務的情況下更新應用程式。在此策略中,Deployment 控制器會逐步替換舊的 Pod,同時保持服務的可用性。
綜合範例
以下是一個綜合範例,展示瞭如何在單一服務佈署中實作版本控制、釋出與滾動更新:
# Web 佈署
apiVersion: apps/v1
kind: Deployment
metadata:
name: gb-web-deploy
labels:
app: guest-book
appver: 1.6.9
environment: production
release: guest-book-stable
release number: 34e57f01
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 3
maxSurge: 2
selector:
matchLabels:
app: gb-web
ver: 1.5.8
matchExpressions:
- {key: environment, operator: In, values: [production]}
template:
metadata:
labels:
app: gb-web
ver: 1.5.8
environment: production
spec:
containers:
- name: gb-web-cont
image: evillgenius/gb-web:v1.5.5
env:
- name: GB_DB_HOST
value: gb-mysql
- name: GB_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
內容解密:
此範例展示了一個使用滾動更新策略的 Web 佈署。strategy 欄位指定了佈署策略,rollingUpdate 欄位則定義了滾動更新的引數,例如 maxUnavailable 和 maxSurge。這些引數控制著更新過程中 Pod 的可用性和數量。
# DB 佈署
apiVersion: apps/v1
kind: Deployment
metadata:
name: gb-mysql
labels:
app: guest-book
appver: 1.6.9
environment: production
release: guest-book-stable
release number: 34e57f01
spec:
selector:
matchLabels:
app: gb-db
tier: backend
strategy:
type: Recreate
template:
metadata:
labels:
app: gb-db
tier: backend
ver: 1.5.9
environment: production
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
內容解密:
此範例展示了一個使用重建策略的 DB 佈署。strategy 欄位指定了佈署策略,type 欄位則設為 Recreate,表示將使用重建策略更新 Pod。
最佳實踐
- 使用語義化版本控制:為應用程式使用語義化版本控制,與容器和 Pod 的版本控制區分開來。這允許容器和應用程式具有獨立的生命週期。
- 使用釋出和釋出版本標籤:在佈署後設資料中使用釋出和釋出版本標籤,以追蹤 CI/CD 管道的釋出。這允許對 CI/CD 過程進行追溯,並簡化了回復操作。
- 使用 Helm 管理服務:如果使用 Helm 封裝服務,請將需要一起回復或升級的服務捆綁在同一個 Helm Chart 中。Helm允許輕鬆回復應用程式的所有元件。
版本控制與釋出管理的重要性
- 版本控制與釋出管理對於確保應用程式的平穩運作至關重要。
- 正確的版本控制和釋出管理可以減少停機時間,提高應用的可靠性。
全球應用程式佈署與分級
到目前為止,本文已經介紹了許多不同的應用程式開發、構建和佈署實踐。然而,當佈署和管理具有全球足跡的應用程式時,會出現一系列全新的挑戰。
為何需要全球佈署
有多種原因會促使應用程式需要擴充套件到全球佈署。首先,最明顯的原因是規模。如果應用程式非常成功或至關重要,那麼就需要將其佈署在全球各地,以提供足夠的使用者容量。這類別應用程式的例子包括全球性的API閘道器、大規模的IoT產品、成功的社群網路等。
雖然很少有系統需要達到全球規模,但更多的應用程式需要全球足跡來降低延遲。即使用容器和Kubernetes,也無法避免光速的限制。為了最小化客戶端與應用程式之間的延遲,有時需要在全球各地分佈應用程式,以減少應用程式與使用者之間的實體距離。
另一個更常見的全球分佈原因是區域性要求。出於頻寬或資料隱私的原因(例如地理限制),有時需要在特定位置佈署應用程式,以使其可行或成功。隨著越來越多的國家和地區實施資料隱私和主權法律法規,越來越多的企業需要在特定位置佈署應用程式,以服務當地使用者。
映像檔分佈
在考慮在全球執行應用程式之前,需要確保映像檔可在全球各地的叢集中使用。首先要考慮的是映像檔登入是否具有自動的地理複製功能。許多雲端供應商提供的映像檔登入會自動將映像檔分佈到全球各地,並將映像檔請求解析到最接近叢集的儲存位置。
使用雲端提供的映像檔登入
如果使用支援地理複製的雲端提供的映像檔登入,分佈映像檔到全球各地就很簡單。只需將映像檔推播到登入中,選擇需要地理分佈的地區,登入就會處理剩下的事情。
自行解決映像檔分佈問題
如果不使用雲端登入,或供應商不支援自動的映像檔地理分佈,就需要自行解決這個問題。一個選擇是使用位於特定位置的登入。然而,這種方法存在幾個問題。映像檔提取延遲通常決定了啟動容器的速度,而這又決定了在機器故障時能夠多快還原。
另一個問題是單一登入可能成為單點故障。如果登入位於單一地區或單一資料中心,那麼該資料中心的大規模事故可能會導致登入離線。如果登入離線,CI/CD管道將停止運作,無法佈署新程式碼。這對開發人員生產力和應用程式運作都有重大影響。
自建映像檔複製服務
如果無法使用雲端提供的地理複製功能,需要自行建立映像檔複製服務。有兩種選擇:使用地理名稱或建立完整的映像檔複製服務。
使用地理名稱
使用地理名稱是一種簡單的方法,但可能無法滿足大規模應用程式的需求。
建立完整的映像檔複製服務
建立完整的映像檔複製服務需要更多的努力,但可以提供更好的效能和可靠性。這種方法需要設計和實作一個能夠將映像檔複製到多個地區的服務。
# 定義一個簡單的 Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 3
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example-container
image: example-image:latest
ports:
- containerPort: 80
內容解密:
此 YAML 檔案定義了一個 Kubernetes Deployment 物件,用於佈署一個名為 example-deployment 的應用程式。以下是每個部分的詳細說明:
apiVersion和kind:定義了 Kubernetes 物件的版本和型別。metadata:提供了 Deployment 的中繼資料,例如名稱。spec:定義了 Deployment 的規格,包括副本數量、選擇器和範本。replicas:指定了 Deployment 的副本數量。selector和template.metadata.labels:定義了 Deployment 的標籤選擇器,用於比對 Pod。template.spec:定義了 Pod 的規格,包括容器列表。containers:定義了容器列表,包括容器名稱、映像檔和連線埠。
這個 Deployment 物件將建立三個副本,並使用 example-image:latest 映像檔執行容器,將容器的 80 連線埠暴露出來。
全球化應用程式佈署與分階段發布
在現代的軟體開發中,將應用程式佈署到全球各地已成為常態。這不僅需要考慮如何高效地將應用程式佈署到不同的地區,還需要確保在不同地區的組態差異能夠得到妥善管理。
影像登入檔的全球分佈
要實作全球化佈署,首先需要考慮的是如何分佈影像登入檔(Image Registry)。有兩種主要的方法:
多登入檔方法:將影像推播到多個地理位置不同的登入檔中,例如
us.my-registry.io、eu.my-registry.io等。這種方法的優點是設定和管理相對簡單,每個登入檔都是獨立的,可以在 CI/CD 管道的末端將影像推播到所有登入檔中。然而,其缺點是每個叢集需要稍微不同的組態,以便從最近的地理位置提取影像。
@startuml skinparam backgroundColor #FEFEFE skinparam defaultTextAlignment center skinparam rectangleBackgroundColor #F5F5F5 skinparam rectangleBorderColor #333333 skinparam arrowColor #333333
title 影像登入檔的全球分佈
rectangle “Push Image” as node1 rectangle “Pull Image” as node2
node1 –> node2
@enduml
#### 內容解密:
- 此圖示展示了多登入檔方法的架構。
- CI/CD 管道將影像推播到不同地區的登入檔中。
- 各地區的叢集從最近的登入檔中提取影像。
2. **單一 DNS 端點方法**:雖然影像仍被推播到多個登入檔中,但它們分享一個 DNS 端點(例如 `my-registry.io`)。可以透過地理感知 DNS(GeoDNS)或多播 IP 地址來實作。這種方法實作起來較為複雜,但可以提供更靈活的流量管理。
### 佈署引數化
當影像被複製到全球各地後,需要對佈署進行引數化,以適應不同地區的組態差異。常見的做法是使用範本化的方法,將大部分組態保留在分享範本中,然後根據不同地區的引數生成地區特定的組態。Helm 是一個常用的工具,用於實作這種範本化管理。
#### 範例程式碼:使用 Helm 進行範本化佈署
```yaml
# values.yaml
replicaCount: 3
image:
repository: my-registry.io/myapp
tag: latest
# values-us.yaml
image:
repository: us.my-registry.io/myapp
# values-eu.yaml
image:
repository: eu.my-registry.io/myapp
內容解密:
values.yaml定義了預設的組態引數。values-us.yaml和values-eu.yaml分別定義了美國和歐洲地區的特定組態。- 透過 Helm,可以根據不同的
values檔案生成不同地區的佈署組態。
全球流量負載平衡
將應用程式佈署到全球各地後,需要確定如何將流量導向最近的應用程式例項。可以使用 DNS 負載平衡或多播 IP 地址來實作。這兩種方法都可以根據使用者的位置和服務的可用性,將流量導向最近且可用的服務例項。
全球軟體發布
在全球範圍內發布軟體時,不能簡單地一次性將軟體佈署到所有地區。這樣做可能會導致全球範圍內的服務中斷。相反,應該採用分階段發布的方法,結合全球負載平衡等技術,確保即使在軟體發布過程中出現問題,也能夠維持高用性。
總之,全球化應用程式佈署需要綜合考慮影像登入檔的分佈、佈署引數化、全球流量負載平衡和分階段軟體發布等多個方面,以確保應用程式能夠高效、可靠地服務於全球使用者。