Kubernetes Service를 이용한 클러스터 외부 공개
여기에서는 Service를 이용한 클러스터 내부 및 외부 공개하는 방법에 대해서 알아보겠다.
클러스터 내부에서 연결
먼저 클러스터 내에서 연결을 확인한다. 클러스터에 curl
컨테이너가 들어있는 Pod를 생성하고, Shell
연결을 한 후에 helloworld Pod에 Curl의 액세스 테스트를 실행해 보겠다.
먼저, 테스트용 Pod를 생성 실행한다.
% kubectl run --port 8080 --image gcr.io/google-samples/hello-app:1.0 --restart Never helloworld
pod/helloworld created
Pod 목록을 IP를 포함해서 표시(-o wide
를 붙인다)한다.
% kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
helloworld 1/1 Running 0 3m44s 172.17.0.3 minikube <none> <none>
클러스터 내부에 들어가 curl
을 실행한다.
% kubectl run --image curlimages/curl:latest -it --restart Never --rm curl sh
If you don't see a command prompt, try pressing enter.
/ $ curl 172.17.0.3:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld
/ $
이 결과를 보면, curl
에서 helloworld의 IP인 172.17.0.3
을 지정하고, 포트를 8080
으로 열렸기 때문에, curl
컨테이너로부터 hellorowld 컨테이너에 접속을 할 수 있게 된 것이다.
이는 내부에 있는지 확인하기 위해 curl 컨테이너가 동작한 상태로, 또 하나의 터미널을 열어서 Pod 목록을 IP를 포함해 표시해 보도록 하자.
% kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curl 1/1 Running 0 23s 172.17.0.4 minikube <none> <none>
helloworld 1/1 Running 0 12m 172.17.0.3 minikube <none> <none>
컨테이너가 같은 네트워크내에 존재해 있는지 확인할 수 있다.
클러스터 외부에서 연결
다음으로 클러스터 외부에서 연결을 시도하려고 하면 되지 않는다. 이는 Docker의 경우와 동일하며 호스트 IP와 Pod의 IP 범위가 다르기 때문이다. 따라서 액세스할 수 있게 하려면 Service라는 것을 만들고 Pod를 외부에 공개를 해야 한다.
서비스는 Pod를 클러스터 내외에 공개하는 정적 IP 주소를 가진 L4 로드 밸런서를 의미한다. Pod 자체는 언제 중지가 되게 될지 모르기 때문에, 분배 되는 곳에서 서비스를 공개한다고 한다.
Service에는 3개가 있고, 각각 아래와 같은 특징을 가지고 있다.
- ClusterIP Service (클러스터내 접속)
언제 소멸할지 불명한 Pod의 IP를 추상화하여, 정적인 IP를 가진 프록시를 두는 것으로 아래와 같은 이점이 있다.- Pod에 액세스할 때, Pod의 IP를 알 필요가 없다.
- Pod에 액세스할 때, 로드 밸런스 해준다.
- NodePort Service (클러스터 내외 접속)
ClusterIP에서는 불가능했던 클러스터 외부에의 Pod의 공개를 NodeIP와 NodePort를 경유해 가능하게 할 수 있다는 점이 장점이 있다.
그러나 다음과 같은 단점도 존재한다.- Node IP를 알아야 한다.
- Node Port를 알아야 한다.
- LoadBalancer Service(클러스터 내외 접속)
프로바이더의 L4 로드 밸런서의 DNS 로부터 각 노드의 특정의 포트에 Routing 하여 Pod에 액세스를 실행한다.
따라서, Node IP 및 Node 포트를 알 필요가 없다. 다만, 아래와 같은 단점도 있다.- 1개의 Service마다 1개의 로드 밸런서가 작성되기 때문에 고비용이 된다.
- L4의 로드 밸런서이므로, L7의 HTTP의 호스트, 패스에서의 LB 배분을 할 수 없다.
위의 각 서비스에 대해 내용을 확인해 보도록 하자.
ClusterIP 서비스
HelloWorld Pod를 ClusterIP Service로 클러스터 내부에 공개하고 동일한 클러스터의 다른 Pod에서 액세스할 수 있음을 살펴보겠다.
아래와 같이 기동하고 있는 Pod에 --type ClusterIP
옵션을 지정하는 것으로 ClusterIP의 Service로서 공개를 실행할 수 있다.
kubectl expose pod [Pod명] --type ClusterIP [Service명]
먼저, 테스트용 Pod를 생성 실행한다. *(기존에 이미 있다면 같은 이름의 Pod가 있다면, kubectl delete pod helloworld
명령으로 삭제 한다.)
% kubectl run --image gcr.io/google-samples/hello-app:1.0 --restart Never helloworld
pod/helloworld created
helloworld Pod을 helloworld-clusterip
라는 Service명으로 공개한다.
% kubectl expose pod helloworld --type ClusterIP --port 8080 --name helloworld-clusterip
service/helloworld-clusterip exposed
아래 명령을 사용하여 서비스 목록을 조회한다.
% kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld-clusterip ClusterIP 10.98.60.0 <none> 8080/TCP 25s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16h
조회 결과 첫번째 행에 Type이 ClusterIP
인 서비스가 생성된 것을 확인할 수 있다.
다음은 curl 컨테이너를 다시 시작하고 해당 컨테이너 내에서 helloworld-clusterip
을 통해 helloworld
에 접근을 해보도록 하겠다.
% kubectl run --image curlimages/curl:7.68.0 -it --restart Never --rm curl sh
If you don't see a command prompt, try pressing enter.
/ $
열린 Shell에 curl
명령어로 접속해 본다.
/ $ curl 10.98.60.0:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld
접속한 결과 helloworld
에 접근이 가능한 것을 확인할 수 있다. 이 결과는 위에서 설명한 “클러스터 내부에서 연결"에서의 결과와 동일하다.
그러나, 위에서 한 것은 curl 컨테이너에서 직접 helloworld
컨테이너에 연결을 한 것이고, 이번의 실행한 결과는 curl 컨테이너에서 Service인 helloworld-clusterip
에 접근해서, 로드 밸런스(1개의 Pod만 생성했기 있기 때문에 특정의 Pod가 되긴 하지만) 기능에 의해 Service가 helloworld
에 접속한다는 흐름이 다르다. 따라서, 서로 의미가 다르므로 주의가 필요하다.
NodePort Service
HelloWorld Pod를 NodeIP Service로 클러스터 내부와 외부에 게시하고 동일한 클러스터의 다른 Pod에서 액세스할 수 있음을 살펴보겠다.
아래와 같이 기동하고 있는 Pod에 대해 --type NodePort
의 옵션을 지정하는 것만으로 ClusterIP의 Service로서 공개할 수 있다.
kubectl expose pod [Pod명] --type NodePortIP [Service명]
helloworld Pod을 helloworld-nodeport
라는 Service명으로 공개한다.
% kubectl expose pod helloworld --type NodePort --port 8080 --name helloworld-nodeport
service/helloworld-nodeport exposed
아래 명령을 사용하여 서비스 목록을 조회해 본다.
% kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld-nodeport NodePort 10.110.238.186 <none> 8080:31942/TCP 38s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16h
그 결과 첫번째 행에 Type
이 Nodeport
인 서비스가 생성된 것을 확인할 수 있다.
다음은 동일한 클러스터 내에서 접속할 수 있는지 확인한다. 절차는 ClusterIP의 경우와 동일하다.
먼저 기존에 curl
컨테이너를 삭제하고 다시 생성한다.
% kubectl delete pod curl
% kubectl run --image curlimages/curl:7.68.0 -it --restart Never --rm curl sh
If you don't see a command prompt, try pressing enter.
/ $
그러고, 해당 컨테이너 내에서 helloworld-nodeport
을 통해 helloworld
에 접근을 해보도록 하겠다.
/ $ curl 10.110.238.186:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld
/ $
그 결과 helloworld-nodeport
를 통해 helloworld
에 접속 할 수 있음을 확인할 수 있다.
그럼 다음으로 클러스터 외부(로컬 환경)에서 접속할 수 있는지 확인한다. 연결을 위해 minikube의 IP가 필요하므로 아래 명령을 실행하여 IP를 조회해 본다.
% minikube ip
192.168.49.2
이 IP에 대해 curl
명령을 로컬 환경에서 실행하여 접속해 본다. 이 때 포트는 Pod에서의 31942
를 지정한다.
/ $ curl 192.168.49.2:31942
Hello, world!
Version: 1.0.0
Hostname: helloworld
접속 결과 helloworld
에 접속을 할 수 있다는 것을 확인할 수 있다.
(minikube 기동시 설정에 따라 액세스 할 수 없는 경우가 있다. 이 경우 minikube service --url helloworld-nodeport
명령을 실행하고 출력된 url에 대해 curl 명령을 실행한다.)
로드밸런서 서비스
HelloWorld Pod를 NodeIP Service로 클러스터 내부와 외부에 게시하고 동일한 클러스터의 다른 Pod에서 액세스할 수 있음을 살펴 보겠다.
아래와 같이 기동하고 있는 Pod에 –type LoadBalancer 옵션을 지정하는 것으로 ClusterIP의 Service로서 공개를 실시할 수 있다.
kubectl expose pod [Pod명] --type NodePortIP [Service명]
helloworld
Pod을 helloworld-loadbalancer
이라는 Service명으로 공개한다.
% kubectl expose pod helloworld --type LoadBalancer --port 8080 --name helloworld-loadbalancer
service/helloworld-loadbalancer exposed
아래 명령을 사용하여 서비스 목록을 조회한다.
% kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld-loadbalancer LoadBalancer 10.104.176.59 <pending> 8080:30100/TCP 27s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16h
그 결과 첫번째 행에 Type
이 LoadBalancer
인 서비스가 생성된 것을 확인할 수 있다.
먼저 동일한 클러스터 내에서 액세스할 수 있는지 확인한다. 절차는 ClusterIP의 경우와 동일하다.
% kubectl run --image curlimages/curl:7.68.0 -it --restart Never --rm curl sh
If you don't see a command prompt, try pressing enter.
/ $
열린 Shell에 curl
명령어로 접속해 본다.
/ $ curl 10.104.176.59:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld
/ $
접속 결과 helloworld-LoadBalancer
를 통해 helloworld
에 접근이 할 수 있음을 확인할 수 있다.
그런 다음 클러스터 외부(로컬 환경)에서 접근 할 수 있는지 확인한다.
% minikube service helloworld-loadbalancer --url
http://127.0.0.1:53240
❗ Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
콘솔을 그대로 두고, 또 다른 콘솔을 켜서 아래 명령으로 접속을 확인 한다.
% curl http://127.0.0.1:53240
Hello, world!
Version: 1.0.0
Hostname: helloworld
실행하면 helloworld
에 접근 할 수 있음을 확인할 수 있다.