[k8s] 5. 서비스 - 파드를 연결하고 외부에 노출

sightstudio

·

2020. 10. 11. 10:52

 

지난 시간엔 디플로이먼트를 통해 레플리카 셋, 파드를 편리하게 관리하는 법을 배웠습니다.

이번 시간에는 파드를 외부에 노출하는 서비스에 대해 알아봅니다.

 

1. 이전까지

이전 글에서는 다른 파드에 접근하기 위해 임시로 테스트 파드를 만든 뒤

테스트 파드에서 해당 파드로 접근을 했었습니다. 즉, 클러스터 내부에서만 사용할 수 있었습니다.

 

또한 더 큰 문제는 파드의 IP는 계속 변한다는 부분입이다. 여러개의 디플로이먼트를 연동하려면

파드의 IP가 아닌 다른 걸로 서로를 발견할 수 있는 방법이 필요합니다. (Discovery)

 

여담이지만, 이 내용을 보니 Spring Cloud의 디스커버리 서비스인 Eureka가 떠오르네요.

 

 

2. 서비스 란

서비스의 주요기능은 다음과 같습니다.

1.  여러 개의 파드에 고유한 도메인 이름 부여

2. 여러 개의 파드 접근 시 , 요청을 로드벨런싱

3. 클라우드 플랫폼의 로드 벨런서, 클러스터 노드의 파드 등을 통해 파드 외부에 노출

 

Docker에서는 -p 옵션을 통해 포트를 외부로 노출시키거나

docker run --link, 오버레이 네트워크 등으로 컨테이너들이 서로 접근 할 수 있었습니다.

 

3. 서비스의  종류 

kubernetes.io/docs/concepts/services-networking/

 

서비스의 종류는 여러가지가 있지만 주로 3개의 서비스 타입을 자주 사용하게됩니다.

 

1. ClusterIP          : k8s 내부에서만 파드들을 접근 할 때 사용합니다.                                            |  private

 

2. NodePort        : 파드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방합니다.    |  public

 

3. LoadBalancer : AWS, GCP와 같은 클라우드 플랫폼 환경에서만 사용할 수 있습니다.

클라우드 플랫폼에서 제공하는 LB들을 동적으로 프로비저닝해서 파드에 연결합니다.

 

 

실습)

먼저 디플로이먼트를 생성합니다. 

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: hostname-deployment
spec: 
  replicas: 3
  selector: 
    matchLabels: 
      app: webserver
  template:
    metadata: 
      name: my-webserver
      labels: 
        app: webserver
    spec: 
      containers:
      - name: my-webserver
        image: alicek106/rr-test:echo-hostname
        ports: 
        - containerPort: 80
kubectl apply -f deployment-hostname.yaml

 

실습 1. ClusterIP 

hostname-svc-clusterip.yaml을 만들고 다음과 같이 서비스를 생성합니다.

apiVersion: v1
kind: Service
metadata: 
  name: hostname-svc-clusterip
spec:
  ports:
   - name: web-port
     port: 8080
     targetPort: 80
  selector:
   app: webserver
  type: ClusterIP
kubectl apply -f hostname-svc-clusterip.yaml

 

이번에도 테스트 파드를 만들어서 접근해보겠습니다.

kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never bash


# 접속 후
curl hostname-svc-clusterip:8080

 

이번에는 IP가 아니라 컨테이너 이름 자체로 접근할 수 있습니다. 이는 k8s가 내부 DNS 를 구동하고 있어 파드들이 

자동으로 DNS를 사용하도록 설정되기 때문입니다. 이 덕분에 파드의 IP를 몰라도 서비스 명을 통해 통신할 수 있습니다.

 

 

 

실습 2.  NodePort 

NodePort 타입의 서비스를 통해 외부에서 클러스터로 접근할 수 있습니다.

단, 이름과 같이 모든 노드의 특정 포트를 개방해서 서비스에 접근하는 방식입니다.

 

위의 hostname-svc-clusterip.yaml 파일에서 타입만 바꾼

hostname-svc-nodeport.yaml를 생성합니다.

apiVersion: v1
kind: Service
metadata: 
  name: hostname-svc-clusterip
spec:
  ports:
   - name: web-port
     port: 8080
     targetPort: 80
  selector:
   app: webserver
  type: NodePort
 
kubectl apply -f hostname-svc-nodeport.yaml

 

서비스 목록을 확인하면 NodePort 타입은 30068 포트가 붙어있는것을 알 수 있습니다.

클러스터의 모든 노드에 내부 IP또는 외부 IP를 통해 30068포트에 접근하면 해당 서비스에 접근 할 수 있습니다.

포트는 환경마다 다를 수 있습니다.

 

이번엔 테스트 컨테이너가 아닌 호스트 환경에서 curl로 요청을 보내보았습니다.

이전과는 다르게 잘 연결되는걸 확인 할 수 있습니다.

 

NodePort타입은 ClusterIP의 기능을 포함하고 있기 때문에

ClusterIP처럼 파드 내에서 내부 IP와 DNS를 사용해서 접근할 수 있습니다.

 

하지만 실제 운영환경에서는 NodePort로 서동동비스를 외부에 제공하는 경우는 많지 않고,

인그래스(Ingress)라고 부르는 k8s 오브젝트에 간접적으로 사용되는 경우가 많습니다.

 

kubernetes.io/docs/concepts/workloads/controllers/deployment/

 

Deployments

A Deployment provides declarative updates for Pods ReplicaSets. You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new Replica

kubernetes.io

www.yes24.com/Product/Goods/84927385

 

시작하세요! 도커/쿠버네티스

본서는 도커를 처음 접하는 개발자를 위한 도커 컨테이너와 이미지의 기본적인 개념을 먼저 설명한 뒤, 도커 컴포즈와 스웜 모드를 통해 컨테이너 애플리케이션을 YAML 파일로 작성하고 클러스��

www.yes24.com