- Published on
K8s 공부 (1)
- Author
- Name
- yceffort
https://www.youtube.com/watch?v=X48VuDVv0do
Table of Contents
1. K8s는 무엇인가?
K8s
- 오픈소스 컨테이너 오케스트레이션 도구
- 구글에서 개발
- 컨테이너화된 애플리케이션을 관리하기 쉽게 도와주는 역할
- 수백~수천개의 다른 환경에 있는 컨테이너에 있는 애플리케이션을 관리하게 쉽게 해준다.
K8s 는 무엇을 해결하려 하는가?
- 모노리스에서 마이크로 서비스로 트렌드가 넘어가고 있음
- 그에 따라서 컨테이너가 많아지고 있음
- 이렇게 다른 환경에 있는 다른 컨테이너들을 쉽게 관리하고자 함
오케스트레이션 도구?
- 고가용성으로, 다운타임이 없다
- 확장성이 뛰어나고, 고성능을 제공할 수 있다.
- 장애로부터 복구가 빠르게 이뤄질 수 있다. (백업, 복구)
2. K8s 주요 컴포넌트
먼저 아주 간단한 예로, 애플리케이션과 데이터베이스만 있는 서비스를 상상해보자.
Node
- 여러개의 pod를 묶는 하나의 단위
- 한대의 서버라고 보면됨
Pod
- K8s에서 가장 작은 단위
- 컨테이너를 추상화 한 것
- 추상화 한 이유는, 대체 하기 쉽고, docker등 다른 컨테이너 기술을 사용하게 할 수 있게 하기 위함
- 따라서 직접 다루는게 아니라, K8s의 레이어에서 다룬다고 볼 수 있음
- pod안에는 일반적으로 하나의 애플리케이션 컨테이너만 실행하도록 함.
- 물론 여러개를 다루는 것도 가능.
위 예제에서는, 하나의 서버에서 두개의 컨테이너가 두개의 pod로 실행되고 있다고 보면 된다.
Service
- K8s는 내부적으로 가상 네트워크를 활용하며, 각 pod는 고유 ip를 가진다. (컨테이너가 아님)
- 각 pod는 이 내부 ip로 통신 가능
- 그러나 pod는 쉽게 죽고, 쉽게 대체가 가능하며, pod가 죽어버리면 새로운 pod가 생성되는데, 이 때 새로운 ip를 할당받아버리므로 ip를 기준으로 통신하는 것은 비효율적임
- 영구적인 IP 주소를 pod에 주는 도구
- pod의 라이프사이클과 서비스가 공유되는 것은 아니므로, pod가 죽어도 서비스의 ips는 유지됨.
- internal과 external로 나눌 수 있으며, internal은 내부에서만 사용 가능
- external을 사용하면 외부와 통신이 가능하나, IP주소와 PORT가 있는 형태라 외부로 공개하기엔 부적절함
Ingress
- 서비스를 외부 주소와 연결하는 도구
- 우리가 일반적으로 알고 있는 URL로 external service를 연결해준다.
ConfigMap
pod가 서비스를 통해서 서로 통신한다는 것을 알게 되었다. 만약 애플리케이션에서 DB의 주소가 필요하다고 하면 어떻게할까? 일반적으로는 환경변수 등을 통해서 DB의 주소 등을 주입할 것이다. (빌드 시) 만약 서비스의 명이나 주소가 바뀌면, 빌드를 새로 해서 다시 해야하는 번거로움이 존재한다.
- 애플리케이션에서 사용하는 외부 변수등을 쓸 수 있게 하는 도구
- pod와 연결하여, ConfigMap에 있는 데이터를 pod에서 가져다가 쓸 수 있음.
Secret
- 민감한 정보 (암호 등)의 경우에는 ConfigMap을 사용하지 않음
- 보안상 중요한 데이터를 plain text가 아닌 base64로 저장해서 ConfigMap과 같이 동일하게 사용할 수 있는 도구
ConfigMap
과 Secret
은 pod에서 환경변수나 속성파일 (yaml, json 등)으로 접근해서 가져다가 쓸 수 있다.
Volumes
- 데이터베이스의 데이터 같은 경우에는, pod안에 해당 데이터가 있다면 pod가 죽어버리면 그 데이터도 날라가게 된다.
- 영구적인 데이터를 저장하기 위해 쓰는 것이 Volume
- 마치 물리적인 하드디스크를 pod에 붙이는 것이라 볼 수 있음
- local, remote, cloud등 어떤 형태로든 가능
- Pod가 재시작되도, 데이터는 별도의 위치에 존재하기 때문에 영구성을 유지할 수 있음
- 따라서 이러한 데이터는 K8s 외부에서 잘 관리해야됨.
Deployment
- 일반적인 경우에는, 사용자가 외부에서 애플리케이션을 접근할 수 없게 된다. 그러므로 하나의 pod만 관리하는 것은 위험
- 따라서 K8s에서는 모든 것을 복제(Replicate)한다.
- Node를 여러개로 복제한다음, 하나의 서비스에 다 연결 시킨다.
- 서비스는 영구적인 IP를 가지고 있고, 내부적으로 로드밸런서도 가지고 있음. 따라서 하나의 pod가 죽거나 바쁘다면, 다른 pod로 알아서 넘겨준다
- 이런식으로 pod를 여러개 복제하기 위해서는 pod의
blueprint
를 정의해야 한다. 이blueprint
에는 얼마나 많은 pod들을 가질 지 정의할 수 있음 - 이러한 나의 애플리케이션 내부의 pod의
blueprint
를 정의한 것이 Deployment다. - 일반적으로 K8s에서는, 직접 pod를 만들지 않는다. deployment를 만들고, 그것이 blueprint에 따라서 알아서 pod를 만든다.
- 여러 pod를 추상화 한것으로 보면 된다.
StatefulSet
- 그러나 데이터베이스는 상태, 즉 데이터가 있기 때문에 deployment로 복제할 수 없음.
- 만약 여러개로 데이터베이스 pod를 복제한다면, 이들이 같은 volume에 접근하려 할 것이다. 이렇게 되면 터의 불일치가 발생하게 된다.
- 그렇기 때문에 이런 상태가 필요한 pod 들은, Deployment가 아니라 StatefulSet으로 만들어져야 한다.
- 마찬가지로 복제하거나, 스케일링을 할 수 있으며, 데이터 베이스들간에 불일치가 발생하지 않도록 도와주는 역할을 한다
- 이건 deployment에 비해 다루기 어려워서, K8s 외부에서 일반적으로 관리한다
요약
- Pod: 컨테이너들을 추상화 한것
- Service: Pod간 통신에 사용
- Ingress: 외부 트래픽을 K8s내부 클러스터로 유입시키기 위한 것
- ConfigMap: 외부 설정
- Secrets: 외부 설정 (보안상 민감한 데이터)
- Volumes: 영구적인 데이터 관리
- Deployment: pod등을 정의하는 것
- Statefulset: 영구적인 데이터를 위한 Deployment
3. K8s의 아키텍쳐
일반적으로 master와 slave 노드로 구성되어 작동된다.
- 각 노드들은 여러개의 pod를 실행하고 있다.
- 워커 노드란 일반적인 작업을 하고 있는 노드를 의미한다.
- 노드에는 세가지 프로세스가 필수적으로 필요하다.
- Container Runtime: 도커 등
- kublet: pod와 컨테이너의 스케쥴을 관리하는 도구. 컨테이너 런타임과 노드의 머신간에 상호작용을 담당. 실제로 pod를 실행하는 역할을 담당하고 있음. 노드에서 CPU 등의 자원을 할당하는 역할을 하고 있다.
- kube proxy: 서비스로들어온 요청을 pod에 전달하는 역할. 네트워크의 오버헤드를 줄이기 위해서, 하나의 요청이 들어왔을 때 동일한 pod의 동일한 db로 가게하는 등의 역할도 하고 있음
이러한 프로세스를 관리하는 것이 마스터 노드에서 이루어진다.
Master Process
여기에는 4개의 process가 필요하다.
- Api server: Cluster gateway, 인증 게이트 키퍼. UI 대쉬보드나, kublet 같은 ci 도구로 노드를 제어할 수 있게 하는 역할. 새로운 pod를 만들거나, 서비스, 컴포넌트를 만들고 싶다면 마스터 서버의 api server를 거치게 된다. api server는 이러한 요청을 검증하고 (인증, 요청의 정합성 등) 이를 다른 프로세스에 전달하여 실행하게 하는 역할을 한다.
- Scheduler: api server로 요청을 보낸다면, 스케쥴러가 이를 받아서 애플리케이션 pod나 컴포넌트를 시작하게 하는 역할을 하고 있음. pod가 어느 노드에 둬야 하는지를 알아서 현명하게 결정함. 노드의 가용성등을 보면서 알아서 결정함. 스케쥴러는 단순히 어느 노드에 pod를 둬야 하는지만 결정함. 그리고 이를 실제로 실행하는 것은 kublet.
- Controller Manager: 클러스터의 상태변화 (pod가 죽는 경우 등)를 감지하여, 이를 가능한 빨리 복구하도록 스케쥴러에게 명령하는 역할을 하고 있음.
- etcd: key-value store. 클러스터의 모든 변화를 기록하는 역할. 클러스터에 필요한 모든 정보가 담겨 있음. (애플리케이션 관련 정보는 없음) 이 정보는 매우 중요하므로, 여러개의 master 노드를 가지고 있음.
일반적인 세팅
- 2개의 마스터 노드 (리소스를 적게 할당)
- 3개의 worker node (실제 애플리케이션을 담당하므로 많은 자원을 할당)
- 이들 모두 필요에 따라 증가 시킬 수 있으며, 필요한 프로세스만 설치하면 됨.