Kubernetes

Cilium Study [1기] (2주차) - Observability

yu3papa 2025. 7. 26. 09:34

Cilium을 이용하면 Observability 측면에서의 강점과, Prmetheus/Grafana의 연동성에 대해 알아보겠습니다.

 

참고 링크

실습환경

  • 윈도우 11 OS 에서 Vmware Workstation v17을 이용한 Linux 가상머신 3대
  • Rocky Linux 9.6 (커널버전 : 5.14.0-570.26.1.el9_6.x86_64)

1. 쿠버네티스 클러스터 구성

아래 명령을 이용하여 쿠버네티스 클러스터를 kube-proxy 없이, Native Routing 모드로 구성하였습니다.

[root@k8s-cp ~]#  helm repo add cilium https://helm.cilium.io/

[root@k8s-cp ~]#  helm install cilium cilium/cilium --version 1.17.6 \
--namespace kube-system \
--set k8sServiceHost=172.31.1.10 --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 kubeProxyReplacement=true \
--set bpf.masquerade=true \
--set installNoConntrackIptablesRules=true \
--set endpointHealthChecking.enabled=false \
--set healthChecking=false \
--set hubble.enabled=false \
--set operator.replicas=1 \
--set debug.enabled=true


# kube-system 네임스페이스 리소스 조회
[root@k8s-cp ~]# k -n kube-system get all
NAME                                   READY   STATUS    RESTARTS       AGE
pod/cilium-envoy-flnws                 1/1     Running   0              2m38s
pod/cilium-envoy-h4tl5                 1/1     Running   0              2m38s
pod/cilium-envoy-x9p7c                 1/1     Running   0              2m38s
pod/cilium-gvc4m                       1/1     Running   0              2m38s
pod/cilium-l5ffn                       1/1     Running   0              2m38s
pod/cilium-llljw                       1/1     Running   0              2m38s
pod/cilium-operator-79f7b78b85-r5jcj   1/1     Running   0              2m38s
pod/coredns-674b8bbfcf-f46nc           1/1     Running   0              6d12h
pod/coredns-674b8bbfcf-wjxkw           1/1     Running   0              6d12h
pod/etcd-k8s-cp                        1/1     Running   2 (5m9s ago)   6d12h
pod/kube-apiserver-k8s-cp              1/1     Running   2 (5m9s ago)   6d12h
pod/kube-controller-manager-k8s-cp     1/1     Running   2 (5m9s ago)   6d12h
pod/kube-scheduler-k8s-cp              1/1     Running   2 (5m9s ago)   6d12h

NAME                   TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
service/cilium-envoy   ClusterIP   None         <none>        9964/TCP                 2m38s
service/kube-dns       ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   6d12h

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/cilium         3         3         3       3            3           kubernetes.io/os=linux   2m38s
daemonset.apps/cilium-envoy   3         3         3       3            3           kubernetes.io/os=linux   2m38s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cilium-operator   1/1     1            1           2m38s
deployment.apps/coredns           2/2     2            2           6d12h

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/cilium-operator-79f7b78b85   1         1         1       2m38s
replicaset.apps/coredns-674b8bbfcf           2         2         2       6d12h

# NIC 에 연결된 eBPF 프로그램 목록 확인
[root@k8s-cp ~]# bpftool net list
xdp:

tc:
ens160(2) tcx/ingress cil_from_netdev prog_id 590 link_id 15
ens160(2) tcx/egress cil_to_netdev prog_id 593 link_id 16
cilium_net(3) tcx/ingress cil_to_host prog_id 579 link_id 14
cilium_host(4) tcx/ingress cil_to_host prog_id 569 link_id 12
cilium_host(4) tcx/egress cil_from_host prog_id 572 link_id 13
lxc6606e8bfb038(6) tcx/ingress cil_from_container prog_id 614 link_id 17
lxc6606e8bfb038(6) tcx/egress cil_to_container prog_id 619 link_id 18
lxc8f72d4651d79(8) tcx/ingress cil_from_container prog_id 622 link_id 19
lxc8f72d4651d79(8) tcx/egress cil_to_container prog_id 611 link_id 20

flow_dissector:

netfilter:

# cilium 상태 확인
[root@k8s-cp ~]# cilium status
    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    OK
 \__/¯¯\__/    Hubble Relay:       disabled
    \__/       ClusterMesh:        disabled

DaemonSet              cilium                   Desired: 3, Ready: 3/3, Available: 3/3
DaemonSet              cilium-envoy             Desired: 3, Ready: 3/3, Available: 3/3
Deployment             cilium-operator          Desired: 1, Ready: 1/1, Available: 1/1
Containers:            cilium                   Running: 3
                       cilium-envoy             Running: 3
                       cilium-operator          Running: 1
                       clustermesh-apiserver
                       hubble-relay
Cluster Pods:          2/2 managed by Cilium
Helm chart version:    1.17.6
Image versions         cilium             quay.io/cilium/cilium:v1.17.6@sha256:544de3d4fed7acba72758413812780a4972d47c39035f2a06d6145d8644a3353: 3
                       cilium-envoy       quay.io/cilium/cilium-envoy:v1.33.4-1752151664-7c2edb0b44cf95f326d628b837fcdd845102ba68@sha256:318eff387835ca2717baab42a84f35a83a5f9e7d519253df87269f80b9ff0171: 3
                       cilium-operator    quay.io/cilium/operator-generic:v1.17.6@sha256:91ac3bf7be7bed30e90218f219d4f3062a63377689ee7246062fa0cc3839d096: 1

# cilium 이 제공하는 podCIDR 확인

[root@k8s-cp ~]# kubectl get ciliumnode -o json | grep podCIDRs -A2
                    "podCIDRs": [
                        "172.20.0.0/24"
                    ],
--
                    "podCIDRs": [
                        "172.20.1.0/24"
                    ],
--
                    "podCIDRs": [
                        "172.20.2.0/24"

 

Cilium Agent는 Prometheus 메트릭을 노출하며, 아래 명령으로 확인 가능합니다. 나중에 Grafana 를 이용하여 시각화 해보겠습니다.

[root@k8s-cp ~]# kubectl exec -n kube-system -c cilium-agent -it ds/cilium -- cilium-dbg metrics list
Metric                                                                  Labels                                                                             Value
cilium_act_processing_time_seconds                                                                                                                         0s / 0s / 0s
cilium_agent_api_process_time_seconds                                   method=GET path=/v1/config return_code=200                                         2.5ms / 4.5ms / 4.95ms
cilium_agent_api_process_time_seconds                                   method=GET path=/v1/endpoint return_code=200                                       2.5ms / 4.5ms / 4.95ms
cilium_agent_api_process_time_seconds                                   method=GET path=/v1/healthz return_code=200                                        2.5ms / 4.5ms / 4.95ms
cilium_agent_api_process_time_seconds                                   method=POST path=/v1/ipam return_code=201                                          2.5ms / 4.5ms / 4.95ms
cilium_agent_api_process_time_seconds                                   method=PUT path=/v1/endpoint return_code=201                                       3.75s / 4.75s / 4.975s
cilium_agent_bootstrap_seconds                                          outcome=success scope=bpfBase                                                      2.5ms / 4.5ms / 4.95ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=cleanup                                                      2.5ms / 4.5ms / 4.95ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=daemonInit                                                   37.5ms / 47.5ms / 49.75ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=earlyInit                                                    175ms / 235ms / 248.5ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=enableConntrack                                              2.5ms / 4.5ms / 4.95ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=fqdn                                                         2.5ms / 4.5ms / 4.95ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=healthCheck                                                  2.5ms / 4.5ms / 4.95ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=ipam                                                         2.5ms / 4.5ms / 4.95ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=k8sInit                                                      175ms / 235ms / 248.5ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=mapsInit                                                     750ms / 950ms / 995ms
cilium_agent_bootstrap_seconds                                          outcome=success scope=overall                                                      1.75s / 2.35s / 2.485s
cilium_agent_bootstrap_seconds                                          outcome=success scope=restore                                                      2.5ms / 4.5ms / 4.95ms
cilium_api_limiter_adjustment_factor                                    api_call=endpoint-create                                                           0.506619
cilium_api_limiter_adjustment_factor                                    api_call=endpoint-list                                                             100.000000
cilium_api_limiter_processed_requests_total                             api_call=endpoint-create outcome=success return_code=200                           2.000000
...(생략)...

 

2. Network Observability with Hubble

Hubble 소개

공식문서 - https://docs.cilium.io/en/stable/overview/intro/#intro

Hubble은 Cilium과 eBPF 위에 구축된 완전 분산형 네트워크 및 보안 관측 플랫폼으로, 서비스 간 통신 및 네트워크 인프라의 동작을 완전히 투명한 방식으로 깊이 있게 관찰할 수 있도록 설계되었습니다. eBPF를 기반으로 하기 때문에 Hubble은 프로그래머블하고 동적으로 구성 가능한 가시성을 제공하며, 성능 오버헤드를 최소화하면서도 사용자에게 필요한 상세한 정보를 제공합니다.

  • Hubble API는 Cilium 에이전트가 실행되는 개별 노드의 범위 내에서 작동합니다. 이는 로컬 Cilium 에이전트가 관찰한 트래픽에 대한 네트워크 인사이트를 제한합니다. Hubble CLI는 로컬 UDS(Unix Domain Socket)을 통해 제공되는 Hubble API를 쿼리하는 데 사용할 수 있습니다. Hubble CLI 바이너리는 기본적으로 cilium-agent POD 에 설치됩니다.
  • Hubble Relay를 배포하면 클러스터 메시 시나리오에서 전체 클러스터 또는 여러 클러스터에 대한 네트워크 가시성이 제공됩니다. 이 모드에서는 Hubble CLI를 Hubble Relay 서비스로 안내하거나 Hubble UI를 통해 Hubble 데이터에 액세스할 수 있습니다. Hubble UI는 웹 인터페이스로, L3/L4 및 심지어 L7 계층에서 서비스 종속성 그래프를 자동으로 검색할 수 있게 하여 사용자 친화적인 시각화 및 서비스 맵으로서의 데이터 흐름 필터링을 가능하게 합니다.

(참고) hubble 작명 어원

 

Cilium의 Observability 컴포넌트인 Hubble은 이름의 어원을 허블 우주 망원경(Hubble Space Telescope)에서 가져왔습니다.허블 우주 망원경은 우주의 광대한 영역을 "관측"하고 "탐색"하여 인류의 우주에 대한 이해를 혁신적으로 변화시킨 상징적인 존재입니다.마찬가지로, Cilium의 Hubble은 클러스터 내부의 네트워크 통신을 깊이 있게 관측하고, 서비스 간의 상호작용을 파악하며, 네트워크 정책 결정을 시각화하는 역할을 합니다. 마치 허블 우주 망원경이 우주를 관측하듯이, Cilium의 Hubble은 클라우드 네이티브 환경의 "네트워크 우주"를 들여다보고 이해를 돕는다는 의미를 담고 있습니다.즉, "관측(Observability)"이라는 핵심 기능에 초점을 맞춰, 우주를 관측하는 데 혁혁한 공을 세운 허블 우주 망원경에서 영감을 받아 이름이 지어졌다고 볼 수 있습니다.

Hubble 구성

현재 Hubble 관련 구성은 되어 있지 않습니다.

[root@k8s-cp ~]# cilium status
    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    OK
 \__/¯¯\__/    Hubble Relay:       disabled
    \__/       ClusterMesh:        disabled

DaemonSet              cilium                   Desired: 3, Ready: 3/3, Available: 3/3
DaemonSet              cilium-envoy             Desired: 3, Ready: 3/3, Available: 3/3
Deployment             cilium-operator          Desired: 1, Ready: 1/1, Available: 1/1
Containers:            cilium                   Running: 3
                       cilium-envoy             Running: 3
                       cilium-operator          Running: 1
                       clustermesh-apiserver
                       hubble-relay
Cluster Pods:          2/2 managed by Cilium
Helm chart version:    1.17.6
Image versions         cilium             quay.io/cilium/cilium:v1.17.6@sha256:544de3d4fed7acba72758413812780a4972d47c39035f2a06d6145d8644a3353: 3
                       cilium-envoy       quay.io/cilium/cilium-envoy:v1.33.4-1752151664-7c2edb0b44cf95f326d628b837fcdd845102ba68@sha256:318eff387835ca2717baab42a84f35a83a5f9e7d519253df87269f80b9ff0
                       cilium-operator    quay.io/cilium/operator-generic:v1.17.6@sha256:91ac3bf7be7bed30e90218f219d4f3062a63377689ee7246062fa0cc3839d096: 1

[root@k8s-cp ~]# cilium config view | grep -i hubble
enable-hubble                                     false

[root@k8s-cp ~]# kubectl get cm -n kube-system cilium-config -o json | jq | grep hubble
    "enable-hubble": "false",

[root@k8s-cp ~]# kubectl get secret -n kube-system | grep -iE 'cilium-ca|hubble'
[root@k8s-cp ~]# ss -tnlp | grep -iE 'cilium|hubble' | tee before.txt
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=35))
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=34))
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=33))
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=32))
LISTEN 0      4096       127.0.0.1:9890       0.0.0.0:*    users:(("cilium-agent",pid=2497,fd=6))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=39))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=38))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=37))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=36))
LISTEN 0      4096       127.0.0.1:9879       0.0.0.0:*    users:(("cilium-agent",pid=2497,fd=9))
LISTEN 0      4096       127.0.0.1:34851      0.0.0.0:*    users:(("cilium-agent",pid=2497,fd=44))

 

Helm을 이용하여 Hubble 을 활성화 합니다.

[root@k8s-cp ~]# helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \
--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=31234 \
--set hubble.export.static.enabled=true \
--set hubble.export.static.filePath=/var/run/cilium/hubble/events.log \
--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}"

# hubble 활성화 후 K8S 리소스 확인
[root@k8s-cp ~]# k -n kube-system get all
NAME                                   READY   STATUS    RESTARTS       AGE
pod/cilium-6tfnn                       1/1     Running   0              69s
pod/cilium-envoy-flnws                 1/1     Running   0              137m
pod/cilium-envoy-h4tl5                 1/1     Running   0              137m
pod/cilium-envoy-x9p7c                 1/1     Running   0              137m
pod/cilium-jlwpg                       1/1     Running   0              69s
pod/cilium-operator-79f7b78b85-r5jcj   1/1     Running   0              137m
pod/cilium-ws25w                       1/1     Running   0              56s
pod/coredns-674b8bbfcf-f46nc           1/1     Running   0              6d14h
pod/coredns-674b8bbfcf-wjxkw           1/1     Running   0              6d14h
pod/etcd-k8s-cp                        1/1     Running   2 (140m ago)   6d14h
pod/hubble-relay-5dcd46f5c-k9fdx       1/1     Running   0              71s
pod/hubble-ui-76d4965bb6-9tn4v         2/2     Running   0              71s
pod/kube-apiserver-k8s-cp              1/1     Running   2 (140m ago)   6d14h
pod/kube-controller-manager-k8s-cp     1/1     Running   2 (140m ago)   6d14h
pod/kube-scheduler-k8s-cp              1/1     Running   2 (140m ago)   6d14h

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
service/cilium-envoy     ClusterIP   None            <none>        9964/TCP                 137m
service/hubble-metrics   ClusterIP   None            <none>        9965/TCP                 71s
service/hubble-peer      ClusterIP   10.105.244.29   <none>        443/TCP                  71s
service/hubble-relay     ClusterIP   10.106.212.72   <none>        80/TCP                   71s
service/hubble-ui        NodePort    10.104.74.47    <none>        80:31234/TCP             71s
service/kube-dns         ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP   6d14h

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/cilium         3         3         3       3            3           kubernetes.io/os=linux   137m
daemonset.apps/cilium-envoy   3         3         3       3            3           kubernetes.io/os=linux   137m

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cilium-operator   1/1     1            1           137m
deployment.apps/coredns           2/2     2            2           6d14h
deployment.apps/hubble-relay      1/1     1            1           71s
deployment.apps/hubble-ui         1/1     1            1           71s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/cilium-operator-79f7b78b85   1         1         1       137m
replicaset.apps/coredns-674b8bbfcf           2         2         2       6d14h
replicaset.apps/hubble-relay-5dcd46f5c       1         1         1       71s
replicaset.apps/hubble-ui-76d4965bb6         1         1         1       71s

# 설치 확인
[root@k8s-cp ~]# cilium status
    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    OK
 \__/¯¯\__/    Hubble Relay:       OK
    \__/       ClusterMesh:        disabled

DaemonSet              cilium                   Desired: 3, Ready: 3/3, Available: 3/3
DaemonSet              cilium-envoy             Desired: 3, Ready: 3/3, Available: 3/3
Deployment             cilium-operator          Desired: 1, Ready: 1/1, Available: 1/1
Deployment             hubble-relay             Desired: 1, Ready: 1/1, Available: 1/1
Deployment             hubble-ui                Desired: 1, Ready: 1/1, Available: 1/1
Containers:            cilium                   Running: 3
                       cilium-envoy             Running: 3
                       cilium-operator          Running: 1
                       clustermesh-apiserver
                       hubble-relay             Running: 1
                       hubble-ui                Running: 1
Cluster Pods:          4/4 managed by Cilium
Helm chart version:    1.17.6
Image versions         cilium             quay.io/cilium/cilium:v1.17.6@sha256:544de3d4fed7acba72758413812780a4972d47c39035f2a06d6145d8644a3353: 3
                       cilium-envoy       quay.io/cilium/cilium-envoy:v1.33.4-1752151664-7c2edb0b44cf95f326d628b837fcdd845102ba68@sha256:318eff387835ca2717baab42a84f35a83a5f9e7d519253df87269f80b9ff0171: 3
                       cilium-operator    quay.io/cilium/operator-generic:v1.17.6@sha256:91ac3bf7be7bed30e90218f219d4f3062a63377689ee7246062fa0cc3839d096: 1
                       hubble-relay       quay.io/cilium/hubble-relay:v1.17.6@sha256:7d17ec10b3d37341c18ca56165b2f29a715cb8ee81311fd07088d8bf68c01e60: 1
                       hubble-ui          quay.io/cilium/hubble-ui-backend:v0.13.2@sha256:a034b7e98e6ea796ed26df8f4e71f83fc16465a19d166eff67a03b822c0bfa15: 1
                       hubble-ui          quay.io/cilium/hubble-ui:v0.13.2@sha256:9e37c1296b802830834cc87342a9182ccbb71ffebb711971e849221bd9d59392: 1

# 변경된 config 정보 확인
[root@k8s-cp ~]# cilium config view | grep -i hubble
enable-hubble                                     true
enable-hubble-open-metrics                        true
hubble-disable-tls                                false
hubble-export-allowlist
hubble-export-denylist
hubble-export-fieldmask
hubble-export-file-max-backups                    5
hubble-export-file-max-size-mb                    10
hubble-export-file-path                           /var/run/cilium/hubble/events.log
hubble-listen-address                             :4244
hubble-metrics                                    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
hubble-metrics-server                             :9965
hubble-metrics-server-enable-tls                  false
hubble-socket-path                                /var/run/cilium/hubble.sock
hubble-tls-cert-file                              /var/lib/cilium/tls/hubble/server.crt
hubble-tls-client-ca-files                        /var/lib/cilium/tls/hubble/client-ca.crt
hubble-tls-key-file                               /var/lib/cilium/tls/hubble/server.key

[root@k8s-cp ~]# kubectl get cm -n kube-system cilium-config -o json | grep -i hubble
        "enable-hubble": "true",
        "enable-hubble-open-metrics": "true",
        "hubble-disable-tls": "false",
        "hubble-export-allowlist": "",
        "hubble-export-denylist": "",
        "hubble-export-fieldmask": "",
        "hubble-export-file-max-backups": "5",
        "hubble-export-file-max-size-mb": "10",
        "hubble-export-file-path": "/var/run/cilium/hubble/events.log",
        "hubble-listen-address": ":4244",
        "hubble-metrics": "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",
        "hubble-metrics-server": ":9965",
        "hubble-metrics-server-enable-tls": "false",
        "hubble-socket-path": "/var/run/cilium/hubble.sock",
        "hubble-tls-cert-file": "/var/lib/cilium/tls/hubble/server.crt",
        "hubble-tls-client-ca-files": "/var/lib/cilium/tls/hubble/client-ca.crt",
        "hubble-tls-key-file": "/var/lib/cilium/tls/hubble/server.key",

# hubble 활성화 후 생성된 Secret 확인
[root@k8s-cp ~]# kubectl get secret -n kube-system | grep -iE 'cilium-ca|hubble'
cilium-ca                      Opaque                          2      12m
hubble-relay-client-certs      kubernetes.io/tls               3      12m
hubble-server-certs            kubernetes.io/tls               3      12m

# 새롭게 열리는 포트 확인
[root@k8s-cp ~]# ss -tnlp | grep -iE 'cilium|hubble' | tee after.txt
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=35))
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=34))
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=33))
LISTEN 0      4096         0.0.0.0:9964       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=32))
LISTEN 0      4096       127.0.0.1:9890       0.0.0.0:*    users:(("cilium-agent",pid=33770,fd=6))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=39))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=38))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=37))
LISTEN 0      4096       127.0.0.1:9878       0.0.0.0:*    users:(("cilium-envoy",pid=3097,fd=36))
LISTEN 0      4096       127.0.0.1:9879       0.0.0.0:*    users:(("cilium-agent",pid=33770,fd=63))
LISTEN 0      4096       127.0.0.1:34851      0.0.0.0:*    users:(("cilium-agent",pid=33770,fd=57))
LISTEN 0      4096               *:9965             *:*    users:(("cilium-agent",pid=33770,fd=36))
LISTEN 0      4096               *:9962             *:*    users:(("cilium-agent",pid=33770,fd=7))
LISTEN 0      4096               *:4244             *:*    users:(("cilium-agent",pid=33770,fd=45))

[root@k8s-cp ~]# vimdiff before.txt after.txt


# hubble-relay 는 hubble-peer 의 서비스(ClusterIP :443)을 통해 모든 노드의 :4244에 요청 가져올 수 있음

[root@k8s-cp ~]# k -n kube-system describe cm hubble-relay-config
Name:         hubble-relay-config
Namespace:    kube-system
Labels:       app.kubernetes.io/managed-by=Helm
Annotations:  meta.helm.sh/release-name: cilium
              meta.helm.sh/release-namespace: kube-system

Data
====
config.yaml:
----
cluster-name: default
peer-service: "hubble-peer.kube-systehttp://m.svc.cluster.local.:443"
listen-address: :4245
gops: true
gops-port: "9893"
retry-timeout:
sort-buffer-len-max:
sort-buffer-drain-timeout:
tls-hubble-client-cert-file: /var/lib/hubble-relay/tls/client.crt
tls-hubble-client-key-file: /var/lib/hubble-relay/tls/client.key
tls-hubble-server-ca-files: /var/lib/hubble-relay/tls/hubble-server-ca.crt

disable-server-tls: true



BinaryData
====

Events:  <none>

# hubble-peer 서비스 확인
[root@k8s-cp ~]# kubectl get svc,ep -n kube-system hubble-peer
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/hubble-peer   ClusterIP   10.105.244.29   <none>        443/TCP   38m

NAME                    ENDPOINTS                                            AGE
endpoints/hubble-peer   172.31.1.10:4244,172.31.1.11:4244,172.31.1.12:4244   38m

--> cilium-agent는 DaemonSet으로 생성되면 host 네트워크네임스페이스를 사용하고 4244 포트를 통해 hubble 제공하는 정보를 조회할 수 있습니다. 결국은 hubble-relay 서비스가 모든 노드의 hubble-peer 를 통해 정보를 수집 가능합니다.


 

hubble UI POD 에는 2개의 container(front, backend) 가 있으며 front 는 실제 nginx 웹서버가 실행중입니다.

[root@k8s-cp ~]# k -n kube-system get po hubble-ui-76d4965bb6-9tn4v
NAME                         READY   STATUS    RESTARTS   AGE
hubble-ui-76d4965bb6-9tn4v   2/2     Running   0          53m

[root@k8s-cp ~]# k -n kube-system describe po hubble-ui-76d4965bb6-9tn4v
...(생략)...
Containers:
  frontend:
    Container ID:   containerd://7747481986de0c8fe816f75773fc7c8169ba293d5bd3e9e7a13013a345f79e84
    Image:          quay.io/cilium/hubble-ui:v0.13.2@sha256:9e37c1296b802830834cc87342a9182ccbb71ffebb711971e849221bd9d59392
...(생략)...
    Mounts:
      /etc/nginx/conf.d/default.conf from hubble-ui-nginx-conf (rw,path="nginx.conf")
...(생략)...
  backend:
    Container ID:   containerd://bc50f24bfea5bb916563d4c8d8904bdf3da4c3b3ff07b483c2e9910d9dcd839e
    Image:          quay.io/cilium/hubble-ui-backend:v0.13.2@sha256:a034b7e98e6ea796ed26df8f4e71f83fc16465a19d166eff67a03b822c0bfa15
...(생략)...
Volumes:
  hubble-ui-nginx-conf:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      hubble-ui-nginx
    Optional:  false


# hubble-ui NGINX 설정 파일 확인
[root@k8s-cp ~]# k -n kube-system describe cm hubble-ui-nginx
Name:         hubble-ui-nginx
Namespace:    kube-system
Labels:       app.kubernetes.io/managed-by=Helm
Annotations:  meta.helm.sh/release-name: cilium
              meta.helm.sh/release-namespace: kube-system

Data
====
nginx.conf:
----
server {
    listen       8081;
    listen       [::]:8081;
    server_name  localhost;
    root /app;
    index index.html;
    client_max_body_size 1G;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        location /api {
            proxy_http_version 1.1;
            proxy_pass_request_headers on;
            proxy_pass http://127.0.0.1:8090;
        }
        location / {
            # double `/index.html` is required here
            try_files $uri $uri/ /index.html /index.html;
        }

        # Liveness probe
        location /healthz {
            access_log off;
            add_header Content-Type text/plain;
            return 200 'ok';
        }
    }
}


BinaryData
====

Events:  <none>

# 편의성을 위한 Node 포트를 확인하고 웹 접속
[root@k8s-cp ~]# k -n kube-system get svc hubble-ui
NAME        TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
hubble-ui   NodePort   10.104.74.47   <none>        80:31234/TCP   62m



 

kube-system 네입스페이스를 선택하면 아래와 같이

  • 실제 Flow 데이터를 hubble-relay 를 통해서 수집하고
  • 기본적으로 L3/L4 데이트 흐름만 보이고, L7 데이터 흐름은 아직 확인 할 수 없습니다. (추후 설정 예정)

 

Hubble Clinet 도구 설치

hubble 도 자체 client 도구가 존재하고 아래 명령으로 설치합니다.

# Linux 실습 환경에 설치 시
HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
HUBBLE_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then HUBBLE_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-${HUBBLE_ARCH}.tar.gz{,.sha256sum}
sudo tar xzvfC hubble-linux-${HUBBLE_ARCH}.tar.gz /usr/local/bin

 

설치 확인해보면 정상 동작이 안됩니다. 4245 포트에 대해 127.0.0.1 에 접속해야 합니다.

[root@k8s-cp ~]# hubble status
failed getting status: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp 127.0.0.1:4245: connect: connection refused"

 

Validate Hubble API Access

쉽게 구성하기 위해서 cilium 의 port-porwading 기능을 이용하겠습니다.

[root@k8s-cp ~]# cilium hubble port-forward&
[1] 56932
ℹ️  Hubble Relay is available at 127.0.0.1:4245

[root@k8s-cp ~]# ss -tnlp | grep 4245
LISTEN 0      4096       127.0.0.1:4245       0.0.0.0:*    users:(("cilium",pid=56932,fd=7))
LISTEN 0      4096           [::1]:4245          [::]:*    users:(("cilium",pid=56932,fd=8))


[root@k8s-cp ~]# hubble status
Healthcheck (via localhost:4245): Ok
Current/Max Flows: 12,285/12,285 (100.00%)
Flows/s: 14.17
Connected Nodes: 3/3

# hubble (api) server 기본 접속 주소 확인
[root@k8s-cp ~]# hubble config view
basic-auth-password: ""
basic-auth-username: ""
config: /root/.config/hubble/config.yaml
debug: false
kube-context: ""
kube-namespace: kube-system
kubeconfig: ""
port-forward: false
port-forward-port: "4245"
request-timeout: 12s
server: localhost:4245
timeout: 5s
tls: false
tls-allow-insecure: false
tls-ca-cert-files: []
tls-client-cert-file: ""
tls-client-key-file: ""
tls-server-name: ""

(option) 외부에서 접속하려면 : 자신의 PC에 kubeconfig 설정 후 아래 --server 옵션을 통해 hubble api server 사용
[root@k8s-cp ~]# hubble help status | grep 'server string'
      --server string                 Address of a Hubble server. Ignored when --input-file or --port-forward is provided. (default "localhost:4245")

 

hubble client 사용해 보기

# kube-system 네임스페이스의 POD IP 확인
[root@k8s-cp ~]# k -n kube-system get ciliumendpoints.cilium.io
NAME                           SECURITY IDENTITY   ENDPOINT STATE   IPV4           IPV6
coredns-674b8bbfcf-f46nc       42830               ready            172.20.0.180
coredns-674b8bbfcf-wjxkw       42830               ready            172.20.0.47
hubble-relay-5dcd46f5c-k9fdx   51117               ready            172.20.2.230
hubble-ui-76d4965bb6-9tn4v     65236               ready            172.20.1.213




 

"hubble observe" 도움말 확인

  • Observe flows and events of a Hubble server
[root@k8s-cp ~]# hubble observe -h
Observe flows and events of a Hubble server

Usage:
  hubble observe [flags]
  hubble observe [command]

Available Commands:
  agent-events Observe Cilium agent events
  debug-events Observe Cilium debug events
  flows        Observe flows of a Hubble server

Selectors Flags:
      --all            Get all flows stored in Hubble's buffer. Note: this option may cause Hubble to return a lot of data. It is recommended to only use it along filters to limit the amount of data returned.
      --first uint     Get first N flows stored in Hubble's buffer. When querying against Hubble Relay, this gets N flows per instance of Hubble connected to that Relay.
  -f, --follow         Follow flows output
      --last uint      Get last N flows stored in Hubble's buffer (default 20). When querying against Hubble Relay, this gets N flows per instance of Hubble connected to that Relay.
      --since string   Filter flows since a specific date. The format is relative (e.g. 3s, 4m, 1h43,, ...) or one of:
                         StampMilli:             Jan _2 15:04:05.000
                         YearMonthDay:           2006-01-02
                         YearMonthDayHour:       2006-01-02T15-07:00
                         YearMonthDayHourMinute: 2006-01-02T15:04-07:00
                         RFC3339:                2006-01-02T15:04:05-07:00
                         RFC3339Milli:           2006-01-02T15:04:05.999-07:00
                         RFC3339Micro:           2006-01-02T15:04:05.999999-07:00
                         RFC3339Nano:            2006-01-02T15:04:05.999999999-07:00
                         RFC1123Z:               Mon, 02 Jan 2006 15:04:05 -0700

      --until string   Filter flows until a specific date. The format is relative (e.g. 3s, 4m, 1h43,, ...) or one of:
                         StampMilli:             Jan _2 15:04:05.000
                         YearMonthDay:           2006-01-02
                         YearMonthDayHour:       2006-01-02T15-07:00
                         YearMonthDayHourMinute: 2006-01-02T15:04-07:00
                         RFC3339:                2006-01-02T15:04:05-07:00
                         RFC3339Milli:           2006-01-02T15:04:05.999-07:00
                         RFC3339Micro:           2006-01-02T15:04:05.999999-07:00
                         RFC3339Nano:            2006-01-02T15:04:05.999999999-07:00
                         RFC1123Z:               Mon, 02 Jan 2006 15:04:05 -0700


Filters Flags:
  -A, --all-namespaces filter[=true]        Show all flows in any Kubernetes namespace.
      --cel-expression filter               Filter flows using the given CEL expression
      --cluster filter                      Show all flows which match the cluster names (e.g. "test-cluster", "prod-*")
      --drop-reason-desc filter             Show only flows which match this drop reason describe (e.g. "POLICY_DENIED", "UNSUPPORTED_L3_PROTOCOL")
      --fqdn filter                         Show all flows related to the given fully qualified domain name (e.g. "*.cilium.io").
      --from-all-namespaces filter[=true]   Show flows originating in any Kubernetes namespace.
      --from-cluster filter                 Show all flows originating from endpoints known to be in the given cluster name
      --from-fqdn filter                    Show all flows originating at the given fully qualified domain name (e.g. "*.cilium.io").
      --from-identity filter                Show all flows originating at an endpoint with the given security identity
      --from-ip filter                      Show all flows originating at the given IP address. Each of the source IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
      --from-label filter                   Show only flows originating in an endpoint with the given labels (e.g. "key1=value1", "reserved:world")
      --from-namespace filter               Show all flows originating in the given Kubernetes namespace.
      --from-pod filter                     Show all flows originating in the given pod name prefix([namespace/]<pod-name>). If namespace is not provided, 'default' is used
      --from-port filter                    Show only flows with the given source port (e.g. 8080)
      --from-service filter                 Shows flows where the source IP address matches the ClusterIP address of the given service name prefix([namespace/]<svc-name>). If namespace is not provided, 'default' is used
      --from-workload filter                Show all flows originating at an endpoint with the given workload
      --http-header filter                  Show only flows which match this HTTP header key:value pairs (e.g. "foo:bar")
      --http-method filter                  Show only flows which match this HTTP method (e.g. "get", "post")
      --http-path filter                    Show only flows which match this HTTP path regular expressions (e.g. "/page/\\d+")
      --http-status filter                  Show only flows which match this HTTP status code prefix (e.g. "404", "5+")
      --http-url filter                     Show only flows which match this HTTP URL regular expressions (e.g. "http://.*cilium\.io/page/\\d+")
      --identity filter                     Show all flows related to an endpoint with the given security identity
      --interface filter                    Show all flows observed at the given interface name (e.g. eth0)
      --ip filter                           Show all flows originating or terminating at the given IP address. Each of the IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
      --ip-version filter                   Show only IPv4, IPv6 flows or non IP flows (e.g. ARP packets) (ie: "none", "v4", "v6")
  -4, --ipv4 filter[=v4]                    Show only IPv4 flows
  -6, --ipv6 filter[=v6]                    Show only IPv6 flows
  -l, --label filter                        Show only flows related to an endpoint with the given labels (e.g. "key1=value1", "reserved:world")
  -n, --namespace filter                    Show all flows related to the given Kubernetes namespace.
      --node-label filter                   Show only flows observed on nodes matching the given label filter (e.g. "key1=value1", "io.cilium/egress-gateway")
      --node-name filter                    Show all flows which match the given node names (e.g. "k8s*", "test-cluster/*.company.com")
      --not filter[=true]                   Reverses the next filter to be blacklist i.e. --not --from-ip 2.2.2.2
      --pod filter                          Show all flows related to the given pod name prefix ([namespace/]<pod-name>). If namespace is not provided, 'default' is used.
      --port filter                         Show only flows with given port in either source or destination (e.g. 8080)
      --protocol filter                     Show only flows which match the given L4/L7 flow protocol (e.g. "udp", "http")
      --service filter                      Shows flows where either the source or destination IP address matches the ClusterIP address of the given service name prefix ([namespace/]<svc-name>). If namespace is not provided, 'default' is used.
      --snat-ip filter                      Show all flows SNATed with the given IP address. Each of the SNAT IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
      --tcp-flags filter                    Show only flows which match the given TCP flags (e.g. "syn", "ack", "fin")
      --to-all-namespaces filter[=true]     Show flows terminating in any Kubernetes namespace.
      --to-cluster filter                   Show all flows destined to endpoints known to be in the given cluster name
      --to-fqdn filter                      Show all flows terminating at the given fully qualified domain name (e.g. "*.cilium.io").
      --to-identity filter                  Show all flows terminating at an endpoint with the given security identity
      --to-ip filter                        Show all flows terminating at the given IP address. Each of the destination IPs can be specified as an exact match (e.g. '1.1.1.1') or as a CIDR range (e.g.'1.1.1.0/24').
      --to-label filter                     Show only flows terminating in an endpoint with given labels (e.g. "key1=value1", "reserved:world")
      --to-namespace filter                 Show all flows terminating in the given Kubernetes namespace.
      --to-pod filter                       Show all flows terminating in the given pod name prefix([namespace/]<pod-name>). If namespace is not provided, 'default' is used
      --to-port filter                      Show only flows with the given destination port (e.g. 8080)
      --to-service filter                   Shows flows where the destination IP address matches the ClusterIP address of the given service name prefix ([namespace/]<svc-name>). If namespace is not provided, 'default' is used
      --to-workload filter                  Show all flows terminating at an endpoint with the given workload
      --trace-id filter                     Show only flows which match this trace ID
      --traffic-direction filter            Show all flows in the given traffic direction (either ingress or egress)
  -t, --type filter                         Filter by event types TYPE[:SUBTYPE]. Available types and subtypes:
                                            TYPE             SUBTYPE
                                            capture          n/a
                                            drop             n/a
                                            l7               n/a
                                            policy-verdict   n/a
                                            trace            from-endpoint
                                                             from-host
                                                             from-network
                                                             from-overlay
                                                             from-proxy
                                                             from-stack
                                                             from-crypto
                                                             to-endpoint
                                                             to-host
                                                             to-network
                                                             to-overlay
                                                             to-proxy
                                                             to-stack
                                                             to-crypto
                                            trace-sock       n/a
      --uuid filter                         Show the only flow matching this unique flow identifier, if any
      --verdict filter                      Show only flows with this verdict [FORWARDED, DROPPED, AUDIT, REDIRECTED, ERROR, TRACED, TRANSLATED]
      --workload filter                     Show all flows related to an endpoint with the given workload

Raw-Filters Flags:
      --allowlist stringArray   Specify allowlist as JSON encoded FlowFilters
      --denylist stringArray    Specify denylist as JSON encoded FlowFilters

Formatting Flags:
  -o, --output string        Specify the output format, one of:
                               compact:  Compact output
                               dict:     Each flow is shown as KEY:VALUE pair
                               jsonpb:   JSON encoded GetFlowResponse according to proto3's JSON mapping
                               json:     Alias for jsonpb
                               table:    Tab-aligned columns
                              (default "compact")
      --print-node-name      Print node name in output
      --time-format string   Specify the time format for printing. This option does not apply to the json and jsonpb output type. One of:
                               StampMilli:             Jan _2 15:04:05.000
                               YearMonthDay:           2006-01-02
                               YearMonthDayHour:       2006-01-02T15Z07:00
                               YearMonthDayHourMinute: 2006-01-02T15:04Z07:00
                               RFC3339:                2006-01-02T15:04:05Z07:00
                               RFC3339Milli:           2006-01-02T15:04:05.999Z07:00
                               RFC3339Micro:           2006-01-02T15:04:05.999999Z07:00
                               RFC3339Nano:            2006-01-02T15:04:05.999999999Z07:00
                               RFC1123Z:               Mon, 02 Jan 2006 15:04:05 -0700
                               (default "StampMilli")

Flow Format Flags:
      --color string     Colorize the output when the output format is one of 'compact' or 'dict'. The value is one of 'auto' (default), 'always' or 'never' (default "auto")
      --ip-translation   Translate IP addresses to logical names such as pod name, FQDN, ... (default true)
      --numeric          Display all information in numeric form

Server Flags:
      --basic-auth-password string    Specify a password for basic auth
      --basic-auth-username string    Specify a username for basic auth
      --kube-context string           Kubernetes configuration context. This option is only considered when --port-forward is set.
      --kube-namespace string         Namespace Cilium is running in. This option is only considered when --port-forward is set. (default "kube-system")
      --kubeconfig string             Path to the kubeconfig file. This option is only considered when --port-forward is set.
  -P, --port-forward                  Automatically forward the relay port to the local machine. Analoguous to running: 'cilium hubble port-forward'.
      --port-forward-port uint16      Local port to forward to. 0 will select a random port. This option is only considered when --port-forward is set. (default 4245)
      --request-timeout duration      Unary Request timeout. Only applies to non-streaming RPCs (ServerStatus, ListNodes, ListNamespaces). (default 12s)
      --server string                 Address of a Hubble server. Ignored when --input-file or --port-forward is provided. (default "localhost:4245")
      --timeout duration              Hubble server dialing timeout (default 5s)
      --tls                           Specify that TLS must be used when establishing a connection to a Hubble server.
                                      By default, TLS is only enabled if the server address starts with 'tls://'.
      --tls-allow-insecure            Allows the client to skip verifying the server's certificate chain and host name.
                                      This option is NOT recommended as, in this mode, TLS is susceptible to machine-in-the-middle attacks.
                                      See also the 'tls-server-name' option which allows setting the server name.
      --tls-ca-cert-files strings     Paths to custom Certificate Authority (CA) certificate files.The files must contain PEM encoded data.
      --tls-client-cert-file string   Path to the public key file for the client certificate to connect to a Hubble server (implies TLS).
                                      The file must contain PEM encoded data.
      --tls-client-key-file string    Path to the private key file for the client certificate to connect a Hubble server (implies TLS).
                                      The file must contain PEM encoded data.
      --tls-server-name string        Specify a server name to verify the hostname on the returned certificate (eg: 'instance.hubble-relay.cilium.io').

Other Flags:
      --experimental-field-mask strings        Experimental: Comma-separated list of fields for mask. Fields not in the mask will be removed from server response.
      --experimental-use-default-field-masks   Experimental: request only visible fields when the output format is compact, tab, or dict.
      --input-file string                      Query flows from this file instead of the server. Use '-' to read from stdin.
      --print-raw-filters                      Print allowlist/denylist filters and exit without sending the request to Hubble server
  -s, --silent-errors                          Silently ignores errors and warnings

Global Flags:
      --config string   Optional config file (default "/root/.config/hubble/config.yaml")
  -D, --debug           Enable debug messages

Get help:
  -h, --help    Help for any command or subcommand

Use "hubble observe [command] --help" for more information about a command.

 

hubble observe --follow 명령을 이용하여 flow 흐름 관찰

[root@k8s-cp ~]# hubble observe --follow

Jul 26 05:47:57.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:57.342: 127.0.0.1:36322 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:57.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:57.342: 127.0.0.1:36338 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:58.210: kube-system/hubble-relay-5dcd46f5c-k9fdx:34366 (ID:51117) <- 172.31.1.11:4244 (remote-node) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:47:58.342: 127.0.0.1:36342 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:58.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:58.342: 127.0.0.1:36358 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:58.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:58.689: 172.31.1.12:50536 (host) -> 172.31.1.10:6443 (kube-apiserver) to-network FORWARDED (TCP Flags: ACK)
Jul 26 05:47:59.186: 172.31.1.12:45594 (host) -> 172.31.1.10:6443 (kube-apiserver) to-network FORWARDED (TCP Flags: ACK)
Jul 26 05:47:59.211: 172.31.1.10:40180 (kube-apiserver) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:47:59.212: 127.0.0.1:59328 (world) <> kube-system/hubble-ui-76d4965bb6-9tn4v (ID:65236) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:59.219: 172.31.1.10:40180 (kube-apiserver) <- kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-network FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:47:59.343: 127.0.0.1:36376 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:59.343: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:59.343: 127.0.0.1:36360 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:59.343: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:47:59.531: 172.31.1.11:34106 (host) -> 172.31.1.10:6443 (kube-apiserver) to-network FORWARDED (TCP Flags: ACK)
Jul 26 05:47:59.916: 172.31.1.11:58682 (host) -> 172.31.1.10:6443 (kube-apiserver) to-network FORWARDED (TCP Flags: ACK)
Jul 26 05:48:00.030: 172.31.1.12:51606 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: SYN)
Jul 26 05:48:00.030: 172.31.1.12:51606 (host) <- kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-stack FORWARDED (TCP Flags: SYN, ACK)
Jul 26 05:48:00.030: 172.31.1.12:51606 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: ACK)
Jul 26 05:48:00.031: 172.31.1.12:51606 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:00.031: 172.31.1.12:51606 (host) <> kube-system/hubble-relay-5dcd46f5c-k9fdx (ID:51117) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:00.031: 172.31.1.12:51606 (host) <- kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-stack FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:00.032: 172.31.1.12:51606 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: ACK, RST)
Jul 26 05:48:00.033: 172.31.1.11:42652 (host) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: SYN)
Jul 26 05:48:00.033: 172.31.1.11:42652 (host) <- kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-stack FORWARDED (TCP Flags: SYN, ACK)
Jul 26 05:48:00.033: 172.31.1.11:42652 (host) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: ACK)
Jul 26 05:48:00.033: 172.31.1.11:42652 (host) <> kube-system/hubble-ui-76d4965bb6-9tn4v (ID:65236) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:00.033: 172.31.1.11:42652 (host) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:00.034: 172.31.1.11:42652 (host) <- kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-stack FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:00.034: 172.31.1.11:42652 (host) <- kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-stack FORWARDED (TCP Flags: ACK, FIN)
Jul 26 05:48:00.034: 172.31.1.11:42652 (host) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Jul 26 05:48:00.262: 172.31.1.11:42668 (host) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: SYN)
Jul 26 05:48:00.262: 172.31.1.11:42668 (host) <- kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-stack FORWARDED (TCP Flags: SYN, ACK)
Jul 26 05:48:00.262: 172.31.1.11:42668 (host) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: ACK)
Jul 26 05:48:00.262: 172.31.1.11:42668 (host) <> kube-system/hubble-ui-76d4965bb6-9tn4v (ID:65236) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:00.262: 172.31.1.11:42668 (host) -> kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:00.263: 172.31.1.11:42668 (host) <- kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-stack FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:00.263: 172.31.1.11:42668 (host) <- kube-system/hubble-ui-76d4965bb6-9tn4v:8081 (ID:65236) to-stack FORWARDED (TCP Flags: ACK, FIN)
Jul 26 05:48:00.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:00.342: 127.0.0.1:36390 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:00.342: 127.0.0.1:36394 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:00.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:00.458: 172.31.1.12:37576 (host) -> 172.31.1.10:6443 (kube-apiserver) to-network FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:01.039: 172.31.1.12:51614 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: SYN)
Jul 26 05:48:01.040: 172.31.1.12:51614 (host) <- kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-stack FORWARDED (TCP Flags: SYN, ACK)
Jul 26 05:48:01.040: 172.31.1.12:51614 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: ACK)
Jul 26 05:48:01.040: 172.31.1.12:51614 (host) <> kube-system/hubble-relay-5dcd46f5c-k9fdx (ID:51117) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:01.040: 172.31.1.12:51614 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:01.040: 172.31.1.12:51614 (host) <- kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-stack FORWARDED (TCP Flags: ACK, PSH)
Jul 26 05:48:01.042: 172.31.1.12:51614 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Jul 26 05:48:01.042: 172.31.1.12:51614 (host) <- kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-stack FORWARDED (TCP Flags: ACK, FIN)
Jul 26 05:48:01.042: 172.31.1.12:51614 (host) -> kube-system/hubble-relay-5dcd46f5c-k9fdx:4222 (ID:51117) to-endpoint FORWARDED (TCP Flags: ACK)
Jul 26 05:48:01.342: 127.0.0.1:36402 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:01.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:01.342: 127.0.0.1:8080 (world) <> kube-system/coredns-674b8bbfcf-wjxkw (ID:42830) pre-xlate-rev TRACED (TCP)
Jul 26 05:48:01.342: 127.0.0.1:36418 (world) <> kube-system/coredns-674b8bbfcf-f46nc (ID:42830) pre-xlate-rev TRACED (TCP)

 

실습편의를 위한 단축키 설정

# cilium 파드 이름
export CILIUMPOD0=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-cp -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD1=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w1  -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD2=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w2  -o jsonpath='{.items[0].metadata.name}')
echo $CILIUMPOD0 $CILIUMPOD1 $CILIUMPOD2

# 단축키(alias) 지정
alias c0="kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium"
alias c1="kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- cilium"
alias c2="kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- cilium"

alias c0bpf="kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- bpftool"
alias c1bpf="kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- bpftool"
alias c2bpf="kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- bpftool"

 

Hubble 공식 문서의 샘플 어플리케이션 배포

  • 스타워즈에서 영감을 받은 예제에서는 데스스타, 타이파이터, 엑스윙의 세 가지 마이크로서비스 애플리케이션이 있습니다.
  • 데스스타는 포트 80에서 HTTP 웹서비스를 실행하며, 이 서비스는 두 개의 포드 복제본에 걸쳐 데스스타에 대한 요청을 로드 밸런싱하는 Kubernetes 서비스로 노출됩니다.
  • 데스스타 서비스는 제국의 우주선에 착륙 서비스를 제공하여 착륙 포트를 요청할 수 있도록 합니다.
    타이파이터 포드는 일반적인 제국 선박의 착륙 요청 클라이언트 서비스를 나타내며, 엑스윙은 동맹 선박의 유사한 서비스를 나타냅니다.
  • 데스스타 착륙 서비스에 대한 접근 제어를 위한 다양한 보안 정책을 테스트할 수 있도록 존재합니다.
[root@k8s-cp ~]# kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.17.6/examples/minikube/http-sw-app.yaml
service/deathstar created
deployment.apps/deathstar created
pod/tiefighter created
pod/xwing created

# 파드 라벨 labels 확인
[root@k8s-cp ~]# kubectl get pod --show-labels
NAME                        READY   STATUS    RESTARTS   AGE   LABELS
deathstar-8c4c77fb7-gpvpb   1/1     Running   0          46s   app.kubernetes.io/name=deathstar,class=deathstar,org=empire,pod-template-hash=8c4c77fb7
deathstar-8c4c77fb7-wd62w   1/1     Running   0          46s   app.kubernetes.io/name=deathstar,class=deathstar,org=empire,pod-template-hash=8c4c77fb7
tiefighter                  1/1     Running   0          46s   app.kubernetes.io/name=tiefighter,class=tiefighter,org=empire
xwing                       1/1     Running   0          46s   app.kubernetes.io/name=xwing,class=xwing,org=alliance

[root@k8s-cp ~]# kubectl get deploy,svc,ep deathstar
Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deathstar   2/2     2            2           75s

NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/deathstar   ClusterIP   10.104.26.236   <none>        80/TCP    75s

NAME                  ENDPOINTS                         AGE
endpoints/deathstar   172.20.1.165:80,172.20.2.169:80   75s

[root@k8s-cp ~]# kubectl get ciliumendpoints.cilium.io -A
NAMESPACE     NAME                           SECURITY IDENTITY   ENDPOINT STATE   IPV4           IPV6
default       deathstar-8c4c77fb7-gpvpb      377                 ready            172.20.1.165
default       deathstar-8c4c77fb7-wd62w      377                 ready            172.20.2.169
default       tiefighter                     33825               ready            172.20.2.173
default       xwing                          2593                ready            172.20.1.1
kube-system   coredns-674b8bbfcf-f46nc       42830               ready            172.20.0.180
kube-system   coredns-674b8bbfcf-wjxkw       42830               ready            172.20.0.47
kube-system   hubble-relay-5dcd46f5c-k9fdx   51117               ready            172.20.2.230
kube-system   hubble-ui-76d4965bb6-9tn4v     65236               ready            172.20.1.213

[root@k8s-cp ~]# kubectl get ciliumidentities.cilium.io
NAME    NAMESPACE     AGE
2593    default       2m13s
33825   default       2m13s
377     default       2m13s
42830   kube-system   4h23m
51117   kube-system   128m
65236   kube-system   128m


# 현재 ingress/egress 에 정책(Policy) 없음! , Labels 정보 확인
# 해당 노드의 endpint 목록 확인

[root@k8s-cp ~]# c0 endpoint list
ENDPOINT   POLICY (ingress)   POLICY (egress)   IDENTITY   LABELS (source:key[=value])                                                  IPv6   IPv4           STATUS
           ENFORCEMENT        ENFORCEMENT
953        Disabled           Disabled          42830      k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system 172.20.0.47    ready
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=coredns
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=kube-dns
1757       Disabled           Disabled          42830      k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system 172.20.0.180   ready
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=coredns
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=kube-dns
2694       Disabled           Disabled          1          k8s:node-role.kubernetes.io/control-plane                                                          ready
                                                           k8s:node.kubernetes.io/exclude-from-external-load-balancers
                                                           reserved:host

[root@k8s-cp ~]# c1 endpoint list
ENDPOINT   POLICY (ingress)   POLICY (egress)   IDENTITY   LABELS (source:key[=value])                                                  IPv6   IPv4           STATUS
           ENFORCEMENT        ENFORCEMENT
156        Disabled           Disabled          1          reserved:host                                                                                      ready
372        Disabled           Disabled          377        k8s:app.kubernetes.io/name=deathstar                                                172.20.1.165   ready
                                                           k8s:class=deathstar
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=empire
1795       Disabled           Disabled          65236      k8s:app.kubernetes.io/name=hubble-ui                                                172.20.1.213   ready
                                                           k8s:app.kubernetes.io/part-of=cilium
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=hubble-ui
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=hubble-ui
3153       Disabled           Disabled          2593       k8s:app.kubernetes.io/name=xwing                                                    172.20.1.1     ready
                                                           k8s:class=xwing
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=alliance

[root@k8s-cp ~]# c2 endpoint list
ENDPOINT   POLICY (ingress)   POLICY (egress)   IDENTITY   LABELS (source:key[=value])                                                  IPv6   IPv4           STATUS
           ENFORCEMENT        ENFORCEMENT
462        Disabled           Disabled          1          reserved:host                                                                                      ready
2116       Disabled           Disabled          377        k8s:app.kubernetes.io/name=deathstar                                                172.20.2.169   ready
                                                           k8s:class=deathstar
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=empire
2937       Disabled           Disabled          33825      k8s:app.kubernetes.io/name=tiefighter                                               172.20.2.173   ready
                                                           k8s:class=tiefighter
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=empire
3441       Disabled           Disabled          51117      k8s:app.kubernetes.io/name=hubble-relay                                             172.20.2.230   ready
                                                           k8s:app.kubernetes.io/part-of=cilium
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=hubble-relay
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=hubble-relay

# 현재 EndPoint 에 대한 Ingress, Egress 정책은 없는 상태
# IDENTITY는 보안 설정과 관련이 있으며 deathstar POD 의 경우 2개의 workder node에 1개씩 존재하지만 동일한 IDENTITY 값을 가짐

 

Check Current Access

  • 데스스타 서비스의 관점에서 보면, org= empire 라벨이 부착된 선박만 연결하여 착륙을 요청할 수 있습니다.
  • 우리는 규칙을 시행하지 않기 때문에 Xwing과 타이파이터 모두 착륙을 요청할 수 있습니다. 이를 테스트하려면 아래 명령을 사용하세요.
# 호출 시도 1 : xwing --> deathstart
[root@k8s-cp ~]# kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed

# hubble ui 에서 확인해보면 모든 트래픽이 정상 호출됨을 확인할 수 있습니다.


# 호출 시도 2 : tiefighter--> deathstart
[root@k8s-cp ~]# kubectl exec tiefighter-- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed

# hubble ui 에서 확인해보면 모든 트래픽이 정상 호출됨을 확인할 수 있습니다.


# hubble observe 를 편하게 하기 위한 변수 설정
[root@k8s-cp ~]# c1 endpoint list | grep -iE 'xwing|tiefighter|deathstar'
[root@k8s-cp ~]# c2 endpoint list | grep -iE 'xwing|tiefighter|deathstar'
372        Disabled           Disabled          377        k8s:app.kubernetes.io/name=deathstar                                                172.20.1.165   ready
                                                           k8s:class=deathstar
3153       Disabled           Disabled          2593       k8s:app.kubernetes.io/name=xwing                                                    172.20.1.1     ready
                                                           k8s:class=xwing
2116       Disabled           Disabled          377        k8s:app.kubernetes.io/name=deathstar                                                172.20.2.169   ready
                                                           k8s:class=deathstar
2937       Disabled           Disabled          33825      k8s:app.kubernetes.io/name=tiefighter                                               172.20.2.173   ready
                                                           k8s:class=tiefighter

[root@k8s-cp ~]# XWINGID=2593
[root@k8s-cp ~]# TIEFIGHTERID=33825
[root@k8s-cp ~]# DEATHSTARID=377

# xwing POD로 부터 출발한 트래픽만 조회
[root@k8s-cp ~]# hubble observe -f --from-identity $XWINGID

# udp 프로토콜만 조회 : hubble observe -f --protocol udp --from-identity $XWINGID
# tcp 프로토콜만 조회 : hubble observe -f --protocol tcp --from-identity $XWINGID

 

Apply an L3/L4 Policy

  • Cilium을 사용할 때 보안 정책을 정의할 때 엔드포인트 IP 주소는 중요하지 않습니다. 대신 포드에 할당된 레이블을 사용하여 보안 정책을 정의할 수 있습니다. 정책은 클러스터 내에서 실행 중이거나 실행 중인 위치에 관계없이 레이블을 기반으로 올바른 포드에 적용됩니다.
  • 데스스타 착륙 요청을 라벨이 있는 선박(org=empire)으로만 제한하는 기본 정책부터 시작하겠습니다. 이렇게 하면 org=empire 라벨이 없는 선박은 데스스타 서비스와 연결조차 할 수 없습니다. 이 정책은 IP 프로토콜(네트워크 계층 3)과 TCP 프로토콜(네트워크 계층 4)에만 적용되는 간단한 정책이므로 흔히 L3/L4 네트워크 보안 정책이라고 합니다.
  • 참고: 실리움은 상태별 연결 추적을 수행합니다. 이는 정책이 프론트엔드가 백엔드에 도달할 수 있도록 허용하면, 동일한 TCP/UDP 연결 내에서 백엔드 응답의 일부인 모든 필수 응답 패킷이 자동으로 프론트엔드에 도달하도록 허용한다는 것을 의미합니다. → 리턴 패킷 자동 허용!

CiliumNetworkPolicy

[root@k8s-cp ~]# k explain CiliumNetworkPolicy
GROUP:      cilium.io
KIND:       CiliumNetworkPolicy
VERSION:    v2

DESCRIPTION:
    CiliumNetworkPolicy is a Kubernetes third-party resource with an extended
    version of NetworkPolicy.
  • CiliumNetworkPolicys는 "endpointSelector"를 사용하여 팟 레이블에서 정책이 적용되는 소스와 목적지를 식별합니다. 
  • 아래 정책은 TCP 포트 80에서 레이블(org=empire)이 있는 모든 팟에서 레이블(org=empire, class=deathstar)이 있는 데스스타 팟으로 전송되는 트래픽을 화이트리스트로 작성합니다.  (그외는 default 로 deny 정책 적용됨)
# https://raw.githubusercontent.com/cilium/cilium/1.17.6/examples/minikube/sw_l3_l4_policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
spec:
  description: "L3-L4 policy to restrict deathstar access to empire ships only"
  endpointSelector:
    matchLabels:
      org: empire
      class: deathstar
  ingress:
  - fromEndpoints:
    - matchLabels:
        org: empire
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP


# 위의 NetworkPolicy 적용
[root@k8s-cp ~]# kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.17.6/examples/minikube/sw_l3_l4_policy.yaml
ciliumnetworkpolicy.cilium.io/rule1 created

[root@k8s-cp ~]# k get cnp
NAME    AGE   VALID
rule1   3s    True

[root@k8s-cp ~]# k describe cnp rule1
Name:         rule1
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  cilium.io/v2
Kind:         CiliumNetworkPolicy
Metadata:
  Creation Timestamp:  2025-07-26T07:12:35Z
  Generation:          1
  Resource Version:    42511
  UID:                 b43fd6bf-998e-4457-89d0-5e7b0a7a9c45
Spec:
  Description:  L3-L4 policy to restrict deathstar access to empire ships only
  Endpoint Selector:
    Match Labels:
      Class:  deathstar
      Org:    empire
  Ingress:
    From Endpoints:
      Match Labels:
        Org:  empire
    To Ports:
      Ports:
        Port:      80
        Protocol:  TCP
Status:
  Conditions:
    Last Transition Time:  2025-07-26T07:12:35Z
    Message:               Policy validation succeeded
    Status:                True
    Type:                  Valid
Events:                    <none>

# 이제 xwing에 deathstar 로 가는 트래픽은 Drop 됨
[root@k8s-cp ~]# kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing --connect-timeout 2
command terminated with exit code 28


# tiefighter -> deathstar 트래픽 : 정상 호출
[root@k8s-cp ~]# kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed


# deathstar 에 ingress 에 policy 활성화 확인
[root@k8s-cp ~]# c0 endpoint list
ENDPOINT   POLICY (ingress)   POLICY (egress)   IDENTITY   LABELS (source:key[=value])                                                  IPv6   IPv4           STATUS
           ENFORCEMENT        ENFORCEMENT
953        Disabled           Disabled          42830      k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system 172.20.0.47    ready
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=coredns
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=kube-dns
1757       Disabled           Disabled          42830      k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system 172.20.0.180   ready
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=coredns
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=kube-dns
2694       Disabled           Disabled          1          k8s:node-role.kubernetes.io/control-plane                                                          ready
                                                           k8s:node.kubernetes.io/exclude-from-external-load-balancers
                                                           reserved:host

[root@k8s-cp ~]# c1 endpoint list
ENDPOINT   POLICY (ingress)   POLICY (egress)   IDENTITY   LABELS (source:key[=value])                                                  IPv6   IPv4           STATUS
           ENFORCEMENT        ENFORCEMENT
156        Disabled           Disabled          1          reserved:host                                                                                      ready
372        Enabled            Disabled          377        k8s:app.kubernetes.io/name=deathstar                                                172.20.1.165   ready
                                                           k8s:class=deathstar
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=empire
1795       Disabled           Disabled          65236      k8s:app.kubernetes.io/name=hubble-ui                                                172.20.1.213   ready
                                                           k8s:app.kubernetes.io/part-of=cilium
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=hubble-ui
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=hubble-ui
3153       Disabled           Disabled          2593       k8s:app.kubernetes.io/name=xwing                                                    172.20.1.1     ready
                                                           k8s:class=xwing
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=alliance

[root@k8s-cp ~]# c2 endpoint list
ENDPOINT   POLICY (ingress)   POLICY (egress)   IDENTITY   LABELS (source:key[=value])                                                  IPv6   IPv4           STATUS
           ENFORCEMENT        ENFORCEMENT
462        Disabled           Disabled          1          reserved:host                                                                                      ready
2116       Enabled            Disabled          377        k8s:app.kubernetes.io/name=deathstar                                                172.20.2.169   ready
                                                           k8s:class=deathstar
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=empire
2937       Disabled           Disabled          33825      k8s:app.kubernetes.io/name=tiefighter                                               172.20.2.173   ready
                                                           k8s:class=tiefighter
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=default
                                                           k8s:io.kubernetes.pod.namespace=default
                                                           k8s:org=empire
3441       Disabled           Disabled          51117      k8s:app.kubernetes.io/name=hubble-relay                                             172.20.2.230   ready
                                                           k8s:app.kubernetes.io/part-of=cilium
                                                           k8s:io.ciliuhttp://m.k8s.namespace.labels.kubernetes.io/metadata.name=kube-system
                                                           k8s:io.ciliuhttp://m.k8s.policy.cluster=default
                                                           k8s:io.ciliuhttp://m.k8s.policy.serviceaccount=hubble-relay
                                                           k8s:io.kubernetes.pod.namespace=kube-system
                                                           k8s:k8s-app=hubble-relay

 

Apply and Test HTTP-aware L7 Policy 

 

테스트 시나리오

  • 위의 간단한 시나리오에서는 tiefighter / xwing에게 데스스타 API에 대한 전체 액세스 권한을 부여하거나 아예 액세스 권한을 부여하지 않는 것으로 충분했습니다. 그러나 마이크로서비스 간에 가장 강력한 보안(즉, 최소 권한 격리를 강제하는 것)을 제공하기 위해서는 데스스타 API를 호출하는 각 서비스가 합법적인 운영에 필요한 HTTP 요청 세트만 수행하도록 제한해야 합니다.
  • 예를 들어, 데스스타 서비스가 임의의 제국 선박이 호출해서는 안 되는 일부 유지보수 API를 노출한다고 가정해 보겠습니다.
[root@k8s-cp ~]# kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Panic: deathstar exploded

goroutine 1 [running]:
main.HandleGarbage(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
        /code/src/github.com/empire/deathstar/
        temp/main.go:9 +0x64
main.main()
        /code/src/github.com/empire/deathstar/
        temp/main.go:5 +0x85

 

Cilium은 HTTP 계층(즉, L7) 정책을 적용하여 타이파이터가 도달할 수 있는 URL을 제한할 수 있습니다. 다음은 타이파이터를 POST /v1/요청-랜딩 API 호출만 수행하도록 제한하고 다른 모든 호출(PUT /v1/배기포트 포함)은 허용하지 않는 정책 파일의 예입니다.

# 기존 rule1 정책을 업데이트 해서 사용
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
spec:
  description: "L7 policy to restrict access to specific HTTP call"
  endpointSelector:
    matchLabels:
      org: empire
      class: deathstar
  ingress:
  - fromEndpoints:
    - matchLabels:
        org: empire
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP
      rules:
        http:
        - method: "POST"
          path: "/v1/request-landing"

 

# Update the existing rule to apply L7-aware policy to protect deathstar using:
[root@k8s-cp ~]# kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.17.6/examples/minikube/sw_l3_l4_l7_policy.yaml
ciliumnetworkpolicy.cilium.io/rule1 configured

[root@k8s-cp ~]# k describe cnp rule1
Name:         rule1
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  cilium.io/v2
Kind:         CiliumNetworkPolicy
Metadata:
  Creation Timestamp:  2025-07-26T07:12:35Z
  Generation:          2
  Resource Version:    45353
  UID:                 b43fd6bf-998e-4457-89d0-5e7b0a7a9c45
Spec:
  Description:  L7 policy to restrict access to specific HTTP call
  Endpoint Selector:
    Match Labels:
      Class:  deathstar
      Org:    empire
  Ingress:
    From Endpoints:
      Match Labels:
        Org:  empire
    To Ports:
      Ports:
        Port:      80
        Protocol:  TCP
      Rules:
        Http:
          Method:  POST
          Path:    /v1/request-landing
Status:
  Conditions:
    Last Transition Time:  2025-07-26T07:12:35Z
    Message:               Policy validation succeeded
    Status:                True
    Type:                  Valid
Events:                    <none>


# We can now re-run the same test as above, but we will see a different outcome
[root@k8s-cp ~]# kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed




# We can now re-run the same test as above, but we will see a different outcome
[root@k8s-cp ~]# kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Access denied


 

다음 실습을 위해 리소스 삭제

[root@k8s-cp ~]# kubectl delete -f https://raw.githubusercontent.com/cilium/cilium/1.17.6/examples/minikube/http-sw-app.yaml
service "deathstar" deleted
deployment.apps "deathstar" deleted
pod "tiefighter" deleted
pod "xwing" deleted

[root@k8s-cp ~]# kubectl delete cnp rule1
ciliumnetworkpolicy.cilium.io "rule1" deleted

 

3. Prometheus + Grafana 를 이용한 Cilium Observability 환경 구성

샘플 어플리케이션 배포

# 샘플 애플리케이션 배포
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-cp 노드에 curl-pod 파드 배포
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: curl-pod
  labels:
    app: curl
spec:
  nodeName: k8s-cp
  containers:
  - name: curl
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

 

통신 확인

# 배포 확인
kubectl get deploy,svc,ep webpod -owide
kubectl get endpointslices -l app=webpod
kubectl get ciliumendpoints
kubectl exec -it -n kube-system ds/cilium -c cilium-agent -- cilium-dbg endpoint list

# 통신 확인
kubectl exec -it curl-pod -- curl webpod | grep Hostname
kubectl exec -it curl-pod -- sh -c 'while true; do curl -s webpod | grep Hostname; sleep 1; done'
Hostname: webpod-697b545f57-57mgp
Hostname: webpod-697b545f57-h9krv
Hostname: webpod-697b545f57-57mgp
Hostname: webpod-697b545f57-h9krv
Hostname: webpod-697b545f57-57mgp
...(생략)...

 

Prometheus + Grafana 설치

# Prometheus + Grafana 배포
[root@k8s-cp ~]# kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.17.6/examples/kubernetes/addons/prometheus/monitoring-example.yaml
namespace/cilium-monitoring created
serviceaccount/prometheus-k8s created
configmap/grafana-config created
configmap/grafana-cilium-dashboard created
configmap/grafana-cilium-operator-dashboard created
configmap/grafana-hubble-dashboard created
configmap/grafana-hubble-l7-http-metrics-by-workload created
configmap/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
service/grafana created
service/prometheus created
deployment.apps/grafana created
deployment.apps/prometheus created

# 확인
[root@k8s-cp ~]# kubectl -n cilium-monitoring get all
NAME                              READY   STATUS    RESTARTS   AGE
pod/grafana-5c69859d9-mg9zj       1/1     Running   0          54s
pod/prometheus-6fc896bc5d-g2d5z   1/1     Running   0          54s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/grafana      ClusterIP   10.96.4.45       <none>        3000/TCP   54s
service/prometheus   ClusterIP   10.105.222.252   <none>        9090/TCP   54s

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/grafana      1/1     1            1           54s
deployment.apps/prometheus   1/1     1            1           54s

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/grafana-5c69859d9       1         1         1       54s
replicaset.apps/prometheus-6fc896bc5d   1         1         1       54s

# 아래 대시보드가 Grafana 에 임포트 되어 있음
[root@k8s-cp ~]# kubectl get cm -n cilium-monitoring
NAME                                         DATA   AGE
grafana-cilium-dashboard                     1      2m51s
grafana-cilium-operator-dashboard            1      2m51s
grafana-config                               3      2m52s
grafana-hubble-dashboard                     1      2m51s
grafana-hubble-l7-http-metrics-by-workload   1      2m51s
kube-root-ca.crt                             1      2m52s
prometheus                                   1      2m51s

 

Deploy Cilium and Hubble with metrics enabled

  • Cilium, Hubble, and Cilium Operator는 기본적으로 메트릭을 노출하지 않습니다.
  • 이러한 서비스에 대한 메트릭을 활성화하면 이러한 구성 요소가 실행 중인 클러스터의 모든 노드에 각각 9962, 9965, 9963 포트가 열립니다.
    • cilium-agent metric : 9962
    • cilium-operator metric :9963
    • Hubble metric : 9965
  • Cilium, Hubble, and Cilium Operator의 메트릭은 모두 다음 헬름 값으로 서로 독립적으로 활성화할 수 있습니다

현재 설정으로 메트릭 노출설정 되어 있음.

hostPC에서 쉬운 접속을 위해 NodePort 30001, 30002 로 설정합니다.

# NodePort 설정
kubectl patch svc -n cilium-monitoring prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
kubectl patch svc -n cilium-monitoring grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'

 

prometheus 에 접속하야 관련 Target 이 잘 등록되었는지 확인

http://172.31.1.10:30001/targets

  • cilium-agent metric : 9962

  • cilium-operator metric :9963

  • Hubble metric : 9965

# cilium-agent metric 메트릭 확인
curl http://172.31.1.11:9962/metrics

# cilium-operator metric 메트릭 확인
curl http://172.31.1.12:9963/metrics

# Hubble metric 확인
curl http://172.31.1.10:9965/metrics

 

각 메트릭을 csv 로 변환하는 스크립트 :

vi ~/MetricToCsv.sh

URL=$1 # Metric URL - http://172.31.1.10:9090/metrics
curl -s -k $1 | grep \# > ~/tempMetric.txt
echo "TYPE,NAME,HELP"
while read line;
do
    if [ "$(echo $line | grep '# HELP' | wc -l)" == "1" ]; then
        HELP=$(echo $line | sed 's/# HELP //g')
    fi
    if [ "$(echo $line | grep '# TYPE' | wc -l)" == "1" ]; then
        TYPE=$(echo $line | awk '{ print $4 }')
        NAME=$(echo $line | awk '{ print $3 }')
        HELP=$(echo $HELP | sed "s/$NAME //g")
        echo $TYPE,$NAME,\"$HELP\"
    fi
done < ~/tempMetric.txt
rm -fr ~/tempMetric.txt

 

위의 스크립트를 이용하여 3개의 csv 파일을 생성하고 윈도우 OS 로 가져온 후 엑셀 작업

sh ~/MetricToCsv.sh http://172.31.1.11:9962/metrics > ~/cilium-agent.csv
sh ~/MetricToCsv.sh http://172.31.1.12:9963/metrics > ~/cilium-operator.csv
sh ~/MetricToCsv.sh http://172.31.1.10:9965/metrics > ~/hubble.csv

Promeehus_Cilium-Metric.xlsx
0.02MB

 

Grafana 에 접속하면 아래와 같은 대시보드가 임포트 되어 있습니다.