오늘도 한 걸음씩 GitHub

Kubenetes

Kubernetes (2)

YongE 2025. 4. 10. 13:12

개념 정리


쿠버네티스의 핵심 개념인 Pod, Service, Volume, ConfigMap 및 Secret을 중심으로 이해하기 쉽게 정리해보고자 한다!

Pod - Container, Label, NodeSchedule

Pod의 기본 개념

Pod는 쿠버네티스에서 배포할 수 있는 가장 작은 단위로, 하나 이상의 컨테이너를 포함한다. 같은 Pod 내의 컨테이너들은 스토리지와 네트워크를 공유하며 서로 로컬호스트처럼 통신할 수 있다.

노드 스케줄링

쿠버네티스는 자동으로 Pod를 노드에 배치하지만, 특정 노드에 Pod를 배치해야 하는 경우가 있다. 이를 위한 방법으로는

  1. nodeSelector: Pod 명세의 spec 섹션에 특정 레이블을 가진 노드를 지정하는 방법
  2. Node Affinity: 노드 선택에 더 유연한 표현식을 제공하는 방법
  3. nodeName: 직접 노드 이름을 지정하는 방법
  4. Pod 토폴로지 스프레드 제약조건: Pod를 클러스터 전체에 분산하는 방법
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        pod: nginx  # 이 레이블을 가진 노드에만 Pod 배치
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

노드 Affinity

Node Affinity는 nodeSelector보다 더 세밀한 제어를 제공한다. 두 가지 유형이 있다

  • requiredDuringSchedulingIgnoredDuringExecution: 조건을 만족하는 노드에만 Pod 배치
  • preferredDuringSchedulingIgnoredDuringExecution: 조건을 만족하는 노드를 선호하지만, 필수는 아님

Static Pod

/etc/kubernetes/manifests 경로에는 컨트롤플레인(마스터노드)에 필요한 kube-apiserver, etcd cluster, control-manager 등이 정의돼 있다. 이는 apiserver의 정보가 없어도 쿠버네티스 자체적으로 운영에 꼭 필요한 구성 요소를 정적인 Pod로 만들 수 있게 한 것이다. static으로 생성된 파드들은 kubectl 명령어로 외부에서 삭제할 수 없다. 수정 및 삭제하기 위해서는 반드시 해당 경로 내에 있는 파일을 수정 및 삭제해야 한다.

  • static pod는 기본적으로 컨트롤플레인에서만 생성된다.

Service - ClusterIP, NodePort, LoadBalancer

Service의 필요성

Pod는 일시적이라 IP 주소가 변경될 수 있어서 직접적인 연결에 의존할 수 없다. Service는 안정적인 IP 주소와 포트를 제공해 Pod에 접근할 수 있게 한다.

Service 유형

쿠버네티스는 다음과 같은 Service 유형을 제공한다

  1. ClusterIP
    • 클러스터 내부에서만 접근 가능한 서비스
    • 클러스터 내 Pod 간 통신에 사용
    • 기본 Service 유형, type 속성을 정하거나 작성하지 않으면 디폴트로 정해짐
    • apiVersion: v1 kind: Service metadata: name: clusterIp spec: type: ClusterIp <--- 중요! ports: - targetPort: 80 <- Pod들의 port port: 80 <- Service Port selector: app: myapp <--- 이 부분부터 아래 부분은 pod 생성시에 할당한 label을 그대로 옮겨온 것이다. type: backend
  2. NodePort
    • 모든 워커 노드의 특정 포트를 통해 서비스 노출
    • 외부 네트워크와 연결됨
    • 30000-32767 범위의 포트 사용
    • 내부적으로 ClusterIP 서비스를 생성
    • apiVersion: v1 kind: Service metadata: name: node-service spec: type: NodePort <--- 중요! ports: - targetPort: 80 <- Pod들의 port port: 80 <- Service Port nodePort: 30008 <- 해당 node의 열린 Port
  3. LoadBalancer
    • NodePort의 확장으로, 외부 로드 밸런서를 생성
    • 단일 외부 IP를 통해 서비스에 접근 가능
    • 트래픽을 여러 노드에 분산
    • 클라우드 제공자의 로드 밸런싱 기능 활용
  4. ExternalName
    • 외부 서비스에 대한 내부 별칭 생성
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: myapp
  ports:
  - port: 80         # 서비스 포트
    targetPort: 8080 # 대상 애플리케이션 포트
    nodePort: 30036  # 노드 포트 (NodePort 유형인 경우)
  type: ClusterIP    # 서비스 유형 (ClusterIP, NodePort, LoadBalancer)

Volume - emptyDir, hostPath, PV/PVC

Volume의 필요성

쿠버네티스의 Pod는 일시적이므로 데이터 지속성을 위해 볼륨이 필요하다. 볼륨은 Pod의 컨테이너 간 데이터 공유나 영구 저장소 역할을 한다.

emptyDir

  • 초기에 비어있는 디렉토리로 시작
  • 같은 Pod 내 컨테이너 간 데이터 공유에 사용
  • Pod가 삭제되면 emptyDir 데이터도 삭제됨
  • 일시적인 데이터 사용에 적합
apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-1
spec:
  containers:
  - name: container1
    image: kubetm/init
    volumeMounts:
    - name: empty-dir
      mountPath: /mount1
  - name: container2
    image: kubetm/init
    volumeMounts:
    - name: empty-dir
      mountPath: /mount2
  volumes:
  - name: empty-dir
    emptyDir: {}

hostPath

  • 노드의 파일시스템을 Pod에 마운트
  • Pod가 삭제되어도 데이터 유지
  • 단, Pod가 다른 노드에 재생성되면 이전 데이터 접근 불가
  • 노드의 시스템 파일이나 데이터를 Pod에서 사용할 때 적합
apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-3
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-node1
  containers:
  - name: container
    image: kubetm/init
    volumeMounts:
    - name: host-path
      mountPath: /mount1
  volumes:
  - name: host-path
    hostPath:
      path: /node-v
      type: DirectoryOrCreate

PV/PVC (Persistent Volume/Persistent Volume Claim)

파드(Pod)의 데이터를 영구적으로 저장하기 위한 중요한 개념이다. 파드는 기본적으로 상태를 저장하지 않는(stateless) 특성이 있어, 파드가 재시작되거나 삭제되면 파드 내부에 저장된 데이터도 함께 사라진다. PV와 PVC는 이러한 문제를 해결하여 파드의 생명주기와 독립적으로 데이터를 보존할 수 있게 해준다.

  • PV: 관리자가 프로비저닝한 저장소
  • PVC: 사용자가 PV에 대한 요청을 정의
  • Pod는 PVC를 통해 PV에 접근
  • 클라우드 제공자의 저장소 등 다양한 백엔드 지원
  • Pod의 생명주기와 독립적으로 데이터 유지
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv # PV의 이름
spec:
  capacity:
    storage: 1Gi # 스토리지 용량
  volumeMode: Block # 볼륨 모드 (Filesystem 또는 Block)
  accessModes:
    - ReadWriteOnce # 접근 모드 (단일 노드에서 읽기/쓰기)
  persistentVolumeReclaimPolicy: Recycle # 회수 정책 (PVC 해제 시 PV 재활용)
  storageClassName: manual # 스토리지 클래스 이름 (동적 프로비저닝 시 중요)
  hostPath: # 실제 스토리지 유형 및 경로
    path: "/mnt/data/my-pv-data" # 노드의 해당 경로에 데이터 저장
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc # PVC의 이름
spec:
  accessModes:
    - ReadWriteOnce # PV와 동일한 접근 모드 요청
  resources:
    requests:
      storage: 500Mi # 요청하는 스토리지 용량 (PV의 capacity보다 작거나 같아야 함)
  storageClassName: manual # PV의 storageClassName과 일치해야 정적 바인딩 가능
  # volumeName: my-pv # 특정 PV와 직접 바인딩하려면 PV 이름을 명시 (선택 사항)
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pvc-pod
spec:
  volumes:
    - name: my-persistent-storage # 파드 내에서 사용할 볼륨 이름
      persistentVolumeClaim:
        claimName: my-pvc # 사용할 PVC의 이름
  containers:
    - name: my-app-container
      image: nginx # 예시 이미지
      ports:
        - containerPort: 80
      volumeMounts:
        - name: my-persistent-storage # 위에서 정의한 볼륨 이름
          mountPath: "/usr/share/nginx/html" # 컨테이너 내부에 마운트할 경로

ConfigMap, Secret - Env, Mount

ConfigMap과 Secret의 필요성

애플리케이션 설정과 민감 정보를 컨테이너 이미지와 분리하여 관리할 필요가 있다. 환경별로 다른 설정을 적용할 때 유용하다.

ConfigMap

  • 키-값 쌍으로 구성된 비민감 데이터 저장
  • 환경 변수, 명령줄 인자, 설정 파일 등에 사용

Secret

  • 민감한 정보(비밀번호, API 키 등) 저장
  • base64 인코딩으로 저장해야 한다.
  • 메모리에 유지되어 보안성 향상
  • 크기는 1MB로 제한

사용 방법

  1. 환경 변수(Literal)로 사용
apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-dev
data:
  SSH: 'false'
  User: dev
---
apiVersion: v1
kind: Secret
metadata:
  name: sec-dev
data:
  Key: MTIzNA==  # base64로 인코딩된 값
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-1
spec:
  containers:
  - name: container
    image: kubetm/init
    envFrom:
    - configMapRef:
        name: cm-dev
    - secretRef:
        name: sec-dev
  1. 파일 내용을 ConfigMap/Secret으로 사용
# ConfigMap 생성
echo "Content" >> file-c.txt
kubectl create configmap cm-file --from-file=./file-c.txt

# Secret 생성
echo "Content" >> file-s.txt
kubectl create secret generic sec-file --from-file=./file-s.txt
  1. 볼륨 마운트로 사용
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
  - name: test-container
    image: registry.k8s.io/busybox:1.27.2
    command: [ "/bin/sh", "-c", "ls /etc/config/" ]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: special-config
  restartPolicy: Never
반응형

'Kubenetes' 카테고리의 다른 글

Kubernetes (6)  (0) 2025.04.16
Kubernetes (5)  (1) 2025.04.15
Kubernetes (4)  (0) 2025.04.14
Kubernetes (3)  (0) 2025.04.11
Kubernetes (1)  (0) 2025.04.08