앞선 논의들을 정리하며 도커에서 쿠버네티스로 생태계가 나아간건지 이해해보자.
컨테이너 기술이란
컨테이너란, 애플리케이션 구동 환경을 추상화할 수 있는 패키징 기술을 뜻한다.
OS의 커널은 공유하면서 사용자마다 각각 격리된 컴퓨팅 자원을 제공해주는 가상화 기술이다.
물류 시장에서 물건을 옮기는 규격화된 박스이자 프로토콜이 컨테이너이듯이,
애플리케이션도 컨테이너라는 표준화된 방식으로 배포한다면, 어떤 환경이든 동일한 방식으로 배포가 가능하다는 측면에서 의의를 갖는다
OS 커널이란?
커널은 컴퓨팅 하드웨어 리소스를 관리하는 메커니즘을 관리하는 것이다.
커널의 기능 커널은 다음과 같은 4가지 기능을 수행합니다.
메모리 관리: 메모리가 어디에서 무엇을 저장하는 데 얼마나 사용되는지를 추적합니다.
프로세스 관리: 어느 프로세스가 중앙 처리 장치(CPU)를 언제 얼마나 오랫동안 사용할지를 결정합니다.
장치 드라이버: 하드웨어와 프로세스 사이에서 중재자/인터프리터의 역할을 수행합니다.
시스템 호출 및 보안: 프로세스의 서비스 요청을 수신합니다.
https://www.redhat.com/ko/topics/linux/what-is-the-linux-kernel
컨테이너를 구성하는 기술
컨테이너 기술 1. 리눅스 네임스페이스
네임스페이스는 하나의 시스템에서 수행되지만, 각각 별개 독립 공간인것처럼 격리된 환경을 제공하는 경량화된 가상화 기술이다.
리눅스 네임스페이스는 프로세스를 실행할 때 시스템의 리소스를 분리해서 실행할 수 있도록 도와주는 기능입니다.
한 시스템의 프로세스들은 기본적으로 시스템의 리소스들을 공유해서 실행됩니다.
이를 단일 네임스페이스라고 생각해볼 수 있습니다.
실제로 리눅스에서는 1번 프로세스(init)에 할당되어있는 네임스페이스들을 자식 프로세스들이 모두 공유해서 사용하는 구조로 이루어져있습니다.
* Cgroup 네임스페이스(cgorup)
* IPC 네임스페이스(ipc) (찾아보니, inter-process communication, 프로세스간 통신)
* 네트워크 네임스페이스(network)
* 마운트 네임스페이스(mnt)
* PID 네임스페이스(pid) (찾아보니, process ID)
* UTS 네임스페이스(user)
* 사용자 네임스페이스(uts)
* 시간 네임스페이스(time)
https://www.44bits.io/ko/keyword/linux-namespace
기존 하이퍼바이저 기반 가상화 기술과 달리, 리눅스 네임스페이스는,
OS의 커널은 공유하고, 유저가 사용하는 스페이스만 격리된다.
컨테이너 런타임은 OS는 공유하지만 라이브러리 단계부터는 별개로 동작한다.
이와 달리 하이퍼바이저 기반의 VM은 OS를 공유하지 않는다.
OS를 공유하지 않기 때문에 가상화 오버헤드가 커서 성능 저하가 발생하지만, 대신 사용자는 자유도가 더 높다.
최근에는 하이퍼바이저 기술의 발전으로 오버헤드가 많이 감소해서, 컨테이너는 가상화로 인한 성능 저하가 거의 없다는 이야기도 있다.
리눅스 네임스페이스는 리눅스 커널을 활용한 것으로,
리눅스 커널을 사용하는 같은 호스트 위에서만 가능하므로, 리눅스 컨테이너만 올릴 수 있다.
(하지만 배포판은 달라도 가능하다 - 우분투나 centos 등)
리눅스 배포판은, 리눅스 커널 위에 올라간다.
커널은 컴퓨팅 하드웨어 리소스를 관리하는 메커니즘을 관리하는 것이다.
배포판은 커널 그 위에 올라가는 프로세스의 관리를 달리 하는 버전들이기 때문에
배포판과 무관히 리눅스 커널 기반이면 가능하다는 의미이다.
컨테이너 기술 2. 리눅스 cgroup
C그룹, 컨트롤 그룹은, 컴퓨팅 리소스 자원에 접근하는 것을 파티셔닝하여 관리하는 기술을 의미한다.
1장. 컨트롤 그룹 (CGROUPS) 소개
Cgroup을 통해 사용자는 CPU 시간, 시스템 메모리, 네트워크 대역폭과 같은 자원이나 이러한 자원의 조합을 시스템에서 실행 중인 사용자 정의 작업 그룹 (프로세스) 간에 할당할 수 있습니다. 또한 설정한 cgroup을 모니터링하거나 특정 자원으로의 cgroup 액세스를 거부하는 것 이외에 실행 중인 시스템에서 cgroup을 동적으로 다시 구성할 수 있습니다. cgconfig (“control group config ”) 서비스는 부팅시 시작 및 사전 정의된 cgroup을 다시 구성하도록 설정하여 재부팅 후에도 구성된 사항이 지속되도록 설정할 수 있습니다. 시스템의 프로세스들은 기본적으로 시스템의 리소스들을 공유해서 실행됩니다.
https://access.redhat.com/documentation/ko-kr/red_hat_enterprise_linux/6/html/resource_management_guide/ch01
cgroup은 단일 또는 태스크 단위의 프로세스 그룹에 대한 자원 할당을 제어하는 커널 모듈입니다. Cgroup은 Control group으로 처음 개발되었을 때는 group이 아니라 container란 용어를 사용했었습니다. 하지만 container란 용어는 너무 많은 의미를 내포하고 있다고 판단하여 지금의 group이만 이름으로 변경되었습니다. 현재 cgroup은 v1와 v2 두가지 버전이 공존하고 있습니다. v1의 서비스시템 중 일부는 v2에 포함되어 있는 상태입니다. 언젠가 v2만 남겠죠..? cgroup의 실체는 파일시스템입니다. cgroup은 오직 프로세스(태스크) 들을 그룹화 하는 역할만 하며 내부적으로 자원을 제한하거나 할당하는 역할은 서브시스템에서 수행됩니다. 출
출처: https://sonseungha.tistory.com/535 [Developer's Delight]
컴퓨팅 리소스 자원에 접근하는 것을 파티셔닝하여 관리하는 기술로,
CPU 할당, Memory, Disk IO, Network, Device 접근제한 등,
다수의 컨테이너가 호스트를 공동으로 사용하므로 리소스 과점을 막는 기능을 수행한다.
도커가 주목을 받게 된 이유
컨테이너의 대중화를 이끈 도커의 등장
도커란, 컨테이너 기반 오픈소스 가상화 플랫폼이다.
2013.03 파이콘 세션에서 처음 공개되었다.
도커는 기존 리소스 격리 기술과 네트워크, 파일시스템 기술을 조합해 편의성을 올렸다.
새로운 혁신이라기 보다, 조합을 통한 편의성 극대화가 더 걸맞는 표현이라는 평이다.
도커의 특징
도커의 특징 1. 네트워크 가상화 & 리눅스 브릿지
도커를 통해 우리는 리눅스 네임스페이스를 활용해 독립된 네트워크 영역을 할당받는다.
각 컨테이너마다 격리된 독립적 네트워크 환경을 가지게 되는데,
도커를 통해서는 네트워크 가상화가 진행되기 때문에,
같은 호스트 안에 컨테이너 A, B가 있을 때 각각의 네트워크를 가지고 있다는 것이다 (도커가 자동으로 생성).
서로 격리된, 별개의 네트워크를 가졌다는 의미는,
같은 호스트 안에 있어도 서로를 모른다는 것이고,
같은 호스트 안에 있더라도 다른 컨테이너와 통신하기 어렵다는 이미이다.
이 문제를 해결하기 위해, 리눅스 브릿지를 활용해 옆에 있는 컨테이너와 통신한다.
도커에서의 브릿지 도커에서의 브릿지는 주로 소프트웨어 브릿지를 의미합니다.
이 브릿지는 같은 브릿지에 연결된 컨테이너들끼리의 통신을 할 수 있게 해 주고,
브릿지에 연결되지 않은 컨테이너로부터는 고립시켜주는 역할을 합니다.
이 브릿지 네트워크는 같은 도커 데몬 호스트의 컨테이너에서만 동작합니다.
즉 다른 도커 데몬 호스트의 컨테이너와는 OS 레벨의 라우팅이 필요합니다.
대안으로는 overlay 네트워크를 사용하는 방법이 있습니다.
도커를 설치하고, 실행하면, 기본적으로 브릿지 네트워크가 생성되어있는 것을 확인할 수 있습니다.
도커 컨테이너를 생성할 때에 아무런 네트워크를 설정해주지 않으면 자동으로 기본 브릿지 네트워크에 연결됩니다.
도커에서는 사용자가 직접 브릿지를 만드는 것도 가능합니다.
https://mns010.tistory.com/20
리눅스 브릿지를 활용해 컨테이너 내부 통신을 진행할 때는에는,
컨테이너 각각이 격리되어 있으므로 호스트 내부에서 사용할 컨테이너 포트는 중복되어도 무관하다.
여기서 잠깐! 도커 데몬이란?
도커의 구조
우리는 도커를 사용할 때 docker라는 명령어를 맨 앞에 붙여서 사용합니다. 그리고 실제 docker는 /usr/bin/docker에 위치하고 있습니다. 이는 'which docker' 를 입력하면 확인할 수 있습니다. 이처럼 도커 명령어는 /usr/bin/docker에 위치한 파일을 통해 사용되고 있습니다. 하지만 실제 도커 엔진의 프로세스를 확인해보면 /usr/bin/dockerd 파일로 실행되는 것을 알 수 있습니다. 컨테이너나 이미지를 다루는 명령어는 /usr/bin/docker에서 실행되지만 도커 엔진의 프로세스는 /usr/bin/dockerd 파일로 실행되고 있습니다. 이는 docker의 명령어가 실제 도커 엔진이 아닌 클라이언트로서의 도구이기 때문입니다.
도커의 구조는 크게 두 가지로 나누어집니다. 하나는 클라이언트로서의 도커이고, 다른 하나는 서버로서의 도커입니다.
실제로 컨테이너를 생성하고 실행하며 이미지를 관리하는 주체는 서버도커이고, 이는 dockerd 프로세스로서 동작합니다. 도커 엔진은 외부에서 API 입력을 받아 도커 엔진의 기능을 수행하는데, 도커 프로세스가 실행되어 서버로서 입력을 받을 준비가 된 상태를 도커 데몬이라고 이야기합니다.
출처: https://junstar92.tistory.com/169 [별준 코딩]
도커의 특징 2. 외부 통신을 위한 포트 노출
호스트 내부의 통신은 리눅스 브릿지를 활용한다면,
호스트 바깥과의 통신은 포트를 활용해 통신한다.
인터넷 프로토콜 스위트에서 포트(port)는 운영 체제 통신의 종단점이다. 이 용어는 하드웨어 장치에도 사용되지만, 소프트웨어에서는 네트워크 서비스나 특정 프로세스를 식별하는 논리 단위이다. 주로 포트를 사용하는 프로토콜은 전송 계층 프로토콜이라 하며, 예를 들어 전송 제어 프로토콜(TCP)와 사용자 데이터그램 프로토콜(UDP)가 있다. 각 포트는 번호로 구별되며 이 번호를 포트 번호라고 한다. 포트 번호는 IP 주소와 함께 쓰여 해당하는 프로토콜에 의해 사용된다.
https://ko.wikipedia.org/wiki/%ED%8F%AC%ED%8A%B8_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9)
컴퓨터에서의 포트(port)란 외부의 다른 장비와 접속하기 위한 플러그와 같은 것을 의미합니다.
이러한 포트 개념은 프로그램에도 있습니다. 만약 우리가 웹브라우저를 이용하여 인터넷상에 있는 서버에 접속할 때 컴퓨터에 있는 웹브라우저 프로그램과 서버에 있는 웹서버 프로그램간을 연결해주는 플러그와 같은 역할을 하는 것이 포트입니다!
우리가 특정 서버에 접속하려면 URL이나 IP 주소를 입력합니다. 그러면 인터넷상에서 URL 또는 IP를 토대로 해당 서버가 있는 컴퓨터로 찾아갑니다. 그런데 대부분의 컴퓨터에서는 여러 개의 프로그램이 동시에 실행되고 있어서, 이 여러개의 프로그램 중 어느 프로그램이 내가 접속하려는 프로그램인지 컴퓨터에게 알려 주어야 합니다. 여기서! 포트 번호는 어떤 프로그램에 접속 할 것인지 컴퓨터에게 알려줍니다.
https://run-it.tistory.com/19
포트는 간단히 이야기하면, 와이파이 공유기와 같다.
집 바깥, 외부에서 집에 있는 컴퓨터로 원격접속할 때 포트포워딩을 한다고 보면 된다.
포트를 호출해 연결된 안쪽 포트로 포워딩하는 것이다.
이처럼, 컨테이너 내부 네트워크 중 바깥으로 노출한 포트를 외부와 연결해 통신한다
(port expose가 그것이다) - expose, 포트 노출을 진행해야지만, 외부 통신이 가능하다.
다만, 앞에서 설명한 호스트 내 컨테이너 간 통신에서는 컨테이너별 포트가 중복되어도 무관했지만,
호스트 외부의 통신의 경우, 호스트의 포트가 필요한데, 호스트의 포트는 동시 점유가 어려워, 중복 사용이 불가능하다.
도커의 특징 3. 이미지 레이어
도커는 유니온 파일 시스템을 기반으로 해서, 여러 레이어로 파일 시스템을 겹겹이 쌓는다.
UFS는 Union File System의 약자이다. UFS는 여러 개의 파일 시스템을 하나의 파일 시스템에 마운트 하는 기능이다. 여러 파일 시스템을 하나로 합치다보면 중복되는 파일이 있기 마련인데, UFS에서는 이 경우 나중에 마운트된 파일로 덮어쓴다(overlay).도커 이미지에서 레이어는 개념적으로 각각의 파일 시스템을 겹쳐 놓은 형태와 유사하다. 도커의 컨테이너는 UFS를 기반으로 동작한다. 도커의 이미지와 컨테이너의 관계는 일반적으로 바이너리 프로그램과 프로세스의 관계와 유사하다. 하나의 바이너리 프로그램에서 여러 개의 프로세스가 독립적으로 실행될 수 있듯이, 하나의 이미지로 여러 컨테이너를 독립적으로 실행할 수 있다. 그런데, 하나의 이미지에서 생성된 컨테이너들이 동일한 파일 시스템을 공유하고 있다면 어떻게 컨테이너가 독립적으로 실행될 수 있을까? 해답은 UFS의 CoW(Copy on Write) 전략과 관련이 있다. UFS에서는 기존 레이어(하위 레이어) 위에 새로운 레이어(상위 레이어)가 쌓일 경우, 하위 레이어는 읽기 전용 상태가 된다. 또한, 상위 레이어에서 하위 레이어에 쓰기 작업을 수행할 경우, 하위 레이어를 복사하여 사용(CoW)하기 때문에 상위 레이어에서는 하위 레이어에 아무런 영향을 주지 않는다.
https://velog.io/@koo8624/Docker-%EC%9C%A0%EB%8B%88%EC%98%A8-%ED%8C%8C%EC%9D%BC-%EC%8B%9C%EC%8A%A4%ED%85%9C-Union-File-System
하나의 이미지라도 여러개의 레이어라도 구성된다.
이 여러개의 이미지를 하나로 결합해 하나인 것처럼 보여주는 것이 유니온 파일 시스템이다.
예를 들어, 우분투 위에 Nginx를 설치한다면, 우분투 위에 하나의 레이어를 얹어 이미지로 말아버린다.
그 위에 웹앱 소스코드 레이어를 추가하면, 그 아래를 손대지 않고 하나의 이미지로 말아버리고 배포한다.
도커의 배포도, 이미지 레이어 설명 맥락에서 이야기하자면,
파일 시스템 레벨에서 생각하면, 웹앱을 컨테이너로 만드는 행위이다.
즉 도커의 배포는 기존 이미지 위에 읽기 쓰기가 가능한 레이어를 하나 더 쌓는 행위이다.
이미지화된 기존의 레이어는 읽기 권한만 설정된 수정 불가능 레이어로 보면 된다.
도커의 특징 4. 도커 파일, 빌드와 배포
도커 컨테이너를 이미지화 하는 도커 빌드 행위에서, 어떻게 빌드할지에 대한 명세서가 바로도커 파일이다.
즉 도커 파일만 있으면 이미지가 없어도 명세에 따라 언제나 같은 이미지를 다시 생성할 수 있다.
빌드된 이미지는, 도커 노드의 로컬에 존재한다. (명령을 수행한 호스트의 로컬)
이를 push하여 도커 허브나 특정 프라이빗 레지스트리로 네트워크 통해 올린다.
업로드된 이미지를 각 호스트 별로 run을 통해 컨테이너로 배포한다.
pull을 통해 실행은 안하고 이미지만 당겨올 수도 있다.
이미지는 레이어들을 합친 수정 불가능한 읽기 전용 파일 시스템이다.
COW = Write하는 순간에 Copy해서 공유한다.
컨테이너 배포를, Read-write 권한 가진 변경분을 추가하는 것으로 해석할 수 있는 이유는 그것 때문이다.
이러한 도커의 특성 덕에 우리는 새로운 인프라 관리 기법을 맞이했다.
Immutable Infrastructure
인프라 관리 기법의 하나로,
서비스 환경을 한번 생성 하면 변경되지 않는 이미지 형태로 묶고, 이를 기반으로 배포한다는 것이다.
Immutable Infrastructure ( 변경 불가능한 인프라 )
변경 불가능한 인프라는 서버를 일회용으로 취급하는 개념이고, 변경 가능한 인프라는 항상 운영가능한 상태이고, 대체 불가능한 유일한 시스템으로 다루는 개념입니다.
모든 서버를 동일한 상태로 유지
서버를 수동이 아닌 자동화된 방식으로 관리한다는 것은 관리의 효율성은 보장하지만 모든 서버들의 상태를 동일하게 유지 한다고 할 수 없습니다. “변경 불가능한 인프라”에서는 서버의 변경이 필요하게 되면 모든 서버의 이미지를 새로 만들기 때문에 모든 서버가 동일한 상태임을 보장합니다
언제든지 즉시 운영 가능한 서버 구축
언제든지 즉시 운영 가능한 서버 환경을 구축할 수 있다면 서비스의 가용성을 확실하게 보장 할 수 있습니다.
Provisioning 은 단순하게
mmutable Infrastructure 환경에서는 최초의 상태에서 변화가 필요없기 때문에 역동성이 불필요합니다. 테스트의 편이성 Immutable Infrastructure에서는 개발/스테이징/운영 단계에서 모든 서버 상태가 동일하게 보장되어 있기 때문에, CI를 통한 테스트에 대한 신뢰도가 높아집니다.
Docker Test 편이성 제공
애플리케이션 이식성 향상 Docker Hub 를 통해 컨테이너 이미지를 공유 할 수 있기 때문에 전세계 누구나 동일한 시스템 사양이면 같은 환경의 서버를 구축 할 수 있습니다. 글로벌한 개발 커뮤니티에서는 머신 이미지와 간단한 스크립트를 공유하면 손쉽게 개발환경을 공유할 수 있습니다.
http://www.opennaru.com/openshift/immutable-infrastructure-vs-old-infra/
예전에는, 서버를 만들고, 앱을 올리고, 잘 운영되도록 설정을 올리고,
업데이트 시에는, 서버에 앱을 재설치하고, 설정을 다시 넣어 재사용했다.
서버가 죽지 않게 관리하는 게 중요하던 과거에는 앱을 덧씌우며 유지했다.
하지만, 컨테이너의 등장으로,
소스 A 기반으로 서버를 배포하면, 소스 A를 구워내 컨테이너로 배포했다고 할 때,
추가 소스 B의 경우, 다시 그 소스 코드를 다시 배포하고, 기존에 있던 A 컨테이너는 죽일 수 있다.
서버의 재사용이 아니라, 컨테이너의 생성 삭제가 간편해졌으므로 기존 서비스는 죽인다는 것이다.
서버 개별 라이프사이클 관점에서 변경이 없는 것으로,
수정 사항이 있으면 그냥 이미지를 교체하게 되어, 빠른 교체로 중점이 변경되었다.
도커 네트워크 문제
네트워크 가상화 문제를 다룬 앞부분을 조금 더 깊이 확인해보자.
도커 네트워크 전제 : 컨테이너는 격리된 네트워크를 가진다
도커는 리눅스 네임스페이스를 기반으로 네트워크 가상화를 진행한다.
각 독립된 네트워크 환경이 주어지는 컨테이너 입장에서는,
호스트의 네트워크 정보를 알 수 없으며 같은 호스트 내 다른 컨테이너 정보도 알 수 없다.
컨테이너는 각자 네트워크 디바이스와 IP를 가지고 있다.
네트워크 디바이스 = 이더넷 인터페이스 = 노트북 네트워크 어댑터의 가상 버전
가상 어댑터에 할당된 IP는, 내부 프라이빗 IP로 디폴트 값은 172.17.X.X가 할당된다.
컨테이너 내부 확인 가능한 디바이스는 VETH, Virtual Ethernet Interface (Device)라 부른다.
veth: 리눅스 가상 이더넷 인터페이스란?
veth는 리눅스의 버추얼 이더넷 인터페이스를 의미합니다. v
eth는 쌍으로 만들어지며 네트워크 네임스페이스들을 터널로서 연결하거나,
물리 디바이스와 다른 네트워크 네임스페이스의 장비를 연결하는 용도로 사용할 수 있습니다.
https://www.44bits.io/ko/keyword/veth
도커 컨테이너는 IP 상태 정보를 저장하지 않는다
컨테이너는 자신의 네트워크 상태 정보를 저장하고 있지 않다.
컨테이너 재시작 시, MAC / IP 주소 모두 초기화되어 변경된다는 의미이다.
그리고, 컨테이너는 언제든 사라질 수 있음을 가정해야 한다.
컨테이너를 올린다는 것은 각각 프로세스 - OS 레벨에서, 어떤 파일 정보를 구동시키기 위해 메모리를 할당하는 행위이다.
컨테이너는 시작하면서 메모리에 올라가는 순간 프로세스가 구동되는 행위이므로
수초 안에 동작될 수 있도록, 언제든지 재시작이 가능하도록 가정해야 한다.
따라서 컨테이너는 IP 설정 통신을 조심해야 한다
동일 호스트 내 컨테이너 사이 통신을 위해 리눅스 브릿지를 활용한다고 이야기했다.
이때 리눅스 브릿지는 네트워크 레이어 2라고 보면 된다.
격리된 네트워크 환경마다 이더넷 인터페이스가 생기고, 리눅스 브릿지를 통해 레이어2 통신을 한다.
여기서 잠깐! 네트워크 레이어 2 통신이란?
OSI 7 계층이란?
OSI 7 계층은 네트워크에서 통신이 일어나는 과정을 7단계로 나눈 것을 말한다.
계층을 나눈 이유는 통신이 일어나는 과정이 단계별로 파악할 수 있기 때문이다.
1계층 - 물리계층(Physical Layer)
이 계층에서는 주로 전기적, 기계적, 기능적인 특성을 이용해서 통신 케이블로 데이터를 전송하게 된다.
2계층 - 데이터 링크계층(DataLink Layer)
물리계층을 통해 송수신되는 정보의 오류와 흐름을 관리하여 안전한 정보의 전달을 수행할 수 있도록 도와주는 역할을 한다.
따라서 통신에서의 오류도 찾아주고 재전송도 하는 기능을 가지고 있는 것이다. 이 계층에서는 맥 주소를 가지고 통신하게 된다.
이 계층에서 전송되는 단위를 프레임이라고 하고, 대표적인 장비로는 브리지, 스위치 등이 있다.(여기서 MAC주소를 사용한다.)
MAC 주소
MAC 주소(Media Access Control Address)는 네트워크 세그먼트의 데이터 링크 계층에서 통신을 위한 네트워크 인터페이스에 할당된 고유 식별자이다.
https://ko.wikipedia.org/wiki/MAC_%EC%A3%BC%EC%86%8C
3계층 - 네트워크 계층(Network Layer)
이 계층에서 가장 중요한 기능은 데이터를 목적지까지 가장 안전하고 빠르게 전달하는 기능(라우팅)이다.
여기에 사용되는 프로토콜의 종류도 다양하고, 라우팅하는 기술도 다양하다.
이 계층은 경로를 선택하고 주소를 정하고 경로에 따라 패킷을 전달해주는 것이 이 계층의 역할이다.
3-1) IP계층 : TCP/IP 상에서 IP 계층이란 네트워크의 주소 (IP 주소)를 정의하고, IP 패킷의 전달 및 라우팅을 담당하는 계층
3-2) IP 프로토콜 : TCP/IP 기반의 인터넷 망을 통하여 데이타그램의 전달을 담당하는 프로토콜
4계층 - 전송 계층(Transport Layer)
통신을 활성화하기 위한 계층이다. 보통 TCP프로토콜을 이용하며, 포트를 열어서 응용프로그램들이 전송을 할 수 있게 한다.
만약 데이터가 왔다면 4계층에서 해당 데이터를 하나로 합쳐서 5계층에 던져 준다.
단대단 오류제어 및 흐름제어 이 계층 까지는 물리적인 계층에 속한다.(TCP/UDP프로토콜을 사용한다.)
5계층 -세션 계층(Session Layer)
데이터가 통신하기 위한 논리적인 연결을 말한다. 통신을 하기위한 대문이라고 보면 된다.
세션 계층(Session layer)은 양 끝단의 응용 프로세스가 통신을 관리하기 위한 방법을 제공한다.
6계층 - 표현 계층(Presentation Layer)
데이터 표현이 상이한 응용 프로세스의 독립성을 제공하고, 암호화 한다.
7계층 - 응용 계층(Application Layer)
최종 목적지로서 HTTP, FTP, SMTP, POP3, IMAP, Telnet 등과 같은 프로토콜이 있다.
해당 통신 패킷들은 방금 나열한 프로토콜에 의해 모두 처리되며 우리가 사용하는 브라우저나, 메일 프로그램은 프로토콜을
보다 쉽게 사용하게 해주는 응용프로그램이다. 한마디로 모든 통신의 양 끝단은 HTTP와 같은 프로토콜이지 응용프로그램이 아니다.
표현 계층(Presentation layer)은 코드 간의 번역을 담당하여 사용자 시스템에서 데이터의 형식상 차이를 다루는 부담을 응용 계층으로부터 덜어 준다. MIME 인코딩이나 암호화 등의 동작이 이 계층에서 이루어진다.
리눅스 브릿지라는 큰 하나의 네트워크 공간체를 만들어 브릿지를 통한 통신을 진행한다.
도커의 경우 docker0라는 이름으로 만든다. 도커 내에서 docker0라는 인터페이스를 항상 확인할 수 있다
systemctl status docker >> docker 있음을 확인
ifconfig >> docker0 혹은 bridge0라는 가상 인터페이스 확인 가능
brctl show >> docker0 확인 가능
도커에는 브릿지가 없었던 과거가 있다 - 의존성 문제 일으키는 링크
도커가 처음 나왔을 때, 컨테이너 간 통신 이슈가 등장했다.
하지만 지금과 달리 브릿지라는 기술을 활용하지 않았고, 컨테이너 간 통신을 링크를 통해 구현했었다.
컨테이너 재시작시 IP가 변경될 수 있으므로, IP 기반 통신은 위험하다고 이야기한 바 있다.
링크란, 컨테이너가 배포될 때 링크라는 것을 설정해서,
링크의 대상이 되는 컨테이너 B를 먼저 배포하고, 컨테이너 A를 배포할 때 설정을 통해 link를 B로 설정해 연결하는 방식이다.
IP 변경과 무관히 정해진 링크 값으로 연결한다.
컨테이너 재배포시마다 endpoint IP를 변경해주는 기술을 활용한 것이다.
이런 링크에게는, 컨테이너 간 실행 순서가 존재해야 한다는 치명적인 문제가 발생한다.
링크의 대상이 되는 컨테이너를 무조건 먼저 배포해야 한다.
이는 컨테이너 간 의존성이 생긴다는 의미이고, 컨테이너 배포의 본질인 유동성을 잃게 되는 것이다.
호스트가 2개로 분리되었다고 한다면?
프로덕션 레벨로 확장하려면 호스트도 다수로 운영해야 하는데,
이때는 링크를 활용할 수도 없다. 호스트 외부 통신이 구현되지 않았던 것이다.
링크는 같은 노드, 같은 호스트 안에서만 사용 가능하기 때문이다.
브릿지 네트워크가 있으면 브릿지 레벨로 통신이 가능한데, (Layer 2)
같은 호스트에서는 통신 가능하지만, 멀티 호스트는 불가
컨테이너 포트 - 도커0 - 호스트 포트 - 외부 호스트 포트 - 외부 호스트 도커0 - 외부컨테이너 포트
결국 컨테이너 간 노드가 다를 경우, 외부 호스트 IP를 알아야 하고, 노출 포트도 알아야 함
즉, 어느 호스트에 가 있는지가 중요해지는 외부 호스트와의 통신.
-> 컨테이너와 호스트 간 의존성이 발생
그럼 지금 기술은 어디까지 왔지? 도커 컴포즈 살펴보기
도커-컴포즈 :
여러개의 컨테이너를 동시에 실행하고 배포하는 도구이다.
Docker CE 설치 시 기본 제공되는 Docker Compose를 의미한다.
YAML 파일로 정의해 형상 관리가 가능하다.
여러개의 컨테이너를 동시에 docker-compose up으로 띄울 수 있다.
docker compose로 다수의 컨테이너를 올리면,
컨테이너는 개별적이지만, 네트워크는 그 둘을 공유해버린다.
즉, 같은 호스트 안의 여러 컨테이너끼리 로컬 통신처럼 그냥 통신할 수 있다.
(docker0과 같은 연동 필요 없음)
도커 컴포즈도 문제가 있는데 하나의 호스트 내 멀티 컨테이너에는 유리하지만, 노드가 분리되면 문제는 여전히 남는다는 점이다.
호스트 외부 통신 ) 포트 중복 불가로 인한 호스트 - 컨테이너 의존성 문제
컨테이너가 호스트 바깥의 외부와 통신할 경우 이런 순서로 통신한다.
컨테이너 가상 인터페이스 - docker0 - 호스트 실제 eth0
컨테이너는 미리 정의된 포트를 노출할 수 있다. (layer 4)
외부 통신을 위해 docker host의 eth0에서 사용할 컨테이너의 port를 바인딩해서 사용한다.
도커 호스트 포트가 각 컨테이너 포트로 라우팅되는 것이다. (DNAT 기술을 통한 config)
여기서 잠깐! DNAT이란?
NAT, 네트워크 주소 변환
네트워크 주소 변환(영어: network address translation, 줄여서 NAT)은 컴퓨터 네트워킹에서 쓰이는 용어로서, IP 패킷의 TCP/UDP 포트 숫자와 소스 및 목적지의 IP 주소 등을 재기록하면서 라우터를 통해 네트워크 트래픽을 주고 받는 기술을 말한다. 패킷에 변화가 생기기 때문에 IP나 TCP/UDP의 체크섬(checksum)도 다시 계산되어 재기록해야 한다. NAT를 이용하는 이유는 대개 사설 네트워크에 속한 여러 개의 호스트가 하나의 공인 IP 주소를 사용하여 인터넷에 접속하기 위함이다. 많은 네트워크 관리자들이 NAT를 편리한 기법이라고 보고 널리 사용하고 있다. NAT가 호스트 간의 통신에 있어서 복잡성을 증가시킬 수 있으므로 네트워크 성능에 영향을 줄 수 있는 것은 당연하다.
https://ko.wikipedia.org/wiki/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC_%EC%A3%BC%EC%86%8C_%EB%B3%80%ED%99%98
(NAT을 사용하는 목적)
첫째, 인터넷의 공인 IP주소를 절약할 수 있다는 점
둘째, 인터넷이란 공공망과 연결되는 사용자들의 고유한 사설망을 침입자들로부터 보호할 수 있다는 점
출처: https://jwprogramming.tistory.com/30 [개발자를 꿈꾸는 프로그래머]
NAT를 사용해 네트워크 주소를 변환할 때 어떤 IP 주소를 변환하는지에 따라 두 가지로 구분합니다.
• SNAT(Source NAT) - 출발지 주소를 변경하는 NAT
• DNAT(Destination NAT) - 도착지 주소를 변경하는 NAT
SNAT와 DNAT는 트래픽이 출발하는 시작 지점을 기준으로 구분합니다.
어떤 주소를 변경해야 하는지는 서비스 흐름과 목적에 따라 결정됩니다.
앞에서 말했듯이 SNAT와 DNAT의 기준은 NAT가 수행되기 이전의 트래픽이 출발하는 시작 지점입니다.
즉, 요청 시 SNAT를 해 목적지로 전송하면 해당 트래픽에 대한 응답을 받을 때는 출발지와 목적지가 반대가 되므로 DNAT가 되는데 이때 트래픽을 요청하는 시작 지점만 고려해 SNAT 설정을 해야 합니다.
이러한 구조에서, 앞에서 설명했듯 호스트 외부와의 통신에는, 포트 중복이 어렵다는 문제가 있다.
이는 프로덕션 레벨로 확장할 때 치명적이다. 여러 호스트와의 외부 통신이 필요하기 때문이다.
호스트 당 포트 중복이 안되는 것은,
같은 종류의 컨테이너는 도커 호스트 당 단일 컨테이너만 가능하다는 의미이고,
이는 호스트 - 컨테이너 간 의존성이 발생했다는 것이다.
결론은? 쿠버네티스
결국 이런 도커의 여러 컨테이너를 한번에 잘 관리할 수 있는,
도커 매니지먼트 시스템의 일환으로 등장한 것이 쿠버네티스였고,
쿠버네티스를 통해 이런 네트워크 기술 상의 의존성 문제를 비롯해
대규모 프로덕션 운영 상의 문제를 모두 해결해주었다!
다음 글은, 개발자가 바라보는 쿠버네티스의 의의를 살펴보자!
'기술 공부 > 쿠버네티스' 카테고리의 다른 글
쿠버네티스 (1-5) | 쿠버네티스 소개 (0) | 2022.02.02 |
---|---|
쿠버네티스 (1-4-2) | 개발자가 바라보는 도커의 필요성 (0) | 2022.01.18 |
쿠버네티스 (1-3) | 도커 이미지 멀티 스테이지 빌드 및 경량화 (0) | 2022.01.18 |
쿠버네티스 (1-2) | 도커 파일 명령어 정리 (0) | 2022.01.18 |
쿠버네티스 (1) | 도커의 기본 개념 (0) | 2022.01.11 |