쿠버네티스 개요
쿠버네티스 개념
컨테이너란?
전통적으로 물리적인 서버에서 애플리케이션을 실행 하였다. 이 방법은 하나의 물리적인 서버에 애플리케이션을 통제로 배포 하는 방법이였다. 이 방법은 서버의 리소스 관리, 애플리케이션 유지 보수 및 업데이트 같은 중요한 면들이 어렵고 비용이 많이 들었다. 이러한 어려움을 해결하기 위해 가상화 (Virtualization)가 도입 되었다. 단일한 물리적 서버의 CPU에서 여러 대의 가상머신 (Virtual Machine)을 실행하고, 물리적인 서버의 리소스를 최대한 사용 할 수 있었다. 하지만 한 가상머신당 새로운 OS(Operating System)가 존재 하여 애플리케이션 배포 및 리소스 면에서는 물리적인 서버와는 다른 이점이 없었다. 그래서 나온 컨테이너는 프로세스 단위의 격리 환경을 조성하고 있어 상호 간의 의존도를 낮추었다. 그 외 컨테이너는 호스트 서버의 OS를 그대로 사용하기 때문에 VM보다 훨씬 사이즈가 작고, 배포가 빠르고, 성능 손실은 거의 없었다.
컨테이너로 서비스를 제공하기 전 알아야 될 애플리케이션 배포의 형태들이 있다. 모놀리식(monolithic) 애플리케이션은 하나의 큰 애플리케이션으로, 모든 기능이 하나의 코드베이스에서 동작한다. 예를 들면 LAMP (Linux, Apache, MySQL, PHP) 스택을 사용하는 웹 서비스가 있다. 이러한 모놀리식 애플리케이션은 복잡하고 무거워지는 경향이 있다. 반면에, 컨테이너화된 애플리케이션은 애플리케이션을 실행하는 데 필요한 모든 것을 포함하고 있는 작은 패키지인 컨테이너 안에 애플리케이션을 묶는 것이고 이를 통해 애플리케이션을 더욱 효율적으로 실행할 수 있다. 컨테이너화된 애플리케이션의 예시로는 Docker, Podman, LXC와 같은 컨테이너화 기술을 사용하는 웹 서비스, 데이터베이스, 애플리케이션, 마이크로서비스 등이 있다.
컨테이너화된 서비스
다양한 컨테이너 런타임 기술이 존재하지만, 그중에 도커(Docker)가 표준으로 여겨지고 있다. 만약에 도커 컨테이너로 마이크로서비스 형태의 애플리케이션을 배포 하게 된다면, 하나의 도커 이미지 안에 서비스 운영에 필요한 모든 것들이 들어 있어 개발자들이 손쉽게 협업을 할 수가 있다. 또한 서비스 운영 환경과 개발 환경의 느슨한 결합으로 한쪽의 에러에도 다른 한쪽은 작업을 계속해서 이어 나갈 수가 있다. 도커컨테이너는 배포가 쉽고 빠르며 시스템 의존성을 쉽게 업그레이드할 수 있어 스케일 아웃에 용이하다. CPU limit, Memory limit 등의 시스템 자원을 효율적으로 활용할 수가 있고 무엇보다도 가상머신 보다 성능 면에서 뛰어나다. 하지만 이렇게 컨테이너화된 애플리케이션도 역시 관리를 해야 한다. 만약에 컨테이너화된 애플리케이션이 다운이 되면 직접 재실행 시켜야 된다. 전통적인 방식과 VM보다 관리가 용이하지만 컨테이너의 스케일 아웃 장점 때문에 관리해야 하는 컨테이너 수가 많아지게 되면 관리 와 운영에 어려움이 따르게 된다.
쿠버네티스의 등장
각각 독립적으로 배치된 컨테이너를 연결, 관리 및 확장하면서 요소들 전체가 하나로 실행 되도록 해야 한다. 이렇게 다수의 컨테이너 실행을 관리해주는 것을 컨테이너 오케스트레이션 이라고 부른다. 오케스트레이션(Orchestration)은 수많은 연주자들이 지휘에 맞춰 연주하는 것을 "오케스트라"라고 한다. 오케스트레이션은 음악에서 다양한 음악적 요소들을 조화롭게 배열하고 조율하여 완성도 높은 작품을 만들어내는 과정이고, 컨테이너 오케스트레이션 또한 다양한 컨테이너들을 효율적으로 관리하고 조율하여 원활한 애플리케이션 운영을 가능하게 한다. 마치 오케스트레이션의 역할처럼, 컨테이너 오케스트레이션은 각각의 요소를 조화롭게 배치하고 조율하여 시스템 전체가 조화롭게 동작하도록 돕는다. 쿠버네티스는 구글이 개발한 오케스트레이션 엔진으로서 컨테이너를 쉽고 빠르게 배포/확장하고 관리를 자동화해주는 오픈소스 플랫폼이다. 쿠버네티스는 구글에서 내부적으로 사용하던 Borg 시스템에서 발전되었고, 2014년에 쿠버네티스 프로젝트를 오픈 소스 화 했다. Kubernetes를 가끔 K8s라고 표현한다. K8s는 "K"와 "s"와 그 사이에 있는 8글자를 나타내는 약식 표기이다.
실제 프로덕션 환경에서의 애플리케이션들은 여러 컨테이너에 걸쳐 있으며 이러한 컨테이너는 여러 서버 호스트에 배포되어야 한다. 이 때문에 컨테이너를 위한 보안은 멀티 레이어 구조로 되어 있고 복잡할 수 있다. 쿠버네티스는 이러한 워크로드를 위해 규모에 맞는 컨테이너를 배포하는 데 필요한 오케스트레이션 및 관리 기능을 제공한다. 쿠버네티스 오케스트레이션을 사용하면 여러 컨테이너에 걸쳐 애플리케이션 서비스를 구축하고 클러스터 전체에서 컨테이너의 일정을 계획하고 이러한 컨테이너를 확장하여 컨테이너의 상태를 지속적으로 관리할 수 있다. 그것 뿐만이 아니라 컨테이너 오케스트레이션 도구를 사용하면 자동화된 배포 및 스케일링, 롤아웃/롤백 및 컨테이너 복구 작업을 구현 할 수가 있다는 장점들이 존재한다.
쿠버네티스 주요 기능
-
Self-healing: 쿠버네티스는 제대로 실행되지 않는 컨테이너를 자동으로 재시작하거나 교체할 수 있다.
-
Automated Rollouts & Rollbacks: 원하는 배포 상태에 맞는 속도로 현재 배포 상태를 변경할 수 있다.
-
Service Discovery & Load Balancing: DNS 또는 IP 주소를 사용하여 클러스터 내의 컨테이너를 외부에 노출시킬 수 있다. 네트워크 트래픽이 많은 서비스의 경우, 안정적인 서비스 운영을 위해 네트워크 트래픽을 로드밸런싱도 가능 하다.
-
Storage Orchestration: 로컬 스토리지 서버와 퍼블릭 클라우드 스토리지 서비스를 연결하여 사용할 수 있다. 외부 스토리지 서버 자원을 쉽게 사용할 수 있으며, 데이터 지속성을 보장할 수 있다.
-
Secret and Configuration Management: 비밀번호, SSH Key, OAuth 토큰과 같은 중요한 정보를 안전하게 저장하고 관리할 수 있다. 컨테이너 구성 정보가 변경되면, 쿠버네티스는 컨테이너 이미지를 재구성하지 않고 구성 정보의 변경 사항을 반영하여 배포 및 업데이트할 수 있다.
-
Automatic Bin Packing: 컨테이너 운영에 필요한 자원 사용률을 수신하고 가장 적합한 클러스터 노드를 제공한다.
클러스터 구성 요소 소개
쿠버네티스 중요 요소들을 논리적으로 간단하게 설명 하고 나눤다면:
Hardware(하드웨어) | Node |
---|---|
Orchestration(오케스트레이션) | Deployment, Job, CronJob, StatefulSet, DaemonSet |
Configuration(구성) | ConfigMap, Secret |
Persistence(지속성) | PersistentVolume, PersistentVolumeClaim(PVC) |
AccessControl(접근 제어) | Namespace, ServiceAccount, Role, ClusterRole |
Exposure(외부 노출) | Service, Ingress |
Node
클러스터 내에서 하드웨어 역할을 한다. 컨테이너화된 워크로드를 실행할 수 있는 물리적 또는 가상의 서버이다. 쿠버네티스 클러스터 내에서 노드는 워커(Worker) 및 마스터(Master)노드로 나눠줘 있다. 각 노드는 클러스터의 일부가되어 컨테이너화된 애플리케이션을 실행하고 클러스터 내에서 다른 노드와 통신한다.
Pod
쿠버네티스에서는 애플리케이션을 배포할 수 있는 최소 단위인 파드(Pod)라는 개념을 제공한다. 파드는 하나 이상의 컨테이너를 포함할 수 있으며, 같은 파드 안에 있는 컨테이너는 동일한 호스트에서 실행된다.
Deployment
레플리카셋(ReplicaSet)을 이용하여 애플리케이션의 배포를 관리한다. Deployment을 사용하면 롤아웃 및 롤백, 업데이트, 스케일링 등을 쉽게 처리할 수 있다.
ReplicaSet
Pod의 수를 관리하고, 원하는 수의 Pod가 항상 실행되도록 유지하는 역할을 하는 오브젝트. ReplicaSet은 주로 Pod을 생성하고, 감시하고, Pod가 정상적으로 실행되지 않을 경우 다른 Pod으로 대체하는 작업을 수행한다.
Job
일회성 작업을 실행하며, 해당 작업이 성공적으로 완료될 때까지 실행을 유지하는 쿠버네티스 리소스. 일반적으로 배치 작업 또는 데이터 처리와 같은 일회성 작업을 수행하는 데 사용된다.
CronJob
쿠버네티스에서 제공하는 오브젝트 중 하나로, 정해진 시간 간격으로 반복적으로 실행되는 Job을 생성하기 위해 사용된다. CronJob을 사용하면 정기적인 작업을 반복적으로 실행할 수 있으며, 예를 들어 백업, 데이터베이스 업데이트, 인덱스 생성 등의 작업을 스케줄링할 수 있다.
StatefulSet
StatefulSet은 ReplicaSet의 확장된 버전이다. 상태(state)를 가지는 애플리케이션을 관리하기 위해 사용된다. 일반적인 Deployment와는 달리, StatefulSet은 각 Pod에 고유한 식별자를 부여하며, Pod가 재시작되더라도 동일한 식별자를 유지한다. 이로 인해 StatefulSet은 데이터베이스나 메시지와 같이 상태가 중요한 애플리케이션을 배포하는 데 적합하다.
HPA(Horizontal Pod Autoscaler)
HPA는 쿠버네티스 클러스터에서 현재 실행 중인 파드 수를 모니터링하고, 이에 대한 CPU나 메모리 사용량 등의 지표를 기반으로 파드 수를 자동으로 조절한다. 이를 통해 클러스터에서 파드 수를 최적화하고, 예상치 못한 트래픽 급증에 대응할 수 있도록 한다.
DaemonSet
모든 노드에 특정 파드를 실행하도록 하는 Kubernetes 오브젝트. 이러한 파드들은 클러스터의 모든 노드에서 실행되며, 노드가 추가될 때 자동으로 파드가 추가되며, 노드가 제거될 때 자동으로 파드도 제거된다. 로그 수집 에이전트나 모니터링 에이전트 실행할때 활용할 수 있다.
Service
하나 이상의 Pod 집합에 대한 네트워크 엔드포인트를 정의하고 안정적인 DNS 이름을 제공하는 Kubernetes 오브젝트. 서비스 옵젝트는 파드 집합에 대한 네트워크 엔드포인트를 제공하며, 애플리케이션에 접근할 수 있는 방법을 제공한다. 서비스 옵젝트에는 ClusterIP, NodePort, LoadBalancer 및 ExternalName이 있다.
Ingress & Ingress Controller
클러스터 내부에 있는 서비스에 접근하기 위한 외부에서의 진입점을 제공하는 쿠버네티스 리소스 옵젝트. HTTP, HTTPS, 그리고 TLS 등의 프로토콜을 지원하며, 라우팅 규칙을 설정하여 클러스터 내부의 다양한 서비스에 대한 접근을 제어할 수 있다.
인그레스는 Ingress Controller와 함께 사용되며, 인그레스 규칙을 수신하여 요청을 올바른 서비스로 라우팅한다. Ingress Controller는 클라우드 제공 업체에서 제공하는 로드밸런서, Nginx, Traefik 등의 소프트웨어를 사용할 수 있다.
Volume
볼륨(Volume)은 컨테이너에서 사용할 수 있는 디스크 공간을 제공합니다. 파드 안에 있는 컨테이너는 볼륨을 공유할 수 있으며, 디스크에 저장된 데이터를 읽고 쓸 수 있습니다.
Persistent Volume Claim & Persistent Volume
Persistent Volume(PV)은 컨테이너화된 어플리케이션에서 사용될 수 있는, 클러스터 레벨에서 정의된 스토리지 볼륨이다. 이 스토리지 볼륨은 클러스터 안의 노드에 있는 물리적 스토리지와 매핑되어, 클러스터 안의 다른 오브젝트와 마찬가지로 클러스터 노드 사이에서 이동될 수 있다.
Persistent Volume Claim(PVC)은 어플리케이션에서 사용할 특정한 Persistent Volume을 요청하는 Kubernetes 오브젝트. 어플리케이션이 필요한 용량, 스토리지 클래스 및 액세스 모드 등을 정의하고 PVC를 사용하여 해당 요청 사항을 표현한다. 이를 통해 어플리케이션은 실제 스토리지를 직접 다루지 않아도 되며, 볼륨에 대한 액세스를 안전하게 보호할 수 있다.
ConfigMap/Secret
애플리케이션에서 사용되는 환경변수, 설정 값 등과 같은 구성 데이터를 저장하는 쿠버네티스 옵젝트. ConfigMap과 Secret의 차이점은, Secret은 보안 데이터를 저장하는데 사용되고, ConfigMap은 설정값 및 환경변수 데이터를 저장한다.
Namespace
쿠버네티스 클러스터 안에서 리소스들을 논리적인 그룹으로 분류하기 위한 추상화된 방법. 각각의 네임스페이스는 자신만의 리소스를 가질 수 있으며, 다른 네임스페이스의 리소스와 격리된다. 즉 Namespace는 클러스터를 논리적으로 분리한다.
Role
Role은 사용자 또는 서비스 계정이 클러스터 내에서 수행할 수 있는 작업 집합을 정의하는 Kubernetes 리소스 중 하나. Role을 사용하여 사용자 또는 서비스 계정에 권한을 할당할 수 있다. Role은 RoleBinding과 함께 사용되며, RoleBinding은 특정 사용자 또는 서비스 계정에 Role을 할당하는 데 사용된다. 즉, RoleBinding은 Role을 사용하여 사용자 또는 서비스 계정에 권한을 부여한다.
ClusterRole
클러스터 자체에서 동작하며 권한을 부여하는 권한 모음이다. 예를 들어, 클러스터 관리자는 클러스터 전체에 대한 역할을 만들어 로그 및 이벤트를 볼 수 있지만, 개발자 역할은 각 네임스페이스에서 사용할 수 있는 권한만 가질 수 있다. 이러한 역할은 클러스터의 모든 네임스페이스에서 권한을 가질 수 있다.
ServiceAccount
클러스터 내부에서 사용자나 프로세스에게 권한을 부여하기 위한 리소스. 쿠버네티스의 계정에는 2종류(유저 어카운트, 서비스 어카운트)가 존재. UserAccount는 엔지니어/개발자 등이 클러스터를 운영하는데 활용. ServiceAccount는 쿠버네티스 서비스 또는 3rd party 서비스(Prometheus, Jenkins등)가 사용하는 계정. 각 네임스페이스마다 디폴트 ServiceAccount가 있다. 이 디폴트 ServiceAccount는 해당 네임스페이스의 모든 파드에 대해 기본적으로 사용되며, 이외의 ServiceAccount는 수동으로 생성하고 사용해야한다.
쿠버네티스 아키텍처
쿠버네티스 클러스터는 MSA(Micro Service Architecture) 구조에서 컨테이너 배포와 서비스 장애 복구와 같은 컨테이너 기반 서비스 운영에 필요한 대부분의 기능을 지원한다. 쿠버네티스 클러스터는 기본적으로 마스터와 워커 노드 형태로 구성된다. 마스터 노드는 물론 Control Plane(Orchestra)의 역할, 쉽게 말하면 제어판과 비슷한 역할, 그리고 워커 노드에서는 실제 워크로드가 실행 된다.
마스터 노드
마스터 노드에는 "Kubernetes Control Plane"을 구성하는 다양한 핵심 구성 요소가 있고, 관리적 작업에만 사용된다. 마스터 노드는 전체 클러스터를 관리하며, 워커노드에 예약된 작업을 할당하고 시스템의 상태를 관리한다. 본질적으로 쿠버네티스 클러스터의 뇌라고 생각하면 된다. 쿠버네티스 마스터 노드의 중요한 구성요소는 아래와 같다: `
- API Server:- 클러스터 내부 리소스를 제어하는 API를 제공하는 서버를 의미한다. 쿠버네티스의 리소스 정보를 관리하기 위한 프론트엔드 REST API. 각 컴포턴트로 부터 리소스 정보를 받아 데이터스토어(etcd)에 저장하는 역할을 갖고 있다. 다른 컴포넌트는 API Server를 통해 이 etcd 정보에 액세스한다. 개발자 혹은 시스템 관리자가 이 Server에 액세스하려면 kubectl 명령을 사용한다. 또 애플리케이션 안에서 API Server를 호출할 수도 있다.
- Scheduler:- 쿠버네티스 리소스에 대한 리소스 요청을 예약하는 역할을 한다. 스케줄러는 노드에 할당되어 있지 않은 Pod에 대해 쿠버네티스 클러스터의 상태를 확인하고 빈 공간을 갖고 있는 노드를 찾아 Pod를 실행 시킨다. 클러스터를 구성하는 워커 노드의 상태를 검토하여 리소스 할당이 필요한 리소스 요청을 처리할 최적의 노드를 선택 한다.
- Controller-manager:- 쿠버네티스 클러스터의 컴포넌트들의 상태를 모니터링 하고 본래 되어야 할 상태를 유지하는 백엔드 컴포넌트. 정의 파일에서 정의한 것과 실제 노드나 컨테이너에서 작동하고 있는 상태를 모아서 관리 한다.
- etcd(데이터스토어):- 쿠버네티스 클러스터의 구성 데이터를 저장하기 위해 사용되는 분산 키-값 저장소다. 노드 상태 및 서비스 상태와 같은 쿠버네티스 클러스터의 상태를 저장하는 데 사용된다. Key-Value형으로 관리하며 어떤 Pod를 어떻게 배치할지와 같은 정보를 갖고 있어서 API Server가 이를 참조한다. 이 데이터스토어는 마스터 서버에서 분리 시킬 수도 있다.
워커 노드
이전에는 '미니언' 이라고 불렸으며, 워커 노드는 쿠버네티스 클러스터의 애플리케이션 및 워크로드를 실행한다. 컨테이너를 실행하고 컨테이너 런타임 환경을 처리하는 역할을 한다. 워커 노드의 핵심 구성 요소는 아래와 같다:
- Kubelet:- 쿠버네티스의 주요 구성 요소로, 워커 노드에서 API 서버와 통신하여 쿠버네티스 클러스터에 노드를 등록한다. 파드의 라이프 사이클을 관리하고 노드 및 파드의 상태를 모니터링한다.
- Kube-proxy:- 모든 워커 노드에서 실행되며 각 노드에 대한 네트워크 규칙을 생성 및 관리하는 네트워크 프록시 역할을 한다. K8s 프라이빗 네트워크 내에서 적절한 서비스 또는 응용 프로그램으로 요청을 전달하는 reverse 프록시와 같은 역할을 수행 한다.
- Container runtime:- 모든 워커 노드에서 실행되며 컨테이너를 실행하고 관리하는 역할을 한다 (예: Docker).