Nodejs

 

Ubuntu 5노드 Kubernetes 클러스터 구축 매뉴얼 (v1.30 기준)

 

:  CPU/RAM 최소 스펙

  • master: 2 vCPU, 2GB 이상

  • worker: 1 vCPU, 1GB 이상

 

 

각 워커  아이피 설정

예) vi /etc/netplan/00-installer-config.yaml 

# This is the network config written by 'subiquity'
network:
  version: 2
  renderer: networkd
  ethernets:
    ens33:
      dhcp4: false
      addresses:
        - 192.168.120.201/24
      routes:
        - to: default
          via: 192.168.120.1
      nameservers:
        addresses: [8.8.8.8, 1.1.1.1]

    ens34:
      dhcp4: true


 

# 1. 설정 적용
sudo netplan apply

# 2. 적용 확인
ip addr show
ping -c 3 8.8.8.8

 

Ubuntu에서 UFW 방화벽  열기

sudo ufw allow 6443/tcp
sudo ufw allow 2379:2380/tcp
sudo ufw allow 10250/tcp
sudo ufw allow 10251/tcp
sudo ufw allow 10252/tcp
sudo ufw reload

 

 

 

 

 

 

모든 서버는 Ubuntu Server 22.04 LTS 기준이며, 네트워크 모드는 Host-Only로 설정하는 것을 권장합니다.

1️⃣ 모든 노드 공통 설정

# 스왑 비활성화
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

# 시스템 업데이트
sudo apt update -y

# containerd 및 필수 패키지 설치
sudo apt install -y containerd apt-transport-https ca-certificates curl gpg

# Kubernetes 저장소 키 추가
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | \
  sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | \
  sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt update

# kubeadm, kubelet, kubectl 설치
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

# containerd 서비스 활성화
sudo systemctl enable containerd
sudo systemctl start containerd

 

/proc/sys/net/ipv4/ip_forward가 1로 설정

 

1)  IP 포워딩 활성화 (즉시 적용)

sudo sysctl -w net.ipv4.ip_forward=1

2) 재부팅 후에도 유지되도록 설정

sudo sed -i '/net.ipv4.ip_forward/c\net.ipv4.ip_forward=1' /etc/sysctl.conf
sudo sysctl -p

 

 

 

 

 

 

2️⃣ 마스터 노드 초기화 (192.168.120.200)

다음 명령어 실행전 아래  Kubernetes는 Pod 간 통신을 위해 IP 포워딩이 반드시 활성화 처리 할것

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

⭕마서터 노드 및 워커노드  위 명령어 실행시 다음 오류 발생시

[ERROR FileContent--proc-sys-net-ipv4-ip_forward]: /proc/sys/net/ipv4/ip_forward contents are not set to 1


[preflight] If you know what you are doing, you can make a check non-fatal with --ignore-preflight-errors=... To see the stack trace of this error execute with --v=5 or higher

 

이 오류 메시지는 **IP 포워딩이 비활성화되어 있어서** Kubernetes 초기화(`kubeadm init`)가 실패한 경우입니다.

Kubernetes는 Pod 간 통신을 위해 **IP 포워딩이 반드시 활성화되어야** 합니다.

---

## ???? 해결 방법

### 1️⃣ 현재 설정 확인

```bash
cat /proc/sys/net/ipv4/ip_forward
```

> 결과가 `0`이면 비활성화 상태입니다.

---

### 2️⃣ 일시적으로 IP 포워딩 활성화

```bash
sudo sysctl -w net.ipv4.ip_forward=1
```

> 이 설정은 재부팅 시 사라집니다.

---

### 3️⃣ 영구적으로 IP 포워딩 활성화

다음 파일을 수정합니다:

```bash
sudo nano /etc/sysctl.conf
```

아래 항목을 찾아서 수정 또는 추가합니다:

```
net.ipv4.ip_forward = 1
```

적용 명령:

```bash
sudo sysctl -p
```

---

### 4️⃣ containerd에도 적용 확인 (선택 사항)

일부 환경에서는 containerd의 네트워크 설정이 iptables나 IP 포워딩에 영향을 줍니다.

다음 설정 파일을 확인:

```bash
sudo nano /etc/containerd/config.toml
```

아래 항목이 존재하면 다음과 같이 설정:

```
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true
```

적용 후 containerd 재시작:

```bash
sudo systemctl restart containerd
```

---

### 5️⃣ 다시 초기화 시도

```bash
sudo kubeadm reset -f
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
```

---

✅ **정상 동작 확인**

```bash
cat /proc/sys/net/ipv4/ip_forward
```

> 결과가 `1`이면 설정 완료!

이제 `kubeadm init`을 다시 실행하면 정상적으로 클러스터 초기화가 진행됩니다

 

 

✅ 성공 시 마지막에 출력되는 kubeadm join ... 명령어를 복사해 두세요.
이 명령은 워커 노드에서 클러스터에 참여할 때 사용합니다.

kubeconfig 설정

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

 

 

3️⃣ 네트워크 플러그인 설치 (flannel)

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

대안: Calico를 사용하면 고급 네트워크 정책 제어 가능 (kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml)

 

 

Flannel이나 Calico 같은 네트워크 플러그인(Network Plugin)마스터 노드에서만 한 번 설치하면 됩니다.

설치 이후, 해당 네트워크 플러그인은 마스터가 관리하는 전체 클러스터에 자동으로 적용되며,
각 워커 노드들은 kubeadm join 으로 클러스터에 합류할 때 네트워크 설정을 자동으로 상속받습니다.

✅ 정리하자면

구분설치 위치설명

Flannel마스터 1대기본 오버레이 네트워크, 간단하고 가볍습니다

Calico마스터 1대고급 네트워크 정책, 성능 및 보안 제어 강화

⚠️ 워커 노드에서는 kubectl apply -f ... 명령을 실행할 필요 없습니다.
워커는 마스터의 설정을 자동으로 받아서 통신하게 됩니다.

설치 예시 (Calico 버전 선택 시)

# 마스터 노드에서만 실행
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

적용 후 상태 확인:

kubectl get pods -n kube-system

calico-node, calico-kube-controllers 등의 Pod가 Running 상태면 정상입니다.

추가 팁

  • Flannel과 Calico는 동시에 설치하면 안 됩니다. (둘 중 하나만 선택)

  • Calico를 쓰면 나중에 NetworkPolicy 리소스로 Pod 간 통신을 세밀하게 제어할 수 있습니다.

 

 

 

 

 4️⃣ 워커 노드 4대에서 클러스터 조인

각 워커 노드(worker1~worker4)에서 아래 명령 실행:

sudo kubeadm join 192.168.120.200:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

 

 

 5️⃣ 클러스터 상태 확인 (마스터에서)

kubectl get nodes

정상 출력 예시 

NAME       STATUS   ROLES           AGE   VERSION
master     Ready    control-plane   5m    v1.30.0
worker1    Ready    <none>          3m    v1.30.0
worker2    Ready    <none>          2m    v1.30.0
worker3    Ready    <none>          2m    v1.30.0
worker4    Ready    <none>          1m    v1.30.0

 

 

✅ 위와 같이 나오면 클러스터 구축 완료 

 실전 팁

  1. /etc/hosts 파일에 모든 노드의 IP와 호스트명을 미리 등록하세요.

  2. 마스터 노드 스냅샷을 찍어두면 클러스터가 깨져도 빠르게 복구할 수 있습니다.

  3. Calico 네트워크 플러그인을 쓰면 보안 정책 제어에 유리합니다.

  4. 워커 노드가 많을 경우, 로드밸런서나 Ingress Controller(NGINX 등) 설정을 추가하면 운영 환경에 가깝게 실습 가능합니다.

 

 

 

 

 

 

 

✅ 1.오류시 Kubernetes 프로세스  초기화후 재 설치

1️⃣ 모든 Kubernetes 프로세스 정리

sudo systemctl stop kubelet
sudo systemctl stop containerd
docker ps  # (만약 containerd 대신 docker 사용 시)

2️⃣ 기존 Kubernetes 설정 초기화

sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d
sudo rm -rf /var/lib/cni/
sudo rm -rf /var/lib/kubelet/*
sudo rm -rf /etc/kubernetes/
sudo rm -rf /var/lib/etcd

3️⃣ 네트워크 잔여 설정 제거 (필요시)

ip link show  # cni0, flannel.1 등이 있다면 제거
sudo ip link delete cni0
sudo ip link delete flannel.1

4️⃣ containerd 및 kubelet 재시작

sudo systemctl restart containerd
sudo systemctl restart kubelet

5️⃣ 다시 초기화 명령 실행

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

6️⃣ 성공 시 관리자 설정 복사 (필수)

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

7️⃣ Flannel 네트워크 설치

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

요약:

  • 에러 원인: 이전 클러스터 잔재로 포트 점유

  • 해결 방법: kubeadm reset + /etc/kubernetes / /var/lib/etcd 삭제 후 재시작

  • 이후 kubeadm init 재실행하면 해결됩니다.

 

 

2. 마스터 노드에서 -  다음 오류일때

root@ubuntu:/home/master# kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml error: error validating 

"https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml": error validating data: failed to download openapi: Get 

"https://192.168.120.200:6443/openapi/v2?timeout=32s": 

dial tcp 192.168.120.200:6443: connect: connection refused; if you choose to ignore these errors, turn validation off with --validate=false

 

Kubernetes 문제 해결 순서

1. kubelet 상태 확인

sudo systemctl status kubelet
journalctl -xeu kubelet | tail -n 50

2. containerd와 kubelet 재시작

sudo systemctl restart containerd
sudo systemctl restart kubelet

3. 필요 시 kubeadm 초기화

sudo kubeadm reset -f
sudo rm -rf /etc/kubernetes/ /var/lib/etcd /var/lib/kubelet/* /etc/cni/net.d
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

4. 초기화 후 kubeconfig 설정

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

5. 마스터 노드에서 Flannel 설치

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

6. 상태 확인

kubectl get nodes
kubectl get pods -n kube-system

 

 

 

 

 

3. Ubuntu 22.04 전용 스크립트 형태로 만들어서 명령어 바로 구축

 

1.마스터 노드

1) sudo vi K8s-master-reinstall..sh

#!/bin/bash
# Kubernetes Master Node 완전 자동화 재초기화 및 재설치 스크립트
# Ubuntu/Debian 계열 기준 (Ubuntu 20.04/22.04 등)
# root 권한으로 실행하세요: sudo ./k8s-master-install-complete.sh

set -euo pipefail

log(){ printf "%s %s\n" "$(date +'%F %T')" "$*"; }
ensure_cmd(){ command -v "$1" >/dev/null 2>&1 || return 1; }

###########################
# 사용자 설정 (필요 시 수정)
###########################
K8S_VERSION="1.30.14"   # 기본 kubeadm/kubelet/kubectl 버전(apt 저장소에서 가용한 최신 안정버전 사용 가능)
DEFAULT_POD_CIDR="10.244.0.0/16"  # Flannel/Calico 등에 맞춰 변경 가능
CNI_DEFAULT="calico"  # 자동으로 설치할 CNI: calico | flannel | none

###########################
# 사전검증
###########################
log "=== Kubernetes Master 자동 재설치 스크립트 ==="
if [ "$EUID" -ne 0 ]; then
  log "Must run as root. Use sudo."
  exit 1
fi

# swap off
if swapon --show | grep -q '^'; then
  log "Disabling swap..."
  swapoff -a || true
  cp /etc/fstab /etc/fstab.bak_$(date +%s) || true
  sed -i.bak '/\bswap\b/s/^/#/g' /etc/fstab || true
fi

# sysctl for k8s
log "Applying required sysctl settings"
modprobe br_netfilter || true
cat >/etc/sysctl.d/k8s.conf <<'EOF'
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system || true

###########################
# 패키지 설치
###########################
install_pkgs(){
  log "Checking/Installing Docker and Kubernetes packages"

  # Install docker
  if ! ensure_cmd docker; then
    log "Installing docker.io..."
    apt update -y
    apt install -y docker.io
    systemctl enable --now docker
  else
    log "docker already installed: $(docker --version 2>/dev/null || echo 'unknown')"
  fi

  # Install kubeadm,kubelet,kubectl
  if ! ensure_cmd kubeadm || ! ensure_cmd kubelet || ! ensure_cmd kubectl; then
    log "Installing kubeadm/kubelet/kubectl"
    apt update -y
    apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

    if [ ! -f /etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg ]; then
      curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg
    fi
    if [ ! -f /etc/apt/sources.list.d/kubernetes.list ]; then
      echo "deb [signed-by=/etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
    fi

    apt update -y
    apt install -y kubelet kubeadm kubectl
    apt-mark hold kubelet kubeadm kubectl
  else
    log "kubeadm/kubelet/kubectl already present: $(kubeadm version -o short 2>/dev/null || echo '')"
  fi
}
install_pkgs

###########################
# 기존 구성 정리
###########################
if [ -d /etc/kubernetes ] || ensure_cmd kubeadm; then
  log "Resetting existing kubeadm configuration (if any)"
  if ensure_cmd kubeadm; then
    kubeadm reset -f || true
  fi
  systemctl stop kubelet || true
  systemctl stop docker || true
else
  log "No existing kubeadm config detected, continuing"
fi

# remove dirs
log "Cleaning K8s directories"
rm -rf /etc/cni/net.d || true
rm -rf /var/lib/cni || true
rm -rf /var/lib/kubelet || true
rm -rf /var/lib/etcd || true
rm -rf /etc/kubernetes || true
rm -rf $HOME/.kube || true

###########################
# kubeadm 이미지 사전풀
###########################
if ensure_cmd kubeadm; then
  log "Pre-pulling kubeadm images (may fail behind restricted networks)"
  kubeadm config images pull || log "Image pull failed, continuing"
fi

###########################
# systemd 서비스 활성화
###########################
log "Enabling docker/kubelet"
systemctl daemon-reload || true
if ensure_cmd docker; then
  systemctl enable --now docker || true
fi
if ensure_cmd kubelet; then
  systemctl enable --now kubelet || true
  systemctl restart kubelet || true
fi

###########################
# kubeadm init
###########################
ALREADY_MASTER=false
if [ -f /etc/kubernetes/manifests/kube-apiserver.yaml ] || [ -d /etc/kubernetes/pki ]; then
  ALREADY_MASTER=true
fi

if [ "$ALREADY_MASTER" = true ]; then
  log "Master manifests/pki detected - skipping kubeadm init"
else
  read -p "Initialize control-plane on this node? (y/N): " DO_INIT
  DO_INIT=${DO_INIT:-N}
  if [[ "$DO_INIT" =~ ^[Yy]$ ]]; then
    DEFAULT_ADDR=$(hostname -I | awk '{print $1}')
    read -p "API server bind IP (default: $DEFAULT_ADDR): " APISERVER_ADDR
    APISERVER_ADDR=${APISERVER_ADDR:-$DEFAULT_ADDR}
    read -p "Pod network CIDR (default: $DEFAULT_POD_CIDR): " POD_CIDR
    POD_CIDR=${POD_CIDR:-$DEFAULT_POD_CIDR}

    log "Running kubeadm init --apiserver-advertise-address=$APISERVER_ADDR --pod-network-cidr=$POD_CIDR"
    kubeadm init --apiserver-advertise-address=$APISERVER_ADDR --pod-network-cidr=$POD_CIDR || true

    # configure kubeconfig for the current user
    mkdir -p $HOME/.kube
    if [ -f /etc/kubernetes/admin.conf ]; then
      cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
      chown $(id -u):$(id -g) $HOME/.kube/config || true
    fi

    # Wait for API ready
    wait_for_api(){
      log "Waiting for API server (max 300s)"
      local t=0
      while ! kubectl version --short >/dev/null 2>&1; do
        sleep 5
        t=$((t+5))
        if [ $t -ge 300 ]; then
          log "API server timeout"
          return 1
        fi
      done
      return 0
    }

    if wait_for_api; then
      log "API server is ready"
    else
      log "API server did not become ready in time. Check 'journalctl -u kubelet -b' and container runtime logs. Proceeding but cluster may be unhealthy."
    fi

    # Auto-apply CNI if user wants
    read -p "Apply default CNI automatically? (calico/flannel/none) (default: $CNI_DEFAULT): " CNI_SEL
    CNI_SEL=${CNI_SEL:-$CNI_DEFAULT}
    if [[ "$CNI_SEL" =~ ^(calico|flannel)$ ]]; then
      if [ "$CNI_SEL" = "calico" ]; then
        log "Applying Calico CNI"
        kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml || log "Failed to apply Calico"
      else
        log "Applying Flannel CNI"
        kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml || log "Failed to apply Flannel"
      fi
    else
      log "Skipping automatic CNI installation"
    fi

    # Wait for CoreDNS ready (long timeout)
    if ensure_cmd kubectl; then
      log "Waiting for CoreDNS rollout (max 600s)"
      t=0
      while true; do
        if kubectl -n kube-system get deployment coredns >/dev/null 2>&1; then
          kubectl -n kube-system rollout status deployment/coredns --timeout=120s && break || true
        fi
        sleep 10
        t=$((t+10))
        if [ $t -ge 600 ]; then
          log "CoreDNS did not become ready within 600s. Check pod logs and node networking."
          break
        fi
      done
    fi

    # print worker join command for convenience
    if ensure_cmd kubeadm; then
      log "Worker join command (if available):"
      kubeadm token create --print-join-command || log "Join token generation failed. You can run 'kubeadm token create --print-join-command' on the master later."
    fi
  else
    log "Skipping kubeadm init"
  fi
fi

###########################
# Firewall / port open
###########################
log "Opening firewall ports if ufw present"
if ensure_cmd ufw; then
  ufw allow 6443/tcp
  ufw allow 2379:2380/tcp
  ufw allow 10250/tcp
  ufw allow 30000:32767/tcp
  ufw reload || true
else
  log "ufw not detected - ensure external firewalls/security groups allow 6443 from worker nodes"
fi

###########################
# Final checks
###########################
log "Final health checks"
if ensure_cmd kubectl; then
  kubectl get nodes -o wide || log "kubectl cannot reach API server - check master status"
  kubectl get pods -n kube-system -o wide || true
else
  log "kubectl not available or kubeconfig missing"
fi

log "Script finished. If cluster isn't healthy, check: 'journalctl -u kubelet -b', 'docker ps -a', and 'kubectl -n kube-system get pods -o wide'"

 

2) 실행 권한 부여

sudo chmod +x K8s-master-reinstall.sh

 

3)  스크립트 실행

sudo ./K8s-master-reinstall.sh

 

실행 중에 마스터 노드에서 생성된 kubeadm join 명령어복사

  • 예시:

kubeadm join 192.168.120.200:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 

4)  확인

스크립트 완료 후:

워커 노드가 정상적으로 Ready 상태로 표시되는지 확인합니다.

 

스크립트는 다음을 처리합니다(간단 요약):

  • swap 비활성화, 필요한 sysctl 영구 적용

  • Docker 및 kubeadm/kubelet/kubectl 설치(중복 설치 방지)

  • 기존 kubeadm 설정 안전 초기화 및 관련 디렉토리 정리

  • kubeadm 이미지 사전 풀링(가능한 경우)

  • kubeadm init 자동 실행(사용자 선택) — API 바인드 IP, Pod CIDR 입력 가능

  • 자동 CNI 적용 옵션(Calico 또는 Flannel) — 기본은 Calico

  • CoreDNS 롤아웃을 위한 장시간 대기 로직(최대 600s)

  • 마스터에서 워커가 사용할 kubeadm join 명령 자동 출력

  • UFW 기반 포트 개방(존재 시) 및 최종 헬스체크

  •  

 

 

 워커노드

#!/bin/bash
# Kubernetes Worker Node 자동 생성기 및 재설치 스크립트 (마스터 연동 지원)
# Ubuntu/Debian 계열 기준
# root 권한으로 실행: sudo ./k8s-worker-install-robust.sh

set -euo pipefail

log(){ printf "%s %s\n" "$(date +'%F %T')" "$*"; }
ensure_cmd(){ command -v "$1" >/dev/null 2>&1 || return 1; }

if [ "$EUID" -ne 0 ]; then
  log "루트 권한으로 실행하세요 (sudo 필요)."
  exit 1
fi

log "=== Kubernetes Worker 자동 재설치 스크립트 ==="

# 0. swap off
if swapon --show | grep -q '^'; then
  log "스왑 비활성화 중..."
  swapoff -a || true
  cp /etc/fstab /etc/fstab.bak_$(date +%s) || true
  sed -i.bak '/\bswap\b/s/^/#/g' /etc/fstab || true
fi

# 0-1. sysctl 네트워크 설정
log "필요한 sysctl 적용 (net.bridge, ip_forward)"
modprobe br_netfilter || true
cat >/etc/sysctl.d/99-k8s-worker.conf <<'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system || true

# 1. 패키지 설치
install_pkgs(){
  log "필수 패키지 존재 여부 확인 및 설치(kubeadm,kubelet,kubectl,docker)"

  if ! ensure_cmd docker; then
    log "docker 설치중..."
    apt update -y
    apt install -y docker.io
    systemctl enable --now docker
  else
    log "docker: $(docker --version 2>/dev/null || echo 'version?')"
  fi

  if ! ensure_cmd kubeadm || ! ensure_cmd kubelet || ! ensure_cmd kubectl; then
    log "kubeadm/kubelet/kubectl 설치중..."
    apt update -y
    apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

    if [ ! -f /etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg ]; then
      curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg
    fi
    if [ ! -f /etc/apt/sources.list.d/kubernetes.list ]; then
      echo "deb [signed-by=/etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
    fi

    apt update -y
    apt install -y kubelet kubeadm kubectl
    apt-mark hold kubelet kubeadm kubectl
  else
    log "kubeadm/kubelet/kubectl 설치됨: $(kubeadm version -o short 2>/dev/null || echo '')"
  fi
}
install_pkgs

# 2. 기존 kubeadm 구성 제거 (있을때만)
if [ -d /etc/kubernetes ] || ensure_cmd kubeadm; then
  log "기존 kubeadm 구성 reset 시도(있을 경우)"
  if ensure_cmd kubeadm; then
    kubeadm reset -f || true
  fi
  systemctl stop kubelet || true
  systemctl stop docker || true
else
  log "기존 kubeadm 구성 없음 - 초기화 단계 건너뜀"
fi

# 3. cleanup
log "CNI 및 관련 디렉토리 정리(존재 여부 상관없이)"
rm -rf /etc/cni/net.d || true
rm -rf /var/lib/cni || true
rm -rf /var/lib/kubelet || true
rm -rf /var/lib/etcd || true
rm -rf /etc/kubernetes || true
rm -rf $HOME/.kube || true

# 4. kubeadm 이미지 사전 풀링
log "kubeadm 이미지 사전 풀링 시도"
if ensure_cmd kubeadm; then
  kubeadm config images pull || log "이미지 풀 실패(네트워크/레지스트리 문제 가능), 계속 진행"
fi

# 5. 서비스 재시작
log "Docker/kubelet 활성화 및 재시작"
systemctl daemon-reload || true
if ensure_cmd docker; then
  systemctl enable --now docker || true
fi
if ensure_cmd kubelet; then
  systemctl enable --now kubelet || true
  systemctl restart kubelet || true
fi

# 6. 조인 명령 준비
log "조인 정보를 입력받습니다. 두 가지 방식 지원:"
log " - 1) 전체 join 명령어를 붙여넣기 (권장)"
log " - 2) master:ssh_user@MASTER_IP 처럼 입력하면 SSH로 마스터에서 join 명령을 자동 생성하려 시도"

read -p "마스터에서 생성된 kubeadm join 명령어 혹은 ssh:USER@MASTER_IP 를 입력하세요: " JOIN_INPUT
JOIN_INPUT=${JOIN_INPUT:-}

JOIN_CMD=""
if [[ "$JOIN_INPUT" =~ ^ssh: ]]; then
  # 형식: ssh:user@host (예: ssh:ubuntu@192.168.120.200)
  MASTER_SSH=${JOIN_INPUT#ssh:}
  log "마스터에 SSH로 접속하여 join 명령을 생성합니다: $MASTER_SSH"
  if ensure_cmd ssh; then
    # 사용자에게 SSH 키/비밀번호 등의 준비를 요구함 (비대화형 환경에서는 실패할 수 있음)
    JOIN_CMD=$(ssh -o BatchMode=yes -o StrictHostKeyChecking=no "$MASTER_SSH" "kubeadm token create --print-join-command" 2>/dev/null || true)
    if [ -z "$JOIN_CMD" ]; then
      log "SSH로 자동 생성 실패: 비대화형 연결 실패 또는 권한 문제. 수동으로 join 명령을 입력하세요."
    else
      log "마스터에서 받은 join 명령: $JOIN_CMD"
    fi
  else
    log "ssh 명령을 찾을 수 없음. 수동으로 join 명령을 입력하세요."
  fi
else
  JOIN_CMD="$JOIN_INPUT"
fi

if [ -z "$JOIN_CMD" ]; then
  read -p "수동으로 kubeadm join 전체 명령을 입력하세요: " JOIN_CMD
fi

# 안전히 실행: 앞뒤 공백 제거
JOIN_CMD=$(echo "$JOIN_CMD" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

if [ -z "$JOIN_CMD" ]; then
  log "join 명령이 제공되지 않았습니다. 스크립트를 종료합니다."
  exit 1
fi

log "입력된 join 명령 실행: $JOIN_CMD"
# eval은 필요하지만 사용자 입력이므로 주의. 일단 실행.
set +e
eval $JOIN_CMD
RC=$?
set -e
if [ $RC -ne 0 ]; then
  log "kubeadm join 명령이 실패했습니다 (exit code $RC). kubelet/journal 및 네트워크 확인 필요"
  log "kubelet 로그: sudo journalctl -u kubelet -n 200"
  exit $RC
fi

# 7. 방화벽 포트 설정
if command -v ufw &>/dev/null; then
  log "UFW 감지: 필요한 포트 허용"
  ufw allow 10250/tcp || true
  ufw allow 30000:32767/tcp || true
  ufw reload || true
else
  log "UFW 미설치: 외부 방화벽/보안그룹에서 포트 10250 및 NodePort 범위 허용 필요"
fi

# 8. 완료 및 검증
log "=== 완료: 노드가 클러스터에 조인되었는지 마스터에서 확인하세요 ==="
if ensure_cmd kubectl; then
  kubectl get nodes -o wide || log "kubectl이 API 서버에 접속할 수 없습니다. 마스터에서 상태 확인 필요"
else
  log "kubectl 미설치 또는 kubeconfig 미설정. 마스터에서 'kubectl get nodes'로 확인하세요."
fi

log "작업 종료: 문제가 있으면 'journalctl -u kubelet -b'와 'docker ps -a'를 확인하세요."

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

이 세상에서는 당신이 영원히 죽지 않는다고 생각하고 모든 것을 계획하라. 그러나 저 세상을 위해서는 내일 죽는다고 생각하고 계획하라. -유태격언

댓글 ( 0)

댓글 남기기

작성