레이블이 caddy인 게시물을 표시합니다. 모든 게시물 표시
레이블이 caddy인 게시물을 표시합니다. 모든 게시물 표시

k8s 디폴트 서비스로 커스텀 에러 페이지 응답하기

# 다음과 같은 흐름에서
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 를 만들었다.
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

caddy web server 사용하기

# caddy 는 golang 로 작성된 웹서버 오픈소스다.
# 간단한 설정으로 원하는 스타일의 웹서버를 띄울 수 있다.
# 윈도우, 리눅스, 맥, 안드로이드 환경에서도 동작한다.
# osx 설치 (add on 미포함)
brew install caddy

# linux 설치
mkdir caddy && cd caddy
curl -L -O https://github.com/mholt/caddy/releases/download/v0.11.5/caddy_v0.11.5_linux_amd64.tar.gz
tar zxvf caddy_v0.11.5_linux_amd64.tar.gz

# 8080(디폴트) 포트로 기본 실행
caddy

# 접속해보기
http://localhost:8080

# 설정 파일 사용
# vi Caddyfile
# port
:8080

# 사용자 인증 id pw
basicauth / ysoftman qwer1234

# 기본 적인 파일 브라우징(읽기)만 하는 설정
# 서비스할 루트 경로
root /home/ysoftman/myfiles
browse /

# http.filebrowser 플러그인 사용시
https://docs.filebrowser.xyz/installation
# 브라우저로 접속시 파일 추가 삭제를 가능 한 설정
filemanager / {
    show    /home/ysoftman/myfiles
    myfiles:
    allow_new       true
    allow_edit      true
    allow_commands  true
    allow_command   rm
    allow_command   mv
    allow           dotfiles
}

# 이전 캐디 프로세스 죽이기
cat mycaddy.pid | xargs kill -9

# 데몬으로 캐디 띄우기
nohup ./caddy -conf ./Caddyfile -pidfile mycaddy.pid > mycaddy.out 2>&1 &

# ansible shell 로 nohup 사용시 다음과 같이 ()로 subshell 을 사용해야한다.
# () 가 없으면 ansible 실행 종료 후 nohup 실행이 종료된다.
- shell: (nohup ./caddy -conf ./Caddyfile -pidfile mycaddy.pid > mycaddy.out 2>&1 &)