Kubernetes and Cloud Native Associate (KCNA) #4 Container Orchestration (22%): 런타임, 보안, 네트워킹, 스토리지, Service Mesh

#3까지가 쿠버네티스 자체의 핵심 리소스와 API였다면, 이번 글은 그 쿠버네티스 아래에서 컨테이너를 실제로 떠받치는 계층입니다. Pod 안의 컨테이너가 어떤 런타임 위에서 도는지, 네트워크 패킷이 어떤 플러그인을 거치는지, 데이터가 어디에 저장되는지, 그리고 이 모든 것을 누가 호출할 권한이 있는지를 다룹니다.

이 계층을 관통하는 한 가지 사상은 표준 인터페이스입니다. 쿠버네티스는 런타임,네트워크,스토리지를 직접 구현하지 않고, CRI,CNI,CSI라는 표준 경계만 정의한 뒤 구현체를 플러그인으로 갈아 끼웁니다. KCNA Container Orchestration 도메인의 비중은 **22%**로 Fundamentals 다음으로 크며, 이 인터페이스 3종의 구분이 출제 단골입니다.

컨테이너 런타임 #

컨테이너 런타임은 이미지를 실제 프로세스로 띄우고 격리하는 소프트웨어입니다. 쿠버네티스에서 worker node의 kubelet이 Pod를 띄울 때 직접 컨테이너를 만들지 않고, 이 런타임에게 일을 맡깁니다. 런타임은 추상화 수준에 따라 두 층으로 나뉩니다.

고수준 런타임과 저수준 런타임 #

  • 고수준(high-level) 런타임. 이미지를 받아 와서 풀어 두고, 저장소를 관리하고, 컨테이너의 수명 주기를 다룹니다. containerdCRI-O가 대표적입니다. kubelet이 직접 대화하는 상대가 이 고수준 런타임입니다.
  • 저수준(low-level) 런타임. 실제로 리눅스 커널의 namespace와 cgroup을 설정해 프로세스를 격리하고 실행하는 가장 낮은 층입니다. runc가 사실상 표준이며, 고수준 런타임이 내부적으로 runc를 호출합니다.

정리하면 kubelet이 containerd를 부르고, containerd가 runc를 불러 컨테이너 프로세스를 띄우는 흐름입니다. containerd가 “관리자”, runc가 “실행기” 역할을 나눠 맡는다고 보면 됩니다.

OCI 표준 #

런타임과 이미지가 제각각이면 호환성이 깨집니다. 이를 막는 표준이 **OCI(Open Container Initiative)**입니다. OCI는 두 가지 명세로 구성됩니다.

  • image-spec. 컨테이너 이미지의 포맷(레이어 구조, 매니페스트 등)을 정의합니다.
  • runtime-spec. 풀어 둔 이미지를 어떻게 실행할지(파일시스템 번들, 수명 주기)를 정의합니다.

OCI 덕분에 어느 도구로 빌드한 이미지든 OCI를 따르는 어느 런타임에서나 동일하게 동작합니다. runc는 OCI runtime-spec의 참조 구현입니다.

CRI: kubelet과 런타임의 경계 #

**CRI(Container Runtime Interface)**는 kubelet과 컨테이너 런타임 사이의 표준 gRPC API입니다. kubelet은 CRI라는 약속된 인터페이스로만 런타임과 대화하므로, 그 뒤에 containerd가 있든 CRI-O가 있든 kubelet 코드는 바뀌지 않습니다. 런타임을 갈아 끼워도 쿠버네티스가 흔들리지 않는 이유가 이 경계입니다.

초기 쿠버네티스는 Docker를 쓰기 위해 dockershim이라는 변환 계층을 코어에 두고 있었으나, 표준 CRI 런타임이 자리 잡으면서 dockershim은 v1.24에서 제거되었습니다(dockershim deprecation). Docker로 빌드한 이미지는 OCI 표준을 따르므로 containerd 위에서 그대로 잘 동작합니다. 빌드 도구와 런타임은 별개라는 점이 핵심입니다.

표준 인터페이스 3종: CRI,CNI,CSI #

이 도메인에서 가장 많이 헷갈리는 지점이자 가장 자주 나오는 문항이 세 인터페이스의 구분입니다. 셋 다 “쿠버네티스가 직접 구현하지 않고 플러그인에 위임하는 표준 경계"라는 공통점이 있으나, 위임하는 대상이 다릅니다.

인터페이스풀네임무엇을 플러그인화하는가대표 구현체
CRIContainer Runtime Interface컨테이너 런타임(실행)containerd, CRI-O
CNIContainer Network InterfacePod 네트워킹(연결)Calico, Cilium, Flannel
CSIContainer Storage Interface영구 스토리지(저장)EBS,Ceph 등 드라이버

“R은 Runtime, N은 Network, S는 Storage"로 약자를 풀어 두면 보기에서 바로 갈립니다. 시험에서 “Pod에 영구 볼륨을 붙이는 표준 인터페이스는?” 같은 문항은 CSI를, “런타임을 교체하는 표준은?“은 CRI를 묻는 식입니다.

보안 #

RBAC #

**RBAC(Role-Based Access Control)**는 “누가 무엇을 할 수 있는가"를 정의하는 권한 모델입니다. 네 종류의 리소스가 짝을 이룹니다.

  • Role. 특정 Namespace 안에서 허용할 동작(verb)과 대상(resource)을 묶은 권한 묶음입니다.
  • ClusterRole. 클러스터 전체 범위의 권한 묶음입니다. Namespace에 묶이지 않습니다.
  • RoleBinding / ClusterRoleBinding. Role 또는 ClusterRole을 사용자,그룹,ServiceAccount에 연결합니다. 권한 묶음과 주체를 잇는 다리입니다.

여기서 ServiceAccount는 Pod 안에서 도는 프로세스가 쿠버네티스 API를 호출할 때 쓰는 신원입니다. 사람 사용자가 아니라 워크로드의 신원이라는 점이 구분 포인트입니다. RBAC는 화이트리스트 방식이라 명시적으로 부여하지 않은 권한은 기본적으로 거부됩니다.

NetworkPolicy #

기본 상태의 쿠버네티스는 모든 Pod가 서로 자유롭게 통신할 수 있습니다(default allow). NetworkPolicy는 이 평면에 방화벽 규칙을 얹어 ingress(들어오는 트래픽)와 egress(나가는 트래픽)를 제한합니다.

핵심 동작은 이렇습니다. 어떤 Pod에 NetworkPolicy가 하나라도 적용되는 순간, 그 Pod는 정책에 명시적으로 허용된 트래픽만 받게 되고 나머지는 차단됩니다. 즉 정책이 없으면 전부 허용, 정책이 붙으면 허용 목록 외 전부 차단으로 바뀝니다. 단, NetworkPolicy는 이를 실제로 강제하는 CNI 플러그인이 지원해야 효과가 있습니다(예: Calico, Cilium). 지원하지 않는 플러그인에서는 정책을 만들어도 동작하지 않습니다.

SecurityContext와 Pod Security #

SecurityContext는 컨테이너나 Pod가 어떤 권한으로 실행될지를 지정합니다. runAsNonRoot: true로 루트 실행을 막거나, readOnlyRootFilesystem, allowPrivilegeEscalation: false 같은 설정으로 권한을 좁힙니다. 컨테이너가 호스트를 위협하지 못하도록 실행 권한을 최소화하는 장치입니다.

클러스터 수준에서는 **Pod Security Admission(PSA)**이 게이트 역할을 합니다. Pod가 생성될 때 Pod Security Standards라는 세 단계 정책에 비추어 통과 여부를 판정합니다.

  • Privileged. 제한 없음. 신뢰된 시스템 워크로드용입니다.
  • Baseline. 알려진 권한 상승을 막는 최소 제한입니다.
  • Restricted. 모범 사례를 강하게 강제하는 가장 엄격한 단계입니다.

과거의 PodSecurityPolicy(PSP)가 제거되고 Pod Security Admission이 그 역할을 대신했다는 흐름 정도만 알아 두면 됩니다.

RBAC와 NetworkPolicy의 실무 적용은 실무 트랙 중급 #7에서 매니페스트와 함께 다룹니다.

네트워킹 #

쿠버네티스 네트워크 모델 #

쿠버네티스 네트워킹의 출발점은 단순한 규칙입니다. 모든 Pod는 NAT 없이 서로의 IP로 직접 통신한다는 것입니다. 즉 모든 Pod가 평평한 하나의 네트워크에 속한 것처럼 보이며, 각 Pod는 고유한 IP를 가집니다. 이 모델을 실제로 구현하는 책임이 CNI 플러그인에 있습니다.

CNI 플러그인 #

**CNI(Container Network Interface)**는 Pod가 생성될 때 네트워크 인터페이스를 붙이고 IP를 할당하는 표준입니다. 대표 구현체는 다음과 같습니다.

  • Flannel. 단순한 오버레이 네트워크. 설정이 쉽고 가볍습니다.
  • Calico. NetworkPolicy를 강하게 지원하고 BGP 라우팅을 제공합니다.
  • Cilium. eBPF 기반으로 고성능과 정교한 정책,관측을 제공합니다.

CNI 플러그인 선택과 동작 원리는 실무 트랙 고급 #1에서 더 깊이 다룹니다.

Service와 kube-proxy #

Pod의 IP는 Pod가 재생성될 때마다 바뀝니다. 이 불안정한 IP를 가리는 안정적인 접점이 Service입니다. Service는 고정된 가상 IP(ClusterIP)와 이름을 제공하고, 라벨 셀렉터로 묶은 Pod 집합으로 트래픽을 분배합니다. 이 분배 규칙을 각 노드에서 실제로 적용하는 컴포넌트가 kube-proxy입니다. Service 타입은 세 가지를 구분해 두어야 합니다.

타입노출 범위용도
ClusterIP클러스터 내부 전용(기본값)내부 서비스 간 통신
NodePort각 노드의 특정 포트로 외부 노출간단한 외부 접근,테스트
LoadBalancer클라우드 로드밸런서로 외부 노출운영 환경의 외부 진입점

세 타입은 포함 관계로 이해하면 쉽습니다. NodePort는 ClusterIP를 포함하고, LoadBalancer는 NodePort를 포함합니다.

CoreDNS와 서비스 디스커버리 #

Service에 이름으로 접근하려면 그 이름을 IP로 풀어 줄 DNS가 필요합니다. 그 역할을 CoreDNS가 맡습니다. 클러스터 안에서 도는 DNS 서버로, my-svc.my-namespace.svc.cluster.local 같은 이름을 Service의 ClusterIP로 변환합니다. Pod는 다른 서비스의 IP를 몰라도 이름만으로 찾아갈 수 있으며, 이 이름 기반 찾기를 서비스 디스커버리라 부릅니다.

Ingress #

Service의 LoadBalancer 타입은 서비스마다 로드밸런서를 하나씩 띄워야 해서 비용이 큽니다. Ingress는 하나의 진입점에서 HTTP/HTTPS 요청을 호스트,경로 규칙에 따라 여러 Service로 라우팅하는 L7 계층입니다. 단, Ingress 리소스만 만든다고 동작하지 않고, 이를 해석해 실제 트래픽을 처리하는 Ingress Controller(예: nginx, Traefik)가 클러스터에 떠 있어야 합니다.

스토리지 #

ephemeral vs persistent #

컨테이너의 파일시스템은 컨테이너가 사라지면 함께 사라집니다. 스토리지는 수명에 따라 둘로 나뉩니다.

  • 임시(ephemeral) 볼륨. Pod의 수명과 함께합니다. 대표 예가 emptyDir로, Pod가 삭제되면 데이터도 사라집니다. 캐시나 컨테이너 간 임시 공유에 씁니다.
  • 영구(persistent) 볼륨. Pod가 사라져도 데이터가 남습니다. 데이터베이스처럼 상태를 지켜야 하는 워크로드에 필요합니다.

Volume / PV / PVC / StorageClass #

영구 스토리지는 네 개념의 관계로 정리됩니다.

  • PersistentVolume(PV). 실제 저장 공간 자원입니다. 클러스터 관리자나 동적 프로비저닝이 공급합니다.
  • PersistentVolumeClaim(PVC). 사용자가 “이만큼의 저장 공간이 필요하다"고 요청하는 신청서입니다. Pod는 PVC를 통해 볼륨을 씁니다.
  • StorageClass. PV를 어떤 종류,성능으로 만들지 정의하는 템플릿입니다. 동적 프로비저닝의 기준이 됩니다.

사용자는 PVC를 제출하고, 그 요청이 적절한 PV에 바인딩되어 Pod에 마운트되는 흐름입니다. PV,PVC의 실무 사용은 실무 트랙 중급 #2에서 매니페스트와 함께 다룹니다.

CSI와 동적 프로비저닝 #

**CSI(Container Storage Interface)**는 외부 스토리지 시스템을 쿠버네티스에 연결하는 표준입니다. 클라우드 블록 스토리지나 분산 파일시스템 벤더가 CSI 드라이버를 제공하면, 쿠버네티스가 이를 통해 볼륨을 붙이고 뗍니다. CSI와 StorageClass가 맞물리면 동적 프로비저닝이 가능해집니다. 즉 PVC가 들어오면 관리자가 미리 PV를 만들어 두지 않아도, StorageClass 정의에 따라 PV가 자동으로 생성되어 바인딩됩니다.

PVC가 해제될 때 PV를 어떻게 처리할지는 reclaim policy가 정합니다. Delete는 실제 저장소까지 삭제하고, Retain은 데이터를 남겨 수동 처리를 기다립니다.

Service Mesh #

무엇이고 왜 쓰는가 #

마이크로서비스가 늘어나면 서비스 간 통신에서 재시도, 타임아웃, 암호화, 인증, 트래픽 분배, 호출 추적 같은 요구가 반복됩니다. 이를 애플리케이션 코드마다 구현하면 언어,팀마다 제각각이 됩니다. Service Mesh는 이 서비스 간 통신 관리를 앱 코드 밖의 인프라 계층으로 끌어내는 접근입니다.

sidecar 패턴 #

전통적인 Service Mesh는 sidecar 패턴을 씁니다. 각 Pod에 프록시 컨테이너(예: Envoy)를 함께 붙여, 그 Pod가 주고받는 모든 트래픽이 프록시를 거치게 합니다. 애플리케이션은 통신 제어를 의식하지 않고, 프록시들이 모인 데이터 플레인과 이를 통제하는 컨트롤 플레인이 메시 전체를 관리합니다. 대표 구현체로 IstioLinkerd가 있습니다.

무엇을 얻는가 #

Service Mesh가 코드 밖에서 제공하는 기능은 크게 셋입니다.

  • mTLS. 서비스 간 통신을 자동으로 상호 인증,암호화합니다.
  • 트래픽 관리. 카나리 배포, 가중치 라우팅, 재시도,타임아웃을 선언적으로 다룹니다.
  • 관측성. 서비스 간 호출의 지표와 트레이스를 자동으로 수집합니다.

KCNA는 Service Mesh를 개념 수준으로만 묻습니다. “서비스 간 통신을 앱 밖에서 sidecar 프록시로 관리하며 mTLS,트래픽 관리,관측을 제공하는 계층"이라는 한 문장과 Istio,Linkerd라는 이름 정도면 충분합니다.

시험 포인트 #

  • CRI,CNI,CSI 구분. Runtime,Network,Storage. 이 도메인 최다 출제 패턴입니다.
  • 고수준 vs 저수준 런타임. containerd,CRI-O(고수준)가 runc(저수준)를 호출합니다. dockershim은 제거되었고 Docker 이미지는 OCI 표준이라 그대로 동작합니다.
  • NetworkPolicy 기본 동작. 정책이 없으면 전부 허용, 정책이 붙으면 명시 허용 외 차단. 동작에는 지원 CNI가 필요합니다.
  • Service 타입. ClusterIP(내부) ⊂ NodePort(노드 포트) ⊂ LoadBalancer(클라우드). CoreDNS가 서비스 디스커버리를 담당합니다.
  • PV,PVC,StorageClass,CSI. 사용자는 PVC로 요청하고, CSI와 StorageClass가 동적 프로비저닝을 처리합니다.
  • RBAC 구성요소. Role/ClusterRole + RoleBinding/ClusterRoleBinding + ServiceAccount(워크로드 신원).

정리 #

이번 글에서 잡은 것:

  • 런타임. kubelet이 CRI로 고수준 런타임(containerd,CRI-O)을 부르고, 그것이 저수준 런타임(runc)을 호출. OCI(image-spec,runtime-spec)가 호환성을 보장
  • 인터페이스 3종. CRI(런타임),CNI(네트워크),CSI(스토리지)가 각각 다른 계층을 플러그인화
  • 보안. RBAC(권한),NetworkPolicy(트래픽 격리),SecurityContext와 Pod Security Standards(실행 권한 제한)
  • 네트워킹. NAT 없는 Pod 통신 모델, CNI 플러그인, Service 타입(ClusterIP,NodePort,LoadBalancer), CoreDNS와 Ingress
  • 스토리지. 임시(emptyDir) vs 영구(PV,PVC,StorageClass), CSI 동적 프로비저닝, reclaim policy
  • Service Mesh. 서비스 간 통신을 sidecar 프록시로 앱 밖에서 관리. mTLS,트래픽 관리,관측. Istio,Linkerd

다음: Cloud Native Architecture #

컨테이너를 떠받치는 계층까지 잡았습니다. 이제 쿠버네티스를 넘어 클라우드 네이티브 설계 사상으로 시야를 넓힙니다.

#5 Cloud Native Architecture (16%): 오토스케일링, 서버리스, 커뮤니티, 오픈 스탠다드에서는 오토스케일링(HPA,VPA,Cluster Autoscaler), 서버리스와 FaaS, CNCF 커뮤니티와 프로젝트 성숙도 단계, 오픈 스탠다드까지 정리하겠습니다.

X