Step 14 연습 과제 — 인그레스

전제: ingress-nginx 컨트롤러가 떠 있고, step14 네임스페이스에 tea/coffee/hello 서비스가 있으며, kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 18080:80 18443:443 로 접근한다고 가정.


과제 1. 경로 + 호스트 혼합

shop.example.com 에서 /tea 는 tea, /coffee 는 coffee 로 보내고, 같은 컨트롤러에서 blog.example.com/ 은 hello 로 보내는 Ingress 를 하나의 오브젝트로 작성하라.

해답
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mixed
  namespace: step14
spec:
  ingressClassName: nginx
  rules:
    - host: shop.example.com
      http:
        paths:
          - { path: /tea,    pathType: Prefix, backend: { service: { name: tea,    port: { number: 80 } } } }
          - { path: /coffee, pathType: Prefix, backend: { service: { name: coffee, port: { number: 80 } } } }
    - host: blog.example.com
      http:
        paths:
          - { path: /, pathType: Prefix, backend: { service: { name: hello, port: { number: 80 } } } }

검증:

curl -H "Host: shop.example.com" http://localhost:18080/tea       # tea
curl -H "Host: shop.example.com" http://localhost:18080/coffee    # coffee
curl -H "Host: blog.example.com" http://localhost:18080/ | grep -o "Hello from the hello service"

과제 2. rewrite-target 로 경로 벗겨 넘기기

/api/tea 로 들어온 요청의 앞 /api 를 떼고 백엔드에는 /tea 만 보이게 하고 싶다. nginx.ingress.kubernetes.io/rewrite-target 과 캡처 그룹((.*)) 을 써서 구성하라. (http-echo 는 경로와 무관하게 응답하므로, 실제 경로 재작성 여부는 실서비스에서 확인한다는 점을 명시하라.)

해답
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rewrite-demo
  namespace: step14
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend: { service: { name: tea, port: { number: 80 } } }
  • rewrite-target: /$2 는 정규식 두 번째 캡처 그룹((.*))을 백엔드 경로로 사용.
  • 정규식 경로에는 pathType: ImplementationSpecific 를 쓴다.
curl -H "Host: api.example.com" http://localhost:18080/api/tea   # tea (백엔드는 /tea 를 받음)

과제 3. 다중 호스트 TLS

a.example.comb.example.com 두 호스트를 각각 tea, coffee 로 보내되, 둘 다 HTTPS 로 서비스하라. 하나의 인증서(SAN 에 두 호스트 포함)로 처리한다.

해답
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /tmp/multi.key -out /tmp/multi.crt \
  -subj "/CN=a.example.com/O=step14" \
  -addext "subjectAltName=DNS:a.example.com,DNS:b.example.com"
kubectl create secret tls multi-tls -n step14 --cert=/tmp/multi.crt --key=/tmp/multi.key
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: { name: multi-tls, namespace: step14 }
spec:
  ingressClassName: nginx
  tls:
    - hosts: [a.example.com, b.example.com]
      secretName: multi-tls
  rules:
    - host: a.example.com
      http: { paths: [ { path: /, pathType: Prefix, backend: { service: { name: tea,    port: { number: 80 } } } } ] }
    - host: b.example.com
      http: { paths: [ { path: /, pathType: Prefix, backend: { service: { name: coffee, port: { number: 80 } } } } ] }
curl -k --resolve a.example.com:18443:127.0.0.1 https://a.example.com:18443/   # tea
curl -k --resolve b.example.com:18443:127.0.0.1 https://b.example.com:18443/   # coffee

과제 4. (함정 진단) 502/404 원인 찾기

동료가 만든 아래 Ingress 가 curl 하면 계속 404 가 난다. 원인 2가지를 찾아 고쳐라.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: { name: broken, namespace: step14 }
spec:
  # (a)
  rules:
    - host: broken.example.com
      http:
        paths:
          - path: /tea
            pathType: Prefix
            backend:
              service:
                name: tea
                port:
                  number: 5678   # (b)
해답
  • (a) ingressClassName: nginx 누락. 기본 IngressClass 가 없으면 아무 컨트롤러도 이 Ingress 를 안 맡는다 → ADDRESS 비어 있고 404. spec.ingressClassName: nginx 추가.
  • (b) 포트 번호가 컨테이너 포트(5678). Ingress 는 Service 의 port 를 가리켜야 한다. tea Service 의 port 는 80(→ targetPort 5678). number: 80 으로 수정.

진단 순서: kubectl get ingress broken -n step14(ADDRESS 확인) → kubectl describe ingress broken -n step14(Backends 뒤 엔드포인트 확인) → Service 의 포트(kubectl get svc tea -n step14)와 대조.


과제 5. pathType 함정

Exact/health 를 걸었더니 브라우저가 /health/ 로 접근해 404 가 난다. 왜인지 설명하고, /health/health/ 둘 다 받으려면 어떻게 해야 하는지 답하라.

해답
  • Exact 는 후행 슬래시까지 완전히 동일해야 매치한다. /health 규칙은 /health/ 를 매치하지 않는다.
  • 해결: pathType: Prefix 로 바꾸면 /health, /health/, /health/live 를 모두 매치한다. 정확히 두 경로만 원하면 규칙을 두 개(/health Exact, /health/ Exact) 두거나 Prefix 를 쓴다.