EKS 로 밑바닥부터 K8S cluster 구축하기 (1)

제각기 EC2 쓰던 동아리에 자동 K8S 배포와 GitOps 정착

Davin
wafflestudio
23 min readMar 28, 2023

--

개발 동아리 ‘와플스튜디오’

와플스튜디오 프프리 (디자이너: 여건주)

저는 ‘와플스튜디오’라는 서울대학교 컴퓨터공학부 웹/앱 개발 동아리에서 몇 년째 활동하고 있습니다. 학부생 중심의 동아리로 시작되었으나, 현재는 학교 및 졸업 여부와 다소 무관히 저처럼 직장을 다니고 있는 분들도 함께 하고 있습니다. 제가 입학하기 한참 전부터 있던 오래된 동아리지만 한동안 침체기를 겪다가, 2020년 경부터 의지 있는 친구들과 함께 운영팀을 맡아 개발 세미나들을 진행하며, 지금은 이전보단 훨씬 규모 있고 활성화된 동아리가 되었습니다. 관련해서도 여러 이야기가 있겠지만 다른 기회에 다루고, 이 글에선 지난 반 년 간 주도했던 infra 차원의 발전과, 그 과정에서 K8S 에 관련해 겪은 고민과 얻은 지식을 공유하려 합니다. 어떤 분들께는 충분히 쉬운 내용일 수도 있으나, 처음 K8S(Kubernetes) cluster 를 만들어보려는 분께 특히 도움이 되리라 기대합니다.

다루는 내용이 많아 글을 나누었으며, 이번 편의 목차는 아래와 같습니다.

  • K8S 도입 전의 풍경과 도입 동기
  • K8S 의 개괄적 구조
  • EKS cluster 기본 네트워크 설정
  • Node group 설정
  • 선언적 관리와 GitOps 를 위한 GitHub repo ‘waffle-world’
  • Ingress 생성 및 관련 add-on 설치, OIDC provider 설정

K8S 도입 전의 풍경과 도입 동기

여러 작은 조직이 그렇듯, 기존의 동아리에서 AWS 활용은 EC2 하나에 각자 서버 하나씩 올리고 쓰는 경우가 거의 대부분이였습니다. 와플스튜디오 내부엔 여러 팀들이 각자의 프로젝트를 진행하고 있는데, 팀에 따라 상황 차이가 컸지만 대체로 서버 배포 방식을 아래와 같이 정리할 수 있었습니다.

  • EC2 인스턴스에 ssh 로 매번 직접 접속하여 git 원격 저장소를 활용해 최신 코드를 pull 받아와서 서버를 재시작 (일명 git-pull 배포)
  • GitHub Actions 에서 AWS CodeDeploy 와 스크립트를 이용해 EC2 자동 배포
  • GitHub Actions 에서 Docker build 해 ECR 에 올리고 EB 환경 업데이트를 트리거해 자동 배포
  • 로컬에서 스크립트로 Docker build 해 ECR 에 올리고, AWS ECS, Lambda 기반의 서버리스 환경으로 배포

2020년에 와플스튜디오 AWS 계정을 만들고 각 구성원들이 IAM 유저 기반으로 사용하도록 안내했기에, 이후에도 권한 관리는 후속 운영팀 분들을 통해 체계적으로 이뤄져온 편이었습니다. 다만 위처럼 다양한 방식으로 각 팀이 서버 운영을 하다보니, 매번 설정하고 권한을 부여하는 과정이 번거로웠습니다.

이전부터 VPC 를 만들어 public, private subnet 들을 구분해 사용할 수 있게 했지만(개념이 낯설다면 참고할 글), 팀마다 직접 EC2 를 생성하다보니 어떤 서비스는 아예 VPC 밖에, 또는 불필요하게 큰 사양으로, 또는 심지어 다른 region 에 생성하는 경우도 있었습니다. 회사가 아닌 동아리기에 상시적으로 이를 모니터링할 도구와 사람이 부족했고, 때문에 비효율적인 비용 지출과 잠재적 보안 문제가 종종 발생해왔습니다. 뿐만 아니라 작은 프로젝트들이 많아 그 필요성이 높지는 않았지만, autoscaling 같은 기능은 EB 나 서버리스 환경을 이용하고 있지 않은 팀의 경우 불가능했으며, 빠른 롤백도 사실상 어려웠습니다.

K8S 도입을 하고 싶었던 개인적인 이유도 있었습니다. 회사에서 K8S 를 꾸준히 사용하고는 있었지만 DevOps 팀은 아니었기에 깊이 있게 이해하기보단 Backend Developer 라는 사용자 입장에서만 cluster 를 주로 다뤄왔습니다. 때문에 관련 공부의 갈증을 느끼던 차, 위와 같은 동아리 상황을 보고 K8S 를 통해 여러 문제를 해결할 수 있겠다고 생각했습니다. 또한 일정 규모 이상의 회사를 다니지 않는 이상 쉽게 학습 기회를 얻기 어려울 수도 있는, 실제 동작하는 cluster 환경에 대해 더 많은 동아리 구성원들이 익숙해질 수 있겠다는 기대도 있었습니다.

그래서 이렇게 요청했고, 현 운영팀 분들이 허락해주셨습니다!

동아리 비용을 사용해 EKS cluster 를 만드는 것에 허락을 받았지만, 막막했습니다. 자주 접하는 Pod, ReplicaSet, Deployment 정도만 대략 알았고 다른 리소스들은 잘 모를 뿐더러, cluster 구조 자체에 대한 이해는 부족했으니까요. 그래서, 작업을 시작한 9월엔 ‘쿠버네티스 인 액션’이라는 책과 K8S 공식 문서를 훑어보는 것에 집중하고, EKS cluster 생성 버튼을 눌렀을 때 물어보는 것들부터 하나씩 답하기 위해 노력했습니다.

K8S 의 개괄적 구조

https://kubernetes.io/ko/docs/concepts/overview/components/

아래 내용은 control plane, node 에 관한 기초적인 이해가 전제되기에 이에 낯선 분들은 먼저 이 K8S 문서를 구경해 보시길 권합니다. node 들은 실제 서비스들이 배포되는 Pod 들이 위치하게 될 인스턴스들이며, 하나의 node 인스턴스에 여러 개의 Pod 가 배치되고, 자동으로 옮겨다닙니다. EKS 에서 EC2 를 사용하는 cluster 의 경우, node 인스턴스 하나가 EC2 인스턴스 하나에 대응됩니다. 어떤 Pod 가 실제 어떤 인스턴스에 배치되는가를 일반적으로는 신경 쓰지 않아도 되는 추상화를 제공하는 것이 K8S 의 역할 중 하나입니다. control plane 은 K8S cluster 가 자동으로 동작할 수 있도록 중앙에서 관리를 해주는 영역입니다. 모든 K8S 구성요소들은 control plane 을 통해 상호작용하며, 사용자 역시 kubectl 등의 도구를 이용해 cluster 와 소통할 때 control plane 의 kube-apiserver 를 이용하게 됩니다.

EKS cluster 기본 네트워크 설정

EKS cluster 생성 시, 기존에 있던 VPC 안에 cluster 를 배치할 생각이었기에 쉽게 택했으나, subnet 및 cluster endpoint access 설정부터 고민되는 점이 있었습니다.

cluster endpoint access 는 최종적으로는 Public and private 을 택했습니다.

우선 cluster 생성 시 택하는 subnet 들의 의미를 파악해야 했습니다. subnet CIDR 블록 크기에 따라 subnet 에 들어갈 IP 개수가 달라지는데(예컨대 /26 인 CIDR 라면 2^(32–26)=64), 이를 적게 해서 cluster 를 만들었다가 나중에 cluster 의 규모가 커지면 낭패가 아닌가 하는 걱정이 있었습니다. 다만 찬찬히 읽어보니 control plane 이 배치될 subnet 에 대한 설정이었으며, AWS EKS 네트워크 문서에서도 control plane 과 worker node 의 subnet 은 서로 다를 수 있으며, 초기에 설정하지 않은 subnet 으로 나중에 worker node 를 배포할 수 있다고 언급하고 있었습니다. control plane 용의 private subnet 두 개를 작은 CIDR 블록 크기로 만들어 택해주었습니다.

다음으로 고민한 것은 아래의 endpoint access 에 대한 것이었습니다. control plane 을 private subnet 에 배치하고 이 설정을 Public 이나 Public and private 으로 택하는 경우 어떻게 되는 것인지 궁금했으나, 친절한 AWS 블로그 글이 각 선택지에 대한 이해를 도와주었습니다. endpoint access 는 control plane 이 어느 subnet 에 위치하는 것과는 무관했으며, control plane 에 VPC 외부에서 접근할 수 있는가(즉 kubectl을 로컬에서 쉽게 사용 가능한가)에 대한 것과 control plane 과 node 들 간의 통신이 VPC 내부에서 가능한가에 대한 것이었습니다.

https://aws.amazon.com/blogs/containers/de-mystifying-cluster-networking-for-amazon-eks-worker-nodes/

control plane 과 node 간 통신은 굳이 VPC 외부로 오갈 필요가 없을 것 같아 Public and private 과 Private 두 개의 선택지를 염두에 두었습니다. 궁금하기도 하고 보안을 우선해본다는 생각에 Private 을 택해 cluster 를 생성해보기도 했습니다. VPC 내부에서 control plane 에 접근 가능한 bastion 역할을 할 EC2 인스턴스를 만들고 적절한 권한 부여 후, 로컬에서 bastion을 통해 kubectl 을 실행하는 것에 성공해서 이론적으론 이용할 수 있음을 확인했습니다. 또는 VPN 을 사용하는 방법도 있었을 것입니다. 다만 일상 이용이 번거롭기도 하고 bastion 인스턴스에 접속하거나 VPN 을 이용할 권한을 따로 관리하느니, control plane 에 대한 접근을 public 으로 만들고 K8S RBAC(Role-based Access Control) 및 AWS IAM을 이용해 kubectl 이용 권한을 관리하는 것이 훨씬 편리하겠다는 생각이 들었습니다. 때문에 결과적으로 endpoint access 로 Public and private 을 택했습니다.

Node group 설정

EKS cluster 생성 후엔 Node group 을 만들어주어야 했습니다. Node group 은 K8S 고유 개념이라기보단 EKS 에서 각 node 들을 생성해내는 템플릿에 가깝습니다. Node group 에서 node 의 인스턴스 크기, 네트워크, 보안 등에 관련한 설정을 해두면 autoscaling 하는 경우 해당 설정으로 node 들이 계속 만들어지는 것입니다. 또한 node 가 생성될 수 있는 최대/최소 개수 등도 설정 가능했습니다.

일반적으로 cluster subnet 관련해 best practice 로 여겨지는 방식은 cluster 앞단에서 외부 요청을 받아주는 Ingress 리소스를 제외하고는 모두 private subnet 에 배치하는 것이기에, Node group 을 위해서 private subnet 들을 적절한 크기로 생성 후 택해주었습니다. 하나의 Node 에도 여러 Pod 가 들어가 서로 다른 IP 를 할당 받아야하기에 control plane 의 subnet 보다 더 큰 CIDR 블록으로 생성하는 것이 일반적일 것입니다.

node 가 속하는 subnet 중 하나. route table 에 외부 인터넷으로 향하는 internet gateway 이 없는 것을 보고 private subnet 임을 알 수 있습니다. 0.0.0.0/0 이 향하는 곳은 직접 구축한 NAT instance 입니다.

여기서 고려할 지점이 있는데, private subnet 이라 해도 내부 서버들이 외부 API 를 이용하거나 다른 곳에 위치한 DB 에 접속하기 위해선 외부 인터넷으로 나가는 연결은 일반적으로 열어주어야 합니다. 이를 위해 필요한 것이 NAT(Network Address Transition) gateway 입니다. AWS 가 제공하는 NAT gateway 기능을 이용하면 편리하지만 가격이 비싸서 과거에 EC2 로 NAT 인스턴스를 직접 구축해둔 바 있었습니다. 다만 AZ(Available Zone)마다 NAT 인스턴스를 둘 필요성이 적고 비용을 아끼기 위해 ap-northeast-2a 에만 배치하고, 다른 AZ 에 속하는 private subnet 들도 이를 이용하게 route table 을 설정해두었습니다. 만약 AWS ap-northeast-2a 에 장애가 발생한다면 모든 AZ 의 private subnet 들이 외부 인터넷으로의 연결을 못해 고가용성을 보장하기 위한 AZ 분할의 의미가 떨어질 것입니다. 회사 등 안정성이 중요한 경우라면, 반드시 AZ 마다 NAT 를 배치해야 합니다. 별개로, 다른 AZ 간 data transfer 에 대해 AWS 가 비용을 부과한다는 점도 고려되어야 합니다. 저 같은 경우엔 이 점들을 인지하고 일단 하나의 NAT 인스턴스만 이용하게 유지해두었습니다. 노파심에 첨언하자면, NAT 역할이 속한 Security Group 의 inbound rule 에, 연결할 private subnet 의 대역을 추가하는 것을 잊고 삽질하지 않기를 바랍니다. (예전 메모에 적어둔 걸 보니 과거의 저도 삽질했나 봅니다.)

선언적 관리와 GitOps 를 위한 GitHub repo ‘waffle-world

K8S 는 kubectl 의 여러 커맨드를 통해 리소스들을 생성/수정/삭제하는 등 명령형 방식으로 이용 가능하지만, 다른 사람들과 협업하는 cluster 에서 이런 식으로 각자 필요에 따라 명령을 날리게 된다면 곧 대혼란의 상황에 빠질 것입니다. 각 명령을 누가 적용했는지 어떻게든 추적을 하고, RBAC 으로 권한 관리를 하여 잠재적 문제를 줄일 수도 있겠지만, 한 눈에 현재 상황을 알기도, 실수를 방지하기도 어렵습니다. 또한 명령형 방식은 현재의 상태를 확인 후 원하는 상태를 만들기 위해 필요한 동작을 지시하는 것인데, 자칫 동일한 명령을 중첩해서 내리면 상태가 꼬일 수도 있을 것입니다.

때문에 용이한 cluster 운영을 위해서는, 원하는 상태 자체를 기술하는 것에 집중하는 선언적 방식을 이용하는 것이 이롭습니다. 대표적인 방식이 리소스에 대해 바라는 상태를 기술한 manifest yaml 파일을 작성하고, kubectl apply -f 로 적용하는 것입니다. 이러한 manifest 파일들을 Git 으로 관리한다면 main branch 의 최신 Git 상황이 즉 현 cluster 상황이 되어, 상시적으로 현 상태를 파악하기 쉬울 것입니다. 누가 어떤 변경을 적용했는지는 Git history 를 보면 됩니다. GitHub 과 같은 서비스를 이용한다면, PR 방식으로 변경 사항을 제안하고 함께 리뷰할 수 있으며, 권한 있는 사람이 approve 및 merge 하고 해당 변경을 적용할 수 있습니다.

서버 코드를 Git 으로 관리하다 특정 branch 에 적용하면 자동 배포까지 되는 CD 를 구축하는 것처럼, Git 으로 작성한 infra 상태 기술 파일들이 실제 상황에 자동 반영되게 하는 개념을 GitOps 라고 합니다. Argo CD 가 K8S 에 대한 GitOps 를 쉽게 운영할 수 있도록 해주는 유명한 도구입니다.

저는 Argo CD 를 이용해 GitOps 를 cluster 운영에 적용하고 싶었고, 협업과 학습 차원에서도 cluster 당시 상황이 최대한 git 에 반영되기를 바랐기 때문에, waffle-world 라는 GitHub repository 를 만들었습니다. (관심 있는 분들은 ⭐️ 해주셔도 좋습니다!) 이 글을 작성하는 2023년 3월 기준으로, 해당 repo 의 apps/ 하위는 변경 사항이 Argo CD 를 통해 cluster 에 자동 반영됩니다. cluster infra 상 매우 중요한 부분은 Argo CD 로 관리하는 것은 부담스럽다고 보았기에, 직접 kubectl 이나 Helm 으로 적용했습니다. charts/ 에는 Helm 으로 적용한 파일들이, misc/ 는 kubectl 로 적용한 파일들이 존재합니다. 갑자기 여러 얘기가 쏟아졌는데, Helm 및 Argo CD 에 관련해선 나중에 더 다룰 것입니다.

Ingress 생성 및 관련 add-on 설치, OIDC provider 설정

일반적인 서비스 용도의 cluster 라면 외부의 유저 트래픽이 내부로 들어올 수 있어야 할 것입니다. 이를 위해 필요한 것이 Ingress 입니다. Istio 라는 cluster 네트워킹 레이어를 담당하는 service mesh 플랫폼이 워낙 많이 쓰이고 있어서 Istio 가 반드시 필요하다거나 Ingress 가 Istio 의 개념이라고 착각하는 경우가 있지만, 그렇지 않습니다. Istio 는 어디까지나 K8S cluster 를 구축하는 데에 사용할지 선택할 수 있는 기술이며, Istio 없이도 충분히 동작하는 cluster 를 구축 가능합니다.(‘쿠버네티스 인 액션’ 같은 K8S 초창기 책을 보면 Istio 언급이 없습니다.) 물론, 현실적으로는 Istio 를 안 쓸 이유가 없다고 생각하며 사용하는 것을 권장합니다.

저 같은 경우 공부 목적도 있고 차근차근 이해도를 높여가며 cluster 구축을 진행하고 싶었기에, 최초에는 Istio 없이 Ingress 를 설정했으며, 따로 Istio 를 적용했습니다. Ingress 만 사용할 당시의 K8S manifest 파일들은 waffle-world 의 이 history 쯤에서 확인 가능합니다.

ALB Ingress 를 cluster 앞단에 위치시키고, Istio Ingress Gateway 의 Service 를 NodePort 타입으로 설정한 모습.

여기선 Istio 를 사용하면서 K8S Ingress 에 AWS ALB(Application Load Balancer)를 적용한다는 전제로 진행하겠습니다. ALB 유형의 LB 를 사용하기 위해서는 결국 cluster 앞단에서 Ingress 를 이용해야 합니다. AWS 가 제공하는 LB 는 ALB 외에도 NLB(Network LB), CLB(Classic LB) 가 있습니다. CLB 는 deprecated 되었으며, NLB 는 OSI 모델 기준 4계층에서, ALB 는 7계층에서 동작합니다. Istio Ingress Gateway 를 사용해 LB 를 구성한다고 해도 결국 K8S Service 리소스의 LoadBalancer 타입을 이용하는 것인데, Service 를 LB 로 사용하는 경우에는 AWS ALB 사용이 불가능합니다. ALB 를 cluster 앞단에 두면 외부 HTTPS 트래픽에 대해 해당 지점에서 SSL termination을 하여 cluster 내부적으론 관련 오버헤드 없이 통신할 수 있는 등 OSI 7계층 수준을 활용한 섬세한 제어가 가능해집니다.

이 경우, 위 그림처럼 AWS ALB 를 이용하는 Ingress 가 cluster 의 모든 서비스에 대한 요청을 받아 전부 Istio Ingress 의 Service 로 보내고, 해당 Service 가 가리키는 Ingress Gateway 가 cluster 내부의 트래픽 흐름을 관장하여 각 VirtualService 로 라우팅 합니다. Ingress 만을 사용하여 cluster 라우팅을 하는 경우와 비교해보면, Istio 에게 clsuter 네트워킹 역할을 모두 위임한 것입니다.

Istio 자체에 대한 구체적인 내용은 나중에 다루고, 일단 Ingress 에 집중해보겠습니다. Ingress 라는 K8S 리소스를 만드는 것만으로 AWS 라는 클라우드 서비스의 ALB 가 생성 및 연결되는 것이 가능하려면, cluster 에 AWS Load Balancer Controller add-on 을 설치해야 합니다. AWS 문서를 참고하면 어렵지 않게 진행 가능하며, waffle-world 에서 해당하는 내용은 여기에 있습니다.

cluster 의 infra 와 관련해서 Controller 라는 용어를 자주 접할 수 있습니다. K8S 에는 다양한 Controller 들이 존재합니다. 기본적인 것들로는 Node Controller, Job Controller 등이 있으며, 각자 자신이 담당하는 리소스의 상황을 모니터링하다가, 필요한 경우 자동으로 적절한 조치를 취하는 개별 프로세스들이라고 할 수 있습니다. 이러한 Controller 들을 실행하는 구성요소가 control plane 의 kube-controller-manager 입니다.

생성한 EKS cluster Overview 에서 볼 수 있는 OIDC provider URL

설치 과정에서 빠뜨리지 말아야 할 것은 OIDC(OpenID Connect) 관련 설정입니다. ServiceAccount 는 Pod, Service 처럼 K8S 리소스 중 하나이며, 사람이 아닌 Pod 와 같은 리소스에 권한을 부여하는 역할을 가집니다. aws-load-balancer-controller 역시 ALB 를 생성하는 등의 동작을 하기 위해 ServiceAccount 가 필요(관련 yaml)합니다. EKS cluster 는 ServiceAccount 에 IAM role 을 연결(관련 yaml)할 수 있습니다. cluster 가 이렇게 AWS 리소스들과 연동하는 경우 AWS 와 일정한 인증 과정이 필요할 것입니다. 이러한 연동을 가능하게 하는 것이 OIDC 라는 OAuth 2.0 을 이용해 만들어진 인증 레이어입니다. EKS cluster 를 생성하면 OIDC provider URL 이 함께 만들어지므로, 이를 이용해 IAM 에서 Identity Provider 를 생성하면 됩니다. 앞으로 cluster 내에서 사용할 IAM role 을 만드는 경우, 해당 OIDC provider 를 이용해 Trust relationships 를 아래와 같은 식으로 설정해줍니다.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::12345:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/ABCDE"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.ap-northeast-2.amazonaws.com/id/ABCDE:aud": "sts.amazonaws.com",
"oidc.eks.ap-northeast-2.amazonaws.com/id/ABCDE:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
}
}
}
]
}

이 경우 마지막 부분에 “~:sub”을 보면 kube-system NameSpace 의 aws-load-balancer-controller 를 전제하여 설정하고 있음을 확인할 수 있습니다. 이는 해당 IAM role 을 부여받을 수 있는 대상을 제한한 것으로, 필수는 아닙니다. 만약 IAM role 마다 sub 으로 cluster 의 리소스를 명시하기로 결정했다면, 이 부분에서 실수하지 않아야 할 것입니다.

와플스튜디오는 *.wafflestudio.com 에 대한 HTTPS 인증서를 ACM(AWS Certificate Manager)을 이용해 기존에도 관리하고 있었습니다. Ingress ALB 가 이러한 인증서를 다룰 수 있으려면, cert-manager 또한 설치해야 합니다. 저는 아래와 같이 인터넷에서 해당 manifest 를 다운받아 바로 적용했으며, 똑같이 진행한다면 v1.9.1 에 해당하는 부분을 적절한 버전으로 수정하면 될 것입니다.

kubectl apply --validate=false -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml

결과적으로 Ingress 의 manifest 파일을 살펴보면 아래와 같습니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: istio-ingress
name: istio-gateway-alb
annotations:
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/subnets: subnet-087aa13726bc757a3, subnet-0040edcc601f06fcf
alb.ingress.kubernetes.io/group.name: "ingress-external-group"
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:405906814034:certificate/69084f78-4a27-40b8-b6a6-065e27219174
alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: istio-ingressgateway
port:
number: 80

annotations 들에 중요한 정보가 있는데, target-type 이 instance 가 아닌 ip 인 것은 cluster 의 node 단위가 라우팅 대상이 아니라는 것을 나타냅니다. node 인스턴스를 의식하지 않고 istio-ingressgateway 라는 Pod 앞의 Service 로 트래픽을 라우팅할 것이므로 이렇게 설정했습니다. scheme 이 internet-facing 인 것은 VPC 외부에서의 요청을 받는다는 것을 뜻합니다. internal 로 설정하면 VPC 내부에서의 접속만 가능하게 됩니다. VPC 외부에서의 요청을 받아야하기 때문에 지정한 subnets 들은 internet gateway 가 route table 에 연결되어 있는 public subnet 들입니다. certificate-arn 은 cert-manager 를 통해 이용하는 ACM 인증서 리소스를 가리키며, ssl-redirect 를 통해 HTTP 를 HTTPS 로 자동 리아디렉트시키도록 합니다. group.name 에 지정한 이름은, 아래처럼 결과적으로 생성된 ALB 의 이름에 반영된 것을 확인할 수 있습니다.

이러한 Ingress 를 kubectl 로 적용하면 ALB 가 자동으로 생성될 것입니다. 앞으로 cluster 내 서비스들에 대한 도메인이 생길 때마다 이 ALB 로 연결하면 됩니다. 결과적으로 K8S 로의 이주를 성공적으로 마친 후의 이야기지만, ALB 의 비용이 결코 적지 않기 때문에, 어떤 경우 서버마다 ALB 를 쓰고 있던 것을 이렇게 하나로 줄이면서 EKS 를 사용하며 생긴 추가 비용을 상쇄할 수 있었습니다.

cluster 에 있는 여러 서버에 해당하는 endpoint 들이 하나의 Ingress ALB 로 연결된 Route 53 의 모습

다음으로

EKS cluster 를 AWS 콘솔에서 생성하는 시점부터, 외부 트래픽이 cluster 내부로 들어올 수 있도록 하는 과정을 설명하고 중간중간 K8S 의 대표적인 개념들과 네트워크 및 권한 관련 내용들을 다뤘습니다. 그러나 아직 K8S 운영과 관련해 다루지 않은 내용이 꽤 있습니다. 정작 Deployment 를 이용해 서버를 배포하는 것은 언급도 하지 않았습니다. 다음에는 Helm 을 이용해 Istio 와 Argo CD 를 설치하고 적용하는 방법과, 현재 와플스튜디오 cluster 구조 및 각 팀들이 서버 자동 배포에 사용하고 있는 파이프라인, 그리고 개발자 권한 관리 등을 다뤄보도록 하겠습니다.

--

--