앞서

이 게시글은 subicura 님의 인프런 유료 강의, "초보를 위한 쿠버네티스 안내서"를 듣고 정리하기 위해 작성했습니다.

https://www.inflearn.com/course/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EC%9E%85%EB%AC%B8/dashboard

 

초보를 위한 쿠버네티스 안내서 - 인프런 | 강의

쿠버네티스를 1도 모르는 입문자, 초보자를 위한 쿠버네티스 안내서 입니다. 초보자도 이해하기 쉬운 내용과 흐름으로 구성했어요., 데브옵스 입문자라면 주목! 지금, 초보자를 위한 쿠버네티스

www.inflearn.com

아키텍처

사람을 시켜 컨테이너를 하나를 띄우려면?

1. 컨테이너 한개 생성 해달라는 요청을 받음

2. 그 요청을 어딘가에 적어둠

3. 서버의 현재 상태가 방금 적어둔 ( 컨테이너 1개 생성 ) 상태와 같은지 체크

4. 컨테이너 하나 있어야 하는데 없네? 만들기

 

이 개념이 굉장히 중요하다.

 

Desired State

1. Observe (상태 체크) : 현재 상태 == 원하는 상태 인지 체크

2. Diff ( 차이점 발견 ) : 현재 상태 != 원하는 상태 이므로

3. Act ( 조치 ) : 현재 상태 -> 원하는 상태

 

쿠버네티스는 이 3가지를 반복함.

 

다시 위의 예시로 돌아가서, 이번에는 서버를 2대로 증설하라는 요청을 받았다!

그렇게 서버를 새로 하나 띄웠다. 이 때 새로운 컨테이너는 어디에 띄워야 할까?

당연히 아무 것도 띄워져 있지 않은 2번 서버에 띄워야 할 것이다.

 

이 때, 어느 서버에 띄워줄 지 결정하는 사람을 Scheduler 라 하자.

컨테이너나 네트워크, 노드 등을 체크해주는 사람을 Controller 라 하자.

 

즉, 컨트롤러의 갯수에 따라 Desired State 가 굉장히 많아질 수 있다.

 

다시 나눠보면, 쿠버네티스의 영역은 두 가지가 생긴다.

 

실제로 컨테이너들이 띄워져있는 Node 부분과, Node 를 관리하기 위해 움직이는 Master 영역으로 나뉜다.

중간에서 Scheduler, Controller 들에게 명령을 해줬던 사람은 API Server 라는 용어로 부르고, API Server 가 명령을 기억해해두기 위해 적어두던 데이터베이스를 etcd 라고 한다.

 

etcd

  •  모든 상태와 데이터를 저장
  • 분산 시스템으로 구성하여 안전성을 높임 (고가용성, 보통 3대 정도 띄움 )
  • 가볍고 빠르면서 정확하게 설계
  • Key(directory) - Value 형태로 데이터 저장
  • TTL, watch 같은 부가 기능 제공.
  • 백업은 필수!

API Server

  • 상태를 바꾸거나 조회
  • etcd 와 유일하게 통신하는 모듈
  • REST API 형태로 제공
  • 권한을 체크하여 적절한 권한이 없을 경우 요청을 차단
  • 관리자 요청 뿐만 아니라 다양한 내부 모듈과 통신
  • 요청이 굉장히 많음. 수평으로 확장되도록 디자인

Scheduler

  • 새로 생성된 Pod ( 지금은 컨테이너라고 생각하세요)  를 감지하고 실행할 노드를 선택 ( 어떤 노드에 어떤 컨테이너를? )
  • 노드의 현재 상태와 Pod의 요구사항을 체크
  • 노드에 라벨을 부여 ( 그래픽이 필요한 경우, gpu-enabled 라벨이 되어있는 노드에 배포한다던가..)

Controller

  • 논리적으로 다양한 컨트롤러가 존재 (복제 컨트롤러, 노드 컨트롤러, 엔드포인트 컨트롤러...)
  • 끊임 없이 상태를 체크하고 Desired State를 유지
  • 복잡성을 낮추기 위해 하나의 프로세스로 실행

조회 흐름

  • Controller 는 etcd 와 직접 통신하지 않고 API Server 에게 요청한다.
  • API Server는 해당 Controller 가 조회 권한이 있는지 체크
  • 권한이 있다면 etcd 에 정보 조회함.
  • etcd 가 Desired State가 변경되었다고 API Server에 알려줌
  • API Server는 Controller 에게 변경되었다고 알려줌
  • Controller 는 Desired State 로 리소스 변경
  • Contoller 는 변경 후에 API Server 에 변경 사항 전달
  • API Server 는 얘가 정보를 변경할 권한이 있는지 체크하고,
  • 권한이 있다면 etcd 에 정보 갱신을 기록함.

즉, Scheduler, Controller 들 모두가 API Server 와의 통신을 하고 있다.

 

이제 Node 부분을 살펴보자

크게 Proxy 와 Kubelet 이라는 컴포넌트가 있다. 마찬가지로 API Server 와 통신함.

 

Proxy 는 iptables, ipvs 방식을 사용하고, Kubelet 이 Pod 와 직접 통신한다.

 

Kubelet

  • 각 노드에서 실행
  • Pod을 실행/중지하고 상태를 체크
  • CRI (Container Runtime Interface)
  • 컨테이너를 직접 쓰는게 아니라 Pod 이라는 것으로 감싸서 사용함.

Proxy

  • 네트워크 프록시 같이 부하 분산 역할
  • 성능상의 이유로 별도의 프록시 프로그램 대신 iptables 또는 IPVS를 사용 ( 설정 파일만 관리 )

그럼 용어를 토대로 다시 예제로 돌아가볼까요?

  1. 관리자가 API Server 에게 Pod 를 띄워달라고 요청함
  2. API Server 는 etcd 에게 "Pod 을 생성하라는 요청이 들어왔다!" 라고 적어둔다.
  3. Controller 는 "새 Pod 가 확인 되어야 하나??" 를 계속 API Server 에게 체크 중이다.
  4. 헐, 요청이 들어왔네! Pod 할당 요청을 API Server에게 한다.
  5. API Server 는 다시 받아서 etcd 의 상태를 "Pod 할당 요청" 으로 바꾼다.
  6. Scheduler 또한 계속 API Server 에게 할당할 Pod 가 있는지 체크 중이다.
  7.  헐 있네! 새 노드에 할당하겠다고 API Server 에 요청함.
  8. API Server 는 etcd 에 "새로운 Pod 를 특정 노드에 할당하는데, 아직 미실행 상태다!" 를 기록함.
  9. Node 단의 Kubelet 은 "어, 내 담당 노드에 할당된 Pod 중에서 아직 미실행 된 게 있네?"를 체크함.
  10. 정보를 가져와서 Pod 생성하고, API Server 에 Pod 생성했다고 알려줌
  11. API Server 는 etcd 에 "새 Pod를 특정 노드에 할당해서 실행중이다" 를 기록함.

Addons

CNI (네트워크), DNS(도메인, 서비스 디스커버리), 대시보드(시각화) 등의 컴포넌트가 있다.

 

 

오브젝트

지금까지 쿠버네티스가 어떻게 내부적으로 동작하는 지 알아봤다. 이제 각 오브젝트를 알아보자.

 

Pod

  • 가장 작은 배포 단위 ( 컨테이너를 감싼다 )
  • 각 Pod 마다 고유 IP 를 받는다.
  • 하나의 Pod 에 여러 개의 컨테이너가 들어갈 수 있다. 각 컨테이너가 localhost 의 폴더를 공유할 수도 있고 포트로 네트워크를 공유할 수도 있다.

 

ReplicaSet

  • 여러 개의 Pod 를 관리
  • 새로운 Pod 는 Pod Template 을 보고 하나 더 띄워줌.
  • 원하는 Pod의 수(Replicas) 에 맞춰 Pod 를 관리

 

Delpoyment

  • 배포 버전을 관리
  • 무중단으로 배포하기 위해서, 순간적으로 ReplicaSet 을 2개로 만들고, 각 replicas 를 한 쪽 컨테이너는 줄이고, 한 쪽 컨테이너는 늘이면서 자연스럽게 update 시킴.

이 외에도 다양한 Workload 가 있다.

  1. Daemon Set : 모든 Node 에 꼭 하나씩만 떠있길 원하는 Pod 을 만들고 싶을 때(모니터링, 로그)
  2. Staeful Sets : 순서대로 Pod을 실행하고 싶거나, 같은 볼륨을 재활용하고 싶을 때
  3. Job : 한 번 실행하고 죽는 Pod

Service - Cluster IP

  • 3개의 Pod 이 있을 때, ClusterIP 로 묶여 있으면 ClusterIP 로 요청을 보내면 3개 중에 하나로 보내서 수행함.
  • 이렇게 하는 이유는, Pod 가 업데이트될 때 기존 Pod 이 유지되지 않고 죽었다가 새로 만들어진다.
  • 즉 IP 가 유동적이기 때문에, 고유 IP 를 갖는 Service 의 ClusterIP 로 요청을 보내는 것.
  • web 에서 redis 가 있는 Pod 로 요청을 보낸다면, redis 가 속해있는 ClusterIP 로 요청을 보냄.

Service - NodePort

  • Cluster IP 는 내부 통신만 가능하다. 외부 브라우저에서는 접근이 안 된다.
  • 외부에서 접근하기 위해서, Cluster IP 를 NodePort 로 감싸준다. (30000-32767 포트)
  • 노드01 과 노드02 가 있다면, 노드01 로 직접 요청해서 Pod 에 접근할 수도 있고, 노드02에서 노드01 내부의 ClusterIP 에 요청해서 접근할 수도 있다. 즉 둘 중 어느 노드에 접근해도 같은 Pod 에 접근할 수 있게 되는 것

Service - LoadBalancer

  • 노드01 로 도메인을 연결해놨는데 노드01이 갑자기 죽어버린다면? 노드02로 붙어야 하는데,,
  • 직접 연결해뒀다면 접속이 안될 것이다.
  • 이 때 사용자는 LoadBalancer 에게 요청을 한다. 그 요청이 NodePort 로 가고, ClusterIp 로 가고, Pod 로 가는 방식

Ingress

  • 도메인 또는 경로 별 라우팅
  • Nginx, HAProxy, ALB ...

일반적인 구성

  • Pod 를 직접 띄우는 일은 잘 없다. Deployment 를 띄우면 자동으로 ReplicaSet 을 생성하고, 얘는 Pod 를 생성하고..
  • 외부 노출을 위해 Service (ClusterIp) 를 붙이고, 얘는 NodePort 에 붙이고, LoadBalancer 에 붙이고..
  • Ingress 에 연결해 도메인을 연결하면, 사용자가 www.어디어디 로 들어왔을 때 요청이 간다. 

그 외 기본 오브젝트

  • Volume ( Storage )
  • Namespace - 논리적인 리소스 구분
  • ConfigMap/Secret - 설정
  • ServiceAccount - 권한 계정
  • Role/ClusterRole - 권한 설정

API 호출

원하는 상태(Desired State) 를 다양한 오브젝트(Object) 로 정의(Spec) 하고 API 서버에 yaml 형식으로 전달

 

'DevOps > Kubernetes' 카테고리의 다른 글

초보를 위한 Kubernetes 안내서 (1) : 소개  (0) 2021.06.22
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기