skip to Main Content

Draft를 사용하여 Kubernetes에 애플리케이션 배포하기

Kubernetes에 사용자가 만든 컨테이너를 쉽게 배포해 주는 Helm Chart라는 툴이 있습니다. (Helm 참고 사이트 : https://helm.sh/)

Helm Chart는 사용자가 정의한 kubernetes 배포 스크립트를 Tiller 서버를 통해 쉽게 배포하는데 목적이 있습니다.

오늘은 Draft라는 툴을 사용하여 kubernetes에 배포하는 방법을 소개해 드리도록 하겠습니다. ( Draft 참고 사이트 : https://draft.sh/ )

Draft는 개발자가 개발한 소스를 감지하여 Docker파일과 Helm Chart를 자동으로 생성해 주는 기능을 제공함으로써 Kubernetes에서 실행되는 응용 프로그램을 보다 쉽게 ​​만들 수 있습니다.

현재 Draft는 8가지의 언어를 지원합니다. .Net, GO, NODEJS, PHP, JAVA (Maven, Gradle), PYTHON, RUBY

그럼 Draft 설치와 사용법에 대해 알아보겠습니다.

1. 설치

Draft를 사용하기 위해서는 사전에 아래와 같은 패키지가 설치되어 있어야 합니다. (단, Dockerfile과 Helm Chart 생성만 하고 kubenetes에 deploy를 하지 않는 경우에는 아래 패키지는 필요 없습니다.)

– kubectl CLI Tool (https://kubernetes.io/docs/tasks/tools/install-kubectl/)

– Helm (https://github.com/helm/helm/releases)

– Draft는 세 가지 플랫폼(Windows, OSX, Linux) 에서 사용 가능합니다. 설치 바이너리는 https://github.com/Azure/draft/releases에서 다운로드 가능합니다.

먼저 draft 를 다운로드 받습니다.

$ wget https://azuredraft.blob.core.windows.net/draft/draft-v0.16.0-linux-amd64.tar.gz
--2019-01-23 13:14:39--  https://azuredraft.blob.core.windows.net/draft/draft-v0.16.0-linux-amd64.tar.gz
Resolving azuredraft.blob.core.windows.net (azuredraft.blob.core.windows.net)... 40.71.240.16
Connecting to azuredraft.blob.core.windows.net (azuredraft.blob.core.windows.net)|40.71.240.16|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 14328890 (14M) [application/x-tar]
Saving to: ‘draft-v0.16.0-linux-amd64.tar.gz’

100%[======================================================================================>] 14,328,890   850KB/s   in 23s    

2019-01-23 13:15:03 (610 KB/s) - ‘draft-v0.16.0-linux-amd64.tar.gz’ saved [14328890/14328890]

다운로드 받은 후 압축을 해제한 후 draft 명령어를 수행해 보도록 하겠습니다.

$ cd linux-amd64/
$ ls
draft  LICENSE  README.md
$./draft 
The application deployment tool for Kubernetes.

Usage:
  draft [command]

Available Commands:
  config      manage Draft configuration
  connect     connect to your application locally
  create      transform the local directory to be deployable to Kubernetes
  delete      delete an application
  help        Help about any command
  history     Display the build history of a Draft application.
  home        print the location of DRAFT_HOME
  init        sets up local environment to work with Draft
  logs        This command outputs logs from the draft server to help debug builds.
  pack        manage Draft packs
  plugin      add Draft plugins
  up          build and push Docker image, then install the Helm chart, referencing the image just built
  version     print the client version information

Flags:
      --debug                     enable verbose output
  -h, --help                      help for draft
      --home string               location of your Draft config. Overrides $DRAFT_HOME (default "/root/.draft")
      --kube-context string       name of the kubeconfig context to use when talking to Tiller
      --tiller-namespace string   namespace where Tiller is running. This is used when Tiller was installed in a different namespace than kube-system. Overrides $TILLER_NAMESPACE (default "kube-system")

Use "draft [command] --help" for more information about a command.

$ ./draft  version
&version.Version{SemVer:"v0.16.0", GitCommit:"5433afea1421810ae9d828631d8651de913b347a", GitTreeState:"dirty"}

설치가 완료되었으면 “draft init” 명령어를 수행합니다.

$ draft init
Installing default plugins...
Downloading https://azuredraft.blob.core.windows.net/draft/pack-repo-v0.4.2-linux-amd64.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 3286k  100 3286k    0     0   373k      0  0:00:08  0:00:08 --:--:--  528k
Preparing to install into /root/.draft/plugins/draft-pack-repo
draft-pack-repo installed into /root/.draft/plugins/draft-pack-repo/draft-pack-repo
Installed plugin: pack-repo
Installation of default plugins complete
Installing default pack repositories...
Installing pack repo from https://github.com/Azure/draft
Installed pack repository github.com/Azure/draft
Installation of default pack repositories complete
$DRAFT_HOME has been configured at /root/.draft.

2. 사용법

이제 python으로 개발된 샘플소스를 한번 만들어 보겠습니다.

$ vi app.py
from flask import Flask
app = Flask(__name__)

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

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

그리고 requirements.txt파일을 만들도록 하겠습니다.

$ vi requirements.txt
Flask==0.12.0

이제 python 소스가 존재하는 곳에서 “draft create” 명령을 수행해 보도록 하겠습니다.

$ draft create
--> Draft detected Coq (63.068182%)
--> Could not find a pack for Coq. Trying to find the next likely language match...
--> Draft detected Python (28.409091%)
--> Ready to sail

이렇게 실행이 정상적으로 완료되면 Dockerfile와 Helm Chart가 생성된 것을 보실 수 있습니다.

$ ls -al
total 20
drwxr-xr-x 3 root root 138 Jan 23 13:35 .
drwxr-xr-x 4 root root  40 Jan 23 13:25 ..
drwxr-xr-x 3 root root  21 Jan 23 13:34 charts
-rw-r--r-- 1 root root 183 Jan 23 13:34 Dockerfile
-rw-r--r-- 1 root root  30 Jan 23 13:34 .dockerignore
-rw-r--r-- 1 root root  25 Jan 23 13:34 .draftignore
-rw-r--r-- 1 root root   0 Jan 23 13:34 .draft-tasks.toml
-rw-r--r-- 1 root root 215 Jan 23 13:34 draft.toml
-rw-r--r-- 1 root root 138 Jan 23 13:27 hello.py

이제 생성된 Docker 파일과 helm chart를 이용하여 Kubernetes에 배포를 해 보도록 하겠습니다. 먼저 draft up을 실행하기에 앞서 환경설정이 필요합니다.

*Docker build 후 Docker registry에 사용자 어플리케이션 Docker가 Push됩니다. 이때 push되는 Docker registry 정보를 먼저 세팅해 놓아야 합니다.

$ draft config set registry [docker registry 주소]

세팅이 준비완료되면 “draft up” 명령어로 배포를 시작해보겠습니다.

$ draft up
Draft Up Started: 'sample1': 01D1WRFY7YEKADWAYP2EHD90D3
sample1: Building Docker Image: SUCCESS âš“  (92.0203s)
sample1: Pushing Docker Image: SUCCESS âš“  (35.6183s)
sample1: Releasing Application: SUCCESS âš“  (2.5325s)
Inspect the logs with `draft logs 01D1WRFY7YEKADWAYP2EHD90D3`

 실행된 로그를 보려면 “draft logs [실행ID]”로 조회 할 수 있습니다.

$ draft logs 01D1WRFY7YEKADWAYP2EHD90D3
Step 1/9 : FROM python
latest: Pulling from library/python
cd8eada9c7bb: Pulling fs layer
c2677faec825: Pulling fs layer
fcce419a96b1: Pulling fs layer
045b51e26e75: Pulling fs layer
3b969ad6f147: Pulling fs layer
2d18bcd81c37: Pulling fs layer
8719ec5c24c9: Pulling fs layer
6b29038f9369: Pulling fs layer
239fef4b4f5c: Pulling fs layer
8719ec5c24c9: Waiting
6b29038f9369: Waiting
045b51e26e75: Waiting
3b969ad6f147: Waiting
2d18bcd81c37: Waiting
239fef4b4f5c: Waiting
fcce419a96b1: Verifying Checksum
fcce419a96b1: Download complete
c2677faec825: Verifying Checksum
c2677faec825: Download complete
cd8eada9c7bb: Verifying Checksum
cd8eada9c7bb: Download complete
2d18bcd81c37: Verifying Checksum
2d18bcd81c37: Download complete
cd8eada9c7bb: Pull complete
c2677faec825: Pull complete
fcce419a96b1: Pull complete
8719ec5c24c9: Verifying Checksum
8719ec5c24c9: Download complete
6b29038f9369: Download complete
239fef4b4f5c: Verifying Checksum
239fef4b4f5c: Download complete
045b51e26e75: Verifying Checksum
045b51e26e75: Download complete
045b51e26e75: Pull complete
3b969ad6f147: Verifying Checksum
3b969ad6f147: Download complete
3b969ad6f147: Pull complete
2d18bcd81c37: Pull complete
8719ec5c24c9: Pull complete
6b29038f9369: Pull complete
239fef4b4f5c: Pull complete
Digest: sha256:47fd3cafa3d01a4358e304bcb2a851076b32c5470d7199b98d4e6ab694ba4052
Status: Downloaded newer image for python:latest
 ---> 7c5fd2af3815
Step 2/9 : ENV PORT 8080
 ---> Running in 5973a5206066
 ---> 072f542f3864
Step 3/9 : EXPOSE 8080
 ---> Running in 182751d4a836
 ---> 62c0c98afe7c
Step 4/9 : WORKDIR /usr/src/app
 ---> 15c1a8c9308f
Step 5/9 : COPY requirements.txt ./
 ---> 54f17b807600
Step 6/9 : RUN pip install --no-cache-dir -r requirements.txt
 ---> Running in 8742ae992a95
Collecting Flask==0.12.0 (from -r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/0e/e9/37ee66dde483dceefe45bb5e92b387f990d4f097df40c400cf816dcebaa4/Flask-0.12-py2.py3-none-any.whl (82kB)
Collecting Jinja2==2.8.1 (from -r requirements.txt (line 2))
  Downloading https://files.pythonhosted.org/packages/67/ea/92b1d9d8f2dc43302df7f5271b9500bbfc237386782343561a5f62beb306/Jinja2-2.8.1-py2.py3-none-any.whl (264kB)
Collecting gunicorn==19.6.0 (from -r requirements.txt (line 3))
  Downloading https://files.pythonhosted.org/packages/72/de/ec28a64885e0b390063379cca601b60b1f9e51367e0c76030ac8a5cddd5e/gunicorn-19.6.0-py2.py3-none-any.whl (114kB)
Collecting itsdangerous>=0.21 (from Flask==0.12.0->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Collecting Werkzeug>=0.7 (from Flask==0.12.0->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
Collecting click>=2.0 (from Flask==0.12.0->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
Collecting MarkupSafe (from Jinja2==2.8.1->-r requirements.txt (line 2))
  Downloading https://files.pythonhosted.org/packages/e4/c4/adcc2d6f2ac2146cc04e076f14f1006c1de8e1e747fa067668b6573000b8/MarkupSafe-1.1.0-cp37-cp37m-manylinux1_x86_64.whl
Installing collected packages: MarkupSafe, Jinja2, itsdangerous, Werkzeug, click, Flask, gunicorn
Successfully installed Flask-0.12 Jinja2-2.8.1 MarkupSafe-1.1.0 Werkzeug-0.14.1 click-7.0 gunicorn-19.6.0 itsdangerous-1.1.0
You are using pip version 18.1, however version 19.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
 ---> 3fe3fcdd9a6d
Step 7/9 : COPY . .
 ---> 1709d32fb60f
Step 8/9 : ENTRYPOINT python
 ---> Running in cedf96e582fd
 ---> ccfc494d6ec3
Step 9/9 : CMD app.py
 ---> Running in 099e08b46d86
 ---> a5611505f600
Successfully built a5611505f600
The push refers to a repository [127.0.0.1:30001/sample1]
b5f9fbf4f363: Preparing
912f83b1ec05: Preparing
1db3cffe1397: Preparing
6cb7b0fab3e8: Preparing
45b4a7ebd721: Preparing
bf37704a7eab: Preparing
a70b9475716b: Preparing
889326ab9a3b: Preparing
1a36262221c3: Preparing
bf37704a7eab: Waiting
d2217ead3a1c: Preparing
b53b57a50746: Preparing
d2518892581f: Preparing
c581f4ede92d: Preparing
889326ab9a3b: Waiting
1a36262221c3: Waiting
a70b9475716b: Waiting
d2217ead3a1c: Waiting
d2518892581f: Waiting
c581f4ede92d: Waiting
b53b57a50746: Waiting
b5f9fbf4f363: Pushed
1db3cffe1397: Pushed
6cb7b0fab3e8: Pushed
bf37704a7eab: Pushed
45b4a7ebd721: Pushed
912f83b1ec05: Pushed
b53b57a50746: Mounted from scouter-server
d2518892581f: Mounted from scouter-server
c581f4ede92d: Mounted from scouter-server
889326ab9a3b: Pushed
a70b9475716b: Pushed
d2217ead3a1c: Pushed
1a36262221c3: Pushed
2637e3e68b34810548c0b1588f22e0c7728ba898: digest: sha256:797f9cf64c66e54ee58e88dc4fce3f73b6913ded64731ddd1bc5725b30062194 size: 3050

배포가 정상적으로 완료되었는지 kubectl로 조회해 보겠습니다.

$ kubectl get po,svc
NAME                                   READY     STATUS    RESTARTS   AGE
pod/sample1-sample1-6f85496dc7-72mrz   1/1       Running   0          1m

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP   13d
service/sample1-sample1   ClusterIP   10.102.35.221   <none>        80/TCP    7m

노드 포트로 변경 후 서비스를 호출해 보도록 하겠습니다.

$ kubectl patch svc sample1-sample1 --type='json' -p '[{"op":"replace","path":"/spec/type","value":"NodePort"}]'
service/sample1-sample1 patched
[root@acc-master sample1]# kubectl get po,svc
NAME                                   READY     STATUS        RESTARTS   AGE
pod/sample1-sample1-6b476469-c872r     1/1       Running       0          35s
pod/sample1-sample1-6f85496dc7-72mrz   0/1       Terminating   0          14m

NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP          13d
service/sample1-sample1   NodePort    10.102.35.221   <none>        5000:30855/TCP   20m

여기까지 개발자가 개발한 소스를 draft를 이용하여 docker 컨테이너로 생성하고 Kubernetes로 배포하는 절차를 안내드렸습니다. 참고로, 다른언어로 개발된 draft 사용 예제는 https://github.com/Azure/draft/tree/master/examples 를 참고하시기 바랍니다.

Back To Top