소개
Kubernetes가 내장된 Docker 지원을 종료하기로 발표함에 따라, 컨테이너 런타임으로 Containerd를 사용하는 방식이 점차 보편화되고 있습니다. Containerd는 Docker에 비해 더 간결한 호출 체인을 제공하여, Kubernetes 클러스터 구축 시 더욱 효율적인 선택지가 될 수 있습니다. 이 가이드는 CentOS 7.6 환경에서 Kubernetes 1.23.4와 Containerd 1.4.12 버전을 사용하여 클러스터를 배포하는 과정을 설명합니다. 모든 명령어는 root 권한으로 실행됨을 가정합니다.
환경 설정
시스템 정보
- 운영 체제: CentOS 7.6
- Kubernetes 버전: 1.23.4
- Containerd 버전: 1.4.12
YUM 저장소 미러 변경
기본 YUM 저장소를 국내 미러(예: 카카오, 네이버 클라우드) 또는 Alibaba Cloud 미러로 변경하여 패키지 다운로드 속도를 향상시킵니다.
# 1. wget 설치 (만약 설치되어 있지 않다면)
sudo yum install -y wget
# 2. 기존 CentOS-Base.repo 파일 백업 후 새 미러 저장소 다운로드
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak || true
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 또는 curl 사용
# sudo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 3. YUM 캐시 정리 및 재생성
sudo yum clean all
sudo yum makecache
SELinux 비활성화
Kubernetes는 SELinux가 permissive 모드이거나 비활성화되어 있을 때 가장 잘 작동합니다.
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
방화벽 비활성화
클러스터 구성 요소 간의 통신을 위해 방화벽을 비활성화합니다.
sudo systemctl stop firewalld
sudo systemctl disable --now firewalld
Kubernetes 저장소 및 필수 도구 추가
Kubernetes 패키지를 다운로드하기 위한 저장소를 추가하고, 필요한 유틸리티를 설치합니다.
# Kubernetes YUM 저장소 설정
sudo tee /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF
# 필수 유틸리티 설치
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Docker CE 저장소 추가 (Containerd 설치에 필요할 수 있음)
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# OpenStack Rocky 저장소 추가 (일부 종속성 해결에 필요할 수 있음)
sudo yum install centos-release-openstack-rocky -y
</code>
kubelet, kubeadm, kubectl 설치
Kubernetes 클러스터 관리에 필요한 핵심 도구들을 설치합니다.
sudo yum install -y kubeadm-1.23.4 kubectl-1.23.4 kubelet-1.23.4 --disableexcludes=kubernetes
Containerd 설치 및 구성
Kubernetes의 컨테이너 런타임인 Containerd를 설치하고 설정합니다.
# Containerd 및 관련 도구 설치
sudo yum install -y containerd.io openvswitch* certbot
# crictl 다운로드 및 설치 (Containerd CRI 인터페이스와 통신하는 CLI 도구)
cd /tmp
sudo wget https://mirror.ghproxy.com/https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.23.0/crictl-v1.23.0-linux-amd64.tar.gz
sudo tar zxf crictl-v1.23.0-linux-amd64.tar.gz
sudo mv crictl /usr/local/bin/
sudo rm -rf crictl-v1.23.0-linux-amd64.tar.gz
# 커널 모듈 설정
sudo modprobe overlay
sudo modprobe br_netfilter
sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
# 필수 sysctl 파라미터 설정 (재부팅 후에도 유지되도록)
sudo tee /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# sysctl 파라미터 적용
sudo sysctl --system
# Containerd 기본 설정 파일 생성
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml >/dev/null
# Containerd 설정 파일 수정: SystemdCgroup 활성화 및 샌드박스 이미지 미러링
# Containerd의 CRI 플러그인 설정에서 SystemdCgroup을 true로 변경하고
# 샌드박스(pause) 이미지 주소를 Alibaba Cloud 미러로 변경합니다.
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo sed -i 's|sandbox_image = "k8s.gcr.io/pause:.*"|sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2"|g' /etc/containerd/config.toml
# Containerd 서비스 재시작 및 활성화
sudo systemctl restart containerd
sudo systemctl enable containerd
# Kubelet 추가 인자 설정 (cgroup 드라이버 지정)
sudo echo "KUBELET_EXTRA_ARGS=--cgroup-driver=systemd" | sudo tee /etc/sysconfig/kubelet >/dev/null
# crictl 설정 파일 생성 (Containerd 소켓 경로 지정)
sudo tee /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
</code>
kubeadm 설정 파일 초기화
클러스터 초기화에 사용될 kubeadm 구성 파일을 생성합니다. 여기서는 Pod 네트워크 CIDR과 이미지 저장소 미러를 지정합니다.
sudo mkdir -p /etc/kubernetes
sudo tee /etc/kubernetes/kubeadm.yaml <<EOF
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
bootstrapTokens:
- ttl: "0"
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
networking:
podSubnet: "10.244.0.0/16"
kubernetesVersion: "v1.23.4"
imageRepository: "registry.cn-hangzhou.aliyuncs.com/google_containers"
EOF
</code>
Kubernetes 클러스터 배포
kubelet 서비스 활성화
kubelet이 시스템 시작 시 자동으로 실행되도록 설정하고 시작합니다.
sudo systemctl restart kubelet
sudo systemctl enable kubelet
Swap 비활성화
Kubernetes는 노드에서 스왑이 비활성화되어 있을 것을 요구합니다.
sudo swapoff -a && sudo sysctl -w vm.swappiness=0
sudo sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
브릿지 트래픽에 대한 iptables 검사 허용
클러스터 내부 통신 및 서비스 메시를 위해 브릿지 트래픽이 iptables에 의해 처리되도록 설정합니다.
sudo echo "1" | sudo tee /proc/sys/net/bridge/bridge-nf-call-iptables >/dev/null
sudo echo "1" | sudo tee /proc/sys/net/ipv4/ip_forward >/dev/null
kubeadm을 사용하여 클러스터 시작
앞서 준비한 kubeadm 설정 파일을 사용하여 Kubernetes 마스터 노드를 초기화합니다.
sudo kubeadm init --config /etc/kubernetes/kubeadm.yaml
명령어 실행 완료 후 출력되는 kubeadm join ... 명령은 워커 노드를 클러스터에 추가할 때 필요하니 기록해 두십시오. 만약 나중에 필요하다면 kubeadm token create --print-join-command 명령으로 다시 생성할 수 있습니다.
kubectl 환경 설정
현재 사용자 계정에서 kubectl 명령어를 사용할 수 있도록 설정합니다.
rm -rf $HOME/.kube
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
sudo iptables -P FORWARD ACCEPT
CNI 플러그인 적용
Pod 간의 네트워크 통신을 위해 CNI(Container Network Interface) 플러그인을 설치합니다. 여기서는 Calico를 사용합니다.
kubectl apply -f https://docs.projectcalico.org/archive/v3.17/manifests/calico.yaml
클러스터 상태 확인
모든 Pod가 정상적으로 실행 중인지 확인합니다.
kubectl get pod -A
모든 Pod의 STATUS가 Running 상태여야 합니다.
문제 해결 팁
이미지 풀링 문제 해결
Kubernetes가 기본적으로 k8s.gcr.io에서 이미지를 가져오려고 시도하지만, 간혹 네트워크 문제로 실패할 수 있습니다. 이미 미러 저장소로 대부분을 설정했지만, 특정 Pod에서 여전히 문제가 발생한다면 다음 방법을 시도할 수 있습니다. 예시로 k8s.gcr.io/pause:3.2 이미지가 필요한 경우:
# 미러 저장소에서 이미지 다운로드
sudo crictl pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2
# 다운로드한 이미지에 원본 태그 추가
# containerd CLI(ctr)를 사용하여 k8s.io 네임스페이스에 태그를 지정합니다.
sudo ctr -n=k8s.io images tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 k8s.gcr.io/pause:3.2
대부분의 k8s.gcr.io 이미지는 registry.cn-hangzhou.aliyuncs.com/google_containers로 대체하여 풀링할 수 있습니다. 다른 미러로 lank8s.cn 또는 gcr.lank8s.cn을 시도해 볼 수도 있습니다.
kubelet 서비스 문제 해결
kubelet이 비정상적으로 작동하는 경우, 다음 명령어로 상태와 로그를 확인합니다.
# kubelet 서비스 상태 확인
sudo systemctl status kubelet
# kubelet 상세 로그 확인
sudo journalctl -xeu kubelet
로그를 통해 오류 메시지를 파악하고, 필요한 경우 kubelet의 실행 인자를 확인합니다.
# 실행 중인 kubelet 프로세스 확인
ps -ef | grep kubelet
정상적인 kubelet 프로세스는 대략 다음과 같은 인자를 포함해야 합니다:
/usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
--kubeconfig=/etc/kubernetes/kubelet.conf \
--config=/var/lib/kubelet/config.yaml \
--container-runtime=remote \
--container-runtime-endpoint=/run/containerd/containerd.sock \
--cgroup-driver=systemd
만약 --cgroup-driver, --container-runtime, --container-runtime-endpoint 인자가 누락되어 있다면, /etc/sysconfig/kubelet 파일에 추가하여 설정할 수 있습니다.
sudo echo "KUBELET_EXTRA_ARGS=--cgroup-driver=systemd --container-runtime=remote --container-runtime-endpoint=/run/containerd/containerd.sock" | sudo tee /etc/sysconfig/kubelet >/dev/null
sudo systemctl restart kubelet
kubelet이 여전히 시작되지 않는다면, 의존하는 컨테이너 이미지가 로컬에 있는지, 버전이 올바른지, Containerd가 정상적으로 작동하는지 등을 확인해야 합니다.