DevOps/Study

Cilium Study [1기] 6주차 1/2 ServiceMesh

juyeon22 2025. 8. 22. 22:04

Cilium Study [1기] 6주차 1/2 ServiceMesh

안녕하세요 이번 게시물에서는 ServiceMesh, K8S Ingress Support 라는 주제에 대한 정보를 전달 드리고자 합니다.

1. 실습 환경 구성

실습 환경 구성은 지난주와 동일하지만 배포되는 Application이 많아 Node의 리소스가

vCPU 4, Mem 2560MB로 구성 했습니다.

Figure 1.1 실습환경 구성


curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/cilium-study/6w/Vagrantfile
vagrant up

Helm을 이용하여 Cilum 설치 시 사용한 스크립트는 다음과 같습니다.

helm install cilium cilium/cilium --version $2 --namespace kube-system \
--set k8sServiceHost=192.168.10.100 --set k8sServicePort=6443 \
--set ipam.mode="cluster-pool" --set ipam.operator.clusterPoolIPv4PodCIDRList={"172.20.0.0/16"} --set ipv4NativeRoutingCIDR=172.20.0.0/16 \
--set routingMode=native --set autoDirectNodeRoutes=true --set endpointRoutes.enabled=true --set directRoutingSkipUnreachable=true \
--set kubeProxyReplacement=true --set bpf.masquerade=true --set installNoConntrackIptablesRules=true \
--set endpointHealthChecking.enabled=false --set healthChecking=false \
--set hubble.enabled=true --set hubble.relay.enabled=true --set hubble.ui.enabled=true \
--set hubble.ui.service.type=NodePort --set hubble.ui.service.nodePort=30003 \
--set prometheus.enabled=true --set operator.prometheus.enabled=true --set hubble.metrics.enableOpenMetrics=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,httpV2:exemplars=true;labelsContext=source_ip\,source_namespace\,source_workload\,destination_ip\,destination_namespace\,destination_workload\,traffic_direction}" \
--set ingressController.enabled=true --set ingressController.loadbalancerMode=shared --set loadBalancer.l7.backend=envoy \
--set localRedirectPolicy=true --set l2announcements.enabled=true \
--set operator.replicas=1 --set debug.enabled=true >/dev/null 2>&1

샘플 Application 배포


sshpass -p 'vagrant' ssh -o StrictHostKeyChecking=no vagrant@k8s-w1 hostname
sshpass -p 'vagrant' ssh -o StrictHostKeyChecking=no vagrant@router hostname

# 샘플 애플리케이션 배포
cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webpod
spec:
  replicas: 2
  selector:
    matchLabels:
      app: webpod
  template:
    metadata:
      labels:
        app: webpod
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - sample-app
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: webpod
        image: traefik/whoami
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: webpod
  labels:
    app: webpod
spec:
  selector:
    app: webpod
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
EOF


# k8s-ctr 노드에 curl-pod 파드 배포
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: curl-pod
  labels:
    app: curl
spec:
  nodeName: k8s-ctr
  containers:
  - name: curl
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

2. pwru

✅ pwru 개념

이번 시간에는 간단하게 pwru에 대해서 알아보겠습니다.

pwru 란 "Packet, where are you?"의 줄임말로, eBPF 기술을 활용하여 Linux 커널 내에서 네트워크 패킷의 경로를 추적하는 디버깅 도구입니다.

Cilium 조직에서 개발한 이 도구는 전통적인 네트워크 디버깅 도구들이 제공하지 못하는 커널 레벨의 상세한 패킷 추적 기능을 제공합니다.

pwru는 eBPF kprobe를 통해 작동하며, /proc.kallsyms 파일을 읽어 Socket Buffer 관련 모든 커널 함수들을 후킹합니다.

네트워크 인터페이스 레벨에서만 패킷을 캡쳐하는 tcpdump와는 다르게 pwru는 커널 내부 함수 레벨에서 패킷 경로를 추적합니다.

pwru는 주로 컨테이너, Kubernetes 환경에서 복잡한 네트워크 스택 환경이나 eBPF 기반 네트워크 프로그램을 사용하는 환경에서 문제가 발생하는 경우 디버깅을 위해 사용합니다.

Linux 커널 5.3이상이 필수적이며 전체적인 모든 기능들을 사용하기 위해서는 5.18 버전 이상을 사용해야하기 떄문에 레거시 시스템에서는 사용하기가 어려우며, 커널 함수에서 kprobe를 부착하기 때문에 높은 시스템 오버헤드가 발생한다는 단점이 있습니다.

pwru 실습

pwru를 이용한 간단한 실습을 진행해보겠습니다.

시나리오는 1.1.1.1 목적지 차단을 설정하고, curl을 호출한 상태에서 pwru를 이용하여 모니터링해서 차단 이유를 확인 과정 입니다.

# 1.1.1.1 목적지 차단 설정
iptables -t filter -I OUTPUT 1 -m tcp --proto tcp --dst 1.1.1.1/32 -j DROP

# curl 호출 : 아래 모니터링 후 호출
curl 1.1.1.1 -v


# 새터미널 명령어 수행 후 결과 확인

pwru 'dst host 1.1.1.1 and tcp and dst port 80'
# 2025/08/22 14:37:37 Attaching kprobes (via kprobe-multi)...
# 1642 / 1642 [------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% ? p/s
# 2025/08/22 14:37:37 Attached (ignored 0)
# 2025/08/22 14:37:37 Listening for events..
# SKB                CPU PROCESS          NETNS      MARK/x        IFACE       PROTO  MTU   LEN   TUPLE FUNC
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0000 1500  60    10.0.2.15:58766->1.1.1.1:80(tcp) ip_local_out
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0000 1500  60    10.0.2.15:58766->1.1.1.1:80(tcp) __ip_local_out
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0800 1500  60    10.0.2.15:58766->1.1.1.1:80(tcp) nf_hook_slow
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0800 1500  60    10.0.2.15:58766->1.1.1.1:80(tcp) kfree_skb_reason(SKB_DROP_REASON_NETFILTER_DROP)
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0800 1500  60    10.0.2.15:58766->1.1.1.1:80(tcp) skb_release_head_state
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0800 0     60    10.0.2.15:58766->1.1.1.1:80(tcp) tcp_wfree
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0800 0     60    10.0.2.15:58766->1.1.1.1:80(tcp) skb_release_data
# 0xffff8a9e03b082e8 1   ~r/bin/curl:4286 4026531840 0               0         0x0800 0     60    10.0.2.15:58766->1.1.1.1:80(tcp) kfree_skbmem

3. Cilium Service Mesh

Service Mesh 소개

Service Mesh란 Application 네트워킹을 Application이 하는 것이 아닌, 외부에서 투명한 방식으로 구현하는 방식을 뜻합니다.

일반적으로 Istio가 대표적인 Service Mesh의 구현체중 하나인데, Istio는 운영자가 네트워크 정책을 적용하는 Control Plane부과 정책을 적용하는 Data Plane으로 구성되어있습니다.

Cilum Service Mesh vs Istio

Cilium Service Mesh는 eBPF(extended Berkeley Packet Filter)를 활용한 사이드카 없는(sidecarless) 아키텍처를 채택했습니다. 이는 리눅스 커널 레벨에서 직접 동작하여 네트워킹, 보안, 관찰 기능을 제공합니다.

주된 특징으로는 다음과 같습니다.

  • 커널 레벨 통합
    • 사용자 공간과 커널 공간 간 컨텍스트 스위치를 제거하여 성능 최적화
  • 노드 단위 프록시
    • 각 노드에서 공유 프록시가 모든 Application의 트래픽을 처리

Istio는 Envoy 프록시를 사이드카 형태로 배포하는 전통적인 서비스 메시 아키텍처를 사용합니다. 각 애플리케이션 파드에 Envoy 프록시 컨테이너가 주입되어 모든 인바운드/아웃바운드 트래픽을 가로채고 제어합니다

최근에는 Istio가 사이드카가 아닌 AmbientMesh형태로 ServieMesh를 제공하지만, Ambient Mesh는 공식적으로 2024년에 Release 됐기때문에, 상대적으로 자료가 적다는 특징이 있습니다.

Cilum Service Mesh 소개

Figure 3.1 Cilum Service Mesh

Cilum Service Mesh는 L3/L3 수준 프로토콜은 eBPF로 진행을하며, L7 수준 Application 처리는 cilum-envoy를 이용하여 처리합니다.

4. K8S Ingress Support

✅ K8S Ingress Support

일반적인 kubernetes Ingress와는 다르게, cilum에서 지원하는 Ingress는 리소스에 대해 LoadBalancer 모드를 지정할 수 있습니다.

dedicated Mode를 사용하게되면 Ingress Controller가 Ingress를 위해 전용 LoadBalancer를 생성합니다.

Shared Mode를 사용하게되면 Ingress Controller가 모든 Ingress 리소스에 대해 공유 LoadBalancer를 사용합니다.

각 모드 사용 중 Mode를 변경할 수는 있지만, Mode변경 시에는, Ingress Backend로의 연결이 종료되는 문제가 발생할 수 있습니다.

K8S Ingress Support 사용시 사전 요구사항은 다음과 같습니다.

Cilum에서 NodePort가 활성화된 상태로 구성되어야 합니다. nodePort.enabled=true 를 사용하거나 kubeProxyReplacement=true 로 kube-proxy 대체 기능을 활성화 되어있어야합니다.

기본적으로 L7 Proxy가 활성화가 되어있지만, L7Proxy=true 옵션으로 활성화가 되어있어야합니다.

Cilium Ingress와 Gateway API의 특징

다른 Ingress 또는 Gateway API 컨트롤러는 일반적으로 클러스터에 Deployment 또는 데몬셋으로 설치되며, Loadbalancer Service 또는 이와 유사한 서비스를 통해 노출하지만, Cilium Ingress 및 Gateway API 구성은 Loadbalancer 또는 NodePort 서비스를 통해 노출되거나, 선택적으로 Host network에서도 노출될 수 있습니다. 이 모든 경우에 트래픽이 서비스의 포트에 도착하면 eBPF 코드가 트래픽을 가로채어 투명하게 Envoy에 전달합니다.

Cilium의 네트워크 정책 엔진이 Ingress에서 들어오는 트래픽 경계와 트래픽에 CiliumNetworkPolicy를 적용할 수 있도록 합니다.

Host network mode를 사용할 수 있으며 사용 시 Envoy 리스너가 직접 호스트 네트워크에 노출됩니다. 이는 0.0.0.0 , :: (IPv6)의 모든 인터페이스에서 리스닝하며, LoadBalancer/NodePort Service 생성을 완전히 비활성화 합니다

Shared Mode 사용 시에는 ingressController.hostNetwork.sharedListenerPort에 해당하는 값을 사용합니다. 기본 값은 8080입니다.

Dedicated Mode 사용 시에는 각 Ingress 리소스마다 고유한 포트가 필요하며, ingress.cilium.io/host-listener-port 어노테이션으로 개별 지정을 해야합니다.

1023 이하의 권한 포트 사용 시 NET_BIND_SERVICE capability를 필수적으로 지정해야합니다.

eBPF Data Path

Figure 4.1 Cilum Service Mesh의 Data Path

Cilium K8S Ingress Support 관련 정보 확인

# ingress 에 예약된 내부 IP 확인 : node(cilium-envoy) 별로 존재
kubectl exec -it -n kube-system ds/cilium -- cilium ip list | grep ingress
# 172.20.0.122/32     reserved:ingress
# 172.20.1.5/32       reserved:ingress

# Envoy Socket 확인
kc describe pod -n kube-system -l k8s-app=cilium-envoy
# .......
# Volumes:
#   envoy-sockets:
#     Type:          HostPath (bare host directory volume)
#     Path:          /var/run/cilium/envoy/sockets
#     HostPathType:  DirectoryOrCreate
#   envoy-artifacts:
#     Type:          HostPath (bare host directory volume)
#     Path:          /var/run/cilium/envoy/artifacts
#     HostPathType:  DirectoryOrCreate
#   envoy-config:
#     Type:      ConfigMap (a volume populated by a ConfigMap)
#     Name:      cilium-envoy-config
#     Optional:  false
# .......

ls -al /var/run/cilium/envoy/sockets
#  total 0
# drwxr-xr-x 3 root root 120 Aug 22 14:23 .
# drwxr-xr-x 4 root root  80 Aug 22 14:23 ..
# srw-rw---- 1 root 1337   0 Aug 22 14:23 access_log.sock
# srwxr-xr-x 1 root root   0 Aug 22 14:23 admin.sock
# drwxr-xr-x 3 root root  60 Aug 22 14:23 envoy
# srw-rw---- 1 root 1337   0 Aug 22 14:23 xds.sock



kubectl get svc,ep -n kube-system cilium-ingress
# NAME                     TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
# service/cilium-ingress   LoadBalancer   10.96.167.84   <pending>     80:30621/TCP,443:31500/TCP   133m

# NAME                       ENDPOINTS              AGE
# endpoints/cilium-ingress   192.192.192.192:9999   133m

LB IP를 설정하지 않았기 때문에 EXTERNAL-IP는 Pending이며, endpoints/cilium-ingress는 Ingress/Gateway API사용 시 모든 노드가 트래픽을 수신하기 위해 내부에서 사용하는 논리적인 EndPoint입니다.

CiliumL2AnnouncementPolicy 지정


# IP Pool 지정
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


kc get svc cilium-ingress -n kube-system
# NAME             TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
# cilium-ingress   LoadBalancer   10.96.167.84   192.168.10.211   80:30621/TCP,443:31500/TCP   3h5m


# L2 Announcement 정책 설정
cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2alpha1"
kind: CiliumL2AnnouncementPolicy
metadata:
  name: policy1
spec:
  interfaces:
  - eth1
  externalIPs: true
  loadBalancerIPs: true
EOF

# 현재 리더 역할 노드 확인
kubectl -n kube-system get lease | grep "cilium-l2announce"
# cilium-l2announce-kube-system-cilium-ingress   k8s-w1                                                                      15s


# k8s 외부 노드(router)에서 LB EX-IP로 호출 가능 확인
LBIP=$(kubectl get svc -n kube-system cilium-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo $LBIP
sshpass -p 'vagrant' ssh vagrant@router sudo arping -i eth1 $LBIP -c 2
# ARPING 192.168.10.211
# 60 bytes from 08:00:27:36:e6:f0 (192.168.10.211): index=0 time=31.292 usec
# 60 bytes from 08:00:27:36:e6:f0 (192.168.10.211): index=1 time=453.729 usec

Ingress HTTP Example


# Deploy the Demo App
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.26/samples/bookinfo/platform/kube/bookinfo.yaml


# Istio와 다르게 SideCar가 없는 것 확인
kubectl get pod
# NAME                                  READY   STATUS    RESTARTS   AGE
# pod/details-v1-766844796b-x9mnf       1/1     Running   0          3m29s
# pod/productpage-v1-54bb874995-4bcmg   1/1     Running   0          3m26s
# pod/ratings-v1-5dc79b6bcd-xvdv2       1/1     Running   0          3m29s
# pod/reviews-v1-598b896c9d-wwdnd       1/1     Running   0          3m28s
# pod/reviews-v2-556d6457d-4ffjt        1/1     Running   0          3m27s
# pod/reviews-v3-564544b4d6-vbg7s       1/1     Running   0          3m27s

# Ingress 정보 확인
kubectl get ingressclasses.networking.k8s.io
# NAME     CONTROLLER                     PARAMETERS   AGE
# cilium   cilium.io/ingress-controller   <none>       3h12m


# Ingress 생성 후 배포

cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: basic-ingress
  namespace: default
spec:
  ingressClassName: cilium
  rules:
  - http:
      paths:
      - backend:
          service:
            name: details
            port:
              number: 9080
        path: /details
        pathType: Prefix
      - backend:
          service:
            name: productpage
            port:
              number: 9080
        path: /
        pathType: Prefix
EOF

# cilium-ingress LoadBalancer 의 EX-IP 확인
kubectl get svc -n kube-system cilium-ingress
# NAME             TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
# cilium-ingress   LoadBalancer   10.96.167.84   192.168.10.211   80:30621/TCP,443:31500/TCP   3h15m

# 호출 확인
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/details/1

# Match가 안되기 떄문에 404리턴
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/ratings


# router에서 호출
sshpass -p 'vagrant' ssh vagrant@router curl -s http://$LBIP/
sshpass -p 'vagrant' ssh vagrant@router curl -s http://$LBIP/details/1 -v

# * Connected to 192.168.10.211 (192.168.10.211) port 80
# > GET /details/1 HTTP/1.1
# > Host: 192.168.10.211
# > User-Agent: curl/8.5.0
# > Accept: */*
# >
# < HTTP/1.1 200 OK
# < content-type: application/json
# < server: envoy
# < date: Fri, 22 Aug 2025 08:35:06 GMT
# < content-length: 178
# < x-envoy-upstream-service-time: 32

Figure 4.2 Hubble UI에서 확인된 패킷 로그

이번에는 productpage Application에서 tcpdump를 수행하여 패킷을 추적해보겠습니다.

# productpage-v1 파드가 배포된 노드 확인 
kubectl get pod -l app=productpage -owide
# NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
# productpage-v1-54bb874995-4bcmg   1/1     Running   0          11m   172.20.1.27   k8s-w1   <none>           <none>


# k8s-w1 노드 접근
vagrant ssh k8s-w1

PROID=172.20.1.27

# veth 인터페이스 정보 확인
ip route |grep $PROID
# 172.20.1.27 dev lxcc9ffdcc5a24c proto kernel scope link

PROVETH=lxcc9ffdcc5a24c

ngrep -tW byline -d $PROVETH '' 'tcp port 9080'


# k8s-ctr 서버에서 수행 외부에서 호출 시도
# x-forwarded-for Header에 클라이언트 IP가 출력되는 것 확인

sshpass -p 'vagrant' ssh vagrant@router curl -s http://$LBIP



####
# T 2025/08/22 17:59:35.782450 10.0.2.15:57976 -> 172.20.1.27:9080 [AP] #4
# GET / HTTP/1.1.
# host: 192.168.10.211.
# user-agent: curl/8.5.0.
# accept: */*.
# x-forwarded-for: 192.168.10.200.
# x-forwarded-proto: http.
# x-envoy-internal: true.
# x-request-id: 82787e70-4f1f-4301-a771-13afc598ad8d.
# .

# ##
# T 2025/08/22 17:59:35.805372 172.20.1.27:9080 -> 10.0.2.15:57976 [AP] #6
# HTTP/1.1 200 OK.
# Server: gunicorn.
# Date: Fri, 22 Aug 2025 08:59:35 GMT.
# Connection: keep-alive.
# Content-Type: text/html; charset=utf-8.
# Content-Length: 2080.
# .

Dedicated

실습 시에는 Shared Mode를 사용하고 있지만, Dedicated Mode를 Annotation을 이용해서 구현할 수 있습니다.

cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webpod-ingress
  namespace: default
  annotations:
    ingress.cilium.io/loadbalancer-mode: dedicated
spec:
  ingressClassName: cilium
  rules:
  - http:
      paths:
      - backend:
          service:
            name: webpod
            port:
              number: 80
        path: /
        pathType: Prefix
EOF

kubectl get ingress
# NAME             CLASS    HOSTS   ADDRESS          PORTS   AGE
# basic-ingress    cilium   *       192.168.10.211   80      37m
# webpod-ingress   cilium   *       192.168.10.212   80      42s

# webpod 파드 IP 확인
kubectl get pod -l app=webpod -owide
# NAME                      READY   STATUS    RESTARTS   AGE   IP             NODE      NOMINATED NODE   READINESS GATES
# webpod-697b545f57-drt4t   1/1     Running   0          23s   172.20.0.125   k8s-ctr   <none>           <none>
# webpod-697b545f57-hdqrk   1/1     Running   0          23s   172.20.1.23    k8s-w1    <none>           <none>


# ctr, w1 Node에서 veth interface 찾기
ip route | grep 172.20.0.125 
# lxcd5a90259c63f
WPODVETH=lxcd5a90259c63f
ip route | grep 172.20.1.23
# lxc7d69b66fcd76
WPODVETH=lxc7d69b66fcd76

ngrep -tW byline -d $WPODVETH '' 'tcp port 80'

# interface: lxcd5a90259c63f
# ...
# Hostname: webpod-697b545f57-drt4t
# IP: 127.0.0.1
# IP: ::1
# IP: 172.20.0.125
# IP: fe80::9001:73ff:fecb:97ef
# RemoteAddr: 172.20.1.5:41271
# GET / HTTP/1.1.
# Host: 192.168.10.212.
# User-Agent: curl/8.5.0.
# Accept: */*.
# X-Envoy-Internal: true.
# X-Forwarded-For: 192.168.10.200.
# ...

# interface: lxc7d69b66fcd76
# Hostname: webpod-697b545f57-hdqrk
# ...
# IP: 127.0.0.1
# IP: ::1
# IP: 172.20.1.23
# IP: fe80::8413:8eff:fe18:83c3
# RemoteAddr: 10.0.2.15:34254
# GET / HTTP/1.1.
# Host: 192.168.10.212.
# User-Agent: curl/8.5.0.
# Accept: */*.
# X-Envoy-Internal: true.
# X-Forwarded-For: 192.168.10.200.

# 외부 호출
LB2IP=$(kubectl get svc cilium-ingress-webpod-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
sshpass -p 'vagrant' ssh vagrant@router curl -s http://$LB2IP

Ingress and Network Policy

기본적으로 Network Policy는 클러스터 전체에 적용되는 정책입니다.

cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: "external-lockdown"
spec:
  description: "Block all the traffic originating from outside of the cluster"
  endpointSelector: {}
  ingress:
  - fromEntities:
    - cluster
EOF


# 403 리턴 확인
curl --fail -v http://"$LBIP"/details/1
# < HTTP/1.1 403 Forbidden

# 허용 정책 적용
cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: "allow-cidr"
spec:
  description: "Allow all the traffic originating from a specific CIDR"
  endpointSelector:
    matchExpressions:
    - key: reserved:ingress
      operator: Exists
  ingress:
  - fromCIDRSet:
    # Please update the CIDR to match your environment
    - cidr: 192.168.10.200/32
    - cidr: 127.0.0.1/32
EOF

# curl 요청
curl --fail -v http://"$LBIP"/details/1
# < HTTP/1.1 200 OK

# Default Deny Ingress Policy : DNS쿼리와 kube-system내의 파드 제외 to deny all traffic by default
cat << EOF | kubectl apply -f -
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: "default-deny"
spec:
  description: "Block all the traffic (except DNS) by default"
  egress:
  - toEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: kube-system
        k8s-app: kube-dns
    toPorts:
    - ports:
      - port: '53'
        protocol: UDP
      rules:
        dns:
        - matchPattern: '*'
  endpointSelector:
    matchExpressions:
    - key: io.kubernetes.pod.namespace
      operator: NotIn
      values:
      - kube-system
EOF

curl --fail -v http://"$LBIP"/details/1
# < HTTP/1.1 403 Forbidden

# ingress 를 통해서 인입 시 허용
cat << EOF | kubectl apply -f -
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-ingress-egress
spec:
  description: "Allow all the egress traffic from reserved ingress identity to any endpoints in the cluster"
  endpointSelector:
    matchExpressions:
    - key: reserved:ingress
      operator: Exists
  egress:
  - toEntities:
    - cluster
EOF

curl --fail -v http://"$LBIP"/details/1
# < HTTP/1.1 200 OK

# 정책 삭제
kubectl delete CiliumClusterwideNetworkPolicy --all

# 실습 내용 전체 삭제
# kubectl delete ingress basic-ingress tls-ingress webpod-ingress