이야기박스
Kubernetes 1. Introduction 본문
# 쿠버네티스 필요한 이유
최근 어플리케이션 개발 트렌드가 변화하였기 때문입니다. 과거에는 거대한 모놀리식 애플리케이션 개발/운영이었다면, 요즘 들어서는 "마이크로 서비스"로 세분화되고 애플리케이션을 실행하는 인프라도 사설 IDC에서 거대한 클라우드 플랫폼으로 옮겨가고 있습니다.
모놀리식 방법은 여러 서비스가 단일 OS 환경에서 실행되기 때문에 하나의 개체로 관리(개발, 배포 등)가 이루어져야 합니다. 이러한 구조의 단점은 아래와 같습니다.
- 조금의 변경만 있더라도 전체 어플리케이션을 재배포해야 합니다.
- 시간이 지날수록 어플리케이션 내 서비스 간의 경계가 모호해져서 프로그램은 점점 더 복잡해지고 유지보수가 어렵게 됩니다.
- 프로그램 자체가 무겁기 때문에 높은 성능의 서버가 필요합니다.
- Scaling-up : 좋은 하드웨어는 비쌉니다..
- Scaling-out : 상대적으로 저렴하지만, 관리가 많이 복잡해집니다.
마이크로 서비스는 이러한 모놀리식의 단점을 보완하기 위하여 등장하였습니다. 마이크로 서비스는 모놀리식 애플리케이션에서 제공되는 서비스들을 배포 가능한 수준의 구성요소로 나누어 독립적인 프로세스로 실행합니다. 마이크로 서비스는 일반적으로 RESTful API를 제공하여 서로 다른 서비스 간 통신이 가능하도록 하고 있습니다. 그렇기 때문에 마이크로 서비스 간의 구현 언어의 선택은 자유로운 편입니다. 또한 마이크로 서비스는 위에서 이야기하였듯이 보통 정적인 외부 API가 있기 때문에 서비스의 변경이 이루어져도 제공하는 API가 이전 버전과 호환이 되는 방식으로 변경된다면 다른 마이크로 서비스에는 지장이 적은 편입니다.
마이크로 서비스의 확장은 모놀리식의 비해 단순합니다. 모놀리식은 전체 시스템을 확장해야 했지만, 마이크로 서비스는 부족한 리소스의 서비스만 확장해주면 됩니다.
하지만 위의 확장/배포에서 마이크로서비스가 가지는 큰 단점이 있습니다. 배포해야 할 서비스가 적은 경우에는 문제가 없지만, 많은 서비스를 배포해야 하는 경우 문제는 복잡해지게 됩니다. 또한 마이크로 서비스는 여러 프로세스와 시스템에 분산되어 배포되기 때문에 이들 서비스들의 호출과 디버깅과 같은 관리 문제도 우리를 복잡하게 합니다.
# DevOps & NoOps
비교적 최근에 DevOps가 하나의 트렌드로 자리 잡았던것 같습니다. DevOps란 개발, 배포, 운영을 하나의 통합된 프로세스로 묶어서 협업을 통하여 매뉴얼 된 작업을 자동화하여 효율을 극대화한 작업 방식입니다. 하지만 이러한 방법은 개발자가 인프라와 하드웨어의 구성 정보, 운영 프로세스 들을 어느 정도 알고 있어야 하니 순수 개발에 몰두할 수 없는 환경을 만들게 되었던 것 같습니다.
그러다 보니 요즘 들어서는 개발자가 하드웨어 인프라를 몰라도 되고 운영팀을 거치지 않고 배포할 수 있는 NoOps라는 방식이 대두되고 있습니다. 사실 아직 그렇게 보편화된 작업 방식이 아닌것 같지만, 쿠버네티스를 통하여 멀지 않은 미래에 실현될 수 있을 것 같습니다.
# 컨테이너
과거의 개발에서는 소프트웨어 컴포넌트들의 충돌을 방지하기 위하여 VM을 구성하여 이들을 분리하였었습니다. 하지만 서비스가 점차 작아지고 수가 늘어나기 시작하니 적합한 리소스의 VM을 제공하는 일이 점차 어려워지기 시작했습니다. 이러한 상황에서 각 컴포넌트들을 격리하기 위하여 컨테이너(Container)의 개념이 도입되었습니다.
별도의 게스트 OS를 가지던 VM과는 달리 컨테이너는 호스트 OS를 공유하게 됩니다. 단, 다른 프로세스와는 여전히 분리되어 있는 상태입니다. 해당 프로세스 내부에서 본다면 자신이 해당 System & OS에서 실행되고 있는 유일한 프로세스처럼 보일겁니다. 또한 VM과 다르게 컨테이너는 하드웨어 자체 시스템/프로세스 집합을 실행/관리할 필요가 없기 때문에 훨씬 가볍게 동작할 수 있습니다.
컨테이너는 다음 두가지 매커니즘을 통하여 프로세스 격리를 가능하게 해 줍니다.
- Linux Namespaces : 각 프로세스가 파일, 프로세스, 네트워크 인터페이스, 호스트 이름 등 시스템에 독립 뷰를 제공
- cgroups : 프로세스가 소비할 수 있는 리소스 양을 제한하는 리눅스 컨트롤 그룹
# 도커
물론 도커 이전에도 컨테이너는 사용되고 있었지만, 도커의 등장 이후에 더욱 크게 알려지게 되었다고 합니다. 도커는 컨테이너를 여러 시스템에 쉽게 이식할 수 있게 해주는 컨테이너 시스템입니다. 개발자는 도커가 운영되고 있는 다른 머신에 간단하게 애플리케이션 프로비저닝 작업을 진행할 수 있습니다. 심지어 OS가 달라도 리눅스 계열이라면 가상 머신과 동일한 수준의 격리 효과를 보실 수 있습니다.
도커를 다시 정의하자면, 애플리케이션의 패키징, 배포, 실행 플랫폼이라고 할 수 있습니다. 애플리케이션을 전체 환경과 함께 패키징하고 이를 중앙 스토리지로 전송한 후, 도커를 실행하는 시스템에 패키지를 전송하여 사용할 수 있습니다. 도커의 세 가지 주요 개념은 아래와 같습니다.
- 이미지
- 애플리케이션 + 환경을 패키지로 묶은 것
- 메타 데이터 (이미지가 실행될 때 실행해야 하는 실행 파일의 경로 등)
- 애플리케이션에서 사용할 수 있는 파일 시스템
- 레지스트리
- 이미지를 저장하는 스토리지
- 레지스트리에 이미지를 푸시, 다른 컴퓨터에서 이미지를 다운로드하여 실행
- 공개/비공개 레지스트리 존재
- 컨테이너
- 일반적인 형태의 리눅스 컨테이너
- 리소스가 제한되어 있음
- 동일한 호스트에서 실행되고 있는 다른 프로세스와 완전히 독립되어 있음
참고로 도커 이미지는 레이어로 구성되어 있습니다. 또한 도커 이미지는 다른 이미지 위에 올라갈 수 있기 때문에 동일한 레이어를 포함할 수도 있습니다. 컨테이너 이미지 레이어는 읽기 전용으로 구성되어 있기 때문에 그 위에 이미지가 올라가게 되면 별도의 쓰기 전용 레이어가 구성됩니다. 그래서 동일한 이미지 레이어 위에 있어도 서로 완전히 독립된 프로세스처럼 동작할 수 있습니다.
이론상으로는 컨테이너 이미지는 도커를 실행하는 모든 리눅스 시스템에서 실행할 수 있습니다. 한 가지 주의할 점은 컨테이너가 호스트의 리눅스 커널을 사용한다는 것입니다. 만약, 컨테이너가 특정 커널 버전을 요구한다면 어떠한 시스템에서는 동작하지 않을 수 있습니다.
## rkt (락잇) ; 도커의 대안
실제 프로세스 격리는 컨테이너에서 리눅스 네임스페이스, cgroups의 역할이지 도커가 해주는 게 아닙니다. 도커는 이런 기능을 쉽게 사용할 수 있도록 도와주는 역할을 합니다. rkt도 도커와 마찬가지로 이러한 컨테이너 실행 플랫폼이라고 이해하시면 될 것 같습니다. rkt도 OCI에서 정의한 컨테이너 이미지 형식을 사용하고 있기 때문에 도커 컨테이너 이미지를 사용할 수도 있습니다.
원래 쿠버네티스는 도커만 지원하였었지만, 최근들어 rkt도 지원하기 시작하였기 때문에 언급만 하고 들어가도록 하겠습니다.
# 쿠버네티스
드디어 이번 포스트의 마지막 콘텐츠인 쿠버네티스입니다. 쿠버네티스는 구글에서 개발된 Borg라는 다수의 애플리케이션과 서비스를 관리할 수 있는 내부 시스템에에서 발전하여 출시된 오픈소스 시스템입니다. 쿠버네티스를 사용하면 마치 모든 노드가 하나의 거대한 컴퓨터인 것처럼, 수천 개의 컴퓨터 노드에서 소프트웨어 애플리케이션을 실행할 수 있습니다. 기본 인프라를 추상화하고 이는 개발, 배포, 관리를 단순화해줍니다.
## 쿠버네티스 개요
쿠버네티스 시스템은 마스터 노드와 다수의 워커 노드로 구성됩니다. 개발자가 애플리케이션 매니페스트를 마스터에 제출하면 쿠버네티스는 이 내용을 워커 노드 클러스터에 배포해줍니다. 개발자/관리자는 해당 애플리케이션이 어떠한 노드에서 배포되었는지 신경쓸 필요가 없습니다. 쿠버네티스가 모든걸 관리해주거든요. 만약 특정 노드를 지정한다면, 쿠버네티스는 동일한 워커 노드에 배포해주기도 합니다.
즉, 쿠버네티스는 다음 두 가지의 핵심 요소를 가지고 있습니다.
1. 개발자가 핵심 애플리케이션 기능에 집중할 수 있도록 해줍니다.
쿠버네티스는 클러스터 운영체제와 같이 서비스 검색, 로드 밸런싱, 자가 회복, 리더 선출 같은 서비스를 제공해줍니다. 이를 통해서 개발자는 인프라 관련 구축에 대한 시간을 아낄 수 있게 되었습니다.
2. 운영팀이 효과적으로 리소스를 활용할 수 있도록 도와줍니다.
쿠버네티스는 실행을 유지하고 워커 노드가 서로 통신할 수 있도록 컴포넌트에게 정보를 제공하기 때문에 운영팀이 해당 애플리케이션을 배치, 관리하는데 큰 도움을 줍니다.
## 쿠버네티스 클러스터 아키텍처
쿠버네티스 클러스터는 전체 시스템을 관리하고 통제하는 컨트롤 플레인이 있는 마스터 노드와 실제 배포가 이루어지는 워커 노드로 구분됩니다. 두 구성 요소의 자세한 내용은 다음과 같습니다.
### 컨트롤 플레인
마스터 노드라고도 불리는 컨트롤 플레인은 클러스터를 관리하고 기능을 실행하는 역할을 합니다. 단일 마스터 노드로 구성될 수도 있고, HA를 지원할 수 있는 여러 노드로 분할되어 구성될 수도 있습니다. 구성요소는 다음과 같습니다.
- 쿠버네티스 API 서버 : 외부와의 통신을 담당합니다. (워커노드, 사용자 등 )
- 쿠버네티스 스케줄러 : 애플리케이션의 배포 가능한 각 구성 요소에 워커 노드를 할당하는 작업을 하게 됩니다.
- 컨트롤러 매니저 : 구성 요소 복제, 워커 노드 추적, 노드 장애 처리 등 클러스터 수준 기능을 실행하는 역할을 합니다.
- etcd : 클러스터 구성을 지속적으로 저장하는 안정적인 분산 데이터 스토리지입니다.
컨트롤러 플레인은 클러스터를 관리할 뿐, 애플리케이션을 실행하지는 않습니다! 실행하는 건 아래 나올 워커 노드에서 이루어집니다.
### 워커 노드
애플리케이션을 실행, 모니터링 등의 작업이 이루어지는 시스템입니다. 구성 요소는 아래와 같습니다.
- 컨테이너 런타임 : 위 아키텍처 그림에서는 안 나왔지만, kubelet과 연결되어 있고, 컨테이너의 실행을 담당합니다. 도커 또는 rkt라 생각하시면 됩니다.
- Kubelet : API 서버와 통신하고 노드에서 컨테이너를 관리해주는 역할을 합니다.
- 쿠버네티스 서비스 프록시 : 애플리케이션 구성 요소 간 네트워크 트래픽을 분산시켜주는 역할을 합니다.
## 쿠버네티스 애플리케이션 실행
실행은 단순합니다. 우선 하나 이상의 컨테이너 이미지를 패키징하여 레지스트리에 푸시합니다. 그리고 쿠버네티스 API 서버에 애플리케이션의 디스크립션을 게시해야 합니다. 디스크립션에는 컨테이너 이미지와 애플리케이션 컴포넌트, 컴포넌트 간의 노드 배치나 관련성, 실행 복제본 수 등의 정보들이 포함됩니다.
Pod의 개념은 다음에 다시 다루도록 하겠습니다. 우선 컨테이너의 묶음이라고 간단하게 생각하시면 될 것 같습니다.
애플리케이션이 디스크립션을 처리할 때, 스케줄러는 각 그룹에서 필요한 연산 리소스와 각 노드의 할당되지 않은 리소스를 기반으로 사용 가능한 워커 노드로 컨테이너 지정 그룹을 예약합니다. 이후, Kubelet이 컨테이너 이미지를 가져와서 컨테이너 런타임에게 실행을 지시합니다.
애플리케이션이 실행되면 쿠버네티스는 지속적으로 배포된 상태가 사용자가 제공한 디스크립션과 일치하는지 확인합니다. 만약 인스턴스가 정상 동작하지 않는다고 판단되는 경우, 쿠버네티스는 인스턴스를 자동으로 다시 시작합니다. 마찬가지로 워커 노드 레벨에서 정상적이지 않은 상황이 판단되면 쿠버네티스는 새로운 워커 노드를 선택하고 실행하게 됩니다.
애플리케이션의 실행 도중, 사용자는 Replica 개수를 변경할 수 있습니다. 또한 최적의 레플리카 개수를 정하기 어려운 경우, 쿠버네티스에게 판단을 맡길 수도 있습니다. 쿠버네티스에게 맡기는 경우, 리소스의 상황을 보고 이를 자동으로 조정하게 됩니다.
컨테이너는 클러스터 내부를 특정 이유에 의해서 이동하면서 서비스가 될 수 있습니다. 쿠버네티스는 컨테이너가 클러스터 내 노드를 계속 이동해 다니더라도 Kube-proxy를 통하여 위치를 확인할 수 있고 항상 클라이언트가 해당 컨테이너에 연결할 수 있도록 도와줍니다.
## 쿠버네티스 장점
쿠버네티스가 모든 서버에 적용되어 있다면 운영팀은 더 이상 배포를 담당할 필요가 없겠죠. 또한 시스템 관리자의 도움 없이 손쉽게 애플리케이션을 실행할 수도 있습니다.
자세한 쿠버네티스의 장점은 아래와 같습니다.
- 애플리케이션 배포 단순화
- 개발자가 자체적으로 배포 가능
- 어떠한 서버에서 실행되고 있는지 신경 쓰지 않아도 됨
- 쿠버네티스가 실행할 하드웨어 환경도 적절하게 찾아서 실행해줌
- 높은 하드웨어 활용도
- 인프라와 애플리케이션의 분리
- 쿠버네티스가 가용 리소스에 맞추어 적절하게 배치
- 상태 확인, 자가 치유
- 모니터링 지원
- 장애 시 자동으로 재 조정
- 오토스케일링
- 부하 급증에 대해서 쿠버네티스가 자체적으로 오토스케일링 지원
- 가용 리소스만 적절하게 등록해주면 됨
- 애플리케이션 개발 단순화
- 모두 동일한 환경에서 실행된다는 보장이 주어지기 때문에 개발이 단순화됨
- 새로운 버전이 릴리즈 된 경우, 만약 문제가 발생하면 쿠버네티스가 자동으로 롤아웃 진행해 줌
# 마무리
이상으로 쿠버네티스 도입 부분을 마치겠습니다. 거의 책을 그대로 옮기다시피 적었네요.
이론 공부는 실습에 비해 흥미도 떨어지고 지치기 마련이지만 이걸 잘해두어야 나중에 실습에서 시행착오를 조금이라도 줄일 수 있다고 생각됩니다. 열심히 파이팅하면서 쿠버네티스를 공부하여 배포 고수가 되도록 합시다!
'Computer & Data > Orchestration' 카테고리의 다른 글
Kubernetes vs Mesos with Marathon (0) | 2019.04.25 |
---|---|
Mesos; Master, Slave, Marathon 설치 (0) | 2019.04.24 |
VirtualBox를 통한 클러스터용 VM 생성 (0) | 2019.04.23 |
Mesos; 자원 관리 플랫폼 (0) | 2019.04.17 |
Kubernetes 스터디 시작 (0) | 2019.04.12 |