Kubernetes Ingress Nedir?

Kubernetes Ingress, Kubernetes Service nesnelerine HTTP(S) protokolü aracılığıyla dışarıdan erişim sağlamak için kullanılır.

Ingress, cluster'ınızdaki bir grup Service'e erişimi tek bir IP adresi veya domain adı altında birleştirir. Böylece, Ingress kurulumu yapıldıktan sonra dışarıdan uygulamanıza erişmek için tek bir IP adresi veya domain adı kullanabilirsiniz.

Daha önceki Service yazımızda, Pod'larımıza erişebilmek için Service nesnelerini kullanarak dışarıdan gelen istekleri karşılayabilmiştik. Peki dışarıdan gelen trafiği Service nesneleri ile karşılayabiliyorsak neden ayrı bir Ingress nesnesine ihtiyacımız var?

Kubernetes Service Nedir?
Kubernetes Service, bir Pod grubuna sabit bir adresten erişmek için kullanılan bir Kubernetes nesnesidir.

Bu sorunun önemli bir cevabı, her bir LoadBalancer hizmetinin kendi public IP adresine sahip bir Load Balancer servisi gerektirmesidir. Bu hem maaliyet hemde yönetim açısından oldukça zordur.

Ingress ile onlarca Service'e erişim sağlarken yalnızca bir load balancer servisi ile tüm bu ihtiyaçlarımızı giderebilmekteyiz. Bir client, Ingress'e bir HTTP(S) isteği gönderdiğinde, istekteki host ve path ile isteğin hangi Service'e iletileceğini belirleyebiliriz.

Ingress ile Service'ler ile kullanamadığımız cookie-based session affinity özelliğine de kavuşmuş oluruz. Çünkü Ingress, application layer seviyesinde çalışır.

1. Ingress Controller Yüklemek

Ingress kullanmak için bir Ingress controller yüklemek ve yapılandırmak gerekir. Bu controller, farklı platformlarda farklı şekillerde çalışır ve özelleştirilebilirler. Cloud providerlar gerekli Ingress Controller yapılandırmasını otomatik sunarlar.

Eğer minikube kullanıyorsanız Ingress Controller'u kendiniz yüklemelisiniz. Bunun için ingress eklentisini aktif hale getirmemiz gerekiyor. Çünkü minikube kurulumda Ingress Controller disabled olarak gelir.

$ minikube addons list
- default-storageclass: enabled
- kube-dns: enabled
- heapster: disabled
- ingress: disabled
- registry-creds: disabled
- addon-manager: enabled
- dashboard: enabled

Ingress Controller'u aktifleştirmek için şu komutu çalıştırınız.

minikube addons enable ingress

Ardından clusterdaki kube-system namespace'i altında çalışan tüm podları listelediğinizde ingress-controller Pod'unun çalıştığını göreceksiniz.

$ kubectl get pods -n kube-system
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system nginx-ingress-controller-gdts0 1/1 Running 0 18m

2. Ingress Nesnesi Oluşturmak

Kubernetes Ingress oluşturmak için JSON veya YAML formatında bir manifest dosyası hazırlayarak Kubernetes API Server'a göndermemiz gerekiyor. Bunun için ilk olarak manifest dosyamızı görelim:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myingress
  labels:
    name: myingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: my-nodeport-service
            port: 
              number: 80

Buradaki örnekte, example.com a gelen istekler, my-nodeport-service isimli Service'in 80 portuna yönlendirilecektir.

Manifest dosyası hazır olduktan sonra kubectl create veya kubectl apply komutlarından birisi ile Ingress nesnesini oluşturabilirsiniz.

 kubectl create -f ingress-test.yaml

Ardından kubectl get ingress komutu ile oluşturduğumuz ingress nesnesini göreceksiniz.

$ kubectl get ingress
NAME        CLASS   HOSTS         ADDRESS        PORTS   AGE
myingress   nginx   example.com   192.168.49.2   80      2s
💡
Ingress nesnesine atanan IP adresini, belirlediğiniz host adreslerinin DNS A kaydına eklemelisiniz. Yukarıdaki örneği localinizde test etmek için C:\windows\system32\drivers\etc\ hosts dosyasına 192.168.49.2 example.com satırını eklemelisiniz.
💡
Cloud providerlardaki (örneğin GKE'deki) Ingress Controller, Ingress'in bir NodePort Service yönlendirilmesini gerektirir. Ancak bu, Kubernetes'in kendisinin bir gerekliliği değildir.

3. Ingress Host ve Prefix Eşleşmeleri

Üstteki manifest örneğinde gördüğümüz pathType parametresi, gelen isteklerdeki host ve path değerine göre Ingress yönlendirmesinin çalışıp çalışmayacağını belirtir.

Kubernetes 1.18 ve sonraki sürümlerinde, pathType parametresi, aşağıdaki değerleri alabilir:

  • Exact: Yalnızca belirtilen path ile tam olarak eşleşen istekler bu kurala uyar.
  • Prefix: Belirtilen path önekiyle başlayan tüm istekler bu kurala uyar.
  • ImplementationSpecific: Bu değerin eşleştirmesi, IngressClass'a bağlıdır. Uygulamalar bunu ayrı bir pathType olarak ele alabilir veya Prefix veya Exact path türleri ile aynı şekilde ele alabilir.

Bu parametrenin aldığı değere göre davranış şeklini gözlemleyebilmek için aşağıdaki örnekleri inceleyebilirsiniz:

Type Path(s) Request path(s) Matches?
Prefix / (all paths) Yes
Exact /foo /foo Yes
Exact /foo /bar No
Exact /foo /foo/ No
Exact /foo/ /foo No
Prefix /foo /foo, /foo/ Yes
Prefix /foo/ /foo, /foo/ Yes
Prefix /aaa/bb /aaa/bbb No
Prefix /aaa/bbb /aaa/bbb Yes
Prefix /aaa/bbb/ /aaa/bbb Yes, ignores trailing slash
Prefix /aaa/bbb /aaa/bbb/ Yes, matches trailing slash
Prefix /aaa/bbb /aaa/bbb/ccc Yes, matches subpath
Prefix /aaa/bbb /aaa/bbbxyz No, does not match string prefix
Prefix /, /aaa /aaa/ccc Yes, matches /aaa prefix
Prefix /, /aaa, /aaa/bbb /aaa/bbb Yes, matches /aaa/bbb prefix
Prefix /, /aaa, /aaa/bbb /ccc Yes, matches / prefix
Prefix /aaa /ccc No, uses default backend
Mixed /foo (Prefix), /foo (Exact) /foo Yes, prefers Exact

host parametresinin değeri ise ya tam eşleşen bir host değeri yada wildcard içeren host değerleri olabilir. Wildcard host adresleri için aşağıdaki örnekleri inceleyebilirsiniz.

Host Host header **Match? **
*.foo.com bar.foo.com Matches based on shared suffix
*.foo.com baz.bar.foo.com No match, wildcard only covers a single DNS label
*.foo.com foo.com No match, wildcard only covers a single DNS label

4. Ingress Nasıl Çalışır?

Ingress nesnesinin nasıl çalıştığını anlamak için bir örnek üzerinden konuşalım.

  • Bir client Ingress yapılandırmasında eşleşen bir host adresine istek attığında önce DNS Server, Ingress Controller'un IP adresini döndürür.
  • Ardından client, bu IP adresine, yani Ingress Controller'a HTTP(S) isteğini gönderir.
  • Gelen isteğin header'ında yer alan host adresinden, istemcinin hangi Service'e erişmeye çalıştığını belirlebir.
  • İlgili Service ile ilişkili Endpoints nesnesi aracılığıyla Pod IP'leri bulunur ve biri seçilir.
  • Ingress Controller, bu isteği, elde ettiği Pod IP adresine iletir.
💡
Örnekte de gördüğünüz gibi Ingress Controller gelen isteği Service nesnesine iletmez. Service nesnelerinden sadece trafiğin yönlendirileceği Pod'ları veya harici hedefleri seçmek için kullanılır.

5. Birden Fazla Host ve Path İle Aynı Anda Çalışmak

Ingress manifest dosyasına yakından bakarsanız, hem rule hem de path için array verdiğimizi ve dolayısıyla birden çok öğe içerebileceğini görürsünüz. Ingress için birden fazla host ve path içeren örneği aşağıdaki kodda inceleyebilirsiniz.

...
- host: example.com
  http:
    paths:
      - path: /test
        pathType: Prefix
    	backend:
          serviceName: test
          servicePort: 80
- host: test.example.com
  http:
    paths:
      - path: /foo
        pathType: Prefix
    	backend:
          serviceName: foo
          servicePort: 80
      - path: /bar
        pathType: Prefix
        backend:
          serviceName: bar
          servicePort: 80

6. TLS Trafiğini Aktif Etmek

Şimdiye kadarki başlıklarda bir Ingress'in HTTP trafiğini nasıl yönlendirdiğini gördük. Şimdi ise HTTPS trafiği için TLS'i nasıl yapılandırılacağına hızlıca bir göz atalım.

6.1. TLS Sertifika Oluşturmak

Client, Ingress Controller'a bir TLS bağlantısı açtığında, controller direkt olarak TLS bağlantısını sonlandırır. Client ile controller arasındaki iletişim şifrelenirken controller ile Pod arasındaki iletişim şifrelenmez. Bu nedenle Pod'da çalışan uygulamanın TLS'i desteklemesi gerekmez.

Örneğin, Pod bir web sunucusu çalıştırıyorsa, yalnızca HTTP trafiğini kabul edebilir ve Ingress Controller'ın TLS ile ilgili her şeyi halletmesini bekler. Controller'ın bunu yapmasını sağlamak için Ingress için bir sertifika ve private key eklemeniz gerekir. İkisinin, daha sonra Ingress manifestinde başvurulan Secret adlı bir Kubernetes nesnesinde saklanması gerekir.

Öncelikle, private key ve sertifikayı oluşturmanız gerekir:

openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj /CN=test.example.com

Sonra Secret'i şu şekilde iki dosyadan yaratırsınız:

kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key
💡
Sertifikayı kendimiz imzalamak yerine, bir CertificateSigningRequest (CSR) oluşturarak sertifikayı imzalatabilirsiniz. Kullanıcılar veya uygulamaları, normal bir sertifika isteği oluşturabilir, bunu bir CSR'ye koyabilir ve ardından bir operatör veya otomatik bir süreç, isteği şu şekilde onaylayabilir: kubectl certificate approve <name of the CSR>

Private key ve sertifika artık tls-secret adlı Secret'da saklanmaktadır. Artık Ingress nesnenizi test.example.com için HTTPS isteklerini de kabul edecek şekilde güncelleyebilirsiniz. Ingress manifest dosyası şimdi aşağıdaki gibi görünmelidir.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubia
spec:
  tls:
  - hosts:
    - test.example.com
    secretName: tls-secret
  rules:
  - host: test.example.com
    http:
      paths:
        - path: /
          backend:
          serviceName: kubia-nodeport
          servicePort: 80

Artık HTTPS ile Ingress trafiğini başlatabilirsiniz.


Sıradaki yazı ile eğitim serisine devam edebilirsiniz.

Kubernetes Volume Nedir?
Kubernetes Volume, Container nesnelerinin kullandığı disk kaynaklarıdır