k8s 클러스터에 애플리케이션 서버 실행하기

최초작성일 [2020.01.26]

쿠버네티스 클러스터에서 가동되고 있는 노드(node)를 확인한다.

마스터 노드 1개가 작동중임을 알 수 있다.

$ kubectl get nodes
NAME       STATUS   ROLES    AGE    VERSION
minikube   Ready    master   7d5h   v1.17.0

1. 노드에 컨테이너 생성하기

도커이미지로 만들어진 애플리케이션을 노드에 배포하는 명령어는 아래와 같다.

$ kubectl create deployment <pod이름> --image=<이미지이름>

dockerhub에 올라가있는 이미지를 이용하여 컨테이너를 노드에 생성해보자.

$ kubectl create deployment my-housing-prices --image=kde6260/housing-prices:0.0.1
deployment.apps/my-housing-prices created

생성된 애플리케이션을 확인하려면 $ kubectl get deployments 를 실행한다.

➜  ~ kubectl get deployments
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
my-housing-prices          0/1     1            0           4m29s

쿠버네티스에서는 컨테이너를 pod라는 단위로 관리하므로 $ kubectl get pods 를 통해 생성된 pod를 조회해보자. pod의 이름은 my-housing-prices-65db4dc56b-jxcnr 이고 STATUS 필드를 통해 아직 컨테이너를 생성하고 있음을 알 수 있다.

$ kubectl get pods
NAME                                     READY   STATUS             RESTARTS   AGE
my-housing-prices-65db4dc56b-jxcnr       0/1     ContainerCreating   0          68s

pod 이름이 너무 길기 때문에 POD_NAME 이라는 환경변수에 이름을 저장해서 쓰기로 한다.

$ export POD_NAME=my-housing-prices-65db4dc56b-jxcnr

2. 생성된 pod 정보 확인하기

pod에 할당된 IP주소, DNS 이름, 컨테이너 등의 자세한 정보를 확인하려면 $ kubectl describe pod <pod이름> 을 실행한다.

➜  ~ kubectl describe pod $POD_NAME
Name:               my-housing-prices-65db4dc56b-jxcnr
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               minikube/192.168.64.2
Start Time:         Sun, 26 Jan 2020 20:29:00 +0900
Labels:             app=my-housing-prices
                    pod-template-hash=65db4dc56b
Annotations:        <none>
Status:             Running
IP:                 172.17.0.4
Controlled By:      ReplicaSet/my-housing-prices-65db4dc56b
Containers:
  housing-prices:
    Container ID:   docker://8d850e074cc9c80a74a84768f2ae49ed79e10d886b56c78b0912ab67b1a9287a
    Image:          kde6260/housing-prices:0.0.1
    Image ID:       docker-pullable://kde6260/housing-prices@sha256:abb95f9a835e5e09cfa8832b9d751a24cb1d604930e1f7c6de98d1f8495a7e1b
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Sun, 26 Jan 2020 20:37:44 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-l9tww (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-l9tww:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-l9tww
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  9m24s                  default-scheduler  Successfully assigned default/my-housing-prices-65db4dc56b-jxcnr to minikube
  Warning  Failed     4m48s                  kubelet, minikube  Failed to pull image "kde6260/housing-prices:0.0.1": rpc error: code = Unknown desc = context canceled
  Warning  Failed     4m48s                  kubelet, minikube  Error: ErrImagePull
  Normal   BackOff    4m47s                  kubelet, minikube  Back-off pulling image "kde6260/housing-prices:0.0.1"
  Warning  Failed     4m47s                  kubelet, minikube  Error: ImagePullBackOff
  Normal   Pulling    4m35s (x2 over 9m23s)  kubelet, minikube  Pulling image "kde6260/housing-prices:0.0.1"
  Normal   Pulled     40s                    kubelet, minikube  Successfully pulled image "kde6260/housing-prices:0.0.1"
  Normal   Created    40s                    kubelet, minikube  Created container housing-prices
  Normal   Started    40s                    kubelet, minikube  Started container housing-prices

생성된 pod의 IP주소는 172.17.0.4이고 Containers 항목을 통해 pod 안에 생성된 컨테이너의 상세정보를 알 수 있다. Events 항목에서는 pod의 생성 과정을 볼 수 있다.

3. 노드에 배포된 애플리케이션과 통신하기

클러스터 내 노드에 배포된 애플리케이션과 통신하기 위해서는 프록시 서버가 있어야 한다. 프록시 서버를 실행하는 명령어는 기본적으로 아래와 같다.

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

$ kubectl proxy creates a proxy server or application-level gateway between localhost and the Kubernetes API Server. It also allows serving static content over specified HTTP path. All incoming data enters through one port and gets forwarded to the remote kubernetes API Server port, except for the path matching the static content path.

마스터노드에 생성된 flask 애플리케이션은 루트 URL로 요청이 왔을 때 아래와 같이 응답을 보낸다.

@app.route("/")
def home():
    html = f"<h3>Sklearn Prediction Home</h3>"
    return html.format(format)

프록시 서버에 요청을 보냈을 때 배포된 flask 애플리케이션으로부터 응답이 제대로 오는지 확인해보자.

쿠버네티스 클러스터에서 namespace는 물리적인 클러스터 위에 여러 개의 논리적인 클러스터를 식별하는 용도로 쓰인다. 현재 클러스터에서 namespacedefault 1개만 존재한다. default로 식별되는 가상 클러스터 안에 있는 pod들 중에 $POD_NAME에 배포된 애플리케이션의 API에 접근하는 URL은 아래와 같다.

http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/

curl로 요청을 보내면 flask 애플리케이션에 작성한 응답이 돌아오는 것을 확인할 수 있다.

$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
<h3>Sklearn Prediction Home</h3>%

4. 애플리케이션 로그 확인하기

컨테이너로 실행중인 애플리케이션 서버의 로그를 조회하려면 아래 명령어를 실행한다.

$ kubectl log <pod이름>
$ kubectl log $POD_NAME
log is DEPRECATED and will be removed in a future version. Use logs instead.
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/__init__.py:15: FutureWarning: sklearn.externals.joblib is deprecated in 0.21 and will be removed in 0.23. Please import this functionality directly from joblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.
  warnings.warn(msg, category=FutureWarning)
/usr/local/lib/python3.7/site-packages/sklearn/utils/deprecation.py:144: FutureWarning: The sklearn.ensemble.gradient_boosting module is  deprecated in version 0.22 and will be removed in version 0.24. The corresponding classes / functions should instead be imported from sklearn.ensemble. Anything that cannot be imported from sklearn.ensemble is now part of the private API.
...

flask 애플리케이션의 로그가 출력되는 것을 확인할 수 있다.

5. 호스트에 pod 포워딩하기

pod에서 동작하는 애플리케이션 서버에 접속하기 위해서는 프록시 대신에 포트포워딩을 사용할 수도 있다.

$ kubectl port-forward $POD_NAME <호스트포트번호>:<애플리케이션 서버 포트번호>

Dockerfile을 참고하면 flask 애플리케이션은 포트번호 80에서 동작한다.

EXPOSE 80

로컬호스트에서 포트번호 8888으로 pod에서 실행중인 flask 애플리케이션 서버에 접속하려면 아래와 같이 포트포워딩을 해주면 된다.

$ kubectl port-forward $POD_NAME 8888:80

출처

Last updated