Kubernetes Service Türleri

H. Alperen Selcuk
6 min readApr 8, 2021

örneklerle ClusterIP, NodePort, LoadBalancer

Bu yazımda Kubernetes üzerinde kullandığımız servicelerden uygulamalı bir şekilde bahsedeceğim.

Kubernetes ortamına uygulamanızı taşıdığınız zaman bu uygulamaya gerek dışardan erişim, gerek uygulamanın içeride başka ortamlara (database loglama vs..) erişmi için biz service objesi oluşturuyoruz. Biz service objectini labellar ile poda bağlayabiliyoruz, böylece gelen istekleri pod veya podlara yönlendirebiliyoruz.

Kubernetes servisleri ClusterIp, Nodeport, LoadBalancer olmak üzere 3farklı tür olabilir. Uygulamamızın erişim isteği veya davranışına göre bunlardan birini seçeriz.

örnekler için bir nginx pod yaratalım.

apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

ClusterIP

Cluster içinde yer alan podların birbirleri arasındaki iletişim için atanan IP lerdir. Cluster dışından erişilemez. Deployment anında port expose ettiğimiz anda default olarak ClusterIp atanır.

örnek bir manifest verirsek;

kubectl apply -f clusterip.yaml

burada selector ibaresi bu servisin hangi podla ilişkilendireceğinizi belirtir. deployment yaml file ında labels olarak aynısını olduğunu görebilirsiniz. service i kontrol ettiğimiz ClusterIP olarak bir IP aldığını görebilirsiniz. bu service 8080 portuna istek yaptığımız ClusterIP servisi bu isteğimizi pod un 80 portuna iletecek.

bir tane erişim için pod yaratıp içine girip oradan ulaşmaya çalışalım. herhangi bir pod kullanabilirsin. alpine image kullanarak ya da busybox.

➜  alperen-selcuk kubectl apply -f platform.yam
➜ alperen-selcuk kubectl exec -ti platform /bin/bash

gördüğünüz gibi nginx in default sayfasının geldiğini göreceksiniz. dışarıdan erişim ihtiyacı olmayan uygulamanın backend gibi içeride erişmesi gereken yerleri clusterIP ile yapıyoruz.

NodePort

Bu service türü pod a cluster dışından da erişim için kullanılır. Adı üstünden de anlayabilceğiniz gibi Node üzerinde bir port açarak bunu podla ilişkilendirir. Nodeport eğer manuel vermezseniz 30000–32767 aralığında otomatik olarak atacaktır.

bir tane manifest ile service i açalım.

➜  alperen-selcuk kubectl apply -f 
nodeport.yamlservice/nginx-nodeport created
➜ alperen-selcuk

service e nodeIp sinden erişeceğimiz için detaylı bir şekilde node Iplerini şu şekilde görürürüz.

burada NodeIp sinin 31111 portuna istek yaptıgımız zaman (kaç tane node olduğu önemli değil sayısı fazla olsa bile birine istek yaptığınızda yine aynı şekilde yönlendirme yapılır) pod 80 e istekler iletilecek. http ile istek yaparsak default nginx sayfasını görebiliriz.

eğer cloud platformundaysanız node un public IP sine de denerseniz çalıştığını göreceksiniz.

LoadBalancer

LoadBalancer servisi bir çeşit nodeport servisidir, nodeport da eksiğimiz sadece istek yaptıgımız portun sürekli elle belirlenmesi ya da otomatik atandığında hangi porta atacağımızın değişmesi. production için uygun ortam olmuyor. LoadBalancer burada imdadımıza yetişiyor; podların portunu node bazında değil hepsini birden dışarıdan erişime açar. şekilden de görebilceğiniz gibi bir external IP ye istek yaparız default olarak round-robin şeklinde istekleri podlara dağıtır. klasik dünyadaki loadbalancerdan mantık olarak farkı yok.

Cloud Provideları bunu otomatik bir şekilde yapar. type olarak LoadBalancer seçtiğiniz zaman service için bir dış IP atar. bir örnekle pekiştirelim.

manifesti apply ettiğiniz zaman bir süre providerdan external-ip için bekleyecek pending olarak görebilirsiniz. daha sonra size kullanım için public IP verecek.

servis görüntüsü önceden de belirttiğim gibi NodePort a benziyor fakat burada Node Ip sine değil service üzerinde atanan external-ip ye istek yapacağız ve istek yapacağımız port manifeste verdiğimiz 80 portu olacak.

hatta round robin dağıtıp dağıtmadığına bakalım, öncelikle pod u kaldırıp app=nginx olacak şekilde replicası 2 olan bir deployment yapalım.

daha sonra nginx podlarına girerek default index.html lerini değiştirelim. nginx için /usr/share/nginx/html/index.html altındaki index file ın yerine 2 tane yarattığımız dosyayı atalım birinde 1 birinde 2 yazsın web pageleri gösterecek şekilde. bunu da kubectl cp ile pod a gönderelim.

<html>
<head>
<title> nginx web-page 1 </title>
<h1> nginx web-page 1</h1>
</head>
</html>

(kubectl cp komutu çalıştığınız directoryden istediğiniz podun istediğiniz directorysine dosya kopyalamaya yarar)

şimdi LB de external-ip mize basit bir loop yazalım curl ile çekelim sırayla geldiğini göreceksiniz. isterseniz browserdan da görebilirsiniz.

LoadBalancer on Local Cluster

Eğer cloud providerdan bir kubernetes ortamınız yoksa lokal bir ortamda loadbalancer kullanmak için ayrı bir application yüklemeniz gerek. en çok kullanılanları MetalLB, HAProxy ve NGINX olmaktadır. şimdi lokal bir kubernetes ortamında MetalLB kurarak loadbalancerdan IP alalım.

lokal kubernetes için KinD kullanacağım.

KinD size docker üzerinde kubernetes cluster kurmanızı sağlar.

Kind ile ilgili yazımdan faydalanabilirsiniz.

Kind ile cluster kurduktan sonra yine bir nginx yaratıp load balancer olarak servisi expose edelim.

kubectl create deployment myweb --image=nginxkubectl expose deployment myweb --port 80 --type=LoadBalancer

göreceğiniz gibi External-IP kısmı pending de eğer cloudda olsaydı provider bize bir IP verecekti fakat lokalde bunu kendimiz yapmamız gerekiyor.

service objesini silip bir MetalLB kurulumu yapalım. sitesinden de yardım alabilirsiniz.

MetalLB şartlarından biri kubernetes clusterınızda network configurationun bulunması yani calico ya da flannel işimizi görecektir. flannel yükleyelim.

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

flannel kurduktan sonra kube-system içinde kube-proxy configmapinde strictARP: true olarak set edeceğiz.

kubectl edit configmap -n kube-system kube-proxy

and set:

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true

daha sonra ilgili manifesteri apply ederek metallb kurulumu tamamlayacağız.

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.11.0/manifests/namespace.yaml 
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.11.0/manifests/metallb.yaml

kubectl get all -n metallb-system deyip podların durumuna bakabiliriz. eğer hata alırsanız.

kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"

bu secreti yaratarak podların running olmasını sağlayabilirsiniz.

podlar running olduktan sonra metallb nin kullanacağı IP adreslerini bir configmap ile berlileyeceğiz bunlar da Node subnetinden kullanacağız.

ben 172.19.0.100–172.19.0.200 arası kullanacağım.

apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 172.19.0.100-172.19.0.200

configmap i de apply ettikten sonra tekrar ilk kısımda yaptıgımız expose işlemini yapıp MetalLb IP verecek mi bakalım.

loadbalancerin verdiğimiz range içinden ilk IP yi External-IP olarak atadığını görebiliriz. bu IP ye curl atalım;

default nginx sayfasının geldiğini göreceksiniz.

umarım faydalı bir yazı olmuştur. sağlıklar günler dilerim

h.a.s.

--

--