在AWS ECS上目前有提供EC2 mode, Fargate, ECS Anywhere,分別為EC2執行Docker、Serverless方式去建立Container,以及雲地混合執行Container,主要會以前兩者去作深入探討
在EC2裡執行Container,並透過ECS agent來確認目前執行的Container狀態
由Cluster做instance的管理以及服務功能的調用,Task則可以定義Instance裡需要執行哪種Container以及數量,使用Cluster的Service指派哪個Instance去執行維護Task。主要以Cluster、Service和Task三者來建構出ECS這項服務,所以在撰寫CDK時,就會需要用到這三個相關的API。
cluster = ecs.Cluster(self, "Cluster", cluster_name="itdemo-cdk", vpc=vpc,
capacity=ecs.AddCapacityOptions(
can_containers_access_instance_role=True,
instance_type=ec2.InstanceType("t3.micro"),
desired_capacity=1,
machine_image_type=ecs.MachineImageType.AMAZON_LINUX_2,
key_name="itdemo",
block_devices=[block]))
vpc:預設是跨兩個AZ,兩個public & subnet。這邊VPC筆者採用新建立而非預設。
capacity:在ECS的cluster底下註冊有安裝ECS agent和Docker agent的EC2配置。
block_devices:配置EC2的硬碟空間
vpc = ec2.Vpc(self, "vpc",
cidr="10.10.0.0/16",
enable_dns_hostnames=True,
enable_dns_support=True,
max_azs=1,
nat_gateways=0,
subnet_configuration=[
ec2.SubnetConfiguration(name="public1",
subnet_type=ec2.SubnetType.PUBLIC,
cidr_mask=24)
])
block = auto.BlockDevice(device_name="/dev/xvda",
volume=auto.BlockDeviceVolume.ebs(volume_size=30,volume_type=auto.EbsDeviceVolumeType.GP3), mapping_enabled=True)
vpc:建立一個public subnet
block:這裡調用的library跟Day14/15,所用的不太一樣,因為會把EC2註冊到autoscaling group(ASG),會使用到autoscaling這個library,所以需要安裝以及import。其他參數都跟前兩天的雷同
volume_size:這邊最低限制需要填30GB,否則在deploy的時侯會出現error
cluster.connections.allow_from_any_ipv4(ec2.Port.all_traffic())
task1 = ecs.TaskDefinition(self, "task-cdk",
network_mode=ecs.NetworkMode.BRIDGE,
compatibility=ecs.Compatibility.EC2,
cpu="256",
memory_mib="512")
network_mode:這邊採用Bridge的方式,透過EC2的網路來訪問Container
compatibility:ECS EC2 mode
cpu:1vcpu = 1024。256 = 0.25vcpu
memory_mib:512MB
task1.add_container("Application",
memory_limit_mib=128,
# image=ecs.ContainerImage.from_registry("httpd:2.4"),
image=ecs.ContainerImage.from_registry("johnson860312/awswebdb")
# entry_point=["sh", "-c"],
# command=["/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\""],
).add_port_mappings(ecs.PortMapping(container_port=80,
host_port=80,
protocol=ecs.Protocol.TCP))
memory_limit_mib:限制最低的記憶體
image:選擇想要的Container image,這裡將Day4 build好的Container image push到自己的Docker hub中,所以這邊使用同一個Container image
add_port_mappings這邊採用的網路模式是Bridge可以透過EC2的port mapping到Container的port。可以透過EC2 public DNS/IP access Container,如下:
http://<EC2-DNS/IP>:
ecs.Ec2Service(self, "Service",
cluster=cluster,
task_definition=task1,
desired_count=1,
service_name="SVC-CDK",
)
desired_count:執行task的數量
在撰寫CDK的同時,可以熟悉ECS上面的細節以及地雷,更加了解AWS的服務
from aws_cdk import core as cdk
from aws_cdk import (
aws_ec2 as ec2,
aws_ecs as ecs,
aws_autoscaling as auto,
core
)
class EcsTestStack(cdk.Stack):
def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# The code that defines your stack goes here
vpc = ec2.Vpc(self, "vpc",
cidr="10.10.0.0/16",
enable_dns_hostnames=True,
enable_dns_support=True,
max_azs=1,
nat_gateways=0,
subnet_configuration=[
ec2.SubnetConfiguration(name="public1",
subnet_type=ec2.SubnetType.PUBLIC,
cidr_mask=24)
])
block = auto.BlockDevice(device_name="/dev/xvda",
volume=auto.BlockDeviceVolume.ebs(volume_size=30, volume_type=auto.EbsDeviceVolumeType.GP3),
mapping_enabled=True)
cluster = ecs.Cluster(self, "Cluster", cluster_name="itdemo-cdk", vpc=vpc,
capacity=ecs.AddCapacityOptions(
can_containers_access_instance_role=True,
instance_type=ec2.InstanceType("t3.micro"),
desired_capacity=1,
machine_image_type=ecs.MachineImageType.AMAZON_LINUX_2,
key_name="itdemo",
block_devices=[block]))
cluster.connections.allow_from_any_ipv4(ec2.Port.all_traffic())
task1 = ecs.TaskDefinition(self, "task-cdk",
network_mode=ecs.NetworkMode.BRIDGE,
compatibility=ecs.Compatibility.EC2,
cpu="256",
memory_mib="512")
task1.add_container("Application",
memory_limit_mib=128,
# image=ecs.ContainerImage.from_registry("httpd:2.4"),
image=ecs.ContainerImage.from_registry("johnson860312/awswebdb")
# entry_point=["sh", "-c"],
# command=["/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\""],
).add_port_mappings(ecs.PortMapping(container_port=80,
host_port=80,
protocol=ecs.Protocol.TCP))
ecs.Ec2Service(self, "Service",
cluster=cluster,
task_definition=task1,
desired_count=1,
service_name="SVC-CDK",
)