本文以Java應用為例為您介紹如何通過云效flow流水線配置實現應用快速構建、持續部署與交付。
背景信息
云原生浪潮中,如何基于云原生架構快速實現K8s應用部署交付越發的優勢。相較于傳統部署方式,Kubernetes可以快速便捷的針對場景對服務進行擴縮容版本迭代,通過自動化一鍵打包做到應用容器化部署,跨環境輕松地保證其一致性;面對基礎設施的挑戰,服務Pod憑借智能自愈,自動創建遷移,無需人工干預等場景;并且以容器為單位對應用資源進行精細調控,極大的提高了資源利用率。
解決方案
使用阿里云云效Flow流水線和K8s資源的結合,為應用的持續交付提供了很好的基礎保障,大致可分為3步,如下:
開發者提交代碼變更:開發者將代碼變更提交到代碼倉庫,例如,使用
git push
命令將代碼推送到遠程倉庫。代碼庫變更監測:云效通過Webhook監聽代碼倉庫的變更事件,一旦檢測到代碼提交,自動觸發持續部署流水線。
持續部署流水線:代碼檢查,執行靜態代碼分析,確保代碼質量;
使用Dockerfile構建應用鏡像,將構建好的Docker鏡像推送到鏡像倉庫(如阿里云容器鏡像倉庫);
使用自動化流水線部署應用到測試環境;
執行自動化測試用例,確保應用功能正常;
使用自動化流水線部署發布應用到生產環境。
前提條件
注冊阿里云賬號或RAM賬號。
準備阿里云ACK集群,創建方式請參考創建ACK托管集群。
準備一個已備案的域名,通過域名路由Ingress訪問后端服務。
容器服務ACK集群安裝Nginx Ingress Controller組件。
準備阿里云鏡像倉庫ACR。為了能夠快速的拉取鏡像,建議將ACK集群與ACR放在同一地域,如本例中的華東1(杭州),這樣后續在進行Kubernetes部署的時候,我們可以選擇鏡像VPC地址。若不在同一地域,請選擇鏡像公網地址。創建方式請參考創建個人版實例。
場景案例
本文通過一個Springboot項目來實踐,如何通過云效快速實現K8s相關部署發布。
案例代碼庫地址:https://atomgit.com/flow-example/spring-boot.git。
代碼庫主要目錄結構如下所示:
spring-boot
|---app-configs
|---manifest-app
|---app.YAML
|---ingress.YAML
|---service.YAML
|---Dockerfile2
其中包含了一個deployment,一個service,以及一個ingress將這個服務暴露到公網上。Dockerfile2是我們在本例中構建鏡像會用到的Dockerfile。
調用關系如下:
操作步驟
步驟一:創建流水線
進入云效工作臺,在云效產品選擇流水線。
在流水線Flow頁面新建流水線,通過流水線模板,單擊
為例,完成創建。
步驟二:添加流水線源
創建流水線之后,
,此處以Java代碼類型為例,完成添加,其它參數默認會自動填寫到表單中。步驟三:配置鏡像構建任務
單擊Java構建Docker鏡像并推送鏡像倉庫設置相關參數,如下圖所示。
參數
描述
添加服務連接
服務連接即憑證,用于連接RAM用戶與容器鏡像服務(ACR)之間的授權。
地域
指創建的容器鏡像服務(ACR)所在的開服地域。
倉庫
創建鏡像倉庫,用于存儲流水線構建鏡像制品的上傳與拉取倉庫地址。
標簽
${DATETIME},表示以流水線觸發時的時間戳為例作為鏡像的標簽,很多企業習慣將分支名或者tag作為鏡像的標簽,云效也是支持的,詳情參考環境變量。
Dockerfile路徑指案例的代碼倉庫路徑,即文件名稱Dockerfile2 ,如下圖所示。
任務輸出是添加構建鏡像階段自動生成的,變量可以在后續的任務中引用。
說明關注其中的第二個和第三個變量即可,其中第二個是該鏡像地址的公網地址,第三個是該鏡像地址的VPC地址。這里推薦將鏡像倉庫和ACK集群放在同一個地域,然后在后續的部署任務中選擇VPC地址,以加速部署過程。
步驟四:配置部署任務
Kubernetes發布配置,在集群連接右側單擊新建連接,創建阿里云Kubernetes集群服務與RAM用戶的服務連接。創建保存之后,選擇對應的服務連接信息。
說明不同企業資源互通:云效支持不同企業資源在同一賬號下進行使用,具體參考鏈接授權管理—添加多個阿里云賬號的授權服務。
配置YAML路徑:示例中YAML路徑為:app-configs/manifest-app。
添加變量,本案例配置的自定義參數變量如下。
變量
描述
IMAGE
指變量的鏡像地址IMAGE,選擇“鏡像構建并推送至阿里云鏡像倉庫個人版.鏡像公網地址” 或 “鏡像構建并推送至阿里云鏡像倉庫個人版.鏡像VPC地址”作為變量值。
HOST
指路由Ingress規則中定義的
host
映射的域名,通過域名鏈路到路由訪問不同的后端服務。Ingress 定義host
可以簡化配置,具體操作,請參見創建Nginx Ingress。添加變量 IMAGE,如下圖所示。案例代碼庫中的app.yaml文件內容如下,在運行時Flow路徑下YAML文件中 ${IMAGE} 變量以及引用的參數變量會被渲染成真實的鏡像地址,通過拉取倉庫鏡像完成kubectl發布。
apiVersion: apps/v1 kind: Deployment metadata: labels: run: spring-boot-sample name: spring-boot-sample spec: replicas: 2 selector: matchLabels: run: spring-boot-sample template: metadata: labels: run: spring-boot-sample spec: containers: - image: ${IMAGE} name: app ports: - containerPort: 8080
添加變量 HOST,進入目標集群
復制規則中的域名。添加自定義參數變量 HOST,如下圖所示。
參考案例代碼庫Ingress.yaml文件修改內容如下,其中的${HOST}變量會被渲染替換成真實的測試請求地址。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: spring-boot-ingress namespace: default spec: rules: - host: ${HOST} http: paths: - path: /foo pathType: ImplementationSpecific backend: service: name: spring-boot-sample port: number: 8080
步驟五:運行流水線
配置完畢,單擊保存并運行,運行流水線。
由于在manifest中包含了ingress配置,因此可以通過ack規則的ingress綁定的域名訪問服務,在瀏覽器中輸入地址 http://${HOST}進行驗證,也可以在Shell命令行中進行驗證。
curl http://${HOST}
#Greetings from Spring Boot!V4
步驟六:鏡像升級發布
新建云效倉庫:單擊代碼管理進入云效Codeup頁面,單擊導入代碼庫,將案例代碼導入到云效代碼庫。
單擊URL導入,在源代碼庫地址框中輸入案例代碼庫地址,單擊確定。
切換流水線源
進入流水線頁面,編輯步驟一:創建流水線,如下圖所示。
刪除之前的流水線源,如下圖所示。
然后單擊添加流水線源,將新建的Codeup代碼倉庫添加進來,選擇默認分支,單擊添加,如下圖所示。
YAML 發布
修改代碼:進入導入的代碼庫,修改 src/main/java/com/example/demo/ 文件夾下的HelloController.java 文件,做出如下圖修改。
運行流水線:單擊左上角我的流水線,找到目標流水線,單擊運行,如下圖所示。
訪問驗證:運行成功后,通過下面的方式進行訪問驗證。
$ curl http://${HOST} #Greetings from Spring Boot! V5
鏡像升級
應用場景:開發團隊只負責完成代碼開發,并通過流水線自動化完成應用鏡像構建,并使用該鏡像對集群中已有的應用進行升級。開發團隊只關心應用的工作負載實例資源。
修改代碼:進入導入的代碼庫,修改 src/main/java/com/example/demo/ 文件夾下的 HelloController.java 文件,做出如下圖修改。
編輯流水線
單擊左上角然后單擊流水線,進入流水線頁面,選擇之前創建的流水線,單擊編輯,在Kubernetes發布任務中,單擊刪除,如下圖所示。
然后單擊新的任務,選擇如下圖所示Kubernetes鏡像升級任務。
在Kubernetes鏡像升級任務中,選擇相應集群、命名空間、應用類型、應用名稱、容器名稱、鏡像地址,如下圖所示。
單擊保存并運行,運行成功后,通過下面的方式進行訪問驗證。
curl http://${HOST} #Greetings from Spring Boot!V6
分批發布
應用場景:前兩種策略主要是用的Kubernetes原生的發布策略RollingUpdate模式進行滾動升級,整個發布過程是不可逆的,假如認定當前發布出現了異常我們只能通過重新發布的方式來使應用回到可用狀態。
而在云效的分批發布中,我們以Service為最小發布單元,在發布開始階段我們將基于新版鏡像創建出應用的版本V2,并根據當前應用的副本總數以及分批數量,對新舊兩個版本的應用實例分別進行縮容和擴容,來控制實際進入到新版應用的流量比例,從而可以實現小規模的發布驗證,在對發布進行充分驗證后再逐步完全下線老版應用。同時批次之間支持暫停和手動恢復讓用戶可以靈活對發布過程進行控制。
修改代碼
進入導入的代碼庫,修改 src/main/java/com/example/demo/ 文件夾下的HelloController.java 文件,做出如下圖修改。
編輯流水線
單擊左上角流水線,進入流水線頁面,選擇之前創建的流水線,單擊編輯,在Kubernetes鏡像升級任務中,單擊刪除,如下圖所示。
然后單擊新的任務,選擇如下圖所示Kubernetes 分批發布任務。
在Kubernetes 分批發布任務中,選擇相應集群、命名空間、服務Service、關聯Workloads類型、分批策略、分批數、容器名稱、鏡像地址,如下圖所示。
單擊保存并運行,運行成功后,流水線會在第一批發布完成后暫停,等待發布第二批,如下圖所示。
進入阿里云容器服務控制臺,單擊目標集群,進入無狀態工作負載,如下圖所示,有兩個不同容器組,每個容器組的數量是1。
通過下面的方式進行訪問驗證,會發現V6與V7 交替出現。
curl http://${HOST} #Greetings from Spring Boot!V6 curl http://${HOST} #Greetings from Spring Boot!V7
此時用戶可以在V7上進行驗證,如果有問題,可以通過【回退發布】按鈕回退到V6版本,如果沒有問題可以單擊按鈕【繼續發布】,如下圖所示。
常見問題
如何解決集群版本不支持extensions/v1beta1問題?
問題描述:Kubectl發布部署,Kubernetes 集群版本不支持
extensions/v1beta1
,失敗提示:"no matches for kind "Ingress" in version "extensions/v1beta1"
解決方案:公共案例代碼庫ingress.yaml文件中配置的Kubernetes集群版本與當前使用的集群版本不匹配,具體解決方案請參考1.19及之后版本集群更新Ingress.yaml參數值
apiVersion: networking.k8s.io/v1
。鏡像倉庫拉取容器鏡像失敗如何處理?
問題描述:Kubectl發布,鏡像倉庫拉取容器鏡像失敗,事件日志如下:
Error:ImagePullBackOff,Failed to pull image "registry.cn-hangzhou.aliyuncs.com/xxxx/xxxxxx:tag": failed to pull and unpack image "registry.cn-hangzhou.aliyuncs.comxxxx/xxxxxx:tag": failed to resolve reference "registry.cn-hangzhou.aliyuncs.com/xxxx/xxxxxx:tag": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
解決方案:安裝免密組件,創建配置項,詳細請參考使用免密組件拉取容器鏡像。