
도커에서는 하나의 프로그램을 실행하는 단위를 컨테이너(Container)라고 부릅니다. 쿠버네티스에서는 이와 유사하게 프로그램 실행 단위를 파드(Pod)라고 부르며, 파드는 쿠버네티스의 기본 실행 단위입니다.
즉, 파드(Pod)는 쿠버네티스에서 하나의 애플리케이션(프로그램)을 실행하는 가장 작은 단위입니다.

쿠버네티스에서 가장 작은 배포 단위
파드와 컨테이너의 관계
컨테이너(Container)란?

쿠버네티스는 도커와 마찬가지로 이미지를 기반으로 애플리케이션을 실행합니다.
즉, 파드(Pod)는 특정 도커 이미지에서 컨테이너를 생성하여 애플리케이션을 실행합니다.
nginx 이미지라면 Nginx 웹 서버를 실행하기 위한 설정이 담겨 있습니다.파드는 다음과 같은 과정을 통해 동작합니다:
1. 사용자가 실행하려는 애플리케이션에 대한 이미지를 지정합니다.
2. 쿠버네티스가 해당 이미지를 기반으로 컨테이너를 생성합니다.
3. 이 컨테이너가 파드에 포함되어 실행됩니다.
쿠버네티스에서 웹 서버(Nginx)를 실행하기 위해 파드(Pod)를 생성합니다. 파드를 생성하는 방법에는 크게 두 가지가 있습니다.
실제 현업에서는 YAML 파일을 주로 사용합니다. 이유는 YAML 파일을 활용하면 구성(스펙)을 명확하게 문서화하고, 버전 관리(Git)를 통해 쉽게 추적할 수 있기 때문입니다. 따라서, 이번에는 YAML 파일을 사용해 파드를 생성하는 방법을 알아보겠습니다.

nginx-pod.yamlapiVersion: v1 # Pod를 생성할 때 사용하는 API 버전 (Pod 생성 시에는 항상 v1 사용)
kind: Pod # 생성할 리소스 종류를 Pod로 명시
metadata:
name: nginx-pod # Pod의 이름 (리소스를 구분하는 고유 식별자)
spec:
containers:
- name: nginx-container # 컨테이너 이름 (Pod 내부에서 사용)
image: nginx # 생성할 컨테이너에 사용할 Docker 이미지
ports:
- containerPort: 80 # 실제 작동에는 영향을 미치지 않으며, 문서화 목적 (Dockerfile의 EXPOSE와 유사)
nginx-pod.yaml 설명:v1을 사용합니다.Pod를 명시합니다.name: 파드의 이름으로, 리소스를 구분하기 위한 고유 식별자입니다.nginx 이미지를 사용합니다.참고:
containerPort는 실제 작동에는 영향을 미치지 않고, 주로 문서화 목적으로 사용됩니다. Dockerfile에서의EXPOSE와 유사한 역할을 합니다.
❗️YAML 문법 작성 시 들여쓰기는 Tab 대신 반드시 띄어쓰기(Space)를 사용해야 합니다.
YAML 파일을 작성한 후, kubectl 명령어를 사용하여 파드를 생성합니다.
$ kubectl apply -f nginx-pod.yaml
-f: 명령어 뒤에 YAML 파일의 경로를 지정합니다.파드가 제대로 생성되었는지 확인하려면 다음 명령어를 실행합니다.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 10s
1/1이면 정상 실행)Running, Pending, Completed 등)생성된 파드의 더 자세한 정보를 보려면 다음 명령어를 사용합니다.
$ kubectl describe pod nginx-pod
파드는 잘 생성되었으나, 접속이 안 되는 결과를 확인할 수 있습니다.

파드 네트워크는 클러스터 내부에서만 통신 가능
보안 설계상 분리
컨테이너 내부에서만 접근 가능
외부 접근을 위한 추가 설정 필요

kubectl exec -it [파드명] -- bash
docker exec -it [컨테이너 ID] bashkubectl exec -it nginx-pod -- bash
nginx-pod라는 이름의 파드 내부에 접속합니다.curl 명령어를 사용해 Nginx로 요청을 보냅니다.curl localhost:80
localhost:80은 Nginx가 기본적으로 사용하는 포트입니다.
쿠버네티스에서는 파드(Pod) 내부에 있는 컨테이너들이 같은 네트워크를 함께 사용합니다.
즉, 파드 내부에서 localhost로 요청을 보내면, 같은 파드 안에 있는 Nginx와 바로 통신할 수 있습니다.
쉽게 말해, 파드 안의 컨테이너들은 하나의 컴퓨터를 같이 사용하는 것처럼 동작하기 때문에, 서로 요청을 주고받기가 매우 간단합니다.
그래서 파드 내부로 들어가서 localhost:80으로 요청을 보내면 Nginx가 응답할 수 있습니다.
파드 내부의 Nginx에 로컬 환경에서도 접근하려면 포트 포워딩(port forwarding)을 설정해야 합니다. 포트 포워딩은 로컬 컴퓨터의 포트와 파드 내부 포트를 연결해 주는 작업입니다.

kubectl port-forward pod/[파드명] [로컬 포트]:[파드 포트]
sudo kubectl port-forward pod/nginx-pod 80:80
http://localhost:80으로 Nginx에 접근할 수 있습니다.

Control + C를 눌러 실행 중인 프로세스를 종료합니다.kubectl delete pod [파드명]
kubectl delete pod nginx-pod
nginx-pod가 클러스터에서 삭제됩니다.
Spring Initializr에서 기본적인 스프링 부트 프로젝트를 생성한 후, 간단한 REST API를 구현합니다.
@RestController
public class AppController {
@GetMapping("/)
public String home() {
return "Hello, World"
}
}
/ 엔드포인트로 요청하면 "Hello, World"를 응답합니다.스프링 부트 애플리케이션을 컨테이너로 실행하기 위해 Dockerfile을 작성합니다.
FROM openjdk:17-jdk
COPY build/libs/*SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
FROM openjdk:17-jdk: OpenJDK 17 기반 이미지 사용COPY build/libs/*SNAPSHOT.jar app.jar: 빌드된 JAR 파일을 컨테이너 내부에 복사ENTRYPOINT: 컨테이너 실행 시 Spring Boot 애플리케이션을 실행Gradle을 사용하여 JAR 파일을 빌드합니다.
$ ./gradlew clean build
build/libs/ 디렉토리에 JAR 파일이 생성됩니다.Dockerfile을 기반으로 이미지를 생성합니다.
$ docker build -t spring-server .
spring-server라는 이름의 이미지를 생성합니다.$ docker image ls

쿠버네티스에서 파드를 생성하기 위한 매니페스트 파일을 작성합니다.
apiVersion: v1
kind: Pod
metadata:
name: spring-pod
spec:
- name: spring-container
image: spring-server
ports:
- containerPort: 8080
apiVersion: v1kind: Podmetadataname: spring-pod:specContainers:- name: spring-containerimage: spring-serverportscontainerPort: 8080containerPort는 컨테이너 내부에서 사용하는 포트를 명시하는 것(문서화 목적)으로, 외부에서 바로 접근할 수 있는 설정은 아닙니다.작성한 매니페스트 파일을 사용하여 파드를 생성합니다.
$ kubectl apply -f spring-pod.yaml

$ kubectl get pods
STATUS가 ImagePullBackOff인 경우, 이미지를 Pull 받아오는 과정에서 문제가 발생했음을 나타냅니다.
Spring Boot 프로젝트를 컨테이너 이미지로 빌드하고 이를 기반으로 파드를 생성했지만, ImagePullBackOff라는 에러가 발생했습니다.
이 문제는 쿠버네티스의 이미지 Pull 정책(Image Pull Policy) 때문에 발생한 것입니다.
이미지 풀 정책(Image Pull Policy)이란 쿠버네티스가 매니페스트 파일을 읽어 파드를 생성할 때, 이미지를 어떻게 가져올지 결정하는 정책입니다.
1. Always
2. IfNotPresent
3. Never
apiVersion: v1
kind: Pod
metadata:
name: spring-pod
spec:
containers:
- name: spring-container
image: spring-server
ports:
- containerPort: 8080
latest이거나 명시되지 않은 경우, 기본적으로 Always로 동작합니다.latest가 아닌 경우, 기본적으로 IfNotPresent로 동작합니다.로컬 이미지를 사용하려면 imagePullPolicy: IfNotPresent를 설정해야 합니다.
apiVersion: v1
kind: Pod
metadata:
name: spring-pod
spec:
containers:
- name: spring-container
image: spring-server
ports:
- containerPort: 8080
imagePullPolicy: IfNotPresent
$ kubectl delete pod spring-pod
$ kubectl apply -f spring-pod.yaml
$ kubectl get pods

파드 내부에 접속합니다.
$ kubectl exec -it spring-pod -- bash
요청을 확인합니다.
$ curl localhost:8080


로컬 포트와 파드 포트를 연결합니다.
$ kubectl port-forward pod/spring-pod

브라우저에서 확인합니다.
http://localhost:1234로 접속하여 Spring Boot 서버의 응답을 확인합니다.

작업이 끝난 후 파드를 삭제하려면 아래 명령어를 입력합니다.
$ kubectl delete pod spring-pod
실제 서비스 운영 중 트래픽이 증가하면 서버의 부하가 커질 수 있습니다. 이를 해결하기 위해 서버를 수평적 확장(서버의 개수를 늘리는 방식)하는 방법을 사용합니다. 이번에는 백엔드(Spring Boot) 서버를 3대로 늘려보는 과정을 실습해 보겠습니다.
실습 #2. 백엔드(Spring Boot) 서버를 파드(Pod)로 띄워보기에서 사용한 프로젝트를 다음과 같이 수정합니다.
기존 프로젝트의 매니페스트 파일(spring-pod.yaml)을 수정하여 Spring Boot 서버를 3개로 확장합니다.
spring-pod.yaml 파일에 3개의 Pod를 정의합니다. 각 Pod는 같은 이미지를 사용하지만 고유한 이름으로 구분됩니다.
apiVersion: v1
kind: Pod
metadata:
name: spring-pod-1
spec:
containers:
- name: spring-container
image: spring-server
ports:
- containerPort: 8080
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
name: spring-pod-2
spec:
containers:
- name: spring-container
image: spring-server
ports:
- containerPort: 8080
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
name: spring-pod-3
spec:
containers:
- name: spring-container
image: spring-server
ports:
- containerPort: 8080
imagePullPolicy: IfNotPresent
spring-pod-1, spring-pod-2, spring-pod-3으로 구분됩니다.spring-server 이미지를 사용합니다.IfNotPresent로 설정하여, 로컬에 이미지가 없으면 외부에서 이미지를 가져옵니다.수정한 매니페스트 파일을 기반으로 Pod를 생성합니다.
$ kubectl apply -f spring-pod.yaml
$ kubectl get pods
