서론
해당 글은 일프로 님의 인프런 강의 쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2의 내용을 정리한 글입니다.
해당 글에 사용된 내용, 사진 및 그림은 모두 강의와 강의 자료에 포함된 내용입니다.
리눅스 흐름으로 이해하는 컨테이너
선요약
- 쿠버네티스는 현재 표준을 넘어 여러 분야에서 활용되고 있음
- 쿠버네티스는 컨테이너를 더 쉽게 사용할 수 있게 함
- 컨테이너는 쿠버네티스와의 인터페이스(호환성)이 중요함
Linux History
![](https://velog.velcdn.com/images/appti/post/c78fbed9-1e72-47ab-a591-0be85af10c6b/image.png)
- 위와 같이 쿠버네티스는 debian 계열, red hat 계열을 모두 지원
- 어떤 배포판을 선택해야 할지 Linux History를 통해 분석한 뒤 선택
![](https://velog.velcdn.com/images/appti/post/bc7d744d-fef6-4c20-a7c5-b4e3cdcb8dc7/image.png)
- UNIX 등장
- Linux 등장
- 대표 버전
- debian : 무료
- redhat : 유료
- 기업에서 OS를 관리하기 까다로운 경우에 주로 사용
- ubuntu : 무료
- debian 확장 버전
- GUI와 같은 사용자 편의 기능 제공
- red hat
- IBM 인수 전
- fedora -> RHEL -> CentOS 순으로 개발 진행
- fedora : 무료
- Red Hat Enterprise Linux(RHEL) : 유료
- CentOS : 무료
- RHEL을 복사해 만든 배포판
- CentOS 8 : 2021 지원 종료
- CentOS 7 : 2024 지원 종료
- IBM 인수 후
- fedora -> CentOS Stream -> RHEL 순으로 개발 진행
- CentOS Stream : 무료
- 테스트 베드
- 바이너리 호환성 보장이 안될 수 있음
![](https://velog.velcdn.com/images/appti/post/b0c23464-fe86-4b17-850c-de05b642e758/image.png)
- CentOS 사용 방법
- 기존 red hat 계열 Linux를 RHEL로 마이그레이션
- CentOS를 그대로 지원해주는 기업의 서비스 이용
- 타 OS로 마이그레이션 할 수 있도록 스크립트 제공
- red hat을 복사한 무료 배포판 프로젝트 사용
![](https://velog.velcdn.com/images/appti/post/eff0396b-e309-460f-a7b8-7915568338ea/image.png)
- 구글 트렌드, github start 및 fork 수 등 다양한 사항을 고려했을 때 Rocky Linux를 기준으로 강의 진행
- Rocky Linux는 red hat 계열이므로 쿠버네티스 red hat 기반 배포판 사용
컨테이너
![](https://velog.velcdn.com/images/appti/post/d129c311-0e7e-4abe-997f-117c1e7589bf/image.png)
- 도커
- 최초의 리눅스 컨테이너인 LXC 기반으로 생성
- 일반적인 사용자(개발자)라도 누구나 편하게 사용할 수 있음
- 초기에는 root로 설치를 해야 했으므로 보안이 좋지 않았음
- rkt
- 도커 rootless
- rootless 설치 모드를 지원해 보안 문제 해소
- 도커 등장 이후 여러 오케스트레이션 등장(쿠버네티스, 도커 스웜, 노마드 등)
- 쿠버네티스의 인터페이스가 도커와 잘 맞지 않아 도커를 제외
- 앞으로 컨테이너를 선택하는 중요한 요소 중 하나로 쿠버네티스와 호환성이 좋은지 여부가 됨
- 이후 containerd(도커에서 컨테이너를 생성하는 기능만을 분리한 기술)과 cri-o가 등장
- 둘 모두 CNCF에 기부되었으며, containerd는 CNCF를 졸업(Graduated)한 상태
- 여러 기업에서 쿠버네티스를 토대로 제품 개발 시작(기업 관리형)
- 쿠버네티스를 사용하기 위해 사용자가 관리하고 학습해야 하는 내용이 많기 때문에 쿠버네티스 기능을 더 편리하게 지원
- 처음에는 사용자의 편의성을 위주로 컨테이너를 선택
- 이후 컨테이너 오케스트레이션이 사실상 컨테이너와 자주 사용되기 시작
- 컨테이너를 사용자가 직접 다룰 일이 없어짐
- 컨테이너 편의성보다는 컨테이너 오케스트레이션과 호환성이 뛰어난 컨테이너를 선택
- 쿠버네티스가 컨테이너 런타임을 알아서 조작해주기 때문
컨테이너 & 컨테이너 오케스트레이션
- 컨테이너 오케스트레이션
- App을 컨테이너에 담아서 배포
- 시스템 운영 노하우를 많이 가지고 있음(오토 스케일링, 셀프 힐링 등)
![](https://velog.velcdn.com/images/appti/post/ca752970-67a0-4ba3-9d21-c570cff51fe0/image.png)
- 컨테이너
- 컨테이너 생성 시
- 사용자가 App V1 생성을 도커에게 요청
- 도커가 컨테이너 생성
- 컨테이너 변경 시(App V1 -> V2로 마이그레이션)
- 사용자가 App V1 생성을 도커에게 요청
도커가 컨테이너 생성 수행
- 사용자가 App V2가 정상적으로 기동되었는지 확인하기 위해 health check를 도커에게 요청
도커가 컨테이너 조회 수행
- App V2가 정상적으로 기동되었으므로 App V1에 몰려있던 트래픽을 전환하기 위해 도커에게 요청
도커가 네트워크 수정 수행
- App V2가 정상적으로 기동되었으므로 필요가 없어진 이전 버전의 컨테이너 삭제를 도커에게 요청
도커가 컨테이너 삭제 수행
- 컨테이너 오케스트레이션 (쿠버네티스)
- 컨테이너 생성 시
- 사용자가 App V1 생성을 쿠버네티스에게 요청
- 쿠버네티스는 내부적으로 도커에게 컨테이너 생성 요청
- 도커가 컨테이너 생성
- 컨테이너 변경 시(App V1 -> V2로 마이그레이션)
- 사용자가 App V2 생성을 쿠버네티스에게 요청
쿠버네티스는 내부적으로 도커에게 컨테이너 생성 요청 -> 기동 확인을 위한 컨테이너 조회 요청 -> 정상적으로 기동이 된 경우 트래픽 처리를 위한 네트워크 수정 요청 -> 이전 버전 컨테이너 삭제 요청까지 처리
쿠버네티스 흐름으로 이해하는 컨테이너
![](https://velog.velcdn.com/images/appti/post/3ece1dea-c51a-4722-b78c-64c3c76d04dd/image.png)
- LXC
- 커널 레벨의 기술을 가지고 만든 Low Level의 컨테이너 런타임
- 운영체제를 컨테이너 가상화로 나누기 위함
- libcontainer
- LXC 기반으로 만든 Low Level 컨테이너 런타임
- 도커
- libcontainer를 기반으로 만든 사용자 친화적인 High LEvel 컨테이너 런타임
- App을 독립적인 환경에서 실행하기 위함
- rkt
- 도커보다 보안이 좋고 성능도 일부 뛰어남
- Low Level이므로 외면받음
- pod
- 쿠버네티스는 단일 컨테이너를 생성할 수 있는 api는 지원하지 않음
- pod를 생성할 때 하나 이상의 컨테이너를 명시하는 방식
- kube-apiserver
- kublet
- pod 생성을 책임지는 기능
- api 요청에 따라 pod 내부에 생성할 내용을 분석하고 내부 컨테이너에 생성 요청
- kubelet과 컨테이너 인터페이스
- kubelet은 컨테이너 런타임이 받을 수 있는 형태로 api 호출
- 내부 구현 코드를 확인해보면 분기 처리로 도커인지 rkt인지 확인하는 로직 존재
- 관련 호출 api들을 모아놓은 패키지 존재
- 이를 토대로 컨테이너 런타임에 알맞는 요청 처리
- 도커에서 containerd가 분리되는 등 다양한 컨테이너 런타임 등장
- 컨테이너 런타임이 추가될 수록 kubelet을 수정해야 하는 상황이 놓임
- 이를 해결하기 위해 kubelet 인터페이스 추가
- 컨테이너 런타임 인터페이스(CRI, Container Runtime Interface)
- 인터페이스 규격을 정해 구현부 구현
- 구현부는 쿠버네티스 프로젝트에 포함되어 있음
- 오픈 소스이기 때문에 도커나 containerd와 같은 컨테이너 런타임이 쿠버네티스 프로젝트의 소스를 contribution 하는 형태로 진행
- 구현부에서 각각의 컨테이너 런타임 호출
- 이러한 CRI는 내부적으로 grpc를 통해 통신
- v1.27 기본 구조
- v1.23까지는 여전히 구체적인 컨테이너 런타임에 종속적인 상황
- 컨테이너 런타임이 변경되면 CRI 구현체도 수정되어야 함
- 도커에 새 기능이 추가되면 쿠버네티스 프로젝트도 영향을 받아 패치 필요
- 이를 개선하기 위해 kubelet에서 컨테이너 런타임으로 바로 받을 수 있게 구조 변경
- containerd에서는 이를 수행할 수 있는 CRI-Plugin 추가
- cri-o는 처음부터 kubelet의 규격을 맞춘 컨테이너 런타임
- 미란티스 컨테이너 런타임 또한 이 규격을 맞추기 위해 cri-dockerd 추가
용어 정리
- 컨테이너 런타임 : 컨테이너를 생성해주는 역할
- 컨테이너 : 컨테이너 런타임이 만들어준 생산물
도커 엔진 구조
![](https://velog.velcdn.com/images/appti/post/b8d73cb4-c786-4154-9039-bd0ba2ec5bda/image.png)
- dockerd에서 로그, 저장 공간 등 여러 기능을 지원
- 실질적으로 컨테이너를 만드는 역할을 수행하는 것은 containerd
- containerd는 Low Level의 컨테이너 런타임인 libcontainer를 이용
- 쿠버네티스 입장에서는 컨테이너만 생성해야 하기 때문에 dockerd의 부가적인 기능이 과하게 느껴질 수 있음
쿠버네티스 & 도커
- 쿠버네티스에서 도커를 지원하지 않는다는 오해
- v1.0에서 지원하던 로직을 v1.20에서 deprecated
- v1.5부터 인터페이스 규격으로 정한 로직을 사용하겠다는 의미
- CRI 규격에 맞는 dockershim이 그대로 존재하기 때문에 도커는 그대로 사용 가능
- v1.23부터 dockershim deprecated
- 이 때 containerd로 많이 전환됨
- dockershim은 도커를 인수한 mirantis에서 cri-dockerd 어댑터를 통해 쿠버네티스 지원
- 이를 미란티스 컨테이너 런타임이라고 표현함
- 도커 유료화
- 도커라는 컨테이너 런타임을 유료화 하는 것이 아닌, 도커 데스크탑(GUI)를 유료화하겠다는 의미
컨테이너 표준
- OCI(Open Conatiner Initiative)
- 컨테이너 런타임을 만들 때 지켜야 하는 표준 규약 관리
- 이 규약을 지켰다면 컨테이너 런타임끼리 이미지를 공유할 수 있음
- 도커와 containerd 모두 OCI를 지키기 위해 runC를 사용하도록 변경
- runC
- libcontainer와 달리 LXC를 사용하기 않고 커널 레벨의 가상화 기술을 직접 사용
도커에 대한 오해
![](https://velog.velcdn.com/images/appti/post/5f44fd8a-c672-4844-940f-00a3b9b3d34d/image.jpg)
- 도커 유료화 자체는 맞지만, 도커 데스크탑만 유료화되므로 컨테이너 런타임으로의 도커는 무료로 사용 가능
- containerd는 도커 엔진에서 사용하던, 컨테이너 생성 기술만 분리한 기술
- 도커는 OCI 표준을 지키기 때문에 이미지를 다시 만들지 않아도 됨