Istio ServiceEntry'de DNS Resolution Ayarı

Selamlar, bu yazıda Istio ServiceEntry'nin en sinsi alanlarından birine, resolution alanına bakacağız. Mesh dışındaki bir servise bağlanmaya çalışıp 'YAML doğru görünüyor ama timeout yiyoruz' dediğiniz oldu mu? Bende oldu, hem de bir sürü kez. Sorunun büyük çoğunluğu bu küçük alanın yanlış seçilmesinden çıkıyor.

resolution, Envoy'a 'bu hostname'i nasıl bir IP'ye çevireyim' sorusunun cevabını veriyor. Dört seçeneğimiz var: DNS, DNS_ROUND_ROBIN, STATIC ve NONE. İsimleri yakın ama davranışları çok farklı. Hadi tek tek bakalım.

Resolution seçenekleri kabaca

Önce kuş bakışı bir özet:

  • DNS: Envoy hostname'i kendisi resolve eder, gelen IP'leri cluster endpoint'i olarak kullanır.
  • DNS_ROUND_ROBIN: DNS gibi ama gelen IP'ler arasında dengeli dağıtım yapar.
  • STATIC: DNS yok; siz IP'leri elinizle yazıyorsunuz.
  • NONE: Envoy hiç çözmez, uygulamanın hedeflediği IP'ye doğrudan iletir.

Hangisini ne zaman seçeceğimiz, dışarıdaki servisin altyapısına göre değişiyor.

DNS resolution

En çok kullanılan mod bu. Envoy hostname'i çözer ve TTL süresince cache'ler. Bulut sağlayıcılarının çoğu API'si bu modla uyumlu çalışır.

apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: external-api-dns
spec:
  hosts:
    - api.example.com
  location: MESH_EXTERNAL
  ports:
    - number: 443
      name: https
      protocol: HTTPS
  resolution: DNS

Arka planda olan şu: uygulama api.example.com'a istek atar, sidecar yakalar, Envoy DNS sorgusu yapar, dönen IP'lerden birini seçip bağlantıyı kurar. Sonuçlar TTL boyunca cache'te tutulur. Çalışıp çalışmadığını şöyle doğruluyoruz:

istioctl proxy-config endpoints deploy/my-app | grep example.com

Endpoint listesi boşsa Envoy ismi çözememiş demektir; ilk bakacağınız yer pod'un DNS politikası ve cluster içinden nslookup.

DNS_ROUND_ROBIN ne zaman gerek?

DNS modunda Envoy cluster endpoint olarak ilk dönen IP'ye yapışma eğilimindedir; diğerlerine ancak hata aldığında geçer. Bazı dış servislerde bu istediğiniz davranış olmayabilir, özellikle DNS arkasında birden fazla backend varsa ve trafiği dengeli dağıtmak istiyorsanız.

spec:
  hosts:
    - api.example.com
  resolution: DNS_ROUND_ROBIN
  ports:
    - number: 443
      name: https
      protocol: HTTPS

Bence DNS_ROUND_ROBIN'i ancak ihtiyaç netse açın. Aksi halde plain DNS daha öngörülebilir davranıyor.

STATIC resolution

DNS'e güvenmediğiniz, IP'lerin sabit olduğu on-prem servisler için biçilmiş kaftan. Envoy hiçbir DNS sorgusu yapmaz, siz endpoint listesini yazarsınız.

apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: legacy-static
spec:
  hosts:
    - legacy-service.company.com
  location: MESH_EXTERNAL
  ports:
    - number: 8080
      name: http
      protocol: HTTP
  resolution: STATIC
  endpoints:
    - address: 192.168.1.100
      ports:
        http: 8080
    - address: 192.168.1.101
      ports:
        http: 8080

Endpoint'lere locality ve labels ekleyip locality-aware load balancing veya subset routing yapabilirsiniz. Tek dikkat: STATIC modunda endpoint listesi vermeyi unutursanız bağlantı hiç kurulmaz, en sık karşılaşılan hata bu.

NONE resolution

NONE, Envoy'un işin içinden çıkmadığını söylediği mod. Genellikle wildcard hostname'lerde kullanılır.

spec:
  hosts:
    - "*.example.com"
  resolution: NONE
  ports:
    - number: 443
      name: https
      protocol: HTTPS

Uygulama DNS'i kendisi çözüyorsa ve siz yalnızca trafiğin geçmesine izin vermek istiyorsanız NONE iş görür. Ama bu modda Envoy size endpoint sağlığı, locality dengelemesi gibi şeyler sunmaz, sadece paketi öbür tarafa iletir.

Sık karşılaşılan tuzaklar

  • STATIC seçip endpoint vermemek: YAML geçerli görünür, validator de patlamaz, ama Envoy cluster boş kalır ve istemci timeout yer.
  • AWS ELB'ye STATIC yazmak: ELB'nin IP'si değişir, bir gün hiç beklemediğiniz anda bağlantı kopar. Bu tür servisler için DNS doğru seçim.
  • Bayat DNS cache'i: Dış servis IP değiştirdi ama sidecar hala eskisini deniyor. dnsRefreshRate'i mesh seviyesinde 60s gibi makul bir değere çekin, ya da geçici çözüm olarak kubectl rollout restart ile sidecar'ı tazeleyin.
  • Wildcard host ile DNS denemek: Wildcard'da Envoy neyi resolve edeceğini bilemez. Bu durumda NONE doğru cevap.

DNS refresh rate'i agresif kısmamak gerekiyor; her saniye DNS sorgulayan bir mesh, DNS sunucularınızı boş yere yorar. 60-300 saniye aralığı çoğu durum için yeter.

Kapanış

resolution alanı küçük bir detay gibi duruyor ama mesh içinden dış dünyaya açılan her bağlantının davranışını belirliyor. Şahsi kanaatim, default'a DNS ile başlayın, on-prem sabit IP varsa STATIC'e geçin, wildcard varsa NONE deyin, DNS_ROUND_ROBIN'e ise gerçekten ihtiyaç doğunca dönün. Umarım faydalı olur, bir sonraki yazıda görüşmek üzere.