ประหยัดค่าใช้จ่ายระบบคลาวด์ Kubernetes บน AWS

การแปลบทความจัดทำขึ้นในวันเริ่มต้นหลักสูตร "แพลตฟอร์มโครงสร้างพื้นฐานบน Kubernetes".

ประหยัดค่าใช้จ่ายระบบคลาวด์ Kubernetes บน AWS

จะประหยัดต้นทุนคลาวด์เมื่อทำงานกับ Kubernetes ได้อย่างไร ไม่มีวิธีแก้ปัญหาที่ถูกต้องเพียงวิธีเดียว แต่บทความนี้จะอธิบายเครื่องมือต่างๆ ที่สามารถช่วยให้คุณจัดการทรัพยากรได้อย่างมีประสิทธิภาพมากขึ้น และลดต้นทุนการประมวลผลบนระบบคลาวด์

ฉันเขียนบทความนี้โดยคำนึงถึง Kubernetes สำหรับ AWS แต่จะนำไปใช้กับผู้ให้บริการคลาวด์รายอื่นๆ (เกือบ) ในลักษณะเดียวกันทุกประการ ฉันสมมติว่าคลัสเตอร์ของคุณมีการกำหนดค่าการปรับขนาดอัตโนมัติแล้ว (คลัสเตอร์ autoscaler). การลบทรัพยากรและการลดขนาดการปรับใช้ของคุณจะช่วยให้คุณประหยัดเงินได้ก็ต่อเมื่อลดฟลีตโหนดผู้ปฏิบัติงาน (อินสแตนซ์ EC2) ด้วย

บทความนี้จะครอบคลุม:

  • ทำความสะอาดทรัพยากรที่ไม่ได้ใช้ (kube-ภารโรง)
  • ลดมาตราส่วนในช่วงนอกเวลาทำงาน (kube-downscaler)
  • ใช้การปรับขนาดอัตโนมัติแนวนอน (HPA)
  • ลดการสำรองทรัพยากรส่วนเกิน (รายงานทรัพยากร kube, วีพีเอ)
  • การใช้อินสแตนซ์ Spot

ทำความสะอาดทรัพยากรที่ไม่ได้ใช้

การทำงานในสภาพแวดล้อมที่เร่งรีบเป็นสิ่งที่ดีมาก เราต้องการองค์กรด้านเทคโนโลยี เร่ง. การส่งมอบซอฟต์แวร์ที่เร็วขึ้นยังหมายถึงการปรับใช้การประชาสัมพันธ์ สภาพแวดล้อมการแสดงตัวอย่าง ต้นแบบ และโซลูชันการวิเคราะห์ที่มากขึ้น ทุกอย่างถูกปรับใช้บน Kubernetes ใครมีเวลาล้างข้อมูลการปรับใช้การทดสอบด้วยตนเอง เป็นเรื่องง่ายที่จะลืมการลบการทดสอบที่มีอายุหนึ่งสัปดาห์ไปได้เลย บิลคลาวด์จะเพิ่มขึ้นเนื่องจากบางสิ่งที่เราลืมปิด:

ประหยัดค่าใช้จ่ายระบบคลาวด์ Kubernetes บน AWS

(เฮนนิ่งจาคอบส์:
ซิซ่า:
(คำพูด) Corey Quinn:
ตำนาน: บัญชี AWS ของคุณเป็นฟังก์ชันของจำนวนผู้ใช้ที่คุณมี
ข้อเท็จจริง: คะแนน AWS ของคุณขึ้นอยู่กับจำนวนวิศวกรที่คุณมี

อีวาน คูร์โนซอฟ (ตอบกลับ):
ข้อเท็จจริง: คะแนน AWS ของคุณเป็นฟังก์ชันของจำนวนสิ่งที่คุณลืมปิดการใช้งาน/ลบ)

ภารโรง Kubernetes (kube-janitor) ช่วยทำความสะอาดคลัสเตอร์ของคุณ การกำหนดค่าภารโรงมีความยืดหยุ่นสำหรับการใช้งานทั้งส่วนกลางและภายใน:

  • กฎทั่วทั้งคลัสเตอร์สามารถกำหนดเวลาสูงสุดในการใช้งาน (TTL) สำหรับการปรับใช้ PR/การทดสอบ
  • ทรัพยากรแต่ละรายการสามารถใส่คำอธิบายประกอบด้วยภารโรง/ttl ได้ เช่น เพื่อลบขัดขวาง/ต้นแบบโดยอัตโนมัติหลังจาก 7 วัน

กฎทั่วไปถูกกำหนดไว้ในไฟล์ YAML เส้นทางของมันถูกส่งผ่านพารามิเตอร์ --rules-file ใน kube-ภารโรง นี่คือกฎตัวอย่างในการลบเนมสเปซทั้งหมดด้วย -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 คุเบะภารโรง.

ลดขนาดในช่วงเวลาที่ไม่ทำงาน

โดยทั่วไประบบการทดสอบและการจัดเตรียมจำเป็นสำหรับการทำงานเฉพาะในช่วงเวลาทำการเท่านั้น แอปพลิเคชันการผลิตบางอย่าง เช่น เครื่องมือแบ็คออฟฟิศ/ผู้ดูแลระบบ ต้องการความพร้อมใช้งานที่จำกัดและอาจถูกปิดใช้งานข้ามคืน

Kubernetes Downscaler (kube-downscaler) ช่วยให้ผู้ใช้และผู้ปฏิบัติงานสามารถลดขนาดระบบในช่วงเวลาที่ไม่ใช่เวลาทำงาน การปรับใช้และ StatefulSets สามารถปรับขนาดเป็นศูนย์เรพลิกาได้ CronJobs อาจถูกระงับ Kubernetes Downscaler ได้รับการกำหนดค่าสำหรับทั้งคลัสเตอร์ เนมสเปซตั้งแต่ XNUMX รายการขึ้นไป หรือทรัพยากรแต่ละรายการ คุณสามารถตั้งค่า "เวลาว่าง" หรือ "เวลาทำงาน" ในทางกลับกัน ตัวอย่างเช่น หากต้องการลดการปรับขนาดให้มากที่สุดในช่วงกลางคืนและวันหยุดสุดสัปดาห์:

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 ของคุณอย่างแน่นอน

แต่ถ้าฉันต้องทำงานระหว่าง "เวลาหยุดทำงาน" ของคลัสเตอร์ล่ะ การใช้งานบางอย่างสามารถแยกออกจากการปรับขนาดได้อย่างถาวรโดยการเพิ่ม downscaler/exclude: true annotation การปรับใช้สามารถยกเว้นได้ชั่วคราวโดยใช้ downscaler/exclude-until คำอธิบายประกอบที่มีการประทับเวลาที่แน่นอนในรูปแบบ YYYY-MM-DD HH:MM (UTC) หากจำเป็น คุณสามารถปรับขนาดคลัสเตอร์ทั้งหมดกลับได้โดยการปรับใช้พ็อดที่มีคำอธิบายประกอบ downscaler/force-uptimeตัวอย่างเช่น โดยการเปิดตัว nginx Blank:

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 รองรับการปรับขนาดอัตโนมัติในแนวนอนทั่วทั้งทรัพยากร แนวนอนPodAutoscaler (เอชพีเอ). การใช้งาน CPU มักเป็นตัวบ่งชี้ที่ดีในการปรับขนาด:

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 จะกำหนดความต้องการ CPU/หน่วยความจำผ่าน "คำขอทรัพยากร" ทรัพยากร CPU วัดเป็นคอร์เสมือนหรือโดยทั่วไปมีหน่วยเป็น “มิลลิคอร์” เช่น 500m หมายถึง vCPU 50% ทรัพยากรหน่วยความจำวัดเป็นไบต์ และส่วนต่อท้ายทั่วไปสามารถใช้ได้ เช่น 500Mi ซึ่งหมายถึง 500 เมกะไบต์ ความจุคำขอ "ล็อก" ทรัพยากรบนโหนดของผู้ปฏิบัติงาน หมายความว่าพ็อดที่มีคำขอ CPU 1000 เมตรบนโหนดที่มี 4 vCPU จะเหลือเพียง 3 vCPU ที่พร้อมใช้งานสำหรับพ็อดอื่น [1]

หย่อน (สำรองส่วนเกิน) คือความแตกต่างระหว่างทรัพยากรที่ร้องขอและการใช้งานจริง ตัวอย่างเช่น พ็อดที่ขอหน่วยความจำ 2 GiB แต่ใช้เพียง 200 MiB จะมีหน่วยความจำ “ส่วนเกิน” ~1,8 GiB ส่วนเกินต้องเสียเงิน เราสามารถประมาณคร่าวๆได้ว่าหน่วยความจำสำรอง 1 GiB มีราคาประมาณ 10 เหรียญสหรัฐฯ ต่อเดือน [2]

รายงานทรัพยากร Kubernetes (kube-resource-report) แสดงปริมาณสำรองส่วนเกินและสามารถช่วยคุณกำหนดศักยภาพในการออม:

ประหยัดค่าใช้จ่ายระบบคลาวด์ Kubernetes บน AWS

รายงานทรัพยากร Kubernetes แสดงส่วนเกินที่รวบรวมโดยแอปพลิเคชันและคำสั่ง สิ่งนี้ช่วยให้คุณค้นหาจุดที่สามารถลดความต้องการทรัพยากรได้ รายงาน HTML ที่สร้างขึ้นจะให้ภาพรวมของการใช้ทรัพยากรเท่านั้น คุณควรดูการใช้งาน CPU/หน่วยความจำในช่วงเวลาหนึ่งเพื่อพิจารณาคำขอทรัพยากรที่เพียงพอ นี่คือแผนภูมิ Grafana สำหรับบริการที่ใช้ CPU หนัก "ทั่วไป": พ็อดทั้งหมดใช้งานน้อยกว่า 3 คอร์ CPU ที่ร้องขออย่างมาก:

ประหยัดค่าใช้จ่ายระบบคลาวด์ Kubernetes บน AWS

การลดคำขอ CPU จาก 3000 ม. เหลือ ~ 400 ม. จะทำให้ทรัพยากรว่างสำหรับเวิร์กโหลดอื่น ๆ และช่วยให้คลัสเตอร์มีขนาดเล็กลง

“การใช้งาน CPU โดยเฉลี่ยของ EC2 instance มักจะอยู่ในช่วงเปอร์เซ็นต์หลักเดียว” เขียนคอเรย์ควินน์. ในขณะที่สำหรับ EC2 การประมาณขนาดที่เหมาะสมอาจเป็นการตัดสินใจที่ไม่ดีการเปลี่ยนแปลงการค้นหาทรัพยากร Kubernetes บางส่วนในไฟล์ YAML เป็นเรื่องง่ายและช่วยประหยัดได้มาก

แต่เราต้องการให้ผู้คนเปลี่ยนค่าในไฟล์ YAML จริงหรือ? ไม่ เครื่องจักรสามารถทำได้ดีกว่ามาก! คูเบอร์เนเตส ตัวปรับขนาดอัตโนมัติพ็อดแนวตั้ง (VPA) ทำเช่นนั้น: ปรับคำขอทรัพยากรและข้อจำกัดตามปริมาณงาน นี่คือกราฟตัวอย่างของคำขอ CPU ของ Prometheus (เส้นสีน้ำเงินบาง) ที่ดัดแปลงโดย VPA เมื่อเวลาผ่านไป:

ประหยัดค่าใช้จ่ายระบบคลาวด์ Kubernetes บน AWS

Zalando ใช้ VPA ในทุกคลัสเตอร์ สำหรับส่วนประกอบโครงสร้างพื้นฐาน แอปพลิเคชันที่ไม่สำคัญก็สามารถใช้ VPA ได้เช่นกัน

Goldilocks จาก Fairwind เป็นเครื่องมือที่สร้าง VPA สำหรับการปรับใช้แต่ละครั้งในเนมสเปซ จากนั้นจึงแสดงคำแนะนำ VPA บนแดชบอร์ด โดยสามารถช่วยนักพัฒนาตั้งค่าคำขอ CPU/หน่วยความจำที่ถูกต้องสำหรับแอปพลิเคชันของตนได้:

ประหยัดค่าใช้จ่ายระบบคลาวด์ Kubernetes บน AWS

ฉันเขียนเรื่องเล็กๆ โพสต์บนบล็อกเกี่ยวกับ VPA ในปี 2019 และเร็วๆ นี้ ชุมชนผู้ใช้ CNCF ปลายทางหารือเกี่ยวกับปัญหา VPA.

การใช้อินสแตนซ์สปอต EC2

สุดท้ายแต่ไม่ท้ายสุด คุณสามารถลดต้นทุน AWS EC2 ได้โดยใช้อินสแตนซ์ Spot เป็นโหนดผู้ปฏิบัติงาน Kubernetes [3]. อินสแตนซ์ Spot มีส่วนลดสูงสุดถึง 90% เมื่อเทียบกับราคาแบบตามความต้องการ การเรียกใช้ Kubernetes บน EC2 Spot เป็นการผสมผสานที่ดี: คุณต้องระบุประเภทอินสแตนซ์ที่แตกต่างกันหลายประเภทเพื่อความพร้อมใช้งานที่สูงขึ้น ซึ่งหมายความว่าคุณจะได้รับโหนดที่ใหญ่ขึ้นในราคาเท่ากันหรือต่ำกว่า และความจุที่เพิ่มขึ้นสามารถนำไปใช้โดยปริมาณงาน Kubernetes ที่ถูกบรรจุในคอนเทนเนอร์ได้

จะรัน Kubernetes บน EC2 Spot ได้อย่างไร มีหลายตัวเลือก: ใช้บริการของบุคคลที่สาม เช่น SpotInst (ปัจจุบันเรียกว่า "Spot" ไม่ต้องถามฉันว่าทำไม) หรือเพียงเพิ่ม Spot AutoScalingGroup (ASG) ลงในคลัสเตอร์ของคุณ ตัวอย่างเช่น นี่คือตัวอย่างข้อมูล CloudFormation สำหรับ Spot ASG ที่ "ปรับความจุให้เหมาะสม" ซึ่งมีอินสแตนซ์หลายประเภท:

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 เช่น การรวมโหนดเมื่ออินสแตนซ์หยุดทำงาน
  • ซาลันโด้ใช้ ส้อม การปรับขนาดคลัสเตอร์อย่างเป็นทางการอย่างเป็นทางการพร้อมลำดับความสำคัญของ Node Pool
  • จุดโหนด สามารถบังคับได้ ยอมรับ "การลงทะเบียน" ของปริมาณงานเพื่อทำงานใน Spot

สรุป

ฉันหวังว่าคุณจะพบว่าเครื่องมือบางอย่างที่นำเสนอมีประโยชน์ในการลดค่าบริการคลาวด์ของคุณ คุณสามารถค้นหาเนื้อหาส่วนใหญ่ของบทความได้ที่ การพูดคุยของฉันที่ DevOps Gathering 2019 บน YouTube และในสไลด์.

แนวทางปฏิบัติที่ดีที่สุดในการประหยัดต้นทุนระบบคลาวด์บน Kubernetes คืออะไร กรุณาแจ้งได้ที่ ทวิตเตอร์ (@try_ยกเว้น_).

[1] ในความเป็นจริง vCPU น้อยกว่า 3 ตัวจะยังคงใช้งานได้ เนื่องจากปริมาณงานของโหนดลดลงตามทรัพยากรระบบที่สงวนไว้ Kubernetes แยกความแตกต่างระหว่างความจุของโหนดจริงและทรัพยากรที่ "จัดเตรียม" (โหนดที่จัดสรรได้).

[2] ตัวอย่างการคำนวณ: อินสแตนซ์ m5.large หนึ่งอินสแตนซ์ที่มีหน่วยความจำ 8 GiB คือ ~84 ​​$ต่อเดือน (eu-central-1 ตามความต้องการ) เช่น การบล็อกโหนด 1/8 อยู่ที่ประมาณ ~$10/เดือน

[3] มีหลายวิธีในการลดการเรียกเก็บเงิน EC2 ของคุณ เช่น อินสแตนซ์แบบเหมาจ่าย Savings Plan ฯลฯ ฉันจะไม่กล่าวถึงหัวข้อเหล่านั้นที่นี่ แต่คุณควรพิจารณาหัวข้อเหล่านี้อย่างแน่นอน!

เรียนรู้เพิ่มเติมเกี่ยวกับหลักสูตร

ที่มา: will.com

เพิ่มความคิดเห็น