Kapsamlı Envoy Proxy Rehberi — Özellikler, Best Practice'ler ve Pattern'ler

12 Ağustos 2026 · netologist · 22 dakika, 4555 kelime ·

Envoy Proxy ile sistem kurmak, işletmek ve ölçeklendirmek için derinlemesine, pratisyen seviyesinde bir referans — mimari, xDS, trafik yönetimi, gözlemlenebilirlik, güvenlik ve üretimde kanıtlanmış pattern’leri kapsar.


İçindekiler

  1. Envoy Nedir ve Neden Önemlidir
  2. Temel Mimari
  3. Konfigürasyon Modeli: Statik vs Dinamik
  4. xDS API’leri Açıklaması
  5. Listener’lar ve Filter Chain’leri
  6. Cluster’lar, Endpoint’ler ve Servis Keşfi
  7. Routing (Yönlendirme)
  8. Load Balancing (Yük Dengeleme)
  9. Dayanıklılık: Retry, Timeout, Circuit Breaking, Outlier Detection
  10. Rate Limiting (Hız Sınırlama)
  11. TLS, mTLS ve Güvenlik
  12. Kimlik Doğrulama ve Yetkilendirme (RBAC, ExtAuthz, JWT)
  13. Gözlemlenebilirlik: Stats, Access Log, Tracing
  14. HTTP Filter’lar ve Genişletilebilirlik (Wasm, Lua, ext_proc)
  15. Deployment Pattern’leri
  16. Service Mesh Pattern’leri (Istio, Gateway API)
  17. Performans Ayarlama (Tuning)
  18. Operasyonel Best Practice’ler
  19. Yaygın Tuzaklar ve Anti-Pattern’ler
  20. Hızlı Referans Cheat Sheet

1. Envoy Nedir ve Neden Önemlidir

Envoy, C++ ile yazılmış, yüksek performanslı bir L3/L4/L7 proxy’dir. Aslen Lyft’te geliştirilmiş olup şu anda mezun olmuş bir CNCF projesidir. Envoy, mevcut bir yığına eklenen sıradan bir yük dengeleyici olarak değil, modern, cloud-native, çok dilli (polyglot) servis mimarileri için ağın kendisi olacak şekilde sıfırdan tasarlanmıştır.

Envoy’u farklı kılan temel özellikler:

Envoy’un pratikte kullanıldığı yerler:


2. Temel Mimari

Config’e dokunmadan önce yapabileceğiniz en yüksek getirili şey, Envoy’un terminolojisini anlamaktır.

                     ┌─────────────────────────────────────────┐
                     │                Envoy                     │
                     │                                           │
  Downstream  ─────▶ │  Listener → Filter Chain → HTTP Filters  │ ─────▶  Upstream
  (istemci)          │                     │                     │        (Cluster)
                     │                  Router Filter            │
                     │                     │                     │
                     │                  Route Config              │
                     │                     │                     │
                     │                  Cluster Manager            │
                     └─────────────────────────────────────────┘

Temel yapı taşları:

TerimAnlamı
DownstreamEnvoy’a bağlanan bir host (istemci veya bu Envoy’u çağıran upstream servis).
UpstreamEnvoy’un bağlandığı bir host (Envoy’un proxy’lediği backend servis).
ListenerEnvoy’un bağlanıp (bind) dinlediği isimlendirilmiş bir ağ konumu (IP:port veya Unix domain socket).
Filter ChainBir listener üzerindeki bağlantılara/isteklere uygulanan sıralı network (L3/L4) ve HTTP (L7) filter’lar kümesi.
ClusterEnvoy’un yük dengelemesi yaptığı upstream host’ların (endpoint’lerin) mantıksal grubu — bir Kubernetes Service’e veya Nginx’teki upstream bloğuna benzer.
EndpointBir cluster içindeki tek bir upstream host/instance.
RouteGelen istek özelliklerini (path, header, host) bir hedef cluster’a eşler.
RuntimeEnvoy’un çalışma zamanında okuyabildiği (RTDS aracılığıyla) dinamik özellik-bayrağı/yüzde tabanlı config değerleri.

Envoy temelde olay güdümlü (event-driven) ve non-blocking çalışır; sabit boyutlu bir worker thread havuzu (--concurrency) çalıştırır, her biri kendi event loop’unu yürütür ve bağlantıları bağımsız olarak kabul edip tamamen işleyebilir. Konfigürasyon işleme, stats flushing ve admin için ayrı bir main thread vardır.


3. Konfigürasyon Modeli: Statik vs Dinamik

Envoy konfigürasyonu temelde protobuf tabanlıdır, genellikle YAML veya JSON olarak yazılır.

Statik konfigürasyon

Her şey doğrudan bootstrap config dosyasında tanımlanır. Basittir; öğrenmek için, küçük/tek amaçlı proxy’ler için veya config’in gerçekten hiç değişmediği durumlar için uygundur.

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 10000 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route: { cluster: backend_service }
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: backend_service
    connect_timeout: 5s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: backend_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: backend.internal, port_value: 8080 }

Dinamik konfigürasyon (xDS)

Üretimdeki Envoy deployment’ları neredeyse her zaman dinamik konfigürasyon kullanır; burada bir control plane (Istio Pilot, go-control-plane tabanlı sunucular, Contour, vb.) config’i gRPC stream’leri üzerinden Envoy’a gönderir (push eder). Sıfır kesintili, filo genelinde (fleet-wide) güncellemeleri mümkün kılan şey budur.

dynamic_resources:
  lds_config:
    resource_api_version: V3
    ads: {}
  cds_config:
    resource_api_version: V3
    ads: {}
  ads_config:
    api_type: GRPC
    transport_api_version: V3
    grpc_services:
    - envoy_grpc: { cluster_name: xds_cluster }

Best practice: Dinamik kurulumlarda bile, bootstrap config’i (Envoy’un control plane’ini nasıl bulacağını tanımlayan kısım) statiktir — elle/config-management ile yönettiğiniz tek parça budur, geri kalan her şey xDS’ten akar.


4. xDS API’leri Açıklaması

xDS = “discovery service” (keşif servisi) ailesi. Her harf bir kaynak türüne karşılık gelir:

APITam AdıNeyi Keşfeder
LDSListener Discovery ServiceListener’lar
RDSRoute Discovery ServiceRoute konfigürasyonları
CDSCluster Discovery ServiceCluster’lar
EDSEndpoint Discovery ServiceCluster üyeliği (endpoint’ler/IP’ler)
SDSSecret Discovery ServiceTLS sertifikaları/anahtarları, çalışma zamanında güvenli şekilde teslim edilir
VHDSVirtual Host Discovery ServiceTek tek virtual host’lar (ince taneli RDS)
RTDSRuntime Discovery ServiceÇalışma zamanı özellik bayrakları
ECDSExtension Config Discovery ServiceFilter/extension konfigürasyonu

ADS (Aggregated Discovery Service), yukarıdakilerin tümünü tek bir gRPC stream üzerinden multiplekslerçalıştırır — ayrı LDS/RDS/CDS/EDS stream’leri arasında güncelleme sırası (ordering) yarışlarından kaçınmak için üretimde şiddetle önerilir.

Güncelleme sırası önemlidir

Envoy’un control plane implementasyonları, trafiğin karadeliğe düşmesini (blackhole) önlemek için belirli bir güncelleme sırasına uymalıdır:

CDS (cluster'lar) → EDS (o cluster'lar için endpoint'ler) → LDS (listener'lar) → RDS (cluster'lara referans veren route'lar)

Henüz var olmayan bir cluster’a yeni bir route eklemek = isteklerin başarısız olması demektir. İyi control plane’ler (Istio, go-control-plane’in SnapshotCache‘i) bu sırayı sizin için yönetir, ancak rollout sırasında blackhole’ları debug ederken bunu anlamak esastır.

State-of-the-World vs Incremental (Delta) xDS

Best practice: Birkaç yüzden fazla cluster/route olan herhangi bir ortamda, control-plane ve data-plane kaynak kullanımını kontrol altında tutmak için ADS + Delta xDS kullanın.


5. Listener’lar ve Filter Chain’leri

Bir Listener, bir adrese bağlanır ve kabul edilen her bağlantıya bir filter chain uygular.

Filter chain eşleştirme (matching)

Tek bir listener’ın birden fazla filter chain’i olabilir; bunlar gelen bağlantının özelliklerine göre seçilir — SNI, hedef port, kaynak IP aralığı, ALPN, transport protokolü (örn. tls_inspector ile TLS’in tespit edilmesi).

listeners:
- name: multiplexed_listener
  address:
    socket_address: { address: 0.0.0.0, port_value: 443 }
  listener_filters:
  - name: envoy.filters.listener.tls_inspector
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
  filter_chains:
  - filter_chain_match:
      server_names: ["api.example.com"]
    filters: [ ... api için http_connection_manager ... ]
  - filter_chain_match:
      server_names: ["admin.example.com"]
    filters: [ ... admin için http_connection_manager ... ]

Bu, L4 seviyesinde SNI tabanlı yönlendirmenin arkasındaki mekanizmadır — Envoy, hostname’e göre farklı backend’lere yönlendirmek için TLS’i sonlandırmak (terminate) zorunda bile değildir (bkz. TLS passthrough pattern’leri).

Network filter’lar vs HTTP filter’lar

Sıra önemlidir. HTTP filter’lar istek yolunda listelenme sırasına göre, yanıt yolunda ise ters sırada çalışır. Gerçekte upstream’e yönlendirmeyi yapan router filter’ı her zaman en sonda olmalıdır.

http_filters:
- name: envoy.filters.http.jwt_authn        # 1. önce kimlik doğrula
- name: envoy.filters.http.rbac              # 2. sonra yetkilendir
- name: envoy.filters.http.ext_authz        # 3. opsiyonel harici auth kontrolü
- name: envoy.filters.http.fault             # 4. fault injection (test amaçlı)
- name: envoy.filters.http.cors              # 5. CORS işleme
- name: envoy.filters.http.router            # 6. HER ZAMAN SONDA — gerçek proxy'lemeyi yapar

6. Cluster’lar, Endpoint’ler ve Servis Keşfi

Bir Cluster, Envoy’un “yük dengelemesi yapabileceğim isimlendirilmiş backend grubu” soyutlamasıdır. Envoy birden fazla keşif türünü (discovery type) destekler:

TürAçıklamaKullanım Senaryosu
STATICConfig’te sabit IP listesiTest, gerçekten statik altyapı
STRICT_DNSDNS’i çözer, TTL’de yeniler, dönen tüm IP’leri takip ederGeleneksel DNS tabanlı servis keşfi
LOGICAL_DNSDNS’i çözer ama yalnızca ilk dönen IP’yi kullanır; her yeni bağlantıda tekrar çözerBüyük/rotasyonlu DNS havuzları (örn. cloud LB’ler)
EDSControl plane tarafından Endpoint Discovery Service ile push edilen dinamikKubernetes, service mesh — üretim varsayılanı
ORIGINAL_DSTBağlantının orijinal hedefine (NAT/redirect öncesi) yönlendirirŞeffaf proxy’leme, sidecar interception
clusters:
- name: payments_service
  connect_timeout: 2s
  type: EDS
  eds_cluster_config:
    eds_config: { ads: {} }
  lb_policy: ROUND_ROBIN
  health_checks:
  - timeout: 1s
    interval: 5s
    unhealthy_threshold: 3
    healthy_threshold: 2
    http_health_check:
      path: /healthz
  circuit_breakers:
    thresholds:
    - priority: DEFAULT
      max_connections: 1000
      max_pending_requests: 1000
      max_requests: 1000
      max_retries: 3

Best practice: Kubernetes’te DNS tabanlı keşif yerine (gerçek bir control plane tarafından beslenen) EDS‘yi tercih edin — DNS tabanlı keşifte cache/TTL gecikme sorunları vardır ve endpoint başına sağlık sinyalleri veya ağırlıklı (weighted) yönlendirme gibi özellikleri bu kadar temiz vermez.

Health check: aktif vs pasif

Best practice: İkisini birlikte çalıştırın. Aktif kontroller, trafik onlara ulaşmadan önce ölü host’ları yakalar; outlier detection ise aktif kontrollerin kaçırabileceği “gri hata"yı (host yanıt verir ama kötü yanıt verir) yakalar.


7. Routing (Yönlendirme)

Route konfigürasyonu, virtual host’lara (Host/:authority header’ı ile eşleşir) ve route match kurallarına (path, header, query param, gRPC method, vb.) göre istekleri cluster’lara eşler.

route_config:
  name: main_routes
  virtual_hosts:
  - name: api
    domains: ["api.example.com"]
    routes:
    - match:
        prefix: "/v2/"
        headers:
        - name: "x-canary"
          string_match: { exact: "true" }
      route:
        cluster: api_service_canary
    - match: { prefix: "/v2/" }
      route:
        cluster: api_service_v2
        timeout: 15s
        retry_policy:
          retry_on: "5xx,reset,connect-failure"
          num_retries: 2
    - match: { prefix: "/" }
      route: { cluster: api_service_v1 }

Trafik bölme / ağırlıklı cluster’lar (weighted clusters)

Canary release’ler ve blue/green deploy’lar weighted_clusters ile yapılır:

route:
  weighted_clusters:
    clusters:
    - name: api_service_v1
      weight: 90
    - name: api_service_v2
      weight: 10
  total_weight: 100

Header tabanlı yönlendirme pattern’leri

Yaygın üretim pattern’leri:

route:
  cluster: api_service_v1
  request_mirror_policies:
  - cluster: api_service_v2_shadow
    runtime_fraction:
      default_value: { numerator: 10, denominator: HUNDRED }

Mirroring, yeni bir servis sürümünü gerçek yanıtlar vermeye başlamadan önce gerçek üretim yükü altında doğrulamanın en güvenli yoludur.

Redirect’ler, rewrite’lar ve doğrudan yanıtlar

- match: { prefix: "/old-path" }
  redirect: { path_redirect: "/new-path", response_code: MOVED_PERMANENTLY }
- match: { prefix: "/health" }
  direct_response: { status: 200, body: { inline_string: "OK" } }
- match: { prefix: "/api/" }
  route:
    cluster: backend
    prefix_rewrite: "/"

8. Load Balancing (Yük Dengeleme)

Envoy cluster seviyesinde birden fazla LB politikasını destekler:

PolitikaDavranışEn Uygun Kullanım
ROUND_ROBINSağlıklı host’lar arasında sırayla dönerBasit, homojen backend’ler
LEAST_REQUESTEn az aktif isteğe sahip host’u seçer (varsayılan olarak power-of-two-choices kullanır)Değişken istek maliyeti/süresi — genellikle en iyi varsayılan
RANDOMRastgele seçimYüksek throughput, stateless, basit
RING_HASHBir halka (ring) üzerinde consistent hashingSession affinity / cache dostu yönlendirme
MAGLEVGoogle’ın consistent hashing algoritması, ring hash’ten daha hızlı tablo oluşturmaÖlçekte consistent hashing gerektiren büyük cluster’lar
CLUSTER_PROVIDEDCluster seviyesinde uygulanan özel bir LB implementasyonuna devrederÖzel LB mantığı

Best practice: LEAST_REQUEST, değişken gecikmeli HTTP servisleri için genellikle ROUND_ROBIN‘e tercih edilen varsayılan seçenektir; çünkü round robin, sırf sıra gereği zaten aşırı yüklenmiş bir host’a istek gönderebilir.

Locality-aware ve zone-aware load balancing

Envoy, çağıranla aynı zone/bölge içinde yönlendirmeyi tercih edebilir; yalnızca yerel zone’da kapasite yoksa diğer zone’lara düşer — cross-AZ veri transfer maliyetlerini ve gecikmeyi azaltmak için kritiktir.

cluster:
  common_lb_config:
    locality_weighted_lb_config: {}
    zone_aware_lb_config:
      routing_enabled: { value: 100 }
      min_cluster_size: 6

Session affinity

Stateful backend’ler için, RING_HASH veya MAGLEV‘in bir hash policy’si (cookie, header veya kaynak IP) ile birleştirilmesi, istemci başına tutarlı yönlendirme sağlar:

route:
  cluster: sticky_backend
  hash_policy:
  - cookie:
      name: "session-id"
      ttl: 3600s

9. Dayanıklılık: Retry, Timeout, Circuit Breaking, Outlier Detection

Envoy’un sadece bir router değil, bir dayanıklılık (resiliency) katmanı olarak ününü kazandığı yer burasıdır.

Timeout’lar

İki timeout kavramı önemlidir ve sık sık karıştırılır:

route:
  cluster: backend
  timeout: 10s
  retry_policy:
    retry_on: "5xx,reconnect,connect-failure,refused-stream"
    num_retries: 3
    per_try_timeout: 2s
    retry_back_off:
      base_interval: 0.1s
      max_interval: 1s

Best practice: Her zaman açık (explicit) timeout’lar ayarlayın. Envoy’un varsayılan istek timeout’u 15 saniyedir; bu genellikle gecikmeye duyarlı API’ler için çok uzun, long-polling/streaming için ise çok kısadır — her route için ayrı ayarlayın.

Retry’lar — iki tarafı keskin bıçak

Retry’lar, geçici hatalar için kuyruk gecikmesini (tail latency) ve güvenilirliği iyileştirir, ancak yük altında naif retry’lar bir kesintiyi büyüten retry storm (retry fırtınası) yaratabilir.

Bunu şu şekillerde hafifletin:

retry_policy:
  retry_on: "5xx"
  retry_back_off:
    base_interval: 0.1s
retry_budget:
  budget_percent: { value: 20 }
  min_retry_concurrency: 3

Circuit Breaking

Klasik “N hata sonrası tripleyen” circuit breaker’lardan (örn. Hystrix) farklı olarak, Envoy’un circuit breaker’ları kaynak sınırı kapılarıdır (resource limit gate) — hem Envoy’u hem de upstream’i aşırı yüklenmeye karşı korumak için bir cluster’a eşzamanlı bağlantı/istek/retry sayısını sınırlar:

circuit_breakers:
  thresholds:
  - priority: DEFAULT
    max_connections: 1024
    max_pending_requests: 1024
    max_requests: 1024
    max_retries: 3
    track_remaining: true

Bir eşik (threshold) aşıldığında, yeni istekler süresiz kuyruğa girmek yerine hızlı başarısız olur (fail fast) (503) — bu, kademeli hataya (cascading failure) karşı kritik bir korumadır.

Outlier Detection (pasif health checking)

Aktif bir health-check endpoint’ine ihtiyaç duymadan, gözlemlenen hata oranlarına dayanarak host’ları load balancing havuzundan dışarı atar:

outlier_detection:
  consecutive_5xx: 5
  interval: 10s
  base_ejection_time: 30s
  max_ejection_percent: 50
  split_external_local_origin_errors: true

Best practice kombinasyonu: timeout’lar + retry budget’lı sınırlı retry’lar + circuit breaker’lar + outlier detection birlikte Envoy’un dayanıklılık yığınını (resilience stack) oluşturur — bunlardan sadece birini kullanmak boşluklar bırakır (örn. circuit breaker olmadan retry, kısmi bir kesintiyi tam bir kesintiye dönüştürebilir).


10. Rate Limiting (Hız Sınırlama)

Envoy hem local (Envoy instance başına, harici bağımlılık yok) hem de global (gRPC rate limit servisi üzerinden, filo genelinde paylaşılan state ile) rate limiting’i destekler.

Local rate limiting (token bucket, instance başına)

http_filters:
- name: envoy.filters.http.local_ratelimit
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    stat_prefix: http_local_rate_limiter
    token_bucket:
      max_tokens: 100
      tokens_per_fill: 100
      fill_interval: 60s
    filter_enabled:
      runtime_key: local_rate_limit_enabled
      default_value: { numerator: 100, denominator: HUNDRED }
    filter_enforced:
      runtime_key: local_rate_limit_enforced
      default_value: { numerator: 100, denominator: HUNDRED }
    response_headers_to_add:
    - append_action: OVERWRITE_IF_EXISTS_OR_ADD
      header: { key: "x-local-rate-limit", value: "true" }

Ucuz, hızlı, ağ hop’u yok — ancak her Envoy instance’ı kendi bucket’ını uyguladığından, etkili limitler replica sayısıyla ölçeklenir.

Global rate limiting (ext_ratelimit gRPC servisi ile)

http_filters:
- name: envoy.filters.http.ratelimit
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
    domain: "api_ratelimit"
    rate_limit_service:
      grpc_service:
        envoy_grpc: { cluster_name: ratelimit_service }
      transport_api_version: V3

Tüm filo genelinde state paylaşan bir rate-limit servisinin (örn. Redis destekli envoyproxy/ratelimit) deploy edilmesini gerektirir.

Best practice: Local rate limiting’i ucuz bir ilk savunma hattı olarak (instance başına DoS koruması), global rate limiting’i ise gerçek iş mantığı kotası uygulaması için kullanın (örn. “API anahtarı başına dakikada 100 istek”).


11. TLS, mTLS ve Güvenlik

TLS sonlandırma (downstream)

filter_chains:
- transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
      common_tls_context:
        tls_certificate_sds_secret_configs:
        - name: server_cert
          sds_config: { ads: {} }
        tls_params:
          tls_minimum_protocol_version: TLSv1_2

Upstream’e TLS başlatma

clusters:
- name: secure_backend
  transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
      sni: backend.internal

Servisler arası mTLS (mutual TLS)

İstemci sertifikalarını zorunlu kılmak güçlü servisten servise kimlik sağlar — zero-trust service mesh’lerin temelidir:

common_tls_context:
  tls_certificate_sds_secret_configs: [...]
  validation_context_sds_secret_config:
    name: validation_context
    sds_config: { ads: {} }
require_client_certificate: true

Best practice: TLS sertifikalarını her zaman statik config’te satır içi (inline) dosya yolları yerine SDS (Secret Discovery Service) ile teslim edin — SDS, restart olmadan rotasyona izin verir ve secret’ların düz metin config dosyalarında/git repolarında durmasını önler.

Yaygın TLS tuzakları


12. Kimlik Doğrulama ve Yetkilendirme (RBAC, ExtAuthz, JWT)

JWT kimlik doğrulama

http_filters:
- name: envoy.filters.http.jwt_authn
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
    providers:
      auth0:
        issuer: "https://example.auth0.com/"
        remote_jwks:
          http_uri:
            uri: "https://example.auth0.com/.well-known/jwks.json"
            cluster: auth0_jwks
            timeout: 5s
          cache_duration: 300s
        forward: true
    rules:
    - match: { prefix: "/api/" }
      requires: { provider_name: "auth0" }

RBAC (rol tabanlı erişim kontrolü)

Principal’a (kaynak IP, mTLS kimliği, JWT claim’leri) ve izne (path, method, header) dayalı ince taneli allow/deny kuralları:

http_filters:
- name: envoy.filters.http.rbac
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
    rules:
      action: ALLOW
      policies:
        "admin-access":
          permissions:
          - and_rules:
              rules:
              - url_path: { path: { prefix: "/admin" } }
          principals:
          - authenticated:
              principal_name: { exact: "spiffe://cluster.local/ns/default/sa/admin" }

Harici yetkilendirme (ext_authz)

Allow/deny kararını harici bir gRPC veya HTTP servisine devreder — karmaşık politikalar için kullanışlıdır (OPA/Open Policy Agent çok yaygın bir eşleşmedir):

http_filters:
- name: envoy.filters.http.ext_authz
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
    grpc_service:
      envoy_grpc: { cluster_name: opa_authz }
      timeout: 0.25s
    failure_mode_allow: false

Best practice: failure_mode_allow: false güvenli varsayılandır — authz servisine ulaşılamazsa, varsayılan olarak açık başarısız olmak (fail open) yerine reddedin (deny). Yalnızca açıkça kritik olmayan yollarda true olarak ayarlayın.


13. Gözlemlenebilirlik: Stats, Access Log, Tracing

Envoy kutudan çıktığı haliyle son derece gözlemlenebilirdir — bu, onu tanımlayan güçlü yönlerinden biridir.

Stats (İstatistikler)

Üç tür vardır: counter, gauge, histogram/stats, /stats/prometheus üzerinden expose edilir veya StatsD/dogstatsd sink’leri aracılığıyla push edilir.

Üretimde alarm kurulması gereken kilit istatistikler:

stats_sinks:
- name: envoy.stat_sinks.metrics_service
  typed_config:
    "@type": type.googleapis.com/envoy.config.metrics.v3.MetricsServiceConfig
    grpc_service:
      envoy_grpc: { cluster_name: stats_sink }

Best practice: Yüksek cluster/route sayılarında hangi istatistiklerin gerçekten yayınlandığını filtrelemek için stats_matcher kullanın — sınırsız endpoint başına istatistikler, ölçekte gerçek bir bellek/kardinalite sorununa dönüşebilir.

Access logging

Listener/filter chain başına yapılandırılabilir, yapılandırılmış (structured) log:

access_log:
- name: envoy.access_loggers.file
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
    path: "/dev/stdout"
    log_format:
      json_format:
        start_time: "%START_TIME%"
        method: "%REQ(:METHOD)%"
        path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
        response_code: "%RESPONSE_CODE%"
        upstream_cluster: "%UPSTREAM_CLUSTER%"
        duration_ms: "%DURATION%"
        upstream_host: "%UPSTREAM_HOST%"
        response_flags: "%RESPONSE_FLAGS%"

%RESPONSE_FLAGS% altın değerindedir — bir isteğin neden başarısız olduğunu (UO = upstream overflow, UF = upstream bağlantı hatası, UT = upstream timeout, NR = route yok, RL = rate limit uygulandı, vb.) upstream log’larıyla korelasyon kurma ihtiyacı olmadan söyler.

Dağıtık tracing (distributed tracing)

Envoy, Zipkin, Jaeger, Datadog, OpenTelemetry ve AWS X-Ray’i native olarak destekler:

tracing:
  provider:
    name: envoy.tracers.opentelemetry
    typed_config:
      "@type": type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig
      grpc_service:
        envoy_grpc: { cluster_name: otel_collector }
      service_name: "checkout-service"

Envoy, trace header’larını (traceparent, x-b3-*) otomatik olarak yayar/oluşturur, ancak uygulamaların gelen trace header’larını kendi giden çağrılarında yaymaları gerekir — Envoy, uygulamanızın iş mantığı boyunca span’leri birbirine dikemez.


14. HTTP Filter’lar ve Genişletilebilirlik (Wasm, Lua, ext_proc)

Yerleşik filter’lar yeterli olmadığında, Envoy artan esneklik/karmaşıklık sırasına göre üç genişletme mekanizması sunar:

Lua filter (hızlı yazılır, process içinde)

http_filters:
- name: envoy.filters.http.lua
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
    default_source_code:
      inline_string: |
        function envoy_on_request(request_handle)
          request_handle:headers():add("x-custom-header", "hello")
        end

Hafif header manipülasyonu, basit özel mantık ve prototipleme için iyidir.

WebAssembly (Wasm) filter

Rust, C++, AssemblyScript, TinyGo ile filter’lar derleyin — sandbox’lanmış, Envoy sürümleri arasında taşınabilir, Envoy’un kendisini yeniden derlemeden hot-swap edilebilir.

http_filters:
- name: envoy.filters.http.wasm
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
    config:
      name: "my_filter"
      vm_config:
        runtime: "envoy.wasm.runtime.v8"
        code:
          local: { filename: "/etc/envoy/filters/my_filter.wasm" }

Best practice: Wasm, yeniden kullanılabilir, versiyonlanmış, organizasyon geneli filter’lar için doğru seçimdir (örn. 50 ekip arasında paylaşılan standart bir auth-header-injection filter’ı) — filter mantığını Envoy binary release döngüsünden ayırır.

External Processing (ext_proc)

İstek/yanıt verisini keyfi dönüşüm için process-dışı bir gRPC servisine akıtır — en güçlü ve en yüksek gecikmeli seçenektir, proxy’nin kendisinde bulunmaması gereken karmaşık iş mantığı için idealdir:

http_filters:
- name: envoy.filters.http.ext_proc
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor
    grpc_service:
      envoy_grpc: { cluster_name: ext_proc_service }
    processing_mode:
      request_header_mode: SEND
      response_header_mode: SEND

Aralarında seçim yapma: Hızlı process-içi değişiklikler için Lua → ekipler arasında paylaşılan taşınabilir/yeniden kullanılabilir filter’lar için Wasm → data plane’in hot path’inde tutulmaması gereken ağır/karmaşık mantık için ext_proc (tam dil/kütüphane özgürlüğü karşılığında ağ hop’u gecikmesini kabul ederek).


15. Deployment Pattern’leri

1. Sidecar proxy (service mesh)

Her uygulama pod’u/instance’ı için bir Envoy instance’ı, tüm gelen/giden trafiği şeffaf şekilde yakalar (genellikle iptables yönlendirmesi ile ORIGINAL_DST cluster’ına). Bu, Istio/Consul Connect/App Mesh modelidir. Uygulama kod değişikliği olmadan servis başına mTLS, retry ve gözlemlenebilirlik sağlar.

2. Edge/gateway proxy

Çevrede (perimeter) paylaşılan bir Envoy instance filosu; TLS sonlandırma, dahili servislere yönlendirme, auth, rate limiting işlemlerini yürütür. Bu “API Gateway” pattern’idir (Envoy Gateway, Contour, Gloo, Emissary-ingress, Istio Ingress Gateway).

3. Front proxy + TLS passthrough (çift proxy / SNI routing)

TLS’i hiç sonlandırmayan, yalnızca SNI’ye göre (tcp_proxy + tls_inspector ile) TLS’i gerçekten sonlandıran dahili Envoy instance’larına yönlendiren bir edge Envoy — edge’in özel anahtarları tutmaması gerektiğinde veya istemcilerin gerçek uçtan uca TLS’e ihtiyacı olduğunda kullanılır.

4. Bağımsız L4/L7 yük dengeleyici

Dahili yük dengeleme için HAProxy/Nginx’in yerine geçer — config oluşturma araçları (control plane’ler) reload olmadan güncellemeleri sürebildiğinden genellikle daha basittir.

5. Veritabanı/protokol proxy’si

Envoy’un redis_proxy, mongo_proxy, thrift_proxy, dubbo_proxy ve kafka_broker filter’ları, HTTP olmayan protokolleri de proxy’lemesine izin verir — bu protokoller için de HTTP’de olduğu gibi connection pooling, gözlemlenebilirlik ve auth sağlar.

Sidecar mesh’ler için best practice: Kaynak overhead’ini izleyin — her sidecar pod başına CPU/bellek tüketir. concurrency‘i ayarlayın, LEAST_REQUEST LB kullanın ve kullanılmayan stats/filter’ları devre dışı bırakın (her istekte gereksiz Wasm/Lua çalıştırmak gerçek istek başına gecikme ekler).


16. Service Mesh Pattern’leri (Istio, Gateway API)

Günümüzde çoğu kişinin Envoy ile ilk karşılaşması Istio üzerinden olur; Istio, data plane’i olarak yalnızca Envoy’u kullanır, istiod ise xDS config’ini push eden control plane’dir.

Ham Envoy üzerine katmanlanmış Istio’ya özgü kavramlar

Kubernetes Gateway API

Ingress’in yerini alan daha yeni, vendor-neutral standart — birkaç implementasyon, Envoy’u altta yatan data plane olarak kullanır (Envoy Gateway, Envoy projesinin kendisi tarafından bakımı yapılan referans implementasyondur; ayrıca Istio’nun Gateway API desteği, GKE Gateway, vb.). Envoy’un Listener/Route modeline temiz şekilde eşlenen rol odaklı kaynaklar (GatewayClass, Gateway, HTTPRoute, TCPRoute) getirir.

Best practice: Yalnızca mTLS + gözlemlenebilirlik için bir mesh benimsiyorsanız ve gelişmiş trafik kaydırma (traffic shifting) ihtiyacınız yoksa, klasik sidecar’lardan daha az pod başına overhead ile ihtiyaçlarınızı karşılayıp karşılamadığını görmek için daha basit sidecar’sız bir mesh’i (Istio’nun ambient mode’u; pod başına Envoy “ztunnel” + waypoint proxy’leri kullanır) değerlendirin.


17. Performans Ayarlama (Tuning)

Envoy’a özgü metrik korelasyonuna ihtiyacınız olduğunda genel araçlar yerine gerçekçi, Envoy farkındalıklı benchmark için Nighthawk‘ı (Envoy’un yoldaş yük üreticisi) kullanın.


18. Operasyonel Best Practice’ler

  1. Üretimde her zaman tek bir gRPC stream ile ADS kullanın, ayrı LDS/RDS/CDS/EDS bağlantıları değil — config sapması/sıralama yarışlarından kaçının.
  2. Control plane değişikliklerinizi versiyonlayın ve canary’leyin — kötü bir xDS push’u anında filo genelinde etki yapabilir; control-plane config değişikliklerini tıpkı uygulama deploy’ları gibi kademeli olarak sürün.
  3. Her yerde açık timeout’lar ayarlayın — üretim route’ları için asla varsayılanlara güvenmeyin.
  4. Retry’ları circuit breaker’lar ve retry budget’larla eşleştirin — asla tek başına “num_retries” göndermeyin.
  5. Tüm sertifikalar için SDS kullanın — sertifikaları asla statik config’e veya image’lara gömmeyin.
  6. Sadece ham 5xx sayılarını değil, RESPONSE_FLAGS‘ı, circuit breaker tetiklenmelerini ve outlier ejection’ları izleyin — bayraklar size nedenini söyler.
  7. Güvenlik açısından kritik yollarda ext_authz için failure_mode_allow: false‘ı koruyun.
  8. Birkaç yüz cluster/route’u geçtiğinizde kardinaliteyi kontrol etmek için stats_matcher kullanın.
  9. Shutdown/deploy sırasında bağlantıları düzgünce drain edin (drain_time, listener drain, SIGTERM öncesi healthcheck-fail pattern’leri).
  10. Envoy/Istio sürümlerini dikkatle sabitleyin ve release notlarını okuyun — deprecated/kaldırılmış extension’lar (Envoy’un belgelenmiş bir deprecation politikası vardır, genellikle 2 minor sürüm), upgrade sırasında config’leri sessizce bozabilir.
  11. Rollout’tan önce config değişikliklerini envoy --mode validate ile test edin ve gerçekte neyin aktif olduğunu doğrulamak için admin /config_dump endpoint’ini kullanın.
  12. İlk debug durağınız olarak admin arayüzünün /clusters, /listeners, /stats, /server_info endpoint’lerini kullanın — tahmin etmeyin, gerçek çalışma zamanı state’ini inceleyin.

19. Yaygın Tuzaklar ve Anti-Pattern’ler

TuzakNeden Zarar VerirÇözüm
Circuit breaker’sız retry’larKısmi kesintileri tam kesintiye büyütür (“retry storm”)retry_budget + circuit_breakers ekleyin
Config dosyalarında statik TLS sertifikalarıRestart olmadan rotasyona sokulamaz; secret’lar git/config-management içindeSDS kullanın
Açık route timeout’ları yokVarsayılanlar gecikme profilinize uygun olmayabilir; askıda kalan istekler birikirRoute başına timeout ve per_try_timeout ayarlayın
Ayrı LDS/RDS/CDS/EDS stream’leriRollout sırasında güncelleme sırası yarışları geçici 503’lere yol açarADS kullanın (tek birleştirilmiş stream)
Ölçekte sınırsız endpoint başına istatistikBüyük filolarda bellek/kardinalite patlamasıstats_matcher exclusion’ları
Auth yollarında failure_mode_allow: trueAuthz servisi kapandığında açık başarısız olur — güvenlik açığıKritik yollarda false ayarlayın
Log’larda %RESPONSE_FLAGS%‘ı görmezden gelmekHataların gerçek kök nedenini (UO/UF/UT/NR/vb.) kaçırırsınızAccess log formatına ekleyin, üzerlerine alarm kurun
Idempotent olmayan POST’ları körlemesine retry etmekYinelenen yan etkilere neden olabilir (çift ödeme vb.)retry_on‘ı kısıtlayın, idempotency key kullanın
Filter chain matching yerine tek dev bir filter chainAkıl yürütmesi zor, domain’ler arasında yeniden kullanımı zorSNI/port tabanlı bölünmeler için filter_chain_match kullanın
EnvoyFilter’ı (Istio) ilk çare olarak ele almakIstio upgrade’leri arasında kırılgan, denetlemesi zorNative Istio CRD’lerini tercih edin; EnvoyFilter’ı az kullanın

20. Hızlı Referans Cheat Sheet

# Çalıştırmadan config'i doğrula
envoy --mode validate -c envoy.yaml

# N worker thread ile çalıştır
envoy -c envoy.yaml --concurrency 4

# Admin endpoint'leri (varsayılan port 9901)
GET /stats                  → tüm istatistikler (metin)
GET /stats/prometheus       → Prometheus formatlı istatistikler
GET /clusters               → cluster sağlığı/üyeliği
GET /listeners              → aktif listener'lar
GET /config_dump            → şu anda aktif config (xDS sonrası)
GET /server_info            → versiyon, uptime, state
POST /healthcheck/fail      → bu Envoy'u sağlıksız olarak işaretle (graceful drain)
POST /drain_listeners       → bağlantıları drain etmeye başla

# Kilit yanıt bayrakları (access log'larda)
UO  = Upstream Overflow (circuit breaker tetiklendi)
UF  = Upstream bağlantı hatası (Failure)
UT  = Upstream istek Timeout'u
NR  = Yapılandırılmış Route yok (No Route)
RL  = Rate Limited (hız sınırlandı)
UAEX = Unauthorized (ext_authz reddetti)
LR  = Bağlantı Yerel Reset'i
DC  = Downstream bağlantı sonlandırması

Herhangi bir üretim route’u için önerilen varsayılan dayanıklılık yığını

route:
  timeout: 10s
  retry_policy:
    retry_on: "5xx,reset,connect-failure,refused-stream"
    num_retries: 2
    per_try_timeout: 3s
    retry_back_off: { base_interval: 0.1s, max_interval: 1s }
    retry_budget:
      budget_percent: { value: 20 }
      min_retry_concurrency: 3
cluster:
  circuit_breakers:
    thresholds:
    - priority: DEFAULT
      max_connections: 1000
      max_pending_requests: 1000
      max_requests: 1000
      max_retries: 3
  outlier_detection:
    consecutive_5xx: 5
    interval: 10s
    base_ejection_time: 30s
    max_ejection_percent: 50
  health_checks:
  - timeout: 1s
    interval: 5s
    unhealthy_threshold: 3
    healthy_threshold: 2
    http_health_check: { path: /healthz }

Daha Fazla Okuma


Bu rehber, Envoy’un stabil v3 API yüzeyini ve mevcut Envoy release hatları itibarıyla yaygın üretim pattern’lerini yansıtmaktadır. Extension isimleri/alanları major sürümler arasında değişebilir — her zaman çalıştırdığınız sürüme karşı /config_dump ve resmi API referansı üzerinden çapraz kontrol yapın.