-
[Kubernetes] Service Cluster IP란? Kubernetes Network? Kubernetes iptables?인프라/Kubernetes 2020. 11. 19. 18:57
Service의 Cluster IP란 무엇이냐! Virtual IP 라고 하는데 무슨 의미인고 하니
실제로 존재하지 않지만 kube-proxy에 의해 관리되어지는 IP인 것이다. Components에 대해 이야기할 떄 등장한 녀석인데 네트워크 관리를 담당한다는게 무슨뜻인지 그 당시에는 몰랐었다.
그러나 알고보니 kube-proxy가 iptables에 규칙들을 생성하고 삭제하는 역할을 하면서 클러스터 내부의 통신, 외부와 내부의 통신을 가능하게끔하는 역할을 하는것이었다.
생성된 Service에 대해 알아보자.
kubectl get services -o wide
여기서 kubernetes-bootcamp는 내가 만든 Service이다.
"kubernetes-bootcamp" app은 pod에 8080번으로 접속하면 "Hello~~~%$#%"를 출력해주는 node.js application이다.
kubectl describe services/kubernetes-bootcamp
Service Type으로 NodePort로 만들었으며 이는 {공인IP}:31110 으로 접속하면 Cluster IP 10.111.14.255가 받아서 Pod속 Endpoints 172.16.0.3:8080 으로 전송한다는 뜻이다.
지금부터는 누군가의 pc에서 192.168.5.1(쿠버네티스 클러스터환경인 pc의 공인IP):31110 으로 패킷을 보냈을 경우 패킷이 변화하는 과정을 알아볼 것이다.
현재패킷 (어디서 들어왔는지는 상관없다 목적지가 중요하다) | sourceIP: ? | sourcePort: ? | destinationIP:192.168.5.1 | destinationPort:31110 |
ipchain이 어떤형식으로 실행되는지 (webterror.net/?p=1622)를 참조하도록 하자.
첫번째로 Service가 생성되면 kube-proxy에 의해 iptables에 규칙이 추가되는듯 하다.
가장처음 PREROUTING Chain을 거친다.
iptables -t nat -S PREROUTING
cali-PREROUTING은 건너뛰고 KUBE-SERVICES로 점프
iptables -t nat -S KUBE-SERVICES
현재패킷 | sourceIP: ? | sourcePort: ? | destinationIP:192.168.5.1 | destinationPort:31110 |state:NEW |
-d 목적지에대한 IP에 맞는게 없으니 맨 마지막 정책 --dst-type LOCAL이 실행된다. LOCAL의 뜻은 현재 host pc가 가지고 있는 network interface가 목적지인지를 검사하는것인데 192.168.5.1이 ens33에 할당되어 있으니 만족한다!
KUBE-NODEPORTS로 점프
iptables -t nat -S KUBE-NODEPORTS
--dport 31110 목적지 포트번호가 일치한다! KUBE-MARK-MASQ 으로 점프
현재패킷 | sourceIP: ? | sourcePort: ? | destinationIP:192.168.5.1 | destinationPort:31110 | mark:0x4000 |
다시 돌아와서 다음 정책도 만족하니 KUBE-SVC-2TYZFXBKM236ELT2 로 점프
KUBE-SEP-EOM7RMYQTXAH45UH 까지 바로 넘어와서 첫번째 -s 는 만족하지 않으니 패스하고 두번째 정책을 보면 DNAT --to-destination 172.16.0.3:8080 으로 목적지를 변경한다!
현재패킷 | sourceIP: ? | sourcePort: ? | destinationIP:172.16.0.3 | destinationPort:8080 | mark:0x4000 |
DNAT으로 인해 PREROUTING -> FORWARD로 넘어간다!
iptables -t filter -S KUBE-FORWARD
KUBE-FORWARD 점프
상태가 INVALID가 아니니 넘어가고, mark가 0x4000 으로 되어있으니 ACCEPT 되어서 FORWARD Chain은 통과된다.
FORWARD -> POSTROUTING 으로!
마크가 0x4000/0x4000 이니 건너뛰고 -j MARK --set-xmark 0x4000/0x0로 인하여 0이 되면서 mark가 사라진다?..
--set-xmark 에 대해 좀 알아봐야겠다...
현재패킷 | sourceIP: ? | sourcePort: ? | destinationIP:172.16.0.3 | destinationPort:8080 |
MASQUERADE 로 인하여 패킷은 나가게 된다!
+ 2020-11-20 추가
iptables -t nat -I PREROUTING 1 -d 192.168.5.1/32 -p tcp -m tcp --dport 31110 -j LOG --log-prefix "192.168.5.1 log" iptables -t nat -I KUBE-NODEPORTS 2 -j LOG --log-prefix "KUBE-NODEPORTS " iptables -t nat -I KUBE-NODEPORTS 1 -p tcp --dport 31110 -j LOG --log-prefix "KUBE-NODEPORTS bf " iptables -t nat -I KUBE-NODEPORTS 3 -p tcp --dport 31110 -j LOG --log-prefix "KUBE-NODEPORTS af " iptables -t nat -I POSTROUTING -j LOG --log-prefix "POSTROUTING bf " iptables -t nat -I KUBE-POSTROUTING 2 -j LOG --log-prefix "MARK bf " iptables -t nat -I KUBE-POSTROUTING 4 -j LOG --log-prefix "MASQUERADE bf "
Nov 20 15:20:51 kube-master kernel: 192.168.5.1 logIN=ens33 OUT= MAC=00:0c:29:1d:57:33:00:0c:29:e4:bc:6e:08:00
SRC=192.168.5.128 DST=192.168.5.1 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=27773 DF PROTO=TCP SPT=52930 DPT=31110 WINDOW=29200 RES=0x00 SYN URGP=0
Nov 20 15:20:51 kube-master kernel: FORWARD before IN=ens33 OUT=tunl0 MAC=00:0c:29:1d:57:33:00:0c:29:e4:bc:6e:08:00
SRC=192.168.5.128 DST=172.16.0.4 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=27773 DF PROTO=TCP SPT=52930 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0 MARK=0x4000
Nov 20 15:20:51 kube-master kernel: POSTROUTING bf IN= OUT=tunl0
SRC=192.168.5.128 DST=172.16.0.4 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=27773 DF PROTO=TCP SPT=52930 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0 MARK=0x4000
Nov 20 15:20:51 kube-master kernel: MARK bf IN= OUT=tunl0
SRC=192.168.5.128 DST=172.16.0.4 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=27773 DF PROTO=TCP SPT=52930 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0 MARK=0x4000
Nov 20 15:20:51 kube-master kernel: MASQUERADE bf IN= OUT=tunl0
SRC=192.168.5.128 DST=172.16.0.4 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=27773 DF PROTO=TCP SPT=52930 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0
실제 iptables에 LOG 모듈을 추가하여 로그를 찍어보니
DNAT으로 인한 패킷의 목적지가 변한것을 확인할 수 있었다.
마지막에 MASQUERADE 로그를 보면 최종적으로 tunl0 network interface를 통하여 나가라고 되어있다.
그래서 최종적으로 나가게 되는 패킷의 SRC=172.16.0.128 으로 나가게될 것으로 예상된다. 그리고 next hop 으로 Slave Node로 향할 것이다.
iptables -t nat -I PREROUTING -p tcp -j LOG --log-prefix "PREROUTING bf " iptables -I INPUT -s 172.16.0.128 -j LOG --log-prefix "INPUT 1 "
Nov 20 16:00:46 kube-node1 kernel: PREROUTING bf IN=tunl0 OUT= MAC= SRC=172.16.0.128 DST=172.16.0.4 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=59862 DF PROTO=TCP SPT=44589 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0
Nov 20 16:00:46 kube-node1 kernel: INPUT 1 IN=tunl0 OUT=calie1760be6016 MAC= SRC=172.16.0.128 DST=172.16.0.4 LEN=60 TOS=0x00 PREC=0x00 TTL=62 ID=59862 DF PROTO=TCP SPT=44589 DPT=8080 WINDOW=29200 RES=0x00 SYN URGP=0 MARK=0x10000Slave Node의 iptables Log를 보면 tunl0 interface로 패킷을 받아서 calie1760be6016 이라는 생소한 인터페이스 로 내보낸다고 되어있다.
cali~ 로시작하는 인터페이스는 우리가 CNI(Container Network Interface) plugin으로 calico를 설치했을 때 생성되는 네트워크 인터페이스이다. 그래서 이 인터페이스로 패킷이 가게되면 calico가 따로 관리하는 테이블을 보고 목적지가 172.16.0.4:8080 이므로 이에 맞는 container의 네트워크 인터페이스로 전송해줄 듯 하다.
그런데 아직까지 Cluster-IP에 대해서 나오지 않았다 ... 아무리 찾아봐도 공인IP -> Cluster IP -> Pod IP 로의 변환과정을 제대로 찾질 못하겠다... 현재 그냥 보기로는 공인IP -> Pod IP로 바로 바뀌어버리는데 이게 NodePort Type으로 인한 효과인지 그리고 1개의 replica를 사용해서 그런지 모르겠다. 일단 2개 이상의 replica를 생성했을 때 다시 봐야겠다.
아래 블로그를 참조하여 공부했다.
'인프라 > Kubernetes' 카테고리의 다른 글
[Kubernetes] 쿠버네티스 설치하기 (7) - Performing a Rolling Update (0) 2020.11.23 [Kubernetes] 쿠버네티스 설치하기 (6) - Running Multiple Instances of Your App (0) 2020.11.20 [Kubernetes] 쿠버네티스 설치하기 (5) - Using a Service to Expose Your App (0) 2020.11.18 [Kubernetes] 쿠버네티스 설치하기 (4) - Deploy an app (0) 2020.11.16 [Kubernetes] 쿠버네티스 설치하기 (3) - Creating a cluster with kubeadm (0) 2020.11.13