Pod ?

Pod 개념

  • Pod은 kubernetes 클러스터 내 최소 배포단위
  • 하나의 Pod는 하나의 node에 속하고 node 단위로 옮겨다닐 수 있음
  • Pod 에는 여러개의 container가 포함될 수 있고 Pod 내 container들은 storage와 network를 공유하며 내부통신이 가능함

Pod 사용 현황

$ kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
kimdubi-test-redis-cluster-0   1/1     Running   0          23h
kimdubi-test-redis-cluster-1   1/1     Running   0          2d1h
kimdubi-test-redis-cluster-2   1/1     Running   1          23h
kimdubi-test-redis-cluster-3   1/1     Running   1          2d1h
kimdubi-test-redis-cluster-4   1/1     Running   0          23h
kimdubi-test-redis-cluster-5   1/1     Running   0          23h
  • 본문에서 사용하는 helm chart 에서는 Redis Pod을 6대 생성함
  • 3대는 Master , 3대는 Slave 로 동작 중
  • Pod은 statefulset 에 의해 생성되고 관리되며 Pod의 container image나 개수, 설정등을 변경하고 싶다면 helm chart 내 statefulset과 values.yaml을 수정해야함

Pod template을 살펴보자

$ kubectl get pod/kimdubi-test-redis-cluster-0 -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    checksum/scripts: 13c84ab100b949b2a69989dbcfa1079e3d930ee56d79744da9abc6d691709923
    checksum/secret: 3fb9c96414bd6f5e1a0841de974fcb260231a9c12bebb2c49af0f02b651e47cf
  creationTimestamp: "2021-02-22T09:21:50Z"
  generateName: kimdubi-test-redis-cluster-
  labels:
    app.kubernetes.io/instance: kimdubi-test
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: redis-cluster
    controller-revision-hash: kimdubi-test-redis-cluster-86585bd988
    helm.sh/chart: redis-cluster-4.3.0
    statefulset.kubernetes.io/pod-name: kimdubi-test-redis-cluster-0
  name: kimdubi-test-redis-cluster-0
  namespace: default
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: StatefulSet
    name: kimdubi-test-redis-cluster
    uid: b348894a-e930-4dc2-ba10-c8566eeec0b9
  resourceVersion: "358338"
  selfLink: /api/v1/namespaces/default/pods/kimdubi-test-redis-cluster-0
  uid: ccfca1d7-e997-4375-acbd-aa44b1428c35
spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - podAffinityTerm:
          labelSelector:
            matchLabels:
              app.kubernetes.io/instance: kimdubi-test
              app.kubernetes.io/name: redis-cluster
          namespaces:
          - default
          topologyKey: kubernetes.io/hostname
        weight: 1
  containers:
  - args:
    - |
      # Backwards compatibility change
      if ! [[ -f /opt/bitnami/redis/etc/redis.conf ]]; then
          echo COPYING FILE
          cp  /opt/bitnami/redis/etc/redis-default.conf /opt/bitnami/redis/etc/redis.conf
      fi
      /opt/bitnami/scripts/redis-cluster/entrypoint.sh /opt/bitnami/scripts/redis-cluster/run.sh
    command:
    - /bin/bash
    - -c
    env:
    - name: REDIS_NODES
      value: 'kimdubi-test-redis-cluster-0.kimdubi-test-redis-cluster-headless kimdubi-test-redis-cluster-1.kimdubi-test-redis-cluster-headless
        kimdubi-test-redis-cluster-2.kimdubi-test-redis-cluster-headless kimdubi-test-redis-cluster-3.kimdubi-test-redis-cluster-headless
        kimdubi-test-redis-cluster-4.kimdubi-test-redis-cluster-headless kimdubi-test-redis-cluster-5.kimdubi-test-redis-cluster-headless '
    - name: REDISCLI_AUTH
      valueFrom:
        secretKeyRef:
          key: redis-password
          name: kimdubi-test-redis-cluster
    - name: REDIS_PASSWORD
      valueFrom:
        secretKeyRef:
          key: redis-password
          name: kimdubi-test-redis-cluster
    - name: REDIS_AOF_ENABLED
      value: "yes"
    - name: REDIS_TLS_ENABLED
      value: "no"
    - name: REDIS_PORT
      value: "6379"
    image: docker.io/bitnami/redis-cluster:6.0.10-debian-10-r5
    imagePullPolicy: IfNotPresent
    livenessProbe:
      exec:
        command:
        - sh
        - -c
        - /scripts/ping_liveness_local.sh 5
      failureThreshold: 5
      initialDelaySeconds: 5
      periodSeconds: 5
      successThreshold: 1
      timeoutSeconds: 5
    name: kimdubi-test-redis-cluster
    ports:
    - containerPort: 6379
      name: tcp-redis
      protocol: TCP
    - containerPort: 16379
      name: tcp-redis-bus
      protocol: TCP
    readinessProbe:
      exec:
        command:
        - sh
        - -c
        - /scripts/ping_readiness_local.sh 1
      failureThreshold: 5
      initialDelaySeconds: 5
      periodSeconds: 5
      successThreshold: 1
      timeoutSeconds: 1
    resources:
      limits:
        cpu: 100m
        memory: 100Mi
      requests:
        cpu: 50m
        memory: 50Mi
    securityContext:
      runAsUser: 1001
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /scripts
      name: scripts
    - mountPath: /bitnami/redis/data
      name: redis-data
    - mountPath: /opt/bitnami/redis/etc/redis-default.conf
      name: default-config
      subPath: redis-default.conf
    - mountPath: /opt/bitnami/redis/etc/
      name: redis-tmp-conf
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-5zmdw
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: false
  hostname: kimdubi-test-redis-cluster-0
  nodeName: kimdubi-test-default-w-46niimovcith-node-2
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext:
    fsGroup: 1001
  serviceAccount: default
  serviceAccountName: default
  subdomain: kimdubi-test-redis-cluster-headless
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: redis-data
    persistentVolumeClaim:
      claimName: redis-data-kimdubi-test-redis-cluster-0
  - configMap:
      defaultMode: 493
      name: kimdubi-test-redis-cluster-scripts
    name: scripts
  - configMap:
      defaultMode: 420
      name: kimdubi-test-redis-cluster-default
    name: default-config
  - emptyDir: {}
    name: redis-tmp-conf
  - name: default-token-5zmdw
    secret:
      defaultMode: 420
      secretName: default-token-5zmdw
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2021-02-22T09:21:51Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2021-02-22T09:22:23Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2021-02-22T09:22:23Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2021-02-22T09:21:50Z"
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: docker://ffe64f7d3ca9e5f302a9269d87c2598522b883169ef82bd931186bbd8e721482
    image: bitnami/redis-cluster:6.0.10-debian-10-r5
    imageID: docker-pullable://bitnami/redis-cluster@sha256:dfedcaa03878564f6eb75c101a66d8ecd18a9558971ade5c82611bfa9fb6da96
    lastState: {}
    name: kimdubi-test-redis-cluster
    ready: true
    restartCount: 0
    started: true
    state:
      running:
        startedAt: "2021-02-22T09:22:12Z"
  hostIP: 192.168.0.8
  phase: Running
  podIP: 10.100.14.8
  podIPs:
  - ip: 10.100.14.8
  qosClass: Burstable
  startTime: "2021-02-22T09:21:51Z"

.labels

  • key-value 형태로 controller가 자신이 관리해야하는 Pod를 구분하기 위해 사용함
  • Pod에 lables 을 달아놓으면 statefulset,service 같은 controller에서 labelSelector를 통해 매치되는 Pod을 관리함

.spec.affinity

  • Pod를 스케줄링 할 때 어떤 worker-node에 배치할 지 조건을 설정하는 옵션
  • podAffinity 설정으로 특정 Pod들을 같은 노드에 모아 네트워크 비용을 줄일 수도 있고
  • podAntiAffinity 설정으로 같은 기능의 Pod들을 같은 노드에 배치하지 않고 여러 노드에 분산배치할 수 있음
  • 위 Pod설정에서는 podAntiAffinity 설정으로 Pod들을 분산배치하고자 하는데 podAffinityTerm[].labelSelector.matchLabels: 옵션으로 해당 label이 달린 Pod가 속한 node 에는 ‘되도록’ 배치하지 않으려한다. (preferredDuringSchedulingIgnoredDuringExecution)

.spec.containers[].args

  • Pod 내 container를 생성할 때 entrypoint로 넘겨줄 arguments 지정
  • /opt/bitnami/redis/etc/redis.conf redis configure 파일을 복사하고
  • redis cluster 구성을 위한 shell을 수행하기 위해 설정하고 있음
    • /opt/bitnami/scripts/redis-cluster/entrypoint.sh
    • /opt/bitnami/scripts/redis-cluster/run.sh

.spec.containers[].env

  • container에서 사용할 환경변수를 설정해서 넘겨줌

.spec.containers[].image

  • 생성할 container image 지정

.spec.containers[].livenessProbe

  • Container가 동작 중 인지 /scripts/ping_liveness_local.sh 수행을 통해 확인함
  • livenessProbe 동작에 실패하는 경우 worker node의 kubelet은 해당 container를 재기동함

.spec.containers[].readinessProbe

  • Container 가 요청을 처리할 수 있는 상태인지 /scripts/ping_readiness_local.sh 수행을 통해 확인함
  • readinessProbe 동작에 실패하는 경우 endpoint Controller는 해당 Pod의 IP를 모든 endpoint에서 제거함

.spec.containers[].resources

  • .spec.containers[].resources.limit -> Pod가 최대한 사용할 수 있는 서버 리소스 한계선을 지정, 없으면 Pod 하나가 노드의 모든 리소스를 사용할 수 있음
  • .spec.containers[].resources.requests -> Pod를 생성할 때 지정한 만큼의 최소한의 리소스를 할당 할 수 있는 노드에 배치, 만족하는 노드가 없으면 Pod pending

.spec.conatiners.volumeMounts

  • .spec.volumes 에서 준비한 volume을 container 에 매핑하는 설정
  • 예를들어 .spec.volumes 에서 redis-data 이름으로 생성한 PVC 볼륨은 container의 /bitnami/redis/data 디렉토리와 매핑됨

.spec.volumes

  • Container는 stateless 한 특성이 있으나 보존해야하는 데이터가 있을 경우 volume을 생성하여 노드의 디스크와 container의 디렉토리를 매핑할 수 있음
  • PVC redis-data-kimdubi-test-redis-cluster-0를 통해 hostPath type의 PV 와 매핑함, Pod는 이 PVC를 통해 실제 볼륨 역할을 하는 PV와 매핑됨
  • 그 외에 configmap volume 과 Pod가 restart 되면 초기화되는 emptyDir 을 선언함