7.5.3 [실습] 데몬셋을 이용한 노드 정보 표시 웹서버 배포

데몬셋의 이론적인 동작 방식을 이해했으니, 이제 직접 데몬셋을 만들어보고 그 결과를 눈으로 확인해 볼 시간입니다. 이번 실습에서는 매우 간단한 웹서버를 데몬셋을 이용하여 클러스터의 모든 (또는 선택된) 노드에 배포해 보겠습니다. 이 웹서버는 자신이 실행되고 있는 노드의 호스트 이름과 같은 간단한 정보를 표시하도록 하여, 각 노드에 데몬셋 파드가 독립적으로 실행되고 있음을 쉽게 확인할 수 있도록 할 것입니다.

본 실습을 위해서는 이전 실습들과 마찬가지로 쿠버네티스 클러스터와 kubectl CLI가 준비되어 있어야 합니다. Minikube, kind, Docker Desktop의 쿠버네티스 기능 또는 클라우드 제공업체의 관리형 서비스를 사용하시면 됩니다. 특히, 이번 실습에서는 데몬셋이 각 노드에 파드를 배포하는 것을 확인해야 하므로, 가능하다면 여러 개의 워커 노드를 가진 클러스터 환경에서 테스트하는 것이 더 명확한 결과를 보여줄 수 있습니다. (Minikube와 같은 단일 노드 클러스터에서도 실습은 가능하지만, 데몬셋의 “모든 노드에 배포”라는 특징을 체감하기에는 다소 제한적일 수 있습니다.)

자, 그럼 모든 노드의 충실한 일꾼, 데몬셋을 직접 지휘하여 각 노드에 파견해 볼까요?

7.5.3.1 데몬셋 YAML 파일 작성

가장 먼저 할 일은 데몬셋을 정의하는 YAML 파일을 작성하는 것입니다. 이 YAML 파일에는 데몬셋의 이름, 실행할 파드의 템플릿(어떤 컨테이너 이미지를 사용할지, 어떤 포트를 노출할지 등), 그리고 필요한 경우 노드 셀렉터나 톨러레이션 등이 포함됩니다. 이번 실습에서는 간단하게 모든 적격한 노드에 배포되는 데몬셋을 만들겠습니다.

파드 내에서 실행될 웹서버는 Nginx를 사용하고, 컨테이너 시작 시 간단한 스크립트를 실행하여 현재 노드의 호스트 이름을 index.html 파일에 기록하도록 구성할 것입니다. 이렇게 하면 각 노드의 데몬셋 파드에 접속했을 때 서로 다른 내용을 보여주어, 각 파드가 독립적으로 실행되고 있음을 확인할 수 있습니다.

아래 내용을 my-node-info-daemonset.yaml 이라는 이름의 파일로 저장해 주세요.

클립보드에 복사

이 YAML 파일의 주요 부분을 자세히 살펴보겠습니다.

  • kind: DaemonSet: 이 명세가 데몬셋을 위한 것임을 명시합니다.
  • spec.selector.matchLabels와 spec.template.metadata.labels: app: node-info로 동일하게 설정하여 데몬셋이 관리할 파드를 정확히 식별하도록 합니다.
  • spec.template.spec.containers[0].ports:
    • containerPort: 80: Nginx 컨테이너는 80번 포트에서 리스닝합니다.
    • hostPort: 8080: 이 부분이 중요합니다. hostPort를 사용하면 이 데몬셋 파드가 실행되는 각 노드의 8080번 포트가 해당 파드 컨테이너의 80번 포트로 직접 매핑됩니다. 이를 통해 우리는 외부에서 <각 노드의 IP 주소>:8080 형태로 각 노드에 배포된 데몬셋 파드에 개별적으로 접근할 수 있게 됩니다. (실제 프로덕션 환경에서는 hostPort 사용 시 포트 충돌의 위험이 있으므로, NodePort 타입의 서비스나 Ingress를 통해 노출하는 것이 더 일반적입니다. 하지만 이번 실습에서는 데몬셋의 동작을 간단히 확인하기 위해 hostPort를 사용합니다.)
  • spec.template.spec.containers[0].env: Downward API를 사용하여 파드가 실행 중인 노드의 이름(spec.nodeName)과 파드의 IP 주소(status.podIP)를 환경 변수 MY_NODE_NAME과 MY_POD_IP로 주입받습니다. Downward API는 파드가 자기 자신이나 자신이 실행되는 환경에 대한 정보를 컨테이너 내부로 가져올 수 있게 해주는 유용한 기능입니다.
  • spec.template.spec.containers[0].command와 args: 컨테이너가 시작될 때, 주입받은 환경 변수 MY_NODE_NAME과 MY_POD_IP를 사용하여 “Hello from Node: [노드이름]” 과 “Pod IP: [파드IP]” 라는 내용을 포함하는 HTML을 생성하여 Nginx의 기본 웹 페이지(index.html)에 덮어쓰고, 그 후에 Nginx를 실행합니다.

이제 터미널에서 이 YAML 파일이 저장된 디렉토리로 이동한 후, 다음 명령어를 실행하여 데몬셋을 생성합니다.

클립보드에 복사

“daemonset.apps/node-info-ds created” 와 같은 메시지가 출력될 것입니다. 데몬셋이 잘 생성되었는지 확인해 보겠습니다.

클립보드에 복사

node-info-ds라는 이름의 데몬셋이 보이고, DESIRED, CURRENT, READY, UP-TO-DATE, AVAILABLE 등의 상태 정보가 표시될 것입니다. DESIRED 값은 데몬셋 파드가 실행되어야 하는 적격한 노드의 수를 나타냅니다. CURRENT는 현재 실제로 실행 중인 파드의 수, READY는 그중 요청을 받을 준비가 된 파드의 수 등을 의미합니다. 단일 노드 클러스터라면 이 값들이 대부분 1로 표시될 것이고, 여러 노드를 가진 클러스터라면 노드 수만큼 표시될 것입니다. (마스터 노드에는 기본적으로 스케줄링되지 않으므로, 워커 노드 수만큼 표시될 가능성이 높습니다. 만약 마스터 노드에도 배포되도록 톨러레이션을 추가했다면 마스터 노드 수도 포함됩니다.)

7.5.3.2 각 노드에 파드가 배포되었는지 확인

데몬셋을 성공적으로 생성했으니, 이제 실제로 각 (적격한) 노드에 데몬셋 파드가 하나씩 배포되었는지 확인해 볼 차례입니다.

먼저, 데몬셋에 의해 생성된 파드들의 목록을 확인합니다.

클립보드에 복사
  • app=node-info 옵션은 app: node-info 레이블을 가진 파드들만 필터링하여 보여줍니다. -o wide 옵션은 각 파드가 어느 노드(NODE 컬럼)에 스케줄링되었는지와 파드의 IP 주소 등 더 자세한 정보를 보여줍니다.

출력 결과를 보면, node-info-ds-xxxxx (앞부분은 데몬셋 이름, 뒷부분은 랜덤 문자열) 형태의 이름을 가진 파드들이 보일 것입니다. 중요한 점은, 각 파드가 서로 다른 노드에 배포되어 있어야 한다는 것입니다 (단일 노드 클러스터가 아니라면). 만약 3개의 워커 노드가 있는 클러스터라면, 3개의 node-info-ds-xxxxx 파드가 각각 다른 워커 노드 이름을 NODE 컬럼에 표시하며 Running 상태로 나타나야 합니다.

이제 각 노드에 배포된 웹서버에 직접 접근하여, 각 파드가 해당 노드의 정보를 올바르게 표시하는지 확인해 보겠습니다. 앞서 YAML 파일에서 hostPort: 8080으로 설정했으므로, 우리는 <각 노드의 IP 주소 또는 외부에서 접근 가능한 호스트명>:8080으로 접속하면 됩니다.

먼저, 클러스터 노드들의 IP 주소를 알아야 합니다. 다음 명령어로 노드 목록과 IP 정보를 확인할 수 있습니다.

클립보드에 복사

INTERNAL-IP 또는 EXTERNAL-IP (만약 외부 IP가 있다면) 컬럼에서 각 워커 노드의 IP 주소를 확인합니다. (Minikube의 경우 minikube ip 명령으로 IP를 확인할 수 있고, Docker Desktop은 보통 localhost로 접근 가능합니다. 클라우드 환경에서는 각 노드의 외부 IP를 확인해야 할 수 있습니다.)

확인된 각 워커 노드의 IP 주소에 대해, 웹 브라우저나 curl 명령어를 사용하여 http://<노드 IP>:8080으로 접속해 보세요.

예를 들어, 첫 번째 워커 노드의 IP가 192.168.1.101 이라면:

클립보드에 복사

응답으로 “<h1>Hello from Node: [node-1-hostname]</h1><h2>Pod IP: [pod-ip-on-node-1]</h2>” 와 같이 해당 노드의 실제 호스트 이름과 그 노드에서 실행 중인 데몬셋 파드의 IP가 포함된 HTML을 볼 수 있어야 합니다.

두 번째 워커 노드의 IP가 192.168.1.102 이라면:

클립보드에 복사

응답으로 “<h1>Hello from Node: [node-2-hostname]</h1><h2>Pod IP: [pod-ip-on-node-2]</h2>” 와 같이 다른 노드의 정보가 표시되어야 합니다.

이처럼 각기 다른 노드의 8080번 포트로 접속했을 때, 해당 노드의 이름이 포함된 서로 다른 내용이 보인다면, 데몬셋이 각 노드에 독립적인 파드를 성공적으로 배포하고 각 파드가 해당 노드의 정보를 올바르게 참조하고 있음을 확인한 것입니다.

만약 노드를 추가하거나 삭제할 수 있는 환경이라면 (예: 클라우드 환경 또는 로컬에서 kind 등으로 노드 조작이 가능한 경우), 새로운 워커 노드를 클러스터에 추가했을 때 잠시 후 kubectl get pods -l app=node-info -o wide 명령으로 확인하면 새로운 노드에도 node-info-ds 파드가 자동으로 생성되어 실행되는 것을 볼 수 있습니다. 반대로, 워커 노드를 클러스터에서 제거하면 해당 노드에서 실행되던 데몬셋 파드도 자동으로 사라지는 것을 확인할 수 있습니다. (단, 테스트 환경에서 노드를 직접 조작하는 것은 주의가 필요합니다.)

이 실습을 통해 우리는 데몬셋 YAML 파일을 작성하여 각 노드에 파드를 배포하고, hostPort와 Downward API를 활용하여 각 파드가 자신이 실행되는 노드의 정보를 표시하도록 구성하는 방법을 배웠습니다. 그리고 실제로 각 노드에 파드가 하나씩 배포되었으며, 각 파드에 개별적으로 접근하여 독립적인 동작을 확인했습니다. 데몬셋은 이처럼 클러스터의 모든 노드에 걸쳐 일관된 작업을 수행해야 할 때 매우 강력하고 편리한 도구임을 알 수 있습니다.