Kubernetes ‐ Basic Object - thought-corner/Backend-PlayGround GitHub Wiki

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.requestslimits를 정의하지 않아도 클러스터 관리자가 정한 기본값을 자동으로 할당한다.
    • 과도한 자원 점유 방지 : 하나의 컨테이너가 무리하게 많은 자원을 요청하여 다른 컨테이너에 영향을 주는 것을 방지한다.
  • 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개 제한