전공영역 공부 기록

EKS AMI에 user data설정하는 방법

악분 2024. 12. 31. 15:30
반응형

 

1. 개요

이 글은 EKS AMI에 user data를 설정하는 방법을 설명합니다. 여기서는 managed node group과 karpenter를 사용하는 두 가지 방법에 대해 설명합니다.


2. 배경지식

1) EKS 워커 노드는 EC2 인스턴스를 사용합니다.
2) EKS는 EKS AMI를 사용합니다.

3. EKS AMI의 user data에는 EKS 클러스터에 조인하는 스크립트가 포함되어 있습니다. EKS 클러스터 조인은 nodeadm을 사용합니다.

 

 

3. Managed Node Group에 user data 설정 방법

3.1 설정 방법

managed node group에 user data를 설정하려면 MIME 포맷으로 작성해야 합니다. MIME 포맷은 여러 데이터를 하나로 합칩니다. 이는 이메일에서 사용되는 포맷이며, 오늘날 HTTP, cloud-init 등에서도 사용됩니다. MIME 포맷 작성 방법은 EKS 공식문서에 설명되어 있습니다.

 

1) MIME 포맷의 시작은 MIME-Version으로 시작합니다.

2) 다음 줄에는 Content-Type과 여러 데이터의 경계인 boundary를 설정합니다. 아래 예제는 데이터 경계를 "\==MYBOUNDARY\=="로 구분합니다.

3) 데이터 구분은 dash 두 개(--) + boundary입니다.

4) MIME 포맷 맨 끝에는 dash 두 개(--) + boundary + dash 두 개(--) 입니다.

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="==MYBOUNDARY=="

--==MYBOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
echo "Running custom user data script"

--==MYBOUNDARY==--

 

MIME 포맷으로 작성하지 않으면 user data 유효성검사 오류가 발생합니다.

Ec2LaunchTemplateInvalidConfiguration: User data was not in the MIME multipart format

 

최종 user data는 EKS AMI user data와 여러 분의 user data가 합쳐진 결과입니다. 따라서 최종 user data는 아래 형태입니다.

EKS 클러스터 조인 + 여러 분의 user data

 

3.2 테라폼에서 작업

Managed node group의 user data는 launch template에 설정합니다. user data는 base64인코딩이 되어 있어야 합니다.

resource "aws_launch_template" "example" {
  user_data = base64encode(<<EOF
#!/bin/bash
echo "Running custom user data script"
EOF
  )
}

resource "aws_eks_node_group" "example" {
  cluster_name    = example
  node_group_name = "example-node-group"
  
  scaling_config {
    desired_size = 2
    max_size     = 3
    min_size     = 1
  }

  launch_template {
    id      = aws_launch_template.example.id
    version = "$Latest"
  }
}

 

3.3 예제

예제코드: https://github.com/choisungwook/portfolio/tree/master/kubernetes/eks/eks_ami_with_userdata

 

예제는 managed node group이 시작할 때 nginx를 설치하고 시작하도록 설정했습니다. launch template에 user data를 아래처럼 설정했습니다.

resource "aws_launch_template" "example" {
  user_data = base64encode(<<EOF
#!/bin/bash
dnf update -y
dnf install -y nginx
systemctl start nginx
systemctl enable nginx
EOF
  )
}

 

user data가 잘 적용되었는지 확인하려면, terraform apply결과가 아래처럼 "Apply complete"가 보여야 합니다.

terraform apply

 

kubectl get node할 때 node가 보여야합니다.

kubectl get node

 

새로 추가된 노드(EC2 인스턴스)의 user data에는 EKS 클러스터 조인 설정과 nginx설치 명령어가 있습니다.

 

 

EC2인스턴스 쉘에서 nginx가 실행되고 있는지 확인합니다.

 

4. karpenter user data 설정 방법

4.1 설정 방법

karpenter에서 user data설정은 managed node group보다 쉽습니다. nodeclass에서 userData필드에 EC2인스턴스가 실행될 때 원하는 작업내용만 설정하면 됩니다.

apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: example
spec:
  userData: |
    #!/bin/bash
    dnf update -y
    dnf install -y nginx
    systemctl start nginx
    systemctl enable nginx

 

karpenter는 userData에 설정된 내용을 EKS AMI user data와 병합합니다. managed node group 동작과 동일합니다. 차이점은 managed node group은 user data를 MIME포맷으로 작성해야 하고 karepnter는 바로 작성하면 됩니다.

 

karpenter가 설정된 EC2 인스턴스 user data를 확인하면, managed node group과 차이점이 보입니다. karpenter user data가 먼저 실행되고 그다음 EKS 클러스터 조인 명령어가 실행됩니다.

 

4.2 예제

karpenter 예제는 저의 github 있습니다.

 

5. user data보다는 daemonset을 권장

쿠버네티스 관점에서는 user data로 노드 공통 설정하는 것은 바람직하지 않다고 생각합니다. 쿠버네티스에서는 노드 공통 설정을 daemonset으로 할 수 있어 쿠버네티스 메커니즘으로 노드를 관리하는게 바람직합니다. user data로 노드를 커스터마이징을 하면 쿠버네티스도 확인하고 노드도 확인해야 하는 이중작업이 필요합니다. 

그러므로, daemonset으로 설정하지 못한 노드 설정만 user data로 하는 것이 좋습니다. 또는 golden AMI를 사용하는 선택지도 있습니다. golden AMI를 생성하면 EKS 클러스터 조인하는 설정이 user data에 있어야 합니다.

 

 

참고자료

반응형