티스토리 뷰
K8s는 컨테이너를 그 자체로 관리하지 않고 여러개의 컨테이너를 묶어 또 하나의 Object 단위로 관리합니다.
이때, 여러개의 컨테이너가 묶여 있는 기본 관리 단위를 Pod라고 하며, K8s는 Pod 단위로 대부분의 작업을 처리합니다.
즉, Pod는 1개 이상의 컨테이너로 구성된 컨테이너의 집합이고, 하나의 Pod 안에는 여러개의 컨테이너가 존재합니다.
물론 Pod 안에 1개의 컨테이너로 구성하는 것도 가능합니다.
기본적으로 컨테이너들은 리눅스에서 제공하는 다양한 기본 관리 기능을 이용하여 컨테이너 운영환경을 제공합니다.
예를 들어, cgroup은 프로세스의 자원사용량을 제한하며, namespace는 프로세스의 격리된 환경을 제공합니다.
이 중 namespace는 하나의 시스템 내에서 다수의 독립된 공간으로 격리된 환경을 제공하는 가상화 기술로써,
컨테이너 관련 기술은 모두 namespcae 기반의 격리를 밑바탕으로 하고 있습니다.
다만, namespace를 이용한 컨테이너간의 격리는 모든 자원에 대한 완벽한 격리는 아닙니다.
일부 namespace의 경우 컨테이너끼리 공유되며, OS의 권한을 통해 컨테이너 안의 파일에 접근할 수도 있습니다.
따라서, 하이퍼바이저를 이용한 서버가상화의 격리 수준과 비교해 보자면, 상대적으로 약한 격리라고 볼 수 있습니다.
앞서 말한 Pod 내 공유되는 namespace는 무엇이 있을까요?
Pod내 위치한 컨테이너는 Network namespace와 IPC namespace를 모두 동일하게 사용합니다.
즉, 하나의 namsespace를 공유하여 사용합니다.
1. Network namespace
프로세스의 네트워크 환경을 분리할 수 있는 namespace입니다.
다른 namespace에 속한 프로세스들에게 새로운 IP를 부여하거나, 새로운 인터페이스를 추가할 수 있습니다.
2. IPC(Interprocess Communication) namespace
프로세스간 서로 데이터를 주고 받는 경로를 뜻하며, 대표적인 IPC 방식은 Signal, Socket, pipe 등이 있습니다.
IPC namespace는 IPC 리소스를 격리시켜 줍니다.
그럼 Pod 내 공유하는 Network namespace와 IPC namespace에 대한 정보 관리는 누가 하는걸까요?
Pod 내에서 먼저 생성된 컨테이너가 나중에 생성된 컨테이너에 제공하는 것일까요?
만약 그렇다면 namespace를 생성한 컨테이너에 문제가 생기면 공유받은 컨테이너는 어떻게 되는 걸까요?
기본적으로 Pod 안에는 PAUSE 컨테이너라 불리는 기본 컨테이너가 위치하고 있습니다.
PAUSE 컨테이너는 별도의 사용자의 정의에 의한 생성이 아니라, Pod의 생성시 함께 자동으로 생성되며,
Pod의 삭제시 함께 삭제되는, Pod와 모든 Lifecycle을 함께하는 기본 컨테이너입니다.
즉, 모든 Pod에는 1개의 PAUSE 컨테이너가 반드시 존재하며, K8s 세상에서 제일 많이 사용되는 컨테이너입니다.
바로 이 PAUSE 컨테이너가 Network namespace와 IPC namespace를 생성하고 유지/공유합니다.
PAUSE 컨테이너는 단순하게 무한 루프를 돌면서 SIGINT, SIGTERM을 받으면 종료되는 컨테이너지만,
네트워크 환경을 Pod 내 다른 컨테이너들에게 공유해주는 아주 중요한 컨테이너로,
Pod 내 특정 컨테이너가 비정상 종료되어, namespace에 문제가 발생하는 것을 방지하는 역할도 담당하고 있습니다.
PAUSE 컨테이너는 외부와 통신할 수 있는 네트워크 인터페이스를 가지고 있습니다.
처음 Pod가 생성되고 함께 PAUSE 컨테이너가 생성될때, PAUSE 컨테이너에 네트워크 인터페이스(eth0)가 생성됩니다.
Pod가 생성되는 Node(구 worker node)에도 네트워크 서비스를 위한 Network namspace를 가지고 있을 것입니다.
이 Node에도 새로운 가상의 인터페이스(veth0)가 하나 생성되며, PAUSE 컨테이너의 인터페이스와 직접 연결됩니다.
즉, Pod가 생성될때마다 Node에 가상 인터페이스가 생겨서 Pod의 PASUE 컨테이너와 1:1로 연결됩니다.
이후 PAUSE 컨테이너는 해당 인터페이스에 새로운 IP주소도 자동으로 할당받아 갖게 됩니다.
K8s는 PAUSE 컨테이너가 가진 네트워크 인터페이스를 Pod 내 모든 컨테이너가 사용할 수 있도록 구성합니다.
이제 Pod 내 위치한 모든 컨테이너는 동일한 IP를 사용하게 되며, 포트를 통해 컨테이너를 구분합니다.
이때 할당된 IP는 휘발성으로 Pod가 삭제되고, 생성될때마다 변경되며, Pod 외부와의 통신에 사용됩니다.
결론적으로, Pod 내 컨테이너가 사용하는 Network 정보는 바로 이 PAUSE 컨테이너를 통해 공유 받고 있으며,
자동으로 배포되어 인프라같은 역할을 해주기는 때문에, PAUSE 컨테이너를 인프라 컨테이너로 설명하기도 합니다.
예를 들어, 하나의 Pod(eddiepod) 내에 nginx 컨테이너와 netshoot 컨테이너가 있다고 가정해봅시다.
Pod의 IP가 172,16.1.6이라고 하면, nginx 컨테이너의 IP를 확인해도 172.16.1.6,
netshoot 컨테이너의 IP를 확인해도 172.16.1.6입니다.
즉 PAUSE 컨테이너의 IP가 172.16.1.6이며, 이 네트워크를 Pod 내 모든 컨테이너가 공유하고 있습니다.
다만, kubectl get pods를 통한 모니터링 정보에서는 컨테이너가 전체 3개가 아닌 2개로 보여집니다.
인프라 역할로 만들어졌지만 사용자가 지정 배포한 컨테이너는 아니며,
실제 작업은 이루어지지 않기 때문에 PAUSE 컨테이너는 Node에 직접 접속해야만 확인할 수 있습니다.
해당 Pod가 배포되어 있는 Node에 직접 접속해서 구동중인 컨테이너를 살펴본다면,
K8s 운영을 위한 다른 Pod들도 함께 구동중인 각각의 Pod별로 가진 다수의 PAUSE 컨테이너를 만날 수 있으며,
새롭게 배포한 Pod(eddiepod)와 같은 Uptime을 가진 PAUSE 컨테이너를 확인할 수 있습니다.
이 PAUSE 컨테이너는 Pod를 삭제한다면 nginx 컨테이너 그리고 netshoot 컨테이너와 함께 삭제됩니다.
Node에서 개별 컨테이너가 사용중인 프로세스 리스트로 보면 서로간의 격리와 공유 상태를 확인할 수 있습니다.
기본적으로 PAUSE로부터 공유 받은 Network namespace와 IPC namespace의 PID(47197)는 서로 같고,
컨테이너별로 소유한 MNT, UTS, PID namespace는 고유의 PID를 가지고 격리되어 있음을 확인할 수 있습니다.
이번엔 동일한 Pod내에 있는 컨테이너끼리 통신을 가정해봅시다.
nginx 컨테이너가 TCP 80을 통해 HTTP를 서비스한다고 할때, netshoot 컨테이너에서 127.0.0.1:80으로 접근을하면,
아무 제약 없이 nginx 컨테이너의 HTTP 서비스에 접근할 수 있으며, 이는 IP 대신 localhost로 접근해도 동일합니다.
또한, netshoot 컨테이너에서도 nginx 컨테이너에서 열어둔 포트가 동일하게 열려 있음을 확인할 수 있습니다.
netshoot은 HTTP 서비스를 제공하지 않지만, 동일한 namespace를 공유하기 때문에 생기는 일입니다.
만약, nginx 컨테이너 A가 TCP 80포트를 통해 서비스 중인데 netshoot 컨테이너가 TCP 80포트로 서비스를 시도하면,
이미 Pod 내에서 TCP 80포트는 사용중이기 때문에 동작하자마자 포트 충돌로 서비스가 내려갑니다.
이 역시 Pod 내 nginx 컨테이너와 netshoot 컨테이너가 동일한 Network namespace를 공유하기 때문입니다.
※ 만약 다른 Node에 위치한 Pod/컨테이너와 통신이 필요할 경우,
다른 Pod의 PAUSE 컨테이너의 IP를 목적지로 통신이 가능하며,
Pod 서로간의 통신 경로는 K8s의 CNI(Container Network Interface) 플러그인을 통해 제공됩니다.
-----------------------------------------------------------------------------------------------
이 내용은 NDKS(Networking : Docker & K8s Study)의 중간 과제로써 작성되었습니다.
NDKS는 '가시다'님이 속한 CloudNet@에서 진행하는 네트워크 엔지니어들을 위한 K8s 네트워킹 스터디입니다.
매주말마다 소중한 정보를 퍼주시는 '가시다'님께 항상 고맙습니다.
https://www.notion.so/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863
'에디.Container' 카테고리의 다른 글
AEWS 2주차. EKS Networking - 실습 (0) | 2023.05.04 |
---|---|
AEWS 2주차. EKS Networking (0) | 2023.05.03 |
AEWS 1주차. Amazon EKS 설치 및 기본 사용 - 실습 (0) | 2023.04.29 |
AEWS 1주차. Amazon EKS 설치 및 기본 사용 (0) | 2023.04.27 |
Calico의 Overlay 네트워킹 (0) | 2021.12.26 |