AWS ECS使用EBS作为Volume

  在 基于Terraform在AWS ECS中构建Jenkins持续集成体系 一文中, Alliot 采用了 EFS 作为 Jenkins 容器的数据卷,直接挂载了 /var/jenkins_home 目录。
正如评论区提到的, 我们在使用 bursting 模式的 EFS 时,遇到了 IO 性能的问题, 虽然 master + slave 架构的 Jenkins 将构建任务分发到了 slave 节点,减少了 master 节点的压力,但是在启动构建任务时, master 节点依然会有大量的 IO 操作, 这个时候会导致 bursting 模式下的 EFS 瞬间打光 Credit 从而导致整个 master 挂掉。当然,我们可以使用 Provisoning 模式缓解性能问题,但其价格又非常贵,性价比不高。
  好在从今年(2024)的一月开始, AWS ECS 的 Fargate 支持使用 EBS 卷作为 Volume 了。 目前官网的文档还比较分散,这里小记一些需要注意的点。

前置条件

IAM role

  想要使用 EBS 作为 ECS 的数据卷,我们需要为 ECS task 提供一个 ECS infrastructure IAM role,这是一个比较新奇的东西,与前面我们用到的 ECS task execution IAM role 和 Task IAM role 都不同,在这里主要是用来允许 ECS 管理 EBS 的。
Console 和 CLI 配置这个 Role 的方法在前面官方文档已经写的很明白了,这里顺手贴一下 Terraform 创建的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
locals {
infrastructure_role = [
"AmazonECSInfrastructureRolePolicyForServiceConnectTransportLayerSecurity",
"AmazonECSInfrastructureRolePolicyForVolumes"
]
}

resource "aws_iam_role" "jenkins_service_infrastructure_role" {
name = "jenkins-service-infrastructure-role"

assume_role_policy = jsonencode({
"Statement" = [
{
"Action" = "sts:AssumeRole",
"Effect" = "Allow",
"Principal" = {
"Service" = "ecs.amazonaws.com"
},
"Sid" = "AllowAccessToECSForInfrastructureManagement"
}
],
"Version" = "2012-10-17"
})
force_detach_policies = false
path = "/"
tags = merge(
var.tags
)
}

resource "aws_iam_role_policy_attachment" "this" {
for_each = toset(local.infrastructure_role)
role = aws_iam_role.jenkins_service_infrastructure_role.name
policy_arn = format("arn:aws:iam::aws:policy/service-role/%s", each.key)
}

修改 Task-definition

在 Volume 配置中,”Configuration type” 需要修改为 “Configure at deployment”。

更新 ECS services

选择 “Update” services, 在 Volume 选项中我们可以看到 EBS 的配置,包括容量大小、IOPS、File System等,还可以指定从那个 Snapshot 来创建。
值得注意的是 “Infrastructure role” 务必选择前面我们创建的 role, 否则可能会在创建时出现权限问题。

局限

参考文档

Configuring Amazon EBS volumes at deployment - AWS