在 Kubernetes 叢集中,為多位開發者建立分享環境需要謹慎規劃與管理。本文將探討如何利用名稱空間、資源配額和 RBAC 等機制,開發安全且高效的多開發者協作環境。同時,我們也會探討證書管理、監控和日誌管理等重要議題,並提供實用的指令碼和程式碼範例,協助開發者快速上手。此外,文章也將探討如何整合 CI/CD 流程,進一步提升開發效率,讓團隊能更專注於應用程式的開發與迭代。
在 Kubernetes 叢集中設定多開發者的分享環境
在開發者工作空間中,Kubernetes 叢集的設定和管理是至關重要的。本章節將介紹如何為多位開發者設定分享的 Kubernetes 叢集,並確保其安全性。
開發者上線流程
在將使用者分配到特定的名稱空間之前,首先需要將該使用者上線到 Kubernetes 叢集。有兩種方法可以實作這一點:使用根據證書的身份驗證,或組態叢集使用外部身份系統。
使用外部身份系統
使用外部身份系統(如 Microsoft Entra ID 或 AWS Identity and Access Management)是一種最佳實踐,因為它避免了維護兩個不同的身份來源。此外,大多數外部系統使用短期令牌,而不是長期證書,因此令牌的意外洩露所造成的影響是有限的。
使用證書身份驗證
如果無法使用外部身份系統,則需要使用證書。幸運的是,Kubernetes 提供了一個證書 API 用於建立和管理證書。
證書籤發流程
首先,需要生成一個證書籤名請求(Certificate Signing Request, CSR)。以下是一個簡單的 Go 程式,用於生成 CSR:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"os"
)
func main() {
name := os.Args[1]
user := os.Args[2]
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
// ...
}
證書籤發程式碼解說
此 Go 程式首先生成一個 RSA 私鑰,然後建立一個證書籤名請求。程式碼中關鍵的部分包括:
- 使用
rsa.GenerateKey生成私鑰。 - 使用
x509.MarshalPKCS1PrivateKey將私鑰編碼為 PKCS#1 格式。 - 使用
pem.Encode將私鑰儲存到檔案中。 - 建立一個
x509.CertificateRequest物件,並使用x509.CreateCertificateRequest生成 CSR。
內容解密:
- 私鑰生成:使用
rsa.GenerateKey函式生成一個 1024 位的 RSA 私鑰。 - CSR 生成:使用
x509.CreateCertificateRequest函式根據提供的資訊生成 CSR。 - PEM 編碼:使用
pem.Encode將私鑰和 CSR 儲存到檔案中,方便後續使用。
使用指令碼簽發證書
生成 CSR 後,可以使用以下指令碼建立並下載證書:
#!/bin/bash
csr_name="my-client-csr"
name="${1:-my-user}"
csr="${2}"
cat <<EOF | kubectl create -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: ${csr_name}
spec:
groups:
- system:authenticated
request: $(cat ${csr} | base64 | tr -d '\n')
usages:
- key encipherment
- client auth
EOF
# ...
指令碼解說
此指令碼建立一個 CertificateSigningRequest 物件,並使用 kubectl certificate approve 批准該請求。然後,它下載生成的證書,並輸出新增到 kubeconfig 檔案中的資訊。
證書籤發流程
圖表翻譯: 此圖展示了證書籤發的流程,從生成私鑰開始,到下載證書結束。
建立和保護名稱空間
建立名稱空間後,需要為其新增後設資料,如團隊聯絡資訊。通常,這些資訊以註解的形式新增。
ns='my-namespace'
team='some team'
kubectl create namespace ${ns}
kubectl annotate namespace ${ns} team=${team}
然後,透過建立 RoleBinding 物件,將角色繫結到使用者,從而授予對名稱空間的存取許可權。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: example
namespace: my-namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: edit
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: myuser
資源配額與名稱空間管理
在 Kubernetes 叢集中,為了控制成本或確保資源在開發者之間公平分配,可以使用 ResourceQuota 資源來限制特定名稱空間的資源使用總量。例如,以下配額限制了名稱空間 my-namespace 中的 Pod 資源總量:
apiVersion: v1
kind: ResourceQuota
metadata:
name: limit-compute
namespace: my-namespace
spec:
hard:
requests.cpu: "10"
requests.memory: 100Gi
limits.cpu: 10
limits.memory: 100Gi
內容解密:
ResourceQuota用於限制名稱空間中的資源使用量。requests.cpu和requests.memory分別限制了 Pod 請求的 CPU 和記憶體總量。limits.cpu和limits.memory分別限制了 Pod 使用的 CPU 和記憶體上限。- 這種組態確保了名稱空間不會過度消耗叢集資源。
管理名稱空間
為開發者分配名稱空間有兩種主要方法:
- 持久名稱空間:為每個開發者分配一個獨立的名稱空間,方便他們進行開發和管理應用程式。
- 臨時名稱空間:建立具有有限生命週期(TTL)的名稱空間,鼓勵開發者將資源視為臨時性,並簡化資源回收。
臨時名稱空間的優勢
- 自動化資源回收:當 TTL 到期時,名稱空間可以自動被刪除。
- 簡化資源管理:透過後設資料追蹤資源使用情況和所屬開發者。
工具開發與整合
為了實作動態分配名稱空間,可以開發簡單的工具或指令碼。例如:
- 使用指令碼建立名稱空間並附加後設資料(如 TTL、開發者資訊等)。
- 利用 Kubernetes 的自定義資源定義(CRDs)實作透過
kubectl動態建立和管理名稱空間。
資源回收
開發工具定期檢查名稱空間的 TTL,當 TTL 到期時自動刪除過期的名稱空間。可以將此邏輯封裝成容器,並使用 ScheduledJob 定期執行。
叢集層級服務
除了名稱空間管理工具,還可以啟用以下叢集層級服務:
- 日誌聚合:將容器日誌集中到日誌服務(如 Elasticsearch),方便開發者搜尋和分析。
啟用開發工作流程
成功建立分享叢集後,需要簡化開發者的入門流程。除了快速認證和分配名稱空間外,還需提供應用程式開發的支援,以縮短從入門到上線的時間。
圖表翻譯: 此圖示展示了開發者從入門到應用程式上線的流程,包括認證、名稱空間分配、應用程式開發和日誌聚合等步驟。
啟用開發者工作流程
在現代微服務架構中,將應用程式佈署至 Kubernetes 叢集通常需要大量的設定與協調工作,而非簡單的自動化流程。以下將介紹一種實用的方法來達成此目標,雖然這不是唯一的方法,但可以作為參考或啟發,幫助開發者建立自己的解決方案。
初始設定
佈署應用程式的主要挑戰之一是安裝所有依賴項。在許多情況下,尤其是在現代微服務架構中,開發單一微服務需要佈署多個依賴項,例如資料函式庫或其他微服務。雖然佈署應用程式本身相對簡單,但識別和佈署所有依賴項以構建完整的應用程式往往是一個令人沮喪的試錯過程,並且常常伴隨著不完整或過時的說明。
為瞭解決這個問題,引入一個描述和安裝依賴項的慣例是非常有價值的。這類別似於 npm install 命令,它安裝所有所需的 JavaScript 依賴項。最終,未來可能會出現類別似於 npm 的工具,為根據 Kubernetes 的應用程式提供此服務,但在那之前,最佳實踐是依靠團隊內部的慣例。
其中一個選項是在所有專案儲存函式庫的根目錄中建立一個 setup.sh 指令碼。該指令碼負責在特定的名稱空間中建立所有依賴項,以確保應用程式的所有依賴項都正確建立。例如,一個 setup 指令碼可能如下所示:
kubectl create -f my-service/database-stateful-set.yaml
kubectl create -f my-service/middle-tier.yaml
kubectl create -f my-service/configs.yaml
內容解密:
此指令碼使用 kubectl create 命令根據 YAML 檔案建立所需的 Kubernetes 資源。這些 YAML 檔案定義了資料函式庫 StatefulSet、中間層服務和其他組態資源。透過執行此指令碼,開發者可以快速建立所需的依賴項。
你可以將此指令碼與 npm 整合,在 package.json 中新增以下內容:
{
"scripts": {
"setup": "./setup.sh"
}
}
內容解密:
此 JSON 組態將 setup.sh 指令碼整合到 npm 的指令碼命令中,使得開發者可以執行 npm run setup 來安裝叢集依賴項。這種方法使得依賴項的安裝變得簡單且一致。
透過這種設定,新的開發者只需執行 npm run setup,即可安裝叢集依賴項。顯然,這種整合是針對 Node.js/npm 的,在其他程式語言中,可以與語言特定的工具鏈整合。例如,在 Java 中,可以將其與 Maven 的 pom.xml 檔案整合。
啟用活躍開發
在設定好開發者工作空間並安裝所需的依賴項後,下一步是使開發者能夠快速迭代他們的應用程式。首先需要具備建立和推播容器映像的能力。假設你已經設定好了這一步,如果沒有,可以參考其他線上資源和書籍瞭解如何進行。
在建立並推播容器映像後,接下來的任務是將其佈署到叢集中。與傳統的佈署不同,在開發者迭代的情況下,保持可用性並不是主要關注點。因此,最簡單的佈署新程式碼的方法是刪除與前一次佈署相關聯的 Deployment 物件,然後建立一個指向新建立映像的新 Deployment 物件。雖然也可以直接更新現有的 Deployment 物件,但這會觸發 Deployment 資源中的滾動更新邏輯。
kubectl delete -f ./my-service/deployment.yaml
perl -pi -e 's/${old_version}/${new_version}/' ./my-service/deployment.yaml
kubectl create -f ./my-service/deployment.yaml
內容解密:
此指令碼首先刪除現有的 Deployment 物件,然後使用 Perl 命令替換 deployment.yaml 檔案中的舊版本號為新版本號,最後建立新的 Deployment 物件。這種方法確保了每次佈署的都是全新的版本,避免了因滾動更新帶來的風險。
如同安裝依賴項一樣,建立一個指令碼來執行此佈署也是一種良好的實踐。可以將其與現有的程式語言工具鏈整合,使得開發者可以簡單地執行 npm run deploy 將新程式碼佈署到叢集中。
隨著自動化的建立,將其整合到持續整合和交付(CI/CD)工具(如 GitHub Actions、Azure DevOps 或 Jenkins)中是非常有用的。與 CI/CD 工具的整合使得進一步的自動化(如在開發者的 PR 被合併時自動佈署)變得更加容易。
提升開發效率:測試與偵錯的最佳實踐
在 Kubernetes 環境中開發應用程式時,測試和偵錯是至關重要的步驟。為了幫助開發者更順暢地完成這些任務,許多工具和技術被開發出來。本文將介紹如何在 Kubernetes 中設定開發環境的最佳實踐,以及如何利用現有的工具來簡化測試和偵錯流程。
測試與偵錯的挑戰
在 Kubernetes 環境中進行測試和偵錯面臨著多項挑戰。首先,Kubernetes 的架構和操作模式對於新手來說可能較為複雜,需要一定的學習曲線。其次,傳統的測試和偵錯工具可能無法直接適用於 Kubernetes 環境。因此,開發者需要熟悉新的工具和技術來克服這些挑戰。
利用 kubectl 進行測試與偵錯
kubectl 是 Kubernetes 的命令列工具,提供了豐富的功能來管理和除錯叢集中的資源。開發者可以利用 kubectl logs、kubectl exec 和 kubectl port-forward 等命令來檢查應用程式的日誌、執行命令以及建立本地與叢集之間的網路連線。
程式碼範例:使用 kubectl port-forward
kubectl port-forward pod/mypod 8080:80 &
curl http://localhost:8080
內容解密:
kubectl port-forward pod/mypod 8080:80將本地的 8080 連線埠轉發到 Podmypod的 80 連線埠。&將該命令放入背景執行。curl http://localhost:8080用於測試轉發是否成功。
將 Kubernetes 整合到開發環境
為了簡化測試和偵錯流程,許多開發環境(如 Visual Studio Code)提供了對 Kubernetes 的整合支援。以 VS Code 為例,其 Kubernetes 擴充套件可以自動發現 kubeconfig 檔案中的叢集,並提供樹狀檢視來導航叢集內容。開發者可以直接從樹狀檢視中右鍵點選 Pod 來使用連線埠轉發、日誌檢視或終端存取等功能。
建立開發環境的最佳實踐
分階段思考開發者體驗:將開發流程分為上線、開發和測試三個階段,並確保開發環境能夠支援這三個階段。
選擇適合的叢集架構:決定是使用單一大叢集還是每個開發者擁有獨立的叢集。單一大叢集通常是較好的選擇。
安全管理:為每個使用者分配獨立的身分和名稱空間,並使用資源限制來控制他們對叢集資源的存取。
資源清理:自動清理未使用的資源,以避免資源浪費。
叢集層級服務:設定叢集層級的服務,如日誌收集和監控,以支援所有使用者的需求。
Kubernetes 中的監控與日誌記錄
在 Kubernetes 環境中,監控和日誌記錄是確保應用程式健康執行的關鍵。本章將介紹監控和日誌記錄的最佳實踐,包括不同的監控模式、重要指標的收集以及如何建立儀錶板。
指標與日誌的區別
指標(Metrics)和日誌(Logs)是兩種不同的資料收集方式:
- 指標:一系列隨時間變化的數值,用於衡量系統的效能和健康狀態。
- 日誌:記錄程式執行過程中的事件,包括錯誤、警告和其他重要資訊。
指標與日誌的比較
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Kubernetes 多開發者分享叢集設定
package "Kubernetes Cluster" {
package "Control Plane" {
component [API Server] as api
component [Controller Manager] as cm
component [Scheduler] as sched
database [etcd] as etcd
}
package "Worker Nodes" {
component [Kubelet] as kubelet
component [Kube-proxy] as proxy
package "Pods" {
component [Container 1] as c1
component [Container 2] as c2
}
}
}
api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2
note right of api
核心 API 入口
所有操作經由此處
end note
@enduml
圖表翻譯: 此圖示展示了資料收集的兩種主要形式:指標和日誌。指標用於效能監控,而日誌則有助於問題排查。
監控技術
封閉盒監控(Closed-box monitoring)關注於從外部監控應用程式的表現,傳統上用於監控 CPU、記憶體、儲存等基礎設施層面的指標。雖然這種方法仍然有其價值,但它缺乏對應用程式內部運作的深入洞察。
Kubernetes 監控與日誌管理:監控模式與指標概述
在 Kubernetes 環境中,監控系統的健康狀態和應用程式的效能是至關重要的。傳統的監控方法可能無法滿足 Kubernetes 動態和短暫的特性,因此需要採用新的監控策略和工具。
黑箱與白箱監控
監控可以分為黑箱(Black-box)和白箱(White-box)兩種方法。黑箱監控關注系統的外部表現,例如檢查叢集是否健康。白箱監控則深入系統內部,關注應用程式的狀態,例如 HTTP 請求總數、500 錯誤數量和請求延遲等。
監控模式
在監控分散式系統時,有兩種主要的監控模式:USE 方法和 RED 方法。
USE 方法
USE 方法由 Brendan Gregg 提出,關注以下三個方面:
- U - Utilization(利用率)
- S - Saturation(飽和度)
- E - Errors(錯誤率)
USE 方法適用於基礎設施監控,可以快速識別資源限制和錯誤率。例如,監控叢集中節點的網路利用率、飽和度和錯誤率,可以幫助識別網路瓶頸或錯誤。
def check_network_health(node):
# 檢查網路利用率
utilization = get_network_utilization(node)
# 檢查網路飽和度
saturation = get_network_saturation(node)
# 檢查網路錯誤率
error_rate = get_network_error_rate(node)
return utilization, saturation, error_rate
#### 內容解密:
此函式用於檢查節點的網路健康狀態。它首先取得網路利用率、飽和度和錯誤率,然後傳回這些值。
- `get_network_utilization(node)`:取得指定節點的網路利用率。
- `get_network_saturation(node)`:取得指定節點的網路飽和度。
- `get_network_error_rate(node)`:取得指定節點的網路錯誤率。
此函式可用於 USE 方法中檢查網路的健康狀態。
RED 方法
RED 方法由 Tom Wilkie 提出,關注以下三個方面:
- R - Rate(請求率)
- E - Errors(錯誤率)
- D - Duration(請求延遲)
RED 方法適用於監控應用程式的使用者經驗。例如,監控前端服務的請求率、錯誤率和請求延遲,可以幫助瞭解使用者的體驗。
def check_service_health(service):
# 計算請求率
rate = get_request_rate(service)
# 計算錯誤率
error_rate = get_error_rate(service)
# 計算請求延遲
duration = get_request_duration(service)
return rate, error_rate, duration
#### 內容解密:
此函式用於檢查服務的健康狀態。它首先計算請求率、錯誤率和請求延遲,然後傳回這些值。
- `get_request_rate(service)`:計算指定服務的請求率。
- `get_error_rate(service)`:計算指定服務的錯誤率。
- `get_request_duration(service)`:計算指定服務的請求延遲。
此函式可用於 RED 方法中檢查服務的使用者經驗。
Kubernetes 指標概述
Kubernetes 提供了多種方式來暴露指標,包括:
- cAdvisor:收集容器的資源使用指標,例如 CPU 和記憶體使用率。
- Metrics Server:收集叢集中的資源使用指標,例如 CPU 和記憶體使用率,並提供給 Kubernetes 使用。
- kube-state-metrics:監控 Kubernetes 物件的狀態,例如 Pod 和 Deployment 的狀態。