Kubernetes 환경에서 효과적인 로드 밸런싱 및 트래픽 관리를 위해서는 Ingress Controller가 필요합니다. Ingress Controller는 다양한 솔루션이 있지만 이 중에서 가장 많은 점유율을 가지고 있는 NGINX Ingress Controller를 구성하는 방법을 살펴보겠습니다. NGINX Plus 이미지를 사용하여 NGINX Ingress Controller 구축하고 테스트를 해보겠습니다.
해당 가이드를 참고하여 서버를 구축해주세요.
링크를 통해 NGINX Plus Trial License를 준비합니다.
.crt, .key, .jwt 파일을 준비합니다.
Ingress Controller에서 NGINX Plus 기능을 활성화하기 위해서 .jwt 파일을 Secret에 등록해야 합니다.
kubectl create secret docker-registry regcred --docker-server=private-registry.nginx.com --docker-username=<JWT Token 값> --docker-password=none -n nginx-ingress
준비한 .jwt 파일의 값을 사용하여 secret을 생성합니다.
해당 가이드를 참고하여 사설 인증서를 생성합니다. 인증서를 보유하고 있다면 그 인증서를 사용하시면 됩니다.
kubectl create secret tls tls-secret --key <key path> --cert <crt path>
NGINX Ingress Controller를 올리기 위해 필요한 인증서를 secret으로 생성합니다.
LB가 없으면 클러스터 내부의 서비스를 외부로 노출시키기 위한 외부 IP 주소를 할당할 수 없으므로 LB가 필요합니다.
일반적으로 Cloud 환경에서 구축한 Kubernetes(EKS, AKS GKE 등)는 자체적으로 LB를 제공해주지만, On-Premise 환경에서는 직접 구축해야 합니다.
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
metalLB 배포 후, 사용하기 위해서는 추가적으로 IP Pool을 설정해야 합니다.
vi metallb_ip_pool.yaml
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- <Kubernetes Cluster IP>/32
autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default
addresses: Kubernetes Cluster의 실제 IP를 지정해야 합니다.kubectl apply -f metallb_ip_pool.yaml
IP Pool을 배포하여 사전 준비를 마무리합니다.
kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v3.5.0/deploy/crds.yaml
NGINX Ingress Controller를 사용하기 위해 Kubernetes에 CRD를 등록합니다.
git clone https://github.com/kubernetes/ingress-nginx
Ingress Controller를 구축하기 위한 공식 Helm Chart를 가져옵니다.
cd ingress-nginx/charts/ingress-nginx
vi values.yaml
controller:
# ..............................생략..............................
nginxplus: true # Nginx Plus 활성화
# ..............................생략..............................
image:
repository: private-registry.nginx.com/nginx-ic-nap-dos/nginx-plus-ingress # Nginx Plus Image 지정
# ..............................생략..............................
defaultTLS:
secret: "nginx-ingress/tls-secret"
wildcardTLS:
secret: "nginx-ingress/tls-secret"
# ..............................생략..............................
serviceAccount:
imagePullSecretName: regcred # JWT Token 값을 사용하여 Nginx Plus 인증
# ..............................생략..............................
NGINX Plus를 사용하기 위해 values 파일을 일부 수정합니다.
helm install nginx-ingress-controller -f values.yaml -n nginx-ingress ./
배포를 시작합니다.
kubectl get pod -n nginx-ingress
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-controller-9f9c7bc8-g4bw7 1/1 Running 0 3m4s
정상적으로 pod가 올라감을 확인합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
name: hello-world
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: load-balancer-example
template:
metadata:
labels:
app.kubernetes.io/name: load-balancer-example
spec:
containers:
- image: gcr.io/google-samples/node-hello:1.0
name: hello-world
ports:
- containerPort: 8080
간단한 문구를 출력해주는 Test Deployment를 배포합니다.
apiVersion: v1
kind: Service
metadata:
name: hello-world-service
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app.kubernetes.io/name: load-balancer-example
sessionAffinity: None
type: ClusterIP
VirtualServer가 대상으로 할 Service를 배포합니다.
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: hello-world-vs
spec:
host: hello.gweowe.com
upstreams:
- name: hello
service: hello-world-service
port: 8080
routes:
- path: /
action:
pass: hello
VirtualServer는 NGINX CRD를 사용하여 배포합니다.
기재되어 있는 spec에 대한 설명은 다음과 같습니다. 더 자세한 내용은 링크를 참고해주세요.
host: VirtualServer 리소스를 사용하여 외부로 노출시킬 도메인입니다. Ingress 및 VirtualServer 리소스에서 중복되서는 안됩니다.upsteam: 라우팅할 upstream을 구성합니다.name: upstream의 이름을 기재합니다. service: 라우팅할 Service를 지정합니다. 해당 Service는 VirtualServer와 동일한 namespace에 존재해야 합니다.port: 실제로 라우팅할 Service의 Port를 지정합니다.routes: VirtualServer의 경로를 구성합니다.path: 도메인으로 라우팅할 경로를 지정합니다. 이는 Pod에서 사용하고 있는 경로와 일치해야 합니다.action: 요청에 대해 수행할 작업을 구성합니다.pass: 요청을 전달할 upstream 이름을 지정합니다. 해당 이름은 upstream에서 기재한 이름과 일치해야 합니다.255.255.255.255 broadcasthost
::1 localhost
<Kubernetes Cluster IP> hello.gweowe.com
테스트를 위해 Host에 넣은 도메인을 /etc/hosts 파일에 추가하여 진행했습니다.
kubectl get vs
VirtualServer가 제대로 배포되었는지 확인합니다.
NAME STATE HOST IP PORTS AGE
hello-world-vs Valid hello.gweowe.com xxx.xxx.xxx.xxx [80,443] 157m
STATE가 Valid임을 확인할 수 있습니다.
curl hello.gweowe.com
Hello Kubernetes!
배포한 VirtualServer를 대상으로 curl 명령어를 날려서 정상적으로 출력되었음을 확인할 수 있습니다.