no image
OpenStack을 활용한 Local Cloud 구축 (1)
OpenStack이란 OpenStack은 가상화된 서버, 네트워크, 스토리지를 통합 관리하여 클라우드 인프라를 구축할 수 있도록 해주는 오픈 소스 플랫폼입니다. 주로 기업 내부의 프라이빗 클라우드 환경을 구축할 때 사용됩니다. 다음과 같은 주요 컴포넌트들이 존재합니다.컴포넌트 설명 Nova가상 머신(VM) 생성 및 관리 (컴퓨팅 자원 담당)Neutron네트워크 연결 설정 및 관리 (IP, 라우팅 등)Cinder블록 스토리지 제공 (VM용 디스크)GlanceVM 이미지 저장 및 관리Keystone인증과 권한 관리 (사용자 로그인 등)Horizon대시보드(UI) 제공Swift객체 스토리지 제공 (대용량 데이터 저장에 적합)Heat인프라 자동화 템플릿 (IaC, Infrastructure as Code)C..
2025.06.08
no image
RHCSA 취득 후기
취득 배경 Cloud 부트캠프가 끝난 후에 RHCSA 자격증을 따야겠다고 마음 먹었으나 취준생에겐 너무나 비싼 비용(55만원..) 그리고 타 이유들로 취득을 미뤘었습니다.하지만 여러 차례 면접을 보면서 Linux 관련 질문이 들어왔을 때 공부가 부족함을 느꼈고 그리고 자격증으로 역량을 증명해야겠다는 생각이 들어 취득을 결정하게 되었습니다. 시험 준비 https://www.udemy.com/course/linux-redhat-certified-system-administrator-rhcsa-ex200-korean/ 해당 강의를 보면서 공부를 진행했으나 자막이 있음에도 불구하고 인도식 영어를 알아듣는게 매우 힘들었습니다.다른 인도 분이 진행하신 CKA 강의는 훨씬 수월했던 것을 기억하면 더욱 그랬습니다. ..
2025.05.23
no image
[Linux] Oracle Virtualbox에 RHEL 구축
개요https://www.udemy.com/course/linux-redhat-certified-system-administrator-rhcsa-ex200-korean/ 해당 강의를 보며 RHCSA 자격증 취득을 준비하려 한다.  RHEL 9 버전을 사용할 것이고 지난 번 K8S 환경을 구축하면서 사용했던 Oracle Virtual box를 사용하고자 한다.  선행 과정 1. Redhat 회원 가입 ISO 이미지 파일을 다운로드 받기 위해 Redhat 회원 가입을 진행한다. 2. ISO 이미지 파일 다운로드 https://developers.redhat.com/products/rhel/download Download Red Hat Enterprise Linux at no cost | Red Hat Dev..
2025.04.02
no image
Local K8S 환경에서 Monitoring 환경 구축
개요지난 Cloud wave 프로젝트 때 경험하지 못한 K8S 환경에서 Monitoring 구축을 진행해보았다.   UI 중심으로 빠른 시각화를 경험하고 싶고 또 리소스가 부족한 로컬 클러스터인 것을 감안하여 ELK를 사용하지 않고 Grafana와 Prometheus를 사용한 메트릭 기반의 Monitoring을 구축하였다. 하지만 Log 기반의 Monitoring 또한 확인하고 싶었기에 리소스 측면에서 그나마 나은 Loki를 사용해 보았지만 그럼에도 리소스가 부족해 Pending되는 Pod들이 많았기에 Grafana와 Prometheus만을 사용해서 Monitoring 환경을 구성해보았다. Prometheus Prometheus는 시계열 데이터(Metric)를 수집, 저장, 쿼리 및 경고를 생성하는 오픈..
2024.12.15
no image
[CI CD] 로컬 K8S 환경에서 Gitops 구축하기 (2)
개요  지난 포스팅에 이어서 Jenkins CI 부분 추가 작업과 Argo cd 작업을 마무리하고자 한다.  최종적으로 완성할 Flow는 다음과 같다.  1. 개발자가 개발 환경에서 코드를 수정한 후, Github Code Repo에 변경된 코드를 push한다.2. Github Code Repo Target Branch에 변경사항이 발생했을 시 Webhook을 통해 Jenkins를 트리거한다.3. Jenkins가 Git Code Repo에서 Code를 Pull 해온 뒤 image로 Build하여 Docker Hub에 push한다.4. Jenkins가 Git Manifest Repo에 Rollout.yaml에 변경된 이미지 태크를 push한다.5. Argocd가 Auto sync를 통해 주기적으로 현재 클..
2024.12.12
no image
[CI CD] 로컬 K8S 환경에서 Gitops 구축하기 (1)
개요 GitOps는 애플리케이션과 인프라의 관리를 Git 저장소를 중심으로 빌드하고 배포하는 과정을 프로세스를 자동화한 방법론이다.  이번에 구축할 Gitops 목표 Flow는 다음 사진과 같다.   이번 포스팅에선 Jenkins를 통해 CI 과정을 완성할 예정이다. 다음과 같은 Flow로 진행된다.1. 개발자가 개발 환경에서 코드를 수정한 후, Github Repo에 변경된 코드를 push한다.2. Github Repo Target Branch에 변경사항이 발생했을 시 Webhook을 통해 Jenkins를 트리거한다.3. Jenkins가 Git repo에서 Code를 Pull 해온 뒤 image로 Build하여 Docker Hub에 push한다. Jenkins 공식 문서를 보며 Jenkins를 K8S ..
2024.12.12
no image
[Kubernetes] Kubeadm을 이용해 Local K8S 구축
개요 유데미  Certified Kubernetes Administrator (CKA) with Practice Tests 강의에서 제공되는 영상과 Vagrantfile을 이용하여 K8S를 구축하였다. 구축한 과정과 트러블 슈팅 내역을 기록하기 위해 글을 작성하였다.  강의에서 제공되는 Vagrantfile을 이용해 virtualBox에서 2 개의 Workernode와 1개의 Control plane을 생성하고 Vagrant ssh를 이용하여 node에 접속한 뒤 환경을 구축하였다.  K8S Cluster버전 1.31.3containerd, flannel 사용ubuntu 22.4 사용 아래 1번부터 5번까지의 과정은 모든 노드에서 진행해주어야 한다.1. IP Forwarding 활성화쿠버네티스의 네트워크..
2024.12.10
no image
[Terraform] AWS ALB 프로비저닝
AWS ALB란? AWS ALB(Application Load Balancer)는 AWS에서 제공하는 Elastic Load Balancing(ELB) 서비스의 한 유형으로, 주로 애플리케이션 계층(HTTP/HTTPS)에서 즉 7계층에서 작동하는 로드 밸런싱을 제공한다. ALB는 웹 애플리케이션이나 마이크로서비스 환경에서 트래픽을 효율적으로 분산하고 관리하는 데 사용된다. AWS ALB Controller란? AWS ALB Controller는 Kubernetes에서 AWS의 Application Load Balancer(ALB)를 관리하기 위해 사용하는 Kubernetes Ingress Controller이다. AWS에서 제공하는 공식 도구이며, Kubernetes Ingress 리소스를 기반으로 AL..
2024.12.09
no image
[Terraform] Karpenter 프로비저닝
Karpenter란?Karpenter는 AWS에서 제공하는 오픈소스 Kubernetes 노드 자동 스케일링 솔루션으로, 애플리케이션 워크로드의 요구 사항에 따라 클러스터의 노드를 자동으로 확장하거나 축소하는 기능을 제공한다. 기존 Kubernetes Cluster Autoscaler보다 더 빠르고 효율적으로 작동하도록 설계되었으며, 복잡한 설정 없이 동적으로 자원을 관리할 수 있다. Karpenter 특징 1. 속도와 효율성Karpenter는 워크로드에 필요한 노드를 몇 초 안에 프로비저닝할 수 있다.기존 Cluster Autoscaler가 노드 그룹을 기반으로 작동하는 반면, Karpenter는 개별 Pod의 요구사항에 따라 최적의 인스턴스를 직접 프로비저닝한다. 2. 다양한 인스턴스 선택 Amazon..
2024.12.09

OpenStack이란

 

OpenStack은 가상화된 서버, 네트워크, 스토리지를 통합 관리하여 클라우드 인프라를 구축할 수 있도록 해주는 오픈 소스 플랫폼입니다. 주로 기업 내부의 프라이빗 클라우드 환경을 구축할 때 사용됩니다. 

 

 

다음과 같은 주요 컴포넌트들이 존재합니다.

컴포넌트 설명

 

Nova 가상 머신(VM) 생성 및 관리 (컴퓨팅 자원 담당)
Neutron 네트워크 연결 설정 및 관리 (IP, 라우팅 등)
Cinder 블록 스토리지 제공 (VM용 디스크)
Glance VM 이미지 저장 및 관리
Keystone 인증과 권한 관리 (사용자 로그인 등)
Horizon 대시보드(UI) 제공
Swift 객체 스토리지 제공 (대용량 데이터 저장에 적합)
Heat 인프라 자동화 템플릿 (IaC, Infrastructure as Code)
Ceilometer 모니터링 및 사용량 통계 수집

 

모듈식 구조이기에 필요한 기능만 선택하여 사용 가능합니다.

 

프로젝트 배경

클라우드 관련 공고들을 확인하는 과정에서 private cloud에 대해서도 알게되었고 그 과정에서 오픈스택이란 것을 알게 되었습니다. K8S 환경을 직접 구축했던 것처럼 Openstack 환경도 실제로 구축해보고 이해하고자 프로젝트를 진행하게 되었습니다. 

 

Node 설정

 

실습이 진행된 호스트 PC는 위와 같습니다.  2개의 Node를 생성해서 진행하였으며 각각 Compute, Controller입니다.

리눅스 이미지는 Ubuntu 22.04.5 live-server를 사용하였고, Controller 스펙은 4 core CPU, 4 GB RAM, 40 GB Storage

Compute 스펙은  4 core CPU, 2 GB RAM, 40 GB Storage으로 진행하였습니다. 

 

Nat Network 생성

 

 

Controller Node 네트워크 설정

 

 

어댑터 2는 브리지로 호스트 네트워크 사용합니다.

 

이후 다음과 같이 netplan을 수정하고 변경된 네트워크 설정을 적용합니다. 만약 enp0s8 네트워크에 IP가 할당된다면  /etc/netplan/50으로 시작하는 파일에서 dhcp4 할당을 false로 해주면 됩니다.

IP가 할당될 경우 호스트에서 직접 ssh 접근이 불가하고 할당된 IP로 접근해야 하기에 확인이 필요합니다.

cat << EOF > /etc/netplan/00-installer-config.yaml
network:
  ethernets:
    enp0s3:
      addresses: [10.0.0.11/24]
      routes:
        - to: default
          via: 10.0.0.1
      nameservers:
        addresses: [8.8.8.8]
    enp0s8:
      dhcp4: no
      dhcp6: no
  version: 2
EOF
  
sudo netplan apply

 

이후에 포트 포워딩을 해주고 ssh 접근을 합니다.

 

 

 

Controller Node 기본 설정

  • 계정 sudo 권한 비밀번호 입력 해제
visudo
dlwpdnr213 ALL=(ALL:ALL) NOPASSWD:ALL

  • ssh 설정

virtual box 내부에선 복사 붙여넣기가 안됐기 때문에 추가적인 작업은 ssh 설정 완료 후 Mobaxterm에서 ssh 연결한 후 작업을 진행합니다.

vi /etc/ssh/sshd_config
port 7890
PasswordAuthentication yes
systemctl restart ssh
  • 미러 사이트 설정

필요 패키지들을 고속으로 설치하기 위해 카이스트에서 제공하는 국내 미러 사이트로 설정합니다.

cd /etc/apt
cp sources.list sources.list.v1
sed -i 's/http:\\/\\/kr.archive.ubuntu.com/https:\\/\\/ftp.kaist.ac.kr/g' /etc/apt/sources.list
apt update
  • 필요 유틸리티 설치 패키지 업데이트
apt install -y lrzsz net-tools zip bzip2 make gcc perl
apt upgrade -y
reboot
  • 커널 버전 자동 업데이트 금지, 보안 업데이트 자동 수행
apt-mark hold $(uname -r)
apt install unattended-upgrades
dpkg-reconfigure unattended-upgrades
  • timezone 설정

시간대를 서울로 변경합니다.

timedatectl set-timezone Asia/Seoul
timedatectl
  • nfs 설정

controller와 compute 노드 간 파일 공유를 위해 nfs를 통해 /nfs 디렉토리를 공유하도록 설정합니다. Controller가 nfs 서버 역할을 맡습니다.

apt install -y nfs-kernel-server nfs-common
mkdir -p /nfs/
chown nobody:nogroup /nfs

echo "/nfs    10.0.0.0/24(rw,all_squash,sync,no_subtree_check)" >> /etc/exports
exportfs -avr

showmount -e
  • /etc/hosts 수정
vi /etc/hosts

cp /etc/hosts /nfs/

 

Compute Node 생성

compute Node는 기존에 생성했었던 controller node를 복제하는 것에서 출발합니다.

 

 

 

  • host이름 변경
hostnamectl

sudo hostnamectl set-hostname compute
  • netplan 수정

netplan을 수정하여 compute 노드에 10.0.0.31 IP 주소를 할당하고, NAT 네트워크에 포트포워딩 규칙을 추가해줍니다.

 

 

 

  • nfs 설정

이후 compute 노드의 /nfs 디렉토리에 controller 노드의 /nfs 디렉토리를 마운트합니다

echo "10.0.0.11:/nfs	/nfs	nfs	noauto	0	0" >> /etc/fstab

mount /nfs
mount -l | grep nfs
  • 서로 간의 통신 확인

 

 

ping 또한 정상적으로 되는 것을 확인 가능합니다.

 

기본적인 노드 설정과 생성이 완료되었습니다. 오픈스택을 구축하기 위한 설정은 다음 포스팅에서 진행하겠습니다.

RHCSA 취득 후기

dlwpdnr213
|2025. 5. 23. 02:38

 

취득 배경 

 

Cloud 부트캠프가 끝난 후에 RHCSA 자격증을 따야겠다고 마음 먹었으나 취준생에겐 너무나 비싼 비용(55만원..) 그리고 타 이유들로 취득을 미뤘었습니다.

하지만 여러 차례 면접을 보면서 Linux 관련 질문이 들어왔을 때 공부가 부족함을 느꼈고 그리고 자격증으로 역량을 증명해야겠다는 생각이 들어 취득을 결정하게 되었습니다.

 

시험 준비

 

https://www.udemy.com/course/linux-redhat-certified-system-administrator-rhcsa-ex200-korean/

 

해당 강의를 보면서 공부를 진행했으나 자막이 있음에도 불구하고 인도식 영어를 알아듣는게 매우 힘들었습니다.

다른 인도 분이 진행하신 CKA 강의는 훨씬 수월했던 것을 기억하면 더욱 그랬습니다.

 

실습은 Oracle Virtual box를 통해 rhel 9 환경에서 진행했습니다. 구축 과정은 이전에 포스팅해두었습니다.

 

https://dlwpdnr213.tistory.com/category/CS/Linux

 

'CS/Linux' 카테고리의 글 목록

cloud / devops 에 관심이 있는 개발자입니다.

dlwpdnr213.tistory.com

 

이후에 덤프를 풀면서 본격적인 시험 준비를 하였습니다. 해당 자료들을 보면서 공부를 진행했습니다.

 

https://www.geuni.tech/linux/rhcsa_practice

 

RHCSA 9 연습/기출문제 (EX200) | Geuni's Blog

RHCSA 9 (EX200) 시험 대비를 위한 완벽 가이드! 네트워크 설정, YUM, SELinux, LVM, podman, systemd 등 핵심 주제별 연습 문제 및 상세 해설 제공. rd.break를 이용한 root 비밀번호 복구 방법까지 완벽 정리

www.geuni.tech

 

https://mandarindeveloper.tistory.com/2/

 

RHCSA v9 [2025년 1월] 취득 후기 및 주의사항

2025년 1월 13일, RHCSA v9을 취득했다.준비 기간 5일,사전 지식은 2년 전 리눅스 기초 수업을 1개월 들었던 정도였다. 시험 준비 기간이 왜 이렇게 짧았냐 하면...사실 1년 전 신청을 해 두고 까맣게

mandarindeveloper.tistory.com

 

 

시험 방식 및 환경

시험 방식

시험장에서 보는 방식과 개인 환경에서 보는 방식이 존재합니다.

개인 환경에서 보는 방식은 웹캠과 직접 시험 환경을 위해 USB에 운영체제를 준비해야 했으므로 양재역에 위치한 패스트레인 시험장에서 시험을 치루기로 결정하였습니다.

  • 여권 필요
  • 3시간 동안 시험 진행
  • 시험 코드와 레드햇 ID를 적어 넣는 부분이 GUI 존재하므로 확인하고 입실 필요
  • 시험 시작 전에 영어로 설문하는 부분이 존재합니다. 
  • 웹캠을 통해 영어로 감독관과 소통하며 책상 바닥 벽면 손 팔 등 요청하는 부분을 보여줘야 합니다. 
  • 위의 2 요소 때문에 시험 시작전 15분에서 20분 전에 입실해야 합니다.

시험 환경 및 예약

레드햇에서 직접 계좌이체로 결제하는 방식과 대행사(패스트레인)에서 결제하는 방식이 존재합니다.

저는 패스트레인에서 결제를 진행하였고 결제 후 하루 뒤에 유선 전화를 받고 구매를 결정지을 수 있었습니다.

결정 후에는 당일 혹은 하루 뒤에 레드햇에서 시험 예약이 완료되었으니 시험 일정을 결정해달라는 메일을 받을 수 있었습니다.

 

 

시험 결과

 

 

  • 위와 같은 형태로 점수와 합격 메일이 전송됩니다. 
  • 썸네일과 같은 형태의 뱃지는 이 메일이 전송된 후 2~3일이 지난 후에 Credly에서 다운로드가 가능했습니다.

개요

https://www.udemy.com/course/linux-redhat-certified-system-administrator-rhcsa-ex200-korean/

 

해당 강의를 보며 RHCSA 자격증 취득을 준비하려 한다. 

 

RHEL 9 버전을 사용할 것이고 지난 번 K8S 환경을 구축하면서 사용했던 Oracle Virtual box를 사용하고자 한다.

 

 

선행 과정

 

1. Redhat 회원 가입

 

ISO 이미지 파일을 다운로드 받기 위해 Redhat 회원 가입을 진행한다.

 

2. ISO 이미지 파일 다운로드

 

https://developers.redhat.com/products/rhel/download

 

Download Red Hat Enterprise Linux at no cost | Red Hat Developer

Download Red Hat Enterprise Linux at no cost. Get access to RHEL cloud ready images, ISOs, and more.

developers.redhat.com

 

해당 링크에 접근하여 ISO 이미지 파일은 다운로드 한다. 

 

 

글을 작성하는 25년 4월을 기준으론 9.5 버전이 최신이다.

 

3.  가상 머신 생성

 

다음과 같은 스펙의 가상머신을 생성한다.

 

  • RHEL 9.5 ISO 이미지 파일 사용
  • 1024Mb 메모리 사용
  • 20GB 디스크 사용
  • 브리지 네트워크 사용

 

RHEL  구축

 

0. 언어 설정

 

영어나 한국어로 언어를 설정한다.

 

다음 요소들을 해결해야 설치를 진행할 수 있다.

 

1. 네트워크 설정 및 호스트 이름 등록

 

가상머신에서 설정한 브릿지 네트워크를 활성화하고 호스트 이름을 등록한다.

 

2. 시간 설정

 

 

3. 레드햇 계정 등록

 

ISO 이미지 파일을 다운로드 받을 때 사용했던 계정과 동일하다.

 

정상 등록됐다면 다음과 같은 화면이 나온다.

 

 

4. 디스크 설정

 

자동 설정을 사용하고 가상머신을 생성할 때 만들었던 디스크를 사용한다.

 

5. 사용자, 루트 비밀번호 생성

 

 

 

 

 

6.  소프트웨어 선택

 

기본 서버를 선택한다.

 

7. 설치 진행

 

정상적으로 설정이 됐다면 다음과 같은 화면이 나오고 설치를 진행할 수 있다.

 

 

가상머신 시간과 로컬 PC의 시간이 다를 때 문제가 발생하기에 문제가 발생했다면 재부팅 후 다시 진행해야한다.

 

8. 최종 결과

 

설치를 완료한 후에 리부팅 하면 다음과 같이 RHEL 환경 구축을 완료했음을 확인 가능하다.

 

개요

지난 Cloud wave 프로젝트 때 경험하지 못한 K8S 환경에서 Monitoring 구축을 진행해보았다.  

 

UI 중심으로 빠른 시각화를 경험하고 싶고 또 리소스가 부족한 로컬 클러스터인 것을 감안하여 ELK를 사용하지 않고 Grafana와 Prometheus를 사용한 메트릭 기반의 Monitoring을 구축하였다.

 

하지만 Log 기반의 Monitoring 또한 확인하고 싶었기에 리소스 측면에서 그나마 나은 Loki를 사용해 보았지만 그럼에도 리소스가 부족해 Pending되는 Pod들이 많았기에 Grafana와 Prometheus만을 사용해서 Monitoring 환경을 구성해보았다.

 

Prometheus

 

Prometheus는 시계열 데이터(Metric)를 수집, 저장, 쿼리 및 경고를 생성하는 오픈 소스 모니터링 및 알림 시스템이다.

 

2012년 SoundCloud에서 개발되었고, 현재 CNCF(Cloud Native Computing Foundation)의 프로젝트로 관리되고 있다. Docker 환경에서도 사용되지만 Kubernetes와 같은 클라우드 네이티브 환경에서 특히 자주 사용된다.

 

특징

 

1. 시계열 데이터 (Metric) 수집

 

데이터를 metric name과 label(key-value)의 조합으로 저장하고, 고유 식별자(time series)와 타임스탬프가 포함된 값으로 구성한다.

 

2. Pull 방식의 데이터 수집

 

Prometheus는 모니터링 대상(exporter)으로부터 데이터를 Pull 방식으로 가져온다.


HTTP 기반의 /metrics 엔드포인트를 통해 데이터를 수집한다.

 

3. 다양한 Exporter 제공

 

기본 시스템 메트릭 수집용 Node Exporter.


애플리케이션 메트릭을 제공하는 Custom Exporter.


데이터베이스(MySQL, PostgreSQL 등), 메시지 브로커(RabbitMQ, Kafka) 등 다양한 서드파티 서비스에 대한 Exporter가 제공된다.

 

해당 Exporter들은 클러스터의 Node, Container, Pod들의 상세한 메트릭을 수집하고 서버로 제공한다.

 

4. PromQL (Prometheus Query Language)

 

수집한 시계열 데이터를 분석하고 시각화할 수 있는 강력한 쿼리 언어를 제공한다.

 

이 쿼리 언어는 Prometheus UI, Grafana 대시보드에서 다양한 함수와 연산자와 함께 사용되어 시계열 데이터를 시각화한다.

 

5. 알림 기능 제공

 

Alertmanager와 통합되어 경고를 관리한다. 특정 조건이 되었을 떄 Slack, Email, PagerDuty 등 다양한 채널로 알림을 전송할 수 있다.

 

구축

 

1. helm을 통해 Prometheus와 grafana을 설치할 예정이기에 homebrew를 통해 먼저 helm을 설치한다.

 

homebrew가 없었기 때문에 먼저 homebrew를 설치해주었다.

 

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/vagrant/.bashrc
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"

brew --version

 

brew install helm

helm repo update

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

 

2. monitoring 네임스페이스를 만들고, 클러스터의 해당 네임스페이스에 Prometheus Helm 차트를 install한다.

 

kubectl create namespace monitoring

helm install prometheus prometheus-community/prometheus --namespace monitoring

 

 

몇 Pod가 Pending 되는 것을 확인했고 describe를 통해 오류를 분석해보았다.

 

 

 

 

Pod에서 PVC 사용을 요하나 PV가 생성되어 있지 않기에 PVC가 Bound되지 못했기에 발생한 문제이다.

 

이전 Jenkins를 구축할 떄 사용했던 Stroage class를 그대로 사용하고 PVC의 Request를 기반으로 PV를 생성한다.

 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pm-pv1
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /mnt
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node01
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pm-pv2
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /mnt
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node02

 

 

 

정상적으로 Pod가 동작하는 것을 확인할 수 있었다.

 

3. NodePort를 통해 Prometheus에 접근한다.

 

k expose service prometheus-server --namespace monitoring --name=pm-server --type=NodePort --target-port=9090

 

 

 

Prometheus server가 띄워진 Nodeip와 NodePort Port로 접근 가능하다.

 

Grafana

 

Grafana는 다양한 데이터 소스의 데이터를 시각화하고, 대시보드를 통해 실시간 모니터링 및 분석을 할 수 있는 오픈 소스 데이터 시각화 플랫폼이다. 

 

주요 특징

 

1. 다양한 데이터 소스 지원

 

Prometheus 외에도 Graphite, Elasticsearch, InfluxDB 등 다양한 데이터베이스를 지원하여, 여러 시스템의 데이터를 통합하여 시각화할 수 있다.

 

2. 맞춤형 대시보드

 

사용자의 요구에 맞춰 다양한 패널을 활용하여 맞춤형 대시보드를 제작할 수 있다.

 

3. 높은 유연성과 확장성

 

사용자의 요구에 맞게 자유롭게 커스터마이징이 가능하며, 다양한 플러그인을 통해 기능을 확장할 수 있다.

 

구축

1. helm repo에 grafana를 추가하고 monitoring 네임스페이스에 grafana를 설치한다.

 

helm repo add grafana https://grafana.github.io/helm-charts
helm install grafana grafana/grafana --namespace monitoring

 

 

2. 다음 명령어를 통해 grafana admin password를 확인한다.

 

kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

 

3. NodePort를 생성해 grafana server에 접근한다.

 

kubectl expose service grafana --namespace monitoring --type=NodePort --target-port=3000 --name=grafana-service

 

 

 

 

4. Home-> DATA SOURCES-> Prometheus를 클릭하여 이동한 후, Connection에 prometheus server의 URL을 입력하여 data source로 prometheus를 추가한다.

 

 

 

5. 대시보드를 생성한.

 

https://grafana.com/grafana/dashboards/

 

Grafana dashboards | Grafana Labs

No results found. Please clear one or more filters.

grafana.com

 

위 사이트에서 본인이 사용하고 싶은 대시보드를 고른 뒤 ID를 확인하여 Import하여 사용하면 된다.

 

 

대시보드 예시

1. 1860

 

https://grafana.com/grafana/dashboards/1860-node-exporter-full/

 

Node Exporter Full | Grafana Labs

Nearly all default values exported by Prometheus node exporter graphed. Only requires the default job_name: node, add as many targets as you need in ‘/etc/prometheus/prometheus.yml’. - job_name: node static_configs: - targets: ['localhost:9100'] Recomm

grafana.com

 

 

2. 8171

 

https://grafana.com/grafana/dashboards/8171-kubernetes-nodes/

 

Kubernetes Nodes | Grafana Labs

Kubernetes Nodes for node exporter 0.16+ (via Prometheus) It includes a host selection which will show you: CPUMemoryDisk UsageNetwork TX/RX Note that this dashboard makes no distinction between node types (master / noagents).

grafana.com

 

 

3. 315

 

https://grafana.com/grafana/dashboards/315-kubernetes-cluster-monitoring-via-prometheus/

 

Kubernetes cluster monitoring (via Prometheus) | Grafana Labs

 

grafana.com

 

 

4. 13770

 

https://grafana.com/grafana/dashboards/13770-1-kubernetes-all-in-one-cluster-monitoring-kr/

 

1 Kubernetes All-in-one Cluster Monitoring KR | Grafana Labs

쿠버네티스 올인원 모니터링 대시보드 제작자 관련 정보 중요한 알림 이 대시보드는 ?컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커 책에서 사용된 대시보드입니다. 따라서 ?컨테이너 인

grafana.com

 

 

5. 14282

 

https://grafana.com/grafana/dashboards/14282-cadvisor-exporter/

 

Cadvisor exporter | Grafana Labs

Simple set of several graphs. Just for getting Cadvisor’s metrics only Set includes: CPU Usage by containerMemory UsageMemory CachedReceived Network TrafficSent Network Traffic And a table with info: LabelWorking dirServiceRegistry ImageInstanceNameRunni

grafana.com

 

 

 

회고

이전 프로젝트에서 팀원이 구축한 모니터링을 통해 멀티 리전을 테스트 해본 경험은 있지만, 직접 구축을 하진 않았었기에 이번에 직접 구축해볼 수 있어서 기쁘다.

 

오픈소스인 Prometheus와 Grafana는 오픈소스로서 다양한 커뮤니티가 활성화 되어있고 자료들도 많아 다양한 문제 해결을 위한 솔루션과 지식을 쉽게 얻을 수 있었다. 

 

또 사용자가 자유롭게 커스터마이징을 하여 본인의 환경에 맞게 원하는 정보를 시각화 할 수 있고 또 그것을 기반으로 알림을 받는다면 큰 장점이 될 것이라 생각했다.

 

Prometheus와 Grafana에 대해 깊이 학습한 후 사용하지 않고 이미 완성되어있는 대쉬보드 템플릿을 사용하였기에 구축한 것을 확인하는 과정에서 끝났지만, Prometheus의 PromQL을 학습하여 익숙해진다면 여러 메트릭을 직접 수집하고 대시보드 또한 직접 커스터마이징 할 수 있을 것이라 생각한다.

 

개요

 

 

지난 포스팅에 이어서 Jenkins CI 부분 추가 작업과 Argo cd 작업을 마무리하고자 한다. 

 

최종적으로 완성할 Flow는 다음과 같다. 

 

1. 개발자가 개발 환경에서 코드를 수정한 후, Github Code Repo에 변경된 코드를 push한다.

2. Github Code Repo Target Branch에 변경사항이 발생했을 시 Webhook을 통해 Jenkins를 트리거한다.

3. Jenkins가 Git Code Repo에서 Code를 Pull 해온 뒤 image로 Build하여 Docker Hub에 push한다.

4. Jenkins가 Git Manifest Repo에 Rollout.yaml에 변경된 이미지 태크를 push한다.

5. Argocd가 Auto sync를 통해 주기적으로 현재 클러스터와 Mainfest Repo의 상태 차이를 확인한다.

6. Argocd가 차이를 발견하면 Github Manitfest Repo와 동기화해 변경사항을 반영한다.

7. 변경된 이미지를 pull해 새로 배포한다.

 

이번 포스팅에선 4번부터 7번 과정을 진행할 예정이다. 

 

Jenkins 추가 작업

 

4번 작업을 진행하기 위해 Jenkinsfile을 수정하고 추가적인 작업을 진행해주었다.

 

Jenkinsfile 수정

pipeline {
    agent any

    environment {
        DOCKER_IMAGE = 'dlwpdnr213/gitops-test'
        GIT_COMMIT_HASH = ''
        TAG = ''
        JENKINS_REPO = 'https://github.com/Leejeuk213/gitops_cicd.git'
        ARGOCD_REPO = 'https://github.com/Leejeuk213/argocd_yaml.git'
    }

    stages {
        stage('Initialize') {
            steps {
                script {
                    GIT_COMMIT_HASH = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
                    TAG = "build-${GIT_COMMIT_HASH}"
                }
            }
        }

        stage('Clone Repository') {
            steps {
                git credentialsId: 'jenkins', branch: 'main', url: JENKINS_REPO
            }
        }

        stage('Build Docker Image') {
            steps {
                script {
                    sh "docker build -t ${DOCKER_IMAGE}:${TAG} ."
                }
            }
        }

        stage('Push Docker Image') {
            steps {
                script {
                    withDockerRegistry([credentialsId: 'docker', url: 'https://index.docker.io/v1/']) {
                        sh "docker push ${DOCKER_IMAGE}:${TAG}"
                    }
                }
            }
        }

        stage('Update Argo CD Configuration') {
            steps {
                script {
                    dir('argocd_yaml') {
                        git credentialsId: 'jenkins', branch: 'main', url: ARGOCD_REPO

                        sh """
                        sed -i 's|image: .*|image: ${DOCKER_IMAGE}:${TAG}|' rollout.yaml
                        """

                        sh """
                        git add rollout.yaml
                        git commit -m "Update image tag to ${TAG}"
                        git push origin main
                        """
                    }
                }
            }
        }
    }

    post {
        success {
            echo 'Pipeline completed successfully!'
        }
        failure {
            echo 'Pipeline failed!'
        }
    }
}

 

Build 오류 해결 

그 후 새로 Build를 진행할 떄 다음과 같은 오류가 발생했다.

 

Jenkins container가 git push를 수행할 때 git user와 비밀번호를 찾지 못해 발생하는 문제라 확인됐고 다음과 같은 작업을 통해 해결했다.

 

kubectl exec -it {jenkins pod name} -n jenkins -- /bin/bash

cd /var/jenkins_home/workspace/{pipeline에서 clone한 깃 레포 코드}

git config --global credential.helper store

git push origin main

 

git config --global credential.helper store 커맨드를 통해 영구 설정하겠다는 옵션을 설정하고 git으로부터 clone해온 디렉토리에서 push 명령어를 실행한다.

 

그럴 경우 user명과 비밀번호를 입력할 것을 요청받고 정상적으로 입력할 경우 push가 되고  ~/.git-credentials 아래에 비밀번호와 user 명이 영구적으로 저장이 된다.

 

이후 build에선 더 이상 오류가 발생하지 않는다.

 

 

위와 같이 build-{git commit hash}로 이미지 태그가 할당되게 된다.

 

추가 리소스 다운로드

 

Argo rollout

 

Blue Green 배포를 Test하기 위해 Argo rolleout을 배포한다.

kubectl create namespace argo-rollouts

# apply argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

# install kubectl plugin for argo rollout & 설치 확인
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
sudo install -o root -g root -m 0755 kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
kubectl argo rollouts version

 

Ingress controller

service 접근을 Ingress로 진행하기 위해 Nginx Ingress controller를 구축한다.

 

# kubeadm으로 구축한 경우, label을 controlplane에 추가해야 ingress-controller가 controlplane 노드에 생성될 수 있습니다.
kubectl label no controlplane ingress-ready=true

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

 

Mertic-server

HPA를 사용하기 위해 Metric-server를 구축한다. 

 

wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

 

component.yaml을 다운로드 받고 수정한다.

 

 

Readness probe 오류가 발생하지 않게끔 --kubelet-insecure-tls 옵션을 켜준다. 보안적으로 취약점이 생기지만 로컬에서 테스트를 진행하기에 켜도 문제가 없다.

 

port를 10250이 아닌 port로 바꿔준다. 현재 사용중인 port가 아니면 된다. 10250은 kubelet에서 사용하는 port임으로 수정하지 않을 경우 오류가 발생한다. 

args안의 port 뿐 만 아닌 svc에 있는 port 또한 바꿔야 한다.

 

 

또 hostNetwork 옵션을 사용해야 한다. 사용하지 않을 경우 Error from server (ServiceUnavailable): the server is currently unable to 오류가 발생한다. 

 

Argocd

 

Argocd 구축

 

# argocd namespace 생성
kubectl create namespace argocd

# apply argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

VERSION=$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
sudo curl --silent --location -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-linux-amd64
sudo chmod +x /usr/local/bin/argocd

kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "NodePort"}}'

 

공식문서와 달리 Argocd를 로드밸런서가 아닌 NodePort로 열어 Local에서 접근할 수 있게끔 한다.

 

 

Argocd 초기 비밀번호 획득

다음 명령어를 통해 초기 비밀번호를 얻고 Argocd에 접근한다. 

# argocd 초기 비밀번호 확인
ARGO_PWD=`kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d`
echo $ARGO_PWD

 

 

Argocd Git repo 연결

argocd web console -> Settings -> Repositories -> Connect Repo를 통해 설정한다.

 

Private Repo를 사용할 경우 Jenkins에서 사용한 Github token을 사용하고 User 이름을 명시해야 하지만 Public Repo로 진행할 경우 생략해도 괜찮다.

 

사용할 Git Repo URL을 입력하고 연결을 완료한다.

 

Argocd Application 생성

 

Application -> New app을 통해 새로운 Applicaiton을 생성한다.

 

 

원하는 App 이름을 적고 Sync Policy로 Manuel 혹은 Auto sync를 택한다.

 

Manuel을 사용자가 Console에서 직접 Sync하는 것이고 Auto sync는 3분 주기로 Argocd가 연결된 Git repo에서 차이점을 비교한다.

 

 

방금 연결한 Git이 정상적으로 연결되었다면 list에 나오게 된다.

 

list에 나온 Git repo를 연결한다.

 

다음과 같이 Kubernetes 연결 설정을 하고 생성한다.

 

Argocd Test

 

첫 Sync

 

정상적으로 완성될 경우 다음과 같은 화면이 나온다. 

 

Sync를 눌러 첫 Sync를 진행한다.

 

오류 없이 Manifest 파일을 작성했을 경우 다음과 같이 모든 리소스가 생성되는 것을 확인할 수 있다.

 

 

미리 만들어둔 Ingress Controller를 통해 Ingress가 작동되는 것을 UI로 확인할 수 있다.

 

 

그 후 ingress controller가 뜬 node로 접속햇을 떄 Fastapi가 잘 작동하는 것을 확인할 수 있다.

 

 

Blue Green 배포 테스트

 

전체적인 CI CD가 잘 작동하는 것을 확인하고 Blue Green 전략 테스트를 위해 Fastapi root 메시지를 V2로 바꿔보겠다.

 

1. Local에서 코드 변경 후 push한다.

 

2. Jenkins에서 Webhook 트리거를 통해 자동으로 CI 작업을 진행한다.

 

 

3. Git Manifest Repo에 변경된 이미지 태그로 Push 된다.

 

4. Argocd에서 현재 클러스터와의 차이를 확인하고 동기화 한다.

 

 

 

5. 최종 적용을 위해 관리자가 Console에서 Promote Full을 클릭해 변경을 적용한다.

 

 

변경된 Pod로 Ingress 및 Service들이 연결 된  것을 확인 가능하다. 

 

그 후 버전이 바뀐 것을 확인할 수 있다.

 

Rollback Test

 

새로 배포한 버전이 오류가 났다는 가정하에 Rollback을 진행해보겠다.

 

1. History & Rollback에서 이전 배포를 찾은 뒤 Rollback을 진행한다.

 

2. 그 후 Rollout에서 Prompt Full을 클릭한다. 

 

 

3. 이전 버전으로 돌아간다.

 

 

 

회고

 

이전에 진행했던 프로젝트에서 K8S 환경을 사용해봤지만 Jenkins와 Argocd를 이용한 gitops를 직접 구축하진 못하였고 또 Github Actions 경험은 있지만 다른 CI CD Tool은 사용해본 경험이 없었었다. 

그렇기에 이번에 Local K8S에 간단하게라도 Gitops를 구축해볼 수 있어서 기쁘다.

 

Gitops에 대한 개념을 조금이나마 더 알게 된 것 같고 CKA 자격증 취득으로 그치지 않고 K8S 환경에 대한 공부도 된 것 같다.

 

 

 

 

 

 

'DevOps > CI CD' 카테고리의 다른 글

[CI CD] 로컬 K8S 환경에서 Gitops 구축하기 (1)  (0) 2024.12.12

개요

 

GitOps는 애플리케이션과 인프라의 관리를 Git 저장소를 중심으로 빌드하고 배포하는 과정을 프로세스를 자동화한 방법론이다. 

 

이번에 구축할 Gitops 목표 Flow는 다음 사진과 같다. 

 

 

이번 포스팅에선 Jenkins를 통해 CI 과정을 완성할 예정이다. 다음과 같은 Flow로 진행된다.

1. 개발자가 개발 환경에서 코드를 수정한 후, Github Repo에 변경된 코드를 push한다.

2. Github Repo Target Branch에 변경사항이 발생했을 시 Webhook을 통해 Jenkins를 트리거한다.

3. Jenkins가 Git repo에서 Code를 Pull 해온 뒤 image로 Build하여 Docker Hub에 push한다.

 

Jenkins

 

공식 문서를 보며 Jenkins를 K8S 환경에 올려보았다.

 

https://www.jenkins.io/doc/book/installing/kubernetes/

 

Kubernetes

Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software

www.jenkins.io

 

 

namespace.yaml

apiVersion: v1 
kind: Namespace
metadata:
  name: jenkins

 

공식문서에서는 namespace가 jenkins가 아닌 devops-tools이기에 jenkins라는 이름으로 사용할 경우 이후에 나오는 모든 yaml파일에 들어가는 metadata.namespace를 jenkins로 바꿔 줄 필요가 있다.

 

serviceAccount.yaml

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins-admin
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-admin
  namespace: jenkins

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins-admin
subjects:
- kind: ServiceAccount
  name: jenkins-admin
  namespace: jenkins

 

모든 RBAC 요소를 jenkins-admin 이름으로 통일한다.

 

클러스터 구성 요소를 관리할 수 있는 모든 권한이 있는 ClusterRole을 먼저 만들고, 사용하기 위한 ServiceAccount와 ServiceAccount에 ClusterRole을 연결하기 위한 ClusterRoleBinding을 생성해준다.

 

Volume.yaml

 

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv-volume
  labels:
    type: local
spec:
  storageClassName: local-storage
  claimRef:
    name: jenkins-pv-claim
    namespace: jenkins
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  local:
    path: /mnt
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - {worker-node}

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pv-claim
  namespace: jenkins
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

 

 

볼륨의 경우 직접 생성한 local storage class를 사용한다.
주의해야 할 점은 {worker-node} 부분을 직접 사용하는 worker node에 이름으로 바꿔야 한다는 것이다.
이 과정에서 생성되는 PV에는 Jenkins data가 기록되며 node가 삭제 될 경우 data가 삭제되게 된다.
local storage class를 사용하고 pv의 기본 정책인 Retain을 사용하기에 pv가 삭제되어도 바로 데이터가 삭제되지는 않는다.
또 pvc를 생성하는데 여기서 생성하는 pvc는 이후에 생성할 deployment에서 사용된다.

 

deployment.yaml

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins-server
  template:
    metadata:
      labels:
        app: jenkins-server
    spec:
      securityContext:
        fsGroup: 1000
        runAsUser: 1000
      serviceAccountName: jenkins-admin
      containers:
        - name: jenkins
          image: jenkins/jenkins:lts
          resources:
            limits:
              memory: "1.5Gi"
              cpu: "1000m"
            requests:
              memory: "500Mi"
              cpu: "500m"
          ports:
            - name: httpport
              containerPort: 8080
            - name: jnlpport
              containerPort: 50000
          livenessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 90
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home
            - name: docker-socket
              mountPath: /var/run/docker.sock
            - name: docker-bin
              mountPath: /usr/bin/docker
      volumes:
        - name: jenkins-data
          persistentVolumeClaim:
            claimName: jenkins-pv-claim
        - name: docker-socket
          hostPath:
            path: /var/run/docker.sock
            type: Socket
        - name: docker-bin
          hostPath:
            path: /usr/bin/docker
            type: File

 

선행 과정

 

Jenkins pipeline에서 build할 때 docker를 사용하기 위해서 docker socket과 docker bin 파일을 hostPath를 통해 jenkins 컨테이너에 넣어준다. 

 

작업 이전에 모든 노드에서 docker를 설치한 후 service를 활성화 해준 뒤, sudo chmod 666 /var/run/docker.sock로 접근 권한을 허용해줘야 된다.  

 

해당 권한 작업은 node가 재부팅될 때마다 해야되며 하지 않는다면 오류가 발생할 수 있다.

 

Service.yaml

 

apiVersion: v1
kind: Service
metadata:
  name: jenkins-service
  namespace: jenkins
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/path:   /
      prometheus.io/port:   '8080'
spec:
  selector:
    app: jenkins-server
  type: NodePort
  ports:
    - port: 8080
      name: tcp
      targetPort: 8080
      nodePort: 32000
    - name: jnlpport
      port: 50000
      targetPort: 50000

 

 

NodePort를 32000으로 서비스를 생성한다. http://<<worker - node ip>:32000 으로 접속할 수 있다.  jnlport는 Cloud 설정을 하기 위해 열어둔다.
(설정만 할 뿐 실제로 사용하지는 않기 때문에 따라하지 않으셔도 됩니다.)
 

Jenkins 설정

 

생성 확인 및 로그인

k logs {jenkins pod} -n jenkins를 통해 초기 비밀번호를 얻을 수 있다. 

 

다음과 같은 log에 비밀번호가 적혀있고 직접 exec를 통해 들어간 뒤 cat /var/jenkins_home/secrets/initialAdminPassword를 통하여서도 확인할 수 있다.

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

dab6423296a64832a422e252107711ca

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************

 

 

해당 화면에 비밀번호를 입력하고 로그인한다.

 

 

그 후 suggestd option을 클릭해 plugin을 다운받는다. 

오류가 나서 못받는 plugin이 존재할 수도 있는데 수동으로 다운 받아도 괜찮다.

 

 

그 후 계속해서 사용할 admin user를 생성한다.

 

Jenkins github 연동

 

연동 과정은 해당 블로그를 보며 진행하였다.

 

https://velog.io/@rungoat/CICD-Jenkins와-GitHub-연동하기

 

[CI/CD] Jenkins와 GitHub 연동하기

Jenkins와 GitHub 연동하기

velog.io

 

작성자 분꼐서 상당히 자세하게 적어주셨기에 해당 부분을 그대로 따라갔고 변경한 부분만 적도록 하겠다.

 

Webhook을 하기 위해선  공인 ip가 필요하나 제목에서부터 알 수 있듯이 로컬에서 K8S를 실행하였기 때문에 모든 Node들이 사설 ip일 수 밖에 없다. polling 방식으로도 jenkins를 사용할 수 있겠으나 그러기엔 아쉬워 Ngrok을 통해 공인 IP를 발급받고 Webhook 설정을 해주었다.

 

Ngrok 설정

마찬가지로 공식문서를 보며 진행하였다.

 

https://dashboard.ngrok.com/get-started/setup/linux

 

ngrok - Online in One Line

 

dashboard.ngrok.com

 

모든 작업은 Jenkins가 올려진 Pod에서 진행해야 한다. 그래야 해당 노드 IP의 Port로 Open 해 줄 수가 있다.

 

Open하는 과정은 상당히 쉬우며 Ngrok 회원 가입을 한 뒤 아래 명령어를 그대로 사용하면 된다.

개인 계정에 고유 발급된 Token을 사용하면 된다.

Port는 Jenkins NodePort인 32000번을 열어주도록 하며 다른 Port를 사용했을 경우 변경해주면 된다.

curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
	| sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null \
	&& echo "deb https://ngrok-agent.s3.amazonaws.com buster main" \
	| sudo tee /etc/apt/sources.list.d/ngrok.list \
	&& sudo apt update \
	&& sudo apt install ngrok
    
    ngrok config add-authtoken $YOUR_AUTHTOKEN
    
    ngrok http $PORT_NUMBER

 

정상적으로 실행됐다면 다음과 같은 결과를 얻을 수 있다.

 

 

그 후 Jenkins에서 프록시 설정과 Webhook 설정을 생성된 url로 바꿔준다. 

 

 

 

Ngrok 무료 버전을 사용하였기 때문에 해당 과정은 Ngrok이 꺼질 때마다 반복해야 한다.

 

Pipeline 생성

 

1. 원하는 이름으로 pipeline을 생성

 

2. Github repo 링크 연결

 

 

3. Github hook trigger 세팅

 

4. Token 연결 후 Github Repo Target Branch 연결

 

 

5. Jenkins 파일 위치 명시

 

 

Jenkins file

 

pipeline {
    agent any
    environment {
        DOCKER_IMAGE = 'dlwpdnr213/gitops-test'
        DOCKER_TAG = 'latest'
    }
    stages {
        stage('Clone Repository') {
            steps {
                git credentialsId: 'jenkins',branch: 'main', url: 'https://github.com/Leejeuk213/gitops_cicd.git'
            }
        }
        stage('Build Docker Image') {
            steps {
                script {
                    sh 'docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} .'
                }
            }
        }
        stage('Push Docker Image') {
            steps {
                script {
                    withDockerRegistry([credentialsId: 'docker', url: 'https://index.docker.io/v1/']) {
                        sh 'docker push ${DOCKER_IMAGE}:${DOCKER_TAG}'
                    }
                }
            }
        }
    }
    post {
        success {
            echo 'Pipeline completed successfully!'
        }
        failure {
            echo 'Pipeline failed!'
        }
    }
}

 

 

결과

다음과 같이 빌드가 끝난 후 초록색 체크 표시가 나오며 Docker hub에 업로드가 됐으면 성공이다.

 

 

트러블 슈팅

Webhook 연결이 끝나고 첫 빌드를 시작할 때 다음과 같은 오류를 발견했다.

 

 

해당 블로그를 통해 오류를 해결했으며 자세한 설정 과정은 위 deployment.yaml 부분에 적어놓았다.

https://froggydisk.github.io/21th-post/

 

[Jenkins] 젠킨스에서 도커 이미지를 빌드할 때 발생하는 이슈들 | ./workspace

This is for frogs in the world.

froggydisk.github.io

 

Jenkins 컨테이너에서 docker를 사용하기 위해 공식문서와 여러 블로그를 찾아보았고 DinD DooD 방식이 있다는 것을 알게되었다.

 

간단하게 DinD는 Jenkins 컨테이너 내부에 새로운 Docker Container를 만드는 것으로 일종의 Multi container 형식으로 사용하는 방식이라 할 수 있다.

 

반면에 DooD는 Jenkins 컨테이너에 Host Docker container를 공유하는 방식이다.

 

DinD를 여러 설정을 바꿔가며 수십 차례 시도해봤지만 전부 해결이 되지는 않았고 위 블로그를 통해 알게 된 방법으로 docker bin 파일과 socket을 Jenkins deployment를 생성할 때 전부 mount 하는 Dood 방식을 택했더니 놀랍게도 됐다. 

 

 결국 41번의 시도 끝에 성공해서 기분이 좋다.

 

 

'DevOps > CI CD' 카테고리의 다른 글

[CI CD] 로컬 K8S 환경에서 Gitops 구축하기 (2)  (2) 2024.12.12

개요

 

유데미  Certified Kubernetes Administrator (CKA) with Practice Tests 강의에서 제공되는 영상과 Vagrantfile을 이용하여 K8S를 구축하였다.

 

구축한 과정과 트러블 슈팅 내역을 기록하기 위해 글을 작성하였다.

 

 

강의에서 제공되는 Vagrantfile을 이용해 virtualBox에서 2 개의 Workernode와 1개의 Control plane을 생성하고 Vagrant ssh를 이용하여 node에 접속한 뒤 환경을 구축하였다.

 

 

K8S Cluster

  • 버전 1.31.3
  • containerd, flannel 사용
  • ubuntu 22.4 사용

 

아래 1번부터 5번까지의 과정은 모든 노드에서 진행해주어야 한다.

1. IP Forwarding 활성화

쿠버네티스의 네트워크 플러그인(CNI, 예: Flannel, Calico 등)은 여러 노드 간 패킷 전달 및 포워딩을 전제로 설계되었기 때문에 사전에 몇 개의 설정이 필요하다. 

 

먼저 IPV4 Forwarding을 활성화 해준다.

# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF

# Apply sysctl params without reboot
sudo sysctl --system

 

sysctl net.ipv4.ip_forward

 

위 명령어의 결과가 1이면 활성화 된 것이다.

 

 

2. br_netfilter 활성화

 

br_netfilter 모듈이 없으면 브리지 네트워크를 통해 전달되는 패킷이 iptables 규칙을 적용받지 않게 되어 네트워크 정책이 올바르게 작동하지 않을 수 있다.

 

다음과 같은 명령어로 br_netfilter 모듈을 활성화하고 추가적인 설정을 한다.

 

sudo modprobe br_netfilter

sudo sysctl net.bridge.bridge-nf-call-iptables=1
sudo sysctl net.bridge.bridge-nf-call-ip6tables=1

echo "net.bridge.bridge-nf-call-iptables=1" | sudo tee -a /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

echo "br_netfilter" | sudo tee /etc/modules-load.d/br_netfilter.conf

 

3. Container Runtime 설치

 

Kubernetes와 같은 오케스트레이션 시스템에서 컨테이너를 실행하려면, 컨테이너 런타임이 필수적으로 필요하다. 

 

 

  • Docker:
    • 가장 널리 사용되는 컨테이너 런타임으로, 컨테이너의 빌드, 배포, 실행을 위한 도구를 제공한다.
  • containerd:
    • Docker에서 분리된 런타임으로, 컨테이너의 실행, 이미지 관리 등을 담당, Kubernetes와 함께 사용할 수 있다.
  • CRI-O:
    • Kubernetes와의 호환성을 중시하는 경량화된 컨테이너 런타임으로 Docker의 대신 Kubernetes 클러스터에서 컨테이너를 실행하는 데 사용된다.

 

이 글에서는 containerd를 Container Runtime으로 사용하였다.


https://docs.docker.com/engine/install/ubuntu/

 

Ubuntu

Jumpstart your client-side server applications with Docker Engine on Ubuntu. This guide details prerequisites and multiple methods to install Docker Engine on Ubuntu.

docs.docker.com

 

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

#  Install containerd
sudo apt-get install containerd.io

 

 

systemctl status containerd

 

 

위 명령어로 실행 확인 가능하다. 

 

 

4. Cgroup driver 설정

cgroupfs 드라이버는 kubelet의 기본 cgroup 드라이버이다. 

 

cgroupfs 드라이버가 사용될 때, kubelet과 컨테이너 런타임은 직접적으로 cgroup 파일시스템과 상호작용하여 cgroup들을 설정한다.

 

sudo su -c "containerd config default > /etc/containerd/config.toml"

sudo vi /etc/containerd/config.toml

 

vi 에디터를 통해 containerd가 systemd의 cgroup 관리 기능을 사용할 수 있도록 해당 부분을 수정해준다.

 

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

 

sudo systemctl restart containerd

 

그 후에 containerd를 재시작한다.

 

5. kubeadm, kubelet, kubectl 설치

 

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

 

Creating a cluster with kubeadm

Using kubeadm, you can create a minimum viable Kubernetes cluster that conforms to best practices. In fact, you can use kubeadm to set up a cluster that will pass the Kubernetes Conformance tests. kubeadm also supports other cluster lifecycle functions, su

kubernetes.io

 

sudo apt-get update

# apt-transport-https may be a dummy package; if so, you can skip that package
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

sudo systemctl enable --now kubelet

 

 

6. kubeadm init

 kubernetes에서 pod-network-cidr default 값이 10.244.0.0/16이기에 추가적인 설정을 피하려면 default 값을 사용해준다. 

 

ip address값은 ip add 명령어를 통해 확인할 수 있으며 동일한 과정을 따라왔다면 enp0s8이 해당 값이 되겠다.

 

 

kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address={control plane node ip}

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

 

kubectl get node, po, ns 어떤 명령으로도 정상 동작을 확인할 수 있다.

 

 

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

sudo kubeadm join 172.30.1.96:6443 --token udr7l0.hu1o5801ove1jnns \
        --discovery-token-ca-cert-hash sha256:d0f0941ac6c28bbf051d552358d8260b7ed1f7c0a2dceb48f2ec80f31799a26e

 

정상적으로 init이 성공하였다면 위와 같이 결과가 나올텐데 'sudo kubeadm join {controlplane ip}:6443 -token {token} 
--discovery-token-ca-cert-hash sha256:{hash} ' 해당 내용을 기록해두었다가 후에 worker node에서 join할 때 사용해야 한다.

 

7. Network cni 설치

 

https://github.com/flannel-io/flannel#deploying-flannel-manually

 

GitHub - flannel-io/flannel: flannel is a network fabric for containers, designed for Kubernetes

flannel is a network fabric for containers, designed for Kubernetes - flannel-io/flannel

github.com

 

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

 

다음 명령어를 통해 실행하며 정상적으로 실행이 되었다면 아래와 같은 결과를 얻을 수 있다.

 

만약 이와 같이 error, crashloopbackoff가 발생한다면 1~4번까지의 단계 중 안한 것이 있는지 체크를 해야 한다. 

 

나 또한 구축하던 도중 아래와 같은 오류를 확인했고 2번 과정을 해주었더니 정상적으로 실행이 되었다.

 

8.  worker node 추가

 

kubectl 명령어가 길기에 alias를 통해 축약해서 사용하겠다.

alias k='kubectl'

 

앞서 복사해둔 명령어로 정상적으로 조인이 되었다면 다음과 같이 모든 node들이 ready인 것을 확인할 수가 있다.

 

 

만약 Not Ready 상태의 노드가 있다면 해당 노드에서 sudo systemctl restart kubelet을 실행하거나, flannel이 정상 작동중인지 확인해본다.

 

정상 작동 확인

 

kubectl run nginx --image=nginx

 

정상적으로 nginx pod가 worker node 2에 배치가 된 것을 확인할 수 있다.

 

트러블 슈팅

dns와 flannel 정상 작동하지 않는 경우

 

control plane에서 각 worker node 위의 뜬 pod 간 통신이 안되고 pod들이 coredns를 통해 dns 시스템에 접근하지 못하는 문제가 발생함 

 

 

node에 ip가 2개 있었는데 더 작은 ip인 enp0s3가 모두 같아서 생긴 문제라 해석했다.

 

 

아래와 같은 명령어로 vi editor로 들어간 다음 --node-ip={구분 가능한 노드 ip}를 추가한다.

sudo vi /var/lib/kubelet/kubeadm-flags.env

 

그 후 flannel 데이터와 pod를 삭제한 후 다시 생성한다. 

'DevOps > Kubernetes' 카테고리의 다른 글

Kubernetes 외부 ETCD Backup and Restore  (1) 2024.10.27
Kubernetes 내부 ETCD Backup and Restore  (0) 2024.10.26
Kubernetes Cluster Upgrade  (0) 2024.10.24
Kubernetes Drain, Cordon and Uncordon  (0) 2024.10.23
Kubernetes InitContainer  (0) 2024.10.23

AWS ALB란?

 

AWS ALB(Application Load Balancer)는 AWS에서 제공하는 Elastic Load Balancing(ELB) 서비스의 한 유형으로, 주로 애플리케이션 계층(HTTP/HTTPS)에서 즉 7계층에서 작동하는 로드 밸런싱을 제공한다.

 

ALB는 웹 애플리케이션이나 마이크로서비스 환경에서 트래픽을 효율적으로 분산하고 관리하는 데 사용된다.

 

AWS ALB Controller란?

 

AWS ALB Controller는 Kubernetes에서 AWS의 Application Load Balancer(ALB)를 관리하기 위해 사용하는 Kubernetes Ingress Controller이다.

 

AWS에서 제공하는 공식 도구이며, Kubernetes Ingress 리소스를 기반으로 ALB를 자동으로 생성하고 관리한다.

 

AWS ALB Controller 사용 이유

 

앞에서 말했듯이 Application Load Balancer를 사용하기 위해 Application Load Balancer controller가 필요하다.

 

프로젝트에서 MSA 도입을 위해 Istio 서비스 메쉬가 필요했고 또 DR을 위한 multi region을 구현하기 위해 Global Accelerator가 필요했다.

 

해당 서비스들을 사용하기 위해선 Application Load Balancer의 7계층 접근이 필요했고 Application Load Balancer controller를 Pod로 띄워야만 했다.

 

해당 과정 또한 Terraform으로 자동화를 한다면 매우 좋을 것이라 생각했고 AWS ALB Controller를 사용하기로 결정하였다.

 

Nginx Application Load Balancer controller가 오픈소스로서 가장 많이 사용되지만 EKS 환경에서 구축하기 때문에 AWS ALB Controller를 사용하였다.

 

Terraform code

 

resource "kubernetes_service_account" "alb_controller" {
  metadata {
    name      = var.alb_chart.name
    namespace = var.alb_chart.namespace

    annotations = {
      "eks.amazonaws.com/role-arn" = module.alb_controller_irsa.iam_role_arn
    }
  }
}

resource "helm_release" "alb_controller" {
  namespace  = var.alb_chart.namespace
  repository = var.alb_chart.repository
  name    = var.alb_chart.name
  chart   = var.alb_chart.chart
  version = var.alb_chart.version
  
  set {
    name  = "clusterName"
    value = local.eks_cluster_info.cluster_name
  }
  set {
    name  = "serviceAccount.create"
    value = "false"
  }
  set {
    name  = "serviceAccount.name"
    value = kubernetes_service_account.alb_controller.metadata.0.name
  }
  set {
    name  = "region"
    value = local.eks_cluster_info.region
  }
  set {
    name  = "vpcId"
    value = module.vpc.vpc_id
  }
  depends_on = [kubernetes_service_account.alb_controller]
}

module "alb_controller_irsa" {
  source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"

  role_name = "${local.eks_cluster_info.cluster_name}-${var.alb_chart.name}"

  attach_load_balancer_controller_policy = true

  oidc_providers = {
    one = {
      provider_arn               = module.eks.oidc_provider_arn
      namespace_service_accounts = ["kube-system:${var.alb_chart.name}"]
    }
  }
}

 

최종 아키텍처

 

앞 포스팅들(Karpenter, VPC, Bastion, EKS)을 포함해 Terraform으로 구축한 최종 아키텍처는 다음과 같다.

 

 

후기 

 

프로젝트에서 Terraform을 이용한 EKS 환경 구축을 딤당하며 배운 기술들(Terraform, AWS, Network, Kubernetes)을 제대로 활용한 것 같다는 생각이 들어서 뿌듯했고 또 많은 복습을 할 수 있었다.

 

이 경험을 살려 다른 프로젝트에서 Cloud 환경을 구축해야 하는 일이 있다면 이번처럼 Terraform을 사용할 것이고 코드를 Custom해서 빠르게 작업을 처리하고자 한다.매우 시간 효율적일 것이라 생각한다.

 

 

Karpenter란?

Karpenter는 AWS에서 제공하는 오픈소스 Kubernetes 노드 자동 스케일링 솔루션으로, 애플리케이션 워크로드의 요구 사항에 따라 클러스터의 노드를 자동으로 확장하거나 축소하는 기능을 제공한다.

 

기존 Kubernetes Cluster Autoscaler보다 더 빠르고 효율적으로 작동하도록 설계되었으며, 복잡한 설정 없이 동적으로 자원을 관리할 수 있다.

 

Karpenter 특징

 

1. 속도와 효율성

  • Karpenter는 워크로드에 필요한 노드를 몇 초 안에 프로비저닝할 수 있다.
  • 기존 Cluster Autoscaler가 노드 그룹을 기반으로 작동하는 반면, Karpenter는 개별 Pod의 요구사항에 따라 최적의 인스턴스를 직접 프로비저닝한다.

 

2. 다양한 인스턴스 선택

 

  • Amazon EC2의 다양한 인스턴스 유형을 활용하여 비용 효율적이고 성능 최적화된 리소스를 선택한다.
  • 스팟 인스턴스와 온디맨드 인스턴스를 혼합하여 비용을 절감할 수 있다.

 

3. Pod의 요구사항 기반 프로비저닝

  • Pod의 리소스 요청이나 지역,  AMI,  레이블,  태그 등 세부적인 요구사항을 기반으로 적합한 인스턴스를 자동으로 선택한다.

 

4. 유연한 노드 종료

 

  • 워크로드가 줄어들면 불필요한 노드를 종료하여 비용을 절감한다.
  • 노드 종료 전에 Kubernetes의 스케줄러와 협력하여 Pod를 안전하게 다른 노드로 이동시킨다.

 

5. 간단한 설정

 

  • 복잡한 노드 그룹 설정이 필요하지 않으며, 간단한 정책만으로 동작힌다.
  • Terraform 또는 Helm Chart를 사용하여 빠르게 설정 가능하다.

 

Karpenter 사용 이유

 

MSA 서비스에서 사용 Traffic이 증가함에 따라 Pod만 scale out하는 것이 아닌 Node 또한 scale out 해줘야 한다. 

 

Pod는 HPA를 이용하여 scale out 할 수 있지만 Node 수가 부족할 경우 한계가 존재한다.  

 

그 떄 제안되는 선택지가  Cluster autoscaler와 Karpenter이다. 

 

두 선택지를 비교한 결과 Karpenter를 사용하기로 결정했고 이유는 다음과 같다. 

 

  •  Karpenter는 스팟 인스턴스와 온디맨드 인스턴스를 혼합하여 비용을 최적화할 수 있는 반면, Cluster Autoscaler는 고정된 노드 그룹 만을 사용하기에 비용에 있어 비효율적이다.
  • Node를  프로비저닝 하는 것에 있어 Karpenter는 몇 초 이내로 빠르게 프로비저닝할 수 있는 반면, Cluster Autoscaler는 최대 몇 분이 소요될 수 있다.

Terraform 코드

 

resource "helm_release" "karpenter" {
  namespace        = "karpenter"
  create_namespace = true

  name                = "karpenter"
  repository          = "oci://public.ecr.aws/karpenter"
  repository_username = data.aws_ecrpublic_authorization_token.token.user_name
  repository_password = data.aws_ecrpublic_authorization_token.token.password
  chart               = "karpenter"
  version             = "v0.31.3"

  set {
    name  = "settings.aws.clusterName"
    value = local.eks_cluster_info.cluster_name
  }

  set {
    name  = "settings.aws.clusterEndpoint"
    value = module.eks.cluster_endpoint
  }

  set {
    name  = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
    value = module.karpenter.irsa_arn
  }

  set {
    name  = "settings.aws.defaultInstanceProfile"
    value = module.karpenter.instance_profile_name
  }

  set {
    name  = "settings.aws.interruptionQueueName"
    value = module.karpenter.queue_name
  }
}

resource "kubectl_manifest" "karpenter_provisioner" {
  yaml_body = <<-YAML
    apiVersion: karpenter.sh/v1alpha5
    kind: Provisioner
    metadata:
      name: default
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"] #"spot"
        - key: "node.kubernetes.io/instance-type"
          operator: In
          values: ["t3.xlarge", "t3.medium", "t3.large"]
      limits:
        resources:
          cpu: 50
          memory: 192Gi
      providerRef:
        name: default
      ttlSecondsAfterEmpty: 30
  YAML

  depends_on = [
    helm_release.karpenter
  ]
}

resource "kubectl_manifest" "karpenter_node_template" {
  yaml_body = <<-YAML
    apiVersion: karpenter.k8s.aws/v1alpha1
    kind: AWSNodeTemplate
    metadata:
      name: default
    spec:
      subnetSelector:
        karpenter.sh/discovery: ${local.eks_cluster_info.cluster_name}
      securityGroupSelector:
        karpenter.sh/discovery: ${local.eks_cluster_info.cluster_name}
      tags:
        karpenter.sh/discovery: ${local.eks_cluster_info.cluster_name}
  YAML

  depends_on = [
    helm_release.karpenter
  ]
}

module "karpenter" {
  source  = "terraform-aws-modules/eks/aws//modules/karpenter"
  version = "19.20.0"

  cluster_name                    = local.eks_cluster_info.cluster_name
  irsa_oidc_provider_arn          = module.eks.oidc_provider_arn
  irsa_namespace_service_accounts = ["karpenter:karpenter"]

  create_iam_role      = false

  iam_role_arn    = module.eks.eks_managed_node_groups["service"].iam_role_arn
  irsa_use_name_prefix = false

  tags = {
    Environment = "dev"
    Terraform   = "true"
  }
}

 

Karpenter Test

 

실제 프로젝트에 사용한 Service에 의도적으로 부하를 가했고 Kube Ops view를 통해 Karpenter가 작동하는 것을 확인하였다.