개발 중에는 Java + Gradle 프로젝트에서 결과물을 확인하기 위해, ssh 플러그인을 사용해 개발 서버에 배포하고 있다. 실서버 ECS 배포를 위해 이미지를 만들고 ECR 에 푸시하고 Task 를 배포하는 플러그인이 있나 열심히 검색해 보았으나, 음... 생각만큼 지원이 덜 되어 있는거 같아 그냥 AWS Cli 명령으로 도배했다. 난 포기했지만 생각 있으면 써보시길...
'com.bmuschko.docker-remote-api'
'com.patdouble.awsecr'
build.gradle 로 처리하려는 것들을 나열해 봤다.
- 인스턴스 수량 증가
- Docker 이미지 빌드
- 기존 ECR latest 이미지 태그 변경 -> backup
- 이미지 ECR 로 푸시
- 서비스 업데이트 (배포)
- 인스턴스 수량 감소
이 모든걸 원클릭으로 끝내버리고 싶었는데, 배포 완료 시점을 알아야 했고 그로 인한 서브 작업들이 꼴도 보기 싫어서 그만 두었다. (꽤 지긋지긋해졌다) 저 얼마되지도 않는 작업을 실행하는데 필요한 오라질 도구가 참 많다. Docker, AWS Cli, ECS-Cli, PowerShell, ... 물론 Linux 환경이라면 PowerShell 하나 정도는 줄일 수 있겠지만 그러자고 Linux 환경을 하나 더 구축하는 것 역시 오라질이다. 그리고 ECR 이미지 태그를 변경하는 것 역시 포기했다. PowerShell 에서 AWSPowerShell 을 설치해야 되는데 에러 투성이다. 포기하고 backup 은 push 를 두 번 하는 방향으로; AWS Cli 로 통합하지 못하고 AWS Cli, ECS-Cli, PowerShell 을 다 깔 수 밖에 없게끔 만들어 놓은 이유가 참으로 궁금하다. docker 가 PowerShell 을 사용한 원죄가 있긴 하지만... 그렇게 따지면 윈도우를 만든... ㅡ.ㅡ;
아무튼 내가 구축하려는 구성은 기본 인스턴스 2 대, 배포시 4 대, 배포후 다시 2 대.
Cluster, Service, Task, ECR 등은 이미 콘솔에 생성되어 있다. (구성 내용 생략)
그리하여 실행할 gradle Task 는 3 개 정도 되겠다.
1,2,3,4 번을 묶어 backup 이 어찌될지 모르니 푸시까지 하나 (createImageNpushToECR), 5 번 배포 하나(ECSDeploy), 6 번 인스턴스 감소 하나(ECSInstanceDown).
* build.gradle
ext { clusterName = 'clusterName' serviceName = 'serviceName' taskName = 'taskName' stackName = 'EC2ContainerService-now-web' accountId = '8707500123456' region = 'ap-northeast-1' tagName = '870750012345.dkr.ecr.ap-northeast-1.amazonaws.com/web:latest' instanceMinCnt = 2 instanceMaxCnt = 4 getInstanceCnt = 0 } task createImageNpushToECR() { group = 'docker' dependsOn war doFirst { exec { commandLine 'cmd', '/c', 'aws ecr get-login --no-include-email --profile profileName > temp.cmd' } exec { commandLine 'cmd', '/c', 'call temp.cmd' } exec { commandLine 'cmd', '/c', 'del temp.cmd' } } doLast { exec { commandLine 'cmd', '/c', 'docker build -t '+tags+' .' } exec { commandLine 'docker', 'push', tags } } } task ECSDeploy { group = 'docker' doLast { exec { commandLine 'cmd', '/c', 'aws ecs update-service --force-new-deployment --profile profileName --cluster ' + clusterName + ' --service ' + serviceName + ' --task-definition ' + taskName } } } task ECSInstanceCnt { group = 'docker' doLast { new ByteArrayOutputStream().withStream { cnt -> exec { commandLine 'cmd', '/c', 'aws ecs list-container-instances --cluster ' + clusterName + ' | findstr /R /C:"[' + accountId + ']" | find /c /v ""' standardOutput = cnt } getInstanceCnt = cnt.toString().toInteger() } println '# Current Web Instance Cnt : ' + getInstanceCnt } } task ECSInstanceUp { group = 'docker' dependsOn ECSInstanceCnt doLast { if (instanceMaxCnt > getInstanceCnt) { exec { commandLine 'cmd', '/c', 'aws ecs update-service --cluster ' + clusterName + ' --service ' + serviceName + ' --deployment-configuration minimumHealthyPercent=50,maximumPercent=200' } exec { commandLine 'cmd', '/c', 'ecs-cli configure --cluster ' + clusterName + ' --default-launch-type EC2 --region ' + region + ' --cfn-stack-name ' + stackName + ' --config-name ' + clusterName } exec { commandLine 'cmd', '/c', 'ecs-cli scale --capability-iam --size ' + instanceMaxCnt + ' --cluster ' + clusterName + ' --aws-profile profileName' } } } } task ECSInstanceDown { group = 'docker' dependsOn ECSInstanceCnt doLast { if (instanceMinCnt < getInstanceCnt) { exec { commandLine 'cmd', '/c', 'aws ecs update-service --cluster ' + clusterName + ' --service ' + serviceName + ' --deployment-configuration minimumHealthyPercent=100,maximumPercent=200' } exec { commandLine 'cmd', '/c', 'ecs-cli configure --cluster ' + clusterName + ' --default-launch-type EC2 --region ' + region + ' --cfn-stack-name ' + stackName + ' --config-name ' + clusterName } exec { commandLine 'cmd', '/c', 'ecs-cli scale --capability-iam --size ' + instanceMinCnt + ' --cluster ' + clusterName + ' --aws-profile profileName' } } } } | cs |
대충 이렇다. 지금 딱 필요한 만큼만 꾸역꾸역 만들어 놓긴 했는데... 맘엔 안들지만 그래도 그냥 쓸란다.
간단하게 설명하자면...
- createImageNpushToECR : war 파일 만들고 ECR 에 로그인 후 Docker 이미지 만들고 푸시.
- ECSDeploy : Service 업데이트로 최신 이미지(latest) 배포
- ECSInstanceCnt : 현재 Cluster 의 인스턴스 수량 (2개 설정)
- ECSInstanceUp : 인스턴스 증가시킬 수량인 4 개 보다 작으면 4 개로 증설
- ECSInstanceDown : 인스턴스 감소시킬 수량인 2 개 보다 크면 2 개로 감소
ECR 로그인은 gradle 소스에 있고 ECS-Cli 자격 증명 역시 aws profile 로 통합했다. AWS Cli 를 위한 자격 증명은 잘 등록해 보자... aws configure...
명령어도 윈도우 명령어로 바꿔 넣느라 삽질 좀 했다. 후...
개발에만 집중할 수 있게 해준다더니, 빡이쳐서 개발을 할 수가 없다. 아오...
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.