[Kubernetes] VM 실습환경 구성 / PC에 직접 설치하기

Xabi·2025년 7월 27일

kubernetes

목록 보기
4/20

내 PC에 마스터 노드 1대와 워커 노드 2대를 의미하는 VM을 각각 설치하고, 각 VM 내 도커와 쿠버네티스를 설치해 실습 환경을 구성해보았다. 아래는 관련 방법과 오류 핸들링한 내용에 관한 기록이다.

ref. 따배쿠 https://www.youtube.com/watch?v=lheclzO-G7k&list=PLApuRlvrZKohaBHvXAOhUD-RxD0uQ3z0c&index=4

1. 쿠버네티스 클러스터 구성

Control Plane (Master Node)

  • 워커 노드들의 상태를 관리하고 제어
  • Single Master
  • Multi Master

Worker Node

  • 도커 플랫폼을 통해 컨테이너를 동작하며 실제 서비스 제공

VM을 3대 만들어 1대는 마스터 노드, 2대는 워커 노드로 설치해보자!

1) k8s 클러스터 구성 설치방법

  1. Oracle VM VirtualBox 설치
  2. ubuntu LTS 20.04 ver iso 다운로드
  3. VM 3대 각각 생성 - 위 iso 삽입, k8s-master, k8s-node1, k8s-node2 설치
  4. VM 네트워크 설정에 Host-Only Adapter 추가해서 서로 통신 가능하게 만들기 (기본 NAT만 구성되어 있음)
  5. MobaXterm 설치 및 각 VM별 SSH 연결

(참고) VM 네트워크 설정 - Host-Only Adapter

✅ 단계별 설정 가이드 (VirtualBox 기준)
📌 1. VirtualBox에서 VM 꺼진 상태로 설정 시작
VirtualBox → 각 VM 선택

설정(Settings) → 네트워크(Network)

[어댑터 1]
연결 방식: NAT

체크: ✅ 네트워크 어댑터 사용

[어댑터 2]
"어댑터 2" 탭으로 이동

체크: ✅ 네트워크 어댑터 사용

연결 방식: 호스트 전용 어댑터 (Host-only Adapter)
→ 드롭다운에서 vboxnet0 또는 기존 Host-only 네트워크 선택

❗ 만약 Host-only 어댑터가 없다면:
VirtualBox 상단 메뉴 → 도구 → 네트워크 → 호스트 전용 네트워크 추가 먼저 해줘야 함

네트워크 설정이 완료되면,
우분투 VM 내 터미널(ctrl+alt+f3)에서 IP 확인 명령어 수행 시 (hostname -I),
10.~이 아닌 192.~ IP가 함께 나온다.

❗ 해당 IP로 MobaXterm에서 SSH 접근하도록 한다.

(참고) SSH 연결 오류 수정

조회한 IP로 ssh 연결 시 connection refused 발생하여 우분투에서 sudo 계정으로 ssh 설치 및 22 포트 연결하였다.

1) 개인 계정에 관리자권한 부여

# root 로그인
xabi@~ su
[password]
# 읽기 전용 마운트 해제
root@~ mount -o remount,rw /
# xabi를 sudo 그룹에 추가
root@~ sudo usermod -aG sudo xabi
# 재부팅
root@~ reboot

2) SSH 서버 설치 여부 확인

sudo systemctl status ssh
> not found 발생 → 설치 필요!

3) SSH 서버 설치

sudo apt update
sudo apt install openssh-server -y
sudo systemctl enable ssh
sudo systemctl start ssh

설치하고 나서 다시 확인하면 이렇게 active (running)이 떠야 한다!

4) 포트 22 열려 있는지 확인

# 포트 확인 → 아무 것도 안 뜨면 sshd가 안 열려 있는 것임. 나는 listen 확인했음!
sudo ss -tnlp | grep :22

5) 방화벽 확인

# 방화벽 확인 → Status: inactive → 괜찮음
sudo ufw status

6) 만약 active인데 22/tcp 안 열려 있다면

sudo ufw allow ssh
sudo ufw reload

위 모든 과정을 거치고 나니.. MobaXterm에서 SSH로 연결이 되었다 (감격)

(참고) MobaXterm VM SSH 연결

Remote host: VM의 IP 주소 (예: 192.168.56.101)
Specify username: 내 계정명 (예: xabi)
Port: 기본값 22

설치 후 각 VM 별 통신 확인 진행

# VM별 각각 서로 ping 이상없는지 확인
ping 192.xxx.xx.xxx

2) VM에 Docker 설치하기

all system에 도커를 모두 설치한다.

아..OS requirements에 내가 설치한 20.04 ver이 없어서 당황했는데 ChatGPT에게 물어본 결과..
Docker 문서는 현재 기준으로 적극적으로 유지보수하는 버전만 표기해서 24.04 / 22.04 / 24.10 만 써놓은 것일 뿐이고, Docker APT 저장소에는 아직도 Ubuntu 20.04 (focal) 용 패키지가 남아 있고, lsb_release -cs 가 focal인 경우에도 정상 설치 가능하다고 한다. 고맙다 챗지야! 그대로 진행하기로 한다.. ㅎㅎ

설치 명령어

설치페이지를 참고하여 작성하고, ChatGPT에게 보완받은 버전이다.

# 사전 패키지 설치
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release

# GPG key 저장 경로 생성 및 다운로드
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# APT 저장소 추가
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Docker 설치
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# docker 권한 확인
sudo systemctl enable docker
sudo systemctl start docker
sudo docker version

# 테스트
sudo docker run hello-world

MobaXterm으로 열심히 세 대의 VM에 같이 설치 진행했다.

설치 결과 확인

# docker 최신 버전 설치 완료!
guru@k8s-node1:~$ sudo docker version
Client: Docker Engine - Community
 Version:           28.1.1
 API version:       1.49
 Go version:        go1.23.8
 Git commit:        4eba377
 Built:             Fri Apr 18 09:52:18 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.1.1
  API version:      1.49 (minimum version 1.24)
  Go version:       go1.23.8
  Git commit:       01f442b
  Built:            Fri Apr 18 09:52:18 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.27
  GitCommit:        05044ec0a9a75232cad458027ca83437aae3f4da
 runc:
  Version:          1.2.5
  GitCommit:        v1.2.5-0-g59923ef
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

(참고) sudo 명령어에서 비밀번호 입력하지 않아도 수행되도록 guru 관리자계정 생성하고 관리자권한 부여하기 > 매우 편하므로 추천!

# 1. guru 계정 생성
sudo adduser guru

# 2. sudo 권한 부여
sudo usermod -aG sudo guru

# 3. guru 계정으로 접속
su - guru

# 4. guru 계정 sudo 시 비번 없이 실행되게 만들기 (개인 실습에 추천)
sudo visudo

# 5. 에디터 열리면 맨 아랫줄에 아래 추가
guru ALL=(ALL) NOPASSWD:ALL

3) VM에 Kubernetes 설치하기

공식 홈페이지 - Installing kubeadm
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

3.1) 설치 전 환경설정

1) Swap configuration

Swap 메모리란?
  • Swap은 시스템 메모리가 부족할 때, 디스크 공간 일부를 마치 메모리처럼 사용하는 기능
  • 하지만 쿠버네티스에서는 이 swap이 기본적으로 허용되지 않음
기본 동작
  • kubelet (노드에서 Pod를 관리하는 에이전트)은 Swap이 활성화되어 있으면 작동하지 않음
  • 즉, 설치 시 kubelet이 실행 자체를 실패할 수 있음
  • 아래 명령어를 통해 Swap 설정을 비활성화 하고 진행함
설정 이유
  • 쿠버네티스는 리소스 스케줄링 정확성을 위해 Swap 메모리 사용을 기본적으로 허용하지 않는다.
  • Swap이 활성화된 상태에서는 kubelet이 실행되지 않거나 클러스터가 정상 동작하지 않을 수 있다.
명령어 설명
# swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab
  • swapoff -a: 현재 시스템의 모든 swap 영역을 일시적으로 비활성화
  • sed -i '/swap/s/^/#/' /etc/fstab: /etc/fstab 파일에서 swap 항목에 주석을 추가하여 재부팅 후에도 swap이 자동으로 켜지지 않도록 설정

2) Letting iptables see bridged traffic

설정 이유
  • 쿠버네티스는 CNI 플러그인을 사용하여 브릿지 네트워크를 구성한다. iptables가 브릿지 네트워크의 트래픽을 인식하지 못하면, Pod 간 네트워크 통신이 차단될 수 있다.
  • 마스터 노드, 노드 1, 노드2가 브릿지 네트워크를 리슨할 수 있도록 지원해야 함
명령어 설명
# cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# sysctl --system
  • net.bridge.bridge-nf-call-iptables = 1: IPv4 브릿지 네트워크 트래픽을 iptables에서 처리하도록 설정
  • net.bridge.bridge-nf-call-ip6tables = 1: IPv6 브릿지 트래픽도 마찬가지로 처리
  • sysctl --system: 설정 파일들을 적용하여 커널 파라미터를 시스템 전역에 반영

3) Disable firewall

설정 이유
  • 쿠버네티스는 노드 간 다양한 포트를 사용하여 통신한다. 방화벽(firewalld)이 활성화되어 있으면 일부 포트가 차단되어 kubelet, API 서버 또는 Pod 간 통신에 문제가 발생할 수 있다.
  • 방화벽 비활성화 진행
  • 마스터 노드, 워커 노드 별 열어야 할 포트가 정해져 있으나 방화벽을 해제하여 진행하도록 함
  • 이미 미실행 중이라면 그냥 패스하면 됨
명령어 설명
# systemctl stop firewalld 
# systemctl disable firewalld
  • stop: 현재 실행 중인 firewalld 서비스를 즉시 중지
  • disable: 재부팅 시 firewalld가 자동으로 시작되지 않도록 설정

4) Set SELinux in permissive mode (effectively disabling it)

설정 이유
  • SELinux는 리눅스 보안 정책을 적용하는 기능으로, 컨테이너나 쿠버네티스 구성요소가 시스템 접근 시 제한을 받을 수 있다.
  • 설치 과정에서는 permissive 모드로 설정하여 제약을 줄이는 것이 일반적이다.
명령어 설명
# setenforce 0
# sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
  • setenforce 0: 현재 실행 중인 시스템에서 SELinux를 permissive 모드로 전환 (로그만 기록하고 차단하지 않음)
  • sed 명령어: /etc/selinux/config 파일에서 SELINUX=enforcing을 SELINUX=permissive로 변경하여 재부팅 후에도 적용

3.2) kubeadm, kubelet and kubectl 설치

kubeadm: the command to bootstrap the cluster.

  • 쿠버네티스 전체를 관리/운영해주는 커맨드
    클러스터를 부트스트랩(초기화)하는 명령어

kubelet: the component that runs on all of the machines in your cluster and does things like starting pods and containers.

  • 쿠버네티스 컨테이너를 조작해주고 통신할 때 사용되는 데몬
  • 클러스터 내 모든 노드에서 실행되며, 파드(pod)나 컨테이너를 시작하는 등의 작업을 수행하는 구성 요소

kubectl: the command line util to talk to your cluster.

  • 클러스터와 통신하기 위한 커맨드 라인

우분투 Debian-based distributions 설치 방법 채택

전체 설치 절차 요약 및 검토 (Ubuntu 20.04 기준)

1) APT 인덱스 업데이트 및 필요한 패키지 설치

  • apt-transport-https는 Ubuntu 20.04에서는 dummy package일 수 있으나, 설치해도 문제 없음.
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

2) GPG 키 저장소 디렉토리 생성 (Ubuntu 20.04에는 기본 없음)

  • Ubuntu 22.04 이상에는 존재하지만, 20.04는 직접 만들어야 함 → 꼭 필요
sudo mkdir -p -m 755 /etc/apt/keyrings

3) Kubernetes 패키지 GPG 서명 키 등록

  • 정상적으로 GPG 키 파일이 /etc/apt/keyrings/에 저장됨.
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key \
  | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

4) Kubernetes apt 저장소 추가

  • /etc/apt/sources.list.d/kubernetes.list를 덮어쓰기 때문에 기존에 설치한 쿠버네티스 버전이 있다면 주의 필요.
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' \
  | sudo tee /etc/apt/sources.list.d/kubernetes.list

5) 패키지 목록 재갱신 후 Kubernetes 핵심 패키지 설치 및 버전 고정

  • apt-mark hold: 버전 고정을 위한 명령어로, 이후 업데이트 시 자동으로 업그레이드되지 않음.
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

결과)

root@k8s-node1:~# sudo apt-mark hold kubelet kubeadm kubectl
kubelet set on hold.
kubeadm set on hold.
kubectl set on hold.

6) (선택) kubelet 서비스 활성화 및 즉시 실행

sudo systemctl enable --now kubelet

kubeadm 실행 전 상태에서 kubelet 서비스가 자동 실행될 수 있도록 준비하는 단계.
kubeadm init 전에 실행하는 것이 권장됨.

3.3) Control-plane (Master Node) 구성

Initializing your control-plane node
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

Control-plane (Master Node) 노드에서만 아래 커맨드 실행!

kubeadm init

위 커맨드를 실행했더니 [ERROR NumCPU]: the number of available CPUs 1 is less than the required 2 라는 오류가 발생했다. 이 경우 VM에서 CPU 할당이 1개 뿐이라 발생한 것이라 VM 설정에서 CPU 할당을 2개로 늘려주면 해결된다.

'kubeadm init' 명령어 실행 시 마스터에 component들이 생긴다.
API인 컨트롤러, 스케쥴러, etcd, CoreDNS가 구성된다.
대기 후 아래와 같은 성공 메시지가 출력된다!

Your Kubernetes control-plane has initialized successfully!

성공 메시지 하단에 출력되는 명령어를 복사하여 실행해준다.
root가 아닌 guru 등 다른 유저들이 kubectl 명령어를 실행할 수 있도록 지원하기 위해서는 유저의 홈 디렉토리에 아래와 같은 설정하면 된다고 나와있다.

To start using your cluster, you need to run the following as a regular user:

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

kubectl get nodes 명령어 실행 시 잘 나오는 것을 볼 수 있다. 다른 유저에게도 동일하게 하고 싶다면 해당 유저의 계정으로 위 세 개의 명령어를 동일하게 실행한다.


kubeadm join 커맨드가 출력된다. 이 커맨드로 워커 노드들이 Join할 때 사용할 것이므로 보관해둔다.

cgroup 드라이버 구성

cgroup(Control Groups)은 리눅스 커널 기능으로, 프로세스들의 CPU, 메모리, I/O 같은 자원을 제한하고 격리시킬 수 있는 메커니즘이다. 컨테이너 런타임과 kubelet은 "cgroup 드라이버"라는 속성을 갖고 있으며, cgroup 드라이버는 리눅스 머신의 cgroup 관리 측면에 있어서 중요하다. 컨테이너 런타임과 kubelet의 cgroup 드라이버를 일치시켜야 하며, 그렇지 않으면 kubelet 프로세스에 오류가 발생한다.

containerd가 systemd를 쓰고 있고 kubelet이 cgroupfs를 쓰면 아래와 같은 로그가 나올 수 있음

"failed to run Kubelet" cgroup driver mismatch: kubelet cgroupfs != containerd systemd

✅ 내 시스템에 맞게 cgroup 드라이버 설정하는 방법
1) containerd가 사용하는 cgroup driver 확인

cat /etc/containerd/config.toml | grep SystemdCgroup

위 결과, SystemdCgroup = true 로 나와야 함
만약 없다면 containerd 설정을 수정해야 함

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd

2) kubelet에도 systemd 드라이버로 설정
/var/lib/kubelet/config.yaml 파일에 아래 추가 또는 수정
위 파일이 없는 경우 kubeadm init 하면 생김

cgroupDriver: systemd

또는 kubeadm init 시 아래처럼 명시

sudo kubeadm init --cgroup-driver=systemd ...

3) kubelet과 containerd의 cgroup driver가 둘 다 systemd로 되어 있는지를 확인
3-1) containerd의 cgroup 드라이버 확인

sudo grep SystemdCgroup /etc/containerd/config.toml
> SystemdCgroup = true
> true이면 systemd, false면 cgroupfs

3-2) kubelet의 cgroup 드라이버 확인
kubelet은 보통 /var/lib/kubelet/config.yaml 또는 systemd 설정 파일에 따라 cgroup 드라이버를 지정

sudo grep cgroupDriver /var/lib/kubelet/config.yaml
> cgroupDriver: systemd
> systemd인지 확인

위브넷 CNI 설정 Installing a Pod network add-on

CNI (Container Network Interface)

  • 컨테이너 간 통신을 지원하는 VxLAN. Pod Network 라고도 부름
  • 다양한 종류의 플러그인이 존재한다. (플라넬, 칼리코, 위브넷 등)

위브넷을 설치할 예정! 마스터 노드에서만 설치해준다.

kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
root@k8s-master:~# kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
serviceaccount/weave-net created
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.apps/weave-net created
root@k8s-master:~#
root@k8s-master:~#
root@k8s-master:~#
root@k8s-master:~# kubectl get nodes
NAME         STATUS   ROLES           AGE   VERSION
k8s-master   Ready    control-plane   16m   v1.33.3

STATUS가 Ready로 바뀌었다!

3.4) Worker Node 구성 (Join)

worker node 에서 kubectl get nodes 하면 오류가 나기 때문에
마스터 노드의 /etc/kubernetes/admin.conf 파일을 워커 노드에 config 파일로 복사하고 권한부여가 필요

마스터 노드에서 출력된 토큰 정보를 복사하여 워커 노드 1, 2에 kubeadm join 명령어를 실행한다.

며칠 지나 명령어를 다시 수행해보려고 하니 연결이 되지 않았다.
원인을 파악해보니 마스터의 NAT IP로 연결이 불가한 문제가 있었다.

그리고 --token 값은 유효기간이 기본 24시간이라 시간이 지나면 사용이 불가하여 마스터 노드에서 새 토큰 발급이 필요하다.

kubeadm token create --print-join-command

root@k8s-master:~# kubeadm token create --print-join-command
kubeadm join 192.168.56.103:6443 --token 6jk5yj.vi35y2p4xq7j7p7g --discovery-token-ca-cert-hash sha256:29d27cde3cef8e4534f1c69db945e4c8bb7a5e271868d20d99a26ad258a79900
> 위 IP를 192.168.56.103로 변경하여 명령어를 수행해준다.

VirtualBox 환경에서 쿠버네티스 워커 노드 join 문제

방법 1: NAT IP(10.x.x.x) 사용 – 빠른 임시 해결

  • 장점: 바로 TLS 문제 없이 join 가능 (인증서 수정 불필요)
  • 단점: NAT 네트워크 특성상 VM 간 직접 통신이 안 될 수 있음 → 포트포워딩 필요

1-1. 마스터 NAT IP 확인

ip addr show
enp0s3: inet 10.0.2.15/24

1-2. VirtualBox에서 NAT 네트워크 설정 확인

각 VM → 설정 → 네트워크 → 어댑터 1 → NAT
"고급" → "포트 포워딩" 클릭
TCP 규칙 추가:
이름: kube-apiserver
호스트 IP: (비워두기)
호스트 포트: 6443
게스트 IP: 10.0.2.15
게스트 포트: 6443

1-3. 마스터에서 join 명령 생성

kubeadm token create --print-join-command
→ 여기서 나온 IP가 NAT IP(10.0.2.15)라면 그대로 사용

1-4. 워커에서 NAT IP로 join

kubeadm join 10.0.2.15:6443 --token ... --discovery-token-ca-cert-hash sha256:...

방법 2: Host-Only IP(192.168.x.x) 사용 – 안정적 권장 방식

  • 장점: 포트포워딩 없이 VM 간 통신 확실, 실제 멀티노드 환경과 유사
  • 단점: kube-apiserver 인증서에 Host-Only IP를 추가해야 함

2-1. 마스터 Host-Only IP 확인

ip addr show
enp0s8: inet 192.168.56.103/24

2-2. kube-apiserver 설정 수정

sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
> command 섹션에 다음 줄 추가/수정:
- --apiserver-cert-extra-sans=10.0.2.15,192.168.56.103
> 기존 값이 있다면 콤마로 Host-Only IP 추가

2-3. 인증서 재발급 (SAN 반영)

mv /etc/kubernetes/pki/apiserver.crt /etc/kubernetes/pki/apiserver.crt.bak
mv /etc/kubernetes/pki/apiserver.key /etc/kubernetes/pki/apiserver.key.bak

kubeadm init phase certs apiserver --apiserver-advertise-address=192.168.56.103 \
  --apiserver-cert-extra-sans=10.0.2.15,192.168.56.103
kubelet이 /etc/kubernetes/manifests/kube-apiserver.yaml
> 변화를 감지하고 자동 재시작
> 몇 초 후 새 인증서 적용됨

2-4. 새 join 명령 생성

kubeadm token create --print-join-command
→ 출력된 IP를 192.168.56.103으로 바꿔서 사용

2-5. 워커에서 join

kubeadm join 192.168.56.103:6443 --token ... --discovery-token-ca-cert-hash sha256:...

선택 기준:

  • 빠르게 실습 → 방법 1 (NAT + 포트포워딩)
  • 장기적으로 안정적인 멀티노드 환경 → 방법 2 (Host-Only + SAN 추가)

챗지피티의 조언에 따라 방법 2로 가기로 했다..
그런데도 오류로 되지 않아 초기화하고 SAN에 192~ IP 추가해서 컨트롤 플레인을 재설치하니 되었다.

방법 3: 마스터 노드 새로 init 시 Host-only IP 포함하여 실행

# 1. 현재 마스터 노드 클러스터 데이터 초기화
kubeadm reset -f

# 2. 기존 manifest, cert 남은 거 정리
rm -rf /etc/kubernetes/pki
rm -rf /etc/kubernetes/manifests

# 3. 새로 init (여기서 SAN에 모든 IP 포함)
kubeadm init \
  --apiserver-advertise-address=192.168.56.103 \
  --apiserver-cert-extra-sans=192.168.56.103,10.0.2.15 \
  --pod-network-cidr=10.244.0.0/16
  
# 4. 마스터 노드의 kubeconfig 파일 업데이트
# /etc/kubernetes/admin.conf 파일을 수정해 API 서버 주소를 Host-Only IP로 변경
# 이 파일은 kubeadm과 kubectl이 API 서버와 통신할 때 사용하는 기본 설정
sudo sed -i 's/10.0.2.15/192.168.56.103/g' /etc/kubernetes/admin.conf

# 5. 환경 변수 설정
# kubectl이나 kubeadm 실행 시 환경변수로 KUBECONFIG 경로 지정 확인
export KUBECONFIG=/etc/kubernetes/admin.conf

# 5-2. 사용자 환경 변수 영구 설정 (root에서 진행해줬다)
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc
source ~/.bashrc

# 6. kubeadm 토큰 다시 생성 시도
kubeadm token create --print-join-command

드디어 워커 노드에서 Join 성공~~

root@k8s-node1:~# kubeadm join 192.168.56.103:6443 --token 2qmayx.rcf0zw9n9sgi2533 \
>         --discovery-token-ca-cert-hash sha256:75560221d269db44c0bd413fc66cff5d92f355c735fd6d821212568b9edf3998
[preflight] Running pre-flight checks
        [WARNING SystemVerification]: cgroups v1 support is in maintenance mode, please migrate to cgroups v2
[preflight] Reading configuration from the "kubeadm-config" ConfigMap in namespace "kube-system"...
[preflight] Use 'kubeadm init phase upload-config --config your-config-file' to re-upload it.
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-check] Waiting for a healthy kubelet at http://127.0.0.1:10248/healthz. This can take up to 4m0s
[kubelet-check] The kubelet is healthy after 1.513061986s
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

컨트롤플레인에서 워커노드가 조인된 것을 확인할 수 있다.

root@k8s-master:~# kubectl get nodes
NAME         STATUS     ROLES           AGE     VERSION
k8s-master   Ready      control-plane   2m51s   v1.33.3
k8s-node1    NotReady   <none>          2m28s   v1.33.3
k8s-node2    NotReady   <none>          2m25s   v1.33.3

root@k8s-master:~# kubectl get nodes -o wide
NAME         STATUS     ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
k8s-master   Ready      control-plane   3m33s   v1.33.3   10.0.2.15     <none>        Ubuntu 20.04.6 LTS   5.15.0-139-generic   containerd://1.7.27
k8s-node1    NotReady   <none>          3m10s   v1.33.3   10.0.2.15     <none>        Ubuntu 20.04.6 LTS   5.15.0-139-generic   containerd://1.7.27
k8s-node2    NotReady   <none>          3m7s    v1.33.3   10.0.2.15     <none>        Ubuntu 20.04.6 LTS   5.15.0-139-generic   containerd://1.7.27

root@k8s-master:~# kubectl get pod --all-namespaces
NAMESPACE     NAME                                 READY   STATUS              RESTARTS   AGE
kube-system   coredns-674b8bbfcf-bsg7l             0/1     ContainerCreating   0          3m47s
kube-system   coredns-674b8bbfcf-j8kfm             0/1     ContainerCreating   0          3m47s
kube-system   etcd-k8s-master                      1/1     Running             0          3m52s
kube-system   kube-apiserver-k8s-master            1/1     Running             0          3m54s
kube-system   kube-controller-manager-k8s-master   1/1     Running             0          3m52s
kube-system   kube-proxy-4jdm4                     1/1     Running             0          3m33s
kube-system   kube-proxy-bws7x                     1/1     Running             0          3m48s
kube-system   kube-proxy-h7cx8                     1/1     Running             0          3m30s
kube-system   kube-scheduler-k8s-master            1/1     Running             3          3m52s
> 아직 컨테이너가 생성 중이다. 대기한다.

계속 대기하다 보니 CNI가 제대로 연결이 안되었다고 하여 재설치해주었다.. 아까 Kubeadm init했기 때문에 재설치가 필요했다.
설치 이후 아래 명령어를 통해 위브넷이 설치된 것을 확인할 수 있다!

root@k8s-master:/home/xabi# kubectl get pods -n kube-system
NAME                                 READY   STATUS              RESTARTS   AGE
coredns-674b8bbfcf-bsg7l             0/1     ContainerCreating   0          30m
coredns-674b8bbfcf-j8kfm             0/1     ContainerCreating   0          30m
etcd-k8s-master                      1/1     Running             0          30m
kube-apiserver-k8s-master            1/1     Running             0          30m
kube-controller-manager-k8s-master   1/1     Running             0          30m
kube-proxy-4jdm4                     1/1     Running             0          30m
kube-proxy-bws7x                     1/1     Running             0          30m
kube-proxy-h7cx8                     1/1     Running             0          30m
kube-scheduler-k8s-master            1/1     Running             3          30m
weave-net-5b8gc                      0/2     Init:0/1            0          13s
weave-net-bf76f                      0/2     Init:0/1            0          13s
weave-net-fzrmb                      0/2     PodInitializing     0          13s

잠시 후, 모두 running 상태가 되었고, get nodes 시 상태도 ready도 변경됨을 확인할 수 있었다....!!!!(감격)😭😭😭🎆🎇✨🎉🎊

root@k8s-master:/home/xabi# kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-674b8bbfcf-bsg7l             1/1     Running   0          31m
coredns-674b8bbfcf-j8kfm             1/1     Running   0          31m
etcd-k8s-master                      1/1     Running   0          31m
kube-apiserver-k8s-master            1/1     Running   0          31m
kube-controller-manager-k8s-master   1/1     Running   0          31m
kube-proxy-4jdm4                     1/1     Running   0          31m
kube-proxy-bws7x                     1/1     Running   0          31m
kube-proxy-h7cx8                     1/1     Running   0          31m
kube-scheduler-k8s-master            1/1     Running   3          31m
weave-net-5b8gc                      2/2     Running   0          79s
weave-net-bf76f                      2/2     Running   0          79s
weave-net-fzrmb                      2/2     Running   0          79s
root@k8s-master:/home/xabi# kubectl get nodes
NAME         STATUS   ROLES           AGE   VERSION
k8s-master   Ready    control-plane   32m   v1.33.3
k8s-node1    Ready    <none>          31m   v1.33.3
k8s-node2    Ready    <none>          31m   v1.33.3

(추가) 작업

컨트롤 플레인의 /etc/hosts 파일에 워커 노드 Host-Only IP 추가
DNS에서 워커 노드 이름을 찾을 수 있도록 설정

root@k8s-master:/etc/kubernetes# ping k8s-node2
ping: k8s-node2: Temporary failure in name resolution
> 이름을 찾지 못함

root@k8s-master:/etc/kubernetes# echo "192.168.56.102 k8s-node2" >> /etc/hosts
root@k8s-master:/etc/kubernetes# ping k8s-node2
PING k8s-node2 (192.168.56.102) 56(84) bytes of data.
64 bytes from k8s-node2 (192.168.56.102): icmp_seq=1 ttl=64 time=0.545 ms
--- k8s-node2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.545/0.973/1.312/0.319 ms
> node2 Host-Only IP를 /etc/hosts 파일에 등록 후 정상 확인

root@k8s-master:/etc/kubernetes# echo "192.168.56.101 k8s-node1" >> /etc/hosts
root@k8s-master:/etc/kubernetes# ping k8s-node1
PING k8s-node1 (192.168.56.101) 56(84) bytes of data.
64 bytes from k8s-node1 (192.168.56.101): icmp_seq=1 ttl=64 time=0.649 ms
--- k8s-node1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.649/1.158/1.623/0.398 ms
> node1 Host-Only IP를 /etc/hosts 파일에 등록 후 정상 확인

컨트롤 플레인의 /etc/kubernetes/admin.conf 파일을 워커 노드의 config 파일로 복사하고 권한부여가 필요
-> 워커 노드에서 kubectl 명령어를 사용하기 위함

1) 컨트롤 플레인에서 실행
root@k8s-master:/etc/kubernetes# scp /etc/kubernetes/admin.conf xabi@k8s-node2:/home/xabi/
The authenticity of host 'k8s-node2 (192.168.56.102)' can't be established.
ECDSA key fingerprint is SHA256:r/CqsT7vPtGBqgjNFqlvoNX9bvbpCxsb7y8NgvkilV4.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'k8s-node2,192.168.56.102' (ECDSA) to the list of known hosts.
xabi@k8s-node2's password:
admin.conf                                                                                               100% 5658     2.5MB/s   00:00

2) 워커 노드에서 실행
root@k8s-node2:/home/xabi# mkdir -p /root/.kube
root@k8s-node2:/home/xabi# cp /home/xabi/admin.conf /root/.kube/config
root@k8s-node2:/home/xabi# chown root:root /root/.kube/config
root@k8s-node2:/home/xabi# chmod 600 /root/.kube/config
root@k8s-node2:/home/xabi#
root@k8s-node2:/home/xabi# kubectl get nodes
NAME         STATUS   ROLES           AGE   VERSION
k8s-master   Ready    control-plane   19d   v1.33.3
k8s-node1    Ready    <none>          19d   v1.33.3
k8s-node2    Ready    <none>          19d   v1.33.3
root@k8s-node2:/home/xabi# kubectl get pods -A
NAMESPACE     NAME                                 READY   STATUS    RESTARTS      AGE
default       webserver                            1/1     Running   0             27m
kube-system   coredns-674b8bbfcf-bsg7l             1/1     Running   2 (45m ago)   19d
kube-system   coredns-674b8bbfcf-j8kfm             1/1     Running   2 (45m ago)   19d
kube-system   etcd-k8s-master                      1/1     Running   2 (45m ago)   19d
kube-system   kube-apiserver-k8s-master            1/1     Running   2 (45m ago)   19d
kube-system   kube-controller-manager-k8s-master   1/1     Running   2 (45m ago)   19d
kube-system   kube-proxy-4jdm4                     1/1     Running   2 (44m ago)   19d
kube-system   kube-proxy-bws7x                     1/1     Running   2 (45m ago)   19d
kube-system   kube-proxy-h7cx8                     1/1     Running   2 (44m ago)   19d
kube-system   kube-scheduler-k8s-master            1/1     Running   5 (45m ago)   19d
kube-system   weave-net-5b8gc                      2/2     Running   4 (44m ago)   19d
kube-system   weave-net-bf76f                      2/2     Running   4 (44m ago)   19d
kube-system   weave-net-fzrmb                      2/2     Running   4 (45m ago)   19d
root@k8s-node2:/home/xabi#

(부록) kubectl 명령어 자동으로 완성하기

https://kubernetes.io/vi/docs/reference/kubectl/cheatsheet/

Kubectl Autocomplete 명령어를 사용자 별로 실행해준다.
이후 Tab 키로 Kubectl 이라는 명령어를 자동완성 시킬 수 있다.

source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

Kubeadm 명령어도 자동완성을 생성해준다.

source <(kubeadm completion bash)
echo "source <(kubeadm completion bash)" >> ~/.bashrc
profile
롱런하는 개발자!

0개의 댓글