在此文章中,我們將探索Kubernetes(K8s),結合DigitalOcean Kubernetes叢集與Buddy自動化運維繫統部署以達到以下列出的目標:
K8s可以將其描述為一個容器編排平臺,它可以在雲端或遠端機器上擴充套件和執行您的應用程式。為了更容易理解,您可以把它想象成一個容器管理器,它會自動處理您必須手動執行的操作。
以下是使用K8s的一些優勢:
即使沒有持續部署,K8s也能夠在幾乎沒有停機時間的情況下促進和管理各種規模的釋出。
K8s本身由幾個元件組成。但我們不會在本文中介紹所有內容,主要關注於容器,我們還將使用Docker。
K8s上的容器以稱為Pod的組合執行。Pod中的容器共用相同的網路、儲存和地址。這說明存取pod的地址實際上意味著存取pod中的容器之一:
雖然您確實不需要流水線來讓應用程式在雲服務上執行,但由於SDK,在更大範圍內,團隊會發現依賴本地機子部署效率非常低。
流水線可以被認為是將服務或應用程式從A點移動到B點的一種方式。在CI/CD方面,我們可以將其分為三種型別:
微服務模式引入了一種新的軟體實現方式。將此視為一種移動模式,涉及多個移動部件,所有部件都統一起來以呈現單個應用程式。
無論有沒有DevOps工作人員,您的團隊都不必擔心與運維相關的問題,比如弄清楚三個應用程式元件的交付。最重要的是保持對產品的聚焦。
過去,部署堆疊主要基於Shell指令碼構建。對於以前沒有堆疊經驗的團隊成員來說,這通常很複雜。現在,幾乎每個平臺都提供 YAML。作為一種宣告式和更透明的語言,YAML的學習曲線相當容易。然而,不幸的是,有些平臺仍然需要YAML上對shell的解決方案。
Buddy憑藉著其直觀的GUI和流水線宣告式YAML設定解決了這些問題。
安全性是任何流水線的關鍵組成部分。關鍵的安全問題之一是處理金鑰和敏感資訊。在大多數情況下,金鑰或敏感資訊在進行加密後作為環境變數新增到平臺上,然後在構建過程中進行轉譯和解密。在定義這些作業的過程中,很容易通過列印金鑰或對公共Docker映象進行版本控制來洩露這些細節資訊。同時還建議避免在第三方服務上使用不受限制的API金鑰。
Buddy如何處理安全問題
平臺關聯肯定是最大的挑戰之一。不同的團隊以不同的方式處理此問題:從開箱即用的特定於平臺YAML模組到指令碼連線。建議採用模組化方法代替指令碼化流水線,通常涉及幾個步驟:從獲取SDK到授權,再到實際部署。這通常會導致相當複雜、容易出錯且體積龐大的流水線。
Buddy提供與各大商家的各種整合,以及具有宣告性流水線操作模式豐富的buddy.yml
指令碼。
本文的K8s範例應用可以在這個GitHub Repo中下載原始碼!
首先建立一個名為hello的Buddy專案,並選擇Buddy自帶的Git託管作為程式碼儲存倉:
下載GitHub儲存倉中的原始碼並推播至剛剛建立的專案儲存倉:
然後在Buddy中新增DigitalOcean整合,以方便持續整合所要使用的DigitalOcean Kubernetes叢集:
在hello專案中建立一條流水線:
接下來,我們將在流水線上新增第一個操作,即Docker構建映象,為將所構建的映象推播至Docker Hub而做準備:
選擇儲存倉上的Dockerfile
檔案並提交完成新增Docker構建映象操作:
新增第二個操作:推播Docker映象
推播Docker映象的作用是可將上一個操作構建好的映象推播至目標Docker註冊中心,也就是Docker映象儲存倉,例如:Docker Hub、Amazon ECR、Google GCR以及私有的映象註冊中心等等不一。
如果您是第一次接觸Docker映象構建,推薦使用Docker Hub,目前只需要在Docker官方網站上免費註冊一個帳戶即可使用。
填寫好相關要推播的映象資訊完成新增推播Docker映象
此時,您應該看到如下圖有兩個操作新增於流水線之中:
點選以上藍色「執行」按鈕開始執行流水線:
執行完成之後,我們就可以在Docker Hub帳戶中看到已有相關映象資訊顯示:
在hello專案儲存倉中新增第一個Hello World YAML檔案hello-kubernetes-first.yaml
,同時在檔案中新增以下程式碼:
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes-first
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
selector:
app: hello-kubernetes-first
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes-first
spec:
replicas: 3
selector:
matchLabels:
app: hello-kubernetes-first
template:
metadata:
labels:
app: hello-kubernetes-first
spec:
containers:
- name: hello-kubernetes
image: paulbouwer/hello-kubernetes:1.10
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: 這是第一個Hello World部署!
此設定定義了部署(Deployment
)和服務(Service
)。 部署包含aulbouwer/hello-kubernetes:1.7
映象的三個副本(replicas
)和一個名為MESSAGE
的環境變數(您將在存取應用程式時看到此資訊)。這裡的服務(Service
)定義為在80
埠顯露(expose
)叢集內的部署(Deployment
)。
在流水線中新增K8s提交部署操作:
新增hello-kubernetes-first.yaml
檔案,這個檔案將在流水線執行時提交部署至K8s叢集中:
根據以上相同的新增步驟再新增一個hello-kubernetes-second.yaml
檔案作為第二個Hello World演示,並在檔案中新增以下程式碼:
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes-second
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
selector:
app: hello-kubernetes-second
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes-second
spec:
replicas: 3
selector:
matchLabels:
app: hello-kubernetes-second
template:
metadata:
labels:
app: hello-kubernetes-second
spec:
containers:
- name: hello-kubernetes
image: paulbouwer/hello-kubernetes:1.10
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: 這是第二個Hello World部署!
此時我們就可以在流水線中看到如下圖所示的流水線資訊:
如上圖在流水線上點選藍色「執行」按鈕,將會看到如下圖所示的構建Docker映象、推播Docker映象以及提交兩個Hello World YAML組態檔至K8s叢集的流水線執行資訊:
在命令列介面上執行以下命令:(建立DigitalOcean Kubernetes叢集時會提示您如何設定您的電腦與其連線)
kubectl get service
執行以上程式碼後會顯示以下資訊
hello-kubernetes-first和hello-kubernetes-second都已列出,說明已經建立成功Kubernetes。
您已經使用Buddy自動化運維建立了hello-kubernetes應用程式的兩個部署。每個在部署規範中都有不同的資訊顯示,以便在測試期間區分。 下一步,我們將安裝Nginx Ingress Controller:
我們將使用Helm安裝Nginx Ingress 控制器
Nginx Ingress控制器 由一個Pod和一個Service組成。Pod執行控制器,控制器不斷輪詢叢集API伺服器上的/ingresses
端點以獲取可用Ingress資源的更新。該服務的型別為LoadBalancer
。因為您將其部署到DigitalOcean Kubernetes叢集,叢集將自動建立一個DigitalOcean負載均衡器,所有外部流量將通過該負載均衡器流向控制器。然後控制器會將流量路由到適當的服務,如Ingress資源中定義的那樣。
只有LoadBalancer
服務知道自動建立的負載均衡IP地址。某些應用程式(例如:ExternalDNS)需要知道其IP地址,但只能讀取Ingress的設定。通過在helm install
安裝期間將controller.publishService.enabled
引數設定為true
,可以將控制器設定為在每個Ingress上釋出IP地址。建議啟用此設定以支援可能依賴於負載均衡器IP地址的應用程式。
要安裝 K8s Nginx Ingress 控制器,我們首先需要通過執行以下命令將其儲存庫新增到Helm:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
更新系統,讓Helm知道所包含的內容:
helm repo update
最後,執行以下命令安裝Nginx Ingress:
helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.publishService.enabled=true
此命令從穩定chart儲存倉安裝Nginx Ingress,將Helm版本命名為nginx-ingress
,並將publishService
引數設定為true
。
執行後,您將看到類似以下的輸出:
Helm已將其在Kubernetes中建立的資源記錄為chart安裝的一部分。
執行此命令以檢視負載均衡器是否可用:
kubectl --namespace default get services -o wide -w nginx-ingress-ingress-nginx-controller
該命令在預設名稱空間中獲取Nginx Ingress服務並輸出其資訊,但該命令不會立即退出。使用-w
引數,它會在發生更改時監測並重新整理輸出資訊。
我們已經安裝了由Kubernetes社群維護的Nginx Ingress。它將HTTP和HTTPS流量從負載均衡器路由到Ingress資源中適配後端服務。 下一步,我們將顯露(expose)公開hello-kubernetes
應用程式部署。
在公開應用程式之前,我們需要準備兩個域名並指向負載均衡器IP,我們將使用以下兩個域名作為演示:
首先,通過以上已在Buddy建立的hello專案儲存倉中再建立一個名為hello-kubernetes-ingress.yaml的檔案,並新增以下程式碼部署兩個範例域名以便在瀏覽器中測試:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: "1.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-first
port:
number: 80
- host: "2.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-second
port:
number: 80
我們使用名稱hello-kubernetes-ingress定義Ingress資源。然後指定兩個主機規則,以便將1.m2jd.com域名轉向路由到hello-kubernetes-first服務,並將2.m2jd.com域名轉向路由到第二個部署hello-kubernetes-second的服務。
接下來,新增hello-kubernetes-ingress.yaml檔案到流水線操作提交Kubernetes部署之中並執行流水線。我們就可看到如下圖的hello-kubernetes-ingress部署到K8s叢集的Buddy流水線執行記錄:
現在我們可以在瀏覽器中開啟域名1.m2jd.com即可看到如下顯示:
在瀏覽器中開啟域名2.m2jd.com即可看到如下顯示:
為了保護Ingress資源,我們將安裝Cert-Manager,為生產運營建立ClusterIssuer
,並修改Ingress的設定以使用TLS證書。安裝和設定後,應用程式將在HTTPS之下執行。
ClusterIssuers
是Kubernetes中的Cert-Manager資源,它為整個叢集提供TLS證書。ClusterIssuer
是一種特定型別的發行者。
在通過Helm將Cert-Manager安裝到您的叢集之前,您將為它建立一個名稱空間:
kubectl create namespace cert-manager
這時,您需要將Jetstack Helm儲存倉新增到託管Cert-Manager圖譜(chart)的Helm。 為此,執行以下命令:
helm repo add jetstack https://charts.jetstack.io
Helm將顯示以下輸出資訊:
更新Helm圖譜快取:
helm repo update
更新命令執行將顯示以下輸出資訊:
最後,通過執行以下命令將Cert-Manager安裝到cert-manager名稱空間中:
helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.10.1 --set installCRDs=true
在此命令中,我們也將installCRDs
引數設定為true
,以便在Helm安裝期間安裝cert-managerCustomResourceDefinition
設定清單。在寫本文時,v1.10.1是最新版本。您可以參考ArtifactHub查詢最新版本號。
除了在命令列介面上執行Helm命令,您也可以在Buddy流水線上新增Helm CLI操作並執行流水線:
輸出資訊將顯示如下:
我們現在建立一個由Let's Encrypt頒發的證書,並將其設定儲存在名為production_issuer.yaml
的檔案中。在hello專案儲存倉中建立並開啟此檔案並新增以下程式碼:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# Email address used for ACME registration
email: 請在此輸入您的電子郵件地址
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Name of a secret used to store the ACME account private key
name: letsencrypt-prod-private-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: nginx
接下來,同樣在流水線中新增production_issuer.yaml檔案到流水線操作提交Kubernetes部署之中並執行流水線:
在hello-kubernetes-ingress.yaml檔案中新增第7行與9-13行的程式碼:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- 1.m2jd.com
- 2.m2jd.com
secretName: hello-kubernetes-tls
rules:
- host: "1.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-first
port:
number: 80
- host: "2.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-second
port:
number: 80
提交檔案後Buddy將自動為您執行流水線,此時您的域名已支援SSL證書,恭喜!
在實際操作中,請將域名換成您自己的域名,而不是照搬1.m2jd.com與2.m2jd.com,那樣將不會正常執行!
Kubernetes是一個基於容器的平臺,用於部署、擴充套件和執行應用程式。Buddy讓您可以通過一系列專用的K8s操作來自動化您的Kubernetes交付工作流。
每次更改應用程式程式碼或Kubernetes設定時,您都有兩個選項來更新叢集:kubectl apply
或 kubectl set image
。
在這種情況下,您的工作流程通常如下所示:
kubectl apply
或 kubectl set image
如果您經常使用 kubectl apply
或 kubectl set image
,這個就是更好的解決方案!
如果你經常在容器中執行任務,比如:
您可以使用pods或任務,第一種型別使用任務啟動單個pod;第二個啟動系列pod,直到指定數量的pod以成功狀態結束。
假設您在K8s叢集上有一個應用程式,儲存倉包含如下內容:
在這種情況下,您可以設定一個流水線:
A. 構建應用程式並遷移映象(第一個操作)
B. 推播至Docker Hub(第二個操作)
C. 觸發資料庫遷移 使用先前構建的映象(第三個操作)。您可以使用YAML檔案定義映象、命令和部署:
進行推播後,流水線將自動構建並將映象推播到儲存倉並執行遷移指令碼,是不是很酷?
作業操作將等到命令執行完畢,如果退出狀態不同於0,則操作將被標記為「失敗」。
D. 最後一個操作是使用提交Kubernetes部署或Kubernetes設定映象來更新K8s應用程式中的映象。新增操作後,整個流水線將如下所示:
一切就緒後,再次推播,即可看到Buddy自動執行整個工作流程。
希望您有所收穫,非常感謝您花時間閱讀本文!