발자국 1주차: Pod 파티를 개최합니다

발자국 1주차: Pod 파티를 개최합니다

 

Pod Party에 초대합니다!

 

 

해당 글은 인프런 워밍업 클럽 스터디 4기 - DevOps (쿠버네티스)를 진행하며 깊게 고민해 보려고 한 내용을 담습니다. 개괄적 정리보다 아는 것과의 비교를 통한 이해를 추구합니다.

 

Pod 파티. 내가 지어 본 농담 겸 이번 도전의 시작을 알리는 단어다.

 

나는 좋은 Pod 파티의 주최진이 되어서, 수많은 Pod들을 중구난방이 아니라 예쁘고 잘 정렬된 형태로 빚어 보고 싶으니까.

 

그를 위해 이번에 수강을 참여하게 된 강의는 쿠버네티스 어나더 클래스 (지상편).

 

일프로님과 함께 멋진 빙산(?)의 일각을 한 달간 맛볼 시간을 만들어 보았다.

 

image

 

그렇게 만나게 된 이번 주는 쿠버네티스의 전체적인 생태계와 핵심 개념들을 깊이 있게 학습하는 주간.

 

유닉스부터 이어지는 리눅스 배포판의 흐름부터 시작해서 컨테이너 기술의 발전 과정, 그리고 쿠버네티스의 실제 설치와 운영까지 체계적으로 접근할 수 있었다.

 

리눅스가 가지고 있는 역사의 흐름을 강의에서 보여 주셨는데, 사진을 하나 더 찾게 되어서 첨부해 보았다.

 

리눅스 배포판 관련해서는 Debian 계열(Ubuntu)이 개인/중소기업에 적합하고 시장 점유율이 높다는 점, 그리고 Red Hat 계열에서 CentOS가 2024년에 종료되면서 Rocky Linux와 Alma Linux로 기업들이 이동하고 있다는 현실적인 변화를 이해할 수 있었다.

 

컨테이너 기술의 발전 과정에서는 chroot, namespace, cgroup 같은 리눅스 격리 기술이 어떻게 *LXC를 거쳐 Docker로 발전했는지, 그리고 Docker가 어떻게 개발자 친화적으로 재구성되어 앱 배포와 실행에 최적화되었는지 순서대로 이해할 수 있었다.

 

  • LXC: 리눅스 커널을 공유하면서 각 컨테이너가 독립적인 환경을 가지도록 하는 경량화된 가상화 방법

 

 

image 

그래, 도커의 등장.

 

시스템 가상화에서 애플리케이션 가상화. 정말 커다란 패러다임 시프트가 아니었을까?

 

 

일단 파티 건물을 만들어 볼까?

 

일프로님의 경험이 조금 더 많음에 따라 천천히 구성된 Rocky Linux 환경.

 

이 안에서 직접 쿠버네티스 클러스터를 구축해 보는 시간이다.

 

기본 설정 단계에서 패키지 업데이트를 주석 처리하고, Asia/Seoul 타임존 설정, NTP 시간 동기화, tc와 openssl 관련 패키지 설치 등을 진행하면서 강의 환경 통일의 중요성을 이해했다.

 

특히 hosts 파일에 클러스터 노드 IP와 이름을 등록하고, 방화벽을 비활성화하고, Swap을 해제하는 등의 작업은 언젠가 맥락을 이해할 수 있지 않을까 (ㅋㅋ) 하는 생각을 하게 되는 시간이었다.

 

containerd 설치 과정에 조금 더 중점을 가져 보자는 생각을 했는데, 이는 containerd가 Kubernetes의 기본 컨테이너 런타임이자 OCI 표준이기 때문이다.

 

containerd 기본 설정에서 SystemdCgroup을 true로 변경해 kubelet과 호환성을 맞추는 부분을 보면서, kubelet의 역할이 뭔지 한 번 더 생각해 보았다.

 

kubelet은 Kubernetes 노드에서 컨테이너를 관리하는 에이전트이자 containerd와 통신하여 컨테이너의 생성, 실행, 중지 등의 작업을 수행하는 것.

 

 

kubelet과 Docker의 역사: CRI와 OCI 표준

 

  • CRI: Container Runtime Interface

  • OCI: Open Container Initiative

 

결국 kubelet은 에이전트다. containerd 통신을 토대로 컨테이너를 관리한다.

 

그런데 통신이 멋대로 되면 괜찮을까? 음, 아닐 것이다. 우리는 중구난방에서 규약으로 가는 것을 좋아한다.

 

이때 우리는 인터페이스를 생각한다. CRI다.

 

CRI를 도입하며, 사람들은 kubelet이 런타임에 gRPC로 Pod 실행을 요청하는 과정을 훨씬 규약으로 다듬을 수 있게 되었다.

 

초기에는 Docker와 rkt만 대응했지만, 1.23에서 dockershim을 사용하고, 1.24에서 dockershim이 제거되면서 containerd, CRI-O 등 다양한 런타임을 지원하게 된 변화 과정이 흥미로웠다.

 

그것을 누가 주도했느냐? 바로 OCI다.

 

이런 상황이 되면서 발생한 Docker의 우여곡절도 인상적이었다.

 

  • docker-containerd라는 고수준 런타임

  • docker-runC라는 저수준 런타임

 

image

 

Docker가 처음에는 많은 기능을 포함한 솔루션이지만, containerd만을 쿠버네티스를 위해서 분리하고, runC가 Docker의 실행 엔진으로 OCI 표준에 부합하게 된 과정, 그리고 Red Hat이 개발한 CRI-O가 Kubernetes 친화적인 경량화 런타임으로 등장한 배경을 이해할 수 있었다.

 

비롯해 이를 강한 이식성을 토대로 적용할 수 있도록 오픈소스 커뮤니티 생태계를 컨트롤하는 CNCF(Cloud Native Computing Foundation)의 역할도 생각해 볼 수 있었다.

 

 

너 살아 있니?

 

다 좋다. 이제 건물도 세워졌고, Pod도 살아 있다고 한다.

 

그런데 얘가 갑자기 뻗어버리면 어떻게 해?

 

<서버 모니터링>이라고 했을 때, 서버 개발자들은 주로 Prometheus와 Grafana를 가장 먼저 떠올릴 것이다.

 

이들은 이미 세팅을 해 본 적이 있었는데, Loki는 처음이었다.

 

쿠버네티스에서는 에이전트 삽입 없이도 자동으로 메트릭을 수집할 수 있다는 점이 기존 모니터링 방식과의 큰 차이점이었다. 신규 앱이 추가되어도 label 기준으로 자동 인식되어 모니터링 누락을 방지할 수 있다는 점에서 운영의 편의성이 크게 향상된다고 느꼈다.

 

개발 환경과 운영 환경 간의 모니터링 불일치 문제를 해결할 수 있다는 점도 실무적으로 매우 중요한 장점이라고 생각했다. Spring Boot Actuator로 메트릭을 노출하는 것과 유사하게, 쿠버네티스에서는 표준화된 방식으로 메트릭을 수집할 수 있어서 일관성 있는 모니터링이 가능하다는 점이 인상적이었다.

 

HPA(Horizontal Pod Autoscaler)를 통한 자동 스케일링 기능에서는 CPU 사용률 등 메트릭을 기준으로 Pod 수를 자동 조절하고, Behavior 설정을 통해 스케일 아웃 속도를 제한할 수 있다는 점을 학습했다.

 

 

 

이거 누가 수정했어?

 

모든 것이 잘 돌아가고 있었다. 근데 갑자기 어느 날부터 문제가 터지기 시작했다?

 

자, 이제부터 누가 이 파티 주최자인지 식별해 볼 시간이다. 옛날엔 누군지 몰랐겠지만 지금은 다 안다.

 

인프라를 YAML로 선언적으로 관리하는 GitOps 개념을 토대로, Git을 통한 버전 관리와 변경 이력 추적이 가능해졌... 다는 점이 두려웠지만... 좋은 게 좋은 거라고? (농담)

 

이 방식은 기존 방식에 비해 재현성이 높고 기록이 남으며, 환경 간 차이를 줄이고 운영 이슈 대응이 수월해지는 장점을 지닌다.

  

 

설정은 어디다가 해요?

 

그리고 ConfigMap과 Secret을 통한 설정 관리 방식.

 

이 부분을 보면서는 Spring Boot의 @ConfigurationProperties나 application.properties와 매우 유사한 관심사 분리 개념이 적용되어 있다고 느꼈다.

 

ConfigMap은 주로 metadata와 data로 구성되어 Pod에 환경변수 값을 제공하는 용도로 사용되고, Secret은 stringData 형태로 정의해 Pod 안에 파일로 만들어져 민감한 정보를 안전하게 관리할 수 있다는 점이 실용적이었다.

 

유사한 이름의 둘도 있었다.

 

  • PVC(PersistentVolumeClaim): Pod가 저장공간을 요청할 때 사용 / 저장공간 크기와 accessMode가 필수 설정 항목

  • PV(PersistentVolume): 실제 물리적 저장공간을 지정하는 역할

 

PV가 Namespace에 속하지 않고 클러스터 단위로 관리된다는 점에서 글로벌 리소스의 특성을 잘 보여준다고 생각했다.

 

비롯해 Prometheus 라벨링 및 네이밍에서 쿠버네티스 권고 라벨링 방식을 학습했는데, 일관성 있는 메타데이터 관리를 통해 모니터링과 운영의 효율성을 높일 수 있다고 생각했다.

 

그리고 자동화 기능.

 

Self-Healing, AutoScaling, RollingUpdate 등의 자동화 운영 기능들을 학습하면서 쿠버네티스의 진정한 가치를 이해할 수 있었다. Self-Healing으로 Pod가 죽으면 자동 복구되고, AutoScaling으로 CPU 사용률에 따라 Pod 수가 자동 조절되며, RollingUpdate로 무중단 배포와 실패 시 롤백이 지원된다는 점에서 운영 부담을 크게 줄일 수 있다고 느꼈다.

 

 

그래서, 다음 주는?

 

이번 주는 학습을 통해 쿠버네티스의 전체적인 그림을 그려 보는 시간이었던 것 같다.

 

앞으로의 시간이 기대되는데, 아무래도 애플리케이션 생명 주기와 서버의 상태와의 연동을 조금 더 눈여겨 보게 되는 것 같다.

 

Spring Boot Actuator의 health check 엔드포인트를 쿠버네티스와 연동하는 방법이나, Spring Boot의 Graceful Shutdown 기능과 쿠버네티스의 Pod 종료 프로세스를 매끄럽게 연결하는 방법도 궁금해진다.

 

다음 주에도 멋진 파티 주최자로서의 발돋움을 하는 것으로.

 

댓글을 작성해보세요.

  • 일프로
    일프로

    정말 공들여 작성하셨네요~ 끝까지 화이팅입니다!!

채널톡 아이콘