[Cilium] #4์ฃผ์ฐจ (2) Service LB-IPAM

25๋…„๋„ Cilium Study 1๊ธฐ ์ •๋ฆฌ ๊ธ€์ž…๋‹ˆ๋‹ค.

 

์‹ค์Šต ํ™˜๊ฒฝ ์…‹ํŒ…

Cilium์˜ LoadBalancer IP Pool ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด ์‚ฌ์ „์— ์ •์˜ํ•œ IP ๋Œ€์—ญ์—์„œ Kubernetes LoadBalancer ์„œ๋น„์Šค์— VIP๋ฅผ ์ž๋™ ํ• ๋‹นํ•˜๊ณ  L2Announce๋ฅผ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ์— ํ•ด๋‹น VIP๋ฅผ ๊ด‘๊ณ ํ•˜๋Š” ๊ณผ์ •์„ ์•Œ์•„๋ณธ๋‹ค!

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get CiliumLoadBalancerIPPool -A
No resources found

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2"
kind: CiliumLoadBalancerIPPool
metadata:
  name: "cilium-lb-ippool"
spec:
  blocks:
  - start: "192.168.10.211"
    stop:  "192.168.10.215"
EOF

ciliumloadbalancerippool.cilium.io/cilium-lb-ippool created
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl api-resources | grep -i CiliumLoadBalancerIPPool
ciliumloadbalancerippools           ippools,ippool,lbippool,lbippools   cilium.io/v2                      false        CiliumLoadBalancerIPPool

์„ค์ • ํ™•์ธ

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl api-resources | grep -i CiliumLoadBalancerIPPool
ciliumloadbalancerippools           ippools,ippool,lbippool,lbippools   cilium.io/v2                      false        CiliumLoadBalancerIPPool

 

 

ํด๋Ÿฌ์Šคํ„ฐ์— CiliumLoadBalancerIPPool CRD๊ฐ€ ๋“ฑ๋ก๋˜์–ด  ์žˆ๋Š”๋ฐ ์ด๋Š” LB์šฉ IP ํ’€์„ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฆฌ์†Œ์Šค๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋‹ค.

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get ippools
NAME               DISABLED   CONFLICTING   IPS AVAILABLE   AGE
cilium-lb-ippool   false      False         5               44s

 

 

cilium-lb-ippool์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๊ณ  ์ถฉ๋Œ ์—†์ด(Conflicting=False) ํ• ๋‹น ๊ฐ€๋Šฅํ•œ IP๊ฐ€ 5๊ฐœ ๋‚จ์•„ ์žˆ๋‹ค๊ณ  ๋‚˜์˜จ๋‹ค. ์ด ํ’€์—์„œ ์„œ๋น„์Šค ํƒ€์ž…์ด ๋กœ๋“œ๋ฐธ๋Ÿฐ์„œ์ธ ์„œ๋น„์Šค๋“ค์— ์™ธ๋ถ€ IP๊ฐ€ ์ž๋™์œผ๋กœ ๋ถ„๋ฐฐ๋œ๋‹ค.

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
LBIP=$(kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
192.168.10.211

 

 

๊ธฐ์กด webpod ์„œ๋น„์Šค๋ฅผ LoadBalancer ํƒ€์ž…์œผ๋กœ ๋ฐ”๋€Œ๊ฒŒ ๋˜์–ด์„œ Cilium LB IPAM์ด ํ’€์—์„œ IP ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ด ์„œ๋น„์Šค์— ๋ถ™์ธ๋‹ค. ์ดํ›„ kubectl get svc webpod์—์„œ EXTERNAL-IP๊ฐ€ 192.168.10.211๋กœ ์ฑ„์›Œ์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋‚ด๋ถ€ ClusterIP(10.96.177.120)๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜๊ณ  NodePort(80:30905/TCP)๋„ ๊ณ„์† ๋…ธ์ถœ๋˜์ง€๋งŒ L2 ์ƒ์˜ VIP(192.168.10.211)๋ฅผ ํ†ตํ•ด ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. Cilium์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด VIP๋ฅผ L2(ARP/NDP)๋กœ ๊ด‘๊ณ ํ•ด ๋™์ผ L2 ์„ธ๊ทธ๋จผํŠธ์—์„œ ๊ณง๋ฐ”๋กœ ๋ผ์šฐํŒ… ์—†์ด ๋„๋‹ฌ๋˜๊ฒŒ ํ•œ๋‹ค.

 

๊ฐ™์€ ๋…ธ๋“œ์— ์žˆ๋Š” ํŒŒ๋“œ ํ˜ธ์ถœ ์‹œ

kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
LBIP=$(kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# k8s-ctr์—์„œ VIP๋กœ HTTP ์š”์ฒญ
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# curl -s $LBIP
Hostname: webpod-697b545f57-j524d
IP: 127.0.0.1
IP: ::1
IP: 172.20.0.102
IP: fe80::854:22ff:fea8:fcf4
RemoteAddr: 172.20.0.65:59194
GET / HTTP/1.1
Host: 192.168.10.211
User-Agent: curl/8.5.0
Accept: */*

 

 

RemoteAddr: 172.20.0.65:59194์ธ๋ฐ ์—ฌ๊ธฐ์„œ 172.20.0.65๋Š” k8s-ctr ๋…ธ๋“œ์˜ cilium_host ์ธํ„ฐํŽ˜์ด์Šค IP์ด๋‹ค.

 

 

VIP → ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ → ๊ฐ™์€ ๋…ธ๋“œ์— ์žˆ๋Š” ํŒŒ๋“œ๋กœ ๊ฐ€๋Š” ๊ฒฝ์šฐ ๊ทธ๋Œ€๋กœ ๋ณด๋‚ด๋ฉด ์ž๊ธฐ ์ž์‹ ์„ ๋‹ค์‹œ ๊ฑฐ์น˜๋Š” ์š”์ฒญํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด SNATํ•˜์—ฌ ์†Œ์Šค ip๋ฅผ cilium_host๋กœ ๋ฐ”๊พธ๊ฒŒ ๋˜๊ณ  ํŒŒ๋“œ ์ž…์žฅ์—์„œ๋Š” ์š”์ฒญ์ด ๋…ธ๋“œ(cilium_host)์—์„œ ์˜จ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ๋œ๋‹ค.

 

 

๋‹ค๋ฅธ ๋…ธ๋“œ์— ์žˆ๋Š” ํŒŒ๋“œ ํ˜ธ์ถœ ์‹œ

# ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€์˜ Pod(curl-pod) ์—์„œ VIP๋กœ ์š”์ฒญ
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl exec -it curl-pod -- curl -s $LBIP
Hostname: webpod-697b545f57-7vgtj
IP: 127.0.0.1
IP: ::1
IP: 172.20.1.25 # k8s-w1 ๋…ธ๋“œ์— ์žˆ๋Š” ํŒŒ๋“œ
IP: fe80::301b:7cff:fee1:9a9b
RemoteAddr: 172.20.0.221:35828
GET / HTTP/1.1
Host: 192.168.10.211
User-Agent: curl/8.14.1
Accept: */*

 

 

curl-pod์˜ ํŒŒ๋“œ IP๋กœ ๋‹ค๋ฅธ ํŒŒ๋“œ์—์„œ VIP๋กœ ์š”์ฒญํ•˜๋ฉด ์œ„์ฒ˜๋Ÿผ SNAT ์—†์ด ํด๋ผ์ด์–ธํŠธ ํŒŒ๋“œ IP๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ฃผ์–ด ์–ด๋””์„œ ํ˜ธ์ถœํ•˜์˜€๋Š”์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get ippools
NAME               DISABLED   CONFLICTING   IPS AVAILABLE   AGE
cilium-lb-ippool   false      False         4               20m

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get ippools -o jsonpath='{.items[*].status.conditions[?(@.type!="cilium.io/PoolConflict")]}' | jq
...
{
  "lastTransitionTime": "2025-08-09T14:34:47Z",
  "message": "1",
  "observedGeneration": 1,
  "reason": "noreason",
  "status": "Unknown",
  "type": "cilium.io/IPsUsed"
}

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get svc webpod -o jsonpath='{.status}' | jq
{
  "conditions": [
    {
      "lastTransitionTime": "2025-08-09T14:35:37Z",
      "message": "",
      "reason": "satisfied",
      "status": "True",
      "type": "cilium.io/IPAMRequestSatisfied"
    }
  ],
  "loadBalancer": {
    "ingress": [
      {
        "ip": "192.168.10.211",
        "ipMode": "VIP"
      }
    ]
  }
}

 

ํ•˜๋‚˜๋ฅผ ํ• ๋‹นํ•ด์„œ 5 -> 4๋กœ ๋ณ€ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋ผ์šฐํ„ฐ์—์„œ LBIP๋กœ ํ†ต์‹ 

root@router:~# LBIP=192.168.10.211
root@router:~# curl --connect-timeout 1 $LBIP
curl: (28) Failed to connect to 192.168.10.211 port 80 after 1003 ms: Timeout was reached
root@router:~# arping -i eth1 $LBIP -c 1
ARPING 192.168.10.211
Timeout
root@router:~# arp -a
? (192.168.10.211) at <incomplete> on eth1 # ARP ์š”์ฒญ์„ ๋ณด๋ƒˆ์ง€๋งŒ MAC ์ฃผ์†Œ๋ฅผ ๋ชป ๋ฐ›์€ ์ƒํƒœ๋กœ ๋Œ€์ƒ ํ˜ธ์ŠคํŠธ๊ฐ€ ๊ฐ™์€ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธ ๋„๋ฉ”์ธ์— ์—†๊ฑฐ๋‚˜ ์‘๋‹ตํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ
? (192.168.10.100) at 00:0c:29:2c:5d:fa [ether] on eth1
? (192.168.20.100) at 00:0c:29:92:fa:d7 [ether] on eth2
? (192.168.163.1) at 9e:58:84:52:81:66 [ether] on eth0
_gateway (192.168.163.2) at 00:50:56:f1:a5:32 [ether] on eth0
? (192.168.163.254) at 00:50:56:f5:76:f6 [ether] on eth0

 

192.168.10.211์€ MAC ์ฃผ์†Œ๋ฅผ ๋ชจ๋ฅด๋Š”๋ฐ ๊ฐ™์€ Layer2์— ์—†๊ฑฐ๋‚˜ ํ•ด๋‹น IP๋ฅผ ๊ฐ€์ง„ ์žฅ์น˜๊ฐ€ ๋„คํŠธ์›Œํฌ์— ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์‹ค๋ฆฌ์›€ L2 ๊ด‘๊ณ 

์œ„ ์ฆ์ƒ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด l2 ๊ด‘๊ณ  ๋ชจ๋“œ๋ฅผ ์ผœ์ค€๋‹ค.

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# helm upgrade cilium cilium/cilium --namespace kube-system --version 1.18.0 --reuse-values \
   --set l2announcements.enabled=true && watch -d kubectl get pod -A
Release "cilium" has been upgraded. Happy Helming!
NAME: cilium
LAST DEPLOYED: Sun Aug 10 00:07:55 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 3
TEST SUITE: None
NOTES:
You have successfully installed Cilium with Hubble Relay and Hubble UI.

Your release version is 1.18.0.

For any further help, visit https://docs.cilium.io/en/v1.18/gettinghelp

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl rollout restart -n kube-system ds/cilium
daemonset.apps/cilium restarted
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n kube-system exec ds/cilium -c cilium-agent -- cilium-dbg config --all | grep EnableL2Announcements
EnableL2Announcements             : true
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# cilium config view | grep enable-l2
enable-l2-announcements                           true
enable-l2-neigh-discovery                         false
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2alpha1"  # not v2
kind: CiliumL2AnnouncementPolicy
metadata:
  name: policy1
spec:
  serviceSelector:
    matchLabels:
      app: webpod
  nodeSelector:
    matchExpressions:
      - key: kubernetes.io/hostname
        operator: NotIn
        values:
          - k8s-w0
  interfaces:
  - ^eth[1-9]+
  externalIPs: true
  loadBalancerIPs: true
EOF
ciliuml2announcementpolicy.cilium.io/policy1 created

 

๋ฆฌ๋” ํ™•์ธ

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n kube-system get lease | grep "cilium-l2announce"
cilium-l2announce-default-webpod       k8s-ctr                                                                     2m1s
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n kube-system get lease/cilium-l2announce-default-webpod -o yaml | yq
{
  "apiVersion": "coordination.k8s.io/v1",
  "kind": "Lease",
  "metadata": {
    "creationTimestamp": "2025-08-09T16:06:01Z",
    "name": "cilium-l2announce-default-webpod",
    "namespace": "kube-system",
    "resourceVersion": "101975",
    "uid": "7563bc1e-b8ef-4fff-b9d7-99110ef32a26"
  },
  "spec": {
    "acquireTime": "2025-08-09T16:06:01.973450Z",
    "holderIdentity": "k8s-ctr",
    "leaseDurationSeconds": 15,
    "leaseTransitions": 0,
    "renewTime": "2025-08-09T16:08:10.585356Z"
  }
}
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl exec -n kube-system $CILIUMPOD0 -- cilium-dbg shell -- db/show l2-announce
IP               NetworkInterface
192.168.10.211   eth1

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl exec -n kube-system $CILIUMPOD1 -- cilium-dbg shell -- db/show l2-announce
IP   NetworkInterface

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl exec -n kube-system $CILIUMPOD2 -- cilium-dbg shell -- db/show l2-announce
IP   NetworkInterface

 

VIP 192.168.10.211์„ k8s-ctr ๋…ธ๋“œ์˜ Cilium์ด eth1์—์„œ ๋‹จ๋…์œผ๋กœ L2 ๊ด‘๊ณ ์ค‘์ธ ์ƒํƒœ์ด๋‹ค.

๋‹ค๋ฅธ ๋…ธ๋“œ๋Š” ๊ด‘๊ณ ํ•˜์ง€ ์•Š์Œ์œผ๋กœ์จ ๋‹จ์ผ ๋ฆฌ๋” ๋…ธ๋“œ๋กœ ARP ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.

 

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n kube-system logs ds/cilium | grep "l2"
Found 3 pods, using pod/cilium-69nxs
...

# ํŒŒ๋ผ๋ฏธํ„ฐ ํ™•์ธ
--enable-l2-announcements=true
--l2-announcements-lease-duration=15s
--l2-announcements-renew-deadline=5s
--l2-announcements-retry-period=2s

# ์ปดํฌ๋„ŒํŠธ ์ดˆ๊ธฐํ™”
l2announcer.init...
l2responder.NewL2ResponderReconciler...

# BPF ๋งต ๋“ฑ๋ก
Registered BPF map /sys/fs/bpf/tc/globals/cilium_l2_responder_v4
l2 announcer table full reconciliation

# ๋ฆฌ๋” ์„ ์ถœ
attempting to acquire leader lease kube-system/cilium-l2announce-default-webpod...
successfully acquired lease ...

# ํ—ฌ์Šค ์ฒดํฌ
Timer job triggered ... l2-announcer-lease-gc
Timer job finished ...

 

 

๋ผ์šฐํ„ฐ์—์„œ ํ†ต์‹  ํ™•์ธ

L2 ์‘๋‹ต ํ™•์ธ

root@router:~# arping -i eth1 $LBIP -c 1000
ARPING 192.168.10.211
60 bytes from 00:0c:29:2c:5d:fa (192.168.10.211): index=0 time=195.438 usec
60 bytes from 00:0c:29:2c:5d:fa (192.168.10.211): index=1 time=304.491 usec
60 bytes from 00:0c:29:2c:5d:fa (192.168.10.211): index=2 time=821.920 usec
60 bytes from 00:0c:29:2c:5d:fa (192.168.10.211): index=3 time=491.136 usec
60 bytes from 00:0c:29:2c:5d:fa (192.168.10.211): index=4 time=299.574 usec
^C
--- 192.168.10.211 statistics ---
5 packets transmitted, 5 packets received,   0% unanswered (0 extra)
rtt min/avg/max/std-dev = 0.195/0.423/0.822/0.221 ms

 

ํ•ด๋‹น VIP๊ฐ€ ์ •์ƒ์ ์œผ๋กœ L2์—์„œ ์‘๋‹ตํ•˜๊ณ  ์žˆ๋‹ค.

ARP ํ…Œ์ด๋ธ” ํ™•์ธ

root@router:~# arp -a
? (192.168.10.211) at 00:0c:29:2c:5d:fa [ether] on eth1 # VIP์™€ ์ด VIP์˜ ๋งฅ ์ฃผ์†Œ
? (192.168.10.100) at 00:0c:29:2c:5d:fa [ether] on eth1 # 192.168.10.100๋„ ๊ฐ™์€ MAC ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉ → ๊ฐ™์€ ๋…ธ๋“œ์— ์†ํ•œ ๋‹ค๋ฅธ IP
? (192.168.20.100) at 00:0c:29:92:fa:d7 [ether] on eth2
? (192.168.163.1) at 9e:58:84:52:81:66 [ether] on eth0
_gateway (192.168.163.2) at 00:50:56:f1:a5:32 [ether] on eth0
? (192.168.163.254) at 00:50:56:f5:76:f6 [ether] on eth0

 

root@router:~# curl -s $LBIP | grep Hostname
curl -s $LBIP | grep RemoteAddr
Hostname: webpod-697b545f57-7vgtj
RemoteAddr: 172.20.0.65:42486 # VIP๋ฅผ ๊ด‘๊ณ ํ•œ ๋…ธ๋“œ์˜ cilium_host ์ธํ„ฐํŽ˜์ด์Šค IP

 

์™ธ๋ถ€์—์„œ VIP๋กœ ์ ‘์†ํ•˜๋ฉด ์š”์ฒญ์€ VIP๋ฅผ ๋ณด์œ ํ•œ ๋…ธ๋“œ๋กœ ๋“ค์–ด์˜ค๊ฒŒ ๋˜๊ณ  Cilium์ด Pod ๋„คํŠธ์›Œํฌ(cilium_host) IP๋ฅผ ์†Œ์Šค๋กœ ํ•˜์—ฌ Pod๋กœ ์ „๋‹ฌํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ์„œ๋ฒ„ ์‘๋‹ต ์‹œ ์™ธ๋ถ€ IP ๋Œ€์‹  VIP๋ฅผ ๊ฐ€์ง„ ๋…ธ๋“œ์˜ ํŒŒ๋“œ ๋„คํŠธ์›Œํฌ IP๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค.

์„œ๋น„์Šค ์ถ”๊ฐ€ ์‹œ ๋™์ž‘ ํ™•์ธ

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netshoot-web
  labels:
    app: netshoot-web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: netshoot-web
  template:
    metadata:
      labels:
        app: netshoot-web
    spec:
      terminationGracePeriodSeconds: 0
      containers:
        - name: netshoot
EOF           done080 -q 1;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nOK from \$POD_NAM
deployment.apps/netshoot-web created
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: netshoot-web
  labels:
    app: netshoot-web
spec:
  type: LoadBalancer
  selector:
    app: netshoot-web
  ports:
    - name: http
      port: 80
      targetPort: 8080
EOF
service/netshoot-web created
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get svc netshoot-web
NAME           TYPE           CLUSTER-IP   EXTERNAL-IP      PORT(S)        AGE
netshoot-web   LoadBalancer   10.96.70.7   192.168.10.212   80:31636/TCP   8s
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2alpha1"  # not v2
kind: CiliumL2AnnouncementPolicy
metadata:
  name: policy2
spec:
  serviceSelector:
    matchLabels:
      app: netshoot-web
  nodeSelector:
    matchExpressions:
      - key: kubernetes.io/hostname
        operator: NotIn
        values:
          - k8s-w0
  interfaces:
  - ^eth[1-9]+
  externalIPs: true
  loadBalancerIPs: true
EOF
ciliuml2announcementpolicy.cilium.io/policy2 created

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n kube-system get lease | grep "cilium-l2announce"
cilium-l2announce-default-netshoot-web   k8s-w1                                                                      27s
cilium-l2announce-default-webpod         k8s-ctr                                                                     27m
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get svc netshoot-web -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# LB2IP=$(kubectl get svc netshoot-web -o jsonpath='{.status.loadBalancer.ingress[0].ip}')gress[0].ip}')
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# curl -s $LB2IP
OK from netshoot-web-5c59d94bd4-x7c6l

root@router:~# arping -i eth1 $LB2IP -c 2
ARPING 192.168.10.212
60 bytes from 00:0c:29:79:f7:02 (192.168.10.212): index=0 time=584.052 usec
60 bytes from 00:0c:29:79:f7:02 (192.168.10.212): index=1 time=276.338 usec

--- 192.168.10.212 statistics ---
2 packets transmitted, 2 packets received,   0% unanswered (0 extra)
rtt min/avg/max/std-dev = 0.276/0.430/0.584/0.154 ms

root@router:~# curl -s $LB2IP
OK from netshoot-web-5c59d94bd4-42xwj

 

์ƒˆ๋กœ์šด ์„œ๋น„์Šค(netshoot-web)๋ฅผ LoadBalancer ํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด Cilium LoadBalancer IP Pool์—์„œ ์ƒˆ๋กœ์šด VIP(192.168.10.212)๊ฐ€ ํ• ๋‹น๋œ๋‹ค.

 

VIP๋Š” L2Announce๋ฅผ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ ์ƒ์— ๊ด‘๊ณ ๋˜๊ณ   ์™ธ๋ถ€ ์žฅ๋น„(๋ผ์šฐํ„ฐ)์—์„œ๋„ ํ•ด๋‹น VIP๋ฅผ ARP๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

netshoot-web ์— EX-IP๋ฅผ  ์ง์ ‘ ๋ณ€๊ฒฝ

 

K9S > SVC > netshoot-web E

root@router:~# arping -i eth1 192.168.10.215 -c 2
ARPING 192.168.10.215
60 bytes from 00:0c:29:79:f7:02 (192.168.10.215): index=0 time=310.505 usec
60 bytes from 00:0c:29:79:f7:02 (192.168.10.215): index=1 time=479.675 usec

--- 192.168.10.215 statistics ---
2 packets transmitted, 2 packets received,   0% unanswered (0 extra)
rtt min/avg/max/std-dev = 0.311/0.395/0.480/0.085 ms

 

Sharing Keys : EX-IP 1๊ฐœ๋ฅผ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ํฌํŠธ ์‚ฌ์šฉํ•˜๊ธฐ

cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: netshoot-web2
  labels:
    app: netshoot-web
spec:
  type: LoadBalancer
  selector:
    app: netshoot-web
  ports:
    - name: http
      port: 8080      
      targetPort: 8080
EOF

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get svc -l app=netshoot-web
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)          AGE
netshoot-web    LoadBalancer   10.96.70.7     192.168.10.215   80:31636/TCP     11m
netshoot-web2   LoadBalancer   10.96.58.141   192.168.10.212   8080:31282/TCP   115s

 

๊ฐ™์€ external ip๋กœ ๋ณ€๊ฒฝ๋œ ์  ํ™•์ธ

(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl get svc -l app=netshoot-web
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)          AGE
netshoot-web    LoadBalancer   10.96.70.7     192.168.10.215   80:31636/TCP     11m
netshoot-web2   LoadBalancer   10.96.58.141   192.168.10.215   8080:31282/TCP   115s
(โŽˆ|HomeLab:N/A) root@k8s-ctr:~# kubectl -n kube-system get lease | grep "cilium-l2announce"
cilium-l2announce-default-netshoot-web    k8s-w1                                                                      11m
cilium-l2announce-default-netshoot-web2   k8s-w1                                                                      2m51s
cilium-l2announce-default-webpod          k8s-ctr                                                                     39m

 

root@router:~# LB2IP=192.168.10.215
root@router:~# curl -s $LB2IP
OK from netshoot-web-5c59d94bd4-x7c6l
root@router:~# arping -i eth1 $LB2IP -c 2
ARPING 192.168.10.215
60 bytes from 00:0c:29:79:f7:02 (192.168.10.215): index=0 time=477.965 usec
60 bytes from 00:0c:29:79:f7:02 (192.168.10.215): index=1 time=193.587 usec

--- 192.168.10.215 statistics ---
2 packets transmitted, 2 packets received,   0% unanswered (0 extra)
rtt min/avg/max/std-dev = 0.194/0.336/0.478/0.142 ms
root@router:~# curl -s $LB2IP:8080
OK from netshoot-web-5c59d94bd4-bhs69

 

๋ผ์šฐํ„ฐ์—์„œ ์ •์ƒ์ ์œผ๋กœ ํ†ต์‹ ์ด ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.