노드

노드 (Nodes)

쿠버네티스는 파드를 노드 에 배치해 워크로드를 실행합니다. 노드는 클러스터에 따라 가상 또는 물리 머신일 수 있습니다. 각 노드는 컨트롤 플레인에 의해 관리되며 파드를 실행하는 데 필요한 서비스를 포함합니다.

일반적으로 클러스터에는 여러 노드가 있습니다. 학습 또는 리소스 제한 환경에서는 노드가 하나뿐일 수 있습니다.

노드의 구성 요소에는 kubelet, 컨테이너 런타임, kube-proxy가 포함됩니다.

출처: 문서

본문

관리

노드가 API 서버에 추가되는 두 가지 주요 방법이 있습니다:

  1. 노드의 kubelet이 컨트롤 플레인에 스스로를 등록
  2. 사용자(또는 다른 인간 사용자)가 Node 객체를 수동으로 추가

Node 객체를 만들거나 노드의 kubelet이 스스로를 등록한 후, 컨트롤 플레인은 새 Node 객체가 유효한지 확인합니다. 예를 들어 다음 JSON 매니페스트에서 Node를 만들려고 한다면:

{
  "kind": "Node",
  "apiVersion": "v1",
  "metadata": {
    "name": "10.240.79.157",
    "labels": {
      "name": "my-first-k8s-node"
    }
  }
}

쿠버네티스는 내부적으로 Node 객체(표현)를 만듭니다. 쿠버네티스는 Node의 metadata.name 필드와 일치하는 kubelet이 API 서버에 등록되었는지 확인합니다. 노드가 정상이면(즉 필요한 모든 서비스가 실행 중), 파드를 실행할 자격이 있습니다. 그렇지 않으면 그 노드는 정상이 될 때까지 어떤 클러스터 활동에서도 무시됩니다.

쿠버네티스는 유효하지 않은 Node 객체를 유지하고 정상이 되는지 계속 확인합니다.

노드 객체를 삭제하려면 사용자 또는 컨트롤러가 명시적으로 삭제해야 그 건강 검사를 중지합니다.

Node 객체의 이름은 유효한 DNS 서브도메인 이름이어야 합니다.

노드 이름 고유성

이름은 노드를 식별합니다. 두 노드는 동시에 같은 이름을 가질 수 없습니다. 쿠버네티스는 같은 이름을 가진 리소스가 같은 객체라고 가정합니다. 노드의 경우 같은 이름을 사용하는 인스턴스가 같은 상태(예: 네트워크 설정, 루트 디스크 내용)와 노드 라벨 같은 속성을 가질 것이라고 암시적으로 가정합니다. 이는 인스턴스가 이름을 바꾸지 않고 수정되면 불일치로 이어질 수 있습니다. 노드를 크게 교체하거나 업데이트해야 한다면 기존 Node 객체를 먼저 API 서버에서 제거하고 업데이트 후 다시 추가해야 합니다.

노드의 자체 등록

kubelet 플래그 --register-node가 true(기본값)일 때 kubelet은 API 서버에 스스로를 등록하려 시도합니다. 이는 대부분의 배포판이 사용하는 선호 패턴입니다.

자체 등록을 위해 kubelet은 다음 옵션으로 시작됩니다:

  • --kubeconfig - API 서버에 자신을 인증할 자격 증명의 경로.

  • --cloud-provider - 자신에 대한 메타데이터를 읽기 위해 클라우드 제공자와 통신하는 방법.

  • --register-node - API 서버에 자동으로 등록.

  • --register-with-taints - 주어진 테인트 목록(쉼표로 구분된 <key>=<value>:<effect>)으로 노드를 등록.

    register-node가 false면 아무 작업도 하지 않습니다.

  • --node-ip - 선택적 쉼표로 구분된 노드 IP 주소 목록. 각 주소 패밀리에 대해 단일 주소만 지정할 수 있습니다. 예를 들어 단일 스택 IPv4 클러스터에서 이 값을 kubelet이 노드에 사용해야 하는 IPv4 주소로 설정합니다. 듀얼 스택 클러스터 실행의 세부 사항은 IPv4/IPv6 듀얼 스택 구성을 참조하세요.

    이 인자를 제공하지 않으면 kubelet은 노드의 기본 IPv4 주소(있는 경우)를 사용합니다. 노드에 IPv4 주소가 없으면 kubelet은 노드의 기본 IPv6 주소를 사용합니다.

  • --node-labels - 클러스터에 노드를 등록할 때 추가할 라벨(NodeRestriction admission plugin이 강제하는 라벨 제한 참조).

  • --node-status-update-frequency - kubelet이 API 서버에 노드 상태를 게시하는 빈도 지정.

Node authorization modeNodeRestriction admission plugin이 활성화되면 kubelet은 자신의 Node 리소스만 만들/수정할 권한이 있습니다.

노드 이름 고유성 섹션에서 언급했듯이, 노드 구성을 업데이트해야 할 때 노드를 API 서버에 다시 등록하는 것이 좋은 관행입니다. 예를 들어 kubelet이 새 --node-labels 집합으로 재시작되는데 같은 노드 이름을 사용한다면, 라벨은 API 서버에 노드가 등록될 때만 설정(또는 수정)되므로 변경이 적용되지 않습니다.

노드 구성이 kubelet 재시작 시 변경되면 이미 노드에 스케줄링된 파드가 잘못 동작하거나 문제를 일으킬 수 있습니다. 예를 들어 이미 실행 중인 파드가 노드에 할당된 새 라벨에 대해 테인트될 수 있고, 그 파드와 호환되지 않는 다른 파드가 이 새 라벨을 기반으로 스케줄링될 수 있습니다. 노드 재등록은 모든 파드가 드레인되고 적절히 재배치되도록 보장합니다.

수동 노드 관리

kubectl을 사용해 Node 객체를 만들고 수정할 수 있습니다.

Node 객체를 수동으로 만들 때는 kubelet 플래그 --register-node=false를 설정하세요.

--register-node의 설정과 무관하게 Node 객체를 수정할 수 있습니다. 예를 들어 기존 노드에 라벨을 설정하거나 unschedulable로 표시할 수 있습니다.

<role>의 문자를 라벨의 구문 규칙으로 제한하는 하나 이상의 node-role.kubernetes.io/<role>: <role> 라벨을 노드에 추가해 선택적 노드 역할을 설정할 수 있습니다.

쿠버네티스는 노드 역할의 라벨 값을 무시합니다. 관례상 라벨 키의 노드 역할에 사용한 것과 같은 문자열로 설정할 수 있습니다.

노드의 라벨을 파드의 노드 선택자와 함께 사용해 스케줄링을 제어할 수 있습니다. 예를 들어 파드가 사용 가능한 노드의 하위 집합에서만 실행 가능하도록 제약할 수 있습니다.

노드를 unschedulable로 표시하면 스케줄러가 그 노드에 새 파드를 배치하지 못하게 하지만 기존 파드에는 영향을 주지 않습니다. 이는 노드 재부팅이나 다른 유지보수 전의 준비 단계로 유용합니다.

노드를 unschedulable로 표시하려면 실행:

kubectl cordon $NODENAME

자세한 내용은 노드 안전하게 드레인을 참조하세요.

DaemonSet의 일부인 파드는 unschedulable 노드에서 실행되는 것을 견딥니다. DaemonSet은 보통 노드 로컬 서비스를 제공하며, 워크로드 애플리케이션에서 드레인 중이라도 노드에서 실행되어야 합니다.

노드 상태

노드의 상태에는 다음 정보가 포함됩니다:

kubectl을 사용해 노드의 상태와 다른 세부 사항을 볼 수 있습니다:

kubectl describe node <insert-node-name-here>

자세한 내용은 노드 상태를 참조하세요.

노드 하트비트

쿠버네티스 노드가 보내는 하트비트는 클러스터가 각 노드의 가용성을 결정하고 실패가 감지되면 조치를 취하도록 돕습니다.

노드에는 두 가지 형태의 하트비트가 있습니다:

  • 노드의 .status 업데이트.
  • kube-node-lease 네임스페이스 안의 Lease 객체. 각 노드는 연관된 Lease 객체를 가집니다.

노드 컨트롤러

노드 컨트롤러는 노드의 다양한 측면을 관리하는 쿠버네티스 컨트롤 플레인 구성 요소입니다.

노드 컨트롤러는 노드의 수명에서 여러 역할을 합니다. 첫 번째는 노드가 등록될 때(또는 CIDR 할당이 켜져 있을 때) CIDR 블록을 할당하는 것입니다.

두 번째는 클라우드 제공자의 사용 가능한 머신 목록으로 노드 컨트롤러의 내부 노드 목록을 최신 상태로 유지하는 것입니다. 클라우드 환경에서 실행되고 노드가 건강하지 않을 때마다 노드 컨트롤러는 클라우드 제공자에게 해당 노드의 VM이 여전히 사용 가능한지 묻습니다. 아니면 노드 컨트롤러는 노드를 노드 목록에서 삭제합니다.

세 번째는 노드의 건강을 모니터링하는 것입니다. 노드 컨트롤러는 다음을 책임집니다:

  • 노드에 도달할 수 없게 되면 노드의 .status 필드의 Ready 조건을 업데이트. 이 경우 노드 컨트롤러는 Ready 조건을 Unknown으로 설정한다.
  • 노드가 계속 도달할 수 없으면: 도달할 수 없는 노드의 모든 파드에 대해 API 개시 축출을 트리거. 기본적으로 노드 컨트롤러는 노드를 Unknown으로 표시한 후 첫 번째 축출 요청을 제출하기까지 5분을 기다린다.

기본적으로 노드 컨트롤러는 매 5초마다 각 노드의 상태를 확인합니다. 이 주기는 kube-controller-manager 구성 요소의 --node-monitor-period 플래그를 사용해 구성할 수 있습니다.

축출의 속도 제한

대부분의 경우 노드 컨트롤러는 축출 속도를 초당 --node-eviction-rate(기본 0.1)로 제한하므로, 10초마다 1개 이상의 노드에서 파드를 축출하지 않습니다.

주어진 가용성 영역의 노드가 건강하지 않게 되면 노드 축출 동작이 변경됩니다. 노드 컨트롤러는 영역의 노드가 동시에 건강하지 않은 비율(Ready 조건이 Unknown 또는 False)을 확인합니다:

  • 건강하지 않은 노드의 비율이 --unhealthy-zone-threshold(기본 0.55) 이상이면 축출 속도가 줄어듭니다.
  • 클러스터가 작으면(즉 --large-cluster-size-threshold 노드 이하 - 기본 50), 축출이 중지됩니다.
  • 그렇지 않으면 축출 속도가 초당 --secondary-node-eviction-rate(기본 0.01)로 줄어듭니다.

이 정책이 가용성 영역별로 구현되는 이유는 한 가용성 영역이 컨트롤 플레인에서 분할될 수 있는 반면 다른 영역은 연결된 상태로 유지될 수 있기 때문입니다. 클러스터가 여러 클라우드 제공자 가용성 영역에 걸쳐 있지 않으면 축출 메커니즘은 영역별 장애를 고려하지 않습니다.

노드를 가용성 영역에 분산하는 핵심 이유는 전체 영역이 다운될 때 워크로드를 정상 영역으로 옮길 수 있기 때문입니다. 따라서 영역의 모든 노드가 건강하지 않으면 노드 컨트롤러는 정상 속도 --node-eviction-rate로 축출합니다. 극단적인 경우는 모든 영역이 완전히 건강하지 않을 때입니다(클러스터의 어떤 노드도 건강하지 않음). 이 경우 노드 컨트롤러는 컨트롤 플레인과 노드 사이의 연결에 문제가 있다고 가정하고 어떤 축출도 수행하지 않습니다. (정전이 있었고 일부 노드가 다시 나타난다면 노드 컨트롤러는 남은 건강하지 않거나 도달할 수 없는 노드에서 파드를 축출합니다).

노드 컨트롤러는 NoExecute 테인트가 있는 노드에서 실행되는 파드를 축출하는 것도 책임지며, 그 파드가 그 테인트를 허용하지 않는 한 그렇습니다. 노드 컨트롤러는 또한 노드 도달 불가 또는 준비 안 됨 같은 노드 문제에 해당하는 테인트를 추가합니다. 이는 스케줄러가 건강하지 않은 노드에 파드를 배치하지 않도록 합니다.

리소스 용량 추적 {#node-capacity}

Node 객체는 노드의 리소스 용량에 대한 정보를 추적합니다: 예를 들어 사용 가능한 메모리 양과 CPU 수. 자체 등록하는 노드는 등록 중에 용량을 보고합니다. 수동으로 노드를 추가한다면, 추가할 때 노드의 용량 정보를 설정해야 합니다.

쿠버네티스 스케줄러는 노드의 모든 파드에 충분한 리소스가 있도록 보장합니다. 스케줄러는 노드의 컨테이너 요청 합계가 노드의 용량보다 크지 않은지 확인합니다. 그 요청 합계는 kubelet이 관리하는 모든 컨테이너를 포함하지만, 컨테이너 런타임이 직접 시작한 컨테이너와 kubelet의 제어 밖에서 실행되는 모든 프로세스는 제외합니다.

비파드 프로세스를 위해 리소스를 명시적으로 예약하려면 시스템 데몬용 리소스 예약을 참조하세요.

노드 토폴로지

TopologyManager 기능 게이트를 활성화했다면 kubelet은 리소스 할당 결정을 내릴 때 토폴로지 힌트를 사용할 수 있습니다. 자세한 내용은 노드의 토폴로지 관리 정책 제어를 참조하세요.

더 알아보기 (Learn more)

다음에 대해 더 알아보세요: