이제 쿠버네티스를 설치해야한다.

 

Windows 의 경우는

개발환경: Java/Spring Boot/IntelliJ(Gradle)

컨테이너 오케스트레이션: Kubernetes

컨테이너 런타임: ContainerD

가상환경: Virtual Box(Rocky Linux)

컨테이너 빌드: Docker

CI/CD: Jenkins

 

지금 나는 M1 pro MacBook Pro에서 환경설정 중

1. Rocky9 ISO 파일 다운

2. UTM 맥용 하이퍼바이저 방식의 가상화 도구 설치

3. Rocky OS 설치

4. 클러스터 설치 및 Pod 확인

설치 스크립트 전문

echo '======== [4] Rocky Linux 기본 설정 ========'
echo '======== [4-1] 패키지 업데이트 ========'
# 강의와 동일한 실습 환경을 유지하기 위해 Linux Update 주석 처리
# yum -y update

echo '======== [4-2] 타임존 설정 ========'
timedatectl set-timezone Asia/Seoul
timedatectl set-ntp true
chronyc makestep

echo '======== [4-3] [WARNING FileExisting-tc]: tc not found in system path 로그 관련 업데이트 ========'
yum install -y yum-utils iproute-tc
echo '======== [4-3] [WARNING OpenSSL version mismatch 로그 관련 업데이트 ========'
yum update openssl openssh-server -y

echo '======= [4-4] hosts 설정 =========='
cat << EOF >> /etc/hosts
192.168.56.30 k8s-master
EOF

echo '======== [5] kubeadm 설치 전 사전작업 ========'
echo '======== [5] 방화벽 해제 ========'
systemctl stop firewalld && systemctl disable firewalld

echo '======== [5] Swap 비활성화 ========'
swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab

echo '======== [6] 컨테이너 런타임 설치 ========'
echo '======== [6-1] 컨테이너 런타임 설치 전 사전작업 ========'
echo '======== [6-1] iptable 세팅 ========'
cat <<EOF |tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

cat <<EOF |tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sysctl --system

echo '======== [6-2] 컨테이너 런타임 (containerd 설치) ========'
echo '======== [6-2-1] containerd 패키지 설치 (option2) ========'
echo '======== [6-2-1-1] docker engine 설치 ========'
echo '======== [6-2-1-1] repo 설정 ========'
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

echo '======== [6-2-1-1] containerd 설치 ========'
yum install -y containerd.io-1.6.21-3.1.el9.aarch64
systemctl daemon-reload
systemctl enable --now containerd

echo '======== [6-3] 컨테이너 런타임 : cri 활성화 ========'
containerd config default > /etc/containerd/config.toml
sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd

echo '======== [7] kubeadm 설치 ========'
echo '======== [7] repo 설정 ========'
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

echo '======== [7] SELinux 설정 ========'
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

echo '======== [7] kubelet, kubeadm, kubectl 패키지 설치 ========'
yum install -y kubelet-1.27.2-150500.1.1.aarch64 kubeadm-1.27.2-150500.1.1.aarch64 kubectl-1.27.2-150500.1.1.aarch64 --disableexcludes=kubernetes
systemctl enable --now kubelet

echo '======== [8] kubeadm으로 클러스터 생성  ========'
echo '======== [8-1] 클러스터 초기화 (Pod Network 세팅) ========'
kubeadm init --pod-network-cidr=20.96.0.0/16 --apiserver-advertise-address 192.168.56.30

echo '======== [8-2] kubectl 사용 설정 ========'
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

echo '======== [8-3] Pod Network 설치 (calico) ========'
kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico.yaml
kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico-custom.yaml

echo '======== [8-4] Master에 Pod를 생성 할수 있도록 설정 ========'
kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane-

echo '======== [9] 쿠버네티스 편의기능 설치 ========'
echo '======== [9-1] kubectl 자동완성 기능 ========'
yum -y install bash-completion
echo "source <(kubectl completion bash)" >> ~/.bashrc
echo 'alias k=kubectl' >>~/.bashrc
echo 'complete -o default -F __start_kubectl k' >>~/.bashrc
source ~/.bashrc

echo '======== [9-2] Dashboard 설치 ========'
kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/dashboard-2.7.0/dashboard.yaml

echo '======== [9-3] Metrics Server 설치 ========'
kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/metrics-server-0.6.3/metrics-server.yaml

 

 

전체 흐름 요약 (쿠버네티스 설치 스크립트 해설)


[1~4단계] 기본 OS 설정

  • 패키지 업데이트는 주석 처리 (강의 환경 통일 목적)
  • 타임존 설정: Asia/Seoul + NTP 동기화
  • 필수 키지 설치: tc, openssl 관련 경고 방지
  • hosts 파일 등록: IP ↔ 호스트명 등록 (e.g., 192.168.56.30 k8s-master)
  • 방화벽 해제: firewalld 비활성화
  • Swap 비활성화: 쿠버네티스는 Swap 사용 비권장

[6단계] 컨테이너 런타임 설치 (containerd)

  • 커널 모듈 설정: overlay, br_netfilter 로 브리지 네트워크 처리 가능하게
  • iptables 세팅: 파드 간 포워딩 설정
  • IP 포워딩 및 브리지 네트워크 설정 (/etc/sysctl.d/k8s.conf)
  • containerd 설치
    • docker-ce.repo를 추가해 Docker 공식 저장소 사용
    • containerd.io 설치 (버전 명시되어 있음)
  • containerd 설정
    • 기본 설정 파일 생성 (/etc/containerd/config.toml)
    • SystemdCgroup 설정 true → 쿠버네티스와 호환을 위한 설정
    • 재시작

[7단계] 쿠버네티스 설치

  • YUM repo 설정: Kubernetes 공식 저장소 설정
  • SELinux 완화: permissive로 변경 (쿠버네티스 호환 목적)
  • kubelet, kubeadm, kubectl 설치
    • 버전 명시 (1.27.2)
    • 시스템 서비스 등록

[8단계] 클러스터 초기화 및 네트워크 구성

  • kubeadm으로 초기화
    • -pod-network-cidr=20.96.0.0/16: Pod 네트워크 범위 설정
    • -apiserver-advertise-address: 마스터 노드 IP 지정
  • kubectl 사용 환경 설정
    • ~/.kube/config 설정
  • Calico Pod 네트워크 설치
    • 기본 설정 + 사용자 정의 설정 두 개 yaml 적용
    • Calico는 CNI 플러그인
      • CNI를 실제로 구현한 구현체 프로그램
      • Pod 간 통신 구성
      • Pod에 IP 할당
    • CNI(Container Network Interface): 쿠버네티스가 컨테이너에 네트워크를 붙여주는 방식에 대한 표준 인터페이스
  • Master 노드에 Pod 생성 허용
    • taint 제거 명령으로 Master에 워크로드 배포 가능하게

[9단계] 편의 기능 설치

  • kubectl 자동완성 + alias 등록
  • Kubernetes Dashboard 설치
  • Metrics Server 설치
  • → Dashboard에 리소스 사용량 데이터 표시 가능

핵심 흐름 도식

[OS 세팅] → 
[런타임(containerd)] → 
[Kubernetes 설치(kubeadm)]→ 
[클러스터 초기화] → 
[네트워크(Calico)] → 
[Dashboard & Metrics]

결과

이 스크립트를 실행하면:

  • 단일 노드 쿠버네티스 클러스터
  • Calico 네트워크 플러그인
  • Web UI (Dashboard) + Metrics
  • CLI 편의 기능 포함

추가적으로 알아본 것

kubeadm

쿠버네티스 클러스터 설치/초기화 도구

쿠버네티스 클러스터를 빠르게 설치하고 초기화하기 위한 명령어 도구

처음 구축 시에 사용

  • Control Plane 구성
  • 마스터노드 생성
  • 워커노드 조인
  • TLS 인증서, 키 생성
  • etcd, API server, schedulerm controller-manager 등 핵심 컴포넌트 실행
kubeadm init            # 마스터 노드 초기화 (클러스터 생성)
kubeadm join            # 워커 노드 클러스터에 참여
kubeadm reset           # 클러스터 초기화 상태로 되돌리기

kubectl

쿠버네티스 클러스터에 명령을 내리고 상태를 확인하는 CLI 도구

구축 후 계속 사용

  • 클러스터에 명령 전달
  • 리소스 생성, 삭제, 로그 확인 등 관리
  • kube-apiserver와 통신 → 실제 리소스 조작
kubectl get pods        # 파드 목록 확인
kubectl apply -f a.yaml # yaml로 리소스 생성/업데이트
kubectl delete pod xxx  # 파드 삭제
kubectl logs pod-name   # 파드 로그 확인
kubectl exec -it pod -- bash  # 파드 안으로 접속

kubeadm이 핵심 컴포넌트 실행해준다고 할때 나왔던 것들

  1. etcd: 기억저장소
    1. 쿠버네티스의 모든 상태 정보를 저장하는 DB(키벨류 형태)
    2. 분산 저장도 가능
  2. kube-apiserver: 호텔 리셉션
    1. 쿠버네티스의 중앙 API 엔드포인트
    2. kubectl 또는 내부 컴포터넌트가 보내는 모든 요청 수신
    3. 인증, 권한 부여, 유효성 검사를 거쳐 etcd와 통신
  3. kube-scheduler: Pod 에게 집을 골라주는 중개인
    1. 새로운 Pod이 생성될 때 어떤 노드에 배치할지 결정
    2. 자원 상황, taint(Pod이 오지않게 설정), affinity(Pod이 어떤 노드에 올라갈지 유도), 정책 등을 고래해 결정
  4. kebe-controller-manager: 자동화 관리자
    1. 여러 종류의 컨트롤러를 실행하는 컴포넌트
      1. Node Controller: 노드가 살아있는지 확인
      2. Replication Controller: 파드 개수 맞추기
      3. Endpoint Controller: 서비스와 파드 연결 유지

이 핵심 컴포넌트들의 흐름

사용자가 Deployment 요청
↓

kube-apiserver가 요청 저장 (etcd에)
↓

Controller Manager

Deployment → ReplicaSet → Pod 리소스 생성

이때 생성된 Pod는 아직 node가 지정되지 않음 (.spec.nodeName이 없음)
↓

Scheduler

이런 "스케줄되지 않은 Pod"를 감지

적절한 노드에 배치 (.spec.nodeName 설정)
↓

kubelet

자신 노드에 배치된 Pod를 확인

해당 컨테이너를 실제로 실행

내 식대로 이해하기

사용자가 명령어로 요청하면

apiserver가 인증/인가하고 저장해 etcd에

그 후 요청에 맞게 Pod을 만들어 컨트롤러 매니저가

이걸 실행할 VM 즉 워커노드에 뿌려줘야하는데 그걸 스캐쥴러가하고 할당되면 워커노드는 kubelet을 통해 Pod을 실행해


iptables의 역할

패킷 필터링 특정 패킷을 허용/거부할 수 있도록 함 (기본적인 방화벽 기능)
네트워크 포워딩 Pod에서 나온 트래픽을 다른 Pod 또는 외부로 전달할 수 있도록
Service → Pod 라우팅 ClusterIP 같은 Service 주소를 해당하는 Pod로 NAT 처리
DNAT/SNAT 내부 IP ↔ 외부 IP 변환 처리 등도 포함됨

iptables에 포워딩 규칙을 작성하는 것

하지만 pod들은 자주 생성되고 삭제됨

이 과정에서 다양한 노드들에 뿌려지고 각 노드마다 IP가 바뀜

이걸 사용자가 일일이 규칙을 추가할 수는 없다. → kube-proxy가 대신 해줌

  1. 그래서 사용자는 Service를 정의함
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: myapp
  ports:
    - port: 80
      targetPort: 8080
  1. kube-proxy가 감시하면서
    • app= myapp인 pod가 뜰 때마다
    • 해당 Pod의 ip와 Port 정보를 알아냄
  2. kube-proxy가 자동으로 iptables에 DNAT 규칙 추가
-A KUBE-SERVICES -d 10.96.0.1/32 --dport 80 -j KUBE-SVC-XXXXX
-A KUBE-SVC-XXXXX -j KUBE-SEP-YYYYY
-A KUBE-SEP-YYYYY -s <pod-ip> --to-destination <pod-ip>:8080

결국 Service IP로 들어온 요청은 Pod IP:8080으로 라우팅 됨

서비스 리소스?

쿠버네티스에서 Pod들을 네트워크로 안정적으로 접근하기 위한 추상화 계층

배정 받은 IP대역이 존재

쿠버네티스 설치 시 서비스 리소스의 대역을 지정함

왜필요할까

  1. Pod는 언제든 삭제 생성됨 → IP 유동적
  2. 그러면 다른 컴포넌트가 Pod에 직접 연결할 수 없음
  3. 항상 같은 이름과 IP로 접속 가능한 Service 리소스가 필요해짐

하는일

  • 뒤에 여러 Pod을 묶고
  • 클러스터 내에서 접근 가능한 가상 IP(ClusterIP) 할당 → 가용성 확보
  • kube-proxy가 해당 IP로 들어온 트래픽을 실제 Pod들로 라운딩해줌

즉, IP가 계속 바뀌니까 DNS처럼 문자열을 지정해서, 외부에선 변경 없이 사용하고 내부에선 IP가 바뀌면 갈아끼워주는 구조다.

서비스 리소스를 만든다는 건?

  1. 자주 쓰는 역할(Pod들) 을 묶는 논리적 집합을 만드는 것
  2. 그 집합(Pod들)에 고정된 Cluster 내부 IP (ClusterIP) 를 부여
  3. → 이 IP를 통해 언제나 일관되게 접근 가능

Pod은 계속 바뀌는데, 어떻게 연결돼?

  1. Pod은 생성/삭제될 때마다 IP가 바뀜
  2. 하지만 서비스 리소스(예: my-service)는 고정된 ClusterIP를 가짐
  3. kube-proxy가:
    • Service가 감시하는 Pod들을 확인
    • 해당 Pod들의 IP를 동적으로 추적
    • iptables에 포워딩 룰을 자동으로 생성

결과적으로 사용자는?

  • 바뀌는 Pod IP를 몰라도 됨
  • 항상 고정된 ClusterIP 또는 DNS 주소 (my-service.default.svc.cluster.local)로 접근 가능
  • Service가 내부적으로 알아서 적절한 Pod으로 라우팅해 줌

ClusterIP

서비스 리소스 타입 중 하나

클러스터 내부에서만 접근 가능한 가상 IP를 생성/내부통신용

내부란

모든 노드 간 즉 내 쿠버네티스 안에서

CoreDNS?

Kubernetes 클러스터 내부 DNS 서버

Service와 Pod의 이름을 IP로 변환

설정한 서비스 ip 대역의 고정된 IP로 가지고있음

이것 또한 Pod이기 때문에 IP가 바뀌고 고정될 Cluster IP가 만들어져있는것

설치 시 서비스 리소스도 만들어짐 자동으로

 

마무리

쿠버네티스 설치를 해봤다.

01에 정리했던 것들 컨테이너 런타임, 마스터 노드, 워커 노드 같이 이런 것들을 설정하는 것도 나왔다.

역시 고차원의 툴이라서 그런지 설치과정이 매우 복잡하고 알아야할게 많다고 느껴졌다.

 

요약하자면 마스터 노드와 워커 노드를 돌릴 VM을 위해 하이퍼바이저 기반 가상화 툴 사용

Pod 간 통신을 위해 사전 준비 + 컨테이너 런타임 설치

쿠버네티스 설치(필요한 컨포넌트들도)

클러스터 설정 + 노드 초기 세팅 + 마스터 노드 세팅 + Pod 간 네트워크 통신 설정

대시보드 설치 + 편의 기능들 설치

+ Recent posts