ํํ ๋ฆฌ์ผ ์ฟ ๋ฒ๋คํฐ์ค ๋ฌธ์์ ๋ณธ ์น์
์ ํํ ๋ฆฌ์ผ์ ํฌํจํ๊ณ ์๋ค.
ํํ ๋ฆฌ์ผ์ ๊ฐ๋ณ ์์
๋จ์๋ณด๋ค ๋ ํฐ ๋ชฉํ๋ฅผ ๋ฌ์ฑํ๊ธฐ
์ํ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋ค. ์ผ๋ฐ์ ์ผ๋ก ํํ ๋ฆฌ์ผ์ ๊ฐ๊ฐ ์์ฐจ์ ๋จ๊ณ๊ฐ ์๋ ์ฌ๋ฌ
์น์
์ผ๋ก ๊ตฌ์ฑ๋๋ค.
๊ฐ ํํ ๋ฆฌ์ผ์ ๋ฐ๋ผํ๊ธฐ ์ ์, ๋์ค์ ์ฐธ์กฐํ ์ ์๋๋ก
ํ์ค ์ฉ์ด์ง ํ์ด์ง๋ฅผ ๋ถ๋งํฌํ๊ธฐ๋ฅผ ๊ถํ๋ค.
๊ธฐ์ด ๊ตฌ์ฑ ์ํ ์ ์ง๋ฅผ ํ์ง ์๋(stateless) ์ ํ๋ฆฌ์ผ์ด์
์ํ ์ ์ง๊ฐ ํ์ํ(stateful) ์ ํ๋ฆฌ์ผ์ด์
์๋น์ค ๋ณด์ ๋ค์ ๋ด์ฉ ํํ ๋ฆฌ์ผ์ ์์ฑํ๊ณ ์ถ๋ค๋ฉด, ํํ ๋ฆฌ์ผ ํ์ด์ง ์ ํ์ ๋ํ ์ ๋ณด๊ฐ ์๋
์ฝํ
์ธ ํ์ด์ง ์ ํ
ํ์ด์ง๋ฅผ ์ฐธ์กฐํ๋ค.
1 - Hello Minikube ์ด ํํ ๋ฆฌ์ผ์์๋ Minikube๋ฅผ ์ด์ฉํ์ฌ ์ฟ ๋ฒ๋คํฐ์ค์์ ์ํ ์ ํ๋ฆฌ์ผ์ด์
์ ์ด๋ป๊ฒ ์คํํ๋์ง ์ดํด๋ณธ๋ค.
์ด ํํ ๋ฆฌ์ผ์ NGINX๋ฅผ ํตํด ๋ชจ๋ ์์ฒญ์ ๊ทธ๋๋ก ๋๋๋ ค ์ฃผ๋ (echo back) ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํ๋ค.
๋ชฉ์ ์ํ ์ ํ๋ฆฌ์ผ์ด์
์ minikube์ ๋ฐฐํฌํ๋ค. ๋ฐฐํฌํ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ๋ค. ์ ํ๋ฆฌ์ผ์ด์
์ ๋ก๊ทธ๋ฅผ ํ์ธํ๋ค. ์์ํ๊ธฐ ์ ์ ์ด ํํ ๋ฆฌ์ผ์ ์ด๋ฏธ minikube
๊ฐ ์ด๋ฏธ ๊ตฌ์ถ๋์ด ์๋ค๊ณ ๊ฐ์ ํ๋ค.
์ค์น ๋ฐฉ๋ฒ์ minikube ์์ ์ Step 1, Installation ์ ์ฐธ๊ณ ํ๋ค.
์ฐธ๊ณ : Step 1, Installation ์ ์ง์นจ๋ง ์คํํ๋ค. ๋๋จธ์ง ๋ด์ฉ์ ์ด ํ์ด์ง์์ ๋ค๋ฃฌ๋ค.
๋ํ, kubectl
์ ์ค์นํด์ผ ํ๋ค.
์ค์น ๋ฐฉ๋ฒ์ ๋๊ตฌ ์ค์น ๋ฅผ ์ฐธ๊ณ ํ๋ค.
minikube ํด๋ฌ์คํฐ ๋ง๋ค๊ธฐ ๋์๋ณด๋ ์ ์ํ๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค ๋์๋ณด๋๋ฅผ ์ฌ๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค.
์ ํฐ๋ฏธ๋์ ์ด๊ณ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
# ์ ํฐ๋ฏธ๋์์ ์์ํ๊ณ , ํด๋น ํฐ๋ฏธ๋์ ์คํ ์ํ๋ก ๋์ด์ผ ํจ.
minikube dashboard
์ด์ minikube start
๋ฅผ ์คํํ๋ ํฐ๋ฏธ๋๋ก ๋ค์ ์ ํํ๋ค.
์ฐธ๊ณ : dashboard
๋ช
๋ น์ด๋ ๋์๋ณด๋ ์ ๋์จ์ ํ์ฑํํ๊ณ ๊ธฐ๋ณธ ์น ๋ธ๋ผ์ฐ์ ์์ ํ๋ก์๋ฅผ ์ฐ๋ค.
๋์๋ณด๋์์ ๋ํ๋ก์ด๋จผํธ(Deployment), ์๋น์ค์ ๊ฐ์ ์ฟ ๋ฒ๋คํฐ์ค ๋ฆฌ์์ค๋ฅผ ์์ฑํ ์ ์๋ค.
๋ธ๋ผ์ฐ์ ๋ฅผ ํฐ๋ฏธ๋์์ ์ง์ ํธ์ถํ์ง ์๊ณ ์น ๋์๋ณด๋์ ์ ์ํ๊ธฐ ์ํ URL์ ์ป๋ ๋ฐฉ๋ฒ์ ์์๋ณด๋ ค๋ฉด, "URL ๋ณต์ฌ ๋ฐ ๋ถ์ฌ๋ฃ๊ธฐ" ํญ์ ์ฐธ๊ณ ํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ๋์๋ณด๋๋ ์ฟ ๋ฒ๋คํฐ์ค ๋ด๋ถ ๊ฐ์ ๋คํธ์ํฌ ๋ด์์๋ง ์ ๊ทผํ ์ ์๋ค.
dashboard
๋ช
๋ น์ด๋ ๋์๋ณด๋๊ฐ ์ฟ ๋ฒ๋คํฐ์ค ๊ฐ์ ๋คํธ์ํฌ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋๋ก ์์ ํ๋ก์๋ฅผ ์์ฑํ๋ค.
ํ๋ก์๋ฅผ ์ค์งํ๋ ค๋ฉด Ctrl+C
๋ฅผ ์คํํ์ฌ ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃํ๋ค.
๋ช
๋ น์ด ์ข
๋ฃ๋ ํ์๋ ๋์๋ณด๋๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์์ ๊ณ์ ์คํ๋๋ค.
๋์๋ณด๋์ ์ ๊ทผํ๊ธฐ ์ํ ๋ ๋ค๋ฅธ ํ๋ก์๋ฅผ ์์ฑํ๋ ค๋ฉด dashboard
๋ช
๋ น์ด๋ฅผ ๋ค์ ์คํํ๋ฉด ๋๋ค.
minikube๊ฐ ์๋์ผ๋ก ์น ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด์ง ์๊ฒ ํ๋ ค๋ฉด, dashboard
์๋ธ์ปค๋งจ๋๋ฅผ
--url
ํ๋๊ทธ์ ํจ๊ป ์คํํ๋ค. minikube
๋ ์ฌ์ฉ์๊ฐ ์ ํธํ๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก URL์ ์ถ๋ ฅํ๋ค.
์ ํฐ๋ฏธ๋์ ์ด๊ณ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
# ์ ํฐ๋ฏธ๋์์ ์์ํ๊ณ , ํด๋น ํฐ๋ฏธ๋์ ์คํ ์ํ๋ก ๋์ด์ผ ํจ.
minikube dashboard --url
์ด์ ์ด URL์ ์ฌ์ฉํ์ฌ minikube start
๋ฅผ ์คํํ๋ ํฐ๋ฏธ๋๋ก ๋ค์ ์ ํํ ์ ์๋ค.
๋ํ๋ก์ด๋จผํธ ๋ง๋ค๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ๋ ๊ด๋ฆฌ์
๋คํธ์ํน ๋ชฉ์ ์ผ๋ก ํจ๊ป ๋ฌถ์ฌ ์๋ ํ๋ ์ด์์ ์ปจํ
์ด๋ ๊ทธ๋ฃน์ด๋ค.
์ด ํํ ๋ฆฌ์ผ์ ํ๋์๋ ๋จ ํ๋์ ์ปจํ
์ด๋๋ง ์๋ค. ์ฟ ๋ฒ๋คํฐ์ค
๋ํ๋ก์ด๋จผํธ ๋ ํ๋์
์ํ๋ฅผ ํ์ธํ๊ณ , ํ๋์ ์ปจํ
์ด๋๊ฐ ์ข
๋ฃ๋์๋ค๋ฉด ์ฌ์์ํ๋ค.
ํ๋์ ์์ฑ ๋ฐ ์ค์ผ์ผ๋ง์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ํ๋ก์ด๋จผํธ๋ฅผ ๊ถ์ฅํ๋ค.
kubectl create
๋ช
๋ น์ด๋ฅผ ์คํํ์ฌ ํ๋๋ฅผ ๊ด๋ฆฌํ ๋ํ๋ก์ด๋จผํธ๋ฅผ ๋ง๋ ๋ค. ์ด
ํ๋๋ ์ ๊ณต๋ Docker ์ด๋ฏธ์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์ปจํ
์ด๋๋ฅผ ์คํํ๋ค.
# ํ
์คํธ์ฉ ์น ์๋ฒ ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ์คํํ๋ค.
kubectl create deployment hello-node --image= registry.k8s.io/e2e-test-images/agnhost:2.39 -- /agnhost netexec --http-port= 8080
๋ํ๋ก์ด๋จผํธ ๋ณด๊ธฐ
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
NAME READY UP-TO-DATE AVAILABLE AGE
hello-node 1/1 1 1 1m
(ํ๋๊ฐ ์ค๋น๋๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์๋ค. "0/1"์ด ํ์๋๋ฉด ๋ช ์ด ํ์ ๋ค์ ์๋ํด๋ณธ๋ค.)
ํ๋ ๋ณด๊ธฐ
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
NAME READY STATUS RESTARTS AGE
hello-node-5f76cf6ccf-br9b5 1/1 Running 0 1m
ํด๋ฌ์คํฐ ์ด๋ฒคํธ ๋ณด๊ธฐ
kubectl
ํ๊ฒฝ์ค์ ๋ณด๊ธฐ
ํ๋ ๋ด ์ปจํ
์ด๋์ ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ๋ฅผ ํ์ธํ๋ค. (ํ๋ ์ด๋ฆ์ kubectl get pods
๋ช
๋ น์ด๋ก ์ป์ ์ด๋ฆ์ผ๋ก ๊ต์ฒดํ๋ค)
์ฐธ๊ณ : ์๋ `kubectl logs` ๋ช
๋ น์ด์์ `hello-node-5f76cf6ccf-br9b5` ๋ถ๋ถ์ `kubectl get pods` ๋ช
๋ น์ด ์ถ๋ ฅ์์ ์ป์ ํ๋ ์ด๋ฆ์ผ๋ก ๊ต์ฒดํ๋ค.
kubectl logs hello-node-5f76cf6ccf-br9b5
์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
I0911 09:19:26.677397 1 log.go:195] Started HTTP server on port 8080
I0911 09:19:26.677586 1 log.go:195] Started UDP server on port 8081
์ฐธ๊ณ : kubectl
๋ช
๋ น์ด์ ๊ดํด ์์ธํ ์๊ณ ์ถ๋ค๋ฉด
kubectl ๊ฐ์ ์ ์ดํด๋ณธ๋ค.
์๋น์ค ๋ง๋ค๊ธฐ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด๋ถ์ IP ์ฃผ์๋ก๋ง
์ ๊ทผํ ์ ์๋ค. hello-node
์ปจํ
์ด๋๋ฅผ ์ฟ ๋ฒ๋คํฐ์ค ๊ฐ์ ๋คํธ์ํฌ
์ธ๋ถ์์ ์ ๊ทผํ๋ ค๋ฉด ํ๋๋ฅผ ์ฟ ๋ฒ๋คํฐ์ค
์๋น์ค ๋ก ๋
ธ์ถํด์ผ ํ๋ค.
๊ฒฝ๊ณ : agnhost ์ปจํ
์ด๋์๋ ๋๋ฒ๊น
์ ์ ์ฉํ /shell
์๋ํฌ์ธํธ๊ฐ ์์ง๋ง, ์ด๋
๊ณต์ฉ ์ธํฐ๋ท์ ๋
ธ์ถํ๊ธฐ์ ์ํํ๋ค. ์ด ์ปจํ
์ด๋๋ฅผ ์ธํฐ๋ท์ ์ฐ๊ฒฐ๋ ํด๋ฌ์คํฐ๋
ํ๋ก๋์
ํด๋ฌ์คํฐ์์ ์คํํ์ง ์๋๋ค.kubectl expose
๋ช
๋ น์ด๋ก ํผ๋ธ๋ฆญ ์ธํฐ๋ท์ ํ๋ ๋
ธ์ถํ๊ธฐ
kubectl expose deployment hello-node --type= LoadBalancer --port= 8080
--type=LoadBalancer
ํ๋๊ทธ๋ ํด๋ฌ์คํฐ ๋ฐ์ ์๋น์ค๋ก ๋
ธ์ถํ๊ธฐ
์ํ๋ค๋ ๋ป์ด๋ค.
registry.k8s.io/echoserver
์ด๋ฏธ์ง ๋ด์ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๋ TCP ํฌํธ 8080์์๋ง ์์ ํ๋ค. kubectl expose
๋ฅผ
์ฌ์ฉํ์ฌ ๋ค๋ฅธ ํฌํธ๋ฅผ ๋
ธ์ถํ ๊ฒฝ์ฐ, ํด๋ผ์ด์ธํธ๋ ๋ค๋ฅธ ํฌํธ์ ์ฐ๊ฒฐํ ์ ์๋ค.
์์ฑํ ์๋น์ค ์ดํด๋ณด๊ธฐ
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node LoadBalancer 10.108.144.78 <pending> 8080:30369/TCP 21s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23m
๋ก๋ ๋ฐธ๋ฐ์๋ฅผ ์ง์ํ๋ ํด๋ผ์ฐ๋ ๊ณต๊ธ์์ ๊ฒฝ์ฐ์๋
์๋น์ค์ ์ ๊ทผํ ์ ์๋๋ก ์ธ๋ถ IP ์ฃผ์๊ฐ ํ๋ก๋น์ ๋ ํ๋ค.
minikube์์ LoadBalancer
ํ์
์ minikube service
๋ช
๋ น์ด๋ฅผ ํตํด์ ํด๋น ์๋น์ค๋ฅผ ์ ๊ทผํ ์
์๊ฒ ํ๋ค.
๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค
minikube service hello-node
์ด ๋ช
๋ น์ ๋ธ๋ผ์ฐ์ ์ฐฝ์ ์ด์ด ์ฑ์ ๋ณด์ฌ์ฃผ๊ณ , ๊ทธ ์๋ต์ ํ์ํ๋ค.
์ ๋์จ ์ฌ์ฉํ๊ธฐ minikube ํด์ ํ์ฑํํ๊ฑฐ๋ ๋นํ์ฑํํ ์ ์๊ณ ๋ก์ปฌ ์ฟ ๋ฒ๋คํฐ์ค ํ๊ฒฝ์์ ์ ์ํด ๋ณผ ์ ์๋ ๋ด์ฅ ์ ๋์จ ์
์ด ํฌํจ๋์ด ์๋ค.
ํ์ฌ ์ง์ํ๋ ์ ๋์จ ๋ชฉ๋ก์ ํ์ธํ๋ค.
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
addon-manager: enabled
dashboard: enabled
default-storageclass: enabled
efk: disabled
freshpod: disabled
gvisor: disabled
helm-tiller: disabled
ingress: disabled
ingress-dns: disabled
logviewer: disabled
metrics-server: disabled
nvidia-driver-installer: disabled
nvidia-gpu-device-plugin: disabled
registry: disabled
registry-creds: disabled
storage-provisioner: enabled
storage-provisioner-gluster: disabled
์ ๋์จ์ ํ์ฑํ ํ๋ค. ์ฌ๊ธฐ์๋ metrics-server
๋ฅผ ์์๋ก ์ฌ์ฉํ๋ค.
minikube addons enable metrics-server
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
The 'metrics-server' addon is enabled
์์ฑํ ํ๋์ ์๋น์ค๋ฅผ ํ์ธํ๋ค.
kubectl get pod,svc -n kube-system
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
NAME READY STATUS RESTARTS AGE
pod/coredns-5644d7b6d9-mh9ll 1/1 Running 0 34m
pod/coredns-5644d7b6d9-pqd2t 1/1 Running 0 34m
pod/metrics-server-67fb648c5 1/1 Running 0 26s
pod/etcd-minikube 1/1 Running 0 34m
pod/influxdb-grafana-b29w8 2/2 Running 0 26s
pod/kube-addon-manager-minikube 1/1 Running 0 34m
pod/kube-apiserver-minikube 1/1 Running 0 34m
pod/kube-controller-manager-minikube 1/1 Running 0 34m
pod/kube-proxy-rnlps 1/1 Running 0 34m
pod/kube-scheduler-minikube 1/1 Running 0 34m
pod/storage-provisioner 1/1 Running 0 34m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT( S) AGE
service/metrics-server ClusterIP 10.96.241.45 <none> 80/TCP 26s
service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 34m
service/monitoring-grafana NodePort 10.99.24.54 <none> 80:30002/TCP 26s
service/monitoring-influxdb ClusterIP 10.111.169.94 <none> 8083/TCP,8086/TCP 26s
metrics-server
์ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๋ค.
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
NAME CPU(cores) MEMORY(bytes)
hello-node-ccf4b9788-4jn97 1m 6Mi
๋ง์ฝ ๋ค์์ ๋ฉ์์ง๊ฐ ๋ณด์ธ๋ค๋ฉด, ์ ์ ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ค์ ์๋ํ๋ค.
error: Metrics API not available
metrics-server
๋ฅผ ๋นํ์ฑํํ๋ค.
minikube addons disable metrics-server
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
metrics-server was successfully disabled
์ ๊ฑฐํ๊ธฐ ์ด์ ํด๋ฌ์คํฐ์์ ๋ง๋ค์ด์ง ๋ฆฌ์์ค๋ฅผ ์ ๊ฑฐํ ์ ์๋ค.
kubectl delete service hello-node
kubectl delete deployment hello-node
Minikube ํด๋ฌ์คํฐ๋ฅผ ์ข
๋ฃํ๋ค.
ํ์ํ๋ฉด minikube VM์ ์ญ์ ํ๋ค.
# ์ ํ์ฌํญ
minikube delete
์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ๋ ๋ฐฐ์ฐ๊ธฐ ์ํด minikube๋ฅผ ๋ค์ ์ฌ์ฉํ ๊ณํ์ด๋ผ๋ฉด, ๊ตณ์ด ์ญ์ ํ์ง ์์๋ ๋๋ค.
๊ฒฐ๋ก ์ด ํ์ด์ง์์๋ minikube ํด๋ฌ์คํฐ๋ฅผ ์คํํ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ๊ธฐ ์ํ ๊ธฐ๋ณธ์ ์ธ ๋ด์ฉ์ ๋ค๋ฃจ์๋ค. ์ด์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ์ค๋น๊ฐ ๋์๋ค.
๋ค์ ๋ด์ฉ 2 - ์ฟ ๋ฒ๋คํฐ์ค ๊ธฐ์ด ํ์ต ์ฟ ๋ฒ๋คํฐ์ค ๊ธฐ์ด ์ด ํํ ๋ฆฌ์ผ์์๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ์ค์ผ์คํธ๋ ์ด์
์์คํ
์ ๊ธฐ์ด๋ฅผ ์ตํ ์ ์๋ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํ๋ค. ๊ฐ๊ฐ์ ๋ชจ๋์๋ ์ฟ ๋ฒ๋คํฐ์ค์ ์ฃผ์ ๊ธฐ๋ฅ๊ณผ ๊ฐ๋
์ ๋ํ ๋ฐฐ๊ฒฝ ์ง์์ด ๋ด๊ฒจ ์์ผ๋ฉฐ ๋ํํ ์จ๋ผ์ธ ํํ ๋ฆฌ์ผ๋ ํฌํจ๋์ด ์๋ค. ๋ํํ ํํ ๋ฆฌ์ผ์์ ๊ฐ๋จํ ํด๋ฌ์คํฐ์ ๊ทธ ํด๋ฌ์คํฐ ์์ ์ปจํ
์ด๋ํ ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ง์ ๊ด๋ฆฌํด๋ณผ ์ ์๋ค.
๋ํํ ํํ ๋ฆฌ์ผ์ ์ฌ์ฉํด์ ๋ค์์ ๋ด์ฉ์ ๋ฐฐ์ธ ์ ์๋ค.
์ปจํ
์ด๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ํด๋ฌ์คํฐ์ ๋ฐฐํฌํ๊ธฐ. ๋ํ๋ก์ด๋จผํธ๋ฅผ ์ค์ผ์ผ๋งํ๊ธฐ. ์ปจํ
์ด๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์๋ก์ด ์ํํธ์จ์ด ๋ฒ์ ์ผ๋ก ์
๋ฐ์ดํธํ๊ธฐ. ์ปจํ
์ด๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋๋ฒ๊ทธํ๊ธฐ. ์ด ํํ ๋ฆฌ์ผ์์๋ Katacoda๋ฅผ ์ฌ์ฉํด์ ๋
์์ ์น๋ธ๋ผ์ฐ์ ์์ Minikube๊ฐ ๋์ํ๋ ๊ฐ์ ํฐ๋ฏธ๋์ ๊ตฌ๋์ํจ๋ค. Minikube๋ ๋ก์ปฌ์ ์ค์นํ ์ ์๋ ์์ ๊ท๋ชจ์ ์ฟ ๋ฒ๋คํฐ์ค๋ก์จ ์ด๋์์๋ ์๋๋๋ค. ์ด๋ค ์ํํธ์จ์ด๋ ์ค์นํ ํ์๊ฐ ์๊ณ , ์๋ฌด ๊ฒ๋ ์ค์ ํ ํ์๊ฐ ์๋ค. ์๋ํ๋ฉด ๋ํํ ํํ ๋ฆฌ์ผ์ด ์น๋ธ๋ผ์ฐ์ ์์ฒด์์ ๋ฐ๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ฟ ๋ฒ๋คํฐ์ค๊ฐ ์ด๋ค ๋์์ด ๋ ๊น? ์ค๋๋ ์ ์น์๋น์ค์ ๋ํด์, ์ฌ์ฉ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ด 24/7 ๊ฐ์ฉํ๊ธฐ๋ฅผ ๋ฐ๋ผ๊ณ , ๊ฐ๋ฐ์๋ ํ๋ฃจ์๋ ๋ช ๋ฒ์ด๊ณ ์๋ก์ด ๋ฒ์ ์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ๊ธฐ๋ฅผ ๋ฐ๋๋ค. ์ปจํ
์ด๋ํ๋ฅผ ํตํด ์ํํธ์จ์ด๋ฅผ ํจํค์งํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์
์ ๋ค์ดํ์ ์์ด ๋ฆด๋ฆฌ์ค ๋ฐ ์
๋ฐ์ดํธํ ์ ์๊ฒ ๋์ด์ ์ด๋ฐ ๋ชฉํ๋ฅผ ๋ฌ์ฑํ๋๋ฐ ๋์์ด ๋๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋ ์ด๋ ๊ฒ ์ปจํ
์ด๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ๋ ๊ณณ ์ด๋์๋ ๋ ์ธ์ ๋ ๊ตฌ๋์ํฌ ์ ์๋ค๋ ํ์ ์ ๊ฐ๋๋ฐ ๋์์ ์ฃผ๋ฉฐ, ๊ทธ ์ ํ๋ฆฌ์ผ์ด์
์ด ์๋ํ๋๋ฐ ํ์ํ ์์๊ณผ ๋๊ตฌ๋ฅผ ์ฐพ๋ ๊ฒ์ ๋์์ค๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋ ๊ตฌ๊ธ์ ์ปจํ
์ด๋ ์ค์ผ์คํธ๋ ์ด์
๋ถ๋ฌธ์ ์ถ์ ๋ ๊ฒฝํ์ผ๋ก ์ค๊ณ๋๊ณ ์ปค๋ฎค๋ํฐ๋ก๋ถํฐ ๋์ถ๋ ์ต๊ณ ์ ์์ด๋์ด๊ฐ ๊ฒฐํฉ๋ ์ด์ ์์ค์ ์คํ ์์ค ํ๋ซํผ์ด๋ค.
์ฟ ๋ฒ๋คํฐ์ค ๊ธฐ์ด ๋ชจ๋ 2.1 - ํด๋ฌ์คํฐ ์์ฑํ๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ์ ๋ํ ๋ด์ฉ์ ํ์ธํ๊ณ Minikube๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ํด๋ฌ์คํฐ๋ฅผ ์์ฑํด ๋ณธ๋ค.
2.1.1 - Minikube๋ฅผ ์ฌ์ฉํด์ ํด๋ฌ์คํฐ ์์ฑํ๊ธฐ ๋ชฉํ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๊ฐ ๋ฌด์์ธ์ง ๋ฐฐ์ด๋ค. Minikube๊ฐ ๋ฌด์์ธ์ง ๋ฐฐ์ด๋ค. ์จ๋ผ์ธ ํฐ๋ฏธ๋์ ์ฌ์ฉํด์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ฅผ ์์ํ๋ค. ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ์ฟ ๋ฒ๋คํฐ์ค๋ ์ปดํจํฐ๋ค์ ์ฐ๊ฒฐํ์ฌ ๋จ์ผ ํ์์ผ๋ก ๋์ํ๋๋ก ์ปดํจํ
ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ์ฑํ๊ณ ๋์ ๊ฐ์ฉ์ฑ์ ์ ๊ณตํ๋๋ก ์กฐ์จํ๋ค. ์ฌ์ฉ์๋ ์ฟ ๋ฒ๋คํฐ์ค์ ์ถ์ํ ๊ฐ๋
์ ํตํด ๊ฐ๋ณ ๋จธ์ ์ ์ฝ๋งค์ด์ง ์๊ณ ์ปจํ
์ด๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ํด๋ฌ์คํฐ์ ๋ฐฐํฌํ ์ ์๋ค. ์ด๋ ๊ฒ ์๋ก์ด ๋ฐฐํฌ ๋ชจ๋ธ์ ํ์ฉํ๋ ค๋ฉด, ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ณ ํธ์คํธ์ ๋
๋ฆฝ์ ์ธ ๋ฐฉ์์ผ๋ก ํจํค์งํ ํ์๊ฐ ์๋ค. ์ฆ, ์ปจํ
์ด๋ํ๊ฐ ํ์ํ๋ค. ์์ ๋ฐฐ์น ๋ชจ๋ธ์ธ ์ค์นํ ์ ํ๋ฆฌ์ผ์ด์
์ด ํน์ ๋จธ์ ์ ํธ์คํธ์ ๋ฐ์ ํ๊ฒ ํตํฉ๋๋ ํจํค์ง์ธ ๊ฒ์ ๋นํด, ์ปจํ
์ด๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ฐ์ฑ(flexible)๊ณผ ๊ฐ์ฉ์ฑ(available)์ด ํจ์ฌ ๋๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋ ์ด๋ฌํ ์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์ด๋๋ฅผ ํด๋ฌ์คํฐ์ ๋ถ์ฐ์ํค๊ณ ์ค์ผ์ค๋งํ๋ ์ผ์ ๋์ฑ ํจ์จ์ ์ผ๋ก ์๋ํํ๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋ ์คํ์์ค ํ๋ซํผ์ด๋ฉฐ ์ด์ ์์ค์ ์์ ์ฑ(production-ready)์ ์ ๊ณตํ๋ค.
์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ ๋ ๊ฐ์ง ํํ์ ์์์ผ๋ก ๊ตฌ์ฑ๋๋ค.
์ปจํธ๋กค ํ๋ ์ธ ์ ํด๋ฌ์คํฐ๋ฅผ ์กฐ์จํ๋ค.๋
ธ๋ ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ๋ํ๋ ์์
์(worker)์ด๋ค.
์์ฝ: ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ Minikube ์ฟ ๋ฒ๋คํฐ์ค๋ ์ปดํจํฐ ํด๋ฌ์คํฐ์ ์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์ด๋์ ๋ฐฐ์น(์ค์ผ์ค๋ง) ๋ฐ ์คํ์ ์ค์ผ์คํธ๋ ์ด์
ํ๋ ์ด์ ์์ค์ ์คํ์์ค ํ๋ซํผ์ด๋ค.
ํด๋ฌ์คํฐ ๋ค์ด์ด๊ทธ๋จ ์ปจํธ๋กค ํ๋ ์ธ์ ํด๋ฌ์คํฐ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํ๋ค. ์ปจํธ๋กค ํ๋ ์ธ์ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ผ์ค๋งํ๊ฑฐ๋, ์ ํ๋ฆฌ์ผ์ด์
์ ํญ์์ฑ์ ์ ์งํ๊ฑฐ๋, ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ผ์ผ๋งํ๊ณ , ์๋ก์ด ๋ณ๊ฒฝ์ฌํญ์ ์์๋๋ก ๋ฐ์(rolling out)ํ๋ ์ผ๊ณผ ๊ฐ์ ํด๋ฌ์คํฐ ๋ด ๋ชจ๋ ํ๋์ ์กฐ์จํ๋ค.
๋
ธ๋๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด ์์ปค ๋จธ์ ์ผ๋ก ๋์ํ๋ VM ๋๋ ๋ฌผ๋ฆฌ์ ์ธ ์ปดํจํฐ๋ค. ๊ฐ ๋
ธ๋๋ ๋
ธ๋๋ฅผ ๊ด๋ฆฌํ๊ณ ์ฟ ๋ฒ๋คํฐ์ค ์ปจํธ๋กค ํ๋ ์ธ๊ณผ ํต์ ํ๋ Kubelet์ด๋ผ๋ ์์ด์ ํธ๋ฅผ ๊ฐ๋๋ค. ๋
ธ๋๋ ์ปจํ
์ด๋ ์ด์์ ๋ด๋นํ๋ containerd ๋๋ ๋์ปค์ ๊ฐ์ ํด๋ ๊ฐ๋๋ค. ์ด์ ํธ๋ํฝ์ ์ฒ๋ฆฌํ๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ ์ต์ ์ธ ๋์ ๋
ธ๋๋ฅผ ๊ฐ์ ธ์ผ ํ๋๋ฐ, ์ด๋ ํ ๋
ธ๋๊ฐ ๋ค์ด๋๋ฉด etcd ๋ฉค๋ฒ์ ์ปจํธ๋กค ํ๋ ์ธ ์ธ์คํด์ค๊ฐ ์ฌ๋ผ์ ธ ์ค๋ณต์ฑ(redundancy)์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ปจํธ๋กค ํ๋ ์ธ ๋
ธ๋๋ฅผ ์ถ๊ฐํ์ฌ ์ด๋ฌํ ์ํ์ ์ค์ผ ์ ์๋ค.
์ปจํธ๋กค ํ๋ ์ธ์ ์คํ ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ ํธ์คํ
ํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๋
ธ๋์ ํด๋ฌ์คํฐ๋ฅผ ๊ด๋ฆฌํ๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ ์ฟ ๋ฒ๋คํฐ์ค์ ๋ฐฐํฌํ๊ธฐ ์ํด์๋, ์ปจํธ๋กค ํ๋ ์ธ์ ์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์ด๋์ ๊ตฌ๋์ ์ง์ํ๋ฉด ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ปจํธ๋กค ํ๋ ์ธ์ ์ปจํ
์ด๋๋ฅผ ํด๋ฌ์คํฐ์ ์ด๋ ๋
ธ๋์ ๊ตฌ๋์ํฌ์ง ์ค์ผ์คํ๋ค. ๋
ธ๋๋ ์ปจํธ๋กค ํ๋ ์ธ์ด ์ ๊ณตํ๋ ์ฟ ๋ฒ๋คํฐ์ค API ๋ฅผ ํตํด์ ์ปจํธ๋กค ํ๋ ์ธ๊ณผ ํต์ ํ๋ค. ์ต์ข
์ฌ์ฉ์๋ ์ฟ ๋ฒ๋คํฐ์ค API๋ฅผ ์ฌ์ฉํด์ ํด๋ฌ์คํฐ์ ์ง์ ์ํธ์์ฉ(interact)ํ ์ ์๋ค.
์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ ๋ฌผ๋ฆฌ ๋ฐ ๊ฐ์ ๋จธ์ ๋ชจ๋์ ์ค์น๋ ์ ์๋ค. ์ฟ ๋ฒ๋คํฐ์ค ๊ฐ๋ฐ์ ์์ํ๋ ค๋ฉด Minikube๋ฅผ ์ฌ์ฉํ ์ ์๋ค. Minikube๋ ๊ฐ๋ฒผ์ด ์ฟ ๋ฒ๋คํฐ์ค ๊ตฌํ์ฒด์ด๋ฉฐ, ๋ก์ปฌ ๋จธ์ ์ VM์ ๋ง๋ค๊ณ ํ๋์ ๋
ธ๋๋ก ๊ตฌ์ฑ๋ ๊ฐ๋จํ ํด๋ฌ์คํฐ๋ฅผ ์์ฑํ๋ค. Minikube๋ ๋ฆฌ๋
์ค, ๋งฅ, ๊ทธ๋ฆฌ๊ณ ์๋์ฐ ์์คํ
์์ ๊ตฌ๋์ด ๊ฐ๋ฅํ๋ค. Minikube CLI๋ ํด๋ฌ์คํฐ์ ๋ํด ์์, ์ค์ง, ์ํ ์กฐํ ๋ฐ ์ญ์ ๋ฑ์ ๊ธฐ๋ณธ์ ์ธ ๋ถํธ์คํธ๋ํ(bootstrapping) ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ํ์ง๋ง, ๋ณธ ํํ ๋ฆฌ์ผ์์๋ Minikube๊ฐ ๋ฏธ๋ฆฌ ์ค์น๋ ์ฑ๋ก ์ ๊ณต๋๋ ์จ๋ผ์ธ ํฐ๋ฏธ๋์ ์ฌ์ฉํ ๊ฒ์ด๋ค.
์ฟ ๋ฒ๋คํฐ์ค๊ฐ ๋ฌด์์ธ์ง ์์๋ดค์ผ๋, ์ด์ ์จ๋ผ์ธ ํํ ๋ฆฌ์ผ๋ก ์ด๋ํด์ ์ฐ๋ฆฌ์ ์ฒซ ๋ฒ์งธ ํด๋ฌ์คํฐ๋ฅผ ์์ํด๋ณด์!
2.1.2 - ๋ํํ ํํ ๋ฆฌ์ผ - ํด๋ฌ์คํฐ ์์ฑํ๊ธฐ ํ๋ฉด์ด ๋๋ฌด ์ข์ ํฐ๋ฏธ๋๊ณผ ์ํธ์์ฉํ ์ ์์ต๋๋ค. ๋ฐ์คํฌํฑ/ํ๋ธ๋ฆฟ์ ์ฌ์ฉํด์ฃผ์ธ์.
2.2 - ์ฑ ๋ฐฐํฌํ๊ธฐ 2.2.1 - kubectl์ ์ฌ์ฉํด์ ๋ํ๋ก์ด๋จผํธ ์์ฑํ๊ธฐ ๋ชฉํ ์ ํ๋ฆฌ์ผ์ด์
๋ํ๋ก์ด๋จผํธ(Deployment)์ ๋ํด ๋ฐฐ์ด๋ค. kubectl๋ก ์ฒซ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฟ ๋ฒ๋คํฐ์ค์ ๋ฐฐํฌํ๋ค. ์ฟ ๋ฒ๋คํฐ์ค ๋ํ๋ก์ด๋จผํธ ์ผ๋จ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ๋์ํค๋ฉด, ๊ทธ ์์ ์ปจํ
์ด๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ์ ์๋ค.
๊ทธ๋ฌ๊ธฐ ์ํด์, ์ฟ ๋ฒ๋คํฐ์ค ๋ํ๋ก์ด๋จผํธ ์ค์ ์ ๋ง๋ค์ด์ผ ํ๋ค. ๋ํ๋ก์ด๋จผํธ๋ ์ฟ ๋ฒ๋คํฐ์ค๊ฐ
์ ํ๋ฆฌ์ผ์ด์
์ ์ธ์คํด์ค๋ฅผ ์ด๋ป๊ฒ ์์ฑํ๊ณ ์
๋ฐ์ดํธํด์ผ ํ๋์ง๋ฅผ ์ง์ํ๋ค. ๋ํ๋ก์ด๋จผํธ๊ฐ ๋ง๋ค์ด์ง๋ฉด,
์ฟ ๋ฒ๋คํฐ์ค ์ปจํธ๋กค ํ๋ ์ธ์ด ํด๋น ๋ํ๋ก์ด๋จผํธ์ ํฌํจ๋ ์ ํ๋ฆฌ์ผ์ด์
์ธ์คํด์ค๊ฐ ํด๋ฌ์คํฐ์ ๊ฐ๋ณ ๋
ธ๋์์ ์คํ๋๋๋ก ์ค์ผ์คํ๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ธ์คํด์ค๊ฐ ์์ฑ๋๋ฉด, ์ฟ ๋ฒ๋คํฐ์ค ๋ํ๋ก์ด๋จผํธ ์ปจํธ๋กค๋ฌ๋ ์ง์์ ์ผ๋ก ์ด๋ค ์ธ์คํด์ค๋ฅผ
๋ชจ๋ํฐ๋งํ๋ค. ์ธ์คํด์ค๋ฅผ ๊ตฌ๋ ์ค์ธ ๋
ธ๋๊ฐ ๋ค์ด๋๊ฑฐ๋ ์ญ์ ๋๋ฉด, ๋ํ๋ก์ด๋จผํธ ์ปจํธ๋กค๋ฌ๊ฐ ์ธ์คํด์ค๋ฅผ
ํด๋ฌ์คํฐ ๋ด๋ถ์ ๋ค๋ฅธ ๋
ธ๋์ ์ธ์คํด์ค๋ก ๊ต์ฒด์์ผ์ค๋ค.์ด๋ ๊ฒ ๋จธ์ ์ ์ฅ์ ๋ ์ ๋น์ ๋์ํ ์ ์๋ ์๋ ๋ณต๊ตฌ(self-healing) ๋ฉ์ปค๋์ฆ์
์ ๊ณตํ๋ค.
์ค์ผ์คํธ๋ ์ด์
๊ธฐ๋ฅ์ด ์๋ ํ๊ฒฝ์์๋, ์ค์น ์คํฌ๋ฆฝํธ๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์์ํ๋๋ฐ ์ข
์ข
์ฌ์ฉ๋๊ณค
ํ์ง๋ง, ๋จธ์ ์ ์ฅ์ ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ๋ณต๊ตฌ๋ฅผ ํด์ฃผ์ง๋ ์์๋ค. ์ฟ ๋ฒ๋คํฐ์ค ๋ํ๋ก์ด๋จผํธ๋ ์ ํ๋ฆฌ์ผ์ด์
์ธ์คํด์ค๋ฅผ ์์ฑํด์ฃผ๊ณ ์ฌ๋ฌ ๋
ธ๋์ ๊ฑธ์ณ์ ์ง์์ ์ผ๋ก ์ธ์คํด์ค๊ฐ ๊ตฌ๋๋๋๋ก ํ๋ ๋ ๊ฐ์ง๋ฅผ ๋ชจ๋
ํ๊ธฐ ๋๋ฌธ์ ์ ํ๋ฆฌ์ผ์ด์
๊ด๋ฆฌ๋ฅผ ์ํ ์ ๊ทผ๋ฒ์์ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด๋ฅผ ๊ฐ์ ธ๋ค์ค๋ค.
์์ฝ: ๋ํ๋ก์ด๋จผํธ Kubectl ๋ํ๋ก์ด๋จผํธ๋ ์ ํ๋ฆฌ์ผ์ด์
์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์
๋ฐ์ดํธํ๋ ์ญํ ์ ๋ด๋นํ๋ค.
์ฟ ๋ฒ๋คํฐ์ค์ ์ฒซ ๋ฒ์งธ ์ ํ๋ฆฌ์ผ์ด์
๋ฐฐํฌํ๊ธฐ Kubectl ์ด๋ผ๋ ์ฟ ๋ฒ๋คํฐ์ค CLI๋ฅผ ํตํด ๋ํ๋ก์ด๋จผํธ๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ ์ ์๋ค.
Kubectl์ ํด๋ฌ์คํฐ์ ์ํธ ์์ฉํ๊ธฐ ์ํด ์ฟ ๋ฒ๋คํฐ์ค API๋ฅผ ์ฌ์ฉํ๋ค. ์ด ๋ชจ๋์์๋, ์ฟ ๋ฒ๋คํฐ์ค
ํด๋ฌ์คํฐ ์์ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ๋์ํค๋ ๋ํ๋ก์ด๋จผํธ๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ํ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ Kubectl
๋ช
๋ น์ด๋ฅผ ๋ฐฐ์ฐ๊ฒ ๋๋ค.
๋ํ๋ก์ด๋จผํธ๋ฅผ ์์ฑํ ๋, ์ ํ๋ฆฌ์ผ์ด์
์ ๋ํ ์ปจํ
์ด๋ ์ด๋ฏธ์ง์ ๊ตฌ๋์ํค๊ณ ์ ํ๋ ๋ณต์ ์๋ฅผ ์ง์ ํด์ผ
ํ๋ค. ๋ํ๋ก์ด๋จผํธ๋ฅผ ์
๋ฐ์ดํธํด์ ์ด๋ฐ ์ ๋ณด๋ฅผ ๋์ค์ ๋ณ๊ฒฝํ ์ ์๋ค. ๋ชจ๋
5 ์ 6 ์ ๋ถํธ์บ ํ์์ ์ด๋ป๊ฒ
์ค์ผ์ผํ๊ณ ์
๋ฐ์ดํธํ๋์ง์ ๋ํด ๋ค๋ฃฌ๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ด ์ฟ ๋ฒ๋คํฐ์ค ์์ ๋ฐฐํฌ๋๋ ค๋ฉด ์ง์๋๋ ์ปจํ
์ด๋ ํ์ ์ค ํ๋๋ก ํจํค์ง ๋์ด์ผํ๋ค.
์ฒซ ๋ฒ์งธ ๋ํ๋ก์ด๋จผํธ๋ก, NGINX๋ฅผ ์ฌ์ฉํด ๋ชจ๋ ์์ฒญ์ ์์ฝ(echo)ํ๋ ๋์ปค ์ปจํ
์ด๋๋ก ํจํค์งํ hello-node ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉํด๋ณด์. (์์ง hello-node ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฑํ๊ณ ์ปจํ
์ด๋๋ฅผ ํ์ฉํด์ ๋ฐฐํฌํด๋ณด์ง ์์๋ค๋ฉด, Hello Minikube ํํ ๋ฆฌ์ผ ์ ์ง์๋ฅผ ๋ฐ๋ฅธ๋ค.)
์ด์ ๋ํ๋ก์ด๋จผํธ๋ฅผ ์ดํดํ์ผ๋, ์จ๋ผ์ธ ํํ ๋ฆฌ์ผ์ ํตํด ์ฐ๋ฆฌ์ ์ฒซ ๋ฒ์งธ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํด๋ณด์!
2.2.2 - ๋ํํ ํํ ๋ฆฌ์ผ - ์ฑ ๋ฐฐํฌํ๊ธฐ ํฐ๋ฏธ๋๋ก ์ํธ ์์ฉํ๊ธฐ ์ํด์, ๋ฐ์คํฌํ/ํ๋ธ๋ฆฟ ๋ฒ์ ์ ์ฌ์ฉํด์ฃผ์ธ์
2.3 - ์ฑ ์กฐ์ฌํ๊ธฐ 2.3.1 - ํ๋์ ๋
ธ๋ ๋ณด๊ธฐ ๋ชฉํ ์ฟ ๋ฒ๋คํฐ์ค ํ๋์ ๋ํด ๋ฐฐ์ด๋ค. ์ฟ ๋ฒ๋คํฐ์ค ๋
ธ๋์ ๋ํด ๋ฐฐ์ด๋ค. ๋ฐฐํฌ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค. ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ๋ชจ๋ 2 ์์ ๋ฐฐํฌ๋ฅผ ์์ฑํ์ ๋, ์ฟ ๋ฒ๋คํฐ์ค๋ ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์
์ธ์คํด์ค์ ํ๋ ๋ฅผ ์์ฑํ๋ค. ํ๋๋ ํ๋ ๋๋ ๊ทธ ์ด์์ ์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์ด๋ (๋์ปค์ ๊ฐ์)๋ค์ ๊ทธ๋ฃน์ ๋ํ๋ด๋ ์ฟ ๋ฒ๋คํฐ์ค์ ์ถ์์ ๊ฐ๋
์ผ๋ก ์ผ๋ถ๋ ์ปจํ
์ด๋์ ๋ํ ์์์ ๊ณต์ ํ๋ค. ๊ทธ ์์์ ๋ค์์ ํฌํจํ๋ค:
๋ณผ๋ฅจ๊ณผ ๊ฐ์, ๊ณต์ ์คํ ๋ฆฌ์ง ํด๋ฌ์คํฐ IP ์ฃผ์์ ๊ฐ์, ๋คํธ์ํน ์ปจํ
์ด๋ ์ด๋ฏธ์ง ๋ฒ์ ๋๋ ์ฌ์ฉํ ํน์ ํฌํธ์ ๊ฐ์ด, ๊ฐ ์ปจํ
์ด๋๊ฐ ๋์ํ๋ ๋ฐฉ์์ ๋ํ ์ ๋ณด ํ๋๋ ํน์ ํ "๋ก์ปฌํธ์คํธ" ์ ํ๋ฆฌ์ผ์ด์
๋ชจํ์ ๋ง๋ค์ด. ์๋์ ์ผ๋ก ๋ฐ์ ํ๊ฒ ๊ฒฐํฉ๋์ด์ง ์์ดํ ์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์ด๋๋ค์ ์์ฉํ ์ ์๋ค. ๊ฐ๋ น, ํ๋๋ Node.js ์ฑ๊ณผ ๋๋ถ์ด Node.js ์น์๋ฒ์ ์ํด ๋ฐํ๋๋ ๋ฐ์ดํฐ๋ฅผ ๊ณต๊ธํ๋ ์์ดํ ์ปจํ
์ด๋๋ฅผ ํจ๊ป ์์ฉํ ์ ์๋ค. ํ๋ ๋ด ์ปจํ
์ด๋๋ IP ์ฃผ์, ๊ทธ๋ฆฌ๊ณ ํฌํธ ์คํ์ด์ค๋ฅผ ๊ณต์ ํ๊ณ ํญ์ ํจ๊ป ์์นํ๊ณ ํจ๊ป ์ค์ผ์ฅด๋ง ๋๊ณ ๋์ผ ๋
ธ๋ ์์ ์ปจํ
์คํธ๋ฅผ ๊ณต์ ํ๋ฉด์ ๋์ํ๋ค.
ํ๋๋ ์ฟ ๋ฒ๋คํฐ์ค ํ๋ซํผ ์์์ ์ต์ ๋จ์๊ฐ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ฟ ๋ฒ๋คํฐ์ค์์ ๋ฐฐํฌ๋ฅผ ์์ฑํ ๋, ๊ทธ ๋ฐฐํฌ๋ ์ปจํ
์ด๋ ๋ด๋ถ์์ ์ปจํ
์ด๋์ ํจ๊ป ํ๋๋ฅผ ์์ฑํ๋ค. ๊ฐ ํ๋๋ ์ค์ผ์ฅด ๋์ด์ง ๋
ธ๋์๊ฒ ๋ฌถ์ฌ์ง๊ฒ ๋๋ค. ๊ทธ๋ฆฌ๊ณ (์ฌ๊ตฌ๋ ์ ์ฑ
์ ๋ฐ๋ผ) ์๋ฉธ๋๊ฑฐ๋ ์ญ์ ๋๊ธฐ ์ ๊น์ง ๊ทธ ๋
ธ๋์ ์ ์ง๋๋ค. ๋
ธ๋์ ์คํจ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, ํด๋ฌ์คํฐ ๋ด์ ๊ฐ์ฉํ ๋ค๋ฅธ ๋
ธ๋๋ค์ ๋์์ผ๋ก ์ค์ผ์ฅด๋์ด์ง๋ค.
์์ฝ: ํ๋ ๋
ธ๋ Kubectl ์ฃผ์ ๋ช
๋ น์ด ํ๋๋ ํ๋ ๋๋ ๊ทธ ์ด์์ ์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์ด๋ (๋์ปค์ ๊ฐ์)๋ค์ ๊ทธ๋ฃน์ด๊ณ ๊ณต์ ์คํ ๋ฆฌ์ง (๋ณผ๋ฅจ), IP ์ฃผ์ ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ๋์์ํค๋ ๋ฐฉ์์ ๋ํ ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์๋ค.
๋
ธ๋ ํ๋๋ ์ธ์ ๋ ๋
ธ๋ ์์์ ๋์ํ๋ค. ๋
ธ๋๋ ์ฟ ๋ฒ๋คํฐ์ค์์ ์์ปค ๋จธ์ ์ ๋งํ๋ฉฐ ํด๋ฌ์คํฐ์ ๋ฐ๋ผ ๊ฐ์ ๋๋ ๋ฌผ๋ฆฌ ๋จธ์ ์ผ ์ ์๋ค. ๊ฐ ๋
ธ๋๋ ์ปจํธ๋กค ํ๋ ์ธ์ ์ํด ๊ด๋ฆฌ๋๋ค. ํ๋์ ๋
ธ๋๋ ์ฌ๋ฌ ๊ฐ์ ํ๋๋ฅผ ๊ฐ์ง ์ ์๊ณ , ์ฟ ๋ฒ๋คํฐ์ค ์ปจํธ๋กค ํ๋ ์ธ์ ํด๋ฌ์คํฐ ๋ด ๋
ธ๋๋ฅผ ํตํด์ ํ๋์ ๋ํ ์ค์ผ์ฅด๋ง์ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ค. ์ปจํธ๋กค ํ๋ ์ธ์ ์๋ ์ค์ผ์ค๋ง์ ๊ฐ ๋
ธ๋์ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฆฌ์์ค๋ฅผ ๋ชจ๋ ๊ณ ๋ คํ๋ค.
๋ชจ๋ ์ฟ ๋ฒ๋คํฐ์ค ๋
ธ๋๋ ์ต์ํ ๋ค์๊ณผ ๊ฐ์ด ๋์ํ๋ค.
Kubelet์, ์ฟ ๋ฒ๋คํฐ์ค ์ปจํธ๋กค ํ๋ ์ธ๊ณผ ๋
ธ๋ ๊ฐ ํต์ ์ ์ฑ
์์ง๋ ํ๋ก์ธ์ค์ด๋ฉฐ, ํ๋์ ๋จธ์ ์์์ ๋์ํ๋ ํ๋์ ์ปจํ
์ด๋๋ฅผ ๊ด๋ฆฌํ๋ค. ์ปจํ
์ด๋ ๋ฐํ์(๋์ปค์ ๊ฐ์)์ ๋ ์ง์คํธ๋ฆฌ์์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ ๋ฌถ์ฌ ์๋ ๊ฒ์ ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ๋์์ํค๋ ์ฑ
์์ ๋งก๋๋ค. ๋ง์ฝ ์ปจํ
์ด๋๋ค์ด ๋ฐ์ ํ๊ฒ ๊ฒฐํฉ๋์ด ์๊ณ ๋์คํฌ์ ๊ฐ์ ์์์ ๊ณต์ ํด์ผ ํ๋ค๋ฉด ์ค์ง ํ๋์ ๋จ์ผ ํ๋์ ํจ๊ป ์ค์ผ์ฅด๋์ด์ ธ์ผ ํ๋ค.
kubectl๋ก ๋ฌธ์ ํด๊ฒฐํ๊ธฐ ๋ชจ๋ 2 ์์, Kubectl ์ปค๋งจ๋-๋ผ์ธ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ค. ๋ฐฐํฌ๋ ์ ํ๋ฆฌ์ผ์ด์
๊ณผ ๊ทธ ํ๊ฒฝ์ ๋ํ ์ ๋ณด๋ฅผ ์ป๊ธฐ ์ํด ๋ชจ๋3์์๋ ๊ณ์ ๊ทธ๊ฒ์ ์ฌ์ฉํ ๊ฒ์ด๋ค. ๊ฐ์ฅ ๋ณดํธ์ ์ธ ์ด์ฉ์
๋ฌด๋ ๋ค์ kubectl ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์ฌ ์ฒ๋ฆฌํ ์ ์๋ค:
kubectl get - ์์์ ๋์ดํ๋คkubectl describe - ์์์ ๋ํด ์์ธํ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ค๋ค.kubectl logs - ํ๋ ๋ด ์ปจํ
์ด๋์ ๋ก๊ทธ๋ค์ ์ถ๋ ฅํ๋คkubectl exec - ํ๋ ๋ด ์ปจํ
์ด๋์ ๋ํ ๋ช
๋ น์ ์คํํ๋ค.์ธ์ ์ ํ๋ฆฌ์ผ์ด์
์ด ๋ฐฐํฌ๋์์ผ๋ฉฐ, ํ์ฌ ์ํ๊ฐ ์ด๋ ํ์ง, ๊ทธ๊ฒ์ ๊ตฌ์ฑ์ ์ด๋ ํ์ง ๋ฑ์ ๋ณด๊ธฐ ์ํด ์ด๋ฌํ ๋ช
๋ น์ ์ด์ฉํ ์ ์๋ค.
์ด์ ํด๋ฌ์คํฐ ์ปดํฌ๋ํธ์ ์ปค๋งจ๋ ๋ผ์ธ์ ๋ํด ์์ ๋ณด์์ผ๋, ์ ํ๋ฆฌ์ผ์ด์
์ ์กฐ์ฌํด ๋ณด์.
๋
ธ๋๋ ์ฟ ๋ฒ๋คํฐ์ค์ ์์ด์ ์์ปค ๋จธ์ ์ด๋ฉฐ ํด๋ฌ์คํฐ์ ๋ฐ๋ผ VM ๋๋ ๋ฌผ๋ฆฌ ๋จธ์ ์ด ๋ ์ ์๋ค. ์ฌ๋ฌ ๊ฐ์ ํ๋๋ ํ๋์ ๋
ธ๋ ์์์ ๋์ํ ์ ์๋ค.
2.3.2 - ๋ํํ ํํ ๋ฆฌ์ผ - ์ฑ ์กฐ์ฌํ๊ธฐ ํฐ๋ฏธ๋๊ณผ ์ํธ์์ฉํ๊ธฐ ์ํด, ๋ฐ์คํฌํ/ํ๋ธ๋ฆฟ ๋ฒ์ ์ ์ด์ฉํ๋ค.
2.4 - ์ฑ ์ธ๋ถ๋ก ๋
ธ์ถํ๊ธฐ 2.4.1 - ์ฑ ๋
ธ์ถ์ ์ํด ์๋น์ค ์ด์ฉํ๊ธฐ ๋ชฉํ ์ฟ ๋ฒ๋คํฐ์ค์ ์๋น์ค์ ๋ํด ๋ฐฐ์ด๋ค. ๋ ์ด๋ธ๊ณผ ๋ ์ด๋ธ์
๋ํฐ ์ค๋ธ์ ํธ๊ฐ ์ด๋ป๊ฒ ์๋น์ค์ ์ฐ๊ด๋๋์ง ์ดํดํ๋ค. ์๋น์ค๋ฅผ ์ด์ฉํ์ฌ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ์ธ๋ถ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ๋
ธ์ถํ๋ค. ์ฟ ๋ฒ๋คํฐ์ค ์๋น์ค๋ค์ ๋ํ ๊ฐ์ ์ฟ ๋ฒ๋คํฐ์ค ํ๋๋ค ์ ์ธ์ ๊ฐ๋ ์ฃฝ๊ฒ๋๋ค. ํ๋๋ค์ ์๋ช
์ฃผ๊ธฐ ๋ฅผ ๊ฐ๋๋ค. ์์ปค ๋
ธ๋๊ฐ ์ฃฝ์ผ๋ฉด, ๋
ธ๋ ์์์ ๋์ํ๋ ํ๋๋ค ๋ํ ์ข
๋ฃ๋๋ค. ๋ ํ๋ฆฌ์นด์
(ReplicaSet) ์ ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์
์ด ์ง์์ ์ผ๋ก ๋์ํ ์ ์๋๋ก ์๋ก์ด ํ๋๋ค์ ์์ฑ์ ํตํด ๋์ ์ผ๋ก ํด๋ฌ์คํฐ๋ฅผ ๋ฏธ๋ฆฌ ์ง์ ํด ๋ ์ํ๋ก ๋๋๋ ค ์ค ์๋ ์๋ค. ๋ ๋ค๋ฅธ ์์๋ก์, 3๊ฐ์ ๋ณต์ ๋ณธ์ ๊ฐ๋ ์ด๋ฏธ์ง ์ฒ๋ฆฌ์ฉ ๋ฐฑ์๋๋ฅผ ๊ณ ๋ คํด ๋ณด์. ๊ทธ ๋ณต์ ๋ณธ๋ค์ ๊ต์ฒด ๊ฐ๋ฅํ ์ํ์ด๋ค. ๊ทธ๋์ ํ๋ก ํธ์๋ ์์คํ
์ ํ๋์ ํ๋๊ฐ ์๋ฉธ๋์ด ์ฌ์์ฑ์ด ๋๋๋ผ๋, ๋ฐฑ์๋ ๋ณต์ ๋ณธ๋ค์ ์ํ ์ํฅ์ ๋ฐ์์๋ ์๋๋ค. ์ฆ, ๋์ผ ๋
ธ๋ ์์ ํ๋๋ค์ด๋ผ ํ ์ง๋ผ๋, ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด ๊ฐ ํ๋๋ ์ ์ผํ IP ์ฃผ์๋ฅผ ๊ฐ์ง๋ฉฐ, ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์
๋ค์ด ์ง์์ ์ผ๋ก ๊ธฐ๋ฅํ ์ ์๋๋ก ํ๋๋ค ์์์ ๋ฐ์ํ๋ ๋ณํ์ ๋ํด ์๋์ผ๋ก ์กฐ์ ํด ์ค ๋ฐฉ๋ฒ์ด ์์ด์ผ ํ๋ค.
์ฟ ๋ฒ๋คํฐ์ค์์ ์๋น์ค๋ ํ๋์ ๋
ผ๋ฆฌ์ ์ธ ํ๋ ์
๊ณผ ๊ทธ ํ๋๋ค์ ์ ๊ทผํ ์ ์๋ ์ ์ฑ
์ ์ ์ํ๋ ์ถ์์ ๊ฐ๋
์ด๋ค. ์๋น์ค๋ ์ข
์์ ์ธ ํ๋๋ค ์ฌ์ด๋ฅผ ๋์จํ๊ฒ ๊ฒฐํฉ๋๋๋ก ํด์ค๋ค. ์๋น์ค๋ ๋ชจ๋ ์ฟ ๋ฒ๋คํฐ์ค ์ค๋ธ์ ํธ๋ค๊ณผ ๊ฐ์ด YAML (๋ณด๋ค ์ ํธํ๋) ๋๋ JSON์ ์ด์ฉํ์ฌ ์ ์๋๋ค. ์๋น์ค๊ฐ ๋์์ผ๋ก ํ๋ ํ๋ ์
์ ๋ณดํต LabelSelector ์ ์ํด ๊ฒฐ์ ๋๋ค (์ฌ๋ฌ๋ถ์ด ์ ์คํ์ selector
๊ฐ ํฌํจ๋์ง ์์ ์๋น์ค๋ฅผ ํ์๋ก ํ๊ฒ ๋ ์๋ ์๋์ง์ ๋ํด ์๋์์ ํ์ธํด ๋ณด์).
๋น๋ก ๊ฐ ํ๋๋ค์ด ๊ณ ์ ์ IP๋ฅผ ๊ฐ๊ณ ์๊ธฐ๋ ํ์ง๋ง, ๊ทธ IP๋ค์ ์๋น์ค์ ๋์์์ด ํด๋ฌ์คํฐ ์ธ๋ถ๋ก ๋
ธ์ถ๋์ด์ง ์ ์๋ค. ์๋น์ค๋ค์ ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์
๋ค์๊ฒ ํธ๋ํฝ์ด ์ค๋ฆด ์ ์๋๋ก ํ์ฉํด์ค๋ค. ์๋น์ค๋ค์ ServiceSpec์์ type
์ ์ง์ ํจ์ผ๋ก์จ ๋ค์ํ ๋ฐฉ์๋ค๋ก ๋
ธ์ถ์ํฌ ์ ์๋ค:
ClusterIP (๊ธฐ๋ณธ๊ฐ) - ํด๋ฌ์คํฐ ๋ด์์ ๋ด๋ถ IP ์ ๋ํด ์๋น์ค๋ฅผ ๋
ธ์ถํด์ค๋ค. ์ด ๋ฐฉ์์ ์ค์ง ํด๋ฌ์คํฐ ๋ด์์๋ง ์๋น์ค๊ฐ ์ ๊ทผ๋ ์ ์๋๋ก ํด์ค๋ค.NodePort - NAT๊ฐ ์ด์ฉ๋๋ ํด๋ฌ์คํฐ ๋ด์์ ๊ฐ๊ฐ ์ ํ๋ ๋
ธ๋๋ค์ ๋์ผํ ํฌํธ์ ์๋น์ค๋ฅผ ๋
ธ์ถ์์ผ์ค๋ค. <NodeIP>:<NodePort>
๋ฅผ ์ด์ฉํ์ฌ ํด๋ฌ์คํฐ ์ธ๋ถ๋ก๋ถํฐ ์๋น์ค๊ฐ ์ ๊ทผํ ์ ์๋๋ก ํด์ค๋ค. ClusterIP์ ์์ ์งํฉ์ด๋ค.LoadBalancer - (์ง์ ๊ฐ๋ฅํ ๊ฒฝ์ฐ) ๊ธฐ์กด ํด๋ผ์ฐ๋์์ ์ธ๋ถ์ฉ ๋ก๋๋ฐธ๋ฐ์๋ฅผ ์์ฑํ๊ณ ์๋น์ค์ ๊ณ ์ ๋ ๊ณต์ธ IP๋ฅผ ํ ๋นํด์ค๋ค. NodePort์ ์์ ์งํฉ์ด๋ค.ExternalName - CNAME
๋ ์ฝ๋ ๋ฐ ๊ฐ์ ๋ฐํํจ์ผ๋ก์จ ์๋น์ค๋ฅผ externalName
ํ๋์ ๋ด์ฉ(์๋ฅผ ๋ค๋ฉด, foo.bar.example.com
)์ ๋งคํํ๋ค. ์ด๋ ํ ์ข
๋ฅ์ ํ๋ก์๋ ์ค์ ๋์ง ์๋๋ค. ์ด ๋ฐฉ์์ kube-dns
v1.7 ์ด์ ๋๋ CoreDNS ๋ฒ์ 0.0.8 ์ด์์ ํ์๋ก ํ๋ค.๋ค๋ฅธ ์๋น์ค ํ์
๋ค์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ ์์ค IP ์ด์ฉํ๊ธฐ ํํ ๋ฆฌ์ผ์์ ํ์ธ ๊ฐ๋ฅํ๋ค. ๋ํ ์๋น์ค๋ค๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ํ๊ธฐ ๋ ์ฐธ๊ณ ํด ๋ณด์.
๋ถ๊ฐ์ ์ผ๋ก, spec์ selector
๋ฅผ ์ ์ํ์ง ์๊ณ ๋ง์๋ฃ์ ์๋น์ค๋ค์ ๋ช ๊ฐ์ง ์ ์ฆ์ผ์ด์ค๋ค์ด ์์์ ์ฃผ์ํ์. selector
์์ด ์์ฑ๋ ์๋น์ค๋ ์์ํ๋ ์๋ํฌ์ธํธ ์ค๋ธ์ ํธ๋ค ๋ํ ์์ฑํ์ง ์๋๋ค. ์ด๋ก์จ ์ฌ์ฉ์๋ค๋ก ํ์ฌ๊ธ ํ๋์ ์๋น์ค๋ฅผ ํน์ ํ ์๋ํฌ์ธํธ์ ๋งคํ ์ํฌ์ ์๋๋ก ํด์ค๋ค. selector๋ฅผ ์๋ตํ๊ฒ ๋๋ ๋ ๋ค๋ฅธ ๊ฐ๋ฅ์ฑ์ ์ฌ๋ฌ๋ถ์ด type: ExternalName
์ ์ด์ฉํ๊ฒ ๋ค๊ณ ํ๊ณ ํ๊ฒ ์๋ํ๋ ๊ฒฝ์ฐ์ด๋ค.
์์ฝ ํ๋๋ค์ ์ธ๋ถ ํธ๋ํฝ์ ๋
ธ์ถํ๊ธฐ ์ฌ๋ฌ ํ๋์ ๊ฑธ์ณ์ ํธ๋ํฝ ๋ก๋๋ฐธ๋ฐ์ฑ ํ๊ธฐ ๋ ์ด๋ธ ์ฌ์ฉํ๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค ์๋น์ค๋ ๋
ผ๋ฆฌ์ ํ๋ ์
์ ์ ์ํ๊ณ ์ธ๋ถ ํธ๋ํฝ ๋
ธ์ถ, ๋ก๋๋ฐธ๋ฐ์ฑ ๊ทธ๋ฆฌ๊ณ ๊ทธ ํ๋๋ค์ ๋ํ ์๋น์ค ๋์ค์ปค๋ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ์ถ์ ๊ณ์ธต์ด๋ค.
์๋น์ค๋ ํ๋ ์
์ ๊ฑธ์ณ์ ํธ๋ํฝ์ ๋ผ์ฐํธํ๋ค. ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์
์ ์ํฅ์ ์ฃผ์ง ์์ผ๋ฉด์ ์ฟ ๋ฒ๋คํฐ์ค์์ ํ๋๋ค์ด ์ฃฝ๊ฒ๋ ํ๊ณ , ๋ณต์ ๊ฐ ๋๊ฒ๋ ํด์ฃผ๋ ์ถ์์ ๊ฐ๋
์ด๋ค. ์ข
์์ ์ธ ํ๋๋ค ์ฌ์ด์์์ ๋์ค์ปค๋ฒ๋ฆฌ์ ๋ผ์ฐํ
์ (ํ๋์ ์ ํ๋ฆฌ์ผ์ด์
์์ ํ๋กํธ์๋์ ๋ฐฑ์๋ ์ปดํฌ๋ํธ์ ๊ฐ์) ์ฟ ๋ฒ๋คํฐ์ค ์๋น์ค๋ค์ ์ํด ์ฒ๋ฆฌ๋๋ค.
์๋น์ค๋ ์ฟ ๋ฒ๋คํฐ์ค์ ๊ฐ์ฒด๋ค์ ๋ํด ๋
ผ๋ฆฌ ์ฐ์ฐ์ ํ์ฉํด์ฃผ๋ ๊ธฐ๋ณธ ๊ทธ๋ฃนํ ๋จ์์ธ, ๋ ์ด๋ธ๊ณผ ์
๋ ํฐ ๋ฅผ ์ด์ฉํ์ฌ ํ๋ ์
๊ณผ ๋งค์น์ํจ๋ค. ๋ ์ด๋ธ์ ์ค๋ธ์ ํธ๋ค์ ๋ถ์ฌ์ง ํค/๋ฐธ๋ฅ ์์ผ๋ก ๋ค์ํ ๋ฐฉ์์ผ๋ก ์ด์ฉ ๊ฐ๋ฅํ๋ค:
๊ฐ๋ฐ, ํ
์คํธ, ๊ทธ๋ฆฌ๊ณ ์์ฉํ๊ฒฝ์ ๋ํ ๊ฐ์ฒด๋ค์ ์ง์ ์๋ฒ ๋๋๋ ๋ฒ์ ํ๊ทธ๋ค ํ๊ทธ๋ค์ ์ด์ฉํ๋ ๊ฐ์ฒด๋ค์ ๋ํ ๋ถ๋ฅ ๋ ์ด๋ธ์ ์ค๋ธ์ ํธ์ ์์ฑ ์์ ๋๋ ์ดํ ์์ ์ ๋ถ์ฌ์ง ์ ์๋ค. ์ธ์ ๋ ์ง ์์ ์ด ๊ฐ๋ฅํ๋ค. ์ด์ ์๋น์ค๋ฅผ ์ด์ฉํ์ฌ ์ฐ๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋
ธ์ถ๋ ์์ผ๋ณด๊ณ ๋ ์ด๋ธ๋ ์ ์ฉํด ๋ณด์.
2.4.2 - ๋ํํ ํํ ๋ฆฌ์ผ - ์ฑ ๋
ธ์ถํ๊ธฐ ํฐ๋ฏธ๋๊ณผ ์ํธ์์ฉํ๊ธฐ ์ํด, ๋ฐ์คํฌํ/ํ๋ธ๋ฆฟ ๋ฒ์ ์ ์ด์ฉํ๋ค.
2.5 - ์ฑ ์ค์ผ์ผ๋งํ๊ธฐ 2.5.1 - ๋ณต์์ ์ฑ ์ธ์คํด์ค๋ฅผ ๊ตฌ๋ํ๊ธฐ ๋ชฉํ kubectl์ ์ฌ์ฉํด์ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ผ์ผํ๋ค. ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ผ์ผํ๊ธฐ ์ง๋ ๋ชจ๋์์ ๋ํ๋ก์ด๋จผํธ ๋ฅผ ๋ง๋ค๊ณ ,
์๋น์ค ๋ฅผ
ํตํด์ ๋ํ๋ก์ด๋จผํธ๋ฅผ ์ธ๋ถ์ ๋
ธ์ถ์์ผ ๋ดค๋ค. ํด๋น ๋ํ๋ก์ด๋จผํธ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ๋ํ๊ธฐ ์ํด ๋จ
ํ๋์ ํ๋๋ง์ ์์ฑํ์๋ค. ํธ๋ํฝ์ด ์ฆ๊ฐํ๋ฉด, ์ฌ์ฉ์ ์์ฒญ์ ๋ง์ถ์ด ์ ํ๋ฆฌ์ผ์ด์
์ ๊ท๋ชจ๋ฅผ
์กฐ์ ํ ํ์๊ฐ ์๋ค.
๋ํ๋ก์ด๋จผํธ์ ๋ณต์ ์๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์ค์ผ์ผ๋ง ์ด ์ํ๋๋ค
์์ฝ: ๋ํ๋ก์ด๋จผํธ ์ค์ผ์ผ๋งํ๊ธฐ kubectl create deployment ๋ช
๋ น์ --replicas ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํด์ ์ฒ์๋ถํฐ ๋ณต์์ ์ธ์คํด์ค๋ก ๊ตฌ๋๋๋
๋ํ๋ก์ด๋จผํธ๋ฅผ ๋ง๋ค ์๋ ์๋ค
๋ํ๋ก์ด๋จผํธ๋ฅผ ์ค์ผ์ผ ์์ํ๋ฉด ์ ๊ท ํ๋๊ฐ ์์ฑ๋์ด์ ๊ฐ์ฉํ ์์์ด ์๋ ๋
ธ๋์ ์ค์ผ์ค๋๋ค.
์ค์ผ์ผ๋ง ๊ธฐ๋ฅ์ ์๋ก ์๋ํ ์ํ(desired state)๊น์ง ํ๋์ ์๋ฅผ ๋๋ฆฐ๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋
ํ๋์ ์คํ ์ค์ผ์ผ๋ง
๋ ์ง์ํ์ง๋ง ๋ณธ ํํ ๋ฆฌ์ผ์์๋ ๋ค๋ฃจ์ง ์๋๋ค. 0๊น์ง ์ค์ผ์ผ๋งํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค. ์ด ๊ฒฝ์ฐ ํด๋น
๋ํ๋ก์ด๋จผํธ์ ๋ชจ๋ ํ๋๊ฐ ์ข
๋ฃ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ ์ธ์คํด์ค๋ฅผ ๋ณต์๋ก ๊ตฌ๋ํ๊ฒ ๋๋ฉด ํธ๋ํฝ์ ํด๋น ์ธ์คํด์ค ๋ชจ๋์ ๋ถ์ฐ์ํฌ ๋ฐฉ๋ฒ์ด
ํ์ํด์ง๋ค. ์๋น์ค๋ ๋
ธ์ถ๋ ๋ํ๋ก์ด๋จผํธ์ ๋ชจ๋ ํ๋์ ๋คํธ์ํฌ ํธ๋ํฝ์ ๋ถ์ฐ์์ผ์ค ํตํฉ๋
๋ก๋๋ฐธ๋ฐ์๋ฅผ ๊ฐ๋๋ค. ์๋น์ค๋ ์๋ํฌ์ธํธ๋ฅผ ์ด์ฉํด์ ๊ตฌ๋์ค์ธ ํ๋๋ฅผ ์ง์์ ์ผ๋ก ๋ชจ๋ํฐ๋งํจ์ผ๋ก์จ
๊ฐ์ฉํ ํ๋์๋ง ํธ๋ํฝ์ด ์ ๋ฌ๋๋๋ก ํด์ค๋ค.
๋ํ๋ก์ด๋จผํธ์ ๋ณต์ ์๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์ค์ผ์ผ๋ง์ด ์ํ๋๋ค.
์ผ๋จ ๋ณต์์ ์ ํ๋ฆฌ์ผ์ด์
์ ์ธ์คํด์ค๊ฐ ๊ตฌ๋ ์ค์ด๋ฉด, ๋ค์ดํ์ ์์ด ๋กค๋ง ์
๋ฐ์ดํธ๋ฅผ ํ ์ ์๋ค.
๋ค์ ๋ชจ๋์์ ์ด ๋ด์ฉ์ ๋ค๋ฃจ๋๋ก ํ๊ฒ ๋ค. ์ด์ ์จ๋ผ์ธ ํฐ๋ฏธ๋๋ก ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ผ์ผํด๋ณด์.
2.5.2 - ๋ํํ ํํ ๋ฆฌ์ผ - ์ฑ ์ค์ผ์ผ๋งํ๊ธฐ ํฐ๋ฏธ๋๋ก ์ํธ ์์ฉํ๊ธฐ ์ํด์, ๋ฐ์คํฌํ/ํ๋ธ๋ฆฟ ๋ฒ์ ์ ์ฌ์ฉํด์ฃผ์ธ์
2.6 - ์ฑ ์
๋ฐ์ดํธํ๊ธฐ 2.6.1 - ๋กค๋ง ์
๋ฐ์ดํธ ์ํํ๊ธฐ ๋ชฉํ kubectl์ ์ด์ฉํ์ฌ ๋กค๋ง ์
๋ฐ์ดํธ ์ํํ๊ธฐ ์ ํ๋ฆฌ์ผ์ด์
์
๋ฐ์ดํธํ๊ธฐ ์ฌ์ฉ์๋ค์ ์ ํ๋ฆฌ์ผ์ด์
์ด ํญ์ ๊ฐ์ฉํ ์ํ์ผ ๊ฒ์ด๋ผ ์ฌ๊ธฐ๊ณ ๊ฐ๋ฐ์๋ค์ ํ๋ฃจ์ ์ฌ๋ฌ๋ฒ์ฉ ์๋ก์ด ๋ฒ์ ์
๋ฐฐํฌํ๋๋ก ์๊ตฌ ๋ฐ๊ณ ์๋ค. ์ฟ ๋ฒ๋คํฐ์ค์์๋ ์ด๊ฒ์ ๋กค๋ง ์
๋ฐ์ดํธ๋ฅผ ํตํด ์ด๋ฃจ๊ณ ์๋ค. ๋กค๋ง ์
๋ฐ์ดํธ ๋ ํ๋ ์ธ์คํด์ค๋ฅผ ์ ์ง์ ์ผ๋ก ์๋ก์ด ๊ฒ์ผ๋ก ์
๋ฐ์ดํธํ์ฌ ๋ํ๋ก์ด๋จผํธ ์
๋ฐ์ดํธ๊ฐ ์๋น์ค ์ค๋จ ์์ด ์ด๋ฃจ์ด์ง ์ ์๋๋ก ํด์ค๋ค.
์๋ก์ด ํ๋๋ ๊ฐ์ฉํ ์์์ ๋ณด์ ํ ๋
ธ๋๋ก ์ค์ผ์ค๋ ๊ฒ์ด๋ค.
์ด์ ๋ชจ๋์์ ์ฌ๋ฌ ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๋์์ํค๋๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ผ์ผํ๋ค. ์ด๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ์ฉ์ฑ์ ์ํฅ์ ๋ฏธ์น์ง ์์ผ๋ฉด์
์
๋ฐ์ดํธ๋ฅผ ์ํํ๋ ๊ฒ์ ๋ํ ์๊ตฌ์ด๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก, ์
๋ฐ์ดํธ๊ฐ ์ด๋ฃจ์ด์ง๋ ๋์ ์ด์ฉ ๋ถ๊ฐํ ํ๋์ ์ต๋ ๊ฐ์์ ์์ฑ ๊ฐ๋ฅํ ์๋ก์ด ํ๋์ ์ต๋ ๊ฐ์๋ ํ๋๋ค.
๋ ์ต์
์ (ํ๋์ ๋ํ) ๊ฐ์ ๋๋ ๋ฐฑ๋ถ์จ๋ก ๊ตฌ์ฑ๋ ์ ์๋ค.
์ฟ ๋ฒ๋คํฐ์ค์์, ์
๋ฐ์ดํธ๋ ๋ฒ์ ์ผ๋ก ๊ด๋ฆฌ๋๊ณ ์ด๋ ํ ๋ํ๋ก์ด๋จผํธ ์
๋ฐ์ดํธ๋ผ๋ ์ด์ ์ (์์ ์ ์ธ) ๋ฒ์ ์ผ๋ก ์๋ณต์ด ๊ฐ๋ฅํ๋ค.
๋กค๋ง ์
๋ฐ์ดํธ๋ ํ๋ ์ธ์คํด์ค๋ฅผ ์ ์ง์ ์ผ๋ก ์๋ก์ด ๊ฒ์ผ๋ก ์
๋ฐ์ดํธํ์ฌ ๋ํ๋ก์ด๋จผํธ ์
๋ฐ์ดํธ๊ฐ ์๋น์ค ์ค๋จ ์์ด ์ด๋ฃจ์ด์ง ์ ์๋๋ก ํด์ค๋ค.
๋กค๋ง ์
๋ฐ์ดํธ ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์
์ค์ผ์ผ๋ง๊ณผ ์ ์ฌํ๊ฒ, ๋ํ๋ก์ด๋จผํธ๊ฐ ์ธ๋ถ๋ก ๋
ธ์ถ๋๋ฉด, ์๋น์ค๋ ์
๋ฐ์ดํธ๊ฐ ์ด๋ฃจ์ด์ง๋ ๋์ ์ค์ง ๊ฐ์ฉํ ํ๋์๊ฒ๋ง ํธ๋ํฝ์ ๋ก๋๋ฐธ๋ฐ์ค ํ ๊ฒ์ด๋ค. ๊ฐ์ฉํ ํ๋๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉ์๋ค์๊ฒ ๊ฐ์ฉํ ์ํ์ ์ธ์คํด์ค๋ฅผ ๋งํ๋ค.
๋กค๋ง ์
๋ฐ์ดํธ๋ ๋ค์ ๋์๋ค์ ํ์ฉํด์ค๋ค:
ํ๋์ ํ๊ฒฝ์์ ๋ ๋ค๋ฅธ ํ๊ฒฝ์ผ๋ก์ ์ ํ๋ฆฌ์ผ์ด์
ํ๋ก๋ชจ์
(์ปจํ
์ด๋ ์ด๋ฏธ์ง ์
๋ฐ์ดํธ๋ฅผ ํตํด) ์ด์ ๋ฒ์ ์ผ๋ก์ ๋กค๋ฐฑ ์๋น์ค ์ค๋จ ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ง์์ ์ธ ํตํฉ๊ณผ ์ง์์ ์ธ ์ ๋ฌ ๋ํ๋ก์ด๋จผํธ๊ฐ ์ธ๋ถ๋ก ๋
ธ์ถ๋๋ฉด, ์๋น์ค๋ ์
๋ฐ์ดํธ๊ฐ ์ด๋ฃจ์ด์ง๋ ๋์ ์ค์ง ๊ฐ์ฉํ ํ๋์๊ฒ๋ง ํธ๋ํฝ์ ๋ก๋๋ฐธ๋ฐ์ค ํ ๊ฒ์ด๋ค.
๋ค์ ๋ํํ ํํ ๋ฆฌ์ผ์์, ์๋ก์ด ๋ฒ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์
๋ฐ์ดํธํ๊ณ , ๋กค๋ฐฑ ๋ํ ์ํํด ๋ณผ ๊ฒ์ด๋ค.
2.6.2 - ๋ํํ ํํ ๋ฆฌ์ผ - ์ฑ ์
๋ฐ์ดํธ ํ๊ธฐ ํฐ๋ฏธ๋๊ณผ ์ํธ์์ฉํ๊ธฐ ์ํด, ๋ฐ์คํฌํ/ํ๋ธ๋ฆฟ ๋ฒ์ ์ ์ด์ฉํ๋ค.
3 - ์ค์ 3.1 - ์ปจํผ๊ทธ๋งต์ ์ฌ์ฉํด์ Redis ์ค์ ํ๊ธฐ ์ด ํ์ด์ง์์๋ ์ปจํผ๊ทธ๋งต(ConfigMap)์ ์ฌ์ฉํด์ Redis๋ฅผ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ค์ธ๊ณ ์์ ๋ฅผ ์ ๊ณตํ๊ณ , ์ปจํผ๊ทธ๋งต์ ์ฌ์ฉํด์ ํ๋ ์ค์ ํ๊ธฐ ํ์คํฌ๋ก ๋น๋๋ฅผ ํ๋ค.
๋ชฉ์ Redis ์ค์ ๊ฐ์ผ๋ก ์ปจํผ๊ทธ๋งต์ ์์ฑํ๋ค. ์์ฑ๋ ์ปจํผ๊ทธ๋งต์ ๋ง์ดํธํ๊ณ ์ฌ์ฉํ๋ Redis ํ๋๋ฅผ ์์ฑํ๋ค. ์ค์ ์ด ์ ์ ์ฉ๋์๋์ง ํ์ธํ๋ค. ์์ํ๊ธฐ ์ ์
์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๊ฐ ํ์ํ๊ณ , kubectl ์ปค๋งจ๋-๋ผ์ธ ํด์ด ํด๋ฌ์คํฐ์
ํต์ ํ ์ ์๋๋ก ์ค์ ๋์ด ์์ด์ผ ํ๋ค. ์ด ํํ ๋ฆฌ์ผ์ ์ปจํธ๋กค ํ๋ ์ธ ํธ์คํธ๊ฐ ์๋ ๋
ธ๋๊ฐ ์ ์ด๋ 2๊ฐ ํฌํจ๋ ํด๋ฌ์คํฐ์์ ์คํํ๋ ๊ฒ์ ์ถ์ฒํ๋ค. ๋ง์ฝ, ์์ง ํด๋ฌ์คํฐ๋ฅผ ๊ฐ์ง๊ณ
์์ง ์๋ค๋ฉด,
minikube ๋ฅผ ์ฌ์ฉํด์ ์์ฑํ๊ฑฐ๋
๋ค์ ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ์ด๊ทธ๋ผ์ด๋ ์ค ํ๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
๋ฒ์ ํ์ธ์ ์ํด์, ๋ค์ ์ปค๋งจ๋๋ฅผ ์คํ kubectl version
.
์ค์ธ์ ์์ : ์ปจํผ๊ทธ๋งต์ ์ฌ์ฉํด์ Redis ์ค์ ํ๊ธฐ ์๋ ๋จ๊ณ๋ฅผ ํตํด์, ์ปจํผ๊ทธ๋งต์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ Redis ์บ์๋ฅผ ์ค์ ํ๋ค.
์ฐ์ , ๋น์ด ์๋ ์ค์ ์ผ๋ก ์ปจํผ๊ทธ๋งต์ ์์ฑํ๋ค.
cat <<EOF >./example-redis-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: example-redis-config
data:
redis-config: ""
EOF
์์์ ์์ฑํ ์ปจํผ๊ทธ๋งต์ Redis ํ๋ ๋งค๋ํ์คํธ์ ํจ๊ป ์ ์ฉํ๋ค.
kubectl apply -f example-redis-config.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/pods/config/redis-pod.yaml
Redis ํ๋ ๋งค๋ํ์คํธ์ ๋ด์ฉ์ ๊ฒํ ํ๊ณ ๋ค์์ ์ฌํญ์ ์ผ๋์ ๋๋ค.
config
๋ผ๋ ์ด๋ฆ์ ๋ณผ๋ฅจ์ spec.volumes[1]
์ ์ํด์ ์์ฑ๋๋ค.spec.volumes[1].configMap.items[0]
๋ด๋ถ์ key
์ path
๋ config
๋ณผ๋ฅจ์ redis.conf
๋ผ๋ ํ์ผ๋ช
์ผ๋ก ์ง์ ๋
example-redis-config
์ปจํผ๊ทธ๋งต์ redis-config
ํค๋ฅผ ๋
ธ์ถ์ํจ๋ค.๊ทธ๋ฆฌ๊ณ config
๋ณผ๋ฅจ์ spec.containers[0].volumeMounts[1]
์ ์ํด์ /redis-master
์ ๋ง์ดํธ๋๋ค. ์ด ๋ด์ฉ์ ์์ example-redis-config
์ปจํผ๊ทธ๋งต์ data.redis-config
๋ด๋ถ ๋ฐ์ดํฐ๋ฅผ ํ๋ ์์ ์๋
/redis-master/redis.conf
ํ์ผ์ ๋ด์ฉ์ผ๋ก ๋
ธ์ถ์ํค๋ ์ํจ๊ณผ(net effect)๋ฅผ ๋ธ๋ค.
apiVersion : v1
kind : Pod
metadata :
name : redis
spec :
containers :
- name : redis
image : redis:5.0.4
command :
- redis-server
- "/redis-master/redis.conf"
env :
- name : MASTER
value : "true"
ports :
- containerPort : 6379
resources :
limits :
cpu : "0.1"
volumeMounts :
- mountPath : /redis-master-data
name : data
- mountPath : /redis-master
name : config
volumes :
- name : data
emptyDir : {}
- name : config
configMap :
name : example-redis-config
items :
- key : redis-config
path : redis.conf
์์ฑ๋ ์ค๋ธ์ ํธ๋ฅผ ํ์ธํ๋ค.
kubectl get pod/redis configmap/example-redis-config
๋ค์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ ์๋ค.
NAME READY STATUS RESTARTS AGE
pod/redis 1/1 Running 0 8s
NAME DATA AGE
configmap/example-redis-config 1 14s
example-redis-config
์ปจํผ๊ทธ๋งต์ redis-config
ํค๋ฅผ ๊ณต๋์ผ๋ก ๋ ๊ฒ์ ๊ธฐ์ตํ์.
kubectl describe configmap/example-redis-config
redis-config
ํค๊ฐ ๋น์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
Name: example-redis-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
redis-config:
kubectl exec
๋ฅผ ์ฌ์ฉํ์ฌ ํ๋์ ์ ์ํ๊ณ , ํ์ฌ ์ค์ ํ์ธ์ ์ํด์ redis-cli
๋๊ตฌ๋ฅผ ์คํํ๋ค.
kubectl exec -it redis -- redis-cli
maxmemory
๋ฅผ ํ์ธํ๋ค.
127.0.0.1:6379> CONFIG GET maxmemory
๊ธฐ๋ณธ๊ฐ์ธ 0์ ๋ณผ ์ ์์ ๊ฒ์ด๋ค.
์ ์ฌํ๊ฒ, maxmemory-policy
๋ฅผ ํ์ธํ๋ค.
127.0.0.1:6379> CONFIG GET maxmemory-policy
์ด๊ฒ๋ ๊ธฐ๋ณธ๊ฐ์ธ noeviction
์ ๋ณด์ฌ์ค ๊ฒ์ด๋ค.
1) "maxmemory-policy"
2) "noeviction"
์ด์ example-redis-config
์ปจํผ๊ทธ๋งต์ ๋ช ๊ฐ์ง ์ค์ ๊ฐ์ ์ถ๊ฐํด ๋ณธ๋ค.
apiVersion : v1
kind : ConfigMap
metadata :
name : example-redis-config
data :
redis-config : |
maxmemory 2mb
maxmemory-policy allkeys-lru
๊ฐฑ์ ๋ ์ปจํผ๊ทธ๋งต์ ์ ์ฉํ๋ค.
kubectl apply -f example-redis-config.yaml
์ปจํผ๊ทธ๋งต์ด ๊ฐฑ์ ๋ ๊ฒ์ ํ์ธํ๋ค.
kubectl describe configmap/example-redis-config
๋ฐฉ๊ธ ์ถ๊ฐํ ์ค์ ๊ฐ์ ํ์ธํ ์ ์์ ๊ฒ์ด๋ค.
Name: example-redis-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
redis-config:
----
maxmemory 2mb
maxmemory-policy allkeys-lru
์ค์ ์ด ์ ์ฉ๋์๋์ง ํ์ธํ๋ ค๋ฉด, kubectl exec
๋ฅผ ํตํ redis-cli
๋ก Redis ํ๋๋ฅผ ๋ค์ ํ์ธํ๋ค.
kubectl exec -it redis -- redis-cli
maxmemory
๋ฅผ ํ์ธํ๋ค.
127.0.0.1:6379> CONFIG GET maxmemory
๊ธฐ๋ณธ๊ฐ์ธ 0์ ๋ณผ ์ ์์ ๊ฒ์ด๋ค.
์ ์ฌํ๊ฒ, maxmemory-policy
๋ ๊ธฐ๋ณธ ์ค์ ์ธ noeviction
์ ๋ณด์ฌ์ค ๊ฒ์ด๋ค.
127.0.0.1:6379> CONFIG GET maxmemory-policy
์์ ๋ช
๋ น์ ๋ค์์ ๋ฐํํ๋ค.
1) "maxmemory-policy"
2) "noeviction"
ํ๋๋ ์ฐ๊ด๋ ์ปจํผ๊ทธ๋งต์์ ๊ฐฑ์ ๋ ๊ฐ์ ์ธ์งํ๊ธฐ ์ํด์ ์ฌ์์์ด ํ์ํ๋ฏ๋ก
ํด๋น ์ค์ ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์์ ์ํ์ด๋ค. ํ๋๋ฅผ ์ญ์ ํ๊ณ ๋ค์ ์์ฑํ๋ค.
kubectl delete pod redis
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/pods/config/redis-pod.yaml
์ด์ ๋ง์ง๋ง์ผ๋ก ์ค์ ๊ฐ์ ๋ค์ ํ์ธํด ๋ณธ๋ค.
kubectl exec -it redis -- redis-cli
maxmemory
๋ฅผ ํ์ธํ๋ค.
127.0.0.1:6379> CONFIG GET maxmemory
์ด๊ฒ์ ์ด์ ๊ฐฑ์ ๋ ๊ฐ์ธ 2097152๋ฅผ ๋ฐํํ๋ค.
1) "maxmemory"
2) "2097152"
์ ์ฌํ๊ฒ, maxmemory-policy
๋ ๊ฐฑ์ ๋์ด ์๋ค.
127.0.0.1:6379> CONFIG GET maxmemory-policy
์ด๊ฒ์ ์ํ๋ ๊ฐ์ธ allkeys-lru
๋ฅผ ๋ฐํํ๋ค.
1) "maxmemory-policy"
2) "allkeys-lru"
์์ฑ๋ ์์์ ์ญ์ ํ์ฌ ์์
์ ์ ๋ฆฌํ๋ค.
kubectl delete pod/redis configmap/example-redis-config
๋ค์ ๋ด์ฉ
4 - ๋ณด์ 4.1 - AppArmor๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค์ ๋ํ ์ปจํ
์ด๋์ ์ ๊ทผ ์ ํ ๊ธฐ๋ฅ ์ํ:
Kubernetes v1.4 [beta]
AppArmor๋ ํ์ค ๋ฆฌ๋
์ค ์ฌ์ฉ์์ ๊ทธ๋ฃน ๊ธฐ๋ฐ์ ๊ถํ์ ๋ณด์ํ์ฌ, ํ์ ๋ ๋ฆฌ์์ค ์งํฉ์ผ๋ก
ํ๋ก๊ทธ๋จ์ ์ ํํ๋ ๋ฆฌ๋
์ค ์ปค๋ ๋ณด์ ๋ชจ๋์ด๋ค. AppArmor๋ ์์์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ํด์
์ ์ฌ์ ์ธ ๊ณต๊ฒฉ ๋ฒ์๋ฅผ ์ค์ด๊ณ ๋์ฑ ์ฌ์ธต์ ์ธ ๋ฐฉ์ด๋ฅผ ์ ๊ณตํ๋๋ก ๊ตฌ์ฑํ ์ ์๋ค.
์ด ๊ธฐ๋ฅ์ ํน์ ํ๋ก๊ทธ๋จ์ด๋ ์ปจํ
์ด๋์์ ํ์ํ ๋ฆฌ๋
์ค ๊ธฐ๋ฅ, ๋คํธ์ํฌ ์ฌ์ฉ, ํ์ผ ๊ถํ ๋ฑ์ ๋ํ
์ ๊ทผ์ ํ์ฉํ๋ ํ๋กํ์ผ๋ก ๊ตฌ์ฑํ๋ค. ๊ฐ ํ๋กํ์ผ์
ํ์ฉํ์ง ์์ ๋ฆฌ์์ค ์ ๊ทผ์ ์ฐจ๋จํ๋ ๊ฐ์ (enforcing) ๋ชจ๋ ๋๋
์๋ฐ๋ง์ ๋ณด๊ณ ํ๋ ๋ถํ(complain) ๋ชจ๋๋ก ์คํํ ์ ์๋ค.
AppArmor๋ฅผ ์ด์ฉํ๋ฉด ์ปจํ
์ด๋๊ฐ ์ํํ ์ ์๋ ์์
์ ์ ํํ๊ณ ๋๋
์์คํ
๋ก๊ทธ๋ฅผ ํตํด ๋ ๋์ ๊ฐ์ฌ๋ฅผ ์ ๊ณตํ์ฌ ๋ ์์ ํ ๋ฐฐํฌ๋ฅผ ์คํํ ์ ์๋ค.
๊ทธ๋ฌ๋ AppArmor๊ฐ ์ํํ(์ธ์ ๋ ํตํ๋ ๋ฌด์ ์ ๋ฐฉ๋ฒ)์ด ์๋๋ฉฐ,
์ ํ๋ฆฌ์ผ์ด์
์ฝ๋ ์ทจ์ฝ์ ์ ๋ณดํธํ๊ธฐ ์ํ ์ฌ๋ฌ ์กฐ์น๋ฅผ ํ ์ ์๋ ๊ฒ ๋ฟ์์ ์์ผ๋ฉด ์๋๋ค.
์ํธํ๊ณ ์ ํ์ ์ธ ํ๋กํ์ผ์ ์ ๊ณตํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์
๊ณผ ํด๋ฌ์คํฐ๋ฅผ ์ฌ๋ฌ ์ธก๋ฉด์์ ๊ฐํํ๋ ๊ฒ์ด ์ค์ํ๋ค.
๋ชฉ์ ๋
ธ๋์ ํ๋กํ์ผ์ ์ด๋ป๊ฒ ์ ์ฌํ๋์ง ์์๋ฅผ ๋ณธ๋ค. ํ๋์ ํ๋กํ์ผ์ ์ด๋ป๊ฒ ๊ฐ์ ์ ์ฉํ๋์ง ๋ฐฐ์ด๋ค. ํ๋กํ์ผ์ด ์ ์ฌ๋์๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ด๋ค. ํ๋กํ์ผ์ ์๋ฐํ๋ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณธ๋ค. ํ๋กํ์ผ์ ์ ์ฌํ ์ ์์ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณธ๋ค. ์์ํ๊ธฐ ์ ์ ๋ค์์ ๋ณด์ฅํด์ผ ํ๋ค.
์ฟ ๋ฒ๋คํฐ์ค ๋ฒ์ ์ ์ต์ 1.4 ์ด๋ค. -- ์ฟ ๋ฒ๋คํฐ์ค v1.4๋ถํฐ AppArmor ์ง์์ ์ถ๊ฐํ๋ค.
v1.4 ์ด์ ์ฟ ๋ฒ๋คํฐ์ค ์ปดํฌ๋ํธ๋ ์๋ก์ด AppArmor ์ด๋
ธํ
์ด์
์ ์ธ์ํ์ง ๋ชปํ๊ณ
์ ๊ณต๋๋ AppArmor ์ค์ ์ ์กฐ์ฉํ ๋ฌด์ ํ ๊ฒ์ด๋ค. ํ๋์์ ์์ํ๋ ๋ณดํธ๋ฅผ ๋ฐ๊ณ ์๋์ง ํ์ธํ๋ ค๋ฉด
ํด๋น ๋
ธ๋์ Kubelet ๋ฒ์ ์ ํ์ธํ๋ ๊ฒ์ด ์ค์ํ๋ค.
$ kubectl get nodes -o= jsonpath = $'{range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}'
gke-test-default-pool-239f5d02-gyn2: v1.4.0
gke-test-default-pool-239f5d02-x1kf: v1.4.0
gke-test-default-pool-239f5d02-xwux: v1.4.0
AppArmor ์ปค๋ ๋ชจ๋์ ์ฌ์ฉ ๊ฐ๋ฅํด์ผ ํ๋ค. -- ๋ฆฌ๋
์ค ์ปค๋์ AppArmor ํ๋กํ์ผ์ ๊ฐ์ ์ ์ฉํ๊ธฐ ์ํด AppArmor ์ปค๋ ๋ชจ๋์ ๋ฐ๋์ ์ค์น๋์ด ์๊ณ
์ฌ์ฉ ๊ฐ๋ฅํด์ผ ํ๋ค. ์๋ฅผ ๋ค์ด Ubuntu ๋ฐ SUSE ๊ฐ์ ๋ฐฐํฌํ์ ๋ชจ๋์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ง์ํ๊ณ , ๊ทธ ์ธ ๋ง์ ๋ค๋ฅธ ๋ฐฐํฌํ๋ค์ ์ ํ์ ์ผ๋ก ์ง์ํ๋ค.
๋ชจ๋์ด ์ฌ์ฉ ๊ฐ๋ฅํ์ง ํ์ธํ๋ ค๋ฉด
/sys/module/apparmor/parameters/enabled
ํ์ผ์ ํ์ธํ๋ค.
$ cat /sys/module/apparmor/parameters/enabled
Y
Kubelet(>=v1.4)์ด AppArmor ๊ธฐ๋ฅ ์ง์์ ํฌํจํ์ง๋ง, ์ปค๋ ๋ชจ๋์ ์ฌ์ฉํ ์ ์์ผ๋ฉด
ํ๋์์ AppArmor ์ต์
์ ์คํํ๋ ๊ฒ์ด ๊ฑฐ๋ถ๋๋ค.
์ฐธ๊ณ : ์ฐ๋ถํฌ์๋ ์ถ๊ฐ์ ์ธ ํ
(hook)์ด๋ ์ถ๊ฐ ๊ธฐ๋ฅ ํจ์น๋ฅผ ํฌํจํ ๋ฆฌ๋
์ค ์ปค๋์ ์์ ์คํธ๋ฆผ์ ๋จธ์ง๋์ง ์์
๋ง์ AppArmor ํจ์น๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋
์์ ์คํธ๋ฆผ ๋ฒ์ ์์ ํ
์คํธํ ํจ์น๋ง์ ๊ฐ์ง๊ณ ์์ด์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ง์์ ๋ณด์ฅํ์ง ์๋๋ค.์ปจํ
์ด๋ ๋ฐํ์์ด AppArmor์ ์ง์ํ๋ค. -- ํ์ฌ ๋ชจ๋ ์ผ๋ฐ์ ์ธ ์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ์ง์ํ๋
๋์ปค(Docker) , CRI-O ๋๋
containerd ์ ๊ฐ์ ์ปจํ
์ด๋ ๋ฐํ์๋ค์ AppArmor๋ฅผ ์ง์ํด์ผ ํ๋ค.
์ด ๋ฐํ์ ์ค๋ช
์๋ฅผ ์ฐธ์กฐํด์ ํด๋ฌ์คํฐ๊ฐ AppArmor๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ
์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋์ง ํ์ธํด์ผ ํ๋ค.
ํ๋กํ์ผ์ด ์ ์ฌ๋์ด ์๋ค. -- AppArmor๋ ๊ฐ ์ปจํ
์ด๋์ ํจ๊ป ์คํํด์ผ ํ๋ AppArmor ํ๋กํ์ผ์ ์ง์ ํ์ฌ ํ๋์ ์ ์ฉํ๋ค.
์ปค๋์ ์ง์ ํ ํ๋กํ์ผ์ด ์ ์ฌ๋์ง ์์๋ค๋ฉด, Kubelet(>= v1.4)์ ํ๋๋ฅผ ๊ฑฐ๋ถํ๋ค. ํด๋น ๋
ธ๋์ ์ด๋ค ํ๋กํ์ผ์ด ์ ์ฌ๋์๋์ง๋
/sys/kernel/security/apparmor/profiles
ํ์ผ์ ํตํด ํ์ธํ ์ ์๋ค.
์๋ฅผ ๋ค์ด,
$ ssh gke-test-default-pool-239f5d02-gyn2 "sudo cat /sys/kernel/security/apparmor/profiles | sort"
apparmor-test-deny-write (enforce)
apparmor-test-audit-write (enforce)
docker-default (enforce)
k8s-nginx (enforce)
๋
ธ๋์ ํ๋กํ์ผ์ ์ ์ฌํ๋ ๊ฒ์ ๋ํด ๋ ์์ธํ ๋ด์ฉ์
ํ๋กํ์ผ๊ณผ ํจ๊ป ๋
ธ๋ ์ค์ ํ๊ธฐ .
AppArmor ์ง์์ด ํฌํจ๋ Kubelet (>= v1.4)์ด๋ฉด
์ด๋ค ์ ์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์ง ์์ผ๋ฉด AppArmor์ ํจ๊ปํ ํ๋๋ฅผ ๊ฑฐ๋ถํ๋ค.
๋
ธ๋ ์์ AppArmor ์ง์ ์ฌ๋ถ๋
๋
ธ๋ ์ค๋น ์กฐ๊ฑด ๋ฉ์์ง๋ฅผ ํ์ธํ์ฌ(์ดํ ๋ฆด๋ฆฌ์ค์์๋ ์ญ์ ๋ ๊ฒ ๊ฐ์ง๋ง) ๊ฒ์ฆํ ์ ์๋ค.
kubectl get nodes -o= jsonpath = '{range .items[*]}{@.metadata.name}: {.status.conditions[?(@.reason=="KubeletReady")].message}{"\n"}{end}'
gke-test-default-pool-239f5d02-gyn2: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-x1kf: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-xwux: kubelet is posting ready status. AppArmor enabled
ํ๋ ๋ณด์ ๊ฐํํ๊ธฐ ์ฐธ๊ณ : AppArmor๋ ํ์ฌ ๋ฒ ํ์ด๋ฉฐ, ์ด ๋๋ฌธ์ ์ต์
์ ์ด๋
ธํ
์ด์
ํ์์ผ๋ก ์ง์ ํ๋ค. ์ผ๋ฐ ์ฌ์ฉ์ ๋ฒ์ ์ด ๋๋ฉด,
์ด๋
ธํ
์ด์
์ ์ต์์ ์ข
๋ฅ์ ํ๋๋ก ๋์ฒด๋ ๊ฒ์ด๋ค(์์ธํ ๋ด์ฉ์
์ผ๋ฐ ์ฌ์ฉ์ ๋ฒ์ ์ผ๋ก ์
๊ทธ๋ ์ด๋ ๋ฐฉ๋ฒ ์ฐธ๊ณ )
AppArmor ํ๋กํ์ผ์ ์ปจํ
์ด๋๋ง๋ค ์ง์ ๋๋ค. ํจ๊ป ์คํํ ํ๋ ์ปจํ
์ด๋์ AppArmor ํ๋กํ์ผ์ ์ง์ ํ๋ ค๋ฉด
ํ๋์ ๋ฉํ๋ฐ์ดํฐ์ ์ด๋
ธํ
์ด์
์ ์ถ๊ฐํ๋ค.
container.apparmor.security.beta.kubernetes.io/<container_name> : <profile_ref>
<container_name>
์ ํ๋กํ์ผ์ ์ ์ฉํ๋ ์ปจํ
์ด๋ ์ด๋ฆ์ด๊ณ , <profile_ref>
๋
์ ์ฉํ ํ๋กํ์ผ์ ์ง์ ํ๋ค. profile_ref
๋ ๋ค์ ์ค์ ํ๋์ด๋ค.
๋ฐํ์์ ๊ธฐ๋ณธ ํ๋กํ์ผ์ ์ ์ฉํ๊ธฐ ์ํ runtime/default
<profile_name>
๋ก ์ด๋ฆํ ํธ์คํธ์ ์ ์ฌ๋๋ ํ๋กํ์ผ์ ์ ์ฉํ๊ธฐ ์ํ localhost/<profile_name>
์ ์ฌํ ํ๋กํ์ผ์ด ์์์ ๋ํ๋ด๋ unconfined
์ด๋
ธํ
์ด์
๊ณผ ํ๋กํ์ผ ์ด๋ฆ ํ์์ ์์ธํ ๋ด์ฉ์ API ์ฐธ์กฐ ๋ฅผ ์ดํด๋ณธ๋ค.
์ฟ ๋ฒ๋คํฐ์ค AppArmor ์ ์๋ ์์๋ ๋ชจ๋ ์ ํ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์๋์ง ํ์ธํ๊ณ ,
์ ์ฉ์ ์ํด ์ ํํ ํ๋กํ์ผ์ ์ปจํ
์ด๋ ๋ฐํ์์ผ๋ก ์ ๋ฌํ์ฌ ์ด๋ฃจ์ด์ง๋ค.
๋ง์ฝ ์ ํ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์ง ์์ผ๋ฉด ํ๋๋ ๊ฑฐ๋ถ๋๊ณ ์คํ๋์ง ์๋๋ค.
ํ๋กํ์ผ์ด ์ ์ฉ๋์๋์ง ํ์ธํ๊ธฐ ์ํด, ์ปจํ
์ด๋ ์์ฑ ์ด๋ฒคํธ์ ๋์ด๋ AppArmor ๋ณด์ ์ต์
์ ์ฐพ์ ๋ณผ ์ ์๋ค.
kubectl get events | grep Created
22s 22s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet e2e-test-stclair-node-pool-31nt} Created container with docker id 269a53b202d3; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
์ปจํ
์ด๋์ ๋ฃจํธ ํ๋ก์ธ์ค๊ฐ ์ฌ๋ฐ๋ฅธ ํ๋กํ์ผ๋ก ์คํ๋๋์ง๋ proc attr์ ํ์ธํ์ฌ ์ง์ ๊ฒ์ฆํ ์ ์๋ค.
kubectl exec <pod_name> -- cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
์์ ์ด ์์๋ AppArmor๋ฅผ ์ง์ํ๋ ํด๋ฌ์คํฐ๋ฅผ ์ด๋ฏธ ๊ตฌ์ฑํ์๋ค๊ณ ๊ฐ์ ํ๋ค.
๋จผ์ ๋
ธ๋์์ ์ฌ์ฉํ๋ ค๋ ํ๋กํ์ผ์ ์ ์ฌํด์ผ ํ๋ค. ์ฌ์ฉํ ํ๋กํ์ผ์ ํ์ผ ์ฐ๊ธฐ๋ฅผ ๊ฑฐ๋ถํ๋ค.
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags =( attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
ํ๋๋ฅผ ์ธ์ ์ค์ผ์คํ ์ง ์์ง ๋ชปํ๋ฏ๋ก ๋ชจ๋ ๋
ธ๋์ ํ๋กํ์ผ์ ์ ์ฌํด์ผ ํ๋ค.
์ด ์์์์๋ SSH๋ฅผ ์ด์ฉํ์ฌ ํ๋กํ์ผ์ ์ค์นํ ๊ฒ์ด๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์
ํ๋กํ์ผ๊ณผ ํจ๊ป ๋
ธ๋ ์ค์ ํ๊ธฐ ์์ ๋
ผ์ํ๋ค.
NODES =(
# The SSH-accessible domain names of your nodes
gke-test-default-pool-239f5d02-gyn2.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-x1kf.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-xwux.us-central1-a.my-k8s)
for NODE in ${ NODES [*]} ; do ssh $NODE 'sudo apparmor_parser -q <<EOF
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
EOF'
done
๋ค์์ผ๋ก ์ฐ๊ธฐ ๊ธ์ง ํ๋กํ์ผ๋ "Hello AppArmor" ํ๋๋ฅผ ์คํํ๋ค.
apiVersion : v1
kind : Pod
metadata :
name : hello-apparmor
annotations :
# ์ฟ ๋ฒ๋คํฐ์ค์ 'k8s-apparmor-example-deny-write' AppArmor ํ๋กํ์ผ์ ์ ์ฉํจ์ ์๋ฆฐ๋ค.
# ์์ง ๋ง ๊ฒ์ ์ฟ ๋ฒ๋คํฐ์ค ๋
ธ๋์์ ์คํ ์ค์ธ ๋ฒ์ ์ด 1.4 ์ด์์ด ์๋ ๊ฒฝ์ฐ์๋ ์ด ์ค์ ์ ๋ฌด์๋๋ค๋ ๊ฒ์ด๋ค.
container.apparmor.security.beta.kubernetes.io/hello : localhost/k8s-apparmor-example-deny-write
spec :
containers :
- name : hello
image : busybox:1.28
command : [ "sh" , "-c" , "echo 'Hello AppArmor!' && sleep 1h" ]
kubectl create -f ./hello-apparmor.yaml
ํ๋ ์ด๋ฒคํธ๋ฅผ ์ดํด๋ณด๋ฉด, 'k8s-apparmor-example-deny-write' AppArmor ํ๋กํ์ผ๋ก ์์ฑ๋ ํ๋ ์ปจํ
์ด๋๋ฅผ
ํ์ธํ ์ ์๋ค.
kubectl get events | grep hello-apparmor
14s 14s 1 hello-apparmor Pod Normal Scheduled {default-scheduler } Successfully assigned hello-apparmor to gke-test-default-pool-239f5d02-gyn2
14s 14s 1 hello-apparmor Pod spec.containers{hello} Normal Pulling {kubelet gke-test-default-pool-239f5d02-gyn2} pulling image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Pulled {kubelet gke-test-default-pool-239f5d02-gyn2} Successfully pulled image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet gke-test-default-pool-239f5d02-gyn2} Created container with docker id 06b6cd1c0989; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Started {kubelet gke-test-default-pool-239f5d02-gyn2} Started container with docker id 06b6cd1c0989
proc attr์ ํ์ธํ์ฌ ์ปจํ
์ด๋๊ฐ ์ค์ ๋ก ํด๋น ํ๋กํ์ผ๋ก ์คํ ์ค์ธ์ง ํ์ธํ ์ ์๋ค.
kubectl exec hello-apparmor -- cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
๋ง์ง๋ง์ผ๋ก ํ์ผ ์ฐ๊ธฐ๋ฅผ ํตํด ํ๋กํ์ผ์ ์๋ฐํ๋ฉด ์ด๋ป๊ฒ ๋๋์ง ํ์ธํ ์ ์๋ค.
kubectl exec hello-apparmor -- touch /tmp/test
touch: /tmp/test: Permission denied
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1
์ด์ ์ ๋ฆฌํ๋ฉด์, ์ ์ฌ๋์ง ์์ ํ๋กํ์ผ์ ์ง์ ํ๋ฉด ์ด๋ป๊ฒ ๋๋์ง ์ดํด๋ณธ๋ค.
kubectl create -f /dev/stdin <<EOF
apiVersion : v1
kind : Pod
metadata :
name : hello-apparmor-2
annotations :
container.apparmor.security.beta.kubernetes.io/hello : localhost/k8s-apparmor-example-allow-write
spec :
containers :
- name : hello
image : busybox:1.28
command : [ "sh" , "-c" , "echo 'Hello AppArmor!' && sleep 1h" ]
EOF
pod/hello-apparmor-2 created
kubectl describe pod hello-apparmor-2
Name: hello-apparmor-2
Namespace: default
Node: gke-test-default-pool-239f5d02-x1kf/
Start Time: Tue, 30 Aug 2016 17:58:56 -0700
Labels: <none>
Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write
Status: Pending
Reason: AppArmor
Message: Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
IP:
Controllers: <none>
Containers:
hello:
Container ID:
Image: busybox
Image ID:
Port:
Command:
sh
-c
echo 'Hello AppArmor!' && sleep 1h
State: Waiting
Reason: Blocked
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-dnz7v (ro)
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
Volumes:
default-token-dnz7v:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-dnz7v
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
23s 23s 1 {default-scheduler } Normal Scheduled Successfully assigned hello-apparmor-2 to e2e-test-stclair-minion-group-t1f5
23s 23s 1 {kubelet e2e-test-stclair-node-pool-t1f5} Warning AppArmor Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
ํ๋ ์ํ๋ Pending์ด๋ฉฐ, ์ค๋ฅ ๋ฉ์์ง๋ Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
์ด๋ค. ์ด๋ฒคํธ๋ ๋์ผํ ๋ฉ์์ง๋ก ๊ธฐ๋ก๋์๋ค.
๊ด๋ฆฌ ํ๋กํ์ผ๊ณผ ํจ๊ป ๋
ธ๋ ์ค์ ํ๊ธฐ ํ์ฌ ์ฟ ๋ฒ๋คํฐ์ค๋ AppArmor ํ๋กํ์ผ์ ๋
ธ๋์ ์ ์ฌํ๊ธฐ ์ํ ๋ค์ดํฐ๋ธ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ์ง ์๋๋ค.
ํ๋กํ์ผ์ ์ค์ ํ๋ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๊ฐ ๋
ธ๋์์ ํ๋๋ฅผ ์คํํ๋ ๋ฐ๋ชฌ์
์ ํตํด์
์ฌ๋ฐ๋ฅธ ํ๋กํ์ผ์ด ์ ์ฌ๋์๋์ง ํ์ธํ๋ค. ์์ ๊ตฌํ์
์ฌ๊ธฐ ์์ ์ฐพ์๋ณผ ์ ์๋ค. ๋
ธ๋ ์ด๊ธฐํ ์๊ฐ์ ๋
ธ๋ ์ด๊ธฐํ ์คํฌ๋ฆฝํธ(์๋ฅผ ๋ค์ด Salt, Ansible ๋ฑ)๋
์ด๋ฏธ์ง๋ฅผ ์ด์ฉ ์์ ์์ ๋ณด์ฌ์ค ๊ฒ์ฒ๋ผ,
ํ๋กํ์ผ์ ๊ฐ ๋
ธ๋์ ๋ณต์ฌํ๊ณ SSH๋ฅผ ํตํด ์ ์ฌํ๋ค.์ค์ผ์ค๋ฌ๋ ์ด๋ค ํ๋กํ์ผ์ด ์ด๋ค ๋
ธ๋์ ์ ์ฌ๋๋์ง ๊ณ ๋ คํ์ง ์์ผ๋, ํ๋กํ์ผ ์ ์ฒด ์งํฉ์ด
๋ชจ๋ ๋
ธ๋์ ์ ์ฌ๋์ด์ผ ํ๋ค. ๋์์ ์ธ ๋ฐฉ๋ฒ์
๊ฐ ํ๋กํ์ผ(ํน์ ํ๋กํ์ผ์ ํด๋์ค)์ ์ํ ๋
ธ๋ ๋ ์ด๋ธ์ ๋
ธ๋์ ์ถ๊ฐํ๊ณ ,
๋
ธ๋ ์
๋ ํฐ ๋ฅผ ์ด์ฉํ์ฌ
ํ๋๊ฐ ํ์ํ ํ๋กํ์ผ์ด ์๋ ๋
ธ๋์์ ์คํ๋๋๋ก ํ๋ค.
AppArmor ๋นํ์ฑํ ํด๋ฌ์คํฐ์์ AppArmor๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ ค๋ฉด, ์ปค๋งจ๋๋ผ์ธ ํ๋๊ทธ๋ก ๋นํ์ฑํ ํ ์ ์๋ค.
--feature-gates=AppArmor=false
๋นํ์ฑํ๋๋ฉด, AppArmor ํ๋กํ์ผ์ ํฌํจํ ํ๋๋
"Forbidden" ์ค๋ฅ๋ก ๊ฒ์ฆ ์คํจํ๋ค.
์ฐธ๊ณ : ์ฟ ๋ฒ๋คํฐ์ค ๊ธฐ๋ฅ์ด ๋นํ์ฑํ๋์ด ์์ด๋, ๋ฐํ์์ด ๊ณ์ ๊ธฐ๋ณธ ํ๋กํ์ผ์ ๊ฐ์ ํ ์๋ ์๋ค.
AppArmor๊ฐ general availability (GA) ์ํ๋ก ๋ฐ๋๋ฉด
AppArmor ๊ธฐ๋ฅ์ ๋นํ์ฑํํ๋ ์ต์
์ ์ ๊ฑฐ๋ ๊ฒ์ด๋ค.ํ๋กํ์ผ ์ ์ AppArmor ํ๋กํ์ผ์ ๋ง๋ค๊ณ ์ฌ๋ฐ๋ฅด๊ฒ ์ง์ ํ๋ ๊ฒ์ ๋งค์ฐ ๊น๋ค๋ก์ธ ์ ์๋ค.
๋คํํ ์ด ์์
์ ๋์ ๋๋ ๋๊ตฌ๊ฐ ์๋ค.
aa-genprof
์ aa-logprof
๋ ์ ํ๋ฆฌ์ผ์ด์
ํ๋๊ณผ ๋ก๊ทธ์ ์ํ์ ํ์ํ ํ๋์ ๋ชจ๋ํฐ๋งํ์ฌ
์ผ๋ฐ ํ๋กํ์ผ ๊ท์น์ ์์ฑํ๋ค. ์์ธํ ์ฌ์ฉ๋ฐฉ๋ฒ์
AppArmor ๋ฌธ์ ์์ ์ ๊ณตํ๋ค.bane ์ ๋จ์ํ๋ ํ๋กํ์ผ ์ธ์ด๋ฅผ ์ด์ฉํ๋ ๋์ปค๋ฅผ ์ํ
AppArmor ํ๋กํ์ผ ์์ฑ๊ธฐ์ด๋ค.AppArmor ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น
ํ๊ธฐ ์ํด์ ๊ฑฐ๋ถ๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ ์์คํ
๋ก๊ทธ๋ฅผ ํ์ธํ ์ ์๋ค.
AppArmor ๋ก๊ทธ๋ dmesg
์์ ๋ณด์ด๋ฉฐ, ์ค๋ฅ๋ ๋ณดํต ์์คํ
๋ก๊ทธ๋
journalctl
์์ ๋ณผ ์ ์๋ค. ๋ ๋ง์ ์ ๋ณด๋
AppArmor ์คํจ ์์ ์ ๊ณตํ๋ค.
API ์ฐธ์กฐ ํ๋ ์ด๋
ธํ
์ด์
์ปจํ
์ด๋๋ฅผ ์คํํ ํ๋กํ์ผ์ ์ง์ ํ๋ค.
ํค : container.apparmor.security.beta.kubernetes.io/<container_name>
<container_name>
๋ ํ๋ ๋ด์ ์ปจํ
์ด๋ ์ด๋ฆ๊ณผ ์ผ์นํ๋ค.
๋ถ๋ฆฌ๋ ํ๋กํ์ผ์ ํ๋ ๋ด์ ๊ฐ ์ปจํ
์ด๋๋ก ์ง์ ํ ์ ์๋ค.๊ฐ : ์๋ ๊ธฐ์ ๋ ํ๋กํ์ผ ์ฐธ์กฐํ๋กํ์ผ ์ฐธ์กฐ runtime/default
: ๊ธฐ๋ณธ ๋ฐํ์ ํ๋กํ์ผ์ ์ฐธ์กฐํ๋ค.localhost/<profile_name>
: ๋
ธ๋(localhost)์ ์ ์ฌ๋ ํ๋กํ์ผ์ ์ด๋ฆ์ผ๋ก ์ฐธ์กฐํ๋ค.unconfined
: ์ด๊ฒ์ ์ปจํ
์ด๋์์ AppArmor๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋นํ์ฑ์ํจ๋ค.๋ค๋ฅธ ์ด๋ค ํ๋กํ์ผ ์ฐธ์กฐ ํ์๋ ์ ํจํ์ง ์๋ค.
๋ค์ ๋ด์ฉ ์ฐธ๊ณ ์๋ฃ
4.2 - ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ๋ค์์คํ์ด์ค ์์ค์ ์ ์ฉํ๊ธฐ
Note ์ด ํํ ๋ฆฌ์ผ์ ์๋ก์ด ํด๋ฌ์คํฐ์๋ง ์ ์ฉํ ์ ์๋ค.ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
(PSA, Pod Security Admission)์
๋ฒ ํ๋ก ๋ณ๊ฒฝ ๋์ด v1.23 ์ด์์์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฑํ๋์ด ์๋ค.
ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
์ ํ๋๊ฐ ์์ฑ๋ ๋
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋(Pod Security Standards) ๋ฅผ ์ ์ฉํ๋ ์ด๋๋ฏธ์
์ปจํธ๋กค๋ฌ์ด๋ค.
์ด ํํ ๋ฆฌ์ผ์์๋,
๊ฐ ๋ค์์คํ์ด์ค๋ณ๋ก baseline
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ๊ฐ์ (enforce)ํ ๊ฒ์ด๋ค.
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ํด๋ฌ์คํฐ ์์ค์์ ์ฌ๋ฌ ๋ค์์คํ์ด์ค์ ํ ๋ฒ์ ์ ์ฉํ ์๋ ์๋ค.
์ด์ ๋ํ ์๋ด๋
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ํด๋ฌ์คํฐ ์์ค์ ์ ์ฉํ๊ธฐ ๋ฅผ ์ฐธ๊ณ ํ๋ค.
์์ํ๊ธฐ ์ ์ ์ํฌ์คํ
์ด์
์ ๋ค์์ ์ค์นํ๋ค.
ํด๋ฌ์คํฐ ์์ฑํ๊ธฐ ๋ค์๊ณผ ๊ฐ์ด KinD
ํด๋ฌ์คํฐ๋ฅผ ์์ฑํ๋ค.
kind create cluster --name psa-ns-level --image kindest/node:v1.23.0
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Creating cluster "psa-ns-level" ...
โ Ensuring node image (kindest/node:v1.23.0) ๐ผ
โ Preparing nodes ๐ฆ
โ Writing configuration ๐
โ Starting control-plane ๐น๏ธ
โ Installing CNI ๐
โ Installing StorageClass ๐พ
Set kubectl context to "kind-psa-ns-level"
You can now use your cluster with:
kubectl cluster-info --context kind-psa-ns-level
Not sure what to do next? ๐
Check out https://kind.sigs.k8s.io/docs/user/quick-start/
kubectl context๋ฅผ ์๋ก ์์ฑํ ํด๋ฌ์คํฐ๋ก ์ค์ ํ๋ค.
kubectl cluster-info --context kind-psa-ns-level
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Kubernetes control plane is running at https://127.0.0.1:50996
CoreDNS is running at https://127.0.0.1:50996/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
๋ค์์คํ์ด์ค ์์ฑํ๊ธฐ example
์ด๋ผ๋ ๋ค์์คํ์ด์ค๋ฅผ ์์ฑํ๋ค.
kubectl create ns example
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
namespace/example created
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋ ์ ์ฉํ๊ธฐ ๋ด์ฅ ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
์ด ์ง์ํ๋ ๋ ์ด๋ธ์ ์ฌ์ฉํ์ฌ
์ด ๋ค์์คํ์ด์ค์ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ํ์ฑํํ๋ค.
์ด ๋จ๊ณ์์๋ latest
๋ฒ์ (๊ธฐ๋ณธ๊ฐ)์ ๋ฐ๋ผ baseline(๊ธฐ์ค)
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋์ ๋ํด ๊ฒฝ๊ณ ๋ฅผ ์ค์ ํ๋ค.
kubectl label --overwrite ns example \
pod-security.kubernetes.io/warn= baseline \
pod-security.kubernetes.io/warn-version= latest
์ด๋ ํ ๋ค์์คํ์ด์ค์๋ ๋ณต์ ๊ฐ์ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ํ์ฑํํ ์ ์์ผ๋ฉฐ,
์ด๋ ๋ ์ด๋ธ์ ์ด์ฉํ์ฌ ๊ฐ๋ฅํ๋ค.
๋ค์ ๋ช
๋ น์ด๋ ์ต์ ๋ฒ์ (๊ธฐ๋ณธ๊ฐ)์ ๋ฐ๋ผ, baseline(๊ธฐ์ค)
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ enforce(๊ฐ์ )
ํ์ง๋ง
restricted(์ ํ๋)
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋์ ๋ํด์๋ warn(๊ฒฝ๊ณ )
๋ฐ audit(๊ฐ์ฌ)
ํ๋๋ก ์ค์ ํ๋ค.
kubectl label --overwrite ns example \
pod-security.kubernetes.io/enforce= baseline \
pod-security.kubernetes.io/enforce-version= latest \
pod-security.kubernetes.io/warn= restricted \
pod-security.kubernetes.io/warn-version= latest \
pod-security.kubernetes.io/audit= restricted \
pod-security.kubernetes.io/audit-version= latest
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋ ๊ฒ์ฆํ๊ธฐ example
๋ค์์คํ์ด์ค์ ์ต์ํ์ ํ๋๋ฅผ ์์ฑํ๋ค.
cat <<EOF > /tmp/pss/nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
EOF
ํด๋ฌ์คํฐ์ example
๋ค์์คํ์ด์ค์ ํด๋น ํ๋ ์คํ์ ์ ์ฉํ๋ค.
kubectl apply -n example -f /tmp/pss/nginx-pod.yaml
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
pod/nginx created
ํด๋ฌ์คํฐ์ default
๋ค์์คํ์ด์ค์ ํด๋น ํ๋ ์คํ์ ์ ์ฉํ๋ค.
kubectl apply -n default -f /tmp/pss/nginx-pod.yaml
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
pod/nginx created
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ example
๋ค์์คํ์ด์ค์๋ง ์ ์ฉ๋์๋ค.
๋์ผํ ํ๋๋ฅผ default
๋ค์์คํ์ด์ค์ ์์ฑํ๋๋ผ๋
๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
์ ๋ฆฌํ๊ธฐ kind delete cluster --name psa-ns-level
๋ช
๋ น์ ์คํํ์ฌ ์์ฑํ๋ ํด๋ฌ์คํฐ๋ฅผ ์ญ์ ํ๋ค.
๋ค์ ๋ด์ฉ 4.3 - ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ํด๋ฌ์คํฐ ์์ค์ ์ ์ฉํ๊ธฐ
Note ์ด ํํ ๋ฆฌ์ผ์ ์๋ก์ด ํด๋ฌ์คํฐ์๋ง ์ ์ฉํ ์ ์๋ค.ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
(PSA, Pod Security Admission)์
๋ฒ ํ๋ก ๋ณ๊ฒฝ ๋์ด v1.23 ์ด์์์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฑํ๋์ด ์๋ค.
ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
์ ํ๋๊ฐ ์์ฑ๋ ๋
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋(Pod Security Standards) ๋ฅผ
์ ์ฉํ๋ ์ด๋๋ฏธ์
์ปจํธ๋กค๋ฌ์ด๋ค.
์ด ํํ ๋ฆฌ์ผ์
baseline
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ํด๋ฌ์คํฐ ์์ค(level)์ ์ ์ฉํ์ฌ
ํ์ค ๊ตฌ์ฑ์ ํด๋ฌ์คํฐ์ ๋ชจ๋ ๋ค์์คํ์ด์ค์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ ์ค๋ค.
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ํน์ ๋ค์์คํ์ด์ค์ ์ ์ฉํ๋ ค๋ฉด,
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ๋ค์์คํ์ด์ค ์์ค์ ์ ์ฉํ๊ธฐ ๋ฅผ ์ฐธ๊ณ ํ๋ค.
๋ง์ฝ ์ฟ ๋ฒ๋คํฐ์ค ๋ฒ์ ์ด v1.34์ด ์๋๋ผ๋ฉด,
ํด๋น ๋ฒ์ ์ ๋ฌธ์๋ฅผ ํ์ธํ์.
์์ํ๊ธฐ ์ ์ ์ํฌ์คํ
์ด์
์ ๋ค์์ ์ค์นํ๋ค.
์ ์ฉํ ์๋ง์ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋ ์ ํํ๊ธฐ ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
์ ์ด์ฉํ์ฌ
enforce
, audit
, ๋๋ warn
๋ชจ๋ ์ค ํ๋๋ก
๋ด์ฅ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋ ๋ฅผ ์ ์ฉํ ์ ์๋ค.
ํ์ฌ ๊ตฌ์ฑ์ ๊ฐ์ฅ ์ ํฉํ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ๊ณ ๋ฅด๋ ๋ฐ
๋์์ด ๋๋ ์ ๋ณด๋ฅผ ์์งํ๋ ค๋ฉด, ๋ค์์ ์ํํ๋ค.
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๊ฐ ์ ์ฉ๋์ง ์์ ํด๋ฌ์คํฐ๋ฅผ ์์ฑํ๋ค.
kind create cluster --name psa-wo-cluster-pss --image kindest/node:v1.24.0
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Creating cluster "psa-wo-cluster-pss" ...
โ Ensuring node image (kindest/node:v1.24.0) ๐ผ
โ Preparing nodes ๐ฆ
โ Writing configuration ๐
โ Starting control-plane ๐น๏ธ
โ Installing CNI ๐
โ Installing StorageClass ๐พ
Set kubectl context to "kind-psa-wo-cluster-pss"
You can now use your cluster with:
kubectl cluster-info --context kind-psa-wo-cluster-pss
Thanks for using kind! ๐
kubectl context๋ฅผ ์๋ก ์์ฑํ ํด๋ฌ์คํฐ๋ก ์ค์ ํ๋ค.
kubectl cluster-info --context kind-psa-wo-cluster-pss
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Kubernetes control plane is running at https://127.0.0.1:61350
CoreDNS is running at https://127.0.0.1:61350/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
ํด๋ฌ์คํฐ์ ๋ค์์คํ์ด์ค ๋ชฉ๋ก์ ์กฐํํ๋ค.
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
NAME STATUS AGE
default Active 9m30s
kube-node-lease Active 9m32s
kube-public Active 9m32s
kube-system Active 9m32s
local-path-storage Active 9m26s
--dry-run=server
๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๊ฐ ์ ์ฉ๋์์ ๋
์ด๋ค ๊ฒ์ด ๋ณ๊ฒฝ๋๋์ง ํ์ธํ๋ค.
Privilegedkubectl label --dry-run= server --overwrite ns --all \
pod-security.kubernetes.io/enforce= privileged
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
namespace/default labeled
namespace/kube-node-lease labeled
namespace/kube-public labeled
namespace/kube-system labeled
namespace/local-path-storage labeled
Baselinekubectl label --dry-run= server --overwrite ns --all \
pod-security.kubernetes.io/enforce= baseline
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
namespace/default labeled
namespace/kube-node-lease labeled
namespace/kube-public labeled
Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "baseline:latest"
Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes
Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes
Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged
namespace/kube-system labeled
namespace/local-path-storage labeled
Restricted kubectl label --dry-run= server --overwrite ns --all \
pod-security.kubernetes.io/enforce= restricted
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
namespace/default labeled
namespace/kube-node-lease labeled
namespace/kube-public labeled
Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "restricted:latest"
Warning: coredns-7bb9c7b568-hsptc (and 1 other pod): unrestricted capabilities, runAsNonRoot != true, seccompProfile
Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true
Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
namespace/kube-system labeled
Warning: existing pods in namespace "local-path-storage" violate the new PodSecurity enforce level "restricted:latest"
Warning: local-path-provisioner-d6d9f7ffc-lw9lh: allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile
namespace/local-path-storage labeled
์์ ์ถ๋ ฅ์์, privileged
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ์ ์ฉํ๋ฉด ๋ชจ๋ ๋ค์์คํ์ด์ค์์ ๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํ์ง ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๊ทธ๋ฌ๋ baseline
๋ฐ restricted
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋์ ๋ํด์๋
kube-system
๋ค์์คํ์ด์ค์์ ๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํ๋ค.
๋ชจ๋, ๋ฒ์ , ๋ฐ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋ ์ค์ ์ด ์น์
์์๋, ๋ค์์ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ latest
๋ฒ์ ์ ์ ์ฉํ๋ค.
baseline
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ enforce
๋ชจ๋๋ก ์ ์ฉrestricted
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ warn
๋ฐ audit
๋ชจ๋๋ก ์ ์ฉbaseline
ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋
์์ธ ๋ชฉ๋ก์ ๊ฐ๊ฒฐํ๊ฒ ์ ์งํ๊ณ ์๋ ค์ง ๊ถํ ์์น(privilege escalations)์ ๋ฐฉ์งํ ์ ์๋
ํธ๋ฆฌํ ์ ์ถฉ์์ ์ ๊ณตํ๋ค.
์ถ๊ฐ์ ์ผ๋ก, kube-system
๋ด์ ํ๋๊ฐ ์คํจํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด,
ํด๋น ๋ค์์คํ์ด์ค๋ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๊ฐ ์ ์ฉ๋์ง ์๋๋ก ์ ์ธํ ๊ฒ์ด๋ค.
์ฌ์ฉ ์ค์ธ ํ๊ฒฝ์ ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
์ ์ ์ฉํ ๋์๋
๋ค์์ ์ฌํญ์ ๊ณ ๋ คํ๋ค.
ํด๋ฌ์คํฐ์ ์ ์ฉ๋ ์ํ ์ํ์ ๋ฐ๋ผ,
restricted
์ ๊ฐ์ ๋ ์๊ฒฉํ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๊ฐ ๋ ์ข์ ์๋ ์๋ค.
kube-system
๋ค์์คํ์ด์ค๋ฅผ ์ ์ฉ ๋์์์ ์ ์ธํ๋ฉด
์ด ๋ค์์คํ์ด์ค์ ํ๋๊ฐ privileged
๋ก ์คํ๋ ์ ์๋ค.
์ค์ ์ฌ์ฉ ํ๊ฒฝ์์๋,
์ต์ ๊ถํ ์์น์ ์ค์ํ๋๋ก,
์ ๊ทผ์ kube-system
๋ค์์คํ์ด์ค๋ก ์ ํํ๋
์๊ฒฉํ RBAC ์ ์ฑ
์ ์ ์ฉํ ๊ฒ์ ๊ฐ๋ ฅํ ๊ถ์ฅํ๋ค.
ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
์ปจํธ๋กค๋ฌ๊ฐ ์ด๋ฌํ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ๊ตฌํํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋
๊ตฌ์ฑ ํ์ผ์ ์์ฑํ๋ค.
mkdir -p /tmp/pss
cat <<EOF > /tmp/pss/cluster-level-pss.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "baseline"
enforce-version: "latest"
audit: "restricted"
audit-version: "latest"
warn: "restricted"
warn-version: "latest"
exemptions:
usernames: []
runtimeClasses: []
namespaces: [kube-system]
EOF
์ฐธ๊ณ : `pod-security.admission.config.k8s.io/v1` ์ค์ ์ ์ฟ ๋ฒ๋คํฐ์ค v1.25 ์ด์์ ํ์๋ก ํ๋ค.
์ฟ ๋ฒ๋คํฐ์ค v1.23 ๊ณผ v1.24์ ๊ฒฝ์ฐ, [v1beta1](https://v1-24.docs.kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/)์ ์ฌ์ฉํ๋ค.
์ฟ ๋ฒ๋คํฐ์ค v1.22์ ๊ฒฝ์ฐ, [v1alpha1](https://v1-22.docs.kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/)์ ์ฌ์ฉํ๋ค.
API ์๋ฒ๊ฐ ํด๋ฌ์คํฐ ์์ฑ ๊ณผ์ ์์ ์ด ํ์ผ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ๊ตฌ์ฑํ๋ค.
cat <<EOF > /tmp/pss/cluster-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
extraArgs:
admission-control-config-file: /etc/config/cluster-level-pss.yaml
extraVolumes:
- name: accf
hostPath: /etc/config
mountPath: /etc/config
readOnly: false
pathType: "DirectoryOrCreate"
extraMounts:
- hostPath: /tmp/pss
containerPath: /etc/config
# optional: if set, the mount is read-only.
# default false
readOnly: false
# optional: if set, the mount needs SELinux relabeling.
# default false
selinuxRelabel: false
# optional: set propagation mode (None, HostToContainer or Bidirectional)
# see https://kubernetes.io/ko/docs/concepts/storage/volumes/#๋ง์ดํธ-์ ํ-propagation
# default None
propagation: None
EOF
์ฐธ๊ณ : macOS์์ Docker Desktop๊ณผ KinD๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด,
Preferences > Resources > File Sharing ๋ฉ๋ด์์
/tmp
๋ฅผ Shared Directory๋ก ์ถ๊ฐํ ์ ์๋ค.์ด๋ฌํ ํ๋ ์ํ๋ฆฌํฐ ์คํ ๋ค๋๋ฅผ ์ ์ฉํ๊ธฐ ์ํด
ํ๋ ์ํ๋ฆฌํฐ ์ด๋๋ฏธ์
์ ์ฌ์ฉํ๋ ํด๋ฌ์คํฐ๋ฅผ ์์ฑํ๋ค.
kind create cluster --name psa-with-cluster-pss --image kindest/node:v1.24.0 --config /tmp/pss/cluster-config.yaml
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Creating cluster "psa-with-cluster-pss" ...
โ Ensuring node image (kindest/node:v1.24.0) ๐ผ
โ Preparing nodes ๐ฆ
โ Writing configuration ๐
โ Starting control-plane ๐น๏ธ
โ Installing CNI ๐
โ Installing StorageClass ๐พ
Set kubectl context to "kind-psa-with-cluster-pss"
You can now use your cluster with:
kubectl cluster-info --context kind-psa-with-cluster-pss
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community ๐
kubectl context๋ฅผ ์๋ก ์์ฑํ ํด๋ฌ์คํฐ๋ก ์ค์ ํ๋ค.
kubectl cluster-info --context kind-psa-with-cluster-pss
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Kubernetes control plane is running at https://127.0.0.1:63855
CoreDNS is running at https://127.0.0.1:63855/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
๊ธฐ๋ณธ ๋ค์์คํ์ด์ค์ ์์ฑํ ์ต์ํ์ ๊ตฌ์ฑ์ ๋ํ ํ๋ ๋ช
์ธ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.
cat <<EOF > /tmp/pss/nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
EOF
ํด๋ฌ์คํฐ์ ํด๋น ํ๋๋ฅผ ์์ฑํ๋ค.
kubectl apply -f /tmp/pss/nginx-pod.yaml
๋ค์๊ณผ ๋น์ทํ๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
pod/nginx created
์ ๋ฆฌํ๊ธฐ kind delete cluster --name psa-with-cluster-pss
๋ฐ
kind delete cluster --name psa-wo-cluster-pss
๋ช
๋ น์ ์คํํ์ฌ
์์ฑํ๋ ํด๋ฌ์คํฐ๋ฅผ ์ญ์ ํ๋ค.
๋ค์ ๋ด์ฉ
5 - ์ํ ์ ์ง๋ฅผ ํ์ง ์๋ ์ ํ๋ฆฌ์ผ์ด์
5.1 - ์ธ๋ถ IP ์ฃผ์๋ฅผ ๋
ธ์ถํ์ฌ ํด๋ฌ์คํฐ์ ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ํ๊ธฐ ์ด ํ์ด์ง์์๋ ์ธ๋ถ IP ์ฃผ์๋ฅผ ๋
ธ์ถํ๋
์ฟ ๋ฒ๋คํฐ์ค ์๋น์ค ์ค๋ธ์ ํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช
ํ๋ค.
์์ํ๊ธฐ ์ ์ kubectl ์ ์ค์นํ๋ค.Google Kubernetes Engine ๋๋ Amazon Web Services์ ๊ฐ์ ํด๋ผ์ฐ๋ ๊ณต๊ธ์๋ฅผ ์ฌ์ฉํ์ฌ
์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ฅผ ์์ฑํ๋ค. ์ด ํํ ๋ฆฌ์ผ์
์ธ๋ถ ๋ก๋ ๋ฐธ๋ฐ์ ๋ฅผ ์์ฑํ๋๋ฐ,
ํด๋ผ์ฐ๋ ๊ณต๊ธ์๊ฐ ํ์ํ๋ค. kubectl
์ด ์ฟ ๋ฒ๋คํฐ์ค API ์๋ฒ์ ํต์ ํ๋๋ก ์ค์ ํ๋ค.
์์ธํ ๋ด์ฉ์ ํด๋ผ์ฐ๋ ๊ณต๊ธ์์ ์ค๋ช
์ ์ฐธ๊ณ ํ๋ค.๋ชฉ์ Hello World ์ ํ๋ฆฌ์ผ์ด์
์ ๋ค์ฏ ๊ฐ์ ์ธ์คํด์ค๋ก ์คํํ๋ค. ์ธ๋ถ IP ์ฃผ์๋ฅผ ๋
ธ์ถํ๋ ์๋น์ค๋ฅผ ์์ฑํ๋ค. ์คํ ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ ์ ๊ทผํ๊ธฐ ์ํด ์๋น์ค ์ค๋ธ์ ํธ๋ฅผ ์ฌ์ฉํ๋ค. ๋ค์ฏ ๊ฐ์ ํ๋์์ ์คํ๋๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ํ ์๋น์ค ๋ง๋ค๊ธฐ ํด๋ฌ์คํฐ์์ Hello World ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ๋ค.
apiVersion : apps/v1
kind : Deployment
metadata :
labels :
app.kubernetes.io/name : load-balancer-example
name : hello-world
spec :
replicas : 5
selector :
matchLabels :
app.kubernetes.io/name : load-balancer-example
template :
metadata :
labels :
app.kubernetes.io/name : load-balancer-example
spec :
containers :
- image : gcr.io/google-samples/node-hello:1.0
name : hello-world
ports :
- containerPort : 8080
kubectl apply -f https://k8s.io/examples/service/load-balancer-example.yaml
์์ ๋ช
๋ น์ด๋
๋ํ๋ก์ด๋จผํธ(Deployment)
์ค๋ธ์ ํธ์ ๊ด๋ จ๋
๋ ํ๋ฆฌ์นด์
(ReplicaSet)
์ค๋ธ์ ํธ๋ฅผ ์์ฑํ๋ค. ๋ ํ๋ฆฌ์นด์
์ ๋ค์ฏ ๊ฐ์
ํ๋ ๊ฐ ์์ผ๋ฉฐ,
๊ฐ ํ๋๋ Hello World ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ๋ค.
๋ํ๋ก์ด๋จผํธ์ ๋ํ ์ ๋ณด๋ฅผ ํ์ธํ๋ค.
kubectl get deployments hello-world
kubectl describe deployments hello-world
๋ ํ๋ฆฌ์นด์
์ค๋ธ์ ํธ์ ๋ํ ์ ๋ณด๋ฅผ ํ์ธํ๋ค.
kubectl get replicasets
kubectl describe replicasets
๋ํ๋ก์ด๋จผํธ๋ฅผ ์ธ๋ถ๋ก ๋
ธ์ถ์ํค๋ ์๋น์ค ์ค๋ธ์ ํธ๋ฅผ ์์ฑํ๋ค.
kubectl expose deployment hello-world --type= LoadBalancer --name= my-service
์๋น์ค์ ๋ํ ์ ๋ณด๋ฅผ ํ์ธํ๋ค.
kubectl get services my-service
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service LoadBalancer 10.3.245.137 104.198.205.71 8080/TCP 54s
์ฐธ๊ณ : `type=LoadBalancer` ์๋น์ค๋ ์ด ์์์์ ๋ค๋ฃจ์ง ์์ ์ธ๋ถ ํด๋ผ์ฐ๋ ๊ณต๊ธ์๊ฐ ์ง์ํ๋ฉฐ, ์์ธํ ๋ด์ฉ์ [์ด ํ์ด์ง](/ko/docs/concepts/services-networking/service/#loadbalancer)๋ฅผ ์ฐธ์กฐํ๋ค.
์ฐธ๊ณ : ๋ง์ฝ ์ธ๋ถ IP ์ฃผ์๊ฐ \<pending\>์ผ๋ก ํ์๋๋ฉด ์ ์ ๊ธฐ๋ค๋ฆฐ ๋ค์, ๋์ผํ ๋ช
๋ น์ด๋ฅผ ๋ค์ ์
๋ ฅํ๋ค.
์๋น์ค์ ๋ํ ์์ธํ ์ ๋ณด๋ฅผ ํ์ธํ๋ค.
kubectl describe services my-service
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ์ ์ฌํ๋ค.
Name: my-service
Namespace: default
Labels: app.kubernetes.io/name=load-balancer-example
Annotations: <none>
Selector: app.kubernetes.io/name=load-balancer-example
Type: LoadBalancer
IP: 10.3.245.137
LoadBalancer Ingress: 104.198.205.71
Port: <unset> 8080/TCP
NodePort: <unset> 32377/TCP
Endpoints: 10.0.0.6:8080,10.0.1.6:8080,10.0.1.7:8080 + 2 more...
Session Affinity: None
Events: <none>
์๋น์ค์ ์ํด ๋
ธ์ถ๋ ์ธ๋ถ IP ์ฃผ์ (LoadBalancer Ingress
)๋ฅผ ๊ธฐ์ตํด๋์.
์์์์ ์ธ๋ถ IP ์ฃผ์๋ 104.198.205.71์ด๋ค.
๊ทธ๋ฆฌ๊ณ Port
์NodePort
์ ๊ฐ์ ๊ธฐ์ตํด๋์.
์์์์ Port
๋ 8080์ด๊ณ NodePort
๋ 32377์ด๋ค.
์์ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ํตํด, ์๋น์ค์ ์ฌ๋ฌ ์๋ํฌ์ธํธ๊ฐ ์์์ ์ ์ ์๋ค.
10.0.0.6:8080,10.0.1.6:8080,10.0.1.7:8080 + 2.
์ด ์ฃผ์๋ Hello World ์ ํ๋ฆฌ์ผ์ด์
์ ์คํ ์ค์ธ ํ๋์ ๋ด๋ถ ์ฃผ์๋ค.
ํด๋น ์ฃผ์๊ฐ ํ๋ ์ฃผ์์ธ์ง ํ์ธํ๋ ค๋ฉด, ์๋ ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ๋ฉด ๋๋ค.
kubectl get pods --output= wide
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ์ ์ฌํ๋ค.
NAME ... IP NODE
hello-world-2895499144-1jaz9 ... 10.0.1.6 gke-cluster-1-default-pool-e0b8d269-1afc
hello-world-2895499144-2e5uh ... 10.0.1.8 gke-cluster-1-default-pool-e0b8d269-1afc
hello-world-2895499144-9m4h1 ... 10.0.0.6 gke-cluster-1-default-pool-e0b8d269-5v7a
hello-world-2895499144-o4z13 ... 10.0.1.7 gke-cluster-1-default-pool-e0b8d269-1afc
hello-world-2895499144-segjf ... 10.0.2.5 gke-cluster-1-default-pool-e0b8d269-cpuc
Hello World ์ ํ๋ฆฌ์ผ์ด์
์ ์ ๊ทผํ๊ธฐ ์ํด
์ธ๋ถ IP ์ฃผ์ (LoadBalancer Ingress
)๋ฅผ ์ฌ์ฉํ๋ค.
curl http://<external-ip>:<port>
<external-ip>
๋ ์๋น์ค์ ์ธ๋ถ IP ์ฃผ์ (LoadBalancer Ingress
)๋ฅผ ์๋ฏธํ๋ฉฐ,
<port>
๋ ์๋น์ค ์ ๋ณด์์ Port
๊ฐ์
์๋ฏธํ๋ค.
๋ง์ฝ minikube๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, minikube service my-service
๋ช
๋ น์ด๋ฅผ ํตํด,
์๋์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ด์์ Hello World ์ ํ๋ฆฌ์ผ์ด์
์ ์ ๊ทผํ ์ ์๋ค.
์ฑ๊ณต์ ์ธ ์์ฒญ์ ๋ํ ์๋ต์ผ๋ก hello ๋ฉ์ธ์ง๊ฐ ๋ํ๋๋ค.
์ ๋ฆฌํ๊ธฐ ์๋น์ค๋ฅผ ์ญ์ ํ๋ ค๋ฉด, ์๋์ ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ๋ค.
kubectl delete services my-service
Hello World ์ ํ๋ฆฌ์ผ์ด์
์ ์คํ ์ค์ธ ๋ํ๋ก์ด๋จผํธ, ๋ ํ๋ฆฌ์นด์
, ํ๋๋ฅผ ์ญ์ ํ๋ ค๋ฉด,
์๋์ ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ๋ค.
kubectl delete deployment hello-world
๋ค์ ๋ด์ฉ ์ ํ๋ฆฌ์ผ์ด์
๊ณผ ์๋น์ค ์ฐ๊ฒฐํ๊ธฐ ์ ๋ํด
๋ ๋ฐฐ์ ๋ณธ๋ค.
5.2 - ์์: Redis๋ฅผ ์ฌ์ฉํ PHP ๋ฐฉ๋ช
๋ก ์ ํ๋ฆฌ์ผ์ด์
๋ฐฐํฌํ๊ธฐ ์ด ํํ ๋ฆฌ์ผ์์๋ ์ฟ ๋ฒ๋คํฐ์ค์ Docker ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ
(์ด์ ์์ค์ด ์๋) ๋ฉํฐ ํฐ์ด ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๋น๋ํ๊ณ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋ค.
์ด ์์ ๋ ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์ฑ์ผ๋ก
์ด๋ฃจ์ด์ ธ ์๋ค.
๋ฐฉ๋ช
๋ก ํญ๋ชฉ์ ์ ์ฅํ๊ธฐ ์ํ ๋จ์ผ ์ธ์คํด์ค Redis ์ฌ๋ฌ ๊ฐ์ ์น ํ๋ก ํธ์๋ ์ธ์คํด์ค ๋ชฉ์ Redis ๋ฆฌ๋๋ฅผ ์คํ 2๊ฐ์ Redis ํ๋ก์๋ฅผ ์คํ ๋ฐฉ๋ช
๋ก ํ๋ก ํธ์๋๋ฅผ ์คํ ํ๋ก ํธ์๋ ์๋น์ค๋ฅผ ๋
ธ์ถํ๊ณ ํ์ธ ์ ๋ฆฌํ๊ธฐ ์์ํ๊ธฐ ์ ์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๊ฐ ํ์ํ๊ณ , kubectl ์ปค๋งจ๋-๋ผ์ธ ํด์ด ํด๋ฌ์คํฐ์
ํต์ ํ ์ ์๋๋ก ์ค์ ๋์ด ์์ด์ผ ํ๋ค. ์ด ํํ ๋ฆฌ์ผ์ ์ปจํธ๋กค ํ๋ ์ธ ํธ์คํธ๊ฐ ์๋ ๋
ธ๋๊ฐ ์ ์ด๋ 2๊ฐ ํฌํจ๋ ํด๋ฌ์คํฐ์์ ์คํํ๋ ๊ฒ์ ์ถ์ฒํ๋ค. ๋ง์ฝ, ์์ง ํด๋ฌ์คํฐ๋ฅผ ๊ฐ์ง๊ณ
์์ง ์๋ค๋ฉด,
minikube ๋ฅผ ์ฌ์ฉํด์ ์์ฑํ๊ฑฐ๋
๋ค์ ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ์ด๊ทธ๋ผ์ด๋ ์ค ํ๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ฟ ๋ฒ๋คํฐ์ค ์๋ฒ์ ๋ฒ์ ์ ๋ค์๊ณผ ๊ฐ๊ฑฐ๋ ๋ ๋์์ผ ํจ. ๋ฒ์ : v1.14.
๋ฒ์ ํ์ธ์ ์ํด์, ๋ค์ ์ปค๋งจ๋๋ฅผ ์คํ kubectl version
.
Redis ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์คํ ๋ฐฉ๋ช
๋ก ์ ํ๋ฆฌ์ผ์ด์
์ Redis๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค.
Redis ๋ํ๋ก์ด๋จผํธ๋ฅผ ์์ฑํ๊ธฐ ์๋์ ๋งค๋ํ์คํธ ํ์ผ์ ๋จ์ผ ๋ณต์ ๋ณธ Redis ํ๋๋ฅผ ์คํํ๋ ๋ํ๋ก์ด๋จผํธ ์ปจํธ๋กค๋ฌ์ ๋ํ ๋ช
์ธ๋ฅผ ๋ด๊ณ ์๋ค.
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion : apps/v1
kind : Deployment
metadata :
name : redis-leader
labels :
app : redis
role : leader
tier : backend
spec :
replicas : 1
selector :
matchLabels :
app : redis
template :
metadata :
labels :
app : redis
role : leader
tier : backend
spec :
containers :
- name : leader
image : "docker.io/redis:6.0.5"
resources :
requests :
cpu : 100m
memory : 100Mi
ports :
- containerPort : 6379
๋งค๋ํ์คํธ ํ์ผ์ ๋ค์ด๋ก๋ํ ๋๋ ํฐ๋ฆฌ์์ ํฐ๋ฏธ๋ ์ฐฝ์ ์์ํ๋ค.
redis-leader-deployment.yaml
ํ์ผ์ ์ด์ฉํ์ฌ Redis ๋ํ๋ก์ด๋จผํธ๋ฅผ ์์ฑํ๋ค.
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
ํ๋์ ๋ชฉ๋ก์ ์ง์ํ์ฌ Redis ํ๋๊ฐ ์คํ ์ค์ธ์ง ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME READY STATUS RESTARTS AGE
redis-leader-fb76b4755-xjr2n 1/1 Running 0 13s
Redis ๋ฆฌ๋ ํ๋์ ๋ก๊ทธ๋ฅผ ๋ณด๋ ค๋ฉด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
kubectl logs -f deployment/redis-leader
Redis ๋ฆฌ๋ ์๋น์ค ์์ฑํ๊ธฐ ๋ฐฉ๋ช
๋ก ์ ํ๋ฆฌ์ผ์ด์
์์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ค๋ฉด Redis์ ํต์ ํด์ผ ํ๋ค.
Redis ํ๋๋ก ํธ๋ํฝ์ ํ๋ก์ํ๋ ค๋ฉด ์๋น์ค ๋ฅผ ์์ฑํด์ผ ํ๋ค.
์๋น์ค๋ ํ๋์ ์ ๊ทผํ๊ธฐ ์ํ ์ ์ฑ
์
์ ์ํ๋ค.
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion : v1
kind : Service
metadata :
name : redis-leader
labels :
app : redis
role : leader
tier : backend
spec :
ports :
- port : 6379
targetPort : 6379
selector :
app : redis
role : leader
tier : backend
redis-leader-service.yaml
ํ์ผ์ ์ด์ฉํ์ฌ Redis ์๋น์ค๋ฅผ ์คํํ๋ค.
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml
์๋น์ค์ ๋ชฉ๋ก์ ์ง์ํ์ฌ Redis ์๋น์ค๊ฐ ์คํ ์ค์ธ์ง ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1m
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 16s
์ฐธ๊ณ : ์ด ๋งค๋ํ์คํธ ํ์ผ์ ์ด์ ์ ์ ์๋ ๋ ์ด๋ธ๊ณผ ์ผ์นํ๋ ๋ ์ด๋ธ ์งํฉ์ ๊ฐ์ง
redis-leader
๋ผ๋ ์๋น์ค๋ฅผ ์์ฑํ๋ฏ๋ก, ์๋น์ค๋ ๋คํธ์ํฌ ํธ๋ํฝ์
Redis ํ๋๋ก ๋ผ์ฐํ
ํ๋ค.Redis ํ๋ก์ ๊ตฌ์ฑํ๊ธฐ Redis ๋ฆฌ๋๋ ๋จ์ผ ํ๋์ด์ง๋ง, ๋ช ๊ฐ์ Redis ํ๋ก์ ๋๋ ๋ณต์ ๋ณธ์ ์ถ๊ฐํ์ฌ
๊ฐ์ฉ์ฑ์ ๋์ด๊ณ ํธ๋ํฝ ์๊ตฌ๋ฅผ ์ถฉ์กฑํ ์ ์๋ค.
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion : apps/v1
kind : Deployment
metadata :
name : redis-follower
labels :
app : redis
role : follower
tier : backend
spec :
replicas : 2
selector :
matchLabels :
app : redis
template :
metadata :
labels :
app : redis
role : follower
tier : backend
spec :
containers :
- name : follower
image : gcr.io/google_samples/gb-redis-follower:v2
resources :
requests :
cpu : 100m
memory : 100Mi
ports :
- containerPort : 6379
redis-follower-deployment.yaml
ํ์ผ์ ์ด์ฉํ์ฌ Redis ์๋น์ค๋ฅผ ์คํํ๋ค.
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml
ํ๋์ ๋ชฉ๋ก์ ์ง์ํ์ฌ 2๊ฐ์ Redis ํ๋ก์ ๋ ํ๋ฆฌ์นด๊ฐ ์คํ ์ค์ธ์ง ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME READY STATUS RESTARTS AGE
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 37s
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 38s
redis-leader-fb76b4755-xjr2n 1/1 Running 0 11m
Redis ํ๋ก์ ์๋น์ค ์์ฑํ๊ธฐ ๋ฐฉ๋ช
๋ก ์ ํ๋ฆฌ์ผ์ด์
์ด ๋ฐ์ดํฐ๋ฅผ ์ฝ์ผ๋ ค๋ฉด Redis ํ๋ก์์ ํต์ ํด์ผ ํ๋ค.
Redis ํ๋ก์๋ฅผ ๋ฐ๊ฒฌ ๊ฐ๋ฅ(discoverable)ํ๊ฒ ๋ง๋๋ ค๋ฉด, ์๋ก์ด
์๋น์ค ๋ฅผ ๊ตฌ์ฑํด์ผ ํ๋ค.
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion : v1
kind : Service
metadata :
name : redis-follower
labels :
app : redis
role : follower
tier : backend
spec :
ports :
# the port that this service should serve on
- port : 6379
selector :
app : redis
role : follower
tier : backend
redis-follower-service.yaml
ํ์ผ์ ์ด์ฉํ์ฌ Redis ์๋น์ค๋ฅผ ์คํํ๋ค.
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml
์๋น์ค์ ๋ชฉ๋ก์ ์ง์ํ์ฌ Redis ์๋น์ค๊ฐ ์คํ ์ค์ธ์ง ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 9s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 6m10s
์ฐธ๊ณ : ์ด ๋งค๋ํ์คํธ ํ์ผ์ ์ด์ ์ ์ ์๋ ๋ ์ด๋ธ๊ณผ ์ผ์นํ๋ ๋ ์ด๋ธ ์งํฉ์ ๊ฐ์ง
redis-follower
๋ผ๋ ์๋น์ค๋ฅผ ์์ฑํ๋ฏ๋ก, ์๋น์ค๋ ๋คํธ์ํฌ ํธ๋ํฝ์
Redis ํ๋๋ก ๋ผ์ฐํ
ํ๋ค.๋ฐฉ๋ช
๋ก ํ๋ก ํธ์๋๋ฅผ ์ค์ ํ๊ณ ๋
ธ์ถํ๊ธฐ ๋ฐฉ๋ช
๋ก์ ์ํ Redis ์ ์ฅ์๋ฅผ ๊ตฌ์ฑํ๊ณ ์คํํ์ผ๋ฏ๋ก, ์ด์ ๋ฐฉ๋ช
๋ก ์น ์๋ฒ๋ฅผ ์คํํ๋ค.
Redis ํ๋ก์์ ๋ง์ฐฌ๊ฐ์ง๋ก, ํ๋ก ํธ์๋๋ ์ฟ ๋ฒ๋คํฐ์ค ๋ํ๋ก์ด๋จผํธ(Deployment)๋ฅผ
์ฌ์ฉํ์ฌ ๋ฐฐํฌ๋๋ค.
๋ฐฉ๋ช
๋ก ์ฑ์ PHP ํ๋ก ํธ์๋๋ฅผ ์ฌ์ฉํ๋ค. DB์ ๋ํ ์์ฒญ์ด ์ฝ๊ธฐ์ธ์ง ์ฐ๊ธฐ์ธ์ง์ ๋ฐ๋ผ,
Redis ํ๋ก์ ๋๋ ๋ฆฌ๋ ์๋น์ค์ ํต์ ํ๋๋ก ๊ตฌ์ฑ๋๋ค. ํ๋ก ํธ์๋๋ JSON ์ธํฐํ์ด์ค๋ฅผ
๋
ธ์ถํ๊ณ ,
jQuery-Ajax ๊ธฐ๋ฐ UX๋ฅผ ์ ๊ณตํ๋ค.
๋ฐฉ๋ช
๋ก ํ๋ก ํธ์๋์ ๋ํ๋ก์ด๋จผํธ ์์ฑํ๊ธฐ # SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion : apps/v1
kind : Deployment
metadata :
name : frontend
spec :
replicas : 3
selector :
matchLabels :
app : guestbook
tier : frontend
template :
metadata :
labels :
app : guestbook
tier : frontend
spec :
containers :
- name : php-redis
image : gcr.io/google_samples/gb-frontend:v5
env :
- name : GET_HOSTS_FROM
value : "dns"
resources :
requests :
cpu : 100m
memory : 100Mi
ports :
- containerPort : 80
frontend-deployment.yaml
ํ์ผ์ ์ด์ฉํ์ฌ ํ๋ก ํธ์๋ ๋ํ๋ก์ด๋จผํธ๋ฅผ ์์ฑํ๋ค.
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
ํ๋์ ๋ชฉ๋ก์ ์ง์ํ์ฌ ์ธ ๊ฐ์ ํ๋ก ํธ์๋ ๋ณต์ ๋ณธ์ด ์คํ๋๊ณ ์๋์ง ํ์ธํ๋ค.
kubectl get pods -l app = guestbook -l tier = frontend
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5tqhb 1/1 Running 0 47s
frontend-85595f5bf9-qbzwm 1/1 Running 0 47s
frontend-85595f5bf9-zchwc 1/1 Running 0 47s
ํ๋ก ํธ์๋ ์๋น์ค ์์ฑํ๊ธฐ ์๋น์ค์ ๊ธฐ๋ณธ ์ ํ์
ClusterIP
์ด๊ธฐ ๋๋ฌธ์ ์์ฑํ Redis
์๋น์ค๋ ์ปจํ
์ด๋ ํด๋ฌ์คํฐ ๋ด์์๋ง ์ ๊ทผํ ์ ์๋ค.
ClusterIP
๋ ์๋น์ค๊ฐ ๊ฐ๋ฆฌํค๋ ํ๋ ์งํฉ์ ๋ํ
๋จ์ผ IP ์ฃผ์๋ฅผ ์ ๊ณตํ๋ค. ์ด IP ์ฃผ์๋ ํด๋ฌ์คํฐ ๋ด์์๋ง ์ ๊ทผํ ์ ์๋ค.
๊ฒ์คํธ๊ฐ ๋ฐฉ๋ช
๋ก์ ์ ๊ทผํ ์ ์๋๋ก ํ๋ ค๋ฉด, ์ธ๋ถ์์ ๋ณผ ์ ์๋๋ก ํ๋ก ํธ์๋
์๋น์ค๋ฅผ ๊ตฌ์ฑํด์ผ ํ๋ค. ๊ทธ๋ ๊ฒ ํ๋ฉด ํด๋ผ์ด์ธํธ๊ฐ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ์ธ๋ถ์์
์๋น์ค๋ฅผ ์์ฒญํ ์ ์๋ค. ๊ทธ๋ฌ๋ ์ฟ ๋ฒ๋คํฐ์ค ์ฌ์ฉ์๋ ClusterIP
๋ฅผ
์ฌ์ฉํ๋๋ผ๋ kubectl port-forward
๋ฅผ ์ฌ์ฉํด์ ์๋น์ค์
์ ๊ทผํ ์ ์๋ค.
์ฐธ๊ณ : Google Compute Engine ๋๋ Google Kubernetes Engine
๊ณผ ๊ฐ์ ์ผ๋ถ ํด๋ผ์ฐ๋ ๊ณต๊ธ์๋ ์ธ๋ถ ๋ก๋ ๋ฐธ๋ฐ์๋ฅผ ์ง์ํ๋ค. ํด๋ผ์ฐ๋ ๊ณต๊ธ์๊ฐ ๋ก๋
๋ฐธ๋ฐ์๋ฅผ ์ง์ํ๊ณ ์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด type : LoadBalancer
์ ์ฃผ์์ ์ ๊ฑฐํด์ผ ํ๋ค.# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion : v1
kind : Service
metadata :
name : frontend
labels :
app : guestbook
tier : frontend
spec :
# if your cluster supports it, uncomment the following to automatically create
# an external load-balanced IP for the frontend service.
# type: LoadBalancer
#type: LoadBalancer
ports :
# the port that this service should serve on
- port : 80
selector :
app : guestbook
tier : frontend
frontend-service.yaml
ํ์ผ์ ์ด์ฉํ์ฌ ํ๋ก ํธ์๋ ์๋น์ค๋ฅผ ์คํํ๋ค.
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
์๋น์ค์ ๋ชฉ๋ก์ ์ง์ํ์ฌ ํ๋ก ํธ์๋ ์๋น์ค๊ฐ ์คํ ์ค์ธ์ง ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.97.28.230 <none> 80/TCP 19s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 5m48s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 11m
kubectl port-forward
๋ฅผ ํตํด ํ๋ก ํธ์๋ ์๋น์ค ํ์ธํ๊ธฐ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํด์ ๋ก์ปฌ ๋จธ์ ์ 8080
ํฌํธ๋ฅผ ์๋น์ค์ 80
ํฌํธ๋ก ์ ๋ฌํ๋ค.
kubectl port-forward svc/frontend 8080:80
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
๋ฐฉ๋ช
๋ก์ ๋ณด๊ธฐ ์ํด ๋ธ๋ผ์ฐ์ ์์ http://localhost:8080 ํ์ด์ง๋ฅผ ๋ก๋ํ๋ค.
LoadBalancer
๋ฅผ ํตํด ํ๋ก ํธ์๋ ์๋น์ค ํ์ธํ๊ธฐfrontend-service.yaml
๋งค๋ํ์คํธ๋ฅผ LoadBalancer
์ ํจ๊ป ๋ฐฐํฌํ ๊ฒฝ์ฐ,
๋ฐฉ๋ช
๋ก์ ๋ณด๊ธฐ ์ํด IP ์ฃผ์๋ฅผ ์ฐพ์์ผ ํ๋ค.
ํ๋ก ํธ์๋ ์๋น์ค์ IP ์ฃผ์๋ฅผ ์ป๊ธฐ ์ํด ์๋ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
kubectl get service frontend
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.51.242.136 109.197.92.229 80:32372/TCP 1m
IP ์ฃผ์๋ฅผ ๋ณต์ฌํ๊ณ , ๋ฐฉ๋ช
๋ก์ ๋ณด๊ธฐ ์ํด ๋ธ๋ผ์ฐ์ ์์ ํ์ด์ง๋ฅผ ๋ก๋ํ๋ค.
์ฐธ๊ณ : ๋ฉ์์ง๋ฅผ ์
๋ ฅํ๊ณ 'Submit'์ ํด๋ฆญํ์ฌ ๋ฐฉ๋ช
๋ก์ ๊ธ์ ์์ฑํด ๋ณธ๋ค.
์
๋ ฅํ ๋ฉ์์ง๊ฐ ํ๋ก ํธ์๋์ ๋ํ๋๋ค. ์ด ๋ฉ์์ง๋ ์์ ์์ฑํ ์๋น์ค๋ฅผ
ํตํด ๋ฐ์ดํฐ๊ฐ Redis์ ์ฑ๊ณต์ ์ผ๋ก ์
๋ ฅ๋์์์ ๋ํ๋ธ๋ค.์น ํ๋ก ํธ์๋ ํ์ฅํ๊ธฐ ์๋ฒ๊ฐ ๋ํ๋ก์ด๋จผํธ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ๋ ์๋น์ค๋ก ์ ์๋์ด ์์ผ๋ฏ๋ก
ํ์์ ๋ฐ๋ผ ํ์ฅ ๋๋ ์ถ์ํ ์ ์๋ค.
ํ๋ก ํธ์๋ ํ๋์ ์๋ฅผ ํ์ฅํ๊ธฐ ์ํด ์๋ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
kubectl scale deployment frontend --replicas= 5
ํ๋์ ๋ชฉ๋ก์ ์ง์ํ์ฌ ์คํ ์ค์ธ ํ๋ก ํธ์๋ ํ๋์ ์๋ฅผ ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5df5m 1/1 Running 0 83s
frontend-85595f5bf9-7zmg5 1/1 Running 0 83s
frontend-85595f5bf9-cpskg 1/1 Running 0 15m
frontend-85595f5bf9-l2l54 1/1 Running 0 14m
frontend-85595f5bf9-l9c8z 1/1 Running 0 14m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 97m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 97m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 108m
ํ๋ก ํธ์๋ ํ๋์ ์๋ฅผ ์ถ์ํ๊ธฐ ์ํด ์๋ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
kubectl scale deployment frontend --replicas= 2
ํ๋์ ๋ชฉ๋ก์ ์ง์ํ์ฌ ์คํ ์ค์ธ ํ๋ก ํธ์๋ ํ๋์ ์๋ฅผ ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-cpskg 1/1 Running 0 16m
frontend-85595f5bf9-l9c8z 1/1 Running 0 15m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 98m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 98m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 109m
์ ๋ฆฌํ๊ธฐ ๋ํ๋ก์ด๋จผํธ ๋ฐ ์๋น์ค๋ฅผ ์ญ์ ํ๋ฉด ์คํ ์ค์ธ ๋ชจ๋ ํ๋๋ ์ญ์ ๋๋ค.
๋ ์ด๋ธ์ ์ฌ์ฉํ์ฌ ํ๋์ ๋ช
๋ น์ด๋ก ์ฌ๋ฌ ์์์ ์ญ์ ํด๋ณด์.
๋ชจ๋ ํ๋, ๋ํ๋ก์ด๋จผํธ, ์๋น์ค๋ฅผ ์ญ์ ํ๊ธฐ ์ํด ์๋ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
kubectl delete deployment -l app = redis
kubectl delete service -l app = redis
kubectl delete deployment frontend
kubectl delete service frontend
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
deployment.apps "redis-follower" deleted
deployment.apps "redis-leader" deleted
deployment.apps "frontend" deleted
service "frontend" deleted
ํ๋์ ๋ชฉ๋ก์ ์ง์ํ์ฌ ์คํ ์ค์ธ ํ๋๊ฐ ์๋์ง ํ์ธํ๋ค.
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ ํํ๋ก ๋ํ๋๋ค.
No resources found in default namespace.
๋ค์ ๋ด์ฉ
6 - ์ํ ์ ์ง๊ฐ ํ์ํ(stateful) ์ ํ๋ฆฌ์ผ์ด์
6.1 - ์คํ
์ดํธํ์
๊ธฐ๋ณธ ์ด ํํ ๋ฆฌ์ผ์ ์คํ
์ดํธํ์
(StatefulSet) ์ ์ด์ฉํ์ฌ
์ ํ๋ฆฌ์ผ์ด์
์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๋ค.
์ด๋ป๊ฒ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์์ฑํ๊ณ , ์ญ์ ํ๋ฉฐ, ์ค์ผ์ผ๋งํ๊ณ , ์
๋ฐ์ดํธํ๋์ง ์์ฐํ๋ค.
์์ํ๊ธฐ ์ ์ ํํ ๋ฆฌ์ผ์ ์์ํ๊ธฐ ์ ์ ๋ค์์ ์ฟ ๋ฒ๋คํฐ์ค ์ปจ์
์ ๋ํด
์ต์ํด์ผ ํ๋ค.
์ฐธ๊ณ : ์ด ํํ ๋ฆฌ์ผ์ ํด๋ฌ์คํฐ๊ฐ ํผ์์คํด์ค๋ณผ๋ฅจ์ ๋์ ์ผ๋ก ํ๋ก๋น์ ๋ ํ๋๋ก
์ค์ ๋์๋ค๊ณ ๊ฐ์ ํ๋ค. ๋ง์ฝ ํด๋ฌ์คํฐ๊ฐ ์ด๋ ๊ฒ ์ค์ ๋์ด ์์ง ์๋ค๋ฉด,
ํํ ๋ฆฌ์ผ ์์ ์ ์ ์๋์ผ๋ก 2๊ฐ์ 1 GiB ๋ณผ๋ฅจ์
ํ๋ก๋น์ ๋ํด์ผ ํ๋ค.๋ชฉ์ ์คํ
์ดํธํ์
์ ์ํ ์ ์ง๊ฐ ํ์ํ(stateful) ์ ํ๋ฆฌ์ผ์ด์
๊ณผ ๋ถ์ฐ์์คํ
์์
์ด์ฉํ๋๋ก ์๋ํ๋ค. ๊ทธ๋ฌ๋ ์ฟ ๋ฒ๋คํฐ์ค ์์ ์คํ
์ดํธํ ์ ํ๋ฆฌ์ผ์ด์
๊ณผ
๋ถ์ฐ์์คํ
์ ๊ด๋ฆฌํ๋ ๊ฒ์ ๊ด๋ฒ์ํ๊ณ ๋ณต์กํ ์ฃผ์ ์ด๋ค. ์คํ
์ดํธํ์
์ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด
์ด ๋์ ๊ฒฐํฉํ์ง ์๊ณ , ์คํ
์ดํธํ์
์ ์ฌ์ฉํ
๋จ์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ๊ฒ์ด๋ค.
์ด ํํ ๋ฆฌ์ผ์ ๋ง์น๋ฉด ๋ค์ ํญ๋ชฉ์ ๋ํด ์ต์ํด์ง ๊ฒ์ด๋ค.
์คํ
์ดํธํ์
์ ์ด๋ป๊ฒ ์์ฑํ๋์ง ์คํ
์ดํธํ์
์ด ์ด๋ป๊ฒ ํ๋๋ฅผ ๊ด๋ฆฌํ๋์ง ์คํ
์ดํธํ์
์ ์ด๋ป๊ฒ ์ญ์ ํ๋์ง ์คํ
์ดํธํ์
์ ์ด๋ป๊ฒ ์ค์ผ์ผ๋งํ๋์ง ์คํ
์ดํธํ์
์ ํ๋๋ ์ด๋ป๊ฒ ์
๋ฐ์ดํธํ๋์ง ์คํ
์ดํธํ์
์์ฑํ๊ธฐ ์๋ ์์ ๋ฅผ ์ด์ฉํด์ ์คํ
์ดํธํ์
์ ์์ฑํ์. ์ด๋
์คํ
์ดํธํ์
๊ฐ๋
์์ ๋ณด์ธ
์์ ์ ์ ์ฌํ๋ค. ์ด๊ฒ์ web
๊ณผ ์ด ์คํ
์ดํธํ์
ํ๋์ IP ์ฃผ์๋ฅผ ๊ฒ์ํ๋
ํค๋๋ฆฌ์ค ์๋น์ค ์ธ
nginx
๋ฅผ ์์ฑํ๋ค.
apiVersion : v1
kind : Service
metadata :
name : nginx
labels :
app : nginx
spec :
ports :
- port : 80
name : web
clusterIP : None
selector :
app : nginx
---
apiVersion : apps/v1
kind : StatefulSet
metadata :
name : web
spec :
serviceName : "nginx"
replicas : 2
selector :
matchLabels :
app : nginx
template :
metadata :
labels :
app : nginx
spec :
containers :
- name : nginx
image : registry.k8s.io/nginx-slim:0.8
ports :
- containerPort : 80
name : web
volumeMounts :
- name : www
mountPath : /usr/share/nginx/html
volumeClaimTemplates :
- metadata :
name : www
spec :
accessModes : [ "ReadWriteOnce" ]
resources :
requests :
storage : 1Gi
์์ ์์ ๋ฅผ ๋ค์ด๋ก๋ ๋ฐ์์ ํ์ผ์ด๋ฆ์ web.yaml
์ผ๋ก ์ ์ฅํ์.
2๊ฐ์ ํฐ๋ฏธ๋์ฐฝ์ ์ฌ์ฉํ๋ค. ์ฒซ์งธ ํฐ๋ฏธ๋์์
kubectl get
์ ์ด์ฉํด์
์คํ
์ดํธํ์
์ ํ๋๊ฐ ์์ฑ๋๋์ง ๊ฐ์ํ์.
kubectl get pods -w -l app = nginx
๋ ๋ฒ์งธ ํฐ๋ฏธ๋์์
kubectl apply
๋ก
web.yaml
์ ์ ์๋ ํค๋๋ฆฌ์ค ์๋น์ค์ ์คํ
์ดํธํ์
์ ์์ฑํ๋ค.
kubectl apply -f web.yaml
service/nginx created
statefulset.apps/web created
์๊ธฐ ๋ช
๋ น์ด๋ NGINX ์น ์๋ฒ๋ฅผ
์คํํ๋ 2๊ฐ์ ํ๋๋ฅผ ์์ฑํ๋ค. nginx
์๋น์ค์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
kubectl get service nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 12s
๊ทธ๋ฆฌ๊ณ web
์คํ
์ดํธํ์
์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ ๋ชจ๋ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์๋์ง ํ์ธํ๋ค.
kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 1 20s
์ฐจ๋ก๋๋ก ํ๋ ์์ฑํ๊ธฐ N๊ฐ์ ๋ ํ๋ฆฌ์นด๋ฅผ ๊ฐ์ง ์คํ
์ดํธํ์
์ ๋ฐฐํฌ ์์
์์ฐจ์ ์ผ๋ก {0..N-1} ์์ผ๋ก ์์ฑ๋๋ค.
์ฒซ์งธ ํฐ๋ฏธ๋์์ kubectl get
๋ช
๋ น์ ์ถ๋ ฅ ๋ด์ฉ์ ์ดํด๋ณด์.
๊ฒฐ๊ตญ ๊ทธ ๋ด์ฉ์ ์๋ ์์ ๋น์ทํ ๊ฒ์ด๋ค.
kubectl get pods -w -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 19s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
์ฐธ๊ณ ๋ก web-1
ํ๋๋ web-0
ํ๋๊ฐ
Running (ํ๋์ ๋จ๊ณ ์ฐธ๊ณ )
๋ฐ Ready (ํ๋์ ์ปจ๋์
์์ type
์ฐธ๊ณ ) ์ํ๊ฐ ๋๊ธฐ ์ ์๋ ์์๋์ง ์์์ ์ฃผ์ํ๋ค.
์ฐธ๊ณ : ์คํ
์ดํธํ์
์์ ๊ฐ ํ๋์ ํ ๋น๋๋ ์ ์๊ฐ์ ์์๋ฅผ ์ค์ ํ๋ ค๋ฉด,
์์ ์์ ๋ฅผ ํ์ธํ๋ค.
์คํ
์ดํธํ์
์์ ํ๋ ์คํ
์ดํธํ์
์์ ํ๋๋ ๊ณ ์ ํ ์๋ฒ๊ณผ ๋์ผํ ๋คํธ์ํฌ ์ ์์ ๊ฐ์ง๋ค.
ํ๋ ์๋ฒ ์ดํด๋ณด๊ธฐ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ ธ์ค์.
kubectl get pods -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 1m
web-1 1/1 Running 0 1m
์คํ
์ดํธํ์
๊ฐ๋
์์
์ธ๊ธํ๋ฏ ์คํ
์ดํธํ์
์ ํ๋๋ ๋๋ํ๊ณ ๊ณ ์ ํ ์ ์ฒด์ฑ์ ๊ฐ์ง๋ค.
์ด ์ ์ฒด์ฑ์ ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ ์์
๊ฐ ํ๋์ ์ฃผ์ด์ง๋ ๊ณ ์ ํ ์๋ฒ์ ๊ธฐ์ธํ๋ค. ํ๋์ ์ด๋ฆ์ ํ์์
<์คํ
์ดํธํ์
์ด๋ฆ>-<์๋ฒ>
์ด๋ค. ์์ web
์คํ
์ดํธํ์
์
2๊ฐ์ ๋ ํ๋ฆฌ์นด๋ฅผ ๊ฐ์ก์ผ๋ฏ๋ก web-0
๊ณผ web-1
2๊ฐ ํ๋๋ฅผ ์์ฑํ๋ค.
์์ ์ ์ธ ๋คํธ์ํฌ ์ ์ ์ฌ์ฉํ๊ธฐ ๊ฐ ํ๋๋ ๊ฐ ์๋ฒ์ ๋ฐ๋ฅธ ์์ ์ ์ธ ํธ์คํธ๋ค์์ ๊ฐ๋๋ค. ๊ฐ ํ๋์์
hostname
๋ช
๋ น์ด๋ฅผ ์คํํ๋๋ก
kubectl exec
๋ฅผ ์ด์ฉํ์.
for i in 0 1; do kubectl exec "web- $i " -- sh -c 'hostname' ; done
web-0
web-1
dnsutils
ํจํค์ง์์ nslookup
๋ช
๋ น์ ์ ๊ณตํ๋ ์ปจํ
์ด๋๋ฅผ
์คํํ๋๋ก kubectl run
์ ์ด์ฉํ์.
ํ๋์ ํธ์คํธ๋ค์์ nslookup
์ ์ด์ฉํ๋ฉด ํด๋ฌ์คํฐ ๋ด๋ถ DNS ์ฃผ์๋ฅผ
ํ์ธํ ์ ์๋ค.
kubectl run -i --tty --image busybox:1.28 dns-test --restart= Never --rm
์ ๋ช
๋ น์ผ๋ก ์๋ก์ด ์
ธ์ ์์ํ๋ค. ์ ์
ธ์์ ๋ค์์ ์คํํ๋ค.
# dns-test ์ปจํ
์ด๋ ์
ธ์์ ๋ค์์ ์คํํ๋ค.
nslookup web-0.nginx
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๋น์ทํ๋ค.
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.6
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.6
(์ด์ exit
๋ช
๋ น์ผ๋ก ์ปจํ
์ด๋ ์
ธ์์ ์ข
๋ฃํ๋ค.)
ํค๋๋ฆฌ์ค ์๋น์ค์ CNAME์ SRV ๋ ์ฝ๋๋ฅผ ์ง์นญํ๋ค
(Running๊ณผ Ready ์ํ์ ๊ฐ ํ๋๋ง๋ค 1๊ฐ).
SRV ๋ ์ฝ๋๋ ํ๋์ IP ์ฃผ์๋ฅผ ํฌํจํ A ๋ ์ฝ๋ ์ํธ๋ฆฌ๋ฅผ ์ง์นญํ๋ค.
์ฒซ์งธ ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ ธ์ค์.
kubectl get pod -w -l app = nginx
๋ ๋ฒ์งธ ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
๋ด์ ํ๋๋ฅผ ๋ชจ๋ ์ญ์ ํ๊ธฐ ์ํด
kubectl delete
๋ฅผ
์ด์ฉํ์.
kubectl delete pod -l app = nginx
pod "web-0" deleted
pod "web-1" deleted
์คํ
์ดํธํ์
์ด ์ฌ์์๋๊ณ ๋ ํ๋๊ฐ Running๊ณผ Ready ์ํ๋ก
์ ํ๋๋๋ก ๊ธฐ๋ค๋ฆฌ์.
kubectl get pod -w -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 34s
ํ๋์ ํธ์คํธ๋ค์๊ณผ ํด๋ฌ์คํฐ ๋ด๋ถ DNS ์ํธ๋ฆฌ๋ฅผ ๋ณด๊ธฐ ์ํด
kubectl exec
๊ณผ kubectl run
์ ์ด์ฉํ์. ๋จผ์ , ํ๋์ ํธ์คํธ๋ค์์ ํ์ธํ๋ค.
for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname' ; done
web-0
web-1
๊ทธ๋ฆฌ๊ณ ๋ค์์ ์คํํ๋ค.
kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm /bin/sh
์ด ๋ช
๋ น์ผ๋ก ์๋ก์ด ์
ธ์ด ์์๋๋ค.
์ ์
ธ์์ ๋ค์์ ์คํํ๋ค.
# dns-test ์ปจํ
์ด๋ ์
ธ์์ ์ด๊ฒ์ ์คํํ๋ค.
nslookup web-0.nginx
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๋น์ทํ๋ค.
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.7
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.8
(์ด์ exit
๋ช
๋ น์ผ๋ก ์ปจํ
์ด๋ ์
ธ์ ์ข
๋ฃํ๋ค.)
ํ๋์ ์๋ฒ, ํธ์คํธ๋ค์, SRV ๋ ์ฝ๋์ A ๋ ์ฝ๋์ด๋ฆ์ ๋ณ๊ฒฝ๋์ง ์์ง๋ง
ํ๋์ IP ์ฃผ์๋ ๋ณ๊ฒฝ๋ ์ ์๋ค. ์ด๋ ํํ ๋ฆฌ์ผ์์ ์ฌ์ฉํ๋ ํด๋ฌ์คํฐ๋
๋ค๋ฅธ ํด๋ฌ์คํฐ์๋ ๋์ผํ๋ค. ๋ฐ๋ผ์ ๋ค๋ฅธ ์ ํ๋ฆฌ์ผ์ด์
์ด IP ์ฃผ์๋ก
์คํ
์ดํธํ์
์ ํ๋์ ์ ์ํ์ง ์๋๋ก ํ๋ ๊ฒ์ด ์ค์ํ๋ค.
์คํ
์ดํธํ์
์ ํ์ฑ ๋ฉค๋ฒ๋ฅผ ์ฐพ์ ์ฐ๊ฒฐํ ๊ฒฝ์ฐ
ํค๋๋ฆฌ์ค ์๋น์ค(nginx.default.svc.cluster.local
)์ CNAME์ ์ฟผ๋ฆฌํด์ผ ํ๋ค.
CNAME๊ณผ ์ฐ๊ด๋ SRV ๋ ์ฝ๋๋ ์คํ
์ดํธํ์
์
Running๊ณผ Ready ์ํ์ ๋ชจ๋ ํ๋๋ค์
๋ด๊ณ ์๋ค.
์ ํ๋ฆฌ์ผ์ด์
์์ ์ด๋ฏธ ํ์ฑ์ํ(liveness)์ ์ค๋น์ฑ(readiness) ํ
์คํธํ๋
์ฐ๊ฒฐ ๋ก์ง์ ๊ตฌํ๋์ด ์๋ค๋ฉด
ํ๋web-0.nginx.default.svc.cluster.local
,
web-1.nginx.default.svc.cluster.local
)์ SRV๋ ์ฝ๋๋ฅผ ์์ ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ด
์ ํ๋ฆฌ์ผ์ด์
์ ํ๋๊ฐ Running๊ณผ Ready ์ํ๋ก ์ ํํ ๋
ํ๋์ ์ฃผ์๋ฅผ ๊ฒ์ํ ์ ์๋ค.
์์ ์ ์ธ ์คํ ๋ฆฌ์ง์ ์ฐ๊ธฐ web-0
๊ณผ web-1
์ ๋ํด ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์(PersistentVolumeClaim)์ ๊ฐ์ ธ์ค์.
kubectl get pvc -l app = nginx
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๋น์ทํ๋ค.
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 48s
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 48s
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ 2๊ฐ์
ํผ์์คํดํธ๋ณผ๋ฅจ ์
๋ฌถ์ธ 2๊ฐ์
ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์ ์ ์์ฑํ๋ค.
๋ณธ ํํ ๋ฆฌ์ผ์์ ์ฌ์ฉ๋๋ ํด๋ฌ์คํฐ๋ ํผ์์คํดํธ๋ณผ๋ฅจ์ ๋์ ์ผ๋ก
ํ๋ก๋น์ ๋ํ๋๋ก ์ค์ ๋์์ผ๋ฏ๋ก ์์ฑ๋ ํผ์์คํดํธ๋ณผ๋ฅจ๋ ์๋์ผ๋ก ๋ฌถ์ธ๋ค.
NGINX ์น์๋ฒ๋ ๊ธฐ๋ณธ ์์ธ ํ์ผ๋ก
/usr/share/nginx/html/index.html
์ ์ด์ฉํฉ๋๋ค.
์คํ
์ดํธํ์
spec
๋ด์ volumeMounts
ํ๋๋ /usr/share/nginx/html
๋๋ ํฐ๋ฆฌ๊ฐ
ํผ์์คํดํธ๋ณผ๋ฅจ์ผ๋ก ์ ๊ณต๋๋์ง ๋ณด์ฆํฉ๋๋ค.
ํ๋์ ํธ์คํธ๋ค์์ index.html
ํ์ผ์ ์์ฑํ๊ณ
NGINX ์น์๋ฒ๊ฐ ํด๋น ํธ์คํธ๋ค์์ ์ ๊ณตํ๋์ง ํ์ธํด๋ณด์.
for i in 0 1; do kubectl exec "web- $i " -- sh -c 'echo $(hostname) > /usr/share/nginx/html/index.html' ; done
for i in 0 1; do kubectl exec -it "web- $i " -- curl localhost; done
web-0
web-1
์ฐธ๊ณ : ์์ curl ๋ช
๋ น์ด๋ก 403 Forbidden ์๋ ์๋ต์ ๋ณด๋ ค๋ฉด
๋ค์์ ์คํํ์ฌ volumeMounts
๋ก ๋ง์ดํธ๋ ๋๋ ํฐ๋ฆฌ์ ํผ๋ฏธ์
์ ์์ ํด์ผ ํ๋ค
(hostPath ๋ณผ๋ฅจ์ ์ฌ์ฉํ ๋์ ๋ฒ๊ทธ ๋ก
์ธํจ).
for i in 0 1; do kubectl exec web-$i -- chmod 755 /usr/share/nginx/html; done
์์ curl
๋ช
๋ น์ ์ฌ์๋ํ๊ธฐ ์ ์ ์ ๋ช
๋ น์ ์คํํด์ผ ํ๋ค.
์ฒซ์งธ ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pod -w -l app = nginx
๋ ๋ฒ์งธ ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๋ฅผ ์ญ์ ํ์.
kubectl delete pod -l app = nginx
pod "web-0" deleted
pod "web-1" deleted
์ฒซ ๋ฒ์งธ ํฐ๋ฏธ๋์์ ์คํ ์ค์ธ kubectl get
๋ช
๋ น์ด์ ์ถ๋ ฅ์ ํ์ธํ๊ณ ,
๋ชจ๋ ํ๋๊ฐ Running๊ณผ Ready ์ํ๋ก ์ ํ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pod -w -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 34s
์น์๋ฒ์์ ์์ ์ ํธ์คํธ๋ค์์ ๊ณ์ ์ ๊ณตํ๋์ง ํ์ธํ์.
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
๋น๋ก web-0
๊ณผ web-1
์ด ์ฌ์ค์ผ์ค๋ง๋์ด๋ ๊ณ์ํด์
์์ ์ ํธ์คํธ๋ค์์ ์ ๊ณตํ๋๋ฐ ์ด๋ ๊ฐ ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์์
์ฐ๊ด๋ ํผ์์คํดํธ๋ณผ๋ฅจ์ด ํด๋น volumeMounts
๋ก ์ฌ๋ง์ดํธ๋๊ธฐ ๋๋ฌธ์ด๋ค.
web-0
๊ณผ web-1
์ ์ค์ผ์ค๋ง์ ๊ด๊ณ์์ด
๊ฐ๊ฐ์ ํผ์์คํดํธ๋ณผ๋ฅจ์ ์ ์ ํ๊ฒ ๋ง์ดํธ๋๋ค.
์คํ
์ดํธํ์
์ค์ผ์ผ๋ง ์คํ
์ดํธํ์
์ ์ค์ผ์ผ๋งํ๋ ๊ฒ์ ๋ ํ๋ฆฌ์นด ๊ฐ์๋ฅผ ๋๋ฆฌ๊ฑฐ๋ ์ค์ด๋ ๊ฒ์ ์๋ฏธํ๋ค. ์ด๊ฒ์ replicas
ํ๋๋ฅผ ๊ฐฑ์ ํ์ฌ ์ด๋ค์ง๋ค.
kubectl scale
์ด๋
kubectl patch
์
์ด์ฉํด์ ์คํ
์ดํธํ์
์ ์ค์ผ์ผ๋งํ ์ ์๋ค.
์ค์ผ์ผ ์
ํฐ๋ฏธ๋์ฐฝ์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pods -w -l app = nginx
๋ค๋ฅธ ํฐ๋ฏธ๋์ฐฝ์์ kubectl scale
์ ์ด์ฉํ์ฌ ๋ ํ๋ฆฌ์นด ๊ฐ์๋ฅผ
5๋ก ์ค์ผ์ผ๋งํ์.
kubectl scale sts web --replicas= 5
statefulset.apps/web scaled
์ฒซ ๋ฒ์งธ ํฐ๋ฏธ๋์์ ์คํ ์ค์ธ kubectl get
๋ช
๋ น์ด์ ์ถ๋ ฅ์ ํ์ธํ๊ณ ,
3๊ฐ์ ์ถ๊ฐ ํ๋๊ฐ Running๊ณผ Ready ์ํ๋ก ์ ํ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pods -w -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2h
web-1 1/1 Running 0 2h
NAME READY STATUS RESTARTS AGE
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 1/1 Running 0 18s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 1/1 Running 0 19s
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ ๋ ํ๋ฆฌ์นด ๊ฐ์๋ฅผ ์ค์ผ์ผ๋งํ๋ค.
์คํ
์ดํธํ์
์์ฑ ์ผ๋ก ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋
๊ฐ ํ๋์ ์์ฐจ์ ์ผ๋ก ๊ฐ ์๋ฒ์ ๋ฐ๋ผ ์์ฑํ๊ณ ํ์ ํ๋ ์์ ์ ์
์ด์ ํ๋๊ฐ Running๊ณผ Ready ์ํ๊ฐ ๋ ๋๊น์ง
๊ธฐ๋ค๋ฆฐ๋ค.
์ค์ผ์ผ ๋ค์ด ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pods -w -l app = nginx
๋ค๋ฅธ ํฐ๋ฏธ๋์์ kubectl patch
์ผ๋ก ์คํ
์ดํธํ์
์ ๋ค์
3๊ฐ์ ๋ ํ๋ฆฌ์นด๋ก ์ค์ผ์ผ๋งํ์.
kubectl patch sts web -p '{"spec":{"replicas":3}}'
statefulset.apps/web patched
web-4
์ web-3
์ด Terminating์ผ๋ก ์ ํ๋๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pods -w -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3h
web-1 1/1 Running 0 3h
web-2 1/1 Running 0 55s
web-3 1/1 Running 0 36s
web-4 0/1 ContainerCreating 0 18s
NAME READY STATUS RESTARTS AGE
web-4 1/1 Running 0 19s
web-4 1/1 Terminating 0 24s
web-4 1/1 Terminating 0 24s
web-3 1/1 Terminating 0 42s
web-3 1/1 Terminating 0 42s
์์ฐจ ํ๋ ์ข
๋ฃ ์ปจํธ๋กค๋ฌ๋ ์๋ฒ์ ์ญ์์ผ๋ก ํ ๋ฒ์ 1๊ฐ ํ๋๋ฅผ ์ญ์ ํ๊ณ
๋ค์ ํ๋๋ฅผ ์ญ์ ํ๊ธฐ ์ ์
๊ฐ๊ฐ์ด ์์ ํ๊ฒ ์ข
๋ฃ๋๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.
์คํ
์ดํธํ์
์ ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์์ ๊ฐ์ ธ์ค์.
kubectl get pvc -l app = nginx
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-2 Bound pvc-e1125b27-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-3 Bound pvc-e1176df6-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-4 Bound pvc-e11bb5f8-b508-11e6-932f-42010a800002 1Gi RWO 13h
์ฌ์ ํ 5๊ฐ์ ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์๊ณผ 5๊ฐ์ ํผ์์คํดํธ๋ณผ๋ฅจ์ด ์๋ค.
ํ๋์ ์์ ํ ์คํ ๋ฆฌ์ง ๋ฅผ ํ์ํ๋ฉด์ ์คํ
์ดํธํ์
์ ํ๋๊ฐ ์ญ์ ๋ ๋์ ํ๋์ ๋ง์ดํธ๋ ์คํ
์ดํธํ์
์ ํผ์์คํดํธ๋ณผ๋ฅจ์ด ์ญ์ ๋์ง ์์ ๊ฒ์ ๋ณด์๋ค. ์คํ
์ดํธํ์
์ค์ผ์ผ ๋ค์ด์ผ๋ก ํ๋ ์ญ์ ํ ๋์๋ ์ฌ์ ํ ์ฌ์ค์ด๋ค.
์คํ
์ดํธํ์
์
๋ฐ์ดํธํ๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค 1.7 ์ด์์์ ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ ์๋ ์
๋ฐ์ดํธ๋ฅผ ์ง์ํ๋ค.
์ ๋ต์ ์คํ
์ดํธํ์
API ์ค๋ธ์ ํธ์ spec.updateStrategy
ํ๋๋ก ๊ฒฐ์ ๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง, ์คํ
์ดํธํ์
์ ๋ฆฌ์์ค ์์ฒญ์ด๋
ํน์ ํ๊ณ์ ๋ ์ด๋ธ๊ณผ ํ๋์ ์ด๋
ธํ
์ด์
์ ์
๊ทธ๋ ์ด๋ํ๊ธฐ ์ํด ์ฌ์ฉ๋ ์ ์๋ค.
RollingUpdate
๊ณผ OnDelete
์ 2๊ฐ์
์ ํจํ ์
๋ฐ์ดํธ ์ ๋ต์ด ์๋ค.
RollingUpdate
์
๋ฐ์ดํธ ์ ๋ต์ ์คํ
์ดํธํ์
์์ ๊ธฐ๋ณธ ๊ฐ์ด๋ค.
๋กค๋ง ์
๋ฐ์ดํธ RollingUpdate
์
๋ฐ์ดํธ ์ ๋ต์ ์คํ
์ดํธํ์
์ ๋ณด์ฅ์ฌํญ์ ์ ์งํ๋ฉด์
์คํ
์ดํธํ์
๋ด์ ๋ชจ๋ ํ๋๋ฅผ ์ญ์์ผ๋ก ์
๋ฐ์ดํธํ๋ค.
์คํ
์ดํธํ์
web
์ ์
๋ฐ์ดํธ ์ ๋ต์ RollingUpdate
์ผ๋ก ํจ์นํ์.
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'
statefulset.apps/web patched
ํฐ๋ฏธ๋ ์ฐฝ์์ ์คํ
์ดํธํ์
web
์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ๋ฐ๊พธ๋๋ก
๋ ํจ์นํ์.
kubectl patch statefulset web --type= 'json' -p= '[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.8"}]'
statefulset.apps/web patched
๋ค๋ฅธ ํฐ๋ฏธ๋์ฐฝ์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pod -l app = nginx -w
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๋น์ทํ๋ค.
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 7m
web-1 1/1 Running 0 7m
web-2 1/1 Running 0 8m
web-2 1/1 Terminating 0 8m
web-2 1/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-1 1/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 6s
web-0 1/1 Terminating 0 7m
web-0 1/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 10s
์คํ
์ดํธํ์
๋ด์ ํ๋๋ ์๋ฒ์ ์ญ์์ผ๋ก ์
๋ฐ์ดํธ๋๋ค.
์ด ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ ๊ฐ ํ๋๋ฅผ ์ข
๋ฃ์ํค๊ณ ๋ค์ ํ๋๋ฅผ ์
๋ฐ์ดํธํ๊ธฐ ์ ์
๊ทธ๊ฒ์ด Running๊ณผ Ready ์ํ๋ก ์ ํ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.
์์๋ ๊ฒ์ ๋น๋ก ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ์์ ์ด์ ํ๋๊ฐ Running๊ณผ Ready ์ํ๊ฐ ๋๊ธฐ๊น์ง
๋ค์ ํ๋๋ฅผ ์
๋ฐ์ดํธํ์ง ์์๋ ํ์ฌ ๋ฒ์ ์ผ๋ก ํ๋๋ฅผ ์
๋ฐ์ดํธํ๋ค ์คํจํ๋ฉด
๋ณต์ํ๋ค๋ ๊ฒ์ด๋ค.
์
๋ฐ์ดํธ๋ฅผ ์ด๋ฏธ ๋ฐ์ ํ๋๋ ์
๋ฐ์ดํธ๋ ๋ฒ์ ์ผ๋ก ๋ณต์๋๊ณ ์์ง ์
๋ฐ์ดํธ๋ฅผ ๋ฐ์ง ๋ชปํ ํ๋๋
์ด์ ๋ฒ์ ์ผ๋ก ๋ณต์ํ๋ค. ์ด๋ฐ ์์ผ๋ก ์ปจํธ๋กค๋ฌ๋ ๊ฐํ์ ์ธ ์ค๋ฅ๊ฐ ๋ฐ์ํด๋
์ ํ๋ฆฌ์ผ์ด์
์ ๊ณ์ ๊ฑด๊ฐํ๊ฒ ์ ์งํ๊ณ
์
๋ฐ์ดํธ๋ ์ผ๊ด๋๊ฒ ์ ์งํ๋ ค ํ๋ค.
์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ์ดํด๋ณด๊ธฐ ์ํด ํ๋๋ฅผ ๊ฐ์ ธ์ค์.
for p in 0 1 2; do kubectl get pod "web- $p " --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}' ; echo; done
registry.k8s.io/nginx-slim:0.8
registry.k8s.io/nginx-slim:0.8
registry.k8s.io/nginx-slim:0.8
์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๊ฐ ์ง๊ธ์ ์ด์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ์คํ ์ค์ด์ด๋ค.
์ฐธ๊ณ : ์คํ
์ดํธํ์
์ ๋กค๋ง ์
๋ฐ์ดํธ ์ํฉ์ ์ดํด๋ณด๊ธฐ ์ํด kubectl rollout status sts/<name>
๋ช
๋ น์ด๋ ์ฌ์ฉํ ์ ์๋ค.๋จ๊ณ์ ์ผ๋ก ์
๋ฐ์ดํธ ํ๊ธฐ RollingUpdate
์
๋ฐ์ดํธ ์ ๋ต์ ํ๋ผ๋ฏธํฐ์ธ partition
๋ฅผ ์ด์ฉํ์ฌ
์คํ
์ดํธํ์
์ ๋จ๊ณ์ ์ผ๋ก ์
๋ฐ์ดํธํ ์ ์๋ค.
๋จ๊ณ์ ์
๋ฐ์ดํธ๋ ์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๋ฅผ ํ์ฌ ๋ฒ์ ์ผ๋ก ์ ์งํ๋ฉด์
์คํ
์ดํธํ์
์ .spec.template
์ ๋ณ๊ฒฝ์ ํ์ฉํ๋ค.
์คํ
์ดํธํ์
web
์ updateStrategy
ํ๋์ partition์ ์ถ๊ฐํ์.
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'
statefulset.apps/web patched
์ปจํ
์ด๋์ ์ด๋ฏธ์ง๋ฅผ ๋ฐ๊พธ๋๋ก ์คํ
์ดํธํ์
์ ๋ค์ ํจ์นํ๋ค.
kubectl patch statefulset web --type= 'json' -p= '[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"registry.k8s.io/nginx-slim:0.7"}]'
statefulset.apps/web patched
์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์ญ์ ํ์.
pod "web-2" deleted
ํ๋๊ฐ Running๊ณผ Ready ์ํ๊ฐ ๋๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pod -l app = nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 4m
web-1 1/1 Running 0 4m
web-2 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 18s
ํ๋์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค์.
kubectl get pod web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
registry.k8s.io/nginx-slim:0.8
๋น๋ก ์
๋ฐ์ดํธ ์ ๋ต์ด RollingUpdate
์ด์ง๋ง ์คํ
์ดํธํ์
์
ํ๋๋ฅผ ๊ทธ๊ฒ์ ์๋ ์ปจํ
์ด๋๋ก ๋ณต์ํ๋ค.
ํ๋์ ์๋ฒ์ด updateStrategy
์์ ์ง์ ๋
ํํฐ์
๋ณด๋ค ์๊ธฐ ๋๋ฌธ์ด๋ค.
์นด๋๋ฆฌ(Canary) ๋กค๋ง ์์ ์์์ ์ง์ ํ partition
๊ฐ์ ์ฐจ๊ฐ์ํค๋ฉด
๋ณ๊ฒฝ์ฌํญ์ ํ
์คํธํ๊ธฐ ์ํด ์นด๋๋ฆฌ ๋กค์์์ ํ ์ ์๋ค.
์คํ
์ดํธํ์
์ partition์ ์ฐจ๊ฐํ๋๋ก ํจ์นํ์.
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}'
statefulset.apps/web patched
web-2
ํ๋๊ฐ Running๊ณผ Ready ์ํ๊ฐ ๋๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pod -l app = nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 4m
web-1 1/1 Running 0 4m
web-2 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 18s
ํ๋์ ์ปจํ
์ด๋๋ฅผ ๊ฐ์ ธ์ค์.
kubectl get po web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
registry.k8s.io/nginx-slim:0.7
partition
์ ๋ฐ๊พธ๋ฉด ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ ์๋์ผ๋ก
web-2
ํ๋๋ฅผ ์
๋ฐ์ดํธํ๋๋ฐ
์ด๋ ํด๋น ํ๋์ ์๋ฒ์ด partition
์ด์์ด๊ธฐ ๋๋ฌธ์ด๋ค.
web-1
ํ๋๋ฅผ ์ญ์ ํ์.
pod "web-1" deleted
web-1
ํ๋๊ฐ Running๊ณผ Ready ์ํ๊ฐ ๋๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pod -l app = nginx -w
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๋น์ทํ๋ค.
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 6m
web-1 0/1 Terminating 0 6m
web-2 1/1 Running 0 2m
web-1 0/1 Terminating 0 6m
web-1 0/1 Terminating 0 6m
web-1 0/1 Terminating 0 6m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
web-1
ํ๋์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค์.
kubectl get pod web-1 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
registry.k8s.io/nginx-slim:0.8
web-1
๋ ์๋ ํ๊ฒฝ์ค์ ์ผ๋ก ๋ณต์๋์๋๋ฐ
์ด๋ ํ๋์ ์๋ฒ์ด partition๋ณด๋ค ์๊ธฐ ๋๋ฌธ์ด๋ค.
์คํ
์ดํธํ์
์ .spec.template
์ด ๊ฐฑ์ ๋๋ฉด,
์ง์ ๋ partition ์ด์์ ์๋ฒ์ ๊ฐ์ง ๋ชจ๋ ํ๋๋ ์
๋ฐ์ดํธ๋๋ค.
๋ฏธ๋ง์ ์๋ฒ์ ๊ฐ์ง ํ๋๋ผ๋ฉด ์ญ์ ๋๊ฑฐ๋
์ข
๋ฃ๋์ด ์๋ ํ๊ฒฝ์ค์ ์ผ๋ก ๋ณต์๋๋ค.
๋จ๊ณ์ ๋กค์์ ์นด๋๋ฆฌ ๋กค์์ ์์ ํ๋ ๋ฐฉ๋ฒ๊ณผ ๋น์ทํ๊ฒ
๋ถํ ๋ ๋กค๋ง ์
๋ฐ์ดํธ๋ฅผ ์ด์ฉํ์ฌ ๋จ๊ณ์ ๋กค์์(e.g. ์ ํ, ๊ธฐํ ๋๋ ์ง์์ ๋กค์์)์
์ํํ ์ ์๋ค. ๋จ๊ณ์ ๋กค์์์ ์ํํ๋ ค๋ฉด
์ปจํธ๋กค๋ฌ๊ฐ ์
๋ฐ์ดํธ๋ฅผ ์ผ์ ์ค์งํ ์๋ฒ์ผ๋ก
partition
๋ฅผ ์ ํ์.
partition์ ํ์ฌ 2
์ด๋ค. partition์ 0
์ผ๋ก ๋ฐ๊พธ์.
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":0}}}}'
statefulset.apps/web patched
์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๊ฐ Running๊ณผ Ready ์ํ๊ฐ ๋๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pod -l app = nginx -w
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๋น์ทํ๋ค.
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3m
web-1 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 2m
web-1 1/1 Running 0 18s
web-0 1/1 Terminating 0 3m
web-0 1/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 3s
์คํ
์ดํธํ์
์ ์๋ ํ๋์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง ์์ธ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค์.
for p in 0 1 2; do kubectl get pod "web- $p " --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}' ; echo; done
registry.k8s.io/nginx-slim:0.7
registry.k8s.io/nginx-slim:0.7
registry.k8s.io/nginx-slim:0.7
partition
์ 0
์ผ๋ก ์ด๋ํ์ฌ ์คํ
์ดํธํ์
์์ ๊ณ์ํด์
์
๋ฐ์ดํธ ์ฒ๋ฆฌ๋ฅผ ํ๋๋ก ํ์ฉํ์๋ค.
์ญ์ ์ ๋์ OnDelete
์
๋ฐ์ดํธ ์ ๋ต์ ์์ ๋์(1.6 ์ดํ)์ผ๋ก,
์ด ์
๋ฐ์ดํธ ์ ๋ต์ ์ ํํ๋ฉด,
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ ์คํ
์ดํธํ์
์
.spec.template
ํ๋์ ์์ ์ฌํญ์ด ๋ฐ์ํด๋ ์๋์ผ๋ก ํ๋๋ฅผ ์
๋ฐ์ดํธํ์ง ์๋๋ค.
์ด ์ ๋ต์ .spec.template.updateStrategy.type
์ OnDelete
๋ก ์ค์ ํ์ฌ ์ ํํ ์ ์๋ค.
์คํ
์ดํธํ์
์ญ์ ํ๊ธฐ ์คํ
์ดํธํ์
์ ๋น์ข
์์ (non-cascading), ์ข
์์ (cascading) ์ญ์ ๋ฅผ ๋ ๋ค ์ง์ํ๋ค.
๋น์ข
์์ ์ญ์ ์์๋ ์คํ
์ดํธํ์
์ด ์ง์์ง ๋์ ์คํ
์ดํธํ์
์ ํ๋๋ ์ง์์ง์ง ์๋๋ค.
์ข
์์ ์ญ์ ์์๋ ์คํ
์ดํธํ์
๊ณผ ๊ทธ์ ์ํ ํ๋๊ฐ ๋ชจ๋ ์ง์์ง๋ค.
๋น์ข
์์ ์ญ์ ํฐ๋ฏธ๋์ฐฝ์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pods -w -l app=nginx
๋ค๋ฅธ ํฐ๋ฏธ๋์์๋ ์คํ
์ดํธํ์
์ ์ง์ฐ๊ธฐ ์ํด
kubectl delete
๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
์ด ๋ช
๋ น์ด์ --cascade=orphan
ํ๋ผ๋ฏธํฐ๊ฐ ์ถ๊ฐ๋์๋ค.
์ด ํ๋ผ๋ฏธํฐ๋ ์ฟ ๋ฒ๋คํฐ์ค์ ์คํ
์ดํธํ์
๋ง ์ญ์ ํ๊ณ ๊ทธ์ ์ํ ํ๋๋ ์ง์ฐ์ง ์๋๋ก ์์ฒญํ๋ค.
kubectl delete statefulset web --cascade= orphan
statefulset.apps "web" deleted
์ํ๋ฅผ ํ์ธํ๊ธฐ ์ํด ํ๋๋ฅผ ๊ฐ์ ธ์ค์.
kubectl get pods -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 6m
web-1 1/1 Running 0 7m
web-2 1/1 Running 0 5m
๋น๋ก web
์ด ์ญ์ ๋๊ณ ์์ด๋, ๋ชจ๋ ํ๋๋ ์ฌ์ ํ Running๊ณผ Ready ์ํ์ด๋ค.
web-0
์ ์ญ์ ํ์.
pod "web-0" deleted
์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ ธ์ค์.
kubectl get pods -l app = nginx
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 10m
web-2 1/1 Running 0 7m
์คํ
์ดํธํ์
web
์ด ์ญ์ ๋๋ ๋์ web-0
์ ์ฌ์์ํ์ง ์์๋ค.
์ฒซ์งธ ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pods -w -l app = nginx
๋ ๋ฒ์งธ ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
์ ๋ค์ ์์ฑํ์.
nginx
์๋น์ค(๊ฐ์ง์ง ๋ง์์ด์ผ ํ๋)๋ฅผ ์ญ์ ํ๊ธฐ ์ ๊น์ง๋ ๊ทธ ์๋น์ค๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ค๋ ์๋ฌ๋ฅผ
๋ณผ ๊ฒ์ด๋ผ๋ ๊ฒ์ ๋ช
์ฌํ์.
kubectl apply -f web.yaml
statefulset.apps/web created
service/nginx unchanged
์ด ์๋ฌ๋ ๋ฌด์ํ์. ์ด๊ฒ์ ๋ค๋ง ํด๋น ์๋น์ค๊ฐ ์๋๋ผ๋
nginx ํค๋๋ฆฌ์ค ์๋น์ค๋ฅผ ์์ฑํ๋ ค๊ณ ํ์์ ๋ปํ๋ค.
์ฒซ์งธ ํฐ๋ฏธ๋์์ ์คํ ์ค์ธ kubectl get
๋ช
๋ น์ด์ ์ถ๋ ฅ์ ์ดํด๋ณด์.
kubectl get pods -w -l app = nginx
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 16m
web-2 1/1 Running 0 2m
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 18s
web-2 1/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
web
์คํ
์ดํธํ์
์ด ๋ค์ ์์ฑ๋ ๋ ๋จผ์ web-0
์์ํ๋ค.
web-1
์ ์ด๋ฏธ Running๊ณผ Ready ์ํ์ด๋ฏ๋ก web-0
์ด Running๊ณผ Ready ์ํ๋ก
์ ํ๋ ๋๋ ์ด ํ๋์ ์ ์ฉ๋๋ค. ์คํ
์ดํธํ์
์ replicas
๋ฅผ 2๋ก ํ๊ณ
web-0
์ ์ฌ์์ฑํ๋ค๋ฉด web-1
์ด
์ด๋ฏธ Running๊ณผ Ready ์ํ์ด๊ณ ,
web-2
์ ์ข
๋ฃ๋์์ ๊ฒ์ด๋ค.
ํ๋์ ์น์๋ฒ์์ ์ ๊ณตํ index.html
ํ์ผ ๋ด์ฉ์
๋ค๋ฅธ ๊ด์ ์ผ๋ก ์ดํด๋ณด์.
for i in 0 1; do kubectl exec -i -t "web- $i " -- curl http://localhost/; done
web-0
web-1
์คํ
์ดํธํ์
๊ณผ web-0
ํ๋๋ฅผ ๋ ๋ค ์ญ์ ํ์ผ๋ ์ฌ์ ํ index.html
ํ์ผ์ ์
๋ ฅํ๋
์๋ ํธ์คํธ๋ค์์ ์ ๊ณตํ๋ค. ์คํ
์ดํธํ์
์
ํ๋์ ํ ๋น๋ ํผ์์คํดํธ๋ณผ๋ฅจ์ ๊ฒฐ์ฝ ์ญ์ ํ์ง ์๊ธฐ๋๋ฌธ์ด๋ค.
๋ค์ ์คํ
์ดํธํ์
์ ์์ฑํ๋ฉด web-0
์ ์์ํ๋ฉฐ
์๋ ํผ์์คํดํธ๋ณผ๋ฅจ์ ๋ค์ ๋ง์ดํธํ๋ค.
๋จ๊ณ์ ์ญ์ ํฐ๋ฏธ๋์ฐฝ์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pods -w -l app = nginx
๋ค๋ฅธ ํฐ๋ฏธ๋์ฐฝ์์ ์คํ
์ดํธํ์
์ ๋ค์ ์ง์ฐ์. ์ด๋ฒ์๋
--cascade=orphan
ํ๋ผ๋ฏธํฐ๋ฅผ ์๋ตํ์.
kubectl delete statefulset web
statefulset.apps "web" deleted
์ฒซ์งธ ํฐ๋ฏธ๋์์ ์คํ ์ค์ธ kubectl get
๋ช
๋ น์ด์ ์ถ๋ ฅ์ ์ดํด๋ณด๊ณ
๋ชจ๋ ํ๋๊ฐ Terminating ์ํ๋ก ์ ํ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pods -w -l app = nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 11m
web-1 1/1 Running 0 27m
NAME READY STATUS RESTARTS AGE
web-0 1/1 Terminating 0 12m
web-1 1/1 Terminating 0 29m
web-0 0/1 Terminating 0 12m
web-0 0/1 Terminating 0 12m
web-0 0/1 Terminating 0 12m
web-1 0/1 Terminating 0 29m
web-1 0/1 Terminating 0 29m
web-1 0/1 Terminating 0 29m
์ค์ผ์ผ ๋ค์ด ์น์
์์ ๋ณด์๋ฏ ํ๋๋
๊ฐ ์๋ฒ์ ์ญ์์ผ๋ก ํ๋์ฉ ์ข
๋ฃ๋๋ค. ํ๋๊ฐ ์ข
๋ฃ๋ ๋
์คํ
์ดํธํ ์ปจํธ๋กค๋ฌ๋ ์ด์ ํ๋๊ฐ
์์ ํ ์ข
๋ฃ๋๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.
์ฐธ๊ณ : ์ข
์์ ์ญ์ ๋ ํ๋์ ํจ๊ป ์คํ
์ดํธํ์
์ ์ ๊ฑฐํ์ง๋ง,
์คํ
์ดํธํ์
๊ณผ ๊ด๋ จ๋ ํค๋๋ฆฌ์ค ์๋น์ค๋ฅผ ์ญ์ ํ์ง ์๋๋ค.
๊ผญ nginx
์๋น์ค๋ฅผ ์๋์ผ๋ก ์ญ์ ํด๋ผ.kubectl delete service nginx
service "nginx" deleted
์คํ
์ดํธํ์
๊ณผ ํค๋๋ฆฌ์ค ์๋น์ค๋ฅผ ํ๋ฒ ๋ ๋ค์ ์์ฑํ์.
kubectl apply -f web.yaml
service/nginx created
statefulset.apps/web created
์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๊ฐ Running๊ณผ Ready ์ํ๋ก ์ ํ๋ ๋
index.html
ํ์ผ ๋ด์ฉ์ ๊ฒ์ํ์.
for i in 0 1; do kubectl exec -i -t "web- $i " -- curl http://localhost/; done
web-0
web-1
์คํ
์ดํธํ์
๊ณผ ๊ทธ ๋ด๋ถ์ ๋ชจ๋ ํ๋๋ฅผ ์ญ์ ํ์ง๋ง ํผ์์คํดํธ๋ณผ๋ฅจ์ด ๋ง์ดํธ๋ ์ฑ๋ก
๋ค์ ์์ฑ๋๊ณ web-0
๊ณผ web-1
์ ๊ณ์
๊ฐ ํธ์คํธ๋ค์์ ์ ๊ณตํ๋ค.
์ต์ข
์ ์ผ๋ก nginx
์๋น์ค๋ฅผ ์ญ์ ํ๋ค.
kubectl delete service nginx
service "nginx" deleted
๊ทธ๋ฆฌ๊ณ web
์คํ
์ดํธํ์
์ ์ญ์ ํ๋ค.
kubectl delete statefulset web
statefulset "web" deleted
ํ๋ ๊ด๋ฆฌ ์ ์ฑ
์ผ๋ถ ๋ถ์ฐ ์์คํ
์ ๊ฒฝ์ฐ ์คํ
์ดํธํ์
์ ์์ ๋ณด์ฆ์
๋ถํ์ํ๊ฑฐ๋ ๋ฐ๋์งํ์ง ์๋ค. ์ด๋ฌํ ์์คํ
์ ๊ณ ์ ์ฑ๊ณผ ์ ์๋ง ํ์ํ๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฟ ๋ฒ๋คํฐ์ค 1.7์์ .spec.podManagementPolicy
๋ฅผ
์คํ
์ดํธํ์
API ์ค๋ธ์ ํธ์ ๋์
ํ๋ค.
OrderedReady ํ๋ ๊ด๋ฆฌ OrderedReady
ํ๋ ๊ด๋ฆฌ๋ ์คํ
์ดํธํ์
์์๋ ๊ธฐ๋ณธ์ด๋ค.
์ด๋ ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๊ฐ ์ง๊ธ๊น์ง ์์์ ์ค๋ช
ํ๋ ์์๋ฅผ
๋ณด์ฆํจ์ ๋ปํ๋ค.
Parallel ํ๋ ๊ด๋ฆฌ Parallel
ํ๋ ๊ด๋ฆฌ๋ ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๊ฐ ๋ชจ๋ ํ๋๋ฅผ
๋ณ๋ ฌ๋ก ์์ํ๊ณ ์ข
๋ฃํ๋ ๊ฒ์ผ๋ก, ๋ค๋ฅธ ํ๋๋ฅผ ์์/์ข
๋ฃํ๊ธฐ ์ ์
ํ๋๊ฐ Running๊ณผ Ready ์ํ๋ก ์ ํ๋๊ฑฐ๋ ์์ ํ ์ข
๋ฃ๋๊ธฐ๊น์ง
๊ธฐ๋ค๋ฆฌ์ง ์์์ ๋ปํ๋ค.
์ด ์ต์
์ ์ค์ผ์ผ๋ง ๋์์๋ง ์ํฅ์ ๋ฏธ์น๋ฉฐ, ์
๋ฐ์ดํธ ๋์์๋ ์ํฅ์ ๋ฏธ์น์ง ์๋๋ค.
apiVersion : v1
kind : Service
metadata :
name : nginx
labels :
app : nginx
spec :
ports :
- port : 80
name : web
clusterIP : None
selector :
app : nginx
---
apiVersion : apps/v1
kind : StatefulSet
metadata :
name : web
spec :
serviceName : "nginx"
podManagementPolicy : "Parallel"
replicas : 2
selector :
matchLabels :
app : nginx
template :
metadata :
labels :
app : nginx
spec :
containers :
- name : nginx
image : registry.k8s.io/nginx-slim:0.8
ports :
- containerPort : 80
name : web
volumeMounts :
- name : www
mountPath : /usr/share/nginx/html
volumeClaimTemplates :
- metadata :
name : www
spec :
accessModes : [ "ReadWriteOnce" ]
resources :
requests :
storage : 1Gi
์๊ธฐ ์์ ๋ฅผ ๋ค์ด๋ก๋๋ฐ์ ํ์ผ ์ด๋ฆ์ web-parallel.yaml
๋ก ์ ์ฅํ์.
์ด ๋งค๋ํ์คํธ๋ web
์คํ
์ดํธํ์
์ .spec.podManagementPolicy
์ด
Parallel
์ธ ๊ฒ ๋ง๊ณ ๋ ์ด์ ์ ๋ค์ด๋ก๋ ๋ฐ์๋ ๊ฒ๊ณผ ๋์ผํ๋ค.
ํฐ๋ฏธ๋์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ๊ฐ์ํ์.
kubectl get pod -l app = nginx -w
๋ค๋ฅธ ํฐ๋ฏธ๋์์ ๋งค๋ํ์คํธ ์์ ์คํ
์ดํธํ์
๊ณผ ์๋น์ค๋ฅผ ์์ฑํ์.
kubectl apply -f web-parallel.yaml
service/nginx created
statefulset.apps/web created
์ฒซ์งธ ํฐ๋ฏธ๋์์ ์คํํ๋ kubectl get
๋ช
๋ น์ด์ ์ถ๋ ฅ์ ์ดํด๋ณด์.
kubectl get pod -l app = nginx -w
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-1 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 10s
web-1 1/1 Running 0 10s
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ web-0
์ web-1
๋ฅผ ๋ ๋ค ๋์์ ์์ํ๋ค.
๋ ๋ฒ์งธ ํฐ๋ฏธ๋์ ์ด์ด ๋๊ณ ๋ค๋ฅธ ํฐ๋ฏธ๋์ฐฝ์์ ์คํ
์ดํธํ์
์
์ค์ผ์ผ๋งํ์.
kubectl scale statefulset/web --replicas= 4
statefulset.apps/web scaled
kubectl get
๋ช
๋ น์ด๋ฅผ ์คํ ์ค์ธ ํฐ๋ฏธ๋์ ์ถ๋ ฅ์ ์ดํด๋ณด์.
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 7s
web-3 0/1 ContainerCreating 0 7s
web-2 1/1 Running 0 10s
web-3 1/1 Running 0 26s
์คํ
์ดํธํ์
์ ๋ ๊ฐ์ ์ ํ๋๋ฅผ ์์ํ์๋ค.
๋ ๋ฒ์งธ ๊ฒ์ ๋ฐ์นญํ๊ธฐ ์ํด ๋จผ์ ๋ฐ์นญํ ๊ฒ์ด Running๊ณผ Ready ์ํ๊ฐ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค.
์ ๋ฆฌํ๊ธฐ ์ ๋ฆฌ์ ์ผํ์ผ๋ก kubectl
๋ช
๋ น์ ์คํํ ์ค๋น๊ฐ ๋ ๋ ๊ฐ์ ํฐ๋ฏธ๋์ด ์ด๋ ค
์์ด์ผ ํ๋ค.
kubectl delete sts web
# sts๋ statefulset์ ์ฝ์์ด๋ค.
kubectl get
๋ช
๋ น์ผ๋ก ํด๋น ํ๋๊ฐ ์ญ์ ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
kubectl get pod -l app = nginx -w
web-3 1/1 Terminating 0 9m
web-2 1/1 Terminating 0 9m
web-3 1/1 Terminating 0 9m
web-2 1/1 Terminating 0 9m
web-1 1/1 Terminating 0 44m
web-0 1/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-3 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-1 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-2 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-1 0/1 Terminating 0 44m
web-1 0/1 Terminating 0 44m
web-1 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-3 0/1 Terminating 0 9m
web-3 0/1 Terminating 0 9m
web-3 0/1 Terminating 0 9m
์ญ์ ํ๋ ๋์, ์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๋ฅผ ๋์์ ์ญ์ ํ๋ค. ํด๋น ํ๋๋ฅผ ์ญ์ ํ๊ธฐ ์ ์
๊ทธ ํ๋์ ์์์ ํ๊ณ์๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค.
kubectl get
๋ช
๋ น์ด๊ฐ ์คํ๋ ํฐ๋ฏธ๋์ ๋ซ๊ณ
nginx
์๋น์ค๋ฅผ ์ญ์ ํ์.
์ด ํํ ๋ฆฌ์ผ์์ ํผ์์คํดํธ๋ณผ๋ฅจ์ผ๋ก ์ฌ์ฉํ๋ ์๊ตฌ ์คํ ๋ฆฌ์ง๋ฅผ ์ญ์ ํ๋ค.
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-2bf00408-d366-4a12-bad0-1869c65d0bee 1Gi RWO standard 25m
www-web-1 Bound pvc-ba3bfe9c-413e-4b95-a2c0-3ea8a54dbab4 1Gi RWO standard 24m
www-web-2 Bound pvc-cba6cfa6-3a47-486b-a138-db5930207eaf 1Gi RWO standard 15m
www-web-3 Bound pvc-0c04d7f0-787a-4977-8da3-d9d3a6d8d752 1Gi RWO standard 15m
www-web-4 Bound pvc-b2c73489-e70b-4a4e-9ec1-9eab439aa43e 1Gi RWO standard 14m
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-0c04d7f0-787a-4977-8da3-d9d3a6d8d752 1Gi RWO Delete Bound default/www-web-3 standard 15m
pvc-2bf00408-d366-4a12-bad0-1869c65d0bee 1Gi RWO Delete Bound default/www-web-0 standard 25m
pvc-b2c73489-e70b-4a4e-9ec1-9eab439aa43e 1Gi RWO Delete Bound default/www-web-4 standard 14m
pvc-ba3bfe9c-413e-4b95-a2c0-3ea8a54dbab4 1Gi RWO Delete Bound default/www-web-1 standard 24m
pvc-cba6cfa6-3a47-486b-a138-db5930207eaf 1Gi RWO Delete Bound default/www-web-2 standard 15m
kubectl delete pvc www-web-0 www-web-1 www-web-2 www-web-3 www-web-4
persistentvolumeclaim "www-web-0" deleted
persistentvolumeclaim "www-web-1" deleted
persistentvolumeclaim "www-web-2" deleted
persistentvolumeclaim "www-web-3" deleted
persistentvolumeclaim "www-web-4" deleted
No resources found in default namespace.
์ฐธ๊ณ : ์ด ํํ ๋ฆฌ์ผ์์ ์ฌ์ฉ๋ ํผ์ํดํธ๋ณผ๋ฅจ์ ์ํ
ํผ์์คํดํธ ์คํ ๋ฆฌ์ง ๋ฏธ๋์ด๋ ์ญ์ ํด์ผ ํ๋ค.
๋ชจ๋ ์คํ ๋ฆฌ์ง๋ฅผ ๋ฐํํ๋๋ก ํ๊ฒฝ, ์คํ ๋ฆฌ์ง ์ค์ ๊ณผ
ํ๋ก๋น์ ๋ ๋ฐฉ๋ฒ์ ๋ฐ๋ฅธ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์.6.2 - ์์: WordPress์ MySQL์ ํผ์์คํดํธ ๋ณผ๋ฅจ์ ๋ฐฐํฌํ๊ธฐ ์ด ํํ ๋ฆฌ์ผ์ WordPress ์ฌ์ดํธ์ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ Minikube๋ฅผ ์ด์ฉํ์ฌ ์ด๋ป๊ฒ ๋ฐฐํฌํ๋์ง ๋ณด์ฌ์ค๋ค. ์ ํ๋ฆฌ์ผ์ด์
๋ ๋ค ํผ์์คํดํธ ๋ณผ๋ฅจ๊ณผ ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
ํผ์์คํดํธ๋ณผ๋ฅจ (PV)๋ ๊ด๋ฆฌ์๊ฐ ์๋์ผ๋ก ํ๋ก๋น์ ๋ํ ํด๋ฌ์คํฐ๋ ์ฟ ๋ฒ๋คํฐ์ค ์คํ ๋ฆฌ์งํด๋์ค ๋ฅผ ์ด์ฉํด ๋์ ์ผ๋ก ํ๋ก๋น์ ๋๋ ์ ์ฅ์์ ์ผ๋ถ์ด๋ค. ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์ (PVC)์ PV๋ก ์ถฉ์กฑํ ์ ์๋ ์ฌ์ฉ์์ ์ํ ์คํ ๋ฆฌ์ง ์์ฒญ์ด๋ค. ํผ์์คํดํธ๋ณผ๋ฅจ์ ํ๋ ๋ผ์ดํ์ฌ์ดํด๊ณผ ๋
๋ฆฝ์ ์ด๋ฉฐ ์ฌ์์, ์ฌ์ค์ผ์ค๋ง์ด๋ ํ๋๋ฅผ ์ญ์ ํ ๋์๋ ๋ฐ์ดํฐ๋ฅผ ๋ณด์กดํ๋ค.
๊ฒฝ๊ณ : ์ด ๋ฐฐํฌ๋ ํ๋ก๋์
์ฌ์ฉ ์๋ก๋ ์ ์ ํ์ง ์์๋ฐ ์ด๋ ๋จ์ผ ์ธ์คํด์ค์ WordPress์ MySQL์ ์ด์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค. ํ๋ก๋์
์ด๋ผ๋ฉด
WordPress Helm Chart ๋ก ๋ฐฐํฌํ๊ธฐ๋ฅผ ๊ณ ๋ คํด๋ณด์.
์ฐธ๊ณ : ์ด ํํ ๋ฆฌ์ผ์ ์ ๊ณต๋ ํ์ผ๋ค์ GA ๋ํ๋ก์ด๋จผํธ API๋ฅผ ์ฌ์ฉํ๋ฉฐ ์ฟ ๋ฒ๋คํฐ์ค ๋ฒ์ 1.9 ์ด์์ ์ด์ฉํ๋ค. ์ด ํํ ๋ฆฌ์ผ์ ์ฟ ๋ฒ๋คํฐ์ค ํ์ ๋ฒ์ ์์ ์ ์ฉํ๋ค๋ฉด API ๋ฒ์ ์ ์ ์ ํ ๊ฐฑ์ ํ๊ฑฐ๋ ์ด ํํ ๋ฆฌ์ผ์ ์ด์ ๋ฒ์ ์ ์ฐธ๊ณ ํ์.๋ชฉ์ ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์๊ณผ ํผ์์คํดํธ๋ณผ๋ฅจ ์์ฑ ๋ค์์ ํฌํจํ๋ kustomization.yaml
์์ฑ์ํฌ๋ฆฟ ์์ฑ์ MySQL ๋ฆฌ์์ค ๊ตฌ์ฑ WordPress ๋ฆฌ์์ค ๊ตฌ์ฑ kubectl apply -k ./
๋ก ์์ฑํ kustomization ์ ์ ์ฉ์ ๋ฆฌ ์์ํ๊ธฐ ์ ์
์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๊ฐ ํ์ํ๊ณ , kubectl ์ปค๋งจ๋-๋ผ์ธ ํด์ด ํด๋ฌ์คํฐ์
ํต์ ํ ์ ์๋๋ก ์ค์ ๋์ด ์์ด์ผ ํ๋ค. ์ด ํํ ๋ฆฌ์ผ์ ์ปจํธ๋กค ํ๋ ์ธ ํธ์คํธ๊ฐ ์๋ ๋
ธ๋๊ฐ ์ ์ด๋ 2๊ฐ ํฌํจ๋ ํด๋ฌ์คํฐ์์ ์คํํ๋ ๊ฒ์ ์ถ์ฒํ๋ค. ๋ง์ฝ, ์์ง ํด๋ฌ์คํฐ๋ฅผ ๊ฐ์ง๊ณ
์์ง ์๋ค๋ฉด,
minikube ๋ฅผ ์ฌ์ฉํด์ ์์ฑํ๊ฑฐ๋
๋ค์ ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ์ด๊ทธ๋ผ์ด๋ ์ค ํ๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
๋ฒ์ ํ์ธ์ ์ํด์, ๋ค์ ์ปค๋งจ๋๋ฅผ ์คํ kubectl version
.
์ด ์์๋
kubectl
1.14 ์ด์ ๋ฒ์ ์์ ๋์ํ๋ค.
๋ค์ ์ค์ ํ์ผ์ ๋ค์ด๋ก๋ํ๋ค.
mysql-deployment.yaml
wordpress-deployment.yaml
ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์๊ณผ ํผ์์คํดํธ๋ณผ๋ฅจ ์์ฑ MySQL๊ณผ Wordpress๋ ๊ฐ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ํผ์์คํดํธ๋ณผ๋ฅจ์ด ํ์ํ๋ค. ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์์ ๋ฐฐํฌ ๋จ๊ณ์ ์์ฑ๋๋ค.
๋ง์ ํด๋ฌ์คํฐ ํ๊ฒฝ์์ ์ค์น๋ ๊ธฐ๋ณธ ์คํ ๋ฆฌ์งํด๋์ค(StorageClass)๊ฐ ์๋ค. ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์์ ์คํ ๋ฆฌ์งํด๋์ค๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด ํด๋ฌ์คํฐ์ ๊ธฐ๋ณธ ์คํ ๋ฆฌ์งํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค.
ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์์ด ์์ฑ๋๋ฉด ํผ์์คํดํธ๋ณผ๋ฅจ์ด ์คํ ๋ฆฌ์งํด๋์ค ์ค์ ์ ๊ธฐ์ด๋ก ๋์ ์ผ๋ก ํ๋ก๋น์ ๋๋๋ค.
๊ฒฝ๊ณ : ๋ก์ปฌ ํด๋ฌ์คํฐ์์ ๊ธฐ๋ณธ ์คํ ๋ฆฌ์งํด๋์ค๋ hostPath
ํ๋ก๋น์ ๋๋ฅผ ์ฌ์ฉํ๋ค. hostPath
๋ ๊ฐ๋ฐ๊ณผ ํ
์คํธ ๋ชฉ์ ์๋ง ์ ํฉํ๋ค. hostPath
๋ณผ๋ฅจ์ธ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ ์ค์ผ์ฅด๋ง๋ ํ๋์ ๋
ธ๋์ /tmp
์ด์์๊ณ ๋
ธ๋ ๊ฐ์ ์ด๋ํ์ง ์๋๋ค. ํ๋๊ฐ ์ฃฝ์ด์ ํด๋ฌ์คํฐ ๋ด์ ๋ค๋ฅธ ๋
ธ๋๋ก ์ค์ผ์ค๋ง๋๊ฑฐ๋ ํด๋น ๋
ธ๋๊ฐ ์ฌ๋ถํ
๋๋ฉด ๊ทธ ๋ฐ์ดํฐ๋ ์์ด๋ฒ๋ฆฐ๋ค.
์ฐธ๊ณ : hostPath
ํ๋ก๋น์ ๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ํด๋ฌ์คํฐ๋ฅผ ๊ธฐ๋ํ๋ ๊ฒฝ์ฐ๋ผ๋ฉด --enable-hostpath-provisioner
ํ๋๊ทธ๋ฅผ controller-manager
์ปดํฌ๋ํธ์ ๊ผญ ์ค์ ํด์ผ ํ๋ค.์ฐธ๊ณ : ๋ง์ฝ ๊ตฌ๊ธ ์ฟ ๋ฒ๋คํฐ์ค ์์ง์ผ๋ก ์ด์ํ๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด
๊ฐ์ด๋ ๋ฅผ ๋ฐ๋ฅด๋๋ก ํ๋ค.
kustomization.yaml ์์ฑํ๊ธฐ ์ํฌ๋ฆฟ ์์ฑ์ ์ถ๊ฐ ์ํฌ๋ฆฟ ์ ์ํธ๋ ํค ๊ฐ์ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ค์ ์ ์ฅํ๋ ์ค๋ธ์ ํธ์ด๋ค. 1.14 ๋ฒ์ ๋ถํฐ kubectl
์ kustomization ํ์ผ์ ์ด์ฉํด์ ์ฟ ๋ฒ๋คํฐ์ค ์ค๋ธ์ ํธ๋ฅผ ๊ด๋ฆฌํ๋ค. kustomization.yaml
์ ์ ๋๋ ์ดํฐ๋ก ์ํฌ๋ฆฟ์ ์์ฑํ ์ ์๋ค.
๋ค์ ๋ช
๋ น์ด๋ก kustomization.yaml
๋ด์ ์ํฌ๋ฆฟ ์ ๋ค๋ ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ค. YOUR_PASSWORD
๋ ์ฌ์ฉํ๊ธฐ ์ํ๋ ์ํธ๋ก ๋ณ๊ฒฝํด์ผ ํ๋ค.
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: mysql-pass
literals:
- password=YOUR_PASSWORD
EOF
MySQL๊ณผ WordPress์ ํ์ํ ๋ฆฌ์์ค ๊ตฌ์ฑ ์ถ๊ฐํ๊ธฐ ๋ค์ ๋งค๋ํ์คํธ๋ MySQL ๋ํ๋ก์ด๋จผํธ ๋จ์ผ ์ธ์คํด์ค๋ฅผ ๊ธฐ์ ํ๋ค. MySQL ์ปจ์ผ์ด๋๋ ํผ์์คํดํธ๋ณผ๋ฅจ์ /var/lib/mysql์ ๋ง์ดํธํ๋ค. MYSQL_ROOT_PASSWORD
ํ๊ฒฝ ๋ณ์๋ ์ํฌ๋ฆฟ์์ ๊ฐ์ ธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ๋ก ์ค์ ํ๋ค.
apiVersion : v1
kind : Service
metadata :
name : wordpress-mysql
labels :
app : wordpress
spec :
ports :
- port : 3306
selector :
app : wordpress
tier : mysql
clusterIP : None
---
apiVersion : v1
kind : PersistentVolumeClaim
metadata :
name : mysql-pv-claim
labels :
app : wordpress
spec :
accessModes :
- ReadWriteOnce
resources :
requests :
storage : 20Gi
---
apiVersion : apps/v1
kind : Deployment
metadata :
name : wordpress-mysql
labels :
app : wordpress
spec :
selector :
matchLabels :
app : wordpress
tier : mysql
strategy :
type : Recreate
template :
metadata :
labels :
app : wordpress
tier : mysql
spec :
containers :
- image : mysql:8.0
name : mysql
env :
- name : MYSQL_ROOT_PASSWORD
valueFrom :
secretKeyRef :
name : mysql-pass
key : password
- name : MYSQL_DATABASE
value : wordpress
- name : MYSQL_USER
value : wordpress
- name : MYSQL_PASSWORD
valueFrom :
secretKeyRef :
name : mysql-pass
key : password
ports :
- containerPort : 3306
name : mysql
volumeMounts :
- name : mysql-persistent-storage
mountPath : /var/lib/mysql
volumes :
- name : mysql-persistent-storage
persistentVolumeClaim :
claimName : mysql-pv-claim
๋ค์์ ๋งค๋ํ์คํธ๋ ๋จ์ผ-์ธ์คํด์ค WordPress ๋ํ๋ก์ด๋จผํธ๋ฅผ ๊ธฐ์ ํ๋ค. WordPress ์ปจํ
์ด๋๋
์น์ฌ์ดํธ ๋ฐ์ดํฐ ํ์ผ์ ์ํด /var/www/html
์ ํผ์์คํดํธ๋ณผ๋ฅจ์ ๋ง์ดํธํ๋ค. WORDPRESS_DB_HOST
ํ๊ฒฝ ๋ณ์์๋
์์์ ์ ์ํ MySQL ์๋น์ค์ ์ด๋ฆ์ด ์ค์ ๋๋ฉฐ, WordPress๋ ์๋น์ค๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ๋ค.
WORDPRESS_DB_PASSWORD
ํ๊ฒฝ ๋ณ์์๋ kustomize๊ฐ ์์ฑํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํจ์ค์๋๊ฐ ์ค์ ๋๋ค.
apiVersion : v1
kind : Service
metadata :
name : wordpress
labels :
app : wordpress
spec :
ports :
- port : 80
selector :
app : wordpress
tier : frontend
type : LoadBalancer
---
apiVersion : v1
kind : PersistentVolumeClaim
metadata :
name : wp-pv-claim
labels :
app : wordpress
spec :
accessModes :
- ReadWriteOnce
resources :
requests :
storage : 20Gi
---
apiVersion : apps/v1
kind : Deployment
metadata :
name : wordpress
labels :
app : wordpress
spec :
selector :
matchLabels :
app : wordpress
tier : frontend
strategy :
type : Recreate
template :
metadata :
labels :
app : wordpress
tier : frontend
spec :
containers :
- image : wordpress:4.8-apache
name : wordpress
env :
- name : WORDPRESS_DB_HOST
value : wordpress-mysql
- name : WORDPRESS_DB_PASSWORD
valueFrom :
secretKeyRef :
name : mysql-pass
key : password
ports :
- containerPort : 80
name : wordpress
volumeMounts :
- name : wordpress-persistent-storage
mountPath : /var/www/html
volumes :
- name : wordpress-persistent-storage
persistentVolumeClaim :
claimName : wp-pv-claim
MySQL ๋ํ๋ก์ด๋จผํธ ๊ตฌ์ฑ ํ์ผ์ ๋ค์ด๋ก๋ํ๋ค.
curl -LO https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
WordPress ๊ตฌ์ฑ ํ์ผ์ ๋ค์ด๋ก๋ํ๋ค.
curl -LO https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
๋ ํ์ผ์ kustomization.yaml
์ ์ถ๊ฐํ์.
cat <<EOF >>./kustomization.yaml
resources:
- mysql-deployment.yaml
- wordpress-deployment.yaml
EOF
์ ์ฉํ๊ณ ํ์ธํ๊ธฐ kustomization.yaml
์ WordPress ์ฌ์ดํธ์ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ฐฐํฌํ๋ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ํฌํจํ๋ค.
๋ค์๊ณผ ๊ฐ์ด ๋๋ ํฐ๋ฆฌ๋ฅผ ์ ์ฉํ ์ ์๋ค.
์ด์ ๋ชจ๋ ์ค๋ธ์ ํธ๊ฐ ์กด์ฌํ๋์ง ํ์ธํ ์ ์๋ค.
์ํฌ๋ฆฟ์ด ์กด์ฌํ๋์ง ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ์ฌ ํ์ธํ๋ค.
์๋ต์ ์๋์ ๋น์ทํด์ผ ํ๋ค.
NAME TYPE DATA AGE
mysql-pass-c57bb4t7mf Opaque 1 9s
ํผ์์คํดํธ๋ณผ๋ฅจ์ด ๋์ ์ผ๋ก ํ๋ก๋น์ ๋๋์๋์ง ํ์ธํ๋ค.
์ฐธ๊ณ : PV๋ฅผ ํ๋ก๋น์ ๋ํ๊ณ ์ ์ฐฉ(bound)์ํค๋๋ฐ ์ ๋ถ์ด ๊ฑธ๋ฆด ์ ์๋ค.
์๋ต์ ์๋์ ๋น์ทํด์ผ ํ๋ค.
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-pv-claim Bound pvc-8cbd7b2e-4044-11e9-b2bb-42010a800002 20Gi RWO standard 77s
wp-pv-claim Bound pvc-8cd0df54-4044-11e9-b2bb-42010a800002 20Gi RWO standard 77s
๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ์ฌ ํ๋๊ฐ ์คํ ์ค์ธ์ง ํ์ธํ๋ค.
์ฐธ๊ณ : ํ๋์ ์ํ๊ฐ `RUNNING`๊ฐ ๋๊ธฐ๊น์ง ์ ๋ถ์ด ๊ฑธ๋ฆด ์ ์๋ค.
์๋ต์ ์๋์ ๋น์ทํด์ผ ํ๋ค.
NAME READY STATUS RESTARTS AGE
wordpress-mysql-1894417608-x5dzt 1/1 Running 0 40s
๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ์ฌ ์๋น์ค๊ฐ ์คํ ์ค์ธ์ง ํ์ธํด๋ณด์.
kubectl get services wordpress
์๋ต์ ์๋์ ๋น์ทํด์ผ ํ๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress LoadBalancer 10.0.0.89 <pending> 80:32406/TCP 4m
์ฐธ๊ณ : Minikube์์๋ ์๋น์ค๋ฅผ `NodePort`์ผ๋ก๋ง ๋
ธ์ถํ ์ ์๋ค. EXTERNAL-IP๋ ํญ์ Pending ์ํ์ด๋ค.
๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ์ฌ WordPress ์๋น์ค์ IP ์ฃผ์๋ฅผ ์ป์ด์จ๋ค.
minikube service wordpress --url
์๋ต์ ์๋์ ๋น์ทํด์ผ ํ๋ค.
http://1.2.3.4:32406
IP ์ฃผ์๋ฅผ ๋ณต์ฌํด์ ์น ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ดํธ๋ฅผ ์ด์ด ๋ณด์.
์๋ ์คํฌ๋ฆฐ์ท๊ณผ ์ ์ฌํ WordPress ์ค์ ํ์ด์ง๋ฅผ ๋ณผ ์ ์์ด์ผ ํ๋ค.
๊ฒฝ๊ณ : ์ด ํ์ด์ง์ WordPress ์ค์น๋ฅผ ๋ด๋ฒ๋ ค ๋์ง ๋ง์. ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ์ด ํ์ด์ง๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๊ทํ์ ์ธ์คํด์ค์ ์น ์ฌ์ดํธ๋ฅผ ์ค์ ํ๊ณ ์
์์ ์ธ ์ปจํ
์ธ ๋ฅผ ๊ฒ์ํ๋๋ฐ ์ฌ์ฉํ ์ ์๋ค. WordPress๋ฅผ ์ฌ์ฉ์๋ช
๊ณผ ์ํธ๋ฅผ ๋ฃ์ด ์์ฑํ๊ฑฐ๋ ์ธ์คํด์ค๋ฅผ ์ญ์ ํ์.์ ๋ฆฌํ๊ธฐ ๋ค์ ๋ช
๋ น์ ์คํํ์ฌ ์ํฌ๋ฆฟ, ๋ํ๋ก์ด๋จผํธ, ์๋น์ค์ ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์์ ์ญ์ ํ์.
๋ค์ ๋ด์ฉ 6.3 - ์์: ์นด์ฐ๋๋ผ๋ฅผ ์คํ
์ดํธํ์
์ผ๋ก ๋ฐฐํฌํ๊ธฐ ์ด ํํ ๋ฆฌ์ผ์ ์ฟ ๋ฒ๋คํฐ์ค์์ ์ํ์น ์นด์ฐ๋๋ผ ๋ฅผ ์คํํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์ธ ์นด์ฐ๋๋ผ๋ ๋ฐ์ดํฐ ๋ด๊ตฌ์ฑ์ ์ ๊ณตํ๊ธฐ ์ํด ํผ์์คํดํธ ์คํ ๋ฆฌ์ง๊ฐ ํ์ํ๋ค(์ ํ๋ฆฌ์ผ์ด์
์ํ ).
์ด ์์ ์์ ์ฌ์ฉ์ ์ง์ ์นด์ฐ๋๋ผ ์๋ ๊ณต๊ธ์๋ ์นด์ฐ๋๋ผ๊ฐ ํด๋ฌ์คํฐ์ ๊ฐ์
ํ ๋ ์นด์ฐ๋๋ผ๊ฐ ์ธ์คํด์ค๋ฅผ ๊ฒ์ํ ์ ์๋๋ก ํ๋ค.
์คํ
์ดํธํ์
์ ์ํ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ์ฝ๊ฒ ๋ฐฐํฌํ ์ ์๊ฒ ํ๋ค.
์ด ํํ ๋ฆฌ์ผ์์ ์ด์ฉํ ๊ธฐ๋ฅ์ ์์ธํ ์ ๋ณด๋
์คํ
์ดํธํ์
์ ์ฐธ์กฐํ๋ค.
์ฐธ๊ณ : ์นด์ฐ๋๋ผ์ ์ฟ ๋ฒ๋คํฐ์ค๋ ํด๋ฌ์คํฐ ๋งด๋ฒ๋ผ๋ ์๋ฏธ๋ก ๋
ธ๋ ๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ค. ์ด
ํํ ๋ฆฌ์ผ์์ ์คํ
์ดํธํ์
์ ์ํ๋ ํ๋๋ ์นด์ฐ๋๋ผ ๋
ธ๋์ด๋ฉฐ ์นด์ฐ๋๋ผ
ํด๋ก์คํฐ์ ๋งด๋ฒ(๋ง ์ด๋ผ ํจ)์ด๋ค. ํด๋น ํ๋๊ฐ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์์ ์คํ๋ ๋,
์ฟ ๋ฒ๋คํฐ์ค ์ปจํธ๋กค ํ๋ ์ธ์ ํด๋น ํ๋๋ฅผ ์ฟ ๋ฒ๋คํฐ์ค
๋
ธ๋ ์ ์ค์ผ์ค ํ๋ค.
์นด์ฐ๋๋ผ ๋
ธ๋๊ฐ ์์๋๋ฉด ์๋ ๋ชฉ๋ก ์ ์ฌ์ฉํด์ ๋ง์ ์๋ ๋ค๋ฅธ ๋
ธ๋ ๊ฒ์์ ์ํ
์ํ ๋ถํธ์คํธ๋ฉ์ ํ๋ค.
์ด ํํ ๋ฆฌ์ผ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด๋ถ์ ๋ํ๋ ๋ ์๋ก์ด ์นด์ฐ๋๋ผ
ํ๋๋ฅผ ๊ฒ์ํ ์ ์๋ ์ฌ์ฉ์ ์ง์ ์นด์ฐ๋๋ผ ์๋ ๊ณต๊ธ์๋ฅผ ๋ฐฐํฌํ๋ค.
๋ชฉ์ ์นด์ฐ๋๋ผ ํค๋๋ฆฌ์ค Service ๋ฅผ ์์ฑํ๊ณ ๊ฒ์ฆํ๋ค. ์คํ
์ดํธํ์
(StatefulSet) ์ ์ด์ฉํ์ฌ ์นด์ฐ๋๋ผ ๋ง์ ์์ฑํ๋ค.์คํ
์ดํธํ์
์ ๊ฒ์ฆํ๋ค. ์คํ
์ดํธํ์
์ ์์ ํ๋ค. ์คํ
์ดํธํ์
๊ณผ ํฌํจ๋ ํ๋ ๋ฅผ ์ญ์ ํ๋ค. ์์ํ๊ธฐ ์ ์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๊ฐ ํ์ํ๊ณ , kubectl ์ปค๋งจ๋-๋ผ์ธ ํด์ด ํด๋ฌ์คํฐ์
ํต์ ํ ์ ์๋๋ก ์ค์ ๋์ด ์์ด์ผ ํ๋ค. ์ด ํํ ๋ฆฌ์ผ์ ์ปจํธ๋กค ํ๋ ์ธ ํธ์คํธ๊ฐ ์๋ ๋
ธ๋๊ฐ ์ ์ด๋ 2๊ฐ ํฌํจ๋ ํด๋ฌ์คํฐ์์ ์คํํ๋ ๊ฒ์ ์ถ์ฒํ๋ค. ๋ง์ฝ, ์์ง ํด๋ฌ์คํฐ๋ฅผ ๊ฐ์ง๊ณ
์์ง ์๋ค๋ฉด,
minikube ๋ฅผ ์ฌ์ฉํด์ ์์ฑํ๊ฑฐ๋
๋ค์ ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ์ด๊ทธ๋ผ์ด๋ ์ค ํ๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ด ํํ ๋ฆฌ์ผ์ ์๋ฃํ๋ ค๋ฉด,
ํ๋ ,
์๋น์ค ,
์คํ
์ดํธํ์
์ ๋ํ ๊ธฐ๋ณธ ์ง์์ด ์์ด์ผ ํ๋ค.
์ถ๊ฐ์ ์ธ Minikube ์ค์ ์๋ น ์ฃผ์: Minikube ๋ 2048MB ๋ฉ๋ชจ๋ฆฌ์ 2๊ฐ CPU๊ฐ ๊ธฐ๋ณธ ์ค์ ์ด๋ค.
์ด ํํ ๋ฆฌ์ผ์์ Minikube๋ฅผ ๊ธฐ๋ณธ ๋ฆฌ์์ค ์ค์ ์ผ๋ก ์คํํ๋ฉด ๋ฆฌ์์ค ๋ถ์กฑ ์ค๋ฅ๊ฐ
๋ฐ์ํ๋ค. ์ด๋ฐ ์ค๋ฅ๋ฅผ ํผํ๋ ค๋ฉด Minikube๋ฅผ ๋ค์ ์ค์ ์ผ๋ก ์คํํ์.
minikube start --memory 5120 --cpus= 4
์นด์ฐ๋๋ผ๋ฅผ ์ํ ํค๋๋ฆฌ์ค ์๋น์ค ์์ฑํ๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค ์์ ์๋น์ค ๋ ๋์ผ ์์
์ ์ํํ๋
ํ๋ ์ ์งํฉ์ ๊ธฐ์ ํ๋ค.
๋ค์์ ์๋น์ค๋ ํด๋ฌ์คํฐ์์ ์นด์ฐ๋๋ผ ํ๋์ ํด๋ผ์ด์ธํธ ๊ฐ์ DNS ์ฐพ์๋ณด๊ธฐ ์ฉ๋๋ก ์ฌ์ฉํ๋ค.
apiVersion : v1
kind : Service
metadata :
labels :
app : cassandra
name : cassandra
spec :
clusterIP : None
ports :
- port : 9042
selector :
app : cassandra
cassandra-service.yaml
ํ์ผ์์ ์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
๋
ธ๋๋ฅผ ๋ชจ๋ ์ถ์ ํ๋ ์๋น์ค๋ฅผ ์์ฑํ๋ค.
kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-service.yaml
๊ฒ์ฆํ๊ธฐ(์ ํ) ์นด์ฐ๋๋ผ ์๋น์ค ์ดํด๋ณด๊ธฐ
kubectl get svc cassandra
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra ClusterIP None <none> 9042/TCP 45s
cassandra
์๋น์ค๊ฐ ๋ณด์ด์ง ์๋๋ค๋ฉด, ์ด์ ๋ค๋ฅธ ์๋ต์ด๋ผ๋ฉด ์๋น์ค ์์ฑ์ ์คํจํ ๊ฒ์ด๋ค. ์ผ๋ฐ์ ์ธ ๋ฌธ์ ์ ๋ํ
์๋น์ค ๋๋ฒ๊น
ํ๊ธฐ ๋ฅผ
์ฝ์ด๋ณด์.
์นด์ฐ๋๋ผ ๋ง์ ์์ฑํ๋ ์คํ
์ดํธํ์
์ด์ฉํ๊ธฐ ์คํ
์ดํธํ์
๋งค๋ํ์คํธ์๋ ๋ค์์ ํฌํจํ๋๋ฐ 3๊ฐ ํ๋๋ก ๊ตฌ์ฑ๋ ์นด์ฐ๋๋ผ ๋ง์ ์์ฑํ๋ค.
์ฐธ๊ณ : ์ด ์๋ Minikube๋ฅผ ์ํ ๊ธฐ๋ณธ ํ๋ก๋น์ ๋์ด๋ค.
๋ค์ ์คํ
์ดํธํ์
์ ์์
ํ๋ ํด๋ผ์ฐ๋ ํ๊ฒฝ์์ ๊ฐฑ์ ํ๋ค.apiVersion : apps/v1
kind : StatefulSet
metadata :
name : cassandra
labels :
app : cassandra
spec :
serviceName : cassandra
replicas : 3
selector :
matchLabels :
app : cassandra
template :
metadata :
labels :
app : cassandra
spec :
terminationGracePeriodSeconds : 500
containers :
- name : cassandra
image : gcr.io/google-samples/cassandra:v13
imagePullPolicy : Always
ports :
- containerPort : 7000
name : intra-node
- containerPort : 7001
name : tls-intra-node
- containerPort : 7199
name : jmx
- containerPort : 9042
name : cql
resources :
limits :
cpu : "500m"
memory : 1Gi
requests :
cpu : "500m"
memory : 1Gi
securityContext :
capabilities :
add :
- IPC_LOCK
lifecycle :
preStop :
exec :
command :
- /bin/sh
- -c
- nodetool drain
env :
- name : MAX_HEAP_SIZE
value : 512M
- name : HEAP_NEWSIZE
value : 100M
- name : CASSANDRA_SEEDS
value : "cassandra-0.cassandra.default.svc.cluster.local"
- name : CASSANDRA_CLUSTER_NAME
value : "K8Demo"
- name : CASSANDRA_DC
value : "DC1-K8Demo"
- name : CASSANDRA_RACK
value : "Rack1-K8Demo"
- name : POD_IP
valueFrom :
fieldRef :
fieldPath : status.podIP
readinessProbe :
exec :
command :
- /bin/bash
- -c
- /ready-probe.sh
initialDelaySeconds : 15
timeoutSeconds : 5
# These volume mounts are persistent. They are like inline claims,
# but not exactly because the names need to match exactly one of
# the stateful pod volumes.
volumeMounts :
- name : cassandra-data
mountPath : /cassandra_data
# These are converted to volume claims by the controller
# and mounted at the paths mentioned above.
# do not use these in production until ssd GCEPersistentDisk or other ssd pd
volumeClaimTemplates :
- metadata :
name : cassandra-data
spec :
accessModes : [ "ReadWriteOnce" ]
storageClassName : fast
resources :
requests :
storage : 1Gi
---
kind : StorageClass
apiVersion : storage.k8s.io/v1
metadata :
name : fast
provisioner : k8s.io/minikube-hostpath
parameters :
type : pd-ssd
cassandra-statefulset.yaml
ํ์ผ๋ก ์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
์์ฑ
# cassandra-statefulset.yaml์ ์์ ํ์ง ์์ ๊ฒฝ์ฐ์ ์ด๊ฒ์ ์ฌ์ฉํ๋ค.
kubectl apply -f https://k8s.io/examples/application/cassandra/cassandra-statefulset.yaml
ํด๋ฌ์คํฐ์ ๋ง๊ฒ cassandra-statefulset.yaml
๋ฅผ ์์ ํด์ผ ํ๋ ๊ฒฝ์ฐ ๋ค์์ ๋ค์ด๋ก๋ํ ๋ค์
์์ ๋ ๋ฒ์ ์ ์ ์ฅํ ํด๋์์ ํด๋น ๋งค๋ํ์คํธ๋ฅผ ์ ์ฉํ๋ค.
https://k8s.io/examples/application/cassandra/cassandra-statefulset.yaml
# cassandra-statefulset.yaml์ ๋ก์ปฌ์์ ์์ ํ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.
kubectl apply -f cassandra-statefulset.yaml
์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
๊ฒ์ฆํ๊ธฐ ์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
์ป๊ธฐ
kubectl get statefulset cassandra
์๋ต์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
NAME DESIRED CURRENT AGE
cassandra 3 0 13s
StatefulSet
๋ฆฌ์์ค๋ ์์ฐจ์ ์ผ๋ก ํ๋๋ฅผ ๋ฐฐํฌํ๋ค.
์์ฐจ์ ์ผ๋ก ์์ฑ๋ ํํฉ์ ๋ณด๊ธฐ ์ํด ํ๋๋ฅผ ์ดํด๋ณด์.
kubectl get pods -l= "app=cassandra"
์๋ต์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
NAME READY STATUS RESTARTS AGE
cassandra-0 1/1 Running 0 1m
cassandra-1 0/1 ContainerCreating 0 8s
๋ชจ๋ 3๊ฐ ํ๋๊ฐ ๋ฐฐํฌ๋๊ธฐ๊น์ง ๋ช ๋ถ์ด ์์๋ ์ ์๋ค. ๋ฐฐํฌ ํ, ๋์ผ ๋ช
๋ น์ ๋ค์๊ณผ ์ ์ฌํ๊ฒ
์๋ตํ๋ค.
NAME READY STATUS RESTARTS AGE
cassandra-0 1/1 Running 0 10m
cassandra-1 1/1 Running 0 9m
cassandra-2 1/1 Running 0 8m
์ฒซ ๋ฒ์งธ ํ๋ ๋ด๋ถ์ ๋ง์ ์ํ๋ฅผ ๋ณด์ฌ์ฃผ๋ ์นด์ฐ๋๋ผ
nodetool ์ ์คํํ์.
kubectl exec -it cassandra-0 -- nodetool status
์ด ์๋ต์ ๋ค์๊ณผ ๋น์ทํ๊ฒ ๋ณด์ผ ๊ฒ์ด๋ค.
Datacenter: DC1-K8Demo
======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns (effective) Host ID Rack
UN 172.17.0.5 83.57 KiB 32 74.0% e2dd09e6-d9d3-477e-96c5-45094c08db0f Rack1-K8Demo
UN 172.17.0.4 101.04 KiB 32 58.8% f89d6835-3a42-4419-92b3-0e62cae1479c Rack1-K8Demo
UN 172.17.0.6 84.74 KiB 32 67.1% a6a1e8c2-3dc5-4417-b1a0-26507af2aaad Rack1-K8Demo
์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
์์ ํ๊ธฐ kubectl edit
๋ฅผ ์ฌ์ฉํ์ฌ ์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
์ ํฌ๊ธฐ๋ฅผ ์์ ํ๋ค.
๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
kubectl edit statefulset cassandra
์ด ๋ช
๋ น์ ํฐ๋ฏธ๋์์ ํธ์ง๊ธฐ๋ฅผ ์ฐ๋ค. ๋ณ๊ฒฝํด์ผํ ํ์ replicas
ํ๋์ด๋ค.
๋ค์ ์์ ๋ ์คํ
์ดํธํ์
ํ์ผ์์ ๋ฐ์ทํ๋ค.
# ๋ค์์ ์ค๋ธ์ ํธ๋ฅผ ์์ ํ๋ค. '#'๋ก ์์ํ๋ ํ์ ๋ฌด์๋๊ณ ,
# ๋น ํ์ผ์ ํธ์ง์ ์ค๋จํ๋ค. ์ ์ฅํ ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ด ํ์ผ์ด
# ๊ด๋ จ ์คํจ์ ํจ๊ป ๋ค์ ์ด๋ฆฐ๋ค.
#
apiVersion : apps/v1
kind : StatefulSet
metadata :
creationTimestamp : 2016-08-13T18:40:58Z
generation : 1
labels :
app : cassandra
name : cassandra
namespace : default
resourceVersion : "323"
uid : 7a219483-6185-11e6-a910-42010a8a0fc0
spec :
replicas : 3
๋ ํ๋ฆฌ์นด ๊ฐ์๋ฅผ 4๋ก ๋ฐ๊พธ๊ณ , ๋งค๋ํ์คํธ๋ฅผ ์ ์ฅํ๋ค.
์คํ
์ดํธํ์
์ 4๊ฐ์ ํ๋๋ฅผ ์คํํ๊ธฐ ์ํด ์ค์ผ์ผ ํ๋ค.
๊ฒ์ฆํ๊ธฐ ์ํด ์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
์ ์ดํด๋ณด์
kubectl get statefulset cassandra
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ์ ์ฌํ๋ค.
NAME DESIRED CURRENT AGE
cassandra 4 4 36m
์ ๋ฆฌํ๊ธฐ ์คํ
์ดํธํ์
์ ์ญ์ ํ๊ฑฐ๋ ์ค์ผ์ผ๋งํ๋ ๊ฒ์ ์คํ
์ดํธํ์
์ ์ฐ๊ด๋ ๋ณผ๋ฅจ์ ์ญ์ ํ์ง ์๋๋ค.
๋น์ ์ ๋ฐ์ดํฐ๊ฐ ์คํ
์ดํธํ์
์ ๊ด๋ จ๋ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ์๋์ผ๋ก ์ ๊ฑฐํ๋ ๊ฒ๋ณด๋ค ๋ ๊ฐ์น์๊ธฐ์ ์ด ์ค์ ์ ๋น์ ์ ์์ ์ ์ํ ๊ฒ์ด๋ค.
๊ฒฝ๊ณ : ์คํ ๋ฆฌ์ง ํด๋์ค์ ๋ฆฌํด๋ ์ ์ ์ฑ
์ ๋ฐ๋ผ ํผ์์คํด์ค๋ณผ๋ฅจํด๋ ์ ์ ์ญ์ ํ๋ฉด ๊ทธ์ ์ฐ๊ด๋ ๋ณผ๋ฅจ๋
์ญ์ ๋ ์ ์๋ค. ๋ณผ๋ฅจ ์์ฒญ์ด ์ญ์ ๋์ด๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ทผํ ์ ์๋ค๊ณ ์ ๋๋ก ๊ฐ์ ํ์ง ๋ง์.๋ค์ ๋ช
๋ น์ด(ํ ์ค๋ก ์ฐ๊ฒฐ๋)๋ฅผ ์คํํ์ฌ ์นด์ฐ๋๋ผ ์คํ
์ดํธํ์
์ ๋ชจ๋ ์ ๊ฑฐํ์.
grace = $( kubectl get pod cassandra-0 -o= jsonpath = '{.spec.terminationGracePeriodSeconds}' ) \
&& kubectl delete statefulset -l app = cassandra \
&& echo "Sleeping ${ grace } seconds" 1>&2 \
&& sleep $grace \
&& kubectl delete persistentvolumeclaim -l app = cassandra
๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ์ฌ ์นด์ฐ๋๋ผ์ ๋ํด ์ค์ ํ ์๋น์ค๋ฅผ ์ ๊ฑฐํ์.
kubectl delete service -l app = cassandra
์นด์ฐ๋๋ผ ์ปจํ
์ด๋ ํ๊ฒฝ ๋ณ์ ์ด ํํ ๋ฆฌ์ผ์ ํ๋ ๋ ๊ตฌ๊ธ์ ์ปจํ
์ด๋ ๋ ์ง์คํธ๋ฆฌ ์
gcr.io/google-samples/cassandra:v13
์ด๋ฏธ์ง๋ฅผ ์ด์ฉํ๋ค.
์ด ๋์ปค ์ด๋ฏธ์ง๋ debian-base ์
๊ธฐ๋ฐํ์๊ณ OpenJDK 8์ ํฌํจํ๋ค.
์ด ์ด๋ฏธ์ง๋ ์ํ์น ๋ฐ๋น์ ๋ฆฌํฌ์ ํ์ค ์นด์ฐ๋๋ผ ์ค์น๋ณธ์ ํฌํจํ๋ค.
ํ๊ฒฝ ๋ณ์๋ฅผ ์ด์ฉํ์ฌ cassandra.yaml
์ ์ฝ์
๋ ๊ฐ์ ๋ฐ๊ฟ ์ ์๋ค.
ํ๊ฒฝ ๋ณ์ ๊ธฐ๋ณธ๊ฐ CASSANDRA_CLUSTER_NAME
'Test Cluster'
CASSANDRA_NUM_TOKENS
32
CASSANDRA_RPC_ADDRESS
0.0.0.0
๋ค์ ๋ด์ฉ 6.4 - ๋ถ์ฐ ์์คํ
์ฝ๋๋ค์ดํฐ ZooKeeper ์คํํ๊ธฐ ์ด ํํ ๋ฆฌ์ผ์ ์ํ์น ZooKeeper
์ฟ ๋ฒ๋คํฐ์ค์์ ์คํ
์ดํธํ์
๊ณผ
PodDisruptionBudget ๊ณผ
ํ๋์ํฐ์ดํผ๋ํฐ(PodAntiAffinity) ๋ฅผ ์ด์ฉํ Apache Zookeeper ์คํ์ ์ค๋ช
ํ๋ค.
์์ํ๊ธฐ ์ ์ ์ด ํํ ๋ฆฌ์ผ์ ์์ํ๊ธฐ ์ ์
๋ค์ ์ฟ ๋ฒ๋คํฐ์ค ๊ฐ๋
์ ์น์ํด์ผ ํ๋ค.
๋ฐ๋์ ์ต์ํ 4๊ฐ์ ๋
ธ๋๊ฐ ์๋ ํด๋ฌ์คํฐ๊ฐ ํ์ํ๋ฉฐ, ๊ฐ ๋
ธ๋๋ ์ ์ด๋ 2 ๊ฐ์ CPU์ 4 GiB ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํ๋ค. ์ด ํํ ๋ฆฌ์ผ์์ ํด๋ฌ์คํฐ ๋
ธ๋๋ฅผ ํต์ (cordon)ํ๊ณ ๋น์ฐ๊ฒ(drain) ํ ๊ฒ์ด๋ค. ์ด๊ฒ์ ํด๋ฌ์คํฐ๋ฅผ ์ข
๋ฃํ์ฌ ๋
ธ๋์ ๋ชจ๋ ํ๋๋ฅผ ์ถ์ถ(evict)ํ๋ ๊ฒ์ผ๋ก, ๋ชจ๋ ํ๋๋ ์์๋ก ์ธ์ค์ผ์ค๋๋ค๋ ์๋ฏธ์ด๋ค. ์ด ํํ ๋ฆฌ์ผ์ ์ํด ์ ์ฉ ํด๋ฌ์คํฐ๋ฅผ ์ด์ฉํ๊ฑฐ๋, ๋ค๋ฅธ ํ
๋ํธ์ ๊ฐ์ญ์ ํ๋ ํผ๋์ด ๋ฐ์ํ์ง ์๋๋ก ํด์ผ ํฉ๋๋ค.
์ด ํํ ๋ฆฌ์ผ์ ํด๋ฌ์คํฐ๊ฐ ๋์ ์ผ๋ก ํผ์์คํดํธ๋ณผ๋ฅจ์ ํ๋ก๋น์ ๋ํ๋๋ก ๊ตฌ์ฑํ๋ค๊ณ ๊ฐ์ ํ๋ค.
๊ทธ๋ ๊ฒ ์ค์ ๋์ด ์์ง ์๋ค๋ฉด
ํํ ๋ฆฌ์ผ์ ์์ํ๊ธฐ ์ ์ ์๋์ผ๋ก 3๊ฐ์ 20 GiB ๋ณผ๋ฅจ์
ํ๋ก๋น์ ๋ํด์ผ ํ๋ค.
๋ชฉ์ ์ด ํํ ๋ฆฌ์ผ์ ๋ง์น๋ฉด ๋ค์์ ๋ํด ์๊ฒ ๋๋ค.
์ด๋ป๊ฒ ์คํ
์ดํธํ์
์ ์ด์ฉํ์ฌ ZooKeeper ์์๋ธ์ ๋ฐฐํฌํ๋๊ฐ. ์ด๋ป๊ฒ ์์๋ธ์ ์ผ๊ด๋๊ฒ ์ค์ ํ๋๊ฐ. ์ด๋ป๊ฒ ZooKeeper ์๋ฒ ๋ํ๋ก์ด๋จผํธ๋ฅผ ์์๋ธ ์์์ ํผ๋จ๋ฆฌ๋๊ฐ. ์ด๋ป๊ฒ PodDisruptionBudget์ ์ด์ฉํ์ฌ ๊ณํ๋ ์ ๊ฒ ๊ธฐ๊ฐ ๋์ ์๋น์ค ๊ฐ์ฉ์ฑ์ ๋ณด์ฅํ๋๊ฐ. ZooKeeper ์ํ์น ZooKeeper ๋
๋ถ์ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ ๋ถ์ฐ ์คํ ์์ค ์ฝ๋๋ค์ด์
์๋น์ค์ด๋ค.
ZooKeeper๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ฐ๊ณ ๊ฐฑ์ ์ ์ง์ผ๋ณด๋๋ก ํ๋ค. ๋ฐ์ดํฐ๋
ํ์ผ์์คํ
์ฒ๋ผ ๊ณ์ธต์ ์ผ๋ก ๊ด๋ฆฌ๋๊ณ ์์๋ธ(ZooKeeper ์๋ฒ์ ์งํฉ) ๋ด์ ๋ชจ๋ ZooKeeper์๋ฒ์ ๋ณต์ ๋๋ค.
๋ฐ์ดํฐ์ ๋ชจ๋ ์ฐ์ฐ์ ์์์ ์ด๊ณ ์์ฒ์ ์ผ๋ก ์ผ๊ด๋๋ค. ZooKeeper๋
Zab ํฉ์ ํ๋กํ ์ฝ์
์ด์ฉํ์ฌ ์์๋ธ ๋ด์ ๋ชจ๋ ์๋ฒ์ ๊ฑธ์ณ ์ํ ๋จธ์ ์ ๋ณต์ ํ์ฌ ์ด๋ฅผ ๋ณด์ฅํ๋ค.
์์๋ธ์ ๋ฆฌ๋ ์ ์ถ์ ์ํด Zab ํ๋กํ ์ฝ์ ์ฌ์ฉํ๊ณ , ๋ฆฌ๋ ์ ์ถ๊ณผ ์ ๊ฑฐ๊ฐ ์๋ฃ๋๊ธฐ ์ ๊น์ง ์์๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ธ ์ ์๋ค. ์๋ฃ๋๋ฉด ์์๋ธ์ Zab์ ์ด์ฉํ์ฌ ํ์ธํ๊ณ ํด๋ผ์ด์ธํธ์ ๋ณด์ด๋๋ก ๋ชจ๋ ์ฐ๊ธฐ๋ฅผ ์ฟผ๋ผ(quorum)์ ๋ณต์ ํ๋ค. ๊ฐ์ค์น์๋ ์ฟผ๋ผ๊ณผ ๊ด๋ จ ์์ด, ์ฟผ๋ผ์ ํ์ฌ ๋ฆฌ๋๋ฅผ ํฌํจํ๋ ์์๋ธ์ ๋๋ค์ ์ปดํฌ๋ํธ์ด๋ค. ์๋ฅผ ๋ค์ด ์์๋ธ์ด 3๊ฐ ์๋ฒ์ธ ๊ฒฝ์ฐ, ๋ฆฌ๋์ ๋ค๋ฅธ ์๋ฒ๋ก ์ฟผ๋ผ์ ๊ตฌ์ฑํ๋ค. ์์๋ธ์ด ์ฟผ๋ผ์ ๋ฌ์ฑํ ์ ์๋ค๋ฉด, ์์๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ธ ์ ์๋ค.
ZooKeeper๋ ์ ์ฒด ์ํ ๋จธ์ ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ณด์กดํ๊ณ ๋ชจ๋ ๋์ฐ๋ณ์ด๋ฅผ ์ ์ฅ ๋ฏธ๋์ด์ ๋ด๊ตฌ์ฑ ์๋ WAL(Write Ahead Log)์ ๊ธฐ๋กํ๋ค. ์๋ฒ ์ฅ์ ์ WAL์ ์ฌ์ํ์ฌ ์ด์ ์ํ๋ฅผ ๋ณต์ํ ์ ์๋ค. WAL์ด ๋ฌด์ ํ์ผ๋ก ์ปค์ง๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ZooKeeper๋ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ์ฅ ๋ฏธ๋์ด์ ๋ฉ๋ชจ๋ฆฌ ์ํ์ ์ค๋
์ท์ ์ ์ฅํ๋ค. ์ด ์ค๋
์ท์ ๋ฉ๋ชจ๋ฆฌ์ ์ง์ ์ ์ฌํ ์ ์๊ณ ์ค๋
์ท ์ด์ ์ ๋ชจ๋ WAL ํญ๋ชฉ์ ์ญ์ ๋ ์ ์๋ค.
ZooKeeper ์์๋ธ ์์ฑํ๊ธฐ ์๋ ๋งค๋ํ์คํธ์๋
ํค๋๋ฆฌ์ค ์๋น์ค ,
์๋น์ค ,
PodDisruptionBudget ,
์คํ
์ดํธํ์
์ ํฌํจํ๋ค.
apiVersion : v1
kind : Service
metadata :
name : zk-hs
labels :
app : zk
spec :
ports :
- port : 2888
name : server
- port : 3888
name : leader-election
clusterIP : None
selector :
app : zk
---
apiVersion : v1
kind : Service
metadata :
name : zk-cs
labels :
app : zk
spec :
ports :
- port : 2181
name : client
selector :
app : zk
---
apiVersion : policy/v1
kind : PodDisruptionBudget
metadata :
name : zk-pdb
spec :
selector :
matchLabels :
app : zk
maxUnavailable : 1
---
apiVersion : apps/v1
kind : StatefulSet
metadata :
name : zk
spec :
selector :
matchLabels :
app : zk
serviceName : zk-hs
replicas : 3
updateStrategy :
type : RollingUpdate
podManagementPolicy : OrderedReady
template :
metadata :
labels :
app : zk
spec :
affinity :
podAntiAffinity :
requiredDuringSchedulingIgnoredDuringExecution :
- labelSelector :
matchExpressions :
- key : "app"
operator : In
values :
- zk
topologyKey : "kubernetes.io/hostname"
containers :
- name : kubernetes-zookeeper
imagePullPolicy : Always
image : "registry.k8s.io/kubernetes-zookeeper:1.0-3.4.10"
resources :
requests :
memory : "1Gi"
cpu : "0.5"
ports :
- containerPort : 2181
name : client
- containerPort : 2888
name : server
- containerPort : 3888
name : leader-election
command :
- sh
- -c
- "start-zookeeper \
--servers=3 \
--data_dir=/var/lib/zookeeper/data \
--data_log_dir=/var/lib/zookeeper/data/log \
--conf_dir=/opt/zookeeper/conf \
--client_port=2181 \
--election_port=3888 \
--server_port=2888 \
--tick_time=2000 \
--init_limit=10 \
--sync_limit=5 \
--heap=512M \
--max_client_cnxns=60 \
--snap_retain_count=3 \
--purge_interval=12 \
--max_session_timeout=40000 \
--min_session_timeout=4000 \
--log_level=INFO"
readinessProbe :
exec :
command :
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds : 10
timeoutSeconds : 5
livenessProbe :
exec :
command :
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds : 10
timeoutSeconds : 5
volumeMounts :
- name : datadir
mountPath : /var/lib/zookeeper
securityContext :
runAsUser : 1000
fsGroup : 1000
volumeClaimTemplates :
- metadata :
name : datadir
spec :
accessModes : [ "ReadWriteOnce" ]
resources :
requests :
storage : 10Gi
ํฐ๋ฏธ๋์ ์ด๊ณ
kubectl apply
๋ช
๋ น์ด๋ก
๋งค๋ํ์คํธ๋ฅผ ์์ฑํ์.
kubectl apply -f https://k8s.io/examples/application/zookeeper/zookeeper.yaml
์ด๋ zk-hs
ํค๋๋ฆฌ์ค ์๋น์ค, zk-cs
์๋น์ค,
zk-pdb
PodDisruptionBudget๊ณผ zk
์คํ
์ดํธํ์
์ ์์ฑํ๋ค.
service/zk-hs created
service/zk-cs created
poddisruptionbudget.policy/zk-pdb created
statefulset.apps/zk created
kubectl get
์ ์ฌ์ฉํ์ฌ
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๊ฐ ์คํ
์ดํธํ์
ํ๋๋ฅผ ์์ฑํ๋์ง ํ์ธํ๋ค.
kubectl get pods -w -l app = zk
zk-2
ํ๋๊ฐ Running and Ready ์ํ๊ฐ ๋๋ฉด, CTRL-C
๋ฅผ ๋๋ฌ kubectl์ ์ข
๋ฃํ์.
NAME READY STATUS RESTARTS AGE
zk-0 0/1 Pending 0 0s
zk-0 0/1 Pending 0 0s
zk-0 0/1 ContainerCreating 0 0s
zk-0 0/1 Running 0 19s
zk-0 1/1 Running 0 40s
zk-1 0/1 Pending 0 0s
zk-1 0/1 Pending 0 0s
zk-1 0/1 ContainerCreating 0 0s
zk-1 0/1 Running 0 18s
zk-1 1/1 Running 0 40s
zk-2 0/1 Pending 0 0s
zk-2 0/1 Pending 0 0s
zk-2 0/1 ContainerCreating 0 0s
zk-2 0/1 Running 0 19s
zk-2 1/1 Running 0 40s
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ 3๊ฐ์ ํ๋๋ฅผ ์์ฑํ๊ณ , ๊ฐ ํ๋๋
ZooKeeper ์๋ฒ๋ฅผ ํฌํจํ ์ปจํ
์ด๋๋ฅผ ๊ฐ์ง๋ค.
๋ฆฌ๋ ์ ์ถ ์ด์ง ์ต๋ช
๋คํธ์ํฌ์์ ๋ฆฌ๋ ์ ์ถ์ ์ํ ์ข
๋ฃ ์๊ณ ๋ฆฌ์ฆ์ด ์๊ธฐ์, Zab์ ๋ฆฌ๋ ์ ์ถ์ ์ํด ๋ช
์์ ์ธ ๋ฉค๋ฒ ๊ตฌ์ฑ์ ํด์ผ ํ๋ค. ์์๋ธ์ ๊ฐ ์๋ฒ๋ ๊ณ ์ ์๋ณ์๋ฅผ ๊ฐ์ ธ์ผ ํ๊ณ , ๋ชจ๋ ์๋ฒ๋ ์๋ณ์ ์ ์ญ ์งํฉ์ ์์์ผ ํ๋ฉฐ, ๊ฐ ์๋ณ์๋ ๋คํธ์ํฌ ์ฃผ์์ ์ฐ๊ด๋์ด์ผ ํ๋ค.
kubectl exec
๋ฅผ ์ด์ฉํ์ฌ zk
์คํ
์ดํธํ์
์ ํ๋์
ํธ์คํธ๋ค์์ ์์๋ด์.
for i in 0 1 2; do kubectl exec zk-$i -- hostname; done
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ ๊ฐ ์๋ฒ ์ธ๋ฑ์ค์ ๊ธฐ์ดํ์ฌ ๊ฐ ํ๋์ ๊ณ ์ ํ ํธ์คํธ๋ค์์ ๋ถ์ฌํ๋ค. ๊ฐ ํธ์คํธ๋ค์์ <์คํ
์ดํธํ์
์ด๋ฆ>-<์๋ฒ ์ธ๋ฑ์ค>
ํ์์ ์ทจํ๋ค. zk
์คํ
์ดํธํ์
์ replicas
ํ๋๋ 3
์ผ๋ก ์ค์ ๋์๊ธฐ ๋๋ฌธ์, ๊ทธ ์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ 3๊ฐ ํ๋์ ํธ์คํธ๋ค์์ zk-0
, zk-1
,
zk-2
๋ก ์ ํ๋ค.
zk-0
zk-1
zk-2
ZooKeeper ์์๋ธ์ ์๋ฒ๋ค์ ๊ณ ์ ์๋ณ์๋ก์ ์์ฐ์๋ฅผ ์ด์ฉํ๊ณ ์๋ฒ ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ์ my
๋ผ๋ ํ์ผ๋ก ์๋ฒ ์๋ณ์๋ฅผ ์ ์ฅํ๋ค.
๊ฐ ์๋ฒ์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์ฌ myid
ํ์ผ์ ๋ด์ฉ์ ํ์ธํ์.
for i in 0 1 2; do echo "myid zk- $i " ;kubectl exec zk-$i -- cat /var/lib/zookeeper/data/myid; done
์๋ณ์๋ ์์ฐ์์ด๊ณ , ์๋ฒ ์ธ๋ฑ์ค๋ค๋ ์์๊ฐ ์๋๋ฏ๋ก, ์๋ฒ์ 1์ ๋ํ์ฌ ์๋ฒ์ ๋ง๋ค ์ ์๋ค.
myid zk-0
1
myid zk-1
2
myid zk-2
3
zk
์คํ
์ดํธํ์
์ ๊ฐ ํ๋ Fully Qualified Domain Name (FQDN)์ ์ป๊ธฐ ์ํด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
for i in 0 1 2; do kubectl exec zk-$i -- hostname -f; done
zk-hs
์๋น์ค๋ ๋ชจ๋ ํ๋๋ฅผ ์ํ ๋๋ฉ์ธ์ธ
zk-hs.default.svc.cluster.local
์ ๋ง๋ ๋ค.
zk-0.zk-hs.default.svc.cluster.local
zk-1.zk-hs.default.svc.cluster.local
zk-2.zk-hs.default.svc.cluster.local
์ฟ ๋ฒ๋คํฐ์ค DNS ์ A ๋ ์ฝ๋๋ FQDN์ ํ๋์ IP ์ฃผ์๋ก ํ์ด๋ธ๋ค. ์ฟ ๋ฒ๋คํฐ์ค๊ฐ ํ๋๋ฅผ ๋ฆฌ์ค์ผ์คํ๋ฉด, ํ๋์ ์ IP ์ฃผ์๋ก A ๋ ์ฝ๋๋ฅผ ๊ฐฑ์ ํ์ง๋ง, A ๋ ์ฝ๋์ ์ด๋ฆ์ ๋ฐ๋์ง ์๋๋ค.
ZooKeeper๋ ๊ทธ๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์
ํ๊ฒฝ์ค์ ์ zoo.cfg
ํ์ผ์ ์ ์ฅํ๋ค. kubectl exec
๋ฅผ ์ด์ฉํ์ฌ zk-0
ํ๋์ zoo.cfg
๋ด์ฉ์ ๋ณด์.
kubectl exec zk-0 -- cat /opt/zookeeper/conf/zoo.cfg
์๋ ํ์ผ์ server.1
, server.2
, server.3
์์ฑ์์
1
, 2
, 3
์ ZooKeeper ์๋ฒ์ myid
ํ์ผ์ ๊ตฌ๋ถ์์
์ฐ๊ด๋๋ค.
์ด๋ค์ zk
์คํ
์ดํธํ์
์ ํ๋์ FQDNS์ ์ค์ ํ๋ค.
clientPort=2181
dataDir=/var/lib/zookeeper/data
dataLogDir=/var/lib/zookeeper/log
tickTime=2000
initLimit=10
syncLimit=2000
maxClientCnxns=60
minSessionTimeout= 4000
maxSessionTimeout= 40000
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
server.1=zk-0.zk-hs.default.svc.cluster.local:2888:3888
server.2=zk-1.zk-hs.default.svc.cluster.local:2888:3888
server.3=zk-2.zk-hs.default.svc.cluster.local:2888:3888
ํฉ์ ๋ฌ์ฑ ํฉ์ ํ๋กํ ์ฝ์์ ๊ฐ ์ฐธ๊ฐ์์ ์๋ณ์๋ ์ ์ผํด์ผ ํ๋ค. Zab ํ๋กํ ์ฝ์์ ๋์ผํ ๊ณ ์ ์๋ณ์๋ฅผ ์์ฒญํ๋ ์ฐธ๊ฐ์๋ ์๋ค. ์ด๋ ์์คํ
ํ๋ก์ธ์ค๊ฐ ์ด๋ค ํ๋ก์ธ์ค๊ฐ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ปค๋ฐํ๋์ง ๋์ํ๊ฒ ํ๋๋ฐ ํ์ํ๋ค. 2๊ฐ ํ๋๋ฅผ ๋์ผ ์๋ฒ์ผ๋ก ์์ํ์๋ค๋ฉด ๋ ๋์ ZooKeeper ์๋ฒ๋ ๋ ๋ค ์ค์ค๋ก๋ฅผ ๋์ผ ์๋ฒ๋ก ์๋ณํ๋ค.
ํฉ์ ํ๋กํ ์ฝ์์ ๊ฐ ์ฐธ์ฌ์์ ์๋ณ์๋ ๊ณ ์ ํด์ผ ํ๋ค. Zab ํ๋กํ ์ฝ์ ๋ ์ฐธ์ฌ์๊ฐ ๋์ผํ ๊ณ ์ ์๋ณ์๋ก ์์ฒญํด์๋ ์๋๋ค. ์ด๋ ์์คํ
ํ๋ก์ธ์ค๊ฐ ์ด๋ค ํ๋ก์ธ์ค๊ฐ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ปค๋ฐํ๋์ง ๋์ํ๋๋ก ํ๊ธฐ ์ํด ํ์์ ์ด๋ค. ๋์ผ ์๋ฒ์ผ๋ก ๋ ๊ฐ์ ํ๋๊ฐ ์คํํ๋ค๋ฉด ๋ ZooKeeper ์๋ฒ๋ ๋ชจ๋ ๋์ผํ ์๋ฒ๋ก ์๋ณ๋๋ค.
kubectl get pods -w -l app = zk
NAME READY STATUS RESTARTS AGE
zk-0 0/1 Pending 0 0s
zk-0 0/1 Pending 0 0s
zk-0 0/1 ContainerCreating 0 0s
zk-0 0/1 Running 0 19s
zk-0 1/1 Running 0 40s
zk-1 0/1 Pending 0 0s
zk-1 0/1 Pending 0 0s
zk-1 0/1 ContainerCreating 0 0s
zk-1 0/1 Running 0 18s
zk-1 1/1 Running 0 40s
zk-2 0/1 Pending 0 0s
zk-2 0/1 Pending 0 0s
zk-2 0/1 ContainerCreating 0 0s
zk-2 0/1 Running 0 19s
zk-2 1/1 Running 0 40s
๊ฐ ํ๋์ A ๋ ์ฝ๋๋ ํ๋๊ฐ Ready ์ํ๊ฐ ๋๋ฉด ์
๋ ฅ๋๋ค. ๋ฐ๋ผ์
ZooKeeper ์๋ฒ์ FQDN์ ๋จ์ผ ์๋ํฌ์ธํธ๋ก ํ์ธ๋๊ณ
ํด๋น ์๋ํฌ์ธํธ๋ myid
ํ์ผ์ ๊ตฌ์ฑ๋ ์๋ณ์๋ฅผ ๊ฐ์ง
๊ณ ์ ํ ZooKeeper ์๋ฒ๊ฐ ๋๋ค.
zk-0.zk-hs.default.svc.cluster.local
zk-1.zk-hs.default.svc.cluster.local
zk-2.zk-hs.default.svc.cluster.local
์ด๊ฒ์ ZooKeeper์ zoo.cfg
ํ์ผ์ servers
์์ฑ์ด ์ ํํ ๊ตฌ์ฑ๋ ์์๋ธ๋ก ๋ํ๋๋ ๊ฒ์ ๋ณด์ฆํ๋ค.
server.1=zk-0.zk-hs.default.svc.cluster.local:2888:3888
server.2=zk-1.zk-hs.default.svc.cluster.local:2888:3888
server.3=zk-2.zk-hs.default.svc.cluster.local:2888:3888
์๋ฒ๊ฐ Zab ํ๋กํ ์ฝ๋ก ๊ฐ์ ์ปค๋ฐ ์๋ํ๋ฉด, ํฉ์๋ฅผ ์ด๋ฃจ์ด ๊ฐ์ ์ปค๋ฐํ๊ฑฐ๋(๋ฆฌ๋ ์ ์ถ์ ์ฑ๊ณตํ๊ณ ๋๋จธ์ง ๋ ๊ฐ ํ๋๋ Running๊ณผ Ready ์ํ๋ผ๋ฉด) ์คํจํ๋ค(์กฐ๊ฑด ์ค ํ๋๋ผ๋ ์ถฉ์กฑํ์ง ์์ผ๋ฉด). ๋ค๋ฅธ ์๋ฒ๋ฅผ ๋์ ํ์ฌ ์ฐ๊ธฐ๋ฅผ ์น์ธํ๋ ์ํ๋ ๋ฐ์ํ์ง ์๋๋ค.
์์๋ธ ๋ฌด๊ฒฐ์ฑ ํ
์คํธ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํ
์คํธ๋ ํ ZooKeeper ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ณ
๋ค๋ฅธ ZooKeeper ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๊ฒ์ด๋ค.
์๋ ๋ช
๋ น์ด๋ ์์๋ธ ๋ด์ zk-0
ํ๋์์ /hello
๊ฒฝ๋ก๋ก world
๋ฅผ ์ฐ๋ ์คํฌ๋ฆฝํธ์ธ zkCli.sh
๋ฅผ ์คํํ๋ค.
kubectl exec zk-0 -- zkCli.sh create /hello world
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
Created /hello
zk-1
ํ๋์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ธฐ ์ํด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
kubectl exec zk-1 -- zkCli.sh get /hello
zk-0
์์ ์์ฑํ ๊ทธ ๋ฐ์ดํฐ๋ ์์๋ธ ๋ด์ ๋ชจ๋ ์๋ฒ์์
์ฌ์ฉํ ์ ์๋ค.
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
world
cZxid = 0x100000002
ctime = Thu Dec 08 15:13:30 UTC 2016
mZxid = 0x100000002
mtime = Thu Dec 08 15:13:30 UTC 2016
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
๋ด๊ตฌ์ฑ์๋ ์ ์ฅ์ ์ ๊ณต ZooKeeper ๊ธฐ๋ณธ ์น์
์์ ์ธ๊ธํ๋ฏ์ด
ZooKeeper๋ ๋ชจ๋ ํญ๋ชฉ์ ๋ด๊ตฌ์ฑ์๋ WAL์ ์ปค๋ฐํ๊ณ ๋ฉ๋ชจ๋ฆฌ ์ํ์ ์ค๋
์ท์ ์ ์ฅ ๋ฏธ๋์์ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ์ฅํ๋ค.
๋ด๊ตฌ์ฑ์ ์ ๊ณตํ๊ธฐ ์ํด WAL์ ์ด์ฉํ๋ ๊ฒ์
๋ณต์ ๋ ์ํ ๋จธ์ ์ ์ด๋ฃจ๋ ํฉ์ ํ๋กํ ์ฝ์์
์ด์ฉํ๋ ์ผ๋ฐ์ ์ธ ๊ธฐ๋ฒ์ด๋ค.
kubectl delete
๋ช
๋ น์ ์ด์ฉํ์ฌ
zk
์คํ
์ดํธํ์
์ ์ญ์ ํ์.
kubectl delete statefulset zk
statefulset.apps "zk" deleted
์คํ
์ดํธํ์
์ ํ๋๊ฐ ์ข
๋ฃ๋๋ ๊ฒ์ ์ง์ผ๋ณด์.
kubectl get pods -w -l app = zk
zk-0
์ด ์์ ํ ์ข
๋ฃ๋๋ฉด CTRL-C
๋ฅผ ์ด์ฉํด kubectl์ ์ข
๋ฃํ์.
zk-2 1/1 Terminating 0 9m
zk-0 1/1 Terminating 0 11m
zk-1 1/1 Terminating 0 10m
zk-2 0/1 Terminating 0 9m
zk-2 0/1 Terminating 0 9m
zk-2 0/1 Terminating 0 9m
zk-1 0/1 Terminating 0 10m
zk-1 0/1 Terminating 0 10m
zk-1 0/1 Terminating 0 10m
zk-0 0/1 Terminating 0 11m
zk-0 0/1 Terminating 0 11m
zk-0 0/1 Terminating 0 11m
zookeeper.yaml
๋งค๋ํ์คํธ๋ฅผ ๋ค์ ์ ์ฉํ๋ค.
kubectl apply -f https://k8s.io/examples/application/zookeeper/zookeeper.yaml
zk
์คํ
์ดํธํ์
์ค๋ธ์ ํธ๋ฅผ ์์ฑํ์ง๋ง, ๋งค๋ํ์คํธ์ ๋ค๋ฅธ API ์ค๋ธ์ ํธ๋ ์ด๋ฏธ ์กด์ฌํ๋ฏ๋ก ์์ ๋์ง ์๋๋ค.
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๊ฐ ์คํ
ํธํ์
์ ํ๋๋ฅผ ์ฌ์์ฑํ๋ ๊ฒ์ ํ์ธํ๋ค.
kubectl get pods -w -l app = zk
zk-2
ํ๋๊ฐ Running๊ณผ Ready๊ฐ ๋๋ฉด CTRL-C
๋ฅผ ์ด์ฉํ์ฌ kubectl์ ์ข
๋ฃํ๋ค.
NAME READY STATUS RESTARTS AGE
zk-0 0/1 Pending 0 0s
zk-0 0/1 Pending 0 0s
zk-0 0/1 ContainerCreating 0 0s
zk-0 0/1 Running 0 19s
zk-0 1/1 Running 0 40s
zk-1 0/1 Pending 0 0s
zk-1 0/1 Pending 0 0s
zk-1 0/1 ContainerCreating 0 0s
zk-1 0/1 Running 0 18s
zk-1 1/1 Running 0 40s
zk-2 0/1 Pending 0 0s
zk-2 0/1 Pending 0 0s
zk-2 0/1 ContainerCreating 0 0s
zk-2 0/1 Running 0 19s
zk-2 1/1 Running 0 40s
์๋ ๋ช
๋ น์ด๋ก ๋ฌด๊ฒฐ์ฑ ํ
์คํธ ์์ ์
๋ ฅํ ๊ฐ์
zk-2
ํ๋์์ ์ป์ด์จ๋ค.
kubectl exec zk-2 zkCli.sh get /hello
zk
์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๋ฅผ ์ข
๋ฃํ๊ณ ์ฌ์์ฑํ์์๋, ์์๋ธ์ ์ฌ์ ํ ์๋ ๊ฐ์ ๋๋ ค์ค๋ค.
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
world
cZxid = 0x100000002
ctime = Thu Dec 08 15:13:30 UTC 2016
mZxid = 0x100000002
mtime = Thu Dec 08 15:13:30 UTC 2016
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
zk
์คํ
์ดํธํ์
์ spec
์ volumeClaimTemplates
ํ๋๋ ๊ฐ ํ๋์ ํ๋ก๋น์ ๋ ํผ์์คํดํธ๋ณผ๋ฅจ์ ์ง์ ํ๋ค.
volumeClaimTemplates :
- metadata :
name : datadir
annotations :
volume.alpha.kubernetes.io/storage-class : anything
spec :
accessModes : [ "ReadWriteOnce" ]
resources :
requests :
storage : 20Gi
์คํ
์ดํธํ์
์ปจํธ๋กค๋ฌ๋ ์คํ
์ดํธํ์
์ ๊ฐ ํ๋์ ๋ํ
ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์
์ ์์ฑํ๋ค.
๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์ฌ ์คํ
์ดํธํ์
์ ํผ์์คํดํธ๋ณผ๋ฅจํด๋ ์
์ ์ดํด๋ณด์.
kubectl get pvc -l app = zk
์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์ฌ์์ฑํ ๋์ ํ๋์ ํผ์์คํดํธ๋ณผ๋ฅจ๋ ๋ค์ ๋ง์ดํธํ๋ค.
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
datadir-zk-0 Bound pvc-bed742cd-bcb1-11e6-994f-42010a800002 20Gi RWO 1h
datadir-zk-1 Bound pvc-bedd27d2-bcb1-11e6-994f-42010a800002 20Gi RWO 1h
datadir-zk-2 Bound pvc-bee0817e-bcb1-11e6-994f-42010a800002 20Gi RWO 1h
์คํ
์ดํธํ์
์ ์ปจํ
์ด๋ template
์ volumeMounts
๋ถ๋ถ์ด ZooKeeper ์๋ฒ์ ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ์ ํผ์์คํดํธ๋ณผ๋ฅจ ๋ง์ดํธํ๋ ๋ด์ฉ์ด๋ค.
volumeMounts :
- name : datadir
mountPath : /var/lib/zookeeper
zk
์คํ
์ดํธํ์
์ด (์ฌ)์ค์ผ์ค๋ง๋ ๋ ํญ์ ๋์ผํ ํผ์์คํดํธ๋ณผ๋ฅจ
์
ZooKeeper์ ์๋ฒ ๋๋ ํฐ๋ฆฌ์ ๋ง์ดํธํ๋ค.
ํ๋๋ฅผ ์ฌ์ค์ผ์คํ ๋์๋ ZooKeeper์ WAL์ ํตํด ์ด๋ค์ง ๋ชจ๋ ์ฐ๊ธฐ์
๋ชจ๋ ๊ทธ ์ค๋
์ท๋ ๋ด๊ตฌ์ฑ์ ์ ์งํ๋ค.
์ผ๊ด๋ ๊ตฌ์ฑ ๋ณด์ฅํ๊ธฐ ๋ฆฌ๋ ์ ์ถ ์ด์ง ๊ณผ
ํฉ์ ๋ฌ์ฑ ์น์
์์ ์๋ ธ๋ฏ์ด,
ZooKeeper ์์๋ธ์ ์๋ฒ๋ ๋ฆฌ๋ ์ ์ถ๊ณผ ์ฟผ๋ผ์ ๊ตฌ์ฑํ๊ธฐ ์ํ ์ผ๊ด๋ ์ค์ ์ด ํ์ํ๋ค.
๋ํ Zab ํ๋กํ ์ฝ์ ์ผ๊ด๋ ์ค์ ๋
๋คํธ์ํฌ์ ๊ฑธ์ณ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๊ธฐ ์ํด์
ํ์ํ๋ค. ์ด ์์์์๋ ๋งค๋ํ์คํธ์ ๊ตฌ์ฑ์ ์ง์ ํฌํจ์์ผ์ ์ผ๊ด๋ ๊ตฌ์ฑ์
๋ฌ์ฑํ๋ค.
zk
์คํ
์ดํธํ์
์ ์ดํด๋ณด์.
kubectl get sts zk -o yaml
โฆ
command:
- sh
- -c
- "start-zookeeper \
--servers=3 \
--data_dir=/var/lib/zookeeper/data \
--data_log_dir=/var/lib/zookeeper/data/log \
--conf_dir=/opt/zookeeper/conf \
--client_port=2181 \
--election_port=3888 \
--server_port=2888 \
--tick_time=2000 \
--init_limit=10 \
--sync_limit=5 \
--heap=512M \
--max_client_cnxns=60 \
--snap_retain_count=3 \
--purge_interval=12 \
--max_session_timeout=40000 \
--min_session_timeout=4000 \
--log_level=INFO"
โฆ
ZooKeeper ์๋ฒ๋ฅผ ์์ํ๋๋ฐ ์ฌ์ฉํ ๋ช
๋ น์ด๋ ์ปค๋งจ๋๋ผ์ธ ํ๋ผ๋ฏธํฐ๋ก ํ๊ฒฝ ๊ตฌ์ฑ์ ์ ๋ฌํ๋ค. ํ๊ฒฝ ๋ณ์๋ฅผ ์ด์ฉํ์ฌ์๋ ์์๋ธ์ ํ๊ฒฝ ๊ตฌ์ฑ์ ์ ๋ฌํ ์ ์๋ค.
๋ก๊น
์ค์ ํ๊ธฐ zkGenConfig.sh
์คํฌ๋ฆฝํธ๋ก ์์ฑ๋ ํ์ผ ์ค ํ๋๋ ZooKeeper์ ๋ก๊น
์ ์ ์ดํ๋ค.
ZooKeeper๋ Log4j ๋ฅผ ์ด์ฉํ๋ฉฐ
๊ธฐ๋ณธ ๋ก๊น
๊ตฌ์ฑ์ผ๋ก๋ ์๊ฐ๊ณผ ํ์ผ ํฌ๊ธฐ ๊ธฐ์ค์ ๋กค๋ง ํ์ผ ์ดํ๋๋ฅผ ์ฌ์ฉํ๋ค.
zk
์คํ
์ดํธํ์
์ ํ ํ๋์์ ๋ก๊น
์ค์ ์ ์ดํด๋ณด๋ ์๋ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
kubectl exec zk-0 cat /usr/etc/zookeeper/log4j.properties
์๋ ๋ก๊น
๊ตฌ์ฑ์ ZooKeeper๊ฐ ๋ชจ๋ ๋ก๊ทธ๋ฅผ
ํ์ค ์ถ๋ ฅ ์คํธ๋ฆผ์ผ๋ก ์ฒ๋ฆฌํ๊ฒ ํ๋ค.
zookeeper.root.logger=CONSOLE
zookeeper.console.threshold=INFO
log4j.rootLogger=${zookeeper.root.logger}
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold}
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
์ด๋ ์ปจํ
์ด๋ ๋ด์์ ์์ ํ๊ฒ ๋ก๊น
ํ๋ ๊ฐ์ฅ ๋จ์ํ ๋ฐฉ๋ฒ์ด๋ค.
ํ์ค ์ถ๋ ฅ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ๋ฅผ ์์ฑํ๋ฉด, ์ฟ ๋ฒ๋คํฐ์ค๋ ๋ก๊ทธ ๋กํ
์ด์
์ ์ฒ๋ฆฌํ๋ค.
๋ํ ์ฟ ๋ฒ๋คํฐ์ค๋ ์ ํ๋ฆฌ์ผ์ด์
์ด ํ์ค ์ถ๋ ฅ๊ณผ ํ์ค ์ค๋ฅ์ ์ฐ์ธ ๋ก๊ทธ๋ก ์ธํ์ฌ
๋ก์ปฌ ์ ์ฅ ๋ฏธ๋์ด๊ฐ ๊ณ ๊ฐ๋์ง ์๋๋ก ๋ณด์ฅํ๋ ์ ์์ ์ธ ๋ณด์กด ์ ์ฑ
์ ๊ตฌํํ๋ค.
ํ๋์ ๋ง์ง๋ง 20์ค์ ๋ก๊ทธ๋ฅผ ๊ฐ์ ธ์ค๋ kubectl logs
๋ช
๋ น์ ์ด์ฉํ์.
kubectl logs zk-0 --tail 20
kubectl logs
๋ฅผ ์ด์ฉํ๊ฑฐ๋ ์ฟ ๋ฒ๋คํฐ์ค ๋์๋ณด๋์์ ํ์ค ์ถ๋ ฅ๊ณผ ํ์ค ์ค๋ฅ๋ก ์ฐ์ธ ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ๋ฅผ ๋ณผ ์ ์๋ค.
2016-12-06 19:34:16,236 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52740
2016-12-06 19:34:16,237 [myid:1] - INFO [Thread-1136:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52740 (no session established for client)
2016-12-06 19:34:26,155 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52749
2016-12-06 19:34:26,155 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52749
2016-12-06 19:34:26,156 [myid:1] - INFO [Thread-1137:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52749 (no session established for client)
2016-12-06 19:34:26,222 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52750
2016-12-06 19:34:26,222 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52750
2016-12-06 19:34:26,226 [myid:1] - INFO [Thread-1138:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52750 (no session established for client)
2016-12-06 19:34:36,151 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52760
2016-12-06 19:34:36,152 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52760
2016-12-06 19:34:36,152 [myid:1] - INFO [Thread-1139:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52760 (no session established for client)
2016-12-06 19:34:36,230 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52761
2016-12-06 19:34:36,231 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52761
2016-12-06 19:34:36,231 [myid:1] - INFO [Thread-1140:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52761 (no session established for client)
2016-12-06 19:34:46,149 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52767
2016-12-06 19:34:46,149 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52767
2016-12-06 19:34:46,149 [myid:1] - INFO [Thread-1141:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52767 (no session established for client)
2016-12-06 19:34:46,230 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52768
2016-12-06 19:34:46,230 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52768
2016-12-06 19:34:46,230 [myid:1] - INFO [Thread-1142:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52768 (no session established for client)
์ฟ ๋ฒ๋คํฐ์ค๋ ๋ง์ ๋ก๊ทธ ์๋ฃจ์
๊ณผ ํตํฉ๋๋ค. ํด๋ฌ์คํฐ์ ์ ํ๋ฆฌ์ผ์ด์
์
๊ฐ์ฅ ์ ํฉํ ๋ก๊ทธ ์๋ฃจ์
์ ์ ํํ ์ ์๋ค. ํด๋ฌ์คํฐ ์์ค์
๋ก๊ทธ ์ ์ฌ(ship)์ ํตํฉ์ ์ํด์๋ ๋ก๊ทธ ์ํ๊ณผ ์ ์ฌ๋ฅผ ์ํด ์ฌ์ด๋์นด ์ปจํ
์ด๋ ๋ฅผ ๋ฐฐํฌํ๋ ๊ฒ์ ๊ณ ๋ คํ๋ค.
๊ถํ ์๋ ์ฌ์ฉ์๋ฅผ ์ํด ๊ตฌ์ฑํ๊ธฐ ์ปจํ
์ด๋ ๋ด๋ถ์ ๊ถํ์๋ ์ ์ ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ ์ ์๋๋ก ํ๋
์ต์์ ๋ฐฉ๋ฒ์ ๋
ผ์๊ฑฐ๋ฆฌ์ด๋ค.
์กฐ์ง์์ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ถํ ์๋ ์ฌ์ฉ์๊ฐ ์คํํ๋ค๋ฉด,
์ง์
์ ์ ์คํํ ์ฌ์ฉ์๋ฅผ ์ ์ดํ๊ธฐ ์ํด
์ํ๋ฆฌํฐ์ปจํ
์คํธ ๋ฅผ ์ด์ฉํ ์ ์๋ค.
zk
์คํ
์ดํธํ์
์ ํ๋ template
์ SecurityContext
๋ฅผ ํฌํจํ๋ค.
securityContext :
runAsUser : 1000
fsGroup : 1000
ํ๋ ์ปจํ
์ด๋์์ UID 1000์ ZooKeeper ์ฌ์ฉ์์ด๋ฉฐ, GID 1000์
ZooKeeper์ ๊ทธ๋ฃน์ ํด๋นํ๋ค.
zk-0
ํ๋์์ ํ๋ก์ธ์ค ์ ๋ณด๋ฅผ ์ป์ด์ค์.
kubectl exec zk-0 -- ps -elf
securityContext
์ค๋ธ์ ํธ์ runAsUser
ํ๋ ๊ฐ์ด 1000 ์ด๋ฏ๋ก
๋ฃจํธ ์ฌ์ฉ์๋ก ์คํํ๋ ๋์ ZooKeeper ํ๋ก์ธ์ค๋ ZooKeeper ์ฌ์ฉ์๋ก ์คํ๋๋ค.
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
4 S zookeep+ 1 0 0 80 0 - 1127 - 20:46 ? 00:00:00 sh -c zkGenConfig.sh && zkServer.sh start-foreground
0 S zookeep+ 27 1 0 80 0 - 1155556 - 20:46 ? 00:00:19 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,CONSOLE -cp /usr/bin/../build/classes:/usr/bin/../build/lib/*.jar:/usr/bin/../share/zookeeper/zookeeper-3.4.9.jar:/usr/bin/../share/zookeeper/slf4j-log4j12-1.6.1.jar:/usr/bin/../share/zookeeper/slf4j-api-1.6.1.jar:/usr/bin/../share/zookeeper/netty-3.10.5.Final.jar:/usr/bin/../share/zookeeper/log4j-1.2.16.jar:/usr/bin/../share/zookeeper/jline-0.9.94.jar:/usr/bin/../src/java/lib/*.jar:/usr/bin/../etc/zookeeper: -Xmx2G -Xms2G -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/bin/../etc/zookeeper/zoo.cfg
๊ธฐ๋ณธ์ ์ผ๋ก ํ๋์ ํผ์์คํดํธ๋ณผ๋ฅจ์ ZooKeeper ์๋ฒ์ ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ์ ๋ง์ดํธ๋๊ณ , ๋ฃจํธ ์ฌ์ฉ์๋ง์ด ์ ๊ทผ ๊ฐ๋ฅํ๋ค. ์ด ๊ตฌ์ฑ์ ZooKeeper ํ๋ก์ธ์ค๊ฐ WAL์ ๊ธฐ๋กํ๊ณ ์ค๋
์ท์ ์ ์ฅํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ค.
zk-0
ํ๋์ ZooKeeper ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ์ ๊ถํ์ ์ป์ด์ค๋ ์๋ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
kubectl exec -ti zk-0 -- ls -ld /var/lib/zookeeper/data
securityContext
์ค๋ธ์ ํธ์ fsGroup
ํ๋ ๊ฐ์ด 1000 ์ด๋ฏ๋ก, ํ๋์ ํผ์์คํดํธ ๋ณผ๋ฅจ์ ์์ ๊ถ์ ZooKeeper ๊ทธ๋ฃน์ผ๋ก ์ง์ ๋์ด ZooKeeper ํ๋ก์ธ์ค์์ ์ฝ๊ณ ์ธ ์ ์๋ค.
drwxr-sr-x 3 zookeeper zookeeper 4096 Dec 5 20:45 /var/lib/zookeeper/data
ZooKeeper ํ๋ก์ธ์ค ๊ด๋ฆฌํ๊ธฐ ZooKeeper ๋ฌธ์ ์์๋
"ZooKeeper์ ์๋ฒ ํ๋ก์ธ์ค(JVM)์ ๊ด๋ฆฌํ
๊ฐ๋
ํ๋ก์ธ์ค๋ฅผ ํ์ํ ๊ฒ์ด๋ค."๋ผ๊ณ ๋งํ๋ค.
์์น๋
(๊ฐ๋
ํ๋ก์ธ์ค)๋ฅผ ํ์ฉํ์ฌ ์คํจํ ํ๋ก์ธ์ค๋ฅผ ์ฌ์์ํ๋ ๊ฒ์ ๋ถ์ฐ์์คํ
์์
์ผ๋ฐ์ ์ธ ๋ฐฉ์์ด๋ค. ์ฟ ๋ฒ๋คํฐ์ค์์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ๋์๋
๊ฐ๋
ํ๋ก์ธ์ค๋ก ์ธ๋ถ ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ณด๋ค ์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ์ ํ๋ฆฌ์ผ์ด์
์
์์น๋
์ผ๋ก์ ์ฌ์ฉํด์ผ ํ๋ค.
์์๋ธ ๊ด๋ฆฌํ๊ธฐ zk
์คํ
์ดํธํ์
์ RollingUpdate
์
๋ฐ์ดํธ ์ ๋ต์ ์ด์ฉํ๋๋ก ๊ตฌ์ฑ๋์๋ค.
kubectl patch
๋ก ์๋ฒ์ ํ ๋น๋ cpu
์๋ฅผ ๊ฐฑ์ ํ ์ ์๋ค.
kubectl patch sts zk --type= 'json' -p= '[{"op": "replace", "path": "/spec/template/spec/containers/0/resources/requests/cpu", "value":"0.3"}]'
statefulset.apps/zk patched
์
๋ฐ์ดํธ ์ํฉ์ ์ง์ผ๋ณด๊ธฐ ์ํด kubectl rollout status
์ด์ฉํ์.
kubectl rollout status sts/zk
waiting for statefulset rolling update to complete 0 pods at revision zk-5db4499664...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
waiting for statefulset rolling update to complete 1 pods at revision zk-5db4499664...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
waiting for statefulset rolling update to complete 2 pods at revision zk-5db4499664...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
statefulset rolling update complete 3 pods at revision zk-5db4499664...
์ด๊ฒ์ ํ๋๋ฅผ ์ญ์์ผ๋ก ํ ๋ฒ์ ํ๋์ฉ ์ข
๋ฃํ๊ณ , ์๋ก์ด ๊ตฌ์ฑ์ผ๋ก ์ฌ์์ฑํ๋ค. ์ด๋ ๋กค๋ง์
๋ฐ์ดํธ ๋์์ ์ฟผ๋ผ์ ์ ์งํ๋๋ก ๋ณด์ฅํ๋ค.
์ด๋ ฅ๊ณผ ์ด์ ๊ตฌ์ฑ์ ๋ณด๊ธฐ ์ํด kubectl rollout history
๋ช
๋ น์ ์ด์ฉํ์.
kubectl rollout history sts/zk
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
statefulsets "zk"
REVISION
1
2
์์ ์ฌํญ์ ๋กค๋ฐฑํ๊ธฐ ์ํด kubectl rollout undo
๋ช
๋ น์ ์ด์ฉํ์.
kubectl rollout undo sts/zk
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
statefulset.apps/zk rolled back
ํ๋ก์ธ์ค ์ฅ์ ๊ด๋ฆฌํ๊ธฐ ์ฌ์์ ์ ์ฑ
์
์ฟ ๋ฒ๋คํฐ์ค๊ฐ ํ๋ ๋ด์ ์ปจํ
์ด๋์ ์ง์
์ ์์ ํ๋ก์ธ์ค ์คํจ๋ฅผ ์ด๋ป๊ฒ ๋ค๋ฃจ๋์ง ์ ์ดํ๋ค.
์คํ
์ดํธํ์
์ ํ๋์์ ์ค์ง ์ ์ ํ ์ฌ์์ ์ ์ฑ
๋ Always์ด๋ฉฐ
์ด๊ฒ์ด ๊ธฐ๋ณธ ๊ฐ์ด๋ค. ์ํ๊ฐ ์ ์ง๋๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ํด
๊ธฐ๋ณธ ์ ์ฑ
์ ์ ๋๋ก ๋ณ๊ฒฝํ์ง ๋ง์.
zk-0
ํ๋์์ ์คํ ์ค์ธ ZooKeeper ์๋ฒ์์ ํ๋ก์ธ์ค ํธ๋ฆฌ๋ฅผ ์ดํด๋ณด๊ธฐ ์ํด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
kubectl exec zk-0 -- ps -ef
์ปจํ
์ด๋์ ์ํธ๋ฆฌ ํฌ์ธํธ๋ก PID 1 ์ธ ๋ช
๋ น์ด ์ฌ์ฉ๋์์ผ๋ฉฐ
ZooKeeper ํ๋ก์ธ์ค๋ ์ํธ๋ฆฌ ํฌ์ธํธ์ ์์ ํ๋ก์ธ์ค๋ก PID 27 ์ด๋ค.
UID PID PPID C STIME TTY TIME CMD
zookeep+ 1 0 0 15:03 ? 00:00:00 sh -c zkGenConfig.sh && zkServer.sh start-foreground
zookeep+ 27 1 0 15:03 ? 00:00:03 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,CONSOLE -cp /usr/bin/../build/classes:/usr/bin/../build/lib/*.jar:/usr/bin/../share/zookeeper/zookeeper-3.4.9.jar:/usr/bin/../share/zookeeper/slf4j-log4j12-1.6.1.jar:/usr/bin/../share/zookeeper/slf4j-api-1.6.1.jar:/usr/bin/../share/zookeeper/netty-3.10.5.Final.jar:/usr/bin/../share/zookeeper/log4j-1.2.16.jar:/usr/bin/../share/zookeeper/jline-0.9.94.jar:/usr/bin/../src/java/lib/*.jar:/usr/bin/../etc/zookeeper: -Xmx2G -Xms2G -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/bin/../etc/zookeeper/zoo.cfg
๋ค๋ฅธ ํฐ๋ฏธ๋์์ ๋ค์ ๋ช
๋ น์ด๋ก zk
์คํ
์ดํธํ์
์ ํ๋๋ฅผ ํ์ธํ๋ค.
kubectl get pod -w -l app = zk
๋ ๋ค๋ฅธ ํฐ๋ฏธ๋์์ ๋ค์ ๋ช
๋ น์ด๋ก zk-0
ํ๋์ ZooKeeper ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃ์ํจ๋ค.
kubectl exec zk-0 -- pkill java
ZooKeeper ํ๋ก์ธ์ค์ ์ข
๋ฃ๋ ๋ถ๋ชจ ํ๋ก์ธ์ค์ ์ข
๋ฃ๋ฅผ ์ผ์ผํจ๋ค. ์ปจํ
์ด๋ ์ฌ์์์ ์ฑ
์ด Always์ด๊ธฐ ๋๋ฌธ์ ๋ถ๋ชจ ํ๋ก์ธ์ค๋ฅผ ์ฌ์์ํ๋ค.
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Running 0 21m
zk-1 1/1 Running 0 20m
zk-2 1/1 Running 0 19m
NAME READY STATUS RESTARTS AGE
zk-0 0/1 Error 0 29m
zk-0 0/1 Running 1 29m
zk-0 1/1 Running 1 29m
์ ํ๋ฆฌ์ผ์ด์
์ด ์คํฌ๋ฆฝํธ(zkServer.sh
๊ฐ์)๋ฅผ ์ ํ๋ฆฌ์ผ์ด์
์ ๋น์ง๋์ค ๋ก์ง์ ๊ตฌํํ ํ๋ก์ธ์ค๋ฅผ ์์ํ๊ธฐ ์ํด ์ด์ฉํ๋ค๋ฉด,
๊ทธ ์คํฌ๋ฆฝํธ๋ ์์ ํ๋ก์ธ์ค์ ํจ๊ป ๋ฐ๋์ ์ข
๋ฃ๋์ด์ผ ํ๋ค.
์ด๋ ์ฟ ๋ฒ๋คํฐ์ค๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ๋น์ง๋์ค ๋ก์ง์ ๊ตฌํํ ํ๋ก์ธ์ค๊ฐ ์คํจํ ๋์
์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์ด๋๋ฅผ ์ฌ์์ํ๋ ๊ฒ์ ๋ณด์ฆํ๋ค.
ํ์ฑ๋(Liveness) ํ
์คํธํ๊ธฐ ์คํจํ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์์ํ๋๋ก ๊ตฌ์ฑํ๋ ๊ฒ์ ๋ถ์ฐ ์์คํ
์
๊ฑด๊ฐํ๊ฒ ์ ์งํ๋๋ฐ ์ถฉ๋ถํ์ง ์๋ค. ์์คํ
์ ํ๋ก์ธ์ค๋ ์ด์์์ง๋ง
์๋ต์ด ์์ ์ ์๊ณ , ํน์ ๋ค๋ฅธ ๊ฑด๊ฐํ์ง ์์ ๊ฒฝ์ฐ์ ์๋๋ฆฌ์ค๊ฐ ์๋ค.
์ ํ๋ฆฌ์ผ์ด์
ํ๋ก์ธ์ค๊ฐ ๊ฑด๊ฐํ์ง ์๊ณ ์ฌ์์ํด์ผ๋ง ํ๋ค๋ ๊ฒ์
์ฟ ๋ฒ๋คํฐ์ค์๊ฒ ์๋ฆฌ๋๋ก ํ์ฑ๋ ๊ฒ์ฌ๋ฅผ ์ด์ฉํด์ผ ํ๋ค.
zk
์คํ
์ดํธํ์
์ ํ๋ template
์ ํ์ฑ๋ ๊ฒ์ฌ๋ฅผ ๋ช
์ํ๋ค.
livenessProbe :
exec :
command :
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds : 15
timeoutSeconds : 5
๊ฒ์ฌ๋ ZooKeeper์ ruok
4 ๊ธ์ ๋จ์ด๋ฅผ ์ด์ฉํด์ ์๋ฒ์ ๊ฑด๊ฐ์ ํ
์คํธํ๋
๋ฐฐ์ฌ ์คํฌ๋ฆฝํธ๋ฅผ ํธ์ถํ๋ค.
OK=$(echo ruok | nc 127.0.0.1 $1)
if [ "$OK" == "imok" ]; then
exit 0
else
exit 1
fi
ํ ํฐ๋ฏธ๋์์ zk
์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์ง์ผ๋ณด๊ธฐ ์ํด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
kubectl get pod -w -l app = zk
๋ค๋ฅธ ์ฐฝ์์ zk-0
ํ๋์ ํ์ผ์์คํ
์์ zookeeper-ready
์คํฌ๋ฆฝํธ๋ฅผ ์ญ์ ํ๊ธฐ ์ํด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
kubectl exec zk-0 -- rm /opt/zookeeper/bin/zookeeper-ready
ZooKeeper์ ํ์ฑ๋ ๊ฒ์ฌ์ ์คํจํ๋ฉด,
์ฟ ๋ฒ๋คํฐ์ค๋ ์๋์ผ๋ก ํ๋ก์ธ์ค๋ฅผ ์ฌ์์ํ์ฌ ์์๋ธ์ ๊ฑด๊ฐํ์ง ์์ ํ๋ก์ธ์ค๋ฅผ
์ฌ์์ํ๋ ๊ฒ์ ๋ณด์ฆํ๋ค.
kubectl get pod -w -l app = zk
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Running 0 1h
zk-1 1/1 Running 0 1h
zk-2 1/1 Running 0 1h
NAME READY STATUS RESTARTS AGE
zk-0 0/1 Running 0 1h
zk-0 0/1 Running 1 1h
zk-0 1/1 Running 1 1h
์ค๋น๋ ํ
์คํธ ์ค๋น๋๋ ํ์ฑ๋์ ๋์ผํ์ง ์๋ค. ํ๋ก์ธ์ค๊ฐ ์ด์ ์๋ค๋ฉด, ์ค์ผ์ค๋ง๋๊ณ ๊ฑด๊ฐํ๋ค.
ํ๋ก์ธ์ค๊ฐ ์ค๋น๋๋ฉด ์
๋ ฅ์ ์ฒ๋ฆฌํ ์ ์๋ค. ํ์ฑ๋๋ ํ์์ ์ด๋ ์ค๋น๋์ ์กฐ๊ฑด์ผ๋ก๋
์ถฉ๋ถํ์ง ์๋ค. ๋ช๋ช ๊ฒฝ์ฐ
ํน๋ณํ ์ด๊ธฐํ์ ์ข
๋ฃ ์์ ํ๋ก์ธ์ค๋ ์ด์์์ง๋ง
์ค๋น๋์ง ์์ ์ ์๋ค.
์ค๋น๋ ๊ฒ์ฌ๋ฅผ ์ง์ ํ๋ฉด, ์ฟ ๋ฒ๋คํฐ์ค๋ ์ค๋น๋๊ฐ ํต๊ณผํ ๋๊น์ง
์ ํ๋ฆฌ์ผ์ด์
ํ๋ก์ธ์ค๊ฐ ๋คํธ์ํฌ ํธ๋ํฝ์ ์์ ํ์ง ์๊ฒ ํ๋ค.
ZooKeeper ์๋ฒ์์๋ ์ค๋น๋๊ฐ ํ์ฑ๋๋ฅผ ๋ดํฌํ๋ค. ๊ทธ๋ฌ๋ฏ๋ก zookeeper.yaml
๋งค๋ํ์คํธ์์
์ค๋น๋ ๊ฒ์ฌ๋ ํ์ฑ๋ ๊ฒ์ฌ์ ๋์ผํ๋ค.
readinessProbe :
exec :
command :
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds : 15
timeoutSeconds : 5
ํ์ฑ๋์ ์ค๋น๋ ๊ฒ์ฌ๊ฐ ๋์ผํจ์๋ ๋ ๋ค ์ง์ ํ๋ ๊ฒ์ ์ค์ํ๋ค.
์ด๋ ZooKeeper ์์๋ธ์ ๊ฑด๊ฐํ ์๋ฒ๋ง ์๋๋ผ
๋คํธ์ํฌ ํธ๋ํฝ์ ์์ ํ๋ ๊ฒ์ ๋ณด์ฅํ๋ค.
๋
ธ๋ ์คํจ ๋ฐฉ์ง ZooKeeper๋ ๋ณ์กฐ๋ ๋ฐ์ดํฐ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ์ปค๋ฐํ๊ธฐ ์ํ ์๋ฒ์ ์ฟผ๋ผ์ด ํ์ํ๋ค.
3๊ฐ์ ์๋ฒ ์์๋ธ์์ ์ฑ๊ณต์ ์ผ๋ก ์ ์ฅํ๋ ค๋ฉด 2๊ฐ ์๋ฒ๋ ๋ฐ๋์ ๊ฑด๊ฐํด์ผ ํ๋ค.
์ฟผ๋ผ ๊ธฐ๋ฐ ์์คํ
์์, ๋ฉค๋ฒ๋ ๊ฐ์ฉ์ฑ์ ๋ณด์ฅํ๋
์คํจ ์์ญ์ ๊ฑธ์ณ ๋ฐฐํฌ๋๋ค.
์ค๋จ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๊ฐ๋ณ ์์คํ
์ ์์ค๋ก ์ธํด ๋ชจ๋ฒ ์ฌ๋ก์์๋ ๋์ผํ ์์คํ
์
์ฌ๋ฌ ์ธ์คํด์ค์ ์์ฉ ํ๋ก๊ทธ๋จ์ ํจ๊ป ๋ฐฐ์นํ๋ ๊ฒ์ ๋ฐฐ์ ํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์ฟ ๋ฒ๋คํฐ์ค๋ ๋์ผ ๋
ธ๋์์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์์น์ํฌ ์ ์๋ค.
์์ฑํ 3๊ฐ์ ์๋ฒ ์์๋ธ์์ 2๊ฐ์ ์๋ฒ๊ฐ ๊ฐ์ ๋
ธ๋์ ์๋ค๋ฉด, ๊ทธ ๋
ธ๋๋ ์คํจํ๊ณ
ZooKeeper ์๋น์ค ํด๋ผ์ด์ธํธ๋ ๊ทธ ํ๋๋ค์ ์ต์ ํ๋๊ฐ ์ฌ์ค์ผ์ค๋ง๋ ๋๊น์ง ์๋ ์ค๋จ์ ๊ฒฝํํ ๊ฒ์ด๋ค.
๋
ธ๋ ์คํจํ๋ ์ฌ๊ฑด ์ค์๋ ์ค์ ์์คํ
์ ํ๋ก์ธ์ค๊ฐ ์ฌ์ค์ผ์ค๋ ์ ์๊ฒ
ํญ์ ์ถ๊ฐ์ ์ธ ์ฉ๋์ ํ๋ก๋น์ ํด์ผ ํ๋ค. ๊ทธ๋ ๊ฒ ํ๋ฉด ์ฟ ๋ฒ๋คํฐ์ค ์ค์ผ์ค๋ฌ๊ฐ
ZooKeeper ์๋ฒ ํ๋๋ฅผ ๋ค์ ์ค์ผ์คํ๋ ๋์๊น์ง๋ง ์๋ ์ค๋จ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ ์๋น์ค์์ ๋
ธ๋ ์คํจ๋ก ์ธํ ๋ค์ดํ์์ ๋ฐฉ์งํ๋ ค ํ๋ค๋ฉด,
ํ๋์ํฐ์ดํผ๋ํฐ
๋ฅผ ์ค์ ํด์ผ ํ๋ค.
zk
์คํ
์ดํธํ์
์ ํ๋์ ๋
ธ๋๋ฅผ ์์๋ณด๊ธฐ ์ํด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
for i in 0 1 2; do kubectl get pod zk-$i --template {{ .spec.nodeName}} ; echo "" ; done
zk
์คํ
์ดํธํ์
์ ๋ชจ๋ ํ๋๋ ๋ค๋ฅธ ๋
ธ๋์ ๋ฐฐํฌ๋๋ค.
kubernetes-node-cxpk
kubernetes-node-a5aq
kubernetes-node-2g2d
์ด๋ zk
์คํ
์ดํธํ์
์ ํ๋์ ํ๋์ํฐ์ดํผ๋ํฐ(PodAntiAffinity)
๋ฅผ ์ง์ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
affinity :
podAntiAffinity :
requiredDuringSchedulingIgnoredDuringExecution :
- labelSelector :
matchExpressions :
- key : "app"
operator : In
values :
- zk
topologyKey : "kubernetes.io/hostname"
requiredDuringSchedulingIgnoredDuringExecution
ํ๋๋
์ฟ ๋ฒ๋คํฐ์ค ์ค์ผ์ค๋ฌ์ topologyKey
๋ก ์ ์๋ ๋๋ฉ์ธ์์ app
์ด zk
๋ผ๊ณ ๋ ์ด๋ธ๋ง๋
๋ ๊ฐ ํ๋๊ฐ ์์นํ์ง ์๋๋ก ํ๋ค.
topologyKey
kubernetes.io/hostname
์ ๋๋ฉ์ธ์ด ๊ฐ๋ณ ๋
ธ๋์์ ๋ํ๋ธ๋ค.
๋ค๋ฅธ ๊ท์น๊ณผ ๋ ์ด๋ธ, ์
๋ ํฐ๋ฅผ ์ฌ์ฉํ์ฌ
์์๋ธ์ ๋ฌผ๋ฆฌ์ ์ธ, ๋คํธ์ํฌ, ์ ์ ์ฅ์ ๋ถ์ผ์ ๊ฑธ์ณ ํ์ฐํ๋๋ก ์ด ๊ธฐ๋ฒ์ ํ์ฅํ ์ ์๋ค.
์์กด ์ ์ง ์ด ์น์
์์๋ ๋
ธ๋๋ฅผ ํต์ (cordon)ํ๊ณ ๋น์ด๋ค(drain). ๊ณต์ ๋ ํด๋ฌ์คํฐ์์ ์ด ํํ ๋ฆฌ์ผ์ ์งํํ๋ค๋ฉด,
๋ค๋ฅธ ํ
๋ํธ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋น์น์ง ์์์ ๋ณด์ฆํด์ผ ํ๋ค.
์ด์ ์น์
์ ๊ณํ๋์ง ์์ ๋
ธ๋ ์คํจ์์ ์ด์๋จ๋๋ก
์ด๋ป๊ฒ ํ๋๋ฅผ ํ์ฐํ ๊ฒ์ธ๊ฐ์ ๋ํด ์์๋ณด์๋ค.
๊ทธ๋ฌ๋ ๊ณํ๋ ์ ๊ฒ์ผ๋ก ์ธํด ๋ฐ์ํ๋ ์ผ์์ ์ธ ๋
ธ๋ ์คํจ์ ๋ํ ๊ณํ๋ ํ์ํ๋ค.
ํด๋ฌ์คํฐ์์ ๋ค์ ๋ช
๋ น์ผ๋ก ๋
ธ๋๋ฅผ ์ดํด๋ณด์.
์ด ํํ ๋ฆฌ์ผ์์๋ ํด๋ฌ์คํฐ๊ฐ ์ต์ 4๊ฐ์ ๋
ธ๋๋ก ๊ตฌ์ฑ๋์๋ค๊ณ ๊ฐ์ ํ๋ค. ํด๋ฌ์คํฐ์ ๋
ธ๋๊ฐ 4๊ฐ๋ณด๋ค ๋ง๋ค๋ฉด, kubectl cordon
๋ช
๋ น์ ์ด์ฉํ์ฌ 4๊ฐ ๋
ธ๋๋ฅผ ์ ์ธํ๊ณ ๋ค๋ฅธ ๋ชจ๋ ๋
ธ๋๋ฅผ ํต์ (cordon)ํ๋ค. ์ด๋ ๊ฒ 4๊ฐ ๋
ธ๋๋ง ์ฌ์ฉํ๋๋ก ์ ํํ์ฌ, ๋ค์์ ์ ์ง๋ณด์ ์๋ฎฌ๋ ์ด์
์์์์ ์ฃผํคํผ ํ๋๋ฅผ ์ค์ผ์ค๋งํ ๋ ์ดํผ๋ํฐ์ PodDisruptionBudget ์ ์ฝ์ด ๋ฐ์ํ๋๋ก ํ ์ ์๋ค.
kubectl cordon <๋
ธ๋-์ด๋ฆ>
zk-pdb
PodDisruptionBudget
์ ์ดํด๋ณด๊ณ ์ ์ด ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
max-unavailable
ํ๋๋ ์ฟ ๋ฒ๋คํฐ์ค๊ฐ zk
์คํ
์ดํธํ์
์์ ์ต๋ 1๊ฐ์ ํ๋๋
์ธ์ ๋ ์ง ๊ฐ์ฉํ์ง ์์ ์ ์์์ ๋ํ๋ธ๋ค.
NAME MIN-AVAILABLE MAX-UNAVAILABLE ALLOWED-DISRUPTIONS AGE
zk-pdb N/A 1 1
ํ ํฐ๋ฏธ๋์์ zk
์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์ง์ผ๋ณด๋ ์ด ๋ช
๋ น์ด๋ฅผ ์ด์ฉํ์.
kubectl get pods -w -l app = zk
๋ค๋ฅธ ํฐ๋ฏธ๋์์ ํ์ฌ ์ค์ผ์ค๋๋ ํ๋์ ๋
ธ๋๋ฅผ ์ดํด๋ณด์.
for i in 0 1 2; do kubectl get pod zk-$i --template {{ .spec.nodeName}} ; echo "" ; done
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
kubernetes-node-pb41
kubernetes-node-ixsl
kubernetes-node-i4c4
zk-0
ํ๋๊ฐ ์ค์ผ์ค๋๋ ๋
ธ๋๋ฅผ ํต์ ํ๊ธฐ ์ํด
kubectl drain
๋ฅผ ์ด์ฉํ์.
kubectl drain $( kubectl get pod zk-0 --template {{ .spec.nodeName}} ) --ignore-daemonsets --force --delete-emptydir-data
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
node "kubernetes-node-group-pb41" cordoned
WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-group-pb41, kube-proxy-kubernetes-node-group-pb41; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-o5elz
pod "zk-0" deleted
node "kubernetes-node-group-pb41" drained
ํด๋ฌ์คํฐ์ 4๊ฐ ๋
ธ๋๊ฐ ์๊ธฐ ๋๋ฌธ์ kubectl drain
์ด ์ฑ๊ณตํ์ฌ
zk-0
์ ๋ค๋ฅธ ๋
ธ๋๋ก ์ฌ์ค์ผ์ค๋ง ๋๋ค.
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Running 2 1h
zk-1 1/1 Running 0 1h
zk-2 1/1 Running 0 1h
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Pending 0 0s
zk-0 0/1 Pending 0 0s
zk-0 0/1 ContainerCreating 0 0s
zk-0 0/1 Running 0 51s
zk-0 1/1 Running 0 1m
๊ณ์ํด์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์ฒซ ํฐ๋ฏธ๋์์ ์ง์ผ๋ณด๊ณ
zk-1
์ด ์ค์ผ์ค๋ ๋
ธ๋๋ฅผ ๋น์๋ณด์.
kubectl drain $( kubectl get pod zk-1 --template {{ .spec.nodeName}} ) --ignore-daemonsets --force --delete-emptydir-data
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
"kubernetes-node-ixsl" cordoned
WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-ixsl, kube-proxy-kubernetes-node-ixsl; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-voc74
pod "zk-1" deleted
node "kubernetes-node-ixsl" drained
zk-1
ํ๋๋ ์ค์ผ์ค๋์ง ์๋๋ฐ ์ด๋ zk
StatefulSet
์ด ์ค์ง 2๊ฐ ๋
ธ๋๊ฐ ์ค์ผ์ค๋๋๋ก ํ๋๋ฅผ ์์น์ํค๋ ๊ฒ์ ๊ธํ๋
PodAntiAffinity
๊ท์น์ ํฌํจํ์๊ธฐ ๋๋ฌธ์ด๊ณ ๊ทธ ํ๋๋ Pending ์ํ๋ก ๋จ์ ๊ฒ์ด๋ค.
kubectl get pods -w -l app = zk
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Running 2 1h
zk-1 1/1 Running 0 1h
zk-2 1/1 Running 0 1h
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Pending 0 0s
zk-0 0/1 Pending 0 0s
zk-0 0/1 ContainerCreating 0 0s
zk-0 0/1 Running 0 51s
zk-0 1/1 Running 0 1m
zk-1 1/1 Terminating 0 2h
zk-1 0/1 Terminating 0 2h
zk-1 0/1 Terminating 0 2h
zk-1 0/1 Terminating 0 2h
zk-1 0/1 Pending 0 0s
zk-1 0/1 Pending 0 0s
๊ณ์ํด์ ์คํ
์ดํธํ์
์ ํ๋๋ฅผ ์ง์ผ๋ณด๊ณ
zk-2
๊ฐ ์ค์ผ์ค๋ ๋
ธ๋๋ฅผ ๋น์๋ณด์.
kubectl drain $( kubectl get pod zk-2 --template {{ .spec.nodeName}} ) --ignore-daemonsets --force --delete-emptydir-data
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
node "kubernetes-node-i4c4" cordoned
WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-i4c4, kube-proxy-kubernetes-node-i4c4; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-dyrog
WARNING: Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-dyrog; Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-i4c4, kube-proxy-kubernetes-node-i4c4
There are pending pods when an error occurred: Cannot evict pod as it would violate the pod's disruption budget.
pod/zk-2
kubectl ์ ์ข
๋ฃํ๊ธฐ ์ํด CTRL-C
๋ฅผ ์ด์ฉํ์.
zk-2
๋ฅผ ์ถ์ถํ๋ ๊ฒ์ zk-budget
์ ์๋ฐํ๊ธฐ ๋๋ฌธ์ ์
์งธ ๋
ธ๋๋ฅผ ๋น์ธ ์ ์๋ค. ๊ทธ๋ฌ๋ ๊ทธ ๋
ธ๋๋ ํต์ ์ํ๋ก ๋จ๋๋ค.
zk-0
์์ ์จ์ ์ฑ ํ
์คํธ ๋์ ์
๋ ฅํ ๊ฐ์ ๊ฐ์ ธ์ค๋ zkCli.sh
๋ฅผ ์ด์ฉํ์.
kubectl exec zk-0 zkCli.sh get /hello
PodDisruptionBudget
์ด ์กด์ค๋๊ธฐ ๋๋ฌธ์ ์๋น์ค๋ ์ฌ์ ํ ๊ฐ์ฉํ๋ค.
WatchedEvent state:SyncConnected type:None path:null
world
cZxid = 0x200000002
ctime = Wed Dec 07 00:08:59 UTC 2016
mZxid = 0x200000002
mtime = Wed Dec 07 00:08:59 UTC 2016
pZxid = 0x200000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
kubectl uncordon
์ด์ฉํ์ฌ ์ฒซ ๋
ธ๋์ ํต์ ๋ฅผ ํ์.
kubectl uncordon kubernetes-node-pb41
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
node "kubernetes-node-pb41" uncordoned
zk-1
์ ์ด ๋
ธ๋์์ ์ฌ์ค์ผ์ค๋๋ค. zk-1
์ด Running๊ณผ Ready๊ฐ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์.
kubectl get pods -w -l app = zk
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Running 2 1h
zk-1 1/1 Running 0 1h
zk-2 1/1 Running 0 1h
NAME READY STATUS RESTARTS AGE
zk-0 1/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Terminating 2 2h
zk-0 0/1 Pending 0 0s
zk-0 0/1 Pending 0 0s
zk-0 0/1 ContainerCreating 0 0s
zk-0 0/1 Running 0 51s
zk-0 1/1 Running 0 1m
zk-1 1/1 Terminating 0 2h
zk-1 0/1 Terminating 0 2h
zk-1 0/1 Terminating 0 2h
zk-1 0/1 Terminating 0 2h
zk-1 0/1 Pending 0 0s
zk-1 0/1 Pending 0 0s
zk-1 0/1 Pending 0 12m
zk-1 0/1 ContainerCreating 0 12m
zk-1 0/1 Running 0 13m
zk-1 1/1 Running 0 13m
zk-2
๊ฐ ์ค์ผ์ค๋ ๋
ธ๋๋ฅผ ๋น์๋ณด์.
kubectl drain $( kubectl get pod zk-2 --template {{ .spec.nodeName}} ) --ignore-daemonsets --force --delete-emptydir-data
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
node "kubernetes-node-i4c4" already cordoned
WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-i4c4, kube-proxy-kubernetes-node-i4c4; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-dyrog
pod "heapster-v1.2.0-2604621511-wht1r" deleted
pod "zk-2" deleted
node "kubernetes-node-i4c4" drained
์ด๋ฒ์ kubectl drain
์ด ์ฑ๊ณตํ๋ค.
zk-2
๊ฐ ์ฌ์ค์ผ์ค๋๋๋ก ๋ ๋ฒ์งธ ๋
ธ๋์ ํต์ ๋ฅผ ํ์ด๋ณด์.
kubectl uncordon kubernetes-node-ixsl
์ถ๋ ฅ์ ๋ค์๊ณผ ๋น์ทํ ๊ฒ์ด๋ค.
node "kubernetes-node-ixsl" uncordoned
kubectl drain
์ PodDisruptionBudget
๊ณผ ๊ฒฐํฉํ๋ฉด ์ ์ง๋ณด์ ์ค์๋ ์๋น์ค๋ฅผ ๊ฐ์ฉํ๊ฒ ํ ์ ์๋ค.
drain์ผ๋ก ๋
ธ๋๋ฅผ ํต์ ํ๊ณ ์ ์ง๋ณด์๋ฅผ ์ํด ๋
ธ๋๋ฅผ ์คํ๋ผ์ธํ๊ธฐ ์ ์ ํ๋๋ฅผ ์ถ์ถํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค๋ฉด
์๋น์ค๋ ํผ๋ ์์ฐ์ ํ๊ธฐํ ์๋น์ค๋ ๊ทธ ์์ฐ์ด ์กด์ค์ ์กด์ค๋ ๊ฒ์ด๋ค.
ํ๋๊ฐ ์ฆ๊ฐ์ ์ผ๋ก ์ฌ์ค์ผ์ค ํ ์ ์๋๋ก ํญ์ ์ค์ ์๋น์ค๋ฅผ ์ํ ์ถ๊ฐ ์ฉ๋์ ํ ๋นํด์ผ ํ๋ค.
์ ๋ฆฌํ๊ธฐ kubectl uncordon
์ ํด๋ฌ์คํฐ ๋ด์ ๋ชจ๋ ๋
ธ๋๋ฅผ ํต์ ํด์ ํ๋ค.๋ฐ๋์ ์ด ํํ ๋ฆฌ์ผ์์ ์ฌ์ฉํ ํผ์์คํดํธ ๋ณผ๋ฅจ์ ์ํ ํผ์์คํดํธ ์คํ ๋ฆฌ์ง ๋ฏธ๋์ด๋ฅผ ์ญ์ ํ์.
๊ทํ์ ํ๊ฒฝ๊ณผ ์คํ ๋ฆฌ์ง ๊ตฌ์ฑ๊ณผ ํ๋ก๋น์ ๋ ๋ฐฉ๋ฒ์์ ํ์ํ ์ ์ฐจ๋ฅผ ๋ฐ๋ผ์
๋ชจ๋ ์คํ ๋ฆฌ์ง๊ฐ ์ฌํ๋ณด๋๋๋ก ํ์.
7 - ์๋น์ค 7.1 - ์๋น์ค์ ์ ํ๋ฆฌ์ผ์ด์
์ฐ๊ฒฐํ๊ธฐ ์ปจํ
์ด๋ ์ฐ๊ฒฐ์ ์ํ ์ฟ ๋ฒ๋คํฐ์ค ๋ชจ๋ธ ์ง์์ ์ผ๋ก ์คํ์ค์ด๊ณ , ๋ณต์ ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ์ง๊ณ ์๋ค๋ฉด ๋คํธ์ํฌ์ ๋
ธ์ถํ ์ ์๋ค.
์ฟ ๋ฒ๋คํฐ์ค๋ ํ๋๊ฐ ๋ฐฐ์น๋ ํธ์คํธ์๋ ๋ฌด๊ดํ๊ฒ ๋ค๋ฅธ ํ๋์ ํต์ ํ ์ ์๋ค๊ณ ๊ฐ์ ํ๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋ ๋ชจ๋ ํ๋์๊ฒ ์์ฒด ํด๋ฌ์คํฐ-ํ๋ผ์ด๋น IP ์ฃผ์๋ฅผ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ ํ๋๊ฐ์ ๋ช
์์ ์ผ๋ก ๋งํฌ๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ปจํ
์ด๋ ํฌํธ๋ฅผ ํธ์คํธ ํฌํธ์ ๋งคํํ ํ์๊ฐ ์๋ค. ์ด๊ฒ์ ํ๋ ๋ด์ ์ปจํ
์ด๋๋ ๋ชจ๋ ๋ก์ปฌํธ์คํธ(localhost)์์ ์๋ก์ ํฌํธ์ ๋๋ฌํ ์ ์์ผ๋ฉฐ ํด๋ฌ์คํฐ์ ๋ชจ๋ ํ๋๋ NAT ์์ด ์๋ก๋ฅผ ๋ณผ ์ ์๋ค๋ ์๋ฏธ์ด๋ค. ์ด ๋ฌธ์์ ๋๋จธ์ง ๋ถ๋ถ์์๋ ์ด๋ฌํ ๋คํธ์ํน ๋ชจ๋ธ์์ ์ ๋ขฐํ ์ ์๋ ์๋น์ค๋ฅผ ์คํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์ค๋ช
ํ ๊ฒ์ด๋ค.
์ด ํํ ๋ฆฌ์ผ์ ๊ฐ๋จํ nginx ์๋ฒ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋
์ ์์ฐํ๋ค.
ํ๋๋ฅผ ํด๋ฌ์คํฐ์ ๋
ธ์ถํ๊ธฐ ์ด ์์
์ ์ด์ ์์์์ ์ํํด ๋ณด์์ง๋ง, ๋คํธ์ํน ๊ด์ ์ ์ค์ ์ ๋๊ณ ๋ค์ ํ๋ฒ ์ํํด ๋ณด์.
nginx ํ๋๋ฅผ ์์ฑํ๊ณ , ํด๋น ํ๋์ ์ปจํ
์ด๋ ํฌํธ ์ฌ์์ด ์๋ ๊ฒ์ ์ฐธ๊ณ ํ๋ค.
apiVersion : apps/v1
kind : Deployment
metadata :
name : my-nginx
spec :
selector :
matchLabels :
run : my-nginx
replicas : 2
template :
metadata :
labels :
run : my-nginx
spec :
containers :
- name : my-nginx
image : nginx
ports :
- containerPort : 80
์ด๋ ๊ฒ ํ๋ฉด ํด๋ฌ์คํฐ์ ๋ชจ๋ ๋
ธ๋์์ ์ ๊ทผํ ์ ์๋ค. ํ๋๋ฅผ ์คํ ์ค์ธ ๋
ธ๋๋ฅผ ํ์ธํ๋ค.
kubectl apply -f ./run-my-nginx.yaml
kubectl get pods -l run = my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-jr4a2 1/1 Running 0 13s 10.244.3.4 kubernetes-minion-905m
my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5 kubernetes-minion-ljyd
ํ๋์ IP๋ฅผ ํ์ธํ๋ค.
kubectl get pods -l run = my-nginx -o custom-columns= POD_IP:.status.podIPs
POD_IP
[ map[ ip:10.244.3.4]]
[ map[ ip:10.244.2.5]]
์ด์ ํด๋ฌ์คํฐ์ ๋ชจ๋ ๋
ธ๋๋ก ssh ์ ์ํ๊ฑฐ๋ curl
๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ IP ์ฃผ์์ ์ง์๋ฅผ ์ ์กํ ์ ์์ ๊ฒ์ด๋ค. ์ปจํ
์ด๋๋ ๋
ธ๋์ ํฌํธ 80์ ์ฌ์ฉํ์ง ์์ผ๋ฉฐ , ํธ๋ํฝ์ ํ๋๋ก ๋ผ์ฐํ
ํ๋ ํน๋ณํ NAT ๊ท์น๋ ์๋ค๋ ๊ฒ์ ์ฐธ๊ณ ํ๋ค. ์ด๊ฒ์ ๋์ผํ containerPort
๋ฅผ ์ฌ์ฉํ์ฌ ๋์ผํ ๋
ธ๋์์ ์ฌ๋ฌ nginx ํ๋๋ฅผ ์คํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๊ณ , ๋ํ ์๋น์ค์ ํ ๋น๋ IP ์ฃผ์๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ฌ์คํฐ์ ๋ค๋ฅธ ํ๋๋ ๋
ธ๋์์ ์ ๊ทผํ ์ ์๋ค๋ ์๋ฏธ์ด๋ค. ํธ์คํธ ๋
ธ๋์ ํน์ ํฌํธ๋ฅผ ๋ฐฐํ(backing) ํ๋๋ก ํฌ์๋ํ๊ณ ์ถ๋ค๋ฉด, ๊ฐ๋ฅ์ ํ์ง๋ง ๋คํธ์ํน ๋ชจ๋ธ์ ์ฌ์ฉํ๋ฉด ๊ทธ๋ ๊ฒ ํ ํ์๊ฐ ์์ด์ผ ํ๋ค.
๋ง์ฝ ๊ถ๊ธํ๋ค๋ฉด ์ฟ ๋ฒ๋คํฐ์ค ๋คํธ์ํน ๋ชจ๋ธ ์ ์์ธํ ์ฝ์ด๋ณธ๋ค.
์๋น์ค ์์ฑํ๊ธฐ ์ด์ ์ฐ๋ฆฌ์๊ฒ๋ ํ๋ซ(flat)ํ๊ณ ํด๋ฌ์คํฐ ์ ์ญ์ ๊ฑธ์น๋ ์ฃผ์ ๊ณต๊ฐ์์ ์คํ๋๊ณ ์๋ nginx ํ๋๊ฐ ์๋ค. ์ด๋ก ์ ์ผ๋ก๋ ์ด๋ฌํ ํ๋์ ์ง์ ๋ํํ ์ ์์ง๋ง, ๋
ธ๋๊ฐ ์ฃฝ์ผ๋ฉด ์ด๋ป๊ฒ ๋๋๊ฐ? ํ๋๊ฐ ํจ๊ป ์ฃฝ์ผ๋ฉด ๋ํ๋ก์ด๋จผํธ์์ ๋ค๋ฅธ IP๋ฅผ ๊ฐ์ง ์๋ก์ด ํ๋๋ฅผ ์์ฑํ๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ด ๋ฐ๋ก ์๋น์ค์ด๋ค.
์ฟ ๋ฒ๋คํฐ์ค ์๋น์ค๋ ํด๋ฌ์คํฐ ์ด๋๊ฐ์์ ์คํ๋๋ ๋
ผ๋ฆฌ์ ์ธ ํ๋ ์งํฉ์ ์ ์ํ๊ณ ์ถ์ํํจ์ผ๋ก์จ ๋ชจ๋ ๋์ผํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ์์ฑ์ ๊ฐ ์๋น์ค์๋ ๊ณ ์ ํ IP ์ฃผ์(clusterIP๋ผ๊ณ ๋ ํ๋ค)๊ฐ ํ ๋น๋๋ค. ์ด ์ฃผ์๋ ์๋น์ค์ ์๋ช
๊ณผ ์ฐ๊ด๋์ด ์์ผ๋ฉฐ, ์๋น์ค๊ฐ ํ์ฑํ ๋์ด ์๋ ๋์์๋ ๋ณ๊ฒฝ๋์ง ์๋๋ค. ํ๋๋ ์๋น์ค์ ํต์ ํ๋๋ก ๊ตฌ์ฑํ ์ ์์ผ๋ฉฐ, ์๋น์ค์์ ํต์ ์ ์๋น์ค์ ๋งด๋ฒ ์ค ์ผ๋ถ ํ๋์ ์๋์ ์ผ๋ก ๋ก๋-๋ฐธ๋ฐ์ฑ ๋๋ค.
kubectl expose
๋ฅผ ์ฌ์ฉํด์ 2๊ฐ์ nginx ๋ ํ๋ฆฌ์นด์ ๋ํ ์๋น์ค๋ฅผ ์์ฑํ ์ ์๋ค.
kubectl expose deployment/my-nginx
service/my-nginx exposed
์ด๊ฒ์ ๋ค์ yaml ํ์ผ์ kubectl apply -f
๋ก ์คํํ ๊ฒ๊ณผ ๋์ผํ๋ค.
apiVersion : v1
kind : Service
metadata :
name : my-nginx
labels :
run : my-nginx
spec :
ports :
- port : 80
protocol : TCP
selector :
run : my-nginx
์ด ์ฌ์์ run: my-nginx
๋ ์ด๋ธ์ด ๋ถ์ฐฉ๋ ๋ชจ๋ ํ๋์ TCP ํฌํธ 80์
๋์์ผ๋ก ํ๋ ์๋น์ค๋ฅผ ๋ง๋ค๊ณ ์ถ์ํ๋ ์๋น์ค ํฌํธ์ ๋
ธ์ถ์ํจ๋ค
(targetPort
๋ ์ปจํ
์ด๋๊ฐ ํธ๋ํฝ์ ์์ ํ๋ ํฌํธ, port
๋
์ถ์ํ๋ ์๋น์ค ํฌํธ๋ก ๋ค๋ฅธ ํ๋๋ค์ด ์๋น์ค์ ์ ์ํ๊ธฐ์ํด ์ฌ์ฉํ๋
๋ชจ๋ ํฌํธ์ผ ์ ์๋ค).
์๋น์ค ์
API ์ค๋ธ์ ํธ๋ฅผ ๋ณด๊ณ ์๋น์ค ์ ์์์ ์ง์๋๋ ํ๋ ๋ชฉ๋ก์ ํ์ธํ๋ค.
์๋น์ค๋ฅผ ํ์ธํ๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 <none> 80/TCP 21s
์์์ ์ธ๊ธํ ๋ฐ์ ๊ฐ์ด, ์๋น์ค ๋ฐ์๋ ์ฌ๋ฌ ํ๋๋ค์ด ์๋ค.
์ด ํ๋๋ค์
์๋ํฌ์ธํธ์ฌ๋ผ์ด์ค(EndpointSlice) ๋ฅผ
ํตํด ๋
ธ์ถ๋๋ค. ํด๋น ์๋น์ค์ ์
๋ ํฐ๋ ์ง์์ ์ผ๋ก ํ๊ฐ๋๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋
๋ ์ด๋ธ ์ ์ฌ์ฉํ์ฌ
์๋น์ค์ ์ฐ๊ฒฐ๋ ์๋ํฌ์ธํธ์ฌ๋ผ์ด์ค๋ก POST๋๋ค.
ํ๋๊ฐ ์ฃฝ์ผ๋ฉด, ํด๋น ํ๋๋ฅผ ์๋ํฌ์ธํธ๋ก ๊ฐ๋ ์๋ํฌ์ธํธ์ฌ๋ผ์ด์ค์์ ์๋์ผ๋ก ์ ๊ฑฐ๋๋ค.
์ ๊ท ํ๋๊ฐ ํน์ ์๋น์ค์ ์
๋ ํฐ์ ๋งค์น๋๋ฉด
ํด๋น ์๋น์ค๋ฅผ ์ํ ์๋ํฌ์ธํธ์ฌ๋ผ์ด์ค์ ์๋์ผ๋ก ์ถ๊ฐ๋๋ค.
์๋ํฌ์ธํธ๋ฅผ ํ์ธํด ๋ณด๋ฉด,
IP๊ฐ ์ฒซ ๋ฒ์งธ ๋จ๊ณ์์ ์์ฑ๋ ํ๋์ IP์ ๋์ผํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
kubectl describe svc my-nginx
Name: my-nginx
Namespace: default
Labels: run=my-nginx
Annotations: <none>
Selector: run=my-nginx
Type: ClusterIP
IP: 10.0.162.149
Port: <unset> 80/TCP
Endpoints: 10.244.2.5:80,10.244.3.4:80
Session Affinity: None
Events: <none>
NAME ENDPOINTS AGE
my-nginx 10.244.2.5:80,10.244.3.4:80 1m
์ด์ ํด๋ฌ์คํฐ์ ๋ชจ๋ ๋
ธ๋์์ <CLUSTER-IP>:<PORT>
๋ก nginx ์๋น์ค๋ฅผ
curl์ ํ ์ ์์ ๊ฒ์ด๋ค. ์๋น์ค IP๋ ์์ ํ ๊ฐ์์ด๋ฏ๋ก ์ธ๋ถ์์๋ ์ ๋๋ก ์ฐ๊ฒฐ๋์ง
์์์ ์ฐธ๊ณ ํ๋ค. ๋ง์ฝ ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ๊ถ๊ธํ๋ค๋ฉด
์๋น์ค ํ๋ก์ ์ ๋ํด ๋ ์ฝ์ด๋ณธ๋ค.
์๋น์ค์ ์ ๊ทผํ๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค๋ ์๋น์ค๋ฅผ ์ฐพ๋ ๋ ๊ฐ์ง ๊ธฐ๋ณธ ๋ชจ๋์ธ ํ๊ฒฝ ๋ณ์์ DNS๋ฅผ
์ง์ํ๋ค. ์ ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ํ์ง๋ง ํ์๋
CoreDNS ํด๋ฌ์คํฐ ์ ๋์จ ์ด ํ์ํ๋ค.
์ฐธ๊ณ : ๋ง์ฝ ์๋น์ค ํ๊ฒฝ ๋ณ์๊ฐ ํ์ํ์ง ์์ ๊ฒฝ์ฐ(์์ ํ ํ๋ก๊ทธ๋จ๊ณผ์ ์์๋๋ ์ถฉ๋ ๊ฐ๋ฅ์ฑ,
์ฒ๋ฆฌํ ๋ณ์๊ฐ ๋๋ฌด ๋ง์ ๊ฒฝ์ฐ, DNS๋ง ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ฑ)
ํ๋ ์ฌ์ ์์
enableServiceLinks
ํ๋๊ทธ๋ฅผ
false
๋ก ์ค์ ํ๋ฉด ์ด ๋ชจ๋๋ฅผ ๋นํ์ฑํํ ์ ์๋ค.
ํ๊ฒฝ ๋ณ์ ํ๋๊ฐ ๋
ธ๋์์ ์คํ๋ ๋ kubelet์ ๊ฐ๊ธฐ ํ์ฑํ๋ ์๋น์ค์ ๋ํด ์ผ๋ จ์ ํ๊ฒฝ
๋ณ์ ์งํฉ์ ์ถ๊ฐํ๋ค. ์ด๊ฒ์ ์์ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ๋ค. ์ด์ ๋ฅผ ํ์ธํ๋ ค๋ฉด
์คํ ์ค์ธ nginx ํ๋ ํ๊ฒฝ์ ์ ๊ฒํด์ผ ํ๋ค(์ค์ ์ฌ์ฉ์์ ํ๋ ์ด๋ฆ์ ๋ค๋ฅผ ๊ฒ์ด๋ค).
kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
์๋น์ค์ ๋ํ ์ธ๊ธ์ด ์๋ค๋ ๊ฒ์ ์ฐธ๊ณ ํด์ผ ํ๋ค. ์ด๊ฒ์ ์๋น์ค ์ด์ ์ ๋ ํ๋ฆฌ์นด๋ฅผ
์์ฑํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ์์
์ ์ํํ ๋ ๋ ๋ค๋ฅธ ๋จ์ ์ ์ค์ผ์ค๋ฌ๊ฐ ๋ ํ๋๋ฅผ
๋ชจ๋ ๋์ผํ ๋จธ์ ์ ๋ฐฐ์นํ ์๋ ์๋ค๋ ๊ฒ์ด๋ฉฐ, ์ด๋ก ์ธํด ์ ์ฒด ์๋น์ค๊ฐ ์ค๋จ๋ ์
์๋ค. ๋๊ฐ์ ํ๋๋ฅผ ์ฃฝ์ด๊ณ ๋ํ๋ก์ด๋จผํธ๊ฐ ํ๋๋ฅผ ์ฌ์์ฑํ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ผ๋ก
์ด๋ฅผ ์ ์ํ ํ ์ ์๋ค. ์ด๋ฒ์๋ ์๋น์ค๊ฐ ๋ ํ๋ฆฌ์นด๋ค ์ ์
์กด์ฌํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฌ๋ฐ๋ฅธ ํ๊ฒฝ ๋ณ์๋ฟ๋ง ์๋๋ผ ํ๋์ ์ค์ผ์ค๋ฌ-์์ค์
์๋น์ค ๋ถ๋ฐฐ(๋ชจ๋ ๋
ธ๋์ ๋์ผํ ์ฉ๋์ด ์ ๊ณต๋๋ ๊ฒฝ์ฐ)๊ฐ
๋๋ค.
kubectl scale deployment my-nginx --replicas= 0; kubectl scale deployment my-nginx --replicas= 2;
kubectl get pods -l run = my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-e9ihh 1/1 Running 0 5s 10.244.2.7 kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4 1/1 Running 0 5s 10.244.3.8 kubernetes-minion-905m
ํ๋๊ฐ ์ฃฝ๊ณ ์ฌ์์ฑ๋์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ์ด๋ฆ์ ๊ฐ์ง๋ ๊ฒ์ ์ ์ ์๋ค.
kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
KUBERNETES_SERVICE_PORT=443
MY_NGINX_SERVICE_HOST=10.0.162.149
KUBERNETES_SERVICE_HOST=10.0.0.1
MY_NGINX_SERVICE_PORT=80
KUBERNETES_SERVICE_PORT_HTTPS=443
DNS ์ฟ ๋ฒ๋คํฐ์ค๋ DNS ํด๋ฌ์คํฐ ์ ๋์จ ์๋น์ค๋ฅผ ์ ๊ณตํ๋ฉฐ dns ์ด๋ฆ์ ๋ค๋ฅธ ์๋น์ค์ ์๋์ผ๋ก ํ ๋นํ๋ค. ๋ค์ ๋ช
๋ น์ด๋ก ์ด๊ฒ์ด ํด๋ฌ์คํฐ์์ ์คํ ์ค์ธ์ง ํ์ธํ ์ ์๋ค.
kubectl get services kube-dns --namespace= kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 8m
์ด ์น์
์ ๋๋จธ์ง ๋ถ๋ถ์์๋ ์๋ช
์ด ๊ธด IP์ ์๋น์ค(my-nginx)์ ์ด IP
์ ์ด๋ฆ์ ํ ๋นํ DNS ์๋ฒ๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ค. ์ฌ๊ธฐ์๋ CoreDNS ํด๋ฌ์คํฐ ์ ๋์จ(์ ํ๋ฆฌ์ผ์ด์
์ด๋ฆ kube-dns
)์ ์ฌ์ฉํ๋ฏ๋ก, ํ์ค ๋ฐฉ๋ฒ(์: gethostbyname()
)์ ์ฌ์ฉํด์ ํด๋ฌ์คํฐ์ ๋ชจ๋ ํ๋์์ ์๋น์ค์ ํต์ ํ ์ ์๋ค. ๋ง์ฝ CoreDNS๊ฐ ์คํ ์ค์ด ์๋๋ผ๋ฉด CoreDNS README ๋๋ CoreDNS ์ค์น ๋ฅผ ์ฐธ์กฐํด์ ํ์ฑํ ํ ์ ์๋ค. ์ด๊ฒ์ ํ
์คํธํ๊ธฐ ์ํด ๋ค๋ฅธ curl ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ๋ค.
kubectl run curl --image= radial/busyboxplus:curl -i --tty
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
Hit enter for command prompt
์ด์ , nslookup my-nginx
๋ฅผ ์
๋ ฅํ๊ณ ์คํํ๋ค:
[ root@curl-131556218-9fnch:/ ] $ nslookup my-nginx
Server: 10.0.0.10
Address 1: 10.0.0.10
Name: my-nginx
Address 1: 10.0.162.149
์๋น์ค ๋ณด์ ์ง๊ธ๊น์ง๋ ํด๋ฌ์คํฐ ๋ด๋ถ์์๋ง ngnix ์๋ฒ์ ์์ธ์ค ํด์๋ค. ์๋น์ค๋ฅผ ์ธํฐ๋ท์ ๊ณต๊ฐํ๊ธฐ ์ ์ ํต์ ์ฑ๋์ด ์์ ํ์ง ํ์ธํด์ผ ํ๋ค. ์ด๋ฅผ ์ํด์ ๋ค์์ด ํ์ํ๋ค.
https์ ๋ํ ์์ฒด ์๋ช
ํ ์ธ์ฆ์ (์ ์ ์ธ์ฆ์๋ฅผ ๊ฐ์ง๊ณ ์์ง ์์ ๊ฒฝ์ฐ) ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ๋๋ก ๊ตฌ์ฑ๋ nginx ์๋ฒ ํ๋์ ์ ๊ทผํ ์ ์๋ ์ธ์ฆ์๋ฅผ ๋ง๋๋ ์ํฌ๋ฆฟ nginx https ์์ ์์ ์ด ๋ชจ๋ ๊ฒ์ ์ป์ ์ ์๋ค. ์ด๋ฅผ ์ํด์๋ ๋๊ตฌ๋ฅผ ์ค์นํด์ผ ํ๋ค. ๋ง์ฝ ์ค์นํ์ง ์์ผ๋ ค๋ฉด ๋์ค์ ์๋์ผ๋ก ๋จ๊ณ๋ฅผ ์ํํ๋ค. ํ๋ง๋๋ก:
make keys KEY = /tmp/nginx.key CERT = /tmp/nginx.crt
kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
secret/nginxsecret created
NAME TYPE DATA AGE
nginxsecret kubernetes.io/tls 2 1m
๊ทธ๋ฆฌ๊ณ ๋ํ ์ปจํผ๊ทธ๋งต:
kubectl create configmap nginxconfigmap --from-file= default.conf
configmap/nginxconfigmap created
NAME DATA AGE
nginxconfigmap 1 114s
๋ค์์ make๋ฅผ ์คํํ๋๋ฐ ๋ฌธ์ ๊ฐ ์๋ ๊ฒฝ์ฐ์ ์ํํด์ผ ํ๋ ์๋ ๋จ๊ณ์ด๋ค(์์๋ก windows).
# Create a public private key pair
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
# Convert the keys to base64 encoding
cat /d/tmp/nginx.crt | base64
cat /d/tmp/nginx.key | base64
์ด์ ๋ช
๋ น์ ์ถ๋ ฅ์ ์ฌ์ฉํด์ ๋ค์๊ณผ ๊ฐ์ด yaml ํ์ผ์ ์์ฑํ๋ค. base64๋ก ์ธ์ฝ๋ฉ๋ ๊ฐ์ ๋ชจ๋ ํ ์ค์ ์์ด์ผ ํ๋ค.
apiVersion : "v1"
kind : "Secret"
metadata :
name : "nginxsecret"
namespace : "default"
type : kubernetes.io/tls
data :
# ์ฐธ๊ณ : ์๋ ๊ฐ๋ค์ ์ง์ base64๋ก ์ธ์ฝ๋ฉํ ์ธ์ฆ์์ ํค๋ก ๊ต์ฒดํ์ธ์.
tls.crt : "REPLACE_WITH_BASE64_CERT"
tls.key : "REPLACE_WITH_BASE64_KEY"
์ด์ ํ์ผ์ ์ฌ์ฉํด์ ์ํฌ๋ฆฟ์ ์์ฑํ๋ค.
kubectl apply -f nginxsecrets.yaml
kubectl get secrets
NAME TYPE DATA AGE
nginxsecret kubernetes.io/tls 2 1m
์ด์ nginx ๋ ํ๋ฆฌ์นด๋ฅผ ์์ ํ์ฌ ์ํธํ๋ ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ https ์๋ฒ์ ์๋น์ค๋ฅผ ์คํํ๊ณ , ๋ ํฌํธ(80๊ณผ 443)๋ฅผ ๋
ธ์ถํ๋ค.
apiVersion : v1
kind : Service
metadata :
name : my-nginx
labels :
run : my-nginx
spec :
type : NodePort
ports :
- port : 8080
targetPort : 80
protocol : TCP
name : http
- port : 443
protocol : TCP
name : https
selector :
run : my-nginx
---
apiVersion : apps/v1
kind : Deployment
metadata :
name : my-nginx
spec :
selector :
matchLabels :
run : my-nginx
replicas : 1
template :
metadata :
labels :
run : my-nginx
spec :
volumes :
- name : secret-volume
secret :
secretName : nginxsecret
- name : configmap-volume
configMap :
name : nginxconfigmap
containers :
- name : nginxhttps
image : bprashanth/nginxhttps:1.0
ports :
- containerPort : 443
- containerPort : 80
volumeMounts :
- mountPath : /etc/nginx/ssl
name : secret-volume
- mountPath : /etc/nginx/conf.d
name : configmap-volume
nginx-secure-app์ ๋งค๋ํ์คํธ์ ๋ํ ์ฃผ๋ชฉํ ๋งํ ์ :
์ด๊ฒ์ ๋์ผํ ํ์ผ์ ๋ํ๋ก์ด๋จผํธ์ ์๋น์ค์ ์ฌ์์ ๋ชจ๋ ํฌํจํ๊ณ ์๋ค. nginx ์๋ฒ
๋ ํฌํธ 80์์ HTTP ํธ๋ํฝ์ 443์์ HTTPS ํธ๋ํฝ ์๋น์ค๋ฅผ ์ ๊ณตํ๊ณ , nginx ์๋น์ค๋
๋ ํฌํธ๋ฅผ ๋ชจ๋ ๋
ธ์ถํ๋ค.๊ฐ ์ปจํ
์ด๋๋ /etc/nginx/ssl
์ ๋ง์ดํธ๋ ๋ณผ๋ฅจ์ ํตํด ํค์ ์ ๊ทผํ ์ ์๋ค.
์ด๊ฒ์ nginx ์๋ฒ๊ฐ ์์๋๊ธฐ ์ ์ ์ค์ ๋ ๊ฒ์ด๋ค. kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml
์ด ์์ ์์ ๋ชจ๋ ๋
ธ๋์์ nginx ์๋ฒ์ ์ฐ๊ฒฐํ ์ ์๋ค.
kubectl get pods -l run = my-nginx -o custom-columns= POD_IP:.status.podIPs
POD_IP
[ map[ ip:10.244.3.5]]
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>
๋ง์ง๋ง ๋จ๊ณ์์ curl์ -k
ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๊ณตํ ๋ฐฉ๋ฒ์ ์ฐธ๊ณ ํ๋ค. ์ด๋ ์ธ์ฆ์ ์์ฑ์ nginx๋ฅผ ์คํํ๋ ํ๋์ ๋ํด ์๋ฌด๊ฒ๋ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์
curl์ CName ๋ถ์ผ์น๋ฅผ ๋ฌด์ํ๋๋ก ์ง์ํด์ผํ๊ธฐ ๋๋ฌธ์ด๋ค. ์๋น์ค๋ฅผ ์์ฑํด์ ์ธ์ฆ์์ ์ฌ์ฉ๋ CName์ ์๋น์ค ์กฐํ์ ํ๋์์ ์ฌ์ฉ๋ ์ค์ DNS ์ด๋ฆ๊ณผ ์ฐ๊ฒฐํ๋ค.
ํ๋์์ ์ด๊ฒ์ ํ
์คํธ ํด๋ณด์(๋จ์ํ ๋์ผํ ์ํฌ๋ฆฟ์ด ์ฌ์ฌ์ฉ๋๊ณ ์์ผ๋ฉฐ, ํ๋๋ ์๋น์ค์ ์ ๊ทผํ๊ธฐ์ํด nginx.crt๋ง ํ์ํ๋ค).
apiVersion : apps/v1
kind : Deployment
metadata :
name : curl-deployment
spec :
selector :
matchLabels :
app : curlpod
replicas : 1
template :
metadata :
labels :
app : curlpod
spec :
volumes :
- name : secret-volume
secret :
secretName : nginxsecret
containers :
- name : curlpod
command :
- sh
- -c
- while true; do sleep 1; done
image : radial/busyboxplus:curl
volumeMounts :
- mountPath : /etc/nginx/ssl
name : secret-volume
kubectl apply -f ./curlpod.yaml
kubectl get pods -l app = curlpod
NAME READY STATUS RESTARTS AGE
curl-deployment-1515033274-1410r 1/1 Running 0 1m
kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/tls.crt
...
<title>Welcome to nginx!</title>
...
์๋น์ค ๋
ธ์ถํ๊ธฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ผ๋ถ์ธ ๊ฒฝ์ฐ ์ํ๋ค๋ฉด ์ธ๋ถ IP ์ฃผ์์ ์๋น์ค๋ฅผ
๋
ธ์ถํ ์ ์๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋ ์ด๋ฅผ ์ํํ๋ 2๊ฐ์ง ๋ฐฉ๋ฒ์ธ NodePorts์
LoadBalancers๋ฅผ์ง์ํ๋ค. ๋ง์ง๋ง ์น์
์์ ์์ฑ๋ ์๋น์ค๋ ์ด๋ฏธ NodePort
๋ฅผ ์ฌ์ฉํ๊ธฐ์
๋
ธ๋์ ๊ณต์ฉ IP๊ฐ ์๋๊ฒฝ์ฐ nginx HTTPS ๋ ํ๋ฆฌ์นด๊ฐ ์ธํฐ๋ท ํธ๋ํฝ์ ์ฒ๋ฆฌํ
์ค๋น๊ฐ ๋์ด ์๋ค.
kubectl get svc my-nginx -o yaml | grep nodePort -C 5
uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
clusterIP: 10.0.162.149
ports:
- name: http
nodePort: 31704
port: 8080
protocol: TCP
targetPort: 80
- name: https
nodePort: 32453
port: 443
protocol: TCP
targetPort: 443
selector:
run: my-nginx
kubectl get nodes -o yaml | grep ExternalIP -C 1
- address: 104.197.41.11
type: ExternalIP
allocatable:
--
- address: 23.251.152.56
type: ExternalIP
allocatable:
...
$ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
...
<h1>Welcome to nginx!</h1>
์ด์ ํด๋ผ์ฐ๋ ๋ก๋ ๋ฐธ๋ฐ์๋ฅผ ์ฌ์ฉํ๋๋ก ์๋น์ค๋ฅผ ์ฌ์์ฑํ๋ค. my-nginx
์๋น์ค์ Type
์ NodePort
์์ LoadBalancer
๋ก ๋ณ๊ฒฝํ๋ค.
kubectl edit svc my-nginx
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx LoadBalancer 10.0.162.149 xx.xxx.xxx.xxx 8080:30163/TCP 21s
curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>
EXTERNAL-IP
์ IP ์ฃผ์๋ ๊ณต์ฉ ์ธํฐ๋ท์์ ์ด์ฉํ ์ ์๋ ์ฃผ์์ด๋ค. CLUSTER-IP
๋
ํด๋ฌ์คํฐ/ํ๋ผ์ด๋น ํด๋ผ์ฐ๋ ๋คํธ์ํฌ ๋ด์์๋ง ์ฌ์ฉํ ์ ์๋ค.
AWS์์๋ LoadBalancer
์ ํ์ IP๊ฐ ์๋ (๊ธด)ํธ์คํธ๋ค์์ ์ฌ์ฉํ๋ ELB๋ฅผ
์์ฑํ๋ค๋ ์ ์ ์ฐธ๊ณ ํ๋ค. ์ด๊ฒ์ ์ผ๋ฐ์ ์ธ kubectl get svc
์ ์ถ๋ ฅ์
๋ง์ถ๊ธฐ์๋ ๋งค์ฐ ๊ธธ๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ์ด๋ฅผ ๋ณด๋ ค๋ฉด kubectl describe service my-nginx
๋ฅผ
์ํํด์ผ ํ๋ค. ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ๋ณด๊ฒ ๋๋ค.
kubectl describe service my-nginx
...
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...
๋ค์ ๋ด์ฉ 7.2 - ์์ค IP ์ฃผ์ ์ด์ฉํ๊ธฐ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์์ ์คํ ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ ์๋น์ค ์ถ์ํ๋ฅผ ํตํด์
์๋ก๋ฅผ, ๊ทธ๋ฆฌ๊ณ ์ธ๋ถ ์ธ๊ณ๋ฅผ ์ฐพ๊ณ ํต์ ํ๋ค. ์ด ๋ฌธ์๋
๋ค๋ฅธ ์ข
๋ฅ์ ์๋น์ค๋ก ์ ์ก๋ ํจํท์ ์์ค IP์ ์ด๋ค ์ผ์ด ๋ฒ์ด์ง๋์ง์
์ด ๋์์ ํ์์ ๋ฐ๋ผ ์ด๋ป๊ฒ ์ ํํ ์ ์๋์ง ์ค๋ช
ํ๋ค.
์์ํ๊ธฐ ์ ์ ์ฉ์ด ์ด ๋ฌธ์๋ ๋ค์ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ค.
NAT ๋คํธ์ํฌ ์ฃผ์ ๋ณํ ์์ค NAT ํจํท ์์ ์์ค IP ์ฃผ์๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ. ์ด ํ์ด์ง์์๋ ์ผ๋ฐ์ ์ผ๋ก ๋
ธ๋ IP ์ฃผ์๋ก์ ๋ณ๊ฒฝ์ ์๋ฏธํจ. ๋์ NAT ํจํท ์์ ๋์ IP ์ฃผ์๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ. ์ด ํ์ด์ง์์๋ ์ผ๋ฐ์ ์ผ๋ก ํ๋ IP ์ฃผ์๋ก์ ๋ณ๊ฒฝ์ ์๋ฏธํจ. VIP ์ฟ ๋ฒ๋คํฐ์ค์ ๋ชจ๋ ์๋น์ค ์ ํ ๋น๋์ด ์๋ ๊ฒ๊ณผ ๊ฐ์, ๊ฐ์ IP ์ฃผ์. Kube-proxy ๋ชจ๋ ๋
ธ๋์์ ์๋น์ค VIP ๊ด๋ฆฌ๋ฅผ ์กฐ์จํ๋ ๋คํธ์ํฌ ๋ฐ๋ชฌ. ์ ์ ์กฐ๊ฑด ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๊ฐ ํ์ํ๊ณ , kubectl ์ปค๋งจ๋-๋ผ์ธ ํด์ด ํด๋ฌ์คํฐ์
ํต์ ํ ์ ์๋๋ก ์ค์ ๋์ด ์์ด์ผ ํ๋ค. ์ด ํํ ๋ฆฌ์ผ์ ์ปจํธ๋กค ํ๋ ์ธ ํธ์คํธ๊ฐ ์๋ ๋
ธ๋๊ฐ ์ ์ด๋ 2๊ฐ ํฌํจ๋ ํด๋ฌ์คํฐ์์ ์คํํ๋ ๊ฒ์ ์ถ์ฒํ๋ค. ๋ง์ฝ, ์์ง ํด๋ฌ์คํฐ๋ฅผ ๊ฐ์ง๊ณ
์์ง ์๋ค๋ฉด,
minikube ๋ฅผ ์ฌ์ฉํด์ ์์ฑํ๊ฑฐ๋
๋ค์ ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ์ด๊ทธ๋ผ์ด๋ ์ค ํ๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ด ์์๋ HTTP ํค๋๋ก ์์ ํ ์์ฒญ์ ์์ค IP ์ฃผ์๋ฅผ ํ์ ํ๋
์์ nginx ์น ์๋ฒ๋ฅผ ์ด์ฉํ๋ค. ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์๋ค.
kubectl create deployment source-ip-app --image= registry.k8s.io/echoserver:1.10
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
deployment.apps/source-ip-app created
๋ชฉ์ ๊ฐ๋จํ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ค์ํ ์๋น์ค ์ข
๋ฅ๋ก ๋
ธ์ถํ๊ธฐ ๊ฐ ์๋น์ค ์ ํ์ ๋ฐ๋ฅธ ์์ค IP NAT ์ ๋์ ์ดํดํ๊ธฐ ์์ค IP ์ฃผ์ ๋ณด์กด์ ๊ดํ ์ ์ถฉ ์ฌํญ ์ดํด Type=ClusterIP
์ธ ์๋น์ค์์ ์์ค IPiptables ๋ชจ๋
(๊ธฐ๋ณธ๊ฐ)์์ kube-proxy๋ฅผ ์ด์ํ๋ ๊ฒฝ์ฐ ํด๋ฌ์คํฐ ๋ด์์
ํด๋ฌ์คํฐIP๋ก ํจํท์ ๋ณด๋ด๋ฉด
์์ค NAT๋ฅผ ํต๊ณผํ์ง ์๋๋ค. kube-proxy๊ฐ ์คํ์ค์ธ ๋
ธ๋์์
http://localhost:10249/proxyMode
๋ฅผ ์
๋ ฅํด์ kube-proxy ๋ชจ๋๋ฅผ ์กฐํํ ์ ์๋ค.
์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
NAME STATUS ROLES AGE VERSION
kubernetes-node-6jst Ready <none> 2h v1.13.0
kubernetes-node-cx31 Ready <none> 2h v1.13.0
kubernetes-node-jj1t Ready <none> 2h v1.13.0
ํ ๋
ธ๋์ ํ๋ก์ ๋ชจ๋๋ฅผ ํ์ธํ๋ค. (kube-proxy๋ ํฌํธ 10249์์ ์์ ๋๊ธฐํ๋ค.)
# ์ง์ ํ ๋
ธ๋์ ์์์ ์ด๊ฒ์ ์คํํ๋ค.
curl localhost:10249/proxyMode
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
iptables
์์ค IP ์ ํ๋ฆฌ์ผ์ด์
์ ํตํด ์๋น์ค๋ฅผ ์์ฑํ์ฌ ์์ค IP ์ฃผ์ ๋ณด์กด ์ฌ๋ถ๋ฅผ ํ
์คํธํ ์ ์๋ค.
kubectl expose deployment source-ip-app --name= clusterip --port= 80 --target-port= 8080
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
service/clusterip exposed
kubectl get svc clusterip
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
clusterip ClusterIP 10.0.170.92 <none> 80/TCP 51s
๊ทธ๋ฆฌ๊ณ ๋์ผํ ํด๋ฌ์คํฐ์ ํ๋์์ ํด๋ฌ์คํฐIP
๋ฅผ ์น๋ฉด:
kubectl run busybox -it --image= busybox:1.28 --restart= Never --rm
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
Waiting for pod default/busybox to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.
๊ทธ๋ฐ ๋ค์ ํด๋น ํ๋ ๋ด์์ ๋ช
๋ น์ ์คํํ ์ ์๋ค.
# "kubectl run" ์ผ๋ก ํฐ๋ฏธ๋ ๋ด์์ ์ด๊ฒ์ ์คํํ๋ค.
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue
link/ether 0a:58:0a:f4:03:08 brd ff:ff:ff:ff:ff:ff
inet 10.244.3.8/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::188a:84ff:feb0:26a5/64 scope link
valid_lft forever preferred_lft forever
๊ทธ๋ฐ ๋ค์ wget
์ ์ฌ์ฉํด์ ๋ก์ปฌ ์น ์๋ฒ์ ์ฟผ๋ฆฌํ๋ค.
# "10.0.170.92"๋ฅผ "clusterip"๋ผ๋ ์ด๋ฆ์ ์๋น์ค์ IPv4 ์ฃผ์๋ก ๋ณ๊ฒฝํ๋ค.
wget -qO - 10.0.170.92
CLIENT VALUES:
client_address=10.244.3.8
command=GET
...
client_address
๋ ํด๋ผ์ด์ธํธ ํ๋์ ์๋ฒ ํ๋๊ฐ ๊ฐ์ ๋
ธ๋ ๋๋ ๋ค๋ฅธ ๋
ธ๋์ ์๋์ง ์ฌ๋ถ์ ๊ด๊ณ์์ด ํญ์ ํด๋ผ์ด์ธํธ ํ๋์ IP ์ฃผ์์ด๋ค.
Type=NodePort
์ธ ์๋น์ค์์ ์์ค IPType=NodePort
์ธ
์๋น์ค๋ก ๋ณด๋ด์ง ํจํท์
์์ค NAT๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ ์ฉ๋๋ค. NodePort
์๋น์ค๋ฅผ ์์ฑํ์ฌ ์ด๊ฒ์ ํ
์คํธํ ์ ์๋ค.
kubectl expose deployment source-ip-app --name= nodeport --port= 80 --target-port= 8080 --type= NodePort
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
service/nodeport exposed
NODEPORT = $( kubectl get -o jsonpath = "{.spec.ports[0].nodePort}" services nodeport)
NODES = $( kubectl get nodes -o jsonpath = '{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }' )
ํด๋ผ์ฐ๋ ๊ณต๊ธ์ ์์์ ์คํํ๋ค๋ฉด,
์์ ๋ณด๊ณ ๋ nodes:nodeport
๋ฅผ ์ํ ๋ฐฉํ๋ฒฝ ๊ท์น์ ์ด์ด์ฃผ์ด์ผ ํ๋ค.
์ด์ ์์ ๋
ธ๋ ํฌํธ๋ก ํ ๋น๋ฐ์ ํฌํธ๋ฅผ ํตํด ํด๋ฌ์คํฐ ์ธ๋ถ์์
์๋น์ค์ ๋๋ฌํ ์ ์๋ค.
for node in $NODES ; do curl -s $node :$NODEPORT | grep -i client_address; done
์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
client_address=10.180.1.1
client_address=10.240.0.5
client_address=10.240.0.3
๋ช
์ฌํ ๊ฒ์ ์ ํํ ํด๋ผ์ด์ธํธ IP ์ฃผ์๊ฐ ์๋๊ณ , ํด๋ฌ์คํฐ ๋ด๋ถ IP ์ฃผ์์ด๋ค. ์ ์ด๋ฐ ์ผ์ด ๋ฐ์ํ๋์ง ์ค๋ช
ํ๋ค.
ํด๋ผ์ด์ธํธ๋ node2:nodePort
๋ก ํจํท์ ๋ณด๋ธ๋ค. node2
๋ ์์ค IP ์ฃผ์(SNAT)๋ฅผ ํจํท ์์์ ์์ ์ IP ์ฃผ์๋ก ๊ต์ฒดํ๋ค.noee2
๋ ๋์ IP๋ฅผ ํจํท ์์์ ํ๋์ IP๋ก ๊ต์ฒดํ๋ค.ํจํท์ node 1๋ก ๋ผ์ฐํ
๋ ๋ค์ ์๋ํฌ์ธํธ๋ก ๋ผ์ฐํ
๋๋ค. ํ๋์ ์๋ต์ node2๋ก ๋ค์ ๋ผ์ฐํ
๋๋ค. ํ๋์ ์๋ต์ ํด๋ผ์ด์ธํธ๋ก ๋ค์ ์ ์ก๋๋ค. ์ด๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๊ทธ๋ฆผ. Source IP Type=NodePort using SNAT
์ด๋ฅผ ํผํ๊ธฐ ์ํด ์ฟ ๋ฒ๋คํฐ์ค๋
ํด๋ผ์ด์ธํธ ์์ค IP ์ฃผ์๋ฅผ ๋ณด์กด ํ๋ ๊ธฐ๋ฅ์ด ์๋ค.
service.spec.externalTrafficPolicy
์ ๊ฐ์ Local
๋ก ํ๋ฉด
์ค์ง ๋ก์ปฌ ์๋ํฌ์ธํธ๋ก๋ง ํ๋ก์ ์์ฒญํ๊ณ
๋ค๋ฅธ ๋
ธ๋๋ก ํธ๋ํฝ ์ ๋ฌํ์ง ์๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์๋ณธ
์์ค IP ์ฃผ์๋ฅผ ๋ณด์กดํ๋ค. ๋ง์ฝ ๋ก์ปฌ ์๋ ํฌ์ธํธ๊ฐ ์๋ค๋ฉด,
๊ทธ ๋
ธ๋๋ก ๋ณด๋ด์ง ํจํท์ ๋ฒ๋ ค์ง๋ฏ๋ก
ํจํท ์ฒ๋ฆฌ ๊ท์น์์ ์ ํํ ์์ค IP ์์ ์ ๋ขฐํ ์ ์์ผ๋ฏ๋ก,
ํจํท์ ์๋ํฌ์ธํธ๊น์ง ์ ๋ฌํ ์ ์๋ค.
๋ค์๊ณผ ๊ฐ์ด service.spec.externalTrafficPolicy
ํ๋๋ฅผ ์ค์ ํ์.
kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}'
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
service/nodeport patched
์ด์ ๋ค์ ํ
์คํธ๋ฅผ ์คํํด๋ณด์.
for node in $NODES ; do curl --connect-timeout 1 -s $node :$NODEPORT | grep -i client_address; done
์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
client_address=104.132.1.79
์๋ํฌ์ธํธ ํ๋๊ฐ ์คํ ์ค์ธ ๋
ธ๋์์ ์ฌ๋ฐ๋ฅธ ํด๋ผ์ด์ธํธ IP ์ฃผ์์ธ
๋ฑ ํ ์ข
๋ฅ์ ์๋ต๋ง ์์ ํ๋ค.
์ด๋ป๊ฒ ์ด๋ ๊ฒ ๋์๋๊ฐ:
ํด๋ผ์ด์ธํธ๋ ํจํท์ ์๋ํฌ์ธํธ๊ฐ ์๋ node2:nodePort
๋ณด๋ธ๋ค. ํจํท์ ๋ฒ๋ ค์ง๋ค. ํด๋ผ์ด์ธํธ๋ ํจํท์ ์๋ํฌ์ธํธ๋ฅผ ๊ฐ์ง node1:nodePort
๋ณด๋ธ๋ค. node1์ ํจํท์ ์ฌ๋ฐ๋ฅธ ์์ค IP ์ฃผ์๋ก ์๋ํฌ์ธํธ๋ก ๋ผ์ฐํ
ํ๋ค. ์ด๋ฅผ ์๊ฐ์ ์ผ๋ก ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๊ทธ๋ฆผ. Source IP Type=NodePort preserves client source IP address
Type=LoadBalancer
์ธ ์๋น์ค์์ ์์ค IPType=LoadBalancer
์ธ
์๋น์ค๋ก ๋ณด๋ธ ํจํท์ ์์ค NAT๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ํ๋๋ฐ, Ready
์ํ๋ก
๋ชจ๋ ์ค์ผ์ค๋ ๋ชจ๋ ์ฟ ๋ฒ๋คํฐ์ค ๋
ธ๋๋
๋ก๋ ๋ฐธ๋ฐ์ฑ ํธ๋ํฝ์ ์ ํฉํ๋ค. ๋ฐ๋ผ์ ์๋ํฌ์ธํธ๊ฐ ์๋ ๋
ธ๋์
ํจํท์ด ๋์ฐฉํ๋ฉด ์์คํ
์ ์๋ํฌ์ธํธ๋ฅผ ํฌํจํ ๋
ธ๋์ ํ๋ก์๋ฅผ
์ํํ๊ณ ํจํท ์์์ ๋
ธ๋์ IP ์ฃผ์๋ก ์์ค IP ์ฃผ์๋ฅผ ๋ณ๊ฒฝํ๋ค
(์ด์ ์น์
์์ ๊ธฐ์ ํ ๊ฒ์ฒ๋ผ).
๋ก๋๋ฐธ๋ฐ์๋ฅผ ํตํด source-ip-app์ ๋
ธ์ถํ์ฌ ํ
์คํธํ ์ ์๋ค.
kubectl expose deployment source-ip-app --name= loadbalancer --port= 80 --target-port= 8080 --type= LoadBalancer
์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ๋ค.
service/loadbalancer exposed
์๋น์ค์ IP ์ฃผ์๋ฅผ ์ถ๋ ฅํ๋ค.
kubectl get svc loadbalancer
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loadbalancer LoadBalancer 10.0.65.118 203.0.113.140 80/TCP 5m
๋ค์์ผ๋ก ์ด ์๋น์ค์ ์ธ๋ถ IP์ ์์ฒญ์ ์ ์กํ๋ค.
๋ค์๊ณผ ์ ์ฌํ๊ฒ ์ถ๋ ฅ๋๋ค.
CLIENT VALUES:
client_address=10.240.0.5
...
๊ทธ๋ฌ๋ ๊ตฌ๊ธ ํด๋ผ์ฐ๋ ์์ง/GCE ์์ ์คํ ์ค์ด๋ผ๋ฉด ๋์ผํ service.spec.externalTrafficPolicy
ํ๋๋ฅผ Local
๋ก ์ค์ ํ๋ฉด
์๋น์ค ์๋ํฌ์ธํธ๊ฐ ์๋ ๋
ธ๋๋ ๊ณ ์๋ก ํฌ์ค ์ฒดํฌ์ ์คํจํ์ฌ
๊ฐ์ ๋ก ๋ก๋๋ฐธ๋ฐ์ฑ ํธ๋ํฝ์ ๋ฐ์ ์ ์๋ ๋
ธ๋ ๋ชฉ๋ก์์
์์ ์ ์ค์ค๋ก ์ ๊ฑฐํ๋ค.
์ด๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ด๊ฒ์ ์ด๋
ธํ
์ด์
์ ์ค์ ํ์ฌ ํ
์คํธํ ์ ์๋ค.
kubectl patch svc loadbalancer -p '{"spec":{"externalTrafficPolicy":"Local"}}'
์ฟ ๋ฒ๋คํฐ์ค์ ์ํด service.spec.healthCheckNodePort
ํ๋๊ฐ
์ฆ๊ฐ์ ์ผ๋ก ํ ๋น๋๋ ๊ฒ์ ๋ด์ผ ํ๋ค.
kubectl get svc loadbalancer -o yaml | grep -i healthCheckNodePort
์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
healthCheckNodePort : 32122
service.spec.healthCheckNodePort
ํ๋๋ /healthz
์์ ํฌ์ค ์ฒดํฌ๋ฅผ ์ ๊ณตํ๋
๋ชจ๋ ๋
ธ๋์ ํฌํธ๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ์ด๊ฒ์ ํ
์คํธํ ์ ์๋ค.
kubectl get pod -o wide -l app = source-ip-app
์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
NAME READY STATUS RESTARTS AGE IP NODE
source-ip-app-826191075-qehz4 1/1 Running 0 20h 10.180.1.136 kubernetes-node-6jst
๋ค์ํ ๋
ธ๋์์ /healthz
์๋ํฌ์ธํธ๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด curl
์ ์ฌ์ฉํ๋ค.
# ์ ํํ ๋
ธ๋์์ ๋ก์ปฌ๋ก ์ด๊ฒ์ ์คํํ๋ค.
curl localhost:32122/healthz
1 Service Endpoints found
๋ค๋ฅธ ๋
ธ๋์์๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
# ์ ํํ ๋
ธ๋์์ ๋ก์ปฌ๋ก ์ด๊ฒ์ ์คํํ๋ค.
curl localhost:32122/healthz
No Service Endpoints Found
์ปจํธ๋กค ํ๋ ์ธ ์์
์คํ์ค์ธ ์ปจํธ๋กค๋ฌ๋ ํด๋ผ์ฐ๋ ๋ก๋ ๋ฐธ๋ฐ์๋ฅผ ํ ๋นํ๋ค. ๋ํ ๊ฐ์ ์ปจํธ๋กค๋ฌ๋
๊ฐ ๋
ธ๋์์ ํฌํธ/๊ฒฝ๋ก(port/path)๋ฅผ ๊ฐ๋ฅดํค๋ HTTP ์ํ ํ์ธ๋ ํ ๋นํ๋ค.
์๋ํฌ์ธํธ๊ฐ ์๋ 2๊ฐ์ ๋
ธ๋๊ฐ ์ํ ํ์ธ์ ์คํจํ
๋๊น์ง ์ฝ 10์ด๊ฐ ๋๊ธฐํ ๋ค์,
curl
์ ์ฌ์ฉํด์ ๋ก๋๋ฐธ๋ฐ์์ IPv4 ์ฃผ์๋ฅผ ์ฟผ๋ฆฌํ๋ค.
์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํ๋ค.
CLIENT VALUES:
client_address=198.51.100.79
...
ํฌ๋ก์ค-ํ๋ซํผ ์ง์ ์ผ๋ถ ํด๋ผ์ฐ๋ ๊ณต๊ธ์๋ง Type=LoadBalancer
๋ฅผ ์ฌ์ฉํ๋
์๋น์ค๋ฅผ ํตํด ์์ค IP ๋ณด์กด์ ์ง์ํ๋ค.
์คํ ์ค์ธ ํด๋ผ์ฐ๋ ๊ณต๊ธ์์์ ๋ช ๊ฐ์ง ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก
๋ก๋๋ฐธ๋ฐ์๋ฅผ ์์ฒญํ๋ค.
ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ์ ์ข
๋ฃํ๊ณ ์ ์ฐ๊ฒฐ์ ์ฌ๋ ํ๋ก์๋ฅผ ์ด์ฉํ๋ค.
์ด ๊ฒฝ์ฐ ์์ค IP ์ฃผ์๋ ํด๋ผ์ด์ธํธ IP ์ฃผ์๊ฐ ์๋๊ณ
ํญ์ ํด๋ผ์ฐ๋ ๋ก๋๋ฐธ๋ฐ์์ IP ์ฃผ์์ด๋ค.
๋ก๋๋ฐธ๋ฐ์์ VIP์ ์ ๋ฌ๋ ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ธ ์์ฒญ์
์ค๊ฐ ํ๋ก์๊ฐ ์๋ ํด๋ผ์ด์ธํธ ์์ค IP ์ฃผ์๊ฐ ์๋ ๋
ธ๋๋ก
๋๋๋ ํจํท ์ ๋ฌ์๋ฅผ ์ด์ฉํ๋ค.
์ฒซ ๋ฒ์งธ ๋ฒ์ฃผ์ ๋ก๋๋ฐธ๋ฐ์๋ ์ง์ง ํด๋ผ์ด์ธํธ IP๋ฅผ ํต์ ํ๊ธฐ ์ํด
HTTP Forwarded
๋๋ X-FORWARDED-FOR
ํค๋ ๋๋
ํ๋ก์ ํ๋กํ ์ฝ ๊ณผ
๊ฐ์ ๋ก๋๋ฐธ๋ฐ์์ ๋ฐฑ์๋ ๊ฐ์ ํฉ์๋ ํ๋กํ ์ฝ์ ์ฌ์ฉํด์ผ ํ๋ค.
๋ ๋ฒ์งธ ๋ฒ์ฃผ์ ๋ก๋๋ฐธ๋ฐ์๋ ์๋น์ค์ service.spec.healthCheckNodePort
ํ๋์ ์ ์ฅ๋ ํฌํธ๋ฅผ ๊ฐ๋ฅดํค๋
HTTP ํฌ์ค ์ฒดํฌ๋ฅผ ์์ฑํ์ฌ
์์์ ์ค๋ช
ํ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋ค.
์ ๋ฆฌํ๊ธฐ ์๋น์ค๋ฅผ ์ญ์ ํ๋ค.
kubectl delete svc -l app = source-ip-app
๋ํ๋ก์ด๋จผํธ, ๋ ํ๋ฆฌ์นด์
๊ทธ๋ฆฌ๊ณ ํ๋๋ฅผ ์ญ์ ํ๋ค.
kubectl delete deployment source-ip-app
๋ค์ ๋ด์ฉ