가상화/Kubernetes

[kubernetes] 인그레스(Ingress)를 사용하여 HTTP(S) 부하 분산기 구성 #2 - HTTPS 부하 분산

날았다 고양이 2020. 4. 7. 14:23
반응형

개요

이전 시간에는 HTTP 트래픽에 대한 부하 분산기 구성에 대해 알아보았다. 이번 시간에는 HTTPS 트래픽에 대한 부하 분산기 구성에 대해서 알아 보도록 하자.

구성환경

kubernetes v1.17.4, docker-ce 19.03.8, nginx-ingress-controller 0.30.0

구성절차

1. ngninx-ingress-controller 설치 및 서비스 생성
2. 앱 배포 만들기
3. 인증서 및 키 만들기
4. 인그레스에 대한 인증서 지정 
5. 부하 분산기 테스트

 

1. ingress-controller 설치 및 서비스 생성

 1.1 nginx-ingress-controller 설치

shell> kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
namespace/ingress-nginx unchanged
configmap/nginx-configuration unchanged
configmap/tcp-services unchanged
configmap/udp-services unchanged
serviceaccount/nginx-ingress-serviceaccount unchanged
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole unchanged
role.rbac.authorization.k8s.io/nginx-ingress-role unchanged
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding unchanged
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding unchanged
deployment.apps/nginx-ingress-controller created
limitrange/ingress-nginx configured
shell>

 1.2 확인

shell>  kubectl get pod -n ingress-nginx -o wide
NAME                                        READY   STATUS    RESTARTS   AGE     IP          NODE      NOMINATED NODE   READINESS GATES
nginx-ingress-controller-7f74f657bd-9zgfp   1/1     Running   0          3m15s   10.45.0.1  worker2              
shell>  kubectl get deploy -n ingress-nginx
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
nginx-ingress-controller   1/1     1            1           4m19s
shell>

  - nginx-ingress-controller 파드는 master 노드에서 실행되지 않기를 권고한다. nginx-ingress-controller는 DNS서브도메인의 IP를 가진 Worker Node에서 실행되도록한다. 특정 노드에서 nginx-igress-controller가 실행될수 있도록 아래의 예시를 참조하도록 한다.. 

- 예시 ) woker2 노드에서 실행중인 ingress-controller를 woker1로 변경

shell> kubectl get node
NAME        STATUS   ROLES    AGE   VERSION
master1    Ready    master   16d   v1.17.4
master2    Ready    master   15d   v1.17.4
master3   Ready    master   16d   v1.17.4
woker1   Ready    <none>   16d   v1.17.4
worker2    Ready    <none> 22h   v1.17.4
shell> kubectl get pod -n ingress-nginx -o wide
NAME                                        READY   STATUS    RESTARTS   AGE   IP          NODE      NOMINATED NODE   READINESS GATES
nginx-ingress-controller-7f74f657bd-9zgfp   1/1     Running   0          23m   10.45.0.1   worker2             
shell> kubectl label nodes worker1 node-role.kubernetes.io/ingress="true"
node/worker1 labeled
shell> kubectl -n ingress-nginx patch deployment nginx-ingress-controller -p '{"spec": {"template": {"spec": {"nodeSelector": {"node-role.kubernetes.io/ingress": "true"}}}}}'
deployment.apps/nginx-ingress-controller patched
shell> kubectl get pod -n ingress-nginx -o wide
NAME                                        READY   STATUS    RESTARTS   AGE    IP          NODE        NOMINATED NODE   READINESS GATES
nginx-ingress-controller-844c7cd44f-s7xjr   1/1     Running   0          2m2s   10.38.0.3   worker1              
shell>  kubectl get node
NAME        STATUS   ROLES     AGE   VERSION
master1    Ready    master       16d      v1.17.4
master2    Ready    master        31h     v1.17.4
master2    Ready    master       16d      v1.17.4
worker1    Ready    ingress    16d      v1.17.4
worker2    Ready    <none>      16d      v1.17.4

shell>

 1.3 인그레스 서비스 생성

shell> kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/cloud-generic.yaml
service/ingress-nginx created 
shell> kubectl get service -n ingress-nginx 
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE 
ingress-nginx   LoadBalancer   10.98.191.164   <pending>        80:30998/TCP,443:31101/TCP   89s 
shell>

EXTERNAL-IP가 pending 상태로 지속된다면  아래 명령어로 EXTERNAL-IP를 추가해 주도록 한다. 여기서 EXTERNAL-IP는 DNS서브도메인의 IP이다.

shell> kubectl patch svc ingress-nginx -n ingress-nginx -p '{"spec": {"type": "LoadBalancer", "externalIPs":["192.168.0.148"]}}'
service/ingress-nginx patched
shell>  kubectl get svc -n ingress-nginx
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx   LoadBalancer   10.98.191.164   192.168.0.148   80:30998/TCP,443:31101/TCP   24m
shell> 

 1.4 참조 : ingress controller 버전 확인 방법

shell> POD_NAMESPACE=ingress-nginx
shell> POD_NAME=$(kubectl get pods -n $POD_NAMESPACE -l app.kubernetes.io/name=ingress-nginx -o jsonpath='{.items[0].metadata.name}')
shell> kubectl exec -it $POD_NAME -n $POD_NAMESPACE -- /nginx-ingress-controller --version
-------------------------------------------------------------------------------
NGINX Ingress controller
  Release:       0.30.0
  Build:         git-7e65b90c4
  Repository:    https://github.com/kubernetes/ingress-nginx
  nginx version: nginx/1.17.8

-------------------------------------------------------------------------------

shell>

 

2. 앱 배포 만들기

[kubernetes] 인그레스(Ingress)를 사용하여 HTTP(S) 부하 분산기 구성 #1 - HTTPS 부하 분산 의 2. 앱 배포 참조 

 

3. 인증서(사설) 및 키 만들기

shell> openssl genrsa -out hoya.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................+++++
........................................+++++
e is 65537 (0x010001)
shell> openssl req -new -key hoya.key -out hoya.csr -subj "/CN=www.hoya.com"
shell> openssl x509 -req -days 365 -in hoya.csr -signkey hoya.key -out hoya.crt
Signature ok
subject=CN = www.hoya.com
Getting Private key
shell> ls
hoya.crt  hoya.csr  hoya.key  nginx-ingress-controller.yaml  static-ip-svc.yaml
shell>

 

4. 인그레스에 대한 인증서 지정 

 4.1 부하 분산기의 인증서 제공

shell> kubectl create secret tls hoya-com-secret --cert hoya.crt --key hoya.key
secret/hoya-com-secret created
shell> 

 4.2 인그레스 만들기

 - 인그레스 매니페스트(hoya-com-ingress.yaml)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hoya-com-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1 # 트래픽을 리디렉션해야하는대상 URI

spec:
  tls:
  - secretName: hoya-com-secret
  rules:
  - host: www.hoya.com
    http:
      paths:
        - path: /
          backend:
            serviceName: web
            servicePort: 8080
        - path: /v2/*
          backend:
            serviceName: web2
            servicePort: 8080

* 인그레스 rewrite 설정 : https://kubernetes.github.io/ingress-nginx/examples/rewrite/ 

- 인그레스 리소스 생성 및 확인

shell> kubectl apply -f hoya-com-ingress.yaml
ingress.extensions/hoya-com-ingress created
shell> kubectl get ingress 
NAME               HOSTS          ADDRESS         PORTS     AGE
hoya-com-ingress   www.hoya.com   192.168.0.148   80, 443   33s
shell>

5. 부하 분산기 테스트

shell> curl -k https://www.hoya.com/ 
Hello, world! 
Version: 1.0.0 
Hostname: web-9bbd7b488-rdmf2 
shell>
shell> curl -k https://www.hoya.com/v2/
Hello, world! 
Version: 2.0.0 
Hostname: web2-74cf4946cc-m2bxg 
shell>

 

참고

웹서버를 운영하다 보면 웹접속 로그를 분석할 경우가 많이 있다.  근데 인그레스 구성에서 클러스터 외부에서 컨테이너 접속을 할경우 컨테이너에서는 실제 접속하는 클라이언트의 IP를 확인할 수 없다. 그 이유는 nginx-ingress-controller에 패킷이 도착전 SNAT가 먼저 이루어지기 때문인데,  컨테이너에서 클러스터 외부에서의 웹접속 로그를 보면 모두 cni의 IP가 찍히는 것을 알수 있다. 이를 해결할 방법으로는 클러스터 외부에 proxy 서버를 구성하여  X-Forwarded-For 헤더를 추가해 주어야만 한다.

참조 문서 :

 - 인그레스 컨트롤러 설치 : https://kubernetes.github.io/ingress-nginx/deploy/  

 - 인그레스 구성 :  https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-multi-ssl?hl=ko

반응형