Kubernetes Servis Tipleri

Kubernetes servis tipleri nelerdir? Hangisini ne zaman kullanmalıyız?

NodePort, LoadBalancer, ClusterIP, ExternalName & Ingress

Kubernetes'te servislerinizi yayınlarken ve/veya dış ağa açmak istediğiniz zaman bu kavramlar ile karşılaşıp kendinizi bunlar nedir ve hangisini ne zaman kullanacağım, gibi soruları düşünürken bulabilirsiniz. Bu kavramlar cluster'ınıza dahili veya harici trafik almanın farklı yollarıdır ve hepsi bu işi birbirinden farklı yapar. Hadi gelin öncelikle k8s servis tiplerini ve nasıl çalıştıklarına göz atalım.

ClusterIP

Bu varsayılan servis tipidir. Servisinizi internal bir ip ile yayınlar ve sadece cluster içerisinden (diğer servislerden) erişilebilir hale getirir. Eğer bu tipteki bir servise erişim ihtiyacınız olur ise bunu kubernetes proxy kullanarak yapabilirsiniz.

kubectl proxy --port=8080

Yukarıdaki komut ile kubernetes proxy'i başlatıp servislere erişmek için API havuzunda yüzmeye başlayabilirsiniz. 🙂 Nasıl mı?

http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/

Yukarıdaki taslak üzerinden giderek servislerinize proxy'i açtığınız cihaz üzerinden erişebilirsiniz. Örnek olarak;

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

ClusterIP'den bahsetmişken proxy'e değinmeden geçmek olmazdı.

Kubernetes Proxy'i ne zaman kullanabilirim?

Servislerde hata ayıklama (debugging) veya herhangi bir sebeple lokal cihazınızdan erişim ihtiyacı olduğunda, örneğin; internal dashboard'lara bakmak veya internal trafiği izlemek vb. gibi durumlarda ClusterIP ile çalışan bir servise proxy ile bağlanma ihtiyacı duyabilirsiniz.

Örnek bir ClusterIP servis YAML içeriği aşağıdaki gibi görünebilir;

apiVersion: v1
kind: Service
metadata:  
  name: my-internal-service
spec:
  selector:    
    app: my-app
  type: ClusterIP
  ports:  
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

NodePort

NodePort tipi, dış trafiği doğrudan hizmetinize almanın en ilkel yoludur. Adından da anlaşılacağı üzere servisi her node üzerinde statik bir port ile yayınlar. Servisler <NodeIP>:<NodePort> şeklinde erişilebilir olur.

Örnek bir NodePort servis YAML içeriği aşağıdaki gibi görünebilir;

apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
spec:
  selector:    
    app: my-app
  type: NodePort
  ports:  
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP

ClusterIP'nin yaml'ı ile karşılaştırdığınızda 2 fark göreceksiniz; ilki type: NodePort olması ikincisi ise ports altında bir port tanımının (nodePort:xxxx) olması. Bu port'u belirtmezseniz rastgele bir port açıp tanımlayacaktır. Birçok servisi yönettiğiniz bir platformda bu port seçimini kubernetes'in yönetmesine izin vermeniz faydalı olabilir. Varsayılan olarak 30000-32767 port aralığını kullanmaktadır.

Bu metot fiziksel load balancer üzerinden yönlendirme ile prod ortamlarında kullanılabilir, eğer bu mümkün değil ise maliyet hassasiyeti içeren durumlarda veya demo uygulamalarda da kullanılabilir.

LoadBalancer

LoadBalancer tipi, bir servisi internete sunmanın standart yoludur. Harici yük dengeleyicilerini (external load balancers) destekleyen bulut sağlayıcılarda bu tipi ayarladığımızda servis için bir yük dengeleyicisi sağlarlar. Yük dengeleyicinin oluşturulması eşzamansız (async) olarak gerçekleşir ve servisin .status.loadBalancer alanına aşağıdaki gibi bilgileri gelir.

Örnek bir LoadBalancer servis YAML içeriği aşağıdaki gibi görünebilir;

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 7377
  clusterIP: 10.0.177.244
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 192.0.3.77

Harici yük dengeleyiciden gelen trafik direkt arkadaki pod'lara yönlenir ve bulut sağlayıcısı yükü nasıl dengeleyeceğine karar verir.

Bir servisi doğrudan dışarıya açmak istediğimizde bu tipi kullanabiliriz. Belirtilen porttaki tüm trafik servise iletilecektir. Bu HTTP, TCP, UDP, gRPC, websockets gibi hemen hemen her tür trafiği gönderebileceğiniz anlamına gelir. En büyük dezavantajı, LB ile sunduğunuz her servisin kendi IP adresini alması ve servis başına LoadBalancer için ödeme yapmanız gerektiğinde biraz pahalı olması olabilir. LoadBalancer tipi daha çok bulut tabanlı hizmet sağlayıcılarında görülse de MetalLB gibi çözümler ile on-premise ortamlarda da kullanılabilmektedir. MetalLB detayları için bu makaleyi inceleyebilirsiniz.

ExternalName

ExternalName tipi servisler, tipik bir selector ile değil bir DNS adı ile eşleşirler. Bu eşleşmeyi spec.externalName alanında belirtiriz. Port'ları veya endpoint'leri de tanımlanmaz. Bir alias'ın external bir servise döndürülmesi gibi düşünebiliriz. Örneğin aşağıdaki yapılandırma my-externalname-service isimli servisi database.kubernetesturkey.com adresi ile eşler.

Örnek bir ExternalName servis YAML içeriği aşağıdaki gibi görünebilir;

apiVersion: v1
kind: Service
metadata:
  name: my-externalname-service

spec:
  type: ExternalName
  externalName: database.kubernetesturkey.com

ExternalName tipinde yönlendirme işlemi bir proxying veya forwarding ile değil, DNS seviyesinde gerçekleşmektedir. Örnekteki servise internal erişim isteklerinde DNS servisi CNAME düzeyinde yer alan database.kubernetesturkey.com değerini dönecektir. Bu yanıtı alan istemciler taleplerini bu adrese yapacaklardır.

Bu tip, henüz kubernetes ortamlarına getirilemeyen servisler için faydalı olabilir. Servis k8s ortamına geldiğinde tipini değiştirerek yeniden kullanım da sağlanabilir.

Ingress

Bu kavramların yanında sıkça duyulan ingress yukarıdakiler gibi bir kubernetes servis tipi değildir. Ingress gelen isteklerin servislerimize erişebilmesini sağlayan kurallar bütünüdür. Controller yapılandırmaları ile birden çok servisin önünde durur ve cluster'da bir akıllı yönlendirici veya giriş noktası (entrypoint) görevi görür. Farklı yeteneklere sahip birçok ingress türü (Google Cloud Load Balancer, NGiNX, Contour, Istio etc.) vardır. Bir http(s) load balancer'da path bazlı veya subdomain bazlı yönlendirmeler yapabilirsiniz. Örneğin foo.kubernetesturkey.com'daki her şeyi foo hizmetine veya kubernetesturkey.com/bar yolu altındaki her şeyi bar hizmetine yönlendirebilirsiniz.

Örnek bir L7 HTTP Load Balancer ingress YAML içeriği aşağıdaki gibi görünebilir;

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: other
    servicePort: 8080
  rules:
  - host: foo.kubernetesturkey.com
    http:
      paths:
      - backend:
          serviceName: foo
          servicePort: 8080
  - host: kubernetesturkey.com
    http:
      paths:
      - path: /bar/*
        backend:
          serviceName: bar
          servicePort: 8080

Aynı IP adresi altında birden çok servisi hizmete sunmak istiyorsanız ve bu servislerin tümü aynı L7 protokolünü (tipik olarak HTTP) kullanıyorsa ingress kullanılabilir. ClusterIP tipindeki servislerinizi prod ortamlarınızda ingress ile de yayına alabilirsiniz.

Servis tiplerinden ve ingress'ten bahsettik. Bir sonraki yazımda görüşmek üzere. 🙂

Yorum Yapın