天天看點

Kubernetes部署實操教程

之前,我們基本都是單體Web應用程式:大型的代碼庫,随着新的功能和特性不斷發展,最後它們都會變成巨大的,緩慢移動的,難以管理的巨人。 現在,越來越多的開發人員,架構師和DevOps專家認為,使用微服務比使用大型單體應用更好。 通常,使用基于微服務的體系結構意味着将你的單體應用分成至少兩個應用程式:前端應用程式和後端應用程式(API)。在決定使用微服務之後,出現了一個問題:在什麼環境下運作微服務更好? 我應該選擇什麼來使我的服務穩定,易于管理和部署?簡短的回答是:使用Docker!

在本文中,我将介紹容器,解釋Kubernetes,并教你如何使用CircleCI将應用程式容器化和部署到Kubernetes叢集。

Docker?什麼是Docker?

Docker是一款旨在讓DevOps(和你的生活)更輕松的工具。使用Docker,開發人員可以在容器中建立,部署和運作應用程式。容器允許開發人員使用所需的所有部件(例如庫和其他依賴項)打包應用程式,并将其作為一個包釋出出去。

使用容器,開發人員可以輕松将鏡像(重新)部署到任何作業系統。 隻需安裝Docker,執行指令,你的應用程式即可啟動并運作。哦,不要擔心主機作業系統中新版本庫的任何不一緻。此外,您可以在同一主機上啟動很多容器——不管是相同的應用程式還是其他應用程式,都沒關系。

看起來Docker是一個很棒的工具。但是我應該如何以及在何處啟動容器?

運作容器的方式有很多選擇:

  • AWS Elastic Container Service(AWS Fargate或具有水準和垂直自動伸縮的預留執行個體);
  • Azure或Google Cloud中具有預定義Docker鏡像的雲執行個體(包含模闆,執行個體組和自動縮放);
  • 在你自己的伺服器上;
  • 當然還有Kubernetes!Kubernetes是2014年由Google工程師專門為虛拟化和容器建立的。

Kubernetes?那是什麼?

Kubernetes是一個開源系統,允許你運作容器,管理容器,自動化部署,擴充部署,建立和配置Ingress,部署無狀态或有狀态應用程式以及許多其他内容。基本上,你可以啟動一個或多個執行個體來安裝Kubernetes,将其作為Kubernetes叢集進行操作。然後擷取Kubernetes叢集的API端點,配置kubectl(管理Kubernetes叢集的工具),Kubernetes即可投入使用。

那我為什麼要用Kubernetes呢?

使用Kubernetes,你可以最大限度地利用計算資源。 通過Kubernetes,你将成為你的船(基礎設施)的船長,Kubernetes将為你揚帆。 使用Kubernetes,你的服務将是高可用的。最重要的是,通過Kubernetes,你将節省大量資金。

看起來很有前途,特别是如果它會省錢!讓我們來談談它!

Kubernetes日複一日地更加受歡迎。讓我們更深入地研究一下這幕後的内容。

譯者注:上圖有個小錯誤,kubectl寫成了kubecti。

Kubernetes是整個系統的名稱,但與你的汽車一樣,有許多小部件可以完美地彼此協同工作以使Kubernetes發揮其各種作用。讓我們來了解它們分别是什麼。

主節點(Master Node)——整個Kubernetes叢集的控制台。主節點的元件可以在群集中的任何節點上運作。關鍵組成部分是:

  • API Server:所有REST指令的入口點,是使用者可以通路的主節點的唯一元件。
  • Datastore:Kubernetes群集使用的強大,一緻且高可用的鍵值存儲。
  • Scheduler:監視新建立的Pod并将它們配置設定給節點。Pod和Services部署到節點上主要由Scheduler來控制。
  • Controller manager:管理着處理叢集中日常任務的所有控制器。
  • Worker Node:主要的節點代理,也稱為minion(舊版本Kubernetes的叫法)。Pod在這裡運作。工作節點包含所有必要的服務,這些服務包括管理容器之間的網絡,與主節點通信以及将資源配置設定給已排程容器等。
  • Docker:運作在每個工作節點上,用來下載下傳鏡像和啟動容器。
  • Kubelet:監視Pod的狀态并確定容器已啟動并運作。它還與資料存儲通信,擷取有關服務的資訊并記錄新建立的服務的詳細資訊。
  • Kube-proxy:單個工作節點上的服務的網絡代理和負載均衡。它負責流量路由。
  • Kubectl:一個CLI工具,供使用者與Kubernetes API Server進行通信。

那什麼是Pod和Services?

Pod是Kubernetes叢集中最小的單元,就像一座巨大建築物牆上的一塊磚。 Pod是一組需要一起運作并且可以共享資源的容器(Linux名稱空間,cgroups,IP位址)。Pod的生命周期是非永久性的。

Service是在多個Pod之上的抽象,通常需要在它上面有層代理,以便其他服務通過虛拟IP位址與其通信。

一個簡單部署例子

我将使用簡單的Ruby on Rails應用程式和GKE作為運作Kubernetes的平台。實際上,你可以在AWS或Azure中使用Kubernetes,甚至可以在你自己的硬體中建立叢集,或使用你minikube在本地運作Kubernetes,所有的選項你都可以在這個頁面

Setup - Kubernetes

上找到。

這個app的源碼你可以在

GitHub - d-kononov/simple-rails-app-in-k8s

裡找到。

要建立新的Rails應用程式,請執行:

rails new blog
      

config/database.yml

檔案中配置生産MySQL連接配接:

production:
adapter: mysql2
encoding: utf8
pool: 5
port: 3306
database: <%= ENV['DATABASE_NAME'] %>
host: 127.0.0.1
username: <%= ENV['DATABASE_USERNAME'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>
      

建立Article model、controller、views和migration,請執行:

rails g scaffold Article title:string description:text
      

添加Gems到Gemfile:

gem 'mysql2', '< 0.6.0', '>= 0.4.4'
gem 'health_check'
      

建立Docker鏡像,請下載下傳

Dockerfile

,并執行:

docker build -t REPO_NAME/IMAGE_NAME:TAG . && docker push REPO_NAME/IMAGE_NAME:TAG
      

是時候建立一個Kubernetes叢集了。打開GKE頁面并建立Kubernetes叢集。建立叢集後,單擊“連接配接”按鈕并複制指令——確定你已安裝和配置了

gCloud CLI

工具(

如何

)和kubectl。在PC上執行複制的指令并檢查與Kubernetes叢集的連接配接;執行

kubectl cluster-info

該應用程式已準備好部署到Kubernetes群集。讓我們建立一個MySQL資料庫。在gCloud控制台中打開SQL頁面,為應用程式建立一個MySQL資料庫執行個體。執行個體準備就緒後,建立使用者和資料庫并複制執行個體連接配接名稱。

此外,我們需要在

API和服務

頁面中建立一個

service account

密鑰,以便從sidecar容器通路MySQL資料庫。您可以在

此處

找到有關該流程的更多資訊。 将下載下傳的檔案重命名為

service-account.json

。 我們稍後會用到這個檔案。

我們準備将我們的應用程式部署到Kubernetes,但首先,我們應該為我們的應用程式建立

secret

——在Kubernetes中建立用于存儲敏感資料的secret對象。上傳之前下載下傳的

service-account.json

檔案:

kubectl create secret generic mysql-instance-credentials \
 --from-file=credentials.json=service-account.json
      

為應用程式建立secrets:

kubectl create secret generic simple-app-secrets \
 --from-literal=username=$MYSQL_PASSWORD \
 --from-literal=password=$MYSQL_PASSWORD \
 --from-literal=database-name=$MYSQL_DB_NAME \
 --from-literal=secretkey=$SECRET_RAILS_KEY
      

請不要忘記替換必要的配置,或者記得正确地設定環境變量。

在建立deployment之前,讓我們看一下

deployment.yaml

。我把三個檔案連成一個;第一部分是一個Service,它将公開端口80并轉發到端口80和到3000的所有連接配接。該Service有一個selector,Service通過它知道哪個Pod應該轉發連接配接。

該檔案的下一部分是Deployment,它描述了将在Pod中啟動的部署政策容器,環境變量,資源,探針,每個容器的mounts以及其他資訊。

最後一部分是Horizontal Pod Autoscaler。HPA有一個非常簡單的配置。請記住,如果您未在部署部分中為容器設定資源,則HPA将無法運作。

您可以在GKE編輯頁面中為Kubernetes叢集配置Vertical Autoscaler。它也有一個非常簡單的配置。

是時候将它釋出到GKE叢集了!首先,我們通過

rake-tasks-job.yaml

進行部署。 執行:

kubectl apply -f rake-tasks-job.yaml
      

這個Job對于CI/CD很有用。

kubectl apply -f deployment.yaml
      

上面這條指令用來建立Service、Deployment和HPA。

然後通過

kubectl get pods -w

指令來檢查你的Pod:

NAME READY STATUS RESTARTS AGE
sample-799bf9fd9c-86cqf 2/2 Running 0 1m
sample-799bf9fd9c-887vv 2/2 Running 0 1m
sample-799bf9fd9c-pkscp 2/2 Running 0 1m
      

現在讓我們為應用建立一個Ingress:

  1. 建立一個靜态IP:

    gcloud compute addresses create sample-ip --global

  2. 建立Ingress:

    kubectl apply -f ingress.yaml

  3. 檢查Ingress是否建立成功和檢視它的IP位址:

    kubectl get ingress -w

  4. 為你的應用建立域名或者子域名

CI/CD

讓我們使用CircleCI建立一個CI/CD管道。實際上,使用CircleCI建立CI/CD管道很容易,但請記住,快而髒的未經過測試的全自動部署過程僅适用于小型項目,但請不要在嚴肅的項目上這樣做。如果任何新代碼在生産中出現問題,那麼你将會損失巨大。這就是為什麼你應該考慮設計一個強大的部署過程,在完全推出之前啟動canary任務,在canary啟動後檢查日志中的錯誤,等等。

目前,我們有一個簡單的小項目,是以讓我們建立一個完全自動化,無測試的CI/CD部署過程。首先,您應該将CircleCI與您的代碼倉庫進行內建——你可以在

找到具體内容。 然後我們應該建立一個包含CircleCI系統指令的配置檔案。Config看起來很簡單。要點是GitHub倉庫中有兩個分支:master和production。

  1. 主分支用于開發,用于新代碼。當有人将新代碼推送到主分支時,CircleCI啟動主分支建構和測試代碼的工作流。
  2. 生産分支用于将新版本部署到生産環境。生産分支的工作流程如下:推送新代碼(如果從主分支到生産開放PR則更好)以觸發新的建構和部署過程;在建構過程中,CircleCI建立新的Docker鏡像,将其推送到GCR并建立新的部署;如果失敗,CircleCI将觸發復原過程。

在運作任何建構之前,您應該在CircleCI中配置項目。在API和GCloud中的Service頁面中建立一個新的service account,具有以下角色:完全通路GCR和GKE,打開下載下傳的JSON檔案并複制内容,然後在CircleCI的項目設定中建立一個新的環境變量GCLOUD_SERVICE_KEY并将service account檔案的内容粘貼為值。 此外,您需要建立下一個env vars:GOOGLE_PROJECT_ID(可以在GCloud控制台首頁上找到它),GOOGLE_COMPUTE_ZONE(GKE叢集的區域)和GOOGLE_CLUSTER_NAME(GKE叢集名稱)。

CircleCI的最後一步(部署)如下所示:

kubectl patch deployment sample -p '{"spec":{"template":{"spec":{"containers":[{"name":"sample","image":"gcr.io/test-d6bf8/simple:'"$CIRCLE_SHA1"'"} ] } } } }'
if ! kubectl rollout status deploy/sample; then
echo "DEPLOY FAILED, ROLLING BACK TO PREVIOUS"
kubectl rollout undo deploy/sample
# Deploy failed -> notify slack
else
echo "Deploy succeeded, current version: ${CIRCLE_SHA1}"
# Deploy succeeded -> notify slack
fi
deployment.extensions/sample patched
Waiting for deployment "sample" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "sample" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "sample" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "sample" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "sample" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "sample" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "sample" rollout to finish: 2 of 3 updated replicas are available...
Waiting for deployment "sample" rollout to finish: 2 of 3 updated replicas are available...
deployment "sample" successfully rolled out
Deploy succeeded, current version: 512eabb11c463c5431a1af4ed0b9ebd23597edd9 
      

總結

看起來建立新的Kubernetes叢集的過程并不那麼難!CI/CD自動部署過程也非常棒!

是!Kubernetes太棒了!使用Kubernetes,你的系統将更加穩定,易于管理,并使你成為系統的“船長”。更不用說,Kubernetes對系統施加了一些魔法,并為您的營銷提供了+100分!

現在你已經掌握了基礎知識,可以進一步将其轉換為更進階的配置。我計劃在以後的文章中介紹更多内容,但與此同時,有一個挑戰:使用位于叢集内的有狀态資料庫(包括用于備份的sidecar Pod)為應用程式建立一個強大的Kubernetes叢集,在其中安裝Jenkins用于CI/CD管道,讓Jenkins使用Pod作為建構的slave。使用certmanager為Ingress添加/擷取SSL證書。使用Stackdriver為應用程式建立監控和報警系統。

Kubernetes非常棒,因為它很容易擴充,沒有供應商鎖定,并且,因為你為執行個體付費,是以可以省錢。然而,不是每個人都是Kubernetes專家或者有時間建立一個新的叢集。這裡有一個可選方案:關于如何建構有效的初始部署管道并執行更少的操作任務,我的同僚Toptaler Amin Shah Gilani使用Heroku,GitLab CI以及他能想到的其他自動化部署工具做了一套教程

CI/CD:如何部署有效的初始化部署管道

本文轉自DockOne-

Kubernetes部署實操教程