Kubernetes 리소스 Service에 대해 이해하고 실습해보기

Bakumando·2022년 5월 24일
1

Kubernetes

목록 보기
8/17
post-thumbnail

들어가기에 앞서...

  • 본 글은 쿠버네티스 시리즈 중의 하나로, kubernetes 실습을 위한 기본 환경 세팅이 이루어져 있지 않은 분은 시리즈 1편을 확인해주시길 바란다.
  • 쿠버네티스 실습 시리즈는 아래 학습 자료를 참고하고 있다.

0. 블로깅 목적

  • Service 정의, 주요 기능 및 여러 타입을 이해한다.
  • ClusterIP 타입과 서비스 디스커버리를 이해하고 실습한다.
  • NodePort 타입과 외부에 노출하는 방법을 이해하고 실습한다.
  • LoadBalancer 타입과 클라우드 프로바이더의 로드밸런서 연동을 이해하고 실습한다.
  • ExternalName 타입과 외부 요청 전달을 이해하고 실습한다.

1. Service 정의, 주요 기능 및 배포전략을 이해한다.

  • 위 그림은 Nodeport 타입을 활용한 Service이다. Node마다 30080 port가 열려 있고, 외부로부터 30080으로 요청을 받고 Service가 다시 Pod들에 로드밸런싱(분산)해준다.

1) Service 정의

(1) Service?

  • Service는 클러스터 외부로부터 요청을 받을 수 있게 IP를 노출하는 역할을 하는 리소스다. 그리고 Deployment로 Pod를 수평확장하는 상황에, 트래픽을 적절히 분산시키기는 역할을 할 수 있는 리소스이다.
  • 근본적으로 Pod는 클러스터 내부에서만 접근이 가능하며, 클러스터 외부로 노출되어있지 않다. 그래서 클러스터 외부에서 해당 Pod에 직접 요청할 수가 없다. Pod를 외부로 노출시키려면 포트포워딩을 이용하거나 쿠버네티스 Service 오브젝트를 이용해야 한다. 다만 포트포워딩은 테스팅 목적이 강하므로 Service 리소스를 활용할 줄 알아야 한다.

(2) Service 기능

  • 여러 Pod에 대해 클러스터 내에서 사용 가능한 고유 도메인을 부여한다. (DNS 시스템)
    • 클러스터 내부 etcd를 통해서 도메인 관리를 수행하는 것이다.
  • 여러 Pod에 대한 요청을 분산하는 로드밸런서 기능을 수행한다.
    • L4 즉, IP/Port 계층 기반으로 로드 밸런서 기능을 수행하게 된다.
  • 일반적으로 실무에서는 ClusterIP 타입의 Service와 함께 Ingress 리소스를 사용하여 외부 트래픽을 처리한다.
    • Ingress을 이용하면 L7 즉, 애플리케이션 계층에서 로드 밸런서 기능을 수행할 수 있다.
  • 참고로 Pod의 IP는 항상 변할 수 있음에 유의해야 한다.
    • Pod는 언제든지 생성되거나 삭제될 수 있는 비영구적인 리소스이다. 따라서 가변적인 IP가 아닌 다른 방식으로 Pod에 접근할 수 있어야 하는데, Service가 그 역할을 하는 것이다.

(3) Service 원리

  • Pod의 경우에는 오토스케일링과 같은 동적으로 생성/삭제 및 재시작 되면서 그 IP가 바뀌기 때문에, Service에서 Pod의 목록을 필터할 때 IP주소를 이용하는 것은 어렵다. 그래서 사용하는 것이 label과 label selector 라는 개념이다.
    • spec.metadata 부분에 Pod 생성 시 사용할 label을 정의할 수 있다.
    • spec.selector.machLabels 부분에는 Service 생성 시 어떤 Pod들을 Service로 묶을 것인지 label Selector를 정의한다.
  • Service를 생성하면, label Selector에서 특정 label을 가진 Pod들만 탐지한다. Service는 이렇게 필터된 Pod의 IP들을 엔드포인트로 묶어 관리하게 된다. 그래서 하나의 Service를 통해 여러 Pod에 로드밸런싱이 이루어질 수 있는 것이다.
  • 그리고 Service를 생성하면 Service 이름으로 DNS가 생성되는데, 해당 DNS 이름으로 트래픽이 들어오면 여러 Pod의 엔드포인트로 로드밸런싱된다.


2) Service 타입

(1) ClusterIP

  • 가장 기본이 되는 Service 타입이며, 클러스터 내부 통신만 가능하고 외부 트래픽은 받을 수 없다.
  • 클러스터 내부에서 Service에 요청을 보낼 때, Service가 관리하는 Pod들에게 로드밸런싱하는 역할을 한다.

(2) NodePort

  • 클러스터 내부 및 외부 통신이 가능한 Service 타입이다.
  • NodePort는 외부 트래픽을 전달을 받을 수 있고, NodePort는 ClusetIP를 wrapping 하는 방식이기 때문에 종장의 흐름은 결국 ClusetIP 비슷한 방식으로 이루어진다.
  • NodePort는 이름 그대로 노드의 포트를 사용한다. (30000-32767)
  • 그리고 클러스터를 구성하는 각각의 Node에 동일한 포트를 열게 되는데, 이렇게 열린 포트를 통해서 Node마다 외부 트래픽을 받고 => 그게 결국 ClusetIP로 모인 후 다시 로드를 분산시키는 방식이다.

(3) LoadBalancer

  • LoadBalancer는 기본적으로 외부에 존재하며, 보통 클라우드 프로바이더와 함께 사용되어 외부 트래픽을 받는 역할을 받는다.
  • 받은 트래픽을 각각의 Service로 전달해서 L4 분배가 일어나게 된다.
  • 역시 마찬가지로 흐름은 처음엔 LoadBalancer를 통하고, 이후엔 NodePort를 거쳐 ClusterIP로 이어지기 때문에 해당 기능을 모두 사용할 수 있다.
  • 클라우드 프로바이더를 사용하는 경우 클라우드 로드밸런서를 사용하여 외부로 노출시킨다.

(4) ExternalName

  • 위 3가지와 전혀 다른 Service 타입이라 할 수 있다. 다른 타입이 트래픽을 받기 위한 용도였다면 ExternalName 타입은 외부로 나가는 트래픽을 변환하기 위한 용도이다.
  • ExternalName을 통해 a.b.com이라는 도메인 트래픽을 클러스터 내부에서는 a.b로 호출을 할 수 있게 해준다. 즉, 도메인 이름을 변환하여 연결해주는 역할을 한다.

2. ClusterIP 타입과 서비스 디스커버리를 이해하고 실습한다.

1) ClusterIP 뜯어보기 (+서비스 디스커버리)

  • Service API 리소스의 가장 기본적인 타입이다.
  • ClusterIP 타입의 Service는 쿠버네티스 클러스터 내부 통신 목적으로만 사용 가능하다.
  • Pod에 부여되는 Pod IP는 내부 전용이라 외부에서 사용을 할 수 없다. 반면 Service 오브젝트는 ClusterIP라는 가상 IP를 가진다.
  • ClusterIP가 가지게 되는 IP의 대역은 Cluster IP CIDR이라고 부른다. 참고로 Service의 ClusterIP CIDR 대역을 확인하는 방법은 다음과 같다.
    • kubectl cluster-info dump | grep -m 1 servcie-cluster-ip-range

  • Service는 Deployment와 같은 다른 리소스와 마찬가지로, Label Selector를 통해서 Service와 연결할 Pod 리스트를 관리한다.
  • ClusterIP 로 들어오는 요청에 대하여서는 Pod에 L4 계층의 로드밸런싱이 이루어진다.
  • ClusterIP 뿐만아니라 이와 연결되는 내부 DNS을 통해 Service 이름을 부여하게 되는데, 이렇게 부여된 Service 이름을 통해서도 통신이 가능하다.
    • 이러한 통신을 서비스 디스커버리라 한다. 서비스 디스커버리란 배포된 애플리케이션이 어디에 있는지를 찾아내는 장치인 것이다.
    • 이는 Docker-compose에도 있는 기능이기도 하다. Docker-compose 내에서도 Service명으로 바로 서비스 디스커버리가 가능하기 때문이다.


2) ClusterIP 실습하기

  • 우선 yml 파일을 2개 준비한다.
  • 앞으로 다른 Service 타입 실습도 진행할 예정이기에 service 폴더 내에 ClusterIP 폴더를 따로 만들어 주자.

deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      name: hello
      labels:
        app: hello
    spec:
      containers:
      - name: nginx
        image: nginxdemos/hello:plain-text
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
  • deployment.yml에 metadata.labels에 app: hello를 넣는다는 건, Pod가 app: hello라는 label을 가지게 된다는 뜻이다.

service.yml

apiVersion: v1
kind: Service
metadata:
  name: hello
  labels:
    app: hello
spec:
  type: ClusterIP
  ports:
  - name: http
    protocol: TCP
    port: 8080
    targetPort: 80
  selector:
    app: hello
  • spec.selector는 service가 트래픽을 어떤 Pod에 전달해줄 것인지를 결정한다.
  • spec.type은 ClusterIP라고 되어있는데 이는 지정하지 않아도 사실 디폴트 값이다.
  • spec.ports가 중요하다. hello라는 이름의 Service 객체를 생성할 때, ClusterIp도 만들어지는데, 여기서 port는 그 ClusterIp의 포트값을 지정하는 부분이다. targetPort는 Pod IP들이 공통으로 쓸 타깃 포트값을 지정하는 것이다. 그래서 결국 Cluster Ip port => Pod IP port로 트래픽을 보내도록 설정하는 것이다.

  • cat deployment.yml
  • cat service.yml
    • yml 내용 확인해준다.

  • kubectl apply -f deployment.yml
  • kubectl apply -f service.yml
    • 각각 yml 스펙에 따라 apply 해준다.

  • kubectl get service
    • ClusterIP 타입으로 hello 라는 이름의 service가 생성되었다.
    • CLUSTER-IP는 새롭게 부여되었음을 알 수 있고, PORT는 8080이다.

  • curl http://10.111.240.139:8080
    • 클러스터 외부에서는 접근이 불가능함을 알 수 있다.

  • minikube ssh
  • curl http://10.111.240.139:8080
    • minikube가 제공하는 ssh 커맨드를 통해 클러스터 내부에 진입해야 한다.
    • 내부에서는 10.111.240.139:8080 접근이 가능함을 알 수 있다.
    • 여기서 보이는 Server address는 Pod IP이다. targetPort가 80으로 잘 설정된 걸 알 수 있다.
    • 그리고 Server name은 Pod 이름(랜덤한 식별값이 부여된)이다.

  • curl http://10.111.240.139:8080 * 4
    • 접근을 4회 반복해보았다. 요청할 때마다 Server address와 Servername이 계속해서 바뀌는 걸 볼 수 있다.
    • 즉 hello Service 오브젝트를 거쳐 자동으로 Pod에 로드밸런싱을 이루어지고 있는 것이다.

  • kubectl get pod
    • pod 내역을 조회하면, 이렇게 여러 식별자를 가진 Pod를 확인할 수 있다. 이 3곳으로 랜덤하게 트래픽이 분산되는 것이다.

  • kubectl run -it test --image=posquit0/doraemon bash
  • curl http://hello:8080
    • 새로운 test Pod를 만들고 내부로 진입하여 hello Service에 접근해보자.
    • 이렇게 Service 이름을 도메인으로 접근할 수 있다. 말했듯 내부 DNS을 통해 Service 이름이 부여되기 때문이다. Service 이름을 도메인 이름으로 설정할 수 있으면, 각각의 애플리케이션에 설정을 할때 상당히 편리해진다. 매우 유용한 기능이다.
    • 아무튼 정상 접근이 되며 Pod IP 주소와 식별자를 확인할 수가 있다. 다른 오브젝트 내에서라도, 클러스터 내부를 향하는 통신은 문제 없이 이루어진다는 것이다.

  • kubectl cluster-info dump | grep -m 1 service-cluster-ip-range
    • Service의 Cluster IP CIDR 대역 확인을 할 수 있는 커맨드다.
    • 클러스터를 구성을 할 때 수정할 수 있는 값이라서 원하는 IP 값으로 설정할 수 있다.

3. NodePort 타입과 외부에 노출하는 방법을 이해하고 실습한다.

1) NodePort 뜯어보기

  • NodePort는 Service를 외부에 노출할 수 있도록 하는 타입이다.
  • NodePort는 ClusterIP 타입 서비스를 한 번 더 감싸서 만들어진 것이므로, NodePort를 사용하더라도 ClusterIP를 동일하게 사용 가능하다.
  • NodePort Service는 모든 쿠버네티스 노드의 동일 포트를 개방한다. 그리고 실제로 해당 포트로 트래픽이 들어오면, 결국 ClusterIP로 전달되어 Pod로 로드밸런싱이 이루어진다.
  • 즉, ClusterIP에 Service 포트와 Pod IP가 사용할 공통의 타깃 포트를 지정하는 설정은 그대로 있고, 거기에 모든 Node IP에 공통의 NodePort를 지정하여 오픈하는 설정이 추가된다.


2) NodePort 실습하기

  • 우선 yml 파일을 2개 준비한다.
  • service 폴더 내에 NodePort 폴더를 따로 만들어 주자.

deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      name: hello
      labels:
        app: hello
    spec:
      containers:
      - name: nginx
        image: nginxdemos/hello:plain-text
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
  • deployment.yml은 ClusterIp에 있는 스펙과 동일하게 설정할 것이기 때문에 cp 하였다.

service.yml

apiVersion: v1
kind: Service
metadata:
  name: hello
  labels:
    app: hello
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    port: 8080
    targetPort: 80
    # nodePort: 31000
  selector:
    app: hello
  • 위에서 봤던 service.yml과 다른 건 서비스 type 부분 뿐이다. NodePort로 세팅해줘야 한다.
  • nodePort는 따로 정의하지 않으면 랜덤값으로 지정이 된다.

  • cat service.yml
    • deployment.yml은 동일하니 생략하고 service.yml만 출력해본다.

  • kubectl apply -f service.yml
    • 마찬가지로 service.yml만 apply 하면 된다. created가 아닌 configured라는 결과가 나온다. 변경사항이 적용된 것이다.

  • kubectl get service
    • Type이 NodePort로 바뀐 걸 알 수 있다. 그리고 이전에는 Port에 8080만 보였다면, 이제는 8080:30914 가 되었는데 :은 매핑시에 활용하는 기호이고, 30914는 모든 노드에 동일한 number로 개방된 Node 포트이다.
    • 이제 흐름을 설명해보면, 트래픽이 {NodeIP주소}:{30914}로 들어오면, {ClusterIP주소}:{8080}으로 전달이 되고, 그 다음 {PodIP주소}:{80}로 로드밸런싱 되서 들어가게 된다.
    • 참고로 minikube는 노드가 하나밖에 없어서 테스트할 수는 없지만, 여러 개의 노드가 있는 환경이라 할지라도 다르지 않다. 모든 노드에 30914 포트가 오픈되기 때문에, 트래픽이 어떤 노드를 통해서 들어오든 ClusterIP 서비스에 모이고 Pod로 로드밸런싱 될 수 있다.

  • kubectl describe service hello
    • Port, NodePort, TargetPort가 전부 확인이 가능하며, Endpoints도 볼 수 있다. 저게 전부 Pod들의 경로이며, 언급했듯 {PodIP}:{TargetPort}로 형태로 이루어진다.

  • kubectl get node -o wide
    • minikube 클러스터로 관리하고 있는 마스터 노드(컨트롤 플레인)의 정보를 확인할 수 있다.
    • 마스터 노드의 INTERNAL-IP가 바로 외부에 노출된 minikube의 IP라고 할 수 있다.
    • 즉 여기에 오픈한 NodePort를 붙이면 외부에서 접근 가능한 경로가된다.

  • curl http://192.168.49.2:30914
    • 위에서 확인한 {minkubeIP}:{NodePort}를 넣은 결과이다. 본래는 NodePort 오픈이기 때문에 클러스터 외부에서 접근이 가능해야 정상이다. 하지만 이건 m1의 문제다.(m1을 제외한 다른 운영체제라면 문제가 없을 것이다.)
    • m1 유저라면 어쩔 수없이 포트 포워딩을 한번 더 해줘야한다.

  • minikube service hello
    • minikube에 포트 포워딩을 쉽게 하도록 도와주는 커맨드가 있으므로 이를 활용한다. minkubeIP:NodePort(http://192.168.49.2:30914)로컬IP:포트(http://127.0.0.1:55669)로 포트 포워딩한 결과이다. 해당 로컬 주소를 통해 이제 오픈된 NodePort로 접근할 수 있게 되었다.
    • 참고로 로컬 포트의 값은 랜덤으로 지정된다.
    • 이렇게 브라우저 창도 자동으로 띄워준다.

  • minikube ssh
  • curl 10.98.86.249:8080
    • curl 뒤에는 {ClusterIP}:{Port}이다. 즉, 클러스터 내부로 들어가면 NodePort가 아니라 클러스터 IP와 Port로 직접 접근이 가능하단 얘기다. (마치 ClusterIP타입 서비스 처럼!)
    • 즉, NodePort타입 서비스는 ClusterIP를 wrapping 하고 있기 때문에 해당 기능을 사용할 수 있다.
      • 클러스터 외부로부터 NodePort로 트래픽을 받을 수 있고,
      • 클러스터 내부에서 ClusterIP로도 트래픽을 받을 수 있다.

4. LoadBalancer 타입과 클라우드 프로바이더의 로드밸런서의 연동을 이해하고 실습하기

1) LoadBalancer 뜯어보기

  • LoadBalancer 타입의 Service 리소스는 클라우드 프로바이더에서 제공하는 로드밸런서와 연동되는 기능이다.
  • 클라우드 프로바이더에서 제공하는 로드밸런서를 동적으로 생성하는 방식이다.
    • 가령 AWS의 경우엔 ELB, ALB를 지원하게 되는데 이를 동적으로 관리할 수 있게 해주는 Service가 LoadBalancer 타입이다.
  • 아쉬운 건 AWS, GCP 등과 같은 클라우드 환경이 아니라, minikube 같은 개발 환경의 클러스터에서는 로드밸런서 기능 이용이 불가능하다.
  • 하지만 MetalLB 같은 기술 등을 사용하면 로컬 환경이나 온프레미스 환경에서도 LoadBalancer 타입 사용이 가능하다.

  • LoadBalancer 타입 Service는 NodePort 타입 Service를 한 번 더 감싸서 만들어진 것이다.
    • 따라서 LoadBalancer Service도 ClusterIP 사용이 가능하다.
    • LoadBalancer Service를 통해 만들어진 로드밸런서는 NodePort를 타겟 그룹으로 생성한다.
    • NodePort로 들어온 요청은 실제로 ClusterIP로 전달되어 Pod로 포워딩된다.
    • 즉 NodePort랑 비교하면, 처음 트래픽 진입 시점에 과정 하나가 더 생기는 것이다.

  • NodePort의 단점은 노드가 사라졌을 때 자동으로 다른 노드를 통해 접근이 불가능하다는 점이다. 예를 들어, 3개의 노드가 있다면 3개 중에 아무 노드로 접근해도 NodePort로 연결할 수 있지만 어떤 노드가 살아 있는지는 알 수가 없다.
    • 자동으로 살아 있는 노드에 접근하기 위해 모든 노드를 바라보는 Load Balancer가 필요하다. 브라우저는 NodePort에 직접 요청을 보내는 것이 아니라 Load Balancer에 요청하고 Load Balancer가 알아서 살아 있는 노드에 접근하면 NodePort의 단점을 없앨 수 있는 것이다.


2) LoadBalancer 실습하기

  • 클라우드 환경이 아니면 정상적인 테스트가 불가능하기 때문에, MetalLB로 가상 LoadBalancer를 만들어 실습하고자 한다.
  • 일단 yml 파일을 준비한다.

service.yml

apiVersion: v1
kind: Service
metadata:
  name: hello
  labels:
    app: hello
spec:
  type: LoadBalancer
  ports:
  - name: http
    protocol: TCP
    port: 8080
    targetPort: 80
    # nodePort: 31000
  selector:
    app: hello
  • type만 LoadBalancer로 바꿔주면 된다. 다른 명세는 nodePort와 같다.
  • 클라우드 서비스 환경에서 apply하면 CLB를 생성해준다.

metallb-configmap.yml

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data: 
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses: 
      - 192.168.49.2 
  • 선언형 커맨드로 가상 로드밸런서를 만들어줄 때 사용할 yml 이다.
  • addresses: 에는 minikube ip 값을 넣어야 한다.

  • cat service.yml
    • 정상 출력된다.

  • kubectl apply -f service.yml
  • kubectl get svc
    • service 상태를 변화시키고 조회를 해보았다.
    • LoadBalancer로 타입이 바뀌긴 했지만 minikube에서 지원하지 않기 때문에 EXTERNAL-IP 부분이 pending 상태임을 알 수 있다.
    • 특정 서버(노드)를 가리키는 무언가(Load Balancer)가 필요한데 이런 무언가가 로컬에는 존재하지 않는다.

  • minikube addons enable metallb
    • Load Balancer를 사용할 수 없는 환경에서 가상 환경을 만들어 주는 것이 MetalLB이다. minikube에서는 현재 떠 있는 노드를 Load Balancer로 설정해줄 수밖에 없다.
    • minikube의 addons 명령어로 활성화한다.

  • minikube addons configure metallb
    • configure 세팅시에 Enter Load Balancer Start IPEnter Load Balancer End IP 주소를 입력해줘야 한다. 여기엔 minikube ip 값을 넣어주면 된다.

  • cat metallb-configmap.yml
    • minikube를 안쓰고 yml 파일을 활용해 metallb를 적용할 수도 있다.

  • kubectl apply -f metallb-configmap.yml
    • 적용되었다.

  • kubectl get svc
    • service EXTERNAL-IP가 이젠 pending이 아니라 값이 생긴 것을 알 수 있다.
    • 192.168.49.2는 외부에 노출된 노드 IP였는데, 이제는 동시에 LoadBalancer의 외부 노출 IP가 된 것이다.
    • 그래서 앞으로의 실습 중에 LoadBalancer와 NodePort 방식이 둘다 같은 IP(192.168.49.2)를 사용하더라도, 실제로는 서로 다른 IP를 통해 진입이 되고 있다고 감안하고 따라오길 바란다.
    • svc는 service의 축약어이다.

  • curl http://192.168.49.2:8080
    • LoadBalancer로 접근하는 방식이다.
    • 역시 m1의 문제로 그냥은 외부에서 못들어간다. (원래 m1만 아니면 들어가져야 정상)
  • curl http://192.168.49.2:30934
    • NodePort로 접근하는 방식이다.
    • 마찬가지 상황이다.

  • minikube service hello
    • minikube를 활용하면 이렇게 포트포워딩된 로컬주소에서 NodePort로는 진입할 수 있다.
    • LoadBalancer가 NodePort를 감싸고 있기때문에 NodePort 기능을 사용할 수 있다는 건 증명되었지만, 실질적으로 LoadBalancer를 통해 진입했다고 하긴 어려워 아쉬움이 남는 부분이다.

  • kubectl get all (ubuntu 에서 실행)
    • 이대로 끝낼 수는 없다. mac에 UTM(가상머신)을 설치하여 ubuntu OS를 깔고 ubuntu에 ssh로 접근하여 실습을 속행하였다.
    • 미리 mac에서 만든 yml 파일들은 깃헙에 올린뒤, ubuntu에서 클론하여 세팅하고, minikube, kubectl 등을 모두 설치한 뒤 전부 apply한 결과이다.
    • m1 유저들은 굳이 이렇게까지 따라할 필요는 없다. 눈으로 확인하면 충분하리라 본다.
    • 실습을 하고 마지막으로 흐름정리를 한 뒤에 마무리할 것이다. (LoadBalancer 뿐만아니라 안에 wrapping된 NodePort와 ClusterIP도 각각 실습하고 흐름 정리를 해보겠다.)

  • curl 192.168.49.2:8080
    • LoadBalancer를 통한 외부 접근에 성공하였다. URL형식은 다음과 같아야 한다. {LoadBalancerIP주소}:{Service포트}
    • 트래픽 흐름 순서 정리:
      1. 192.168.49.2:8080 (LoadBalancer)
      2. 192.168.49.2:30135 (NodePort)
      3. 10.102.78.34:8080 (ClusterIP)
        => 172.17.0.?:80 (Pod)
        => LoadBalancer을 통하면 총 3가지 경로를 거쳐 Pod에 트래픽이 전달 되는 것이다.

  • curl 192.168.49.2:30135
    • NodePort를 통한 외부 접근에 성공하였다. URL형식은 다음과 같아야 한다. {NodeIP주소}:{Node포트}
    • LoadBalancer 타입이 NodePort를 wrapping하고 있는 만큼 NodePort 기능을 활용할 수 있는 것이다.
    • 트래픽 흐름 순서 정리:
      1. 192.168.49.2:30135 (NodePort)
      2. 10.102.78.34:8080 (ClusterIP)
        => 172.17.0.?:80 (Pod)
      • NodePort을 통하면 총 2가지 경로를 거쳐 Pod에 트래픽이 전달 되는 것이다.

  • minikube ssh
  • curl 10.102.78.34:8080
    • ClusterIP를 통한 접근이다. 당연히 외부 접근을 불가능하기 때문에 일단 클러스터 내부로 들어와 진행하였다. URL형식은 다음과 같아야 한다. {ClusterIP주소}:{Service포트}
    • LoadBalancer 타입이 NodePort를 wrapping하고 있는 만큼 NodePort가 wrapping하고 있는 ClusterIP 기능도 활용할 수 있는 것이다.
    • 트래픽 흐름 순서 정리:
      1. 10.102.78.34:8080 (ClusterIP)
        => 172.17.0.?:80 (Pod)
      • ClusterIP를 통하면 총 1가지 경로를 거쳐 Pod에 트래픽이 전달 되는 것이다.


참고 1) endpoint를 확인하는 방법은?

  • kubectl get ep
  • kubectl describe ep/hello
    • ep는 endpoint의 축약어다.
    • 개별조회 상세조회 모두 잘 이루어진다. Pod 개수만큼의 엔드포인트가 여러개 있다는 걸 알 수 있다.

5. ExternalName 타입과 외부로 요청 전달을 이해하고 실습한다.

1) ExternalName 뜯어보기

  • ExternalName Service는 외부로 요청을 전달하는 목적의 서비스를 제공한다. (기존의 다른 3가지 타입과 다른 성격을 가지고 있다.)
  • 보통은 클러스터 외부에 존재하는 레거시 시스템을 쿠버네티스로 마이그레이션 해야하는 상황에 활용 가능하다.
  • 다만 실질적으로는 앞서 다룬 3가지 서비스 타입과 비교해 많이 사용되지는 않는다.
  • 서비스가 파드를 가리키는 것이 아닌 외부 도메인을 가리키도록 구성이 가능하다.
  • DNS의 CNAME 레코드와 동일한 역할을 수행하는 데 많이 쓰인다. 이는 도메인의 또 다른 alias 도메인을 만들어서 리다이렉트 시켜주는 기능을 뜻하는 것이다.


2) ExternalName 실습하기

  • yml 파일 준비하자.

apiVersion: v1
kind: Service
metadata:
  name: httpbin
spec:
  type: ExternalName
  externalName: httpbin.org
  • ExternalName타입의 명세는 상당히 단순하다.
  • type을 ExternalName으로 잘 주고, externalName에는 실제 외부서비스 중인 domain 이름을 주면 된다.

  • cat service.yml
    • 내용 출력이다.

  • curl http://httpbin.org/get
    • 실제 연동되는 서비스이기 때문에 로컬 환경에서도 결과를 받을 수가 있다.

  • kubectl apply -f service.yml
    • 그럼 이제 ExternalName 타입 서비스에서 외부 url을 연결시켜주는 작업을 위해 service.yml을 적용해준다.
  • kubectl get service
    • 조회를 하면 ExternalName 타입의 httpbin이 생성된 걸 확인할 수 있고, EXTERNAL-IP로 외부 도메인이 설정된걸 볼 수 있다.

  • kubectl run -it test --image=posquit0/doraemon bash
  • curl httpbin/get
    • test pod를 만들고 쉘환경에서 외부 도메인에 접속해보자.
    • 정상적으로 결과가 리턴됨을 확인할 수 있다.
    • 놀라운 건 외부 도메인명(httpbin.org)을 그대로 입력한 게 아니라, service 이름인 httpbin만 입력하였는데도 내부 DNS 시스템으로 인하여 외부 도메인에 접근할 수 있게 세팅되었다는 것이다.
profile
그렇게 바쿠만도는 개발에 퐁당 빠지고 말았답니다.

0개의 댓글