지난번 포스팅에서는 마스터 노드가 로드밸런서 역할을 하게끔 구성했는데 트래픽이 늘어남에 따라 마스터 노드가 사용할 리소스가 줄어드는 것은 좋지 않다고 생각하여 외부 로드밸런서를 구성해 보기로 했습니다.
워커 노드를 생성하는 절차를 그대로 따라서 로드밸런서 노드를 생성합니다. 레이블은 노드 이름은 k8s-loadbalancer
, 레이블은 type=lb
로 주도록 하겠습니다.
Baremetal
용 Ingress Controller
설치하기baremetal
용 컨트롤러를 설치하겠습니다.$ curl -L -o ingress-nginx-controller.yml \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/baremetal/deploy.yaml
controller
, admission-create
, admission-patch
세 파드는 k8s-loadbalancer
노드에서 동작하도록 nodeAffinity
를 추가해 줍니다.# ingress-nginx-controller.yml
...
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: type
operator: In
values:
- lb
$ kubectl apply -f ingress-nginx-controller.yml
$ kubectl get pods -n ingress-nginx -o wide
===
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-6b4r2 0/1 Completed 0 26m 10.244.4.34 k8s-loadbalancer <none> <none>
ingress-nginx-admission-patch-rbqhs 0/1 Completed 0 26m 10.244.4.35 k8s-loadbalancer <none> <none>
ingress-nginx-controller-7b5876f785-56789 1/1 Running 0 26m 10.244.4.36 k8s-loadbalancer <none> <none>
NodePort
로 동작합니다. 이 상태에서 외부 트래픽은 컨트롤러로 바로 접근할 수 없어 LoadBalancer
타입으로 변경해 주어야 합니다.$ kubectl patch svc ingress-nginx-controller -n \
ingress-nginx -p '{"spec": {"type": "LoadBalancer"}}'
$ kubectl get svc -n ingress-nginx
===
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.96.161.225 <pending> 80:30723/TCP,443:32540/TCP 1m
ingress-nginx-controller-admission ClusterIP 10.107.233.129 <none> 443/TCP 1m
LoadBalancer
타입으로 변경되었지만, EXTERNAL-IP
가 <pending>
상태로 할당되고 있지 않아 외부 접근은 여전히 불가능합니다. MetalLB
를 설치하면 외부에서 접근할 수 있으니 진행해 보겠습니다.MetalLB
설치하기$ kubectl edit configmap -n kube-system kube-proxy
===
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
mode
를 ipvs
로, ipvs.strictARP
를 true
로 변경해야 하는군요.$ curl -L -o namespace.yml https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
$ curl -L -o metallb.yml https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml
$ vi metallb.yml
deployment/controller
및 daemonset/speaker
에 노드 어피니티를 추가해 준 후 설치를 진행합니다.$ kubectl apply -f namespace.yml
$ kubectl apply -f metallb.yml
secret
이 필요합니다.$ kubectl create secret generic -n metallb-system \
memberlist --from-literal=secretKey="$(openssl rand -base64 128)"
configmap.yml
이 필요합니다.# configmap.yml
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- [HOST_IP]
HOST_IP
에는 현재 노드(마스터)의 ipv4 주소를 입력합니다. ifconfig
명령어 혹은 AWS 콘솔 등에서 확인하면 됩니다.$ ifconfig
===
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9001
inet 192.168.51.14 ...
192.168.51.14
이니, HOST_IP
에는 192.168.51.14-192.168.51.14
로 지정해 주겠습니다.$ kubectl apply -f configmap.yml
EXTERNAL-IP
가 할당되는 것을 볼 수 있습니다.# ingress-nginx.yml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-router
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: [YOUR_DOMAIN]
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: application
port:
number: 8080
$ kubectl apply -f ingress-nginx.yml
외부에서 접근시 애플리케이션의 반환값을 표시하는 것을 알 수 있습니다.
혹시 [MetalLB 설치하기] 과정에서 deployment/controller 및 daemonset/speaker 에 노드 어피니티를 추가하는 이유를 알 수 있을까요?
controller는 몰라도 speaker는 다른 노드에 배포되어야 하는게 아닌가 싶어서요..