DevOps/Kubernetes

[Kubernetes] Pod #2: 쿠버네티스 셀프 힐링 및 자원 할당

ooeunz 2020. 7. 13. 15:18
반응형

컨테이너 진단

쿠버네티스는 장애가 생기는 컨테이너가 있는지, 또 있다면 재시작을 하기 위해서 등 컨테이너가 실행된 후에도 주기적으로 kubelet을 이용해 컨테이너를 진단합니다. 이때 필요한 프로브가 두 가지가 있습니다.

 

livenessProbe컨테이너가 실행됐는지 확인합니다. 만약 이 진단에 실패하면 kubelet는 컨테이너를 종료시키고 재시작 정책에 따라 컨테이너를 재시작합니다.

spec:
  selector:
    matchLabels:
      app: sisko
  ...
  template:
    ...
    spec:
      containers:
      - name: sisko
        image: <이미지 명>
        imagePullPolicy: Always
        ...
        livenessProbe:
          httpGet:
            path: /v1/relations/datahub_homo/person/18964
            port: 8080
          initialDelaySeconds: 3 #초기 상태진단 전 대기 시간
          periodSeconds: 1 #상태진단 주기


readinessProbe : 컨테이너가 실행된 후 실제로 서비스 요청에 응답할 수 있는지 진단합니다. readinessProbe를 지원하는 컨테이너는 컨테이너가 실행된 다음 트래픽을 받지 않고, 실제 트래픽을 받을 준비가 되었을 때 트래픽을 받게 됩니다. readinessProbe는 자바 애플리케이션처럼 프로세스가 시작된 후 앱이 초기화될 때까지 시간이 걸리는 컨테이너에 유용하게 작용합니다.

그런데 만약 readinessProbe 진단이 실패하면 엔드포인트 컨트롤러는 해당 파드에 연결된 모든 서비스를 대상으로 엔드포인트 정보를 제거합니다.

spec:
  selector:
    matchLabels:
      app: sisko
  ...
  template:
    ...
    spec:
      containers:
      - name: sisko
        image: <이미지 명>
        imagePullPolicy: Always
        ...
        readinessProbe:
          httpGet:
            path: /v1/relations/datahub_homo/person/18964
            port: 8080
          initialDelaySeconds: 3 #초기 상태진단 전 대기 시간
          periodSeconds: 1 #상태진단 주기

 

컨테이너의 진단은 컨테이너가 구현한 핸들러(handler)를 kubelet이 호출해서 실행하게 됩니다.

  • ExecAction : 컨테이너 안에 지정된 명령을 실행 → 종료 코드가 0이면 Success라고 진단
  • TCPSocketAction : 컨테이너 안에 지정된 IP와 포트로 TCP 상태를 확인 → 포트가 열려있으면 Success라고 진단
  • HTTPGetAction : 컨테이너 안에 지정된 IP, 포트, 경로로 HTTP GET 요청을 보내서 확인 → 응답 상태 코드가 200~400 사이면 Success라고 진단 

진단 결과로는 진단을 성공적으로 마쳤다는 Success와 진단을 실패한  Failure, 그리고 진단 자체가 실패해서 컨테이너 상태를 알 수 없는 Unknown이 있습니다.

 

 

초기화 컨테이너

초기화 컨테이너는 앱 컨테이너가 실행되기 전 파드를 초기화합니다. 이러한 특징을 이용하면 파드를 실행할 때 앱 컨테이너가 외부의 특정 조건을 만족할 때까지 기다렸다가 실행하도록 만들 수 있습니다. 초기화 컨테이너는 일반적인 앱 컨테이너와 비슷하게 동작하지만 몇 가지 다른 점이 있습니다. 그중 가장 큰 특징은 파드가 모두 준비되기 전에 실행한 후 컨테이너기 때문에 앞서 설명드린 readinessProbe를 지원하지 않습니다.

 

초기화 컨테이너 역시 템플릿을 명시해서 사용할 수 있는데, 만약 여러 개의 컨테이너를 사용하게 된다면 템플릿에 명시한 순서대로 초기화 컨테이너가 실행됩니다.

 

아래는 초기화 컨테이너를 설정한 템플릿 예제입니다.

apiVersion: v1
kind: Pod
metadata:
  name: kuberbetes-sample-pod
  labels:
    app: kubernetes-simple-pod
  spec:
    initContainers:
    - name: init-service01
      image: arisu1000/simple-container-app:latest
      command: ['sh', '-c', 'sleep 2; echo helleworld 01;']  # 2초 대기 후 helloworld 01 출력
    - name: init-service02
      image: arisu1000/simple-container-app:latest
      command: ['sh', '-c', 'sleep 2; echo helleworld 02;'] # 2초 대기 후 helloworld 02 출력
    containers:
    - name: kubernetes-simple-pod
      image: arisu1000/simple-container-app:latest
      command: ['sh', '-c', 'echo Application Running! && sleep 100'] # 100초 대기

 

Pod Infra Container

쿠버네티스의 모든 파드에는 항상 실행되는 pause라는 컨테이너가 있습니다. 이 컨테이너를 파드 인프라 컨테이너라고 부릅니다. pause는 파드 안 기본 네트워크로 실행되고, 다른 컨테이너의 부모 컨테이너 역할을 합니다. 파드 안 다른 컨테이너는 pause 컨테이너가 제공하는 네트워크를 공유해서 사용합니다.

 

그래서 파드 안에서 다른 컨테이너는 재시작하더라도 파드의 IP를 그대로 유지하지만, pause 컨테이너가 재시작되면 파드 안 모든 컨테이너도 재시작됩니다.

 

 

Static Pod

이전에 kube-apiserver는 쿠버네티스의 프론트엔드로 api요청을 받아들인다고 하였습니다. 그런데 kube-apiserver를 통하지 않고 kubelet이 직접 실행하는 파드들이 있습니다. 이렇나 파드를 스태틱 파드라고 합니다. 스태틱 파드는 kube-apiserver로 파드를 조회할 수는 있지만 스태틱 파드에 어떤 명령도 할 수 없습니다. 

 

보통 스태틱 파드는 kube-apiserver나 etcd 같은 스태틱 파드를 실행하는 용도로 많이 사용합니다. 예를 들면 쿠버네티스에서 파드를 실행하려면 kube-apiserver가 필요한데 kube-apiserver 자체를 처음 실행하는 수단으로 스태틱 파드를 이용하는 것입니다.

 

스태틱 파드를 확인하기 위해서는 아래의 경로로 이동해서 다음과 같이 명령어를 입력하면 됩니다.

cd /etc/kubernetes/mainfests

ls -alF

 

 

Pod에 CPU와 메모리 할당

이전의 포스팅에서 쿠버네티스에 대해 설명하면서 자동으로 각각의 노드에 파드를 적절히 분배해준다고 이야기했었습니다. 최근 MSA(마이크로 서비스 아키텍처) 기반으로 아키텍처가 구성되면서 여러 개의 작은 프로세스들이 실행되면서 노드 하나에 여러 개의 파드가 실행되는 경우가 많아졌습니다.

 

쿠버네티스가 각각의 노드에 적절히 파드를 분배하는 것은 대단히 중요한 스케줄링입니다. 예를 들어 자원 사용량이 많은 파드가 노드 하나에 모여있다면 각각의 파드들의 성능이 떨어질 것입니다. 또 반대로 어떤 노드에는 파드가 없어서 CPU나 메모리의 자원이 남게 되어 전체 클러스터의 자원 사용 효율이 떨어질 수 있습니다.

 

쿠버네티스에서는 이런 상황을 막기 위해 파드를 설정할 때 파드 안 까 컨테이너에 CPU와 메모리를 최소 얼마만큼 필요한지, 또 최대 얼마만큼 사용하도록 제한할 것인지와 같이 조건을 지정할 수 있습니다.

 

자원 사용량을 설정하는 필드는 아래와 같습니다.

  • .spec.containers[].resources.requests.cpu : cpu 최소 요구 자원
  • .spec.containers[].resources.requests.memory : 메모리 최소 요구 자원
  • .spec.containers[].resources.limits.cpu : cpu 사용제한
  • .spec.containers[].resources.limits.memory : 메모리 사용제한
apiVersion: v1
kind: Pod
metadata:
  name: kuberbetes-sample-pod
  labels:
    app: kubernetes-simple-pod
  spec:
    containers:
    - name: kubernetes-sample
      image: arisu1000/simple-container-app:latest
      resource:
        requests:
          cpu: 0.1
          memory: 200M

위의 yaml 파일이 cpu와 메모리를 할당하는 예시입니다. CPU를 할당할 때는 코어의 개수를 표시합니다. 그런데 위의 예시에서는 0.1이라고 표현되어 있는데 이때의 소수점은 코어의 연산능력을 기준으로 합니다. 만약 1이라고 표시한다면 코어 1개의 온전한 연산능력이 반영되는 것이고, 0.1이라고 한다면 코어 하나의 10%만큼 연산 능력을 할당한다는 뜻입니다.

 

다음으로 메모리는 별도의 용량을 나타내는 단위가 함께 표시되지 않는다면 바이트 단위로 측정됩니다. 위의 예시 같은 경우에는 M(mega)를 나타내는 것으로 200메가를 뜻하게 됩니다. 용량을 나타내는 단위로는 E(exbi), P(pebi), T(tebi), G(gebi), M(mebi), K(kibi)가 있습니다.

반응형