TLS 종료가 포함된 Ingress 예제

TLS 종료가 포함된 Ingress 예제 (Ingress Example with TLS Termination)

이 예제는 HTTP 및 gRPC Ingress 예제를 기반으로 TLS 종료(termination)를 추가한 내용이에요. 같은 라우팅 규칙을 사용하면서도 HTTPS 요청을 받아 처리하는 방법을 다룹니다.

출처: Ingress Example with TLS Termination

본문

아래 두 애플리케이션을 사용하는 TLS Ingress 예제입니다.

# TLS ingress example, requires the below two applications
# https://raw.githubusercontent.com/istio/istio/release-1.11/samples/bookinfo/platform/kube/bookinfo.yaml
# https://github.com/GoogleCloudPlatform/microservices-demo
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
  namespace: default
spec:
  ingressClassName: cilium
  rules:
  - host: hipstershop.cilium.rocks
    http:
      paths:
      - backend:
          service:
            name: productcatalogservice
            port:
              number: 3550
        path: /hipstershop.ProductCatalogService
        pathType: Prefix
      - backend:
          service:
            name: currencyservice
            port:
              number: 7000
        path: /hipstershop.CurrencyService
        pathType: Prefix
  - host: bookinfo.cilium.rocks
    http:
      paths:
      - backend:
          service:
            name: details
            port:
              number: 9080
        path: /details
        pathType: Prefix
      - backend:
          service:
            name: productpage
            port:
              number: 9080
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - bookinfo.cilium.rocks
    - hipstershop.cilium.rocks
    secretName: demo-cert

TLS 인증서와 개인 키 만들기

Self-signed Certificate

시연 목적으로 가상의 자가 서명 인증 기관(CA)이 서명한 TLS 인증서를 사용할 거예요. 이를 위한 가장 쉬운 방법 중 하나는 mkcert를 사용하는 것입니다. 이 예제에서 사용하는 호스트 이름인 bookinfo.cilium.rocks와 hipstershop.cilium.rocks를 검증할 수 있는 인증서가 필요해요.

$ mkcert bookinfo.cilium.rocks hipstershop.cilium.rocks
Note: the local CA is not installed in the system trust store.
Run "mkcert -install" for certificates to be trusted automatically ⚠️

Created a new certificate valid for the following names 📜
 - "bookinfo.cilium.rocks"
 - "hipstershop.cilium.rocks"

The certificate is at "./bookinfo.cilium.rocks+1.pem" and the key at "./bookinfo.cilium.rocks+1-key.pem" ✅

It will expire on 29 November 2026 🗓

이 데모 키와 인증서로 Kubernetes secret을 만드세요.

$ kubectl create secret tls demo-cert --key=bookinfo.cilium.rocks+1-key.pem --cert=bookinfo.cilium.rocks+1.pem

cert-manager

cert-manager를 설치해 봅시다.

$ helm repo add jetstack https://charts.jetstack.io
$ helm install cert-manager jetstack/cert-manager --version v1.16.2 \
    --namespace cert-manager \
    --set crds.enabled=true \
    --create-namespace \
    --set config.apiVersion="controller.config.cert-manager.io/v1alpha1" \
    --set config.kind="ControllerConfiguration" \
    --set config.enableGatewayAPI=true

이제 CA Issuer를 만드세요.

$ kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/servicemesh/ca-issuer.yaml

Ingress 배포

이 데모의 Ingress 구성은 기존 데모들과 동일한 라우팅을 제공하면서 TLS 종료가 추가된 형태예요.

Self-signed Certificate

$ kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/servicemesh/tls-ingress.yaml

cert-manager

$ kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/servicemesh/tls-ingress.yaml

이 Ingress가 인증서를 필요로 한다는 것을 cert-manager에 알리려면, 앞서 만든 CA issuer 이름으로 Ingress에 어노테이션을 추가하세요.

$ kubectl annotate ingress tls-ingress cert-manager.io/issuer=ca-issuer

그러면 TLS 인증서를 담은 Secret과 함께 Certificate 오브젝트가 만들어져요.

$ kubectl get certificate,secret demo-cert
NAME                                    READY   SECRET      AGE
certificate.cert-manager.io/demo-cert   True    demo-cert   33m
NAME               TYPE                DATA   AGE
secret/demo-cert   kubernetes.io/tls   3      33m

External IP 주소는 Ingress에 표시돼요.

$ kubectl get ingress
NAME          CLASS    HOSTS                                            ADDRESS        PORTS     AGE
tls-ingress   cilium   hipstershop.cilium.rocks,bookinfo.cilium.rocks   35.195.24.75   80, 443   6m5s

이 Ingress 구성에서 hipstershop.cilium.rocks와 bookinfo.cilium.rocks 호스트 이름은 경로 라우팅 규칙에 명시돼 있어요. 클라이언트는 접근하려는 호스트를 지정해야 합니다. 이는 로컬의 /etc/hosts 파일을 편집해서 달성할 수 있어요. (이 파일을 편집하려면 거의 확실히 superuser 권한이 필요합니다.) Ingress 서비스에 할당된 IP 주소로 항목을 추가해서, 파일이 다음과 비슷하게 보이게 만드세요:

$ sudo perl -ni -e 'print if !/\.cilium\.rocks$/d' /etc/hosts; sudo tee -a /etc/hosts \
  <<<"$(kubectl get ing tls-ingress -o=jsonpath='{.status.loadBalancer.ingress[0].ip}') bookinfo.cilium.rocks hipstershop.cilium.rocks"

HTTPS 요청 보내기

Self-signed Certificate

curl 요청에 CA의 인증서를 지정하면, 그 CA가 서명한 인증서를 신뢰한다는 뜻이 돼요.

$ curl --cacert minica.pem -v https://bookinfo.cilium.rocks/details/1

원한다면 CA를 지정하는 대신 -k를 사용해서 curl 클라이언트가 서버의 인증서를 검증하지 않게 할 수도 있어요. 둘 다 지정하지 않으면 "알 수 없는 기관(unknown authority)이 서명한 인증서"라는 오류가 발생합니다.

curl 요청에 -v를 지정하면 TLS 핸드셰이크가 성공적으로 일어난 것을 확인할 수 있어요.

gRPC 요청에도 비슷하게 CA를 지정할 수 있어요:

# Download demo.proto file if you have not done before
$ curl -o demo.proto https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/protos/demo.proto
$ grpcurl -proto ./demo.proto -cacert minica.pem hipstershop.cilium.rocks:443 hipstershop.ProductCatalogService/ListProducts

cert-manager

$ curl https://bookinfo.cilium.rocks/details/1

gRPC 요청에도 비슷하게 CA를 지정할 수 있어요:

grpcurl -proto ./demo.proto -cacert minica.pem hipstershop.cilium.rocks:443 hipstershop.ProductCatalogService/ListProducts

Note

아직 demo.proto 파일을 내려받지 않았다면 gRPC Ingress 예제를 참고하세요.

브라우저에서 https://bookinfo.cilium.rocks를 방문할 수도 있어요. 브라우저가 인증 기관을 알 수 없다고 경고할 수 있지만, 이 경고를 넘어서면 bookstore 애플리케이션 홈페이지가 보일 거예요.

https://를 지정하지 않으면 요청이 타임아웃된다는 점을 기억하세요.

더 알아보기 (Learn more)