Kubernetes 네트워킹을 검사하는 방법
소개
Kubernetes는 서버 노드 클러스터에서 컨테이너화된 애플리케이션을 관리할 수 있는 컨테이너 오케스트레이션 시스템입니다. 클러스터의 모든 컨테이너 간에 네트워크 연결을 유지하려면 몇 가지 고급 네트워킹 기술이 필요합니다. 이 기사에서는 이 네트워킹 설정을 검사하기 위한 몇 가지 도구와 기술을 간략하게 다룹니다.
이러한 도구는 연결 문제를 디버깅하거나, 네트워크 처리량 문제를 조사하거나, 작동 방식을 알아보기 위해 Kubernetes를 탐색하는 경우에 유용할 수 있습니다.
일반적인 Kubernetes에 대해 자세히 알아보려면 Kubernetes Networking Under the Hood 가이드를 참조하세요.
시작하기
이 튜토리얼에서는 kubectl
이 로컬에 설치되고 클러스터에 연결하도록 구성된 Kubernetes 클러스터가 있다고 가정합니다.
다음 섹션에는 Kubernetes 노드에서 실행하기 위한 많은 명령이 포함되어 있습니다. 다음과 같이 표시됩니다.
- echo 'this is a node command'
로컬 시스템에서 실행해야 하는 명령은 다음과 같이 표시됩니다.
- echo 'this is a local command'
참고: 이 자습서에 있는 대부분의 명령은 루트 사용자로 실행해야 합니다. 대신 Kubernetes 노드에서 sudo 사용 사용자를 사용하는 경우 sudo
를 추가하여 필요할 때 명령을 실행하십시오.
포드의 클러스터 IP 찾기
Kubernetes 포드의 클러스터 IP 주소를 찾으려면 로컬 시스템에서 -o wide
옵션과 함께 kubectl get pod
명령을 사용합니다. 이 옵션은 포드가 상주하는 노드 및 포드의 클러스터 IP를 포함하여 추가 정보를 나열합니다.
- kubectl get pod -o wide
OutputNAME READY STATUS RESTARTS AGE IP NODE
hello-world-5b446dd74b-7c7pk 1/1 Running 0 22m 10.244.18.4 node-one
hello-world-5b446dd74b-pxtzt 1/1 Running 0 22m 10.244.3.4 node-two
IP 열에는 각 포드의 내부 클러스터 IP 주소가 포함됩니다.
찾고 있는 팟(Pod)이 표시되지 않으면 올바른 네임스페이스에 있는지 확인하십시오. --all-namespaces
플래그를 추가하여 모든 네임스페이스의 모든 포드를 나열할 수 있습니다.
서비스의 IP 찾기
kubectl
을 사용하여 서비스 IP를 찾을 수도 있습니다. 이 경우 모든 네임스페이스의 모든 서비스를 나열합니다.
- kubectl get service --all-namespaces
OutputNAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.32.0.1 <none> 443/TCP 6d
kube-system csi-attacher-doplugin ClusterIP 10.32.159.128 <none> 12345/TCP 6d
kube-system csi-provisioner-doplugin ClusterIP 10.32.61.61 <none> 12345/TCP 6d
kube-system kube-dns ClusterIP 10.32.0.10 <none> 53/UDP,53/TCP 6d
kube-system kubernetes-dashboard ClusterIP 10.32.226.209 <none> 443/TCP 6d
서비스 IP는 CLUSTER-IP 열에서 찾을 수 있습니다.
포드 네트워크 네임스페이스 찾기 및 입력
각 Kubernetes 포드에는 자체 네트워크 네임스페이스가 할당됩니다. 네트워크 네임스페이스(또는 netns)는 네트워크 장치 간에 격리를 제공하는 Linux 네트워킹 기본 요소입니다.
포드의 netns 내에서 명령을 실행하여 DNS 확인 또는 일반 네트워크 연결을 확인하는 것이 유용할 수 있습니다. 이를 위해서는 먼저 포드에 있는 컨테이너 중 하나의 프로세스 ID를 조회해야 합니다. Docker의 경우 일련의 두 가지 명령으로 이를 수행할 수 있습니다. 먼저 노드에서 실행 중인 컨테이너를 나열합니다.
- docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
173ee46a3926 gcr.io/google-samples/node-hello "/bin/sh -c 'node se…" 9 days ago Up 9 days k8s_hello-world_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
11ad51cb72df k8s.gcr.io/pause-amd64:3.1 "/pause" 9 days ago Up 9 days k8s_POD_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
. . .
관심 있는 팟(Pod)에서 컨테이너 ID 또는 컨테이너 이름을 찾으십시오. 위의 출력에는 두 개의 컨테이너가 표시됩니다.
- 첫 번째 컨테이너는
hello-world
포드에서 실행되는hello-world
앱입니다 - 두 번째는
hello-world
포드에서 실행되는 pause 컨테이너입니다. 이 컨테이너는 포드의 네트워크 네임스페이스를 유지하기 위해서만 존재합니다.
두 컨테이너의 프로세스 ID를 가져오려면 컨테이너 ID 또는 이름을 기록하고 다음 docker
명령에서 사용합니다.
- docker inspect --format '{{ .State.Pid }}' container-id-or-name
Output14552
프로세스 ID(또는 PID)가 출력됩니다. 이제 nsenter
프로그램을 사용하여 해당 프로세스의 네트워크 네임스페이스에서 명령을 실행할 수 있습니다.
- nsenter -t your-container-pid -n ip addr
자신의 PID를 사용하고 ip addr
을 포드의 네트워크 네임스페이스 내에서 실행하려는 명령으로 바꾸십시오.
참고: nsenter
를 사용하여 포드의 네임스페이스에서 명령을 실행하는 것의 한 가지 이점은 docker exec
와 같은 것을 사용하는 것과 비교하여 노드에서 사용 가능한 모든 명령에 액세스할 수 있다는 것입니다. , 컨테이너에 설치된 일반적으로 제한된 명령 세트 대신.
포드의 가상 이더넷 인터페이스 찾기
각 포드의 네트워크 네임스페이스는 가상 이더넷 파이프를 통해 노드의 루트 netns와 통신합니다. 노드 측에서 이 파이프는 일반적으로 veth
로 시작하고 veth77f2275
또는 veth01
과 같은 고유 식별자로 끝나는 장치로 나타납니다. 포드 내에서 이 파이프는 eth0
로 나타납니다.
어떤 veth
장치가 특정 포드와 페어링되었는지 상관시키는 것이 유용할 수 있습니다. 이를 위해 노드의 모든 네트워크 장치를 나열한 다음 포드의 네트워크 네임스페이스에 있는 장치를 나열합니다. 그런 다음 두 목록 사이의 장치 번호를 연관시켜 연결할 수 있습니다.
먼저 nsenter
를 사용하여 포드의 네트워크 네임스페이스에서 ip addr
을 실행합니다. 이전 섹션 Pod 네트워크 네임스페이스 찾기 및 입력을 참조하십시오.
- nsenter -t your-container-pid -n ip addr
Output1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether 02:42:0a:f4:03:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.3.4/24 brd 10.244.3.255 scope global eth0
valid_lft forever preferred_lft forever
이 명령은 포드의 인터페이스 목록을 출력합니다. 예제 출력에서 eth0@
뒤에 있는 if11
번호에 유의하십시오. 이는 이 포드의 eth0
이 노드의 11번째 인터페이스에 연결되어 있음을 의미합니다. 이제 노드의 기본 네임스페이스에서 ip addr
을 실행하여 인터페이스를 나열합니다.
- ip addr
Output1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
. . .
7: veth77f2275@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether 26:05:99:58:0d:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::2405:99ff:fe58:db9/64 scope link
valid_lft forever preferred_lft forever
9: vethd36cef3@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether ae:05:21:a2:9a:2b brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::ac05:21ff:fea2:9a2b/64 scope link
valid_lft forever preferred_lft forever
11: veth4f7342d@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether e6:4d:7b:6f:56:4c brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::e44d:7bff:fe6f:564c/64 scope link
valid_lft forever preferred_lft forever
이 예제 출력에서 11번째 인터페이스는 veth4f7342d
입니다. 이것은 우리가 조사하고 있는 포드에 대한 가상 이더넷 파이프입니다.
Conntrack 연결 추적 검사
버전 1.11 이전에 Kubernetes는 iptables NAT 및 conntrack 커널 모듈을 사용하여 연결을 추적했습니다. 현재 추적 중인 모든 연결을 나열하려면 conntrack
명령을 사용하십시오.
- conntrack -L
새로운 연결을 지속적으로 감시하려면 -E
플래그를 사용하십시오.
- conntrack -E
특정 대상 주소에 대한 conntrack 추적 연결을 나열하려면 -d
플래그를 사용하십시오.
- conntrack -L -d 10.32.0.1
노드가 서비스에 안정적으로 연결하는 데 문제가 있는 경우 연결 추적 테이블이 가득 차서 새 연결이 끊어질 수 있습니다. 이 경우 시스템 로그에 다음과 같은 메시지가 표시될 수 있습니다.
Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet.
추적할 최대 연결 수에 대한 sysctl 설정이 있습니다. 다음 명령을 사용하여 현재 값을 나열할 수 있습니다.
- sysctl net.netfilter.nf_conntrack_max
Outputnet.netfilter.nf_conntrack_max = 131072
새 값을 설정하려면 -w
플래그를 사용하십시오.
- sysctl -w net.netfilter.nf_conntrack_max=198000
이 설정을 영구적으로 만들려면 sysctl.conf
파일에 추가하십시오.
. . .
net.ipv4.netfilter.ip_conntrack_max = 198000
Iptables 규칙 검사
버전 1.11 이전에 Kubernetes는 iptables NAT를 사용하여 서비스 IP에 대한 가상 IP 변환 및 로드 밸런싱을 구현했습니다.
노드의 모든 iptables 규칙을 덤프하려면 iptables-save
명령을 사용하십시오.
- iptables-save
출력이 길 수 있으므로 파일(iptables-save > output.txt
) 또는 페이저(iptables-save | less
)로 파이프하여 규칙을 쉽게 검토할 수 있습니다.
Kubernetes Service NAT 규칙만 나열하려면 iptables
명령과 -L
플래그를 사용하여 올바른 체인을 지정합니다.
- iptables -t nat -L KUBE-SERVICES
OutputChain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-TCOU7JCQXEZGVUNU udp -- anywhere 10.32.0.10 /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-SVC-ERIFXISQEP7F7OF4 tcp -- anywhere 10.32.0.10 /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-SVC-XGLOHA7QRQ3V22RZ tcp -- anywhere 10.32.226.209 /* kube-system/kubernetes-dashboard: cluster IP */ tcp dpt:https
. . .
클러스터 DNS 쿼리
클러스터 DNS 확인을 디버깅하는 한 가지 방법은 필요한 모든 도구와 함께 디버그 컨테이너를 배포한 다음 kubectl
을 사용하여 nslookup
을 실행하는 것입니다. 이는 공식 Kubernetes 문서에 설명되어 있습니다.
클러스터 DNS를 쿼리하는 또 다른 방법은 노드에서 dig
및 nsenter
를 사용하는 것입니다. dig
가 설치되지 않은 경우 Debian 기반 Linux 배포판에 apt
를 사용하여 설치할 수 있습니다.
- apt install dnsutils
먼저 kube-dns 서비스의 클러스터 IP를 찾습니다.
- kubectl get service -n kube-system kube-dns
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.32.0.10 <none> 53/UDP,53/TCP 15d
클러스터 IP는 위에 강조 표시되어 있습니다. 다음으로 nsenter
를 사용하여 컨테이너 네임스페이스에서 dig
를 실행합니다. 이에 대한 자세한 내용은 파드 네트워크 네임스페이스 찾기 및 입력 섹션을 참조하십시오.
- nsenter -t 14346 -n dig kubernetes.default.svc.cluster.local @10.32.0.10
이 dig
명령은 서비스의 전체 도메인 이름인 service-name.namespace.svc.cluster.local을 조회하고 클러스터의 IP를 지정합니다. DNS 서비스 IP(@10.32.0.10
).
IPVS 세부 정보 보기
Kubernetes 1.11부터 kube-proxy
는 가상 서비스 IP를 포드 IP로 변환하는 작업을 처리하도록 IPVS를 구성할 수 있습니다. ipvsadm
을 사용하여 IP 변환 테이블을 나열할 수 있습니다.
- ipvsadm -Ln
OutputIP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 100.64.0.1:443 rr
-> 178.128.226.86:443 Masq 1 0 0
TCP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
UDP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
단일 서비스 IP를 표시하려면 -t
옵션을 사용하고 원하는 IP를 지정합니다.
- ipvsadm -Ln -t 100.64.0.10:53
OutputProt LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
결론
이 기사에서는 Kubernetes 클러스터 네트워킹의 세부 정보를 탐색하고 검사하기 위한 몇 가지 명령과 기술을 검토했습니다. Kubernetes에 대한 자세한 내용은 공식 Kubernetes 설명서를 참조하십시오.