قياس تلقائي لتطبيقات Kubernetes باستخدام Prometheus و KEDA

يعد Balloon Man by Cimuanos



Scalability مطلبًا أساسيًا للتطبيقات السحابية. باستخدام Kubernetes ، يكون قياس التطبيق سهلاً مثل زيادة عدد النسخ المتماثلة للنشر المناسب ، أوReplicaSet- لكنها عملية يدوية.



يسمح Kubernetes للتطبيقات بالتدرج التلقائي (أي Pods قيد النشر أوReplicaSet) بطريقة توضيحية باستخدام مواصفات Horizontal Pod Autoscaler. المعيار الافتراضي للقياس التلقائي هو مقاييس استخدام وحدة المعالجة المركزية (مقاييس الموارد) ، ولكن يمكن دمج المقاييس المخصصة والمقاييس المتوفرة خارجيًا.



فريق Kubernetes aaS من Mail.ruترجمة مقال عن كيفية استخدام المقاييس الخارجية لتوسيع نطاق تطبيق Kubernetes الخاص بك تلقائيًا. لإظهار كيفية عمل كل شيء ، يستخدم المؤلف مقاييس طلب وصول HTTP ، ويتم جمعها باستخدام بروميثيوس.



بدلاً من القياس التلقائي للقرون الأفقية ، فإن Kubernetes Event Driven Autoscaling (KEDA) هو مشغل Kubernetes مفتوح المصدر. إنه يتكامل أصلاً مع مقياس البودات الأوتوماتيكي الأفقي لتوفير قياس تلقائي سلس (بما في ذلك من / إلى الصفر) لأحمال العمل التي تحركها الأحداث. الكود متاح على جيثب .



موجز تشغيل النظام







يوضح الرسم البياني وصفًا موجزًا ​​لكيفية عمل كل شيء:



  1. يوفر التطبيق مقاييس لعدد طلبات HTTP بتنسيق Prometheus.
  2. تم تعيين بروميثيوس لجمع هذه المقاييس.
  3. تم تكوين قشارة Prometheus في KEDA لتوسيع نطاق التطبيق تلقائيًا بناءً على عدد طلبات HTTP.


الآن سوف أخبرك بالتفصيل عن كل عنصر.



كيدا وبروميثيوس



بروميثيوس عبارة عن مجموعة أدوات مراقبة وتنبيه نظام مفتوح المصدر ، وهي جزء من Cloud Native Computing Foundation . يجمع المقاييس من مصادر مختلفة ويحفظها كبيانات سلاسل زمنية. لتصور البيانات ، يمكنك استخدام Grafana أو أدوات التمثيل المرئي الأخرى التي تعمل مع Kubernetes API.



يدعم KEDA مفهوم قشارة - يعمل كجسر بين KEDA والنظام الخارجي. يكون تنفيذ المتسلق محددًا لكل نظام مستهدف ويستخرج البيانات منه. ثم يستخدمهم KEDA للتحكم في القياس التلقائي.



تدعم أدوات القياس مصادر بيانات متعددة مثل كافكا وريديس وبروميثيوس. أي أنه يمكن استخدام KEDA لتوسيع نطاق عمليات نشر Kubernetes تلقائيًا باستخدام مقاييس بروميثيوس كمعايير.



تطبيق الاختبار



يوفر تطبيق اختبار Golang وصول HTTP ويؤدي وظيفتين مهمتين:



  1. يستخدم مكتبة عميل Prometheus Go لأداة التطبيق وتوفير http_requests مقياس يحتوي على عداد دخول. توجد نقطة النهاية التي تتوفر لها مقاييس بروميثيوس بواسطة URI /metrics.



    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. استجابةً للطلب ، يقوم GETالتطبيق بزيادة قيمة المفتاح ( access_count) في Redis. هذه طريقة سهلة لإنجاز المهمة كجزء من معالج HTTP ، وكذلك التحقق من مقاييس Prometheus. يجب أن تكون قيمة المقياس مماثلة للقيمة access_countفي Redis.



    func main() {
           http.Handle("/metrics", promhttp.Handler())
           http.HandleFunc("/test", func(w http.ResponseWriter, r 
    *http.Request) {
               defer httpRequestsCounter.Inc()
               count, err := client.Incr(redisCounterName).Result()
               if err != nil {
                   fmt.Println("Unable to increment redis counter", err)
                   os.Exit(1)
               }
               resp := "Accessed on " + time.Now().String() + "\nAccess count " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    


يتم نشر التطبيق على Kubernetes عبر Deployment. يتم أيضًا إنشاء خدمة ClusterIPتتيح لخادم بروميثيوس تلقي مقاييس التطبيق.



هنا بيان النشر للتطبيق .



خادم بروميثيوس



يتكون بيان نشر بروميثيوس من:



  • ConfigMap - لنقل تهيئة بروميثيوس ؛
  • Deployment - لنشر بروميثيوس في مجموعة Kubernetes ؛
  • ClusterIP - خدمة الوصول إلى UI Prometheus ؛
  • ClusterRole، ClusterRoleBindingو ServiceAccount- لصناعة السيارات في الكشف عن الخدمات في Kubernetes (التلقائي اكتشاف).


هنا هو البيان لتشغيل بروميثيوس .



كيدا بروميثيوس ScaledObject



يعمل المتسلق كجسر بين KEDA والنظام الخارجي للحصول على المقاييس منه. ScaledObjectهو مورد مخصص ، يجب نشره لمزامنة النشر مع مصدر الحدث ، في هذه الحالة Prometheus.



ScaledObjectيحتوي على معلومات حول قياس النشر وبيانات تعريف مصدر الحدث (على سبيل المثال ، أسرار الاتصال واسم قائمة الانتظار) والفاصل الزمني للاستقصاء وفترة الاسترداد وبيانات أخرى. ينتج عنه مورد القياس التلقائي المناسب (تعريف HPA) لتوسيع نطاق النشر.



عند ScaledObjectحذف كائن ، يتم مسح تعريف HPA المقابل له.



هذا هو التعريف ScaledObjectلمثالنا ، يستخدم قشارة Prometheus:



apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
 name: prometheus-scaledobject
 namespace: default
 labels:
   deploymentName: go-prom-app
spec:
 scaleTargetRef:
   deploymentName: go-prom-app
 pollingInterval: 15
 cooldownPeriod:  30
 minReplicaCount: 1
 maxReplicaCount: 10
 triggers:
 - type: prometheus
   metadata:
     serverAddress: 
http://prometheus-service.default.svc.cluster.local:9090
     metricName: access_frequency
     threshold: '3'
     query: sum(rate(http_requests[2m]))


ضع في اعتبارك النقاط التالية:



  1. يشير إلى Deploymentباسم go-prom-app.
  2. نوع الزناد - Prometheus. تم ذكر عنوان خادم Prometheus جنبًا إلى جنب مع اسم المقياس والعتبة وطلب PromQL المراد استخدامه. طلب PromQL - sum(rate(http_requests[2m])).
  3. وفقًا لـ pollingIntervalKEDA ، فإنها تطلب هدفًا من بروميثيوس كل خمس عشرة ثانية. minReplicaCountيتم دعم جراب واحد على الأقل ( ) ، ولا يتجاوز الحد الأقصى لعدد الكبسولات maxReplicaCount(في هذا المثال ، عشرة).


يمكن ضبطه minReplicaCountعلى الصفر. في هذه الحالة ، تقوم KEDA بتنشيط نشر صفر إلى واحد ثم توفر HPA لمزيد من القياس التلقائي. الترتيب العكسي ممكن أيضًا ، أي التحجيم من واحد إلى صفر. في المثال ، لم نحدد صفرًا لأن هذه خدمة HTTP وليست نظامًا عند الطلب.



السحر داخل القياس التلقائي



يتم استخدام العتبة كمحفز لتوسيع نطاق النشر. في مثالنا ، يعرض استعلام PromQL sum(rate (http_requests [2m]))القيمة المجمعة لمعدل طلب HTTP (الطلبات في الثانية) ، والتي يتم قياسها على مدار الدقيقتين الأخيرتين.



نظرًا لأن العتبة هي ثلاثة ، فسيكون هناك واحد أقل طالما أن القيمة sum(rate (http_requests [2m]))أقل من ثلاثة. إذا زادت القيمة ، تتم إضافة أقل من القيمة الإضافية في كل مرة sum(rate (http_requests [2m]))تزيد بمقدار ثلاثة. على سبيل المثال ، إذا كانت القيمة من 12 إلى 14 ، فإن عدد الكبسولات هو أربعة.



الآن دعنا نحاول التكوين!



الضبط المسبق



كل ما تحتاجه هو مجموعة Kubernetes وأداة مساعدة مخصصة kubectl. يستخدم هذا المثال مجموعة minikube، ولكن يمكنك استخدام أي نموذج آخر. يوجد دليل لتثبيت الكتلة .



قم بتثبيت أحدث إصدار على جهاز Mac:



curl -Lo minikube 
https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
&& chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/


قم بتثبيت kubectl للوصول إلى مجموعة Kubernetes الخاصة بك.



قم بتثبيت أحدث إصدار على جهاز Mac:



curl -LO 
"https://storage.googleapis.com/kubernetes-release/release/$(curl -s
https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version


تركيب كيدا



يمكنك نشر KEDA بعدة طرق ، فهي مدرجة في الوثائق . أنا أستخدم YAML المتجانسة:



kubectl apply -f
https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml


يتم تثبيت KEDA ومكوناته في مساحة الاسم keda. أمر للتحقق:



kubectl get pods -n keda


انتظر ، عندما يبدأ مشغل KEDA - يذهب إلى Running State. ثم تابع.



تثبيت Redis مع Helm



إذا لم يكن برنامج Helm مثبتًا لديك ، فاستخدم هذا البرنامج التعليمي . أمر للتثبيت على جهاز Mac:



brew install kubernetes-helm
helm init --history-max 200


helm initتهيئة CLI المحلي وتثبيته أيضًا Tillerفي مجموعة Kubernetes.



kubectl get pods -n kube-system | grep tiller


انتظر حتى تدخل جراب الحارث في حالة التشغيل.



ملاحظة المترجم : يستخدم المؤلف Helm @ 2 ، والذي يتطلب تثبيت مكون خادم Tiller. Helm @ 3 وثيق الصلة حاليًا ، ولا يحتاج إلى جزء من الخادم.



بعد تثبيت Helm ، يكفي أمر واحد لبدء Redis:



helm install --name redis-server --set cluster.enabled=false --set 
usePassword=false stable/redis


تحقق من بدء Redis بنجاح:



kubectl get pods/redis-server-master-0


انتظر حتى يذهب ريديس إلى الحالة Running.



انشر التطبيق



القيادة للنشر:



kubectl apply -f go-app.yaml

//output
deployment.apps/go-prom-app created
service/go-prom-app-service created


تأكد من أن كل شيء بدأ:



kubectl get pods -l=app=go-prom-app


انتظر حتى ينتقل Redis إلى الحالة Running.



نشر خادم بروميثيوس



يستخدم Prometheus Manifest يستخدم Kubernetes Service Discovery لـ Prometheus . يسمح لك باكتشاف كبسولات التطبيقات ديناميكيًا بناءً على ملصق الخدمة.



kubernetes_sd_configs:
   - role: service
   relabel_configs:
   - source_labels: [__meta_kubernetes_service_label_run]
     regex: go-prom-app-service
     action: keep


للنشر:



kubectl apply -f prometheus.yaml

//output
clusterrole.rbac.authorization.k8s.io/prometheus created
serviceaccount/default configured
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
configmap/prom-conf created
deployment.extensions/prometheus-deployment created
service/prometheus-service created


تأكد من أن كل شيء بدأ:



kubectl get pods -l=app=prometheus-server


انتظر حتى يذهب تحت بروميثيوس إلى الحالة Running.



استخدم kubectl port-forwardللوصول إلى واجهة مستخدم Prometheus (أو خادم API) على http: // localhost: 9090 .



kubectl port-forward service/prometheus-service 9090


نشر تكوين القياس التلقائي لـ KEDA



أمر للإنشاء ScaledObject:



kubectl apply -f keda-prometheus-scaledobject.yaml


تحقق من سجلات مشغل KEDA:



KEDA_POD_NAME=$(kubectl get pods -n keda 
-o=jsonpath='{.items[0].metadata.name}')
kubectl logs $KEDA_POD_NAME -n keda


تبدو النتيجة كما يلي:



time="2019-10-15T09:38:28Z" level=info msg="Watching ScaledObject:
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="Created HPA with 
namespace default and name keda-hpa-go-prom-app"


تحقق تحت التطبيقات. يجب تشغيل مثيل واحد لأنه minReplicaCount1:



kubectl get pods -l=app=go-prom-app


تحقق من إنشاء مورد HPA بنجاح:



kubectl get hpa


يجب أن ترى شيئًا مثل:



NAME                   REFERENCE                TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (avg)   1         10        1          45s


التحقق من الصحة: ​​الوصول إلى التطبيق



للوصول إلى نقطة نهاية REST لتطبيقنا ، قم بتشغيل:



kubectl port-forward service/go-prom-app-service 8080


يمكنك الآن الوصول إلى تطبيق Go باستخدام العنوان http: // localhost: 8080 . للقيام بذلك ، قم بتشغيل الأمر:



curl http://localhost:8080/test


تبدو النتيجة كما يلي:



Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Access count 1


تحقق من Redis في هذه المرحلة أيضًا. ستلاحظ access_countزيادة المفتاح إلى 1:



kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
"1"


تأكد من أن قيمة المقياس http_requestsهي نفسها:



curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 1


إنشاء الحمل



سوف نستخدم مهلا ، أداة لتوليد الحمل:



curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 
&& chmod a+x hey


يمكنك أيضًا تنزيل الأداة المساعدة لنظامي التشغيل Linux أو Windows .



شغلها:



./hey http://localhost:8080/test


بشكل افتراضي ، ترسل الأداة المساعدة 200 طلب. يمكنك التحقق من ذلك باستخدام مقاييس Prometheus وكذلك Redis.



curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201


قم بتأكيد قيمة المقياس الفعلية (التي يتم إرجاعها بواسطة استعلام PromQL):



curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'
//output
{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1571734214.228,"1.686057971014493"]}]}}


في هذه الحالة ، تكون النتيجة الفعلية متساوية 1,686057971014493ويتم عرضها في الحقل value. هذا لا يكفي للقياس لأن العتبة التي حددناها هي 3.



المزيد من الحمل!



في المحطة الجديدة ، قم بتتبع عدد كبسولات التطبيق:



kubectl get pods -l=app=go-prom-app -w


دعنا نزيد الحمل باستخدام الأمر:



./hey -n 2000 http://localhost:8080/test


بعد فترة ، سترى HPA يوسع نطاق النشر ويطلق كبسولات جديدة. تحقق من HPA للتأكد من:



kubectl get hpa
NAME                   REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (avg)   1         10        6          4m22s


إذا لم يكن الحمل ثابتًا ، فسيتم تقليل النشر إلى النقطة التي يعمل فيها جراب واحد فقط. إذا كنت تريد التحقق من المقياس الفعلي (الذي تم إرجاعه بواسطة استعلام PromQL) ، فاستخدم الأمر:



curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'


تنظيف



//Delete KEDA
kubectl delete namespace keda
//Delete the app, Prometheus server and KEDA scaled object
kubectl delete -f .
//Delete Redis
helm del --purge redis-server


خاتمة



يسمح لك KEDA بتوسيع نطاق عمليات نشر Kubernetes تلقائيًا (من / إلى الصفر) استنادًا إلى البيانات من المقاييس الخارجية. على سبيل المثال ، استنادًا إلى مقاييس بروميثيوس ، وطول قائمة الانتظار في Redis ، ووقت استجابة المستهلك في سمة كافكا.



تتكامل KEDA مع مصدر خارجي وتوفر أيضًا مقاييس من خلال Metrics Server لـ Horizontal Pod Autoscaler.



حظا سعيدا!



ماذا تقرأ:



  1. أفضل الممارسات والإرشادات لتشغيل الحاويات و Kubernetes في بيئات الإنتاج .
  2. أكثر من 90 أداة مفيدة لـ Kubernetes: النشر والإدارة والمراقبة والأمان والمزيد .
  3. قناتنا حول Kubernetes في Telegram .



All Articles