1. 정규표현식 경로 라우팅 에러 현상
쿠버네티스 클러스터에 API를 디플로이먼트로 배포하고 포스트맨에서 URL 호출 테스트를 해보았다. 응답으로 Json 데이터가 내려올 것이라고 생각했지만, 실제로는 404 에러응답이 내려왔다.
도커 이미지부터 인그레스까지 처음부터 다시 살펴보았지만 파드와 서비스들은 모두 정상적으로 동작하고 있었다. 그렇게 멘붕에 빠져있을 때 쿠버네티스 로그에 뭔가 있지않을까라는 생각으로 로그를 확인해봤다. 그러다가 Nginx Ingress Controller에서 문제와 관련된 아래 로그를 발견하였다.
kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-88p6b 0/1 Completed 0 48d
ingress-nginx-admission-patch-qk6rs 0/1 Completed 1 48d
ingress-nginx-controller-6b9f5b98f8-vkpvb 1/1 Running 0 136m
kubectl logs ingress-nginx-controller-6b9f5b98f8-vkpvb -n ingress-nginx
-------------------------------------------------------------------------------
NGINX Ingress controller
Release: v1.6.3
Build: 7ae9ca2f1d04ccdc818fd0d3fb0193266b739d68
Repository: https://github.com/kubernetes/ingress-nginx
nginx version: nginx/1.21.6
-------------------------------------------------------------------------------
W0706 13:19:55.654978 7 client_config.go:618] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.
I0706 13:19:55.655290 7 main.go:209] "Creating API client" host="https://10.96.0.1:443"
I0706 13:19:55.663892 7 main.go:253] "Running in Kubernetes cluster" major="1" minor="28" git="v1.28.10" state="clean" commit="21be1d76a90bc00e2b0f6676a664bdf097224155" platform="linux/amd64"
I0706 13:19:56.048647 7 main.go:104] "SSL fake certificate created" file="/etc/ingress-controller/ssl/default-fake-certificate.pem"
I0706 13:19:56.079234 7 ssl.go:533] "loading tls certificate" path="/usr/local/certificates/cert" key="/usr/local/certificates/key"
I0706 13:19:56.098355 7 nginx.go:261] "Starting NGINX Ingress controller"
I0706 13:19:56.173760 7 event.go:285] Event(v1.ObjectReference{Kind:"ConfigMap", Namespace:"ingress-nginx", Name:"ingress-nginx-controller", UID:"52f5ec3d-e99c-4181-ad56-747425d1e15f", APIVersion:"v1", ResourceVersion:"3998805", FieldPath:""}): type: 'Normal' reason: 'CREATE' ConfigMap ingress-nginx/ingress-nginx-controller
I0706 13:19:57.204064 7 store.go:434] "Found valid IngressClass" ingress="default/ingress-nginx" ingressclass="nginx"
W0706 13:19:57.204270 7 store.go:869] ingress default/ingress-nginx contains invalid path /gold(/|$)(.*)
I0706 13:19:57.204303 7 event.go:285] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"ingress-nginx", UID:"79dbfb39-638a-40ad-a013-cc57a6cbdae3", APIVersion:"networking.k8s.io/v1", ResourceVersion:"1959093", FieldPath:""}): type: 'Normal' reason: 'Sync' Scheduled for sync
I0706 13:19:57.301287 7 nginx.go:304] "Starting NGINX process"
I0706 13:19:57.301674 7 leaderelection.go:248] attempting to acquire leader lease ingress-nginx/ingress-nginx-leader...
I0706 13:19:57.306046 7 status.go:84] "New leader elected" identity="ingress-nginx-controller-779fc596cd-tcztk"
I0706 13:19:57.306554 7 nginx.go:324] "Starting validation webhook" address=":8443" certPath="/usr/local/certificates/cert" keyPath="/usr/local/certificates/key"
I0706 13:19:57.306997 7 controller.go:188] "Configuration changes detected, backend reload required"
I0706 13:19:57.463812 7 controller.go:205] "Backend successfully reloaded"
I0706 13:19:57.463958 7 controller.go:216] "Initial sync, sleeping for 1 second"
I0706 13:19:57.464551 7 event.go:285] Event(v1.ObjectReference{Kind:"Pod", Namespace:"ingress-nginx", Name:"ingress-nginx-controller-6b9f5b98f8-vkpvb", UID:"22c7b156-29cf-4a1e-9389-805edae1d69d", APIVersion:"v1", ResourceVersion:"3998839", FieldPath:""}): type: 'Normal' reason: 'RELOAD' NGINX reload triggered due to a change in configuration
I0706 13:20:56.432434 7 leaderelection.go:258] successfully acquired lease ingress-nginx/ingress-nginx-leader
I0706 13:20:56.432467 7 status.go:84] "New leader elected" identity="ingress-nginx-controller-6b9f5b98f8-vkpvb"
I0706 15:35:15.678985 7 admission.go:149] processed ingress via admission controller {testedIngressLength:1 testedIngressTime:0.073s renderingIngressLength:1 renderingIngressTime:0.001s admissionTime:18.1kBs testedConfigurationSize:0.074}
I0706 15:35:15.679123 7 main.go:100] "successfully validated configuration, accepting" ingress="default/ingress-nginx"
W0706 15:35:15.685711 7 store.go:869] ingress default/ingress-nginx contains invalid path /shop(/|$)(.*)
I0706 15:35:15.685896 7 event.go:285] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"ingress-nginx", UID:"79dbfb39-638a-40ad-a013-cc57a6cbdae3", APIVersion:"networking.k8s.io/v1", ResourceVersion:"4017698", FieldPath:""}): type: 'Normal' reason: 'Sync' Scheduled for sync
로그를 보니 정규표현식을 사용한 부분이 잘못되었다고 나와있었다.
ingress default/ingress-nginx contains invalid path /shop(/|$)(.*)
ingress-config.yaml 의 정규표현식 부분이 문제인 것 같았다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- http:
paths:
- pathType: Prefix
path: /shop(/|$)(.*)
backend:
service:
name: shop-api-svc
port:
number: 80
그래서 이 문제로 구글링을 하다가 동일한 현상에 대해 어떤 분이 쓴 글을 발견했는데 결국은 버전 문제였다.
2. 인그레스 컨트롤러의 에러 원인
https://blog.frec.kr/troubleshooting/ingress_nginx_regex/
Ingress에 정의된 path에 regex 사용시 라우팅되지 않던 이슈
문제 상황 표면적으로 보이던 에러 상황 프론트엔드에서 로의 모든 request가 404 에러 발생 request가 도착해야할 pod에 어떠한 로그도 찍히지 않았다. 다만, ingress-nginx-controller 로그에는 request가 도
blog.frec.kr
글을 통해 인그레스 컨트롤러의 에러 원인에 대해 알 수 있었다. Nginx Ingress Controller 1.6.3 버전에 정규표현식 경로 라우팅 처리와 관련하여 잘못된 코드가 반영되었고 이로 인해 경로 라우팅에 정규표현식을 쓰면 404 에러가 발생한 것이었다.
if !ingressutils.IsSafePath(copyIng, path.Path) {
klog.Warningf("ingress %s contains invalid path %s", key, path.Path)
return
}
문제를 일으켰던 위 코드는 다음 버전인 1.6.4에서 삭제되어 정규표현식 경로 라우팅과 관련한 문제는 해결되었다. 그런데 언제부터인가 1.6.4 버전의 deploy.yaml의 내용에 실제 사용버전이 1.6.3으로 들어가 있는 문제가 확인되었다. 그래서 지금은 문제를 해결하기 위해서 버전을 업그레이드 한다면 1.6.4버전이 아니라 1.7.0 버전을 설치해주어야 한다. 실제로 Nginx Ingress Controller 공식 사이트를 가보면 1.6.4 버전은 없고 1.6.3 다음 버전으로 1.7.0 버전이 있는 것을 확인할 수 있다.
3. 인그레스 컨트롤러 버전 업그레이드
문제를 해결하기 위해서 Nginx Ingress Controller 1.7.0 버전을 받아서 설치해보자.
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.0/deploy/static/provider/cloud/deploy.yaml
kubectl apply -f deploy.yaml
설치가 완료된 후에는 1.7.0 버전이 맞는지 확인해보자.
kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-88p6b 0/1 Completed 0 48d
ingress-nginx-admission-patch-qk6rs 0/1 Completed 1 48d
ingress-nginx-controller-f58659849-qq89j 1/1 Running 0 62s
kubectl exec -it -n ingress-nginx-controller-f58659849-qq89j -- bash
kubectl exec -it -n ingress-nginx ingress-nginx-controller-f58659849-qq89j -- bash
/nginx-ingress-controller --version
-------------------------------------------------------------------------------
NGINX Ingress controller
Release: v1.7.0
Build: 72ff21ed9e26cb969052c753633049ba8a87ecf9
Repository: https://github.com/kubernetes/ingress-nginx
nginx version: nginx/1.21.6
-------------------------------------------------------------------------------
1.7.0 버전으로 설치된 것을 확인하였다.
4. 인그레스 컨트롤러 라우팅 테스트
다시 API 호출 테스트를 해보자.
Nginx Ingress Controller 경로 라우팅이 정상적으로 동작하여 API 응답이 잘 내려오는 것을 확인할 수 있다.
'Kubernetes' 카테고리의 다른 글
[Kubernetes] 쿠버네티스 클러스터 모니터링해보기 [4/4] (0) | 2024.05.25 |
---|---|
[Kubernetes] 쿠버네티스 서비스 알아보기 [3/4] (0) | 2024.05.11 |
[Kubernetes] 쿠버네티스 클러스터 구축해보기 [2/4] (0) | 2024.04.27 |