k8s 클러스터에서 alb ingress controller를 사용하다가 rewrite가 안되서 기록합니다.
├── / --> nginx
└── /api --> nest.js 서버
이렇게 라우팅을 해야하는 상황이었습니다.
다만 /로 요청이 들어오면 / 뒤의 값을 그대로 전달하고
/api로 요청이 들어오면 api 뒤의 값만 전달해야했습니다.
예를 들면
/image/pic1.png --> /image/pic1.png (nginx로 라우팅)
/api/questions/1 --> /questions/1 (nest.js 서버로 라우팅)
/api/ --> / (nest.js 서버로 라우팅)
/favicon.ico --> /favicon.ico (nginx로 라우팅)
이렇게 동작하길 원했습니다.
하지만 alb ingress controller 로는 구현에 실패했습니다.
뭔가 방법이 있는지는 모르겠지만 공식문서와 stack overflow를 찾아본 결과 지원하지 않는 기능으로 보입니다.
차라리 api.domain.com처럼 api에 대해 서브도메인을 썼다면 alb ingress controller로도 구현이 가능했을 것 같지만 이제 와서 api를 수정할 순 없었습니다.
일단 rewrite를 지원하는 nginx ingress controller를 사용하기로 했습니다.
현재 k8s 클러스터 밖에 있는 테스트 서버의 경우 이미 아래의 nginx config로 잘 동작하고 있었기 때문에 걱정도 덜했습니다.
server {
listen 80;
location /api/ {
proxy_pass http://172.17.0.5:3000/;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
location / {
# react 서버로 전달(위와 동일한 방식)
}
}
이제 ingress에 이 설정을 동일하게 적용하기만 하면 됐습니다.
nginx에선 /api/ 이렇게 적으면 알아서 접두사를 제거해줬는데 왜 여기선 안해주는지 참..
저는 helm chart를 사용했지만 결과물 ingress만 보여드리겠습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example
labels:
helm.sh/chart: example-0.1.0
app.kubernetes.io/name: example
app.kubernetes.io/instance: release-name
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- "www.exmaple.com"
secretName: letsencrypt-prod
rules:
- host: "www.exmaple.com"
http:
paths:
- path: /api/(.*)
pathType: Prefix
backend:
service:
name: example-api
port:
number: 3000
- path: /(.*)
pathType: Prefix
backend:
service:
name: example-react
port:
number: 80
이렇게 구현한 결과 모든 기능이 제가 원하는 대로 작동합니다.
한가지 불만이 있다면 /api가 react 서버로 전달된다는 점인데 크게 중요하진 않아서 이대로 놔두고 있습니다ㅎㅎ
사실 그리 어려운 문제는 아닌데 react 컨테이너 이미지를 잘못 만들어서 오랫동안 고생했네요. conf 넣는 걸 깜박했어요;
읽어주셔서 감사합니다.