IT 이야기/쿠버네티스

K8S 클러스터 구축하기

미르호 2025. 4. 21. 17:49

업무를 하면서 사내의 서버들에 K8S 클러스터를 구축해야 할 일이 생겼었고,

여러 블로그들과 공식문서들을 확인하면서 원하는 작업에 맞는 내용으로 정리하였습니다.

 

 


환경

OS : Ubuntu 18.04.6 LTS

K8S : 1.30

 

 

배경지식

K8S 1.24 부터 dockershim 이 지원종료되면서 containerd 를 설치해 진행하였습니다.

 


 

K8S 1.30 version 설치

아래 내용을 bash shell script 로 만들어 놓고, 실행하면 편하게 작업할 수 있습니다.

 

1. controle-plane / Worker Node 공통작업

#/bin/bash
 
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
 
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
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
 
sudo apt update


# docker, containerd 설치
sudo apt install docker-ce docker-ce-cli containerd.io


# 과거 버전은 -H fd:// 를 사용해서 docker에서 오류가 발생할 수 있음
# 아래 명령어 실행 후 Ctrl + C 로 취소
sudo /usr/bin/dockerd -H unix:// --containerd=/run/containerd/containerd.sock


# containerd 시스템에 등록
sudo systemctl start docker
systemctl enable containerd


# 부팅 시 자동으로 모듈을 로드
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF


# 모듈 로드
sudo modprobe overlay           # 오버레이 파일 시스템을 위한 모듈
sudo modprobe br_netfilter      # 브릿지 방화벽을 위한 모듈


# 커널 파라미터 설정
# 필요한 sysctl 파라미터를 설정하면, 재부팅 후에도 값이 유지된다.
# IPv4 포워딩
cat <<EOF | sudo 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 파라미터 적용하기
sudo sysctl --system


# 메모리 swap off
sudo swapoff -a; sudo sed -i '/swap/d' /etc/fstab
sudo systemctl disable --now ufw


# containerd 설정경로
# sudo mkdir /etc/containerd
# 기본 설정파일 생성
sudo containerd config default > /etc/containerd/config.toml

# systemd cgroup 드라이버룰 runc에서 사용하기 위한  환경 설정
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

sudo systemctl restart containerd
sudo systemctl enable containerd


# Ubuntu 22.04 이전 버전에서 기본으로 제공하지 않는 디렉토리 추가
sudo mkdir -p -m 755 /etc/apt/keyrings


# kubernetes 패키지 저장소 공개 서명키 다운로드
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg


# kubernetes 1.30 apt 저장소 추가(마이너 버전 주의)
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
sudo apt install kubeadm=1.30.8-1.1  kubelet=1.30.8-1.1  kubectl=1.30.8-1.1   # 패키지 자동 업데이트를 막고, 해당 버전을 고정
sudo apt-mark hold kubelet kubeadm kubectl


#/etc/containerd/config.toml 파일 수정
    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = ""
 
      [plugins."io.containerd.grpc.v1.cri".registry.auths]
 
      [plugins."io.containerd.grpc.v1.cri".registry.configs]
        [plugins."io.containerd.grpc.v1.cri".registry.configs."registry-1.docker.io".auth]
          username = "<dockerhub user name>"
          password = "<dockerhub user password>"
          
          ...

 
#수정 후 ContainerD 재시작
systemctl restart containerd.service


#확인
crictl ps
 
#에러 로그 제거
sudo crictl config --set runtime-endpoint=unix:///run/containerd/containerd.sock --set image-endpoint=unix:///run/containerd/containerd.sock
 
# 다시 조회시 에러 로그가 발생하지 않는다
crictl ps

 

 

2. controle-plane 에서만 작업할 내용

sudo kubeadm init  --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address={서버IP}

 

kubeadm init 명령어를 실행하면 다음과 같은 가이드가 출력됩니다.

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

Alternatively, if you are the root user, you can run:

export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.

...

-> 여기서 출력되는 join 명령어를 복사해두고 Worker 노드에서 실행합니다.

kubeadm join {IP}:{PORT} --token {토큰} --discovery-token-ca-cert-hash sha256:{인증키}

 

만약, join 명령어를 놓쳤거나 토큰이 만료되었다면 아래의 명령어로 새 토큰값을 가진 join 명령어를 생성할 수 있습니다.

kubeadm token create --print-join-command

 

 

추가적으로 클러스터 접근을 위한 kubeconfig 설정을 해 주면 kubectl 로 클러스터 접근이 가능해집니다.

# 일반 유저일 경우
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
 
# root 권한 확인
export KUBECONFIG=/etc/kubernetes/admin.conf

 

 

 

3. controle-plane 서버에 CNI(Container Network Interface) 설치하기

Calico 란?

컨테이너, 가상 머신 및 기본 호스트 기반 워크로드를 위한 오픈 소스 네트워킹 및 네트워크 보안 솔루션입니다.

Linux 및 Windows에 대해 인터넷과 동일한 IP 네트워킹 원칙을 기반으로 Kubernetes 포드를 연결하기 위한 네트워킹 및 네트워크 정책 솔루션을 제공합니다.

캡슐화 또는 오버레이 없이 구축되어 고성능의 대규모 데이터 센터 네트워킹을 제공할 수 있으며, 분산 방화벽을 통해 Kubernetes 포드에 대해 세분화된 의도 기반 네트워크 보안 정책을 제공할 수 있습니다.

 

1) Calico Manifest 다운로드 및 설치

curl https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/calico.yaml -O

 

2) 다운받은 yaml 파일에서 nodeSelector 를 controle-plane 서버로 지정

nodeSelector: kubernetes.io/hostname: <설치할 nodename>

-> calico.yaml 을 수정해 nodeSelector 추가

 

3) 설치

kubectl apply -f calico.yaml
 
### calicoctl (calico 네트워크 디버깅 용도로 설치) 버전을 calico와 맞추기를 권장
curl -L https://github.com/projectcalico/calico/releases/download/v3.27.2/calicoctl-linux-amd64 -o calicoctl
chmod +x calicoctl
sudo mv calicoctl /usr/local/bin

 

4)  calico default ip pool 설정 (calico cni가 제공할 내부 네트워크 설정)
calico 가 정상적으로 설치되어 있지 않는다면, calico-ipool.yaml 에 "null" 값만 들어있습니다.
(resource does not exist: IPPool(default-ipv4-ippool) with error: ippools.crd.projectcalico.org "default-ipv4-ippool" not found 에러 발생함)

 

calicoctl get ippool default-ipv4-ippool -o yaml > calico-ipool.yaml

# calico-ipool.yaml 수정
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: "2024-05-22T08:53:29Z"
  name: default-ipv4-ippool
  resourceVersion: "13857"
  uid: 0370dbff-1460-4ba2-8f91-6de489893ef9
spec:
  allowedUses:
  - Workload
  - Tunnel
  blockSize: 26
  cidr: 192.168.0.0/16
  ipipMode: Never               # 이 속성값을 Never로 수정
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never

-> ipipMode Never로 변경시, Direct Mode가 활성화되며 불필요한 필드(uid)도 함께 제거됩니다.

 

# 적용
calicoctl apply -f calico-ipool.yaml

# 출력
Successfully applied 1 'IPPool' resource(s)

 

 

4. Worker Node 에서만 작업할 내용

controle-plane 서버에서 출력된 join 명령어를 확인 후 worker node 에 붙여 넣습니다.

kubeadm join 10.158.3.40:6443 --token {토큰} --discovery-token-ca-cert-hash sha256:{인증키}
 
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/kubelet.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

 

 

5. 확인

kubeconfig 가 설정되어 있는 controle-plane 서버에서 아래의 명령어로 클러스터 구성 확인이 가능합니다.

kubectl get nodes