티스토리 뷰

Azure Kubernetes Service 101 시리즈 (4/7)

처음 Kubernetes YAML을 보면 비슷해 보이는 객체가 많습니다. 그런데 대부분의 애플리케이션 배포는 Pod, Deployment, Service 세 가지를 정확히 이해하면 절반 이상 풀립니다. 이 셋은 겹치는 개념이 아니라, 서로 다른 문제를 맡는 레이어입니다.

이번 글에서는 “컨테이너 하나 띄우기”라는 요구가 왜 세 객체로 나뉘는지 설명합니다. AKS를 쓰더라도 이 개념은 그대로 Kubernetes 자체의 언어이기 때문에, 여기서 헷갈리면 뒤의 Ingress와 HPA도 같이 흐려집니다.


세 객체를 한 장으로 보면

Pod Deployment Server 관계


이 그림이 거의 전부입니다.

  • Pod는 컨테이너를 실행하는 최소 단위
  • Deployment는 원하는 Pod 복제본 수와 업데이트 전략을 선언하는 단위
  • Service는 바뀌는 Pod 집합 앞에 고정된 주소와 이름을 두는 단위

각자 맡는 문제가 다르기 때문에 셋이 동시에 필요합니다.


Pod — 스케줄링의 최소 단위

Pod는 Kubernetes가 노드에 배치하는 최소 단위입니다. 컨테이너 하나만 들어 있을 수도 있고, 여러 컨테이너가 함께 들어 있을 수도 있습니다.

중요한 점은 “컨테이너”가 아니라 Pod가 스케줄링 단위라는 사실입니다.

  • Pod는 같은 네트워크 네임스페이스를 공유합니다.
  • 같은 볼륨을 마운트할 수 있습니다.
  • 같이 뜨고 같이 사라집니다.

단일 FastAPI 앱 예제에서는 보통 Pod 안에 앱 컨테이너 하나만 둡니다. 그래도 Kubernetes는 여전히 그 앱을 컨테이너가 아니라 Pod로 취급합니다.

Pod를 단독으로 잘 안 쓰는 이유

Pod는 깨질 수 있고, 노드는 내려갈 수 있고, 수동으로 다시 만들어야 하면 귀찮습니다. 그래서 운영에서는 Pod를 직접 만들기보다, 그 Pod를 관리하는 상위 객체를 둡니다. 그 상위 객체가 보통 Deployment입니다.


Deployment — 원하는 상태를 선언하는 관리자

Deployment는 “이 앱 Pod를 몇 개 유지하고, 업데이트는 어떤 방식으로 할지”를 선언하는 객체입니다.

직접 Pod를 두 개 만들 수도 있지만, Deployment를 쓰면 다음이 달라집니다.

  • Pod가 죽어도 다시 맞춰 줍니다.
  • 복제본 수를 선언적으로 유지합니다.
  • 롤링 업데이트를 지원합니다.
  • 이전 버전으로 되돌릴 단서가 남습니다.

내부적으로는 Deployment가 ReplicaSet을 만들고, ReplicaSet이 Pod 개수를 맞춥니다. 실무에서는 ReplicaSet을 직접 자주 만지지는 않지만, 구조는 알아 두는 편이 좋습니다.


Service — 변하는 Pod 앞에 고정 주소를 둠

Pod는 영구적인 존재가 아닙니다. 교체되면 IP가 바뀔 수 있습니다. 앱 간 통신을 Pod IP에 직접 걸면 운영이 금방 망가집니다.

Service는 이 문제를 푸는 기본 장치입니다.

  • Pod 집합 앞에 고정된 가상 IP를 둡니다.
  • 클러스터 내부 DNS 이름을 제공합니다.
  • 라벨 셀렉터로 대상 Pod 집합을 고릅니다.

즉 Service는 “어떤 Pod들이 현재 살아 있는지”를 직접 알 필요 없이, 이 이름으로 보내면 된다는 인터페이스를 만듭니다.


가장 작은 예시

apiVersion: apps/v1
kind: Deployment
metadata:
  name: fastapi-hello
spec:
  replicas: 2
  selector:
    matchLabels:
      app: fastapi-hello
  template:
    metadata:
      labels:
        app: fastapi-hello
    spec:
      containers:
        - name: app
          image: <your-registry>/fastapi-hello:latest
          ports:
            - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: fastapi-hello
spec:
  selector:
    app: fastapi-hello
  ports:
    - port: 80
      targetPort: 8000
  type: ClusterIP

이 매니페스트에는 Pod 객체가 직접 보이지 않습니다. Deployment의 template이 바로 “이런 모양의 Pod를 만들라”는 뜻이기 때문입니다.


라벨이 왜 이렇게 중요한가

Deployment와 Service는 둘 다 라벨을 통해 연결됩니다.

  • Deployment는 어떤 Pod가 자기 소유인지 라벨로 구분합니다.
  • Service는 어떤 Pod로 트래픽을 보낼지 라벨로 고릅니다.

따라서 라벨 설계는 Kubernetes에서 작은 일이 아닙니다. app: fastapi-hello 한 줄이 단순 장식이 아니라 배포와 라우팅의 연결점입니다.

라벨이 꼬이면 흔히 두 종류 문제가 납니다.

  1. Deployment가 의도한 Pod를 제대로 관리하지 못함
  2. Service가 엉뚱한 Pod로 붙거나 아무 Pod도 못 찾음

Service 타입 세 가지

입문 단계에서는 세 가지를 먼저 익히면 충분합니다.

ClusterIP

기본값입니다.

  • 클러스터 내부에서만 접근 가능
  • 서비스 간 통신에 적합
  • 외부 공개는 별도 Ingress나 LoadBalancer 필요

가장 자주 쓰는 타입입니다. 대부분의 내부 API와 백엔드 서비스는 여기서 시작합니다.

NodePort

  • 각 노드의 특정 포트를 열어 서비스에 연결
  • 학습용이나 특정 제약 환경에서는 보이지만, 운영 주력으로 쓰는 경우는 많지 않음

NodePort는 구조를 이해하는 데는 좋지만, 외부 공개의 최종 형태로 쓰기엔 다소 거칠습니다.

LoadBalancer

  • 클라우드 로드 밸런서를 연결
  • AKS에서는 Azure Load Balancer 리소스와 이어짐
  • 빠르게 외부 진입점을 만들기 좋음

단일 서비스 하나를 바로 공개할 때는 편합니다. 다만 경로 기반 라우팅이나 여러 도메인을 한 진입점에서 처리하려면 5화의 Ingress로 넘어가게 됩니다.


ClusterIP, NodePort, LoadBalancer 비교

타입 접근 범위 주 용도 AKS에서의 느낌
ClusterIP 클러스터 내부 서비스 간 통신 기본값
NodePort 노드 IP + 포트 학습, 특수 접근 직접 운영 부담 있음
LoadBalancer 클러스터 외부 단일 외부 공개 Azure LB와 연결

이 표를 보면 Ingress가 왜 등장하는지도 읽힙니다. LoadBalancer만으로도 외부 공개는 되지만, HTTP 라우팅 제어가 부족합니다.


Pod 수를 늘리는 것과 Service는 별개다

초반에 자주 섞이는 개념입니다.

  • Deployment의 replicas를 늘리는 일은 Pod 수를 바꾸는 일
  • Service는 현재 살아 있는 Pod 집합으로 요청을 나누는 일

즉 Service는 Pod를 만들지 않습니다. Deployment가 Pod를 만들고, Service는 그중 라벨이 맞는 Pod들에게 붙습니다.

이 분리가 좋은 이유는 역할이 단순하기 때문입니다. 앱 수명주기와 네트워크 진입점을 한 객체에 몰아넣지 않습니다.


롤링 업데이트를 떠올리면 Deployment의 역할이 더 잘 보인다

새 버전 이미지를 배포한다고 해 보겠습니다. Deployment는 보통 기존 Pod를 한 번에 다 지우지 않고, 일부씩 새 버전으로 교체합니다.

롤링 업데이트


이 과정에서 Service는 Ready 상태가 된 새 Pod로 자연스럽게 붙습니다. 그래서 readiness probe가 중요합니다. “살아 있다”와 “트래픽 받아도 된다”를 구분하지 않으면, Service가 너무 일찍 새 Pod로 붙어 버릴 수 있습니다.


Pod 안에 컨테이너를 여러 개 넣는 경우

입문에서는 앱 컨테이너 하나만 쓰는 편이 낫습니다. 그래도 Pod가 왜 “컨테이너”가 아니라 “컨테이너 묶음” 단위인지 정도는 알아 둘 필요가 있습니다.

대표적인 패턴은 다음과 같습니다.

  • 로그 수집 사이드카
  • 프록시 사이드카
  • 앱과 매우 강하게 결합된 보조 프로세스

다만 아무 관련 없는 두 서비스를 한 Pod에 같이 넣는 것은 보통 좋지 않습니다. 같이 스케줄되고 같이 죽는다는 뜻이기 때문입니다.


AKS에서 이 셋을 볼 때의 실무 감각

AKS는 Kubernetes를 관리형으로 제공하지만, Pod·Deployment·Service의 의미는 바꾸지 않습니다. 따라서 장애를 볼 때도 순서를 이렇게 잡으면 좋습니다.

  1. Pod가 정상인가
  2. Deployment가 원하는 복제본 수를 유지하는가
  3. Service가 올바른 라벨의 Pod를 잡고 있는가

외부 요청이 실패해도 무조건 Ingress부터 보는 것은 아닙니다. 의외로 Service selector 오타, readiness probe 실패, 이미지 pull 문제 같은 더 아래층에서 막히는 경우가 많습니다.


다음 화를 위한 연결

오늘은 Service를 외부 공개 장치처럼 잠깐 썼지만, 실제 HTTP 라우팅은 곧 더 복잡해집니다.

  • 여러 서비스가 하나의 도메인을 공유하면?
  • /api는 API로, /는 웹 프런트로 보내야 하면?
  • TLS 종료를 어디서 할까?

이 질문이 바로 5화의 네트워킹과 Ingress입니다.


이 글은 Azure Kubernetes Service 101 시리즈의 4화입니다. 3화에서 FastAPI 앱을 클러스터에 올리면서 Pod·Deployment·Service를 처음 사용했다면, 이번 화는 그 세 객체가 각각 무슨 문제를 푸는지 분리해서 설명한 글입니다. 다음 5화에서는 이 Service 앞단에 Ingress와 AKS 네트워킹을 올려, 클러스터 안팎을 잇는 길을 정리합니다.


시리즈 목차


참고 자료

공식 문서

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함