본문 바로가기
DevOps

[Kubernetes] Ubuntu 리눅스 쿠버네티스 클러스터 구축 방법

by Jayson Jeong 2024. 2. 14.

쿠버네티스란?

쿠버네티스 클러스터는 컨테이너화된 애플리케이션을 실행하는 컴퓨팅 노드 또는 작업자 머신 그룹이다.

컨테이너화 된 애플리케이션의 대규모 배포, 스케일링 및 관리를 간편하게 만들어주는 오픈 소스 기반의 컨테이너 오케스트레이션 도구이다.

즉, 도커는 어플리케이션을 프로세스 격리 기술을 사용하여 컨테이너로 관리할 수 있는 도구이고 쿠버네티스는 그런 컨테이너들을 간편하게 관리할 수 있는 컨테이너 오케스트레이션 도구이다.

쿠버네티스 컴포넌트. 출처: https://kubernetes.io/ko/docs/concepts/overview/components/

 

쿠버네티스 클러스트터를 구축하기 위해선 최소 사양을 만족하는 2대 이상의 리눅스를 준비해야 한다.

 

테스트 환경

최소 사양을 만족하는 Ubuntu 22.04LTS 3대

Master Node 1대, Worker Node 2대 구성

 

진행 순서

  1. 쿠버네티스 설치 준비
  2. 컨테이너 런타임 설치
  3. 쿠버네티스 설치
  4. Master Node 설정
  5. Worker Node 등록
  6. 최종 확인

 

※ 모든 설치 과정은 root 계정으로 진행할 것을 권장

#root 계정 접속 방법
sudo su

1. 쿠버네티스 설치 준비

클라스터를 구축하기 위해 필요한 사전 작업은 다음과 같다.

  1. swap 메모리 비활성화
  2. 클러스터의 모든 시스템 간의 네트워크 연결
  3. 컨테이너 런타임 설치

 

1.1. OS 정보 확인

Master Node 최소 사양 Worker Node 최소 사양
CPU: 2 Core, RAM: 2GB CPU: 1 Core, RAM: 1GB
#코어 확인
nproc

#메모리 확인
free -h

#MAC 확인
ifconfig -a

#product uuid 확인
sudo cat /sys/class/dmi/product_uuid
#또는 
sudo cat /sys/class/dmi/id/product_uuid

 

1.2. 메모리 swap 기능 비활성화

#swap 임시 비활성화
sudo swapoff -a 

#swap 영구 비활성화
sudo sed -i '/swap/s/^/#/' /etc/fstab

#메모리 상태 확인
sudo free -m

#swap 메모리 상태 확인, 출력값이 없으면 swap 메모리 비활성화 상태
sudo swapon -s

swap 비활성화 결과

 

※위 방법으로 비활성화 되지 않는 경우

#swap unit 조회
systemctl list-unit-files --type swap

#swap unit(dev-파티션이름.swap)을 mask해서 비활성화
systemctl mask [swap unit명]
ex) systemctl mask dev-sda3.swap

#비활성화 적용 확인
sudo systemctl list-unit-files --type swap

 

1.3. 방화벽 설정

  • 방법1: 쿠버네티스 포트만 방화벽 포트 개방
#방화벽 예외 설정(마스터, 워커)
sudo apt-get install -y firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

#마스터 노드일 경우
sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --permanent --add-port=2379-2380/tcp
sudo firewall-cmd --permanent --add-port=10250-10252/tcp
sudo firewall-cmd --permanent --add-port=8285/udp
sudo firewall-cmd --permanent --add-port=8472/udp
sudo firewall-cmd --reload

#워커 노드일 경우
sudo firewall-cmd --permanent --add-port=10250/tcp
sudo firewall-cmd --permanent --add-port=30000-32767/tcp
sudo firewall-cmd --permanent --add-port=8285/udp
sudo firewall-cmd --permanent --add-port=8472/udp
sudo firewall-cmd --permanent --add-port=26443/tcp
sudo firewall-cmd --reload

 

  • 방법2: 방화벽 비활성화
#방화벽 비활성화(마스터, 워커)
sudo apt-get install -y firewalld
sudo systemctl stop firewalld
sudo systemctl disable firewalld

 

 

  • 방화벽 오픈 상태 확인
#열린 포트 확인
sudo firewall-cmd --list-all

#열린 포트 확인
sudo netstat -tlnp

#다른 노드의 포트 점검
telnet [ip] [port]
ex) telnet 192.168.100.128 6443

>> 
Trying 192.168.111.128...
telnet: Unable to connect to remote host: Connection refused
#Trying 192.168.111.128... 만 계속 나오면 방화벽 오픈되어 있지 않음
#Connection refuesed가 나오면 방화벽 오픈은 되어 있으나 프로세스가 올라가 있지 않은 상태

#방법2
curl -v telnet://[ip]:[port]

방화벽 설정 결과 좌)마스터 노드. 우) 워커 노드.

 

1.4. 네트워크 옵션 설정

#/etc/modules-load.d/k8s.conf 파일 생성
sudo cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
 
#/etc/sysctl.d/k8s.conf 파일 생성
sudo cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

#시스템 재시작 없이 stysctl 파라미터 반영
sudo sysctl --system

 


2. 컨테이너 런타임 설치

 

쿠버네티스는 컨테이너들을 통합 관리하는 오케스트레이션 플랫폼이기 때문에 컨테이너의 실행, 관리 등의 역할을 수행하는 컨테이너 런타임을 별도 설치해야 한다. 

 

쿠버네티스 설치에 앞서 도커를 선행 설치하는 경우가 있는데 이는 Docker의 핵심 컨테이너 런타임 기능을 독립 실행형 구성 요소로 확장한 것이 Containerd이기 때문에 Docker의 컨테이너 런타임인 Containerd를 쿠버네티스의 컨테이너 런타임으로 사용 가능하기 때문이다.

 

쿠버네티스의 컨테이너 런타임으로 도커를 사용 가능한 이유

 

도커 뿐만이 아닌 CRI 표준을 만족하는 컨테이너 런타임은 모두 쿠버네티스 클러스터의 컨테이너 런타임으로 사용이 가능하다. 대표적으로 Containerd와 CRI-O가 있다.

 

 

CRI(Container Runtime Interface)

  • Containerd: 도커의 핵심 컨테이너 런타임 기능을 독립 실행형 구성 요소로 확장한 컨테이너 런타임으로 도커 엔진에 기본으로 탑재되어 있어 지금도 도커를 사용한다면 내부적으로 사용되는 컨테이너 런타임
  • CRI-O: 레드햇이 개발한 쿠버네티스용 OCI(Open Container initiative) 컨테이너 런타임으로 도커를 대체하기 위해 쿠버네티스에서 CRI 구현 목적으로 만든 쿠버네티스 전용 런타임

 

쿠버네티스의 컨테이너 런타임을 설치하는 방법을 몇 가지 소개하도록 하겠다.

  1. docker 설치 시 Depends로 함께 설치되는 containerd 패키지 사용
  2. containerd만 설치 사용
  3. docker engine + cri-dockerd

※ 세가지 방법 중 한가지만 적용하면 된다.

 

2.1. 방법1) Docker 설치 후 Containerd 패키지 사용

2.1.1. apt 업데이트 및 필수 패키지 설치

#apt 업데이트
sudo apt-get update

#필수 패키지 설치
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg

 

2.1.2. 공개키 다운로드 및 저장소 등록

#공개키 다운로드
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 저장소 등록
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

 

2.1.3. 도커 설치

#저장소 추가로 apt 업데이트
sudo apt update

#도커 설치
sudo apt install -y docker.io 또는 sudo apt install -y docker-ce

#도커 버전 조회
docker --version

※ docker.io 데비안(우분투)에서 제공하는 도커 패키지로 데비안 저장소에서 도커 패키지를 가져오게 된다.

docker.io 는 docker의 외부 종속성 패키지는 마이크로 패키징으로 독립적으로 패키징되어 있다.

docker-ce 설치 시 → 외부 종속성 패키지로 containerd.io 설치됨.

docker.io 설치 시 → 외부 종속성 패키지로 containerd 설치됨.

 

2.1.4 도커 데몬 설정

#/etc/docker 디렉토리 없을 경우 생성
sudo mkdir /etc/docker

#daemon.json 파일 추가
sudo cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

 

2.1.5. 필요시 cgroup(runc) 옵션 설정

#containerd 구성 파일 생성
sudo mkdir -p /etc/containerd

#containerd 기본 설정값으로 config.toml 생성
sudo containerd config default | sudo tee /etc/containerd/config.toml

#config.toml 파일 수정
vi /etc/containerd/config.toml

# cgroup driver(runc) 사용하기 설정
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

#수정사항 적용 및 재실행
sudo systemctl restart containerd

 

2.1.6. 도커 재시작

#도커 재시작
sudo service docker restart

#도커 상태 조회
sudo service docker status

docker.io 설치 결과

 


2.2. 방법2) Containerd 설치 후 사용

2.2.1. apt 업데이트 및 필수 패키지 설치

#apt 업데이트
sudo apt-get update

#필수 패키지 설치
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg

 

2.2.2. 공개키 다운로드 및 저장소 등록

#공개키 다운로드
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 저장소 등록
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

 

2.2.3. containerd 패키지 설치

#저장소 적용을 위한 apt 업데이트
sudo apt-get update

#containerd 패키지 설치
sudo apt-get install containerd

#설치 확인
sudo systemctl status containerd

 

2.2.4. containerd config 옵션 설정

#containerd 구성 파일 생성
sudo mkdir -p /etc/containerd

#containerd 기본 설정값으로 config.toml 생성
sudo containerd config default | sudo tee /etc/containerd/config.toml

#config.toml 파일 수정
vi /etc/containerd/config.toml

# cgroup driver(runc) 사용하기 설정
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true

#수정사항 적용 및 재실행
sudo systemctl restart containerd

 

 


2.3. 방법3) Docker Engine + cri-dockerd 적용

  • Docker 엔진 관련 명령을 기반으로 스크립트를 실행
  • 권한이 있는 Pod에서 Docker 명령 실행
  • Docker 특정 로깅 및 모니터링 활용

등의 이유로 도커 엔진을 컨테이너 런타임으로 사용하는 경우가 있다.

또는 dockershim을 대체하기 위해 크리도커드(cri-dockerd)로 마이그레이션 하는 경우가 있다.

 

2.3.1. apt 패키지 업데이트 및 필수 패키지 설치

#apt 업데이트
sudo apt update

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

#설치 패키지 조회
dpkg -l | grep [패키지명]

 

2.3.2. docker gpg 키 다운로드 및 저장소 추가

#공개키 다운로드
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 저장소 등록
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

 

2.3.3. docker 패키지 설치

#등록한 레포지토리를 반영하기 위해 apt update
sudo apt update

#docker 패키지 설치
sudo apt install -y docker-ce

 

2.3.4. 설치 확인

#버전 확인
docker --version

#hello-world container 생성
docker run -it --name [컨테이너명] hello-world

#도커 컨테이너 조회
docker ps -a

#도커 컨테이너 삭제
docker rm [컨테이너ID 또는 컨테이너명]

#도커 이미지 조회
docker images

#도커 이미지 삭제
docker rmi [이미지명]

 

2.3.5. cri-dockerd를 이용하여 도커 엔진과 쿠버네티스 연결

#cri-dockerd 소스코드 복사
git clone https://github.com/Mirantis/cri-dockerd.git

#Go언어 설치
wget https://storage.googleapis.com/golang/getgo/installer_linux
chmod +x ./installer_linux
./installer_linux
source ~/.bash_profile

#cri-dockerd 빌드
cd cri-dockerd
mkdir bin
go build -o bin/cri-dockerd

#/usr/local/bin 으로 빌드파일 복사
mkdir -p /usr/local/bin
install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd

#systemd에 서비스 등록
cp -a packaging/systemd/* /etc/systemd/system
sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

#재기동
systemctl daemon-reload
systemctl enable cri-docker.service
systemctl enable --now cri-docker.socket
sudo systemctl restart docker && sudo systemctl restart cri-docker

#상태 확인
sudo systemctl status cri-docker.socket --no-pager

# Docker daemon Cgroup 변경
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

 


3. 쿠버네티스 클러스터(Kubernetes Cluster) 설치

3.1. apt 패키지 업데이트 및 필수 패키지 설치

필수 패키지 목록

  • apt-transport-https
  • ca-certificates
  • curl
  • gnupg
#apt 업데이트
sudo apt-get update

#필수 패키지 설치
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg

 

 

3.2. 구글 클라우드의 공캐  키 다운로드 및 쿠버네티스 레포지토리 추가

#공개 키 다운로드
curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://dl.k8s.io/apt/doc/apt-key.gpg

#apt 저장소에 쿠버네티스 저장소 추가
sudo echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

#※ 23.01쯤 부터 쿠버네티스 저장소 url이 변경됨.
#https://packages.cloud.google.com/apt/doc/apt-key.gpg -> https://dl.k8s.io/apt/doc/apt-key.gpg

 

※Ubuntu 20.04에는 /etc/apt/keyrings 디렉토리가 없으므로 디렉토리 생성 필요. 22.04 이후에는 디렉토리 존재함

#keyrings 디렉토리 생성
sudo mkdir -p /etc/apt/keyrings

#개인키 다운로드
curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://dl.k8s.io/apt/doc/apt-key.gpg

#쿠버네티스 레포지토리 추가
sudo apt-add-repository "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] http://apt.kubernetes.io/ kubernetes-xenial main"

 

※그래도 문제가 발생할 경우 vi 편집기로 kubenetes.list 파일에 해당 문자열 추가

sudo vi /etc/apt/sources.list.d/kubernetes.list 

#다음 문자열 추가
deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] http://apt.kubernetes.io/ kubernetes-xenial main

 

 

3.3. 쿠버네티스 패키지 설치

#저장소 추가되었기 때문에 apt 업데이트
sudo apt-get update

#쿠버네티스 패키지 설치
sudo apt-get install -y kubelet kubeadm kubectl

#쿠버네티스 패키지 버전 고정
sudo apt-mark hold kubelet kubeadm kubectl

#쿠버네티스 설치 버전 조회
kubelet --version
kubeadm version
kubectl version

#kubelet service 확인
sudo systemctl status kubelet.service

 

쿠버네티스 설치 결과

 


4. Master Node 구성

4.1. Control-Plane 구성

kubeadm을 통해 Control-Plane 설정을 완료하면 Worker Node의 join키가 발급되고 해당 키로 Worker Node를 등록 시 사용하니 꼭 기억해놓자

#쿠버네티스 클러스터를 초기화하여 새로운 마스터 노드를 생성하는 명령어
#별도의 옵션을 설정하지 않으면 기본 디폴트 값으로 적용
kubeadm init [옵션]

#Flannel(디폴트 설정 값)
sudo kubeadm init
#또는
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

#Calico
sudo kubeadm init --pod-network-cidr=192.168.0.0/16

 

옵션 목록

--config : 초기화에 사용할 구성 파일을 지정

--token : 클러스터에 대한 액세스를 허용하는 토큰을 초기화

--pod-network-cidr : 클러스터에 대한 Pod 네트워크 CIDR 범위를 지정

--apiserver-advertise-address : API 서버가 퍼블릭 엔드포인트에 대해 알릴 IP 주소를 지정

--apiserver-cert-extra-sans : 마스터 노드 인정스에 추가할 DNS 이름을 지정

--control-plane-endpoint : 컨트롤 플레인 구성요소가 서로 통신하는데 사용할 엔드포인트를 지정

--cri-socket : 사용할 CRI의 소켓을 지정

 

4.2. kubectl 설정

root 계정이 아닌 다른 계정에서도 kubectl 명령어를 사용하기 위해 config 설정

※config 설정을 진행하지 않을 경우 kubectl 명령어를 사용 시

The connection to the server localhost:8080 was refused - did you specify the right host or port?

문구를 띄우면서 네트워크 연결이 거절될 수 있다.

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

 

 

4.3. CNI(Container Network Interface) 설정

컨테이너 간의 네트워크를 제어할 수 있는 플러그인으로 컨테이너 런타임에서 컨테이너의 네트워크를 사용하게 해주는 인터페이스이다.

쿠버네티스에서 사용되는 Pod들은 기본적으로 오버레이 네트워크 방식을 적용하여 엔드포인트 간의 네트워크 구조를 추상화하여 네트워크 통신 경로를 단순화한다. 이때 사용되는 플러그인 마다 설정 방법이 다르다.

 

Flannel

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

 

Calico

curl https://docs.projectcalico.org/manifests/calico.yaml -O --insecure 
kubectl apply -f calico.yaml

cni 설치 결과

#CNI 적용 확인
kubectl get pods -A -o wide

>>
NAMESPACE      NAME                      READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-g8j8h     1/1     Running   0          87s

 


5. Worker Node 구성

5.1. Worker Node 클러스터 가입

마스터 노드에서 kubeadm init 을 통해 생성한 join 명령어를 이용하여 워커 노드 등록

sudo kubeadm join [ip]:6443 --token [토큰명] --discovery-token-ca-cert-hash [hashkey]

 


6. 최종 확인

6.1. Master Node에서 node 상태 확인

sudo kubectl get node
또는
sudo kubectl get nodes -o wide