使用 Github + CodeBuild + CodePipeline 使用 Terraform 构建 Fargate 部署流程
目录
我叫寺冈,是一名基础设施工程师。
这次我们将讨论将应用程序部署到 Fargate。
尽管它们有时被称为“代码兄弟”,但
AWS 有多种服务在部署到各种服务时非常有用。
使用 CodeBuild 和 CodePipeline
部署到 Fargate
Terraform 版本是“v0.12.24”。
使用它作为参考时请小心。
这次我们建造了什么
看起来像下面这样。
VPC具有Public、DMZ和Private的三层结构,其中
ALB和NatGateway位于Public子网中,
Fargate任务在DMZ子网中启动并链接到ALB目标组。
让我们仔细看看 CodeBuild 和 CodePipeline,它们是部署管道的核心。
一个简单的图表如下所示。
流程非常简单
- 使用WebHook与Github协作,检测向Git推送事件并自动执行CodePipeline
- 从Github获取源代码,使用CodeBuild构建Docker镜像,并推送到ECR
- 从 Fargate 拉取推送到 ECR 的镜像并启动新任务
- 将启动的任务注册到ALB目标组
- 排除最初与目标组链接的旧任务
- 删除旧任务
就变成了。
执行部署时,新旧 Fargate 任务会交换。
现在让我们看一下 Terraform 代码。
目录结构
$ 树 ├── alb.tf ├── buildspec.yml ├── codebuild.tf ├── codepipeline.tf ├── docker │ ├── nginx │ │ ├── Dockerfile │ │ └── conf │ ├── default.conf │ │ └── nginx.conf │ └── 站点 │ └── index.html ├── docker-compose.yml ├── fargate.tf ├── github.tf ├── iam .f _assume_role.json │ └─ ─ fargate_task_execution_policy.json ├── s3.tf ├── 秘密 │ └── github_personal_access_token ├── securitygroup.tf ├── ssm.tf ├── 任务 │ └── container_definitions.json ├── terraform.tfstate ├── ─ terraform.tfstate.backup ├── Variables.tf └── vpc.tf 7个目录,28个文件
提供者和变量
我们来编写Terraform的Provider和Variable。
提供商.tf
提供者“aws”{access_key = var.access_key Secret_key = var.secret_key区域=var.region Should_role {role_arn = var.role_arn}}提供者“github”{token = aws_ssm_parameter.github_personal_access_token.value组织=“Teraoka-Org”}
变量.tf
#################### # 提供程序 ###################### 变量 "access_key" { 描述 = " AWS 访问密钥" } 变量 "secret_key" { 描述 = "AWS 密钥" } 变量 "role_arn" { 描述 = "AWS Role Arn" } 变量 "region" { 默认 = "ap-northeast-1" }
专有网络
创建专有网络。
vpc.tf
#################### # VPC #################### 资源 "aws_vpc" "vpc" { cidr_block =“10.0.0.0/16”enable_dns_support = trueenable_dns_hostnames = true标签={名称=“vpc-fargate-deploy”}}#######################子网 #################### 资源 "aws_subnet" "public_1a" { vpc_id = aws_vpc.vpc.idavailability_zone = "${var.region}a" cidr_block = " 10.0.10.0/24" map_public_ip_on_launch = true 标签 = { Name = "subnet-fargate-deploy-public-1a" } } 资源 "aws_subnet" "public_1c" { vpc_id = aws_vpc.vpc.idavailability_zone = "${var.region }c" cidr_block = "10.0.11.0/24" map_public_ip_on_launch = true 标签 = { Name = "subnet-fargate-deploy-public-1c" } } 资源 "aws_subnet" "dmz_1a" { vpc_id = aws_vpc.vpc.idavailability_zone = "${var.region}a" cidr_block = "10.0.20.0/24" map_public_ip_on_launch = true 标签 = { Name = "subnet-fargate-deploy-dmz-1a" } } 资源 "aws_subnet" "dmz_1c" { vpc_id = aws_vpc .vpc.idavailability_zone =“${var.region}c”cidr_block =“10.0.21.0/24”map_public_ip_on_launch = true标签={名称=“subnet-fargate-deploy-dmz-1c”}}资源“aws_subnet”“ private_1a" { vpc_id = aws_vpc.vpc.idavailability_zone = "${var.region}a" cidr_block = "10.0.30.0/24" map_public_ip_on_launch = true 标签 = { Name = "subnet-fargate-deploy-private-1a" } } 资源“aws_subnet”“private_1c”{ vpc_id = aws_vpc.vpc.idavailability_zone =“${var.region}c”cidr_block =“10.0.31.0/24”map_public_ip_on_launch = true标签={名称=“subnet-fargate-deploy” -private-1c" } } ################### # 路由表####################资源"aws_route_table" "public" { vpc_id = aws_vpc.vpc.id 标签 = { 名称 = "route-fargate-deploy-public" } } 资源 "aws_route_table" "dmz" { vpc_id = aws_vpc.vpc.id 标签 = { 名称 = "route-fargate-deploy-dmz" } } 资源 "aws_route_table" "private" { vpc_id = aws_vpc.vpc.id 标签 = { Name = "route-fargate-deploy-private" } } ####### # ############ # IGW ################### 资源 "aws_internet_gateway" "igw" { vpc_id = aws_vpc.vpc.id 标签 = { 名称 = "igw-fargate-deploy" } } ###################### # NATGW ############## ## ####资源“aws_eip”“natgw”{vpc = true标签={名称=“natgw-fargate-deploy”}}资源“aws_nat_gateway”“natgw”{allocation_id = aws_eip.natgw.idsubnet_id = aws_subnet。 id 标签 = { 名称 = "natgw-fargate-deploy" } dependent_on = [aws_internet_gateway.igw] } #################### # 路由 #### ## ##############资源“aws_route”“public”{route_table_id = aws_route_table.public.id target_cidr_block =“0.0.0.0/0”gateway_id = aws_internet_gateway.igw.iddepends_on = [aws_route_table.公共] }资源“aws_route”“dmz”{route_table_id = aws_route_table.dmz.id target_cidr_block =“0.0.0.0/0”nat_gateway_id = aws_nat_gateway.natgw.id dependent_on = [aws_route_table.dmz] } ###### ## ############ # 路由关联 ################### 资源 "aws_route_table_association" "public_1a" {subnet_id = aws_subnet.public_1a .id route_table_id = aws_route_table.public.id}资源“aws_route_table_association”“public_1c”{subnet_id = aws_subnet.public_1c.idroute_table_id = aws_route_table.public.id}资源“aws_route_table_association”“dmz_1a”{subnet_id = aws_subnet.dmz_1a.idroute_table_id = aws_route _表.dmz .id}资源“aws_route_table_association”“dmz_1c”{subnet_id = aws_subnet.dmz_1c.idroute_table_id = aws_route_table.dmz.id}资源“aws_route_table_association”“private_1a”{subnet_id = aws_subnet.private_1a。 id } 资源“aws_route_table_association”“private_1c”{subnet_id = aws_subnet.private_1c.idroute_table_id = aws_route_table.private.id }
安全组
创建安全组。
安全组.tf
#################### # 安全组 ###################### 资源 "aws_security_group" "alb" { 名称 = "alb-sg" 描述 = "对于 ALB" vpc_id = aws_vpc.vpc.id } 资源 "aws_security_group" "fargate" { 名称 = "fargate-sg" 描述 = "对于 Fargate" vpc_id = aws_vpc.vpc.id } ##################### # 安全组规则 ##################### 资源 "aws_security_group_rule " "allow_http_for_alb" { security_group_id = aws_security_group.alb.id type = "ingress" 协议 = "tcp" from_port = 80 to_port = 80 cidr_blocks = ["0.0.0.0/0"] 描述 = "allow_http_for_alb" } 资源 "aws_security_group_rule" " From_ALB_TO_FARGATE "{Security_Group_id = Aws_Security_group.fargate.id Type = "入口"协议 = "TCP"from_PORT = 80 t = 80 source_security_Group_id = aws_security_Group.alb.id 描述 = "from_ALB_TO_FARGATE"} RESOURCE_RUP_RU Le "" Egress_alb "{Security_Group_id = Aws_Security_Group 。 alb.id 类型 = "egress" 协议 = "-1" from_port = 0 to_port = 0 cidr_blocks = ["0.0.0.0/0"] 描述 = "出站全部" } 资源 "aws_security_group_rule" "egress_fargate" { security_group_id = aws_security_group . fargate.id 类型 = "出口" 协议 = "-1" from_port = 0 to_port = 0 cidr_blocks = ["0.0.0.0/0"] 描述 = "出站全部" }
白蛋白
创建 ALB。
白蛋白.tf
#################### # ALB #################### 资源 "aws_lb" "alb" {名称 = "alb-fargate-deploy" 内部 = false load_balancer_type = "应用程序" security_groups = [ aws_security_group.alb.id ] 子网 = [ aws_subnet.public_1a.id, aws_subnet.public_1c.id ] } ######## ############ # 目标组 ################### 资源 "aws_lb_target_group" "alb" { name = "fargate-deploy- tg ” 端口 = “80” 协议 = “HTTP” target_type = “ip” vpc_id = aws_vpc.vpc.id deregistration_delay = “60” health_check { 间隔 = “10” 路径 = “/” 端口 = “流量端口” 协议 = “ HTTP" timeout = "4"healthy_threshold = "2" unhealthy_threshold = "10" matcher = "200-302" } } #################### # 侦听器 # # ################## 资源 "aws_lb_listener" "alb" { load_balancer_arn = aws_lb.alb.arn 端口 = "80" 协议 = "HTTP" default_action { 类型 = "forward " target_group_arn = aws_lb_target_group.alb.arn } }
准备 Docker 容器
在开始构建 Fargate 之前,为要部署的容器创建 Dockerfile。
我们提前手动将任务推送到ECR来确认它已经开始了。
Dockerfile
从 nginx:alpine 复制 ./docker/nginx/conf/default.conf /etc/nginx/conf.d/ 添加 ./docker/nginx/conf/nginx.conf /etc/nginx/ 复制 ./docker/sites/index .html /var/www/html/ 公开 80
默认配置文件
服务器 { 监听 80 server_name localhost;
nginx.conf
用户nginx; pid /run/nginx.pid; error_log /dev/stdout 事件{worker_connections 1024 } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $ body_bytes_sent "$http_referer" ' '"$http_user_agent"'; sendfile 打开; 包括 /etc/nginx/mime.types; /etc/nginx/conf.d/*.conf; open_file_cache 关闭;
索引.html
<html><body><p>terraform-fargate-部署</p></body></html>
docker-compose.yml
版本:“3”服务:nginx:构建:上下文:dockerfile:./docker/nginx/Dockerfile 图像:fargate-deploy-nginx 端口:-“80:80”
我是
准备要与 Fargate 上基于代码的服务一起使用的 IAM 角色。
iam.tf
#################### # IAM 角色 #################### 资源 "aws_iam_role" "fargate_task_execution" { name = "role-fargate-task-execution" Should_role_policy = file("./roles/fargate_task_assume_role.json") } 资源 "aws_iam_role" "codebuild_service_role" { name = "role-codebuild-service-role" Should_role_policy = file( "./roles/codebuild_assume_role.json") } 资源 "aws_iam_role" "codepipeline_service_role" { name = "role-codepipeline-service-role" Should_role_policy = file("./roles/codepipeline_assume_role.json") } ##### ############### # IAM 角色策略 #################### 资源 "aws_iam_role_policy" "fargate_task_execution" { name = "执行策略" 角色 = aws_iam_role.fargate_task_execution.name 策略 = 文件("./roles/fargate_task_execution_policy.json") } 资源 "aws_iam_role_policy" "codebuild_service_role" { name = "build-policy" 角色 = aws_iam_role.codebuild_service_role.name 策略 =文件(“./roles/codebuild_build_policy.json”)}资源“aws_iam_role_policy”“codepipeline_service_role”{名称=“pipeline-policy”角色=aws_iam_role.codepipeline_service_role.name策略=文件(“./roles/codepipeline_pipeline_policy.json”)}
codebuild_assume_role.json
{ "版本": "2012-10-17", "声明": [ { "效果": "允许", "主体": { "服务": "codebuild.amazonaws.com" }, "操作": " sts:AssumeRole" } ] }
codebuild_build_policy.json
{ "版本": "2012-10-17", "声明": [ { "操作": [ "ecr:BatchCheckLayerAvailability", "ecr:CompleteLayerUpload", "ecr:GetAuthorizationToken", "ecr:InitiateLayerUpload", "ecr:InitiateLayerUpload" :PutImage", "ecr:UploadLayerPart", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage" ], "资源": "*", "效果": "允许" }, { "效果": "允许", "资源": [ "*" ], "操作": [ "日志:CreateLogGroup", "日志:CreateLogStream", "日志:PutLogEvents" ] }, { "效果": "允许", "资源": [ "* " ], "操作": [ "s3:PutObject", "s3:GetObject", "s3:GetObjectVersion" ] }, { "效果": "允许", "操作": "ssm:GetParameters", "资源" : "*" }, { "效果": "允许", "操作": [ "ec2:CreateNetworkInterface", "ec2:DescribeDhcpOptions", "ec2:DescribeNetworkInterfaces", "ec2:DeleteNetworkInterface", "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", "ec2:DescribeVpcs", "ec2:CreateNetworkInterfacePermission" ], "资源": "*" } ] }
codepipeline_assume_role.json
{ "版本": "2012-10-17", "声明": [ { "效果": "允许", "主体": { "服务": "codepipeline.amazonaws.com" }, "操作": " sts:AssumeRole" } ] }
codepipeline_pipeline_policy.json
{ "语句": [ { "操作": [ "iam:PassRole" ], "资源": "*", "效果": "允许", "条件": { "StringEqualsIfExists": { "iam:PassedToService" : [ "cloudformation.amazonaws.com", "elasticbeanstalk.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com" ] } } }, { "操作": [ "codecommit:CancelUploadArchive ", "codecommit:GetBranch", "codecommit:GetCommit", "codecommit:GetUploadArchiveStatus", "codecommit:UploadArchive" ], "资源": "*", "效果": "允许" }, { "操作": [ “codedeploy:CreateDeployment”,“codedeploy:GetApplication”,“codedeploy:GetApplicationRevision”,“codedeploy:GetDeployment”,“codedeploy:GetDeploymentConfig”,“codedeploy:RegisterApplicationRevision”],“资源”:“*”,“效果”:“允许" }, { "操作": [ "elasticbeanstalk:*", "ec2:*", "elasticloadbalancing:*", "自动缩放:*", "cloudwatch:*", "s3:*", "sns:* ", "cloudformation:*", "rds:*", "sqs:*", "ecs:*" ], "资源": "*", "效果": "允许" }, { "操作": [ "lambda:InvokeFunction", "lambda:ListFunctions" ], "资源": "*", "效果": "允许" }, { "操作": [ "opsworks:CreateDeployment", "opsworks:DescribeApps", "opsworks :DescribeCommands", "opsworks:DescribeDeployments", "opsworks:DescribeInstances", "opsworks:DescribeStacks", "opsworks:UpdateApp", "opsworks:UpdateStack" ], "资源": "*", "效果": "允许" }, { "Action": [ "cloudformation:CreateStack", "cloudformation:DeleteStack", "cloudformation:DescribeStacks", "cloudformation:UpdateStack", "cloudformation:CreateChangeSet", "cloudformation:DeleteChangeSet", "cloudformation:DescribeChangeSet", "cloudformation:ExecuteChangeSet", "cloudformation:SetStackPolicy", "cloudformation:ValidateTemplate" ], "资源": "*", "效果": "允许" }, { "操作": [ "codebuild:BatchGetBuilds", "codebuild :StartBuild" ], "资源": "*", "效果": "允许" }, { "效果": "允许", "操作": [ "devicefarm:ListProjects", "devicefarm:ListDevicePools", "devicefarm :GetRun", "devicefarm:GetUpload", "devicefarm:CreateUpload", "devicefarm:ScheduleRun" ], "资源": "*" }, { "效果": "允许", "操作": [ "servicecatalog:ListProvisioningArtifacts ", "servicecatalog:CreateProvisioningArtifact", "servicecatalog:DescribeProvisioningArtifact", "servicecatalog:DeleteProvisioningArtifact", "servicecatalog:UpdateProduct" ], "资源": "*" }, { "效果": "允许", "操作": [ "cloudformation:ValidateTemplate" ], "资源": "*" }, { "效果": "允许", "操作": [ "ecr:DescribeImages" ], "资源": "*" } ], "版本" : "2012-10-17" }
fargate_task_assume_role.json
{ "版本": "2012-10-17", "声明": [ { "效果": "允许", "主体": { "服务": "ecs-tasks.amazonaws.com" }, "操作" : "sts:AssumeRole" } ] }
fargate_task_execution_policy.json
{ "版本": "2012-10-17", "声明": [ { "效果": "允许", "操作": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", “ecr:BatchGetImage”,“日志:CreateLogStream”,“日志:PutLogEvents”],“资源”:“*”}]}
法尔盖特
建造法盖特。
法盖特.tf
#################### # ECR ###################### 资源 "aws_ecr_repository" "nginx" { name = "fargate-deploy-nginx" } ###################### # 集群 ################## ## 资源 "aws_ecs_cluster" "cluster" { name = "cluster-fargate-deploy" 设置 { name = "containerInsights" value = "disabled" } } ################# ### # 任务定义################## 资源 "aws_ecs_task_definition" "task" { family = "task-fargate-nginx" container_definitions = file("tasks/ container_definitions .json") cpu = "256" 内存 = "512" network_mode = "awsvpc"execution_role_arn = aws_iam_role.fargate_task_execution.arn require_compatibility = [ "FARGATE" ] } ############### # #### # 服务 ################### 资源 "aws_ecs_service" "service" { name = "service-fargate-deploy" cluster = aws_ecs_cluster.cluster. = aws_ecs_task_definition.task.arndesired_count=1launch_type=“FARGATE”load_balancer{target_group_arn=aws_lb_target_group.alb.arncontainer_name=“nginx”container_port=“80”}network_configuration{子网=[aws_subnet.dmz_1a.id,aws_subnet.dmz_1c。 id] security_groups = [ aws_security_group.fargate.id ] allocate_public_ip = false } }
容器_定义.json
[ {“名称”:“nginx”,“图像”:“485076298277.dkr.ecr.ap-northeast-1.amazonaws.com/fargate-deploy-nginx:最新”,“基本”:true,“portMappings”: [ { “containerPort”: 80, “hostPort”: 80 } ] } ]
代码构建
构建代码构建。
代码构建.tf
资源“aws_codebuild_project”“项目”{名称=“project-fargate-deploy”描述=“project-fargate-deploy”service_role=aws_iam_role.codebuild_service_role.arn工件{类型=“NO_ARTIFACTS”}环境{compute_type =“BUILD_GENERAL1_SMALL”图像= “aws/codebuild/standard:2.0”类型=“LINUX_CONTAINER”image_pull_credentials_type=“CODEBUILD”privileged_mode=trueenvironment_variable {name=“AWS_DEFAULT_REGION”值=“ap-northeast-1”}environment_variable{name=“AWS_ACCOUNT_ID”值=“485076298277” " }environment_variable { name = "IMAGE_REPO_NAME_NGINX" value = "fargate-deploy-nginx" }environment_variable { name = "IMAGE_TAG" value = "latest" } } source { type = "GITHUB" location = "https://github.com /beyond-teraoka/fargate-deploy-test.git" git_clone_depth = 1 buildspec = "buildspec.yml" } vpc_config { vpc_id = aws_vpc.vpc.id 子网 = [ aws_subnet.dmz_1a.id, aws_subnet.dmz_1c.id ] security_group_ids = [ aws_security_group.fargate.id, ] } }
S3
创建一个 S3 存储桶来存储 CodePipeline 工件。
s3.tf
资源“aws_s3_bucket”“管道”{bucket =“s3-fargate-deploy”acl =“私有”}
SSM
当从 GitHub 存储库检索源代码时,
使用 Github 的个人访问令牌
由于它是机密信息,因此在 SSM 参数存储中进行管理。
ssm.tf
#################### # 参数 #################### 资源 "aws_ssm_parameter" "github_personal_access_token" {名称=“github-personal-access-token”描述=“github-personal-access-token”类型=“字符串”值=文件(“./secrets/github_personal_access_token”)}
value部分读取./secrets下文件的内容。
github_personal_access_token
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
代码管道
构建代码管道。
代码管道.tf
资源 "aws_codepipeline" "pipeline" { name = "pipeline-fargate-deploy" role_arn = aws_iam_role.codepipeline_service_role.arn artifact_store { location = aws_s3_bucket.pipeline.bucket type = "S3" } 阶段 { name = "Source" 操作 { name = “源”类别=“源”所有者=“第三方”提供商=“GitHub”版本=“1”output_artifacts = [“source_output”]配置= {所有者=“Teraoka-Org”Repo =“fargate-deploy-test”分支= "master" OAuthToken = aws_ssm_parameter.github_personal_access_token.value PollForSourceChanges = "false" } } } 阶段 { name = "Build" 操作 { name = "Build" 类别 = "Build" 所有者 = "AWS" 提供商 = "CodeBuild" input_artifacts = [“source_output”]output_artifacts = [“build_output”]版本=“1”配置={ProjectName = aws_codebuild_project.project.name}}}阶段{名称=“部署”操作{名称=“部署”类别=“部署”所有者= "AWS" 提供商 = "ECS" input_artifacts = ["build_output"] 版本 = "1" 配置 = { ClusterName = aws_ecs_cluster.cluster.arn ServiceName = aws_ecs_service.service.name FileName = "imagedef.json" } } } } 资源“aws_codepipeline_webhook”“webhook”{ name =“webhook-fargate-deploy”身份验证=“GITHUB_HMAC”target_action =“源”target_pipeline = aws_codepipeline.pipeline.nameauthentication_configuration {secret_token = aws_ssm_parameter.github_personal_access_token.value }过滤器{json_path =“$。 ref" match_equals = "refs/heads/{Branch}" } }
吉图布
将 WebHook 设置添加到 Github。
github.tf
资源“github_repository_webhook”“webhook”{存储库=“fargate-deploy-test”配置{url=aws_codepipeline_webhook.webhook.url content_type=“json”insecure_ssl=truesecret=aws_ssm_parameter.github_personal_access_token.value}事件=[“push”]}
构建规范
这就是您需要的所有文件。
要使用 CodeBuild 执行的构建处理类型写入 buildspec.yml 中。
这次,我将编写一个构建 Docker 镜像并将其推送到 ECR 的描述。
此外,该文件必须保存在 Git 存储库的根目录中。
构建规范.yml
--- 版本:0.2 阶段:pre_build:命令: - IMAGE_URI_NGINX=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME_NGINX - IMAGE_URI_PHPFPM=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO _NAME_PHPFPM - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION) 构建:命令: - docker-compose 构建 - docker tag fargate-deploy-nginx:$IMAGE_TAG $IMAGE_URI_NGINX post_build: 命令: - docker Push $IMAGE_URI_NGINX:$IMAGE_TAG - echo '[{"name":"nginx","imageUri":"__URI_NGINX__"}]' > imagedef.json - sed -ie "s@__URI_NGINX__@${IMAGE_URI_NGINX}:${IMAGE_TAG} @" imagedef.json 工件:文件:- imagedef.json
当你运行 Terraform 时?
创建必要的资源并使用浏览器访问 ALB 端点后,
将显示如下页面。
尝试运行部署
将index.html的内容重写为“terraform-fargate-deploy-test”并推送到Git。
然后,CodePipeline 将通过 WebHook 自动执行,如下所示。
我正在尝试从 GitHub 获取源代码。
完成后,CodeBuild 处理将开始。
它运行正常。
执行完成后,您可以确认Docker镜像已保存在ECR中,如下所示。
CodeBuild 完成运行后,将开始部署到 Fargate。
查看 Fargate 上的任务数量,数量增加了 1 个,总数达到了 2 个。
我们来看看目标群体的状况。
两项任务已链接,您正尝试删除较旧的任务。
断开连接后,再次尝试通过 ALB 访问。
已正确更新。
CodePipeline 也从头到尾顺利完成。
概括
你觉得怎么样?
在生产环境中使用容器(包括 Fargate)时,
考虑如何部署它们非常重要,这就是通常所说的 CI/CD。
这次,我尝试链接多个基于AWS Code的服务,
这是一个非常易于使用的服务,所以我鼓励大家都尝试一下。