1. 개요
EKS Cluster를 구성할 때 고려해야 할 사항들에 대해서 정리해본다.
- Terraform으로 인프라 구성
- IRSA(IAM Role for Service Account)
- 애드온 서비스들 (AWS Load Balancer Controller, Secrets Store CSI Driver, Cluster Autoscaler, External DNS, EBS CSI Driver, EFS CSI Driver, ..)
- Monitoring, Logging
- ..
2. Terraform으로 인프라 구성
Terraform으로 인프라를 구성할 때는 다음의 고려 사항이 필요했다.
[1] 공용으로 사용하는 변수들을 어떻게 관리할 것인가?
[2] Terraform을 Local에서 수행할 것인가, Github Action을 통해 수행할 것인가, 아니면 Atlantis 등을 통해 수행할 것인가?
[3] Terraform State 파일은 어떻게 관리할 것인가?
[4] Module을 사용할 것인가?
[5] 폴더 구조는 어떻게 가져갈 것인가?
등에 대해서 고민을 하게 되었고, 다음의 결론을 내리게 되었다.
[1] 공용으로 사용하는 변수들을 어떻게 관리할 것인가?
Terragrunt를 활용하며, generate 라는 Function을 활용하여 모든 Terraform 폴더에 동일하게 구성될 수 있도록 하겠다.
[2] Terraform을 Local에서 수행할 것인가, Github Action을 통해 수행할 것인가, 아니면 Atlantis 등을 통해 수행할 것인가?
Local에서 하면 Credential 관리를 직접 해야하기 때문에 매우 번거로울 수 있다.
고로 Atlantis에서 Terraform을 수행할 수 있도록 한다. Atlantis의 Role에는 Terraform을 수행할 수 있는 적절한 Policy가 필요할 것이다.
필자의 경우에는 회사가 멀티 어카운트로 운영되고 있기 때문에, Atlantis 서버가 각기 다른 Account에 대한 권한이 필요했다.
또한 ECS Fargate의 Task Container로 구동되고 있다.
#1 동일 Account일 경우
'관리자 권한을 가진 Role의 신뢰관계'에만 Task Container의 Role이 sts:assumeRole Action을 수행할 수 있도록 설정만 해주면 된다.
Task Container의 Role -> 관리자 권한을 가진 Role의 신뢰관계
#2 다른 Account일 경우
양방향에 대해서 모두 Action을 수행할 수 있도록 Policy랑 신뢰 관계를 설정해주어야 한다.
Task Container의 Role <-> 관리자 권한을 가진 Role의 신뢰관계
[3] Terraform State 파일은 어떻게 관리할 것인가?
tfstate는 S3를 통해 관리했으며, 단일 Account에 모두 모아두었다.
또한, Terragrunt에 remote_state 기능을 활용하여 일괄적으로 모든 폴더에 동일한 백엔드 설정을 진행하였고, ${path_relative_to_include() 함수를 사용하여 폴더의 경로에 맞게 S3 내에 객체 경로를 설정하도록 하였다.
[4] Module을 사용할 것인가?
사실은 Module을 활용하는 것이 Best이지만, 제대로 사용되지 않으면 관리하기가 더욱 힘들어진다.
예를 들어 EKS Nodegroup에 대한 Module을 만든다고 했을 때, A NodeGroup에는 A 기능을, B NodeGroup에는 B 기능을 구현하고 싶고, 개발계와 운영계 각각 다른 스펙 및 환경으로 구성하고 싶다고 가정하면 이를 고려하여 Module을 작성해야 한다.
이런 부분들을 하나하나 고려하면서 Module을 작성한 뒤 다른 곳에서 가져다 쓰는 시간보다, 직접 하나하나 Resource Block 내 옵션 및 파라미터들을 파악하면서 작성하는게 시간 효율성 및 공부하는데 훨씬 이득이라 생각하여 Module 사용은 최소화하였다.
Module은 EKS Cluster에만 활용하였고 NodeGroup 에는 활용하지 않았다. (VPC는 기존에 구성되어 있는 VPC를 terragrunt.hcl에 공용 변수로 값을 넣어서 활용하였다.)
또, Module을 사용하면 나중에 소스코드 업그레이드 측면에서도 힘들어진다.
결론은 제대로 쓸 수 있지 않다면 Resource를 쓰는게 낫지 않을까? 라는 이유로 인해 모듈 사용은 최소화하였다.
[5] 폴더 구조는 어떻게 가져갈 것인가?
폴더 구조는 다양한 방식으로 가져갈 수 있다.
Workspace를 활용할 수도 있고, Branch 별로 다르게 환경을 구성할 수도 있고, dev / qa / stage / prod 폴더를 각각 다르게 구성하여 리소스를 구성할 수도 있다.
필자의 경우에는 Workspace를 예전에 사용해보았을 때 오히려 더 불편하다는 느낌을 받아 폴더별로 구성하였다.
common/
dev/
qa/
stage/
prod/
common의 경우에는 Global 리소스들을 넣으려고 노력했다.
EKS Nodegroup의 경우 동일한 Role을 사용할 것이기 때문에 common/iam/eks_nodegroup 폴더 내에 IAM Role을 구성한 뒤,
eks/nodegroup/launch_template/{NODEGROUP} 에서는 remote_state를 참조하여 IAM Role ARN을 적용할 수 있도록 했다.
또 nodegroup에는 각각 nodegroup마다 다른 Folder로 구성하여, 다른 Nodegroup을 구성 혹은 업데이트할 때 영향도를 최소하하려고 하였다.
3. 그 외 고려사항
[6] Atlantis.yaml Workflow
provider나 backend.tf 등은 terragrunt가 동적으로 생성을 해주는데, Terraform Runner로 Atlantis를 사용하기 때문에 Atlantis에서 terragrunt inint 명령어가 수행되면 자동으로 Atlantis 서버 내에서 생성되고, 삭제되도록 하였다.
Editor에서 보이는 파일 개수를 최소화하기 + 공용 변수는 최대한 관리하지 않도록 하기 위함이다.
[7] IRSA
개발계 클러스터와 운영계 클러스터가 분리되어 있는데, 동일한 IAM Role을 사용하고 싶다면 아래의 신뢰관계 설정을 2개로 구성해야 한다.
현재는 StringsEquals로 되어 있지만 개발계와 운영계에서 1개의 IAM Role을 사용하는데, Namespace와 ServiceAccount Name이 다를 수 있기 때문에 StringLike 조건 연산자를 통해 * 를 넣을 수 있도록 변경할 예정이다.
이러한 IRSA는 각종 서비스들 및 Cluster Autoscaler, AWS LoadBalancer Controller, .. 등에 대해 최소 권한 원칙을 부여할 때 사용된다.
이로 인해 Pod들은 Node Role을 사용하는 것이 아닌 Pod의 ServiceAccount Annotation에 기입되어 있는 IAM Role을 활용하여 AWS 서비스들에 대한 권한을 얻을 수 있을 것이다.
[8] Addon은 어떻게 관리를 할 것인지?
모두 Helm으로 구성할 예정이며, 어떤 설정값을 적용했는지 명시적으로 파악될 수 있도록 --set 옵션을 넣는 것이 아닌 values.yaml을 통해 모든 설정값을 컨트롤 할 예정이다.
이정도로 EKS Cluster를 구성할 때 고려해야 할 사항들을 정리해보았다.
사실 이것 외에도 무수히 많지만 시간 관계상 이정도로만 정리...
- EKS Cluster 모니터링은 어떻게 할 것인가?
-> 자사에서는 Datadog을 사용하고 있기 때문에 Datadog을 활용한다.
- EKS Cluster 모니터링 대시보드 및 알람은 어떻게 구성할 것인가?
- EKS로 인입되는 트래픽 관리는 어떻게 할 것인가?
-> 서비스 메시를 활용할 것인가? 아니면 일반적인 AWS LoadBalancer Controller를 활용할 것인가?
- NodeGroup 생성 시 왜 Launch Template으로 생성한 Image를 사용하는지? 만약 Launch Template을 사용할 것이라면 어떤 방식으로 Launch Template을 만들어서 EKS Nodegroup에 적용하는지?
..
'AWS' 카테고리의 다른 글
[EKS 애드온 #2] Cluster Autoscaler Helm으로 설치하기 (0) | 2022.08.27 |
---|---|
[EKS 애드온 #1] External DNS Helm으로 설치하기 (0) | 2022.08.27 |
[ECS] FireLens로 ECS Fargate 컨테이너 로그 ElasticSearch로 보내기 (0) | 2022.05.02 |
[ECS] ECS Exec를 사용하여 ECS Fargate 컨테이너에 접속하기 (0) | 2022.04.29 |
[AWS] Multi Account에서 IAM 내역 감사하기 #4 - Lambda를 활용한 Slack Notification (2) | 2022.04.17 |