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?
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
C:\windows\system32\drivers\etc\
hosts dosyasına 192.168.49.2 example.com
satırını eklemelisiniz.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
veyaExact
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.
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
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.