Yebali

Kubernetes의 Pod와 Controller 본문

Backend Common

Kubernetes의 Pod와 Controller

예발이 2024. 3. 3. 17:06

Pod

Pod은 kubernetes에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 단위이다.

하나 이상의 Container를 포함하고 있으며 Pod 내에서 Container들은 스토리지와 네트워크를 공유한다.

Pod에는 Pod가 시작될 때 실행되는 InitContainer 등이 포함될 수 있다.

Pod은 제한된 리소스 이상을 사용하게 되면 재시작된다.

apiVersion: v1
kind: Pod
metadata:
  name: nginx # Pod 이름
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
    resources:
      requests:
        cpu: 300m
        memory: 500Mi
      limits: # Pod가 사용할 수 있는 리소스 제한
        cpu: 1
        memory: 1000Mi

 

InitContainer

InitContiner는 Pod의 AppContainer들이 실행되기 전에 실행되는 특수한 컨테이너이다.

AppContainer 이미지에 없는 유틸리티 또는 설정 스크립트 등을 포함할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]


# init-myservice 동작
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

# init-mydb 동작
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

 

Static Pod

Static Pod는 API servier없이 특정 노드에 있는 kubelet Daemon에 의해 직접 관리된다.

그렇기 때문에 항상 특정 노트에 있는 하나의 kubelet에 매여있다.

노트에서 '/var/lib/kubelet/config.yaml'을 보면 'staticPodPath: /etc/kubernetes/manifests'와 같이 static pod 설정을 위한 경로를 알 수 있다.

위 경로에 Pod을 정의하는 yaml파일을 추가하면 Static Pod가 실행된다.

LivenessProbe

Self healing 기능의 일종으로 Container 상태가 비정상일 때 해당 Pod를 재시작하여 정상상태로 만드는 기능이다.

지원하는 매커니즘은 아래 3가지가 있다.

  • httpGet: 지정한 주소 IP, port로 GET요청을 보내서 200 응답이 오지 않으면 Pod을 다시 시작한다.
  • tcpSocket: 지정된 port로 tcp 연결을 시도한다. 연결되지 않으면 Pod을 다시 시작한다.
  • exec: exec 명령을 전달하고 명령의 종료코드가 0이 아니면 Pod을 다시 시작한다.
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-liveness
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
      protocol: TCP
    livenessProbe:
      httpGet: # Pod의 80포트로 Get요청을 보내 Pod 상태를 진단.
        path: /
        port: 80

 

Controller

Kubernetes의 Controller은 클러스터의 상태를 관찰하고 필요한 경우 생성 또는 변경을 요청하는 컨트롤 루프이다.

Controller은 적어도 하나 이상의 Kubernetes 리소스를 추적하고 클러스터의 상태를 의도한 상태와 가깝게 유지되도록 한다.

ReplicationController

ReplicationController은 지정된 수의 Replicas가 실행되는 것을 보장한다.

즉, Replicas가 3이면 항상 3개의 Pod가 실행되는 것을 보장한다.

ReplicationController은 'selector'값을 보고 관리할 Pod를 찾기 때문에 'template.metadata.labels'에는 selector와 동일한 값이 지정되어 있어야 한다.

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

 

ReplicaSet

Replication controller와 비슷하지만 더 풍부한 selector를 지원한다.

mtachLabels, matchExpressions 등을 지원한다

 

matchExpressions

  • In: key와 value를 지정하여 일치하는 Pod만 연결
  • NotIn: key는 일치하고 value는 일치하지 않는 Pod에 연결
  • Exists: key에 맞는 label의 Pod을 연결
  • DoesNotExist: key와 다른 label의 Pod을 연결
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # 케이스에 따라 레플리카를 수정한다.
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3

 

Deployment

Deployment는 ReplicaSet의 일종의 상위호환 개념으로 Pod들의 현재 상태와 의도하는 상태의 비율을 조정하며 변경할 수 있다.

일반적으로 파드 인스턴스를 점진적으로 업데이트하는 것을 RollingUpdate라고 하는데 Deployment를 사용하면 RollingUpdate를 손쉽게 할 수 있다.

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: app-deploy
spec:
  replicas: 5
  progressDeadlineSeconds: 600 # 업데이트 데드라인
  strategy:
    rollingUpdate:
      maxSurge: 25% 
      maxUnavailable: 25%
    type: RollingUpdate
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      labels:
        app: webui
    spec:
      containers:
      - name: web
        image: nginx:1.14
        ports:
        - containerPort: 80

 

  • strategy.rollingUpdate.maxSurge: RollingUpdate 중 정해진 Pod 수 이상으로 만들 수 있는 Pod의 최대 개수.(default: 25%)
  • strategy.rollingUpdate.maxUnavailable: RollingUpdate 중 unavailable 상태인 Pod의 최대 개수. '25%'와 같이 사용할 수 있으며 maxSurge와 maxUnavailable 값이 동시에 0이 될 수 없다.

 

DaemonSet

DaemonSet은 모든 Node에서 특정 Pod가 1개씩 실행되도록 보장한다.

클러스터에 새로운 노드가 추가되면 Pod도 추가되고, 노드가 삭제되면 함께 삭제된다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # 이 톨러레이션(toleration)은 데몬셋이 컨트롤 플레인 노드에서 실행될 수 있도록 만든다.
      # 컨트롤 플레인 노드가 이 파드를 실행해서는 안 되는 경우, 이 톨러레이션을 제거한다.
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log

 

 

StatefulSet

StatefulSet은 Pod의 집합과 Deployment와 스케일링을 관리하며 Pod들의 순서와 고유성을 보장한다.

Deployment와 유사하게 동일한 Container spec을 기반으로 둔 Pod들을 관리한다.

하지만 서로 교체는 불가능하다. 다시 말해 재스케줄링 간에도 지속적으로 유지되는 식별자를 가진다.

StatefulSet에 의해 관리되는 Pod의 이름은 'metadata.name + 번호'로 지정된다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sf-nginx
spec:
  replicas: 3
  serviceName: sf-service
  podManagementPolicy: Parallel
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
      - name: nginx-container
        image: nginx

 

참고자료

- https://kubernetes.io/ko/

- https://www.youtube.com/watch?v=6n5obRKsCRQ&list=PLApuRlvrZKohaBHvXAOhUD-RxD0uQ3z0c