Using CDK to perform continuous deployments in multi-region Kubernetes environments

Bài đăng này cũng có sự đóng góp từ Jiwon Yeom, Solutions Architect, AWS.

Giới thiệu

Khách hàng của AWS sử dụng cơ sở hạ tầng dưới dạng mã (infrastructure as code – IaC) để tạo tài nguyên cloud theo cách có khả năng lặp lại và dự đoán được. IaC đặc biệt hữu ích trong việc quản lý các môi trường có các stacks giống hệt nhau, điều này thường xảy ra trong các hệ thống đa region hoạt động tích cực. Thay vì quản lý từng region triển khai riêng lẻ, các nhóm tránh sự phân tán cơ sở hạ tầng bằng cách quản lý cơ sở hạ tầng ở cả hai region bằng cách sử dụng mã và pipelines.

Các nhóm cần ít tài nguyên hơn để quản lý và khắc phục sự cố cơ sở hạ tầng khi cấu hình hệ thống của họ giống nhau giữa các region hoặc tài khoản. Sử dụng các công cụ IaC như AWS CloudFormation, Terraform, Pulumi, và AWS Cloud Development Kit (CDK), các nhà điều hành  tạo và quản lý nhiều môi trường từ một cơ sở mã duy nhất và tránh các lỗi hệ thống do các thay đổi đột xuất gây ra. IaC cũng giúp dễ dàng khôi phục khi thay đổi không thành công.

Tương tự, cách tiếp cận GitOps cho phép bạn mở rộng cấu hình cụm Kubernetes của mình. Các công cụ GitOps như ArgoCD cho phép bạn lưu trữ trạng thái cụm Kubernetes của mình dưới dạng mã trong kho lưu trữ Git. Nếu bạn quản lý nhiều cụm bản sao, đây là một trường hợp phổ biến trong triển khai nhiều region, thì bạn có thể kiểm soát cấu hình của chúng bằng cách đưa GitOps operator của bạn đến cùng một kho lưu trữ Git.

Cơ sở hạ tầng thống nhất và triển khai khối lượng công việc

Những khách hàng muốn quản lý cơ sở hạ tầng và tài nguyên Kubernetes của họ bằng cách sử dụng cùng một thư viện mã với nhiều giải pháp có sẵn. Các nhóm đã sử dụng Terraform có thể đóng gói ứng dụng của họ bằng cách sử dụng nhà cung cấp HelmKubernetes. Người dùng Pulumi có Pulumi Kubernetes Provider.

Tương tự, CDKcdk8s cho phép bạn viết mã cả cơ sở hạ tầng đám mây và tài nguyên Kubernetes bằng các ngôn ngữ lập trình quen thuộc. Khách hàng có thể khai báo Virtual Private Clouds (VPCs), Subnets, cụm Amazon EKS , Kubernetes namespaces, chính sách kiểm soát truy cập dựa trên vai trò ( role-based access control – RBAC), triển khai, dịch vụ, xâm nhập và các tác vụ khác trong cùng một cơ sở mã. Kho lưu trữ Git lưu trữ mã ứng dụng cũng trở thành nguồn chân lý cho cấu hình cơ sở hạ tầng và khối lượng công việc.

Bài đăng này hướng dẫn bạn cách tạo các cụm Amazon EKS trong nhiều AWS Regions bằng CDK và tạo một quy trình triển khai liên tục cho các thay đổi về cơ sở hạ tầng và ứng dụng.

Các trường hợp sử dụng

Hãy tưởng tượng bạn làm việc cho Independent Software Vendor (ISV) với một sản phẩm nhạy cảm về bảo mật không thể có nhiều người thuê. Thiết kế hệ thống yêu cầu một cụm Amazon EKS cho mỗi người thuê. Khi sản phẩm trở nên thành công, tổ chức của bạn có thể chịu trách nhiệm vận hành vô số cụm bản sao.

Trong các tình huống mà vòng đời của cụm gắn chặt với ứng dụng, bạn có thể lưu trữ định nghĩa về cơ sở hạ tầng, cụm Amazon EKS và tài nguyên ứng dụng của mình trong cùng một cơ sở mã. Để triển khai một stack mới, bạn chạy lại mã CDK, mã này tạo tài nguyên cơ sở hạ tầng cần thiết để chạy ứng dụng và sau đó triển khai ứng dụng trong một cụm Amazon EKS.

Các hoạt động trong ngày thứ hai, chẳng hạn như triển khai các phiên bản mới của ứng dụng và nâng cấp các cụm, cũng được quản lý bằng CDK. Chúng tôi khuyên bạn nên kiểm tra mã bằng công cụ như cdk-nag, cùng với việc sử dụng tiêu chuẩn hóa và tham số hóa để giảm thiểu sự khác biệt giữa các region.

Kiến trúc đa region

Mã có trong bài đăng này tạo ra hai cụm  Amazon EKS proof-of-concept và cơ sở hạ tầng hỗ trợ trong hai AWS Regions.

CDK  mà bài đăng này cung cấp không bao gồm định tuyến lưu lượng truy cập nhiều region. Khách hàng có thể thêm Global Accelerator, như được giải thích trong bài đăng này hoặc sử dụng  Domain Name System (DNS) để định tuyến lưu lượng truy cập giữa các regions.

Tổng quan về giải pháp

Các điều kiện tiên quyết

Bạn sẽ cần những thứ sau để hoàn thành các bước trong bài đăng này:

Hãy bắt đầu bằng cách đặt một vài biến môi trường:

ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)

AWS_PRIMARY_REGION=us-east-2

AWS_SECONDARY_REGION=eu-west-2

Sao chép kho lưu trữ mẫu và cài đặt các gói phụ thuộc. Kho này chứa mã CDK v2 được viết bằng TypeScript.

git clone https://github.com/aws-samples/containers-blog-maelstrom

cd containers-blog-maelstrom/aws-cdk-eks-multi-region-skeleton/

npm install

Định nghĩa Amazon EKS cluster được lưu trữ trong lib / cluster-stack.ts . Sau đây là đoạn mã:

const cluster = new eks.Cluster(this, 'demoeks--cluster', {

        clusterName: `demoeks`,

        mastersRole: clusterAdmin,

        version: eks.KubernetesVersion.V1_21,

        defaultCapacity: 2,

        defaultCapacityInstance: new ec2.InstanceType(props.onDemandInstanceType)

    });

Như được định nghĩa trong bin/multi-cluster-ts.ts , mã tạo ra hai cụm và triển khai cơ sở hạ tầng hỗ trợ, tích hợp liên tục và stack phân phối / triển khai liên tục (CI / CD) (CodePipeline, CodeBuildCodeCommit), các cụm Amazon EKS  và một ứng dụng web mẫu.

Bạn có thể tùy chỉnh tệp multi-cluster-ts.ts để thay đổi khu vực và loại phiên bản dựa trên yêu cầu của bạn.

const primaryRegion = {account: account, region: 'us-east-2'};

const secondaryRegion = {account: account, region: 'eu-west-2'};

const primaryOnDemandInstanceType = 'r5.2xlarge';

const secondaryOnDemandInstanceType = 'm5.2xlarge';
Bootstrap AWS Regions

Bước đầu tiên để triển khai CDK là khởi động môi trường. cdk bootstrap là một công cụ trong giao diện dòng lệnh AWS CDK (AWS CLI) chịu trách nhiệm chuẩn bị môi trường (nghĩa là kết hợp tài khoản AWS và AWS Region) với các tài nguyên mà CDK yêu cầu để thực hiện triển khai vào môi trường đó. Nếu bạn đã sử dụng CDK trong một khu vực, bạn không cần phải lặp lại quy trình khởi động.

Thực thi các lệnh bên dưới để khởi động môi trường AWS ở  us-east-2 và eu-west-2

cdk bootstrap aws://$ACCOUNT_ID/$AWS_PRIMARY_REGION

cdk bootstrap aws://$ACCOUNT_ID/$AWS_SECONDARY_REGION

CDK  tạo ra năm stacks:

  • Một cluster-stack tạo ra một cụm Amazon EKS cho khu vực chính us-east-2
  • Một container-stack triển khai các bộ chứa nginx mẫu cho cụm Amazon EKScho khu vực chính us-east-2
  • Một cluster-stack tạo ra một cụm Amazon EKS cho khu vực phụ eu-west-2
  • container-stack triển khai các bộ chứa nginx mẫu tới cụm Amazon EKS hoặc khu vực phụ eu-west-2
  • Một cicd-stack tạo ra một đường dẫn cicd sử dụng  AWS CodePipelineAWS CodeSuites để chứa và triển khai ứng dụng bình mẫu đi qua các region của Amazon EKS.

Chạy cdk list để xem danh sách các stacks sẽ được tạo:

$ cdk list
ClusterStack-us-east-2
ClusterStack-eu-west-2
ContainerStack-us-east-2
ContainerStack-eu-west-2
CicdStack

Bạn có thể sử dụng cdk diff để nhận danh sách resources mà CDK sẽ tạo:

cdk diff

Nếu kết quả không khớp với đầu ra bên dưới, hãy tham khảo bước này và kiểm tra xem đồng hồ chạy npm có đang chạy trong nền hay không.

Bạn sẽ thấy kết quả sau:

Stack ClusterStack-ap-southeast-2IAM Statement Changes
┌───┬────────────────────────┬────────┬────────────────────────┬────────────────────────┬───────────┐

│   │ Resource               │ Effect │ Action                 │ Principal              │ Condition │

├───┼────────────────────────┼────────┼────────────────────────┼────────────────────────┼───────────┤

│ + │ ${AdminRole.Arn}       │ Allow  │ sts\:AssumeRole        │ AWS\:arn:${AWS::Partiti│           │

│   │                        │        │                        │ on}\:iam::<<ACCOUNT_ID>│           │

│   │                        │        │                        │ root                   │           │

...

...

Resources

[+] AWS::IAM::Role AdminRole AdminRole38563C57 

[+] AWS::EC2::VPC demogo-cluster/DefaultVpc demogoclusterDefaultVpc0F0EA8D6 

[+] AWS::EC2::Subnet demogo-cluster/DefaultVpc/PublicSubnet1/Subnet demogoclusterDefaultVpcPublicSubnet1Subnet9B5D84CC 

[+] AWS::EC2::RouteTable demogo-cluster/DefaultVpc/PublicSubnet1/RouteTable demogoclusterDefaultVpcPublicSubnet1RouteTableA9719167 

[+] AWS::EC2::SubnetRouteTableAssociation demogo-cluster/DefaultVpc/PublicSubnet1/RouteTableAssociation demogoclusterDefaultVpcPublicSubnet1RouteTableAssociationF6BCC682 

[+] AWS::EC2::Route demogo-cluster/DefaultVpc/PublicSubnet1/DefaultRoute demogoclusterDefaultVpcPublicSubnet1DefaultRoute0A0FDBF1 

[+] AWS::EC2::EIP demogo-cluster/DefaultVpc/PublicSubnet1/EIP demogoclusterDefaultVpcPublicSubnet1EIP42D57092 

[+] AWS::EC2::NatGateway demogo-cluster/DefaultVpc/PublicSubnet1/NATGateway

Mã hỗ trợ tùy chỉnh theo khu vực cụ thể. Nó tìm kiếm các tệp triển khai Kubernetes trong các thư mục dành riêng cho khu vực. Mã mẫu chứa các thư mục cho các region chính và phụ (được gọi là  yaml-us-east-2yaml-eu-west-2). CDK sẽ áp dụng các tệp triển khai trong các thư mục này để triển khai ứng dụng Kubernetes ở hai khu vực.

Nếu các khu vực của bạn khác nhau, vui lòng tạo các thư mục theo cách thủ công và sao chép tệp kê khai triển khai Kubernetes trong mỗi thư mục:

# mkdir yaml-<region-name> for primary and secondary regions
mkdir yaml-$AWS_PRIMARY_REGION
mkdir yaml-$AWS_SECONDARY_REGION

cp yaml-us-east-2/00_ap_nginx.yaml yaml-$AWS_PRIMARY_REGION/
cp yaml-us-east-2/00_ap_nginx.yaml yaml-$AWS_SECONDARY_REGION/
Tạo các cụm

Nếu bạn đang làm theo hướng dẫn sử dụng AWS Regions khác với các AWS Regions được sử dụng trong bài đăng, vui lòng cập nhật các giá trị của region chính và phụ trong bin/multi-cluster-ts.ts trước khi tiếp tục.

Lệnh con cdk deploy triển khai stack(s) được chỉ định vào tài khoản AWS của bạn. Hãy triển khai tất cả năm stacks:

cdk deploy "*"

Sau khi hoàn thành, bạn có thể kiểm tra pipeline  trong CodePipeline Console. Chưa có nhánh chính nào trong CodeCommit, do đó pipeline  sẽ ở trạng thái không thành công.

CDK tạo các tài nguyên sau:

  • Amazon EKS phân cụm ở hai khu vực và cơ sở hạ tầng được yêu cầu bao gồm VPC, 3 mạng con công cộng và riêng tư, Internet Gateways, Network Address Translation (NAT) Gateways.
  • Phiên bản Amazon EKS: r5.2xlarge, mv5.2xlarge
  • CI / CD Pipeline để triển khai ứng dụng mẫu cho các cụm Amazon EKS ở us-east-2 và eu-west-2
  • Amazon EKS Repository trong cả hai để lưu trữ hình ảnh vùng chứa ứng dụng mẫu
  • Một Kubernetes namespac trong mỗi cụm
Triển khai ứng dụng mẫu cho nhiều khu vực

Điều hướng đến ứng dụng mẫu trong kho sao chép và đăng ký kho lưu trữ CodeCommit đã tạo trong dự án ứng dụng bằng các lệnh sau:

mkdir ../../sample-app

cp -R ../aws-cdk-multi-region-sample-app ../../sample-app

cd ../../sample-app/aws-cdk-multi-region-sample-app

EKS_CDK_CODECOMMIT_REPO=$(aws codecommit list-repositories --region $AWS_PRIMARY_REGION --query "repositories[?starts_with(repositoryName,'hello-py')].repositoryName" --output text)

EKS_CDK_CODECOMMIT_REPO_URL=$(aws codecommit get-repository --region $AWS_PRIMARY_REGION  --repository-name $EKS_CDK_CODECOMMIT_REPO --query'repositoryMetadata.cloneUrlHttp' --output text)

git init

git remote add codecommit $EKS_CDK_CODECOMMIT_REPO_URL

Trước khi kiểm tra mã vào kho lưu trữ CodeCommit, chúng ta phải định cấu hình ứng dụng khách Git với thông tin đăng nhập CodeCommit. Bước này yêu cầu sử dụng AWS Management Console.

Điều hướng đến bảng điều khiển AWS Identity & Access Management (IAM) User và tạo thông tin đăng nhập HTTPS Git cho AWS CodeCommit cho người dùng IAM mà thiết bị đầu cuối của bạn hiện được định cấu hình để sử dụng. Để biết thêm thông tin, vui lòng tham khảo tài liệu AWS:

Đẩy mã trong thư mục vào CodeCommit bằng lệnh sau:

git add .

git commit -am "initial commit"

git push codecommit master

Nếu đây là lần đầu tiên bạn sử dụng CodeCommit, bạn sẽ được nhắc nhập usernamepassword để đẩy mã vào kho lưu trữ CodeCommit Git. Bạn có thể sử dụng thông tin đăng nhập CodeCommit đã tải xuống ở bước trước.

Sau khi bạn đẩy đến kho lưu trữ, bạn có thể thấy trong bảng điều khiển CodePipeline rằng đường dẫn được kích hoạt như sau:

Sau khi pipeline  triển khai ứng dụng mẫu cho cụm Amazon EKS trong khu vực chính, nó sẽ đợi xem xét thủ công trước khi tiếp tục. Hãy kiểm tra tình trạng triển khai trong cụm chính. Định cấu hình kubectl của bạn để sử dụng cụm chính của bạn:

CLUSTER1_KUBECONFIG_COMMAND=$(aws cloudformation describe-stacks \

  --stack-name "ClusterStack-$AWS_PRIMARY_REGION" \

  --region $AWS_PRIMARY_REGION \

  --query 'Stacks[0].Outputs[?starts_with(OutputKey,`demoeksclusterConfig`)].OutputValue' \

  --output text)

$(echo $CLUSTER1_KUBECONFIG_COMMAND)

Xem các dịch vụ đang chạy:

kubectl get svc

Hãy chuẩn bị dịch vụ hello-py:

curl $(kubectl get service hello-py -o \

  jsonpath='{.status.loadBalancer.ingress[*].hostname}') && echo ""

Dịch vụ phản hồi bằng một thông báo Hello World từ <AWS Region> cho yêu cầu curl. Vì dịch vụ hoạt động trong region chính, việc triển khai này được coi là thành công. Do đó, pipeline  có thể tiến hành triển khai ứng dụng vào region chính.

Trước khi chúng tôi tiếp tục quy trình, hãy xác minh rằng dịch vụ hello-py không tồn tại ở khu vực phụ.

Đặt ngữ cảnh hiện tại của kubectl’s của bạn thành cụm Amazon EKS trong region phụ:

CLUSTER2_KUBECONFIG_COMMAND=$(aws cloudformation describe-stacks \

  --stack-name "ClusterStack-$AWS_SECONDARY_REGION" \

  --region $AWS_SECONDARY_REGION \

  --query 'Stacks[0].Outputs[?starts_with(OutputKey,`demoeksclusterConfig`)].OutputValue' \

  --output text)

$(echo $CLUSTER2_KUBECONFIG_COMMAND)

Xác minh rằng dịch vụ hello-py không chạy trong cụm phụ:

kubectl get service hello-py

Bạn sẽ gặp lỗi:

Error from server (NotFound): services "hello-py" not found

Bây giờ chúng tôi biết không có dịch vụ hello-py trong khu vực thứ cấp. Hãy quay lại CodePipeline và phê duyệt bước thủ công.

Quay lại AWS Management Console và chọn Review và chọn Approve trong lời nhắc tiếp theo. CodePipeline API PutApprovalResult có thể được sử dụng để tự động hóa quy trình phê duyệt này.

Khi pipeline  nhận được sự chấp thuận để triển khai cho khu vực thứ cấp, nó sẽ áp dụng tệp kê khai triển khai ( app-deployment.yaml ) cho cụm Amazon EKS thứ hai.

Khi quá trình kết thúc thành công, hãy kiểm tra xem dịch vụ hello-py có hoạt động không:

kubectl get service hello-py

Sau khi dịch vụ có bộ cân bằng tải ứng dụng (ALB) được đính kèm, sau đó gửi yêu cầu để xác minh rằng dịch vụ phản hồi bằng tên của region phụ trong phản hồi.

curl $(kubectl get service hello-py -o \

  jsonpath='{.status.loadBalancer.ingress[*].hostname}') && echo ""

Điều này hoàn tất quá trình triển khai. Dịch vụ hello-py được triển khai và hoạt động ở cả hai khu vực.

Bản nâng cấp

Khi mã mới được đăng ký vào kho lưu trữ CodeCommit, đường ống sẽ tự động cố gắng tạo một triển khai mới. Khi các nhà khai thác xác minh các thay đổi thành công trong khu vực chính, họ có thể phê duyệt việc triển khai cho khu vực phụ.

Tệp lib / cluster-stack.ts chứa phần khai báo cài đặt cụm Amazon EKS của bạn. Bạn có thể sửa đổi nó để kiểm soát các thuộc tính của cụm và nâng cấp các cụm.

Khi bạn đưa các dịch vụ mới hơn vào các cụm này, bạn có thể sao chép CI/CD stack được tạo trong bài đăng này cho từng dịch vụ.

Dọn dẹp

Hãy xóa cơ sở hạ tầng bạn đã tạo ra để không chịu thêm chi phí. Sử dụng quy trình thủ công và các lệnh sau để dọn dẹp tài nguyên AWS đã tạo cho bài đăng này:

$(echo $CLUSTER1_KUBECONFIG_COMMAND)

kubectl delete svc hello-py

$(echo $CLUSTER2_KUBECONFIG_COMMAND)

kubectl delete svc hello-py

cd ../../containers-blog-maelstrom/aws-cdk-eks-multi-region-skeleton

AWS_ECR_REPO=$(aws ecr describe-repositories --query "repositories[].[repositoryName]" --region $AWS_PRIMARY_REGION | grep 'cicdstack-ecrforhellopy' | sed -e 's/^[[:space:]]*//' | sed -e 's/^"//' -e 's/"$//')

AWS_ECR_IMAGES_TO_DELETE=$(aws ecr list-images --region $AWS_PRIMARY_REGION --repository-name $AWS_ECR_REPO  --query 'imageIds[*]' --output json )

aws ecr batch-delete-image --region $AWS_PRIMARY_REGION --repository-name $AWS_ECR_REPO --image-ids "$AWS_ECR_IMAGES_TO_DELETE" || true

cdk destroy "*"

CDK sẽ hỏi bạn

Are you sure you want to delete: CicdStack, ContainerStack-<primary region>, ContainerStack-<secondary region>, ClusterStack-<primary region>, ClusterStack<secondary region> (y/n)?

và nhập y để xóa.

Kết luận

Bài đăng này đã trình bày quy trình tạo quy trình triển khai liên tục để triển khai các ứng dụng trong nhiều cụm Amazon EKS chạy ở các khu vực khác nhau. Mã CDK đi kèm tạo ra các cụm EKS và CI/CD stack để liên tục triển khai ứng dụng cho các cụm.

CDK giúp bạn xác định cơ sở hạ tầng đám mây, tài nguyên Kubernetes và ứng dụng của mình trong cùng một cơ sở mã. Nếu cơ sở mã của bạn bằng ngôn ngữ mà CDK hỗ trợ, thì các ứng dụng, cấu hình và cơ sở hạ tầng cơ bản của bạn có thể được mã hóa bằng cùng một ngôn ngữ. Nếu bạn phải tạo bảng kê khai Kubernetes bằng mã, bạn cũng có thể sử dụng cdk8s để xác định tài nguyên Kubernetes theo chương trình.

Bước tiếp theo, bạn cũng có thể khám phá EKS Blueprints, là một tập hợp các mô-đun IaC, để giúp bạn định cấu hình và triển khai các cụm Amazon EKS nhất quán và bao gồm pin trên các tài khoản và Khu vực. Bạn có thể sử dụng EKS Blueprints để dễ dàng khởi động cụm Amazon EKS với các Amazon EKS add-ons. Một loạt các tiện ích bổ sung nguồn mở phổ biến, bao gồm Prometheus, Karpenter, Nginx, Traefik, AWS Load Balancer Controller, Fluentbit, Keda, Argo CD, v.v.

Bài đăng này cũng có sẵn dưới dạng workshop sử dụng CDK v1. Bạn có thể tìm thấy những thay đổi giữa AWS CDK v1 và v2 tại đây.


Bài được dịch từ bài viết trên AWS Blogs, bạn có thể xem bài viết gốc tại đây.

Leave a comment