Post

쿠버네티스 & AWS EKS: kubeadm EC2 실습부터 실전 운영까지

쿠버네티스 핵심 개념, EKS 아키텍처, eksctl로 프로덕션 준비 클러스터 구성, 네트워킹/스토리지/보안/오토스케일링/관측성, 그리고 EC2에서 kubeadm 단일 노드 실습까지 정리

쿠버네티스 & AWS EKS: kubeadm EC2 실습부터 실전 운영까지

쿠버네티스(Kubernetes, K8s)는 컨테이너 애플리케이션의 배포·확장·운영을 자동화하는 표준 플랫폼입니다. AWS에서는 이 쿠버네티스를 완전관리형으로 제공하는 Amazon EKS(Elastic Kubernetes Service)를 통해, 제어plane 운영 부담 없이 안전하고 일관된 클러스터를 구축·운영할 수 있습니다.

이 글은 다음을 모두 담습니다.

  • K8s 핵심 개념 & 아키텍처
  • EKS 아키텍처와 실전 구성 요소 (네트워킹, 스토리지, 보안, 오토스케일링, 관측성)
  • eksctl로 EKS 빠른 구축 + 필수 애드온 설치 예시
  • EC2에서 kubeadm로 단일 노드 실습(학습용) — 제공된 스크립트 보완 버전 포함
  • 체크리스트/트러블슈팅 꿀팁

1) 쿠버네티스 한눈에 보기

왜 쿠버네티스인가?

  • 자동 배포/롤백: 롤링 업데이트, 실패 시 자동 롤백
  • 오토스케일: 트래픽 증가에 자동 대응 (HPA/VPA/Cluster Autoscaler)
  • 자기 치유: 비정상 Pod 자동 교체/재시작
  • 서비스 디스커버리/로드밸런싱: 서비스 단위로 안정적인 접근
  • 스토리지/시크릿 관리: 다양한 스토리지·비밀 관리 연계

기본 오브젝트

  • Pod(최소 실행 단위), Deployment(배포전략), Service(내/외부 노출), ConfigMap/Secret, Ingress, Namespace

아키텍처 요약

1
2
3
4
5
6
7
8
9
10
11
[ Control Plane ]
 ├─ kube-apiserver   (모든 요청 관문)
 ├─ etcd             (상태 저장 KV 스토어)
 ├─ scheduler        (Pod 배치 결정)
 └─ controller-mgr   (원하는 상태 유지)

[ Worker Node ]
 ├─ kubelet          (노드 에이전트)
 ├─ kube-proxy       (서비스 네트워킹)
 └─ Container Runtime(containerd 등)
      └─ Pods → Containers

2) EKS 핵심 개념

EKS 아키텍처(요약 다이어그램)

flowchart LR
  subgraph AWS[Amazon EKS]
    CP[k8s Control Plane<br/>API Server/etcd/Controllers AWS 관리]
    subgraph DP[Data Plane]
      MNG[Managed Node Group EC2]
      Fargate[Fargate Profiles]
    end
  end
  Users[DevOps/Apps] -->|kubectl/CI| CP
  CP <-->|CNI/Pod IP| DP
  DP --> ALB[ALB/NLB via AWS Load Balancer Controller]
  DP --> EBS[EBS CSI]
  DP --> EFS[EFS CSI]
  DP --> CW[CloudWatch/OTel/Prometheus]

Control Plane

  • 완전관리형: 고가용성, 자동 패치/백업. VPC 외부에 AWS가 운영.

Data Plane(선택)

  • Managed Node Group(EC2): 버전/AMI 롤링, 온디맨드·스팟 혼합 가능
  • Fargate: 서버리스 Pod 실행(노드 운영 無), 빌드·잡·저부하 워크로드에 적합

Add-ons(관리형/수동)

  • VPC CNI, CoreDNS, kube-proxyManaged Add-on으로 버전 고정/업그레이드 관리
  • 필수 애드온: EBS/EFS CSI, AWS Load Balancer Controller, Metrics Server, (선택) Karpenter/Cluster Autoscaler, OpenTelemetry/Prometheus

3) EKS 네트워킹 제대로 이해하기

VPC CNI (aws-node)

  • Pod에 VPC IP를 직접 할당. 노드 ENI/Prefix Delegation 설정에 따라 Pod 수용량이 달라짐.
  • 고밀도 환경은 Prefix Delegation 활성화보조 CIDR로 여유 확보 권장.

보안그룹

  • Cluster Security Group(제어plane↔노드), Node SG, (선택)Security Group for Pods로 세분화 가능.

외부 노출

  • Service Type: ClusterIP / NodePort / LoadBalancer(NLB/ALB)
  • Ingress + AWS Load Balancer Controller로 L7 라우팅(도메인·경로 기반) 권장
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port: { number: 80 }

4) 스토리지 전략

EBS CSI (블록)

  • StatefulSet, DB 등 AZ 종속 워크로드에 적합. StorageClass로 동적 프로비저닝.
1
2
3
4
5
6
7
8
9
10
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer

EFS CSI (공유)

  • 다수 Pod가 공유 읽기/쓰기 필요 시 적합(웹 자산 등). AZ 무관 공유.

5) 권한·보안

인증/인가

  • aws-iam-authenticator: IAM 사용자/역할을 K8s RBAC에 매핑(aws-auth ConfigMap)
  • IRSA(IAM Roles for Service Accounts): Pod에 세분화된 IAM 권한 부여(비밀키 無)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: ServiceAccount
metadata:
  name: s3-reader
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<ACC>:role/sa-s3-read
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  template:
    spec:
      serviceAccountName: s3-reader

Pod 보안

  • Pod Security Admission(Baseline/Restricted), SecurityContext(cap drop, runAsNonRoot)
  • Secrets Store CSI + AWS Secrets Manager로 시크릿 마운트
  • 프라이빗 클러스터 & API 엔드포인트 제한, ECR 프라이빗

6) 오토스케일링

계층도구포인트
PodHPACPU/메모리/외부 지표 기반 레플리카 증감
PodVPA컨테이너 리소스 권장치 산출/적용
노드Cluster Autoscaler노드그룹 증감(빈패드/스케줄 실패 시)
노드Karpenter워크로드 기반 즉시 노드 프로비저닝·정리(비용/속도 유리)

7) 관측성·로깅

  • CloudWatch Container Insights: 메트릭/로그 수집(에이전트/EMF)
  • Prometheus/Grafana: 메트릭 표준(AMP/AMG 관리형도 선택지)
  • OpenTelemetry: 추적/로그/메트릭 통합 파이프라인 (X-Ray/OTLP)

8) 업그레이드 전략

  1. Control Plane 버전 업(콘솔/CLI)
  2. Managed Node Group 롤링 업데이트(AMI/버전)
  3. Add-on(VPC CNI, CoreDNS, kube-proxy, CSI) 순서대로

워크로드 중단 최소화를 위해 블루그린 노드그룹, 서지 업그레이드, PDB/PDB 고려


9) 비용 최적화 팁

  • 스팟 + 온디맨드 혼합 노드그룹, Karpenter로 인스턴스 선택 자동화
  • HPA/CA로 과도한 프로비저닝 방지, 적절한 리소스 리밋/리퀘스트
  • ALB/NLB/데이터 전송 비용 체킹, EBS gp3 전환

10) 실습: eksctl로 EKS 빠르게 만들기

사전 준비: AWS CLI, eksctl, kubectl 설치 및 자격증명, 기본 VPC(또는 지정 VPC/Subnet)

10-1) 클러스터 정의 파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# eksctl-cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: minji-eks
  region: ap-northeast-2
  version: "1.29"
vpc:
  # 기존 VPC/서브넷을 지정하려면 여기 매핑
managedNodeGroups:
  - name: mng-spot
    instanceTypes: ["m5.large","m5a.large","c6i.large"]
    desiredCapacity: 2
    minSize: 1
    maxSize: 5
    spot: true
    labels: { role: app }
addons:
  - name: vpc-cni
  - name: kube-proxy
  - name: coredns
iam:
  withOIDC: true
1
2
3
4
5
# 생성
eksctl create cluster -f eksctl-cluster.yaml

# 컨텍스트 확인
kubectl get nodes -o wide

10-2) 필수 애드온 설치

AWS Load Balancer Controller(IRSA)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# IRSA용 IAM 정책/역할 생성 (eksctl 헬퍼 사용)
eksctl utils associate-iam-oidc-provider --region ap-northeast-2 --cluster minji-eks --approve
eksctl create iamserviceaccount \
  --cluster minji-eks \
  --namespace kube-system \
  --name aws-load-balancer-controller \
  --attach-policy-arn arn:aws:iam::aws:policy/ElasticLoadBalancingFullAccess \
  --approve

# Helm 설치	hel m repo add eks https://aws.github.io/eks-charts
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=minji-eks \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller

EBS CSI Driver(관리형 Add-on 권장)

1
2
3
aws eks create-addon \
  --cluster-name minji-eks \
  --addon-name aws-ebs-csi-driver

Metrics Server

1
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

(선택) Karpenter로 노드 최적화, AMP/AMG로 관측성 관리형 전환 가능

10-3) 샘플 앱 배포/Ingress

1
2
kubectl create deployment web --image=nginx:1.27
kubectl expose deployment web --port 80 --type ClusterIP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web
            port:
              number: 80
1
2
3
kubectl apply -f ingress.yaml
# 생성된 ALB 주소 확인 후 접속
kubectl get ingress web

11) (학습용) EC2에 kubeadm로 단일 노드 설치

목적: K8s 내부 동작을 손에 익히기 위한 온프레미스 스타일 실습. 운영은 EKS 권장.

준비물

  • EC2 Amazon Linux 2023, t3.medium 권장
  • 보안그룹 인바운드: SSH(22), API 서버(6443), NodePort(30000–32767)
  • sudo 권한 계정

필수 보완 사항 요약

  1. SELinux: AL2023 기본 permissive. 필요 시 sed로 안전 변경, 무분별한 파일 덮어쓰기 금지.
  2. cgroup v2 + containerd SystemdCgroup: SystemdCgroup=true 필수.
  3. Swap 비활성: kubelet 호환성 위해 꺼두기 권장.
  4. Calico 호환: v1.31~v1.33 ⇄ v3.30 계열 안전.

정리된 설치 스크립트(수정본)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
### 1) 커널 모듈/네트워크, SELinux, containerd
cat <<'EOF' | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay && sudo modprobe br_netfilter

cat <<'EOF' | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
EOF
sudo sysctl --system

# SELinux 상태 확인(기본 permissive), 필요 시에만 안전 교체
getenforce || true
# sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
# sudo setenforce 0 || true

sudo dnf -y update && sudo dnf -y install containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl enable --now containerd

# Swap 비활성
sudo swapoff -a
sudo sed -ri 's/^(\s*[^#].*\sswap\s)/# \1/' /etc/fstab
1
2
3
4
5
6
7
8
9
10
11
### 2) kubeadm/kubelet/kubectl 설치 (v1.33 예시)
cat <<'EOF' | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key
EOF
sudo dnf -y install kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable kubelet
1
2
3
4
5
6
7
8
### 3) 컨트롤 플레인 초기화
sudo reboot
# 재접속 후, 단일 NIC가 아니면 --apiserver-advertise-address=<프라이빗IP> 추가
sudo kubeadm init --pod-network-cidr=192.168.0.0/16

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
1
2
3
4
### 4) Calico 설치 & 단일 노드 테인트 제거
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.30.2/manifests/calico.yaml
kubectl -n kube-system get pods -w
kubectl taint nodes --all node-role.kubernetes.io/control-plane- || true
1
2
3
4
5
### 5) 샘플 NGINX 배포/노출
kubectl create deployment web --image=nginx:1.27
kubectl expose deployment web --type=NodePort --port=80
kubectl get svc web -o wide
# 보안그룹에 30000–32767/tcp 열고 외부에서 http://<EC2_PUBLIC_IP>:<NODE_PORT>

빠른 점검 체크리스트

  • SystemdCgroup=true 미적용 시 CNI/etcd CrashLoop → containerd·kubelet 재시작
  • kubectl get nodes, kubectl -n kube-system get pods가 Ready/Running?
  • NodePort 접근 불가 → 보안그룹/NACL/서브넷 라우팅 확인

12) 트러블슈팅 & 체크리스트

  • DNS 이슈: CoreDNS Pending/Crash → 노드 IP/Pod CIDR 충돌, CNI 버전 맞춤
  • 이미지 풀 실패: ECR 권한/프라이빗 서브넷 NAT 확인
  • HPA 미동작: Metrics Server 설치·TLS 옵션 확인
  • IRSA 안 먹힘: OIDC Provider 연결, ServiceAccount annotation/정책 확인
  • ALB Ingress 실패: 컨트롤러 이벤트, ACM 인증서, 서브넷 태깅(kubernetes.io/role/elb) 점검
This post is licensed under CC BY 4.0 by the author.