1. Introduction

 

1.1 What is Kubernetes

쿠버네티스는 컨테이너를 쉽고 빠르게 배포/확장하고 관리를 자동화해주는 오픈소스 플랫폼이다. 

1주일에 수십억 개의 컨테이너를 생성하는 구글이 내부 배포시스템으로 사용하던 borg를 기반으로 오픈소스 프로젝트를 통해 빠르게 발전하고 있다.

단순한 컨테이너 플랫폼이 아닌 마이크로서비스, 클라우드 플랫폼을 지향하고 컨테이너로 이루어진 것들을 손쉽게 담고 관리할 수 있는 그릇 역할을 합니다. 서버리스, CI/CD, 머신러닝 등 다양한 기능을 쿠버네티스 상에서 이용할 수 있다.

 

 

 

Kubernetes가 제공하는 구체적인 항목은 다음과 같다.

1. Service Discovery and Load Balancing
Kubernetes는 DNS나 자체 ip를 이용하여 container를 외부에 노출 시킬 수 있다. 컨테이너에 트래픽이 몰리게 되면, kubernetes는 배포된 컨테이너가 안정적이도록 네트워크 트래픽을 LoadBalancing하고, 분산시킨다.

2. Storage Orchestration
Kubernetes는 local storage나 public cloud등 원하는 storage를 mount할 수 있다.

3. Automated Rollouts and Rollbacks
Kubernetes를 이용하여 컨테이너의 상태를 사용자가 지정한 속도에 맞추어 설정 할 수 있다.

4. Automatic bin packing
Kubernetes를 이용하여 컨테이너에 필요한 자원의 양을 지정할 수 있다.

5. Self-healing
오류가 난 컨테이너를 다시 시작하고, 다른 컨테이너로 대체 할 수 있으며, 이러한 과정을 클라이언트에 노출시키지 않는다.

 

 



1.2. Kubernetes Architecture

Kubernetes Cluster는 다음과 같이 구성되어 있다

 

 

 

1.2.1. Master Node (Control Plain)

Cluster의 뇌와 같은 역할을 하는 노드이다. Worker Node에 있는 컨테이너의 Orchestration을 담당한다.

  • API Server : Worker node와 통신하기 위한 api 서버.

  • etcd :클러스터의 상태를 key-value로 저장하는 내부 데이터베이스.

  • Scheduler : Node가 배정되지 않은 새로운 Pod를 감지하고, 이를 노드에 배정하는 기능을 담당한다.

  • Controller Manager : API Server를 통해 클러스터의 상태를 공유하는 역할을 한다. 컨트롤러는 다음과 같은 역할을 수행한다.

    • Node Control : 노드가 다운되었을 때, 통지와 대응에 관한 책임을 가짐.
    • Replication Control ; 시스템의 모든 오브젝트에 대해 적절한 수의 pod를 유지시키는 책임을 가짐.
    • Endpoint Control : service와 pod를 연결시키는 책임을 가짐
    • Service Account & Token Control : 새로운 namespace에 대한 기본 계정과 API 접근 토큰을 생성한다.

 

 

 

1.2.2. Worker Node

실제 컨테이너 이미지를 실행시키는 역할을 하며, 각 노드에는 여러개의 컨테이너가 올 수 있다.

  • Kube Proxy : node의 네트워킹 서비스를 반영하는 프록시이다. 사용자는 이 proxy를 통해 각 node에 접근 가능하다.

  • kubelet : Master Node와 통신을 담당하는 구성요소

  • Controller Runtime(Pods) : 실제 기능을 담당하는 여러개의 Pod로 구성되어있다.

 

 

 

1.2.3. Pod

하나 이상의 스토리지 및 네트워크를 공유하고 해당 컨테이너를 구동하는 방식에 대한 명세를 가지는 컨테이너 그룹이다. 이를 통해 어플리케이션에 대한 헬퍼 프로그램을 지원할 수 있으며, 그 예는 다음과 같다.

  • 컨텐츠 관리 시스템, 파일과 데이터 로더, 로컬 캐시 관리 등.

  • 로그와 백업 체크포인트, 압축, 로테이션, 스냅샷 등.

  • 데이터 변동 감시자, 로그 추적자, 로깅 및 모니터링 어댑터, 이벤트 관리 등.

  • 프록시, 브릿지, 어댑터

  • 컨트롤러, 매니저, 설정, 업데이트

 

 

1.2.4. Service

여러개의 pod로 이루어진 고정 ip를 할당받은 논리적인 단위이다. Pod이 어디있든 service를 통해 pod으로 접근 할 수 있다.

 

다음은 Service의 종류에 대해서 서술해보았다.

  • Cluster IP : 클러스터 내부에서 할당받은 ip이다. Kubectl을 이용하여 service를 생성하게 되면 기본으로 구성되게 되어있다.
  • Node Port : 클러스터 내부에서 할당받은 서비스 포트. 이 옵션으로 생성 시, Cluster IP가 자동으로 함께 만들어지며, 이 포트를 통해 외부에서 <Note IP>:<Node Port>의 형태로 접근이 가능하다.
  • Load Balancer : 서비스를 외부적으로 노출 시킬 수 있다. 이 옵션으로 생성시, Node Port와 Cluster IP가 자동으로 생성된다.
  • External Name : 서비스를 외부 CNAME레코드와 매핑시켜준다.

 

 


1.2.5 Deployment

pod는 쿠버네티스의 가장 기본적인 단위이지만, cluster에서 직접 시작되지 않는다. 대신, 추상화 계층인 deployment로 관리된다. 배포의 기본적인 목적은 pod의 복제본과 구체적인 spec에 대해 명세하는 것이며, deployment가 클러스터에 추가되면 그에 해당하는 spec에 맞게 app이 실행되고, 모니터링 됩니다. pod에 장애 발생 시, deployment에 명시된 spec에 따라 자동으로 다시 pod를 생성하고 관리한다.

 

다음 그림은 pod-service-deployment에 대한 모식도를 나타낸 것입니다. 

출처 : https://medium.com/google-cloud/kubernetes-101-pods-nodes-containers-and-clusters-c1509e409e16

 

 

 

2. Elastic Kubernetes Service

 

 

2.1. EKS Architecture Best Practice

AWS가 권장하는 EKS Architecture best practice는 다음과 같다.

출처 : AWS EKS QuickStart

 

위 아키텍처와 같이 Kubernetes 노드를 여러 AZ에 private subnet에 배포하여 보안성과 가용성, 자동프로비저닝을 잡고, public subnet를 각 private subnet의 전방에 배치함으로써 proxy 및 bastion host역할을 부여하게 할 수 있다.

 

 

2.2. EKS Data Flow Architecture

위 best practice를 설명하기 위해 data I/O를 포함하여 아키텍처를 다시 그려보았다.

위 아키텍처에서 우리가 주목해야 할 부분은 AWS ALB Ingress Controller이다.

ALB Ingress Controller를 한마디로 말하자면, EKS와 클러스터 간 변동 명세를에 api server로 전달하는 provider이다. 이러한 방식을 통해 AWS에서 적용 할 수 있는 서비스를 cluster내부의 node 및 pod에 대해 적용 가능하게 된다.

ex) Resource Scaling, Container Management, Versioning, traffic control, state monitoring ….

위 아키텍처의 데이터 흐름을 포함한 작동 방식은 다음의 순서를 따른다.

 

  1. 지속적으로 EKS APi Seerver로부터 ALB Ingress Controller는 모니터링은 받는다.
  2. yaml 파일 업데이트 또는 터미널 입력 등으로 부터 AWS 자원의 변동사항 명세를 입력 받는다.
  3. 이러한 입력을 ALB Ingress Controller가 모니터링을 한다.
  4. ALB Ingress Controller는 EKS API Server로 모니터링 도중 발생한 변경사항에 대해 전달을 한다.
  5. 변동사항 명세를 받은 EKS(Control Plain)는 AWS 리소스(Worker Group)에 대해 변동사항을 적용한다.

 

 

 

3. Conclusion

다음과 같은 요소를 종합하였을 때, 우리는 쿠버네티스를 다음과 같은 이유로 사용 한다고 할 수 있다.

  • 많은 호스트에서 운영되는 컨테이너들을 쉽게 조작하고 모니터링 한다.

  • 컨테이너가 언제 시작되고 멈추는지 결정 할 수 있다.

  • 새로운 코드를 빠르게 호스트 안의 컨테이너에 적용 할 수 있다.

  • 컨테이너의 트레픽과 라우팅을 관리할 수 있다.

Virtualization

기존에는 하나의 app이나 task에 하나의 전용서버를 할당하였다. 이렇게 함으로써 app에서 발생하는 문제의 원인을 쉽게 발견 할 수 있었으며, 네트워크 구성이 용이했다.

그러나 이는 서버의 능력 중 극히 적은 능력만을 사용하여 효율성이 떨어지고, 네트워크 규모가 커지고 복잡해짐에 따라 서버가 점유하는 물리적 공간이 커지고 그에 따라 전력 소모도 심해진다.

이를 해결하고 전략을 세우기 위해 물리서버의 최대 처리능력만큼 여러개의 가상머신으로 분할하여 물리서버의 처리 능력을 최대한 활용 할 수 있게 한 것이 (서버) 가상화이다.

가상화를 하게 되면, 원래 os와 가상화한 파티션의 os를 다르게 설정 할 수 있다. 이 때, 상이한 os의 명령 또는 동작을 해석하여 하드웨어에 전달해줌으로써 인터페이스를 제공하는 것이 hypervisor이다.

즉, 위와 같은 역할을 hypervisor가 해줌으로써 widnow상에서 CentOS같은 운영체제를 사용 할 수 있다. VMWare, Parallels같은 것도 hypervisor이다.

hypervisor는 bare-metal형 hypervisor(type 1), os위에 올려져서 쓰이는 hypervisor(type 2)으로 나뉜다.

 

 

Type 1 (Native or Bare-Metal Hypervisor)

하이퍼바이저가 OS에 종속되지 않고, 하드웨어에 직접 설치된다.
보통 OS가 하드웨어를 컨트롤 하지만, type 1방식의 Hypervisor를 절치하게 되면, Hypervisor가 직접 하드웨어를 제어 할 수 있기 때문에 OS의 Overhead가 적어지고, 자원 관리가 유연해진다.

그러나 Hypervisor 자체에는 별도의 관리기능이 없기 때문에 이 방식에서는 구동 시 DOM0(Hypervisor 구동시 Hypervisor가 실행시키는 도메인)라는 관리 머신이 함께 구동된다. DOM0에서 얼마나 일을 부담하는가에 따라 전가상화, 반가상화로 나뉜다.

 

 

Full-Virtualization (전가상화)

로마에 가면 로마법을 따르는 것 처럼, 각 OS는 고유의 규칙을 가지고 있고 같은 것을 표현하는 방식도 OS마다 틀리다. 각기 다른 표현을 Hypervisor(엄밀히 말하면 DOM0)가 핸들링하여 Hardware가 알아 먹을 수 있는 표현으로 변환 한 다음, Hardware에게 전달한다.


https://blog.naver.com/alice_k106/220218878967 -> 사진 출처 (Alice님 Blog)

 

 

Para-Virtualization (반가상화)

전가상화에서는 Hypervisor(엄밀히 말하면 DOM0)가 각기 다른 표현을 번역하여 Hardware에 전달하였지만, 반가상화에서는 표현하는 사람이 직접 하드웨어가 알아먹게 전달하는 방식(Hyper-Call)이다. 즉, 우리가 영어권으로 여행가면 한국어를 안쓰고 영어를 사용하여 대화하는 것과 마찬가지다.
하지만, 기본적으로 커널에는 Hyper-Call에 대한 정보가 없다. 그래서 가상 OS의 커널을 직접 수정해야하는 단점이 있다. 그러나 DOM0를 거치는 횟수가 줄기 때문에 전가상화에 대비하여 좋은 퍼포먼스를 보인다.


https://blog.naver.com/alice_k106/220218878967 -> 사진 출처 (Alice님 Blog)

Type 2

일반적으로 우리가 쓰는 VMWare같은 것과 같다.
Hardware에 OS를 설치하고, 그 위에 Hypervisor를 설치한다.
OS가 Hardware를 관리하기 때문에 DOM0가 필요없다. 

그러나 OS위에 Hypervisor가 구동되고 그 위에 가상화가 이루어 지는 방식이기 때문에 Overhead가 크다.

1. Timeout Error 상황의 리소스 현황 및 Data Flow

 

 

 

1-1. 리소스 현황

  • 활성화된 로드밸런서 가용영역 : private-2a, private-2c

  • 대상 그룹 : private-2a와 private-2c subnet에 있는 인스턴스 ip address

  • 리스너 : HTTP 80

  • 목적지 : Tomcat 8080

  • Public ip는 오직 public subnet의 인스턴스만 할당.

  • IGW 및 NAT 서브넷 연결현황은 다음과 같다.

    • IGW : public-2a, public-2c
    • NAT : private-2a, private-2c, db subnet

 

 

1-2. Data Flow

1. 사용자는 Public DNS를 통해 ALB에 접근한다.

2. ALB의 트래픽은 IGW를 통해 VPC내로 들어온다.

3. 트래픽은 활성화된 로드밸런서 가용영역 subnet만 참조하게 된다.

3-1. 활성화 된 로드밸런서 가용영역 subnet은 private subnet이다.

3-2. private subnet안에 있는 로드밸런싱 대상의 인스턴스는 public 주소 또는 탄력적 ip가 없다.

3-3. public ip 또는 탄력적 ip없이는 외부와 통신을 할 수 없다.

3-4. 로드밸런서는 계속해서 활성화된 로드밸런서 가용영역 서브넷으로 브로드캐스트 주소로 패킷을 전송하다 유휴제한시간을 초과한다.

3-5. 최종적으로 사용자에게 timeout error을 출력한다.

 

 

 

2. Issue 해결 솔루션 및 Data Flow

 

 

 

2-1. 문제점 분석 및 해결법

먼저 로드밸런서 가용영역에 대해 알아보자. 로드밸런서 가용영역이란, 일반적인 우리가 알고 있는 AZ가 아닌 로드밸런서가 접근할 수 있는 subnet을 의미 한다. 이에 대해서는 다음 캡쳐본을 참고한다.

 

현재 로드밸런서는 활성화된 가용 영역(서브넷)이 private subnet이다. private subnet은 igw와 연결되어있지 않으며, 로드밸런싱 대상은 public ip 또는 탄력적 ip가 할당되어 있지 않기 때문에 외부 트래픽을 다룰 수 없게 된다.

이를 해결하기 위해서는 로드밸런서의 활성화된 가용영역(서브넷)을 public subnet으로 설정해준다. public 서브넷은 외부와는 물론 내부 서브넷과 통신이 가능하므로 public subnet을 거쳐 로드밸런싱 대상으로 트래픽을 전달하면 쌍방으로 통신이 가능해지기 때문에 위와 같은 이슈를 해결 할 수 있다.

 

 

2-2. Data Flow Diagram

다음과 같이 public subnet을 통해서 private subnet의 인스턴스로 접근하게 설정해준다.

 

 

3. 참고문헌

http://thebluenode.com/exposing-private-ec2-instances-behind-public-elastic-load-balancer-elb-aws

https://aws.amazon.com/ko/premiumsupport/knowledge-center/public-load-balancer-private-ec2/?nc1=h_ls

https://docs.aws.amazon.com/ko_kr/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html

https://docs.cloud.oracle.com/iaas/Content/Balance/Concepts/balanceoverview.htm

+ Recent posts