Jenkins, Kubespray, Terraform을 활용한 Openstack 상 Kubernetes 및 모니터링 환경 구축 자동화 - 2

변재한·2023년 12월 5일
0
post-thumbnail

Overview


졸업과제 프로젝트를 진행하며 Openstack 플랫폼 상에 쿠버네티스 클러스터와 모니터링 환경을 자동화했던 과정을 정리한 글이다.
졸업과제에서는 쿠버네티스 환경에 대한 사용자의 입력(마스터 노드 수, 워커 노드 수, 노드의 이미지, 노드의 하드웨어 명세 등) 기반 동적인 구축을 진행하며, 본 포스트에선 자동화 구축을 위한 사전설정 및 프로세스를 기술하려고 한다. 기술을 많이 사용하고, 볼륨이 길다 보니 기술에 대한 설명은 하지 않고 필요한 부분만 설명을 진행하고자 한다.

아래 그림은 졸업과제에서 만든 인프라 관리 시스템의 구성도이다.
Orchstrator - Monitor - Openstack 파트가 본 포스트에서 해당한다.


2. Terraform

왜 Terraform?

  1. Terraform은 IaC(Infrastructure as a Code)도구로써, 쿠버네티스가 구축되기 위한 기반 인프라 환경을 미리 정의하여 이를 바탕으로 정형화된 환경의 구축과 템플릿을 재활용하고자 하였다.
  2. 쿠버네티스는 특히, Master & Worker Node의 명세(개수, OS, 하드웨어)가 중요하여, 이러한 요소들은 Terraform의 variable을 이용하여 동적으로 인프라를 구축할 수 있게 되었다.
  3. Terraform 상태파일을 이용하여 구축한 환경을 추후 쉽게 삭제도 가능하다.

리소스 명세 및 요구사항 매핑

Terraform으로 아래와 같은 리소스들을 오픈스택 플랫폼 상에 생성하고자 했다.

또한, 아래 항목들을 Terraform의 variable 블록 타입을 이용하여 매핑시키도록 하고 resource 블록 타입 내에서 variable, count를 이용하여 동적으로 구축하게 하였다.

Terraform Code

Terraform Create Template - Tree Command Output

3. Kubespray

왜 Kubespray ?

쿠버네티스를 생성함에 있어 Kubeadm, Kops, Kubespray 등의 도구가 존재하는데, Jenkins 파이프라인과의 쉬운 통합을 위해 Kubespray를 선택했다. 아래는 Kubeadm, Kops를 선택하지 않은 이유, Kubespray를 선택한 이유에 대해 적어보았다.
1. Kubeadm:
노드별 수동 접근: 각 노드를 개별적으로 설정해야 하는 경우, Jenkins 파이프라인을 통해 각 노드에 접속하고 설정을 적용하는 과정이 번거로울 수 있다.
2. Kops:
클라우드 제한성: Kops는 주로 AWS에 최적화되어 있어, OpenStack과 같은 다른 클라우드 환경이나 베어 메탈 환경에서 사용할 때 제한적일 수 있다.
3. Kubespray:
단일 설정 파일의 이점: Kubespray는 inventory.ini라고 하는 Master, Worker Node 등 쿠버네티스를 구성하는 노드들에 대한 IP, Host Name 등을 명시하는 파일이 존재하며, Kubespray는 해당 파일만 구성한 후 실행시키면 클러스터가 만들어진다.
유연성 및 범용성: Kubespray는 Ansible을 기반으로 하며, 다양한 클라우드 환경 및 베어 메탈에 걸쳐 유연하게 사용할 수 있다.

inventory.ini

위에서, Kubespray는 inventory.ini라고 하는 설정 파일이 필요하다고 했고, 기반 인프라는 Terraform으로 구축됨을 언급했다.
이제, Terraform으로 구축된 노드(인스턴스)들의 IP 정보로 inventory.ini 파일을 만들어야 했고, 이를 Jenkins Pipeline에서 Terraform Output과 아래 Shell Script 파일을 활용하여 생성했다.

#!/bin/bash

# we need three arguments
if [[ $# -ne 4 ]]; then
  echo "Usage: $0 <CLUSTER_NAME> <BASTION_IP> <MASTER_IPS> <WORKER_IPS>"
  exit 1
fi

CLUSTER_NAME=$1
BASTION_IP=$2
MASTER_IPS=$3
WORKER_IPS=$4

# Create inventory.ini file
echo "[all]" > inventory.ini

# Master nodes
count=1
IFS=',' read -ra ADDR <<< "$MASTER_IPS"
for ip in "${ADDR[@]}"; do
  ip_clean=$(echo $ip | tr -d ' ')
  echo "k8s-${CLUSTER_NAME}-master${count} ansible_host=${ip_clean} ip=${ip_clean} etcd_member_name=etcd${count}" >> inventory.ini
  ((count++))
done

# Worker nodes
count=1
IFS=',' read -ra ADDR <<< "$WORKER_IPS"
for ip in "${ADDR[@]}"; do
  ip_clean=$(echo $ip | tr -d ' ')
  echo "k8s-${CLUSTER_NAME}-worker${count} ansible_host=${ip_clean} ip=${ip_clean}" >> inventory.ini
  ((count++))
done

echo -e "\n[bastion]" >> inventory.ini
echo "k8s-${CLUSTER_NAME}-bastion ansible_host=${BASTION_IP} ansible_user=ubuntu" >> inventory.ini

echo -e "\n[kube_control_plane]" >> inventory.ini
count=1
IFS=',' read -ra ADDR <<< "$MASTER_IPS"
for ip in "${ADDR[@]}"; do
  echo "k8s-${CLUSTER_NAME}-master${count}" >> inventory.ini
  ((count++))
done

echo -e "\n[etcd]" >> inventory.ini
count=1
IFS=',' read -ra ADDR <<< "$MASTER_IPS"
for ip in "${ADDR[@]}"; do
  echo "k8s-${CLUSTER_NAME}-master${count}" >> inventory.ini
  ((count++))
done

echo -e "\n[kube_node]" >> inventory.ini
count=1
IFS=',' read -ra ADDR <<< "$MASTER_IPS"
for ip in "${ADDR[@]}"; do
  echo "k8s-${CLUSTER_NAME}-master${count}" >> inventory.ini
  ((count++))
done
count=1
IFS=',' read -ra ADDR <<< "$WORKER_IPS"
for ip in "${ADDR[@]}"; do
  echo "k8s-${CLUSTER_NAME}-worker${count}" >> inventory.ini
  ((count++))
done

echo -e "\n[k8s_cluster:children]" >> inventory.ini
echo "kube_control_plane" >> inventory.ini
echo "kube_node" >> inventory.ini

Kubernetes Ingress를 위한 사전준비

Kubernetes Ingress, Loadbalancer를 생성하기 위해 Controller가 필요한데, AWS에서는 AWS Load Balancer Controller가 존재한다.

Openstack에서도 이와 같이 Openstack의 로드밸런싱을 담당하는 컴포넌트인 Octavia에서 Octavia Ingress Controller가 존재한다. 이를 위해, Kubespray에서 설정해줘야 하는 항목이 존재한다.

해당 부분도 또한 마찬가지로 Terraform으로 생성한 Network ID, Subnet ID가 존재하여 이를 Terraform Output, Linux Sed Command를 이용하여 Jenkins Pipeline 상에서 반영시켜 주었다.(뒤이어 언급)

4. Jenkins 설치

왜 Jenkins ?

  1. 먼저, 쿠버네티스가 구축될 기반 인프라(네트워크, 노드 등)를 Terraform으로 구축, 이후 Kubespray로 쿠버네티스 클러스터 설치의 자동화 성공 프로세스를 Jenkins Pipeline을 통해 정의하고자 하였다.
  2. Jenkins Job을 파라미터와 함께 API 호출 가능
    이로 인해, Front(Master Node 및 Worker Node 개수, 이미지, 하드웨어 명세 등을 입력) -> Back(입력값을 통한 Jenkins Job 트리거) -> Jenkins Job순으로 구축 요청!

설치 및 실행

Jenkins는 오픈스택이 설치된 VMware 가상머신 위에 Docker Container로 띄워 동작하게 하였다.

Jenkins Dockerfile

FROM jenkins/jenkins:lts

USER root

RUN apt-get update && \
    apt-get install -y wget unzip && \
	apt-get install -y jq netcat-openbsd && \
    wget https://releases.hashicorp.com/terraform/0.14.0/terraform_0.14.0_linux_amd64.zip && \
    unzip terraform_0.14.0_linux_amd64.zip && \
    mv terraform /usr/local/bin/ && \
    rm terraform_0.14.0_linux_amd64.zip && \
    apt-get clean

USER jenkins

Jenkins의 Image를 만들기 위한 Dockerfile이 위와 같다.
Jenkins의 파이프라인에서 Terraform 명령어를 사용해야 하기에 관련된 명령어를 Dockerfile에 추가하였다.
특히, 특정 Terraform 0.14.0 버전을 다운로드하게 된 이유로는 Terraform 상태파일 저장과 관련이 있다.
Terraform에는 상태파일이라고 하는 동기화 및 협업 등의 목적으로 사용하는 'terraform.tfstate'이 있는데, AWS에서 Terraform을 사용할 때는 AWS S3 서비스에 상태파일을 저장하여 사용하게 된다.
Openstack에도 S3와 같은 오브젝트 스토리지 서비스가 존재하며, 'Swift'라고 불린다.
Terraform 상태파일 저장소를 Swift로 지정하기 위해서는 terraform 0.14.0 버전 이하에서만 동작하게 바껴서, 특정 버전을 사용하게 되었다.
조금 더 상세한 이유는 HashiCorp Discuss - Replacement for (now deprecated) Swift Backend?

Jenkins 실행

# jenkins image build 위한 폴더 생성
mkdir jenkins_img

#Dockerfile 생성
cd jenkins_img
vi Dockerfile

# docker image build
docker build -t jenkins .

# Jenkins Container 구동
docker run --name jenkins -d -p 9090:8080 -v ~/jenkins:/var/jenkins_home -u root jenkins/jenkins:latest

# 초기 Admin Password 가져오기
docker exec -it jenkins bash -c "cat /var/jenkins_home/secrets/initialAdminPassword"

이후, 로그인을 수행하고 몇몇 필요한 플러그인을 설치한 후, 파이프라인을 만들어주었다.

profile
Infra and Devops 엔지니어가 되고 싶어용

0개의 댓글