kubernetes 로 flask web app 배포하기

kubernetes?

고대 그리스어로 조타수? 키잡이? 라는 의미라고 한다.
구글에서 개발한 container orchestration tool(vm 또는 container 관리를 자동화해주는 도구)이다.

 

why kubernetes?

사실 이 부분은 충분한 경험이 없어서 자신있게 말을 못하겠다.
온라인에서 이것 저것 찾아보면 몇 가지 후보군이 더 있다.

  • swarm
  • mesos / marathon
  • 기타(kotena, nomad …)

이 중에서 kubernetes 를 선택한 이유는
기본적으로 제공하는 기능과 설계구조가 전반적으로 낫다는 평(카더라)
업계의 선택 – 실무 활용 사례가 많다는 점

때문이다. 다른 오케스트레이션 툴 중에 더 나은 것이 있다면 얼마든지 변경할 수 있다.

 

설치

는 생략… 공식 홈페이지에 tutorial 이 잘 나와 있다.

클러스터링 전략을 어떻게 가져가느냐에 따라 다양한 방법으로 설치가 가능하므로
문서를 잘 읽어보고 본인의 환경에 맞게 설치하길 바란다.

처음 시작하는 사람들은 로컬 개발환경에 docker / minikube / kubectl 설치하면 된다.
https://kubernetes.io/docs/getting-started-guides/minikube/

 

flask app 만들기

아래와 같이 간단하게 동작하는 flask app을 만들자.

중요!
host 설정을 0.0.0.0 으로 하여야 가상 컨테이너 외부에서 별도 proxy 없이 접근 가능하다.

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello!!"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

특별한 설정 없이 실행하는 것 만으로 웹 서비스를 제공한다.

$ python3 hello.py
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [11/Apr/2017 08:40:53] "GET / HTTP/1.1" 200 -

이 flask app 을 docker image 로 만들어 보자.

docker image / container 만들기

다음과 같이 Dockerfile 을 만들자.
기존에 제공된 python image 기반으로 조금 전에 만든 flask app 을 복사/실행하도록 하자.

FROM python:3.6
EXPOSE 5000
COPY hello.py .
RUN pip install flask
CMD ["python",  "./hello.py"]

만든 Dockerfile로부터 docker image 를 만들자.

$ docker build -t hello-flask:v1 .

이 docker image 가 잘 동작하는지 확인해 보자.

docker run -it --rm -p 5000:5000 hello-flask:v1
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.0.1 - - [10/Apr/2017 23:54:50] "GET / HTTP/1.1" 200 -

 

 

kubernetes 로 docker container(pod 또는 deployment) 만들기

다음 2가지를 주의한다.
kubernetes 는 Dockerfile 로부터 container를 생성하는 기능은 제공하지 않는다. docker image를 미리 만들어 두어야 한다.
kubernetes 하위에서 실행되는 docker 환경은 시스템에 설치된 docker 환경과는 완전히 독립적이다. docker image / container 를 공유하지 않으므로 image를 다시 만들어야 한다.

$ eval $(minikube docker-env) //kubernetes docker 실행환경 전환
$ eval $(minikube docker-env -u) //kubernetes docker 실행환경 원복

kubernetes docker 실행환경으로 전환하여 docker image 를 만든 후, kubectl을 이용하여 다음과 같이 deployment(pod) 를 생성한다.

$ kubectl run hello-flask --image=hello-flask:v1 --port=5000
deployment "hello-flask" created

kubectl 을 이용해 deployment / pod 정보를 보면 아래와 같다.

$ kubectl get deployments
NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-flask      1         1         1            1           24s

$ kubectl get pods
NAME                              READY     STATUS    RESTARTS   AGE
hello-flask-2475082718-xw1s3      1/1       Running   0          3m

 

 

pod vs deployment ?

kubernetes 는 container / container group 의 단위로 pod 를 사용한다.
반면 deployment 는 pod 의 상태를 체크하여 pod 생성/재시작/scaling 을 담당한다.
pod 가 Object 라면 deployment 는 Factory 나 Builder 와 같은 관계랄까.

위와 같은 이유로 보통 kubectl 로 container 를 생성/삭제할 때에는 deployment 로 호칭하므로 참고하기 바란다.

 

deployment 로 service 만들기

deployment 만 생성하여서는 아직 서비스를 할 수가 없다.
다음과 같이 kubectl 명령을 사용하여 deployment 를 service 로 실행한다.

kubectl expose deployment hello-flask --type=LoadBalancer --name=hello-flask

kubectl 을 이용해 service 정보를 확인해 보자

$ kubectl get service hello-flask
NAME          CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
hello-flask   10.0.0.245   <pending>     5000:30276/TCP   <invalid>

$ kubectl describe service hello-flask
Name:                   hello-flask
Namespace:              default
Labels:                 run=hello-flask
Selector:               run=hello-flask
Type:                   LoadBalancer
IP:                     10.0.0.245
Port:                   <unset> 5000/TCP
NodePort:               <unset> 30276/TCP
Endpoints:              172.17.0.2:5000
Session Affinity:       None
No events.

다음 minikube 명령을 이용하면 flask app 이 어느 external ip 와 mapping 되어 있는지 브라우저로 확인할 수 있다. 현재 별도로 kubernetes 에게 external ip/port 할당 관련한 설정을 하지 않았으므로 아무렇게나 할 것이다.

$ minikube service hello-flask
Opening kubernetes service default/hello-flask in default browser...

다음과 같이 stdout log 도 확인 가능하다.

$ kubectl logs -f hello-flask-2475082718-xw1s3
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.0.1 - - [11/Apr/2017 00:36:00] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Apr/2017 00:36:00] "GET /favicon.ico HTTP/1.1" 404 -
172.17.0.1 - - [11/Apr/2017 00:38:15] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Apr/2017 00:40:47] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Apr/2017 00:42:22] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Apr/2017 00:47:26] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Apr/2017 00:47:27] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Apr/2017 00:47:27] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Apr/2017 00:47:27] "GET / HTTP/1.1" 200 -

중요!
container 기반 app 을 작성할 때에는 log를 반드시 stdout 으로 남기도록 한다.
그래야 log 를 container 와 별도로 수집 가능하다.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

w

%s에 연결하는 중