HTTPS 예제

HTTPS 예제 (HTTPS Example)

이 예제는 앞선 HTTP 예제를 바탕으로 두 HTTP 라우트에 TLS 종료(termination)를 추가해요. 간단히 하기 위해 productpage로 가는 두 번째 라우트는 생략했어요.

출처: HTTPS Example

본문

이 예제는 앞선 HTTP 예제를 바탕으로 두 HTTP 라우트에 TLS 종료를 추가해요. 간단히 하기 위해 productpage로 가는 두 번째 라우트는 생략했어요.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: tls-gateway
spec:
  gatewayClassName: cilium
  listeners:
  - name: https-1
    protocol: HTTPS
    port: 443
    hostname: "bookinfo.cilium.rocks"
    tls:
      certificateRefs:
      - kind: Secret
        name: ca
  - name: https-2
    protocol: HTTPS
    port: 443
    hostname: "hipstershop.cilium.rocks"
    tls:
      certificateRefs:
      - kind: Secret
        name: ca
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: https-app-route-1
spec:
  parentRefs:
  - name: tls-gateway
  hostnames:
  - "bookinfo.cilium.rocks"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /details
    backendRefs:
    - name: details
      port: 9080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: https-app-route-2
spec:
  parentRefs:
  - name: tls-gateway
  hostnames:
  - "hipstershop.cilium.rocks"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: productpage
      port: 9080

TLS 인증서와 개인 키 생성하기 (Create TLS Certificate and Private Key)

데모 목적으로는 만들어낸 셀프 사이닝 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 시크릿을 만들어볼게요:

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

(대안) 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

Gateway와 HTTPRoute 배포하기 (Deploy the Gateway and HTTPRoute)

이 데모의 Gateway 구성은 details와 productpage 서비스에 대해 유사한 라우팅을 제공해요.

$ kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/gateway/basic-https.yaml

cert-manager에게 이 Ingress에 인증서가 필요하다고 알리려면, 앞에서 만든 CA issuer의 이름으로 Gateway에 어노테이션을 달아주세요:

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

그러면 TLS 인증서가 포함된 Certificate 객체와 Secret이 생성돼요.

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

외부 IP 주소는 Gateway에 표시돼요. 또한 관련 HTTPRoute에는 호스트 이름이 표시돼야 해요.

$ kubectl get gateway tls-gateway
NAME          CLASS    ADDRESS         PROGRAMMED   AGE
tls-gateway   cilium   10.104.247.23   True         29s

$ kubectl get httproutes https-app-route-1 https-app-route-2
NAME                HOSTNAMES                      AGE
https-app-route-1   ["bookinfo.cilium.rocks"]      29s
https-app-route-2   ["hipstershop.cilium.rocks"]   29s

Gateway의 호스트 이름과 IP 주소로 /etc/hosts를 업데이트해볼게요:

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

HTTPS 요청 보내기 (Make HTTPS Requests)

curl 요청에 CA의 인증서를 지정하면 해당 CA가 서명한 인증서를 신뢰한다고 말하는 셈이 돼요.

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

원한다면 CA를 제공하는 대신 -k를 지정해서 curl 클라이언트가 서버의 인증서를 검증하지 않도록 할 수도 있어요. 둘 중 어느 것도 없으면 알 수 없는 기관이 서명한 인증서라는 오류가 나요.

curl 요청에 -v를 지정하면 TLS 핸드셰이크가 성공적으로 일어났음을 볼 수 있어요.

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

더 알아보기 (Learn more)