Container/Kubernetes

GCP VM Instance에 Kubernetes 구축하기

제이널 2023. 1. 3. 00:20

들어가며...

GCP(Google Cloud Platform)에서 CI/CD 적용을 고민하던 중, Cloud Build와 GKE를 사용하면 편리하게 CI/CD를 구현할 수 있다는 걸 알게되었습니다.

하지만 Kubernetes를 사용해본 적이 없는 상태에서 GKE를 사용하는 건 위험한 것 같아서, Kubernetes를 먼저 이해하고 직접 구축해보기로 했습니다.

 

Kubernetes?

https://bcho.tistory.com/1255

https://www.samsungsds.com/kr/insights/220222_kubernetes1.html

https://www.samsungsds.com/kr/insights/kubernetes-2.html

 

Kubernetes 구성요소

https://kubernetes.io/ko/docs/concepts/overview/components/

 

이 글은 아래의 글을 보고 따라하며 작성했습니다.

https://aoc55.tistory.com/53?category=979845

 


1. VM Instance 생성

먼저 Compute Engine 서비스를 활성화 해주고,

GCP > 메뉴 > Compute Engine > VM 인스턴스로 이동해 인스턴스를 새로 만들어 줍니다.

Kubernetes 환경을 구축하기 위해 마스터 1개, 워커 3개, 총 4개의 CentOS 인스턴스를 생성했습니다.

 

 

원하시는 OS와 리소스를 선택해서 완료해주시면 됩니다.


2. 인스턴스에 접속

VM 인스턴스의 SSH 기능을 사용하시거나, 터미널에서 접속을 원하시는 경우 SSH 설정을 해주시면 됩니다.

기본적인 SSH 설정 방법: https://sty110357.tistory.com/94

 

GCP에 SSH를 설정하려면, 공개키를 VM 인스턴스에 등록해야 합니다.

root 계정으로 접속을 원하는 경우, 인스턴스에서 root 계정으로 공개키/개인키를 만들어서 사용하면 됩니다.

(추가적으로 ssh config에서 root 계종으로 접속 허용 설정 필요)

인스턴스를 클릭

 

수정 클릭

 

SSH 공개키를 인스턴스에 등록

 

3. 사전 준비

4개 인스턴스의 패키지를 업데이트하고, kubelet 컴포넌트의 정상 작동을 위해 SWAP 메모리를 해제해 줍니다.

yum update -y
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
swapoff -a

 

저는 맥 데스크톱의 작업 공간을 확장해서 사용했습니다.

 

4. 도커 설치

Kubernetes가 동작하려면 컨테이너 런타임이 필요하기 때문에 가장 대표적인 도커를 설치했습니다.

4개의 인스턴스에 모두 설치해 줍니다.

 

도커 공식 설치 가이드: https://docs.docker.com/engine/install/centos/

 

저장소 설정

sudo yum install -y yum-utils
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

 

도커 엔진 설치

sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

 

도커 드라이버 설정(쿠버네티스 권장)

sudo mkdir /etc/docker
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

 

도커 재시작 및 부팅 시 시작 설정

sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker

 


5. 방화벽 및 네트워크 설정

Kubernetes 환경에서 각 노드들이 CNI(Container Network Interface)를 통해 통신을 하게 되는데, 이에 필요한 설정을 4개의 인스턴스에 모두 해줍니다.

https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#network-plugin-requirements

modprobe overlay
modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
  • modprobe: 리눅스 커널 모듈을 커널에 추가하거나 제거하는 데 사용

6. kubernetes 설치

https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

 

kubernetes 설치를 위해선 kubeadm, kubelet, kubectl 등이 필요하기 때문에 4개의 인스턴스에 모두 설치해야 합니다.

 

kubeadm, kubelet, kubectl을 이해하려면 kubernetes의 구성 요소를 알아야 합니다.

https://www.samsungsds.com/kr/insights/kubernetes-3.html

 

- kubeadm: 클러스터를 쉽고 빠르게 구축하기 위한 기능을 제공합니다.(https://kgw7401.tistory.com/46)

- kublet: 각 노드에서 파드를 생성하고 컨테이너가 동작하도록 관리해 주는 핵심 요소입니다.

- kubectl: 클러스터에 명령을 내리는 CLI(Command Line Interface)입니다.

 

공식 문서에 적혀 있는 대로, 아래 명령을 통해 kubernetes를 설치합니다.

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
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=kubelet kubeadm kubectl
EOF

# permissive 모드로 SELinux 설정(효과적으로 비활성화)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

sudo systemctl enable --now kubelet

 


7.  클러스터 생성

마스터 노드 인스턴스의 클러스터를 kubeadm으로 초기화해줍니다.

kubeadm init

 

container runtime is not running 오류가 발생하면 /etc/containerd/config.toml 파일에서 disabled_plugins 항목에서 cri를 없애주고( ['cri']  --> [] ), containerd 서비스를 재시작해줍니다.

systemctl restart containerd

 

클러스터 초기화 성공

 

클러스터를 사용하기 위해선, 초기화 결과의 가이드 대로 아래 명령을 실행해줘야 합니다.

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

 

마지막으로, 방금 구축한 클러스터에 워커 노드들을 join시키기 위해서 각 워커 노드에 토큰을 적용하겠습니다.

# 예시입니다
kubeadm join xxx.xxx.xxx.xxx:6443 --token XXXXXXXX \
	--discovery-token-ca-cert-hash sha256:XXXXXXXX

 

이제 마스터 노드에서 워커 노드들이 join 됐는지 확인해봅니다.

kubectl get nodes

노드들의 상태가 NotReady인 이유는 아직 Pod 간 네트워킹이 되지 않기 때문입니다.


8. Pod Network add-on (CNI) 설치

구성한 클러스터 내에 CNI를 설치해서 Pod들이 서로 통신이 가능하도록 해주겠습니다.

CNI는 여러 종류가 있으며, 원글에 따라 WeaveNet을 설치했습니다.

 

아래 명령어를 마스터 노드에서 실행해주세요.

https://www.weave.works/docs/net/latest/kubernetes/kube-addon/

kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml

 

3분 정도 기다린 후에 노드들의 상태를 다시 확인하면 NotReady --> Ready로 바뀌어 있는 걸 확인할 수 있습니다.

kubectl get nodes

 


9. 테스트 용 Pod 실행

테스트로 NginX Pod를 만들어 실행해보겠습니다.

마스터 노드에서 아래 명령어를 실행해주세요.

kubectl run test-nginx --image=nginx:1.14

 

Pod가 정상적으로 실행됐는지 확인해 봅니다.

kubectl get pods -o wide

 

 

현재 워커3 노드에서 Pod이 실행됐음을 알 수 있고, 내부 네트워크 통신으로 IP 항목에 적힌 IP로 요청을 보내보면 NginX가 정상적으로 HTML을 응답하는 걸 확인할 수 있습니다.

yum install -y curl
curl 10.32.0.2

 

외부에서도 접속이 가능하게 하려면 서비스 오브젝트를 생성해주어야 합니다.

https://kubernetes.io/ko/docs/tutorials/stateless-application/expose-external-ip-address/