3-4 운영 설계
- ‘운영 우수성’을 만족시키기 위해선 다음 설계 검토 사항을 확인한다.
- 어떻게 시스템 상태를 파악할 것인가
- 어떻게 시스템의 버그 수정을 쉽게 할 것인가
- 어떻게 배포할 때의 위험을 줄일 것인가
- 이번 장에서는 ECS/Fargate 이용 시 시스템 상태 파악을 위한 다음 설계에 대해 검토해보자
- 모니터링과 감시에 대한 설계
- 버그 수정과 배포할 때의 위험을 줄이기 위한 CI/CD 설계
모니터링과 옵저버빌리티(Observability)의 중요성
- 모니터링의 주 목적은 시스템에 문제가 발생하는 것을 즉시 발견해 시스템의 가용성을 유지하는 것이다.
- 메모리 사용율이나 디스크 사용율
- 애플리케이션 로그를 통한 정성적 정보
- 상태 이상을 감지해 경보를 발생
- 옵저버빌리티(가관측성)
- 시스템 전체를 살펴보며 내부 상태까지 깊이 파고들 수 있는 상태를 말한다.
- 문제 발생 원인을 조사하려면 트랜잭션 흐름과 애플리케이션 내부 자세한 흐름을 파악해야 하는 경우도 있다.
- AWS에는 CloudWatch와 연계해 각종 로그와 지표 정보를 수집할 수 있는 서비스가 있다.
- ECS/Fargate 구성에선 CloudWatch Logs나 FireLens를 활용할 수 있다.
- X-Ray와의 조합으로 요청 흐름을 추적 가능
모니터링의 목적은 ‘이용자가 애플리케이션을 이용할 수 있는 상태를 유지하기 위한 것’이다. 중요한 점은 로그나 지표에 관계없이 모니터링은 이용자의 경험이 손상되는 이벤트를 염두에 둬야 한다는 점이다.
로깅 설계
- ECS/Fargate 구성에서 로그 수집 절차는 크게 두 가지 방법이 있다.
CloudWatch Logs를 이용한 로그 운영
- 애플리케이션 로그 검색 가능
- ‘구독 필터’를 이용하면 로그 내 특정 문자열이 포함된 경우의 로그만 추출 가능
- Lambda나 SNS 연계를 통한 장애 알림을 구성할 수도 있다.
- 로그 보존 기간을 설정할 수 있으므로 로그의 유지보수 처리도 자동화할 수 있다.
- 단순한 애플리케이션이나 대량으로 로그가 발생하지 않는 경우라면 CloudWatch Logs만으로 충분하다.
FireLens를 이용한 로그 운영
- FireLens를 이용하면 AWS 서비스나 그 외의 SaaS에 로그를 쉽게 전송할 수 있다.
- Fluent Bit
- 로그 라우팅 기능을 담당하는 소프트웨어 (오픈 소스)
- AWS는 높은 자원 효율로 인해 FireLens와 Fluent Bit의 연계를 추천한다.
- AWS가 공식적으로 제공하는 전용 컨테이너 이미지 사용 가능
- ECS 태스크 정의 안에 애플리케이션용 컨테이너와 Fluent Bit 컨테이너를 함께 구성 가능
- FireLens는 아래 SaaS와 연동이 가능하여 데이터 분석 용도로 많이 사용될 수 있다.
- Redshift - 데이터 웨어하우스용 관리형 데이터베이스
- OpenSearch Service - 관리형 검색 엔진 서비스
- FireLens는 S3뿐 아니라 CloudWatch Logs에도 동시에 로그를 전송할 수 있다.
CloudWatch Logs와 FireLens의 선택 기준 및 로그 운영 디자인
- ECS 태스크 정의 사양의 한계
- 각 컨테이너가 어디에 로그를 출력할지 지정하는 로그 드라이버 정의는 1개뿐이다.
- 로그를 장기 보존하기 위해 애플리케이션 접속 로그는 S3에, 에러 로그는 CloudWatchLogs에 전송하려면 어떻게 해야할까?
- CloudWatch Logs에 로그를 한 번 전송한 뒤 S3로 내보내는 방법
- CloudWatch Logs는 로그 취득 시점에 과금이 발생한다.
- CloudWatch Logs의 구독 필터 기능을 이용해 Firehose를 경유해 S3에 로그를 저장하는 방법
- 결국 CloudWatch에 한 번 로그를 저장하므로 비용이 발생한다는 점은 똑같다.
- Firehose 또한 요금이 추가된다.
- FireLens를 로그 드라이버로 지정하는 방법
- 로그 보존 관점의 비용 최적화와 운영을 모두 만족시키는 방법
- Fluent Bit는 CloudWatch Logs와 S3 양쪽에 동시에 로그를 전송할 수 있다.
- 이 구성을 위해선 AWS 내부의 태스크 정의가 아닌 Fluent Bit 자체 설정 파일을 수정해 Fluent Bit 컨테이너 안에 넣어야 한다.
- Fluent Bit에서 로그 출력을 나누는 방법
- 첫 번째는 S3 버킷에 설정 파일을 올려두고 태스크 정의를 할 때 해당 버킷 위치를 지정해서 태스크가 시작될 때 파일을 읽어 들이는 방법
- 복잡한 로그 라우팅을 설정해야 한다면 S3는 한 개 파일만 가능하므로 여러 파일을 함께 교체할 수 없다.
- 두 번째는 사용자 정의 설정 파일을 추가한 Fluent Bit 컨테이너 이미지를 직접 만든 뒤 태스크 정의에서 대상 컨테이너로 지정하는 방법
- S3를 만약 이용한다면 이미지 관리를 비롯해 이미지 버전과 수명 주기 등 관리가 발생한다.
지표 설계
- 지표(Metric)란 정기적으로 계측되고 수집되는 시스템 내부의 정량적인 동작 데이터다.
- ECS에서 취득 가능한 지표는 크게 두 가지로 나눌 수 있다.
- CloudWatch 지표
- CloudWatch Container Insights
기본적인 CloudWatch 지표
- ECS 클러스터 또는 ECS 단위로 다음 지표를 받을 수 있다.
- CPU Utilization: 이용 중인 CPU 비율
- MemoryUtilization: 이용 중인 메모리 비율
- 자세한 지표를 얻기 위해선 CloudWatch Container Insights를 활성화해야 한다.
CloudWatch Container Insights 활용
- CloudWatch 지표는 ECS 서비스 단위이기에 태스크별로 정보를 표시할 수 없다.
- CloudWatch Container Insights를 이용하면 더 자세한 지표를 파악할 수 있다.
- ECS 태스크 수준의 정보를 파악
- 디스크나 네트워크에 대한 지표도 수집
- 차원(Dimension) 단위 축을 통해 각 지표값을 그래프로 볼 수 있는 대시보드도 이용할 수 있다.
- 주의점
- ECS 클러스터 단위로 명시적인 옵트인(내용을 수락하고 활성화하는 것)이 필요
- 사용자 지정 지표이기에 모든 지표가 추가 과금 대상이다.
트레이스 설계
- 옵저버빌리티를 가지기 위해선 로그 외에 트랜잭션 정보와 같은 트레이스 정보를 취득해야 한다.
- AWS X-Ray 서비스를 이용해 트레이스 정보 수집을 할 수 있다.
- 서비스 맵 대시보드도 제공해 시스템 전체를 시각적으로 표시해준다.
사이드카 구성으로 X-Ray 컨테이너를 배치
- ECS/Fargate에서 X-Ray를 이용하는 경우 ECS 태스크 정의 안에 애플리케이션 컨테이너와 X-Ray 컨테이너를 함께 넣는다.
- 애플리케이션 자체에 AWS가 제공하는 X-Ray 용 SDK로 일부 코딩을 하면 X-Ray에 트레이스 정보를 보낼 수 있다.
ECS 태스크 역할 부여
- 컨테이너 애플리케이션에서 X-Ray에 트레이스 정보를 보내려면 특정 IAM 권한이 필요하다.
- AWSXRayEaemonWriteAccess가 부여되어 있어야 한다.
- X-Ray에 트레이스 정보를 저장하는 주체는 ECS 컨테이너 에이전트가 아닌 ECS 태스크다.
- 때문에 태스크 식행 역할이 아닌 ECS 태스크에 역할을 부여해야 한다.
VPC와 퍼블릭 네트워크 간 통신 경로
- X-Ray는 VPC 밖의 AWS 퍼블릭 네트워크에 서비스 엔드포인트가 존지한다.
- ECS 태스크는 VPC 내에 있으므로 VPC - 퍼블릭 네트워크까지의 경로를 고려해야 한다.
- ECS가 프라이빗 네트워크에 있는 경우 NAT 게이트웨이 등을 필요할 수도 있다.
- X-Ray를 활용하기 위해선 애플리케이션에서 SDK를 적극 활용해야 한다.
- 트레이스 정보를 자세히 취득하려면 매번 코딩을 해야 하는 언어도 있기에 미리 개발자와 검토하는 것이 좋다.
CI/CD 설계
- AWS Code 시리즈로 CI/CD 프로세스를 설계할 수 있다.
CI/CD가 주는 혜택
- CI/CD란 빌드와 테스트, 패키징, 배포와 같은 소프트웨어 개발 사이클을 자동화하고 고속화하기 위해 사용되는 방법이다.
- 빌드 및 배포에 소모된 시간을 애플리케이션 개발에 집중할 수 있다.
- 테스트 자동화를 통합해 신속하게 문제를 발견할 수 있으므로 품질 개선 효율화도 기대할 수 있다.
CI/CD와 잘 어울리는 컨테이너
- 컨테이너는 우수한 이식성, 재현성, 경량성이라는 특성을 가지고 있다.
- 때문에 CI/CD를 구현하기에 적합하다.
- 개발 환경, 스테이징 환경, 프로덕션 환경 등 여러 환경이 있는 상태에선 컨테이너의 특징이 도움이 된다.
- 컨테이너는 애플리케이션에 필요한 필요한 종속성까지 패키징해서 빌드하기에 어느 머신에서 실행해도 동일한 동작을 한다.
- 컨테이너는 최소한의 컴퓨팅 자원만을 소비하기에 신속한 실행이 가능하다는 것도 장점이다.
AWS가 제공하는 관리형 CI/CD 서비스
- AWS에선 Code 시리즈 서비스군을 활용해 CI/CD 파이프라인을 구축할 수 있다.
- AWS Code를 활용하면 다음과 같은 파이프라인을 구성할 수 있다.
- CodCommit - 소스 코드 관리
- CodeBuild - 애플리케이션 빌드 → 단위 테스트 → 컨테이너 이미지 빌드 → 이미지를 레지스트리에 등록
- CodeDeploy - 컨테이너 배포
- CodePipeline을 이용하여 위 플로우를 쉽게 구현할 수 있을 뿐 아니라 다양한 AWS 서비스와 조합하여 유연한 파이프라인을 운영할 수 있다.
- CodePipeline에서 각 액션 카테고리별 연계 가능한 기본 서비스
- Source - CodeCommit, ECR, S3, Bitbucket, Github
- Build - CodeBuild, Jenkins
- Test - CodeBuild, Device Farm, BlazeMeter, Jenkins, Ghost Inspector
- Deploy - CodeDeploy, ECS, S3, CloudFormation, Elastic Beanstalk
- Invoke(호출) - Lambda, Step Functions
- Approval(승인) - 수동 승인
프로덕션 운영을 상정한 CI/CD 설계
아래 아키텍처는 어디까지나 하나의 예다. 필요한 부분만 적절히 활용하기 바란다.
- 좀 더 실전적인 CI/CD 설계를 위해 다음과 같이 요건을 가정하자
- 요건 1: 각 환경 분리 및 인프라 계층에 따른 품질 담보를 위해 프로덕션 환경과는 별도로 스테이징 환경을 마련
- 요건 2: 개발 효율화를 위해 스테이징 환경과는 별도로 개발 환경을 마련
- 요건 3: 거버넌스 강화를 위해 프로덕션 환경의 CI/CD 파이프라인은 다른 환경과 분리
- 요건 4: 애플리케이션 동작 품질을 유지하기 위해 스테이징 환경에서 빌드 및 테스트가 완료된 컨테이너 이미지를 프로덕션 환경에 배포
- 요건 1과 요건 2를 충족하기 위한 환경 분리 방법 검토
- VPC를 이용한 환경 분리도 가능하지만 AWS 계정으로 분리하면 자원을 확실히 분리할 수 있다.
- 여기에선 환경별로 3개 AWS 계정을 마련한다.
- 개발 환경, 스테이징 환경, 프로덕션 환경
- 공유 자원용 AWS 계정에 CodeCommit을 사용한다.
- 요건 3을 충족하기 위한 파이프라인 분리 검토
- CodeCommit 구성
- 각 환경마다 정의하면 소스코드가 분산되기에 각 환경이 공유 자원으로서 한 곳에서 관리할 필요가 있다.
- 환경별로 브랜치를 준비해두면 소스 코드는 한 곳에서 관리하면서 별도 환경의 CodePipeline이 실행되게 할 수 있다.
- CodeBuild 구성
- CodeBuild는 환경별로 분리해 배치해야 한다.
- 스테이징 환경에선 컨테이너 이미지를 빌드 및 테스트하고 ECR에 이미지를 푸시
- 프로덕션 환경에선 빌드 및 테스트 없이 스테이징 환경에서 빌드된 이미지를 이용
- CodeDeploy 구성
- CodeDeploy는 환경별로 분리해서 배치해야 한다.
- 공유 자원으로 취급하면 계정 권한을 넘는 설계를 해야 햐므로 설계가 복잡해진다.
- 요건 4를 충족하기 위한 배포 구성 검토
- 스테이징 환경과 프로덕션 환경에 동일 컨테이너 이미지를 이용하는 것이 이상적
- 스테이징 환경에 빌드된 프로덕션 환경에서 이용할 수 있어야 하므로 하나의 ECR를 이용하는 형태여야 한다.
- ECR과 컨테이너 이미지 관리
- ECR은 CodeCommit과 마찬가지로 공유 자원용 계정에 2개를 운영 (개발 환경용, 스테이징/프로덕션용)
- 프로덕션 환경에서 보다 강력한 통제가 필요하다면 별도 ECR을 준비해야 한다.
이미지 유지 보수 운영
- 빌드된 이미지를 ECR에 저장하면 이미지 내구성과 확장성에 신경 쓰지 않고 ECS와 연계할 수 있다.
- ECR에 저장된 컨테이너 이미지는 실제로는 S3에 저장된다.
- S3의 우수한 내구성 덕에 ECR 외에 다른 곳에 백업할 필요는 없다는게 필자의 견해라고 한다.
- ECR은 용량만큼 요금이 발생하기에 적절한 수명 주기 정책을 설정하는 것이 좋다.
- 수명 주기 정책 1 - 세대 수 (과거 3세대 이미지를 보관)
- 수명 주기 정책 2 - 기간 (최근 2주간 이미지를 보관)
다중 계정 구성에서의 이미지 보관
- 복수 환경 또는 복수 애플리케이션을 한 ECR에서 관리하는 경우 설계상 주의가 필요하다.
- ex) 스테이징 환경과 프로덕션 환경의 이미지 수명 주기가 다른 경우 프로덕션 환경에서 이미지를 취득할 수 없는 문제 발생
- 환경마다 고유의 태그 식별 문자를 부여해 태그별 수명 주기 정책을 지정하여 해결할 수 있다.
- Docker에는 1개 이미지에 여러 태그를 붙이는 것이 가능
- 즉 여러 태그를 사용해 복수의 수명 주기 정책 적용 가능
거버넌스와 컴플라이언스 요건 교려
- 시스템에 따라선 조직의 정책과 지침을 준수해야 하는 경우가 있다.
- 거버넌스 요건
- 업계별 법률 및 규정
- 컴플라이언스 요건
- 예를 들면 다음의 요건들이 있다.
- 배포와 관련된 파일은 변조되지 않도록 방재 대책을 세울 것
- 의도하지 않은 소프트웨어 배포를 막기 위해 승인 프로세스를 마련할 것
- 지정한 CI/CD 파이프라인 외 배포를 금지할 것
- 파일 변조 방지 대책
- CI/CD 플로우를 보면 S3, ECR 등에 배포 관련 데이터가 저장된다.
- IAM 정책과 S3 버킷 정책을 이용해 각 IAM 사용자를 제한할 수 있다.
- 승인 프로세스
- CodePipeline에 승인 액션 설정 가능
- ECS나 ECR에 대해 쓰기 및 실행 권한을 제한하여 예상치 못한 파이프라인 실행을 금지할 수 있다.
Bastion 설계
- 장애 분리 목적으로 다음과 같은 사항이 필요한 경우가 있다.
- 내부 내트워크에서 애플리케이션 통신 확인
- DB 인스턴스에 로그인해 데이터베이스 정비
- 보안상 위와 같은 작업이 불가한 경우가 대부분이고 감사 기록으로 이러한 활동에 대해 로깅을 요구하기도 한다.
- Bastion(Jump Server)을 이용해 이런 요구사항을 충족할 수 있다.
- 불특정 다수로부터의 내부 접속을 막을 수 있다.
- 내부 작업에 대한 기록도 취득할 수 있다.
- EC2에 Bastion을 구축하는 것이 가능
- ECS/Fargate 구성에서 EC2/Bastion으로 구축할 때 주의할 점
- 점프 서버 자체는 누구나 접속 가능한 상태가 된다.
- 컨테이너와 관련된 서비스로 구성한 통일된 아키텍처였으나 새롭게 EC2 설계 및 구축을 해야 한다.
- 공동 책임 모델이므로 EC2 인스턴스 OS 관리 운영 부담이 발생한다.
- 위 문제점은 다음 아키텍처로 해결할 수 있다.
- 점프 서버 자체를 프라이빗 서브넷에 두어 공격 지점을 줄인다.
- SSH 접속이 아닌 세션 관리자를 활용해 IAM 권한으로 보안 설정이 가능하다.
- EC2 점프 서버를 ECS/Fargate 구성으로 하여 OS 관리를 AWS에 위탁한다.
- ECS 태스크 안에 SSM 에이전트를 포함시켜 Bastion을 구축할 수 있다.