실습
- Nodeport 사용하여 외부에서 POD 접속해 보세요
: nodeport 를 특정 Port로 지정해 보세요. - MetalLB 설치
- LoadBalancer 사용하여 POD 접속하기
- LoadBalancer IP를 특정 IP로 할당하고 동일 IP로 2개의 Protocol(TCP, UDP)를 할당해 보세요
Why NodePort, LoadBalancer?
NGINX 웹 서버를 설치하고 나면 당연히 내 PC에서 웹 서버로 정상적으로 접속이 되는지 검증하고 싶습니다. 하지만 Kube POD는 노드 안에서 실행되는 거라 노드 안에 있는 POD를 외부에서 바로 접속할 수 있는 방법이 없습니다. (D-NAT 등의 추가 네트워크 설정이 필요합니다.) 노드의 IP와 POD의 IP는 서로 다른 대역이라 다이렉트 통신이 안 됩니다.
그래서 Kube에서는 POD로 접속하는 방법으로 아래 3가지를 제공합니다
- Service : NodePort, LoadBalancer
- Ingress
(이번 포스팅에서는 Service NodePort, LoadBalancer만 다루고 Ingress는 Traefik 포스팅에서 설명 하겠습니다. )
Service NodePort란?
외부 Traffic이 이름 그대로 NodePort, 물리 Node(VM, 혹은 Baremetal)의 특정 Port를 이용하여 내부 POD와 통신하는 방법을 의미합니다. 서비스에서 NodePort를 사용하기 위해서는 spec.type 부문을 NodePort로 변경하면 됩니다.
NodePort 에서 사용하는 Port 대역은?
Default로 30000 ~ 32767 Port 대역을 사용 합니다.
NodePort로 사용하는 Port를 특정 Port로 지정하는 방법은?
Service YAML 파일, spec.ports.nodePort로 특정 Port를 지정합니다. (만약 해당 Port가 이미 사용 중이면 에러가 발생합니다.) 특별히 nodePort를 지정하지 않으면 30000 ~ 32767 Port 중 하나를 random하게 할당합니다. 그러면 매번 재시작 시 계속 변경되어 불편합니다.
그럼, NodePort 실습해 보겠습니다.
기존 실행 중인 NGINX POD가 있으면 그대로 활용하시고 삭제를 하셨으면 신규로 다시 만들어 줍니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx # Deploy Label 이름
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx # Service에서 사용할 Label
spec:
containers:
- name: nginx
image: nginxdemos/hello
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: nginx
spec:
type: NodePort
ports:
- name: tcp
port: 80
protocol: TCP
targetPort: 80
nodePort: 30080 # 원하는 port 번호로 고정합니다.
selector: # 선택해야 할 POD 선택
app: nginx # POD Label 과 동일
[spkr@erdia22 41.NGINX (k3s:nginx)]$ ka nginx-deploy.yml
deployment.apps/nginx-deployment created
[spkr@erdia22 41.NGINX (k3s:nginx)]$ ka nginx-svc.yml
service/nginx-svc created
정상적으로 생성이 되면 endpoint 확인이 가능합니다.
[spkr@erdia22 41.NGINX (k3s:nginx)]$ k get endpoints
NAME ENDPOINTS AGE
nginx-svc 10.42.0.155:80 6s
적용된 NodePort Port는 Service 리스트로 확인 가능합니다.
k [spkr@erdia22 ~ (k3s:nginx)]$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc NodePort 10.43.26.55 <none> 80:30080/TCP 2m38s
위 서비스 내역의 PORT(S) 30080 Port가 NodePort 입니다. 이제 이 포트로 접속하면 NGINX 웹 서비스 확인이 가능합니다.
[spkr@erdia22 ~ (k3s:nginx)]$ k get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
localhost.localdomain Ready control-plane,master 14d v1.20.7+k3s1 172.17.29.166 <none> CentOS Linux 7 (Core) 3.10.0-1062.12.1.el7.x86_64 containerd://1.4.4-k3s1
Node IP는 위와 같이 확인 합니다. 이제 웹브라우저에서 확인해 보겠습니다.
위와 같이 정상적으로 웹브라우저에서 확인 가능합니다.
NodePort 제약 사항은?
: 외부 고객, 클라이언트가 웹 서버 접속 시 80, 443 등 Well-known port 가 아닌 30000 ~ 32767 Port를 사용해야 합니다. 따라서 실 운영 환경이라면 NodePort를 사용하지 않고 LoadBalancer Service Type, 또는 Ingress, or 물리 L4 스위치를 사용합니다.
외부의 L4 스위치 사용 시 Target IP, Port는 어떻게 지정할까요?
: 단일 노드가 아닌 전체 노드의 IP와 NodePort Port 등록합니다. 복수 노드를 선택하므로 HA 구성이 가능합니다.
Service LoadBalancer란?
외부에서 들어오는 Traffic 등을 별도의 외부 Object를 통하여 Traffic을 분산시키는 것을 LoadBalancer라고 합니다. (설명이 너무 부실하네요…) 기존 물리 L4 스위치가 traffic을 분산 시키는 것과 유사하다고 생각하시면 될 것 같습니다.
공식 홈페이지 인용
LoadBalancer: Exposes the Service externally using a cloud provider's load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.
LoadBalancer: 클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출시킨다. 외부 로드 밸런서가 라우팅되는 NodePort와 ClusterIP 서비스가 자동으로 생성된다.
공식 홈페이지는 클라우드 공급자라고 명시하는데 실제로는 Public Cloud(aws, azure, gcp)가 아닌 Local On-Prem 환경에서도 MetalLB 등을 통하여 LoadBalancer 기능을 구현 가능합니다.
LoadBalancer 설치
On-Prem 환경에 사용 가능한 LoadBalancer로 대표적으로 MetalLB가 있습니다. (MetalLB 설치는 K3S 환경에서 지원하지 않습니다. K3S 설치 시 같이 설치되는 Traefik Ingress 사용합니다.)
MetalLB 설치는 아주 간단합니다.
: 공식 홈피 참조, https://metallb.universe.tf/installation/
kubectl edit configmap -n kube-system kube-proxy
: stricARP false to true 변경
: kube-proxy restart
kubectl rollout restart -n kube-system daemonset kube-proxy
[user@git ~]$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/namespace.yaml
namespace/metallb-system created
[user@git ~]$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/metallb.yaml
podsecuritypolicy.policy/controller created
podsecuritypolicy.policy/speaker created
serviceaccount/controller created
serviceaccount/speaker created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
role.rbac.authorization.k8s.io/config-watcher created
role.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/config-watcher created
rolebinding.rbac.authorization.k8s.io/pod-lister created
daemonset.apps/speaker created
deployment.apps/controller created
[user@git ~]$ kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
secret/memberlist created
POD 확인
[user@git ~]$ k get pod -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-65db86ddc6-bt6rg 1/1 Running 0 55s
speaker-2xsnx 1/1 Running 0 55s
speaker-r4kp4 1/1 Running 0 55s
speaker-xpgfg 1/1 Running 0 55s
설치가 정상적으로 완료 되었습니다.
이제 LoadBalancer 에서 사용할 IP 대역을 추가해 보겠습니다. IP 추가는 MetalLB ConfigMap을 사용 합니다. IP는 외부에서 접속 가능한 IP 대역으로 할당합니다.
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.146 - 192.168.1.151 # IP 대역 지정
# - 192.168.1.152 - 192.168.1.152 # 단일 IP 시 지정 방법
서비스 Type을 LoadBalancer 로 지정하여 생성하세요.
apiVersion: v1
kind: Service
metadata:
name: nginxhello-svc
# namespace: default
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-hello
sessionAffinity: None
type: LoadBalancer
서비스 확인
[spkr@erdia22 06.Deployment (spkn02:nginx)]$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginxhello-svc LoadBalancer 10.233.9.86 172.17.28.160 80:32240/TCP 5d20h
TYPE LoadBalancer로 정상적으로 생성이 되었습니다. 이제 외부에서 접속해 보겠습니다.
(물론 ^^) 정상적으로 잘 됩니다.
특정 IP 주소를 LoadBalancer IP로 할당하세요.
동일 IP에 2개의 Protocol(UDP, TCP)를 할당하세요.
spec.loadBalancerIP를 이용하여 특정 IP 지정이 가능합니다. 그리고 2개의 Serivce에서 annotations(allow-shared-ip)을 같이 지정하여 동일 IP + 2개의 Protocol 가지는 Service 생성이 가능합니다.
apiVersion: v1
kind: Service
metadata:
annotations:
meta.helm.sh/release-name: traefik
meta.helm.sh/release-namespace: traefik
metallb.universe.tf/allow-shared-ip: 192.168.1.146
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
labels:
app.kubernetes.io/instance: traefik
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: traefik
helm.sh/chart: traefik-9.17.2
name: traefik
namespace: traefik
spec:
externalTrafficPolicy: Local
loadBalancerIP: 192.168.1.146
ports:
- name: traefik
nodePort: 32246
port: 9000
targetPort: traefik
selector:
app.kubernetes.io/instance: traefik
app.kubernetes.io/name: traefik
sessionAffinity: None
type: LoadBalancer
apiVersion: v1
kind: Service
metadata:
annotations:
meta.helm.sh/release-name: traefik
meta.helm.sh/release-namespace: traefik
metallb.universe.tf/allow-shared-ip: 192.168.1.146
labels:
app.kubernetes.io/instance: traefik
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: traefik
helm.sh/chart: traefik-9.17.2
name: traefik-udp
namespace: traefik
spec:
externalTrafficPolicy: Local
loadBalancerIP: 192.168.1.146
ports:
- name: jvb-udp
protocol: UDP
port: 10000
targetPort: 10000
selector:
app.kubernetes.io/instance: traefik
app.kubernetes.io/name: traefik
sessionAffinity: None
type: LoadBalancer
확인을 해보면
[spkr@erdia22 06.Deployment (dzbumin:nginx)]$ k get svc -n traefik
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
AGE
traefik LoadBalancer 10.233.43.121 192.168.1.146 9000:32246/TCP,80:32299/TCP,443:30933/TCP,54321:32195/TCP,11887:30976/TCP,4443:31583/TCP 18h
traefik-udp LoadBalancer 10.233.9.219 192.168.1.146 10000:30545/UDP
18h
위와 같이 192.168.1.146 IP로 2개의 Protocol(TCP, UDP)를 사용하는 Service가 생성되었습니다. 외부에서 TCP, UDP 둘 다 접속 가능합니다.
참조
'쿠버네티스 교육' 카테고리의 다른 글
10. Kube 교육 - Kube Storage(PV PVC SC) (0) | 2021.06.04 |
---|---|
09. Kube 교육 - MetalLB (2) | 2021.06.04 |
07. Kube 교육 - Service Discovery (0) | 2021.06.04 |
14. Kube 교육 - Readiness/Liveness Probe (0) | 2021.06.04 |
13. Kube 교육 - Label & Affinity (0) | 2021.06.04 |