지난 포스트 글에 이어 Packer를 통해 EKS Node에 대한 최적화 AMI를 구성하겠습니다. 먼저, AWS 공식문서를 참고하면 EKS 최적화 AMI 구성 내용을 확인할 수 있는데요. 주요 구성 요소와 특징은 다음과 같습니다.
- 최신 EKS addon 구성
- AWS IAM 인증 관리
- 커널 업그레이드 및 최적화
- 워크 노드 필수 패키지 설치 : 컨테이너 엔진 설치
- 보안 및 프라이버시 이벤트 추적
- GPU 드라이버 설치 및 가속 설정
공식 문서 마지막을 참고하면, 최적화 AMI를 빌드하는 데 사용되는 오픈소스 스크립트를 확인할 수 있습니다.
amazon-eks-ami
https://github.com/awslabs/amazon-eks-ami/tree/master
https://awslabs.github.io/amazon-eks-ami/USER_GUIDE/ (가이드)
Packer를 사용하여 Amazon EKS 최적화 Amazon Linux AMI를 사용자 지정하여 구축하기 위한 구성 스크립트와 리소스를 제공하는 오픈소스 프로젝트입니다. amazon-eks-ami는 awslabs의 프로젝트로 AWS가 공식적으로 지원하는 프로젝트입니다. 구성 스크립트를 통해 사용자 정의의 AMI를 최적화된 EKS worker node AMI로 생성해줍니다.
사용자 지정의 AMI를 기반으로 노드 최적화 스크립트를 실행하여 워크 노드 최적화 AMI를 구성합니다. amazon-eks-ami의 동작 구성을 확인하여 최적화 과정을 이해하겠습니다.
실행 원리
amazon-eks-ami 는 Packer 실행을 Make 유틸리티를 통해 감싸서 실행합니다. 이유는 EKS 버전별 addon 바이너를 s3에 찾아 가져와야하기 때문인데요. Makefile 구성을 확인하면 다음과 같이 확인할 수 있습니다.
[ec2-user@kops-ec2 amazon-eks-ami]$ make help
which: no shfmt in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/root/.krew/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin)
which: no shellcheck in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/root/.krew/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin)
Usage:
make <target>
build Build EKS Optimized AL2 AMI
fmt Format the source files
lint Check the source files for syntax and format issues
test run the test-harness
validate Validate packer config
k8s Build default K8s version of EKS Optimized AL2 AMI
1.23 Build EKS Optimized AL2 AMI - K8s 1.23
1.24 Build EKS Optimized AL2 AMI - K8s 1.24
1.25 Build EKS Optimized AL2 AMI - K8s 1.25
1.26 Build EKS Optimized AL2 AMI - K8s 1.26
1.27 Build EKS Optimized AL2 AMI - K8s 1.27
1.28 Build EKS Optimized AL2 AMI - K8s 1.28
lint-docs Lint the docs
help Display help
makefile 의 실행 부분을 확인하면 k8s는 packer 실행 명령어이며, $(shell hack/latest-binaries.sh 1.2X) 에서 버전별 워커노드에 맞는 변수들을 설정합니다. 스크립트를 실행한 결과의 환경 변수를 가지고 Packer를 실행합니다.
.PHONY: k8s
k8s: validate ## Build default K8s version of EKS Optimized AL2 AMI
@echo "$(T_GREEN)Building AMI for version $(T_YELLOW)$(kubernetes_version)$(T_GREEN) on $(T_YELLOW)$(arch)$(T_RESET)"
$(PACKER_BINARY) build -timestamp-ui -color=false $(PACKER_VAR_FLAGS) $(PACKER_TEMPLATE_FILE)
.PHONY: 1.23
1.23: ## Build EKS Optimized AL2 AMI - K8s 1.23
$(MAKE) k8s $(shell hack/latest-binaries.sh 1.23)
.PHONY: 1.24
1.24: ## Build EKS Optimized AL2 AMI - K8s 1.24
$(MAKE) k8s $(shell hack/latest-binaries.sh 1.24)
.
.
.
- 환경 변수 설정 스크립트를 확인하면 s3 버킷에서 EKS 노드의 버전 & 아키텍처의 맞는 addon 바이너리를 검색하여 가져오는 것을 확인할 수 있습니다.
# hack/latest-binaries.sh
MINOR_VERSION="${1}"
# retrieve the available "VERSION/BUILD_DATE" prefixes (e.g. "1.28.1/2023-09-14")
# from the binary object keys, sorted in descending semver order, and pick the first one
LATEST_BINARIES=$(aws s3api list-objects-v2 --bucket amazon-eks --prefix "${MINOR_VERSION}" --query 'Contents[*].[Key]' --output text | cut -d'/' -f-2 | sort -Vru | head -n1)
if [ "${LATEST_BINARIES}" == "None" ]; then
echo >&2 "No binaries available for minor version: ${MINOR_VERSION}"
exit 1
fi
LATEST_VERSION=$(echo "${LATEST_BINARIES}" | cut -d'/' -f1)
LATEST_BUILD_DATE=$(echo "${LATEST_BINARIES}" | cut -d'/' -f2)
...
# List build dates
aws s3 ls s3://amazon-eks/1.25.15/
# List platforms
$ aws s3 ls s3://amazon-eks/1.25.15/2023-11-14/bin/
PRE darwin/
PRE linux/
PRE windows/
$ aws s3 ls s3://amazon-eks/1.25.15/2023-11-14/bin/linux/amd64/
2023-11-15 09:06:06 53121024 aws-iam-authenticator
2023-11-15 09:06:06 55 aws-iam-authenticator.md5
2023-11-15 09:06:06 63 aws-iam-authenticator.sha1
2023-11-15 09:06:07 87 aws-iam-authenticator.sha256
2023-11-15 09:06:07 1865035 cni-amd64-v0.6.0.tgz
2023-11-15 09:06:07 54 cni-amd64-v0.6.0.tgz.md5
2023-11-15 09:06:07 62 cni-amd64-v0.6.0.tgz.sha1
2023-11-15 09:06:07 86 cni-amd64-v0.6.0.tgz.sha256
2023-11-15 09:06:07 40517426 cni-plugins-linux-amd64-v1.2.0.tgz
2023-11-15 09:06:07 68 cni-plugins-linux-amd64-v1.2.0.tgz.md5
2023-11-15 09:06:07 76 cni-plugins-linux-amd64-v1.2.0.tgz.sha1
2023-11-15 09:06:07 100 cni-plugins-linux-amd64-v1.2.0.tgz.sha256
2023-11-15 09:06:07 15671296 ecr-credential-provider
2023-11-15 09:06:07 57 ecr-credential-provider.md5
2023-11-15 09:06:07 65 ecr-credential-provider.sha1
2023-11-15 09:06:07 89 ecr-credential-provider.sha256
2023-11-15 09:06:07 41930752 kube-proxy
2023-11-15 09:06:07 44 kube-proxy.md5
2023-11-15 09:06:07 52 kube-proxy.sha1
2023-11-15 09:06:07 76 kube-proxy.sha256
2023-11-15 09:06:07 45658112 kubectl
2023-11-15 09:06:07 41 kubectl.md5
2023-11-15 09:06:07 49 kubectl.sha1
2023-11-15 09:06:07 73 kubectl.sha256
2023-11-15 09:06:07 120671264 kubelet
2023-11-15 09:06:07 41 kubelet.md5
2023-11-15 09:06:07 49 kubelet.sha1
2023-11-15 09:06:07 73 kubelet.sha256
환경변수 설정이 되었다면, make를 통해 packer에서 구성된 스크립트를 실행하여 AMI를 생성합니다. AWS-EKS-AMI 에서는 어떻게 이미지를 최적화하였는 지 확인하겠습니다.
이미지 최적화 빌드
빌드 부분은 scripts 폴더의 스크립트를 가져와 실행합니다.
- {{user ami_name}} : 사용자 정의 변수, {{user working_dir}} 로컬 작업 디렉토리, { user remote_folder}} : 원격 작업 디렉토리 , {{template_dir}} : 템플릿 파일이 위치한 디렉토리 경로(내장변수)
- 로컬에서 원격으로 폴더를 복사하고 노드 설정 스크립트를 순차적으로 실행합니다. 순차적으로 로그 스크립트, 커널 업그레이드, 워커 노드 설치와 설치 패키지 삭제를 실행합니다.
- post-processors : 이미지가 성공적으로 생성된 이후에 작업입니다. 빌드 정보를 포함하는 매니페스트 파일을 생성합니다.
스크립트 작업 이해하기
json에 정의한 AMI에 따라 인스턴스가 구성되면 provisinoer 작업을 순차적으로 진행합니다.
로그 컬렉터 스크립트 설정 (/log-collector-script/eks-log-collector.sh)
워크 노드 구성의 로그를 기록하기 위한 스크립트입니다. 워크 노드가 구성된다면 로그 디렉토리 /etc/eks/log-collector-script/ 에서 다음과 같이 확인할 수 있고, 옵션에 따라 aws ssm 을 이용하여 s3 버킷에 로그를 업로드할 수 있습니다. 기본 디렉토리에 저장되는 로그 형식은 다음과 같습니다.
$ sudo bash eks-log-collector.sh
This is version 0.7.3. New versions can be found at https://github.com/awslabs/amazon-eks-ami/blob/master/log-collector-script/
Trying to collect common operating system logs...
Trying to collect kernel logs...
Trying to collect mount points and volume information...
Trying to collect SELinux status...
Trying to collect iptables information...
Trying to collect installed packages...
Trying to collect active system services...
Trying to Collect Containerd daemon information...
Trying to Collect Containerd running information...
Trying to Collect Docker daemon information...
Warning: The Docker daemon is not running.
Trying to collect kubelet information...
Trying to collect L-IPAMD introspection information... Trying to collect L-IPAMD prometheus metrics... Trying to collect L-IPAMD checkpoint...
Trying to collect Multus logs if they exist...
Trying to collect sysctls information...
Trying to collect networking infomation... conntrack v1.4.4 (conntrack-tools): 165 flow entries have been shown.
Trying to collect CNI configuration information...
Trying to collect Docker daemon logs...
Trying to Collect sandbox-image daemon information...
Trying to Collect CPU Throttled Process Information...
Trying to Collect IO Throttled Process Information...
Trying to archive gathered information...
Done... your bundled logs are located in /var/log/eks_i-XXXXXXXXXXXXXXXXX_2022-12-19_1639-UTC_0.7.3.tar.gz
추가 repo 구성 (scripts/install_additional_repos.sh)
사용자 정의의 repo를 구성합니다.
[patches-repo]
name=Install patches
baseurl=http://amazonlinux.us-east-1.amazonaws.com/patches
priority=10
커널 업그레이드 및 최적화 (scripts/iupgrade_kernel.sh, enable-fips.sh)
쿠버네티스 버전에 맞춰 자동으로 커널 버전을 설정하고 최적화하는 스크립트입니다.
- K8s 1.24.0 이상 버전에서는 커널 5.10을 그보다 낮은 버전에서는 커널 버전 5.2을 사용합니다. 또한, 커널 패키지(kernel, kernel-header, kernel-devel)를 설치하여 시스템 최적화 환경을 구성합니다.
- 시스템 안정성과 성능을 향상시키기 위해 pressure stall information(PSI) 기능,tsc 클록소스, fips를 활성화 합니다.
워크 노드 환경 구성(install-worker.sh)
워크 노드 환경 구성을 위한 스크립트입니다. 구성 스크립트에서 실행되는 항목은 다음과 같습니다.
- 커널 버전 정리 & 필요 yum 패키지 설치
- VPC CNI을 위한 네트워크 설정 (amazon linux 2023일 경우)
- eks 환경 경로 설정(clocksource, Iptables, systemd) 설정된 서비스는 /etc/eks/ 에서 확인이 가능합니다.
- 보안 설정(sshd)
- awscli, containerd, nerdctl, docker(< 1.25) 설치
- kubernetes 경로 설정 및 바이너리 설치
- iam-auth 버전 검증, CNI 플러그인 설치, KubeletCredentialProviders 활성화
- EKS 설정 파일 복사
- ECR 프로바이더, 캐시 이미지 설정
- AMI 메타데이터 설정
- AWS SSM agnet, logrotate 설치, 로그 활성화(cloud-init, log-collect-script)
- 커널 보안 설정, sysctl 프로퍼티 설정
설치 패키지 정리 및 유효성 검증 (cleanup.sh, vaildate.sh)
설치한 패키지 파일들을 삭제하고, 설정한 파일 및 경로들이 정상적으로 구성 확인 및 버전 체크가 실행됩니다
위 스크립트를 기반으로 AMI가 생성됩니다. 해당 AMI를 통해 노드 구성시 file/bootstrap.sh 가 실행되어 노드 구성을 시작합니다.
amazon-eks-ami 테스트
베스천 환경 구성 및 packer 빌드 실행
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
sudo yum -y install packer
packer plugins install github.com/hashicorp/amazon
git clone https://github.com/awslabs/amazon-eks-ami.git
cd amazon-eks-ami
make 1.28
테스트
생성된 AMI를 기반으로 EKS 노드가 정상적으로 등록되는 지 확인하겠습니다. 콘솔에서 생성된 AMI 이름을 아래 변수에 넣고 진행하겠습니다.
# eksctl install
# for ARM systems, set ARCH to: `arm64`, `armv6` or `armv7`
ARCH=amd64
PLATFORM=$(uname -s)_$ARCH
curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"
# (Optional) Verify checksum
curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check
tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz
sudo mv /tmp/eksctl /usr/local/bin
# mycluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-cluster
region: ap-northeast-2
version: '1.25'
nodeGroups:
- name: ng-1
minSize: 1
maxSize: 2
amiFamily: AmazonLinux2
instanceType: m5.large
ami: ami-09466600bdc834c28
desiredCapacity: 1
overrideBootstrapCommand: |
#!/bin/bash
source /var/lib/cloud/scripts/eksctl/bootstrap.helper.sh
/etc/eks/bootstrap.sh my-cluster --container-runtime containerd
eksctl create cluster -f mycluster.yaml
정상적으로 구성됩니다! 다음은 노드로 접근하여 구성 요소를 확인하겠습니다.
# kubelet 확인
systemctl status kubelet
# 부트스트랩 로그 확인
cat /var/log/cloud-init-output.log
# 볼륨 확인
lsblk
# 컨테이너 확인
ps axf | grep /usr/bin/containerd
여담
GPU 드라이버 설치 및 가속 설정
bootstrap.sh 에는 GPU 드라이버 설치와 가속 설정도 설정되어 있습니다. 물론 aws linux 한정된 얘기이며 ubuntu로 노드 구성시 gpu 드라이버 설치를 못합니다.
[ec2-user@kops-ec2 amazon-eks-ami]$ eksctl create cluster -f eksctl.yaml
2024-01-09 15:45:03 [!] Ubuntu2004 does not ship with NVIDIA GPU drivers installed, hence won't support running GPU-accelerated workloads out of the box
2024-01-09 15:45:03 [ℹ] eksctl version 0.167.0
2024-01-09 15:45:03 [ℹ] using region ap-northeast-2
2024-01-09 15:45:03 [ℹ] skipping ap-northeast-2b from selection because it doesn't support the following instance type(s): p2.xlarge
2024-01-09 15:45:03 [ℹ] skipping ap-northeast-2d from selection because it doesn't support the following instance type(s): p2.xlarge
2024-01-09 15:45:03 [ℹ] setting availability zones to [ap-northeast-2a ap-northeast-2c]
2024-01-09 15:45:03 [ℹ] subnets for ap-northeast-2a - public:192.168.0.0/19 private:192.168.64.0/19
2024-01-09 15:45:03 [ℹ] subnets for ap-northeast-2c - public:192.168.32.0/19 private:192.168.96.0/19
2024-01-09 15:45:03 [ℹ] nodegroup "ng-1" will use "ami-0ba3b2f4ccf237e79" [Ubuntu2004/1.24]
또한, k8s 1.25 버전 이상의 경우 p2 인스턴스는 지원되지 않습니다. (NVIDIA 525 이후 시리즈만 지원)
공식문서에 나와있는 내용이였지만, 필자는 확인을 못하였고 가장 값싼 p2 타입으로 선택하여 노드를 구성했는데 다음의 에러가 나와 당황했습니다.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-cluster
region: ap-northeast-2
version: "1.25"
nodeGroups:
- name: ng-1
instanceType: p2.xlarge
desiredCapacity: 1
ami: ami-0ba3b2f4ccf237e79
ssh:
publicKeyName: keypair
노드 커스터마이징 설정
노드의 추가 커스터마이징이 필요할 경우 bootstrap 에 추가 경로를 설정해야 하는데요, 노드 구성의 추가 커맨드에서 설정하면 됩니다. 필자의 경우 노드별 할당 MAX 파드 수를 설정하기 위해 다음과 같이 노드 그룹을 구성하였습니다.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-cluster
region: ap-northeast-2
version: "1.25"
nodeGroups:
- name: ng-2
instanceType: c5.xlarge
desiredCapacity: 1
ami: ami-0ba3b2f4ccf237e79
amiFamily: Ubuntu2004
overrideBootstrapCommand: | # 추가 설정
/etc/eks/bootstrap.sh my-cluster --use-max-pods false --kubelet-extra-args '--max-pods=50'
앤서블은 같이 안쓰나요?
필자의 지난 블로그 글에서는 ansible과 packer를 통해 골드 이미지를 구성하였는데요. 여기서는 앤서블을 같이 쓰지 않았냐고 생각하실 수 있습니다. 확장성을 생각하면 간단한데요. 해당 프로젝트는 AWS linux OS만 지원하기 때문입니다. 스크립트를 확인하면 yum, awslinuxextra 같이 특정 OS만 지원되는 것을 확인할 수 있습니다. ubuntu OS 나 다른 플랫폼(google, VM)에서 사용할 경우 스크립트 수정이 필요합니다.
실무에서 도입 고려시 AWS linux OS만 사용한다면 무조건 도입해야할 것으로 생각됩니다. 그러나 운영 환경이 멀티 클라우드나 다른 OS를 사용한다면, 각 환경에 맞게 커스터마이징이 필요합니다. 앤서블에서는 구성 환경과 플랫폼 환경에 따라 role을 설정한다면 일관성있게 최적의 이미지를 관리할 수 있을 것으로 생각됩니다. 이와 관련된 오픈소스를 찾아봤는데, 아직은 없는 것으로 확인되네요. 알고 계시면 댓글 부탁드립니다~
'Cloud Tech' 카테고리의 다른 글
Gitops Bridge를 통한 멀티클러스터 구성 자동화 (0) | 2024.03.09 |
---|---|
AWS Bedrock(LLM)을 활용한 앤서블 GPT 모델 만들기 (1) | 2024.02.11 |
Ansible과 Packer를 활용한 Golden Image 구성 (0) | 2024.02.03 |
앤서블 기본 문법 이해하기 (0) | 2024.01.20 |
Ansible 개념 이해와 k8s 클러스터 관리하기 (0) | 2024.01.14 |