Legacy System 은
그러나 요즘은 :
Microservice (작고 독립적, 개별적으로 개발, 배포, 업데이트, 확장)
빠른 대응과 개발이 가능해졌다.
배포할 컴포넌트의 수가 많아지고 데이터 센터가 확장되며, 운영하기 까다로워졌다. 어디에 어떤 컴포넌트를 배치할지 결정하고 자원을 효율적으로 운영하기 위해 수작업 관리하는 것은 사실상 어려워졌다. 자동화가 필요해진 순간이다.
k8s를 통해 우리는:
많은 기업들이 k8s를 채택하며 클라우드 및 온프레미스(기업 자체 인프라 운영)를 아우르는 분산 애플리케이션 실행의 표준 방식으로 자리 잡았다.
개발/배포 방식의 변화 : monolithic → microservice
Monolitic apps는 모든 구성 요소가 하나로 움직이기 때문에 개발, 배포 및 관리도 하나의 단위로 이루어져야 한다. 그렇기 때문에 일부분 수정이 곧 전체 재배포로 이어진다.
Monolithic apps에서 서버 확장이 필요할 땐 두 가지 방법이 있다:
그래서 이 거대한 앱을 잘게 쪼개기 시작했다. 각 microservice들은 독립적 프로세스이고 다른 서비스와 API - HTTP, AMQP 등 -로 소통한다. 그래서 일부분 수정이 있어도 전체를 갈아엎을 필요가 없어졌다.
마이크로서비스의 스케일링은 개별 서비스 단위로 가능하다. 리소스가 많이 필요한 서비스만 선택적으로 확장 가능하다. 예를 들어, 일부 컴포넌트는 여러 서버에서 복제되어 실행되고 어떤 컴포넌트는 단일 프로세스로 돌아간다.

물론 마이크로서비스가 능사는 아니다. 컴포넌트 수가 적을 땐 관리하기 쉽지만, 그 수가 늘어날수록 배포 관련 이슈를 다루기 어려워지고(왜냐면 서로간 의존성의 수도 증가하기 때문에) 서비스 간 소통을 관리해 하나의 시스템으로 작동할 수 있도록 하는 게 까다로워진다.
마이크로서비스들은 서로 다른 라이브러리를 사용하기 때문에 구성 요소 간의 의존성 차이가 발생한다. A 서비스는 lib a v1.0를 쓰지만 B 서비스는 lib a v2.3을 쓸 수 있다. 이게 얽히고 설키다 보면 동일한 서버에 배포할 때 의존성 관리가 힘들어진다.
가장 큰 문제는 서비스들이 각기 다른 환경에서 돌아간다는 점이다. 단일 production machine도 환경이 계속 일정할 거라고 보장할 수 없다.
하드웨어, 운영체제, 라이브러리 등 개발 환경과 운영 환경을 동일하게 유지해야 prod 환경에서 발생하는 문제를 줄일 수 있는데, 현실적으로 어렵다.
DevOps : 개발자, QA, 운영 팀이 전체 프로세스동안 협력한다.
NoOps : 운영팀을 거치지 않고 개발자 스스로 배포한다. ← k8s의 도움과 함께
k8s를 통해 개발자는 실제 하드웨어에 대해 자세히 알지 못해도 배포가 가능하며, 시스템 관리자는 앱에 대해 자세히 알 필요 없이 인프라 유지 관리에 집중할 수 있다.
k8s는 리눅스 컨테이너를 이용한다.
application이 적은 컴포넌트로 이루어져 있다면 각 컴포넌트마다 VM을 줄 수 있다. VM에는 각자 필요한 게스트 OS가 들어있다. 그래서 VM을 많이 쓸 수록 하드웨어 자원을 많이 잡아먹기 때문에 비효율적이다.
VM대신 linux Container 기술이 더 많이 쓰인다. 컨테이너는 서비스들을 동일한 호스트 OS에서 실행하면서 각 서비스를 격리시킨다. 컨테이너끼리 격리되어 있기 때문에, 모든 서비스들이 호스트 OS에서 돌아가도 각 서비스는 OS위에서 혼자 돌아가는 것처럼 보인다.
컨테이너는 VM에 비해 가볍다. 오버헤드도 적다. 그래서 VM보다 훨씬 많은 수의 서비스를 각자 독립된 컨테이너 환경에서 실행할 수 있다. VM과 달리 게스트 OS를 가지지 않기 때문에 부팅 시간을 기다리지 않아도 된다.

그런데 컨테이너들은 동일한 호스트OS위에서 돌아가는데, 어떻게 환경이 격리되었다 말할 수 있을까? 다음 두 메커니즘이 이를 가능하게 한다:
Linux Namespace의 종류:
예를 들어, UTS 네임스페이스를 두 개 생성하면 각 네임스페이스는 서로 다른 로컬 호스트네임을 가질 수 있다.
도커는 애플리케이션 패키징, 배포, 실행을 위한 플랫폼이다. 애플리케이션과 더불어 그 환경 전체 또한 함께 패키징할 수 있다. 이 패키지를 중앙 저장소에 전송하고 필요한 서버가 이를 다운로드 받아 실행할 수 있다. 도커의 세 가지 요소는 다음과 같다:

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

분명 컨테이너끼리 격리된 환경에서 돌아간다고 했는데, 컨테이너 1과 2가 같은 파일시스템을 공유하고 있다. 이는 도커 이미지가 여러 겹의 레이어로 구성되어 있기 때문이다.
서로 다른 이미지여도 같은 레이어를 가지고 있을 수 있다(parent layer). 레이어는 한 번만 저장되기 때문에, 겹치는 레이어가 있다면 두 번 저장할 필요 없이 위 그림처럼 파일시스템(레이어)을 공유할 수 있다. 파일시스템을 공유하며 한 컨테이너가 파일을 수정하면 다른 컨테이너에 영향을 미칠까? 그렇지 않다. 이미지 레이어는 read-only이기 때문에, 수정이 일어나면 새로운 writable layer가 생성되어 파일 변경 사항은 최상위 레이어로 쌓인다.
이론적으론 컨테이너가 도커가 설치된 모든 리눅스 머신에서 돌아갈 수 있지만, 예외가 있다. 컨테니어는 호스트의 커널을 이용하는데, 만약 애플리케이션이 특정 커널 버전이나 모듈을 써야 한다면 어떤 머신은 제한될 수 있다. 또한 특정 하드웨어 아키텍처용으로 빌드된 컨테이너는 다른 아키텍쳐 위에서 돌아갈 수 없다 (a86 → AFM 불가능). 이런 경우엔 VM이 여전히 필요하다.
구글이 글로벌 회사가 되며, 수 천개의 애플리케이션의 개발 및 배포를 잘 관리할 수 있는 솔루션을 만들어야 했다.
구글은 내부적으로 Borg와 Omega를 만들어 개발자 및 시스템 관리자가 수 많은 애플리케이션과 서비스를 관리하는 데에 사용했다. 개발과 관리를 쉽게만들 뿐 아니라 인프라 활용도를 끌어올렸다. 한동안 이 시스템들을 비밀에 부쳤다 2014년 오픈 소스 시스템으로 Kubernetes를 발표했다.
K8s는 당신이:

K8s는 마스터 노드와 워커 노드로 이루어져 있다. 개발자가 앱 리스트를 마스터에 넘기면 k8s는 워커 노드 클러스터에 배포한다. 만약 특정 앱들이 같이 실행되어야 한다면 k8s는 같은 워커 노드에 그것들을 배포한다. 아니면 일반적으론 클러스터 곳곳에 흩뿌려 놓는다.
K8s 덕분에, 개발자는 core app feature 개발에 집중할 수 있고, 운영팀은 리소스를 더 잘 활용할 수 있다.
K8s 클러스터는 여러 노드들로 구성된다. 노드는 두 가지 종류로 분류할 수 있다.

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

앱이 실행되면 k8s는 그 상태가 description과 일치하도록 지속적을 관리한다. 예를 들어, 웹 서버 인스턴스를 항상 5개 실행하도록 지정했다면 k8s는 정확히 5개의 인스턴스를 실행 상태로 유지한다. 만약 하나의 인스턴스가 fail하면, 자동으로 해당 인스턴스를 재시작한다. 마찬가지로, 전체 worker node가 실패하거나 접근이 불가능하면 k8s는 해당 노드에서 실행중인 컨테니어들을 새로운 노드로 재배치한다.
앱이 실행되는 동안 replica 수를 조정하면 k8s가 자동으로 그 수를 맞춘다. 더 나아가 CPU 부하, 메모리 사용량, 초당 쿼리 수 등 실시간 메트릭을 기반으로 k8s가 직접 최적의 replica 수를 조정할 수 있다.
어떤 컨테이너는 노드 실행 실패나 다른 컨테이너로 인해 노드에서 나가야 하는 경우가 생기며 클러스터 내에서 이동하게 된다. 이렇게 클러스터 내에서 이동을 하면 클라이언트는 어떻게 컨테이너를 잘 이용할 수 있을까? K8s는 이들 컨테이너를 하나의 고정 IP 주소로 클라이언트에 노출시키고, kube-proxy의 서비스 제공 컨테이너 간 load balancing을 통해 일관된 접근을 보장한다. 그러므로 클라이언트는 안심하고 이용할 수 있다.
K8s가 우리에게 가져다 준 혜택들
자료 출처: Kubernetes In Action (2018)