이전 게시물에서 cilium + ingress를 이용한 service mesh에 대해서 소개했다.
근데 kubernetes에서는 더이상 ingress에 대한 개발은 없고 gateway api 사용하는걸 권장한다.
그리고 이러한 트렌드 변화에 맞춰서 당연하게도 cilium + gateway api를 이용한 service mesh도 가능하다.
Gateway api 무엇인가?
ingress 객체는 kubernetes는 초창기(1.2)부터 있었던 객체로, 초기에는 외부 HTTP 요청을 backend로 연결하는것을 위해 나왔다.
HTTP/HTTPS를 제외한 프로토콜 지원 미비, 라우팅 규칙 단순, 단일 객체에 의존하여 확장성에서 낮은 평가를 받았다.
그리고 이러한 한계를 극복하기 위해서 나온것이 gateway api이다.
| Ingress | Gateway api | |
| 지원 프로토콜 | HTTP, HTTPS 중심 | HTTP, HTTPS, gRPC, TCP, UDP |
| 리로스 모델 | 단일 ingress 객체 | gatewayclass / gateway / route 등 crd 분리 |
| 라우팅 정책 | host + path 정책 활용 | host + path + methd +header + rate |
gateway api를 검색하면 아래 그림이 가장 많이 나온다.
crd가 분리되어 있는 만큼 해당 역할을 하는 사용자에게 권한을 분리하는것이다.

그리고 ingress와 유사한듯.. 유사하지 않은 트래픽 흐름을 보인다.

Cilium Service Mesh w.gateway api support
Cilium Gateway api Support 사전 작업
gateway api로 service mesh를 구현하기 위해서는 kubeProxyReplacement, l7Proxy=true가 필수이다.
- 6주차 실습 환경 구성에서 cilium helm values에 이미 반영되어 있다.
그리고 gateway api를 위한 crd는 수동으로 배포해야 하고, kubenretes 공식 github에 있는것을 사용한다. 총 6개의 crd를 사용한다.
--- gateway api crd 배포 ---
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.0/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.0/config/crd/standard/gateway.networking.k8s.io_gateways.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.0/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.0/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.0/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.0/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml
그리고 이전 게시물에서 ingress를 이용해서 service mesh를 구현했는데, 공존이 불가능하기 때문에 helm values를 변경한다.
helm upgrade cilium cilium/cilium --version 1.18.1 --namespace kube-system --reuse-values \
--set ingressController.enabled=false --set gatewayAPI.enabled=true
--- helm values 변경하고 재시작해야 반영된다 ---
kubectl -n kube-system rollout restart deployment/cilium-operator
kubectl -n kube-system rollout restart ds/cilium
--- gateway api config 확인 ---
cilium config view | grep gateway-api
(⎈|HomeLab:default) root@k8s-ctr:~# cilium config view | grep gateway-api
enable-gateway-api true
enable-gateway-api-alpn false
enable-gateway-api-app-protocol false
enable-gateway-api-proxy-protocol false
enable-gateway-api-secrets-sync true
gateway-api-hostnetwork-enabled false
gateway-api-hostnetwork-nodelabelselector
gateway-api-secrets-namespace cilium-secrets
gateway-api-service-externaltrafficpolicy Cluster
cilium 재시작까지 완료되면 gatewayclass가 true 상태로 변경된다.
--- gateway class가 생성된다. ---
(⎈|HomeLab:kube-system) root@k8s-ctr:~# k get gatewayclass
NAME CONTROLLER ACCEPTED AGE
cilium io.cilium/gateway-controller True 3m32s
Cilium Gateway api 테스트
ingress에서는 단일 객체에서 라우팅까지 정하게 되는데, gateway api는 분리되어 있다.
gateway 객체를 통해서, 80 포트를 허용하게 되고 같은 namespace에 있는 서비스만 라우팅하도록 한다.
그리고 httproute 객체를 통해서 path, header, queryparam을 기준으로 backend 라우팅을 정한다.
- ingress에서는 단순히 path 기준으로만 지정이 가능한데, gateway는 path 외 다양한 방법을 제공하고 있다.
- from: Same은 gateway와 같은 namespace에 있는 서비스 로만 라우팅하겠다는것을 의미한다.
cat << EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
spec:
gatewayClassName: cilium
listeners:
- protocol: HTTP
port: 80
name: web-gw
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-app-1
spec:
parentRefs:
- name: my-gateway
namespace: default
rules:
- matches:
- path:
type: PathPrefix
value: /details
backendRefs:
- name: details
port: 9080
- matches:
- headers:
- type: Exact
name: magic
value: foo
queryParams:
- type: Exact
name: great
value: example
path:
type: PathPrefix
value: /
method: GET
backendRefs:
- name: productpage
port: 9080
EOF
gateway를 배포하면 cilium ingress support와 유사하게 load balancer type으로 서비스가 생성된다.
그리고 lb list를 보면 load balancer ip로 80으로 트래픽을 받는것을 확인할 수 있다.

gateway 서비스의 load balancer의 ip로 통신을 하면 아래와 같이 잘 된다.

한가지 특이한점은 gateway는 배포할 때 마다 서로 다른 load balancer ip를 사용한다.
- ingress의 경우에는 shared로 사용하면 같은 load balancer ip를 사용하고, 달리 사용하려면 dedicated 옵션을 사용해야만 했다.
- 하지만 gateway api는 ingress보다 복잡한 라우팅 규칙을 지원하다 보니, 기본적으로 load balancer ip가 매번 생성된다.

Cilium Gateway api TLS 테스트 - Terminate
HTTPS를 지원하기 위해서 gateway를 배포할 때는 ingrss와 필드가 거의 유사하다.
이전 게시물에서 mkcert를 통해서 cert를 만들고 이를 secrets으로 만들었는데, secrets을 그대로 사용하면 된다.
cat << EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tls-gateway
spec:
gatewayClassName: cilium
listeners:
- name: https-1
protocol: HTTPS
port: 443
hostname: "bookinfo.cilium.rocks"
tls:
certificateRefs:
- kind: Secret
name: demo-cert
- name: https-2
protocol: HTTPS
port: 443
hostname: "webpod.cilium.rocks"
tls:
certificateRefs:
- kind: Secret
name: demo-cert
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: https-app-route-1
spec:
parentRefs:
- name: tls-gateway
hostnames:
- "bookinfo.cilium.rocks"
rules:
- matches:
- path:
type: PathPrefix
value: /details
backendRefs:
- name: details
port: 9080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: https-app-route-2
spec:
parentRefs:
- name: tls-gateway
hostnames:
- "webpod.cilium.rocks"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: webpod
port: 80
EOF
tls-gateway load balancer ip로 요청을 하면, 서비스 호출이 잘 된다.
(⎈|HomeLab:default) root@k8s-ctr:~# GATEWAY2=$(kubectl get gateway tls-gateway -o jsonpath='{.status.addresses[0].value}')
(⎈|HomeLab:default) root@k8s-ctrecho $GATEWAY2
192.168.10.213
(⎈|HomeLab:default) root@k8s-ctr:~# k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
'''
cilium-gateway-tls-gateway LoadBalancer 10.96.127.171 192.168.10.213 443:32572/TCP 10m
'''
(⎈|HomeLab:default) root@k8s-ctr:~# curl -s --resolve bookinfo.cilium.rocks:443:${GATEWAY2} https://bookinfo.cilium.rocks/details/1 | jq
{
"id": 1,
"author": "William Shakespeare",
"year": 1595,
"type": "paperback",
"pages": 200,
"publisher": "PublisherA",
"language": "English",
"ISBN-10": "1234567890",
"ISBN-13": "123-1234567890"
}
gateway에서 tls 설정을 하면 client -> gatway까지는 HTTPS 트래픽으로 인입된다.
그리고 gateway -> backend까지는 HTTP 평문 데이터가 전송된다. 만약 End-to-End의 HTTPS를 위한 요건이 있으면 어떻게할까?
Cilium Gateway api TLS 테스트 - Passthrough
passthrough는 tls termination도 믿을 수 없다. backend에서 직접 cert로 복호화를 하는것이다.
이를 위해서는 tls를 수용할 수 있는 서비스가 필요하므로 nginx를 테스트 앱으로 배포해서 테스트한다.
cat <<'EOF' > nginx.conf
events {
}
http {
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
server {
listen 443 ssl;
root /usr/share/nginx/html;
index index.html;
server_name nginx.cilium.rocks;
ssl_certificate /etc/nginx-server-certs/tls.crt;
ssl_certificate_key /etc/nginx-server-certs/tls.key;
}
}
EOF
---
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 443
protocol: TCP
selector:
run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 443
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx
readOnly: true
- name: nginx-server-certs
mountPath: /etc/nginx-server-certs
readOnly: true
volumes:
- name: nginx-config
configMap:
name: nginx-configmap
- name: nginx-server-certs
secret:
secretName: demo-cert
EOF
그리고 중요한건 gateway에서 tls mode를 추가로 선택해서 배포한다. 그리고 http route가 아니라 tls route crd를 사용한다.
cat << EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: cilium-tls-gateway
spec:
gatewayClassName: cilium
listeners:
- name: https
hostname: "nginx.cilium.rocks"
port: 443
protocol: TLS
tls:
mode: Passthrough
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: nginx
spec:
parentRefs:
- name: cilium-tls-gateway
hostnames:
- "nginx.cilium.rocks"
rules:
- backendRefs:
- name: my-nginx
port: 443
EOF
gateway를 배포했기 때문에 tls-gateway를 위한 서비스는 새로 생성되고, load balancer ip도 새롭게 추가된다.
그리고 ip는 자동 할당뿐만 아니라 gateway에서 spec.addresses.type을 수정하면 수동 ip로 설정도 가능하다.

Cilium Gateway api 여러가지 테스트
Cilium Gateway api Traffic Weight
gateway api를 이용하면 트래픽 분배 비율도 조정이 가능하고, 설정하는 방법만 route crd에 반영만 하면 된다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route-1
spec:
parentRefs:
- name: cilium-gw
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- kind: Service
name: echo-1
port: 80
weight: 50 # 트래픽 분배 비율
- kind: Service
name: echo-2
port: 80
weight: 50 # 트래픽 분배 비율
weight 비율에 따라서 비슷하게 트래픽이 분배되는걸 확인할 수 있다.
현재 회사에서는 istio destinationrule을 통해서 canary 트래픽 분배비율을 조정하고, 배포를 하는데 같은 개념이다.

Cilium Gateway api Header add
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route-1
namespace: default
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: cilium-gw
rules:
- backendRefs:
- group: ""
kind: Service
name: echo-1
port: 80
weight: 90
- group: ""
kind: Service
name: echo-2
port: 80
weight: 10
filters:
- requestHeaderModifier:
add:
- name: my-header-name ### 추가하고자 하는 헤더 키를 넣고
value: my-header-value ### 추가하고자 하는 헤더 값을 넣는다.
type: RequestHeaderModifier
matches:
- path:
type: PathPrefix
value: /
header를 추가하는것도 간단하다. 특정 경로로 인입되는 트래픽에 대해서 특정 header를 추가할 수 있다.
A/B 테스트, api server 등 header는 어떻게 활용하느냐에 따라서 가치가 있느냐, 없느냐 정해지는것 같다.

지금까지 k8s ingress 객체만 사용했었다. 그때는 당연히 path 기반의 backend 라우팅이 당연하다고 생각했는데
gateway api를 사용해보니, path뿐만 아니라 header, methd 등 엄청 다양하게 활용할 수 있을것 같다.
이번 주차에는 모르는 내용이 많았다. 모르는건 리서치해보고 GPT랑 대화하고 하느라 시간도 오래 걸리고, 지치는것도 많은것 같다.

'기술 토론장 > [K8s] Kubernetes' 카테고리의 다른 글
| [Cilium][7주차] K8s, Cilium 부하 테스트 & 성능 측정 (1) | 2025.08.30 |
|---|---|
| [Cilium][6주차] L7 Aware Traffic Management (0) | 2025.08.24 |
| [Cilium][6주차] Service Mesh Ingress Support (1) | 2025.08.23 |
| [Cilium][5주차] Cilium Clsuter Mesh (5) | 2025.08.17 |
| [Cilium][5주차] Cilium native + BGP 활용 (2) | 2025.08.16 |