返回文章列表

Docker Swarm Kubernetes 雲原生持續交付流程

本文闡述如何在 Docker Swarm 和 Kubernetes 上建構雲原生應用程式的持續交付流程。涵蓋 Docker Swarm 佈署、Jenkins 流程建置、多環境管理與 Kubernetes EKS 叢集設定。探討 VPC 對等連線、Docker

雲原生 持續交付

在雲原生時代,持續交付流程至關重要。本文將探討如何在 Docker Swarm 和 Kubernetes 上建構高效的持續交付流程,以確保應用程式快速且可靠地佈署到不同環境。首先,我們會在 Docker Swarm 上利用 Jenkins 建立自動化Pipeline,實作程式碼更新後的自動建置、測試和佈署。過程中,我們會使用 VPC 對等連線確保環境隔離,並透過 Docker Compose 進行服務協調。同時,Jenkinsfile 的使用能更精細地控制佈署流程,並整合手動驗證步驟以確保佈署品質。接著,我們將轉向 Kubernetes,使用 Terraform 在 AWS EKS 上建立叢集,並佈署微服務應用程式。過程中,我們會探討如何設定節點群組、組態 kubectl 以及建立佈署和服務資源。最後,我們將比較 Docker Swarm 和 Kubernetes 的佈署策略,並說明如何選擇適合自身需求的平台。

在 Docker Swarm 上實作雲原生應用程式的持續交付流程

10.5 實作 Jenkins 交付流程

要將應用程式堆積疊佈署到生產環境,首先需要為生產環境建立新的 Swarm 叢集。再次強調,為了隔離生產工作負載,選擇在專用的生產 VPC 中建立 Swarm 叢集,該 VPC 的 CIDR 位址區塊為 10.3.0.0/16,並在管理 VPC(Jenkins 所在位置)與生產 VPC(Swarm 生產環境佈署位置)之間設定 VPC 對等連線。圖 10.45 總結了已佈署的架構。

圖表翻譯:

此圖示展示了多個 Swarm 叢集 VPC 與管理 VPC 之間的對等連線。管理 VPC 中佈署了 Jenkins 叢集,可以存取沙盒(sandbox)、預生產(staging)和生產(production)VPC。

VPC 對等連線的注意事項

VPC 對等連線不支援過渡式對等連線(transitive peering)。這意味著生產、預生產和沙盒環境是完全隔離的,封包無法直接從沙盒路由到生產環境,例如透過管理 VPC。

在生產環境中佈署 Docker Compose

watchlist-deployment 儲存函式庫的主分支(master branch)上,建立一個 docker-compose.yml 檔案。這次,我們使用 latest 標籤來代表在生產環境中執行的服務,如下所示:

version: "3.3"
services:
  movies-loader:
    image: ID.dkr.ecr.REGION.amazonaws.com/USER/movies-loader:latest
    environment:
      - AWS_REGION=eu-west-3
      - SQS_URL=https://sqs.REGION.amazonaws.com/ID/movies_to_parse_production
  movies-parser:
    image: ID.dkr.ecr.REGION.amazonaws.com/USER/movies-parser:latest

內容解密:

此 Docker Compose 檔案定義了兩個服務:movies-loadermovies-parser。這兩個服務分別使用了來自 Amazon ECR 的 Docker 映像,並設定了必要的環境變數,如 AWS_REGIONSQS_URL。使用 latest 標籤確保佈署的是最新的映像版本。

設定 Jenkins 認證與佈署流程

  1. 在 Jenkins 中建立一個認證憑證,使用用於佈署 Swarm 叢集的 SSH 金鑰,並將其命名為 swarm-production

  2. 建立一個 Jenkinsfile,用於遠端上傳 docker-compose.yml 檔案到管理節點,並執行 docker stack deploy 命令來佈署應用程式。

def swarmManager = 'manager.production.domain.com'
def region = 'AWS REGION'

node('master') {
    stage('Checkout') {
        // 克隆 GitHub 儲存函式庫的指令,請參考清單 10.25
    }
    sshagent(credentials: ['swarm-production']) {
        stage('Copy') {
            // 將 docker-compose.yml 複製到 Swarm 管理節點的指令,請參考清單 10.25
        }
        stage('Deploy stack') {
            // 透過 SSH 重新佈署 Docker Compose 堆積疊的指令,請參考清單 10.25
        }
    }
}

內容解密:

此 Jenkinsfile 定義了一個Pipeline,包含了簽出程式碼、複製 docker-compose.yml 到遠端伺服器以及佈署 Docker 堆積疊的階段。使用 sshagentswarm-production 認證憑證來安全地連線到 Swarm 管理節點。

自動化與手動驗證的佈署流程

為了模擬產品/業務驗證或 QA 團隊在佈署到生產環境前進行測試,我們需要在佈署到生產環境前加入手動驗證步驟。

stage('Deploy') {
    if (env.BRANCH_NAME == 'develop' || env.BRANCH_NAME == 'preprod') {
        build job: "watchlist-deployment/${env.BRANCH_NAME}"
    }
    if (env.BRANCH_NAME == 'master') {
        timeout(time: 2, unit: "HOURS") {
            input message: "Approve Deploy?", ok: "Yes"
        }
        build job: "watchlist-deployment/master"
    }
}

內容解密:

在此階段中,如果分支是 developpreprod,則自動觸發對應的佈署作業。如果是 master 分支,則暫停Pipeline執行,並等待手動確認是否佈署到生產環境。設定了2小時的超時時間,以避免 Jenkins 工作節點長時間閒置。

合併變更與觸發佈署

  1. 將變更推播到功能分支,並提出一個合併請求,將變更合併到 develop 分支。
  2. 合併變更到 develop 分支後,會觸發沙盒叢集的佈署。
  3. 然後,提出另一個合併請求,將 develop 合併到 preprod 分支,觸發預生產叢集的佈署。
  4. 最後,將 preprod 合併到 master 分支,觸發生產環境的佈署,但需經過手動驗證。

圖表翻譯:

此圖示展示了從功能分支到 developpreprod 和最終 master 分支的合併流程,每一步都觸發了相應環境的佈署。確保每一步都經過適當的測試和驗證,以保證軟體品質。

在Docker Swarm上佈署雲原生應用程式的持續整合與交付

Jenkins交付流程的實作

當程式碼合併發生時,Jenkins將觸發movies-loader服務的主分支建置。如圖10.54所示。然而,這次當它到達佈署階段時,將彈出一個輸入對話方塊以確認佈署。

圖10.54 主分支上的CI/CD流程執行

如圖10.55所示,互動式輸入將詢問是否批准佈署。

圖10.55 佈署使用者輸入對話方塊

如果我們點選“是”,流程將繼續,並在主分支上觸發佈署作業,如圖10.56所示。

圖10.56 生產佈署批准

在佈署過程結束時,新的堆積疊將被佈署到Swarm生產環境,並向組態的Slack頻道傳送通知(圖10.57)。

圖10.57 生產佈署成功通知

透過生產佈署的介紹,我們已經瞭解瞭如何將容器化的微服務應用程式佈署到多個環境中,以及如何在CI/CD流程中處理程式碼升級。然而,由於我們只管理三個環境(沙盒、預釋出和生產),因此我們將透過定義正規表示式來限制佈署作業的發現行為,如圖10.58所示。

圖10.58 根據正規表示式的Jenkins發現行為

因此,Jenkins將只在三個主要分支之一發生變化時才會發現並觸發,如圖10.59所示。

圖10.59 佈署多分支作業

現在,如果我們對應用程式進行任何更改,CI/CD流程將被觸發,並執行docker stack deploy,這將更新與前一版本相比發生變化的任何服務。

內容解密:

本文描述了Jenkins交付流程的實作細節,包括觸發建置、佈署確認和生產佈署的通知機制。重點介紹瞭如何透過定義正規表示式來限制佈署作業的發現行為,從而實作對多個環境的管理。

將微服務佈署到Kubernetes

設定Kubernetes叢集

AWS提供了Amazon Elastic Kubernetes Service(EKS),這是一種託管的Kubernetes服務。EKS叢集將被佈署在自定義VPC內的多個私有子網路中。EKS跨多個AWS可用區域執行Kubernetes控制平面,以消除單點故障,如圖11.2所示。

圖11.2 AWS EKS架構由佈署在私有子網路中的節點組組成

有多種工具(包括AWS CloudFormation、eksctl和kOps)可以讓您快速上手EKS。在本章中,我們選擇了Terraform,因為我們已經使用它來管理我們的Jenkins叢集在AWS上。

首先,為了託管沙盒環境,建立一個新的VPC,並將其劃分為兩個私有子網路。Amazon EKS要求至少在兩個可用區域中有子網路。

resource "aws_vpc" "sandbox" {
  cidr_block = var.cidr_block
  enable_dns_hostnames = true
  tags = {
    Name = var.vpc_name
    Author = var.author
    "kubernetes.io/cluster/${var.cluster_name}" = "shared"
  }
}

建立EKS叢集

接下來,建立一個新的eks_masters.tf檔案,並定義sandbox EKS叢集,這是一個託管的K8s控制平面,如下所示。

resource "aws_eks_cluster" "sandbox" {
  name     = var.cluster_name
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    security_group_ids = [aws_security_group.cluster_sg.id]
    subnet_ids         = [for subnet in aws_subnet.private_subnets : subnet.id]
  }
  depends_on = [
    aws_iam_role_policy_attachment.cluster_policy,
    aws_iam_role_policy_attachment.service_policy,
  ]
}

託管控制平面使用具有AmazonEKSClusterPolicyAmazonEKServicePolicy策略的IAM角色。這些附件授予叢集所需的許可,以便其能夠自行管理。

工作節點的建立

現在是時候啟動一些工作節點了。節點是一個簡單的EC2例項,它執行Kubernetes物件(pod、deployment、service等)。主節點的管理由EKS控制平面負責。

內容解密:

本文描述瞭如何使用Terraform在AWS上建立EKS叢集,包括建立VPC、子網路和EKS叢集本身。同時,也介紹瞭如何組態IAM角色和策略,以授予EKS叢集必要的許可。重點介紹了使用Terraform的好處,即可以重用已有的Jenkins叢集管理經驗。

在 Kubernetes(K8s)上佈署 Dockerized 微服務

建立 Amazon EKS 叢集

要使用 Terraform 建立 Amazon Elastic Kubernetes Service(EKS)叢集,首先需要在 eks_workers.tf 檔案中定義 EKS 節點群組資源。以下範例程式碼展示瞭如何定義節點群組:

resource "aws_eks_node_group" "workers_node_group" {
  cluster_name    = aws_eks_cluster.sandbox.name
  node_group_name = "${var.cluster_name}-workers-node-group"
  node_role_arn   = aws_iam_role.worker_role.arn
  subnet_ids      = [for subnet in aws_subnet.private_subnets : subnet.id]

  scaling_config {
    desired_size = 2
    max_size     = 5
    min_size     = 2
  }

  depends_on = [
    aws_iam_role_policy_attachment.worker_node_policy,
    aws_iam_role_policy_attachment.cni_policy,
    aws_iam_role_policy_attachment.ecr_policy,
  ]
}

內容解密:

  • aws_eks_node_group 資源用於建立 EKS 節點群組。
  • cluster_namenode_group_name 分別指定了 EKS 叢集名稱和節點群組名稱。
  • node_role_arn 指定了節點群組所使用的 IAM 角色。
  • subnet_ids 指定了節點群組所使用的子網路 ID。
  • scaling_config 用於設定節點群組的擴充套件組態,包括所需的節點數量、最大節點數量和最小節點數量。
  • depends_on 用於指定建立節點群組所依賴的資源。

設定 Kubernetes 叢集

在建立 EKS 叢集後,需要組態 kubectl 命令列工具以與叢集 API 伺服器進行通訊。首先,需要使用 AWS CLI 的 update-kubeconfig 命令來生成 kubeconfig 檔案:

aws eks update-kubeconfig --name sandbox --region AWS_REGION

然後,可以使用以下命令來驗證叢集是否正確組態和執行:

kubectl get nodes

自動化佈署流程

要使用 Jenkins 自動佈署 Watchlist 應用程式,需要建立 Kubernetes 佈署檔案。以下範例程式碼展示瞭如何定義 movies-loader 服務的佈署資源:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: movies-loader
  namespace: watchlist
spec:
  selector:
    matchLabels:
      app: movies-loader
  template:
    metadata:
      labels:
        app: movies-loader
    spec:
      containers:
      - name: movies-loader
        image: ID.dkr.ecr.REGION.amazonaws.com/USER/movies-loader:develop
        env:
        - name: AWS_REGION
          value: REGION
        - name: SQS_URL
          value: https://sqs.REGION.amazonaws.com/ID/movies_to_parse_sandbox

內容解密:

  • apiVersionkind 分別指定了 Kubernetes API 版本和資源型別。
  • metadata 用於指定佈署資源的後設資料,包括名稱和名稱空間。
  • spec 用於指定佈署資源的規格,包括選擇器、範本和容器組態。
  • containers 用於指定容器組態,包括映像檔名稱、環境變數等。

MongoDB 佈署資源

以下範例程式碼展示瞭如何定義 MongoDB 的佈署資源:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongodb
  namespace: watchlist
spec:
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
      - name: mongodb
        image: bitnami/mongodb:latest
        env:
        - name: MONGODB_USERNAME
          valueFrom:
            secretKeyRef:
              name: mongodb-access
              key: username
        - name: MONGODB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mongodb-access
              key: password
        - name: MONGODB_DATABASE
          valueFrom:
            secretKeyRef:
              name: mongodb-access
              key: database

內容解密:

  • apiVersionkind 分別指定了 Kubernetes API 版本和資源型別。
  • metadata 用於指定佈署資源的後設資料,包括名稱和名稱空間。
  • spec 用於指定佈署資源的規格,包括選擇器、範本和容器組態。
  • containers 用於指定容器組態,包括映像檔名稱、環境變數等。
  • 環境變數的值從 Secret 資源中取得。