๊ธฐ์ฌ์ ๋ฒ์ญ์ ๊ณผ์ ์์ ์ ๋ ์ ์ค๋น๋์์ต๋๋ค.
Kubernetes๋ก ์์
ํ ๋ ํด๋ผ์ฐ๋ ๋น์ฉ์ ์ ์ฝํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์
๋๊น? ๋จ ํ๋์ ์ฌ๋ฐ๋ฅธ ์๋ฃจ์
์ ์์ง๋ง ์ด ๋ฌธ์์์๋ ๋ฆฌ์์ค๋ฅผ ๋ณด๋ค ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ํด๋ผ์ฐ๋ ์ปดํจํ
๋น์ฉ์ ์ค์ด๋ ๋ฐ ๋์์ด ๋๋ ์ฌ๋ฌ ๋๊ตฌ์ ๋ํด ์ค๋ช
ํฉ๋๋ค.
์ ๋ AWS์ฉ Kubernetes๋ฅผ ์ผ๋์ ๋๊ณ ์ด ๊ธฐ์ฌ๋ฅผ ์์ฑํ์ง๋ง ๋ค๋ฅธ ํด๋ผ์ฐ๋ ์ ๊ณต์
์ฒด์๋ ๊ฑฐ์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ ์ฉ๋ฉ๋๋ค. ๊ทํ์ ํด๋ฌ์คํฐ์ ์ด๋ฏธ ์๋ ํ์ฅ์ด ๊ตฌ์ฑ๋์ด ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค(
์ด ๋ฌธ์์์๋ ๋ค์์ ๋ค๋ฃน๋๋ค.
- ์ฌ์ฉํ์ง ์๋ ๋ฆฌ์์ค ์ ๋ฆฌ(
์ฟ ๋ฒ ๊ด๋ฆฌ์ธ ) - ๊ทผ๋ฌด ์ธ ์๊ฐ์๋ ์ค์ผ์ผ๋ง์ ์ค์
๋๋ค(
ํ๋ธ ๋ค์ด์ค์ผ์ผ๋ฌ ) - ์ํ ์๋ ํ์ฅ(HPA) ์ฌ์ฉ
- ๊ณผ๋ํ ์์ ์์ฝ ๊ฐ์ (
kube-๋ฆฌ์์ค-๋ณด๊ณ ์ , VPA) - ์คํ ์ธ์คํด์ค ์ฌ์ฉ
์ฌ์ฉํ์ง ์๋ ๋ฆฌ์์ค ์ ๋ฆฌ
๋น ๋ฅด๊ฒ ๋ณํํ๋ ํ๊ฒฝ์์ ์ผํ๋ ๊ฒ์ ์ข์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ธฐ์ ์กฐ์ง์ ์ํฉ๋๋ค
(ํค๋ ์ ์ด์ฝฅ์ค:
์ง์:
(์ธ์ฉ๋ฌธ) ์ฝ๋ฆฌ ํธ:
์คํด: AWS ๊ณ์ ์ ๋ณด์ ํ ์ฌ์ฉ์ ์์ ๋ฐ๋ผ ๊ฒฐ์ ๋ฉ๋๋ค.
์ฌ์ค: AWS ์ ์๋ ๋ณด์ ํ ์์ง๋์ด ์์ ๋ฐ๋ผ ๊ฒฐ์ ๋ฉ๋๋ค.
Ivan Kurnosov (๋๋ต):
์ค์ ์ฌ์ค: AWS ์ ์๋ ๋นํ์ฑํ/์ญ์ ํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆฐ ํญ๋ชฉ ์์ ํจ์์
๋๋ค.)
- ํด๋ฌ์คํฐ ์ ์ฒด ๊ท์น์ PR/ํ ์คํธ ๋ฐฐํฌ์ ๋ํ ์ต๋ TTL(Time-to-Live)์ ์ ์ํ ์ ์์ต๋๋ค.
- ์๋ฅผ ๋ค์ด 7์ผ ํ์ ์คํ์ดํฌ/ํ๋กํ ํ์ ์ ์๋์ผ๋ก ์ ๊ฑฐํ๋๋ก ๊ฐ๋ณ ๋ฆฌ์์ค์ janitor/ttl๋ก ์ฃผ์์ ๋ฌ ์ ์์ต๋๋ค.
์ผ๋ฐ ๊ท์น์ YAML ํ์ผ์ ์ ์๋์ด ์์ต๋๋ค. ํด๋น ๊ฒฝ๋ก๋ ๋งค๊ฐ๋ณ์๋ฅผ ํตํด ์ ๋ฌ๋ฉ๋๋ค. --rules-file
kube-janitor์์. ๋ค์์ ๋ชจ๋ ๋ค์์คํ์ด์ค๋ฅผ ์ ๊ฑฐํ๋ ์์ ๊ท์น์
๋๋ค. -pr-
์ดํ ํ ์ด๋ฆ์ผ๋ก:
- id: cleanup-resources-from-pull-requests
resources:
- namespaces
jmespath: "contains(metadata.name, '-pr-')"
ttl: 2d
๋ค์ ์์์๋ 2020๋ ์ ๋ชจ๋ ์๋ก์ด ๋ฐฐํฌ/StatefulSet์ ๋ํ ๋ฐฐํฌ ๋ฐ StatefulSet ํฌ๋์ ์ ํ๋ฆฌ์ผ์ด์ ๋ผ๋ฒจ ์ฌ์ฉ์ ๊ท์ ํ์ง๋ง ๋์์ ์ผ์ฃผ์ผ ๋์ ์ด ๋ผ๋ฒจ ์์ด ํ ์คํธ๋ฅผ ์คํํ ์ ์๋๋ก ํ์ฉํฉ๋๋ค.
- id: require-application-label
# ัะดะฐะปะธัั deployments ะธ statefulsets ะฑะตะท ะผะตัะบะธ "application"
resources:
- deployments
- statefulsets
# ัะผ. http://jmespath.org/specification.html
jmespath: "!(spec.template.metadata.labels.application) && metadata.creationTimestamp > '2020-01-01'"
ttl: 7d
kube-janitor๋ฅผ ์คํํ๋ ํด๋ฌ์คํฐ์์ 30๋ถ ๋์ ์๊ฐ ์ ํ์ด ์๋ ๋ฐ๋ชจ๋ฅผ ์คํํฉ๋๋ค.
kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30m
๋น์ฉ ์ฆ๊ฐ์ ๋ ๋ค๋ฅธ ์์ธ์ ์๊ตฌ ๋ณผ๋ฅจ(AWS EBS)์ ๋๋ค. Kubernetes StatefulSet๋ฅผ ์ญ์ ํด๋ ํด๋น ์๊ตฌ ๋ณผ๋ฅจ(PVC - PertantVolumeClaim)์ ์ญ์ ๋์ง ์์ต๋๋ค. ์ฌ์ฉ๋์ง ์์ EBS ๋ณผ๋ฅจ์ผ๋ก ์ธํด ๋งค์ ์๋ฐฑ ๋ฌ๋ฌ์ ๋น์ฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค. Kubernetes Janitor์๋ ์ฌ์ฉํ์ง ์๋ PVC๋ฅผ ์ ๋ฆฌํ๋ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ด ๊ท์น์ ๋ชจ๋์ ์ํด ๋ง์ดํธ๋์ง ์๊ณ StatefulSet ๋๋ CronJob์ ์ํด ์ฐธ์กฐ๋์ง ์๋ ๋ชจ๋ PVC๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
# ัะดะฐะปะธัั ะฒัะต PVC, ะบะพัะพััะต ะฝะต ัะผะพะฝัะธัะพะฒะฐะฝั ะธ ะฝะฐ ะบะพัะพััะต ะฝะต ัััะปะฐัััั StatefulSets
- id: remove-unused-pvcs
resources:
- persistentvolumeclaims
jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
ttl: 24h
Kubernetes Janitor๋ ํด๋ฌ์คํฐ๋ฅผ ๊น๋ํ๊ฒ ์ ์งํ๊ณ ํด๋ผ์ฐ๋ ์ปดํจํ
๋น์ฉ์ด ์ฒ์ฒํ ์ฆ๊ฐํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ ์ค ์ ์์ต๋๋ค. ๋ฐฐํฌ ๋ฐ ๊ตฌ์ฑ ์ง์นจ์ ๋ค์์ ๋ฐ๋ฅด์ธ์.
๊ทผ๋ฌด ์ธ ์๊ฐ์๋ ์ค์ผ์ผ๋ง์ ์ค์ ๋๋ค.
ํ ์คํธ ๋ฐ ์คํ ์ด์ง ์์คํ ์ ์ผ๋ฐ์ ์ผ๋ก ์ ๋ฌด ์๊ฐ ๋์์๋ง ์๋ํด์ผ ํฉ๋๋ค. ๋ฐฑ์คํผ์ค/๊ด๋ฆฌ ๋๊ตฌ์ ๊ฐ์ ์ผ๋ถ ํ๋ก๋์ ์ ํ๋ฆฌ์ผ์ด์ ๋ ์ ํ๋ ๊ฐ์ฉ์ฑ๋ง ํ์ํ๋ฉฐ ํ๋ฃป๋ฐค ์ฌ์ด์ ๋นํ์ฑํ๋ ์ ์์ต๋๋ค.
image: hjacobs/kube-downscaler:20.4.3
args:
- --interval=30
# ะฝะต ะพัะบะปััะฐัั ะบะพะผะฟะพะฝะตะฝัั ะธะฝััะฐััััะบัััั
- --exclude-namespaces=kube-system,infra
# ะฝะต ะพัะบะปััะฐัั kube-downscaler, ะฐ ัะฐะบะถะต ะพััะฐะฒะธัั Postgres Operator, ััะพะฑั ะธัะบะปััะตะฝะฝัะผะธ ะะ ะผะพะถะฝะพ ะฑัะปะพ ัะฟัะฐะฒะปััั
- --exclude-deployments=kube-downscaler,postgres-operator
- --default-uptime=Mon-Fri 08:00-20:00 Europe/Berlin
- --include-resources=deployments,statefulsets,stacks,cronjobs
- --deployment-time-annotation=deployment-time
๋ค์์ ์ฃผ๋ง์ ํด๋ฌ์คํฐ ์์ ์ ๋ ธ๋๋ฅผ ํ์ฅํ๋ ๊ทธ๋ํ์ ๋๋ค.
~13๊ฐ์์ 4๊ฐ์ ์์
์ ๋
ธ๋๋ก ์ถ์ํ๋ฉด ํ์คํ AWS ์ฒญ๊ตฌ์์ ๋์ ๋๋ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
ํ์ง๋ง ํด๋ฌ์คํฐ "๋ค์ดํ์" ๋์ ์์
ํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น? downscaler/exclude: true ์ฃผ์์ ์ถ๊ฐํ์ฌ ํน์ ๋ฐฐํฌ๋ฅผ ํ์ฅ์์ ์๊ตฌ์ ์ผ๋ก ์ ์ธํ ์ ์์ต๋๋ค. YYYY-MM-DD HH:MM(UTC) ํ์์ ์ ๋ ํ์์คํฌํ๊ฐ ์๋ downscaler/exclude-until ์ฃผ์์ ์ฌ์ฉํ์ฌ ๋ฐฐํฌ๋ฅผ ์ผ์์ ์ผ๋ก ์ ์ธํ ์ ์์ต๋๋ค. ํ์ํ ๊ฒฝ์ฐ ์ฃผ์์ด ํฌํจ๋ ํฌ๋๋ฅผ ๋ฐฐํฌํ์ฌ ์ ์ฒด ํด๋ฌ์คํฐ๋ฅผ ์ถ์ํ ์ ์์ต๋๋ค. downscaler/force-uptime
์๋ฅผ ๋ค์ด nginx ๊ณต๋ฐฑ์ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
kubectl run scale-up --image=nginx
kubectl annotate deploy scale-up janitor/ttl=1h # ัะดะฐะปะธัั ัะฐะทะฒะตัััะฒะฐะฝะธะต ัะตัะตะท ัะฐั
kubectl annotate pod $(kubectl get pod -l run=scale-up -o jsonpath="{.items[0].metadata.name}") downscaler/force-uptime=true
์ฐธ์กฐ
์ํ ์๋ ํ์ฅ ์ฌ์ฉ
๋ง์ ์ ํ๋ฆฌ์ผ์ด์
/์๋น์ค๋ ๋์ ๋ก๋ฉ ํจํด์ ์ฒ๋ฆฌํฉ๋๋ค. ๋๋ก๋ ๋ชจ๋์ด ์ ํด ์ํ์ด๊ณ ๋๋ก๋ ์ ์ฒด ์ฉ๋์ผ๋ก ์๋ํฉ๋๋ค. ์ต๋ ํผํฌ ๋ถํ์ ๋์ฒํ๊ธฐ ์ํด ์๊ตฌ์ ์ธ ํฌ๋ ์ ํ๊ตฐ์ ์ด์ํ๋ ๊ฒ์ ๊ฒฝ์ ์ ์ด์ง ์์ต๋๋ค. Kubernetes๋ ๋ฆฌ์์ค ์ ๋ฐ์ ๊ฑธ์ณ ์ํ ์๋ ํฌ๊ธฐ ์กฐ์ ์ ์ง์ํฉ๋๋ค.
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: my-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
averageUtilization: 100
type: Utilization
Zalando๋ ํ์ฅ์ ์ํด ์ฌ์ฉ์ ์ ์ ์งํ๋ฅผ ์ฝ๊ฒ ์ฐ๊ฒฐํ ์ ์๋ ๊ตฌ์ฑ ์์๋ฅผ ๋ง๋ค์์ต๋๋ค.
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
annotations:
# metric-config.<metricType>.<metricName>.<collectorName>/<configKey>
metric-config.pods.requests-per-second.json-path/json-key: "$.http_server.rps"
metric-config.pods.requests-per-second.json-path/path: /metrics
metric-config.pods.requests-per-second.json-path/port: "9090"
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 1
maxReplicas: 10
metrics:
- type: Pods
pods:
metric:
name: requests-per-second
target:
averageValue: 1k
type: AverageValue
HPA๋ฅผ ์ฌ์ฉํ ์ํ ์๋ ํ์ฅ ๊ตฌ์ฑ์ ์ํ ๋น์ ์ฅ ์๋น์ค์ ํจ์จ์ฑ์ ๋์ด๊ธฐ ์ํ ๊ธฐ๋ณธ ์์
์ค ํ๋์
๋๋ค. Spotify๋ HPA์ ๋ํ ๊ฒฝํ๊ณผ ๊ถ์ฅ ์ฌํญ์ ๋ด์ ํ๋ ์ ํ
์ด์
์ ์ ๊ณตํฉ๋๋ค.
๋ฆฌ์์ค ์ด๊ณผ ์์ฝ ๊ฐ์
Kubernetes ์ํฌ๋ก๋๋ "๋ฆฌ์์ค ์์ฒญ"์ ํตํด CPU/๋ฉ๋ชจ๋ฆฌ ์๊ตฌ ์ฌํญ์ ๊ฒฐ์ ํฉ๋๋ค. CPU ๋ฆฌ์์ค๋ ๊ฐ์ ์ฝ์ด ๋๋ ๋ณด๋ค ์ผ๋ฐ์ ์ผ๋ก "๋ฐ๋ฆฌ์ฝ์ด"๋ก ์ธก์ ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด 500m๋ 50% vCPU๋ฅผ ์๋ฏธํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋ฆฌ์์ค๋ ๋ฐ์ดํธ ๋จ์๋ก ์ธก์ ๋๋ฉฐ 500MB๋ฅผ ์๋ฏธํ๋ 500Mi์ ๊ฐ์ ์ผ๋ฐ์ ์ธ ์ ๋ฏธ์ฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ฆฌ์์ค๋ ์์
์ ๋
ธ๋์์ "์ ๊ธ" ์ฉ๋์ ์์ฒญํฉ๋๋ค. ์ฆ, vCPU๊ฐ 1000๊ฐ์ธ ๋
ธ๋์์ 4m CPU ์์ฒญ์ด ์๋ ํฌ๋๋ ๋ค๋ฅธ ํฌ๋์์ ์ฌ์ฉํ ์ ์๋ vCPU๋ฅผ 3๊ฐ๋ง ๋จ๊ฒจ๋ก๋๋ค.
Slack(์ด๊ณผ ์์ฝ) ์์ฒญ๋ ๋ฆฌ์์ค์ ์ค์ ์ฌ์ฉ๋์ ์ฐจ์ด์
๋๋ค. ์๋ฅผ ๋ค์ด 2GiB์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์์ฒญํ์ง๋ง 200MiB๋ง ์ฌ์ฉํ๋ ํฌ๋์๋ ~1,8GiB์ "์ด๊ณผ" ๋ฉ๋ชจ๋ฆฌ๊ฐ ์์ต๋๋ค. ์ด๊ณผ ๋น์ฉ์ด ๋ฐ์ํฉ๋๋ค. 1GiB์ ์ค๋ณต ๋ฉ๋ชจ๋ฆฌ ๋น์ฉ์ ๋๋ต ์ $10 ์ ๋๋ผ๊ณ ์ถ์ ํ ์ ์์ต๋๋ค.
CPU ์์ฒญ์ 3000m์์ ~400m๋ก ์ค์ด๋ฉด ๋ค๋ฅธ ์ํฌ๋ก๋๋ฅผ ์ํ ๋ฆฌ์์ค๊ฐ ํ๋ณด๋๊ณ ํด๋ฌ์คํฐ๊ฐ ๋ ์์์ง ์ ์์ต๋๋ค.
"EC2 ์ธ์คํด์ค์ ํ๊ท CPU ์ฌ์ฉ๋์ ํ ์๋ฆฟ์ ๋ฐฑ๋ถ์จ ๋ฒ์์ ๋จธ๋ฌด๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค."
ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ ๋ง๋ก ์ฌ๋๋ค์ด YAML ํ์ผ์ ๊ฐ์ ๋ณ๊ฒฝํ๊ธฐ๋ฅผ ์ํฉ๋๊น? ์๋์, ๊ธฐ๊ณ๊ฐ ํจ์ฌ ๋ ์ํ ์ ์์ต๋๋ค! ์ฟ ๋ฒ๋คํฐ์ค
์๊ฒ ์ผ์ด์
EC2 ์คํ ์ธ์คํด์ค ์ฌ์ฉ
๋ง์ง๋ง์ผ๋ก ์คํ ์ธ์คํด์ค๋ฅผ Kubernetes ์์
์ ๋
ธ๋๋ก ์ฌ์ฉํ๋ฉด AWS EC2 ๋น์ฉ์ ์ค์ผ ์ ์์ต๋๋ค.
EC2 Spot์์ Kubernetes๋ฅผ ์คํํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น? ์ฌ๋ฌ ๊ฐ์ง ์ต์ ์ด ์์ต๋๋ค. SpotInst(ํ์ฌ๋ "Spot"์ด๋ผ๊ณ ํจ. ์ด์ ๋ ๋ฌป์ง ๋ง์ธ์)์ ๊ฐ์ ํ์ฌ ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ASG(Spot AutoScalingGroup)๋ฅผ ํด๋ฌ์คํฐ์ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ค์์ ์ฌ๋ฌ ์ธ์คํด์ค ์ ํ์ด ์๋ "์ฉ๋ ์ต์ ํ" Spot ASG์ ๋ํ CloudFormation ์ฝ๋ ์กฐ๊ฐ์ ๋๋ค.
MySpotAutoScalingGroup:
Properties:
HealthCheckGracePeriod: 300
HealthCheckType: EC2
MixedInstancesPolicy:
InstancesDistribution:
OnDemandPercentageAboveBaseCapacity: 0
SpotAllocationStrategy: capacity-optimized
LaunchTemplate:
LaunchTemplateSpecification:
LaunchTemplateId: !Ref LaunchTemplate
Version: !GetAtt LaunchTemplate.LatestVersionNumber
Overrides:
- InstanceType: "m4.2xlarge"
- InstanceType: "m4.4xlarge"
- InstanceType: "m5.2xlarge"
- InstanceType: "m5.4xlarge"
- InstanceType: "r4.2xlarge"
- InstanceType: "r4.4xlarge"
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplate
Version: !GetAtt LaunchTemplate.LatestVersionNumber
MinSize: 0
MaxSize: 100
Tags:
- Key: k8s.io/cluster-autoscaler/node-template/label/aws.amazon.com/spot
PropagateAtLaunch: true
Value: "true"
Kubernetes์์ Spot ์ฌ์ฉ์ ๋ํ ๋ช ๊ฐ์ง ์ฐธ๊ณ ์ฌํญ:
- ์๋ฅผ ๋ค์ด ์ธ์คํด์ค๊ฐ ์ค์ง๋ ๋ ๋ ธ๋๋ฅผ ๋ณํฉํ์ฌ ์คํ ์ข ๋ฃ๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
- Zalando๋ ๋ค์์ ์ฌ์ฉํฉ๋๋ค.
ํฌํฌ ๋ ธ๋ ํ ์ฐ์ ์์์ ๋ฐ๋ฅธ ๊ณต์ ํด๋ฌ์คํฐ ์๋ ํ์ฅ - ์คํ ๋
ธ๋
๊ฐ์ ๋ก ํ ์ ์๋ค Spot์์ ์คํํ ์ํฌ๋ก๋์ "๋ฑ๋ก"์ ์๋ฝํฉ๋๋ค.
๊ฐ์
์ ์๋ ๋๊ตฌ ์ค ์ผ๋ถ๊ฐ ํด๋ผ์ฐ๋ ๋น์ฉ์ ์ค์ด๋ ๋ฐ ์ ์ฉํ๊ธธ ๋ฐ๋๋๋ค. ๊ธฐ์ฌ ๋ด์ฉ์ ๋๋ถ๋ถ์ ๋ค์์์๋ ์ฐพ์ ์ ์์ต๋๋ค.
Kubernetes์์ ํด๋ผ์ฐ๋ ๋น์ฉ์ ์ ์ฝํ๊ธฐ ์ํ ๋ชจ๋ฒ ์ฌ๋ก๋ ๋ฌด์์
๋๊น? ๋ค์ ์ฃผ์๋ก ์๋ ค์ฃผ์ธ์.
์ถ์ฒ : habr.com