backend/kubernetes in action

[kubernetes in action] 5.4 Exposing services externally through an Ingress resource

seul chan 2020. 6. 8. 21:25

5.4 Exposing services externally through an Ingress resource

Ingress (noun)—The act of going in or entering; the right to enter; a means or place of entering; entryway.

Understanding why Ingresses are needed

LoadBalancer service는 각각의 load balancer마다 각자의 IP 주소가 있어야 하지만, Ingress는 여러 서비스에 한개의 IP 주소만 필요하다.

client가 HTTP 요청을 Ingress에게 보내면 request의 host와 path로 어떤 서비스로 포워딩할지를 결정한다.

Understanding that an Ingress controller is required

Ingress object를 사용하려면 Ingress controller가 필요하다.

GKE는 GCP의 HTTP 로드밸런싱 기능을 사용한다. Minikube의 경우에는 따로 controller를 제공하지 않지만 add-on을 사용하여 Ingress controller를 사용할 수 있다.

Enabling the Ingress add-on in Minikube

$ minikube addons list
|-----------------------------|----------|--------------|
|         ADDON NAME          | PROFILE  |    STATUS    |
|-----------------------------|----------|--------------|
| dashboard                   | minikube | disabled     |
| default-storageclass        | minikube | enabled ✅   |
| efk                         | minikube | disabled     |
| freshpod                    | minikube | disabled     |
| gvisor                      | minikube | disabled     |
| helm-tiller                 | minikube | disabled     |
| ingress                     | minikube | disabled     |
| ingress-dns                 | minikube | disabled     |
| istio                       | minikube | disabled     |
| istio-provisioner           | minikube | disabled     |
| logviewer                   | minikube | disabled     |
| metrics-server              | minikube | disabled     |
| nvidia-driver-installer     | minikube | disabled     |
| nvidia-gpu-device-plugin    | minikube | disabled     |
| registry                    | minikube | disabled     |
| registry-creds              | minikube | disabled     |
| storage-provisioner         | minikube | enabled ✅   |
| storage-provisioner-gluster | minikube | disabled     |
|-----------------------------|----------|--------------|

위에 ingressdisabled인 것을 볼 수 있다.

$ minikube addons enable ingress
🌟  The 'ingress' addon is enabled

$ minikube addons list | grep ingress
| ingress                     | minikube | enabled ✅   |
| ingress-dns                 | minikube | disabled     |
$ kubectl get po --all-namespaces
NAMESPACE     NAME                                               READY   STATUS             RESTARTS   AGE
default       kubia-766tj                                        1/1     Running            0          47h
default       kubia-qtfdt                                        1/1     Running            0          47h
default       kubia-zphvm                                        1/1     Running            0          47h
kube-system   coredns-6955765f44-9swsw                           1/1     Running            0          6d9h
kube-system   coredns-6955765f44-gllc6                           1/1     Running            0          6d9h
kube-system   etcd-m01                                           1/1     Running            4          36d
kube-system   kube-apiserver-m01                                 1/1     Running            4          36d
kube-system   kube-controller-manager-m01                        1/1     Running            28         36d
kube-system   kube-proxy-9558l                                   1/1     Running            4          36d
kube-system   kube-scheduler-m01                                 1/1     Running            29         36d
kube-system   nginx-ingress-controller-6fc5bcc8c9-zj58m          1/1     Running            0          53s

Creating an Ingress resource

kubia-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubia
spec:
  rules:
  - host: kubia.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kubia-nodeport
          servicePort: 80

kubia.example.com으로 request가 들어오면 kubia-nodeport 서비스의 80 포트로 보낸다.

Accessing the service through the ingress

$ kubectl create -f kubia-ingress.yaml
ingress.extensions/kubia created

$ kubectl get ingresses
NAME    HOSTS               ADDRESS   PORTS   AGE
kubia   kubia.example.com             80      14s

GKE의 경우에는 ADDRESS에 나온 결과를 사용하면 되고, minikube는 minikube service kubia-nodeport --url의 address를 사용하면 된다.

/etc/hosts (window의 경우에는 C:\windows\system32\drivers\etc\hosts)에 DNS를 수정해주어야한다.

192.168.64.4    kubia.example.com

이제 curl로 호출이 가능하다.

$ curl http://kubia.example.com
You've hit kubia-zphvm

image

Exposing multiple servies through the same Imgress

Ingress resource를 잘 살펴보면 rulespaths는 array로 되어 있어서 여러개를 담을 수 있다.

우선 여러 개의 paths를 가져 같은 호스트에 다른 서비스를 추가할 수 있다.

...
  - host: kubia.example.com
    http:
      paths:
      - path: /kubia                1
        backend:                    1
          serviceName: kubia        1
          servicePort: 80           1
      - path: /foo                  2
        backend:                    2
          serviceName: bar          2
          servicePort: 80           2
  • 1: kubia.example.com/kubia로 들어오는 requets는 kubia 서비스로 라우트
  • 2: kubia.example.com/foo로 들어오는 requets는 bar 서비스로 라우트

이와 비슷하게 path 대신 host를 기준으로 다른 서비스로 매핑시킬 수 있다.

spec:
  rules:
  - host: foo.example.com          1
    http:
      paths:
      - path: /
        backend:
          serviceName: foo         1
          servicePort: 80
  - host: bar.example.com          2
    http:
      paths:
      - path: /
        backend:
          serviceName: bar         2
          servicePort: 80
  • 1 Requests for foo.example.com will be routed to service foo.
  • 2 Requests for bar.example.com will be routed to service bar.

Configuring Ingress to handle TLS traffic

pod가 web server를 돌리면 이는 HTTP traffic밖에 받지 못하고 TLS와 관련된 모든 것은 Ingress controller가 처리하게 한다. 이를 위해서는 Ingress에 certificate와 private key가 필요하다.

이는 Kubernetes의 Secret이라는 리소스에 저장된다. 자세한 내용은 7장에서 설명되기 때문에 여기서는 그냥 사용하는 방법만 보면됨

우선 private key와 certificate 생성

$ openssl genrsa -out tls.key 2048
$ openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj /CN=kubia.example.com

$ kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key
secret/tls-secret created

private key와 certificate는 tls-secret이라는 secret resource에 저장되었다. 이제 Ingress를 HTTPS 리퀘스트를 받게 수정하자.

kubia-ingress-tls.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubia
spec:
  tls:
  - hosts: 
    - kubia.example.com
    secretName: tls-secret
  rules:
  - host: kubia.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kubia-nodeport
          servicePort: 80

기존 Ingress를 지우고 다시 만드는 대신 kubectl apply -f kubia-ingress-tls.yaml로 기존 Ingress resource를 update 하여도 된다.

이제 HTTPS로 서비스 접속이 가능하다.

$ curl -k -v https://kubia.example.com/kubia
* About to connect() to kubia.example.com port 443 (#0)
...
* Server certificate:
*   subject: CN=kubia.example.com
...
> GET /kubia HTTP/1.1
> ...
You've hit kubia-xueq1