개발 관련 일지/k8s

그림으로 배우는 쿠버네티스 CH4 애플리케이션 노출

worldi 2024. 2. 10. 14:49

배포한 애플리케이션을 노출하는 방법

다음과 같은 방법이 있다.

  1. 간단한 방법
    • port-forward
    • HostPort
    • hostNetwork
  2. NodePort
  3. LoadBalancer
  4. ExternalName
  5. ClusterIP, Headless
  6. Endpoints
  7. Ingress

간단한 방법(port-forward, HostPort, hostNetwork)

포트 포워딩

  • 호스트 PC에서 가상 머신으로 접속 시 포트 포워딩 사용

 

port-forward 옵션

 

  • k port-forward fwd-chk-hn 80:80: 마스터 노드의 80번 포트를 fwd-chk-hn 노드의 80번 포트로 포워딩
  • 노드가 재시작 될 경우 포트 포워딩이 사라짐. 내부에서 포트를 포워딩할 때만 쓰지 영속적으로 쓸수는 없음

실습

  • 마스터 노드 → 워커 노드 포트포워딩하는 구조이다.
  • 마스터 노드에 127.0.0.1.80 으로 들어온 글 파드에 80으로 보내주라는 의미
k port-forward fwd-chk-hn 80:80
  • curl 192.168.1.10 이렇게 하면 failed connection이 뜬다. 하지만, port-forward —address 0.0.0.0 fwd-chk-hn 80:80 이라고 하면 모든 연결에 대해서 열어 준 것이므로 다시 curl 요청하면 연결된다.

HostPort

 

  • containerPort: 파드의 포트
  • hostPort: 노드의 포트
  • 노드의 IP와 포트를 알고 있어야 하므로 실용적이지 않음. 사용자가 어디에 디플로이 되었는지 알아야 함 워커노드 8080:80으로 해주는 것임

HostNetwork

 

  • eth0을 그대로 쓸 수 있게 해주는 기능
  • 클러스터의 노드에 직접 접속하므로 실용적이지 않음. 클러스터에 어디에 배포되어있는지 알아야 함
  • 클러스터의 대문이 없어서 사용할 수 없음. → 이를 대비해서 노드포트, 로드밸런서가 있는 것이다.
  • 호스트 네트워크 점유하는 설정 그대로 가져온 것임
  • 제한적인 부분 많음, 어느 노드 deploy 되었는지 알수없어서 쓰이지 않는다.
  • 포트 포워딩은 어느정도 사용되지만 hostport와 hostNetwork는 거의 사용이 되지 않는다.

노드포트(NodePort)

nodeport.yaml

 

  • 노드 포트는 파드나 디플로이가 있어야 한다.
  • selector : 노출할 오브젝트
  • nodePort : 노드 포트, 미입력 시 랜덤으로 지정
  • port : 서비스 포트
  • targetPort : 파드 포트
  • 두 개의 오브젝트 구분할 때는 구분선 3개 써줘야 한다.
  • 셀렉터는 디플로이멘트를 노출한다. → 이름을 노출한다.
  • 노드 포트 3만번 외부 노출
    • 80번 pod → 80 port : 앞에 있는 포트는 서비스에 대한 포트번호를 의미한다. 뒤는 컨테이너 pod에 대한 타켓에 대한 포트를 의미한다.
  • 노드 포트 서비스로 노출된 것이니 NodePort 서비스로 보내줘야겠군.
    • 서비스가 이걸 받아서 파드 저기에 있는데 알려주는 구조

Overview

 

  1. 사용자가 워커 노드의 NodePort 서비스 포트로 접속
  2. 연결을 NodePort 서비스로 보내줌
  3. NodePort는 워커 노드의 파드로 연결을 보냄

로드밸런서(LoadBalancer)

loadbalancer-11.yaml

 

https://user-images.githubusercontent.com/52024566/157054135-0c7036b6-4131-4cbe-af6a-79ab9e2c1699.png

  • port: 서비스 포트
  • targetPort: 파드 포트
  • Metallb 로 접근
  • 로드밸런서는 노드 포트 필요없고 Metallb을 통해서 구성하게 된다.
  • 한 개 더 배포하면, 포트와 타켓 포트를 통해서, 로드 밸런서를 통해서 선언된다.

loadbalancer-12.yaml

 

Overview

 

  1. 사용자는 ConfigMap을 통하여 EXT IP로 접속
  2. 내부의 파드로 연결됨
k get po -n metalb-system
k apply -f ~11
k apply -f ~12 
k delete -f _/ch4/4.4/* 

노드 밸런서 두개 실행한다. 순서에 따라서 ip가 제공이 되기 때문에 순서가 바뀌면 안된다. 11번을 먼저 실행해야한다.

노드포트와 로드 밸런서 2개 동작을 확인한다.

외부 이름(ExternalName)

externalname-1.yaml

 

externalname-2.yaml

 

  • 서비스 굳이 들어가야 하나 라는 생각
  • 외부의 이름을 그대로 서비스하는 것이다.
  • 외부 도메인 주소. 자기가 원하는 대로 수정해야한다. 외부 주소 변경되면 코드 자체를 수정해야 한다. 외부의 서비스를 서비스화 해서 만들어준 독특한 컨셉이다.

Overview

 

  • 컨테이너 내부에서 외부 도메인을 aliasing 하는 데에 사용
ls _Lecture/...
k get svc
k run net --image=sysnet4admin/net-tools-ifn 

k get po
k exec net -it -- /bin/bash

nslookup ex-url-1 # 클러스터 안에서. 외부에 있는 이름을 aliasing 해준다. 
exit

k delete -f external_service 

클러스터주소(ClusterIP)와 헤드리스(Headless)

cluster ip.yaml

 

  • 파드와 파드의 연결을 위한 내부 IP
  • 포트와 타깃 포트를 지정한다.
  • 클러스터 ip는 파드를 연결하는 내부의 ip이다. 클러스터 내부에서 쓰이는 목적이다.

headless.yaml

 

  • 클러스터 IP를 None으로 지정하면 Headless가 됨
  • 헤드 리스는 클러스터 ip는 none. 내부에서 쓰이지만 Ip가 없는 것이다.

클러스터주소와 헤드리스 비교

  • 헤드리스를 사용할 경우 IP 주소를 소진하지 않고 스테이트 풀셋을 연결할 수 있음
  • 헤드리스는 statefulset과 밀접한 연관이있다. ip를 소진하지 않고도 내부에서 도메인 이름으로 통신할 수 있기 때문이다. 헤드리스에서 도메인 이름이 제공된다면 그 도메인 이름으로 스테이트 풀셋을 연결할 수 있다. 만약 다른 거라면 레플리카셋 이름이 해시값이어서 내부에서 도메인으로 호출되는 호스트 이름이 매번 바뀐다. 하지만 statefulset은 이름이 고정이다.
  • 스테이트 풀셋 각각의 파드는 고정된 이름을 갖고 각각의 목적을 갖고 있도록 설계할 수 있음
    • NodePort나 LoadBalancer를 사용할 경우 각각의 파드에 대한 접속을 통제하기 어려움
    • 따라서 헤드리스를 사용하여 스테이트 풀셋에 대한 연결을 관리

sts-svc-domain-headless.yaml

 

.

nslookup sts-svc-domain

nslookup sts-chk-hn-0.sts-svc.domain nslookup sts-chk-hn-1.sts-svc.domain nslookup sts-chk-hn-2.sts-svc.domain

  • 위와 같은 명령어로 스테이트풀셋 내 각각의 노드에 서비스 이름으로 접근 가능
  • serviceName을 통하여 노드와 헤드리스가 결합됨
  • LoadBalancer로 노출은 가능하나 스테이트풀셋의 목적에 부합하지 않으므로 자주 사용하지는 않음

 

 

💡 stateFulset + headless 조합으로 쓰고 싶은 경우, service metadata의 이름과 stateFulSet의 serviceName과 매핑 시켜주어야 함!!!

 

엔드포인트(Endpoints)

  • 로드밸런서, 디플로이맨트 연결하면 → endPoint가 만들어진다.
  • 로드벨런서 엔드 포인트 확인
k apply -f dsjakdlajsl
k get endpoints #항상 복수임   
k apply -f 
k get po, svc 
k get po -o wide 
  • 엔드포인트란 서비스로 노출한 다음에 서비스가 도달해야 될 종착지. 로드밸런서의 끝점

loadbalancer.yaml의 엔드포인트

 

  • 파드의 개수만큼 엔드포인트가 자동으로 생성됨
  • 외부에 노출된 서비스를 통하여 도달하는 파드의 IP를 일컬음

service-endpoints.yaml

 

  • metadata.name을 클러스터와 일치시켜 수동으로 엔드포인트 생성
  • 위와 같이 로드밸런서의 IP를 엔드포인트로 지정할 경우 로드밸런서를 거쳐 최종적으로 파드에 도달
  • 엔드포인트 임의로 만들어서 경로를 매뉴얼하게 지정하는 것이라 생각하면 됨

인그레스(Ingress)

NodePort와 인그레스

클러스터 → 엔드포인트로 연결하게 된다.

 

  1. 사용자가 워커 노드의 포트로 접근
  2. NodePort 서비스로 이동
  3. 접속 경로에 따라 해당하는 파드로 이동

LoadBalancer와 인그레스

서비스에서 클러스터 서비스로 연결 되고 이는 각각 서비스의 엔드 포인트로

 

  1. 사용자가 로드밸런서 서비스에 접근
  2. 접속 경로에 따라 서비스로 이동
  3. 각각의 서비스의 엔드포인트로 이동

ingress.yaml

 

  • path를 지정하여 각각의 서비스와 연결
  • 각각의 디플로이먼트에 연결해 준다. 서비스 네임으로 연결해준다. 클러스터 ip의 서비스 네임!

레이블(labels)과 애너테이션(annotations)의 차이

 

  • Labels: 관리자, 개발자가 인식하는 부가 정보. 사람이 쓸려고 만든 정보
  • Annotation: 시스템이 인식하는 부가 정보. 레이블도 주석, 애노테이션도 주석

내부적으로 규약에 가깝다.!

각 타입별 ingress controller 설정의 차이

 

  • NodePort의 경우 무작위로 지정되나 실습의 편의를 위해 spec 수정
  • LoadBalancer는 포트를 지정할 필요 없음

실습

k apply -f deploy-hn.yml // 세개 디플로이 먼트 진행한다. 세개 서비스 진행한다.  
k apply -f ingress.yaml // ingress 연결한다.  
// 노드 포트 말고 노드 밸런서로 할 수 있다! 
k get svc -n ingree-nginx