[k8s] 5. 서비스 - 파드를 연결하고 외부에 노출
지난 시간엔 디플로이먼트를 통해 레플리카 셋, 파드를 편리하게 관리하는 법을 배웠습니다.
이번 시간에는 파드를 외부에 노출하는 서비스에 대해 알아봅니다.
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