Kubernetes POD는 원리적으로 프로세스의 집합이다. 프로세서들이 라이프사이클을 가지는 것처럼 POD 들도 라이프사이클을 가진다. 만약 워커 노드가 죽으면, 워커노드위에 작동하는 POD들도 종료된다. 서버가 죽으면 서버 위에서 작동하던 프로세스의 생명이 어떻게 될지를 생각하면 된다.
쿠버네티스에서는 POD에 대한 복제본을 설정할 수 있기 때문에, 워커 노드의 문제로 POD가 내려갈 경우 다른 작동 중인 노드에서 POD를 만들어서 복제본의 총합을 유지한다.
쿠버네티스에서 서비스는 논리적인 POD 셋과 그 POD들에 접근할 수 있는 정책을 정의하는 개념이다. 이 개념을 이용해서 POD들을 느슨하게 결합되도록 할 수 있다. 서비스는 다른 쿠버네티스 객체(POD 등)과 마찬가지로 YAML 혹은 JSON을 이용해서 정의 할 수 있다.
POD가 만들어지면 이들은 고유한 IP를 가지게 되는데, 이들은 클러스터 내부 IP로 외부에서 접근 할 수 없다. 쿠버네티스의 서비스 설정을 이용해서 외부에 IP를 노출 시켜줘야 한다. 쉽게 이해하기 위해서 쿠버네티스 네트워크 정책을 살펴보기로 했다.
Kubernetes Deployments vs Service
쿠버네티스 Deployments의 목표는 단순하다. 그 목표는 "POD의 그룹을 관리하는 것"이다. 이들 POD에 대한 정보는 YAML 형식의 deployment 매니패스트(manifest)파일로 관리 한다. Deployments 컨트롤러(controller)는 복제 세트와 POD를 선언하며, 이를 업데이트하고 관리할 책임을 가진다. Deployments는 선언된 복제 세트와 POD의 정보를 읽어서 실제로 클러스터에 POD(애플리케이션)를 배포를 수행한다.
이제 클러스터에 전개된 POD를 외부에서 접근 할 수 있도록 노출(expose)해야 하는데, 이렇게 외부에 노출될 POD를 명확하게 정의하는 추상객체를 서비스라고 한다. 서비스를 통해서 비로서 외부에서 접근 할 수 있게 된다.
이번에 실행할 애플리케이션은 구글에서 제공하는 gcr.io/google-samples/node-hello:1.0](http://gcr.io/google-samples/node-hello:1.0%5D(http://gcr.io/google-samples/node-hello:1.0)) 애플리케이션이다. 먼저 아래와 같이 Deployment 파일을 만들었다. 파일의 이름은 "hello-application.yaml"이다.
$ docker run --name hello joinc/hello-app
* Serving Flask app 'hello'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on [http://127.0.0.1:5000](http://127.0.0.1:5000/)
* Running on [http://172.17.0.2:5000](http://172.17.0.2:5000/)
Deployment
앞서서 joinc/hello-world을 빌드했는데, 지금 상태에서 minikube 클러스터에 배포하면 실패한다. 왜냐하면 현 상태에서 빌드를 하면 로컬 도커 레지스트리에 이미지가 등록되는데 minikube는 자체 레지스트리를 사용하고 있기때문이다. 따라서 minikube 레지스트리에 이미지를 등록해야 한다. minkube docker-env 명령으로 minikube 도커 환경을 확인할 수 있다.
$ minikube docker-env
exportDOCKER_TLS_VERIFY="1"exportDOCKER_HOST="tcp://[192.168.49.2:2376](http://192.168.49.2:2376/)"exportDOCKER_CERT_PATH="/home/yundream/.minikube/certs"exportMINIKUBE_ACTIVE_DOCKERD="minikube"# To point your shell to minikube's docker-daemon, run: # eval $(minikube -p minikube docker-env)
이제 eval 명령으로 minikube 도커 환경을 등록하자.
$ eval$(minikube -p minikube docker-env)
변경된 도커 레지시트리를 참조하는지 확인해 보자. 성공적으로 환경이 적용됐다면 대략 아래와 같이 kubenetes 이미지 목록이 출력될 것이다.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[registry.k8s.io/kube-apiserver](http://registry.k8s.io/kube-apiserver) v1.26.1 deb04688c4a3 3 weeks ago 134MB
[registry.k8s.io/kube-controller-manager](http://registry.k8s.io/kube-controller-manager) v1.26.1 e9c08e11b07f 3 weeks ago 124MB
[registry.k8s.io/kube-scheduler](http://registry.k8s.io/kube-scheduler) v1.26.1 655493523f60 3 weeks ago 56.3MB
[registry.k8s.io/kube-proxy](http://registry.k8s.io/kube-proxy) v1.26.1 46a6bb3c77ce 3 weeks ago 65.6MB
[registry.k8s.io/etcd](http://registry.k8s.io/etcd)3.5.6-0 fce326961ae2 2 months ago 299MB
[registry.k8s.io/pause](http://registry.k8s.io/pause)3.9 e6f181688397 4 months ago 744kB
kubernetesui/dashboard <none> 07655ddf2eeb 5 months ago 246MB
kubernetesui/metrics-scraper <none> 115053965e86 8 months ago 43.8MB
[registry.k8s.io/coredns/coredns](http://registry.k8s.io/coredns/coredns) v1.9.3 5185b96f0bec 8 months ago 48.8MB
$ kubectl get deployments hello-world
NAME READY UP-TO-DATE AVAILABLE AGE
hello-world 2/2 22 21s
Service
Service Type
Kubernetes 애플리케이션을 외부에 노출하기 위해서는 Kubernetes service 개체를 만들어야 한다. 결국 Kubernetes service는 외부에 노출하기 위한 네트워크 구조를 만드는 건데, 이를 Service Type 이라고 하며 총 4가지의 Service Type이 있다.
ClusterIP는 클러스터 내부에 새로운 IP를 할당하고 여러 개의 POD를 바라보는 로드밸런서 형태로 작동한다. 내부에서만 사용하는 IP인 만큼 kubernetes 클러스터 내에서의 통신및 연결을 관리하기 위해서 사용한다.
내부통신 : 동일한 Kubernetes 클러스터 내의 다른 서비스 또는 POD 간의 통신에 사용 할 수 있다.
로드밸런싱 : 서비스의 일부인 여러 POD에 트래픽을 분산하는데 사용 할 수 있다.
서비스디스커버리(Service Discovery) : ClusterIP는 고정된 IP와 DNS 이름을 제공하기 때문에 이 정보를 이용해서 서비스간 연결을 할 수 있다.
확장 : 로드밸런서처럼 사용 할 수 있기 때문에 IP 주소나 DNS 이름에 영향을 주지 않고 포드를 확장 혹은 축소 할 수 있다.
NodePort는 클러스터의 각 노드에 있느 특정 포트를 이용해서 서비스를 노출하는 Service Type이다. 개발 또는 테스트를 위해서 외부에서 서비스를 쉽게 접근하기 위한 목적으로 주료 사용한다.
LoadBalancer 클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출한다.
Ingress 는 클러스터 외부에서 클러스터 내의 서비스로 HTTP 및 HTTPS 경로를 제공하기 위해서 사용한다. 복잡한 트래픽 라우팅이 가능하다는 점에서 AWS 등에서 제공하는 API Gateway나 Application LoadBalancer과 유사한 면이 있다. Ingress라는 익숙하지 않은 용어로 헷갈린다면 진보된 Application LoadBalancer 혹은 API Gateway라고 이해하면 된다.
Ingress가 하는 일이 LoadBalancer와 유사하기 때문에, 서비스 목적에 따라서 다양한 종류의 LoadBalancer를 Ingress 컨트롤러(controller)로 사용할 수 있다. NginX, Istio, traefik, kong과 같은 오픈소스 LoadBalancer 뿐만 아니라 AWS를 사용하고 있을 경우 Application LoadBalancer를 Ingress 컨트롤러로도 사용 할 수 있다.
LoadBalancer Type의 Service 만들기
이제 hello-world deployment를 expost 해서 외부에서 접근 할 수 있는 서비스로 만들어보자.
spec.selector는 service로 expose하기 위한 app(deployment)이름이다. kubectl apply 명령으로 서비스를 실행해보자.
kubectl apply -f hello-service.yaml
NodePort Type의 Service 만들기
NodePort Type으로 Service를 만들어보자. deployment를 생성한다.
$ kubectl apply -f ./hello-application.yaml
Service 매니패스트 파일은 아래와 같다.
apiVersion: v1
kind: Service
metadata:name: hello-world-service
spec:selector:run: hello-world-app
ports:-port:5000type: NodePort
Service를 생성한다.
$ kubectl apply -f ./hello-service.yaml
Service 가 만들어졌는지 확인하고
$ kubectl get service hello-world-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world-service NodePort 10.99.149.177 <none>5000:30332/TCP 25m
Service URL로 테스트 한다.
$ minikube service --url hello-world-service
http://192.168.49.2:30332
정리
우리는 이 문서에서 minikube를 이용해서 kubernetes service를 만들었다. 다음 문서인 Minikube 와 함께하는 Kubernetes Study 4 - Ingress 에서는 kubernetes ingress를 이용해서 kubernetes 클러스터에서 만들어진 서비스를 HTTP/HTTPS 로 노출하는 방법을 살펴보도록 하겠다.
Minikube 와 함께하는 Kubernetes 목차
이번 문서에서는 지난 Minikube 와 함께하는 Kubernetes Study 2 - deployments 에서 다루었던 deployments에 이어서 kubernetes service를 다룰 것이다. 모든 내용은 로컬에서 kubenetes 구축 및 테스트를 도와주는 툴인 minikube 환경에서 진행한다. minikube 환경은 Minikube 와 함께하는 Kubernetes Study 1 - Minikube 설치 을 참고해서 만들자.
POD와 Service
Kubernetes POD는 원리적으로 프로세스의 집합이다. 프로세서들이 라이프사이클을 가지는 것처럼 POD 들도 라이프사이클을 가진다. 만약 워커 노드가 죽으면, 워커노드위에 작동하는 POD들도 종료된다. 서버가 죽으면 서버 위에서 작동하던 프로세스의 생명이 어떻게 될지를 생각하면 된다.
쿠버네티스에서는 POD에 대한 복제본을 설정할 수 있기 때문에, 워커 노드의 문제로 POD가 내려갈 경우 다른 작동 중인 노드에서 POD를 만들어서 복제본의 총합을 유지한다.
쿠버네티스에서 서비스는 논리적인 POD 셋과 그 POD들에 접근할 수 있는 정책을 정의하는 개념이다. 이 개념을 이용해서 POD들을 느슨하게 결합되도록 할 수 있다. 서비스는 다른 쿠버네티스 객체(POD 등)과 마찬가지로 YAML 혹은 JSON을 이용해서 정의 할 수 있다.
POD가 만들어지면 이들은 고유한 IP를 가지게 되는데, 이들은 클러스터 내부 IP로 외부에서 접근 할 수 없다. 쿠버네티스의 서비스 설정을 이용해서 외부에 IP를 노출 시켜줘야 한다. 쉽게 이해하기 위해서 쿠버네티스 네트워크 정책을 살펴보기로 했다.
Kubernetes Deployments vs Service
쿠버네티스 Deployments의 목표는 단순하다. 그 목표는 "POD의 그룹을 관리하는 것"이다. 이들 POD에 대한 정보는 YAML 형식의 deployment 매니패스트(manifest)파일로 관리 한다. Deployments 컨트롤러(controller)는 복제 세트와 POD를 선언하며, 이를 업데이트하고 관리할 책임을 가진다. Deployments는 선언된 복제 세트와 POD의 정보를 읽어서 실제로 클러스터에 POD(애플리케이션)를 배포를 수행한다.

이제 클러스터에 전개된 POD를 외부에서 접근 할 수 있도록 노출(expose)해야 하는데, 이렇게 외부에 노출될 POD를 명확하게 정의하는 추상객체를 서비스라고 한다. 서비스를 통해서 비로서 외부에서 접근 할 수 있게 된다.
Service 전개
Google에서 제공하는 Service 예제를 이용해서 Service가 어떻게 실행되는지 알아본 다음 직접 Hello World Service를 전개해보기로 했다. Minikube 와 함께하는 Kubernetes Study 1 - Minikube 설치 와 Minikube 와 함께하는 Kubernetes Study 2 - deployments 의 복습 느낌이 될 것이다.
이번에 실행할 애플리케이션은 구글에서 제공하는 gcr.io/google-samples/node-hello:1.0](http://gcr.io/google-samples/node-hello:1.0%5D(http://gcr.io/google-samples/node-hello:1.0)) 애플리케이션이다. 먼저 아래와 같이 Deployment 파일을 만들었다. 파일의 이름은 "hello-application.yaml"이다.
[gcr.io](http://gcr.io/)는%EB%8A%94) Google Cloud의 Container Registry 이다. 여기에 테스트를 위한 도커이미지들을 제공하는데 그 중 node-hello 로 pod를 구성하기로 했다.
![[Screenshot_20230213_150029.png]]
POD를 전개하고
describe 명령으로 상세 정보를 확인해보자.
이제 외부에서 접근 가능하도록 deployment를 expose 한다.
LoadBalancer 타입으로 8080으로 Export 했다.
클라우드 서비스의 경우에 expost를 하면 퍼블릭 IP가 할당됮지만, 로컬에서 테스트하고 있기 때문에 Public IP를 할당 받을 수 없다. 그래서 port-forward 명령을 이용해서 7070포트로 접근할 수 있게 설정했다.
curl로 테스트해보자.
Hello World Service의 개발
이제 본격적으로 나만의 Hello World Service를 개발해 보자. 이 프로그램은 아래와 같이 개발할 것이다.
이 애플리케이션은 Nginx와 Python Flask로 구성된다.
클라이언트는 NginX를 통해서 API를 호출한다.
Python Flask 기반의 hello API 서버 : /hi/{name} 를 호출하면 "Hello World {name}!!"을 리턴한다. 프로그램의 이름은 hello-flask로 한다.
Dockerizing을 해서 로컬에 도커 저장소에 저장한다.
NginX와 hello-flask를 deploy 한다.
NginX를 expose 해서 외부에서 호출할 수 있게 한다.
로컬에서 API를 테스트 한다.
hello-flask application 개발
아래와 같은 python 코드를 만들었다. 파일의 이름은 hello.py 로 했다.
그리고 의존성 관리를 위해서 requirements.txt 파일을 만들었다.
Dockerfile은 아래와 같다.
자 Dockerfile을 빌드해보자.
아래와 같이 실행이 된다면 성공적으로 빌드를 한 것이다.
Deployment
앞서서 joinc/hello-world을 빌드했는데, 지금 상태에서 minikube 클러스터에 배포하면 실패한다. 왜냐하면 현 상태에서 빌드를 하면 로컬 도커 레지스트리에 이미지가 등록되는데 minikube는 자체 레지스트리를 사용하고 있기때문이다. 따라서 minikube 레지스트리에 이미지를 등록해야 한다. minkube docker-env 명령으로 minikube 도커 환경을 확인할 수 있다.
이제 eval 명령으로 minikube 도커 환경을 등록하자.
변경된 도커 레지시트리를 참조하는지 확인해 보자. 성공적으로 환경이 적용됐다면 대략 아래와 같이 kubenetes 이미지 목록이 출력될 것이다.
이제 Dockerfile을 빌드하면 minikube 도커 레지스트리에 등록된다.
테스트에 사용할 Deployment 매니패스트 파일을 준비했다. 파일이름은 "hello-world.yaml"이다.
hello-world를 deploy 해보자.
Service
Service Type
Kubernetes 애플리케이션을 외부에 노출하기 위해서는 Kubernetes service 개체를 만들어야 한다. 결국 Kubernetes service는 외부에 노출하기 위한 네트워크 구조를 만드는 건데, 이를 Service Type 이라고 하며 총 4가지의 Service Type이 있다.
ClusterIP는 클러스터 내부에 새로운 IP를 할당하고 여러 개의 POD를 바라보는 로드밸런서 형태로 작동한다. 내부에서만 사용하는 IP인 만큼 kubernetes 클러스터 내에서의 통신및 연결을 관리하기 위해서 사용한다.
내부통신 : 동일한 Kubernetes 클러스터 내의 다른 서비스 또는 POD 간의 통신에 사용 할 수 있다.
로드밸런싱 : 서비스의 일부인 여러 POD에 트래픽을 분산하는데 사용 할 수 있다.
서비스디스커버리(Service Discovery) : ClusterIP는 고정된 IP와 DNS 이름을 제공하기 때문에 이 정보를 이용해서 서비스간 연결을 할 수 있다.
확장 : 로드밸런서처럼 사용 할 수 있기 때문에 IP 주소나 DNS 이름에 영향을 주지 않고 포드를 확장 혹은 축소 할 수 있다.
NodePort는 클러스터의 각 노드에 있느 특정 포트를 이용해서 서비스를 노출하는 Service Type이다. 개발 또는 테스트를 위해서 외부에서 서비스를 쉽게 접근하기 위한 목적으로 주료 사용한다.
LoadBalancer 클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출한다.
Ingress 는 클러스터 외부에서 클러스터 내의 서비스로 HTTP 및 HTTPS 경로를 제공하기 위해서 사용한다. 복잡한 트래픽 라우팅이 가능하다는 점에서 AWS 등에서 제공하는 API Gateway나 Application LoadBalancer과 유사한 면이 있다. Ingress라는 익숙하지 않은 용어로 헷갈린다면 진보된 Application LoadBalancer 혹은 API Gateway라고 이해하면 된다.
Ingress가 하는 일이 LoadBalancer와 유사하기 때문에, 서비스 목적에 따라서 다양한 종류의 LoadBalancer를 Ingress 컨트롤러(controller)로 사용할 수 있다. NginX, Istio, traefik, kong과 같은 오픈소스 LoadBalancer 뿐만 아니라 AWS를 사용하고 있을 경우 Application LoadBalancer를 Ingress 컨트롤러로도 사용 할 수 있다.
LoadBalancer Type의 Service 만들기
이제 hello-world deployment를 expost 해서 외부에서 접근 할 수 있는 서비스로 만들어보자.
service의 상세 정보를 확인해보자.
service가 성공적으로 전개됐다면, 로컬에서 테스트 할 수 있도록 포트포워딩을 한다.
curl로 테스트해 보자.
지금까지는 service를 kubectl 명령 파라메터로 만들었는데, 관리를 하기 위해서는 매니패스트 파일로 만들어야 할 것이다. 아래와 같이 service 매니패스트 파일을 만들었다. 파일이름은 hello-service.yaml 로 했다.
spec.selector는 service로 expose하기 위한 app(deployment)이름이다. kubectl apply 명령으로 서비스를 실행해보자.
NodePort Type의 Service 만들기
NodePort Type으로 Service를 만들어보자. deployment를 생성한다.
Service 매니패스트 파일은 아래와 같다.
Service를 생성한다.
Service 가 만들어졌는지 확인하고
Service URL로 테스트 한다.
정리
우리는 이 문서에서 minikube를 이용해서 kubernetes service를 만들었다. 다음 문서인 Minikube 와 함께하는 Kubernetes Study 4 - Ingress 에서는 kubernetes ingress를 이용해서 kubernetes 클러스터에서 만들어진 서비스를 HTTP/HTTPS 로 노출하는 방법을 살펴보도록 하겠다.
참고
https://medium.com/avmconsulting-blog/service-types-in-kubernetes-24a1587677d6
Connect a Frontend to a Backend
Recent Posts
Archive Posts
Tags