共計 8079 個字符,預計需要花費 21 分鐘才能閱讀完成。
本篇文章給大家分享的是有關怎么在 Kubernetes 上大規模運行 CI/CD,丸趣 TV 小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著丸趣 TV 小編一起來看看吧。
在云原生領域中,Kubernetes 累積了大量用例。它能夠在云中部署應用容器、安排批處理 job、處理工作負載以及執行逐步升級。Kubernetes 使用高效的編排算法來處理這些操作,即便是大規模集群這些算法依舊表現良好。
此外,Kubernetes 主要用例之一是運行持續集成或持續交付(CI/CD)流水線。也就是說,我們部署一個 CI/CD 容器的唯一實例,該實例將監控代碼版本控制系統。所以,每當我們推送到該倉庫時,該容器都會運行流水線步驟。其最終目標是達到一個“true or false”的狀態。True 即在集成階段 commit 通過了各種測試,False 即未通過測試。
除了以上描述的 CI 流水線之外,在 CI 測試通過之后,另一個流水線可以接管余下的過程,以處理發布過程的 CD 部分。在這一階段,流水線將嘗試將應用程序容器交付到生產中。
需要明白的是,這些操作是按需運行或者是由各種行為(如代碼 check-in、測試觸發器、流程中上一步的結果等)自動觸發的。因此我們需要一種機制來增加單個節點以運行那些流水線的步驟,并在不需要它們時將其淘汰。這種管理不可變基礎架構的方法有助于我們節省資源并降低成本。
當然,最關鍵的機制就是 Kubernetes,它具有聲明式的結構和可定制性,因此可以讓你在任何場景下高效地調度 job、節點以及 pod。
適用于 Kubernetes 的 CI/CD 平臺
Kubernetes 是一個運行 CI/CD 的理想平臺,因為它擁有許多特性使得在上面運行 CI/CD 更為簡單。那么,到底有多少 CI/CD 的平臺可以在 Kubernetes 上運行呢?可以這么說,只要它們能夠被打包為一個容器,Kubernetes 都能夠運行它們。以下是幾個最為流行的 CI/CD 平臺:
Jenkins:Jenkins 是最為流行也最為穩定的 CI/CD 平臺。在世界范圍內有數以千計的企業都在使用它,因為它擁有強大的生態和可擴展性。如果你打算要在 Kubernetes 上使用它,非常建議你安裝它的官方插件。JenkinsX 是專門為云原生領域設計的 Jenkins 版本。它與 Kubernetes 更加兼容,并且提供了更好的集成功能,如 GitOps、自動 CI/CD 和預覽環境。
Spinnaker:Spinnaker 是一個可擴展的多云部署的 CD 平臺,得到了 Netflix 的支持。使用相關的 Helm Chart 即可安裝它。
https://github.com/helm/charts/tree/master/stable/spinnaker
Drone:這是有多種功能的通用云原生 CD 平臺。可以使用關聯的 Runner 在 Kubernetes 中運行它。
GoCD:Thoughtworks 的另一個 CI/CD 平臺,提供了適用于云原生部署的各種工作流程和功能。它可以在 Kubernetes 中作為 Helm Chart 運行。
此外,還有一些與 Kubernetes 緊密合作的云服務,并提供諸如 CircleCI 和 Travis 的 CI/CD 流水線。如果你不打算托管 CI/CD 平臺,那么這些也十分有用。
現在,我們來看看如何在 Kubernetes 集群上安裝 Jenkins。
如何在 Kubernetes 上安裝 Jenkins
首先,我們需要安裝 Helm,它是 Kubernetes 的軟件包管理器:
$ curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 get_helm.sh
$ chmod 700 get_helm.sh
$ ./get_helm.sh -v v2.15.0
同樣,我們還需要安裝 Tiller,以讓 Helm 正常運行:
$ kubectl -n kube-system create serviceaccount tiller
serviceaccount/tiller created
~/.kube
$ kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller
clusterrolebinding.rbac.authorization.k8s.io/tiller created
~/.kube
$ helm init --service-account tiller
$HELM_HOME has been configured at /Users/itspare/.helm.
完成這些步驟之后,我們需要運行檢查命令,以查看 deployment 的配置值:
$ helm inspect values stable/jenkins values.yml
仔細檢查配置值并在需要的時候進行更改。然后安裝 Chart:
$ helm install stable/jenkins --tls \
--name jenkins \
--namespace jenkins
安裝過程中會有一些關于下一步操作的說明:
注意:
運行以下命令獲取”admin“用戶的密碼:
printf $(kubectl get secret --namespace default my-jenkins -o jsonpath= {.data.jenkins-admin-password} | base64 --decode);echo
在相同的 shell 中獲取 Jenkins URL 以訪問這些命令:
export POD_NAME=$(kubectl get pods --namespace default -l app.kubernetes.io/component=jenkins-master -l app.kubernetes.io/instance=my-jenkins -o jsonpath= {.items[0].metadata.name} )
echo http://127.0.0.1:8080
kubectl --namespace default port-forward $POD_NAME 8080:8080
遵循這些步驟,它們將在 http://127.0.0.1:8080 啟動代理服務器。
到那里輸入你的用戶名和密碼。你將會擁有自己的 Jenkins 服務器:
不過,請記住,還有許多配置選項尚未修改,你可以訪問 chart 文檔以了解更多信息:
https://github.com/helm/charts/tree/master/stable/jenkins
在默認情況下,服務器會安裝好最基本的插件,如 Git 和 Kubernetes-Jenkins,我們可以根據自己的需要安裝其他插件。
總而言之,使用 Helm 安裝 Jenkins 十分輕松。
使用 K8S 擴展 CI/CD Jenkins 流水線
既然我們已經大致了解 CI/CD 如何在 Kubernetes 上運行的,那么我們來看一個在 Kubernetes 中部署高度可擴展的 Jenkins 部署的示例用例。人們通常用它(進行了少量修改)來處理基礎結構的 CI/CD,開始吧!
使用 Jenkins 固定發行版
雖然官方 Jenkins 鏡像很適合入門,但它需要的配置超出了我們的期望。許多用戶會選擇一個固定的發行版,如 my-bloody-jenkins(https://github.com/odavid/my-bloody-jenkins),它提供了一個較為完整的預安裝插件以及配置選項。在可用的插件中,我們使用 saml 插件、SonarQubeRunner、Maven 和 Gradle。
它能夠使用以下命令通過 Helm Chart 安裝:
$ helm repo add odavid https://odavid.github.io/k8s-helm-charts
$ helm install odavid/my-bloody-jenkins
我們選擇使用以下 Dockerfile 部署自定義鏡像:
FROM odavid/my-bloody-jenkins:2.190.2-161
USER jenkins
COPY plugins.txt /usr/share/jenkins/ref/
RUN /usr/local/bin/install-plugins.sh /usr/share/jenkins/ref/plugins.txt
USER root
其中 plugins.txt 文件是我們要預安裝到鏡像中的其他插件列表:
build-monitor-plugin
xcode-plugin
rich-text-publisher-plugin
jacoco
scoverage
dependency-check-jenkins-plugin
greenballs
shiningpanda
pyenv-pipeline
pipeline-aws
appcenter
multiple-scms
Testng-plugin
然后,只要 dockerfile 發生更改,我們就使用此通用 Jenkinsfile 來構建 master:
#!/usr/bin/env groovy
node(generic) {
try {
def dockerTag, jenkins_master
stage(Checkout) {
checkout([
$class: GitSCM ,
branches: scm.branches,
doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
extensions: [[$class: CloneOption , noTags: false, shallow: false, depth: 0, reference: ]],
userRemoteConfigs: scm.userRemoteConfigs,
def version = sh(returnStdout: true, script: git describe --tags `git rev-list --tags --max-count=1`).trim()
def tag = sh(returnStdout: true, script: git rev-parse --short HEAD).trim()
dockerTag = version + - + tag
println(Tag: + tag + Version: + version)
stage(Build Master) {jenkins_master = docker.build( jenkins-master , --network=host .)
stage(Push images) {docker.withRegistry( https://$env.DOCKER_REGISTRY , ecr:eu-west-2:jenkins-aws-credentials) {jenkins_master.push( ${dockerTag} )
if(env.BRANCH_NAME == master) {stage( Push Latest images) {docker.withRegistry( https://$env.DOCKER_REGISTRY , ecr:eu-west-2:jenkins-aws-credentials) {jenkins_master.push( latest)
stage(Deploy to K8s cluster) {
withKubeConfig([credentialsId: dev-tools-eks-jenkins-secret ,
serverUrl: env.TOOLS_EKS_URL]) {sh kubectl set image statefulset jenkins jenkins=$env.DOCKER_REGISTRY/jenkins-master:${dockerTag}
currentBuild.result = SUCCESS
} catch(e) {
currentBuild.result = FAILURE
throw e
}
我們所使用的專用集群由 AWS 中的一些大中型實例組成,用于 Jenkins jobs。接下來,我們進入下一個部分。
使用專用的 Jenkins Slaves 和標簽(label)
為了擴展我們的一些 Jenkins slaves,我們使用 Pod 模板并將標簽分配給特定的 agent。因此在我們的 Jenkinsfiles 中,我們可以為 jobs 引用它們。例如,我們有一些需要構建安卓應用程序的 agent。因此,我們引用以下標簽:
pipeline {agent { label android }
…
并且將使用特定于安卓的 pod 模板。我們使用這一 Dockerfile,例如:
FROM dkr.ecr.eu-west-2.amazonaws.com/jenkins-jnlp-slave:latest
RUN apt-get update apt-get install -y -f --no-install-recommends xmlstarlet
ARG GULP_VERSION=4.0.0
ARG CORDOVA_VERSION=8.0.0
# SDK version and build-tools version should be different
ENV SDK_VERSION 25.2.3
ENV BUILD_TOOLS_VERSION 26.0.2
ENV SDK_CHECKSUM 1b35bcb94e9a686dff6460c8bca903aa0281c6696001067f34ec00093145b560
ENV ANDROID_HOME /opt/android-sdk
ENV SDK_UPDATE tools,platform-tools,build-tools-25.0.2,android-25,android-24,android-23,android-22,android-21,sys-img-armeabi-v7a-android-26,sys-img-x86-android-23
ENV LD_LIBRARY_PATH ${ANDROID_HOME}/tools/lib64/qt:${ANDROID_HOME}/tools/lib/libQt5:$LD_LIBRARY_PATH/
ENV PATH ${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
RUN curl -SLO https://dl.google.com/android/repository/tools_r${SDK_VERSION}-linux.zip \
echo ${SDK_CHECKSUM} tools_r${SDK_VERSION}-linux.zip | sha256sum -c - \
mkdir -p ${ANDROID_HOME} \
unzip -qq tools_r${SDK_VERSION}-linux.zip -d ${ANDROID_HOME} \
rm -Rf tools_r${SDK_VERSION}-linux.zip \
echo y | ${ANDROID_HOME}/tools/android update sdk --filter ${SDK_UPDATE} --all --no-ui --force \
mkdir -p ${ANDROID_HOME}/tools/keymaps \
touch ${ANDROID_HOME}/tools/keymaps/en-us \
yes | ${ANDROID_HOME}/tools/bin/sdkmanager --update
RUN chmod -R 777 ${ANDROID_HOME} chown -R jenkins:jenkins ${ANDROID_HOME}
我們還使用了 Jenkinsfile,該文件與上一個文件類似,用于構建 master。每當我們對 Dockerfile 進行更改時,agent 都會重建鏡像。這為我們的 CI/CD 基礎架構提供了極大的靈活性。
使用自動伸縮
盡管我們為 deployment 分配了特定數量的節點,但我們還可以通過啟用 cluster autoscaling,來完成更多的事情。這意味著在工作負載增加和峰值的情況下,我們可以增加額外的節點來處理 job。目前,如果我們有固定數量的節點,那么我們只能處理固定數量的 job。基于以下事實,我們可以進行粗略地估計:每個 slave 通常分配 500ms CPU 和 256MB 內存,并且設置一個很高的并發。這根本不現實。
舉個例子,當你的版本被大幅削減并且需要部署大量微服務時,可能會發生上述情況。然后,大量的 job 堆積在流水線,造成嚴重的延誤。
在這種情況下,我們可以增加該階段的節點數。例如,我們可以添加額外的 VM 實例,然后在過程結束時將其刪除。
我們可以在命令行中使用自動伸縮選項來配置“Vertical”或“集群”自動伸縮選項。但是,此方法需要仔細計劃和配置,因為有時會發生以下情況:
越來越多的 job 達到平穩階段
Autoscaler 增加新的節點,但是需要 10 分鐘來進行部署和分配
舊的 job 已經完成任務,新的 job 將填補空白,進而減少了對新節點的需求
新節點可用,但需要 X 分鐘保持穩定且未利用,X 由–scale-down-unneeded-time 標志定義
同樣的事情每天發生很多次
在這種情況下,最好是根據我們的特定需求進行配置,或者只是增加當天的節點數,并在流程結束后將其還原。所有這些都與尋找最佳方法來利用所有資源并使成本最小化有關。
在任何情況下,我們都應該有一個可伸縮且易于使用的 Jenkins 集群。對于每個 job,都會創建一個 pod 來運行特定的流水線,并在完成后將其銷毀。
大規模使用 K8s 進行 CI / CD 的最佳實踐
現在我們已經了解了 Kubernetes 有哪些 CI/CD 平臺以及如何在你的集群上安裝一個平臺。接下來,我們將討論一些大規模運行它們的方法。
首先,選擇 Kubernetes 發行版是我們需要考慮的最關鍵因素之一。找到最合適的解決方案才能夠進行下一步。
其次,選擇合適的 Docker 鏡像倉庫和應用程序包管理器同樣重要。我們需要尋找可以按需快速檢索的安全可靠的鏡像管理。至于軟件包管理器,Helm 是一個不錯的選擇,因為它可以發現、共享和使用為 Kubernetes 構建的軟件。
第三,使用現代集成流程,如 GitOps 和 ChatOps,在易用性和可預測性方面提供了顯著優勢。將 Git 用作單一數據源,使我們可以運行“通過拉取請求進行操作”,從而簡化了對基礎架構和應用程序的部署控制。使用諸如企業微信或釘釘之類的團隊協作工作來觸發 CI/CD 流水線的自動化任務,有助于我們消除重復勞動并簡化集成。
總體而言,如果我們想更深入地了解,你可以自定義或開發自己的 K8S Operator,與 K8S API 配合更緊密。使用自定義 operator 的好處很多,因為它們可以建立更好的自動化體驗。
以上就是怎么在 Kubernetes 上大規模運行 CI/CD,丸趣 TV 小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注丸趣 TV 行業資訊頻道。