[Kubernetes] EC2 환경에서 Legery Kubernetes 구성하기 with Amazon Linux 2023

ondacloud·3일 전

Kubernetes

목록 보기
1/1
post-thumbnail

Overview

EC2 환경에서 Kubernetes를 직접 구축하는 방식은 AWS의 Managed Service인 EKS와 달리, 모든 구성 요소를 사용자가 직접 설치하고 제어해야 한다는 특징이 있습니다. 이러한 방식은 흔히 “Legacy Kubernetes” 또는 “kubeadm 기반 Self-managed Kubernetes”라고 부르며, Control Plane과 Worker Node를 모두 EC2 인스턴스 위에서 직접 구성하는 형태입니다.

이 글에서는 EC2 기반 Amazon Linux 2023 환경에서 kubeadm을 활용해 Kubernetes 클러스터를 구성하는 전체 과정을 다룹니다. Control Plane EC2 인스턴스를 초기화하고, Worker Node를 클러스터에 조인시키는 기본 구조부터 시작하여, Container Runtime 설정, CNI 네트워크 플러그인 설치, kubeconfig 구성까지 단계적으로 설명합니다.

또한 실제 운영 환경에서 중요한 네트워크 포트 설정, Security Group 구성, 그리고 클러스터 통신 구조까지 함께 다루어 단순 설치가 아닌 “동작하는 Kubernetes 클러스터”를 만드는 것을 목표로 합니다.

즉, EC2 기반 Legacy Kubernetes 구축은 관리형 서비스 없이도 Kubernetes를 직접 구성하고 운영할 수 있도록 해주는 가장 기본적이면서도 핵심적인 Self-managed 클러스터 구성 방식입니다.


Setup

Application

main.py

from fastapi import FastAPI
import uvicorn

app = FastAPI()

@app.get("/version")
def get_version():
    return {"version": "v1.0.0"}

@app.get("/healthcheck")
def get_healthcheck():
    return {"status": "ok"}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8080)

해당 애플리케이션은 Pod의 동작을 확인하기 위한 테스트용 코드입니다.


requirements.txt

fastapi==0.136.1
uvicorn==0.46.0

Dockerfile

FROM python:3.14-alpine

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

WORKDIR /app
COPY ./main.py /app/main.py
COPY ./requirements.txt /app/requirements.txt

RUN apk add --no-cache curl && pip install --no-cache-dir -r requirements.txt && rm -rf /root/.cache/

RUN adduser -D --disabled-password --gecos '' app-user
USER app-user

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

Practice

VPC

Public Subnet과 Private Subnet을 구성합니다. Availability Zone A와 C에 구성합니다.

VPCSubnetRoute TableGateway
demo-vpcdemo-public-ademo-public-rtbdemo-igw
demo-public-cdemo-public-rtbdemo-igw
demo-private-ademo-private-a-rtbdemo-natgw-a
demo-private-cdemo-private-c-rtbdemo-natgw-c

Security Group

Bastion

Inbound

TypePort RangeSourceDescription
SSH220.0.0.0/0EC2 접근

Outbound

TypePort RangeSourceDescription
SSH220.0.0.0/0EC2 접근
HTTP800.0.0.0/0패키지 다운로드 및 외부 통신
HTTPS4430.0.0.0/0패키지 다운로드 및 API 통신

ALB

Inbound

TypePort RangeSourceDescription
HTTP800.0.0.0/0외부 사용자 요청 수신

Outbound

TypePort RangeSourceDescription
Custom TCP30000-327670.0.0.0/0Kubernetes Nodeport Service로 트래픽 전달

Kubernetes Master Node

Inbound

TypePort RangeSourceDescription
SSH22Bastion Security GroupEC2 접근
Custom TCP64430.0.0.0/0Kubernetes API Server 접근
Custom TCP2379 - 23800.0.0.0/0etcd 클러스터 통신
Custom TCP102500.0.0.0/0kubelet API
Custom TCP1790.0.0.0/0Calico BGP 피어링

Outbound

TypePort RangeSourceDescription
HTTP800.0.0.0/0패키지 다운로드
HTTPS4430.0.0.0/0API 및 이미지 레지스트리 통신
Custom TCP64430.0.0.0/0Kubernetes API Server 통신
Custom TCP2379 - 23800.0.0.0/0etcd 통신
Custom TCP102500.0.0.0/0kubelet 통신
Custom TCP530.0.0.0/0DNS 질의
Custom UDP530.0.0.0/0DNS 질의

Kubernetes Worker Node

Inbound

TypePort RangeSourceDescription
SSH22Bastion Security GroupEC2 접근
Custom TCP10250Kubernetes Master Node Security Groupkubelet API
Custom TCP30000-32767ALB Security GroupNodeport Service 트래픽 수신

Outbound

TypePort RangeSourceDescription
HTTP800.0.0.0/0패키지 다운로드
HTTPS4430.0.0.0/0이미지 Pull 및 API 통신
Custom TCP64430.0.0.0/0Kubernetes API Server 통신
Custom TCP1790.0.0.0/0Calico BGP 통신
Custom TCP530.0.0.0/0DNS 질의
Custom UDP530.0.0.0/0DNS 질의

IAM

Kubernetes Node가 ECR 이미지를 Pull할 수 있도록 IAM Role을 생성하고 필요한 권한을 부여합니다.

Bastion

Role NamePolicy Name
bastion-roleAdministratorAccess

Kubernetes Node

Role NamePolicy Name
k8s-node-roleAmazonEC2ContainerRegistryFullAccess

EC2

Bastion

User Data

#!/bin/bash
dnf update -y
dnf upgrade -y
dnf install --allowerasing -y jq curl wget unzip vim

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

sed -i "s|PasswordAuthentication no|PasswordAuthentication yes|g" /etc/ssh/sshd_config
systemctl restart sshd
echo 'Skill53##' | passwd --stdin ec2-user
echo 'Skill53##' | passwd --stdin root

dnf install -y docker
systemctl enable --now docker
usermod -aG docker ec2-user
chmod 666 /var/run/docker.sock

Kubernetes Master Node

User Data

#!/bin/bash
dnf update -y
dnf upgrade -y
dnf install --allowerasing -y jq curl wget unzip vim

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

sed -i "s|PasswordAuthentication no|PasswordAuthentication yes|g" /etc/ssh/sshd_config
systemctl restart sshd
echo 'Skill53##' | passwd --stdin ec2-user
echo 'Skill53##' | passwd --stdin root

dnf install -y docker
systemctl enable --now docker
usermod -aG docker ec2-user
chmod 666 /var/run/docker.sock

Kubernetes Worker Node

User Data

#!/bin/bash
dnf update -y
dnf upgrade -y
dnf install --allowerasing -y jq curl wget unzip vim

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

sed -i "s|PasswordAuthentication no|PasswordAuthentication yes|g" /etc/ssh/sshd_config
systemctl restart sshd
echo 'Skill53##' | passwd --stdin ec2-user
echo 'Skill53##' | passwd --stdin root

ECR

ECR Registry를 생성합니다.


환경변수를 정의합니다.

ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
REGION_CODE="ap-northeast-2"
ECR_NAME="demo-ecr"
IMAGE_TAG="v1.0.0"
ECR_URI=$ACCOUNT_ID.dkr.ecr.$REGION_CODE.amazonaws.com/$ECR_NAME

Docker 이미지를 Build 후 Push합니다.

aws ecr get-login-password --region $REGION_CODE | docker login --username AWS --password-stdin "$ACCOUNT_ID.dkr.ecr.$REGION_CODE.amazonaws.com"
docker build -t "$ECR_URI:$IMAGE_TAG" .
docker push "$ECR_URI:$IMAGE_TAG"

Kubernetes

Master Node

Containerd Package를 설치합니다. Containerd는 컨테이너 런타임으로, kubelet이 컨테이너를 실행할 때 사용됩니다.

CONTAINERD_VERSION=$(curl -s https://api.github.com/repos/containerd/containerd/releases/latest | jq -r .tag_name)
curl -fsSLO https://github.com/containerd/containerd/releases/download/${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION#v}-linux-amd64.tar.gz
sudo tar -C /usr/local -xzf containerd-${CONTAINERD_VERSION#v}-linux-amd64.tar.gz
rm -rf containerd-${CONTAINERD_VERSION#v}-linux-amd64.tar.gz

Containerd 서비스 파일이 위치할 디렉터리를 생성합니다.

sudo mkdir -p /usr/local/lib/systemd/system

Containerd 설정파일을 systemd에 다운로드 합니다.

sudo curl -sSL https://raw.githubusercontent.com/containerd/containerd/main/containerd.service -o /usr/local/lib/systemd/system/containerd.service

systemd 설정을 다시 로드합니다.

sudo systemctl daemon-reload

Containerd를 실행합니다.

sudo systemctl enable --now containerd

runc Package를 설치합니다.

RUNC_VERSION=$(curl -s https://api.github.com/repos/opencontainers/runc/releases/latest | jq -r .tag_name)
curl -sSLO https://github.com/opencontainers/runc/releases/download/${RUNC_VERSION}/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc
rm -rf runc.amd64

CNI 플러그인이 설치될 경로를 생성합니다.

sudo mkdir -p /opt/cni/bin

CNI Package를 설치합니다.

CNI_VERSION=$(curl -s https://api.github.com/repos/containernetworking/plugins/releases/latest | jq -r .tag_name)
curl -sSLO https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-amd64-${CNI_VERSION}.tgz
sudo tar -C /opt/cni/bin -xzf cni-plugins-linux-amd64-${CNI_VERSION}.tgz
rm -rf cni-plugins-linux-amd64-${CNI_VERSION}.tgz

Kubernetes 패키지 저장소를 등록합니다.

sudo tee /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.35/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.35/rpm/repodata/repomd.xml.key
EOF

Kubernetes Package를 설치합니다.

kubeadm: 쿠버네티스 클러스터를 생성, 설정 및 초기화하는 구축 전용 도구
kubelet: 각 노드에서 실행되며 Pod의 컨테이너 상태를 관리하고 명령을 수행
kubectl: 사용자가 클러스터에 명령을 내리고 리소스를 제어하기 위해 사용하는 명령줄 도구

sudo dnf install -y kubeadm kubelet kubectl

패키지 버전을 고정할 수 있는 dnf 플러그인을 설치합니다.

sudo dnf install -y 'dnf-command(versionlock)'

Kubernetes Package의 버전을 고정합니다. (업데이트 방지)

sudo dnf versionlock add kubeadm kubelet kubectl


swap 메모리를 비활성화합니다.

sudo swapoff -a

재부팅 후에도 swap 메모리가 비활성화 되도록 설정합니다.

sudo sed -i '/ swap / s/^/#/' /etc/fstab

SELinux를 비활성화 합니다. (충돌 방지)

sudo setenforce 0

SELinux를 영구적으로 Permissive 모드로 설정합니다.

sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

Pod 네트워크 라우팅을 허용합니다.

sudo sh -c 'echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf'

sysctl 명령어를 사용하여 설정을 적용합니다.

sudo sysctl -p

kubelet을 자동 실행합니다.

sudo systemctl enable --now kubelet

Path를 설정합니다. (kubeadm 실행 오류 방지)

export PATH=$PATH:/sbin

EC2 MetaData 접근 토큰을 생성하며, 토큰을 사용하여 MetaData에서 EC2의 Private IP를 가져옵니다.

TOKEN=$(curl -sSX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
PRIVATE_IP=$(curl -sS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-ipv4)

Kubernetes를 초기화 합니다. 초기화 후 나온 kubeadm join 값을 저장합니다.

  • 나중에 Worker Node에서 Master Node로 Join할 때 사용합니다.

만약, kubeadm join 값이 없어졌다면 아래 명령어를 사용하여 새로 발급받습니다.

sudo kubeadm token create --print-join-command
sudo PATH=$PATH:/sbin kubeadm init --apiserver-advertise-address=$PRIVATE_IP --pod-network-cidr=192.168.0.0/16


kubeconfig 파일을 생성합니다.

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Calico Package를 설치합니다.

CNI_VERSION=$(curl -s https://api.github.com/repos/projectcalico/calico/releases/latest | jq -r .tag_name)
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/$CNI_VERSION/manifests/calico.yaml

Pod의 상태가 Running인지 확인합니다.

kubectl get po -n kube-system


Node의 상태가 Ready인지 확인합니다.

kubectl get no


etcd Package를 설치합니다.

ETCD_VERSION=$(curl -s https://api.github.com/repos/etcd-io/etcd/releases/latest | jq -r .tag_name)
curl -sSLO https://github.com/etcd-io/etcd/releases/download/$ETCD_VERSION/etcd-$ETCD_VERSION-linux-amd64.tar.gz
tar xzf etcd-$ETCD_VERSION-linux-amd64.tar.gz
sudo mv etcd-$ETCD_VERSION-linux-amd64/etcdctl /usr/local/bin/
rm -rf etcd-$ETCD_VERSION-linux-amd64*

etcd Pod가 Running인지 확인합니다.

kubectl get po -n kube-system


etcd에서 사용하는 인증서(SSL/TLS 키 파일)이 존재하는지 확인합니다.

ls /etc/kubernetes/pki/etcd 


Secret을 생성합니다.

kubectl create secret generic demo-old-secrets --from-literal=key=topsecret

etcd 내부 저장값을 확인합니다. 암호화가 안되어 있어 평문으로 나오고 있음을 확인할 수 있습니다.

기본적으로 Kubernetes Secrets은 etcd에 평문(정확히는 단순 Base64 인코딩)으로 저장되어, DB 접근 권한이 있으면 누구나 내용을 확인할 수 있습니다.

sudo etcdctl \
   --cacert=/etc/kubernetes/pki/etcd/ca.crt \
   --cert=/etc/kubernetes/pki/etcd/server.crt \
   --key=/etc/kubernetes/pki/etcd/server.key \
   get /registry/secrets/default/demo-old-secrets | hexdump -C


Secret 암호화 설정 파일을 생성합니다. 이때 AES 암호화 알고리즘 중 CBC 모드를 사용하여 데이터를 암호화 합니다.

AES (Advanced Encryption Standard)
미국 표준 암호화로 대칭키 방식을 사용합니다. 데이터를 암호화할 때와 복호화할 때 동일한 키를 사용합니다.


CBC (Cipher Block Chaining)
AES는 데이터를 한 번에 처리하지 않고 일정한 크기(블록)로 나누어 처리합니다. 이때 블록들을 어떻게 서로 엮어서 암호화할지 결정하는 방식이 바로 CBC입니다.

cat <<\EOF> enc.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key
              secret: ENCRYPTION_KEY
      - identity: {} 
EOF

암호화 키를 생성합니다.

ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)

암호화키를 Secret 암호화 설정 파일에 삽입합니다.

sed -i "s|ENCRYPTION_KEY|$ENCRYPTION_KEY|g" enc.yaml

Secret 암호화 설정 파일이 위치할 디렉터리를 생성합니다.

sudo mkdir -p /etc/kubernetes/enc/

Secret 암호화 설정 파일을 위에서 생성한 디렉터리로 이동합니다.

sudo mv enc.yaml /etc/kubernetes/enc/

API Server의 설정 파일에서 아래 Encryption 설정을 추가합니다. 추가 후 저장하고 나가면 API Server가 자동으로 재시작됩니다.

sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml

spec.containers[0].command

- --encryption-provider-config=/etc/kubernetes/enc/enc.yaml

spec.containers[0].volumeMounts

- name: enc
  mountPath: /etc/kubernetes/enc
  readOnly: true

spec.volumes

- name: enc
  hostPath:
    path: /etc/kubernetes/enc
    type: DirectoryOrCreate


Secret을 생성합니다.

kubectl create secret generic demo-new-secrets --from-literal=key=topsecret

etcd 내부 저장값을 확인합니다. 암호화가 되어 있는 것을 확인할 수 있습니다.

sudo etcdctl \
   --cacert=/etc/kubernetes/pki/etcd/ca.crt \
   --cert=/etc/kubernetes/pki/etcd/server.crt \
   --key=/etc/kubernetes/pki/etcd/server.key \
   get /registry/secrets/default/demo-new-secrets | hexdump -C


Secret 전체에 암호화가 적용되었는지 확인합니다.

kubectl get secrets --all-namespaces -o json | kubectl replace -f -


API Server가 실행중인지 확인합니다.

ps aux | grep kube-api


API Server에서 암호화가 적용되었는지 확인합니다.

ps aux | grep kube-api | grep encry


Worker Node

Containerd Package를 설치합니다.

CONTAINERD_VERSION=$(curl -s https://api.github.com/repos/containerd/containerd/releases/latest | jq -r .tag_name)
curl -fsSLO https://github.com/containerd/containerd/releases/download/${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION#v}-linux-amd64.tar.gz
sudo tar -C /usr/local -xzf containerd-${CONTAINERD_VERSION#v}-linux-amd64.tar.gz
rm -rf containerd-${CONTAINERD_VERSION#v}-linux-amd64.tar.gz

Containerd 서비스 파일이 위치할 디렉터리를 생성합니다.

sudo mkdir -p /usr/local/lib/systemd/system

Containerd 설정파일을 systemd에 다운로드 합니다.

sudo curl -sSL https://raw.githubusercontent.com/containerd/containerd/main/containerd.service -o /usr/local/lib/systemd/system/containerd.service

systemd 설정을 다시 로드합니다.

sudo systemctl daemon-reload

Containerd를 실행합니다.

sudo systemctl enable --now containerd

runc Package를 설치합니다.

RUNC_VERSION=$(curl -s https://api.github.com/repos/opencontainers/runc/releases/latest | jq -r .tag_name)
curl -sSLO https://github.com/opencontainers/runc/releases/download/${RUNC_VERSION}/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc
rm -rf runc.amd64

Kubernetes 패키지 저장소를 등록합니다.

sudo tee /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.35/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.35/rpm/repodata/repomd.xml.key
EOF

Kubernetes Package를 설치합니다.

sudo dnf install -y kubeadm kubelet

패키지 버전을 고정할 수 있는 dnf 플러그인을 설치합니다.

sudo dnf install -y 'dnf-command(versionlock)'

Kubernetes Package의 버전을 고정합니다. (업데이트 방지)

sudo dnf versionlock add kubeadm kubelet


swap 메모리를 비활성화합니다.

sudo swapoff -a

재부팅 후에도 swap 메모리가 비활성화 되도록 설정합니다.

sudo sed -i '/ swap / s/^/#/' /etc/fstab

SELinux를 비활성화 합니다. (충돌 방지)

sudo setenforce 0

SELinux를 영구적으로 Permissive 모드로 설정합니다.

sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

Pod 네트워크 라우팅을 허용합니다.

sudo sh -c 'echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf'

sysctl 명령어를 사용하여 설정을 적용합니다.

sudo sysctl -p

kubelet을 자동 실행합니다.

sudo systemctl enable --now kubelet

Worker Node를 Master Node에 Join합니다. Master Node에서 kubeadm init 후 나온 값을 넣습니다.

만약, 해당 값을 잊어버렸다면 Master Node에서 아래 명령어 입력 후 나온 값을 넣어줍니다.

sudo kubeadm token create --print-join-command
sudo kubeadm join 10.0.2.135:6443 --token a5fwyw.t1nljbrukh3k6d2z \
  --discovery-token-ca-cert-hash sha256:85d09c2a09226d7c2678d178ce8c0ebcc1cd14ff0f4471bcc2b7e1e902b5bc49


Master Node

Worker Node가 Master Node에 정상적으로 Join 되었는지 확인합니다. Node의 상태가 Ready인지 확인합니다.

kubectl get no


Namespace를 생성합니다.

kubectl create ns demo

환경변수를 설정합니다.

ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
REGION_CODE="ap-northeast-2"

ECR에서 이미지를 할당 받을 수 있도록 ECR에 대한 Secrets를 생성합니다.

kubectl create secret docker-registry ecr-secret \
  --namespace=demo \
  --docker-server=$ACCOUNT_ID.dkr.ecr.$REGION_CODE.amazonaws.com \
  --docker-username=AWS \
  --docker-password=$(aws ecr get-login-password --region $REGION_CODE)

Deployment 설정 파일을 생성합니다.

cat <<\EOF> deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-deploy
  namespace: demo
  labels:
    app: demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      imagePullSecrets:
      - name: ecr-secret
      containers:
      - name: demo-cnt
        image: IMAGE
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
EOF

이미지에 대한 환경변수를 설정합니다.

ECR_NAME="demo-ecr"
IMAGE_TAG="v1.0.0"
ECR_URI=$ACCOUNT_ID.dkr.ecr.$REGION_CODE.amazonaws.com/$ECR_NAME

이미지를 ECR Registry에 업로드된 이미지로 변경합니다.

sed -i "s|IMAGE|$ECR_URI:$IMAGE_TAG|g" deployment.yaml

Deployment를 배포합니다.

kubectl apply -f deployment.yaml

Service 설정 파일을 생성합니다.

cat <<\EOF> service.yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-svc
  namespace: demo
spec:
  selector:
    app: demo
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30000
  type: NodePort
EOF

Service를 배포합니다.

kubectl apply -f service.yaml

Worker Node

curl http://localhost:30000/version


curl http://localhost:30000/healthcheck

정상적으로 API 호출이 되는 것을 확인할 수 있습니다.


ALB

Target Group

Target Group Port는 Service의 NodePort(30000)에 맞춰 Target Group Port를 동일하게 설정합니다.


Load Balancer


Test

ALB_NAME="demo-alb"
ALB_DNS=$(aws elbv2 describe-load-balancers --names $ALB_NAME --query "LoadBalancers[].DNSName" --output text)
curl $ALB_DNS/version

curl $ALB_DNS/healthcheck

정상적으로 API 호출이 되는 것을 확인할 수 있습니다.


Result

이번 실습을 통해 kubeadm을 활용하여 Kubernetes 클러스터를 직접 구성하는 전체 과정을 확인할 수 있었습니다.
기존에는 관리형 서비스 없이 Kubernetes 환경을 구축하기 위해 복잡한 설정과 수동 구성이 필요했지만, kubeadm을 사용하면 Control Plane과 Worker Node를 비교적 표준화된 방식으로 손쉽게 구성할 수 있습니다.

또한 containerd, CNI 플러그인, kubelet 등의 구성 요소를 직접 설치하고 설정함으로써 Kubernetes의 내부 구조와 동작 방식을 깊이 이해할 수 있었습니다. 특히 etcd, API Server, 그리고 네트워크 구성 요소 간의 관계를 실습을 통해 명확히 파악할 수 있었습니다.

더불어 Secret의 etcd 저장 구조와 Encryption 설정을 통해 Kubernetes의 보안 메커니즘까지 확인할 수 있었으며, NodePort 기반 서비스와 외부 접근 구성을 통해 실제 서비스 배포 흐름을 경험할 수 있었습니다.

이러한 과정은 관리형 Kubernetes(EKS 등)를 사용할 때는 보이지 않는 내부 동작을 이해하는 데 중요한 기반이 되며, 문제 해결 능력과 운영 역량을 향상시키는 데 큰 도움이 되었습니다.

profile
Devops Engineer가 목표인 학생

0개의 댓글