# 다음과 같은 흐름에서
ysoftman.test.com --> 10.10.10.100 (VIP) --> 10.10.10.11,10.10.10.12 (ingress node)
# 도메인으로 접속을 하면 서비스나 nginx controller 의 custom errorpage 로 응답하는데,
curl ysoftman.test.com
# ip 로 요청하면 nginx 기본 404 page(html)을 응답준다.(nginx 정보가 표시되어 보안 수정 사항!)
curl 10.10.10.100
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
# nginx pod ssh 접속해 설정을 보면
vi /etc/nginx/nginx.conf
# backend 설정이 되지 않거나 endpoints 가 없는 경우 기본 404 페이지를 리턴한다.
... 생략 ...
# backend for when default-backend-service is not configured or it does not have endpoints
server {
listen 8181 default_server reuseport backlog=16777216;
set $proxy_upstream_name "internal";
access_log off;
location / {
return 404;
}
}
... 생략 ...
# 전체 네임스페이스를 찾아보니 디폴트 백엔드가 설정되지 않는 ingress 설정들이 있었다.
kubectl describe ing --all-namespaces | rg 'not found' -B 2
Namespace: aaaa
Address: 10.10.10.11,10.10.10.12
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
... 생략 ...
# 각 네임스페이스 인그레스에 디폴트 백엔드 설정을 하긴 힘들고
# 새 서비스 추가할때마다 backend servcie 설정을 신경써야 하기 때문에
# nginx controller daemoneset (없다면 deployment)의 yaml에 args 부분에
# 다음과 같이 default-backend-service 로 nginx-controller 자체에 디폴트 백엔드를 명시할 수 있다.
spec:
containers:
- args:
- /nginx-ingress-controller
- --enable-ssl-chain-completion=false
- --configmap=$(POD_NAMESPACE)/ingress-nginx
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --annotations-prefix=nginx.ingress.kubernetes.io
- --report-node-internal-ip-address
- --default-backend-service=ysoftman-namespace/ysoftman-service
# 기본적으로 default-backend-service 는 / 404 와 /healthz 200 만 노출한다.
# default-backend-service 으로 보낼 http 에러 코드를 추가 할 수있다.
# ingress-nginx-controller -> configmap 에 다음 키와 값을 추가한다
... 생략 ...
data:
custom-http-errors: 400,401,403,404,405,500,503,505
# 이제 default-backend-service 에서는 X-Code 등의 특정 헤더로 전달 받을 수 있다.
#####
# default-backend-service 는 다음 예제를 사용할수도 있지만
# caddy 도커 이미지로 default-backend-service 를 만들었다.
# caddy dockerfile(https://github.com/caddyserver/caddy-docker/blob/2093c4a571bfe356447008d229195eb7063232b2/2.3/alpine/Dockerfile)에 마지막 부분을 수정
COPY Caddyfile /etc/caddy/Caddyfile
# index.html 를 에러 페이지로 덮어쓰기
COPY error404.html /usr/share/caddy/error404.html
COPY error404.html /usr/share/caddy/index.html
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
# Caddyfile 은 다음과 같다.
:80
root * /usr/share/caddy
file_server
handle_errors {
# @404 {
# expression {http.error.status_code} == 404
# }
# rewrite @404 /error404.html
@fromNginxController40x {
header X-Code 40*
}
@fromNginxController50x {
header X-Code 50*
}
@4xx {
expression "{http.error.status_code} >= 400 && {http.error.status_code} < 500"
}
@5xx {
expression "{http.error.status_code} >= 500 & {http.error.status_code} < 600"
}
rewrite @fromNginxController40x /error404.html
rewrite @fromNginxController50x /error404.html
rewrite @4xx /error404.html
rewrite @5xx /error404.html
file_server
}
log {
level INFO
output file /tmp/caddylog.log {
roll_size 100MiB
roll_keep 5
roll_keep_for 48h
}
}
# caddy 를 로컬 컨테이너로 올려 테스트하면 설정한 에러 페이지가 잘 보인다.
curl http://localhost
curl http://127.0.0.1
curl http://127.0.0.1/aaaaa
# nginx controller --default-backend-service 에 설정하면 에러가 발생한다.
connect() failed (111: Connection refused) while connecting to upstream,
client: 10.10.10.11, server: _, request: "GET /aaaaa HTTP/1.1", upstream: "http://10.10.10.12:443/aaaaa"
# 위 에러 로그를 보면 http 인데 443 포트를 사용하고 있다.
# caddy default-backend-service 에 다음과 같이 443 포트가 설정되어 있었다.
apiVersion: v1
kind: Service
metadata:
namespace: default
name: default-backend-service
spec:
ports:
- name: caddy-https
port: 443
targetPort: 443
- name: caddy-http
port: 80
targetPort: 80
selector:
app: default-backend-service-deployment
# http 인데도 443 포트를 우선으로 시도 하는 것으로 보인다.
# 443 포트 설정을 제거하고 80 포트만 사용하니 잘된다.
spec:
ports:
- name: caddy-http
port: 80
targetPort: 80