[KIA] 1. Introducing Kubernetes

Ananda·2025년 3월 25일

Kubernetes In Action

목록 보기
1/2
📌 이 챕터가 다루는 것
  • 개발과 배포 트렌드의 변화 이해하기
  • 컨테이너를 이용해 애플리케이션 분리와 환경 차이(environment difference) 줄이기
  • 컨테이너와 Docker가 k8s에서 어떻게 쓰이는지 이해하기
  • 개발자와 시스템 관리자의 삶의 윤택함을 더할 k8s

Legacy System 은

  • monolithic (단일형 구조)
  • 하나의 프로세스 or 소수의 서버에 걸쳐 실행된다.
  • 개발자가 전체 시스템 패키징 → Ops(운영팀)에 넘김 → Ops가 배포 및 관리. 하드웨어 이슈도 핸들링해야 했다.

그러나 요즘은 :

  • Microservice (작고 독립적, 개별적으로 개발, 배포, 업데이트, 확장)

  • 빠른 대응과 개발이 가능해졌다.

    배포할 컴포넌트의 수가 많아지고 데이터 센터가 확장되며, 운영하기 까다로워졌다. 어디에 어떤 컴포넌트를 배치할지 결정하고 자원을 효율적으로 운영하기 위해 수작업 관리하는 것은 사실상 어려워졌다. 자동화가 필요해진 순간이다.

k8s를 통해 우리는:

  • 하드웨어를 추상화해 데이터센터 전체를 하나의 거대한 컴퓨팅 자원으로 다룰 수 있다.
  • 실제 서버가 어떻게 돌아가는지 잘 알지 못해도 앱 배포와 실행이 가능해졌다.
  • 여러 컴포넌트 간 통신도 지원한다.

많은 기업들이 k8s를 채택하며 클라우드 및 온프레미스(기업 자체 인프라 운영)를 아우르는 분산 애플리케이션 실행의 표준 방식으로 자리 잡았다.

1.1 Understanding the need for a system like k8s

개발/배포 방식의 변화 : monolithic → microservice

1.1.1 Moving from monolithic apps to microservices

Monolitic apps는 모든 구성 요소가 하나로 움직이기 때문에 개발, 배포 및 관리도 하나의 단위로 이루어져야 한다. 그렇기 때문에 일부분 수정이 곧 전체 재배포로 이어진다.

Monolithic apps에서 서버 확장이 필요할 땐 두 가지 방법이 있다:

  • Scaling Up : 서버 성능 높이기 (cpu, 메모리 등 추가), 간단하지만 비용이 많이 든다.
  • Scaling Out : 서버 수 늘리기, 비용은 적지만 앱 구조 변경이 필요하고 일부 컴포넌트는 scaling out이 어려울 수 있다.

그래서 이 거대한 앱을 잘게 쪼개기 시작했다. 각 microservice들은 독립적 프로세스이고 다른 서비스와 API - HTTP, AMQP 등 -로 소통한다. 그래서 일부분 수정이 있어도 전체를 갈아엎을 필요가 없어졌다.

마이크로서비스의 스케일링은 개별 서비스 단위로 가능하다. 리소스가 많이 필요한 서비스만 선택적으로 확장 가능하다. 예를 들어, 일부 컴포넌트는 여러 서버에서 복제되어 실행되고 어떤 컴포넌트는 단일 프로세스로 돌아간다.

KIA_fig1_2

물론 마이크로서비스가 능사는 아니다. 컴포넌트 수가 적을 땐 관리하기 쉽지만, 그 수가 늘어날수록 배포 관련 이슈를 다루기 어려워지고(왜냐면 서로간 의존성의 수도 증가하기 때문에) 서비스 간 소통을 관리해 하나의 시스템으로 작동할 수 있도록 하는 게 까다로워진다.

마이크로서비스들은 서로 다른 라이브러리를 사용하기 때문에 구성 요소 간의 의존성 차이가 발생한다. A 서비스는 lib a v1.0를 쓰지만 B 서비스는 lib a v2.3을 쓸 수 있다. 이게 얽히고 설키다 보면 동일한 서버에 배포할 때 의존성 관리가 힘들어진다.

1.1.2 Providing a consistent environment to apps

가장 큰 문제는 서비스들이 각기 다른 환경에서 돌아간다는 점이다. 단일 production machine도 환경이 계속 일정할 거라고 보장할 수 없다.

하드웨어, 운영체제, 라이브러리 등 개발 환경과 운영 환경을 동일하게 유지해야 prod 환경에서 발생하는 문제를 줄일 수 있는데, 현실적으로 어렵다.

1.1.3 Moving to continuous delivery: DevOps and NoOps

DevOps : 개발자, QA, 운영 팀이 전체 프로세스동안 협력한다.

NoOps : 운영팀을 거치지 않고 개발자 스스로 배포한다. ← k8s의 도움과 함께

k8s를 통해 개발자는 실제 하드웨어에 대해 자세히 알지 못해도 배포가 가능하며, 시스템 관리자는 앱에 대해 자세히 알 필요 없이 인프라 유지 관리에 집중할 수 있다.

1.2 Introducing container technologies

k8s는 리눅스 컨테이너를 이용한다.

1.2.1 Understanding what containers do

application이 적은 컴포넌트로 이루어져 있다면 각 컴포넌트마다 VM을 줄 수 있다. VM에는 각자 필요한 게스트 OS가 들어있다. 그래서 VM을 많이 쓸 수록 하드웨어 자원을 많이 잡아먹기 때문에 비효율적이다.

VM대신 linux Container 기술이 더 많이 쓰인다. 컨테이너는 서비스들을 동일한 호스트 OS에서 실행하면서 각 서비스를 격리시킨다. 컨테이너끼리 격리되어 있기 때문에, 모든 서비스들이 호스트 OS에서 돌아가도 각 서비스는 OS위에서 혼자 돌아가는 것처럼 보인다.

컨테이너는 VM에 비해 가볍다. 오버헤드도 적다. 그래서 VM보다 훨씬 많은 수의 서비스를 각자 독립된 컨테이너 환경에서 실행할 수 있다. VM과 달리 게스트 OS를 가지지 않기 때문에 부팅 시간을 기다리지 않아도 된다.

KIA_fig1_4.png

그런데 컨테이너들은 동일한 호스트OS위에서 돌아가는데, 어떻게 환경이 격리되었다 말할 수 있을까? 다음 두 메커니즘이 이를 가능하게 한다:

  • linux namespace : 각 프로세스가 리소스를 분리해서 실행할 수 있도록. 자원의 종류 제한
  • linux control groups(cgroups) : 프로세스가 쓸 수 있는 리소스 제한. 자원의 양 제한

Linux Namespace의 종류:

  • PID
  • network
  • User ID
  • Process ID
  • UTS
  • and more

예를 들어, UTS 네임스페이스를 두 개 생성하면 각 네임스페이스는 서로 다른 로컬 호스트네임을 가질 수 있다.

1.2.2 Introducing the Docker container platform

도커는 애플리케이션 패키징, 배포, 실행을 위한 플랫폼이다. 애플리케이션과 더불어 그 환경 전체 또한 함께 패키징할 수 있다. 이 패키지를 중앙 저장소에 전송하고 필요한 서버가 이를 다운로드 받아 실행할 수 있다. 도커의 세 가지 요소는 다음과 같다:

  • Images : 당신이 패키징한 앱과 os환경. 파일시스템, 실행 파일 경로 등의 메타데이터를 포함하고 있다.
  • Registries : 도커 이미지를 저장하고 공유하는 저장소. push를 통해 이미지를 업로드하고 pull을 통해 이미지를 다운로드한다.
  • Containers : 이미지를 기반으로 생성된 리눅스 컨테니어. 실행 중인 컨테이너는 호스트와 다른 프로세스들로부터 격리된다.

KIA_fig1_6.png

도커와 VM의 차이점에 대해 더 알아보자.

KIA_fig1_7.png

분명 컨테이너끼리 격리된 환경에서 돌아간다고 했는데, 컨테이너 1과 2가 같은 파일시스템을 공유하고 있다. 이는 도커 이미지가 여러 겹의 레이어로 구성되어 있기 때문이다.

서로 다른 이미지여도 같은 레이어를 가지고 있을 수 있다(parent layer). 레이어는 한 번만 저장되기 때문에, 겹치는 레이어가 있다면 두 번 저장할 필요 없이 위 그림처럼 파일시스템(레이어)을 공유할 수 있다. 파일시스템을 공유하며 한 컨테이너가 파일을 수정하면 다른 컨테이너에 영향을 미칠까? 그렇지 않다. 이미지 레이어는 read-only이기 때문에, 수정이 일어나면 새로운 writable layer가 생성되어 파일 변경 사항은 최상위 레이어로 쌓인다.

이론적으론 컨테이너가 도커가 설치된 모든 리눅스 머신에서 돌아갈 수 있지만, 예외가 있다. 컨테니어는 호스트의 커널을 이용하는데, 만약 애플리케이션이 특정 커널 버전이나 모듈을 써야 한다면 어떤 머신은 제한될 수 있다. 또한 특정 하드웨어 아키텍처용으로 빌드된 컨테이너는 다른 아키텍쳐 위에서 돌아갈 수 없다 (a86 → AFM 불가능). 이런 경우엔 VM이 여전히 필요하다.

1.3 Introducing Kubernetes

구글이 글로벌 회사가 되며, 수 천개의 애플리케이션의 개발 및 배포를 잘 관리할 수 있는 솔루션을 만들어야 했다.

1.3.1 Understanding its origins

구글은 내부적으로 Borg와 Omega를 만들어 개발자 및 시스템 관리자가 수 많은 애플리케이션과 서비스를 관리하는 데에 사용했다. 개발과 관리를 쉽게만들 뿐 아니라 인프라 활용도를 끌어올렸다. 한동안 이 시스템들을 비밀에 부쳤다 2014년 오픈 소스 시스템으로 Kubernetes를 발표했다.

1.3.2 Looking at Kubernetes from the top of a mountain

K8s는 당신이:

  • 쉽게 애플리케이션을 배포하고 관리할 수 있게 한다. 앱의 내부 디테일이나 각 호스트에 수동으로 배포할 일 없이.
  • 수천개의 컴퓨터 node에서 돌아가지만, 마치 하나의 큰 컴퓨터에 있는 것처럼 애플리케이션을 실행할 수 있게 한다.
  • Cluster가 몇 개의 노드를 가지고 있든 상관이 없다. 그저 클러스터에 노드를 추가할 뿐이다.

KIA_fig1_8

K8s는 마스터 노드와 워커 노드로 이루어져 있다. 개발자가 앱 리스트를 마스터에 넘기면 k8s는 워커 노드 클러스터에 배포한다. 만약 특정 앱들이 같이 실행되어야 한다면 k8s는 같은 워커 노드에 그것들을 배포한다. 아니면 일반적으론 클러스터 곳곳에 흩뿌려 놓는다.

K8s 덕분에, 개발자는 core app feature 개발에 집중할 수 있고, 운영팀은 리소스를 더 잘 활용할 수 있다.

1.3.3 Understanding the architecture of a Kubernetes cluster

K8s 클러스터는 여러 노드들로 구성된다. 노드는 두 가지 종류로 분류할 수 있다.

  1. Master node : kubernetes control plane을 호스팅하는 노드. K8s 시스템 전체를 관리한다.
  2. Worker node : 실제 배포된 애플리케이션을 실행하는 노드.

KIA_fig1_9

  • Control Plane 클러스터를 관리하는 control plane은 여러 컴포넌트로 구성된다. 이 컴포넌트들은 하나의 마스터 노드에서 실행되거나 여러 노드에 분산될 수도 있다.
    • Kubernetes API server : control plane 컴포넌트들과의 통신 담당
    • 스케쥴러 : 애플리케이션의 배포 가능한 컴포넌트에 worker node 할당
    • 컨트롤러 매니저 : 컴포넌트 복제, worker node 추적, 노드 에러 처리 등 클러스터 수준의 작업 관리
    • etcd : 클러스터 구성 정보를 지속적으로 저장하는 분산 데이터 저장소.
  • Nodes Worker node는 컨테이너화된 애플리케이션ㅇ르 실행하는 머신이다. 애플리케이션을 실행하고 모니터링하며 서비스를 제공하는 작업을 수행한다.
    • 컨테이너 런타임 : 컨테이너를 실행. (대표적으로, Docker)
    • Kubelet : API 서버와 통신하며 노드에서 컨테이너 관리
    • Kubernetes 서비스 프록시 (kube-proxy) : 애플리케이션 컴포넌트 간의 네트워크 트래픽을 load balancing

1.3.4 Running an application in Kubernetes

K8s에서 애플리케이션 실행하려면:

앱을 하나 이상의 컨테이너 이미지로 패키징 → 이미지 레지스트리에 푸쉬 → API 서버에 앱 설명(앱들을 포함하는 컨테이너 이미지, 컴포넌트 간 관계, 어떤 것이 같은 노드에서 실행 되어야 하는지, 각 컴포넌트의 replica 수, 어떤 컴포넌트가 내부/외부 클라이언트에 제공되어야 하는지… 에 대한 정보) 제공 → API 서버가 app descriptor 설명 처리 → 스케줄러가 pod를 사용가능한 worker node에 할당 → 각 노드의 Kubelet이 컨테이너 런타임(도커)에게 필요한 이미지들을 레지스트리에서 pull하여 컨테이너 실행하도록 지시 → 또한 Kubelet은 descriptor에 써진 replica 수에 맞게 worker node에 컨테이너를 스케줄하고 실행

  • Pod : 컨테이너 그룹, 위 그림에서 app description에서 박스로 묶여진 단위.

KIA_fig1_10

앱이 실행되면 k8s는 그 상태가 description과 일치하도록 지속적을 관리한다. 예를 들어, 웹 서버 인스턴스를 항상 5개 실행하도록 지정했다면 k8s는 정확히 5개의 인스턴스를 실행 상태로 유지한다. 만약 하나의 인스턴스가 fail하면, 자동으로 해당 인스턴스를 재시작한다. 마찬가지로, 전체 worker node가 실패하거나 접근이 불가능하면 k8s는 해당 노드에서 실행중인 컨테니어들을 새로운 노드로 재배치한다.

앱이 실행되는 동안 replica 수를 조정하면 k8s가 자동으로 그 수를 맞춘다. 더 나아가 CPU 부하, 메모리 사용량, 초당 쿼리 수 등 실시간 메트릭을 기반으로 k8s가 직접 최적의 replica 수를 조정할 수 있다.

어떤 컨테이너는 노드 실행 실패나 다른 컨테이너로 인해 노드에서 나가야 하는 경우가 생기며 클러스터 내에서 이동하게 된다. 이렇게 클러스터 내에서 이동을 하면 클라이언트는 어떻게 컨테이너를 잘 이용할 수 있을까? K8s는 이들 컨테이너를 하나의 고정 IP 주소로 클라이언트에 노출시키고, kube-proxy의 서비스 제공 컨테이너 간 load balancing을 통해 일관된 접근을 보장한다. 그러므로 클라이언트는 안심하고 이용할 수 있다.

1.3.5 Understanding the benefits of using Kubernetes

K8s가 우리에게 가져다 준 혜택들

  • 배포 단순화 개발자들이 서버의 세부 사항을 알 필요 없이 앱 배포가 가능하다. 특정 하드웨어 요구사항이 필요한 경우, 해당 하드웨어를 가진 노드에서 실행하도록 지정할 수 있다. (예를 들어, SSD대신 HDD를 필요로 하는 앱)
  • 인프라 최적화 K8s는 앱의 리소스 요구 사항과 각 노드의 가용 리소스를 기반으로 가장 적합한 노드를 선택하여 앱을 실행한다. 컨테이너를 사용하면 앱이 클러스터 내에서 자유롭게 이동할 수 있어 하드웨어 리소스를 더욱 효율적으로 사용할 수 있다.
  • 인프라 상태 체크 앱이 클러스터 내에서 이동하는 특성이 서버에 문제가 생겼을 경우 매우 유용하게 쓰인다. K8s는 앱과 이를 실행하는 노드를 모니터링하고, 문제가 있을 시 다른 노드로 앱을 재배치한다. 이로 인해 운영팀은 앱 컴포넌트 이동에 신경 쓸 필요 없이 노드 복구에만 집중할 수 있다.
  • 오토 스케일링 K8s는 리소스 사용을 모니터링 해 실행중인 인스턴스의 수를 자동으로 조정할 수 있다. 만약 클라우드 인프라에서 k8s가 실행될 경우, 클라우드 제공자의 API를 통해 노드를 추가하는 것이 쉬우므로 k8s는 배포된 앱의 필요에 따라 클러스터의 크기를 자동으로 확장하거나 축소할 수 있다.
  • 개발 단순화 개발과 프로덕션의 환경 차이를 걱정할 필요가 없다. K8s는 새로운 버전의 앱이 배포될 때 문제가 있을 경우 자동으로 중단 → 지속적인 앱 배포를 가속화한다.

1.4 Summary

  • monolithic app은 배포는 쉬워도 유지와 스케일링이 어렵다
  • Mircroservice 아키텍쳐 도입으로 개별 컴포넌트 개발이 쉬워졌으나, 단일 시스템으로 배포/구성하는 데 어려움이 있다.
  • 리눅스 컨테이너는 VM가 비슷한 이점을 제공하며 훨씬 가볍고 하드웨어 자원을 더 효율적으로 사용한다.
  • 도커는 리눅스 컨테이너 기술을 개선해 컨테이너화된 앱과 OS환경의 제공을 더 쉽고 빠르게 만들었다.
  • K8s는 전체 데이터센터를 앱 실행을 위한 단일 컴퓨팅 자원으로 노출시킨다.
  • 개발자는 시스템 관리자의 도움 없이 k8s를 통해 앱을 배포할 수 있다.
  • 시스템 관리자는 k8s가 실패한 노드를 자동으로 처리해 주기 때문에 한결 편해졌다.

자료 출처: Kubernetes In Action (2018)

profile
이제 한 걸음일 뿐

0개의 댓글