가상화란 물리적인 리소스 위의 가상의 서버 소프트웨어를 의미한다.여기서 발전하여 OS 가상화란, 각 어플리케이션이 CPU와 메모리를 '소유하여 사용하는 것처럼' 사용하는 것이다.
과거 x86 서버 아키텍처에서는 단일 하드웨어에 단일 OS와 단일 어플리케이션이 동작하였다. 그런데 하드웨어 성능이 획기적으로 발전하면서 Multi-App 환경이 가능하지게 되었다. 하지만 여러 어플리케이션이 단일 OS와 하드웨어를 공유하다보니 특정 어플리케이션의 장애가 전체 어플리케이션의 장애로 전파되는 문제가 발생하였고, 어플리케이션 및 OS의 격리가 필요해지게 되었다. 여기서 가상화 환경이 등장하게 되었으며 파티셔닝을 기반으로 어플리케이션 별로 별도의 OS 환경을 구축하게 되었다. 이는 하드웨어 독립적인 표준 서버 인프라 구축을 가능하게 해주었다.
서버 가상화의 장점은 다음과 같다.
자원 활용률 증가 위 그림처럼 3대의 서버에서 각각 다른 작업들이 수행되고 있다고 가정해보자. 각 서버는 현재 30% 밖에 활용되고 있지 못하다. 그런데 만약 서버 가상화를 통해 한 서버에서 두가지 작업이 돌아갈 수 있게 된다면, 아래와 같이 활용이 가능하다. 서버의 자원 활용률이 올라가면서 서버 2대 만으로 모든 작업을 수행할 수 있게 되었다. 이는 비용적인 측면에서 큰 이득이라고 볼 수있다. (물론 한 대의 서버에서 하나의 작업만 돌아가는게 더 좋은 경우도 있다. 한 서버 위에 여러 어플리케이션이 돌아가다보면 그만큼 서버 장애가 여러 어플리케이션에 영향을 줄 수 있기 때문이다. 그러므로 장애가 발생하면 안되는 중요한 어플리케이션의 경우 하나의 서버에 해당 어플리케이션 하나만 돌리는 것도 필요할 수 있다)
장애 고립 서버 가상화를 구축하게 되면 각 사용자가 자신의 VM에만 접속할 수 있도록 설정함으로써 타 사용자(어플리케이션)의 데이터에는 접근하지 못하도록 차단할 수 있다.
모니터링 용이 각 어플리케이션이 OS레벨을 포함하여 독립적으로 돌아가므로 어플리케이션이 다운되더라도 백업해놓은 어플리케이션을 다시 이전하기가 쉽다.
백업 및 마이그레이션 용이 하나의 물리적인 서버 위에 여러 어플리케이션을 동작시키는 것이므로 어플리케이션과 서버 자원을 모니터링하기 좋다.
보안 향상 서버 가상화를 구축할 경우 각 어플리케이션은 하드웨어와 가상화 소프트웨어만 공유할 뿐 OS 레벨부터는 전부 독립적으로 사용하게 된다. 그러므로 OS 또는 어플리케이션 레벨의 장애는 VM에 고립되어 다른 어플리케이션에 영향을 주지 않게된다.
서버 가상화의 한계
서버 가상화는 Multi-App 환경에서 꼭 필요하지만, 다음과 같은 단점도 존재한다.
1. 성능 오버헤드
서버 가상화를 구축할 경우 Host OS위에 Guest OS를 올리는 과정에서 Hypervisor가 설치된다. Hypervisor는 Host OS에게 Guest OS의 요청을 전달하는 중간다리 역할을 하는데, 이 Hypervisor로 인해 오버헤드가 발생할 수 있다.
2. 자원 낭비
물론 하나의 서버 위에서 여러 어플리케이션을 돌릴 수 있다는 점에서는 자원 활용률이 높아졌다고 볼 수 있지만, Guest OS를 위한 추가적인 자원 할당이 필요하다는 점에서는 자원이 낭비되기도 한다. (그리고 Guest OS는 굉장히 많은 자원을 잡아먹는 하마다..)
3. 너무 큰 image 사이즈
VM image에는 기본적으로 어플리케이션 뿐만 아니라 라이브러리, 바이너리 파일, Guest OS 등도 포함되므로 그 크기가 매우 커질 수 밖에 없다. 이로 인해 마이그레이션 속도가 느려지기도 한다.
4. 부팅 속도 저하
어플리케이션 시작 전에 Guest OS를 동작시켜야 하고, 가상 서버 자원도 세팅해야하기 때문에 처음 부팅 속도가 느려진다.
Container란?
Container에 대해 설명하고자 앞서 서버 가상화에 대한 설명을 했고, 이제 드디어 Container이다. 우선 Container란, OS 레벨의 가상화라고 생각하면 된다. 서버 가상화와는 달리 OS(리눅스)를 어플리케이션들이 서로 공유하여 사용하되, 리눅스의 namespace와 cgroup을 이용하여 각 어플리케이션이 독립적으로 하드웨어 자원을 사용할 수 있도록 한다.
chroot의 경우 특정 프로세스의 root 디렉토리를 변경할 수는 있으나 그렇다고 해서 원래 OS의 root 디렉토리를 방문할 수 없는 것도 아니어서, 프로세스를 독립적으로 동작시킨다고 보기 어렵다. 하지만 namespace의 경우 서로 다른 namespace 안의 프로세스를 완전 격리시킨다는 특징이 있다. 그리고 cgroup을 이용하면 프로세스 별로 하드웨어 자원을 사용할 수 있는 양을 제한할 수 있다.
즉, container는 리눅스의 namespace와 cgroup을 활용하여 프로세스를 독립시키는 방식으로 하나의 리눅스 서버 위에 여러 어플리케이션이 독립적으로 돌아갈 수 있도록 한다. Guest OS와 Hypervisor가 필요치 않아 기본의 서버 가상화보다 빠르고 가볍다는 장점이 있다.
또한 Container는 Immutable Infrastructure 환경에서 개발할 수 있도록 해주는데, Image의 설정대로 Infrastructure 환경이 구성되기 때문에 testing 환경과 production 환경이 동일하다는 장점도 존재한다(snowflake 서버 환경의 단점 해소).