'docker'에 해당하는 글 11건

ECS Task

Server/AWS 2018. 8. 17. 22:16

Image 를 푸시하고 Cluster 를 생성하면 Image 를 구동할 수 있는 것처럼 얘기했지만, 해야 할 것이 하나 더 있다.


Docker 저장소의 Image 는 ECS 에서 사용하기 위해 Task 라는 작업에 정의해야 한다. 이 task 정의에는 실행할 이미지, 컨테이너 사양, 포트 등을 설정할 수 있으며, 이러한 Task 정의로부터 특정 ECS Cluster 를 선택하여 실행시킬 수 있다. Image 는 여러 Task 정의에서 가져다 쓸 수 있으며 Task 정의 역시 여러 Cluster 에서 실행시킬 수 있다.


이번에는 Task 정의를 생성하여 사용할 Image 를 설정해 보겠다.



1. 아키텍처 설계


컨테이너 서비스인 ECS 를 사용하여 어플리케이션을 운영한다는 것은 아키텍처 면에서 기존 방식과 조금씩 차이가 있을 수 있다. (이건 각자 알아서 ㅜ) 하나의 이미지를 여러 인스턴스에서 실행할 것인지 하나의 인스턴스에 여러 이미지를 실행할 것인지 등을 생각해 보아야 한다. 일단 하나의 Docker 이미지로 웹 서버 2대를 사용한다고 했을 때 필요한 것은,


web Image:1 -> web Task 정의:1 -> web Cluster (EC2:2)


이렇게 구성하면 될 것이다. 2 대의 인스턴스를 로드 밸런서에 묶기 위해 Cluster 에 Service 라는 것도 추가해야 하지만 일단 생략했다. 공통 모듈을이나 구성 요소에 따라, 하나의 task 정의에 여러 컨테이너(Image) 를 정의할 수도 있을 것이고... 일단 가장 심플하게 가보자.



2. Task 정의 생성


먼저 콘솔의 ECS - Task Definitions - [Create new Task Definition] 을 선택한다. ECR 에서도 잠시 거론했지만, Task 정의도 가장 먼저 선택하는 것이 시작 유형이다. Fargate / EC2 인스턴스 시작 유형 중 하나를 가장 먼저 선택하게 되고, 선택한 시작유형에 따라 미세하게 설정에 차이는 있다. Network 모드나 Port 설정 등... ECS Document 에 보면 Task 정의를 Dockerfile 처럼 json 파일로 정의할 수 있게 만들어놨는데, 그걸 먼저 보면 토나온다. 설정하는 것은 몇개 안되는데 모든 항목들이 다 나와 있어서 매우 복잡해 보이지만, 콘솔 대신 json 파일로 작업해야 한다면 콘솔에서 제공하는 json 형태의 스크립트에서 설정할 항목만 뽑아서 가져다 쓰면 된다. EC2 인스턴스 시작 유형을 선택했다면 이것저것 설정할 항목이 많아 보이는데, 대부분 Default 로 두면 되고 설정할 것은 몇 개 안된다.


- Task 정의 이름

- Add container : 사용할 Image 의 Repository URI, 이 컨테이너에 할당할 메모리/CPU, Port 매핑


메모리와 CPU 는 사용할 인스턴스 사양과 추가할 컨테이너들을 고려하여 설정한다. 이게 끝이다. ㅋㅋ 컨테이너 Image 나 메모리/CPU, 포트 매핑 등을 수정하기 위해 task 를 업데이트 하면 새로운 리비전이 추가된다. 아마도 운영중에는 크게 수정할 일이 없을 것이다.



3. Task 실행


구동을 확인해 보고 싶다면, Task 정의 리스트에서 Task 정의를 선택하고 [Run Task] 를 클릭하여 실행할 Cluster 를 선택하고 Number of tasks 수를 입력하면 끝. 혹은 Cluster - Tasks 에서 [Run new Task] 를 선택해도 결과는 동일하다. Number of tasks 수를 2 로 지정하면 두 개의 인스턴스에서 Task 가 독립적으로 실행될 것이다. Cluster 에 지정된 인스턴스 수가 한 개라면 한 개의 Task 만 실행된다. Task 가 실행되고 나면 PENDING 상태에 돌입하고 수초내에 정상적인 인스턴스에서 실행되고 있다는 뜻의 RUNNING 상태가 된다. Cluster 에 등록된 인스턴스에서 Task 정의의 Image 를 실행시킬 것이고, Public DNS 를 통해 Image 구동을 확인할 수 있다. Task 를 Stop 시키면 인스턴스에의 task 도 곧 중지된다. 개발 중에는 이렇게 로드 밸런서를 통하지 않고 Task 정의를 클러스터에 다이렉트로 실행시켜서 바로 Image 를 확인할 수 있다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

AWS ECR

Server/AWS 2018. 8. 15. 00:33

ECS 를 시작하기 전에 가장 먼저 어플리케이션을 이미지로 만들어 ECR(Elastic Container Registry) 에 등록을 해 보자. ECR 에 이미지를 등록하는 것은 ECS 와 연계되는 부분이 거의 없으므로 ECS 를 몰라도 상관없다. 이미지 등록에만 집중하자.

 

ECS 를 몰라도 상관없다고 말했지만, 꼭 집고 넘어가야 할게 있다. ㅜ ECS 를 사용할 때 사용자가 선택할 수 있는 두 가지 선택지가 있다. 하나는 인스턴스로서 EC2 를 사용할지 Fargate 를 사용할지이고 (이를 시작 유형이라고 함), 또 하나는 Docker Registry 를 공개용(public) 으로 구성할지 비공개용(private) 으로 구성할지 이다. Fargate 라는 것은 컨테이너를 위한 EC2 등의 인스턴스를 필요로 하지 않고 컨테이너 자체를 배포하는 아마존의 기술이다. 지금은 몰라도 된다. 하지만 알고 싶다면... EC2 에서 돌아가던 것이 EC2 없이도 어디선가 돌아간다 라고 생각하면 쉽다; 그만큼 EC2 등의 인스턴스를 관리하는 노력이 줄어드니까 더 좋다고도 볼 수 있다. EC2 를 컨트롤 하는 것 처럼 정밀한 제어는 힘들겠지만. 아무튼 좋아보이니 비싸기도 하다. EC2 시작 유형을 사용해보면 Fargate 설정은 훨씬 더 쉬우므로 EC2 시작 유형 기반으로 설명할 것이다. 아마도 대부분이 실전에서는 private 저장소를 사용하게 될텐데, 혹시라도 public 저장소를 사용하게 되면 EC2 인스턴스 유형을 사용할 수 없다. 즉 EC2 인스턴스 유형은 private 저장소만 지원한다. 이를 유념하도록 하고... ECS 에서 Docker Registry 는 ECR 말고도 아마 거의 다 지원할 것이다. Docker Hub, self-hosted registry 등...

 

여기서는 아마존 패밀리인 ECR 을 사용해 보도록 하겠다.

 

 

1. Docker 이미지 생성

 

docker 이미지를 생성하려면 Docker 를 설치하고 데몬을 실행시켜 docker cli 를 사용할 수 있어야 한다. (여기까지는 알아서 잘 해보자 ㅜ)

그리고 이미지 설정 파일인 dockerfile 을 만들어 필요에 맞게 구성한다.

나는 다음과 같이 tomcat 에서 구동하는 war 파일에 ssl 통신이 가능하도록 이미지화 하는 dockerfile 을 만들었다. (이것도 본인 필요에 맞게 알아서 잘 해보자;)

 

$ vi dockerfile
FROM tomcat:8.0-jre8-alpine
RUN ["rm""-rf""/usr/local/tomcat/webapps/ROOT"]
COPY ["./keystore""./server.xml""./web.xml""/usr/local/tomcat/conf/"]
COPY ./build/libs/WEB-0.0.1-SNAPSHOT.war /usr/local/tomcat/webapps/ROOT.war
cs

 

dockerfile 기반으로 hello-world 라는 이미지를 생성하고 확인한다.

 

$ docker build -t hello-world .
$ docker images --filter reference=hello-world
$ docker run -p 8080:8080 hello-world
cs

 

해당 포트의 반응이 없을 경우, 서버나 VirtualBox VM 에서 컨테이너 포트에 인바운드 트래픽이 허용되어 있는지 체크한다. 

 

 

2. ECR 에 저장소 생성

 

이미지가 정상적으로 생성되었다면, AWS Docker Registry 인 ECR 에 푸시를 해보자.

그 전에 ECR 에 이미지를 푸시하기 위해서는 AWS cli 가 반드시 필요하다. 로그인 및 푸시 명령이 AWS cli 으로만 가능하다. 알아서 cli 를 설치한다. ㅜ

먼저 콘솔이나 cli 로 ECR 에 특정 이름의 저장소를 생성한다.

cli 를 사용할 때는 root 계정을 사용하지 말고 ECS 용 IAM 계정을 새로 생성하고 profile 에 등록하는 편이 낫다. 해당 key 로 profile 에 자격증명 및 리전 등록하는 것은 생략.

 

$ aws ecr create-repository --repository-name hello-world-repo
{
    "repository": {
        "registryId": "aws_account_id",
        "repositoryName": "hello-world-repo",
        "repositoryArn": "arn:aws:ecr:us-east-1:aws_account_id:repository/hello-world-repo",
        "createdAt": 1505337806.0,
        "repositoryUri": "aws_account_id.dkr.ecr.us-east-1.amazonaws.com/hello-world-repo"
    }
}
cs

 

콘솔을 이용하던 cli 를 이용하던 저장소를 생성하고 나면 이미지를 푸시할 주소인 repositoryUri 를 확인할 수 있다.

repositoryUri 에는 12 자리 숫자의 aws_account_id, 리전, 저장소 이름이 포함되어 있다.

 

 

3. ECR 로 이미지 푸시

 

저장소를 생성했으면 이미지를 푸시하면 되는데, 그러기 위해서는 푸시할 이미지를 repositoryUri 값으로 태그 지정해야 한다.

 

$ docker tag hello-world aws_account_id.dkr.ecr.us-east-1.amazonaws.com/hello-world-repo
cs

 

태그 지정을 마쳤으면 푸시를 하기 전에 ECR 에 로그인 과정을 거쳐야 한다.(참 번거롭다.ㅜ)

 

$ aws ecr get-login --no-include-email

// aws cli v2+
$ aws ecr get-login-password --region xxxx (--profile xxx) | docker login --username AWS --password-stdin xxx(accountId).dkr.ecr.xxx(region).amazonaws.com
cs

 

위 명령을 입력하면 로그인에 필요한 명령어를 포함한 12시간 짜리 토큰이 발급된다.

 

docker login -u AWS -p ...base64 encoding token...very...long...  https://aws_account_id.dkr.ecr.us-east-1.amazonaws.com
cs

 

이와 같은 형태인데 이 부분을 그대로 복붙했다가는 프로세스 목록(ps) 에 토큰이 다 노출되게 되므로 패스워드 옵션(-p) 전까지만 입력하고 대화형 방식으로 토큰을 입력하던지 eval 명령을 사용한다.

 

$ eval $(aws ecr get-login --no-include-email)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
cs

 

마지막으로 repositoryUri 태그가 달린 이미지를 푸시한다.

 

$ docker push aws_account_id.dkr.ecr.us-east-1.amazonaws.com/hello-world
cs

 

ECS - Repositories 에서 푸시된 이미지 확인.

 

 

나중에 어떤 식으로든 자동화를 해야겠지만 일단 이렇게 번거로운 과정을 거치면 비로소 ECR 에 이미지를 푸시할 수 있게 된다. 수정된 이미지를 다시 푸시할 경우에 토큰이 만료됐다면 위 로그인 과정을 다시 거쳐야 한다.

그럭저럭 쓸만함...

 

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Amazon ECS

Server/AWS 2018. 8. 13. 19:50

Amazon Elastic Container Service(ECS) 는 클러스터에서 도커 컨테이너를 손쉽게 실행, 중지 및 관리할 수 있게 해주는 컨테이너 관리 서비스이다.

도커 이미지로 Auto scaling, LB, EC2 등과 통합하여 서비스 하고자 할 때 좋은 선택이 될 수 있으며, 무중단 배포가 간편하다는 가장 큰 장점이 있다.





위 그림은 ECS 의 전반적인 아키텍처를 나타낸 것이다.

요점은 배포할 어플리케이션을 이미지 저장소로부터 가져와서 원하는 수 만큼의 인스턴스(EC2 등) 에 배포한다는 것이다.

Docker 의 Cluster, Stack, Service, Task 등과 거의 같은 기능들을 하지만, 비슷하면서도 다르다... ㅡ.ㅡ;


다시 어플리케이션을 ECS 를 통화 배포하는 세분화된 단계를 보자면,


1. 배포할 어플리케이션을 docker 이미지로 생성한다.

2. 해당 이미지를 어디서든 가져올 수 있도록 docker 레지스트리(ECR, docker hub 등) 에 등록한다.


여기까지는 주로 docker 에 관련된 내용이다. docker 레지스트리는 docker 이미지를 버전관리 할 수 있으며, 버전관리 측면에서 github 와 비슷한 기능을 한다.


3. ECS 의 최상위 리소스인 cluster 를 생성한다. 이 때 VPC 설정으로 네트워크의 영역을 정의하며, 사용할 인스턴스 타입/사양 등을 선택한다.

4. 가장 중요한 task 정의를 생성한다. 이 정의에는 사용할 이미지, 포트, 컨테이너 사양 등을 정의한다.

5. 특정 cluster 에서 task 를 효율적으로 관리할 service 를 생성한다. 이 service 구성에는 실행할 task 정의, 실행할 인스턴스 수, LB, Auto Scaling 등을 설정할 수 있다.


여기까지는 일반적으로 EC2 를 생성할 때 구성했었던 VPC, Subnet, Secure group, Key-pair, LB, Auto scaling 과 ECS 를 구성하는 Cluster, Service, Task 등을 설정했다. Cluster - Service - Task 의 상관 관계가 조금 복잡해 보일 수 있는데,


하나의 Cluster 에는 하나 이상의 Service 를 생성할 수 있으며, 생성된 Service 는 해당 Cluster 에서만 사용된다.

하나의 Service 에는 하나의 task 및 인스턴스 수를 관리할 수 있다.

생성된 Task 정의는 하나 이상의 Cluster 또는 하나 이상의 Service 에서 실행될 수 있다.


ECS 의 완성은 Cluster 에서 Task 정의를 실행하는 것이다. 이것이 곧 배포이다. task 정의는 Service 없이도 Cluster 에서 직접 실행 시킬 수 있지만, Service 를 생성하므로써 더 효율적으로 task 를 관리할 수 있다. LB, Auto scaling, 순차 배포 등. 많은 사용자들이 도커 이미지로 Auto scaling, LB, EC2 등과 통합하여 무중단 배포로 서비스 하기 위해 이 ECS 를 선택하게 될 것이다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Jenkins vs ECS

Server/AWS 2018. 8. 12. 02:40



Jenkins 가 지속적 통합(CI), 즉 빌드/테스트 및 배포 자동화 도구라고 할 때, ECS 는 Docker 컨테이너를 실행 및 관리하는 AWS 서비스라고 할 수 있다. 이 설명만으로 볼 때 이 둘이 비교가 가능한건지... 비교할 수는 없겠지만 단지 배포 자동화를 중점으로 간략하게 비교해 보고자 한다. 전 세계에서 대부분의 개발자들이 필요로 하고 사용하는 전문적인 서비스들이지만, 나에겐 그저 자동화라는 가면을 쓴 골치아픈 녀석들 일 뿐.


Jenkins 는 배포가 빠르고 간편하다. 소스 저장소에 push 하거나, 목록에서 배포할 서버를 찾아 버튼을 클릭하는 것 만으로 배포를 완료할 수 있다. 사실 서버도 적고 Release 후에 유지보수가 거의 필요없다면 굳이 이런 CI 툴 등은 필요하지 않을 것이다. 공부하고 설치하고 세팅하고 테스트하고 관리비용 내고... 근데 정작 배포할 일은 거의 없고... 그렇다면 그냥 FTP 로 올리는게 여러가지로 맘이 편할지 모른다. 난 처음 Jenkins 를 설치하고 서버별로 각종 세팅을 하는데에 적지 않은 시간을 할애하면서, 이게 자동화인가... 라는 생각을 했다. 다 만들어놨을 때나 자동화지, 자동화를 위해 흘려야 할 피, 땀, 눈물이... 힘들었다. ㅋㅋ 하지만 이렇게 CI 툴을 하나 익혀놓으면 다른 비슷한 툴들도 쉽게 접근할 수 있다. 방식은 거의가 똑같다.


Jenkins 의 단점을 세가지 정도로 쥐어 짜봤다.


  • 하나는 오토 스케일링. 오토 스케일링이 필요하지 않는 서버라면 상관없겠지만... 늘어난 서버를 수대로, 또 수동으로 세팅해 줘야 한다는건 오토 스케일링이 필요한 사람들에게는 꽤나 번거로운 문제.
  • 또 하나는 복원. 나는 주로 태그로 복원하는 편인데, 롤백할 때마다 설정에 태그 붙였다 뗏다 하는 것도 번거로움. (쥐어짠 티가 남;)
  • 마지막으로 무중단 배포. 이건, 글쎄... 불가능 한건 아니지만 수동적인 무중단 배포(?) 라고 설명하면 되려나.


그렇다면 ECS 가 Jenkins 의 이러한 단점들을 극복해 줄 수 있을까. ECS 는 결론만 말하자면 가능하다. 간단하게 오토 스케일링 및 관리가 가능하고, 이전 버전으로의 복구는 가능은 하지만 그닥 편하다고는 볼 수 없다. 그리고 무중단 배포도 가능하다. 서버 수를 원하는대로 늘였다 줄였다 무중단 연속 배포하는... 이 정도면 배포에 있어서는 거의 완벽하다고 볼 수 있다. 


하지만 안타깝게도 ECS 도 단점이 있다. 기능상의 단점이 아닌 사용자의 능력에 따른 자동화라고 해야 하나. ECS 배포 자동화를 위해 알아야 할 것들이 꽤 많은 편이다. 어느 정도 AWS 나 배포 바닥(?) 을 모르는 초보자라면 이것 저것 시간을 꽤 할애해야 한다. Jenkins 는 사실 Jenkins 만 설치하고 약간의 메뉴얼만 보면 쉽게 따라할 수 있다. ECS 는 Docker 기반이다보니 최소 배포할 이미지는 만들 줄 알아야 한다. 또 이미지 저장소인 ECR 에 이미지를 올리기 위해서는 AWS-Cli 를 사용해야만 한다. 그리고 ECS 를 공부해야 한다. cluster-service-task 를 숙지하고 업데이트/복구 배포 전략을 세워야 한다. 쓰고 보니 크게 공부를 하지 않아도 될 거 같은...; Jenkins 는 구성을 크게 달리할 여지가 별로 없고 인터넷만 조금 뒤져보면 원하는 답을 금방 얻을 수 있지만, ECS 는 운용에 있어 아직 사례들이 부족한 편이라 사용자들이 각자의 환경에 맞게 충분히 헤딩을 해보면서 준비해야 한다. 예를 들자면 이미지 업로드를 어떻게 자동화 할 것인지, 이미지가 업데이트 되었을 때 배포는 어떻게 자동화 시킬 것인지 등이다.



정리하자면 이렇다.


무중단배포, 오토 스케일링이 필요 없다면 그냥 알아서... 해당 사항 없음.

서버 수가 변동될 일이 별로 없고, 업데이트가 잦고, 무중단배포(수동) 가 필요하면 Jenkisn.

지금의 Jenkins 운용에 만족한다면 그냥 Jenkins.

서버 수가 급변하고, 업데이트가 잦고, 무중단배포(자동) 이 필요하다면 ECS.

AWS 에 친숙하고 자동 배포의 끝판왕을 만들고 싶다면 ECS. (얼마나 완벽한 자동화를 만드느냐는 사용자의 몫...)




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

docker 설치 후 docker info 를 확인하자 마자 보이는 경고.


WARNING: No swap limit support


에러를 안나타나게 하려면, 시스템에서 cgroup 에 메모리와 스왑 메모리 관리를 사용할 수 있게 하면 된다.

메모리와 스왑 메모리를 사용 가능하게 하면 Docker 를 사용하지 않을 때도 메모리 오버헤드(약 1%), 성능 저하(약 10%)를 유발한다.

GNU GRUB(GRand Unified Bootloader)을 수정하여 cgroup 에 메모리와 스왑메모리를 가능하게 할 수 있다.


# vi /etc/default/grub

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"


변경된 GRUB 을 적용하고 재부팅한다.


# update-grub

Generating grub configuration file ...

Found linux image: /boot/vmlinuz-3.13.0-74-generic

Found initrd image: /boot/initrd.img-3.13.0-74-generic

done


# shutdown -r now



여기까지가 문서에 있는 얘기고...

현재 커널이 cgroup swap 메모리 제한을 하고 있지 않다는 것인데.

이것을 가능하게 세팅하고 나면 성능 저하가 생긴다는게 말인가 방구인가.

Docker 를 위해서 시스템의 성능을 저하시킨하는게 말인가 방구인가.

Docker 돌리는데는 이러나 저러나 지장은 없지만 이게 무슨 말인지 정말 궁금하긴 하다.

이것때매 cgroup 까지 찾아보기는 좀...ㅜ



WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,