반응형

아래 Script는 Kuberentes Node의 IP Address를 얻어와서, 이 IP Address로 Node에 SSH 접속하여 'shutdown' 명령을 수행하는 예제이다.

 

#!/bin/bash

for ip in $(oc get nodes  -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}')
do
   echo "reboot node $ip"
   ssh -o StrictHostKeyChecking=no core@$ip sudo shutdown -r -t 3
done
반응형

Kubernetes Cluster에서 MetalLB를 사용하다 보면, IP 트래픽을 처리하는 방식이 궁금할 때가 많다.

특히 Baremetal 환경에서 서비스를 운영한 개발자, 운영자라면 특히나 MetalLB의 동작 방식이나 원리가 이해가 안 되고, 감(느낌)도 안 잡힌다.

어디에 MetalLB 설계서 같은 문서가 있으면 좋겠지만, 그런게 없으니까 일단 궁금한 점이 떠오를 때마다 테스트하고 기록하는 수 밖에 ~~~

 

 

Q)  Kubernetes Service 리소스의 External IP 항목에 보여지는 IP Address는 실제로 어디에 있는가?

실제로 LoadBalancer Type으로 서비스 리소스를 설정하고, External IP Address를 할당받아서 테스트를 해보니까, 

External IP Address는 Master Node 또는 Worker Node에 있는 특정한 Network Port(예:  eth2)의 Mac Address를 공유해서 쓰고 있었다.

물론 Network Port(예: eth2)는 External IP Address와 같은 Network 대역이라서 라우팅이 가능한 Port가 된다.

(아마 MetalLB Operator가 동일한 Network 대역을 찾아서 할당해주는 것 같다)

참고: Layer 2 Mode로 MetalLB를 구성하고 테스트한 결과임
그렇다면, Master Node와 Worker Node가 10개가 있을 때, 어떤 Master Node와 Worker Node에 External IP Address가 있게 되는걸까?

 

이 External IP Address와 관련있는 Pod의 위치(Pod가 구동된 Master Node 또는 Worker Node)와는 전혀 관련이 없다.

MetalLB는 External IP Address를 Worker Node의 특정 Ethernet Port에 할당할 때, 최대한 분산되도록 스케쥴링한다.

만약 MetalLB가 External IP를 worker-a에 이미 할당할 것이 있다면, 그 다음 External IP를 worker-a가 아닌 다른 Node에 위치하도록 구성한다. 즉, 이 External IP가 한쪽 Kubernetes Node에 몰려서 외부 트래픽이 한개의 Node에 집중되는 것을 막으려는 노력을 하는 것이다.

 

반응형

Kubernetes의 Pod Scheduling에 관한 공부를 하다보면,

  • Node Label을 이용한 NodeSelector, Node Affinity
  • Node Taint, Tolerlation

가 꼭 등장한다.

위 2가지를 따로 따로 공부하면, 그렇구나 라고 이해가 되다가 

이 2가지를 같이 놓고 생각해보면, 비슷한 기능을 하는 것 같은데 왜 이렇게 2가지 모두 있는거지 라는 질문이 자연스레 떠오른다.

 

아래 블로그가 이런 질문에 대한 답을 잘 하고 있다.

 

https://fisache.tistory.com/19

 

CKA 준비 (7) - Scheduling 2 (Node Selector, Node Affinity)

본 포스팅은 Udemy Certificated Kubernetes Administrator 강좌를 공부한 내용입니다. Certified Kubernetes Administrator (CKA) Practice Exam Tests Prepare for the Certified Kubernetes Administrators C..

fisache.tistory.com

 

 

Node Taint 및 Toleration에 대해 기초부터 알고 싶다면, 아래의 Kubernetes Web Docs를 보면 좋다.

 

https://kubernetes.io/ko/docs/concepts/scheduling-eviction/taint-and-toleration/

 

테인트(Taints)와 톨러레이션(Tolerations)

노드 어피니티는 노드 셋을 (기본 설정 또는 어려운 요구 사항으로) 끌어들이는 파드의 속성이다. 테인트 는 그 반대로, 노드가 파드 셋을 제외할 수 있다. 톨러레이션 은 파드에 적용되며, 파드

kubernetes.io

 

# TODO

위 Web Docs에 TolerationSeconds에 관한 설명이 나오는데, 

내 생각에는 Node 장애가 발생했을 때, 빠르게 Pod가 장애가 발생한 Node에서 종료 처리되고 다른 Node로 스케쥴링되게 하려면, 300초로 설정된 값을 1초로 줄이면 되지 않을까하는 상상을 해본다. 

시간 여유가 있을 때, 한번 1초로 변경하고 Node를 다운시켜서 테스트해봐야겠다.

 

참고:
쿠버네티스는 사용자나 컨트롤러에서 명시적으로 설정하지 않았다면, 자동으로 node.kubernetes.io/not-ready 와 node.kubernetes.io/unreachable 에 대해 tolerationSeconds=300 으로 톨러레이션을 추가한다.
자동으로 추가된 이 톨러레이션은 이러한 문제 중 하나가 감지된 후 5분 동안 파드가 노드에 바인딩된 상태를 유지함을 의미한다.

 

반응형

Kubernetes cluster 운영 환경에서 Pod간 주고 받은 IP packet을 tcpdump하는 방법을 알아보겠다.

 

 

방식 A:  Container 내부에 tcpdump 프로그램을 설치하고, Container 내부에서 직접 tcpdump 명령을 수행

$  kubectl exec  -n my-namespace  my-pod  -c my-container  -it -- bash
(In-Container) $  apt install -y tcpdump 
... 중간 생략 ...

##
## 참고: Kubernetes Pod 내부의 기본 NIC은 eth0이다.
##      만약, Multus CNI를 사용해서 Multi-NIC을 사용하는 경우라면,
##      eth0 이외에 net1, net2 같은 이름으로 NIC이 있을 것이다.
##      따라서, 내가 운영하는 CNI가 1개인지 또는 어떤 종류의 CNI이 인지에 따라
##      NIC의 이름이 다를 수 있으니까, ifconfig 명령 또는 `ip a` 같은 명령으로
##      NIC 이름을 확인하고 tcpdump 명령을 수행해야 한다.
##
(In-Container) $  tcpdump -i eth0 -w  my-capture.pcap
... 중간 생략 ...

위와 같이 생성한 pcap 파일은 Pod 외부에서 볼 수 없기 때문에

   1) Pod 내부에서 scp 명령으로 외부로 옮겨주던지 

   2) 또는 NFS, Ceph storage 같은 PV를 이용하여 저장하는 것을 권장한다.

 

 

 

방식 B: Worker node에서 특정 Pod의 namespace를 이용하여 tcpdump 명령을 수행

예제를 이용하여 설명해보겠다.

'productpage' Pod가 주고 받은 IP packet을 tcpdump하려는 상황을 가정해보자.

우선 'productpage' Pod가 어느 worker node에 있는지 확인한다.

$  kubectl get pod -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP           NODE  
... 중간 생략 ...
productpage-v1-6b746f74dc-xfjdz   2/2     Running   0          2d17h   10.244.2.4   worker-1
... 중간 생략 ...

 

'productpage' pod가 worker-1 node에 있으니까, worker-1에 ssh 접속하여 아래의 스크립트를 수행한다.

 

##
## Filename : run-tcpdump.sh
##

#!/usr/bin/bash

container_id=$(docker container ls | grep k8s_istio-proxy_productpage | awk '{ print $1 }')
echo "Container  ID: $container_id"

container_pid=$(docker inspect -f '{{.State.Pid}}' $container_id)
echo "Container PID: $container_pid"

nsenter -t $container_pid  -n /bin/bash -xec 'tcpdump -i any -w productpage-envoy-any.pcap'


## NOTE: After running this script to capture the packet,
##       Use the packet filter as 'tls or http' with your Wireshark program !

위 `run-tcpdump.sh` 스크립트를 수행하고 나서 만들어진 pcap 파일을 Wireshark으로 열어본다.

 

 


그런데, 위 "방식 A, 방식 B"는 Kubernetes를 사용했을 때나 가능한 얘기이고,
OCP(Openshift Container Platform)을 사용하는 경우라면 위 방식으로 container 내부의 network packet을 dump할 수 없다 !!!
왜? OCP, OKD Cluster의  Worker Node에는 'docker' command가 없다.
그러면 어떻게 하는가?
아래와 같이 "방식 C"를 따라해야 한다.

 

방식 C:  OCP의 Node에서 특정 Pod의 namespace를 이용하여 tcpdump 명령을 수행

예제를 이용하여 설명해보겠다.

(worker2 node에 Pod가 구동되어 있다고 가정하고 설명한다)

 

##
## Working Location:  Bastion Node, or PC (MacBook)
##

$  oc debug node/worker1.andrew.space

Starting pod/worker1.andrew.space-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.10.11.12
If you don't see a command prompt, try pressing enter.

sh-4.4# chroot /host

sh-4.4# container_id=$(crictl ps | grep my-example-app | awk '{ print $1 }')

sh-4.4# echo $container_id
378f096238fdd

sh-4.4# container_pid=$(crictl inspect $container_id | jq '.info.pid')

sh-4.4# echo $container_pid
3458673

sh-4.4# nsenter -t $container_pid  -n /bin/bash -xec 'tcpdump -i eth0'

... TCPDUMP 출력 결과 생략 ...

 

 


만약, OCP 또는 OKD Cluster를 구축할 때, OS를 CoreOS를 사용한 경우라면 
위와 같이 `nsenter -t .... 'tcpdump -i eth0'` 명령을 사용할 수 없다.
왜냐고?
CoreOS는 TCPDUMP 명령을 가지고 있지 않기 때문이다. ㅠㅠ
단, 임시로 CoreOS에 tcpdump command를 설치하고 위 절차를 따라하는 꼼수가 있기는 하다.

 

 

+ Recent posts