5.1 클러스터 내부 서비스
파드는 클러스터 외부의 요청이나 클러스터 내부의 다른 파드의 요청에 응답해야 한다. 또한 파드가 다른 파드에서 제공하는 애플리케이션에 접근하기 위해서는 파드를 찾을 수 있어야 한다!!!
파드는 단일 고정 ip를 통해서 서비스를 제공해야 한다!!
1) 서비스 소개
서비스는 쿠버네티스 시스템에서 같은 애플리케이션을 실행하고 있는 컨트롤러의 파드 그룹에 단일 네트워크 진입 점을 제공하는 리소스다. 서비스에 부여된 ip는 해당 서비스가 종료될 때까지 변경되지 않는다.
클라이언트는 서비스가 제공하는 ip 및 포트를 통해 파드에 접근하게 된다!! 또한 kube-dns가 적용되어 있다면 서비스의 이름에 기반한 고유한 FQDN이 부여됨
서비스는 레이블 셀렉터를 이용해, 서비스의 대상(백엔드) 파드를 설정하는데 서비스에 선택된 파드의 목록은 엔드포인트 리소스로 관리된다
서비스 리소스는 여러 파드가 연결되어 있을 때 라운드 로빈 방식의 부하 분산을 제공한다.
(1) kubernets 서비스
kubectl get services 명령으로 확인가능
또한 서비스 리소스와 동일한 이름의 앤드포인트 리소스도 확인해보자
kubectl get endpoints

2) 서비스 생성
서비스 생성은 두 가지 방법이 있다. 첫 번째는 kubectl expose 명령을 이용하는 방법, 두 번쨰는 YAML파일로 리소스를 생성하는 방법

apiVersion 은 v1인것을 확인
vim myapp-scv.yaml >>> YAML파일을 이용하는 방법

.spec.ports.port : 서비스 리소스의 포트
.spec.ports.targetPort : 파드 리소스의 포트
.spec.selector : 파드 레이블 셀렉터, 엔트포인트 리소스 생성
서비스 오브젝트의 api는 v1을 사용하며 종류는 service이다
.spec.ports.port 필드는 클라이언트가 접근할 서비스의 포트이며, 해당 포트로 접근시 서비스는 .spec.ports.targetPort 필드에 지정된 파드의 서비스 포트로 포워딩하게 된다. service.spec.selector 필드는 서비스에 연결할 파드를 레이블 셀렉터를 이용하여 매칭한다. 레이블 셀렉터가 있는 경우 서비스 리소스 이름과 똑같은 엔드포인트 리소스가 자동으로 생성된다.
서비스를 생성해보자
kubectl create -f myapp-scv.yaml
3) 서비스 및 엔드포인트 확인
(1) 서비스 목록 확인
kubectl get services myapp-svc

클러스터 외부에서 접근할 때는 외부ip(external-ip)를 사용하며 이는 LoadBalancer 타입의 서비스를 선언 시 할당된다. 즉, ClusterIP서비스 타입은 클러스터 내부에서만 접근할 수 있는 서비스 이다.
(2) 엔드포인트 확인
kubectl get endpoints myapp-svc

현재 app=myapp-rs-exp 레이블을 가진 파드가 없기 때문에 엔트포인트 목록도 가지고 있지 않다... 즉, 서비스의 클러스터 ip로 접속하더라도 포워딩 할 파드가 없다!!!!!!
4) 파드 생성 및 엔드포인트 연결
해당되는 레이블을 가진 파드를 생성하면 서비스는 자동으로 엔드포인트를 추가하게 된다. 즉, 나중에 파드가 추가되거나 제거되더라도 레이블 셀렉터에 의해 매칭되는 파드는 엔드포인트가 자동으로 추가 및 제거됨!!!
앞에서 만든 myapp-rs-exp.yaml 파일을 이용해 파드를 생성해보자. 해당 컨트롤러 및 파드는 app=myapp-rs-exp 레이블을 사용하고 있다.
kubectl create -f myapp-rs-exp.yaml
파드를 생성한 이후 엔드포인트를 다시 확인!!

세 개의 엔드포인트가 구성되었으며, 이는 파드의 ip의 포트이다.
파드의 목록과 엔드포인트를 비교해 보자 -o wide 옵션을 사용하면 파드에 할당된 ip를 확인할 수 있다.

5) 서비스 접근 테스트
이제 서비스와 서비스가 포워딩 할 파드가 준비되었다. 이제 클러스터 내의 서비스에 접근하기 위한 테스트용 파드를 생성해 접근을 확인해보자
kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash

kubectl run 명령을 이용하여 파드를 생성할 수 있으며, 이는 서비스 접근에만 사용할 임시 파드이기 떄문에 --rm 옵션을 사용해 컨테이너 종료시 자동으로 삭제할 수 있도록 했음
파드를 실행 후 bash쉘이 실행되며 curl 명령으로 서비스에 할당된 ip로 접근하면 각 파드에 부하 분산이 되는 것을 확인할 수 있다.
2) DNS를 이용한 서비스 탐색
쿠버네티스 클러스터는 클러스터 시스템 내부에서 사용할 수 있는 DNS 서버가 동작하고 있다.
우리는 이미 kube-system 네임스페이스에 DNS 관련 파드 및 컨트롤러 서비스가 존재하는 것을 알고 있다.
(1) DNS관련 리소스 확인
DNS 관련 파드는 k8s-app=kube-dns 레이블을 확인하면 된다.

DNS 관련 서비스인 service/coredns 서비스가 있으며 10.233.0.3 ip로 접근할 수 있다. 그리고 표준 DNS 포트인 53번으로 서비스하고 있다.
(2) 파드 내부 DNS설정 확인
임시 파드를 생성해 파드 내부의 DNS 설정을 확인해보자
kubectl run nettool -it --image=ghcr.io/c1t1d0s7/network-multitool --rm bash
cat /etc/resolv.conf

예상과는 다르게 DNS 서버는 169.254.25.10으로 설정되어 있다. 이는 coredns 서비스인 ip인 10.233.0.3과 어떤 연관이 있을까???
(3) 노드 로컬 DNS 캐시
기존에는 파드 내의 DNS 서버 설정도 coredns 서비스의 ip가 부여되어 이었다. 즉, 파드가 직접적으로 coredns 서비스에 dns 쿼리/응답을 받게 되었는데, 이는 대규모 환경에서 병목현상을 만들어 성능이 저하된다는 단점이 있었다.
그래서 추가된 노드 로컬 dns캐시 기능이 도입되었다. 노드 로컬 dns캐시 기능은 쿠버네티스의 각 노드에 dns캐시 기능을 가지고 있는 파드를 데몬셋으로 배치하고, 파드의 dns쿼리 및 응답을 coredns가 대신하게 되는 구조이다.
pod <> NodeLocal DNSCache(169.254.25.10) <> coredns( 10.233.0.3)
노드 로컬 DNS캐시 기능에 대해 간단하게 살펴보자
kubectl get daemonsets.apps -l k8s-app=kube-dns -n kube-system

현재 구성은 마스터 1대, 노드 3대로 총 4대의 구성이기 떄문에 4개의 파드가 배포된다.
nodelocaldns 관련 파드 목록을 확인해보자.
kubectl get pods -l k8s-app=nodelocaldns -n kube-system

nodelocaldns 파드의 아규먼트 설정이다. 이는 각 노드에서 169.24.25.10 IP인 링크로컬 주소 대역을 사용해 dns캐시 서비스를 제공한다는 의미이다.
kubectl get pods -l k8s-app=nodelocaldns -n kube-system -o jsonpath='{.item[*].spec.containers[*].args[*]}'
5.3 클러스터 외부 서비스
쿠버네티스 클러스터에서 웹의 프론트엔드 서비스를 실행하는 파드의 경우 쿠버네트스 클러스터의 외부로 노출시켜 접근 가능하도록 구성해야 한다.
여태 살펴본 서비스는 쿠버네티스 클러스터 내부에서 사용 가능하도록 구성된 서비스 이다.
서비스의 종류
- ClusterIP : 클러스터 내부용 서비스
- NodePort : NodePort + ClusterIP, 쿠버네티스 모든 노드에 외부 접근용 포트를 할당함, 노드의 포트를 사용하여 외부에서 접근 가능, 노드의 포트로 접근하면 서비스에 의해 파드로 리다이렉션 함, 파드를 실행하고 있지 않은 노드에도 포트가 할당되고 접근가능함
- LoadBalancer : LoadBalancer + NodePort + ClusterIP, NodePort의 확장, 클러스터 외부의 로드 밸런서를 사용하여 외부에서 접근 가능, 외부 로드 밸런서로 접근하면 서비스를 통해 파드로 리다이렉션함, 클라우드 공급업체(aws, gcp등)나 MetalLB에서 지원
- ExternalName : 외부세어 접근하기 위한 종류가 아님, 외부의 특정 FQDN에 대한 CNAME 매핑을 제공, 파드가 CNAME을 이요해 특정 FQDN과 통신하기 위함
1) 외부 서비스용
kubectl create -f myapp-rs-exp.yaml >>> 기존에 작성된 myapp-rs-exp 파일을 이용해 컨트롤러 및 파드를 생성
kubectl get replicasets.apps >>> 컨트롤러 및 파드가 생성되었는지 확인한다.
kubectl get pods

2) NodePort 서비스 생성
vim myapp-svc-np.yaml

.spec.type : 서비스 타입 NodePort(기본 : ClusterIP)
.spec.ports.nodePort : 30000-32767 포트, 포트를 지정하지 않으면 랜덤한 포트 지정
즉, 서비스 타입은 NodePort이며, 노드에 노출할 포트는 31111포트이다. 포트는 기본적으로 30000-32767 포트 내에서만 사용 가능
노드 포트 서비스를 생성하자.
kubectl create -f myapp-svc-np.yaml
3) NodePort 서비스 확인
서비스 목록 및 상태를 확인해보자

노드의 31111 포트로 접근하면 서비스의 80 포트로 포워딩 된다.
서비스의 엔드포인트를 확인해보자
kubectl get endpoints myapp-svc-np

서비스의 80 포트는 파드의 8080 포트로 포워딩 된다.
노드의 ip를 확인해보자
kubectl get nodes -o wide

노드의 ip는 192.168.56.11, 192.168.56.21, 198.168.56.22, 198.168.56.23
노드 ip와 노드 포트로 접근해보자
외부에서 접근

4) LoadBalancer 서비스 생성
클라우드 인프라에서 LoadBalancer 서비스를 생성하면 클라우드 인프라의 로드 밸런서를 자동으로 프로비저닝 하게 되며, 이 로드 밸런서를 통해 서비스와 파드에 접근할 수 있다.
kubectl api-resources | grep service >>> apiVersion 확인
vim myapp-svc-lb.yaml

로드 밸런서 서비스를 생성하자.
kubectl create -f myapp-svc-lb.yaml
5) LoadBalancer 서비스 확인
kubectl get service myapp-svc-lb

로드 밸런서의 외부 ip가 192.168.56.200으로 정상적으로 할당된 것을 확인할 수 있다!!!
외부에서 로드밸런서 서비스의 ip로 접근해 본다

로드 밸런서를 통해 부하 분산이 잉루어지는 것을 확인할 수 있다
결론은 노드포트는 ip주소 뒤에 설정한 노드포트를 입력해 줘야 되지만 로드밸런서는 할당받은 ip를통해 접속이 가능하다!!!
'쿠버네티스,쿠버플로우' 카테고리의 다른 글
| 쿠버네티스(스토리지2) (0) | 2023.07.06 |
|---|---|
| 쿠버네티스(스토리지) (0) | 2023.07.05 |
| 쿠버네티스(네트워크2) (1) | 2023.07.05 |
| 쿠버네티스 2일차 (1) | 2023.07.04 |
| 쿠버네티스 설치, 개념 (0) | 2023.07.03 |