[K8s] 쿠버네티스란 무엇인가?

Dragony·2023년 7월 20일
16

쿠버네티스

목록 보기
6/7
post-thumbnail

쿠버네티스는 간단히 말하면, 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고 확장 가능한 오픈소스 플랫폼입니다.

일단, 쿠버네티스가 뭐고 왜 나타나게 되었는지 이해하기 위해 애플리케이션 배포 환경의 변화부터 살펴보도록 하겠습니다.




애플리케이션 배포 환경의 변화

우리가 무언가 프로그램을 개발해서, 사람들에게 서비스를 제공하려면, 특정 서버에 자신이 만든 소프트웨어를 배포(Deploy)해야 한다. 이 "배포(Deployment)" 방식의 변화 과정을 이해하는 것이 컨테이너, 도커, 쿠버네티스의 개념을 이해하는데 있어서 중요하다.


Container Deployment (컨테이너 배포) 시대로 오기까지의 여정

전통적인 방식 (Traditional Deployment)

  • 가장 오래되고 단순한 방식
  • 물리적인 컴퓨터 한대에 하나의 OS를 깔고, 여러가지 프로그램을 설치하는 방식
  • 문제점
    • 다른 OS 설치하려면? -> 컴퓨터 한대 더 필요
    • 같은 컴퓨터 리소스를 공유하므로, 배포한 애플리케이션 끼리 서로 영향 -> 성능 문제 발생
    • 하드웨어의 성능은 매우 빠르게 좋아지는 반면에, 소프트웨어 발전은 반도 못따라감 (/w 무어의 법칙)
    • 소프트웨어가 요구하는 서버 사양에 비해 소프트웨어를 실행 중인 서버의 성능이 훨씬 좋다 보니, 서버 성능을 10% 수준 밖에 활용하지 못하는 비효율이 발생
    • 심지어 그 당시 컴퓨팅 자원들은 지금보다 훨씬 비쌌음 💸💸💸💸💸

=> 그럼 한대의 컴퓨터를 여러대의 컴퓨터처럼 사용할 수는 없을까?

<무어의 법칙>
무어의 법칙은 반도체 칩의 성능, 즉 메모리의 용량이나 CPU의 속도가 약 24개월마다 2배로 증가하고, 가격은 2배씩 낮아진다는 법칙입니다. 인텔의 공동 창업자인 골든 무어가 1965년에 발표한 내용이기 때문에 무어의 법칙이라고 불립니다.



가상화 배포 (Virtualized Deployment)

전통적인 방식의 이러한 문제점 때문에, 사람들은 "가상화" 라는 개념을 생각해내게 됩니다.

가상화란 무엇이냐? 물리적인 하드웨어 장치를 논리적인 객체로 추상화 하는 것을 의미합니다.

쉽게 말하자면, 하드웨어는 1개인데 이걸 여러대 처럼 동작시키거나, 반대로 여러대의 장치를 묶어 하나의 장치인 것 처럼 해서, 사용자는 내부적으로 어떻게 돌아가는지 알 필요 없이, 사용자가 원하는 방식으로 자원을 사용할 수 있다는 거예요.

즉, 한 대의 서버 위에 동시에 여러개의 OS를 설치하고, 여러 애플리케이션을 실행시키는 방식으로 자원 비효율 문제 해결할 수 있게 되었습니다.


아무튼 가상화 배포는, 가상머신을 기반으로 배포하는 방법입니다.

가상머신은 위에서 말한 가상화 기술이 적용된 컴퓨터인데, 개별적으로 자체 컴퓨팅 자원(CPU, memory, Disk)과 OS를 갖춘 가상 컴퓨팅 환경입니다.


아래와 같은 특징이 있고, 가상화 배포에도 당연히 문제점이 존재합니다.

  • 가상머신은 각각의 논리적으로 구분된 가상 환경에서 실행되기 때문에, 각기 다른 OS, 분리된 리소스를 갖고있음

  • 하이퍼바이저(Hypervisor) : 하나의 시스템 상에서 가상 컴퓨터를 여러개 구동할 수 있도록 해주는 중간 계층, 가상머신 각각에 자원 할당 (VMware Workstation, Oracle VM VirtualBox 등)

  • 문제점

    • VM이 많을수록 전통적인 방식 대비 성능의 안정성이 떨어지고, 실행속도가 느려짐
    • 가상머신은 "완전한 컴퓨터"이기 때문에, 각각의 가상머신에 guest OS를 일일히 설치해주어야 함
      => 독립적인 플랫폼을 하나씩 증가시킬 때마다 불필요한 OS 를 만들어야 해서 확장성이 떨어지고 OS 크기 생각하면 부담스러움


그래서, 이러한 문제를 해결하기위해 등장한 개념이, 컨테이너(Container) 입니다.



컨테이너 중심의 배포(Container Deployment)

컨테이너 중심의 배포는 말 그대로, 컨테이너를 기반으로 애플리케이션을 배포하는 방법입니다.


  • 컨테이너란?
    • Host OS상에 논리적인 구획을 만들어서, 애플리케이션을 작동시키는데 필요한 라이브러리나 종속 항목들을 모아 마치 별도의 서버인 것 처럼 사용할 수 있게 만든 것
    • 애플리케이션과 필요한 모든 파일을 하나의 런타임 환경으로 묶는 데 사용하는 기술 (/w redhat)

컨테이너와 VM의 가장 큰 차이점은, 컨테이너는 애플리케이션 간에 운영체제(OS)를 공유한다는 점입니다.

호스트 OS의 리소스를 논리적으로 분리시키고, 여러개의 컨테이너가 공유하여 사용합니다.

그렇기 때문에, 컨테이너는 VM과 달리 프로그램의 구동을 위해 OS를 매번 설치할 필요가 없습니다.

즉, 하나의 Host OS 위에서 마치 각각의 독립적인 프로그램처럼 관리되고 실행됩니다.

👉🏻 Host OS를 공유하므로 OS 설치 작업이 없어 setup이 빠르고 확장성이 좋음
👉🏻 VM 보다 가벼워 마이그레이션, 백업, 전송이 빠름


또한, 컨테이너는 오버헤드가 적기 때문에, 가볍고 고속으로 작동한다는 것이 특징입니다. (메모리를 적게 차지하고 시작 시간이나 종료 시간이 적게 걸림)


컨테이너는 애플리케이션의 실행에 필요한 모듈을 하나의 컨테이너로 모을 수 있기 떄문에, 여러개의 컨테이너를 조합하여 하나의 애플리케이션을 구축하는 MSA 애플리케이션과 친화성이 높습니다.


그리고, 다른 컴퓨팅 환경으로 이동하더라도 안정적으로 실행 가능합니다.
애플리케이션의 실행에 필요한 라이브러리, 바이너리 파일, 기타 구성파일 등을 패키지로 묶어서 배포하면, 구동 환경이 바뀌어도 실행에 필요한 파일이 함께 따라다니기 때문에 오류를 최소화 할 수 있습니다.


한가지 주의해야할 사항은 컨테이너는 OS를 공유하는 방식이기 때문에, 어떤 프로그램의 문제가 다른 프로그램을 간섭할 수는 없습니다. 그러나 어떤 프로그램의 문제가 OS에 문제를 일으킬 경우에는 OS에서 구동 중인 전체 컨테이너의 문제가 될 가능성이 있죠. 우리는 이 점에 신경을 써야 합니다.




정리

Q. 추가적으로, 컨테이너 기반의 배포는 전통적 배포 위에 Container Runtime이 올라가 있는 것 같은데, 물리적인 컴퓨터 상에서만 유효한 것인지 궁금해 하실 건데요, 꼭 그렇지는 않습니다.
컨테이너 런타임 위에 OS와 하드웨어가 층으로 쌓여 있는 그림을 보고 전통적인 배포 위에서 컨테이너 런타임을 올렸다고 오해를 하곤 하는데, 컨테이너는 OS 하단이 어떻게 동작하는지 직접 관심을 두지 않아요. 그래서 가상머신 위에 올라간 OS에서 컨테이너 기반 배포를 하는 것이 가능합니다.

Q. 전통적인 배포 방식과 비교해보자면, 하나의 OS위에 프로그램을 여러개 구동시킨 것과 별 차이가 없어보이지만, 중요한 기술적인 차이점이 있습니다. 각 프로그램들이 “이 컴퓨터에서는 나만 구동되고 있다" 라고 판단할 수 있도록, 실제로 두 프로그램간에 간섭을 일으킬 수 없는 장벽을 치고, 동시에 OS는 각 프로그램들이 사용할 수 있는 CPU, 메모리 등의 자원 또한 독립적으로 사용할 수 있도록 할당하고 관리합니다. 물론 OS관점에서 보자면 둘다 OS 상에서 구동되는 프로그램이긴 하지만요. 이와 같은 컨테이너 동작 방식을 OS 커널을 공유하는 가상화 라고 하기도 합니다.




도커 (Docker)

본격 쿠버네티스에 들어가기 전에 도커를 먼저 짚고 넘어갑시다. 컨테이너 하면 도커를 빼놓을 수 없는데요.
도커는 컨테이너를 만들고 사용할 수 있도록 하는 컨테이너화 기술입니다.
애플리케이션의 실행에 필요한 환경을 하나의 이미지로 모아두고, 그 이미지를 사용하여 다양한 환경에서 애플리케이션 실행 환경을 구축 및 운영하기 위한 오픈소스 가상화 플랫폼 입니다.

이미지 (Image) 란?

  • 컨테이너 실행에 필요한 파일과 설정 값 등을 포함하는 것으로, 상태값을 가지지 않고 (Stateless) 변하지 않음 (Immutable).
  • 컨테이너는 이미지를 실행한 상태(Runtime)라고 볼 수 있고 추가되거나 변하는 값는 컨테이너에 저장된다.
  • 같은 이미지에서 여러개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 삭제되더라도 이미지는 변하지 않는다.



쿠버네티스 (Kubernetes)

쿠버네티스의 등장배경

도커의 등장으로 컨테이너 기반 배포 방식이 보편화되고, 많은 서비스들이 도커라이징 되어 이미지로 관리되기 시작했습니다.
점점 이미지가 많아지면서, 관리해야할 컨테이너와 서버들 또한 많아지게 되었죠.
이 말은 즉슨, 엔지니어가 할일이 많아졌다는 말입니다.

"컨테이너 어느 서버에 배포하지? 리소스 남는 서버 있나? 확인 확인🤦‍♀️"
"엇! 이 컨테이너 죽었네ㅜㅜ 다시 살려줘.."

할일이 많아지면 이런 잡스러운 일들을 자동화 시켜야겠죠?
컨테이너들의 관리를 자동화할 도구(컨테이너 오케스트레이션 툴) 의 필요성이 대두되고, 비로소 컨테이너 오케스트레이션의 춘추전국시대가 열리게 됩니다.
(Kubernetes, Docker Swarm, AWS의 ECS< 하시코프의 Nomad, Mesos의 Marathone등등)

2015년 7월, 쿠버네티스가 첫 출시 됩니다.
많은 컨테이너 오케스트레이션 도구가 있음에도 불구하고, 현재는 쿠버네티스가 컨테이너 오케스트레이션 툴의 사실상 표준(De facto) 로 자리매김하게 되었습니다.
이렇게 될 수 있었던 몇가지 이유는 다음과 같습니다.

  • 대규모 컨테이너를 관리했던 구글의 노하우와 강력한 확장성
  • 마이크로소프트, RedHat, IBM 등 수많은 기업의 참여
  • AWS, GCP, Zure, Digital Ocean, IBM Cloud, Oracle Cloud 등에서 관리형 서비스를 내놓음으로써 클라우드 컨테이너 시장을 평정

역시... 대기업들의 지원과 물량공세에는 장사 없네요.



쿠버네티스란?

  • 컨테이너를 쉽고 빠르게 배포 및 확장하고, 관리를 자동화해주는 오픈소스 플랫폼
  • 명칭은 조타수(helmsman)나 조종사(pilot)를 뜻하는 그리스어에서 유래
  • k8s라는 약자로 불리는데, 이는 k,s 사이의 8글자를 나타내는 약식 표기
  • 단순한 컨테이너 플랫폼이 아닌 마이크로서비스, 클라우드 네이티브 플랫폼(CNCF) 을 지향하고 컨테이너로 이루어진 것들을 손쉽게 담고 관리할 수 있는 그릇 역할


쿠버네티스 특징

(1) 대기업들의 참여 (거대한 생태계)

  • 전 세계적 스케일의 경험과 기술
  • 거대한 커뮤니티와 생태계
  • 잘 안되는 건 찾아보면 되고 이런거 만들어 볼까 하면 이미 있음

(2) 다양한 배포 방식

  • Deployment, StatefulSets, DaemonSet, Job, CronJob 등 다양한 배포 방식을 지원
  • 여러대의 애플리케이션을 띄우고 싶을 경우에는 Deployment 이용
    로그나 모니터링 등 모든 서버에 설치가 필요한 경우엔 DaemonSet을 이용
  • 배치성 작업은 Job이나 CronJob을 이용
  • 무슨 기능을 원하는지 몰라서 다 준비해놨어

(3) Namespace & Label

  • 네임스페이스(Namespace) 기능으로 하나의 클러스터를 논리적으로 구분하여 사용 가능
  • 라벨(label) 기능으로 유연하면서 확장성 있게 리소스를 관리

(4) RBAC (role-based access control)

  • 역할 기반 액세스 제어
  • 누가(주체), 무엇을(동사), 어디에(네임스페이스) 실행할 수 있는지 결정하는 권한 또는 템플릿 집합을 수반하는 Identity 및 액세스 관리 형식
  • 각각의 리소스에 대해 유저별로 CRUD스러운 권한을 손쉽게 지정
  • 클러스터 전체에 적용하거나 특정 네임스페이스에 적용
  • AWS의 경우 IAM을 연동해서 사용 가능

(5) Auto Scaling

  • 손쉽게 리소스 확장 가능
  • Horizontal Pod Autoscaling(HPA) : CPU, MEM 사용량에 따라 Pod 수평 확장 기능
  • Vertical Pod Autoscaling(VPA) : Pod 리소스 할당량 조정 (CPU, memory..)
  • Cluster Autoscaling(CA) : 노드(서버) 개수 조정 가능 (클라우드 환경에서만)

이 외에도 KEDA 라는 오픈소스를 활용하여 HTTP 요청량이나 이벤트 수에 따라 Pod를 스케일링 할 수 있습니다.


(6) Federation, Multi Cluster

  • 클라우드에 설치한 쿠버네티스 클러스터와 자체 서버에 설치한 쿠버네티스를 묶어서 하나로 사용 가능
  • 구글의 Anthos를 이용하면 한 곳에서 여러 클라우드의 쿠버네티스 클러스터들을 관리 가능

이런 특징들이 있지만 단점도 존재합니다.

  • 복잡하고 러닝커브가 높음
  • Yaml 설정 파일은 너무 많고 클러스터를 만드는 것도 쉽지 않음

물론, 모든 리소스들의 복잡한 yaml manifests를 생성하는 것은 매우 어려운 일이고, 서버에 직접 쿠버네티스 클러스터를 구축하는 것도 만만치 않습니다.
하지만 Helm 이라는 패키지 매니저를 사용하면 비교적 편리하게 Yaml 설정 파일을 관리할 수 있으며, 여러 클라우드에서 관리형 서비스를 제공하고 있습니다.

저는 온프레미스 쿠버네티스와 클라우드 쿠버네티스(EKS, ECS, AKS) 구축 및 운영 경험이 있습니다. 클라우드 쿠버네티스는 매우매우 간편하고, 쿠버네티스를 이해하고 공부하기에 매우 도움이 됩니다. 하지만 온프레미스 쿠버네티스 구축은.... 심지어 폐쇄망에 구축되있을 경우 네트워크 부분에서 골치가 아프고 스토리지 (PVC, PV) 관리도 좀 빡셉니다.



쿠버네티스 기본 개념과 구성 요소

마스터 - 노드 구조

  • 중앙(Master)에 API 서버와 상태 저장소를 두고 각 서버(Node) 의 에이전트(kubelet)과 통신하는 단순한 구조
  • 모든 명령은 마스터의 API 서버를 호출하고, 노드는 마스터와 통신하면서 필요한 작업 수행
  • Kubectl 이라는 Client 도구로 API 서버 접근 가능

Desired State

  • 관리자가 서버를 배포할 때 직접적인 동작을 명령하지 않고 원하는 상태를 선언하는 방식을 사용 (RUN x, Create o)

    “nginx 컨테이너를 실행해줘. 그리고 80 포트로 오픈해줘.”
    -> 현재 상태를 원하는 상태로 바꾸기 위한 명령(imperative)
    “80 포트를 오픈한 nginx 컨테이너를 1개 유지해줘”
    -> 원하는 상태를 선언(declarative)

  • Desired State (원하는 상태)

    • 관리자가 바라는 환경 (구체적으로 웹서버 몇개 띄울건지, 몇번 포트로 띄울건지)
    • 현재 상태(current state) 를 모니터링하면서 관리자가 설정한 원하는 상태(desired state)를 유지하는 방향으로 동작
  • 쿠버네티스의 핵심은 상태이며 쿠버네티스를 사용하려면 어떤 상태가 있고 어떻게 상태를 선언하는지를 알아야 함


Kubernetes Object

제가 생각하는 쿠버네티스의 대표적인 Object들은 단연 Pod, Deployment, Service라고 생각을 합니다.
더 다양한 리소스들이 존재하며, 자세한 설명은 쿠버네티스 공식 홈페이지나 관련 서적을 참고 부탁드립니다.

Pod

  • 쿠버네티스에서 배포할 수 있는 가장 작은 단위
  • 한 개 이상의 컨테이너와 스토리지, 네트워크 속성 가짐
  • 컨테이너를 하나만 사용하는 경우도 반드시 Pod으로 감싸서 관리

Replicaset & Deployment

  • Pod을 여러 개(한 개 이상) 복제하여 관리하는 오브젝트
  • 복제할 개수, 개수를 체크할 라벨 선택자, 생성할 Pod의 설정값(템플릿)등 설정
  • 자동으로 롤링 업데이트 가능

Service

  • 네트워크 관련 Object
  • Pod <-> Pod 연결, 외부에서 접근할때 등등 사용

Kubernetes Object Spec 기술 - Manifest 파일

  • 오브젝트의 명세Spec, 상태desired state 정의는 YAML 파일로 정의
  • 오브젝트의 종류와 원하는 상태를 입력
  • 배포 노드나 RBAC(접근 권한 설정) 도 가능

nginx pod 3개를 배포하는 manifest (저는 아래처럼 간단한 컨테이너를 네트워크 설정이나 pvc mount 확인 할 때 테스트 파드로 자주 사용합니다.)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        command: ["/bin/bash", "-c", "--"]
        args: ["while true; do sleep 30; done;"]
        ports:
        - containerPort: 80

Kubernetes 배포 방식

  • 애플리케이션을 배포하기 위해 오브젝트(object)에 라벨Label 을 붙여 원하는 상태(desired state) 로 정의(yaml)하고 API 서버에 전달하는 방식을 사용
  • yaml 파일을 만들어서, 쿠버네티스 API 서버에 전달하면 됨

“tomcat 컨테이너를 2개 배포하고 8080 포트로 오픈해줘”

==> yaml

“컨테이너를 Pod으로 감싸고 type=app, app=web이라는 라벨을 달아줘. type=app, app=web이라는 라벨이 달린 Pod이 2개 있는지 체크하고 없으면 Deployment Spec에 정의된 템플릿을 참고해서 Pod을 생성해줘. 그리고 해당 라벨을 가진 Pod을 바라보는 가상의 서비스 IP를 만들고 외부의 8080 포트를 방금 만든 서비스 IP랑 연결해줘.”




마침

여기까지 쿠버네티스가 왜 등장하게 되었으며 무엇인지, 간단한 특징까지 살펴보았습니다.
이 내용은 제가 쿠버네티스를 다룬지 1년 반 정도 되었을때 회사에서 프레젠테이션한 내용으로 작성한 글입니다. 그래서 기술적인 것 보다 누구나 이해하기 쉬운 내용으로 구성하려고 노력했습니다.
부족한 글이지만 읽어주셔서 감사합니다.

profile
안녕하세요 :) 제 개인 공부 정리 블로그입니다. 틀린 내용 수정, 피드백 환영합니다.

4개의 댓글

comment-user-thumbnail
2023년 7월 20일

글 잘 봤습니다, 많은 도움이 되었습니다.

답글 달기
comment-user-thumbnail
2023년 7월 24일

잘 정리해주셨네요! 덕분에 많이 배우고 갑니다

답글 달기
comment-user-thumbnail
2024년 1월 18일

정리가 잘 되어있어 이해하는데 큰 도움이 되었습니다!
감사합니다.

답글 달기
comment-user-thumbnail
2024년 2월 22일

잘 봤습니다.

답글 달기