블로그

일프로

[쿠어클#15] 가상화 한방 정리

 [쿠버네티스 어나더 클래스] Sprint3의 첫 번째 강의 주제는 가상화 한방정리 입니다. 그동안 컨테이너 한방정리와 데브옵스 한방정리가 있었고, 이번이 3번째네요. 😀 먼저, 해당 강의 내용에 대한 소개를 드리면, 가상화가 나온지는 오래되긴 했는데, 컨테이너나 데브옵스 처럼, IT를 하는 사람들이라면 누구나 알아야되는 분야가 아니긴 해요. 게다가 로우레벨의 기술이라 재미도 없고, 또 어렵고요. 이걸 안다고 해도 이 분야에서 전문적으로 일을 하는 사람이 아니고서야 크게 메리트가 없습니다. 그냥 VirtualBox나 다른 가상화 도구들을 잘 쓰기만 해도 충분한데, 그만큼 가상화가 많이 발전하고 추상화 되버린 거죠.그래서 이 세션에서는 가상화 한방정리이지만 가상화 기술만을 중점적으로 다루지는 않습니다. 가상화보다 더 큰 개념들을 보면서 가상화에 대한 포지션을 알려드리고, 이후 본격적으로 가상화에 대한 설명을 드릴텐데, 쿠버네티스와 관련된 가상화에 대한 얘기를 할 거에요. 그리고 이번 블로그에서는 누구나 알고 있는 가상화 기술 비교와 쿠버네티에서 가장 어려운 리소스에 대한 얘기를 해보겠습니다.누구나 알고 있는 가상화 기술 비교VM 가상화 부터 설명드리면, 이렇게 호스트 가상화와 하이버파이저 가상화가 있고. 호스트 가상화가 물리 서버에 Host OS로 운영체제가 있고, 그 위에 여러 종류에 하이퍼바이저가 있어서VM을 만드는 방식입니다. 그리고 사용자가 원하는 Guest OS를 설치하게 되는데, 이 호스트 가상화는 자신이 주로 쓰는 운영체제가 있고, 그 외에 보조 적인 운영체제가 일시적으로 필요할 때 많이 쓰는 방식이고요.하이퍼바이저 가상화는 물리 서버위에 바로 하이퍼바이저가 있어서 Host OS 없이 VM이 만들어 지는 구조 에요. 마찬가지로 사용자가 원하는 Guest OS를 설치하지만, Host OS가 없기 때문에 이 호스트 가상화보다 성능이 더 좋다고 볼 수가 있습니다. 하지만 VM을 생성하고 관리하는데 어려울 수는 있는데, 이 Guest OS가 특정 App이나 사용자에 대한 메인 운영체제로 쓰이는 통상 데이터 센터에서 주로 사용을 해요.데이터 센터에는 보안상 외부와 차단된 네트워크 망이 구성되고, 내부 서버들 끼리만 통신이 되는데, 그렇다고 개발 업무도 이 데이터 센터에서 할 수는 없고요. 외부에서 접근을 하려면 VDI라고 해서 외부 사용자에 대한 인증을 거쳐서, 이 사용자 세션에 대해서만 VM에 접속해서 작업을 할 수 있게 해줍니다. 그리고 단순 원격 접속이기 때문에 이 VM으로 부터 내 PC로 데이터를 가져오지도 못하고요.그래서 이렇게 데이터센터가 있는 기업들은 자사의 데이터를 보호하기 위한 솔루션을 적용하는데, 그런 솔루션이 알아서 하이퍼바이저 가상화로 VM들도 관리를 해주기 때문에 어려울 부분은 없습니다.그래서 VM 가상화에는 대표적으로 이 두 가지가 있지만, 현재 대중적으로 크게 관심을 끌 만한 기술이 아니고요. 요즘은 쿠버네티스가 대두 되면서 VM과 컨테이너 가상화에 대한 비교를 많이 하죠.구성을 보면,  호스트 가상화랑 마찬가지로 Host OS 위에 하이퍼바이저와 같은 역할을 하는 컨테이너 런타임이 있고요.그래서 컨테이너를 만들어 주는 구조까지는 똑같은데, 그 내용을 보면 이 VM에는 GuestOS도 있고, 패키지들(Bins/Libs)도 App 뿐만아니라 OS에 관련된 모든 패키지들이 있는 데 반해, 컨테이너에는 GuestOS도 없고 이 App에 필요한 패키지들이 포함이 되는 구조예요. 그래서 결국 VM은 사이즈도 크고 GuestOS를 위한 추가 리소스가 더 필요합니다. 컨테이너의 경우 이 컨테이너가 HostOS의 커널을 공유하기 때문에 이렇게 App이랑 최소한의 추가 패키지들만 가지고 동작 시킬 수 있는 거고요. 이에 따른 장점은 명확합니다. 사이즈가 작아지기 때문에 다운받기도 빨라지는 등 이동적인 면에서 편리하고요. VM에는 GuestOS 기동시간이 있는데 비해서, 컨테이너는 App만 기동하면 되기 때문에 상대적으로 시작과 종료가 빨라집니다.  그래서 결국 자연스럽게 자원 사용에 대한 효율도 높아지게 되는 거죠.그리고 이런 컨테이너를 만들어주는 컨테이너 런타임에 대해서 말씀드리면, 이전 컨테이너 한방정리때 설명드렸던 내용인데, 컨테이너 런타임에는 High 레벨로는 도커나 컨테어너디 그리고 cir-o가 있고, 모두 Low Level인 runC를 사용하는 구조예요. 그리고 이 runC가 OCI라고해서 표준 규격의 컨테이너를 만들어 주기 때문에, 다른 런타임에서도 이런 표준 규격으로 컨테이너를 만든다면 서로 컨테이너를 공유해서 사용할 수가 있어요. 그 방법으로 리눅스 커널에는 이런 기술들이 있고요. 간략하게 이 기술들에 대해서 설명드리면, chroot는 각 프로세스 별로 루트 디렉토리를 할당해 줘서 서로 파일을 분리시키는 거고요. namespace는 HostOS의 시스템들을 프로세스 별로 각각 분리해서 만들어 주는데, 시스템 종류에는 마운팅이라던지 프로세스 id나 유저 등 여러가지가 있습니다. 이런걸 프로세스 별로 각각 할당해 주는거예요.마지막으로 cgroup은 프로세스 별로 HostOS에 리소스를 분리해서 할당해주는 기술이고요. 이 리소스에는 우리가 흔히 아는 메모리나 cpu, 네트워크 들이 있는거죠.그래서 한 프로세스에는 이렇게 디렉토리나 시스템, 그리고 리소스가 할당이 되서 독립적으로 관리가 되는데 이걸 우리는 컨테이너라고 부르는 겁니다.다음으로 쿠버네티스에서 가장 어려운 리소스에 대해서 말씀을 드려 볼게요. 쿠버네티스에서 가장 어려운 리소스바로 아래 세 가지 리소스 입니다.다른 리소스들도 많지만, 이 세 가지 리소스만 제대로 알면, 다른 리소스들은 결국 이 리소스스들 위한 보조 기능이라고 말할 수 있고요. 만약 처음 쿠버네티스 리소스를 만든다면 이 세가지를 확실히 한 다음에 다음 리소스들에 대한 세팅을 마춰 나가시면 됩니다.그만큼 중요한 리소스고요. 앞으로 Sprint3 전체 강의에서 이 리소스들을 상세하게 배워나갈 꺼지만, 여기서는 이 세 가지가 정말 중요할 수 밖에 없는 이유와 또 복잡할 수 밖에 없는 이유 대해서 말씀을 드릴께요.물리 서버들이 있고, 이 서버들은 게이트웨이에 연결이 되서 사내 네트워크 망이 만들어져요. 그리고 이 게이트웨이에 라우터를 붙이면, 기업 외부 인터넷으로 나가거나 외부 사용자들이 내 서비스에 들어 올 수 있게 되요. 그리고 그 서비스에 대한 데이터를 안전하게 보관하기 위해서 이 서버에 스토리지도 붙여 놔야 됩니다.그래서 이렇게 이전부터 이 서버와 네트워크 그리고 스토리지는 App을 서비스 하기 위한 기본 구성이었던 거죠. 이 부분을 편하게 갈려면 클라우드 서비스를 쓰는 거고요.이 물리적인 구성들이 쿠버네티스에서는  Pod와 Service 그리고 PV로 대신 사용하는 거기 때문에 이 세가지 리소스가 가장 중요하다고 말씀을 드리는 거예요.그리고 이제 이 세가지가 또 복잡할 수 밖에 없는 이유에 대해서 말씀을 드리면,물리 서버의 경우, 서버실에 서버가 많아 질 수록 서버실 공간도 커져야 되고, 그럼 전기세도 많이 들어요. 그래서 고 사양의 서버 한 대를 설치하고 위와 같이 가상화를 시켜서 쓰는 게 비용적으로 더 효율적입니다. 그렇기 때문에 쿠버네티스도 결국 이 가상화된 VM위에 올라가지게 되요. 그리고 이제 내부로 들어가서 Pod를 보면, 먼저 CRI라고 해서 컨테이너 런타임 인터페이스로 이런 제품들을 설치할 수가 있고요. 그럼 이 런타임들이 컨테이너를 만들어 주고, 이 컨테이너가 바로 하나의 App이 되는 셈인데, 쿠버네티스는 Pod라는 개념안에 이 컨테이너가 들어 있기 때문에 결국 App을 대표하는게 Pod가 되는거죠.그래서 이전에 VM위에 App을 띄었던 게 Pod라는 엄청 추상화된 리소스에 들어가게 되고요.App으로 사용자의 트래픽이 들어와야 되고요. App에서 만들어지는 데이터도 어딘가에 저장을 해야되야 되는데, 쿠버네티스에서는 그걸 하기 위한 리소스로 Service와 PV가 있는 겁니다.다음으로 Service를 보면, 쿠버네티스에서는 CNI라고해서 컨테이너 네트워크 인터페이스로 여러가지 제품들이 있어요. 저희는 여기서 칼리코를 설치했던 거고요. 이게 오버레이 네트워크라고해서 컨테이너들 간에 통신을 할 수 있게 해줘요.그리고 이 네트워크가 내 운영체제 위에 있는 IPTables랑 연결이 되서 실제 물리적인 서버로 가야 되는데, 그 사이 구간에 또 가상화된 네트워크가 있습니다. 저희는 쿠버네티스를 설치할 때 가상화 도구로 Virtualbox를 썼고요. 여기서 제공해주는 네트워크를 사용했었어요.그래서 이렇게 이 가상화 구간에 대한 네트워크 방식이 있고. 또 이 실제 물리 구성단에 네트워크 방식도 다양하기 때문에 네트워크는 알면 알 수록 어려운 분야지만 그래도 이 그림 정도는 알아야 Service에서 제공하는 타입들에 대해서 이해를 할 수 있게 됩니다.ClusterIP는 컨테이너 간의 네트워크고요. NodePort는 이 VM의 네트워크를 말해요. 그리고 LoadBlancer는 클라우드 서비스 상에서의 네트워크고요. 그리고 이 ExternalName는 DNS 서버와 관련이 있거든요.쿠버네티스를 설치하면 CoreDNS라는 서버도 같이 구성이 되는데, 이 CoreDNS가 서비스가 새로 만들어지면 이름이랑 IP 주소를 자동으로 등록해 놓기 때문에 우리는 특정 Pod에서 Service에 이름으로만 호출을 해도 CoreDNS로 부터 실제 IP를 받아서 원하는 Service로 트래픽을 전달 할 수 있게 됩니다.그리고 회사 내에도 쿠버네티스가 아닌 기존에 VM들을 도메인으로 호출하기 위한 사내 DNS서버가 있을 수 있거든요. 만약 컨테이너 안에서 도메인 명으로 VM에 있는 서비스를 호출하고 싶으면, 이렇게 CoreDNS서버에 이 사내 DNS서버를 업스트림 서버로 설정해 놓으면 됩니다. 결론적으로 Service는 이 네트워크 구성들을 알아야, 더 잘 쓸 수가 있다는 거죠.글고 이제 마지막으로 PV를 보면,PV를 잘 다루려면 이 스토리지에는 여러 종류의 스토리지들이 있다는 걸 알아야 되요. 쿠버네티스에서는 PV로 제공되는 옵션을 보면 ReadWriteMany는 파일 스토리지를 가리키고, ReadWriteOnce는 블록 스토리지를 주로 의미하거든요.그리고 쿠버네티스에서는 CSI라고 해서 Pod 에서 실제 스토리지로 까지 연결 해주기 위한 여러 솔루션들이 있고요. 그래서 이걸 내용들을 잘 알아야. 내가 저장하려는 데이터가 어떤 종류인지에 따라 그에 맞는 스토리지를 결정하고, 또 그걸 지원해주는 솔루션을 절 선택할 수가 있는 거죠. 그래서 여기까지 쿠버네티스에서 가장 어려운 리소스에 대해서 말씀을 드렸는데, 이제 좀 이 세가지 리소스가 Sprint1에서 배웠던 리소스 들중에서 무게감이 좀 다를 거 같다는 느낌이 드시나요?그럼 이번 블로그는  여기까지고요, 해당 강의에서는 아래 내용들에 대해서 더 다룹니다 😀[쿠버네티스 어나더 클래스] : https://inf.run/unreTIT에는 어떤 직군들이 있을까? 한번쯤 알고 넘어가면 좋을 서비스 모델 아무나 모르는 컨테이너 기술의 장점쿠버네티스에 대한 단점ps. 블로그 내용이 도움이 되셨다면 좋아요♡ 부탁 드립니다 :)

데브옵스 · 인프라쿠버네티스어나더클래스지상편Sprint3일프로데브옵스가상화한방정리

일프로

[쿠어클#17] Application 개발자가 꼭 알아야 하는 Pod 기능들

이번 섹션에서는 Application 개발자가 꼭 알아야 하는 Pod 기능들이라는 주제로 여러 얘기 들을 해볼 건데요. 왜 개발자가 꼭 알아야 되냐면, 이번에 배우는 Pod의 기능들은 개발 로직이 받쳐주지 못하면, 써먹을 수 없는 기능들 이라서 그래요. 그래서 내 App이 쿠버네티스 환경 배포된다고 했을 때, 개발자 입장에서는 그 로직들을 잘 구현해 줘야 하고, 데브옵스 엔지니어 입장에서는 개발자에게 이런 로직들이 꼭 필요하다고 잘 얘기할 수 있어야 됩니다. 그럼 블로그를 시작해 볼께요.Application 개발자가 꼭 알아야 하는 Pod 기능들아래 그림을 보면, 워커노드 위에 [Pod가 생성]되는 과정에서 특정 노드(nodeSelector)를 지정 할 수가 있었고요.  이 워커노드에 리소스(resource)는 내 Pod에서 지정된 리소스보다 많이 있어야 겠죠. 그럼 DockerHub에서 이미지(image)를 가져와서 컨테이너와 App이 만들어 집니다. 이제 다음으로 [Pod가 기동하고 운영]되는 과정이 있는데, 여기서부터 컨테이너 안에 Application 개발이랑 관련된 내용들이 시작 됩니다.이제 여기서 이전에 배웠던 내용을 얘기해 볼게요.Probe를 설정하면 kubelet이, App에 헬스 체크 API를 날려주기 때문에 App에는 이 API들에 마춰서 Health를 체크를 해주는 로직이 필요 했고요. Comfigmap을 통해서 환경 변수를 줄 수 있었고, Application에서는 파라미터를 받아서 처리를 해주는 설정이 있어야 됐어요.그리고 또 민감하게 다뤄야 하는 설정 파일의 경우, Secret을 통해 컨테이너로 마운팅 할 수 있었고, App에서 이 파일에 접근하는 로직을 통해서 데이터를 읽을 수가 있어요.그리고 파일을 저장하고, 영구적으로 보관해야 되는 경우,  PV를 통해서 워커노드에 넣을 수 있는데 이것도 개발 로직과 관련된 부분이라고 볼 수 있겠고요. 여기까지는 Sprint1에서 배웠던 내용 이였고. 워밍업 이였습니다. 😀이제부터가 이번 섹션에서 배울 내용들을 설명드릴 건데, 잘 들어 주시길 바랄께요.위 그림을 보시면, 수집 서버 입장에서 모든 Pod의 정보를 조회해 볼 목적으로 API를 날리는 상황이라고 해볼게요. 근데 Service에서는 pod로 트래픽을 랜덤하게 보내주기 때문에, 트래픽을 여러번 시도해야지 모든 Pod를 식별 할 수 있고. 이런 구조는 많은 네트워크 트래픽을 유발 시키기 때문에 좋지 않은 구조입니다.기존 VM 환경에서는 내가 배포할 App에 대해서 고정 IP가 정해져 있었고, 이 IP들을 모두 수집서버에 Config로 등록해서 딱 필요한 만큼의 조회 트래픽을 날렸었거든요. 근데 Pod는 IP가 자동 생성 되기도 하지만, Pod가 재생성 됐을 때 이 IP가 변경되기 때문에 쿠버네티스 환경에서 수집서버는 내가 정보를 조회 해야할 Pod들 한테 트래픽을 보내기가 힘들어 졌습니다.그럼 쿠버네티스 환경에서는 이런 상황을 어떤 구조로 바꿔서 해결해야 되냐면, Pod 스스로가 자신의 Pod 정보를 수집 서버에 전송해 주는  구성으로 만들어야 되요. 그리고 이러기 위해서  App에서 내 Pod 정보를 조회하는 로직이 필요한 거고요. 그 로직에는 이렇게 3가지 방식이 있는데, 이 방법들에 대한 차이와 사용법을 강의 수업에서 설명 드려요.이렇게 마이크로 서비스 아키텍쳐에서 전체 네트워크 트래픽을 줄이기 위해서 수집서버가 주기적으로 Pod 상태를 조회 하는게 아닌 각 Application들이 자신의 상태가 변경이 될 때마다 수집 서버로 API를 전송하는 방법을 쓰고요. 이외에도 Service를 통해서 특정 Pod에 호출이 된 다음에, 이후에는 이 두 Pod 끼리만 서로 양방향 통신을 해야 되는 경우 있습니다. 대표적으로 P2P 통신이고요. 우리가 메세지 관련된 어플리케이션을 만들 때, 그 통신 로직에 내 IP 주소를 넣어야 되요. 시스템 성능적인 면이나, 마찬가지로 전체 네트워크 트래픽을 줄이는 데 유리해요.  그래서 이렇게 개발 입장에서도 내 Pod의 IP 정보가 필요한 상황은 많다라는 말씀을 드리고 싶습니다. 이제 다음으로 Pod가 종료되는 상황에 대해서 얘기를 해볼께요.이건 정말 이전에 배웠던 probe 만큼이나 꼭 필요하고 중요한 내용이에요.통상 Applicaiton이 중단되는 경우는 장애가 발생하거나, 업그레이드, 혹은 시스템 점검이 있어서, 공지를 하고 내리기도 해요. 그리고 주로 새벽에 작업을 하기 때문에 이때 App을 종료시키다가 에러가 좀 나도 딱히 문제라고 생각하지 않습니다. 시스템을 내린 이후에 로그를 볼 생각 자체도 잘 안하고요. 그래서 지금까지 시스템 종료에 대해서 덜 중요하게 생각을 했을 수 있는데, 쿠버네티스 환경에서는 업그레이드나 스케일링들이 운영중도 빈번하게 일어나기 때문에 이런 상황에도 App 종료에 대한 로그를 계속 지켜볼게 아니라면, 이젠 App이 안전하게 종료되도록 만드는 부분이 매우 중요해 졌습니다.그리고 쿠버네티스 또한 App 종료에 대해서 지원해 주는 기능들이 있는데, 이 기능들에 대해서 간략하게 설명 드릴께요. Pod 삭제 명령을 받으면 kubelet은 App한테 종료 신호를 보내고요.  App이 스스로 종료될 때까지 기다려요. 근데 어느 정도 시간이 지나도 App이 종료되지 않으면 강제로 Pod를 삭제 시켜 버리고요. 그래서 App에서는종료신호를 받았을 때, 현재 실행중인 App들을 잘 정리하는 로직을 만들어 놔야 합니다. App이 어떤 정리를 해야 되는 지에 대한 부분은 강의에서 자세히 말씀을 드릴 거고요.그리고 또 App은 종료 신호와는 별개로 내부적으로 메모리 릭이 나거나 해서 장애가 발생하고, 종료 될 수도 있거든요.  이럴 때 쿠버네티스가 알아서 컨테이너를 리스타트 시켜주기 때문에 걱정할 필요는 없지만, 그래도 한번씩 이전 컨테이너가 왜 재시작 됐는지에 대한 사유는 조회를 해봐야 되요.그래서 kubectl로 이전 컨테이너의 상태를 확인하는 방법들을 알려드릴 거고요. 또 App이 종료될 때 특정 파일에 에러에 대한 사유를 저장해 놓으면, Pod에는 이걸 kubectl로 볼 수 있게 해주는 기능도 있습니다.그리고 마지막으로 이렇게 Pod의 생성과 운영, 그리고 종료에 따라  Pod와 컨테이너 상태에 대해서 얘기를 해볼께요.Pod의 상태는 Phase라는 속성에 있고요. 이렇게 각각의 진행에 따라 그 값들이 달라져요.그리고 Pod 종료시에 Succeded와 failed이 있는 걸 보면, 쿠버네티스는 종료에 대해서 성공적인 종료와, 실패적인 종료를 구분해 놨다는 게 느껴지시죠? 그리고 Pod에 상태가 있지만, 컨테이너에도 별도로 상태가 또 존재합니다.containerStatuses라는 속성이고요. 이건 좀 단순해 보일 수 있는데, 여기에 이렇게 세부적인 Reason이 또 있어요.여기 CrashLoopBackOff는 Pod가 재대로 기동이 안될 때 대시보드에서 자주 볼 수 있는데, 실제 Pod는 Pending이고, 컨테이너는 waiting상태에서 이 reason 속성을 화면에 보여줬던 거죠. 그리고 종료에 있어서는 두 가지 Completed와 Error가 있습니다. 일반적으로 컨테이너가 정상 종료되면 Completed고, Pod도 Succeeded로 끝나는데, 한 Pod에는 컨테이너는 두 개 이상 있을 수 있기 때문에, 이때는 컨테이너 하나라도 Error가 있으면 Pod는 Failed 상태가 끝나게 되요. 그래서 다시 Pod 종료에 대한 상태를 정리하면,SIGTERM을 받은 App이 정상적으로 자원을 정리하고 스스로 종료가 되면 컨테이너의 상태가 Completed고 Pod도 Succeeded로 끝나지만, 스스로 정리를 다 못하고, 강제 삭제가 됐을 때는 컨테이너 상태는 Error고 Pod의 상태는 Failed로 끝나는 거에요.그럼 이번 블로그는  여기까지고요, 해당 강의에서는 아래 내용들에 대해서 더 다룹니다 😀[쿠버네티스 어나더 클래스] : https://inf.run/3oKqK내 Pod 정보를 API로 노출시키기 내 Application을 안정적으로 종료하기ps. 한번도 좋아요♡를 안 준 사람은 있어도, 한번만 좋아요♡를 준 사람은 없다. 당신은 어떤 사람인가요? :)

데브옵스 · 인프라쿠버네티스어나더클래스지상편Sprint3일프로데브옵스ApplicationPod

채널톡 아이콘