Yazılara geri dön
Yazı

Latency SLO-Based Canary Analysis and Auto Rollback in Argo Rollouts

Latency SLO-Based Canary Analysis and Auto Rollback in Argo Rollouts

Argo RolloutsPrometheusSLOCanaryDevopsKubernetesObservability

Benim ortamımda, Argo Rollouts'te kanary promociónunun temel kapısı olarak hata oranından gecikme SLO'larına geçtim. Gecikme doğrudan kullanıcı deneyimini etkiler ve 5xx hatalarının artması beklemek zaten hizmetin bozulduğu anlamına gelir. Hata oranları yükseldiğinde kullanıcılar zaten deneyimde kayıt yaşamış olur. Gecikme SLO'larını kullanarak performans gerilemelerini kullanıcıların fark etmesinden önce yakalar ve otomatik geri alma devreye alır.

Temel fikir basit: bir gecikme SLO tanımlayın (örneğin %95'lik persentil istek süresi < 200ms), bunu Prometheus metriği olarak açın ve Argo Rollouts'un kanary adımlarında bu metriği analiz etmesini sağlayın. SLO ihlal edilirse rollout durur ve belirlenen hata sınırına göre otomatik geri alma tetiklenebilir.

Nasıl kurduğumu anlatayım. İlk olarak uygulamanızın gecikme histogramlarını Prometheus üzerinden gösterdiğinden emin olun. Ben Go servislerimde Prometheus istemci kütüphanesini kullanarak istek süresini kaydediyorum:

httpDurationsVec := prometheus.NewHistogramVec(prometheus.HistogramOpts{
    Name: "http_request_duration_seconds",
    Help: "Duration of HTTP requests",
    Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
}, []string{"method", "endpoint", "status"})

Ardından Prometheus kuralınız veya kayıt kuralınızda %95'lik persentili hesaplayın:

- record: job:http_request_duration_seconds:quantile95
  expr: histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, job))

Bu bize temiz bir metrik verir: job:http_request_duration_seconds:quantile95. Ben bunu job etiketiyle işaretliyorum böylece belirli servisleri hedefleyebiliyorum.

Argo Rollouts'te bu metriği bir AnalysisTemplate içinde referans gösteriyorum. Ben latency-slo-analysis.yaml adında bir şablon oluşturdum:

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: latency-slo
spec:
  args:
  - name: service-name
  metrics:
  - name: latency-slo
    interval: 30s
    count: 5
    provider:
      prometheus:
        address: http://prometheus.monitoring.svc:9090
        query: |
          job:http_request_duration_seconds:quantile95{job="{{args.service-name}}"} < 0.2
    successCondition: result == "true"
    failureLimit: 3
    # Optional: add failureLimitSteps to auto-rollback after N failures

Sorgu %95'lik persentil gecikme 200ms'nin altında ise 1 (true), değilse 0 döndürür. Argo Rollouts successCondition: result == "true" koşulunu geçiş olarak kabul eder. 5 aralık (2,5 dakika) sonunda 3 veya daha fazla başarısızlık olursa analiz başarısız olur.

Daha sonra bu şablonu bir Canary adımında kullanıyorum:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-service
spec:
  strategy:
    canary:
      steps:
      - setWeight: 20
      - analysis:
          templateName: latency-slo
          args:
          - name: service-name
            value: my-service
      - setWeight: 50
      - analysis:
          templateName: latency-slo
          args:
          - name: service-name
            value: my-service

%20 ve %50 trafikte Argo gecikme analizini çalıştırır. Gecikme 5 kontrolden 3'ünde 200ms'i aşarsa adım başarısız olur. Varsayılan olarak Argo rollout'u duraklatır. Otomatik geri alma için şu ayarı yapıyorum:

spec:
  strategy:
    canary:
      autoRollbackOnFailure: true

Bu şekilde herhangi bir kanary adımında gecikme SLO ihlali oluşursa Argo otomatik olarak stabil sürüme geri döner.

Bir dikkat etmen gereken şey: Prometheus sorgunuzun eksik verilere karşı dayanıklı olduğundan emin olun. Hedef servis bir scrape sırasında trafik taşımıyorsa sorgu satır döndürmeyebilir ve bu da Argo tarafından hata olarak yorumlanabilir. Ben sorguyu absent() ile sarıyorum ya da or kullanarak güvenli bir varsayılan değer veriyorum:

query: |
  (job:http_request_duration_seconds:quantile95{job="{{args.service-name}}"} < 0.2) or on() vector(0)

Bu sayede metrik yoksa (istek yoksa) 0 (false) olarak varsayılır ve bu bir başarısızlık tetikler — güvenli bir yaklaşım: trafik yoksa bir şeylerin ters gittiği anlamına gelir.

Bu yöntemin kaynak sınırlamaları, verimsiz veritabanı sorguları veya harici API gecikmesi gibi yavaş rolloutları hata oranına dayalı analizlerin kaçırdığı şekilde yakaladığını gördüm. Daha önce hata oranı yerine gecikme SLO'larını kullanma yazımda da belirttiğim gibi bu yaklaşım "mı bozuk?" sorusunu "mı hızlı yeterli?" sorusuyla değiştirir — kullanıcı odaklı daha iyi bir kapı sağlar.

İpucu: Başlangıçta konservatif bir gecikme eşiğiyle başlayın (örneğin 500ms) ve bazeleri doğruladıkça bu eşiği sıkılaştırın. SLO'ları zorunlu kılmadan önce Grafana'yı kullanarak kanary adımları sırasında gerçek %95'lik persentili izleyin.


Kapak görseli: TSGT L. HERNANDEZ, USAF · PDM (Wikimedia Commons / kamu malı) · https://commons.wikimedia.org/wiki/File:Cobra_Dane_radar_system_operation_status_control_console_room.jpg