一起探索Kubernetes —— Kubernetes + Gitlab + Continuous Integration & Deployment
【編者的話】本文用圖示詳細分析了Gitlab如何與Kubernetes叢集整合,進行CI/CD流水線的配置,從而實現更高效的DevOps流程。
我將介紹使用DigitalOcean建立新的Kubernetes叢集(或簡稱k8s)的經驗,配置我的Gitlab專案以使用k8s叢集,以及為部署配置CI/CD程序。 如果你想了解現代堆疊的執行是多麼簡單,請繼續閱讀。
Fatos Bytyqi 拍攝
建立一個Kubernetes叢集
Kubernetes是一個容器編排平臺,由於其簡單性而受到廣泛歡迎。 Kubernetes很棒,因為你可以使用配置檔案定義部署配置,儲存和網路,叢集將確保你的應用程式始終在該配置中執行。
從原始碼構建k8s叢集是一項艱鉅的任務,但是我們可以通過大型雲提供商的幾次點選來實現這一目標。 我個人更喜歡DigitalOcean的簡單性,我很幸運能夠成為他們管理的Kubernetes產品的LTD版本的一部分。
讓我們深入瞭解如何在DigitalOcean上建立叢集。
單擊“建立Kubernetes”選項後,無論是通過側面導航還是頂部導航中的下拉選單,都會顯示此螢幕。
DigitalOceans 的 Kubernetes 叢集建立示例
在撰寫本文時,k8s版本1.13.1是最新版本,因此我在離我最近的地區選擇了該版本。
下一步是配置節點池,標籤並選擇名稱。 我選擇用一個低成本節點來保持簡單,以便學習。 這可以在將來更改,因此從小規格開始不會限制你的未來容量。
標籤是可選的,名稱可以是你想要的任何名稱。 我發現新增“k8s”標籤可以快速識別叢集中的droplet。
配置節點,標籤和名字
單擊“建立群集”後,該過程大約需要4-5分鐘才能完成。 在此期間,我們可以讓你的機器設定連線到新的k8s群集。
用於與k8s群集互動的主要的命令列程式是 kubectl
。 對於MacOS使用者,可以使用 brew
通過執行以下命令來安裝它。
➜ brew install kubernetes-cli
brew完成安裝後,你需要從DigitalOcean下載叢集配置檔案,以使 kubectl
命令知道你的叢集所在的位置。 為此,請在DigitalOcean k8s群集安裝頁面上一直向下滾動到以下部分,然後單擊“下載配置檔案”按鈕
該檔案將儲存到 ~/Downloads
目錄中。 為了簡化操作,請將檔案複製或移動到 ~/.kube/config
檔案。 該檔案將由 kubectl
命令自動讀取。
➜ mkdir -p ~/.kube ➜ mv ~/Downloads/[k8s-cluster].yaml ~/.kube/config
建立集群后,通過執行 kubectl get nodes
測試連線。 這將顯示群集中的單個節點。
➜ kubectl get nodes NAMESTATUSROLESAGEVERSION tender-einstein-8m4mReady<none>21mv1.13.1
在我的例子中,節點(這是一個DigitalOcean Droplet)被命名為“tender-einstein-8m4m”,我們可以在上面看到。 如果看到類似的輸出,則表明你的Kubernetes叢集已成功建立,並且你可以通過 kubectl
命令列程式與其建立連線。
將Gitlab連線到Kubernetes
Gitlab具有本地整合Kubernetes的功能,我們可以配置任何組或專案來使用它。 你需要在Gitlab專案上提升(專案建立者和/或管理員)許可權才能設定k8s整合。
首先,選擇Operations選單下的Kubernetes選項卡,然後單擊Add Kubernetes Cluster。
Gitlab - 新增 Kubernetes 叢集
在下一個螢幕上,單擊“新增現有群集”選項卡。 在這裡,系統將提示你輸入一些不同的專案以允許Gitlab連線到你的k8s群集。 Gitlab有關於 如何新增叢集 的優秀文件,我建議你閱讀這些文件以全面瞭解整合。我將在此強調所需的步驟。
建立帳戶
首先,我們需要為Gitlab建立一個新的系統級帳戶來連線。 此帳戶稱為ServiceAccount。 為此,我們可以使用 kubectl
命令列程式。 我們將使用YAML語法(在整個k8s中使用)定義帳戶,如下所示:
➜ kubectl create -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: gitlab namespace: default EOF
此YAML定義將在“default”名稱空間中建立名為“gitlab”的ServiceAccount。
下一步是授予gitlab帳戶叢集管理員許可權,以便它可以代表你自由建立和銷燬服務。 我們將再次使用 kubectl
和YAML定義。
➜ kubectl create -f - <<EOF kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: gitlab-cluster-admin subjects: - kind: ServiceAccount name: gitlab namespace: default roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io EOF
連線群集
現在,讓我們看一下Gitlab連線到Kubernetes叢集所需的所有資訊。
Gitlab - 新增 Kubernetes 叢集時呈現的表格
第一個欄位是Kubernetes叢集名稱。 這對你來說可以幫助你識別k8s群集。 它並沒有真正使用那麼多,所以不要花太多時間為它命名。
可以通過執行以下命令獲取下一個欄位API URL:
➜ kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}' https://xxxxxx.k8s.ondigitalocean.com
獲取命令返回的URL並將其貼上到API URL欄位中。
可以通過從建立gitlab帳戶時建立的“secret”中提取資料來獲取CA證書和token。 Kubernetes具有 secret
資源的概念,旨在儲存敏感資訊。 除了設定過程,你還可以建立自己的secret來儲存應用程式敏感資訊,如資料庫憑據,API金鑰等。
列出專案執行中的所有secret:
➜ kubectl get secrets NAMETYPEDATA default-token-xfxg9kubernetes.io/service-account-token3 gitlab-token-vxhxqkubernetes.io/service-account-token3
在這裡,我們看到群集中有2個secret物件。 我們感興趣的是名為 gitlab-token-vxhxq
的名字。 找到以 gitlab-token-*
開頭的secret,並在下一個命令中使用它:
➜ kubectl get secret <SECRET_NAME> -o jsonpath="{['data']['ca\.crt']}" | base64 --decode -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
複製並貼上從命令返回的所有內容,從 ----- BEGIN CERTIFICATE -----
開始,以 ----- END CERTIFICATE -----
結尾,進入CA Certificate欄位
可以通過執行以下操作以類似的方式獲取token:
➜ kubectl get secret <SECRET_NAME> -o jsonpath="{['data']['token']}" | base64 --decode WlhsS2FHSkhZMmxQYVVwVFZYc...
再一次,將返回的值貼上到Gitlab中的Token欄位中。
至於Project Namespace,我把它留空了。 確保選中RBAC啟用的群集複選框。 準備好後,繼續並單擊Add Kubernetes Cluster按鈕。
Gitlab - 叢集所有的必填欄位均已填入
設定CI/CD
在Gitlab中設定持續整合和持續部署流水線非常簡單。它融入了Gitlab產品,只需將 .gitlab-ci
檔案新增到專案的根目錄即可輕鬆配置。將程式碼推送到Gitlab倉庫時會觸發CI/CD流水線。流水線必須在伺服器上執行,該伺服器稱為“Runner”。Runner可以是虛擬專用伺服器,公共伺服器,也可以是安裝Gitlab Runner客戶端的任何地方。在我們的用例中,我們將在k8s群集上安裝一個執行器,以便在pod中執行job。此客戶端還使其可擴充套件,因此我們可以並行執行多個job。
要在群集上安裝Gitlab runner客戶端,我們首先需要安裝另一個名為Helm的工具。 Helm是Kubernetes的軟體包管理器,簡化了軟體的安裝。我覺得Helm與Brew for Mac類似,他們都有一個可以安裝到系統上的軟體回購。
安裝Helm
通過Gitlab安裝Helm只需要單擊“安裝”按鈕。假設一切都配置正確,安裝只需幾秒鐘。
在 k8s 叢集上安裝 helm tiller
完成之後,讓我們看看群集,看看Gitlab安裝了什麼。 使用 kubectl get ns
命令,我們可以看到Gitlab已經建立了自己的名稱空間,命名為gitlab-managed-apps。
➜ kubectl get ns NAMESTATUSAGE defaultActive1d gitlab-managed-appsActive23s kube-publicActive1d kube-systemActive1d
如果我們執行 kubectl get pods
,當未指定名稱空間時,預設使用 default
,我們將看不到任何內容。 要檢視Gitlab名稱空間中的pod,請執行 kubectl get pods -n gitlab-managed-apps
。
➜ kubectl get pods -n gitlab-managed-apps NAMEREADYSTATUSRESTARTSAGE tiller-deploy-7dd47f89cc-27cmt1/1Running05m
在這裡,我們看到“Helm tiller”已成功建立並正在執行。
安裝Gitlab Runner
如前所述,Gitlab執行程式允許我們的CI/CD job在k8s叢集中執行。 使用Gitlab安裝Runner很簡單,只需單擊“安裝”按鈕即可。
Gitlab - 在k8s叢集上安裝執行器
我的群集花了大約1分鐘。 完成之後,讓我們再看看pod,你應該看到Gitlab Runner的新pod。
➜ kubectl get pods -n gitlab-managed-apps
NAME READY STATUS RESTARTS
runner-gitlab-runner-5cffc648d7-xr9rq 1/1 Running 0
tiller-deploy-7dd47f89cc-27cmt 1/1 Running 0
你可以通過檢視Gitlab中的設定➜CI/CD➜Runner部分來驗證Runner是否已連線到你的專案。
Gitlab - Kubernetes 執行器已在本專案啟用
執行流水線
很好,所以現在我們有一個功能齊全的Gitlab專案,連線到Kubernetes,Runner準備執行我們的CI/CD流水線。 讓我們設定一個示例Golang專案,看看如何觸發這些流水線。 對於這個專案,我們將執行一個簡單的HTTP伺服器,返回經典的“Hello World”。
首先,寫下go程式碼:
# main.go package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc( "/hello", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") }, ) log.Fatal(http.ListenAndServe(":8080", nil))
}
然後是執行的 Dockerfile:
# Dockerfile FROM golang:1.11 WORKDIR /go/src/app COPY . . RUN go get -d -v ./... RUN go install -v ./... CMD ["app"]
接下來,我們將建立一個.gitlab-ci.yml檔案來定義我們的CI/CD流水線。 該檔案將在每次程式碼推送時進行評估,如果分支或標籤與任何job匹配,它們將由我們之前配置的Gitlab執行程式之一自動執行。
我們流水線的第一步是在我們推送到主分支時建立應用程式的docker映象。 我們可以使用以下配置執行此操作:
# Gitlab CI Definition (.gitlab-ci.yml) stages: - build - deploy services: - docker:dind variables: DOCKER_HOST: tcp://localhost:2375 build_app: image: docker:latest stage: build only: - master script: - docker build -t ${CI_REGISTRY}/${CI_PROJECT_PATH}:${CI_COMMIT_REF_NAME} . - docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY} - docker push ${CI_REGISTRY}/${CI_PROJECT_PATH}:${CI_COMMIT_REF_NAME
}
讓我們瀏覽檔案中的每個塊。 stages:
塊定義流水線中階段的順序。我們只有2個階段,構建然後部署。
services:
塊包括官方Docker-in-Docker(或dind)映象,將在所有job中連結。我們需要這個,因為我們將成為Gitlab CI docker容器內的應用程式docker容器。
接下來我們有 build_app:
job。這個名字由我們的專案組成,可以是你想要的任何名稱。 image
表明我們正在使用Docker Hub中的最新Docker映象。 stage
告訴Gitlab這個job處於什麼階段。要記住的一件好事是,同一階段的job將並行執行。 only:
標籤表示我們只會在提交到 master
分支時執行此job。最後, scrips:
是job的核心,它將執行 docker build
命令來建立我們的映象,然後 docker login
到Gitlab登錄檔,然後 docker push
將該映象推送到我們的登錄檔。
此時我們可以提交併推送程式碼,你應該在Gitlab登錄檔中看到一個全新的映象。
在構建映象並將其儲存在登錄檔上之後,下一步是部署它。我們需要定義部署配置,告訴kubernetes我們想要如何執行應用程式。以下yaml檔案正是如此:
# Deployment Configuration (deployment-template.yaml) apiVersion: apps/v1 kind: Deployment metadata: name: example-deployment labels: app: example spec: replicas: 1 selector: matchLabels: app: example template: metadata: labels: app: example spec: containers: - name: example image: registry.gitlab.com/thisiskj/example:latest ports: - containerPort: 8080
此檔案定義了一個部署,其中包含一個將從專案執行映象的單個副本(registry.gitlab.com/thisiskj/example:latest)。
為了觸發部署,我已經配置了.gitlab-ci.yml檔案,以便在標記程式碼repo時執行此操作。 這是job定義:
deploy_app: image: thisiskj/kubectl-envsubst stage: deploy environment: production only: - tags script: - envsubst \$CI_COMMIT_TAG < deployment-template.yaml > deployment.yaml - kubectl apply -f deployment.yaml
此job將執行envsubst命令,以使用觸發構建的git標籤的名稱替換deployment-template.yaml中的$ CI_COMMIT_TAG變數。 環境變數$CI_COMMIT_TAG由Gitlab執行器設定,我們告訴envsubst基本上搜索並替換檔案中的變數。
檢視應用程式
此時所有內容都已連線,我們的部署將在每個新標籤上執行。
我們可以看到正在執行的pod:
➜kubectl -n example-10311640 get pods NAMEREADYSTATUSRESTARTS example-deployment-756c8f6dc5-jk85w1/1Running0
現在,pod正在執行,但我們無法從外部訪問golang HTTP服務。 為了允許外部訪問,我們可以建立LoadBalancer型別的服務。 將以下規範新增到部署yaml以在DigitalOcean上建立LoadBalancer。
--- kind: Service apiVersion: v1 metadata: name: example-loadbalancer-service spec: selector: app: example ports: - protocol: TCP port: 80 targetPort: 8080 type: LoadBalancer
在下一次部署中,我們可以監視LoadBalancer的建立。 外部IP可能需要幾分鐘才能顯示。
➜kubectl -n example-10311640 get services NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE example-loadbalancer-serviceLoadBalancer10.245.40.9<pending>80:30897/TCP4s ... ➜kubectl -n example-10311640 get services NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE example-loadbalancer-serviceLoadBalancer10.245.40.9157.230.64.20480:30897/TCP2m9s
我們還可以在DigitialOcean控制檯中監控負載均衡器的建立:
DigitalOcean — 網路控制檯
最後,我們可以通過導航到瀏覽器中的IP地址來檢視我們的應用程式:
服務開始執行
總結一下
我希望你發現此演練有助於你設定自己的群集和現代DevOps工作流程。
你可以在 https://gitlab.com/thisiskj/example 上檢視與該專案相關的所有程式碼
如果你有任何其他方法可以將Gitlab CI/CD與Kubernetes部署整合,請隨時分享評論。
原文連結: Lets Explore Kubernetes (翻譯:池劍鋒)