ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

ืชืจื’ื•ื ื”ืžืืžืจ ื”ื•ื›ืŸ ืขืจื‘ ืชื—ื™ืœืช ื”ืงื•ืจืก "ืคืœื˜ืคื•ืจืžืช ืชืฉืชื™ืช ื”ืžื‘ื•ืกืกืช ืขืœ Kubernetes".

ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

ื›ื™ืฆื“ ืœื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ื‘ืขื‘ื•ื“ื” ืขื Kubernetes? ืื™ืŸ ืคืชืจื•ืŸ ืื—ื“ ื ื›ื•ืŸ, ืื‘ืœ ืžืืžืจ ื–ื” ืžืชืืจ ื›ืžื” ื›ืœื™ื ืฉื™ื›ื•ืœื™ื ืœืขื–ื•ืจ ืœืš ืœื ื”ืœ ืืช ื”ืžืฉืื‘ื™ื ืฉืœืš ื‘ืฆื•ืจื” ื™ืขื™ืœื” ื™ื•ืชืจ ื•ืœื”ืคื—ื™ืช ืืช ืขืœื•ื™ื•ืช ืžื—ืฉื•ื‘ ื”ืขื ืŸ ืฉืœืš.

ื›ืชื‘ืชื™ ืืช ื”ืžืืžืจ ื”ื–ื” ืขื Kubernetes ืขื‘ื•ืจ AWS ื‘ืจืืฉ, ืื‘ืœ ื”ื•ื ื™ื—ื•ืœ (ื›ืžืขื˜) ื‘ื“ื™ื•ืง ื‘ืื•ืชื” ืฆื•ืจื” ืขืœ ืกืคืงื™ ืขื ืŸ ืื—ืจื™ื. ืื ื™ ืžื ื™ื— ืœืืฉื›ื•ืœ/ื™ื ืฉืœืš ื›ื‘ืจ ืžื•ื’ื“ืจ ืงื ื” ืžื™ื“ื” ืื•ื˜ื•ืžื˜ื™ (cluster-autoscaler). ื”ืกืจืช ืžืฉืื‘ื™ื ื•ื”ืงื˜ื ืช ื”ืคืจื™ืกื” ืฉืœืš ืชื—ืกื•ืš ืœืš ื›ืกืฃ ืจืง ืื ื”ื™ื ื’ื ืชืคื—ื™ืช ืืช ืฆื™ ืฆืžืชื™ ื”ืขื•ื‘ื“ื™ื ืฉืœืš (ืžื•ืคืขื™ EC2).

ืžืืžืจ ื–ื” ื™ื›ืกื”:

  • ื ื™ืงื•ื™ ืžืฉืื‘ื™ื ืœื ื‘ืฉื™ืžื•ืฉ (ืงื•ื‘-ืฉืจืช)
  • ื”ืงื˜ื ืช ืงื ื” ื”ืžื™ื“ื” ื‘ืฉืขื•ืช ืฉืื™ื ืŸ ืขื•ื‘ื“ื•ืช (kube-downscaler)
  • ื‘ืืžืฆืขื•ืช ืงื ื” ืžื™ื“ื” ืื•ื˜ื•ืžื˜ื™ ืื•ืคืงื™ (HPA),
  • ื”ืคื—ืชืช ืฉืžื™ืจืช ืžืฉืื‘ื™ื ืžื•ื’ื–ืžืช (kube-resource-report, VPA)
  • ื‘ืืžืฆืขื•ืช ืžื•ืคืขื™ Spot

ื ื™ืงื•ื™ ืžืฉืื‘ื™ื ืฉืื™ื ื ื‘ืฉื™ืžื•ืฉ

ืขื‘ื•ื“ื” ื‘ืกื‘ื™ื‘ื” ืžื”ื™ืจื” ื–ื” ื ื”ื“ืจ. ืื ื—ื ื• ืจื•ืฆื™ื ืืจื’ื•ื ื™ื ื˜ื›ื ื•ืœื•ื’ื™ื™ื ืžื•ึผืึธืฅ. ืืกืคืงืช ืชื•ื›ื ื” ืžื”ื™ืจื” ื™ื•ืชืจ ืคื™ืจื•ืฉื” ื’ื ื™ื•ืชืจ ืคืจื™ืกื•ืช ื™ื—ืกื™ ืฆื™ื‘ื•ืจ, ืกื‘ื™ื‘ื•ืช ืชืฆื•ื’ื” ืžืงื“ื™ืžื”, ืื‘ื•ืช ื˜ื™ืคื•ืก ื•ืคืชืจื•ื ื•ืช ื ื™ืชื•ื—. ื”ื›ืœ ืคืจื•ืก ืขืœ Kubernetes. ืœืžื™ ื™ืฉ ื–ืžืŸ ืœื ืงื•ืช ื™ื“ื ื™ืช ืคืจื™ืกื•ืช ื‘ื“ื™ืงื”? ืงืœ ืœืฉื›ื•ื— ืžื—ื™ืงืช ื ื™ืกื•ื™ ื‘ืŸ ืฉื‘ื•ืข. ื—ืฉื‘ื•ืŸ ื”ืขื ืŸ ื™ืขืœื” ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ ื‘ื’ืœืœ ืžืฉื”ื• ืฉืฉื›ื—ื ื• ืœืกื’ื•ืจ:

ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

(ื”ื ื™ื ื’ ื’'ื™ื™ืงื•ื‘ืก:
ื–'ื™ื–ื”:
(ืฆื™ื˜ื•ื˜ื™ื) ืงื•ืจื™ ืงื•ื•ื™ืŸ:
ืžื™ืชื•ืก: ื—ืฉื‘ื•ืŸ AWS ืฉืœืš ื”ื•ื ืคื•ื ืงืฆื™ื” ืฉืœ ืžืกืคืจ ื”ืžืฉืชืžืฉื™ื ืฉื™ืฉ ืœืš.
ืขื•ื‘ื“ื”: ืฆื™ื•ืŸ ื”-AWS ืฉืœืš ื”ื•ื ืคื•ื ืงืฆื™ื” ืฉืœ ืžืกืคืจ ื”ืžื”ื ื“ืกื™ื ืฉื™ืฉ ืœืš.

ืื™ื•ื•ืŸ ืงื•ืจื ื•ืกื•ื‘ (ื‘ืชื’ื•ื‘ื”):
ืขื•ื‘ื“ื” ืืžื™ืชื™ืช: ืฆื™ื•ืŸ ื”-AWS ืฉืœืš ื”ื•ื ืคื•ื ืงืฆื™ื” ืฉืœ ืžืกืคืจ ื”ื“ื‘ืจื™ื ืฉืฉื›ื—ืช ืœื”ืฉื‘ื™ืช/ืœืžื—ื•ืง.)

ืงื•ื‘ืจื ื˜ืก ืฉื•ืขืจ (kube-janitor) ืขื•ื–ืจ ืœื ืงื•ืช ืืช ื”ืืฉื›ื•ืœ ืฉืœืš. ืชืฆื•ืจืช ื”ืฉื•ืขืจ ื’ืžื™ืฉื” ืœืฉื™ืžื•ืฉ ื’ืœื•ื‘ืœื™ ื•ืžืงื•ืžื™ ื›ืื—ื“:

  • ื›ืœืœื™ื ืจื—ื‘ื™ ืืฉื›ื•ืœ ื™ื›ื•ืœื™ื ืœื”ื’ื“ื™ืจ ืืช ื”ื–ืžืŸ ื”ืžืจื‘ื™ ืœื—ื™ื™ื (TTL) ืขื‘ื•ืจ ืคืจื™ืกื•ืช ื™ื—ืกื™ ืฆื™ื‘ื•ืจ/ื‘ื“ื™ืงื•ืช.
  • ื ื™ืชืŸ ืœื”ื•ืกื™ืฃ ื”ืขืจื•ืช ืœืžืฉืื‘ื™ื ื‘ื•ื“ื“ื™ื ื‘-janitor/ttl, ืœืžืฉืœ ื›ื“ื™ ืœื”ืกื™ืจ ืื•ื˜ื•ืžื˜ื™ืช ืืช ื”ืกืคื™ื™ืง/ืื‘-ื˜ื™ืคื•ืก ืœืื—ืจ 7 ื™ืžื™ื.

ื›ืœืœื™ื ื›ืœืœื™ื™ื ืžื•ื’ื“ืจื™ื ื‘ืงื•ื‘ืฅ YAML. ื”ื ืชื™ื‘ ืฉืœื• ืขื•ื‘ืจ ื“ืจืš ื”ืคืจืžื˜ืจ --rules-file ื‘-kube-janitor. ื”ื ื” ื›ืœืœ ืœื“ื•ื’ืžื” ืœื”ืกืจืช ื›ืœ ืžืจื—ื‘ื™ ื”ืฉืžื•ืช ืื™ืชื -pr- ื‘ืฉื ืœืื—ืจ ื™ื•ืžื™ื™ื:

- id: cleanup-resources-from-pull-requests
  resources:
    - namespaces
  jmespath: "contains(metadata.name, '-pr-')"
  ttl: 2d

ื”ื“ื•ื’ืžื” ื”ื‘ืื” ืžืกื“ื™ืจื” ืืช ื”ืฉื™ืžื•ืฉ ื‘ืชื•ื•ื™ืช ื”ืืคืœื™ืงืฆื™ื” ื‘ืชืจืžื™ืœื™ื ืฉืœ Deployment ื•-StatefulSet ืขื‘ื•ืจ ื›ืœ ื”ืคืจื™ืกื”/StatefulSets ื”ื—ื“ืฉื™ื ื‘ืฉื ืช 2020, ืืš ื‘ืžืงื‘ื™ืœ ืžืืคืฉืจืช ื‘ื™ืฆื•ืข ื‘ื“ื™ืงื•ืช ืœืœื ืชื•ื•ื™ืช ื–ื• ืœืžืฉืš ืฉื‘ื•ืข:

- 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

ื”ืคืขืœ ื”ื“ื’ืžื” ืžื•ื’ื‘ืœืช ื‘ื–ืžืŸ ืœืžืฉืš 30 ื“ืงื•ืช ื‘ืืฉื›ื•ืœ ื”ืคื•ืขืœ ืขืœ kube-janitor:

kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30m

ืžืงื•ืจ ื ื•ืกืฃ ืœื”ื’ื“ืœืช ื”ืขืœื•ื™ื•ืช ื”ื•ื ื ืคื—ื™ื ืžืชืžืฉื›ื™ื (AWS EBS). ืžื—ื™ืงืช Kubernetes StatefulSet ืื™ื ื” ืžื•ื—ืงืช ืืช ื”ื ืคื—ื™ื ื”ืงื‘ื•ืขื™ื ืฉืœื• (PVC - PersistentVolumeClaim). ื ืคื—ื™ EBS ืฉืื™ื ื ื‘ืฉื™ืžื•ืฉ ื™ื›ื•ืœื™ื ื‘ืงืœื•ืช ืœื’ืจื•ื ืœืขืœื•ื™ื•ืช ืฉืœ ืžืื•ืช ื“ื•ืœืจื™ื ืœื—ื•ื“ืฉ. ืœ-Kubernetes Janitor ื™ืฉ ืชื›ื•ื ื” ืœื ื™ืงื•ื™ PVC ืฉืื™ื ื ื‘ืฉื™ืžื•ืฉ. ืœื“ื•ื’ืžื”, ื›ืœืœ ื–ื” ื™ืกื™ืจ ืืช ื›ืœ ื”-PVC ืฉืœื ืžื•ืชืงื ื™ื ืขืœ ื™ื“ื™ ืžื•ื“ื•ืœ ื•ืฉืื™ื ื ืžื•ื–ื›ืจื™ื ืขืœ ื™ื“ื™ StatefulSet ืื• CronJob:

# ัƒะดะฐะปะธั‚ัŒ ะฒัะต PVC, ะบะพั‚ะพั€ั‹ะต ะฝะต ัะผะพะฝั‚ะธั€ะพะฒะฐะฝั‹ ะธ ะฝะฐ ะบะพั‚ะพั€ั‹ะต ะฝะต ััั‹ะปะฐัŽั‚ัั StatefulSets
- id: remove-unused-pvcs
  resources:
  - persistentvolumeclaims
  jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
  ttl: 24h

Kubernetes Janitor ื™ื›ื•ืœื” ืœืขื–ื•ืจ ืœืš ืœืฉืžื•ืจ ืขืœ ื”ืืฉื›ื•ืœ ืฉืœืš ื ืงื™ ื•ืœืžื ื•ืข ืขืœื•ื™ื•ืช ืžื—ืฉื•ื‘ ืขื ืŸ ืœื”ืฆื˜ื‘ืจ ืœืื˜. ืœืงื‘ืœืช ื”ื•ืจืื•ืช ืคืจื™ืกื” ื•ืชืฆื•ืจื”, ื‘ืฆืข README kube-janitor.

ื”ืงื˜ื ืช ืงื ื” ื”ืžื™ื“ื” ื‘ืฉืขื•ืช ืฉืื™ื ืŸ ืขื•ื‘ื“ื•ืช

ืžืขืจื›ื•ืช ื‘ื“ื™ืงื” ื•ื”ื™ืขืจื›ื•ืช ื ื“ืจืฉื•ืช ื‘ื“ืจืš ื›ืœืœ ืœืคืขื•ืœ ืจืง ื‘ืฉืขื•ืช ื”ืขื‘ื•ื“ื”. ื™ื™ืฉื•ืžื™ ื™ื™ืฆื•ืจ ืžืกื•ื™ืžื™ื, ื›ื’ื•ืŸ ื›ืœื™ back office/admin, ื“ื•ืจืฉื™ื ื’ื ื–ืžื™ื ื•ืช ืžื•ื’ื‘ืœืช ื‘ืœื‘ื“ ื•ื™ื™ืชื›ืŸ ืฉื”ื ืžื•ืฉื‘ืชื™ื ื‘ืŸ ืœื™ืœื”.

Kubernetes Downscaler (kube-downscaler) ืžืืคืฉืจ ืœืžืฉืชืžืฉื™ื ื•ืœืžืคืขื™ืœื™ื ืœื”ืงื˜ื™ืŸ ืืช ื”ืžืขืจื›ืช ื‘ืฉืขื•ืช ืฉืื™ื ืŸ ืคื•ืขืœื•ืช. ืคืจื™ืกื•ืช ื•-StatefulSets ื™ื›ื•ืœื•ืช ืœื”ืชืื™ื ืœืืคืก ื”ืขืชืงื™ื. CronJobs ืขืฉื•ื™ ืœื”ื™ื•ืช ืžื•ืฉืขื”. Kubernetes Downscaler ืžื•ื’ื“ืจ ืขื‘ื•ืจ ืืฉื›ื•ืœ ืฉืœื, ืžืจื—ื‘ ืฉืžื•ืช ืื—ื“ ืื• ื™ื•ืชืจ, ืื• ืžืฉืื‘ื™ื ื‘ื•ื“ื“ื™ื. ืืชื” ื™ื›ื•ืœ ืœื”ื’ื“ื™ืจ "ื–ืžืŸ ืกืจืง" ืื•, ืœื”ื™ืคืš, "ื–ืžืŸ ืขื‘ื•ื“ื”". ืœื“ื•ื’ืžื”, ื›ื“ื™ ืœืฆืžืฆื ืืช ืงื ื” ื”ืžื™ื“ื” ื›ื›ืœ ื”ืืคืฉืจ ื‘ืœื™ืœื•ืช ื•ื‘ืกื•ืคื™ ืฉื‘ื•ืข:

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

ืœื”ืœืŸ ื’ืจืฃ ืœืฉื™ื ื•ื™ ืงื ื” ืžื™ื“ื” ืฉืœ ืฆืžืชื™ ืขื•ื‘ื“ื™ ืืฉื›ื•ืœ ื‘ืกื•ืคื™ ืฉื‘ื•ืข:

ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

ื”ืงื˜ื ื” ืž-~13 ืœ-4 ืฆืžืชื™ื ืขื•ื‘ื“ื™ื ื‘ื”ื—ืœื˜ ืขื•ืฉื” ื”ื‘ื“ืœ ื ื™ื›ืจ ื‘ื—ืฉื‘ื•ืŸ ื”-AWS ืฉืœืš.

ืื‘ืœ ืžื” ืื ืื ื™ ืฆืจื™ืš ืœืขื‘ื•ื“ ื‘ืžื”ืœืš "ื–ืžืŸ ื”ืฉื‘ืชื”" ืฉืœ ืืฉื›ื•ืœ? ื ื™ืชืŸ ืœืžื ื•ืข ืœืฆืžื™ืชื•ืช ืคืจื™ืกื•ืช ืžืกื•ื™ืžื•ืช ืžืฉื™ื ื•ื™ ืงื ื” ืžื™ื“ื” ืขืœ ื™ื“ื™ ื”ื•ืกืคืช ื”ืขืจื” ืœื”ื•ืจื“ื”/ืื™ ื”ื›ืœืœื”: ืืžืช. ื ื™ืชืŸ ืœื”ื—ืจื™ื’ ื‘ืื•ืคืŸ ื–ืžื ื™ ืคืจื™ืกื•ืช ื‘ืืžืฆืขื•ืช ื”ื”ืขืจื” ืœื”ื•ืจื“ื”/ืื™ ื”ื›ืœืœื”-ืขื“ ืขื ื—ื•ืชืžืช ื–ืžืŸ ืžื•ื—ืœื˜ืช ื‘ืคื•ืจืžื˜ YYYY-MM-DD HH:MM (UTC). ื‘ืžื™ื“ืช ื”ืฆื•ืจืš, ื ื™ืชืŸ ืœื”ืงื˜ื™ืŸ ืืช ื”ืืฉื›ื•ืœ ื›ื•ืœื• ืขืœ ื™ื“ื™ ืคืจื™ืกืช ืชืจืžื™ืœ ืขื ื”ื”ืขืจื” 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

ืœืจืื•ืช README kube-downscaler, ืื ืืชื” ืžืขื•ื ื™ื™ืŸ ื‘ื”ื•ืจืื•ืช ืคืจื™ืกื” ื•ืืคืฉืจื•ื™ื•ืช ื ื•ืกืคื•ืช.

ื”ืฉืชืžืฉ ื‘ืงื ื” ืžื™ื“ื” ืื•ื˜ื•ืžื˜ื™ ืื•ืคืงื™

ื™ื™ืฉื•ืžื™ื/ืฉื™ืจื•ืชื™ื ืจื‘ื™ื ืขื•ืกืงื™ื ื‘ื“ืคื•ืก ื˜ืขื™ื ื” ื“ื™ื ืžื™: ืœืคืขืžื™ื ื”ืžื•ื“ื•ืœื™ื ืฉืœื”ื ืœื ืคืขื™ืœื™ื, ื•ืœืคืขืžื™ื ื”ื ืขื•ื‘ื“ื™ื ื‘ืชืคื•ืงื” ืžืœืื”. ื”ืคืขืœืช ืฆื™ ืงื‘ื•ืข ืฉืœ ืชืจืžื™ืœื™ื ื›ื“ื™ ืœื”ืชืžื•ื“ื“ ืขื ืขื•ืžืก ืฉื™ื ืžืจื‘ื™ ืื™ื ื• ื—ืกื›ื•ื ื™. Kubernetes ืชื•ืžืš ื‘ืฉื™ื ื•ื™ ืงื ื” ืžื™ื“ื” ืื•ื˜ื•ืžื˜ื™ ืื•ืคืงื™ ืขืœ ืคื ื™ ืžืฉืื‘ HorizontalPodAutoscaler (HPA). ืฉื™ืžื•ืฉ ื‘ืžืขื‘ื“ ื”ื•ื ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืื™ื ื“ื™ืงื˜ื•ืจ ื˜ื•ื‘ ืœืฉื™ื ื•ื™ ืงื ื” ืžื™ื“ื”:

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 ื™ืฆืจื” ืจื›ื™ื‘ ื›ื“ื™ ืœื—ื‘ืจ ื‘ืงืœื•ืช ืžื“ื“ื™ื ืžื•ืชืืžื™ื ืื™ืฉื™ืช ืœืฉื™ื ื•ื™ ืงื ื” ืžื™ื“ื”: ืžืชืื ืžื“ื“ื™ Kube (kube-metrics-adapter) ื”ื•ื ืžืชืื ืžื“ื“ื™ื ื’ื ืจื™ ืขื‘ื•ืจ Kubernetes ืฉื™ื›ื•ืœ ืœืืกื•ืฃ ื•ืœื”ื’ื™ืฉ ืžื“ื“ื™ื ืžื•ืชืืžื™ื ืื™ืฉื™ืช ื•ื—ื™ืฆื•ื ื™ื™ื ืขื‘ื•ืจ ืงื ื” ืžื™ื“ื” ืื•ื˜ื•ืžื˜ื™ ืื•ืคืงื™ ืฉืœ ืคื•ื“ื™ื. ื”ื•ื ืชื•ืžืš ื‘ืงื ื” ืžื™ื“ื” ื”ืžื‘ื•ืกืก ืขืœ ืžื“ื“ื™ Prometheus, ืชื•ืจื™ SQS ื•ื”ื’ื“ืจื•ืช ืื—ืจื•ืช. ืœื“ื•ื’ืžื”, ื›ื“ื™ ืœืฉื ื•ืช ืืช ืงื ื” ื”ืžื™ื“ื” ืฉืœ ื”ืคืจื™ืกื” ืฉืœืš ืœืžื“ื“ ืžื•ืชืื ืื™ืฉื™ืช ื”ืžื™ื•ืฆื’ ืขืœ ื™ื“ื™ ื”ืืคืœื™ืงืฆื™ื” ืขืฆืžื” ื›-JSON ื‘-/metrics ื”ืฉืชืžืฉ:

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 ืงื•ื‘ืขื™ื ืืช ืฆืจื›ื™ ื”ืžืขื‘ื“/ื–ื™ื›ืจื•ืŸ ืฉืœื”ื ื‘ืืžืฆืขื•ืช "ื‘ืงืฉื•ืช ืžืฉืื‘ื™ื". ืžืฉืื‘ื™ ืžืขื‘ื“ ื ืžื“ื“ื™ื ื‘ืœื™ื‘ื•ืช ื•ื™ืจื˜ื•ืืœื™ื•ืช ืื• ื™ื•ืชืจ ื ืคื•ืฅ ื‘"ืžื™ืœื™ืงื•ืจื™ื", ืœืžืฉืœ 500m ืžืจืžื– ืขืœ 50% vCPU. ืžืฉืื‘ื™ ื–ื™ื›ืจื•ืŸ ื ืžื“ื“ื™ื ื‘ื‘ืชื™ื, ื•ื ื™ืชืŸ ืœื”ืฉืชืžืฉ ื‘ืกื™ื•ืžื•ืช ื ืคื•ืฆื•ืช, ื›ืžื• 500Mi, ื›ืœื•ืžืจ 500 ืžื’ื”. ืžืฉืื‘ื™ื ืžื‘ืงืฉื™ื "ื ืขื™ืœืช" ืงื™ื‘ื•ืœืช ื‘ืฆืžืชื™ ืขื•ื‘ื“ื™ื, ื›ืœื•ืžืจ ืคื•ื“ ืขื ื‘ืงืฉืช ืžืขื‘ื“ ืฉืœ 1000 ืž' ื‘ืฆื•ืžืช ืขื 4 vCPUs ื™ืฉืื™ืจ ืจืง 3 vCPUs ื–ืžื™ื ื™ื ืœืชืจืžื™ืœื™ื ืื—ืจื™ื. [1]

ืจืคื™ื•ืŸ (ืจื–ืจื‘ื” ืขื•ื“ืคืช) ื”ื•ื ื”ื”ื‘ื“ืœ ื‘ื™ืŸ ื”ืžืฉืื‘ื™ื ื”ืžื‘ื•ืงืฉื™ื ืœืฉื™ืžื•ืฉ ื‘ืคื•ืขืœ. ืœื“ื•ื’ืžื”, ืคื•ื“ ืฉืžื‘ืงืฉ 2 GiB ืฉืœ ื–ื™ื›ืจื•ืŸ ืื‘ืœ ืžืฉืชืžืฉ ืจืง ื‘-200 MiB ื™ืฉ ~1,8 GiB ืฉืœ ื–ื™ื›ืจื•ืŸ "ืขื•ื“ืฃ". ืขื•ื“ืฃ ืขื•ืœื” ื›ืกืฃ. ืืคืฉืจ ืœื”ืขืจื™ืš ื‘ืื•ืคืŸ ื’ืก ืฉ-1 GiB ืฉืœ ื–ื™ื›ืจื•ืŸ ืžื™ื•ืชืจ ืขื•ืœื” ~$10 ืœื—ื•ื“ืฉ. [2]

ื“ื•ื— ืžืฉืื‘ื™ Kubernetes (kube-resource-report) ืžืฆื™ื’ ืขืชื•ื“ื•ืช ืขื•ื“ืคื•ืช ื•ื™ื›ื•ืœ ืœืขื–ื•ืจ ืœืš ืœืงื‘ื•ืข ืคื•ื˜ื ืฆื™ืืœ ื—ื™ืกื›ื•ืŸ:

ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

ื“ื•ื— ืžืฉืื‘ื™ Kubernetes ืžืฆื™ื’ ืืช ื”ืขื•ื“ืฃ ื”ืžืฆื˜ื‘ืจ ืœืคื™ ื™ื™ืฉื•ื ื•ืคืงื•ื“ื”. ื–ื” ืžืืคืฉืจ ืœืš ืœืžืฆื•ื ืžืงื•ืžื•ืช ืฉื‘ื”ื ื ื™ืชืŸ ืœืฆืžืฆื ืืช ื“ืจื™ืฉื•ืช ื”ืžืฉืื‘ื™ื. ื“ื•ื— ื”-HTML ืฉื ื•ืฆืจ ืžืกืคืง ืจืง ืชืžื•ื ืช ืžืฆื‘ ืฉืœ ื”ืฉื™ืžื•ืฉ ื‘ืžืฉืื‘ื™ื. ืขืœื™ืš ืœื”ืกืชื›ืœ ืขืœ ื”ืฉื™ืžื•ืฉ ื‘ืžืขื‘ื“/ื–ื™ื›ืจื•ืŸ ืœืื•ืจืš ื–ืžืŸ ื›ื“ื™ ืœืงื‘ื•ืข ื‘ืงืฉื•ืช ืžืฉืื‘ื™ื ื ืื•ืชื•ืช. ืœื”ืœืŸ ืชืจืฉื™ื Grafana ืขื‘ื•ืจ ืฉื™ืจื•ืช "ื˜ื™ืคื•ืกื™" ื›ื‘ื“ ืžืขื‘ื“: ื›ืœ ื”ืคื•ื“ื™ื ืžืฉืชืžืฉื™ื ื‘ืคื—ื•ืช ืž-3 ืœื™ื‘ื•ืช ื”ืžืขื‘ื“ ื”ืžื‘ื•ืงืฉื•ืช:

ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

ืฆืžืฆื•ื ื‘ืงืฉืช ื”-CPU ืž-3000 ืž' ืœ-~400 ืž' ืžืคื ื” ืžืฉืื‘ื™ื ืœืขื•ืžืกื™ ืขื‘ื•ื“ื” ืื—ืจื™ื ื•ืžืืคืฉืจ ืœืืฉื›ื•ืœ ืœื”ื™ื•ืช ืงื˜ืŸ ื™ื•ืชืจ.

"ื”ืฉื™ืžื•ืฉ ื”ืžืžื•ืฆืข ื‘ืžืขื‘ื“ ื‘ืžื•ืคืขื™ EC2 ืžืจื—ืฃ ืœืขืชื™ื ืงืจื•ื‘ื•ืช ื‘ื˜ื•ื•ื— ื”ืื—ื•ื– ื”ื—ื“-ืกืคืจืชื™," ื›ื•ืชื‘ ืงื•ืจื™ ืงื•ื•ื™ืŸ. ื‘ืขื•ื“ ืขื‘ื•ืจ EC2 ื”ืขืจื›ืช ื”ื’ื•ื“ืœ ื”ื ื›ื•ืŸ ืขืฉื•ื™ื” ืœื”ื™ื•ืช ื”ื—ืœื˜ื” ื’ืจื•ืขื”ืฉื™ื ื•ื™ ืฉืœ ื›ืžื” ืฉืื™ืœืชื•ืช ืžืฉืื‘ื™ Kubernetes ื‘ืงื•ื‘ืฅ YAML ื”ื•ื ืงืœ ื•ื™ื›ื•ืœ ืœื”ื‘ื™ื ืœื—ืกื›ื•ืŸ ืขืฆื•ื.

ืื‘ืœ ื”ืื ืื ื—ื ื• ื‘ืืžืช ืจื•ืฆื™ื ืฉืื ืฉื™ื ื™ืฉื ื• ืขืจื›ื™ื ื‘ืงื‘ืฆื™ YAML? ืœื, ืžื›ื•ื ื•ืช ื™ื›ื•ืœื•ืช ืœืขืฉื•ืช ืืช ื–ื” ื”ืจื‘ื” ื™ื•ืชืจ ื˜ื•ื‘! Kubernetes Autoscaler Pod ืื ื›ื™ (VPA) ืขื•ืฉื” ื‘ื“ื™ื•ืง ืืช ื–ื”: ืžืชืื™ื ื‘ืงืฉื•ืช ืžืฉืื‘ื™ื ื•ืื™ืœื•ืฆื™ื ื‘ื”ืชืื ืœืขื•ืžืก ื”ืขื‘ื•ื“ื”. ืœื”ืœืŸ ื’ืจืฃ ืœื“ื•ื’ืžื” ืฉืœ ื‘ืงืฉื•ืช ืžืขื‘ื“ Prometheus (ืงื• ื›ื—ื•ืœ ื“ืง) ืฉื”ื•ืชืืžื• ืขืœ ื™ื“ื™ VPA ืœืื•ืจืš ื–ืžืŸ:

ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

Zalando ืžืฉืชืžืฉ ื‘-VPA ื‘ื›ืœ ื”ืืฉื›ื•ืœื•ืช ืฉืœื• ืขื‘ื•ืจ ืจื›ื™ื‘ื™ ืชืฉืชื™ืช. ื™ื™ืฉื•ืžื™ื ืœื ืงืจื™ื˜ื™ื™ื ื™ื›ื•ืœื™ื ื’ื ืœื”ืฉืชืžืฉ ื‘-VPA.

ื–ื”ื‘ ืž-Fairwind ื”ื•ื ื›ืœื™ ืฉื™ื•ืฆืจ VPA ืขื‘ื•ืจ ื›ืœ ืคืจื™ืกื” ื‘ืžืจื—ื‘ ืฉืžื•ืช ื•ืœืื—ืจ ืžื›ืŸ ืžืฆื™ื’ ื”ืžืœืฆืช VPA ื‘ืœื•ื— ื”ืžื—ื•ื•ื ื™ื ืฉืœื•. ื–ื” ื™ื›ื•ืœ ืœืขื–ื•ืจ ืœืžืคืชื—ื™ื ืœื”ื’ื“ื™ืจ ืืช ื‘ืงืฉื•ืช ื”ืžืขื‘ื“/ื–ื™ื›ืจื•ืŸ ื”ื ื›ื•ื ื•ืช ืขื‘ื•ืจ ื”ื™ื™ืฉื•ืžื™ื ืฉืœื”ื:

ื—ืกื•ืš ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ืฉืœ Kubernetes ื‘-AWS

ื›ืชื‘ืชื™ ืงื˜ืŸ ืคื•ืกื˜ ื‘ื‘ืœื•ื’ ืขืœ VPA ื‘ืฉื ืช 2019, ื•ืœืื—ืจื•ื ื” ื‘ ืงื”ื™ืœืช ืžืฉืชืžืฉื™ ื”ืงืฆื” ืฉืœ CNCF ื“ื ื” ื‘ื ื•ืฉื VPA.

ืฉื™ืžื•ืฉ ื‘-EC2 Spot Instances

ืื—ืจื•ืŸ ื—ื‘ื™ื‘, ื ื™ืชืŸ ืœื”ื•ื–ื™ืœ ืืช ืขืœื•ื™ื•ืช AWS EC2 ืขืœ ื™ื“ื™ ืฉื™ืžื•ืฉ ื‘ืžื•ืคืขื™ Spot ื›ืฆื•ืžืชื™ ืขื‘ื•ื“ื” ืฉืœ Kubernetes [3]. ืžื•ืคืขื™ ืกืคื•ื˜ ื–ืžื™ื ื™ื ื‘ื”ื ื—ื” ืฉืœ ืขื“ 90% ื‘ื”ืฉื•ื•ืื” ืœืžื—ื™ืจื™ On Demand. ื”ืคืขืœืช Kubernetes ื‘-EC2 Spot ื”ื™ื ืฉื™ืœื•ื‘ ื˜ื•ื‘: ืขืœื™ืš ืœืฆื™ื™ืŸ ืžืกืคืจ ืกื•ื’ื™ ืžื•ืคืขื™ื ืฉื•ื ื™ื ืœื–ืžื™ื ื•ืช ื’ื‘ื•ื”ื” ื™ื•ืชืจ, ื›ืœื•ืžืจ ืืชื” ื™ื›ื•ืœ ืœืงื‘ืœ ืฆื•ืžืช ื’ื“ื•ืœ ื™ื•ืชืจ ื‘ืื•ืชื• ืžื—ื™ืจ ืื• ื ืžื•ืš ื™ื•ืชืจ, ื•ื”ืงื™ื‘ื•ืœืช ื”ืžื•ื’ื“ืœืช ื™ื›ื•ืœื” ืœืฉืžืฉ ืขื•ืžืกื™ ืขื‘ื•ื“ื” ืฉืœ Kubernetes ื‘ืžื›ื•ืœื•ืช.

ื›ื™ืฆื“ ืœื”ืคืขื™ืœ ืืช Kubernetes ื‘-EC2 Spot? ื™ืฉื ืŸ ืžืกืคืจ ืืคืฉืจื•ื™ื•ืช: ื”ืฉืชืžืฉ ื‘ืฉื™ืจื•ืช ืฆื“ ืฉืœื™ืฉื™ ื›ืžื• SpotInst (ื ืงืจื ื›ืขืช "Spot", ืืœ ืชืฉืืœ ืื•ืชื™ ืœืžื”), ืื• ืคืฉื•ื˜ ื”ื•ืกืฃ Spot AutoScalingGroup (ASG) ืœืืฉื›ื•ืœ ืฉืœืš. ืœื“ื•ื’ืžื”, ื”ื ื” ืงื˜ืข CloudFormation ืขื‘ื•ืจ ASG Spot "ืžื•ืชืื ืœืงื™ื‘ื•ืœืช" ืขื ืžืกืคืจ ืกื•ื’ื™ ืžื•ืคืขื™ื:

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"

ื›ืžื” ื”ืขืจื•ืช ืขืœ ื”ืฉื™ืžื•ืฉ ื‘-Spot ืขื Kubernetes:

  • ืืชื” ืฆืจื™ืš ืœื˜ืคืœ ื‘ื”ืคืกืงื•ืช Spot, ืœืžืฉืœ ืขืœ ื™ื“ื™ ืžื™ื–ื•ื’ ื”ืฆื•ืžืช ื›ืืฉืจ ื”ืžื•ืคืข ื ืขืฆืจ
  • ื–ืœื ื“ื• ืžืฉืชืžืฉ ืžื–ืœื’ ืงื ื” ืžื™ื“ื” ืจืฉืžื™ ืฉืœ ืืฉื›ื•ืœ ืขื ืกื“ืจื™ ืขื“ื™ืคื•ื™ื•ืช ืฉืœ ืžืื’ืจ ืฆืžืชื™ื
  • ืฆืžืชื™ื ื ืงื•ื“ืชื™ื™ื ื ื™ืชืŸ ืœื›ืคื•ืช ืœืงื‘ืœ "ื”ืจืฉืžื•ืช" ืฉืœ ืขื•ืžืกื™ ืขื‘ื•ื“ื” ืœื”ืคืขืœื” ื‘-Spot

ืชืงืฆื™ืจ

ืื ื™ ืžืงื•ื•ื” ืฉืชืžืฆื ื›ืžื” ืžื”ื›ืœื™ื ืฉื”ื•ืฆื’ื• ืฉื™ืžื•ืฉื™ื™ื ื‘ื”ืคื—ืชืช ื—ืฉื‘ื•ืŸ ื”ืขื ืŸ ืฉืœืš. ืืชื” ื™ื›ื•ืœ ืœืžืฆื•ื ืืช ืจื•ื‘ ืชื•ื›ืŸ ื”ืžืืžืจ ื’ื ื‘ ื”ื”ืจืฆืื” ืฉืœื™ ื‘-DevOps Gathering 2019 ื‘-YouTube ื•ื‘ืฉืงื•ืคื™ื•ืช.

ืžื”ืŸ ื”ืฉื™ื˜ื•ืช ื”ืžื•ืžืœืฆื•ืช ืฉืœืš ืœื—ื™ืกื›ื•ืŸ ื‘ืขืœื•ื™ื•ืช ื”ืขื ืŸ ื‘-Kubernetes? ืื ื ื”ื•ื“ืข ืœื™ ื‘- ื˜ื•ื•ื™ื˜ืจ (@try_except_).

[1] ืœืžืขืฉื”, ืคื—ื•ืช ืž-3 ืžืขื‘ื“ื™ vCPU ื™ื™ืฉืืจื• ืฉืžื™ืฉื™ื ืžื›ื™ื•ื•ืŸ ืฉืชืคื•ืงืช ื”ืฆื•ืžืช ืžื•ืคื—ืชืช ืขืœ ื™ื“ื™ ืžืฉืื‘ื™ ืžืขืจื›ืช ืฉืžื•ืจื™ื. Kubernetes ืžื‘ื—ื™ืŸ ื‘ื™ืŸ ืงื™ื‘ื•ืœืช ืฆื•ืžืช ืคื™ื–ื™ืช ืœื‘ื™ืŸ ืžืฉืื‘ื™ื "ืžื•ืกืคืงื™ื" (ื ื™ืชืŸ ืœื”ืงืฆืืช ืฆื•ืžืช).

[2] ื“ื•ื’ืžื” ื—ื™ืฉื•ื‘: ืžื•ืคืข ืื—ื“ m5.large ืขื 8 GiB ืฉืœ ื–ื™ื›ืจื•ืŸ ื”ื•ื ~$84 โ€‹โ€‹ืœื—ื•ื“ืฉ (eu-central-1, On-Demand), ื›ืœื•ืžืจ. ื—ืกื™ืžืช ืฆื•ืžืช 1/8 ื”ื™ื ื‘ืขืจืš ~$10 ืœื—ื•ื“ืฉ.

[3] ื™ืฉื ืŸ ื“ืจื›ื™ื ืจื‘ื•ืช ื ื•ืกืคื•ืช ืœื”ืคื—ื™ืช ืืช ื—ืฉื‘ื•ืŸ EC2 ืฉืœืš, ื›ื’ื•ืŸ ืžื•ืคืขื™ื ืฉืžื•ืจื™ื, ืชื•ื›ื ื™ืช ื—ื™ืกื›ื•ืŸ ื•ื›ื•' - ืื ื™ ืœื ืืขืกื•ืง ื‘ื ื•ืฉืื™ื ื”ืืœื” ื›ืืŸ, ืื‘ืœ ื‘ื”ื—ืœื˜ ื›ื“ืื™ ืœืš ืœื‘ื“ื•ืง ืื•ืชื!

ืœืžื™ื“ืข ื ื•ืกืฃ ืขืœ ื”ืงื•ืจืก.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”