๐ณ ํ๋ ๊ฐ๋ฐ์๋ฅผ ๋ํํ๋ Kubernetes๐ณ
์ ๊ฒฐ ์กฐ๊ฑด
microk8s.enable registry
์ ์ฌ์ฉํ์ฌ Microk8sdocker ๋ฑ๋กํ ํ์ฑํpip
์ฐธ๊ณ : ์ด ๊ฐ์ข์ ๋ชจ๋ ์ฝ๋๋ ์ค์ ์ "์์ฐ ์ค๋น"๊ฐ ์๋๋๋ค.
์ด์ ์
docker
๋๋ kubectl
์ด ์์ผ๋ฉด microk8s.
์ ์ ๋์ฌ๋ก ์ฌ์ฉํ์ง ์๋๋ก ๋ช
๋ น ๋ณ์นญ์ ์ง์ ํฉ๋๋ค.sudo snap alias microk8s.docker docker
sudo snap alias microk8s.kubectl kubectl
์ฟ ๋ฒ ๋ฅด๋ํ
์ค๋ ๋ฌด์์
๋๊น?
Kubernetes๋ ์๋ํ ์ฉ๊ธฐ์ ์ฉ๊ธฐํ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ฐฐ์น, ์ค์ , ํ์ฅ์ ์ฌ์ฉ๋๋ ํ๋ํ๋ ํ๋ซํผ์
๋๋ค.๊ธฐ๋ณธ์ ์ผ๋ก Docker ํ๋ซํผ์ ๊ตฌ์ถ๋์ด ๊ฐ๋ฐ์์ ์์คํ
๊ด๋ฆฌ์์๊ฒ ์ ์ฐํ๊ณ ๊ฐ๋ ฅํ ๋๊ตฌ๋ฅผ ์ ๊ณตํ์ฌ ์ด๋ ํ ๊ท๋ชจ์์๋ ๊ทธ๋ค์ ์๋น์ค๋ฅผ ๊ด๋ฆฌํ ์ ์๋ค.์ํฌ์คํ
์ด์
๊ท๋ชจ ํฌํจ๐
์ฒซ ๋ฒ์งธ ์ผ!
๋ชจ๋ ๊ตฌ์ฑ ๋ฐ ์ฝ๋๋ GitHub ํ๋ก์ ํธ์์ ํ์ธํ ์ ์์ต๋๋ค.
์ฒดํ๋
ธ
/
์ฟ ๋ฒ ํธ
kubernetes ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ํ๋ ๊ฐ๋จํ ํ๋ก์ ํธ
์ฟ ๋ฒ ํธ
kubernetes ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ํ๋ ๊ฐ๋จํ ํ๋ก์ ํธ
View on GitHub
์
๋ฌธ๐๐จ
์, ์์ํ ์ค๋น ๋์ด์?์ปจํ
์ด๋์์ ์คํ๋๋ ์์ฉ ํ๋ก๊ทธ๋จ์ด ํ์ํ๋ฏ๋ก Python์ Flask ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ์ํฉ๋๋ค.
# test_server.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def kube():
return "Hello Kubernetes!"
์ด๊ฒ์ ๋จ์ผ ๊ฒฝ๋ก /
์ ํ๋ผ์คํฌ ์์ฉ์ ์ ์ํ๋ค.์ฌ๊ธฐ ๋ฌด์์ด ๊ฑฐ ์์ด!๐พ
์ดํ๋ฆฌ์ผ์ด์
์ ํ
์คํธํ๋ ค๋ฉด Flask ์ข
์์ฑ์ ์ค์นํฉ๋๋ค.
pip install flask
... ์ฌ์ฉ:
FLASK_APP=test_server.py flask run
๊ทธ๋ฆฌ๊ณ http://127.0.0.1:5000/ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด์ด ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ญ์์ค.
๋ฉ์ถ๋์.๐ฆ
๋ค์์ ์๋ก์ด ์น ์๋น์ค์ Dockerfile
์ ์ ์ํด์ผ ํฉ๋๋ค.๋๋ Dockerfiles์ ๋ํด ์ด๋ ์ ๋ ์ต์ํ๋ค๊ณ ๊ฐ์ ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด ์ ์ ์์ธํ๊ฒ ์๊ฐํ์ง ์์ ๊ฒ์ด๋ค.
FROM python:3.6.7-alpine3.7
RUN mkdir /app
WORKDIR /app
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY ./test_server.py /app/test_server.py
ENV FLASK_APP=test_server.py
ENV FLASK_ENV=development
ENTRYPOINT [ "flask", "run", "--host=0.0.0.0" ]
ํ์ฌ ์ฐ๋ฆฌ๋ ์ฝ๋๋ก ์ด๋ฏธ์ง๋ฅผ ๊ตฌ์ถํ๊ณ ํ์ํ๋ฉฐ ๋ฑ๋กํ๋ก ์ ์กํด์ผ ํ๋ค.์ด ์คํ์ ์ํํ๋ ค๋ฉด:
docker build -t localhost:32000/kubetest:v1.0.0 .
docker push localhost:32000/kubetest:v1.0.0
์ฃผ์: ์ฌ์ฉํ ์ฟ ๋ฒ ๋ฅด๋ค์ธ ๋ฒ์ ์ ๋ฐ๋ผ ์ด๋ฏธ์ง ์ด๋ฆ์ด ๋ค๋ฅผ ์ ์์ต๋๋ค. ๋ก์ปฌ ๋ฑ๋กํ์ ํธ์คํธ ์ด๋ฆ์ผ๋ก localhost:32000
์ ๋ฐ๊พธ์ญ์์ค.
์ด ์ด๋ฏธ์ง๋ฅผ ํ ๋ฒ๋ง ๊ตฌ์ถํ๋ฉด ๋ฉ๋๋ค. (์ ์์กด ํญ๋ชฉ์ ์ถ๊ฐํ์ง ์์ผ๋ฉด) ๋์ค์ ์์ ๋ ์ฝ๋๋ฅผ ์ด๋ฏธ์ง์ ์ฃผ์
ํ ๊ฒ์
๋๋ค.
์ฌ๋ฏธ์๋ ์ผ์ ๊ดํด์...๐
ํ์ฌ ์ฐ๋ฆฌ๋ Docker ๋ฏธ๋ฌ๊ฐ ํ๋ ์๋๋ฐ, ๊ทธ ์์๋ ์ฐ๋ฆฌ์ ์ต์ ๋ฒ์ ์ ์ฝ๋๊ฐ ์์ผ๋ฉฐ, ์ฐ๋ฆฌ์ ๋น๋๋ ์ ๊ทธ๋ฃน์์ ์คํํ ์ ์๋ค.๋ณดํต ์ง๊ธ, ๋น์ ์ docker run
์ ๊ฐ๋ํ๊ณ ํ๋ฃจ๋ฅผ ๋๋ผ ์ ์์ง๋ง, ์ฐ๋ฆฌ๋ ๋ ์ํ ๊ฒ์ด๋ค.
์ฐ๋ฆฌ๋ ๋ ๊ฐ์ง ์ ํ์ ์์์ ์ ์ํด์ ์ฐ๋ฆฌ์ ์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์ง๋จ์์ ์คํํด์ผ ํ๋ค. ํ๋๋ Deployment
์ด๊ณ , ๋ค๋ฅธ ํ๋๋ Service
์ด๋ค.๋ง์ฝ ์ด์ ์ docker-compose
์ ์ฌ์ฉํ ์ ์ด ์๋ค๋ฉด, ์ด๊ฒ์ ๊ฐ๋
์ ์ผ๋ก ๋งค์ฐ ๋น์ทํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ์ต์ํด ๋ณด์ผ ๊ฒ์ด๋ค.Deployment
์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์
๋๋ค.
# kubetest.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
...
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ๋ฐฉ๊ธ ์ ์กํ docker ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ์ฌ kubetest
์ด๋ผ๋ ๊ธฐ๋ณธ ์๋น์ค๋ฅผ ์ ์ํ์ต๋๋ค.์ค์ํ ๋นํธ๋ spec
๊ตฌ์กฐ์์ kubetest
์ด๋ผ๋ ์ฉ๊ธฐ ํญ๋ชฉ์ ์ ์ํ์ต๋๋ค. ์ด ํญ๋ชฉ์ ์ด๋ฏธ์ง localhost:32000/kubetest:v1.0.0
์ ์ฌ์ฉํ๊ณ ํฌํธ 5000
์ ๋
ธ์ถํฉ๋๋ค.๋ณด์ด๋คdockercompose์ service
์ฒ๋ผ.๐ ํ์ฌ kubectl create -f kubetest.yaml
์ผ๋กpod๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. HTTP๋ฅผ ํตํดpod์ ์ ๊ทผํ ์ ์์ง๋ง ๋น๋ถ๊ฐ ๊ทธ๋ฌ์ง ๋ง์ญ์์ค.
Pod์ด Kubernetes ๋คํธ์ํฌ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋๋ก Service
์ ์ ์ํด์ผ ํฉ๋๋ค.์ด๊ฒ์ -p
์ docker run
์ต์
๋๋ ports
์ docker-compose.yaml
๋ถ๋ถ๊ณผ ์ ์ฌํฉ๋๋ค.
# kubetest.yaml
...
---
kind: Service
apiVersion: v1
metadata:
name: kubetest
labels:
app: kubetest
spec:
selector:
app: kubetest
ports:
- name: http
port: 5000
protocol: TCP
type: NodePort
์ฃผ์: ๊ฐ๋จํ๊ฒ ๋ณด๊ธฐ ์ํด์, ๋๋ ๊ฐ์ ํ์ผ์ Deployment
๊ณผ Service
์ ์ ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์, ์ด์ ์ฐ๋ฆฌ ์ง๋จ์์ ๊ณ์ ์ค์ ํ์!
noah@kamijou:/opt/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest created
service/kubetest created
๋ค์ ๊ณต์์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ pod
์ ๋ณผ ์ ์์ต๋๋ค.
noah@kamijou:/opt/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-574958d5fd-zpvn5 1/1 Running 0 15s
... ์๋น์ค ์ฌ์ฉ:
noah@kamijou:/opt/kubetest$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 8d
kubetest NodePort 10.152.183.154 <none> 5000:31065/TCP 20s
noah@kamijou:/opt/kubetest$
์๋น์ค ๋ชฉ๋ก์ 5000:31065/TCP
๋ถ๋ถ์ ์ฃผ์ํ์ญ์์ค. 31065
์ ์น ์๋น์ค์ ์ฐ๊ฒฐํ๋ ํฌํธ์
๋๋ค.์ด์ ์ด๋ ๊ฒ ํฉ์๋ค.
noah@kamijou:/opt/kubetest$ curl -i localhost:31065
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 18
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 05:53:10 GMT
Hello Kubernetes!
๊ฒฝํํ์ด๐๐๐
... but wait, I was promised cookies being able to edit my code within the pod! ๐ฃ How am I supposed to do that!?
์ง์ ํด, ๊ทธ๋ด ๊ฑฐ์ผ!๐
kubetest.yaml
ํ์ผ๋ก ๋์๊ฐ์ ๋ช ์ค์ ์ถ๊ฐํฉ์๋ค.
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
+ volumeMounts:
+ - mountPath: /app
+ name: kubetest-volume
+ readOnly: true
+ volumes:
+ - name: kubetest-volume
+ hostPath:
+ path: /home/noah/kubetest
+ type: Directory
์ฌ๊ธฐ์๋ ํจํค์ง๋ฅผ ํด์ ํด์ผ ํ ์ ์ด ํ๋ ์์ง๋ง, ๋๋ ํฐ๋ฆฌ ๊ธฐ๋ฐ ํด๋ ๋ง์ดํธ๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. -v /host/path:/container/path
์ docker run
๋ฌธ๋ฒ๊ณผ ์ ์ฌํฉ๋๋ค.Kubernetes์ ์ฒ๋ฆฌ ๋ฐฉ์์ vanilla docker์ ์ฝ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์๊ณ ์ถ์ผ๋ฉด official documentation on persistent volumes์ ๋ณด์ญ์์ค.
์ฐธ๊ณ : path
๋ฐ์ดํธ์ ๊ฐ์ ๋ณ๊ฒฝํ์ฌ test_server.py
ํ์ผ์ด ์๋ ์์น๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํฉ๋๋ค.์ด๊ฒ์ ์ด ์
๋ฌด์ ์ ์์ ์ธ ์งํ์ ๋งค์ฐ ์ค์ํ๋ค.
๊ณ์ํ์ฌ kubectl apply -f kubetest.yaml
์ ๋ค์ ์คํํ๊ณ ๋ณผ๋ฅจ์ผ๋ก ์
๋ฐ์ดํธ ์ฉ๊ธฐ๋ฅผ ๋ง์ดํธํฉ๋๋ค.
noah@kamijou:~/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest configured
service/kubetest unchanged
๊ธฐ์ค๊ธฐ๊ฐ ์ด๋ฏธ ๊ฐ๋๋๊ณ ๋ค์ ์ดํ๋์๋์ง ๊ฒ์ฌํ๋ค
noah@kamijou:~/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-58f7b7d957-cvdch 1/1 Running 0 63s
์ด ๋ก๊ทธ๋ค์ ๋ชจ๋ pod์ STDOUT
๊ณผ STDERR
์์ ์ถ์ถ๋ ๊ฒ์
๋๋ค.์ ํฌ๋ kubetest
์๋น์ค์๋ง ๊ด์ฌ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
๋ฉ์ง๋ค, ์์ฉ ํ๋ก๊ทธ๋จ์ด ์ฌ์ ํ ์คํ๋๊ณ ์๋ค.
๋ง์ง๋ง์ผ๋ก test_server.py
์ ์๋ก์ด ๋จ์ ์ ์ถ๊ฐํฉ์๋ค
from flask import Flask
app = Flask(__name__)
@app.route("/")
def kube():
return "Hello Kubernetes!\n"
[email protected]("/healthz")
+def health():
+ return "ok\n", 200
... ๋ก๊ทธ๋ฅผ ๋ค์ ๊ฒ์ฌํฉ๋๋ค.
noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
* Detected change in '/app/test_server.py', reloading
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
Flask ์์ test_ ์๋ฒ๊ฐ ๋ณ๊ฒฝ๋์์ต๋๋ค.py ํ์ผ์ ์๋์ผ๋ก ๋ค์ ๋ถ๋ฌ์ต๋๋ค!
ํฌํธ๊ฐ kubectl get svc
์์ ๋ณ๊ฒฝ๋์ง ์์๋์ง ํ์ธํ๊ธฐ ์ํด ์ ๋
ธ๋์ ์ ๊ทผํด ๋ณด๊ฒ ์ต๋๋ค.
noah@kamijou:~/kubetest$ curl -i localhost:30788/healthz
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 06:25:33 GMT
ok
์ค, ์ฐ๋ฆฌ ๋๋ฌ์ด!
์ฝ์ด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
๋๋ ๋ค๊ฐ ๋์ ๋๊ธ์ด ๋์๊ฒ ๋์์ด ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ๊ธธ ๋ฐ๋๋ค.๋ง์ฝ ๋น์ ์๊ฒ ์ด๋ค ๋ฌธ์ ๊ฐ ์๋ค๋ฉด, ๋๊ธ์ ๋ฉ์์ง๋ฅผ ๋จ๊ฒจ ์ฃผ์ญ์์ค. ๋๋ ๊ธฐ๊บผ์ด ๋น์ ์ ๋์ธ ๊ฒ์
๋๋ค.
์ด๊ฒ์ ๋์ ์ฒซ ๋ฒ์งธ ๊ฒ์๋ฌผ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ํผ๋๋ฐฑ๋ ๋งค์ฐ ํ์ํ๋ค.๐โโ๏ธ
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ณ ํ๋ ๊ฐ๋ฐ์๋ฅผ ๋ํํ๋ Kubernetes๐ณ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/chiefnoah/-kubernetes-for-the-modern-developer--5am8
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
๋ชจ๋ ๊ตฌ์ฑ ๋ฐ ์ฝ๋๋ GitHub ํ๋ก์ ํธ์์ ํ์ธํ ์ ์์ต๋๋ค.
์ฒดํ๋ ธ / ์ฟ ๋ฒ ํธ
kubernetes ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ํ๋ ๊ฐ๋จํ ํ๋ก์ ํธ
์ฟ ๋ฒ ํธ
kubernetes ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ํ๋ ๊ฐ๋จํ ํ๋ก์ ํธ
View on GitHub
์
๋ฌธ๐๐จ
์, ์์ํ ์ค๋น ๋์ด์?์ปจํ
์ด๋์์ ์คํ๋๋ ์์ฉ ํ๋ก๊ทธ๋จ์ด ํ์ํ๋ฏ๋ก Python์ Flask ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ์ํฉ๋๋ค.
# test_server.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def kube():
return "Hello Kubernetes!"
์ด๊ฒ์ ๋จ์ผ ๊ฒฝ๋ก /
์ ํ๋ผ์คํฌ ์์ฉ์ ์ ์ํ๋ค.์ฌ๊ธฐ ๋ฌด์์ด ๊ฑฐ ์์ด!๐พ
์ดํ๋ฆฌ์ผ์ด์
์ ํ
์คํธํ๋ ค๋ฉด Flask ์ข
์์ฑ์ ์ค์นํฉ๋๋ค.
pip install flask
... ์ฌ์ฉ:
FLASK_APP=test_server.py flask run
๊ทธ๋ฆฌ๊ณ http://127.0.0.1:5000/ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด์ด ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ญ์์ค.
๋ฉ์ถ๋์.๐ฆ
๋ค์์ ์๋ก์ด ์น ์๋น์ค์ Dockerfile
์ ์ ์ํด์ผ ํฉ๋๋ค.๋๋ Dockerfiles์ ๋ํด ์ด๋ ์ ๋ ์ต์ํ๋ค๊ณ ๊ฐ์ ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด ์ ์ ์์ธํ๊ฒ ์๊ฐํ์ง ์์ ๊ฒ์ด๋ค.
FROM python:3.6.7-alpine3.7
RUN mkdir /app
WORKDIR /app
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY ./test_server.py /app/test_server.py
ENV FLASK_APP=test_server.py
ENV FLASK_ENV=development
ENTRYPOINT [ "flask", "run", "--host=0.0.0.0" ]
ํ์ฌ ์ฐ๋ฆฌ๋ ์ฝ๋๋ก ์ด๋ฏธ์ง๋ฅผ ๊ตฌ์ถํ๊ณ ํ์ํ๋ฉฐ ๋ฑ๋กํ๋ก ์ ์กํด์ผ ํ๋ค.์ด ์คํ์ ์ํํ๋ ค๋ฉด:
docker build -t localhost:32000/kubetest:v1.0.0 .
docker push localhost:32000/kubetest:v1.0.0
์ฃผ์: ์ฌ์ฉํ ์ฟ ๋ฒ ๋ฅด๋ค์ธ ๋ฒ์ ์ ๋ฐ๋ผ ์ด๋ฏธ์ง ์ด๋ฆ์ด ๋ค๋ฅผ ์ ์์ต๋๋ค. ๋ก์ปฌ ๋ฑ๋กํ์ ํธ์คํธ ์ด๋ฆ์ผ๋ก localhost:32000
์ ๋ฐ๊พธ์ญ์์ค.
์ด ์ด๋ฏธ์ง๋ฅผ ํ ๋ฒ๋ง ๊ตฌ์ถํ๋ฉด ๋ฉ๋๋ค. (์ ์์กด ํญ๋ชฉ์ ์ถ๊ฐํ์ง ์์ผ๋ฉด) ๋์ค์ ์์ ๋ ์ฝ๋๋ฅผ ์ด๋ฏธ์ง์ ์ฃผ์
ํ ๊ฒ์
๋๋ค.
์ฌ๋ฏธ์๋ ์ผ์ ๊ดํด์...๐
ํ์ฌ ์ฐ๋ฆฌ๋ Docker ๋ฏธ๋ฌ๊ฐ ํ๋ ์๋๋ฐ, ๊ทธ ์์๋ ์ฐ๋ฆฌ์ ์ต์ ๋ฒ์ ์ ์ฝ๋๊ฐ ์์ผ๋ฉฐ, ์ฐ๋ฆฌ์ ๋น๋๋ ์ ๊ทธ๋ฃน์์ ์คํํ ์ ์๋ค.๋ณดํต ์ง๊ธ, ๋น์ ์ docker run
์ ๊ฐ๋ํ๊ณ ํ๋ฃจ๋ฅผ ๋๋ผ ์ ์์ง๋ง, ์ฐ๋ฆฌ๋ ๋ ์ํ ๊ฒ์ด๋ค.
์ฐ๋ฆฌ๋ ๋ ๊ฐ์ง ์ ํ์ ์์์ ์ ์ํด์ ์ฐ๋ฆฌ์ ์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์ง๋จ์์ ์คํํด์ผ ํ๋ค. ํ๋๋ Deployment
์ด๊ณ , ๋ค๋ฅธ ํ๋๋ Service
์ด๋ค.๋ง์ฝ ์ด์ ์ docker-compose
์ ์ฌ์ฉํ ์ ์ด ์๋ค๋ฉด, ์ด๊ฒ์ ๊ฐ๋
์ ์ผ๋ก ๋งค์ฐ ๋น์ทํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ์ต์ํด ๋ณด์ผ ๊ฒ์ด๋ค.Deployment
์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์
๋๋ค.
# kubetest.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
...
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ๋ฐฉ๊ธ ์ ์กํ docker ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ์ฌ kubetest
์ด๋ผ๋ ๊ธฐ๋ณธ ์๋น์ค๋ฅผ ์ ์ํ์ต๋๋ค.์ค์ํ ๋นํธ๋ spec
๊ตฌ์กฐ์์ kubetest
์ด๋ผ๋ ์ฉ๊ธฐ ํญ๋ชฉ์ ์ ์ํ์ต๋๋ค. ์ด ํญ๋ชฉ์ ์ด๋ฏธ์ง localhost:32000/kubetest:v1.0.0
์ ์ฌ์ฉํ๊ณ ํฌํธ 5000
์ ๋
ธ์ถํฉ๋๋ค.๋ณด์ด๋คdockercompose์ service
์ฒ๋ผ.๐ ํ์ฌ kubectl create -f kubetest.yaml
์ผ๋กpod๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. HTTP๋ฅผ ํตํดpod์ ์ ๊ทผํ ์ ์์ง๋ง ๋น๋ถ๊ฐ ๊ทธ๋ฌ์ง ๋ง์ญ์์ค.
Pod์ด Kubernetes ๋คํธ์ํฌ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋๋ก Service
์ ์ ์ํด์ผ ํฉ๋๋ค.์ด๊ฒ์ -p
์ docker run
์ต์
๋๋ ports
์ docker-compose.yaml
๋ถ๋ถ๊ณผ ์ ์ฌํฉ๋๋ค.
# kubetest.yaml
...
---
kind: Service
apiVersion: v1
metadata:
name: kubetest
labels:
app: kubetest
spec:
selector:
app: kubetest
ports:
- name: http
port: 5000
protocol: TCP
type: NodePort
์ฃผ์: ๊ฐ๋จํ๊ฒ ๋ณด๊ธฐ ์ํด์, ๋๋ ๊ฐ์ ํ์ผ์ Deployment
๊ณผ Service
์ ์ ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์, ์ด์ ์ฐ๋ฆฌ ์ง๋จ์์ ๊ณ์ ์ค์ ํ์!
noah@kamijou:/opt/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest created
service/kubetest created
๋ค์ ๊ณต์์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ pod
์ ๋ณผ ์ ์์ต๋๋ค.
noah@kamijou:/opt/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-574958d5fd-zpvn5 1/1 Running 0 15s
... ์๋น์ค ์ฌ์ฉ:
noah@kamijou:/opt/kubetest$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 8d
kubetest NodePort 10.152.183.154 <none> 5000:31065/TCP 20s
noah@kamijou:/opt/kubetest$
์๋น์ค ๋ชฉ๋ก์ 5000:31065/TCP
๋ถ๋ถ์ ์ฃผ์ํ์ญ์์ค. 31065
์ ์น ์๋น์ค์ ์ฐ๊ฒฐํ๋ ํฌํธ์
๋๋ค.์ด์ ์ด๋ ๊ฒ ํฉ์๋ค.
noah@kamijou:/opt/kubetest$ curl -i localhost:31065
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 18
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 05:53:10 GMT
Hello Kubernetes!
๊ฒฝํํ์ด๐๐๐
... but wait, I was promised cookies being able to edit my code within the pod! ๐ฃ How am I supposed to do that!?
์ง์ ํด, ๊ทธ๋ด ๊ฑฐ์ผ!๐
kubetest.yaml
ํ์ผ๋ก ๋์๊ฐ์ ๋ช ์ค์ ์ถ๊ฐํฉ์๋ค.
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
+ volumeMounts:
+ - mountPath: /app
+ name: kubetest-volume
+ readOnly: true
+ volumes:
+ - name: kubetest-volume
+ hostPath:
+ path: /home/noah/kubetest
+ type: Directory
์ฌ๊ธฐ์๋ ํจํค์ง๋ฅผ ํด์ ํด์ผ ํ ์ ์ด ํ๋ ์์ง๋ง, ๋๋ ํฐ๋ฆฌ ๊ธฐ๋ฐ ํด๋ ๋ง์ดํธ๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. -v /host/path:/container/path
์ docker run
๋ฌธ๋ฒ๊ณผ ์ ์ฌํฉ๋๋ค.Kubernetes์ ์ฒ๋ฆฌ ๋ฐฉ์์ vanilla docker์ ์ฝ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์๊ณ ์ถ์ผ๋ฉด official documentation on persistent volumes์ ๋ณด์ญ์์ค.
์ฐธ๊ณ : path
๋ฐ์ดํธ์ ๊ฐ์ ๋ณ๊ฒฝํ์ฌ test_server.py
ํ์ผ์ด ์๋ ์์น๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํฉ๋๋ค.์ด๊ฒ์ ์ด ์
๋ฌด์ ์ ์์ ์ธ ์งํ์ ๋งค์ฐ ์ค์ํ๋ค.
๊ณ์ํ์ฌ kubectl apply -f kubetest.yaml
์ ๋ค์ ์คํํ๊ณ ๋ณผ๋ฅจ์ผ๋ก ์
๋ฐ์ดํธ ์ฉ๊ธฐ๋ฅผ ๋ง์ดํธํฉ๋๋ค.
noah@kamijou:~/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest configured
service/kubetest unchanged
๊ธฐ์ค๊ธฐ๊ฐ ์ด๋ฏธ ๊ฐ๋๋๊ณ ๋ค์ ์ดํ๋์๋์ง ๊ฒ์ฌํ๋ค
noah@kamijou:~/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-58f7b7d957-cvdch 1/1 Running 0 63s
์ด ๋ก๊ทธ๋ค์ ๋ชจ๋ pod์ STDOUT
๊ณผ STDERR
์์ ์ถ์ถ๋ ๊ฒ์
๋๋ค.์ ํฌ๋ kubetest
์๋น์ค์๋ง ๊ด์ฌ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
๋ฉ์ง๋ค, ์์ฉ ํ๋ก๊ทธ๋จ์ด ์ฌ์ ํ ์คํ๋๊ณ ์๋ค.
๋ง์ง๋ง์ผ๋ก test_server.py
์ ์๋ก์ด ๋จ์ ์ ์ถ๊ฐํฉ์๋ค
from flask import Flask
app = Flask(__name__)
@app.route("/")
def kube():
return "Hello Kubernetes!\n"
[email protected]("/healthz")
+def health():
+ return "ok\n", 200
... ๋ก๊ทธ๋ฅผ ๋ค์ ๊ฒ์ฌํฉ๋๋ค.
noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
* Detected change in '/app/test_server.py', reloading
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
Flask ์์ test_ ์๋ฒ๊ฐ ๋ณ๊ฒฝ๋์์ต๋๋ค.py ํ์ผ์ ์๋์ผ๋ก ๋ค์ ๋ถ๋ฌ์ต๋๋ค!
ํฌํธ๊ฐ kubectl get svc
์์ ๋ณ๊ฒฝ๋์ง ์์๋์ง ํ์ธํ๊ธฐ ์ํด ์ ๋
ธ๋์ ์ ๊ทผํด ๋ณด๊ฒ ์ต๋๋ค.
noah@kamijou:~/kubetest$ curl -i localhost:30788/healthz
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 06:25:33 GMT
ok
์ค, ์ฐ๋ฆฌ ๋๋ฌ์ด!
์ฝ์ด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
๋๋ ๋ค๊ฐ ๋์ ๋๊ธ์ด ๋์๊ฒ ๋์์ด ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ๊ธธ ๋ฐ๋๋ค.๋ง์ฝ ๋น์ ์๊ฒ ์ด๋ค ๋ฌธ์ ๊ฐ ์๋ค๋ฉด, ๋๊ธ์ ๋ฉ์์ง๋ฅผ ๋จ๊ฒจ ์ฃผ์ญ์์ค. ๋๋ ๊ธฐ๊บผ์ด ๋น์ ์ ๋์ธ ๊ฒ์
๋๋ค.
์ด๊ฒ์ ๋์ ์ฒซ ๋ฒ์งธ ๊ฒ์๋ฌผ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ํผ๋๋ฐฑ๋ ๋งค์ฐ ํ์ํ๋ค.๐โโ๏ธ
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ณ ํ๋ ๊ฐ๋ฐ์๋ฅผ ๋ํํ๋ Kubernetes๐ณ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/chiefnoah/-kubernetes-for-the-modern-developer--5am8
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
์, ์์ํ ์ค๋น ๋์ด์?์ปจํ ์ด๋์์ ์คํ๋๋ ์์ฉ ํ๋ก๊ทธ๋จ์ด ํ์ํ๋ฏ๋ก Python์ Flask ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ์ํฉ๋๋ค.
# test_server.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def kube():
return "Hello Kubernetes!"
์ด๊ฒ์ ๋จ์ผ ๊ฒฝ๋ก /
์ ํ๋ผ์คํฌ ์์ฉ์ ์ ์ํ๋ค.์ฌ๊ธฐ ๋ฌด์์ด ๊ฑฐ ์์ด!๐พ์ดํ๋ฆฌ์ผ์ด์ ์ ํ ์คํธํ๋ ค๋ฉด Flask ์ข ์์ฑ์ ์ค์นํฉ๋๋ค.
pip install flask
... ์ฌ์ฉ:FLASK_APP=test_server.py flask run
๊ทธ๋ฆฌ๊ณ http://127.0.0.1:5000/ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด์ด ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ญ์์ค.๋ฉ์ถ๋์.๐ฆ
๋ค์์ ์๋ก์ด ์น ์๋น์ค์ Dockerfile
์ ์ ์ํด์ผ ํฉ๋๋ค.๋๋ Dockerfiles์ ๋ํด ์ด๋ ์ ๋ ์ต์ํ๋ค๊ณ ๊ฐ์ ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด ์ ์ ์์ธํ๊ฒ ์๊ฐํ์ง ์์ ๊ฒ์ด๋ค.
FROM python:3.6.7-alpine3.7
RUN mkdir /app
WORKDIR /app
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY ./test_server.py /app/test_server.py
ENV FLASK_APP=test_server.py
ENV FLASK_ENV=development
ENTRYPOINT [ "flask", "run", "--host=0.0.0.0" ]
ํ์ฌ ์ฐ๋ฆฌ๋ ์ฝ๋๋ก ์ด๋ฏธ์ง๋ฅผ ๊ตฌ์ถํ๊ณ ํ์ํ๋ฉฐ ๋ฑ๋กํ๋ก ์ ์กํด์ผ ํ๋ค.์ด ์คํ์ ์ํํ๋ ค๋ฉด:
docker build -t localhost:32000/kubetest:v1.0.0 .
docker push localhost:32000/kubetest:v1.0.0
์ฃผ์: ์ฌ์ฉํ ์ฟ ๋ฒ ๋ฅด๋ค์ธ ๋ฒ์ ์ ๋ฐ๋ผ ์ด๋ฏธ์ง ์ด๋ฆ์ด ๋ค๋ฅผ ์ ์์ต๋๋ค. ๋ก์ปฌ ๋ฑ๋กํ์ ํธ์คํธ ์ด๋ฆ์ผ๋ก localhost:32000
์ ๋ฐ๊พธ์ญ์์ค.
์ด ์ด๋ฏธ์ง๋ฅผ ํ ๋ฒ๋ง ๊ตฌ์ถํ๋ฉด ๋ฉ๋๋ค. (์ ์์กด ํญ๋ชฉ์ ์ถ๊ฐํ์ง ์์ผ๋ฉด) ๋์ค์ ์์ ๋ ์ฝ๋๋ฅผ ์ด๋ฏธ์ง์ ์ฃผ์
ํ ๊ฒ์
๋๋ค.
์ฌ๋ฏธ์๋ ์ผ์ ๊ดํด์...๐
ํ์ฌ ์ฐ๋ฆฌ๋ Docker ๋ฏธ๋ฌ๊ฐ ํ๋ ์๋๋ฐ, ๊ทธ ์์๋ ์ฐ๋ฆฌ์ ์ต์ ๋ฒ์ ์ ์ฝ๋๊ฐ ์์ผ๋ฉฐ, ์ฐ๋ฆฌ์ ๋น๋๋ ์ ๊ทธ๋ฃน์์ ์คํํ ์ ์๋ค.๋ณดํต ์ง๊ธ, ๋น์ ์ docker run
์ ๊ฐ๋ํ๊ณ ํ๋ฃจ๋ฅผ ๋๋ผ ์ ์์ง๋ง, ์ฐ๋ฆฌ๋ ๋ ์ํ ๊ฒ์ด๋ค.
์ฐ๋ฆฌ๋ ๋ ๊ฐ์ง ์ ํ์ ์์์ ์ ์ํด์ ์ฐ๋ฆฌ์ ์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์ง๋จ์์ ์คํํด์ผ ํ๋ค. ํ๋๋ Deployment
์ด๊ณ , ๋ค๋ฅธ ํ๋๋ Service
์ด๋ค.๋ง์ฝ ์ด์ ์ docker-compose
์ ์ฌ์ฉํ ์ ์ด ์๋ค๋ฉด, ์ด๊ฒ์ ๊ฐ๋
์ ์ผ๋ก ๋งค์ฐ ๋น์ทํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ์ต์ํด ๋ณด์ผ ๊ฒ์ด๋ค.Deployment
์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์
๋๋ค.
# kubetest.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
...
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ๋ฐฉ๊ธ ์ ์กํ docker ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ์ฌ kubetest
์ด๋ผ๋ ๊ธฐ๋ณธ ์๋น์ค๋ฅผ ์ ์ํ์ต๋๋ค.์ค์ํ ๋นํธ๋ spec
๊ตฌ์กฐ์์ kubetest
์ด๋ผ๋ ์ฉ๊ธฐ ํญ๋ชฉ์ ์ ์ํ์ต๋๋ค. ์ด ํญ๋ชฉ์ ์ด๋ฏธ์ง localhost:32000/kubetest:v1.0.0
์ ์ฌ์ฉํ๊ณ ํฌํธ 5000
์ ๋
ธ์ถํฉ๋๋ค.๋ณด์ด๋คdockercompose์ service
์ฒ๋ผ.๐ ํ์ฌ kubectl create -f kubetest.yaml
์ผ๋กpod๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. HTTP๋ฅผ ํตํดpod์ ์ ๊ทผํ ์ ์์ง๋ง ๋น๋ถ๊ฐ ๊ทธ๋ฌ์ง ๋ง์ญ์์ค.
Pod์ด Kubernetes ๋คํธ์ํฌ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋๋ก Service
์ ์ ์ํด์ผ ํฉ๋๋ค.์ด๊ฒ์ -p
์ docker run
์ต์
๋๋ ports
์ docker-compose.yaml
๋ถ๋ถ๊ณผ ์ ์ฌํฉ๋๋ค.
# kubetest.yaml
...
---
kind: Service
apiVersion: v1
metadata:
name: kubetest
labels:
app: kubetest
spec:
selector:
app: kubetest
ports:
- name: http
port: 5000
protocol: TCP
type: NodePort
์ฃผ์: ๊ฐ๋จํ๊ฒ ๋ณด๊ธฐ ์ํด์, ๋๋ ๊ฐ์ ํ์ผ์ Deployment
๊ณผ Service
์ ์ ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์, ์ด์ ์ฐ๋ฆฌ ์ง๋จ์์ ๊ณ์ ์ค์ ํ์!
noah@kamijou:/opt/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest created
service/kubetest created
๋ค์ ๊ณต์์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ pod
์ ๋ณผ ์ ์์ต๋๋ค.
noah@kamijou:/opt/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-574958d5fd-zpvn5 1/1 Running 0 15s
... ์๋น์ค ์ฌ์ฉ:
noah@kamijou:/opt/kubetest$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 8d
kubetest NodePort 10.152.183.154 <none> 5000:31065/TCP 20s
noah@kamijou:/opt/kubetest$
์๋น์ค ๋ชฉ๋ก์ 5000:31065/TCP
๋ถ๋ถ์ ์ฃผ์ํ์ญ์์ค. 31065
์ ์น ์๋น์ค์ ์ฐ๊ฒฐํ๋ ํฌํธ์
๋๋ค.์ด์ ์ด๋ ๊ฒ ํฉ์๋ค.
noah@kamijou:/opt/kubetest$ curl -i localhost:31065
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 18
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 05:53:10 GMT
Hello Kubernetes!
๊ฒฝํํ์ด๐๐๐
... but wait, I was promised cookies being able to edit my code within the pod! ๐ฃ How am I supposed to do that!?
์ง์ ํด, ๊ทธ๋ด ๊ฑฐ์ผ!๐
kubetest.yaml
ํ์ผ๋ก ๋์๊ฐ์ ๋ช ์ค์ ์ถ๊ฐํฉ์๋ค.
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
+ volumeMounts:
+ - mountPath: /app
+ name: kubetest-volume
+ readOnly: true
+ volumes:
+ - name: kubetest-volume
+ hostPath:
+ path: /home/noah/kubetest
+ type: Directory
์ฌ๊ธฐ์๋ ํจํค์ง๋ฅผ ํด์ ํด์ผ ํ ์ ์ด ํ๋ ์์ง๋ง, ๋๋ ํฐ๋ฆฌ ๊ธฐ๋ฐ ํด๋ ๋ง์ดํธ๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. -v /host/path:/container/path
์ docker run
๋ฌธ๋ฒ๊ณผ ์ ์ฌํฉ๋๋ค.Kubernetes์ ์ฒ๋ฆฌ ๋ฐฉ์์ vanilla docker์ ์ฝ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์๊ณ ์ถ์ผ๋ฉด official documentation on persistent volumes์ ๋ณด์ญ์์ค.
์ฐธ๊ณ : path
๋ฐ์ดํธ์ ๊ฐ์ ๋ณ๊ฒฝํ์ฌ test_server.py
ํ์ผ์ด ์๋ ์์น๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํฉ๋๋ค.์ด๊ฒ์ ์ด ์
๋ฌด์ ์ ์์ ์ธ ์งํ์ ๋งค์ฐ ์ค์ํ๋ค.
๊ณ์ํ์ฌ kubectl apply -f kubetest.yaml
์ ๋ค์ ์คํํ๊ณ ๋ณผ๋ฅจ์ผ๋ก ์
๋ฐ์ดํธ ์ฉ๊ธฐ๋ฅผ ๋ง์ดํธํฉ๋๋ค.
noah@kamijou:~/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest configured
service/kubetest unchanged
๊ธฐ์ค๊ธฐ๊ฐ ์ด๋ฏธ ๊ฐ๋๋๊ณ ๋ค์ ์ดํ๋์๋์ง ๊ฒ์ฌํ๋ค
noah@kamijou:~/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-58f7b7d957-cvdch 1/1 Running 0 63s
์ด ๋ก๊ทธ๋ค์ ๋ชจ๋ pod์ STDOUT
๊ณผ STDERR
์์ ์ถ์ถ๋ ๊ฒ์
๋๋ค.์ ํฌ๋ kubetest
์๋น์ค์๋ง ๊ด์ฌ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
๋ฉ์ง๋ค, ์์ฉ ํ๋ก๊ทธ๋จ์ด ์ฌ์ ํ ์คํ๋๊ณ ์๋ค.
๋ง์ง๋ง์ผ๋ก test_server.py
์ ์๋ก์ด ๋จ์ ์ ์ถ๊ฐํฉ์๋ค
from flask import Flask
app = Flask(__name__)
@app.route("/")
def kube():
return "Hello Kubernetes!\n"
[email protected]("/healthz")
+def health():
+ return "ok\n", 200
... ๋ก๊ทธ๋ฅผ ๋ค์ ๊ฒ์ฌํฉ๋๋ค.
noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
* Detected change in '/app/test_server.py', reloading
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
Flask ์์ test_ ์๋ฒ๊ฐ ๋ณ๊ฒฝ๋์์ต๋๋ค.py ํ์ผ์ ์๋์ผ๋ก ๋ค์ ๋ถ๋ฌ์ต๋๋ค!
ํฌํธ๊ฐ kubectl get svc
์์ ๋ณ๊ฒฝ๋์ง ์์๋์ง ํ์ธํ๊ธฐ ์ํด ์ ๋
ธ๋์ ์ ๊ทผํด ๋ณด๊ฒ ์ต๋๋ค.
noah@kamijou:~/kubetest$ curl -i localhost:30788/healthz
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 06:25:33 GMT
ok
์ค, ์ฐ๋ฆฌ ๋๋ฌ์ด!
์ฝ์ด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
๋๋ ๋ค๊ฐ ๋์ ๋๊ธ์ด ๋์๊ฒ ๋์์ด ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ๊ธธ ๋ฐ๋๋ค.๋ง์ฝ ๋น์ ์๊ฒ ์ด๋ค ๋ฌธ์ ๊ฐ ์๋ค๋ฉด, ๋๊ธ์ ๋ฉ์์ง๋ฅผ ๋จ๊ฒจ ์ฃผ์ญ์์ค. ๋๋ ๊ธฐ๊บผ์ด ๋น์ ์ ๋์ธ ๊ฒ์
๋๋ค.
์ด๊ฒ์ ๋์ ์ฒซ ๋ฒ์งธ ๊ฒ์๋ฌผ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ํผ๋๋ฐฑ๋ ๋งค์ฐ ํ์ํ๋ค.๐โโ๏ธ
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ณ ํ๋ ๊ฐ๋ฐ์๋ฅผ ๋ํํ๋ Kubernetes๐ณ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/chiefnoah/-kubernetes-for-the-modern-developer--5am8
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
FROM python:3.6.7-alpine3.7
RUN mkdir /app
WORKDIR /app
COPY ./requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
COPY ./test_server.py /app/test_server.py
ENV FLASK_APP=test_server.py
ENV FLASK_ENV=development
ENTRYPOINT [ "flask", "run", "--host=0.0.0.0" ]
docker build -t localhost:32000/kubetest:v1.0.0 .
docker push localhost:32000/kubetest:v1.0.0
ํ์ฌ ์ฐ๋ฆฌ๋ Docker ๋ฏธ๋ฌ๊ฐ ํ๋ ์๋๋ฐ, ๊ทธ ์์๋ ์ฐ๋ฆฌ์ ์ต์ ๋ฒ์ ์ ์ฝ๋๊ฐ ์์ผ๋ฉฐ, ์ฐ๋ฆฌ์ ๋น๋๋ ์ ๊ทธ๋ฃน์์ ์คํํ ์ ์๋ค.๋ณดํต ์ง๊ธ, ๋น์ ์
docker run
์ ๊ฐ๋ํ๊ณ ํ๋ฃจ๋ฅผ ๋๋ผ ์ ์์ง๋ง, ์ฐ๋ฆฌ๋ ๋ ์ํ ๊ฒ์ด๋ค.์ฐ๋ฆฌ๋ ๋ ๊ฐ์ง ์ ํ์ ์์์ ์ ์ํด์ ์ฐ๋ฆฌ์ ์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์ง๋จ์์ ์คํํด์ผ ํ๋ค. ํ๋๋
Deployment
์ด๊ณ , ๋ค๋ฅธ ํ๋๋ Service
์ด๋ค.๋ง์ฝ ์ด์ ์ docker-compose
์ ์ฌ์ฉํ ์ ์ด ์๋ค๋ฉด, ์ด๊ฒ์ ๊ฐ๋
์ ์ผ๋ก ๋งค์ฐ ๋น์ทํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ์ต์ํด ๋ณด์ผ ๊ฒ์ด๋ค.Deployment
์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์
๋๋ค.# kubetest.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
...
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ๋ฐฉ๊ธ ์ ์กํ docker ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ์ฌ kubetest
์ด๋ผ๋ ๊ธฐ๋ณธ ์๋น์ค๋ฅผ ์ ์ํ์ต๋๋ค.์ค์ํ ๋นํธ๋ spec
๊ตฌ์กฐ์์ kubetest
์ด๋ผ๋ ์ฉ๊ธฐ ํญ๋ชฉ์ ์ ์ํ์ต๋๋ค. ์ด ํญ๋ชฉ์ ์ด๋ฏธ์ง localhost:32000/kubetest:v1.0.0
์ ์ฌ์ฉํ๊ณ ํฌํธ 5000
์ ๋
ธ์ถํฉ๋๋ค.๋ณด์ด๋คdockercompose์ service
์ฒ๋ผ.๐ ํ์ฌ kubectl create -f kubetest.yaml
์ผ๋กpod๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. HTTP๋ฅผ ํตํดpod์ ์ ๊ทผํ ์ ์์ง๋ง ๋น๋ถ๊ฐ ๊ทธ๋ฌ์ง ๋ง์ญ์์ค.Pod์ด Kubernetes ๋คํธ์ํฌ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋๋ก
Service
์ ์ ์ํด์ผ ํฉ๋๋ค.์ด๊ฒ์ -p
์ docker run
์ต์
๋๋ ports
์ docker-compose.yaml
๋ถ๋ถ๊ณผ ์ ์ฌํฉ๋๋ค.# kubetest.yaml
...
---
kind: Service
apiVersion: v1
metadata:
name: kubetest
labels:
app: kubetest
spec:
selector:
app: kubetest
ports:
- name: http
port: 5000
protocol: TCP
type: NodePort
์ฃผ์: ๊ฐ๋จํ๊ฒ ๋ณด๊ธฐ ์ํด์, ๋๋ ๊ฐ์ ํ์ผ์ Deployment
๊ณผ Service
์ ์ ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค.์, ์ด์ ์ฐ๋ฆฌ ์ง๋จ์์ ๊ณ์ ์ค์ ํ์!
noah@kamijou:/opt/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest created
service/kubetest created
๋ค์ ๊ณต์์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ pod
์ ๋ณผ ์ ์์ต๋๋ค.noah@kamijou:/opt/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-574958d5fd-zpvn5 1/1 Running 0 15s
... ์๋น์ค ์ฌ์ฉ:noah@kamijou:/opt/kubetest$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 8d
kubetest NodePort 10.152.183.154 <none> 5000:31065/TCP 20s
noah@kamijou:/opt/kubetest$
์๋น์ค ๋ชฉ๋ก์ 5000:31065/TCP
๋ถ๋ถ์ ์ฃผ์ํ์ญ์์ค. 31065
์ ์น ์๋น์ค์ ์ฐ๊ฒฐํ๋ ํฌํธ์
๋๋ค.์ด์ ์ด๋ ๊ฒ ํฉ์๋ค.noah@kamijou:/opt/kubetest$ curl -i localhost:31065
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 18
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 05:53:10 GMT
Hello Kubernetes!
๊ฒฝํํ์ด๐๐๐... but wait, I was promised
cookiesbeing able to edit my code within the pod! ๐ฃ How am I supposed to do that!?
์ง์ ํด, ๊ทธ๋ด ๊ฑฐ์ผ!๐
kubetest.yaml
ํ์ผ๋ก ๋์๊ฐ์ ๋ช ์ค์ ์ถ๊ฐํฉ์๋ค.apiVersion: apps/v1
kind: Deployment
metadata:
name: kubetest
spec:
selector:
matchLabels:
app: kubetest
template:
metadata:
labels:
app: kubetest
spec:
containers:
- name: kubetest
image: localhost:32000/kubetest:v1.0.0
ports:
- containerPort: 5000
imagePullPolicy: Always
+ volumeMounts:
+ - mountPath: /app
+ name: kubetest-volume
+ readOnly: true
+ volumes:
+ - name: kubetest-volume
+ hostPath:
+ path: /home/noah/kubetest
+ type: Directory
์ฌ๊ธฐ์๋ ํจํค์ง๋ฅผ ํด์ ํด์ผ ํ ์ ์ด ํ๋ ์์ง๋ง, ๋๋ ํฐ๋ฆฌ ๊ธฐ๋ฐ ํด๋ ๋ง์ดํธ๋ฅผ ๋ง๋ค๊ณ ์์ต๋๋ค. -v /host/path:/container/path
์ docker run
๋ฌธ๋ฒ๊ณผ ์ ์ฌํฉ๋๋ค.Kubernetes์ ์ฒ๋ฆฌ ๋ฐฉ์์ vanilla docker์ ์ฝ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์๊ณ ์ถ์ผ๋ฉด official documentation on persistent volumes์ ๋ณด์ญ์์ค.์ฐธ๊ณ :
path
๋ฐ์ดํธ์ ๊ฐ์ ๋ณ๊ฒฝํ์ฌ test_server.py
ํ์ผ์ด ์๋ ์์น๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํฉ๋๋ค.์ด๊ฒ์ ์ด ์
๋ฌด์ ์ ์์ ์ธ ์งํ์ ๋งค์ฐ ์ค์ํ๋ค.๊ณ์ํ์ฌ
kubectl apply -f kubetest.yaml
์ ๋ค์ ์คํํ๊ณ ๋ณผ๋ฅจ์ผ๋ก ์
๋ฐ์ดํธ ์ฉ๊ธฐ๋ฅผ ๋ง์ดํธํฉ๋๋ค.noah@kamijou:~/kubetest$ kubectl apply -f kubetest.yaml
deployment.apps/kubetest configured
service/kubetest unchanged
๊ธฐ์ค๊ธฐ๊ฐ ์ด๋ฏธ ๊ฐ๋๋๊ณ ๋ค์ ์ดํ๋์๋์ง ๊ฒ์ฌํ๋คnoah@kamijou:~/kubetest$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kubetest-58f7b7d957-cvdch 1/1 Running 0 63s
์ด ๋ก๊ทธ๋ค์ ๋ชจ๋ pod์ STDOUT
๊ณผ STDERR
์์ ์ถ์ถ๋ ๊ฒ์
๋๋ค.์ ํฌ๋ kubetest
์๋น์ค์๋ง ๊ด์ฌ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
๋ฉ์ง๋ค, ์์ฉ ํ๋ก๊ทธ๋จ์ด ์ฌ์ ํ ์คํ๋๊ณ ์๋ค.๋ง์ง๋ง์ผ๋ก
test_server.py
์ ์๋ก์ด ๋จ์ ์ ์ถ๊ฐํฉ์๋คfrom flask import Flask
app = Flask(__name__)
@app.route("/")
def kube():
return "Hello Kubernetes!\n"
[email protected]("/healthz")
+def health():
+ return "ok\n", 200
... ๋ก๊ทธ๋ฅผ ๋ค์ ๊ฒ์ฌํฉ๋๋ค.noah@kamijou:~/kubetest$ kubectl logs svc/kubetest
* Serving Flask app "test_server.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
* Detected change in '/app/test_server.py', reloading
* Restarting with stat
* Debugger is active!
* Debugger PIN: 124-402-077
Flask ์์ test_ ์๋ฒ๊ฐ ๋ณ๊ฒฝ๋์์ต๋๋ค.py ํ์ผ์ ์๋์ผ๋ก ๋ค์ ๋ถ๋ฌ์ต๋๋ค!ํฌํธ๊ฐ
kubectl get svc
์์ ๋ณ๊ฒฝ๋์ง ์์๋์ง ํ์ธํ๊ธฐ ์ํด ์ ๋
ธ๋์ ์ ๊ทผํด ๋ณด๊ฒ ์ต๋๋ค.noah@kamijou:~/kubetest$ curl -i localhost:30788/healthz
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 3
Server: Werkzeug/0.14.1 Python/3.6.7
Date: Wed, 12 Dec 2018 06:25:33 GMT
ok
์ค, ์ฐ๋ฆฌ ๋๋ฌ์ด!์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
๋๋ ๋ค๊ฐ ๋์ ๋๊ธ์ด ๋์๊ฒ ๋์์ด ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ๊ธธ ๋ฐ๋๋ค.๋ง์ฝ ๋น์ ์๊ฒ ์ด๋ค ๋ฌธ์ ๊ฐ ์๋ค๋ฉด, ๋๊ธ์ ๋ฉ์์ง๋ฅผ ๋จ๊ฒจ ์ฃผ์ญ์์ค. ๋๋ ๊ธฐ๊บผ์ด ๋น์ ์ ๋์ธ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ ๋์ ์ฒซ ๋ฒ์งธ ๊ฒ์๋ฌผ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ํผ๋๋ฐฑ๋ ๋งค์ฐ ํ์ํ๋ค.๐โโ๏ธ
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ณ ํ๋ ๊ฐ๋ฐ์๋ฅผ ๋ํํ๋ Kubernetes๐ณ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/chiefnoah/-kubernetes-for-the-modern-developer--5am8ํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค