23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
현재 제가 진행 중인 프로젝트의 IT 환경에서 컨테이너 기술은 매일 사용되는 필수적인 요소가 되었습니다.
특히 Kubernetes(K8s)와 같은 오케스트레이션 도구를 통해 클라우드 네이티브 애플리케이션의 배포와 관리를 정말 편리하고 신속하게 수행할 수 있게 되었죠.
과거에는 Kubernetes 설치를 위해 Docker 기반으로 복잡한 설정 과정을 거쳐야 했지만,
containerd와 같은 경량화된 컨테이너 런타임의 발전으로 설치 과정이 간소화되어 온프레미스 환경에서도 보다 효율적이고 안정적인 구축이 가능해졌습니다.
이번 글에서는 컨테이너 런타임의 개념과 발전, 그리고 이를 통해 클라우드 네이티브 Kubernetes 설치가 얼마나 간편해졌는지를 실무 사례와 함께 소개해 드리겠습니다.
컨테이너 런타임(Container Runtime)은 컨테이너의 생성, 실행, 관리를 담당하는 핵심 소프트웨어로, 클라우드 네이티브 환경에서 중추적인 역할을 수행합니다.
여기서 "런타임"은 단순한 실행 시간을 넘어 컨테이너의 전체 생명 주기 관리, 리소스 할당(CPU, 메모리, I/O 등), 격리 환경 유지, 호스트 운영 체제와의 상호작용을 아우르는 포괄적인 개념입니다.
이러한 포괄적인 기능을 통해 컨테이너는 안정적이고 효율적인 방식으로 애플리케이션을 구동할 수 있습니다.
컨테이너 런타임의 본격적인 발전은 2013년 Docker의 등장과 함께 시작되었습니다.
Docker는 컨테이너 기술을 대중화하고 개발자 친화적인 도구와 생태계를 구축했지만, 그 복잡한 아키텍처로 인해 경량화된 런타임이 필요했습니다.
관련해서 Docker는 2016년 containerd를 오픈소스로 분리하여 보다 가볍고 간결한 런타임을 제공했고, Kubernetes와의 긴밀한 통합을 통해 클라우드 네이티브 환경의 사실상 표준으로 자리 잡았습니다.
컨테이너 런타임은 클라우드 네이티브 애플리케이션의 효율적인 배포와 관리를 가능하게 합니다.
특히 OCI(Open Container Initiative)와 CRI(Container Runtime Interface) 표준은 런타임 간 호환성과 상호 운용성을 높여 컨테이너 생태계의 표준화와 유연성을 강화했습니다.
containerd와 같은 경량 런타임은 자원 활용의 효율성과 성능 최적화를 통해 대규모 분산 시스템에서 뛰어난 안정성과 확장성을 제공합니다.
OCI(Open Container Initiative): 2015년 Docker와 주요 업체들이 설립한 오픈소스 프로젝트로, 컨테이너 형식과 런타임에 대한 표준을 정의합니다.
OCI 이미지 스펙과 OCI 런타임 스펙을 통해 Docker, containerd, CRI-O 등 다양한 런타임에서 동일한 이미지를 실행할 수 있습니다.
CRI(Container Runtime Interface): Kubernetes가 컨테이너 런타임과 통신하기 위한 표준 인터페이스로, containerd와 CRI-O는 CRI를 구현하여 Kubernetes와 원활히 통합됩니다.
Docker는 CRI를 직접 지원하지 않아 중간 계층(Dockershim)이 필요했으나, Kubernetes 1.22 이후 지원이 중단되었습니다.
컨테이너 런타임의 발전은 클라우드 네이티브 환경에 여러 가지 의미있는 영향을 미쳤습니다.
컨테이너 런타임의 발전은 클라우드 네이티브 환경에서의 애플리케이션 배포, 관리, 보안 및 유연성을 크게 향상시켰습니다.
이러한 변화는 기업들이 더 빠르고 효율적으로 서비스를 제공할 수 있도록 지원하며, 클라우드 기반의 혁신을 가속화하고 있습니다.
컨테이너 런타임의 발전은 경량화된 아키텍처를 가능하게 하여 애플리케이션의 배포 및 실행 속도를 크게 향상시켰습니다.
예를 들어, containerd와 CRI-O는 Docker와 같은 무거운 런타임에 비해 빠른 시작 시간과 낮은 CPU 및 메모리 사용량을 제공합니다.
이러한 성능 향상은 클라우드 네이티브 애플리케이션이 요구하는 빠른 배포와 확장성을 지원합니다.
OCI와 CRI의 도입은 컨테이너 런타임의 표준화를 촉진했습니다. 이를 통해 다양한 런타임이 Kubernetes와 같은 오케스트레이션 플랫폼과 쉽게 통합될 수 있게 되었습니다.
CRI는 Kubernetes가 여러 런타임을 지원하도록 하여, 개발자들이 특정 런타임에 종속되지 않고 유연하게 선택할 수 있는 환경을 제공합니다.
경량 런타임은 보안 기능을 강화하여 컨테이너 간의 격리와 리소스 관리를 보다 효과적으로 수행합니다.
예를 들어, containerd는 최소한의 기능만 포함하여 공격 표면을 줄이고, Kubernetes에 최적화된 보안 정책을 지원하여 클라우드 네이티브 환경에서의 보안성을 높입니다.
다양한 런타임을 통해 개발자들은 특정 요구 사항에 맞는 최적의 솔루션을 선택할 수 있으며, 이는 마이크로서비스 아키텍처와 같은 현대적인 개발 패러다임에 적합합니다.
이러한 유연성은 기업들이 변화하는 비즈니스 요구에 신속하게 대응할 수 있도록 합니다.
Docker는 2013년 출시 이후 컨테이너 기술의 대중화를 이끌며 개발자와 기업 모두에게 널리 채택되었습니다.
그러나, 시간이 지나면서 Docker의 단일화된 아키텍처와 Kubernetes 중심의 클라우드 네이티브 생태계의 변화로 인해 한계가 드러났습니다.
이러한 변화는 산업이 개발 중심에서 운영 중심으로 이동하며 발생한 자연스러운 결과입니다.
containerd는 불필요한 오버헤드를 줄이고, Kubernetes와의 긴밀한 통합을 통해 대규모 워크로드 관리에 적합한 런타임으로 자리 잡았습니다.
아래는 containerd가 Docker를 대체하며 산업에서 더 채택된 주요 히스토리입니다.
2016년: containerd의 분리와 독립
Docker는 복잡한 기능을 단순화하고 런타임 핵심 로직을 분리하기 위해 containerd를 오픈소스로 공개했습니다.
초기에는 Docker의 일부로 사용되었으나, 곧 독립적인 프로젝트로 자리 잡았습니다.
2017년: CNCF 가입과 Kubernetes 통합
containerd는 CNCF(Cloud Native Computing Foundation)에 기부되어 커뮤니티 주도로 발전했습니다.
CRI 지원을 추가하며 Kubernetes와의 통합이 강화되었고, 대규모 클러스터 환경에서 경량화된 런타임의 필요성이 부각되었습니다.
2019년: Docker의 쇠퇴와 기업 전략 변화
Docker는 컨테이너 오케스트레이션 경쟁에서 Kubernetes에 밀리며 점차 개발자 중심 도구로 재포지셔닝되었습니다.
반면, containerd는 Kubernetes의 기본 런타임으로 자리 잡으며 엔터프라이즈 환경에서 채택이 증가했습니다.
2021년: Kubernetes 1.22와 Dockershim 지원 중단
Kubernetes는 Docker의 CRI 미지원 문제를 해결하기 위해 사용된 Dockershim을 제거하고, CRI를 직접 지원하는 containerd와 CRI-O를 권장했습니다.
이로 인해 많은 기업이 containerd로 전환을 가속화했습니다.
현재 (2025년 기준)
containerd는 경량화, 표준 준수, Kubernetes와의 원활한 통합 덕분에 클라우드 제공업체(AWS, Google Cloud, Azure)와 온프레미스 환경에서 널리 사용됩니다.
Docker는 여전히 로컬 개발 환경에서 유용하지만, 프로덕션 환경에서는 containerd가 지배적입니다.
Kubernetes(K8s) 클러스터를 설치할 때 컨테이너 런타임으로 containerd 또는 Docker를 사용할 수 있습니다. 두 런타임의 차이를 아래 표와 설명으로 비교합니다.
항목 | Docker 기반 설치 | containerd 기반 설치 |
|---|---|---|
컨테이너 런타임 | Docker Engine을 사용하여 컨테이너 관리 | containerd를 사용하여 컨테이너 관리 |
OCI 호환성 | OCI 이미지 및 런타임 스펙 지원, 자체 포맷(Docker 이미지)도 사용 | 완전한 OCI 표준 준수, OCI 이미지 및 런타임 스펙 지원 |
CRI 호환성 | CRI 미지원, Dockershim 통해 K8s 통합 (1.22 이후 지원 중단) | CRI 직접 지원, K8s와 원활한 통합 |
설치 및 설정 복잡성 | Docker CLI로 직관적이고 간단한 설정 가능 | 낮은 수준의 API 및 CLI(예: ctr, nerdctl) 사용, 약간의 추가 설정 필요 |
Kubernetes 호환성 | K8s 1.22 이상에서 Docker 지원 중단, containerd로 전환 권장 | K8s와 기본 호환, 최신 버전에서 안정적 지원 |
이미지 빌드 지원 | BuildKit으로 이미지 빌드 가능 | 이미지 빌드 기능 미포함, 외부 도구(예: BuildKit, Kaniko) 필요 |
멀티 컨테이너 관리 | Docker Compose 지원 | 별도 멀티 컨테이너 관리 도구 필요 |
오케스트레이션 지원 | Docker Swarm 지원, K8s와 별도 통합 필요 | K8s와 직접 통합, 별도 오케스트레이션 도구 불필요 |
리소스 효율성 | 추가 기능으로 자원 소모 큼 | 경량화된 런타임으로 자원 효율성 우수 |
로그 및 모니터링 | 기본적으로 로그 수집 및 모니터링 지원 | 로그 수집은 수동 설정 필요, 모니터링은 기본 제공 |
사용 사례 | 개발자 친화적, 로컬 개발 및 테스트에 적합 | 대규모 클러스터 환경에서 안정적이고 효율적인 컨테이너 관리에 적합 |
Docker: 개발자 친화적이며 로컬 개발에 유용하지만, CRI 미지원과 자원 소모로 인해 Kubernetes 프로덕션 환경에서 점차 외면받고 있습니다.
containerd: OCI와 CRI 표준을 준수하며, Kubernetes와의 통합에 최적화된 경량 런타임으로, 대규모 프로덕션 환경에서 선호됩니다.
containerd는 Kubernetes 환경에서 다음과 같은 이유로 선호됩니다:
경량화된 아키텍처: 불필요한 기능을 제거하여 낮은 자원 소모로 대규모 클러스터에서 효율적입니다.
OCI 및 CRI 표준 준수: 표준화된 환경에서 상호 운용성을 보장하며, Kubernetes와 원활히 통합됩니다.
Kubernetes와의 긴밀한 통합: CRI 지원으로 별도의 중간 계층 없이 최신 Kubernetes 버전에서 안정적으로 동작합니다.
모듈성과 확장성: 플러그인 기반 아키텍처로 커스터마이징과 유지보수가 용이합니다.
오픈소스 커뮤니티 지원: CNCF 관리 하에 활발한 업데이트와 신뢰성을 제공합니다.
보안성: 최소 기능만 포함하여 공격 표면을 줄이고, Kubernetes 보안 정책과 통합됩니다.
이제 온프레미스 환경에서 containerd를 사용해 Kubernetes 클러스터를 설치하는 과정을 설명합니다.
Kubernetes는 스왑 공간을 사용하지 않도록 설정해야 합니다. 스왑을 비활성화하고, 시스템 재부팅 시에도 스왑이 활성화되지 않도록 설정합니다.
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstabKubernetes 클러스터의 네트워크 통신을 위해 필요한 모듈을 로드하고, 시스템 매개변수를 설정합니다.
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --systemoverlay와 br_netfilter 모듈은 Kubernetes의 네트워크 기능을 지원합니다.
sysctl 설정은 iptables가 브리지된 트래픽을 처리할 수 있도록 합니다.
Kubernetes의 컨테이너 런타임으로 사용할 containerd를 설치하고 설정합니다.
sudo apt update
sudo apt install -y containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
sudo systemctl status containerdcontainerd는 컨테이너의 생명 주기를 관리하는 데 필요한 기능을 제공합니다.
Kubernetes를 설치하기 위해 필요한 패키지를 추가하고 설치합니다.
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet=1.29.14-1.1 kubeadm=1.29.14-1.1 kubectl=1.29.14-1.1
sudo apt-mark hold kubelet kubeadm kubectlkubeadm은 클러스터를 초기화하는 도구이며, kubectl은 클러스터와 상호작용하는 CLI 도구입니다.
마스터 노드에서 Kubernetes 클러스터를 초기화합니다.
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///run/containerd/containerd.sock --control-plane-endpoint=10.0.1.4 --upload-certs오버레이 네트워크: 10.244.0.0/16은 Kubernetes에서 사용되는 오버레이 네트워크를 위한 Pod 네트워크 CIDR 범위를 설정합니다.
외부 IP: 명령어에서 --control-plane-endpoint=10.0.1.4로 설정된 값이 외부 IP 또는 DNS 이름을 나타냅니다. 이 옵션은 클러스터의 외부에서 접근할 수 있는 고정된 엔드포인트(예: 로드밸런서의 공인 IP 또는 DNS 이름)를 지정합니다. 이를 통해 클러스터가 다중 노드 환경에서 안정적으로 동작할 수 있도록 합니다
Kubernetes 클러스터에 접근하기 위해 kubeconfig 파일을 설정합니다.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/configKubernetes 클러스터를 관리하기 위한 도구인 k9s를 설치합니다.
mkdir ~/k9s-install && cd ~/k9s-install
wget https://github.com/derailed/k9s/releases/download/v0.40.5/k9s_Linux_amd64.tar.gz
tar -zxvf k9s_Linux_amd64.tar.gz
sudo mv k9s /usr/local/bin
sudo chmod +x /usr/local/bin/k9sPod 간의 통신을 위해 네트워크 플러그인을 설치합니다. 여기서는 Calico를 예로 들겠습니다.
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml각 워커 노드에서 마스터 노드에 조인합니다.
sudo kubeadm join 10.0.1.4:6443 \
--token wvdmu5.l50k489eaonmdm9s \
--discovery-token-ca-cert-hash sha256:b05497c2498cc2221d70a6e4886ea6114610d4e8e8c72044eac5fa7d61537c94클러스터의 상태를 확인하여 모든 노드가 정상적으로 작동하는지 확인합니다.
kubectl get nodes마스터 노드를 워커로 사용하려면 taint를 제거합니다.
kubectl taint nodes <master-node-name> node-role.kubernetes.io/control-plane-설치 과정에서 문제가 발생한 경우, 클러스터를 재설정할 수 있습니다.
sudo kubeadm reset
sudo rm -rf /etc/kubernetes/*
sudo rm -rf /var/lib/etcd/*
sudo systemctl restart kubelet이 과정을 통해 온프레미스 환경에서 containerd를 사용하여 Kubernetes 클러스터를 성공적으로 설치하고 구성할 수 있습니다.
각 단계에서 주의 깊게 설정을 진행하면 안정적인 클러스터 환경을 구축할 수 있습니다! 🎉
containerd 기반 Kubernetes 설치는 OCI와 CRI 표준을 준수하는 경량 런타임을 통해 온프레미스 환경에서 효율적이고 안정적인 클러스터를 구축합니다.
컨테이너 런타임의 발전은 클라우드 네이티브 환경의 성능, 보안, 유연성을 크게 향상시켰으며, containerd는 이러한 변화의 중심에서 산업 표준으로 자리 잡았습니다.
위 과정을 통해 구축된 클러스터는 대규모 워크로드와 클라우드 네이티브 애플리케이션 배포에 최적화된 환경을 제공합니다.
OCI(Open Container Initiative)와 CRI(Container Runtime Interface)의 도입이 컨테이너 런타임 표준화를 촉진한 이유에 대한 추가 설명입니다. 🚀
OCI는 컨테이너 실행 환경의 기술적 기반을, CRI는 오케스트레이션 플랫폼과의 통합 계층을 표준화함으로써 계층적 협업을 가능하게 했습니다.
이로 인해 다양한 런타임이 Kubernetes 및 멀티 클라우드 환경에서 호환성을 유지하며 발전할 수 있는 생태계가 조성되었습니다. 🌱
OCI는 컨테이너 생태계의 기술적 기반을 표준화하는 핵심 컴포넌트를 정의합니다. 📦
주요 컴포넌트와 역할
OCI Image Specification
컨테이너 이미지의 구조(레이어, 매니페스트, 구성 파일)를 표준화합니다.
예를 들어, Docker 이미지와 OCI 호환 이미지는 동일한 구조로 빌드되며, containerd 및 CRI-O에서 모두 실행 가능합니다. ✅
OCI Runtime Specification
컨테이너 실행 환경을 정의하는 런타임 번들(Runtime Bundle)과 리소스 관리 구성을 표준화합니다.
예를 들어, runC는 OCI 런타임 스펙을 구현하여 containerd, CRI-O 등에서 공통으로 사용됩니다. 🔧
OCI Distribution Specification
이미지 레지스트리 간 호환성을 보장하는 배포 표준입니다. 🌐
표준화 효과
호환성 강화: OCI 스펙을 준수하는 모든 런타임(containerd, CRI-O, Podman)은 동일한 이미지를 실행할 수 있습니다. 🔄
벤더 종속성 해소: Docker의 독점 형식에서 벗어나 멀티 클라우드 환경에서의 이식성을 확보합니다. 🌈
CRI는 Kubernetes와 컨테이너 런타임 간의 상호작용 계층을 표준화합니다. 🛠️
주요 컴포넌트와 역할
RuntimeService
컨테이너 생명 주기 관리(생성/실행/정지)를 위한 gRPC API입니다.
예를 들어, kubelet은 CRI를 통해 containerd에 컨테이너 실행을 요청합니다. 📞
ImageService
이미지 풀(pull), 캐싱, 삭제 기능을 표준화합니다. 🗑️
CRI Shim
Docker와 같은 비-CRI 런타임을 Kubernetes에 통합하기 위한 중간 계층입니다(예: Dockershim). 🔗
표준화 효과
런타임 유연성: CRI를 구현한 런타임(containerd, CRI-O)은 Kubernetes와 자동으로 통합됩니다. 🔄
운영 효율성: Kubernetes 코어 코드 변경 없이 새로운 런타임을 추가할 수 있습니다. ⚙️
두 표준은 계층적 구조로 협업하며 생태계를 통합합니다. 🌍
컴포넌트 간 상호작용
Kubernetes → CRI: kubelet이 CRI API를 통해 런타임에 명령을 전달합니다. 📤
CRI → OCI: containerd/CRI-O가 OCI 스펙을 준수하는 runC를 호출하여 컨테이너를 실행합니다. 🔄
OCI → 커널: runC가 Linux 네임스페이스와 cgroups를 활용해 컨테이너를 격리합니다. 🔒
통합 표준화 효과
엔드투엔드 호환성: Kubernetes → CRI → OCI → 커널로 이어지는 계층적 표준화로 멀티 벤더 환경을 지원합니다. 🌈
성능 최적화: 경량 런타임(containerd)이 CRI/OCI를 통해 Kubernetes와 직접 통합되며 오버헤드를 감소시킵니다. ⚡
표준화 촉진 사례
containerd: OCI 런타임(runC)과 CRI를 동시에 구현하여 Kubernetes의 기본 런타임으로 자리잡았습니다. 🏆
CRI-O: Kubernetes 전용으로 설계된 CRI/OCI 호환 런타임으로, Red Hat OpenShift에서 채택되었습니다. 🌟
Docker의 진화: OCI 호환 이미지 형식을 채택하며 생태계 통합에 기여하고 있습니다. 🔄
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.