AEWS study

7주차 - EKS Mode/Nodes - #1

haru224 2025. 3. 20. 00:47

CloudNet@ 가시다님이 진행하는 AWS EKS Hands-on Study 내용 참고.

 

 

사전지식


 

[K8S Docs] Scheduler

  • Kubernetes Scheduler - Docs
  • Scheduling Framework - Docs

출처: https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/

 

[CNKCD2024] 쿠버네티스 스케줄러노드를 어떻게 선택하는가? (임찬식) - Youtube , Blog1* , Blog2* , Blog3

출처: https://beer1.tistory.com/62

  • 파드 생성 시 : 인증/인가 → Admission → ETCD ⇒ 스케줄러 동작 (노드 선택) ⇒ 이후 pod 에 nodename에 업데이트됨

 

[CNKCD2024] 쿠버네티스 스케줄러는 노드를 어떻게 선택하는가? (임찬식) 자료 

 

Terraform


 

☞ 테라폼 소개 : 하시코프사에서 공개한 IaC 도구

  • ‘하시코프의 철학 - 링크’ 중 3가지를 담아서 테라폼을 설계 : 워크플로우에 집중, 코드형 인프라, 실용주의

테라폼 제공 유형 : 3가지 유형

  1. On-premise : Terraform이라 불리는 형태로, 사용자의 컴퓨팅 환경에 오픈소스 바이너리툴인 테라폼을 통해 사용
  2. Hosted SaaS : Terraform Cloud로 불리는 SaaS로 제공되는 구성 환경으로 하시코프가 관리하는 서버 환경이 제공
  3. Private Install : Terraform Enterprise로 불리는 서버 설치형 구성 환경으로, 기업의 사내 정책에 따라 프로비저닝 관리가 외부 네트워크와 격리 - 링크

테라폼 클라우드 가격정책 - [참고: Pricing, Feature]

  • Free : 리소스 500개 까지 무료 → 커뮤니티 버전
  • Standard : Free + 워크플로우 기능 추가 + 동시실행(Concurrency 개수 3개)
  • Plus : 정책, 보안, 신뢰성, 확장성 등 기업형 고객에게 적합(대규모 사용자를 위한 비용모델)
  • Enterprise : Plus와 대부분 유사하며 설치형 모델

☞  테라폼 환경 구성 : macOS, Windows(WSL2)

  • 미리 빌드된 바이너리(실행) 파일 다운로드
  • 테라폼 소스 코드 다운로드 후 빌드
  • OS 패키지 관리자 활용

버전 선택 : 가장 최선 버전 권장 - 하위 버전 호환, 기능 개선, 버그 수정

  • 빌드된 바이너리 네이밍 규칙 : terraform_<버전>_<OS>_<CPU>.zip

PATH 설정 : 리눅스/macOS , 윈도우

  • 리눅스 : /usr/bin
  • 윈도우 : C:\\windows\\system32
  • 실행 환경 구성(3가지) :

 

  • 윈도우 : 방안1(WSL2 리눅스 환경 설치 후 사용 ← 권장 방안)
윈도우 OS사용자의 경우 최성욱(악분일상)님 Youtube 영상 참고

 

 

Chapter (02) 실행 환경 구성

CloudNet@ 가시다님이 진행하는 Terraform 101 Study 2기 "테라폼으로 시작하는 IaC" (한빛미디어) 도서로 진행! ✅ 테라폼 설치 하시코프에서 공식적으로 관리하는 릴리스 사이트 https://releases.hashicorp.com/t

kschoi728.tistory.com

 

  1. 윈도우에 WSL2 설치
  2. WSL2 실행(Shell 접속)
  3. 테라폼 설치 및 확인 - 링크 (Linux → Ubuntu/Debian 선택)
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform

# 테라폼 버전 정보 확인
terraform version

 

 

Fargate


이론

 

☞ Fargate 소개 : EKS(컨트롤 플레인) + Fargate(데이터 플레인)의 완전한 서버리스화(=AWS 관리형)

  • Cluster Autoscaler 불필요, VM 수준의 격리 가능(VM isolation at Pod Level)

출처: https://www.eksworkshop.com/docs/fundamentals/fargate/

  • 파게이트 프로파일(파드가 사용할 서브넷, 네임스페이스, 레이블 조건)을 생성하여 지정한 파드가 파게이트에서 동작하게 함

  • EKS 는 스케줄러가 특정 조건을 기준으로 어느 노드에 파드를 동작시킬지 결정, 혹은 특정 설정으로 특정 노드에 파드가 동작하게 가능함

  • Data Plane

 

Firecracker* - Github ,Install , Blog1 , Blog2 , Blog3 , AWS_Blog*

출처: https://github.com/firecracker-microvm/firecracker/blob/main/docs/design.md

 

  • KVM을 사용하는 새로운 가상화 기술인 Firecracker를 여러분에게 소개하고자 합니다. Firecracker를 통해 여러분은 가상화되지 않은 환경에서 1초도 되지 않는 시간 안에 경량 microVM(마이크로 가상 머신)을 시작할 수 있고, 컨테이너를 통해 제공하는 리소스 효율성과 기존 VM에서 제공하는 워크로드 격리 및 보안의 혜택을 그대로 활용할 수 있습니다.
  • 보안 – 항상 가장 중요한 우선순위입니다! Firecracker는 여러 수준의 격리와 보호를 사용하며, 공격 노출 영역을 최소화합니다.
  • 고성능 – 현 시점 기준으로 125밀리초 안에 microVM을 시작할 수 있으며(2019년에는 더 빨라질 예정), 단기간 또는 일시적인 워크로드를 비롯한 여러 유형의 워크로드에 적합합니다.
  • 검증된 실적 – Firecracker는 실전에서 검증되어 있습니다. 이미 AWS Lambda 및 AWS Fargate를 비롯한 사용량이 많은 여러 AWS 서비스가 Firecracker를 사용하고 있습니다.
  • 낮은 오버헤드 – Firecracker는 microVM당 약 5MiB의 메모리를 사용합니다. 그리고 동일한 인스턴스에서 다양한 vCPU 및 메모리 구성 사양을 갖춘 안전한 수천 개의 VM을 실행할 수 있습니다.
  • 오픈 소스 – Firecracker는 현재 진행 중인 오픈 소스 프로젝트입니다. 이미 검토와 PR(Pull Request)을 수락할 준비가 되었으며, 전 세계 기고자들과 협업할 수 있기를 기대하고 있습니다.
  • Firecracker는 미니멀리즘에 기반하여 제작되었습니다. crosvm에서 시작하여 오버헤드를 줄이고 안전한 멀티 테넌시를 활용하도록 최소 디바이스 모델을 설정했습니다. Firecracker는 스레드 보안을 보장하고 보안 취약성을 야기할 수 있는 여러 유형의 버퍼 오버런 오류를 방지하는 최신 프로그래밍 언어인 Rust로 작성되었습니다.
  • 단순한 게스트 모델 – Firecracker 게스트는 공격 영역을 최소화하기 위해 가상화된 단순한 디바이스 모델로 제시됩니다(예: 네트워크 디바이스, 블록 I/O 디바이스, PIT(Programmable Interval Timer), KVM 클럭, 직렬 콘솔, 부분 키보드(VM을 재설정할 수 있을 정도의 기능)).
  • 잠금(Jail) 처리 – Firecracker 프로세스는 cgroups 및 seccomp BPF를 사용하여 잠기며(Jail), 매우 제한된 소량의 시스템 호출 목록에 액세스합니다.
  • 정적 연결 – firecracker 프로세스는 정적으로 연결되며, 잠금자(Jailer)에서 시작하여 가능한 안전하고 클린한 상태의 호스트 환경을 보장합니다.

 

☞  용찬호님발표* , 발표문서* 소개 : 장점, 단점, 고려사항, 비용

  • AWS EKS Fargate 아키텍처 (추정 포함)

  • 사용자에게 보이지 않지만, Fargate Scheduler(Controller 추정)가 EKS Control Plane 에서 동작.
    • fargate Scheduler(controller) 에 필요한 IAM Role(Policy)는 AWS에서 알아서 관리 하는 것으로 보임. 설치 시에 별도 설정 없음.
  • Fargate 에 의해서 배포된 파드(노드 당 1개 파드)에 ENI는 사용자의 VPC 영역 내에 속하여, Fargate-Owned ENI 로 추정.
    • 파드(노드)에 필요 IAM Role(Policy)는 Fargate 설치 시에 설정 필요함. 필요 시 파드에 IRSA 추가 설정 가능.
  • 파드가 외부 통신 시에는 → NATGW(공인 IP로 SNAT) ⇒ IGW(외부 인터넷)
    • 만약 파드가 퍼블릭 서브넷이 있을 경우 공인IP 비용 부과 및 외부 침입 시도가 빈번할듯..
  • 외부에서 파드 내부로 인입 요청 시에는 → ALB/NLB ⇒ Fargate-Owned ENI 에 연결된 Fargate 파드(노드)로 전달

  • firecracker-containerd 를 통하여 MicroVM(Application 컨테이너)를 배포.
  • VMM을 통해서 MicroVM을 배포하고, FC Snapshotter 를 통해서 Application Container 의 이미지를 구현.
  • MicroVM 마다 ‘Kubelet, Kube-proxy, Containerd’ 가 동작하여, 256 RAM 반드시 필요.
  • 사용자에의 VPC에 보이는 ENIApplication Containter직접 매핑되어 있는 것으로 추정.

☞ 상세 정보 참고

 

  • recracker-containerdFirecracker 가상 머신 모니터(VMM)가 제공하는 가상 머신 격리를 사용하여 컨테이너를 보다 쉽게 실행할 수 있도록 설계되었습니다.
  • firecracker-containerd는 또한 "제어(control) API"라고 부르는 새로운 API를 추가합니다. 이 API는 여러 개의 컨테이너를 실행할 수 있는 Firecracker 마이크로VM의 생명주기(lifecycle)를 모델링하기 위한 것입니다.
    • control 플러그인은 런타임의 생명주기를 관리하고, control API를 구현하며, 명령을 런타임에 프록시(proxying)하는 역할을 합니다. 이 control 플러그인은 containerd 바이너리에 내장되어 컴파일되며, 이로 인해 firecracker-containerd 전용으로 특수하게 빌드된 containerd 바이너리가 필요합니다.
    • 런타임(runtime)control APIV2 runtime API를 모두 구현합니다. 이 런타임은 containerd(마이크로VM 외부)와 Firecracker VMM 간의 VM 생명주기 작업을 연동하고, microVM 내부에서 실행 중인 에이전트(agent)와 연동하여 컨테이너 생명주기 작업을 수행합니다. 이 런타임은 프로세스 외부(out-of-process)에서 동작하는 shim으로 구현되어 있으며, ttrpc를 통해 통신합니다.
    • 에이전트(agent)microVM 내부에서 실행되며, 런타임으로부터 수신한 제어 명령을 실행하고, 이벤트 및 메트릭 정보를 런타임에 전달하며, 컨테이너 프로세스의 STDIO를 프록시(proxying)하는 역할을 담당합니다. 이 에이전트는 microVM 내부에서 일반적인 리눅스 컨테이너를 생성하기 위해 containerd의 containerd-shim-runc-v1을 통해 runC를 호출합니다.

번역: chatgpt

출처: https://github.com/firecracker-microvm/firecracker-containerd/blob/main/docs/architecture.md

 

출처: https://github.com/firecracker-microvm/firecracker-containerd/blob/main/docs/architecture.md

 

☞ [AWS 공식 문서] Fargate* - AWS_Docs

 

  ☞ Simplify compute management with AWS Fargate - Docs

  • mazon EKS를 사용하여 AWS Fargate에서 Kubernetes 포드를 실행하는 방법에 대해 설명합니다.
  • Fargate는 컨테이너에 필요에 따라 적절한 크기의 컴퓨팅 용량을 제공하는 기술입니다.
  • Fargate를 사용하면 컨테이너를 실행하기 위해 가상 머신 그룹을 직접 프로비저닝, 구성 또는 확장할 필요가 없습니다.
  • 서버 유형을 선택하거나 노드 그룹을 확장할 시기를 결정하거나 클러스터 패킹을 최적화할 필요도 없습니다.
  • Fargate 프로필을 사용하여 Fargate에서 시작하는 포드와 실행 방식을 제어할 수 있습니다.
  • Fargate 프로필은 Amazon EKS 클러스터의 일부로 정의됩니다. Amazon EKS는 Kubernetes에서 제공하는 업스트림 확장 모델을 사용하여 AWS에서 구축한 컨트롤러를 사용하여 Kubernetes와 Fargate를 통합합니다.
  • 이 컨트롤러는 Amazon EKS가 관리하는 Kubernetes 제어 평면의 일부로 실행되며 네이티브 Kubernetes 포드를 Fargate로 예약하는 역할을 합니다.
  • Fargate 컨트롤러에는 기본 Kubernetes 스케줄러와 함께 실행되는 새로운 스케줄러와 여러 mutating 및 validating 승인 컨트롤러가 포함되어 있습니다.
    • The Fargate controllers include a new scheduler that runs alongside the default Kubernetes scheduler in addition to several mutating and validating admission controllers.
  • Fargate에서 실행되는 기준을 충족하는 Pod를 시작하면 클러스터에서 실행 중인 Fargate 컨트롤러가 Pod를 Fargate로 인식, 업데이트 및 예약합니다.

    Logging - Docs

  • Fargate의 Amazon EKS는 Fluent Bit 기반의 내장 로그 라우터를 제공합니다. 즉, Fluent Bit 컨테이너를 사이드카로 명시적으로 실행하지 않고 Amazon에서 실행합니다. 로그 라우터를 구성하기만 하면 됩니다.
    • Amazon EKS on Fargate offers a built-in log router based on Fluent Bit. This means that you don’t explicitly run a Fluent Bit container as a sidecar, but Amazon runs it for you.
  • 구성은 다음 기준을 충족해야 하는 전용 ConfigMap을 통해 이루어집니다.
    • 이름 : aws-logging
    • aws-observability라는 전용 네임스페이스에서 생성됨
    • 5300자를 초과할 수 없습니다.
  • ConfigMap을 생성하면 Fargate의 Amazon EKS가 자동으로 이를 감지하고 로그 라우터를 구성합니다. Fargate는 AWS에서 관리하는 Fluent Bit의 업스트림 호환 배포판인 Fluent Bit용 AWS 버전을 사용합니다. 자세한 내용은 GitHub의 Fluent Bit용 AWS를 참조하세요 - Docs
  • 로그 라우터를 사용하면 AWS의 다양한 서비스를 로그 분석 및 저장에 사용할 수 있습니다. Fargate에서 Amazon CloudWatch, Amazon OpenSearch 서비스로 로그를 직접 스트리밍할 수 있습니다. 또한 Amazon Data Firehose를 통해 Amazon S3, Amazon Kinesis 데이터 스트림 및 파트너 도구와 같은 대상으로 로그를 스트리밍할 수도 있습니다.
  • Fargate 포드를 배포할 기존 Kubernetes 네임스페이스를 지정하는 기존 Fargate 프로필입니다.

☞ 제약사항 및 고려사항 최종 정리*

  • 데몬셋은 Fargate에서 지원되지 않습니다. 애플리케이션에 데몬이 필요한 경우 해당 데몬을 포드에서 사이드카 컨테이너로 실행하도록 재구성합니다.
  • Fargate에서는 특권 컨테이너(Privileged containers)가 지원되지 않습니다.
  • Fargate에서 실행되는 포드는 포드 매니페스트에서 HostPort 또는 HostNetwork를 지정할 수 없습니다.
  • 현재 Fargate에서는 GPU를 사용할 수 없습니다.
  • Can run workloads that require Arm processors 미지원.
  • Can SSH into node 미지원
  • Fargate에서 실행되는 포드는 AWS 서비스에 대한 NAT 게이트웨이 액세스 권한이 있는 private 서브넷에서만 지원
  • 포드에는 Amazon EC2 인스턴스 메타데이터 서비스(IMDS)를 사용할 수 없습니다
  • 대체 CNI 플러그인을 사용할 수 없습니다.
  • EFS 동적 영구 볼륨 프로비저닝을 사용할 수 없음.
  • Fargate Spot을 지원하지 않음
  • EBS 볼륨을 Fargate 포드에 마운트할 수 없음
  • Fargate does not currently support Kubernetes topologySpreadConstraints.
  • Can run containers on Amazon EC2 dedicated hosts 미지원
  • Can run AWS Bottlerocket 미지원
  • Fargate Pods run with guaranteed priority, so the requested CPU and memory must be equal to the limit for all of the containers.
  • Fargate는 필요한 Kubernetes 구성 요소(kubelet, kube-proxy, and containerd에 대해 각 Pod메모리 예약에 256MB를 추가합니다.
  • 프로비저닝되면 Fargate에서 실행되는 각 Pod는 기본적으로 20 GiB의 임시 저장소를 받게 됩니다. 임시 저장소의 총 양을 최대 175 GiB까지 늘릴 수 있습니다.
  • Fargate의 Amazon EKS는 Fluent Bit 기반의 내장 로그 라우터를 제공합니다. 즉, Fluent Bit 컨테이너를 사이드카로 명시적으로 실행하지 않고 Amazon에서 실행합니다

실습

☞ Amazon EKS Blueprints for Terraform 소개 : 현재는 더이상 업데이트 되지 않는 것으로 보임 - Link / FAQ - Link

 

  EKS Blueprints for Terraform has been designed to be consumed in the following manners:

  1. 참고 Reference: Users can refer to the patterns and snippets provided to help guide them to their desired solution. Users will typically view how the pattern or snippet is configured to achieve the desired end result and then replicate that in their environment.
  2. 복붙 Copy & Paste: Users can copy and paste the patterns and snippets into their own environment, using EKS Blueprints as the starting point for their implementation. Users can then adapt the initial pattern to customize it to their specific needs.

고려사항

  • EKS Blueprints for Terraform are not intended to be consumed as-is directly from this project. → 그대로 사용은 의도된 것이 아님
  • In "Terraform speak" - the patterns and snippets provided in this repository are not designed to be consumed as a Terraform module. → 패턴과 스니펫은 Terraform 모듈로 사용하도록 설계되지 않음
  • Therefore, the patterns provided only contain variables when certain information is required to deploy the pattern (i.e. - a Route53 hosted zone ID, or ACM certificate ARN) and generally use local variables. If you wish to deploy the patterns into a different region or with other changes, it is recommended that you make those modifications locally before applying the pattern. → 일반적으로 Local 블록을 통해 변경하고, 특정 정보가 필요한 경우(R53 호스트영역 ID 등)만 variables 블록을 사용
  • EKS Blueprints for Terraform will not expose variables and outputs in the same manner that Terraform modules follow in order to avoid confusion around the consumption model. → 복잡성(혼란?)을 줄이기 위해 variables 과 outputs 을 최대한 노출하지 않음
  • However, we do have a number of Terraform modules that were created to support EKS Blueprints in addition to the community hosted modules. Please see the respective projects for more details on the modules constructed to support EKS Blueprints for Terraform; those projects are listed below. → EKS Blueprints 지원을 위해 제작한 모듈은 아래와 같음
  • terraform-aws-eks-blueprint-addon (단수)
    • Terraform module which can provision an addon using the Terraform helm_release resource in addition to an IAM role for service account (IRSA).
    • 서비스 계정(IRSA)에 대한 IAM 역할 외에도 Terraform 리소스를 사용하여 애드온을 프로비저닝할 수 있는 Terraform 모듈입니다.
  • terraform-aws-eks-blueprint-addons (복수)
    • Terraform module which can provision multiple addons; both EKS addons using the aws_eks_addon resource as well as Helm chart based addons using the terraform-aws-eks-blueprint-addon module.
    • 여러 애드온을 프로비저닝할 수 있는 Terraform 모듈입니다 - ‘aws_eks_addon 기반 애드온’ + ‘terraform-aws-eks-blueprint-addon 모듈 사용 헬름 차트 기반 애드온’
  • terraform-aws-eks-blueprints-teams
    • Terraform module that creates Kubernetes multi-tenancy resources and configurations, allowing both administrators and application developers to access only the resources which they are responsible for.
    • 관리자와 애플리케이션 개발자 모두 자신이 담당하는 리소스에만 액세스할 수 있도록 Kubernetes 멀티테넌시 리소스 및 구성을 생성하는 Terraform 모듈.

기타 프로젝트

  1. GitOps
    • terraform-aws-eks-ack-addons - Terraform module to deploy ACK controllers onto EKS clusters
    • crossplane-on-eks - Crossplane Blueprints is an open source repo to bootstrap Amazon EKS clusters and provision AWS resources using a library of Crossplane Compositions (XRs) with Composite Resource Definitions (XRDs).
  2. Data on EKS
    • data-on-eks - A collection of blueprints intended for data workloads on Amazon EKS.
    • terraform-aws-eks-data-addons - Terraform module to deploy multiple addons that are specific to data workloads on EKS clusters.
  3. Observability Accelerator
    • terraform-aws-observability-accelerator - A set of opinionated modules to help you set up observability for your AWS environments with AWS-managed observability services such as Amazon Managed Service for Prometheus, Amazon Managed Grafana, AWS Distro for OpenTelemetry (ADOT) and Amazon CloudWatch
  4. Karpenter Blueprints
  5. karpenter-blueprints - includes a list of common workload scenarios, some of them go in depth with the explanation of why configuring Karpenter and Kubernetes objects in such a way is important.

주의사항 Terraform Caveats

  • EKS Blueprints for Terraform does not intend to teach users the recommended practices for Terraform nor does it offer guidance on how users should structure their Terraform projects. → 권장 사례나 테라폼 구성 지침을 제공하지 않습니다.
  • The patterns provided are intended to show users how they can achieve a defined architecture or configuration in a way that they can quickly and easily get up and running to start interacting with that pattern. Therefore, there are a few caveats users should be aware of when using EKS Blueprints for Terraform: → 최대한 빠르고 쉽게 목표 패턴 실행에 목적
  1. We recognize that most users will already have an existing VPC in a separate Terraform workspace. However, the patterns provided come complete with a VPC to ensure a stable, deployable example that has been tested and validated.
  2. → 사용자가 기존 VPC가 있지만, 제공되는 패턴에서 안정적인 배포 보장을 위해 신규 VPC를 배포
  3. Hashicorp does not recommend providing computed values in provider blocks , which means that the cluster configuration should be defined in a workspace separate from the resources deployed onto the cluster (i.e. - addons). → 분리 권고 지만…
    • However, to simplify the pattern experience, we have defined everything in one workspace and provided instructions to provision the patterns using a targeted apply approach. Users are encouraged to investigate a Terraform project structure that suites their needs; EKS Blueprints for Terraform does not have an opinion in this matter and will defer to Hashicorp's guidance. → 단순화 하여 모든 것을 하나의 작업 공간에서 정의하고 배포함.
  4. Patterns are not intended to be consumed in-place in the same manner that one would consume a module. Therefore, we do not provide variables and outputs to expose various levels of configuration for the examples. Users can modify the pattern locally after cloning to suite their requirements. → Local 블록 수정
  5. Please see the FAQ section on authenticating Kubernetes based providers (kubernetes, helm, kubectl) to Amazon EKS clusters regarding the use of static tokens versus dynamic tokens using the awscli

 

☞  테라폼으로 실습 환경 배포 : EKS, fargate profile

 

코드 가져오기

#
git clone https://github.com/aws-ia/terraform-aws-eks-blueprints
tree terraform-aws-eks-blueprints/patterns
cd terraform-aws-eks-blueprints/patterns/fargate-serverless

 

main.tf 수정 : 리전 등 일부 실습 편리를 위해 수정, Sample App 배포 부분 삭제

provider "aws" {
  region = local.region
}

provider "kubernetes" {
  host                   = module.eks.cluster_endpoint
  cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)

  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "aws"
    # This requires the awscli to be installed locally where Terraform is executed
    args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
  }
}

provider "helm" {
  kubernetes {
    host                   = module.eks.cluster_endpoint
    cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)

    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      command     = "aws"
      # This requires the awscli to be installed locally where Terraform is executed
      args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
    }
  }
}

data "aws_availability_zones" "available" {
  # Do not include local zones
  filter {
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}

locals {
  name     = basename(path.cwd)
  region   = "ap-northeast-2"

  vpc_cidr = "10.10.0.0/16"
  azs      = slice(data.aws_availability_zones.available.names, 0, 3)

  tags = {
    Blueprint  = local.name
    GithubRepo = "github.com/aws-ia/terraform-aws-eks-blueprints"
  }
}

################################################################################
# Cluster
################################################################################

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.11"

  cluster_name                   = local.name
  cluster_version                = "1.30"
  cluster_endpoint_public_access = true

  # Give the Terraform identity admin access to the cluster
  # which will allow resources to be deployed into the cluster
  enable_cluster_creator_admin_permissions = true

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  # Fargate profiles use the cluster primary security group so these are not utilized
  create_cluster_security_group = false
  create_node_security_group    = false

  fargate_profiles = {
    study_wildcard = {
      selectors = [
        { namespace = "study-*" }
      ]
    }
    kube_system = {
      name = "kube-system"
      selectors = [
        { namespace = "kube-system" }
      ]
    }
  }

  fargate_profile_defaults = {
    iam_role_additional_policies = {
      additional = module.eks_blueprints_addons.fargate_fluentbit.iam_policy[0].arn
    }
  }

  tags = local.tags
}

################################################################################
# EKS Blueprints Addons
################################################################################

module "eks_blueprints_addons" {
  source  = "aws-ia/eks-blueprints-addons/aws"
  version = "~> 1.16"

  cluster_name      = module.eks.cluster_name
  cluster_endpoint  = module.eks.cluster_endpoint
  cluster_version   = module.eks.cluster_version
  oidc_provider_arn = module.eks.oidc_provider_arn

  # We want to wait for the Fargate profiles to be deployed first
  create_delay_dependencies = [for prof in module.eks.fargate_profiles : prof.fargate_profile_arn]

  # EKS Add-ons
  eks_addons = {
    coredns = {
      configuration_values = jsonencode({
        computeType = "Fargate"
        # Ensure that the we fully utilize the minimum amount of resources that are supplied by
        # Fargate https://docs.aws.amazon.com/eks/latest/userguide/fargate-pod-configuration.html
        # Fargate adds 256 MB to each pod's memory reservation for the required Kubernetes
        # components (kubelet, kube-proxy, and containerd). Fargate rounds up to the following
        # compute configuration that most closely matches the sum of vCPU and memory requests in
        # order to ensure pods always have the resources that they need to run.
        resources = {
          limits = {
            cpu = "0.25"
            # We are targeting the smallest Task size of 512Mb, so we subtract 256Mb from the
            # request/limit to ensure we can fit within that task
            memory = "256M"
          }
          requests = {
            cpu = "0.25"
            # We are targeting the smallest Task size of 512Mb, so we subtract 256Mb from the
            # request/limit to ensure we can fit within that task
            memory = "256M"
          }
        }
      })
    }
    vpc-cni    = {}
    kube-proxy = {}
  }

  # Enable Fargate logging this may generate a large ammount of logs, disable it if not explicitly required
  enable_fargate_fluentbit = true
  fargate_fluentbit = {
    flb_log_cw = true
  }

  enable_aws_load_balancer_controller = true
  aws_load_balancer_controller = {
    set = [
      {
        name  = "vpcId"
        value = module.vpc.vpc_id
      },
      {
        name  = "podDisruptionBudget.maxUnavailable"
        value = 1
      },
    ]
  }

  tags = local.tags
}

################################################################################
# Supporting Resources
################################################################################

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name = local.name
  cidr = local.vpc_cidr

  azs             = local.azs
  private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)]
  public_subnets  = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)]

  enable_nat_gateway = true
  single_nat_gateway = true

  public_subnet_tags = {
    "kubernetes.io/role/elb" = 1
  }

  private_subnet_tags = {
    "kubernetes.io/role/internal-elb" = 1
  }

  tags = local.tags
}
  • (참고) slide Function - Docs

테라폼 초기화

# init 초기화
terraform init
tree .terraform
cat .terraform/modules/modules.json | jq
tree .terraform/providers/registry.terraform.io/hashicorp -L 2

# plan
terraform plan

  • EKS 배포 : 13분 소요
# 배포 : EKS, Add-ons, fargate profile - 13분 소요
# terraform apply -target="module.eks" -auto-approve
# terraform apply -target="module.eks_blueprints_addons" -auto-approve
terraform apply -auto-approve


# 배포 완료 후 확인
terraform state list
module.eks.data.aws_caller_identity.current
...

terraform output
...

# EKS 자격증명
$(terraform output -raw configure_kubectl) # aws eks --region ap-northeast-2 update-kubeconfig --name fargate-serverless
cat ~/.kube/config

# kubectl context 변경
kubectl ctx
kubectl config rename-context "arn:aws:eks:ap-northeast-2:$(aws sts get-caller-identity --query 'Account' --output text):cluster/fargate-serverless" "fargate-lab"

# k8s 노드, 파드 정보 확인
kubectl ns default
kubectl cluster-info
kubectl get node
kubectl get pod -A

# 상세 정보 확인
terraform show
...
terraform state list
terraform state show 'module.eks.aws_eks_cluster.this[0]'
terraform state show 'module.eks.data.tls_certificate.this[0]'
terraform state show 'module.eks.aws_cloudwatch_log_group.this[0]'
terraform state show 'module.eks.aws_eks_access_entry.this["cluster_creator"]'
terraform state show 'module.eks.aws_iam_openid_connect_provider.oidc_provider[0]'
terraform state show 'module.eks.data.aws_partition.current'
terraform state show 'module.eks.aws_iam_policy.cluster_encryption[0]'
terraform state show 'module.eks.aws_iam_role.this[0]'

terraform state show 'module.eks.time_sleep.this[0]'
terraform state show 'module.eks.module.kms.aws_kms_key.this[0]'
terraform state show 'module.eks.module.fargate_profile["kube_system"].aws_eks_fargate_profile.this[0]'
...

 

terraform 으로 생성되는 자원의 개수를 확인

 

☞ 기본 정보 확인

  • 기본 정보 확인
# k8s api service 확인 : ENDPOINTS 의 IP는 EKS Owned-ENI 2개
kubectl get svc,ep
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   172.20.0.1   <none>        443/TCP   26m

NAME                   ENDPOINTS                           AGE
endpoints/kubernetes   10.10.13.109:443,10.10.29.215:443   26m


# node 확인 : 노드(Micro VM) 4대
kubectl get csr
kubectl get node -owide
NAME                                                      STATUS   ROLES    AGE   VERSION               INTERNAL-IP    EXTERNAL-IP   OS-IMAGE         KERNEL-VERSION                  CONTAINER-RUNTIME
fargate-ip-10-10-11-226.ap-northeast-2.compute.internal   Ready    <none>   17m   v1.30.8-eks-2d5f260   10.10.11.226   <none>        Amazon Linux 2   5.10.234-225.910.amzn2.x86_64   containerd://1.7.25
fargate-ip-10-10-23-186.ap-northeast-2.compute.internal   Ready    <none>   17m   v1.30.8-eks-2d5f260   10.10.23.186   <none>        Amazon Linux 2   5.10.234-225.910.amzn2.x86_64   containerd://1.7.25
fargate-ip-10-10-36-234.ap-northeast-2.compute.internal   Ready    <none>   17m   v1.30.8-eks-2d5f260   10.10.36.234   <none>        Amazon Linux 2   5.10.234-225.910.amzn2.x86_64   containerd://1.7.25
fargate-ip-10-10-44-207.ap-northeast-2.compute.internal   Ready    <none>   17m   v1.30.8-eks-2d5f260   10.10.44.207   <none>        Amazon Linux 2   5.10.234-225.910.amzn2.x86_64   containerd://1.7.25

kubectl describe node | grep eks.amazonaws.com/compute-type
Labels:             eks.amazonaws.com/compute-type=fargate
Taints:             eks.amazonaws.com/compute-type=fargate:NoSchedule
...

# 파드 확인 : 파드의 IP와 노드의 IP가 같다!
kubectl get pdb -n kube-system
kubectl get pod -A -owide
NAMESPACE     NAME                                            READY   STATUS    RESTARTS   AGE   IP             NODE                                                      NOMINATED NODE   READINESS GATES
kube-system   aws-load-balancer-controller-56c94fc557-924p5   1/1     Running   0          19m   10.10.36.234   fargate-ip-10-10-36-234.ap-northeast-2.compute.internal   <none>           <none>
kube-system   aws-load-balancer-controller-56c94fc557-j98wl   1/1     Running   0          19m   10.10.44.207   fargate-ip-10-10-44-207.ap-northeast-2.compute.internal   <none>           <none>
kube-system   coredns-64696d8b7f-8flf9                        1/1     Running   0          20m   10.10.11.226   fargate-ip-10-10-11-226.ap-northeast-2.compute.internal   <none>           <none>
kube-system   coredns-64696d8b7f-8z4q7                        1/1     Running   0          20m   10.10.23.186   fargate-ip-10-10-23-186.ap-northeast-2.compute.internal   <none>           <none>

# aws-load-balancer-webhook-service , eks-extension-metrics-api?
kubectl get svc,ep -n kube-system
NAME                                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
service/aws-load-balancer-webhook-service   ClusterIP   172.20.72.191   <none>        443/TCP                  34m
service/eks-extension-metrics-api           ClusterIP   172.20.173.28   <none>        443/TCP                  42m

# eks-extension-metrics-api?
kubectl get apiservices.apiregistration.k8s.io | grep eks
v1.metrics.eks.amazonaws.com           kube-system/eks-extension-metrics-api   True        53m

kubectl get --raw "/apis/metrics.eks.amazonaws.com" | jq
kubectl get --raw "/apis/metrics.eks.amazonaws.com/v1" | jq


# configmap 확인
kubectl get cm -n kube-system
...

# aws-auth 보다 우선해서 IAM access entry 가 있음을 참고.
# 기본 관리노드 보다 system:node-proxier 그룹이 추가되어 있음.
# fargate profile 이 2개인데, 그 profile 갯수만큼 있음.
kubectl get cm -n kube-system aws-auth -o yaml
...
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      - system:node-proxier
      rolearn: arn:aws:iam::911283464785:role/kube-system-2025031115064156060000000f
      username: system:node:{{SessionName}}
    ...

#
kubectl rbac-tool lookup system:node-proxier
  SUBJECT             | SUBJECT TYPE | SCOPE       | NAMESPACE | ROLE                | BINDING                 
----------------------+--------------+-------------+-----------+---------------------+-------------------------
  system:node-proxier | Group        | ClusterRole |           | system:node-proxier | eks:kube-proxy-fargate  

kubectl rolesum -k Group system:node-proxier
Group: system:node-proxier

Policies:
• [CRB] */eks:kube-proxy-fargate ⟶  [CR] */system:node-proxier
  Resource                         Name  Exclude  Verbs  G L W C U P D DC  
  endpoints                        [*]     [-]     [-]   ✖ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  endpointslices.discovery.k8s.io  [*]     [-]     [-]   ✖ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  events.[,events.k8s.io]          [*]     [-]     [-]   ✖ ✖ ✖ ✔ ✔ ✔ ✖ ✖   
  nodes                            [*]     [-]     [-]   ✔ ✔ ✔ ✖ ✖ ✖ ✖ ✖   
  services                         [*]     [-]     [-]   ✖ ✔ ✔ ✖ ✖ ✖ ✖ ✖   


#
kubectl get cm -n kube-system amazon-vpc-cni -o yaml         
apiVersion: v1
data:
  branch-eni-cooldown: "60"
  minimum-ip-target: "3"
  warm-ip-target: "1"
  warm-prefix-target: "0"
  ...

# coredns 설정 내용
kubectl get cm -n kube-system coredns -o yaml

# 인증서 작성되어 있음 : client-ca-file , requestheader-client-ca-file
kubectl get cm -n kube-system extension-apiserver-authentication -o yaml

#
kubectl get cm -n kube-system kube-proxy -o yaml
kubectl get cm -n kube-system kube-proxy-config -o yaml          
apiVersion: v1
data:
  config: |-
    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    bindAddress: 0.0.0.0
    clientConnection:
      acceptContentTypes: ""
      burst: 10
      contentType: application/vnd.kubernetes.protobuf
      kubeconfig: /var/lib/kube-proxy/kubeconfig
      qps: 5
    clusterCIDR: ""
    configSyncPeriod: 15m0s
    conntrack:
      maxPerCore: 32768
      min: 131072
      tcpCloseWaitTimeout: 1h0m0s
      tcpEstablishedTimeout: 24h0m0s
    enableProfiling: false
    healthzBindAddress: 0.0.0.0:10256
    hostnameOverride: ""
    iptables:
      masqueradeAll: false
      masqueradeBit: 14
      minSyncPeriod: 0s
      syncPeriod: 30s
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      syncPeriod: 30s
    kind: KubeProxyConfiguration
    metricsBindAddress: 0.0.0.0:10249
    mode: "iptables"
    nodePortAddresses: null
    oomScoreAdj: -998
    portRange: ""

  • coredns 파드 상세 정보 확인 : schedulerName: fargate-scheduler
# coredns 파드 상세 정보 확인
kubectl get pod -n kube-system -l k8s-app=kube-dns -o yaml
...
  spec:
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/os
              operator: In
              values:
              - linux
            - key: kubernetes.io/arch
              operator: In
              values:
              - amd64
              - arm64
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
        - podAffinityTerm:
            labelSelector:
              matchExpressions:
              - key: k8s-app
                operator: In
                values:
                - kube-dns
            topologyKey: kubernetes.io/hostname
          weight: 100
      ...
      resources:
        limits:
          cpu: 250m
          memory: 256M
        requests:
          cpu: 250m
          memory: 256M
      ...
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          add:
          - NET_BIND_SERVICE
          drop:
          - ALL
        readOnlyRootFilesystem: true
    ...
    dnsPolicy: Default
    enableServiceLinks: true
    nodeName: fargate-ip-10-10-11-226.ap-northeast-2.compute.internal
    preemptionPolicy: PreemptLowerPriority
    priority: 2000001000
    priorityClassName: system-node-critical
    restartPolicy: Always
    schedulerName: fargate-scheduler
    securityContext: {}
    serviceAccount: coredns
    serviceAccountName: coredns
    terminationGracePeriodSeconds: 30
    tolerations:
    - effect: NoSchedule
      key: node-role.kubernetes.io/control-plane
    - key: CriticalAddonsOnly
      operator: Exists
    - effect: NoExecute
      key: node.kubernetes.io/not-ready
      operator: Exists
      tolerationSeconds: 300
    - effect: NoExecute
      key: node.kubernetes.io/unreachable
      operator: Exists
      tolerationSeconds: 300
    topologySpreadConstraints:
    - labelSelector:
        matchLabels:
          k8s-app: kube-dns
      maxSkew: 1
      topologyKey: topology.kubernetes.io/zone
      whenUnsatisfiable: ScheduleAnyway
    ...
    qosClass: Guaranteed

AWS 관리 콘솔 확인

  • EKS - Compute(Nodes, Fargate profile - Pod execution role 확인), Add-ons, Access(IAM access entry), Control plane logs
KMS v2를 사용한 기본 암호화

기본적으로 향상된 보안 태세
AWS에서 소유한 키를 사용한 기본 봉투 암호화.
Kubernetes 애플리케이션을 위한 심층 방어(Defense-in-depth)를 제공합니다.


클러스터 객체 전체에 대한 암호화
EKS는 이제 시크릿뿐만 아니라 모든 Kubernetes API 데이터를 암호화합니다.
선택적으로, AWS KMS의 고객 관리형 키(CMK)를 계속 사용하여 모든 클러스터 객체를 봉투 암호화할 수 있습니다.


향상된 성능
KMS v2에서는 새로운 DEK(데이터 암호화 키)가 API 서버가 시작될 때와 KMS 플러그인이 KEK(키 암호화 키) 회전이 발생했음을 API 서버에 알릴 때만 생성됩니다.

 

  • EC2 : EC2 읍다!, EBS, ENI(eks owned, fargate owned 확인)

 

  • VPC : NATGW, Routing Table, Public Subnet(/24), Private Subnet(/20)

☞ fargate 에 kube-ops-view

# helm 배포
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system

# 포트 포워딩
kubectl port-forward deployment/kube-ops-view -n kube-system 8080:8080 &

# 접속 주소 확인 : 각각 1배, 1.5배, 3배 크기
echo -e "KUBE-OPS-VIEW URL = http://localhost:8080"
echo -e "KUBE-OPS-VIEW URL = http://localhost:8080/#scale=1.5"
echo -e "KUBE-OPS-VIEW URL = http://localhost:8080/#scale=3"

# open "http://127.0.0.1:8080/#scale=1.5" # macOS

    • kube-ops-view 파드 정보 확인
# node 확인 : 노드(Micro VM)
kubectl get csr
kubectl get node -owide
kubectl describe node | grep eks.amazonaws.com/compute-type

# kube-ops-view 디플로이먼트/파드 상세 정보 확인
kubectl get pod -n kube-system
kubectl get pod -n kube-system -o jsonpath='{.items[0].metadata.annotations.CapacityProvisioned}'
kubectl get pod -n kube-system -l app.kubernetes.io/instance=kube-ops-view -o jsonpath='{.items[0].metadata.annotations.CapacityProvisioned}'
0.25vCPU 0.5GB

# 디플로이먼트 상세 정보
kubectl get deploy -n kube-system kube-ops-view -o yaml
...
  template:
    ...
    spec:
      automountServiceAccountToken: true
      containers:
      - env:
        - name: TZ
          value: Asia/Seoul
        image: hjacobs/kube-ops-view:20.4.0
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 8080
          timeoutSeconds: 1
        name: kube-ops-view
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 8080
          timeoutSeconds: 1
        resources: {}
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        startupProbe:
          failureThreshold: 30
          periodSeconds: 5
          successThreshold: 1
          tcpSocket:
            port: 8080
          timeoutSeconds: 1
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      enableServiceLinks: true
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: kube-ops-view
      serviceAccountName: kube-ops-view
      terminationGracePeriodSeconds: 30
...

# 파드 상세 정보 : admission control 이 동작했음을 알 수 있음
kubectl get pod -n kube-system -l app.kubernetes.io/instance=kube-ops-view -o yaml
...
  metadata:
    annotations:
      CapacityProvisioned: 0.25vCPU 0.5GB
      Logging: LoggingEnabled
    ...
      resources: {}
    ...
  spec:
    automountServiceAccountToken: true
    containers:
    - env:
      - name: TZ
        value: Asia/Seoul
      image: hjacobs/kube-ops-view:20.4.0
      imagePullPolicy: IfNotPresent
      livenessProbe:
        failureThreshold: 3
        periodSeconds: 10
        successThreshold: 1
        tcpSocket:
          port: 8080
        timeoutSeconds: 1
      name: kube-ops-view
      ports:
      - containerPort: 8080
        name: http
        protocol: TCP
      readinessProbe:
        failureThreshold: 3
        periodSeconds: 10
        successThreshold: 1
        tcpSocket:
          port: 8080
        timeoutSeconds: 1
      resources: {}
      securityContext:
        readOnlyRootFilesystem: true
        runAsNonRoot: true
        runAsUser: 1000
      startupProbe:
        failureThreshold: 30
        periodSeconds: 5
        successThreshold: 1
        tcpSocket:
          port: 8080
        timeoutSeconds: 1
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
      volumeMounts:
      - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
        name: kube-api-access-znqs5
        readOnly: true
    dnsPolicy: ClusterFirst
    enableServiceLinks: true
    nodeName: fargate-ip-10-10-24-33.ap-northeast-2.compute.internal
    preemptionPolicy: PreemptLowerPriority
    priority: 2000001000
    priorityClassName: system-node-critical
    restartPolicy: Always
    schedulerName: fargate-scheduler
    securityContext: {}
    serviceAccount: kube-ops-view
    serviceAccountName: kube-ops-view
    terminationGracePeriodSeconds: 30
#
kubectl describe pod -n kube-system -l app.kubernetes.io/instance=kube-ops-view | grep Events: -A10
Events:
  Type    Reason          Age    From               Message
  ----    ------          ----   ----               -------
  Normal  LoggingEnabled  5m42s  fargate-scheduler  Successfully enabled logging for pod
  Normal  Scheduled       5m     fargate-scheduler  Successfully assigned kube-system/kube-ops-view-796947d6dc-sgr2n to fargate-ip-10-10-24-33.ap-northeast-2.compute.internal
...

  • fargate 에 netshoot 디플로이먼트(파드)
vCPU value
Memory value
.25 vCPU
0.5 GB, 1 GB, 2 GB
.5 vCPU
1 GB, 2 GB, 3 GB, 4 GB
1 vCPU
2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB
2 vCPU
Between 4 GB and 16 GB in 1-GB increments
4 vCPU
Between 8 GB and 30 GB in 1-GB increments
8 vCPU
Between 16 GB and 60 GB in 4-GB increments
16 vCPU
Between 32 GB and 120 GB in 8-GB increments
# 네임스페이스 생성
kubectl create ns study-aews

# 테스트용 파드 netshoot 디플로이먼트 생성 : 0.5vCPU 1GB 할당되어, 아래 Limit 값은 의미가 없음. 배포 시 대략 시간 측정해보자!
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netshoot
  namespace: study-aews
spec:
  replicas: 1
  selector:
    matchLabels:
      app: netshoot
  template:
    metadata:
      labels:
        app: netshoot
    spec:
      containers:
      - name: netshoot
        image: nicolaka/netshoot
        command: ["tail"]
        args: ["-f", "/dev/null"]
        resources: 
          requests:
            cpu: 500m
            memory: 500Mi
          limits:
            cpu: 2
            memory: 2Gi
      terminationGracePeriodSeconds: 0
EOF
kubectl get events -w --sort-by '.lastTimestamp'

# 확인 : 메모리 할당 측정은 어떻게 되었는지?
kubectl get pod -n study-aews -o wide
kubectl get pod -n study-aews -o jsonpath='{.items[0].metadata.annotations.CapacityProvisioned}'
0.5vCPU 1GB

# 디플로이먼트 상세 정보
kubectl get deploy -n study-aews netshoot -o yaml
...
  template:
    ...
    spec:
      ...
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 0
...

# 파드 상세 정보 : admission control 이 동작했음을 알 수 있음
kubectl get pod -n study-aews -l app=netshoot -o yaml
...
  metadata:
    annotations:
      CapacityProvisioned: 0.5vCPU 1GB
      Logging: LoggingEnabled
    ...
    preemptionPolicy: PreemptLowerPriority
    priority: 2000001000
    priorityClassName: system-node-critical
    restartPolicy: Always
    schedulerName: fargate-scheduler
    ...
    qosClass: Burstable

#
kubectl describe pod -n study-aews -l app=netshoot | grep Events: -A10

# 
kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io
kubectl describe mutatingwebhookconfigurations 0500-amazon-eks-fargate-mutation.amazonaws.com
kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io

# 파드 내부에 zsh 접속 후 확인
kubectl exec -it deploy/netshoot -n study-aews -- zsh
-----------------------------------------------------
ip -c a
cat /etc/resolv.conf
curl ipinfo.io/ip # 출력되는 IP는 어떤것? , 어떤 경로를 통해서 인터넷이 되는 걸까?
ping -c 1 <다른 파드 IP ex. coredns pod ip>
lsblk
df -hT /
cat /etc/fstab
exit
-----------------------------------------------------

 

 

 

☞ 파드 권한과 호스트 네임스페이스 공유로 호스트 탈취 시도 - Blog

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: root-shell
  namespace: study-aews
spec:
  containers:
  - command:
    - /bin/cat
    image: alpine:3
    name: root-shell
    securityContext:
      privileged: true
    tty: true
    stdin: true
    volumeMounts:
    - mountPath: /host
      name: hostroot
  hostNetwork: true
  hostPID: true
  hostIPC: true
  tolerations:
  - effect: NoSchedule
    operator: Exists
  - effect: NoExecute
    operator: Exists
  volumes:
  - hostPath:
      path: /
    name: hostroot
EOF

#
kubectl get pod -n study-aews root-shell
kubectl describe pod -n study-aews root-shell | grep Events: -A 10
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  48s   fargate-scheduler  Pod not supported on Fargate: fields not supported: HostNetwork, HostPID, HostIPC, volumes not supported: hostroot is of an unsupported volume Type, invalid SecurityContext fields: Privileged

# 출력 메시지
# Pod not supported on Fargate: fields not supported: 
# HostNetwork, HostPID, HostIPC, volumes not supported: 
# hostroot is of an unsupported volume Type, invalid SecurityContext fields: Privileged

# 삭제
kubectl delete pod -n study-aews root-shell


# (참고) fargate가 아닌 권한이 충분한 곳에서 실행 시 : 아래 처럼 호스트 네임스페이스로 진입 가능!
kubectl -n kube-system exec -it root-shell -- chroot /host /bin/bash
root@myk8s-control-plane:/# id
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo)

 

☞ AWS ALB(Ingress)

# 게임 디플로이먼트와 Service, Ingress 배포
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: study-aews
  name: deployment-2048
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app-2048
  replicas: 2
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app-2048
    spec:
      containers:
      - image: public.ecr.aws/l6m2t8p7/docker-2048:latest
        imagePullPolicy: Always
        name: app-2048
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: study-aews
  name: service-2048
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP
  selector:
    app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: study-aews
  name: ingress-2048
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: service-2048
              port:
                number: 80
EOF


# 모니터링
watch -d kubectl get pod,ingress,svc,ep,endpointslices -n study-aews

# 생성 확인
kubectl get-all -n study-aews
kubectl get ingress,svc,ep,pod -n study-aews
kubectl get targetgroupbindings -n study-aews

# Ingress 확인
kubectl describe ingress -n study-aews ingress-2048
kubectl get ingress -n study-aews ingress-2048 -o jsonpath="{.status.loadBalancer.ingress[*].hostname}{'\n'}"

# 게임 접속 : ALB 주소로 웹 접속
kubectl get ingress -n study-aews ingress-2048 -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | awk '{ print "Game URL = http://"$1 }'

# 파드 IP 확인
kubectl get pod -n study-aews -owide

# 파드 증가
kubectl scale deployment -n study-aews  deployment-2048 --replicas 4

# 게임 실습 리소스  삭제
kubectl delete ingress ingress-2048 -n study-aews
kubectl delete svc service-2048 -n study-aews && kubectl delete deploy deployment-2048 -n study-aews

 

fargate job

#
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
  name: busybox1
  namespace: study-aews
spec:
  template:
    spec:
      containers:
      - name: busybox
        image: busybox
        command: ["/bin/sh", "-c", "sleep 10"]
      restartPolicy: Never
  ttlSecondsAfterFinished: 60 # <-- TTL controller
---
apiVersion: batch/v1
kind: Job
metadata:
  name: busybox2
  namespace: study-aews
spec:
  template:
    spec:
      containers:
      - name: busybox
        image: busybox
        command: ["/bin/sh", "-c", "sleep 10"]
      restartPolicy: Never
EOF

#
kubectl get job,pod -n study-aews
kubectl get job -n study-aews -w
kubectl get pod -n study-aews -w
kubectl get job,pod -n study-aews

# 삭제
kubectl delete job -n study-aews --all

 

fargate logging

  • 들어가며 → 내장 로그 라우터는 어디에서 구동될까요???
    • Fargate의 Amazon EKS는 Fluent Bit 기반의 내장 로그 라우터를 제공합니다. 즉, Fluent Bit 컨테이너를 사이드카로 명시적으로 실행하지 않고 Amazon에서 실행합니다. 로그 라우터를 구성하기만 하면 됩니다.
      • Amazon EKS on Fargate offers a built-in log router based on Fluent Bit. This means that you don’t explicitly run a Fluent Bit container as a sidecar, but Amazon runs it for you.
    • 구성은 다음 기준을 충족해야 하는 전용 ConfigMap을 통해 이루어집니다.
      • 이름 : aws-logging
      • aws-observability라는 전용 네임스페이스에서 생성됨
      • 5300자를 초과할 수 없습니다.
    • ConfigMap을 생성하면 Fargate의 Amazon EKS가 자동으로 이를 감지하고 로그 라우터를 구성합니다. Fargate는 AWS에서 관리하는 Fluent Bit의 업스트림 호환 배포판인 Fluent Bit용 AWS 버전을 사용합니다. 자세한 내용은 GitHub의 Fluent Bit용 AWS를 참조하세요 - Docs
    • 로그 라우터를 사용하면 AWS의 다양한 서비스를 로그 분석 및 저장에 사용할 수 있습니다. Fargate에서 Amazon CloudWatch, Amazon OpenSearch 서비스로 로그를 직접 스트리밍할 수 있습니다. 또한 Amazon Data Firehose를 통해 Amazon S3, Amazon Kinesis 데이터 스트림 및 파트너 도구와 같은 대상으로 로그를 스트리밍할 수도 있습니다.
    • Fargate 포드를 배포할 기존 Kubernetes 네임스페이스를 지정하는 기존 Fargate 프로필입니다.
  • 로그 발생 nginx 배포
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  namespace: study-aews
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
          name: http
        resources:
          requests:
            cpu: 500m
            memory: 500Mi
          limits:
            cpu: 2
            memory: 2Gi
---
apiVersion: v1
kind: Service
metadata:
  name: sample-app
  namespace: study-aews
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  type: ClusterIP
EOF

# 확인
kubectl get pod -n study-aews -l app=nginx
kubectl describe pod -n study-aews -l app=nginx

# 반복 접속
kubectl exec -it deploy/netshoot -n study-aews -- curl sample-app | grep title
while true; do kubectl exec -it deploy/netshoot -n study-aews -- curl sample-app | grep title; sleep 1; echo ; date; done;

# 로그 확인
kubectl stern -n study-aews -l app=nginx

 

  • 로그 설정 정보 확인
# main.tf
...
  # Enable Fargate logging this may generate a large ammount of logs, disable it if not explicitly required
  enable_fargate_fluentbit = true
  fargate_fluentbit = {
    flb_log_cw = true
  }
...

# aws-observability라는 이름의 전용 네임스페이스 확인
kubectl get ns --show-labels

# Fluent Conf 데이터 값이 포함된 ConfigMap : 컨테이너 로그를 목적지로 배송 설정
## Amazon EKS Fargate 로깅은 ConfigMap의 동적 구성을 지원하지 않습니다.
## ConfigMap에 대한 모든 변경 사항은 새 포드에만 적용됩니다. 기존 포드에는 변경 사항이 적용되지 않습니다.
kubectl get cm -n aws-observability
kubectl get cm -n aws-observability aws-logging -o yaml
data:
  filters.conf: |
    [FILTER]
      Name parser
      Match *
      Key_name log
      Parser crio
    [FILTER]
      Name kubernetes
      Match kube.*
      Merge_Log On
      Keep_Log Off
      Buffer_Size 0
      Kube_Meta_Cache_TTL 300s
  flb_log_cw: "true"  # Ships Fluent Bit process logs to CloudWatch.
  output.conf: |+
    [OUTPUT]
          Name cloudwatch
          Match kube.*
          region ap-northeast-2
          log_group_name /fargate-serverless/fargate-fluentbit-logs2025031600585521800000000c
          log_stream_prefix fargate-logs-
          auto_create_group true
    [OUTPUT]
          Name cloudwatch_logs
          Match *
          region ap-northeast-2
          log_group_name /fargate-serverless/fargate-fluentbit-logs2025031600585521800000000c
          log_stream_prefix fargate-logs-fluent-bit-
          auto_create_group true

  parsers.conf: |
    [PARSER]
      Name crio
      Format Regex
      Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>P|F) (?<log>.*)$
      Time_Key    time
      Time_Format %Y-%m-%dT%H:%M:%S.%L%z
      Time_Keep On

  • 수집된 파드 로그 확인 : CW Log streams 에서 nginx 로 검색 필터링(fluent-bot 포함 체크) → First event time 중 가장 최근것 클릭

  • 아래 처럼 해당 로그 스트림 화면에서 상세 로그 정보 확인 : curl 접속 로그 확인

  • 삭제 : kubectl delete deploy,svc -n study-aews sample-app

☞  삭제 : 순서대로 삭제 할 것!!! FAQ (삭제 잘 안 되거나 오래 걸릴 때) 10분 소요 - Link

  • 실습 배포 리소스들 먼저 삭제
# 게임 실습 리소스  삭제
kubectl delete ingress ingress-2048 -n study-aews
kubectl delete svc service-2048 -n study-aews && kubectl delete deploy deployment-2048 -n study-aews

# netshoot 삭제
kubectl delete deploy netshoot -n study-aews
 
# kube-ops-view 삭제
helm uninstall kube-ops-view -n kube-system
  • 테라폼 삭제
# 테라폼 삭제 : vpc 삭제가 잘 안될 경우 aws 콘솔에서 vpc 수동 삭제 -> vnic 등 남아 있을 경우 해당 vnic 강제 삭제 
terraform destroy -auto-approve

# VPC 삭제 확인
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false' --output yaml

# kubeconfig 삭제
rm -rf ~/.kube/config