AmazonECS/Fargate로 카나리아 배포 구현
15150 단어 FargateECSdocker-compose도커AWS
그러자, ECS/Fargate를 이용했을 때의 카나리아 배포의 수법이 의외로 화제가 되었기 때문에, 전회는 간단하게 소개해 버린 카나리아 배포를, 이번은 조금 목을 돌진해 소개하고 싶습니다.
전체 아키텍처
전체상은 이쪽입니다.
ECS/Fargate는 무엇입니까? 라고 하는 분이나, 아직 전 기사를 읽지 않은 분은 우선은 이쪽을 봐 주세요.
AmazonECS / Fargate 프로덕션 운영을 위한 구축 및 배포 방법 요약
카나리아 배포를 ECS로 실현
service내에서 task가 2대 움직이고 있는 상태로부터, 카나리아 배포를 해 33% 전달을 실현한다고 하는 예를 소개합니다.
또한 배포용 스크립트는 여기에서 공개하고 있습니다.
히로 무스다 / 에스에서 p ぉ y
1. 새 버전의 이미지를 build하고 push한다
버전을 식별하기 위해 타임 스탬프와 git 커밋 해시를 태그로 빌드 한 이미지에 ECR로 푸시합니다.
def push_latest_image
tag_timestamp = Time.now.strftime("%Y%m%d_%H%M")
tag_git_commit_hash = `git rev-parse HEAD`
tags = [tag_timestamp, tag_git_commit_hash]
puts "-----> Push latest image. Tag: #{tags.join(", ")}"
cmd_build = `docker build -t #{@ecr_name} #{@dockerfile_path}`
tags.each do |tag|
cmd = `
docker tag #{@ecr_name}:latest #{get_ecr_image_name(tag)}
docker push #{get_ecr_image_name(tag)}`
end
return get_ecr_image_name(tag_timestamp)
end
2. push한 이미지를 참조하는 TaskDefinition의 새로운 리비전을 작성합니다.
최신 TaskDefinition을 가져오고 ContainerDefinition에서 참조하는 이미지 버전을 새 버전으로 변경하고 개정을 업데이트합니다.
def update_task_definition(image_name)
puts "-----> Update task definition"
task_definition = get_latest_task_definition_description
container_definitions = task_definition["containerDefinitions"]
new_container_definitions = []
container_definitions.each do |container|
container["image"] = image_name if container["name"] == "#{@container_name}"
new_container_definitions << container
end
new_revision = `aws ecs register-task-definition \
--family #{@task} \
--task-role-arn #{task_definition["taskRoleArn"]} \
--execution-role-arn #{task_definition["executionRoleArn"]} \
--network-mode #{task_definition["networkMode"]} \
--volumes '#{task_definition["volumes"].to_json}' \
--cpu #{task_definition["cpu"]} \
--memory #{task_definition["memory"]} \
--requires-compatibilities #{task_definition["requiresCompatibilities"][0]} \
--container-definitions '#{new_container_definitions.to_json}'`
new_task_definition_arn = JSON.parse(new_revision)["taskDefinition"]["taskDefinitionArn"]
puts "-----> New task definition arn: #{new_task_definition_arn}"
return new_task_definition_arn
end
3. 작성한 TaskDefinition을 바탕으로 1대만 Task를 생성한다
2에서 만든 TaskDefinition을 기반으로 task를 새로 만듭니다. 이때 위 그림과 같이 service 밖으로 만듭니다. 그렇게 함으로써 위의 두 task는 이전 리비전의 TaskDefinition에서, 아래의 하나는 새로운 리비전의 TaskDefinition을 참조하게 됩니다. 또, 지금 작성한 task가 카나리아 배포에 의한 것이라고 판별이 되도록(듯이), started_by
라고 하는 스페이스에 태그를 추가합니다. 이 스크립트는 canary
라는 문자열을 지정합니다.
def run_task(task_definition, started_by_tag)
puts "-----> Run new task"
service_desc = get_service_description
conf = service_desc["networkConfiguration"]["awsvpcConfiguration"]
cmd = `aws ecs run-task \
--cluster #{@cluster} \
--task-definition #{task_definition} \
--network-configuration "awsvpcConfiguration={\
subnets=[#{conf["subnets"].join(",")}],\
securityGroups=[#{conf["securityGroups"].join(",")}],\
assignPublicIp="DISABLED"}" \
--launch-type FARGATE \
--started-by #{started_by_tag}`
return JSON.parse(cmd)
end
4. 생성된 Task의 PrivateIP를 로드 밸런서의 대상 그룹에 추가
먼저 방금 만든 task에서 privateIP를 가져옵니다. task 가 작성되고 나서 몇 초 하지 않으면 privateIP 가 생성되지 않기 때문에 , 취득할 때까지 루프를 돌리고 있습니다.
def canary_deploy
...
task_arn = new_task["tasks"][0]["taskArn"]
puts "-----> task ARN: #{task_arn}"
# take several seconds to get IP
while true
private_ip = get_task_private_ip(task_arn)
if !private_ip.nil?
puts "-----> private IP: #{private_ip}"
break
end
sleep(1)
end
add_task_to_target_group(private_ip)
...
end
그런 다음 얻은 privateIP를 ELB의 대상 그룹에 추가합니다. 이렇게 하면 요청이 카나리아 배포된 하나의 태스크에도 분산되어 흐릅니다.
def add_task_to_target_group(private_ip)
puts "-----> Add #{private_ip} to the target group"
cmd = `aws elbv2 register-targets \
--target-group-arn #{@target_group_arn} \
--targets Id=#{private_ip},Port=8000`
return cmd
end
이상과 같이 카나리아 배포를 실현했습니다.
요약
카나리아 배포를 스크립팅할 수 있어 배포로 인한 장애의 영향을 줄일 수 있습니다. 꼭 시도해보세요.
또, Twitter에서는 항상 기술계・근육 트레이닝계의 아웃풋을 하고 있으므로 꼭 팔로우해 주세요! 👉 htps : // 라고 해서 r. 코m/히로무_bdy
Reference
이 문제에 관하여(AmazonECS/Fargate로 카나리아 배포 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/HiromuMasuda0228/items/503408b396c6d94237ff
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
service내에서 task가 2대 움직이고 있는 상태로부터, 카나리아 배포를 해 33% 전달을 실현한다고 하는 예를 소개합니다.
또한 배포용 스크립트는 여기에서 공개하고 있습니다.
히로 무스다 / 에스에서 p ぉ y
1. 새 버전의 이미지를 build하고 push한다
버전을 식별하기 위해 타임 스탬프와 git 커밋 해시를 태그로 빌드 한 이미지에 ECR로 푸시합니다.
def push_latest_image
tag_timestamp = Time.now.strftime("%Y%m%d_%H%M")
tag_git_commit_hash = `git rev-parse HEAD`
tags = [tag_timestamp, tag_git_commit_hash]
puts "-----> Push latest image. Tag: #{tags.join(", ")}"
cmd_build = `docker build -t #{@ecr_name} #{@dockerfile_path}`
tags.each do |tag|
cmd = `
docker tag #{@ecr_name}:latest #{get_ecr_image_name(tag)}
docker push #{get_ecr_image_name(tag)}`
end
return get_ecr_image_name(tag_timestamp)
end
2. push한 이미지를 참조하는 TaskDefinition의 새로운 리비전을 작성합니다.
최신 TaskDefinition을 가져오고 ContainerDefinition에서 참조하는 이미지 버전을 새 버전으로 변경하고 개정을 업데이트합니다.
def update_task_definition(image_name)
puts "-----> Update task definition"
task_definition = get_latest_task_definition_description
container_definitions = task_definition["containerDefinitions"]
new_container_definitions = []
container_definitions.each do |container|
container["image"] = image_name if container["name"] == "#{@container_name}"
new_container_definitions << container
end
new_revision = `aws ecs register-task-definition \
--family #{@task} \
--task-role-arn #{task_definition["taskRoleArn"]} \
--execution-role-arn #{task_definition["executionRoleArn"]} \
--network-mode #{task_definition["networkMode"]} \
--volumes '#{task_definition["volumes"].to_json}' \
--cpu #{task_definition["cpu"]} \
--memory #{task_definition["memory"]} \
--requires-compatibilities #{task_definition["requiresCompatibilities"][0]} \
--container-definitions '#{new_container_definitions.to_json}'`
new_task_definition_arn = JSON.parse(new_revision)["taskDefinition"]["taskDefinitionArn"]
puts "-----> New task definition arn: #{new_task_definition_arn}"
return new_task_definition_arn
end
3. 작성한 TaskDefinition을 바탕으로 1대만 Task를 생성한다
2에서 만든 TaskDefinition을 기반으로 task를 새로 만듭니다. 이때 위 그림과 같이 service 밖으로 만듭니다. 그렇게 함으로써 위의 두 task는 이전 리비전의 TaskDefinition에서, 아래의 하나는 새로운 리비전의 TaskDefinition을 참조하게 됩니다. 또, 지금 작성한 task가 카나리아 배포에 의한 것이라고 판별이 되도록(듯이),
started_by
라고 하는 스페이스에 태그를 추가합니다. 이 스크립트는 canary
라는 문자열을 지정합니다.def run_task(task_definition, started_by_tag)
puts "-----> Run new task"
service_desc = get_service_description
conf = service_desc["networkConfiguration"]["awsvpcConfiguration"]
cmd = `aws ecs run-task \
--cluster #{@cluster} \
--task-definition #{task_definition} \
--network-configuration "awsvpcConfiguration={\
subnets=[#{conf["subnets"].join(",")}],\
securityGroups=[#{conf["securityGroups"].join(",")}],\
assignPublicIp="DISABLED"}" \
--launch-type FARGATE \
--started-by #{started_by_tag}`
return JSON.parse(cmd)
end
4. 생성된 Task의 PrivateIP를 로드 밸런서의 대상 그룹에 추가
먼저 방금 만든 task에서 privateIP를 가져옵니다. task 가 작성되고 나서 몇 초 하지 않으면 privateIP 가 생성되지 않기 때문에 , 취득할 때까지 루프를 돌리고 있습니다.
def canary_deploy
...
task_arn = new_task["tasks"][0]["taskArn"]
puts "-----> task ARN: #{task_arn}"
# take several seconds to get IP
while true
private_ip = get_task_private_ip(task_arn)
if !private_ip.nil?
puts "-----> private IP: #{private_ip}"
break
end
sleep(1)
end
add_task_to_target_group(private_ip)
...
end
그런 다음 얻은 privateIP를 ELB의 대상 그룹에 추가합니다. 이렇게 하면 요청이 카나리아 배포된 하나의 태스크에도 분산되어 흐릅니다.
def add_task_to_target_group(private_ip)
puts "-----> Add #{private_ip} to the target group"
cmd = `aws elbv2 register-targets \
--target-group-arn #{@target_group_arn} \
--targets Id=#{private_ip},Port=8000`
return cmd
end
이상과 같이 카나리아 배포를 실현했습니다.
요약
카나리아 배포를 스크립팅할 수 있어 배포로 인한 장애의 영향을 줄일 수 있습니다. 꼭 시도해보세요.
또, Twitter에서는 항상 기술계・근육 트레이닝계의 아웃풋을 하고 있으므로 꼭 팔로우해 주세요! 👉 htps : // 라고 해서 r. 코m/히로무_bdy
Reference
이 문제에 관하여(AmazonECS/Fargate로 카나리아 배포 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/HiromuMasuda0228/items/503408b396c6d94237ff
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(AmazonECS/Fargate로 카나리아 배포 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/HiromuMasuda0228/items/503408b396c6d94237ff텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)