Merhabalar,

Yoğun bir istek üzerine, Linux Öğreniyorum Serisinin yanında Kubernetes Öğreniyorum serisine de başladım. Genç arkadaşlarım sağ olsun. 😊

Kubernetes dünyasında, temel bileşenleri anlamak ve doğru şekilde yapılandırmak başarılı bir uygulama yönetimi için büyük önem taşıyor. Bu serinin ilk bölümünde, Kubernetes’in temel birimleri olan pod, servis ve namespace gibi bileşenleri Oracle Kubernetes Engine (OKE) üzerinde uygulamalı olarak tanıyacağız. Özellikle, basit bir nginx uygulaması oluşturup, onu dış dünyaya açarak erişilebilir hale getireceğiz. Bu adımlarla hem Kubernetes’in çalışma prensiplerini daha yakından tanıyacak hem de gerçek bir uygulama üzerinden bu yapıların işleyişini gözlemlemiş olacağız.

Öncelikle Kubernetes nedir?

Kubernetes, konteynerleştirilmiş uygulamaları yönetmek, dağıtmak ve ölçeklendirmek için geliştirilmiş açık kaynaklı bir platformdur. Konteynerler, yazılımı bağımsız bir ortamda çalıştırmak için gereken tüm bağımlılıkları bir araya getirerek taşınabilir ve izole uygulamalar oluşturmayı sağlar. Ancak bir uygulama büyüdükçe ve çok sayıda konteyner kullanıldığında, bunları yönetmek zorlaşır. İşte bu noktada Kubernetes devreye girer ve bu karmaşık yapıyı düzenleyerek bir “orkestratör” görevi görür.

Örneğin, bir e-ticaret sitesi kurduğunuzu düşünün. Bu sitenin farklı işlevleri vardır: ödeme işlemleri, ürün önerileri, kullanıcı hesapları, veri tabanı yönetimi gibi. Her işlevi bir konteyner olarak düşünebilirsiniz. Kubernetes, bu farklı işlevleri bir araya getirerek sitenizin kesintisiz çalışmasını sağlar ve kullanıcı sayısı arttığında (örneğin, bir indirim döneminde) otomatik olarak daha fazla konteyner açarak yükü dengeler.

Neden acaba bu kadar popüler?

Kubernetes, konteyner teknolojilerinin gelişimiyle birlikte hızla popüler hale geldi çünkü yazılım dünyasında birçok zorluğu çözüyor. İşte bu popülerliğin arkasındaki başlıca nedenler:

Taşınabilirlik: Kubernetes, konteynerlere dayandığı için farklı bulut sağlayıcılarında veya veri merkezlerinde sorunsuzca çalışır. Örneğin, bir uygulamanızı önce şirket içi sunucularda çalıştırabilir, daha sonra aynı uygulamayı kolayca buluta taşıyabilirsiniz.

Otomatik Ölçeklendirme: Kubernetes, kullanıcı sayısındaki değişikliklere veya trafik dalgalanmalarına göre uygulama konteynerlerini otomatik olarak ölçeklendirebilir. Örneğin, bir haber sitesinde popüler bir makale yayınlandığında kullanıcı sayısında ani bir artış yaşanabilir. Kubernetes, sunucu yükünü yönetmek için yeni konteynerler açar ve böylece site yavaşlamaz veya çökmez.

Kendi Kendini Onarma: Kubernetes, belirli bir konteyner çöktüğünde otomatik olarak yeniden başlatır veya yenisini başlatır. Bu da uygulamanın kesintisiz çalışmasını sağlar. Örneğin, bir banka uygulamasında bir ödeme hizmeti çökerse, Kubernetes bunu fark eder ve sorunu gidererek hizmetin devam etmesini sağlar.

Kaynak Verimliliği: Kubernetes, kullanılmayan kaynakları minimize ederek maliyetleri düşürmeye yardımcı olur. Birçok farklı işlevi aynı kaynakları kullanarak çalıştırdığı için sunucularda atıl kaynak kalmaz. Örneğin, aynı fiziksel sunucuda birden fazla uygulamayı çalıştırarak sunucu kapasitesinden tasarruf edebilirsiniz.

Kubernetes, esnek ve dayanıklı yapısı sayesinde büyük ve karmaşık uygulamaları bile kolayca yönetilebilir hale getirir. Bu nedenle, dünya genelinde teknoloji şirketleri, özellikle de mikroservis mimarisini benimseyen firmalar, Kubernetes’i tercih etmektedir.

Bu Kubernetes teknolojisi hangi bileşenlerden oluşuyor?

Kubernetes’in bileşenleri, uygulamaları yönetmek, dağıtmak ve ölçeklendirmek için birlikte çalışan çeşitli parçalardan oluşur. Bu bileşenleri tanıyarak her birinin ne iş yaptığını anlamak, Kubernetes’in işleyişini kavramanın temelidir.

Pod – En Küçük Dağıtım Birimi

Pod, Kubernetes’te uygulamaların çalıştığı en küçük birimdir. Her pod, bir veya daha fazla konteyner içerebilir ve bu konteynerler aynı kaynakları paylaşır. Örneğin, bir e-ticaret uygulamasında “sipariş” hizmeti için bir pod oluşturabiliriz. Bu pod, sipariş işleme sürecini yürüten konteyneri içerir. Pod ölçeklendirilmesi gerektiğinde, Kubernetes aynı hizmetin birden fazla kopyasını çalıştırarak yük dağılımını sağlar.

Node – Çalışma Birimi

Node, Kubernetes cluster’ında uygulama bileşenlerinin çalıştığı fiziksel veya sanal bir makinedir. Her node, pod’ları barındırır ve Kubernetes’in ana bileşenlerinden olan kubelet sayesinde API sunucusuyla iletişim kurar. Örneğin, Oracle Kubernetes Engine (OKE) ile kurduğun cluster’da node sayısını artırarak pod’lar için daha fazla kaynak sağlarsın. Yük artışına göre node sayısını artırmak veya azaltmak, uygulama ölçeklendirmesi için önemlidir.

Namespace – Mantıksal Ayrıştırma Birimi

Namespace, Kubernetes cluster’ını mantıksal olarak ayırmak için kullanılır. Örneğin, bir yazılım geliştirme ortamında “test” ve “prod” isimli iki ayrı namespace oluşturabiliriz. Böylece geliştiriciler test uygulamalarını “test” namespace’inde çalıştırırken, canlı (prod) ortam uygulamaları “prod” namespace’inde izole çalışır.

Deployment – Uygulama Yönetim Birimi

Deployment, belirli bir uygulamayı bir pod olarak başlatır ve gerektiğinde bu pod’un kaç kopyasının çalışacağını yönetir. Örneğin, bir web uygulamasını OKE’de başlatmak için bir deployment tanımlayabilirsin. Eğer kullanıcı sayısında ani bir artış olursa, Kubernetes bu deployment ile yeni pod’lar oluşturarak uygulamanın performansını korur.

Service – Ağ Üzerinde Erişim Sağlayan Birim

Service, pod’lara erişim sağlamak için kullanılır. Örneğin, bir veritabanı pod’u oluşturduğunu düşünelim. Bu veri tabanına diğer pod’ların erişebilmesi için bir Service oluşturmalısın. Böylece, veritabanı hizmeti diğer pod’lar tarafından kolayca erişilebilir hale gelir ve ip adresleri değişse bile Kubernetes bağlantıyı sağlar.

ConfigMap ve Secret – Yapılandırma ve Gizli Veriler

ConfigMap, yapılandırma ayarlarını pod’lara aktarmak için kullanılır. Örneğin, bir uygulama için farklı çalışma ortamlarına göre yapılandırmalar yapıyorsan (geliştirme, test ve prod gibi), ConfigMap ile bu ayarları yönetebilirsin. Secret ise hassas bilgileri (örneğin, parolalar veya API anahtarları) şifreli şekilde saklar.

 Ingress – Dış Trafiği Yönlendirme

Ingress, dışarıdan gelen trafiği cluster’daki belirli bir servise yönlendiren bileşendir. Örneğin, web uygulamanın kullanıcılar tarafından erişilmesini istiyorsan, Ingress kullanarak URL’yi belirli bir servise yönlendirebilirsin. Böylece, kullanıcılar örneğin https://uygulama.com adresine tıkladığında Ingress bu trafiği ilgili pod’a yönlendirir.

 Persistent Volume (PV) ve Persistent Volume Claim (PVC) – Kalıcı Depolama

Persistent Volume, Kubernetes’te verileri kalıcı olarak saklamak için kullanılan depolama birimidir. Persistent Volume Claim ise bu depolama birimini kullanma talebidir. Örneğin, bir veritabanı uygulaması verilerini saklamak için kalıcı bir alana ihtiyaç duyar. PV ve PVC ile depolama birimi talep ederek verilerin node’lar yeniden başlatılsa bile kaybolmamasını sağlayabilirsin.

Storage Class – Depolama Yönetim Politikaları

Storage Class, Kubernetes’te kalıcı depolama (Persistent Volume) için kullanılan depolama politikalarını tanımlar. Farklı depolama türlerini ve yapılandırmalarını destekler, bu da kullanıcıların ihtiyaçlarına uygun depolama alanı talep etmesini sağlar.

Örneğin, Oracle Kubernetes Engine (OKE) üzerinde çalışırken, hızlı ama pahalı bir depolama alanına veya daha yavaş ama ekonomik bir alana ihtiyaç duyabilirsin. Storage Class ile yüksek performanslı SSD veya daha ekonomik HDD depolama seçeneklerini tanımlayabilir ve pod’ların ihtiyacına göre seçim yapabilirsin. Bu, veritabanı gibi hız gerektiren uygulamalarla, daha düşük performans gereksinimi olan uygulamaların depolama tercihlerini yönetmek için idealdir.

Bu çalışmalar için Oracle Cloud üzerinde, Oracle Kubernetes Cluster’ı mı üç node’lu olarak oluşturdum. Hadi gelin komutlarla ortam üzerinde biraz oynayalım.

Bu arada, cluster’a yerel laptop’ım dan erişmek için gerekli konfigürasyonu yaptım. Ek olarak Oracle Cloud Shell üzerinden de ulaşabiliyorum.

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get nodes

NAME          STATUS   ROLES   AGE     VERSION

10.0.10.144   Ready    node    4m59s   v1.30.1

10.0.10.171   Ready    node    4m8s    v1.30.1

10.0.10.53    Ready    node    3m25s   v1.30.1

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$

Kopyalama rahatlığı açısından, Oracle Cloud Shell üzerinden devam edeceğim. 😊

“kubectl get nodes” komutuyla öncelikle cluster ve node’ların çalışır durumda olduğundan emin olduk.

Şimdi yukarda anlattığımız bileşenler, cluster’ımızda ne durumda, ona bakalım.

 

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get pods

No resources found in default namespace.

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get deployments

No resources found in default namespace.

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get services

NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE

kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP,12250/TCP   17d

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get configmaps

NAME               DATA   AGE

kube-root-ca.crt   1      17d

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get secrets

No resources found in default namespace.

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get namespaces

NAME              STATUS   AGE

default           Active   17d

kube-node-lease   Active   17d

kube-public       Active   17d

kube-system       Active   17d

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get storageclass

NAME               PROVISIONER                       RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE

oci                oracle.com/oci                    Delete          Immediate              false                  17d

oci-bv (default)   blockvolume.csi.oraclecloud.com   Delete          WaitForFirstConsumer   true                   17d

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get pv

No resources found

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get pvc

No resources found in default namespace.

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$

 

Bu komutlara ilişkin aşağıdaki gibi bir tablo faydalı olacaktır.

 

Kubernetes cluster’ının ilk durumunu gözlemlemek için temel kubectl komutları kullanarak yaptığımız kontrollerde, henüz pod, deployment, secret, Persistent Volume (PV) veya Persistent Volume Claim (PVC) gibi bileşenlerin oluşturulmadığını gördük. Ancak, Kubernetes’in varsayılan bazı bileşenleri hazır durumda:

  • Nodes: Cluster’da kullanılan node’lar çalışır durumda ve dağıtım yapmaya hazır.
  • Pods ve Deployments: Şu anda henüz bir pod veya deployment tanımlı değil, bu nedenle default namespace içerisinde herhangi bir kaynak bulunmamakta.
  • Services: Kubernetes servisi, cluster kurulduğunda varsayılan olarak tanımlanır ve iç trafiği yönetmek için kullanılır. Varsayılan olarak görünen bu servis, cluster içi iletişimi sağlar.
  • ConfigMap: kube-root-ca.crt adlı bir ConfigMap mevcut olup, Kubernetes API sertifikasıyla ilgilidir.
  • Secrets: Henüz özel bir Secret tanımlanmadığı için default namespace’te Secret bulunmamaktadır.
  • Namespaces: Varsayılan namespace’ler (default, kube-system, kube-public) mevcut ve her biri cluster içerisindeki farklı görevler için kullanılır.
  • Storage Classes: Oracle Kubernetes Engine (OKE) varsayılan olarak oci ve oci-bv (default) storage class’ları sağlar. Bu sınıflar, farklı depolama politikalarını belirlemek için kullanılır.
  • Persistent Volume (PV) ve Persistent Volume Claim (PVC): Henüz bir PV veya PVC talebi olmadığı için herhangi bir kaynak görünmemektedir.

Bu başlangıç durumu, cluster’a herhangi bir uygulama dağıtılmadan önceki varsayılan kaynakları ve yapılandırmaları gösterir. İlerleyen adımlarda, her bir bileşeni oluşturdukça çıktılarla birlikte durum değişikliklerini gözlemleyeceğiz.

Öncelike bir namespace oluşturalım.

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl create namespace my-namespace

namespace/my-namespace created

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get namespaces

NAME              STATUS   AGE

default           Active   17d

kube-node-lease   Active   17d

kube-public       Active   17d

kube-system       Active   17d

my-namespace      Active   14s

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl config set-context –current –namespace=my-namespace

Context “context-cd3inph2q5a” modified.

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$

 

Öncelikle, Kubernetes cluster’ında kaynakları daha düzenli bir şekilde yönetmek için my-namespace adında yeni bir namespace oluşturdum. Bu işlem, kaynakları varsayılan namespace olan default yerine özel bir alanda tutarak daha düzenli ve izole bir çalışma ortamı sağlayacak. Namespace’in oluşturulduğunu doğrulamak için mevcut namespace’leri listeledim ve my-namespace adının aktif durumda olduğunu gözlemledim. Son olarak, çalışma ortamını bu yeni namespace’e yönlendirdim. Böylece, tüm kubectl komutların my-namespace içinde çalışacak ve her komutta namespace belirtmeme gerek kalmayacak. Bu adımlarla, Kubernetes kaynaklarını daha izole bir ortamda oluşturup yönetmeye hazırız.

 

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl run my-nginx –image=nginx –port=80

pod/my-nginx created

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get pods

NAME       READY   STATUS    RESTARTS   AGE

my-nginx   1/1     Running   0          21s

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl expose pod my-nginx –type=LoadBalancer –port=80

service/my-nginx exposed

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get services

NAME       TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE

my-nginx   LoadBalancer   10.96.160.90   <pending>     80:30090/TCP   11s

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$ kubectl get services

NAME       TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE

my-nginx   LoadBalancer   10.96.160.90   89.168.68.176   80:30090/TCP   69s

asiye_yigi@cloudshell:~ (eu-frankfurt-1)$

 

Öncelikle kubectl run komutunu kullanarak nginx imajından bir pod oluşturup başlattım. Pod’un çalıştığını ve Running durumda olduğunu doğrulamak için kubectl get pods komutunu kullanarak kontrol ettim. Ardından, bu pod’a dışarıdan erişim sağlamak amacıyla bir LoadBalancer servisi oluşturdum. kubectl expose komutunu kullanarak pod’u LoadBalancer türünde bir servisle dış dünyaya açtım. Servisin durumunu kontrol ettiğimde, başlangıçta dış IP adresinin <pending> durumda olduğunu gördüm, ancak kısa bir süre sonra EXTERNAL-IP sütununda atanmış bir IP adresi belirdi. Bu IP adresi sayesinde, nginx web sunucusuna dışarıdan erişim sağlayarak çalıştığını doğruladık.

Bu ilk bölümde, Kubernetes’in temel yapı taşlarını oluşturan pod ve servis bileşenlerini OKE üzerinde uygulamalı olarak kurarak, dış IP ataması ile dış erişime açmayı başardık. Yaptığımız adımlar, Kubernetes ile çalışan bir uygulamayı nasıl yönetebileceğimizi ve yapılandırabileceğimizi anlamak için önemli bir başlangıç oldu. Serinin devamında, daha karmaşık uygulama yönetimi ve ölçeklendirme konularına adım atarak Kubernetes’in güçlü özelliklerini keşfetmeye devam edeceğiz.

 

Sarav Asiye Yiğit – 10 Kasım 2024