Container화 되어 있는 서비스를 시스템에 Deploy할 때 자동화해주는 도구
→ 쿠버네티스가 스스로 관리를 해준다.
쿠버네티스가 스스로 관리를 해준다는게 무슨 의미인지 OpenStack의 예시로 생각을 해보자
우리가 현재 오픈스택을 사용하고 있고 VM을 생성하고 웹 서버를 배포 중이라고 생각을 해보자 → 우리가 열심히 웹 서버가 문제가 발생하여 서버가 나갈 수도 있다. → 그러면 우리는 해당 문제를 확인하고 다시 VM을 생성하던가 아니면 다른 방식으로 문제를 해결을 해야되는 상황이 발생을 한다. → 즉 사용자가 주기적으로 VM의 상태를 확인하고 문제가 발생했을 때 직접 문제를 해결해야되는 상황이 발생하게 된다. (복잡하고 로직을 추가해야 된다.)
하지만 쿠버네티스는 위와 같이 문제가 발생하였을 때 쿠버네티스 스스로 관리를 해준다!! 즉 사용자가 직접 문제를 해결하지 않아도 된다.
그러면 어떻게 이런 방식이 가능할까? 가능한 이유는 쿠버네티스의 API는 declarative 하다는 원리에 있다.
위의 OpenStack 예시에서 OpenStack의 API 방식에 대해서 생각을 해보자 OpenStack의 API는 내가 직접 명령어를 적어서 요구를 하면 시스템이 명령을 실행하는 형태이다. 즉 Imperative(명령적인)한 특성을 가지게 된다.
하지만 쿠버네티스의 API는 내가 원하는 상태(요구)를 정의를 하면 시스템이 스스로 일을 하는 형식이다. 이러한 API를 Declarative API라고 한다.
그러면 이제 쿠버네티스 환경에서 노드 하나가 망가져서 우리의 웹 서버가 나갔다고 생각을 해보자. 웹 서버가 나가도 우리는 무언가를 안해도 된다. 왜냐하면 쿠버네티스가 자동으로 노드를 복구해주기 때문이다. 이렇게 쿠버네티스는 모니터링, 리커버링이 가능하게 지원을 해주고 이러한 기능이 가능한 이유는 Declarative API에 있다.
결론) 우리는 원하는 상태를 정의하면 되고, 쿠버네티스는 스스로 이 상태를 만족하도록 하기 때문에 모니터링, 리커버링이 쿠버네티스 자체적으로 실행이 된다.
나: 원하는 상태를 define → System : 그 상태를 유지하도록 동작
쿠버네티스의 control plane은 투명하고, 내부적인 숨겨진 API가 없다.
→ Master도 명령을 내리지 않고 투명하게 상태 정보를 쓰는걸로 끝나야 한다. 즉 Node가 스스로(독립적으로) 그 상태가 되도록 해야된다.
간단한 예시를 들어보겠다. Pod A를 만들어야 되는 상황이라고 생각을 하자. Master에 Pod A에 대한 정의 파일을 올려야 한다. 그러면 여러 노드들이 해당 정의 파일을 보게 된다. 이 때 Master의 Scheduler가 해당 정의 파일을 보고 여러 Node들의 상황을 본 뒤 해당 Pod A가 들어갈만 한 적절한 위치의 Node의 정보를 API Server에 적게 된다. 그러면 해당되는 Node가 이를 확인한 뒤 Pod A를 생성하게 된다. 해당 예시의 과정을 잘 살펴보면 그 어떠한 Component들도 명령을 내리지 않음을 알 수 있다. → Work Node가 상태 정보(k8s API)를 보고 그 상태에 맞게 action을 취한다.
이러한 방식의 장점은 무엇일까? declarative한 방식이기 때문에 시스템이 더 안정적이게 된다. → 만약 내부적인 문제가 발생한 경우 문제가 생긴 component만 교체를 해주면 된다. → 쿠버네티스가 확장이 가능한 이유이다.
쿠버네티스가 확장이 쉬운 이유 : 우리가 새로운 상태 정보를 define 해줄 수 있다. → 이 상태 정보에 맞는 action을 하는 Control Logic도 우리가 추가로 정의할 수 있다.
결론 : 쿠버네티스의 동작은 명령을 내리는게 아닌 상태 정보를 적어 그에 맞는 행동을 취하는 방식이다.
principle 3에 대해 알기 전에 먼저 kube API에 어떤 데이터가 있고 보관, 관리 되는지에 대해 알아보자.
kubernetes API에는 많은 data들이 담겨 있다. 몇 가지만 살펴보면
이런 데이터들을 어떻게 보관하고 관리를 해야할까?
우리가 Application을 pod에 넣었다고 생각을 해보자. 이 때 pod가 돌면서 password가 필요해질 수 있다. 그러면 해당 data를 가져와야 되는데 이 data가 API에 있다고 하면 이 API에서 정보를 읽어와야 된다. → application의 코드를 수정해야되는 상황이 발생한다.(api에서 가져오라는 코드를 추가해야되기 때문) → 이는 좋은 방법이 아니다. 여기서 principle 3이 필요하게 된다.
기존의 응용(Application)들을 수정없이 돌릴 수 있게 하자!
Container가 API Server의 데이터를 읽어 오는게 아닌 별도의 Volume(Storage)에서 가져오게 한다.
이 Volume은 Remote Storage 형태로 만들었다. → 내가 Pod를 Define할 때 Pod 정보에 Storage 정보(외부에 있는 storage를 쓸 수 있게 정의)를 쓸 수 있게 해둔다. → System에서 remote storage를 준비시키는 작업을 수행하고 Attach 해준다.
결론 : Storage는 내가 Pod를 define할 때 같이 define을 한다. Remote Storage를 사용하게 되고, storage를 사용할 때 외부의 storage와 container를 attach, mount 한다. → 이렇게 기존의 Application을 수정하지 않고 돌릴 수 있게 된다.
문제점 : pod가 사라진다면?? → application이 생성한 data를 찾을 방법이 사라지게 된다. → Data는 persistent하게 해야된다.(계속 지속되도록) → remote volume을 구체적으로 define하지말고 추상화 된 이름을 사용을 하게하자.
Pod의 이식성을 강화(Storage 측면에서도)
PVC/PV 추가 → Persistent Volume
미리 정해둔 스토리지(추상화 되어 있다.)의 종류를 말하면 쓰게 해준다.