Kubernetes/Network Study

Kubernetes Service 분석 - ClusterIP, NodePort

백곰곰 2024. 9. 28. 20:09
728x90
반응형

가시다님의 Kubernetes Advanced Networking Study에 참여하게 되어, 스터디 때 다룬 주제를 정리하려고 합니다.
4주차는 Service(ClusterIP, NodePort)를 주제로 진행되었습니다.

아래 포함된 테스트는 kind로 구성한 클러스터에서 진행되었습니다.

kube-proxy 모드

kube-proxy는 서비스에서 파드로의 연결이 가능하게 해주는 컴포넌트이기 때문에, 어떤 모드를 사용하느냐에 따라 통신 방식이 다릅니다.

userspace

서비스에 대한 요청이 netfilter에 의해 모두 kube-proxy(user space에 속함)로 보내집니다.

패킷에 대해 user space <-> kernel space 로 전환이 필요하기 때문에 비효율적이며, kube-proxy 다운 시 이슈가 발생합니다.

더 이상 지원하지 않는 모드입니다.

iptables(기본값)

서비스에 대한 요청이 커널 영역의 netfilter에 의해서 처리되고, kube-proxy에 전달되지 않습니다. 따라서 user space <-> kernel space 전환이 필요하지 않습니다. 이때, kube-proxy는 iptables을 통해 netfilter 규칙 관리를 담당합니다.

서비스, 파드 추가/삭제 시 다수의 규칙 변경이 필요하므로 서비스 수가 많은 경우 지연이 발생할 수 있습니다.

때문에 규칙을 효율적으로 관리하기 위하여 minSyncPeriod 옵션을 통해 sync 시간을 상향 조정하는 경우도 있습니다. 

또한, 트래픽이 파드에 대해 동일한 확률로 분배되지만, 랜덤이기 때문에 실제로는 정확한 부하 분산이 이루어지지는 않습니다.

IPVS

netfilter에서 동작하는 IPVS(L4 Load Balancer)가 Service Proxy 역할을 수행합니다.

iptables에 비해 성능(처리 성능, 규칙 수 측면)이 좋고, 다양한 부하 분산 알고리즘을 제공합니다.

nftables

iptables를 nftables로 대체하여 사용하는 모드입니다.

netfilter를 사용하기 때문에 커널 영역에서 패킷이 처리되며, iptables보다 커널 내 패킷을 효율적으로 처리합니다.

kernel 5.13 버전 이상인 경우 사용이 가능합니다.

 

이 외에도 최근에는 kube-proxy를 사용하지 않고, eBPF를 활용하는 경우도 있다고 합니다.

참고) https://isovalent.com/blog/post/why-replace-iptables-with-ebpf/ 

 


Endpoint, EndpointSlice

서비스가 생성되면, 서비스에 연결된 파드를 관리하는 endpoint, endpointslice가 자동으로 생성됩니다.

기존 endpoint를 개선하기 위해 endpointslice가 나왔고 두 개의 차이점을 알아보겠습니다.

Endpoint

하나의 서비스의 모든 endpoint가 하나의 endpoint에 속하기 때문에, 규모가 큽니다.

endpoint에 대해 변경 사항(scaling, rollout 등)이 잦은 경우 변경을 위해 수행하는 작업(API Server <-> 노드, 컨트롤플레인 내 트래픽 등)에 부담이 있습니다.

EndpointSlice

하나의 Endpointslice에는 최대 100개의 endpoint(파드)가 속할 수 있습니다. flag를 통해 최대 1000개로 변경할 수 있습니다.

단일 파드를 추가하거나 제거할 때, 변경 사항을 감시하는 클라이언트에게 전달되는 업데이트의 수는 동일하지만, 대규모에서 업데이트 메시지의 크기가 훨씬 작아집니다.

 

의도적으로 비정상 파드를 생성한 뒤 endpoint, endpointslices 변경 사항을 확인해보겠습니다.

[비정상]

$ watch kubectl get pod,svc,ep,endpointslice -owide
Every 2.0s: kubectl get pod,svc,ep,endpointslice -owide
NAME                        READY   STATUS    RESTARTS        AGE     IP          NODE                  NOMINATED NODE   READINESS GATES
pod/mario-94dc76454-x5zsq   0/1     Running   1 (3m17s ago)   3m57s   10.10.0.5   myk8s-control-plane   <none>           <none>

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE     SELECTOR
service/kubernetes   ClusterIP   10.200.1.1     <none>        443/TCP        91m     <none>
service/mario        NodePort    10.200.1.103   <none>        80:30001/TCP   3m57s   app=mario

NAME                   ENDPOINTS         AGE
endpoints/kubernetes   172.18.0.5:6443   91m
endpoints/mario                          3m57s

NAME                                         ADDRESSTYPE   PORTS   ENDPOINTS    AGE
endpointslice.discovery.k8s.io/kubernetes    IPv4          6443    172.18.0.5   91m
endpointslice.discovery.k8s.io/mario-zskpv   IPv4          8080    10.10.0.5    3m57s

$ k get endpoints mario -oyaml | k neat
apiVersion: v1
kind: Endpoints
metadata:
  name: mario
  namespace: default
subsets:
- notReadyAddresses:
  - ip: 10.10.0.5
    nodeName: myk8s-control-plane
    targetRef:
      kind: Pod
      name: mario-94dc76454-x5zsq
      namespace: default
      uid: 92de98d0-8a96-443e-a6d9-17973b82c560
  ports:
  - name: mario-webport
    port: 8080
    protocol: TCP

$ k get endpointslices mario-zskpv -oyaml | k neat
addressType: IPv4
apiVersion: discovery.k8s.io/v1
endpoints:
- addresses:
  - 10.10.0.5
  conditions:
    ready: false
    serving: false
    terminating: false
  nodeName: myk8s-control-plane
  targetRef:
    kind: Pod
    name: mario-94dc76454-x5zsq
    namespace: default
    uid: 92de98d0-8a96-443e-a6d9-17973b82c560
kind: EndpointSlice
metadata:
  labels:
    endpointslice.kubernetes.io/managed-by: endpointslice-controller.k8s.io
    kubernetes.io/service-name: mario
  name: mario-zskpv
  namespace: default
ports:
- name: mario-webport
  port: 8080
  protocol: TCP
  • endpoint : notReadyAddress에 포함
  • endpointslices : condition false(ready, serving)

[정상]

$ watch kubectl get pod,svc,ep,endpointslice -owide
Every 2.0s: kubectl get pod,svc,ep,endpointslice -owide
NAME                        READY   STATUS    RESTARTS        AGE     IP          NODE                  NOMINATED NODE   READINESS GATES
pod/mario-94dc76454-x5zsq   1/1     Running   1 (5m44s ago)   6m24s   10.10.0.5   myk8s-control-plane   <none>           <none>

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE     SELECTOR
service/kubernetes   ClusterIP   10.200.1.1     <none>        443/TCP        93m     <none>
service/mario        NodePort    10.200.1.103   <none>        80:30001/TCP   6m24s   app=mario

NAME                   ENDPOINTS         AGE
endpoints/kubernetes   172.18.0.5:6443   93m
endpoints/mario        10.10.0.5:8080    6m24s

NAME                                         ADDRESSTYPE   PORTS   ENDPOINTS    AGE
endpointslice.discovery.k8s.io/kubernetes    IPv4          6443    172.18.0.5   93m
endpointslice.discovery.k8s.io/mario-zskpv   IPv4          8080    10.10.0.5    6m24s

$ k get endpoints mario -oyaml | k neat
apiVersion: v1
kind: Endpoints
metadata:
  annotations:
    endpoints.kubernetes.io/last-change-trigger-time: "2024-09-28T06:55:50Z"
  name: mario
  namespace: default
subsets:
- addresses:
  - ip: 10.10.0.5
    nodeName: myk8s-control-plane
    targetRef:
      kind: Pod
      name: mario-94dc76454-x5zsq
      namespace: default
      uid: 92de98d0-8a96-443e-a6d9-17973b82c560
  ports:
  - name: mario-webport
    port: 8080
    protocol: TCP
    
 $ k get endpointslices mario-zskpv -oyaml | k neat
addressType: IPv4
apiVersion: discovery.k8s.io/v1
endpoints:
- addresses:
  - 10.10.0.5
  conditions:
    ready: true
    serving: true
    terminating: false
  nodeName: myk8s-control-plane
  targetRef:
    kind: Pod
    name: mario-94dc76454-x5zsq
    namespace: default
    uid: 92de98d0-8a96-443e-a6d9-17973b82c560
kind: EndpointSlice
metadata:
  annotations:
    endpoints.kubernetes.io/last-change-trigger-time: "2024-09-28T06:55:50Z"
  labels:
    endpointslice.kubernetes.io/managed-by: endpointslice-controller.k8s.io
    kubernetes.io/service-name: mario
  name: mario-zskpv
  namespace: default
ports:
- name: mario-webport
  port: 8080
  protocol: TCP
  • endpoint : address에 포함
  • endpointslice : condition true(ready, serving)

참고) https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#motivation


Cluster IP

클러스터 내부에서만 접근이 가능한 서비스입니다.

서비스 생성 시 모든 노드에 iptables 규칙이 설정됩니다.

 

[서비스 및 파드 배포]

cat <<EOT> 3pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: webpod1
  labels:
    app: webpod
spec:
  nodeName: myk8s-worker
  containers:
  - name: container
    image: traefik/whoami
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
  name: webpod2
  labels:
    app: webpod
spec:
  nodeName: myk8s-worker2
  containers:
  - name: container
    image: traefik/whoami
  terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
  name: webpod3
  labels:
    app: webpod
spec:
  nodeName: myk8s-worker3
  containers:
  - name: container
    image: traefik/whoami
  terminationGracePeriodSeconds: 0
EOT

## 통신 테스트용 파드 생성
cat <<EOT> netpod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: net-pod
spec:
  nodeName: myk8s-control-plane
  containers:
  - name: netshoot-pod
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOT

## 서비스 생성
cat <<EOT> svc-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc-clusterip
spec:
  ports:
    - name: svc-webport
      port: 9000        # 서비스 IP 에 접속 시 사용하는 포트 port 를 의미
      targetPort: 80    # 타킷 targetPort 는 서비스를 통해서 목적지 파드로 접속 시 해당 파드로 접속하는 포트를 의미
  selector:
    app: webpod         # 셀렉터 아래 app:webpod 레이블이 설정되어 있는 파드들은 해당 서비스에 연동됨
  type: ClusterIP       # 서비스 타입
EOT

$ kubectl apply -f 3pod.yaml,netpod.yaml,svc-clusterip.yaml

$ k get po -owide
NAME      READY   STATUS    RESTARTS   AGE   IP          NODE                  NOMINATED NODE   READINESS GATES
net-pod   1/1     Running   0          71s   10.10.0.6   myk8s-control-plane   <none>           <none>
webpod1   1/1     Running   0          71s   10.10.3.2   myk8s-worker          <none>           <none>
webpod2   1/1     Running   0          71s   10.10.2.2   myk8s-worker2         <none>           <none>
webpod3   1/1     Running   0          71s   10.10.1.2   myk8s-worker3         <none>           <none>

$ k get svc svc-clusterip
NAME            TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
svc-clusterip   ClusterIP   10.200.1.52   <none>        9000/TCP   77s

 

테스트용 파드(10.10.0.6) -> 서비스(10.200.1.52:9000) -> 다른 노드 내 파드

curl 요청 시 dst ip, port가 변경되는 것을 확인할 수 있습니다.

 

테스트용 파드2 (10.10.3.3) -> 서비스(10.200.1.52:9000) -> 같은/다른 노드 내 파드

myk8s-worker 노드에 테스트용 파드를 하나 더 생성하여, 같은 노드 내 파드에 접근하는 경우도 살펴보겠습니다.

$ k get po -owide
NAME       READY   STATUS    RESTARTS   AGE   IP          NODE                  NOMINATED NODE   READINESS GATES
net-pod    1/1     Running   0          37m   10.10.0.6   myk8s-control-plane   <none>           <none>
net-pod2   1/1     Running   0          67s   10.10.3.3   myk8s-worker          <none>           <none>
webpod1    1/1     Running   0          37m   10.10.3.2   myk8s-worker          <none>           <none>
webpod2    1/1     Running   0          37m   10.10.2.2   myk8s-worker2         <none>           <none>
webpod3    1/1     Running   0          37m   10.10.1.2   myk8s-worker3         <none>           <none>

서비스에 연결된 파드에 랜덤하게 접근하기 때문에 같은 노드에 파드가 있어도 다른 노드의 파드로 요청이 전달될 수 있습니다.

또한, 같은 노드의 파드로 요청이 전달될 때는 노드의 eth0 인터페이스는 사용하지 않습니다.


NodePort

노드의 포트를 통해 클러스터 외부에서도 접근이 가능한 서비스입니다.

서비스 생성 시 모든 노드에 iptables 규칙이 설정되고 Cluster IP도 설정됩니다.

 

[서비스 및 파드 배포]

cat <<EOT> echo-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-echo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: deploy-websrv
  template:
    metadata:
      labels:
        app: deploy-websrv
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: kans-websrv
        image: mendhak/http-https-echo
        ports:
        - containerPort: 8080
EOT

cat <<EOT> svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc-nodeport
spec:
  ports:
    - name: svc-webport
      port: 9000        # 서비스 ClusterIP 에 접속 시 사용하는 포트 port 를 의미
      targetPort: 8080  # 타킷 targetPort 는 서비스를 통해서 목적지 파드로 접속 시 해당 파드로 접속하는 포트를 의미
  selector:
    app: deploy-websrv
  type: NodePort
EOT

$ kubectl apply -f echo-deploy.yaml,svc-nodeport.yaml
$ kubectl get pod -owide;echo; kubectl get svc,ep svc-nodeport
NAME                           READY   STATUS    RESTARTS   AGE   IP          NODE                  NOMINATED NODE   READINESS GATES
deploy-echo-5c689d5454-97sht   1/1     Running   0          47s   10.10.3.4   myk8s-worker          <none>           <none>
deploy-echo-5c689d5454-bpfsr   1/1     Running   0          47s   10.10.1.3   myk8s-worker3         <none>           <none>
deploy-echo-5c689d5454-wjt2t   1/1     Running   0          47s   10.10.2.3   myk8s-worker2         <none>           <none>
net-pod                        1/1     Running   0          55m   10.10.0.6   myk8s-control-plane   <none>           <none>
net-pod2                       1/1     Running   0          19m   10.10.3.3   myk8s-worker          <none>           <none>

NAME                   TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/svc-nodeport   NodePort   10.200.1.108   <none>        9000:31379/TCP   48s

NAME                     ENDPOINTS                                      AGE
endpoints/svc-nodeport   10.10.1.3:8080,10.10.2.3:8080,10.10.3.4:8080   48s

$ kubectl get no -owide
NAME                  STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION    CONTAINER-RUNTIME
myk8s-control-plane   Ready    control-plane   5h3m   v1.31.0   172.18.0.5    <none>        Debian GNU/Linux 12 (bookworm)   6.6.31-linuxkit   containerd://1.7.18
myk8s-worker          Ready    <none>          5h3m   v1.31.0   172.18.0.2    <none>        Debian GNU/Linux 12 (bookworm)   6.6.31-linuxkit   containerd://1.7.18
myk8s-worker2         Ready    <none>          5h3m   v1.31.0   172.18.0.3    <none>        Debian GNU/Linux 12 (bookworm)   6.6.31-linuxkit   containerd://1.7.18
myk8s-worker3         Ready    <none>          5h3m   v1.31.0   172.18.0.4    <none>        Debian GNU/Linux 12 (bookworm)   6.6.31-linuxkit   containerd://1.7.18

참고로, 서비스 생성 후 노드의 listen 포트를 살펴보면 노드 포트에 설정된 포트는 열려있지 않은 것을 확인할 수 있습니다.

 

[테스트용 외부 컨테이너 생성]

NodePort 서비스에 대한 요청을 보내기 위해 별도의 컨테이너를 생성합니다.

$ docker run -d --rm --name mypc --network kind --ip 172.18.0.100 nicolaka/netshoot sleep infinity
## 통신 확인
$ docker exec -it mypc ping -c 1 172.18.0.1

NodePort 서비스의 endpoint가 없는 컨트롤 플레인 노드에 요청을 보내보겠습니다.

mypc 컨테이너(172.18.0.100) -> 172.18.0.5:31379 (컨트롤플레인 노드 ip:노드 포트)로의 요청이 10.10.1.3:8080 (파드 ip:서비스 타겟 포트)로 보내질 때는 컨트롤플레인 노드의 ip를 갖고(SNAT) 나가는 것을 볼 수 있습니다.

파드가 없는 노드를 통해서도 정상적으로 접근 가능한 것을 확인할 수 있습니다.

 

또한, 클러스터 내부에서 NodePort Service의 Cluster IP로 통신 가능한 것을 확인할 수 있습니다.

 

iptables 규칙과 conntrack 테이블을 살펴보겠습니다.

Chain KUBE-EXT-VTR7MTHHNMFZ3OFS (2 references)
target     prot opt source               destination
KUBE-MARK-MASQ  all  --  anywhere             anywhere             /* masquerade traffic for default/svc-nodeport:svc-webport external destinations */
KUBE-SVC-VTR7MTHHNMFZ3OFS  all  --  anywhere             anywhere

Chain KUBE-NODEPORTS (1 references)
target     prot opt source               destination
KUBE-EXT-VTR7MTHHNMFZ3OFS  tcp  --  anywhere             127.0.0.0/8          /* default/svc-nodeport:svc-webport */ tcp dpt:31379 nfacct-name  localhost_nps_accepted_pkts
KUBE-EXT-VTR7MTHHNMFZ3OFS  tcp  --  anywhere             anywhere             /* default/svc-nodeport:svc-webport */ tcp dpt:31379
...

...
Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-SVC-NPX46M4PTMTKRN6Y  tcp  --  anywhere             10.200.1.1           /* default/kubernetes:https cluster IP */ tcp dpt:https
KUBE-SVC-TCOU7JCQXEZGVUNU  udp  --  anywhere             10.200.1.10          /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-SVC-ERIFXISQEP7F7OF4  tcp  --  anywhere             10.200.1.10          /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-SVC-JD5MR3NA4I4DYORP  tcp  --  anywhere             10.200.1.10          /* kube-system/kube-dns:metrics cluster IP */ tcp dpt:9153
KUBE-SVC-VTR7MTHHNMFZ3OFS  tcp  --  anywhere             10.200.1.108         /* default/svc-nodeport:svc-webport cluster IP */ tcp dpt:9000
KUBE-NODEPORTS  all  --  anywhere             anywhere             /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

Chain KUBE-SVC-ERIFXISQEP7F7OF4 (1 references)
target     prot opt source               destination
KUBE-MARK-MASQ  tcp  -- !10.10.0.0/16         10.200.1.10          /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-SEP-XVHB3NIW2NQLTFP3  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns-tcp -> 10.10.0.2:53 */ statistic mode random probability 0.50000000000
KUBE-SEP-ZEA5VGCBA2QNA7AK  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns-tcp -> 10.10.0.3:53 */

Chain KUBE-SVC-JD5MR3NA4I4DYORP (1 references)
target     prot opt source               destination
KUBE-MARK-MASQ  tcp  -- !10.10.0.0/16         10.200.1.10          /* kube-system/kube-dns:metrics cluster IP */ tcp dpt:9153
KUBE-SEP-RT3F6VLY3P67FIV3  all  --  anywhere             anywhere             /* kube-system/kube-dns:metrics -> 10.10.0.2:9153 */ statistic mode random probability 0.50000000000
KUBE-SEP-6GODNNVFRWQ66GUT  all  --  anywhere             anywhere             /* kube-system/kube-dns:metrics -> 10.10.0.3:9153 */

Chain KUBE-SVC-NPX46M4PTMTKRN6Y (1 references)
target     prot opt source               destination
KUBE-MARK-MASQ  tcp  -- !10.10.0.0/16         10.200.1.1           /* default/kubernetes:https cluster IP */ tcp dpt:https
KUBE-SEP-OJCTP5LCEHQJ3D72  all  --  anywhere             anywhere             /* default/kubernetes:https -> 172.18.0.5:6443 */

Chain KUBE-SVC-TCOU7JCQXEZGVUNU (1 references)
target     prot opt source               destination
KUBE-MARK-MASQ  udp  -- !10.10.0.0/16         10.200.1.10          /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-SEP-2XZJVPRY2PQVE3B3  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns -> 10.10.0.2:53 */ statistic mode random probability 0.50000000000
KUBE-SEP-XWEOB3JN6VI62DQQ  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns -> 10.10.0.3:53 */

Chain KUBE-SVC-VTR7MTHHNMFZ3OFS (2 references)
target     prot opt source               destination
KUBE-MARK-MASQ  tcp  -- !10.10.0.0/16         10.200.1.108         /* default/svc-nodeport:svc-webport cluster IP */ tcp dpt:9000
KUBE-SEP-XEXGJWEWSC2GPNPZ  all  --  anywhere             anywhere             /* default/svc-nodeport:svc-webport -> 10.10.1.3:8080 */ statistic mode random probability 0.33333333349
KUBE-SEP-2AEFSWYPQGZTCWEI  all  --  anywhere             anywhere             /* default/svc-nodeport:svc-webport -> 10.10.2.3:8080 */ statistic mode random probability 0.50000000000
KUBE-SEP-C5MCUQGLTHD455UI  all  --  anywhere             anywhere             /* default/svc-nodeport:svc-webport -> 10.10.3.4:8080 */

...

# conntrack
conntrack v1.4.7 (conntrack-tools): 5 flow entries have been shown.
tcp      6 67 TIME_WAIT src=172.18.0.100 dst=172.18.0.5 sport=40262 dport=31379 src=10.10.2.3 dst=172.18.0.5 sport=8080 dport=21474 [ASSURED] mark=0 use=1
tcp      6 20 TIME_WAIT src=172.18.0.100 dst=172.18.0.5 sport=44104 dport=31379 src=10.10.3.4 dst=172.18.0.5 sport=8080 dport=56485 [ASSURED] mark=0 use=1

KUBE-NODEPORTS 체인에 규칙이 생성된 것을 볼 수 있습니다.

목적지 31379 포트로 들어온 패킷에 KUBE-EXT-VTR7MTHHNMFZ3OFS 체인이 적용됩니다.

KUBE-EXT-VTR7MTHHNMFZ3OFS에서는 마스커레이딩을 통해 SNAT을 하고 KUBE-SVC-VTR7MTHHNMFZ3OFS 체인이 적용됩니다.

KUBE-SVC-VTR7MTHHNMFZ3OFS 에서는 서비스에 연결된 endpoint 중 어느 endpoint로 보낼지 결정됩니다.

참고로 해당 체인은 서비스의 Cluster IP가 목적지인 패킷에도 동일하게 적용됩니다.

 

추가적으로 conntrack 테이블에서는 아래와 같은 정보를 확인할 수 있습니다.

src=172.18.0.100, dst=172.18.0.5, dport=31379로 요청이 발생

NAT 후 요청이 10.10.3.4(Pod)로 전달되었으며, 포트는 8080(서비스 타겟 포트)

 


 

 

참고 문서

 

블로그에서 같이 보면 좋은 글

728x90

'Kubernetes > Network Study' 카테고리의 다른 글

kube-proxy IPVS 모드  (2) 2024.10.18
kube-proxy 모니터링 환경 구성 실습(serviceMonitor, podMonitor)  (3) 2024.10.16
Calico 개념 및 실습  (3) 2024.09.21
Flannel CNI 실습  (3) 2024.09.07
Pause Container 이해하기  (11) 2024.09.02