Pod - Container
- 애플리케이션과 그 의존성(라이브러리, 설정)을 패키징한 독립 실행 단위
- Pod 내부에서 1개 이상의 컨테이너 가능
- 각 컨테이너는 자체 파일 시스템, CPU, 메모리 리소스를 가진다.
- 컨테이너간 네트워크는 localhost로 공유가 가능하다.
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: app-container
image: myapp:1.0
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
- name: sidecar-container
image: sidecar:1.0
Pod - Label
- 쿠버네티스 객체에 붙이는 key-value 쌍의 메타데이터
- 리소스 조직화 및 분류 용도.
Selector로 객체 선택. Service, Deployment 등과 연결한다.
- 런타임에 동적 추가/수정 가능하며 검색, 필터링 기능도 제공한다.
apiVersion: v1
kind: Pod
metadata:
name: labeled-pod
labels:
app: frontend # 애플리케이션 이름
tier: web # 계층 구분
version: v1.0 # 버전
env: production # 환경
spec:
containers:
- name: nginx
image: nginx:latest
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
selector:
app: frontend # 해당 label 가진 Pod 선택
tier: web
ports:
- port: 80
targetPort: 8080
# Equality-based
selector:
app: frontend
tier: web
# Set-based
selector:
matchLabels:
app: frontend
matchExpressions:
- key: tier
operator: In # In, NotIn, Exists, DoesNotExist
values: [web, api]
Pod - Node Scheduling
- Pod를 어느 Node에 배치할지 결정하는 프로세스
# nodeSelector (기본)
spec:
nodeSelector:
disktype: ssd # 해당 label 있는 노드만 선택
# Node Affinity: Pod가 선호하는 Node 지정
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [node-1, node-2]
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: disktype
operator: In
values: [ssd]
# Pod Affinity: Pod 간 함께/분리 배치
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: [backend]
topologyKey: kubernetes.io/hostname # 같은 노드에 배치
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values: [cache]
topologyKey: kubernetes.io/hostname # 다른 노드에 배치
Service - ClusterIP
- 클러스터 내부에서만 접근 가능한 가상 IP
- 클러스터 내부 통신용. 외부에서 직접 접근이 불가능하며 Pod간 통신에 사용된다.
apiVersion: v1
kind: Service
metadata:
name: database-service
spec:
type: ClusterIP # 생략 가능 (기본값)
selector:
app: postgres # 해당 label Pod 선택
ports:
- port: 5432 # Service 포트
targetPort: 5432 # Pod 포트
Service - NodePort
- 각 Node의 특정 포트를 통해 외부에서 접근 가능
외부 요청 → Node IP:NodePort → Service ClusterIP → Pod:targetPort
- 30000 ~ 32767 범위의 포트를 사용한다.
- 모든 Node에서 해당 포트를 개방
- 어느 Node로 접근해도 Pod에 도달 가능하며 고정 IP나 DNS가 불필요하다.
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80 # Service 내부 포트
targetPort: 8080 # Pod 포트
nodePort: 30080 # 외부 접근 포트 (생략하면 자동할당)
Service - LoadBalancer
- 클라우드 제공자의 로드밸런서를 할당받아 외부 트래픽을 수신
외부 요청 → 클라우드 LB(고정 IP) → NodePort → Service → Pod
- 자동으로 고정 Public IP를 할당한다.
- DNS 이름을 제공하며 트래픽을 여러 Node에 분산한다.
apiVersion: v1
kind: Service
metadata:
name: web-lb
spec:
type: LoadBalancer
selector:
app: frontend
ports:
- port: 80 # 외부 접근 포트
targetPort: 8080 # Pod 포트
protocol: TCP
Volume - emptyDir
- Volume이란, Pod의 데이터를 영구 저장 또는 Pod 간 공유하기 위한 메커니즘이다.
emptyDir이란, Pod 생성 시 함께 생성되고, Pod 삭제 시 함께 삭제되는 임시 저장소이다.
- Pod가 재시작하면 데이터 소실이 되며 Pod 내의 여러 컨테이너가 공유할 수 있다.
- 자동 생성되므로 초기화가 불필요하다.
apiVersion: v1
kind: Pod
metadata:
name: emptydir-pod
spec:
containers:
- name: container-1
image: nginx:latest
volumeMounts:
- name: cache-volume # Volume 이름
mountPath: /cache # Container 내부 경로
- name: container-2
image: busybox:latest
volumeMounts:
- name: cache-volume
mountPath: /shared-data # 같은 volume 마운트
volumes:
- name: cache-volume
emptyDir: {} # 빈 디렉토리로 시작
Volume - hostPath
- Node의 파일 시스템을 Pod에 직접 마운트하는 용도로 사용한다.
- Node 디스크의 실제 경로에 접근. Pod가 삭제되더라도 Node에 데이터가 남는다.
- 같은 Node의 다른 Pod와 공유가 가능하다.
- 다른 Node에 배치된 Pod와는 공유가 불가능하다.
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: app
image: nginx:latest
volumeMounts:
- name: host-volume
mountPath: /data # Container 경로
volumes:
- name: host-volume
hostPath:
path: /var/log # Node의 실제 경로
type: Directory # 디렉토리여야 함
Volume - PV/PVC
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-storage
spec:
capacity:
storage: 10Gi # 크기
accessModes:
- ReadWriteOnce # 1개 Node만 쓰기 가능
persistentVolumeReclaimPolicy: Retain # 삭제 후 데이터 유지
nfs: # NFS 저장소
server: 192.168.1.100
path: "/exports/data"
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi # 5Gi 필요
storageClassName: standard # 저장소 종류
ConfigMap
- 애플리케이션 설정을 평문으로 저장하는 객체
- key-value 형식. 파일 또는 직접 입력이 가능하고 변경 후 Pod 재시작이 필요하다.
- 단, 평문으로 저장되기 때문에 누구나 볼 수 있다.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: "postgres.default.svc.cluster.local"
DATABASE_PORT: "5432"
APP_ENV: "production"
LOG_LEVEL: "info"
Secret
- 민감한 정보를 암호화해서 저장하는 객체
- base64 인코딩. ConfigMap처럼 마운트/환경변수 사용이 가능하다.
- 쿠버네티스 내부에서만 접근이 가능하다.
Opaque : 일반 비밀 용도
kubernetes.io/basic-auth : 기본 인증
kubernetes.io/ssh-auth : SSH키
kubernetes.io/dockercfg : Docker 레지스트리
kubernetes.io/tls : TLS/SSL 인증서
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # base64: admin
password: bXlwYXNzd29yZDEyMw== # base64: mypassword123
apiVersion: v1
kind: Pod
metadata:
name: db-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret # Secret 이름
key: username # Secret의 key
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
Namespace, ResourceQuota, LimitRange
- Namespace : 클러스터 내의 논리적 격리 공간
- 정의 : 물리적으로 하나인 Kubernetes 클러스터를 논리적으로 분할하여 독립적인 환경에서 작업할 수 있게 만드는 가상 공간이다.
- 이름 충돌 방지 : 서로 다른 Namespace라면 동일한 이름의 Pod나 Service를 생성할 수 있다.
- 접근제어(RBAC) : 특정 팀원에게 특정 Namespace에 대한 권한만 부여해 보안을 강화한다.
- LimitRange : Namespace 내부에서 생성되는 Pod나 Container가 사용할 수 있는 자원의 최소/최대치와 기본값을 설정하는 정책이다.
- 자원 요청 규제 : 사용자가 Pod를 생성할 때
resources.requests나 limits를 정의하지 않아도 클러스터 관리자가 정한 기본값을 자동으로 할당한다.
- 과도한 자원 점유 방지 : 하나의 컨테이너가 무리하게 많은 자원을 요청하여 다른 컨테이너에 영향을 주는 것을 방지한다.
- ResourceQuota : Namespace 전체 총량 관리
- 총량 제어 : 팀별 자원 한도를 명확히 설정한다.
- 시스템 안정성 : 특정 Namespace 내에서 무분별하게 많은 Pod를 생성해 전체 클러스터의 가용 자원을 고갈시키는 것을 막는다.
apiVersion: v1
kind: Namespace
metadata:
name: team-a-project
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-mem-limit-range
namespace: team-a-project
spec:
limits:
- default: # 기본값 (설정을 누락했을 때 자동 적용)
cpu: "500m"
memory: "256Mi"
defaultRequest: # 최소 요구량
cpu: "100m"
memory: "128Mi"
max: # 최대 사용 가능량
cpu: "2"
memory: "1Gi"
min: # 최소 사용 가능량
cpu: "50m"
memory: "64Mi"
type: Container
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a-project
spec:
hard:
requests.cpu: "4" # 전체 요청 CPU 총합 4코어 제한
requests.memory: "8Gi" # 전체 요청 메모리 총합 8Gi 제한
limits.cpu: "10" # 전체 사용 가능 CPU 최대 10코어 제한
limits.memory: "16Gi" # 전체 사용 가능 메모리 최대 16Gi 제한
pods: "20" # 생성 가능한 최대 Pod 개수 20개 제한