K8s 1.13.1 온프레미스 클러스터 구축 가이드
1. 온프레미스 K8s 구축의 한계점
빌데이터 및 AI 플랫폼을 온프레미스(CentOS) 환경에 구축할 당시, 컨테이너 오케스트레이션의 표준인 Kubernetes(K8s) 클러스터를 처음부터 직접 셋업해야 했습니다. 가장 빈번하게 마주치는 장애물은 크게 세 가지였습니다.
- Docker Engine과 Kubernetes 버전 간의 호환성: 무턱대고 최신 버전을 섞어 설치하면 Kubelet 서비스가 올라오지 않습니다.
- OS 호스트 설정 누락: Swap 메모리, 방화벽, SELinux 컨트롤에 실패하면 프리플라이트(Preflight) 단계에서 끝없이 실패합니다.
- CNI(Container Network Interface) 꼬임 문제: Master Node를 초기화할 때 통신망 대역(
pod-network-cidr)을 잘못 잡으면 파드 간 통신이 전면 마비됩니다.
본 문서는 이러한 시행착오를 수없이 겪으며 정리한 K8s 1.13.1 버전에 최적화된 가장 안정적인 클러스터 스크래치 빌드 가이드입니다.
2. 컨테이너 런타임과 CNI의 핵심 개념 이해
클러스터 구축 전 반드시 이해해야 하는 핵심 컴포넌트들의 관계입니다.
- 컨테이너 런타임 (Docker): K8s는 내부적으로 컨테이너 런타임(CRI)을 구동합니다. Docker 데몬이 컨테이너의 cgroup(리소스 격리)을 관리하는 방식과 Kubelet의 방식(
systemd)을 일치시켜주는 것이 가장 중요합니다. - OS 리소스 제어 (Swap): K8s는 오케스트레이션 시 노드의 리소스를 100% 통제해야 합니다. OS의
Swap메모리가 켜져 있으면 컨테이너의 메모리 제한(QoS)이 우회되어 OOM(Out of Memory) 상황 통제가 불가능해집니다. - 가상 네트워크 (CNI): Master Node(
kubeadm init)가 올라간 직후CoreDNS가 구동되기 위해서는 파드 간 물리적 노드를 뛰어넘는 가상 네트워크 브릿지가 필요한데, 이 가이드에서는 온프레미스에 적합한 Flannel 플러그인을 사용합니다.
3. Step-by-Step 구축 가이드
단계 1: 호스트 OS 사전 준비 (모든 노드 공통)
가장 먼저 컨테이너 런타임과 네트워크 제어를 위해 모든 마스터(Master)와 워커(Worker) 노드에서 아래 setup_k8s_prereq.sh 스크립트를 실행합니다.
#!/bin/bash
# 1. SELinux 비활성화 (보안 정책 충돌 방지)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# 2. Swap 메모리 영구 비활성화 (Kubelet 구동 필수 조건)
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab
# 3. 브릿지 네트워크 트래픽 통과 설정 (CNI 플러그인용)
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
# 4. 방화벽(firewalld) 비활성화 (포트 충돌 방지)
sudo systemctl disable firewalld
sudo systemctl stop firewalld
# 5. K8s YUM 리포지토리 등록 (구글 클라우드)
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
# 6. K8s 컴포넌트(1.13.1) 강제 설치
sudo yum install -y kubelet-1.13.1 kubeadm-1.13.1 kubectl-1.13.1 --disableexcludes=kubernetes
# 7. Kubelet 서비스 활성화 (시작은 아직 안 함, 이후 kubeadm이 제어)
sudo systemctl enable kubelet && systemctl start kubelet단계 2: 안정적인 Docker 18.06 런타임 설치 (모든 노드 공통)
K8s 1.13.1과 완벽히 호환 검증된 버전을 설치합니다. 이 역시 모든 노드에서 실행합니다.
#!/bin/bash
# 1. 필수 유틸리티 및 리포지토리 추가
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 2. 특정 호환 버전(18.06) 지정 설치
sudo yum install docker-ce-18.06.1.ce-3.el7 docker-ce-cli-18.06.1.ce-3.el7 containerd.io -y
# 3. Docker 데몬 설정 디렉토리 생성
sudo mkdir /etc/docker
# 4. cgroup 드라이버 시스템 일치화 및 사내 로컬 레지스트리(Insecure) 등록
cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"insecure-registries": ["192.168.1.189:5000"]
}
EOF
# 5. Docker 서비스 데몬 재시작 및 자동 실행
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl enable docker주의:
"native.cgroupdriver=systemd"설정이 누락되어 Docker가cgroupfs를 바라보게 되면 OOM 발생 시 노드가 죽어버리는 클러스터 파멸을 겪을 수 있습니다.
단계 3: 마스터 노드(Control Plane) 초기화 및 Flannel 적용
모든 사전 준비가 끝났으므로 마스터(Master) 역할을 할 1대의 노드에서만 다음 작업들을 수행합니다.
1. Kubeadm 클러스터 초기화
향후 적용할 Flannel CNI 플러그인을 위해 반드시 --pod-network-cidr을 10.244.0.0/16 기본값으로 강제 지정합니다.
# apiserver-advertise-address에는 마스터 노드 본인의 내부 IP를 적습니다.
kubeadm init --apiserver-advertise-address=192.168.1.134 --pod-network-cidr=10.244.0.0/16명령어가 끝나면 하단에 출력되는
kubeadm join 192.168.1.134:6443 --token ...값을 반드시 메모장에 복사해 둡니다. 워커 노드를 연결할 때 필요합니다.
2. Kubectl CLI 관리자 권한 복사 마스터 노드 터미널에서 클러스터 상태를 조회하기 위한 자격증명 설정을 가져옵니다.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config3. Flannel CNI 네트워크 플러그인 설치 노드 간 통신망을 개통시켜 줍니다.
# Flannel 기본 매니페스트 배포
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml폐쇄망의 경우 인터넷 망에서 도커 이미지를 Tar로 빼와 로컬 레지스트리에 푸시한 뒤, 매니페스트의 이미지 주소를 로컬 저장소로 고쳐서 띄우면 됩니다.
마지막으로 마스터 노드 터미널에서 kubectl get nodes -o wide를 입력했을 때 노드의 상태가 Ready로 변경되면 코어 구축이 완벽하게 완료된 것입니다!
4. 클러스터 구축 요약 및 팁
swapoff -a를 터미널 커맨드로만 치고 /etc/fstab 영구 설정을 주석 처리하지 않으면 서버가 재부팅될 때 Kubelet이 모조리 데드 상태에 빠지는 참사를 자주 겪습니다. fstab 확인은 필수입니다.
또한 kubeadm init을 돌리다 인증서나 프리플라이트 충돌이 생기면 부분 수정을 하려 들지 마시고, 쿨하게 kubeadm reset을 쳐서 초기화한 다음 /etc/kubernetes 폴더와 Docker 컨테이너들을 싹 비우고 처음부터 다시 돌리는 길이 수명 단축을 막는 가장 빠른 지름길이었습니다.
망 분리가 잘 된 온프레미스 망에서는 과도한 OS 방화벽(firewalld) 정책보다는 과감하게 방화벽 데몬을 내리고, K8s 내부의 Network Policy를 활용해 파드 단위의 L4 트래픽 통제 아키텍처를 설계하는 것이 훨씬 깔끔한 엔지니어링 접근 방식입니다.