본문 바로가기
개인 공부/rookies

docker와 k8s 이해 - 1

by 아메리카노와떡볶이 2022. 10. 20.
728x90
도커와 쿠버네티스 이해

최근 기술 면접에서 도커와 쿠버네티스에 대한 질문을 받았는데, 이번 기회에 확실하게 정리해보고자 도커와 쿠버네티스에 대한 포스팅을 작성하려고 합니다.

 

참고 문헌

해당 내용은 아래의 자료를 참조했습니다.

1 .유튜브 "보안프로젝트"

2. https://wooono.tistory.com/109

 

[Kubernetes] 도커와 쿠버네티스 간단 비교

도커와 쿠버네티스 비교 예시 컨테이너를 하나만 띄워서 사용해야지! => 도커 0월 0시에, 100개의 컨테이너를 자동으로 생성해야지! => 쿠버네티스 즉, 도커는 ’이미지를, 컨테이너에 띄우고 실행

wooono.tistory.com

 

3.https://medium.com/future-vision/docker-lifecycle-tutorial-and-quickstart-guide-c5fd5b987e0d

 

Get Started with Docker Lifecycle

Zero to Hero: Get started with Docker Today!

medium.com

 

먼저 도커에 대해 간단하게 알아보면

 

리눅스의 응용 프로그램들을 프로세스 격리 기술들을 사용해 컨테이너로 실행하고 관리하는 오픈 소스 기술입니다.

 

컨테이너화란 아래 그림과 같습니다.

 

응용 프로그램들을 격리 기술들을 사용해서 컨테이너로 실행하고 관리하는? 

개념적으로 이해는 되는데 개발환경에 어떤식으로 적용되는지 잘 이해가 안갔습니다. 따라서 도커라는 프로젝트가 왜 급부상하기 시작했는지, 기존의 개발방식과 비교해서 어떤 장점이 있었는지? 등 스토리를 이해하며 차근차근 알아보겠습니다.

 

 

1. 모놀리식 아키텍쳐 vs 마이크로서비스 아키텍처


도커는 결국 개발환경을 개선하기 위한 프로젝트 이므로, 기존의 개발방식(아키텍처)와 현재 쓰이고 있는 개선된 개발방식을 이해하는 것이 먼저입니다. 결론부터 말하면 도커는 마이크로서비스 아키텍처를 지원하는 프로젝트입니다.

https://www.redhat.com/ko/topics/microservices/what-are-microservices

 

 

두 그림을 통해서, 모놀리식 아키텍처와 마이크로 서비스 아키텍처의 차이를 살펴보겠습니다.

 

먼저 모놀리식 아키텍처란?

전통적인 아키텍처로 기존에 사용하던 서비스 방법이 이에 해당합니다.

서비스가 하나의 애플리케이션으로 돌아가는 구조로, 다양한 기능을 동작하는 서비스를 서버에서 실행하는 방식입니다.

 

일반적으로 소규모 프로젝트는 위의 방식으로 진행됩니다. 

프로젝트 단위가 작기때문에 개발 - 빌드 - 테스트 - 배포 과정이 용이합니다.  

 

하지만 프로젝트 규모가 커질수록 단점들이 쏟아집니다.

1. 애플리케이션 구동시간이 늘어나고, 빌드와 배포에 시간이 길어집니다.

2. 조그마한 수정사항(단일 서비스에 대한)이 있어도 전체를 다시 빌드하고 배포해야합니다.

3. 많은 양의 코드가 하나의 애플리케이션에서 동작하기때문에 유지보수가 힘이 듭니다.

4. 일부분의 오류가 전체 애플리케이션에 영향을 미칩니다.

5. 기능별로 라이브러리, 언어, 프레임워크 등을 선택하는 과정에서 충돌할 가능성이 생깁니다.

6. scale -out 시에 기존의 애플리케이션을 그대로 복제하기때문에 불필요한 서비스까지 모두 복제합니다.

 

여러 단점을 나열했는데 사실 이 그림만 이해하면 한방에 이해할 수 있습니다.

각 개발자들이 하나의 애플리케이션을 개발하기때문에 .. 빌드하고 나서 어떤 특정 기능에 문제가 생기면

많은 개발자들이 다시 빌드 해야하는 것입니다. 이렇게만 생각해도 상당히 비효율적이죠?

 

이러한 문제를 해결하고자 등장한 새로운 개발 아키텍처가 마이크로서비스 아키텍처입니다.

 

마이크로 서비스 아키텍처란?

마이크로서비스 아키텍처는 하나의 큰 애플리케이션을 여러 개의 작은 서비스 유닛으로 쪼개어 변경과 조합이 가능하도록 만든 아키텍처를 말합니다.

 

각 마이크로서비스는 상호 통신이 가능하며 이를 통해 전체 서비스를 구성하게 됩니다.

애플리케이션이 독립적인 구성 요소로 구축되어 각 애플리케이션 프로세스가 서비스로 실행됩니다.

 

이러한 서비스는 경량 API를 사용하여 잘 정의된 인터페이스를 통해 통신합니다. 서비스는 비즈니스 기능을 위해 구축되며 서비스마다 한 가지 기능을 수행합니다.서비스가 독립적으로 실행되기 때문에 애플리케이션의 특정 기능에 대한 수요를 충족하도록 각각의 서비스를 업데이트, 배포 및 확장할 수 있습니다.

 

흠.. 이런 사전적인 정의는 역시 머리아프죠?

 

간단하게 생각하면 여러 기능을 종합한 하나의 애플리케이션을 개발하고 관리하는 대신

각각의 기능을 분리하여 개발하고 관리하는 아키텍쳐라고 이해하면 됩니다.

이렇게 그림으로 비교해보면 훨씬 와닿으시나요?

 

이렇게 기능별로 빌드 테스트 배포 과정을 진행하게 되면

하나의 서비스에서 에러가 발생하면, 해당 서비스만 리빌딩을 하면 됩니다. 따라서 개발과정이 직관적이고 훨씬 간편해지는 것입니다.

 

장점을 한번 나열해보면 아래와 같습니다.

 

1. 독립적인 서비스로 배포가 빠르고 모놀리식보다 가볍다.

2. 서비스별 개별 배포 가능하여 배포 시 전체 서비스의 중단이 없다.

3. 각 서비스에 따라 개별적으로 서버를 나눌 수 있어 메모리 및 cpu 관리에 효율적이다.

4. 각 서비스가 모듈화 되어있고 모듈끼리 RPC, Message-driven 이용하여 통신하기 때문에 각 서비스의 개발 속도가 증가한다.

5. 분리된 서비스로 개발할 수 있기 때문에 서비스마다 가장 적합한 기술을 선택 할 수 있다.

6. 서버 및 프로세스의 장애 시, 격리 및 복구가 쉬워 장애가 전체 서비스로 확장될 가능성이 적다.

 

하지만 이러한 마이크로서비스 아키텍처에서도 단점이 존재합니다.

각 서비스가 분산되어있기때문에 트랜잭션 관리나, 장애추적, 테스트 등이 쉽지 않습니다.

또한 서비스 별 db가 분리되어 있어 데이터의 조회가 어렵고 중복이 발생할 수 있습니다.

이 외에도 분산 서비스 아키텍처가 가지는 여러 단점이 발생할 수 있는데

 

이러한 여러 단점을 최대한 잘 컨트롤 하는 프로젝트가 바로 도커입니다.

 

2. 도커와 쿠버네티스


 

도커란?

 

도커는 마이크로 서비스 아키텍처에서 서비스를 각 기능별로 분산하여 개발할 때,

해당 기능들을 컨테이너 단위로 관리하는 오픈소스 프로젝트입니다.

 

도커를 얘기하면 바로 따라오는 프로젝트가 쿠버네티스인데,

쉽게 이해하면 도커는 컨테이너 개념화를 지원하는 오픈소스 프로젝트 이고

쿠버네티스는 도커를 관리하는 오픈소스 프로젝트라고 생각하면 됩니다.

 

현재 실무에서는 도커 + 쿠버네티스 조합이 편리해서 많이 쓰이고 있다고 합니다.

 

다른 블로그의 표현을 빌리면 아래와 같은 설명도 있습니다.

 

" 컨테이너를 띄우는 기술 => 도커, 일주일 뒤에 10개의 컨테이너 생성 예약 => 쿠버네티스 "

 

즉, 도커는 ’이미지를, 컨테이너에 띄우고 실행하는 기술’이고 쿠버네티스는 '도커를 관리하는 툴'이라고 생각하시면 됩니다. 따라서, 도커는 '한 개의 컨테이너를 관리’하는 데 최적화 되어있고, 쿠버네티스는 '여러 개의 컨테이너를, 서비스 단위로 관리’하는 데 최적화 되어있습니다.

 

쿠버네티스란?

쿠버네티스는 아까 말했듯 컨테이너를 관리하는 툴입니다.

마이크로 서비스 아키텍쳐에서 살펴보았듯이, 각 서비스가 많아지면(컨테이너의 수가 많아지면) 관리하는데 어려움이 생깁니다. 때문에 이를 효율적으로 관리하고자 쿠버네티스를 사용하는 것입니다.

 

구체적으로는

컨테이너의 실행, 생성, 소멸, 중단점 등을 제어하고 컨테이너 스케줄링, 로드 밸런싱, 클러스터링 등 모든 과정을 관리합니다.

 

아래는 쿠버네티스의 특징들로 다른분의 블로그에서 참조해왔습니다. ( 출처는 참고문헌 )

  • 자동화된 복구(self-healing)
    • 컨테이너들을 모니터링하며, 컨테이너 중 하나라도 죽으면 쿠버네티스는 그것을 빠르게 재시작 시킵니다.
  • 로드 밸런싱(Load balancing)
    • 만약 1만명의 유저가 접속하지만, 당신의 웹/앱은 준비가 되지 않았을 경우
    • 쿠버네티스는 해당 웹사이트의 니즈를 수용할 수 있도록
    • 자동으로 새로운 컨테이너들을 만들 수 있습니다.
    • 또한, 니즈가 줄어들면 컨테이너의 숫자를, 지정해둔 최소 숫자로 자동으로 조절합니다.
    • 이전에는 수동으로 했던 작업들을 쿠버네티스가 자동으로 도와주는 것입니다.
  • 무중단(Fault tolerance-FT) 서비스
    • 기업에서는, 서버 업데이트를 위해서 사용자들이 잠든 새벽 시간을 활용하거나, 긴급 점검의 형태로 서비스를 일시 중단해왔습니다.
    • 하지만, 쿠버네티스는 점진적 업데이트를 제공하기 때문에, 서비스를 중단하지 않고도 애플리케이션을 업데이트할 수 있습니다.
  • 호환성(Vendor Lock In 해결)
    • 고객이 A사의 클라우드를 사용하다가 I사의 클라우드로 환경을 이전하고 싶을 때,
    • 서로 다른 업체(Vendor)의 클라우드 제품 간에 호환 문제가 발생하여 이전하기 어려운 상황을 Vendor Lock In 이라고 합니다.
    • 쿠버네티스는 도커 컨테이너를 기반으로 하는 오픈소스이기 때문에, 사용자들이 특정 업체에 종속되지 않고 클라우드의 환경들을 이전할 수 있습니다.
    • 또한, 한 번 쿠버네티스를 익히면 provider 회사에 상관없이 공통된 마이크로서비스 아키텍쳐 개발이 가능합니다.

요약

  • 도커와 쿠버네티스는 상황마다 다르게 사용됩니다.
  • 한 개의 컨테이너만 사용한다면 쿠버네티스는 필요 없습니다.
  • 쿠버네티스는 많은 컨테이너 관리에 유용합니다.

 

3. 도커와 가상머신


컨테이너랑 가상머신이 뭐가 다른데?

 

도커가 오래도록 이해가 안갔던 이유가 가상머신이랑 뭐가 다른지 이해를 못했습니다. 결국 호스트 PC위에

필요한 환경을 얹는 것은 똑같은 것 아닌가? 도커를 쓰는 이유가 뭐지? 이런 의문이 들었습니다.

 

그래서 도커가 관리하는 컨테이너와 가상머신의 차이를 확실하게 이해해봅시다.

 

컨테이너는 가상머신을 사용해서 각 마이크로 서비스를 격리하는 기술이라고 했습니다.

이때 컨테이너의 장점은 기존 VM처럼 OS를 전부 구현하지 않기때문에 기능이 매우 경량화 되어있습니다.

즉 여러 컨테이너를 호스트 위에 올려도 매우 경량화 되어있어서 CPU나 RAM에 부담이 없다는 뜻입니다.

 

위의 그림을 살펴봅시다.

 

2번째 경우처럼 기존에 알던 가상머신으로 앱을 구축할 경우, 각 vm에 os까지 구현이 되어있습니다.

이러한 vm들은 hypervisor에 의해 관리되고, 안정성있게 동작한다는 장점이 있지만

 

무엇보다 무겁기때문에 호스트의 자원을 많이 차지한다는 점이 가장 큰 단점입니다.

예를 들어 호스트pc에서 피해자 머신으로 웹 서버를, 공격자 머신으로 칼리리눅스 환경을 구축하려고 할때

두개의 vm을 만들어서 구축했었습니다. 그렇게 생각해보면 결국 두개의 os를 구축한 것이기때문에 얼마나 무거운지 체감할 수 있습니다.

 

하지만 3번째 경우처럼 도커 컨테이너를 이용하면 각 컨테이너는 os 없이 해당 기능을 위한 최소한의 용량만 가지게 됩니다. 때문에 경량화 되어있다는 표현을 쓰는 것이고, 호스트 입장에서 자원적으로 매우 효율적이라고 할 수 있습니다.

 

4. 도커 실습


이제 실습을 통해 이론을 실제로 적용해보겠습니다.

sudo apt update
sudo apt install docker.io

 

도커가 잘 설치되었는지 확인해봅시다.

┌──(kali㉿kali)-[~]
└─$ sudo docker version
Client:
 Version:           20.10.19+dfsg1
 API version:       1.41
 Go version:        go1.19.2
 Git commit:        d85ef84
 Built:             Sat Oct 15 15:47:37 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server:
 Engine:
  Version:          20.10.19+dfsg1
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.19.2
  Git commit:       c964641
  Built:            Sat Oct 15 15:47:37 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.8~ds1
  GitCommit:        1.6.8~ds1-1+b1
 runc:
  Version:          1.1.4+ds1
  GitCommit:        1.1.4+ds1-1
 docker-init:
  Version:          0.19.0

 

 

docker hub는 apache, nginx 등 official 웹 서버 이미지는 물론이고 일반 사용자들이 업로드한 다양한 이미지 파일이 존재합니다.  

이제 docker hub 에서 원하는 이미지를 pull 해와야합니다.

https://medium.com/future-vision/docker-lifecycle-tutorial-and-quickstart-guide-c5fd5b987e0d

 

위와 같이 docker 에서 pull 을 통해 nginx 웹 서버 이미지파일을 가져왔습니다. 보면 Pull Complete 가 여러 줄로 되어있는 것을 확인할 수 있는데 이것은 해당 이미지 파일이 여러 레이어로 이루어져있다는 것을 의미합니다. 이 또한 이미지를 효과적으로 관리하기 위해 계층을 나눈 것이라 합니다.

 

docker images 를 확인해보면 nginx 이미지파일이 보입니다. 역시 경량화된 이미지라 그런지 사이즈가 142MB로 VM에 비해 매우 작은 것을 알 수 있습니다.

 

docker run 을 통해 nginx 이미지 파일을 실제 프로세스로 실행시켰습니다.

이때 -itd 는 해당 명령에 대한 옵션으로

-it는 입력모드 실행 즉 컨테이너 생성 후 바로 쉘로 접속되게 하는 옵션입니다.

-d는 background에서 실행되는 것을 의미합니다.

 

-p는 포트포워딩을 의미합니다.

외부에서 해당 이미지(프로세스)에 접근하려고 할때 8888 포트를 통해 접근하고,  해당 서비스에서는 80번으로 포워딩되는 것입니다.

 

아직까지 컨테이너의 장점을 모르겠다구요?

바로 보여드리겠습니다.

8889번 포트를 통해 하나의 웹 서버를 더 열었습니다.

즉 원하는 이미지 파일을 도커 허브에서 pull 해온 뒤에는 run 을 통해 언제든지 원하는만큼(자원내에서) 이렇게 컨테이너 할당을 할 수 있게 되는 것입니다.

 

 

 

컨테이너를 띄운 칼리의 ip를 통해 각 웹 서버에 접속해보면 8888번 포트와 8889번 포트에 잘 접속되는 것을 확인할 수 있습니다.

 

글이 길어진 관계로 1편은 여기까지 ㅎㅎ

728x90

댓글