[Kubernetes] EKS(Elastic Kubernetes Service)

EKS(Elastic Kubernetes Service) 와 온프레미스 Kuberentes 환경 차이 

AWS의 EKS(Elastic Kubernetes Service)와 온프레미스 Kubernetes의 가장 큰 차이는 마스터 노드(제어 플레인)의 관리 주체에 있다. EKS는 마스터 노드를 AWS가 완전하게 관리하며, 사용자는 EC2 기반의 노드 그룹을 생성하거나 서버리스 환경인 Fargate를 선택해 워커 노드 없이도 서비스를 운영할 수 있다. 또한 EKS에서는 클러스터 버전 업그레이드가 상대적으로 수월하다. Terraform을 활용한 자동화는 물론, AWS 콘솔에서 수동으로도 간편하게 진행할 수 있다.

반면, 온프레미스 Kubernetes는 컨트롤 플레인 설치부터 업그레이드, 장애 복구까지 모든 작업을 수동으로 직접 처리해야 한다. 노드 운영 측면에서는 온프레미스는 물리 서버나 가상머신을 직접 구성하고 보안, 네트워크 정책도 스스로 세팅해야 한다. 

스토리지 연동 역시 EKS는 EBS, EFS 등 AWS 스토리지 서비스를 바로 사용할 수 있는 반면, 온프레미스는 Ceph, NFS, NAS 등을 직접 구축하고 연동해야 한다. 개인적인  생각으로는 온프레미스 Kubernetes환경을 Private환경으로 잘 만 구성한다면 EKS에 비해 높은 보안성을 유지할 수 있지 않을까 생각한다. 

즉, EKS는 쿠버네티스를 쉽고 안정적으로 운영할 수 있는 매니지드 플랫폼이고, 온프레미스는 유연성은 높지만 그만큼 관리와 운영 부담이 큰 구조다.

ISRA(IAM Roles for Service Accounts)

AWS 공식문서: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html

IRSA(IAM Roles for Service Accounts)는 Kubernetes의 ServiceAccount에 IAM Role을 연결하여, Pod 단위로 AWS 리소스에 대한 접근 권한을 부여하는 메커니즘이다.
기존의 일반 VM 환경에서는 인스턴스 단위로 IAM 역할을 부여했다면, IRSA는 Pod에 붙는 ServiceAccount에 IAM Role을 연결함으로써 더 세분화된 보안 제어가 가능하다.

IRSA를 구성하기 위해서는 먼저 EKS 클러스터를 OIDC 제공자로 등록하여 AWS가 해당 클러스터의 Pod를 인증할 수 있도록 해야 한다. 그 후, 필요한 AWS 리소스에 접근할 수 있는 IAM Role을 생성하고,이를 사용하려는 Pod에 연결될 ServiceAccount를 생성하여 IAM Role과 연결해주면 된다.

aws-loadbalancer-controller

aws 공식문서 : https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/lbc-helm.html

EKS는 기본적으로 AWS API를 인식하지 못하여 AWS 리소스인 ALB(Application Load Balancer)를 직접 만들 수 없다. 그래서 EKS안에서 ALB를 대신 생성해주는 역할이 필요한데, 그게 바로 aws-load-balancer-controller다.

이 컨트롤러는 Kubernetes 안에서 동작하는 하나의 Pod이며, 사용자가 Ingress 리소스를 생성하면 이를 감지하고 AWS API를 호출해 ALB를 자동으로 생성, 관리하는 역할을 한다.

하지만 ALB는 AWS 리소스이기 때문에, AWS API를 사용하려면 반드시 IAM 권한이 필요하다. 이 컨트롤러 Pod는 Kubernetes의 ServiceAccount로 실행되며, 기본적으로는 AWS 권한이 없다.

그래서 OIDC(OpenID Connect)를 이용해 EKS의 ServiceAccount와 AWS IAM 역할을 연결시킨다. 이렇게 하면 이 Pod는 마치 IAM 사용자인 것처럼 AWS API를 사용할 수 있게 되고, 결국 Ingress 생성 시 자동으로 ALB를 만들 수 있는 구조가 되는 것이다.

EKS에서 제공하는 공식 Add-on은 아니지만 , Helm 차트에서 손쉽게 Controller를 다운받을 수 있다.

aws 공식 Helm: https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/lbc-helm.html

Amazon EBS CSI Driver

AWS 공식문서 : https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/ebs-csi.html

EKS에서는 기본적으로 Kubernetes 자체가 스토리지를 직접 생성하거나 연결하는 기능이 없다. 따라서 Kubernetes에서 EBS 볼륨을 자동으로 생성하고 마운트하려면 Amazon EBS CSI Driver라는 Add-on을 설치해야 한다. 이 드라이버는 Kubernetes에서 PVC(PersistentVolumeClaim) 요청이 들어오면, 이를 감지하여 AWS API를 호출해 EBS 볼륨을 생성하고, 해당 볼륨을 Pod가 실행되는 노드(EC2 인스턴스)에 자동으로 attach해준다. 또한 EBS와 같은 AWS 리소스를 조작하기 위해서는 IAM 권한이 필요하기 때문에, aws-ebs-csi-driver에는 적절한 IAM Role을 IRSA 방식으로 연결해주어야 한다. 즉, Amazon EBS CSI Driver는 EKS 환경에서 EBS 볼륨을 동적으로 생성하고 연결할 수 있게 해주는 핵심 Add-on이다. 이 외에도 AWS는 EFS, FSx 등 다양한 CSI Driver를 제공한다.

구성 요소: Controller와 DaemonSet

EBS CSI Driver를 설치하면 두 가지 주요 컴포넌트가 생성된다

  • Controller (Deployment)
    중앙에서 PVC 요청을 감지하고 AWS API를 호출해 EBS 볼륨을 생성하는 역할
  • Node (DaemonSet)
    각 노드에 하나씩 실행되며, EBS 볼륨을 노드에 attach/mount 또는 detach/unmount하는 실질적인 작업을 수행

주로 다음과 같이 PVC와 SC를 사용하여 Dynamic Provisioning을 한다. 

--- pvc 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  storageClassName: gp3-sc
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10G
--- sc 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3-sc
provisioner: ebs.csi.aws.com
parameters:
  type: gp3

External DNS

https://repost.aws/ko/knowledge-center/eks-set-up-externaldns

 AWS에서 도메인은 보통 Route 53과 같은 외부 DNS 서비스에 도메인을 수동으로 등록하고, 레코드를 직접 지정해야 한다. 하지만 EKS에서는 Ingress를 생성한 후 도메인 등록을 자동화하기 위해 External DNS라는 컴포넌트를 사용할 수 있다. External DNS는 클러스터 내에서 Ingress나 Service 리소스를 주기적으로 감지하고, 해당 리소스에 설정된 도메인을 기반으로 Route 53에 자동으로 레코드를 생성하거나 삭제해준다. Ingress를 하나만 사용하는 경우도 있지만, 실제 운영 환경에서는 Grafana, ArgoCD 같은 여러 오픈소스 도구들도 도메인이 자동 등록되어 매우 편리하다. 

보통 이 컴포넌트는 Kubernetes 클러스터 내에 Deployment 리소스 형태로 실행되며,도메인 정보의 등록 상태를 Route 53과 동기화(sync)하는 역할을 한다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    external-dns.alpha.kubernetes.io/hostname: myapp.example.com //
spec:

다음과 같이 Ingress에  external-dns.alpha.kubernetes.io annotations를 추가하면된다.