네트워크교육 33일차 (2022.02.18)

정상훈·2022년 2월 18일
0

서비스 다중 포트 구성

파드의 애플리케이션은 항상 하나의 포트로만 서비스하는 것이 아닌
여러 포트를 사용하여 서비스 가능

서비스 역시 파드의 서비스 포트가 다중 포트인 경우, 노출할 서비스 포트 여시 다중 포트로 구성할 수 있음

예를 들어 웹 서버인 경우 HTTP는 80번, HTTPS는 443번 다중 포트를 가진 파드 및 서비스를 구성해야 할 경우도 있음

다중 포트 구성은 서비스 포트가 단일 포트라고 하더라도, yml의 리스트로 구성 가능

다중 포트를 설정할 때는 반드시 포트의 이름을 부여해야 함

.spec.ports.name: 포트의 이름

- 포트 이름 참조

파드나 파드를 생성하는 컨트롤러의 파드 템플릿의 컨테이너 포트에도 이름을 부여할 수 있음

이렇게 하면 파드(컨테이너)의 포트 이름을 이용하여 서비스 생성 시 
파드의 대상포트(targetPort)에 이름을 이용하여 연결 가능

이는 이름으로 참조하기 때문에 파드의 포트 이름만 변경되지 않았다면,
실제 파드의 포트 번호가 변경되더라도,
스펙의 변경 없이 계속해서 연결할 수 있음
이럴 경우, 엔드포인트도 변경

포트 이름을 사용한 레플리카 셋 및 서비스 생성

컨테이너의 8080 포트에 testapp-http라는 이름을 부여
이름을 서비스 생성 시 참조 가능

포트 이름을 참조하는 서비스 구성

.spec.ports.targetPort: 대상 파드의 포트 이름 지정

레플리카 셋 컨트롤러와 서비스 생성

kubectl create -f testapp-rs-namedport.yml -f testapp-svc-namedport.yml

오브젝트 확인

kubectl replicasets.apps testapp-rs-namedport

엔드포인트 확인

kubectl get endpoints
kubectl get endpoints testapp-svc-namedport

파드 목록 및 IP 확인

kubectl get pods -o wide -l app=testapp-rs-namedport

서비스 탐색

- 쿠버네티스의 클러스터 서비스는 파드에서 직접 탐색하고 접근 가능

● 환경 변수를 이용한 탐색 방법
● DNS를 이용한 탐색 방법

- 환경 변수를 이용한 서비스 탐색
쿠버네티스 클러스터는 파드가 시작될 때 현재 존재하는 서비스를 파드 내의 쉘 환경 변수로 설정

하나의 서비스에 설정되는 여러 형태의 쉘 환경 변수:
● {SVC_NAME}_SERVICE_HOST={SVC_IP}
● {SVC_NAME}_SERVICE_PORT={SVC_PORT}
● {SVC_NAME}_PORT={PROTOCOL}://{SVC_IP}:{SVC_PORT}
● {SVC_NAME}_PORT_{PORT_NUMBER}_{PROTOCOL}={PROTOCOL}://{SVC_IP}:{SVC_PORT}
● {SVC_NAME}_PORT_{PORT_NUMBER}_{PROTOCOL}_ADDR={SVC_IP}
● {SVC_NAME}_PORT_{PORT_NUMBER}_{PROTOCOL}_PORT={SVC_PORT}
● {SVC_NAME}_PORT_{PORT_NUMBER}_{PROTOCOL}_PROTO={PROTOCOL}

쉘 환경 변수는 env 명령으로 확인

kubectl run nettool -it --	image=ghcr.io/c1t1d0s7/network-multitool --rm bash

bash-5.1# env

출력되는 대부분의 환경 변수는 앞서 생성한 kubernetes, testapp-svc, testapp-svc-namedport, testapp-svc-ses-aff 서비스의 환경 변수

testapp-svc 서비스에 대한 다음 환경 변수를 참조할 수 있음
● testapp_SVC_SERVICE_HOST=10.233.24.226
● testapp_SVC_SERVICE_PORT=80

애플리케이션은 서비스 이름만 알고 있다면
적절한 환경 변수를 참조해 
접근하고자 하는 서비스의 IP와 포트를 확인할 수 있음

DNS를 이용한 서비스 탐색

쿠버네티스 클러스터는 클러스터 시스템 내부에서 사용할 수 있는
DNS 서버가 동작하고 있음

DNS 관련 리소스 확인

kubectl get all -n kube-system -l k8s-app=kube-dns

DNS 관련 서비스인 service/coredns 서비스가 있으며 
10.233.xxx.xxxx IP로 접근할 수 있음
표준 DNS 포트인 53번으로 서비스하고 있음

파드 내부 DNS 설정 확인

kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash

bash-5.1# cat /etc/resolv.conf

예상과는 다르게 DNS 서버는 169.254.25.10으로 설정되어 있음

노드 로컬 DNS 캐시

기존에는 파드 내의 DNS 서버 설정도 coredns 서비스의 IP가 부여되어 있음

즉, 파드가 직접적으로 coredns 서비스에 DNS 쿼리/응답을 받게 되었는데, 이는 대규모 환경에서 병목현상을 만들어 성능이 저하된다는 단점이 있음

쿠버네티스 1.15 버전부터 추가된 노드 로컬 DNS 캐시(NodeLocal DNSCache) 기능이 도입

노드 로컬 DNS 캐시 기능은 
쿠버네티스의 각 노드에 DNS 캐시 기능을 가지고 있는 파드를 데몬셋으로 배치하고,
파드의 DNS 쿼리 및 응답을 coredns가 대신하게 되는 구조

NodeLocal
Pod <--> NodeLocal DNSCache(169.254.25.10) <--> iptables <--> coredns(10.233.0.3)

kubectl get daemonsets.apps -l k8s-app=kube-dns -n kube-system

kube-system 네임스페이스에 nodelocaldns 데몬셋 컨트롤러가 존재

nodelocaldns 관련 파드 목록을 확인

kubectl get pods -l k8s-app=nodelocaldns -n kube-system

nodelocaldns 파드의 아규먼트 설정

kubectl get pods -l k8s-app=nodelocaldns -n kube-system -o jsonpath='{.items[*].spec.containers[*].args[*]}'

이는 각 노드에서 169.254.25.10 IP인 링크로컬 주소 대역을 사용해 DNS 캐시 서비스를 제공한다는 의미

FQDN을 이용한 서비스 탐색

kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash


bash-5.1# curl http://testapp-svc

bash-5.1# curl http://testapp-svc.default

bash-5.1# curl http://testapp-svc.default.svc

bash-5.1# curl http://testapp-svc.default.svc.cluster.local

testapp-svc 서비스에 접근하기 위한 FQDN 주소는 mynapp-svc.default.svc.cluster.local 

● mynapp-svc: 서비스의 이름
● default: 서비스 리소스의 네임스페이스 이름
● svc: 서비스 그 자체를 의미함
● cluster.local: 쿠버네티스 클러스터 도메인

FQDN의 주소 형식

<서비스 이름>.<네임스페이스>.<리소스 종류>.<클러스터 도메인>
mynapp-svc.default.svc.cluster.local

클러스터 외부 서비스

쿠버네티스 클러스터에서 웹의 프론트엔드 서비스를 실행하는 파드의 경우 쿠버네티스 클러스터의 외부로 노출시켜 접근 가능하도록 구성

외부 서비스용 레플리카셋 생성 및 확인

기존에 작성된 testapp-rs 파일을 이용하여 컨트롤러 및 파드를 생성

kubectl create -f testapp-rs.yml

컨트롤러 및 파드가 생성되었는지 확인

kubectl get replicasets.apps

kubectl get pods

NodePort 서비스 생성

.spec.type: 서비스 타입 (기본: ClusterIP)
.spec.ports.nodePort: 30000-32767 포트, 포트를 지정하지 않으면 랜덤한 포트 지정

서비스 타입은 NodePort이며, 노드에 노출할 포트는 31111 포트이다.
포트는 기본적으로 30000-32767 포트 내에서만 사용 가능

노드 포트 서비스를 생성

kubectl create -f testapp-svc-np.yml
NodePort 서비스 확인

kubectl get service testapp-svc-np

- 노드의 31111 포드로 접근하면 서비스의 80 포트로 리다이렉션

kubectl get endpoints testapp-svc-np

서비스의 80 포트는 파드의 8080 포트로 리다이렉션

- 노드의 IP를 확인

kubectl get nodes -o wide

- 노드포트 접근

curl http://192.168.56.11:31111

curl http://192.168.56.21:31111

curl http://192.168.56.22:31111

curl http://192.168.56.23:31111

외부에서 192.168.56.X:31111로 접근하면, 서비스 포트인 80번 포트로 리다이렉션 되며,
이는 다시 내부 파드의 8080번 포트로 리다이렉션

LoadBalancer 서비스

생성

클라우드 인프라에서 LoadBalancer 서비스를 생성하면 
클라우드 인프라의 로드 밸런서를 자동으로 프로비저닝 하게 되며, 
이 로드 밸런서를 통해 서비스와 파드에 접근할 수 있음

환경설정

Kubernetes 로드밸런서 서비스를 위한 MetalLB 설치

- 디렉토리 변경

cd ~/kubespray


- Kubernetes 클러스터 설정 변경

vi inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml

kube_proxy_strict_arp: true


- 로드밸런서에 할당할 IP 범위 설정

vi contrib/metallb/roles/provision/defaults/main.yml

  ip_range: "192.168.56.200-192.168.56.220"


- MetalLB 설치

ansible-playbook -i inventory/mycluster/inventory.inicontrib/metallb/metallb.yml -b



- MetalLB 네임스페이스 확인

kubectl get ns

kubectl create -f testapp-svc-lb.yml

로드밸런서 서비스 확인

 kubectl get service testapp-svc-lb

로드 밸런서의 외부 IP가 192.168.56.200으로 정상적으로 할당된 것을 확인할 수 있음

클라우드의 관리형 쿠버네티스 서비스 및 MetalLB를 사용하지 않는 경우, 
외부 로드 밸런서가 프로비저닝 되지 않기 때문에 
외부 IP(로드 밸런서 IP)가 할당되지 않고 <pending> 상태로 보고

실제 외부 로드 밸런서를 사용할 수 있는 경우, 
외부의 로드 밸런서가 생성되고 IP가 할당되기까지 시간이 필요

- 로드 밸런서 서비스의 IP로 접근

curl http://192.168.56.200

ExternalName 서비스 생성

ExternalName 서비스는 NodePort 및 LoadBalancer와 다르게 
외부에서 접근하기 위한 서비스 종류가 아닌 
내부 파트가 외부의 특정 FQDN에 쉽게 접근하기 위한 서비스

즉, 쿠버네티스 클러스터의 coredns 서비스가 특정 FQDN에 대한 CNAME(서비스의 FQDN)을 제공함
해당 CNAME을 이용하여 쉽게 통신할 수 있음

심지어 접속하기 위한 외부 FQDN 주소가 바뀌더라도, 
CNAME은 그대로 유지할 수 있어 애플리케이션을 다시 작성하거나 빌드 하지 않아도 됨

외부 FQDN은 www.google.com이며 
이에 대한 CNAME은 testapp-svc-extname 
이름을 제공하는 서비스
파드와 매칭하지 않기 때문에 레이블 셀렉터는 없음

kubectl create -f testapp-svc-extname.yml

ExternalName 서비스 확인

kubectl get service testapp-svc-extname

서비스 타입은 ExternalName이며, 
외부 IP에는 www.google.com의 FQDN이 할당되어 있음

즉, 파드는 testapp-svc-extername CNAME을 사용하면 
www.google.com의 주소를 알 수 있음

kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash

bash-5.1# host testapp-svc-extname
profile
"@____

0개의 댓글