사전 준비
deployment(배포작업) 생성
deployment 생성
deployment는 pod가 동작하게 만드는 규칙에 대한 정의라고 할 수 있다. 결국 service를 배포하는 작업을 의미하고 생성과 노출의 두 단계로 나눠져 있다.
kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.4
deployment 조회
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
hello-minikube 1/1 1 1 5m44s
hello-minikube라는 deployment가 생성되어 있음을 확인할 수 있다.
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m
아직 "hello-minikube" service는 생성되지 않았다.
kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-minikube-7bc9d7884c-flgk6 1/1 Running 0 6m
pod는 생성되었고 deployment 이름 뒤에 UUID를 붙여서 만들기 때문에 매 생성 시마다 달라진다.
1) NodePort를 이용한 배포작업 노출 및 서비스 생성
구조
actor client
cloud K8sCluster {
package Service {
package NodePort {
component NodePort_8080
component NodePort_3xxxx
}
}
node Node1 {
component Pod1
component Pod2
}
node Node2 {
component Pod3
component Pod4
}
}
client --> Service: 7080, 3xxxx
NodePort_8080 --> Pod1: 8080
NodePort_8080 --> Pod3: 8080
Service --> NodePort_8080: 7080
Service --> NodePort_3xxxx: 3xxxx
NodePort_3xxxx --> Pod2: 3xxxx
NodePort_3xxxx --> Pod4: 3xxxx
NodePort란 각 node(서버)가 가지는 포트를 의미하고, 이렇게 열린 포트는 내부 서비스로 포트 포워딩을 해줘야 한다.
배포
우선, 다음과 같이 deployment를 노출시킨다.
kubectl expose deployment hello-minikube --type=NodePort --port=8080
자동으로 service가 생성/배포되며 같은 이름으로 존재하게 된다. 이 서비스는 8080이라는 포트에 바인딩된다.
service 확인
deployment를 노출하면 service가 자동 생성된다. 같은 이름의 서비스가 생성되어 있음을 확인할 수 있다.
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
hello-minikube 1/1 1 1 4m39s
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-minikube NodePort 10.107.246.105 <none> 8080:30929/TCP 2m39s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20m
deployments는 이미 생성된 상태여서 변화가 없지만, service는 동일한 이름으로 생성된다.
이 서비스에 할당된 IP와 포트로는 여전히 접근이 불가능하다.
deployment와 service와 pod의 차이
- deployment는 container들의 그룹인 pod를 배포하는 규칙을 의미한다.
- service는 pod들을 집합적으로 개념화하여 동일한 이름으로 접근할 수 있는 endpoint 역할을 한다.
- 예를 들어, deployment로 MySQL DB와 이것을 사용하는 backend 서비스를 배포한다고 가정해보자. backend 서비스 입장에서 MySQL DB가 설치되어 있는 pod에 접속하려면 DB 호스트 이름을 알아야 하는데, pod 자체는 영구적인 객체가 아니므로 영구적이고 고정적인 이름을 가진 객체가 필요한데 바로 K8s의 service가 이런 역할을 해준다.
- 이런 이유로 service에 이름을 부여하면 그 이름은 서비스 서버(호스트)의 이름이 된다.
포트 포워딩
kubectl port-forward service/hello-minikube 7080:8080
이 명령은 background daemon으로 실행되지 않고 foreground로 실행된다.
이제부터 localhost:7080으로 접근 가능해진다.
위 구조도에서 NodePort1_7080에 대해 포트 포워딩을 켜준 것이다.
또는, minikube를 이용하여 포트 포워딩을 해줄 수 있다.
minikube service hello-minikube
이 경우에는 minikube가 임의의 포트를 부여해 준다.
|-----------|----------------|-------------|---------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|----------------|-------------|---------------------------|
| default | hello-minikube | 8080 | http://192.168.49.2:30079 |
|-----------|----------------|-------------|---------------------------|
🏃 hello-minikube 서비스의 터널을 시작하는 중
|-----------|----------------|-------------|------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|----------------|-------------|------------------------|
| default | hello-minikube | | http://127.0.0.1:65393 |
|-----------|----------------|-------------|------------------------|
🎉 Opening service default/hello-minikube in default browser...
❗ Because you are using a Docker driver on darwin, the terminal needs to be open to run it.
서비스 접근 확인하기
curl localhost:7080
curl -X POST -d 'msg=hello%20world' localhost:7080
외부에 노출하는 포트는 7080으로 잡고 내부에서 nodeport가 잡은 8080에 연결되도록 설정한다.
2) LoadBalancer를 이용한 배포작업 노출 및 서비스 생성
구조
actor client
cloud K8sCluster {
cloud LoadBalancer
node Service
package Node1 {
component NodePort1_3xxxx
package Pod1
package Pod2
}
package Node2 {
component NodePort2_3xxxx
package Pod3
package Pod4
}
}
client --> LoadBalancer: 8080
LoadBalancer --> Service: 8080
LoadBalancer --> Service: 8080
Service --> NodePort1_3xxxx: 3xxxx
Service --> NodePort2_3xxxx: 3xxxx
NodePort1_3xxxx --> Pod1
NodePort1_3xxxx --> Pod2
NodePort2_3xxxx --> Pod3
NodePort2_3xxxx --> Pod4
배포
kubectl expose deployment hello-minikube --type=LoadBalancer --port=8080
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-minikube LoadBalancer 10.102.223.116 <pending> 8080:30389/TCP 2m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 51m
EXTERNAL-IP가 아직 설정되지 않은 것을 확인할 수 있다.
터널링
minikube가 제공하는 ssh 터널링 기능을 이용하여 service에 대한 접근이 가능하다.
minikube tunnel
8080 포트를 클러스터의 8080 포트로 터널링해 준다.
내부적으로는 ingress를 실행하고 여기에 외부 IP를 할당하고 동일한 포트번호로 터널링한다. (외부에 IP를 노출시키는 효과)
kubectl get serivce -o yaml hello-minikube
status:
loadBalancer:
ingress:
- ip: 127.0.0.1
서비스 확인하기
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-minikube LoadBalancer 10.102.223.116 127.0.0.1 8080:30389/TCP 11m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 60m
EXTERNAL-IP가 설정된 것을 확인할 수 있다.
curl localhost:8080
기존에 생성되어 있던 서비스와 배포작업 삭제가 필요하다면?
혹시 기존 deployment를 제거해야 한다면 다음과 같이 실행하면 된다. 우선 노출된 deployment를 비노출처리하고 service를 삭제한다.
kubectl delete service hello-minikube
생성되어 있던 deployment까지 삭제하려면 다음 명령을 수행하면 된다.
kubectl delete deployment hello-minikube