'Server/AWS'에 해당하는 글 49건

ECS logs / alarms

Server/AWS 2018. 8. 27. 22:57

ECS 를 사용하면 인스턴스에 docker / ecs / container 등에 대한 로그가 생성된다. CloudWatch Logs 로 로그 정보를 전송하면 컨테이너의 로그 용량 관리를 하지 않아도 된다. 인스턴스에서 CloudWatch Logs 에 로그 정보를 전송하도록 구성할 수도 있지만, 인스턴스 수 조정이 빈번하다면 해당 에이전트를 계속해서 설치하고 구성하는 것이 번거로울 수 있다. 이 경우에는 ECS 의 Task 정의에서 awslogs 로그 드라이버를 활성화하여 CloudWatch Logs 를 설정하는 방법이 있다.



Awslogs 설정


CloudWatch Logs 에 로그를 쌓기 위해서는 로그가 분류될 로그 그룹을 만들어야 한다. CloudWatch 콘솔이나 AWS CLI 를 사용하던지 간편하게 ECS 콘솔의 Task 정의에서 로그 그룹을 생성한다. [Task define] - [Container] - [Storage And Logging] - [Auto-configure CloudWatch Logs] 체크. 이렇게 awslogs 로그를 활성화 하면 해당 컨테이너의 로그 설정들이 자동으로 세팅되며, 추가로 옵션을 사용할 수 있다.



해당 Task 정의를 배포하고 나면 CloudWatch Logs 에서 해당 컨테이너의 로그들을 확인할 수 있다.




CPU / Memory 초과 알림


Amazon ECS 는 서비스의 평균 CPU 및 메모리 사용량과 함께 CloudWatch 지표(Metrics) 를 게시하며, 이 지표를 사용하여 알람을 추가할 수 있다. 우선 SNS(Simple Notification Service) 에 해당 알림 전용으로 메일 받을 Topic 을 하나 생성한다. [CloudWatch] - [Alarms] 에서 알람을 생성하고 ECS-Metrics 에서 CPU 나 Memory 의 상한선을 설정한 후, [Send notification to:] 에 알림 받을 Topic 을 선택하면 CPU 나 Memory 가 상한선을 초과할 경우 알림을 수신할 수 있다.




Task 중단시 메일 알림


Task 가 중단 됐을 때 알림을 받기 위해 CloudWatch 이벤트에 Rule 을 설정할 수도 있다.

[CloudWatch] - [Events] - [Rules] 에서 Rule 을 하나 생성하고, [Event Pattern Preview] 항목에 [Edit] 를 클릭하여 다음 코드를 입력한다.


{
   "source": [
     "aws.ecs"
  ],
  "detail-type": [
     "ECS Task State Change"
  ],
  "detail": {
    "clusterArn": [
      "arn:aws:ecs:ap-northeast-1:870750012345:cluster/api",
      "arn:aws:ecs:ap-northeast-1:870750012345:cluster/web"
    ],
  "lastStatus": [
      "STOPPED"
    ],
    "stoppedReason" : [
      "Essential container in task exited"
    ]
  }
}
cs


마찬가지로 알림을 받을 수 있도록 Rule 의 Target 에 생성해 놓은 Topic 을 연결한다.

이제 ECS 의 api/web 클러스터의 Task 상태가 essential 컨테이너로부터 중단되어 STOPPED 로 변경되면 알림을 수신할 수 있다.

stoppedReason 을 작성하지 않으면 Task 가 STOPPED 로 변경될 때마다 알림을 수신할 수 있으며, 위 중단 이유를 제외하고도 특정 stoppedReason 을 지정할 수 있다.





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

,

ECS Deployment strategy

Server/AWS 2018. 8. 27. 02:02

배포 자동화 스크립트를 만들기 전에 가장 궁금했던 것은 배포 전략(?) 이었다.

예를 들어 로드 밸런서에 인스턴스 2 대를 운영 중이라면, 3 가지 정도의 배포 방법을 생각할 수 있다.


  • 인스턴스를 2 대 이용할 경우, A 인스턴스를 중단하고 새로 배포 후, B 인스턴스를 중단하고 새로 배포하는 방법이 있을 수 있다.
  • 인스턴스를 2 대에서 2 대를 추가할 경우, C/D 인스턴스에 새로 배포 후, A/B 인스턴스를 중단하는 방법이 있을 수 있다.
  • 인스턴스를 2 대에서 1 대를 추가할 경우, C 인스턴스에 새로 배포 후에, A 나 B 인스턴스를 중단하든 그 반대로 하든... 아무튼...


Service 설정에 보면 Replica 전략에서 배포구성에 관한 옵션이 두가지 있다. minimumHealthyPercent maximumPercent 인데 이것과 인스턴스 수 조정으로 배포 전략을 결정할 수 있다. minimumHealthyPercent 은 RUNNING 상태인 Task 수를 최소 얼만큼 유지할 것인지를 설정한다. 로드 밸런서를 붙인 상태에서는 동시에 inService 상태 인지도 체크한다. maximumPercent 는 RUNNING 상태이거나 PENDING 상태의 최대 Task 수를 고려하여 설정한다.

(아래는 min / max 로 표현하겠음.)


로드 밸런서를 붙인 상태에서 운영중인 2 대의 인스턴스를 가장 빠르고 안정적으로 배포하기 위한 설정을 위해 다음과 같이 테스트 해 보았다.



A. Instance 2 (+0) 50% 100%


이 설정은 인스턴스 2 대 중, 하나의 인스턴스의 Task(50%) 는 무조건 RUNNING 상태를 유지하게 된다는 것을 예상할 수 있다. 그로 인해 번갈아 가면서 배포가 가능하게 될 것이다.


- Service Log

00:00:00 - 로드밸런스에서 A 인스턴스 등록 해제

00:00:00 - A Task DRAINING 상태 시작

00:00:12 - A Task 중지 완료

00:00:22 - 새로운 A Task 시작

00:00:33 - 로드밸런스에서 A 인스턴스 등록

00:00:54 - 로드밸런스에서 B 인스턴스 등록 해제

00:00:54 - B Task DRAINING 상태 시작

00:01:15 - B Task 중지 완료

00:01:25 - 새로운 B Task 시작

00:01:36 - 로드밸런스에서 B 인스턴스 등록


A Instance -> LB 해제 -> Task 중지 -> Task 시작 -> LB 등록

B Instance                                              -> LB 해제 -> Task 중지 -> Task 시작 -> LB 등록


로그를 보면 Task 를 삭제하거나 실행하는 과정은 간단하다.


1. 로드밸런스에서 인스턴스 등록 해제

2. Task DRAINING 시작

3. Task 중지


4. 새로운 Task 시작

5. 로드밸런스에서 인스턴스 재등록


여기서 max 를 200% 로 둔 다면 하나의 Task 를 DRAINING 으로 변경하며 즉시 여유분의 인스턴스를 찾을 것이므로 경고가 발생한다. 배포는 되겠지만 약간의 딜레이가 발생할 것이다.



B. Instance 2 (+0) 100% 150%


이 설정은 인스턴스 2 대 중, 2 대의 인스턴스의 Task(100%) 가 무조건 RUNNING 상태를 유지하게 되므로 배포할 방법이 없다.

min 을 100% 로 설정하려면 max 값에 대응할 수 있는 추가 인스턴스가 필요하다.

CPU / MEM / PORT 등의 요구사항을 만족하는 인스턴스를 찾지 못했다는 에러 메시지가 나타날 것이다.


- Service Log

00:00:00 - 요구사항에 부합하는 컨테이너 인스턴스가 없으므로 Task 를 실행할 수 없다. 



C. Instance 2 (+1) 50% 150%


- Service Log

00:00:00 - 로드밸런스에서 A 인스턴스 등록 해제

00:00:00 - A Task DRAINING 상태 시작

00:00:00 - 새로운 C Task 시작

00:00:20 - A Task 중지 완료

00:00:20 - 로드밸런스에서 C 인스턴스 등록

00:00:31 - 새로운 A Task 시작

00:00:41 - 로드밸런스에서 B 인스턴스 등록 해제

00:00:41 - B Task DRAINING 상태 시작

00:00:41 - 로드밸런스에서 A 인스턴스 등록

00:01:02 - B Task 중지 완료


A Instance -> LB 해제 -> Task 중지 -> Task 시작 -> LB 등록

B Instance                                              -> LB 해제 -> Task 중지

C Instance -> Task 시작 -> LB 등록          



D. Instance 2 (+1) 100% 150%


- Service Log

00:00:00 - 새로운 C Task 시작

00:00:13 - 로드밸런스에서 C 인스턴스 등록

00:00:34 - 로드밸런스에서 A 인스턴스 등록 해제

00:00:34 - A Task DRAINING 상태 시작

00:00:54 - A Task 중지 완료

00:01:05 - 새로운 A Task 시작

00:01:16 - 로드밸런스에서 A 인스턴스 등록

00:01:37 - 로드밸런스에서 B 인스턴스 등록 해제

00:01:37 - B Task DRAINING 상태 시작

00:01:58 - B Task 중지 완료


A Instance                       -> LB 해제 -> Task 중지 -> Task 시작 -> LB 등록

B Instance                                                                    -> LB 해제 -> Task 중지

C Instance -> Task 시작 -> LB 등록



E. Instance 2 (+2) 50% 200%


- Service Log

00:00:00 - 로드밸런스에서 A 인스턴스 등록 해제

00:00:00 - A Task DRAINING 상태 시작

00:00:00 - 새로운 C, D Task 시작

00:00:10 - 로드밸런스에서 C 인스턴스 등록

00:00:21 - 로드밸런스에서 B 인스턴스 등록 해제

00:00:21 - B Task DRAINING 상태 시작

00:00:21 - A Task 중지 완료

00:00:21 - 로드밸런스에서 D 인스턴스 등록

00:00:32 - B Task 중지 완료


A Instance -> LB 해제 -> Task 중지

B Instance                       -> LB 해제 -> Task 중지

C Instance -> Task 시작 -> LB 등록          

D Instance -> Task 시작           -> LB 등록



F. Instance 2 (+2) 100% 200%


- Service Log

00:00:00 - 새로운 C, D Task 시작

00:00:12 - 로드밸런스에서 C, D 인스턴스 등록

00:00:34 - 로드밸런스에서 A, B 인스턴스 등록 해제

00:00:34 - A, B Task DRAINING 상태 시작

00:00:55 - A, B Task 중지 완료


A Instance                       -> LB 해제 -> Task 중지

B Instance                       -> LB 해제 -> Task 중지

C Instance -> Task 시작 -> LB 등록          

D Instance -> Task 시작 -> LB 등록



위와 같이 minimumHealthyPercent / maximumPercent / task 수를 설정하여 다양한 배포 방법들을 테스트 해 보았다. B 를 제외한 A/C/D/E/F 의 배포는 모두 정상적으로 이루어 졌다. 물론 시간이나 순서 등은 각자의 배포물 용량이나 트래픽에 따라 변할 수 있다. 단계가 간결한 F 배포가 가장 빠를 것 같았는데 E 배포가 더 빨랐다는 것은 예상 밖이다. C 나 D 같은 경우는 min 과 max 값이 동시에 모두 가능할 때 어느쪽으로 먼저 배포에 영향을 미치는지를 보고 싶어서 테스트 한 것이었는데 minimumHealthyPercent 가 매우 중요함을 알게 됐다.이번 테스트로 A 방법이 가장 효율적인 것을 알게 되었고, 빠르고 빈도수가 높은 배포는 E/F 방법을 으로 전략을 세우는 것이 효과적임을 알게 됐다.



결론


가성비 좋은 배포는 A, 속도/빈도수 높은 배포는 E/F 를 사용하자.




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

,

ECS 배포

Server/AWS 2018. 8. 20. 23:32

드디어 ECS 마지막 단계인 배포다. ㅋㅋ 지금까지 Docker Image 를 만들었고, Docker Image 를 ECR 에 푸시했고, 해당 이미지를 Task 정의에 할당했고, Task 정의를 Cluster 의 인스턴스에서 실행해 보았다. 제목의 ECS 배포란 말은 Cluster 의 인스턴스에서 Task 정의를 실행한 것을 말한다. 정확한 표현으로는 단지 Task 실행이다. ^^ 이미 Task 정의를 Cluster 에서 직접 시켜봤으니 사실상 배포를 해 본 셈이다. 실제 웹서버 운영이라면 Auto scaling 이나 Load Balancing 을 붙이게 되는데 이것은 Cluster 의 Service 를 생성하여 설정할 수 있다.


* Service 가 해주는 일

- Auto scaling 이나 Load Balancing 설정.

- Service 스케줄러 전략으로부터 Task 정의 인스턴스를 제어.



1. Service 생성



Cluster - Services - [Create] 를 클릭하고 항목을 작성한다. Service 이름, Task 정의 선택, Task 수, 로드 밸런싱, Auto scaling 등을 설정하고 나머지는 다 default 로 둔다. (로드 밸런싱, Auto scaling 생성/설정은 알아서 ㅜ). Service 생성을 마치고 나면 Task 수 만큼의 인스턴스가 생성되어 바로 구동된다. 즉 바로 배포.


Service 에서는 Task 실행이 실패하거나 중단되어도 Task 수를 유지할 수 있도록 계속해서 Task 실행을 시도하게 된다. 이것 역시 Task 를 직접 실행하는 것과이 차이점이다. Service 에서 Task 수를 유지하려는 것은 Service 생성시 default 설정으로 둔 Replica 전략 때문이다. 이 Replica 는 최소 상태 백분율 및 최대 백분율 파라미터 등의 설정 대로 실행할 Task 정의를 어느 인스턴스에 배포할지를 판단한다.


즉, ECS 배포는 Task 의 실행, 곧 Service 를 생성하거나 업데이트 하는 순간 Task 정의가 실행되며 배포된다고 볼 수 있다. 추후 이미지를 수정하여 변경되거나 했을 때 최신 버전으로 인스턴스에 올리기 위해서는 Service 를 업데이트만 해주면 된다. Service 생성도 배포이고, Service 업데이트도 배포인 것이다.



2. Service 업데이트


Service 를 다른 용도로 업데이트 할 일은 별로 없을 것이다. 주로 인스턴스 수를 조정하거나 최신 이미지를 재배포 할 때 업데이트를 하게 될텐데, 업데이트는 매우 간단하다. Service 리스트에서 업데이트할 Service 에 체크하고 Update 를 클릭하면 기존 세팅이 나타나는데 [Force new deployment] 항목에 체크하고 나머지 항목은 모두 그대로 두면 latest 이미지를 가져와 업데이트 할 것이다.




이렇게 배포를 마쳤다. 여기까지는 ECS Document 만 보고 쉽게 따라할 수 있지만, Free Tier 사용자의 경우 EC2 를 두 개 이상 테스트 해보기는 쉬운 결정이 아닐 수도 있다. Fargate 도 마찬가지. 표면상 배포는 잘 돌아가겠지만, 관리 측면에서 보면 앞으로 고민해야 할 일이 더 많을 수도 있다. Image 업데이트부터 배포까지의 매우 번거로운 단계를 최대한 자동화 시키는 것에 대한 고민과, 인스턴스에 늘어나는 Image 에 대한 용량이나 롤백에 대한 고민, task 실행 실패시 알람 및 전략, ECS/Docker/EC2 로그 수집 방법 등등 필요로 하는 더 많은 기능들에 대해 고민해 봐야 한다. 운영면에서는 관련 문서가 그리 많지 않으니 그냥 열심히들 삽질해 보자.




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

,

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
손가락귀신
정신 못차리면, 벌 받는다.

,

ECS Clusters

Server/AWS 2018. 8. 16. 23:40



Docker 이미지를 생성하여 Repository(ECR) 에 푸시를 해 보았다.

Cluster 는 이러한 Docker 이미지들을 구동시킬 인스턴스들의 논리적 그룹으로 볼 수 있으며, ECS 의 가장 큰 범주로 볼 수 있다.

위 그림에서 처럼 VPC 안의 최상단에서 컨테이너 인스턴스들을 감싸고 있는 것이 바로 ECS Cluster 이다.

Image 를 실행시키려면 일단 Image 를 구동시킬 인스턴스를 배치할 Cluster 를 만들어야 한다.

Cluster 생성할 때 중요한 것은 Image 를 구동시킬 인스턴스의 사양을 정하는 것이다. 인스턴스 개수는 추후 [Scale ECS Instances] 에서 수정이 가능하다.


1. ECS - Cluster - [Create Cluster]

2. 시작 유형 선택 : Fargate 는 인스턴스를 구성할 필요 없음

3. EC2 의 경우 EC2 인스턴스 타입, Key pair, VPC, security group 등을 설정.


Cluster 생성을 완료하면, ECS Instances 탭에 설정한 만큼의 인스턴스가 생성된 것을 확인할 수 있다. 인스턴스 수를 늘리면 인스턴스가 추가되어 ACTIVE 상태가 되고 인스턴스 수를 줄이면 해당 인스턴스는 수 분 안에 삭제된다. 인스턴스를 ACTIVE 상태에서 DRAINING 으로 전환하면 기존 Task 에 영향을 미치지는 않지만, 해당 인스턴스에는 더 이상 Task 정의가 할당될 수 없으며 다시 ACTIVE 상태로 전환하면 가능해 진다.






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

,