본문 바로가기

가상화/Kubernetes

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

반응형

개요

이전 시간에는 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

반응형