- 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
- 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.
로컬에서 Kubernetes 클러스터 구축하기
인그레스와 LoadBalancer 서비스 생성하기
지금까지 NodePort
로 생성된 서비스에 접근해보았습니다. 하지만, NodePort
는 해당 노드에 랜덤한 포트로 접속하기 때문에 실제 서비스에 사용하기는 힘듭니다. 이번에는 도메인과 연동할 수 있는 인그레스와 LoadBalancer
서비스를 생성하고 사용해보겠습니다.
인그레스 컨트롤러 설치하기
인그레스를 사용하려면 먼저 인그레스 컨트롤러를 설치해야 합니다. 여기서는 Nginx 인그레스 컨트롤러를 사용하겠습니다.
다음 명령을 실행하여 베어메탈용 Nginx 인그레스 컨트롤러를 설치합니다.
$ kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/baremetal/deploy.yaml
베어메탈
베어메탈은 하드웨어상에 어떤 소프트웨어도 설치되지 않은 상태를 뜻합니다. 즉, 물리서버 그 자체를 말합니다. 여기에 사용자가 운영체제를 설치한 것이 베어메탈 서버라고 할 수 있습니다.
이 실습을 위해 우리는 물리서버 여러 대를 구입하기 힘들므로, 가상화 소프트웨어인 VirtualBox로 베어메탈 환경을 임시로 구성한 상황입니다.
MetalLB 설치하기
쿠버네티스를 클라우드에 구축했다면 로드밸런서(Load Balancer)를 클라우드에서 제공하는 것을 사용했을 것입니다(예: AWS의 ELB).
하지만 우리는 로컬에 베어메탈 환경을 가정하고 클러스터를 구축했기 때문에 따로 로드밸런서가 없습니다.
따라서 우리는 MetalLB라는 베어메탈용 로드밸런서를 사용하겠습니다. 완전한 클라우드 로드밸런서를 사용하는 방법은 뒤에서 다시 설명하겠습니다.
다음 명령을 실행하여 kube-proxy
에서 strictARP
설정을 false에서 true로 변경해줍니다. 왜냐하면 MetalLB는 ARP 프로토콜(OSI Layer 2)을 이용하기 때문입니다.
$ kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl apply -f - -n kube-system
kubectl get configmap kube-proxy -n kube-system -o yaml | %{$_ -replace "strictARP: false", "strictARP: true"} | kubectl apply -f - -n kube-system
그리고 MetaLB를 설치합니다.
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
이제 로드밸런서로 사용할 IP 대역을 설정해야 합니다. 다음 내용을 metallb-config.yaml
파일로 저장합니다.
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 192.168.56.100-192.168.56.200
autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default
저장이 끝났으면 설정을 생성합니다.
$ kubectl create -f metallb-config.yaml
webhook 에러가 발생한다면?
다음과 같이 Internal error occurred: failed calling webhook
에러가 발생할 수도 있습니다.
Error from server (InternalError): error when creating "metallb-config.yaml": Internal error occurred: failed calling webhook "ipaddresspoolvalidationwebhook.metallb.io": failed to call webhook: Post "https://webhook-service.metallb-system.svc:443/validate-metallb-io-v1beta1-ipaddresspool?timeout=10s": context deadline exceeded
Error from server (InternalError): error when creating "metallb-config.yaml": Internal error occurred: failed calling webhook "l2advertisementvalidationwebhook.metallb.io": failed to call webhook: Post "https://webhook-service.metallb-system.svc:443/validate-metallb-io-v1beta1-l2advertisement?timeout=10s": dial tcp 10.106.129.209:443: i/o timeout
이때는 다음 명령을 입력하여 metallb-webhook-configuration
webhook 설정을 삭제해줍니다. 지금은 이 webhook을 사용하지 않으므로 삭제해도 괜찮습니다.
$ kubectl delete validatingwebhookconfigurations metallb-webhook-configuration
삭제되었다면 다시 설정을 생성해봅니다.
$ kubectl create -f metallb-config.yaml
Nginx 인그레스 컨트롤러를 LoadBalancer로 바꾸기
이제 필요한 것들을 모두 설치하고 설정했습니다. 다음 명령을 입력하여 Nginx 인그레스 컨트롤러의 서비스를 출력해봅니다.
$ kubectl -n ingress-nginx get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.101.223.167 <none> 80:32580/TCP,443:30309/TCP 3m4s
ingress-nginx-controller-admission ClusterIP 10.104.113.40 <none> 443/TCP 3m4s
ingress-nginx-controller
의 TYPE을 보면 NodePort
로 되어 있습니다.
다음 명령을 실행하여 ingress-nginx-controller
의 TYPE을 LoadBalancer
로 변경합니다.
$ kubectl -n ingress-nginx patch service ingress-nginx-controller -p '{"spec":{"type":"LoadBalancer"}}'
kubectl -n ingress-nginx patch service ingress-nginx-controller -p '{\"spec\":{\"type\":\"LoadBalancer\"}}'
다시 Nginx 인그레스 컨트롤러의 서비스를 출력해봅니다.
$ kubectl -n ingress-nginx get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.101.223.167 192.168.56.100 80:32580/TCP,443:30309/TCP 26m
ingress-nginx-controller-admission ClusterIP 10.104.113.40 <none> 443/TCP 26m
ingress-nginx-controller
의 TYPE이 LoadBalancer
로 바뀌었고, EXTERNAL-IP
부분에 192.168.56.100
IP 주소가 할당된 것을 볼 수 있습니다. 이 EXTERNAL-IP
가 외부에서 접속할 수 있는 IP 주소입니다. 만약 도메인 설정을 한다면 이 IP 주소로 A 레코드를 만들면 되는 것입니다. 하지만, 지금은 도메인을 구입하지 않았으므로 로컬에서 설정하는 방법을 뒤에서 설명하겠습니다.
인그레스 만들기
이제 인그레스를 만들 차례입니다. 다음 내용을 ingress.yaml
파일로 저장합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-localhost
spec:
ingressClassName: nginx
rules:
- host: demo.localdev.me
http:
paths:
- backend:
service:
name: hello-nginx
port:
number: 80
path: /
pathType: Prefix
저장이 끝났으면 인그레스를 생성합니다.
$ kubectl create -f ingress.yaml
webhook 에러가 발생한다면?
다음과 같이 Internal error occurred: failed calling webhook
에러가 발생할 수도 있습니다.
error: failed to create ingress: Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s": context deadline exceeded
이때는 다음 명령을 입력하여 ingress-nginx-admission
webhook 설정을 삭제해줍니다. 지금은 이 webhook을 사용하지 않으므로 삭제해도 괜찮습니다.
$ kubectl delete validatingwebhookconfiguration ingress-nginx-admission
삭제되었다면 다시 인그레스를 생성해봅니다.
$ kubectl create -f ingress.yaml
이제 kubectl get ingress
명령으로 인그레스를 출력해보겠습니다.
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
demo-localhost nginx demo.localdev.me 192.168.56.11 80 2m1s
HOSTS에 도메인으로 demo.localdev.me가 설정된 것을 볼 수 있습니다. ADDRESS의 IP 주소는 사용하지 않을 것이므로 신경쓰지 않아도 됩니다. 여기서는 Nginx 인그레스 컨트롤러를 사용할 것이므로 위에서 만든 ingress-nginx-controller
의 EXTERNAL-IP
가 중요합니다.
호스트 설정하기
우리는 실제로 demo.localdev.me 도메인을 구입하지 않았으므로, 로컬에서 임시로 사용할 수 있도록 설정해야 합니다. 운영체제별로 설정 파일이 조금 다른데, 각자 운영체제에 맞는 파일을 수정합니다.
리눅스, macOS는 /etc/hosts
파일을 수정해야 합니다. root 권한이 있어야 하므로 sudo vim
으로 수정합니다.
$ sudo vim /etc/hosts
/etc/hosts
파일의 마지막 부분에 다음 내용을 추가한 뒤 저장합니다.
192.168.56.100 demo.localdev.me
윈도우는 C:\Windows\System32\drivers\etc\hosts
파일을 수정해야 합니다. 관리자 권한이 필요하므로, 메모장을 관리자 권한으로 실행한 뒤 파일을 엽니다.
C:\Windows\System32\drivers\etc\hosts
파일의 마지막 부분에 다음 내용을 추가한 뒤 저장합니다.
192.168.56.100 demo.localdev.me
메모장에서 hosts 파일이 보이지 않는다면?
메모장에서 hosts 파일이 보이지 않는다면, 열기 창에서 열기(O) 버튼 위의 텍스트 문서(*.txt)를 모든 파일 (*.*)로 바꿔주면 됩니다.
웹 브라우저를 열고 http://demo.localdev.me 접속하면 Welcome to nginx!가 표시될 것입니다.
인그레스 삭제
인그레스를 삭제하려면 kubectl delete -f
명령을 사용합니다.
$ kubectl delete -f ingress.yaml
Vagrant 가상머신 삭제하기
사용이 끝난 Vagrant 가상머신은 vagrant destroy
명령으로 삭제할 수 있습니다. [y/N]이 나오면 모두 y를 입력하여 삭제합니다.
$ vagrant destroy
worker3: Are you sure you want to destroy the 'worker3' VM? [y/N] y
==> worker3: Forcing shutdown of VM...
==> worker3: Destroying VM and associated drives...
worker2: Are you sure you want to destroy the 'worker2' VM? [y/N] y
==> worker2: Forcing shutdown of VM...
==> worker2: Destroying VM and associated drives...
worker1: Are you sure you want to destroy the 'worker1' VM? [y/N] y
==> worker1: Forcing shutdown of VM...
==> worker1: Destroying VM and associated drives...
master: Are you sure you want to destroy the 'master' VM? [y/N] y
==> master: Forcing shutdown of VM...
==> master: Destroying VM and associated drives...
MetalLB 설정과 인그레스 구조 살펴보기
MetalLb 설정
이제 YAML 파일을 자세히 살펴보겠습니다. 먼저 MetalLB 설정 파일인 metallb-config.yaml
입니다. 이 파일에는 IPAddressPool
과 L2Advertisement
두 가지가 함께 들아있습니다. YAML에서는 ---
으로 여러 설정을 구분하여 파일 하나에 넣을 수 있습니다.
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 192.168.56.100-192.168.56.200
autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default
.apiVersion
: 현재 MetalLBIPAddressPool
의 버전은metallb.io/v1beta1
입니다..kind
: MetalLB의 IP 주소 풀이라IPAddressPool
로 설정했습니다..metadata.name
: IP 주소 풀의 이름은default
입니다..metadata.namespace
: 네임스페이스는 일종의 디렉터리 역할을 합니다. 즉, 각 오브젝트들을 네임스페이스별로 구분하여 관리할 수 있습니다. 여기서는metallb-system
으로 설정했습니다..spec.addresses
: 서비스의LoadBalancer
에 할당할 IP 주소 대역을 설정합니다. 노드의 IP 주소와는 겹치지 않게 해야 합니다. 여기서는192.168.56.100-192.168.56.200
로 설정했습니다..spec.autoAssign
: 서비스의LoadBalancer
에 IP 주소를 자동 할당한다는 설정입니다.true
로 설정합니다.
.apiVersion
: 현재 MetalLBL2Advertisement
의 버전은metallb.io/v1beta1
입니다..kind
: MetalLB의 L2 레이어 전파(Advertisement) 설정이라L2Advertisement
으로 설정했습니다..metadata.name
: L2 레이어 전파 설정의 이름은default
입니다..metadata.namespace
: 물론 여기서도 네임스페이스는metallb-system
으로 설정했습니다..spec.ipAddressPools
: L2 레이어로 전파할 IP 주소풀을 설정합니다. 위에서 만든default
를 설정했습니다.
인그레스
드디어 인그레스입니다. 인그레스는 앞으로도 자주 접하게 될 설정입니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-localhost
spec:
ingressClassName: nginx
rules:
- host: demo.localdev.me
http:
paths:
- backend:
service:
name: hello-nginx
port:
number: 80
path: /
pathType: Prefix
.apiVersion
: 현재 인그레스의 버전은networking.k8s.io/v1
입니다..kind
: 인그레스를 생성하므로Ingress
로 설정했습니다..metadata.name
: 인그레스의 이름은demo-localhost
로 설정했습니다..spec.ingressClassName
: 인그레스 클래스 설정입니다. 우리는 앞에서 Nginx 인그레스 컨트롤러를 설치했으므로nginx
로 설정합니다..rules
: 여기서부터 인그레스 규칙 설정입니다. 배열 형태이며 여러 개를 넣을 수 있습니다..rules[0].host
: 인그레스와 연동할 도메인입니다. 구입한 도메인을 설정해도 되고, 가상의 도메인을 설정해도 됩니다. 여기서는 가상의 테스트용 도메인인demo.localdev.me
를 설정했습니다..rules[0].http
: HTTP 프로토콜 설정입니다..rules[0].http.paths
: 도메인에 접속했을 때 하위 경로(path) 설정입니다. 배열 형태이며 여러 개를 넣을 수 있습니다. 여기서는 최상위 경로인/
만 처리하고 있습니다..rules[0].http.paths[0].backend
: 현재 경로의 트래픽을 어디로 보낼 것인지 설정하는 부분입니다. 여기서는service
로 보내며 서비스의 이름(name
)은hello-nginx
, 포트 번호(port.number
)는 80으로 설정했습니다..rules[0].http.paths[0].path
: 처리할 하위 경로입니다. 여기서는 최상위 경로를 처리할 것이므로/
로 설정했습니다..rules[0].http.paths[0].pathType
: 경로를 처리할 방식입니다.Prefix
,ImplementationSpecific
,Exact
를 설정할 수 있는데, 우리는/
로 시작하는 모든 경로를 처리할 것이므로Prefix
로 설정했습니다.ImplementationSpecific
는 인그레스 클래스에 따라 달라지며,Exact
는 경로의 대소문자까지 정확하게 일치시킵니다.
Nginx 인그레스 컨트롤러와 MetalLB 삭제
Nginx 인그레스 컨트롤러와 MetalLB를 삭제하려면 kubectl delete -f
명령을 사용합니다.
$ kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/baremetal/deploy.yaml
$ kubectl delete -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
저작권 안내
이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.- 블로그, 게시판 등에 퍼가는 것을 금지합니다.
- 비공개 포스트에 퍼가는 것을 금지합니다.
- 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
- 링크 및 SNS 공유는 허용합니다.