Architecture/k8s

Kubernetes 아주 조금만 알아보자 - Kubernetes의 흐름

KOOCCI 2019. 5. 20. 01:38

※ 개인적으로 받았던 Kubernetes 교육을 정리한 내용입니다.

1편 > Kubernetes 아주 조금만 알아보자 - Kubernetes란? : https://koocci-dev.tistory.com/3

2편 > Kubernetes 아주 조금만 알아보자 - Kubernetes의 흐름 : 현재 Post

3편 > Kubernetes 아주 조금만 알아보자 - 마스터, 노드 : https://koocci-dev.tistory.com/6

4편 > Kubernetes 아주 조금만 알아보자 - Model, Declared State, Pod https://koocci-dev.tistory.com/10

5편 > Kubernetes 아주 조금만 알아보자 - ReplicaSets,Deployments : https://koocci-dev.tistory.com/11

6편 > Kubernetes 아주 조금만 알아보자 - Service : https://koocci-dev.tistory.com/12


MicroService 란?

마이크로 서비스Loosely coupled(느슨한 결합) 서비스의 집합이라 하고, 애플리케이션을 구성하는 서비스 지향 아키텍처 (Service-Oriented Architecture : SOA) 스타일의 변형인 소프트웨어 개발 기술이다.

이런 아키텍쳐이다 보니, 정교하고, 프로토콜이 가벼워진 특징을 가진다.

 

이렇게 만들면서 생기는 이익은 무엇일까?

정리해보면 다음과 같다.

 

  • 모듈성이 올라가며, Application이 아키텍쳐에 대해, 개발하고, 테스트하고, 복원하기 쉽게 한다.
  • 소규모로 개별 서비스를 개발, 배포 및 확장을 할 수 있어, Parallelize 하게 진행할 수 있다.
  • 지속적인 리팩토링이 가능하다.
  • 지속적인 배포 및 개발이 가능하다.

 

그렇다면, 위와 같은 이익을 볼 때, Microservice의 가장 궁극적인 목표는 무엇일까?

이는 "Speed of Change"라고 할 수 있다.

즉, 빠르게 변화를 주고, 확장하고, 변화에 대응하고, 이슈에 대응할 수 있는 부분이 가장 큰 목표라고 할 수 있다.

여기서 한가지 더 중요한 점은, Application 이라는 단어다.

OS Container (VM)과 App Container가 있을 때, Docker는 바로 App Container고, OS를 가상화시킨 것과 달리, App에 초점을 맞춘다.


아주 간단한 Kubernetes 구현

위 제목에서 구현이라 함은, Kubernetes의 흐름을 잘 이해하기 위한 Kubernetes 사용이 아닌, 구현이다

우리가 우리의 App을 쿠버네티스에 제공하여 서비스를 만드는데, 목적을 잘 생각하며, 쿠버네티스를 간략하게 만들어보자!

 

먼저, 우리는 Desired State를 Declare 하고 싶을 것이다.

앞선 포스트에 Kubernetes가 가장 열심히 수행하는 일이 Desired State를 Declare한다는 것이었다.

즉, 이 때 사용하고자 하는 것이, Kubernetes API 이다.

 

Kubernetes가 느슨한 결합(Loosely Connection/Coupled)을 필요로 하며, 이 역시 앞선 포스트에서 HTTP(Stateless, Connectionless)와 함께 설명하였다. 그럼, 여기서 API 형태는 자연스럽게 RESTAPI가 떠오를 것이다.

 

그러면, Kubernetes는 Kubernetes API(RestAPI)로 Desired State를 Declare하는 기능을 제공할 것이다. (Method는 Create이니, POST가 될 것이다)

그럼, 우리는 Desired State를 API를 통해 받아왔다. 이를 어떻게 할 것인가?

 

Stateless인 형태상, 결국 우리는 저장이라는 기능이 따로 필요로 할 것이고, 이를 Kubernetes에서는 Key,Value Store로 구현하였다.

K/V Store는 쿠버네티스가 구동되기 위한 많은 정보가 들어있고, 모든게 Stateless인 Kubernetes 세상에서 유일하게 StateFul한 존재다.

따라서 BackUp, 다중화등이 꼭 필요하다고 할 수 있다.

 

이렇게 API로 가져온 데이터를 Key/Value Store로 전달하기 위해서는 자연스럽게 Web Server가 필요하다.

지금까지 형태를 그림으로 그리면 다음과 같다.

Kubernetes 구성도 1


지금까지 우리는 Desired State가 어떻게 전달되는지 알아보았다. (Desired State의 Init은 당연히, 사용자가 지정해 준다)

그럼 현 상태(Actual State)는 어떻게 되어 있을까?

 

Desired State에 따라 처음 Created 되었을 때, 쿠버네티스는 Kubelet이라는 것과 연결한다.

Kubelet을 설명하기 전에, Kubernetes (Kubernetes Cluster)는 크게 2가지로 구성되어 있다.

1. The Masters : 클러스터를 담당하고, App Scheduling을 담당.
2. The Nodes (a.k.a minions/workers) : Application이 구동하는 곳. 결론적으로 Docker가 도는 곳.

앞서 말한, Kubelet은 Node의 일부이고, 결론적으로 App이 있는 Docker(혹은 Docker들) [=> 이후에 배울 Pod 개념] 가 확실히 동작하도록 관리하는 것이다.

따라서, 처음 Created 되었을 때, 이 App 서비스들이 올라가고, 현상태와 Desired State를 보며, 그 Gap을 줄이기 위해 노력한다.

이 말의 뜻은 Actual State를 계속해서 Desired State가 될 수 있게 노력한다는 것이다.

 

그럼 실질적으로 이렇게 Gap을 줄여주는 일을 하는 것은 무엇일까?

 

Kubernetes 안에는 여러가지 Controller가 있다. Desired State에서 선언된 이 Controller가 바로 그 Gap을 줄여준다.

 

우리는 하나의 Node를 띄우지 않는다. 여러 Node들이 띄워질 것이고, 이들을 어떻게 관리할 수 있을지, 누가 언제, 무엇을, 어떻게 분산해서 실행이 되는지 정해져야 한다.

 

바로 Scheduling 기능이다.

이는 정책적인 부분이고, 기본적으로 진행되는 부분도 있으며, 자유도 높게 Custom도 가능한 부분이 있다.

지금까지를 그림으로 다시 그려보면 다음과 같다.

Kubernetes 구성도 2


위 이미지의 빨간색 부분이 궁금해 질 것이다.

무엇이 Scheduling과 Controller를 다루는가?

앞서, Masters와 Nodes를 적어보았었다.

단순히 Kubelet은 "Node에 속해있는 관리 에이전트"라고 말했는데, 그렇다면 Master는 무엇일까?

 

바로 볼 수 있겠지만, Scheduling와 Controller를 담당한다.

Master는 1개라도 상관없다. 단, 죽으면 Controller에 API Call이 불가능하다 (Desire State를 모른다)

따라서, 보통 Master는 3개 혹은 5개로 설정한다.

그 이유는 다수결 결정을 하기 때문인데, 7개 이상은 Decision Making이 오래걸리고, 짝수는 다수결 결정에 알맞지 않기 때문이다.

 

그럼 위 내용을 통해 Master라는 개념을 가진 무언가가 등장해야 한다.

사실, Master는 Nodes중 하나다.

즉, 모든 것은 Node들이고, Master Role을 가진 것이 있다는 것이다.

따라서, Master Role을 하는 Node도 다른 Node와 같이, 하나의 App을 가진 Worker가 될 수 있다.

다만, 일반적으로 그렇게 사용하지 않고, Master의 역할만 하도록 만든다.

 

마지막으로, 통신의 흐름을 정리해보자.

Master가 만약, 모든 Nodes들에게 요청해 현 상태(Actual State)를 알아내고, Desired State와 비교한다면 그 부하는 어떻게 될까?

 

App이 많아질수록 점점 더 감당이 되지 않을 것이다.

따라서, 통신은 Kubelet -> Master형태가 이루어진다. Master는 현재 진행중인 Scheduler나 Controller 관련 API를 실행하기만 할 뿐, 현 상태에서 무엇인가 달라졌다는 정보 등은 Kubelet이 먼저 보고한다.

 

Image도 마찬가지다. 처음 Kubelet이 올라올 때 어떤 Image가 들어와야하는 지는 Kubelet이 Master에 물어보고, Master는 K/V Store에 들어있는 Registry 위치를 반환해준다. (Image는 Registry에 보관되어 있다(이전 포스트 참조))

 

Master가 먼저 Kubelet에게 통신하는 경우는 장애가 생겼을 때, 어떤 장애인지 물어볼 때 이외에는 없다.

따라서, 최종형상은 다음과 같다.

Kubernetes 구성도 3
Kubernetes 구성도 4

위 이미지 중, 아래 구성도 4의 경우는 구글 이미지에서 본 아키텍쳐이고, 아직 적어놓지 않은 개념도 있지만

내가 그린 것보다 쉽게 이해할 수 있을 것 같아 첨부하였다.


아주 간단한 Kubernetes Deployment

하나씩 정리해볼 필요가 있을 것 같다.

이론적으로 Kubernetes를 사용하려면 그럼 어떻게 해야할까?

 

간단히 정리해보면 다음과 같다.

1. App(Docker) 부터 Containerize
2. Desire State를 Confine (JSON/YAML)
3. HTTP Call

먼저, Container가 있어야 한다. Docker등, App이 Container로서 구현이 되어야 한다.

그리고, Desire State를 Kubernetes에 알려주어야 한다.

 

이 부분은 흔히, yaml로 작성이 되며, (가독성이 좋다) Manifast File이라고 한다.

이 Manifast File을 다음 2가지를 알려준다. (Desire State에 속하는 내용이다)

1. 우리 앱이 어떤 상태를 가질 것인가? (사용할 이미지, 공개할 포트, 가입할 네트워크, 업데이트 수행 방법 등
2. 실행(확장)할 App의 Replica는 몇 개 가질 것인가? (Scale)

이 파일은 Master에게 전달이 된다.

그리고 Http Call이 진행되면, 나머지는 Kubernetes가 알아서 진행한다.

이 다음 포스트에서는 Master와 Node에 대해 조금 더 자세히 알아보도록 하자.