一,引言
上一篇文章記錄了利用 Azure DevOps 跨雲進行構建 Docker images,並且將構建好的 Docker Images 推送到 AWS 的 ECR 中。今天我們繼續講解 Azure DevOps 的 Pipeline,利用 Release Pipeline 實現 Terraform for AWS Infrastructure Resources 自動部署,我們的目標是將 images 部署到 AWS ECS 上。
-------------------- 我是分割線 --------------------
1,Azure DevOps(一)利用Azure DevOps Pipeline 構建應用程式映象到AWS ECR
2,Azure DevOps(二)利用Azure DevOps Pipeline 構建基礎設施資源
二,正文
1,Terraform Code
根據之前利用 Terrraform 部署Azure 資源的時候,我們都知道需要將各個資源模組劃分 Common Module。同樣的,我們當前需要部署的AWS的基礎設施資源也劃分出多個模組,例如,"ECS","Security Group",“ELB”,“IAM”,“VPC” 等
整個專案 mian.tf 的入口,該檔案中包含了各個模組巢狀呼叫等
當前TF Code 中以及整合了 CodeDeploy 的Common Module 可以實現ECS 的藍綠部署,大家下載 TF 程式碼後,可以自行魔改。
provider "aws" { region = "ap-northeast-1" } terraform { backend "s3" { region = "ap-northeast-1" profile = "default" } } locals { container_name = "cnbateblogweb" name = "cnbateblogwebCluster" service_name = "cnbateblogwebservice" http_port = ["80"] cidr_block = "10.255.0.0/16" container_port = tonumber(module.alb.alb_target_group_blue_port) } module "securitygroup" { source = "../modules/securitygroup" enabled_security_group = true security_group_name = "cnbateblogwebCluster_ecs_securitygroup" security_group_vpc_id = module.vpc.vpc_id from_port_ingress = 9021 to_port_ingress = 9021 from_port_egress = 0 to_port_egress = 0 } # module "codedeploy" { # source = "../modules/codedeploy" # name = "example-deploy" # ecs_cluster_name = local.name # ecs_service_name = local.service_name # lb_listener_arns = [module.alb.http_alb_listener_blue_arn] # blue_lb_target_group_name = module.alb.aws_lb_target_group_blue_name # green_lb_target_group_name = module.alb.aws_lb_target_group_green_name # auto_rollback_enabled = true # auto_rollback_events = ["DEPLOYMENT_FAILURE"] # action_on_timeout = "STOP_DEPLOYMENT" # wait_time_in_minutes = 1440 # termination_wait_time_in_minutes = 1440 # test_traffic_route_listener_arns = [] # iam_path = "/service-role/" # description = "This is example" # tags = { # Environment = "prod" # } # } module "ecs_fargate" { source = "../modules/ecs" name = local.name service_name = local.service_name container_name = local.container_name container_port = local.container_port subnets = module.vpc.public_subnet_ids security_groups = [module.securitygroup.security_group_id] target_group_arn = module.alb.alb_target_group_blue_arn vpc_id = module.vpc.vpc_id container_definitions = jsonencode([ { name = local.container_name image = "693275195242.dkr.ecr.ap-northeast-1.amazonaws.com/cnbateblogweb:28" #"693275195242.dkr.ecr.ap-northeast-1.amazonaws.com/cnbateblogweb:28" #"docker.io/yunqian44/cnbateblogweb:laster" essential = true environment = [ { name : "Location", value : "Singapore" }, { name : "ASPNETCORE_ENVIRONMENT", value : "Production" } ] portMappings = [ { containerPort = local.container_port protocol = "tcp" } ] } ]) desired_count = 1 deployment_maximum_percent = 200 deployment_minimum_healthy_percent = 100 deployment_controller_type = "ECS" assign_public_ip = true health_check_grace_period_seconds = 10 platform_version = "LATEST" cpu = 256 memory = 512 requires_compatibilities = ["FARGATE"] iam_path = "/service_role/" description = "This is example" enabled = true ecs_task_execution_role_arn = aws_iam_role.default.arn tags = { Environment = "prod" } } resource "aws_iam_role" "default" { name = "iam-rol-ecs-task-execution" assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json } data "aws_iam_policy_document" "assume_role_policy" { statement { actions = ["sts:AssumeRole"] principals { type = "Service" identifiers = ["ecs-tasks.amazonaws.com"] } } } data "aws_iam_policy" "ecs_task_execution" { arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } resource "aws_iam_policy" "ecs_task_execution" { name = aws_iam_role.default.name policy = data.aws_iam_policy.ecs_task_execution.policy } resource "aws_iam_role_policy_attachment" "ecs_task_execution" { role = aws_iam_role.default.name policy_arn = aws_iam_policy.ecs_task_execution.arn } module "alb" { source = "../modules/elb" name = "elb-cnbateblogweb" vpc_id = module.vpc.vpc_id subnets = module.vpc.public_subnet_ids enable_https_listener = false enable_http_listener = true enable_deletion_protection = false enabled_lb_target_group_blue = true aws_lb_target_group_blue_name = "elb-cnbateblogweb-blue" health_check_path = "" enabled_lb_target_group_green = true aws_lb_target_group_green_name = "elb-cnbateblogweb-green" enable_http_listener_blue = true http_port_blue = 80 target_group_blue_port = 9021 enable_http_listener_rule_blue = true enable_http_listener_green = true http_port_green = 8080 target_group_green_port = 8080 enable_http_listener_rule_green = true } module "vpc" { source = "../modules/vpc" cidr_block = local.cidr_block name = "ecs-fargate" public_subnet_cidr_blocks = [cidrsubnet(local.cidr_block, 2, 0), cidrsubnet(local.cidr_block, 2, 1)] public_availability_zones = data.aws_availability_zones.available.names } data "aws_caller_identity" "current" {} data "aws_availability_zones" "available" {}
具體的各個模組的Common Moudle 點選文章底部的 github 連結
2,Azure DevOps 設定 Release Pipeline
回到上一篇文章中建立好的 Azure DebOps 的專案中,docker images 的構築我們已經在CI 階段的 pipeline 中已經完成了。我們需要建立部署階段的 Release Pipeline
選擇 “CnBateBlogWeb_AWS” 的專案,選擇 “Release” 選單,點選 “New Pipeline”
選擇模板的時候,先點選 “Empty”
修改當前階段的名稱
Stage name:”Deploy AWS ECS“
下一步,我們就得先新增 ”Artifacts“(工件),也就是我們寫的 TF 程式碼
點選 ”+Add“,選擇 TF 程式碼源 ”GitHub“
Service:”Github_Connection44“
Source(repository):”yunqian44/AWS_ECS“(注意:大家選擇fork 到自己的github 倉庫名稱)
Default branch:“master”
Default version:“Latest from the default branch”
Source alias:“yunqian44_AWS_ECS”
點選 “Add”
點選 “1 job,0 task” 連結為部署階段新增新的任務
我們都知道,如果我們的基礎設施程式碼的開發是多人協助,並且是需要儲存狀態檔案,那麼我們就必須得先在執行Terraform 程式碼之前建立用於儲存 terraform 狀態檔案的S3,所以,我們得先新增 AWS CLI 來執行建立S3的動作。
點選圖中 "Agent job" 旁圈中的 “+”,並在 task 的搜尋框中輸入 “AWS CLI” ,點選 “Add” 進行新增
新增相關引數用於執行AWS CLI 命令建立S3
Display name:“AWS CLI:Create S3 for Saving terraform state file”
AWS Credentials 選擇之前手動加的 AWS 的 ServiceConnection
AWS Region:“Asia Pacific(Tokyo)[ap-northeast-1]”
Command:“s3”
Subcommand:“mb”
Options and parameters:“s3://$(terraform_statefile)” (注意:$(terraform_statefile) 是通過Pipleline Variable 來儲存引數的)
接下來新增 Terraform 依賴SDK 的 task,搜尋 “Terraform tool installer”,選擇新增當前任務
經過查詢,我們需要修改當前 Terraform 的版本
Version 版本改為:“0.15.5”
接下來新增 Terraform 初始化的Task
Task 搜尋框中搜尋 “Terraform”,點選 “Add”
修改相關引數:
Display name:“Terraform:aws init”
Provider 選擇:”aws“
Command:”init“
Configuration directory:選擇 Terraform 程式碼執行的目錄
AWS backend configuration
aws service connection 大家可以選擇建立一個新的
Bucket:”$(terraform_statefile)“ 已通過Pipeline Variable 進行設定了
Key:”$(terraform_statefile_key)“ 已通過Pipeline Variable 進行設定了
接下來新增 Terraform 生成部署計劃的Task
修改相關引數:
Display name:”Terraform:aws plan“
Provider 選擇:”aws“
Command 選擇:”plan“
Configuration directory: 選擇 terraform 程式碼的工作目錄
AWS Services connection 選擇剛剛新新增的 terraform 的後端服務連線
最後,我們新增執行 Terraform 部署計劃的 Task
Display name:”Terraform:aws auto-apply“
Provider:”aws“
Command:”validate and apply“
Configuration directory: 選擇 terraform 程式碼的工作目錄
Additional command arguments:”-auto-approve“
AWS Services connection 選擇剛剛新新增的 terraform 的後端服務連線
修改當前 Release Pipeline 的名稱,點選 ”Save“
關於pipeline 的觸發條件,我就不進行設定了,也不是今天演示的目的。
3,測試 Azure DevOps 自動化部署基礎設施資源
手動觸發 Pipeline,點選 ”Create release“ 進行手動觸發
點選 ”Create“
等待整個Pipeline 的執行完成,我們可以看到日誌整個的輸出,併成功進行部署
接下來,我們需要登陸到 AWS Console 檢視資源建立的狀況,ECS 執行成功
找到利用 Terraform 構築好的ELB,複製 dns 名進行訪問
Bingo!!!!! 成功。大功告成!!!!!
?????!!!!
三,結尾
今天的實際操作比較多,大多都是集中在Azure DevOps 上,我們都是需要在Azure DevOps 上進行操作的,大家要多加練習。至於 Terraform 程式碼方面沒有過多的講解,主要是因為結合之前部署Azure 資源,大家都會Terraform 有了一定的理解了。所以大家可以自行下載,進行分析修改。
參考資料:Terraform 官方,Terraform For AWS 文件,AWS CLI 文件
AWS_ECS github:https://github.com/yunqian44/AWS_ECS
文章來自博主本人自己的部落格:https://allenmasters.com/post/2021/6/8/azure-devopsazure-devops-pipeline
歡迎大家關注博主的部落格:https://allenmasters.com/
作者:Allen
版權:轉載請在文章明顯位置註明作者及出處。如發現錯誤,歡迎批評指正。