Tüm yazılar

#docker#kubernetes#devops

Docker ve Kubernetes Nedir? "Benim Bilgisayarımda Çalışıyordu" Sorununun Sonu

Docker uygulamanızı her yerde aynı çalışan bir kutuya koyar, Kubernetes ise yüzlerce kutuyu yönetir. İkisinin farkını, birlikte nasıl çalıştıklarını ve ne zaman gerçekten Kubernetes'e ihtiyacınız olduğunu örneklerle anlatıyoruz.

Docker ve Kubernetes Nedir? "Benim Bilgisayarımda Çalışıyordu" Sorununun Sonu
İçindekiler 10

Yazılım dünyasının en eski şakalarından biri şudur: "Ama benim bilgisayarımda çalışıyordu!" Geliştiricinin makinesinde kusursuz çalışan uygulama, sunucuya taşındığında farklı bir Java sürümü, eksik bir kütüphane ya da başka bir ayar yüzünden çöker. Docker bu sorunu çözmek için doğdu. Kubernetes ise Docker'ın yarattığı yeni sorunu çözmek için: yüzlerce konteyneri kim, nasıl yönetecek?

Bu yazıda ikisini de sıfırdan, gerçek örneklerle anlatıyoruz. Sonunda da en önemli soruya dürüst bir cevap veriyoruz: sizin gerçekten Kubernetes'e ihtiyacınız var mı?

Kısaca:

  • Docker, uygulamanızı tüm bağımlılıklarıyla birlikte her yerde aynı çalışan bir "konteyner"e paketler.
  • Kubernetes, çok sayıda konteyneri birden fazla sunucuda çalıştırır; çökeni yeniden başlatır, yük artınca çoğaltır, güncellemeleri kesintisiz yapar.
  • İkisi rakip değil: Docker (ya da uyumlu bir araç) imajı üretir, Kubernetes o imajları çalıştırır ve yönetir.
  • Tek sunucuda birkaç servis çalıştıran çoğu küçük proje için Docker Compose yeterlidir; Kubernetes'in getirdiği karmaşıklık ancak ölçek büyüdüğünde karşılığını verir.

Konteyner nedir, sanal makineden farkı ne?

Uygulamanızı başka bir yerde çalıştırmanın klasik yolu sanal makineydi (VM). Sanal makine, fiziksel bir bilgisayarın içinde koca bir bilgisayar daha taklit eder: kendi işletim sistemi, kendi çekirdeği, gigabaytlarca disk. Açılması dakikalar sürebilir.

Konteyner ise çok daha hafif bir fikir. Tüm konteynerler aynı işletim sistemi çekirdeğini paylaşır; her konteyner yalnızca uygulamanın ihtiyaç duyduğu dosyaları, kütüphaneleri ve ayarları taşır. Linux'un süreçleri birbirinden yalıtma özellikleri (namespace'ler) ve kaynak sınırlama mekanizması (cgroup'lar) sayesinde her konteyner kendini ayrı bir makinedeymiş gibi hisseder.

Sanal makine Konteyner
İçerdiği Tam işletim sistemi + uygulama Yalnızca uygulama ve bağımlılıkları
Boyut Genellikle gigabaytlar Genellikle megabaytlar
Açılış süresi Dakikalar Saniyeler
Yalıtım Çok güçlü (ayrı çekirdek) Güçlü ama çekirdek ortak

Bir benzetme: sanal makine her kiracıya ayrı bir müstakil ev inşa etmek gibidir. Konteyner ise aynı binada, ortak altyapıyı (su, elektrik, temel) paylaşan ama birbirinden ayrı daireler yapmak.

Docker ne işe yarar?

Docker, konteyner oluşturmayı ve çalıştırmayı herkes için kolaylaştıran araçtır. Üç temel kavramı var:

  • Dockerfile: Uygulamanızın kutusunun nasıl hazırlanacağını anlatan tarif.
  • İmaj (image): Tariften üretilen, değişmeyen paket. Bir kere üretilir, her yerde aynı çalışır.
  • Konteyner: İmajın çalışan hâli. Aynı imajdan istediğiniz kadar konteyner başlatabilirsiniz.

Basit bir Node.js uygulaması için Dockerfile şöyle görünebilir:

FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Her satır bir katman oluşturur: önce hafif bir Node.js tabanı alınır, bağımlılıklar kurulur, kod kopyalanır ve başlatma komutu tanımlanır. package.json dosyasını kodun geri kalanından önce kopyalamak bilinçli bir tercih: kodunuz değişse bile bağımlılıklar değişmediyse Docker o katmanı önbellekten kullanır ve derleme saniyeler sürer.

İmajı üretip çalıştırmak iki komut:

docker build -t benim-uygulamam:1.0 .
docker run -d -p 3000:3000 benim-uygulamam:1.0

Artık bu imaj; sizin dizüstü bilgisayarınızda, test sunucusunda ve canlı ortamda birebir aynı çalışır. "Benim bilgisayarımda çalışıyordu" sorununun sonu budur.

Docker Compose: Birden fazla servisi birlikte çalıştırmak

Gerçek uygulamalar nadiren tek parçadır. Bir web sitesi genellikle bir ön yüz, bir API ve bir veritabanından oluşur. Docker Compose, bunları tek bir dosyada tanımlamanızı sağlar:

services:
  api:
    image: benim-uygulamam:1.0
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://app:gizli@db:5432/app
    depends_on:
      - db
  db:
    image: postgres:18
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: gizli
    volumes:
      - pgdata:/var/lib/postgresql

volumes:
  pgdata:

docker compose up -d komutuyla iki servis birlikte ayağa kalkar. API, veritabanına db adıyla ulaşır; Compose aralarında bir ağ kurar. Birçok şirket, canlı ortamını da tek bir sunucuda bu şekilde çalıştırır ve bu gayet sağlıklı bir yaklaşımdır. Bizim de kendi web sitemiz dahil birçok projemiz bu yapıda çalışıyor.

Kubernetes'e neden ihtiyaç duyulur?

Docker tek bir makinede harikadır. Ama şu sorular belirdiğinde işler değişir:

  • Sunucu çökerse konteynerler ne olacak?
  • Trafik on katına çıkınca API'den on kopya nasıl çalıştırılacak, önlerine yük dengeleyici kim koyacak?
  • Yeni sürümü, kullanıcılar hiçbir kesinti yaşamadan nasıl yayınlayacağız?
  • Yeni sürüm hatalıysa nasıl hızla geri döneceğiz?
  • Elli servisi yirmi sunucuya kim, hangi mantıkla yerleştirecek?

Kubernetes (kısaca K8s) bu soruların cevabıdır. Google'ın içerideki Borg sisteminden edindiği deneyimle geliştirilip 2014'te açık kaynak olarak yayınlandı; bugün Cloud Native Computing Foundation (CNCF) bünyesinde. Kubernetes'e "ne istediğinizi" söylersiniz, o da bunu sürekli gerçekleştirmeye çalışır. Bu yaklaşıma bildirimsel (declarative) yönetim denir.

Kubernetes'in temel kavramları

  • Cluster (küme): Kubernetes'in yönettiği makinelerin tamamı.
  • Node (düğüm): Kümedeki her bir sunucu. Konteynerler node'larda çalışır.
  • Control plane: Kümenin beyni. Neyin nerede çalışacağına karar verir ve durumu sürekli izler.
  • Pod: Kubernetes'in en küçük birimi. Genellikle tek bir konteyner içerir; birlikte çalışması gereken birkaç konteyner de aynı pod'da olabilir.
  • Deployment: "Bu imajdan her zaman 3 kopya çalışsın" gibi bir hedef tanımı. Pod çökerse yenisini başlatır, güncellemeleri kademeli yapar.
  • Service: Değişen pod'ların önüne sabit bir ağ adresi koyar ve trafiği aralarında dağıtır.
  • Ingress: Dış dünyadan gelen HTTP trafiğini alan adı ve yola göre doğru servise yönlendirir.
  • ConfigMap ve Secret: Ayarları ve gizli bilgileri (parolalar, API anahtarları) imajın dışında tutar.

İlk Deployment'ınız

Yukarıdaki Docker imajını Kubernetes'te üç kopya olarak çalıştırmak için şu YAML yeterli:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: benim-uygulamam
spec:
  replicas: 3
  selector:
    matchLabels:
      app: benim-uygulamam
  template:
    metadata:
      labels:
        app: benim-uygulamam
    spec:
      containers:
        - name: api
          image: ghcr.io/sirketim/benim-uygulamam:1.0
          ports:
            - containerPort: 3000
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: benim-uygulamam
spec:
  selector:
    app: benim-uygulamam
  ports:
    - port: 80
      targetPort: 3000

kubectl apply -f uygulama.yaml dediğinizde Kubernetes işe koyulur. Burada birkaç kritik ayrıntı var:

  • replicas: 3 — Kubernetes her zaman üç pod çalıştırmaya çalışır. Birini elle silseniz bile saniyeler içinde yenisi gelir.
  • readinessProbe — Pod, /health adresi başarılı cevap verene kadar trafik almaz. Yeni sürüm tam hazır olmadan kullanıcıya gösterilmez.
  • resources — Her pod'un ne kadar işlemci ve bellek isteyeceğini belirtir. Kubernetes pod'ları bu bilgiye göre node'lara yerleştirir; bellek sınırını aşan konteyner yeniden başlatılır.

Yeni sürümü yayınlamak için imaj etiketini değiştirip dosyayı yeniden uygulamanız yeterli. Kubernetes pod'ları tek tek yenisiyle değiştirir (rolling update). Bir sorun çıkarsa kubectl rollout undo deployment/benim-uygulamam ile önceki sürüme dönersiniz.

Docker ve Kubernetes birlikte nasıl çalışır?

Sık yapılan bir hata, ikisini rakip sanmak. Aslında bir üretim hattının iki ucu gibiler:

  1. Geliştirici kodu yazar, Dockerfile ile imaj üretilir.
  2. İmaj bir registry'ye (Docker Hub, GitHub Container Registry vb.) gönderilir.
  3. Kubernetes o imajı registry'den çeker ve kümedeki node'larda çalıştırır.

Bir ayrıntıya dikkat: Kubernetes 1.24 sürümüyle Docker Engine'i doğrudan çalışma zamanı olarak kullanmak için gereken ara katmanı (dockershim) kaldırdı. Bugün kümeler genellikle containerd ya da CRI-O kullanıyor. Ama bu sizi etkilemez: Docker ile ürettiğiniz imajlar, OCI adlı ortak bir standarda uyduğu için bu çalışma zamanlarında sorunsuz çalışır. Docker, geliştiricinin masasında imaj üretme aracı olarak yerini koruyor.

Gerçekten Kubernetes'e ihtiyacınız var mı?

Dürüst olalım: Kubernetes güçlü ama karmaşık. Bir küme kurmak, güncel tutmak, izlemek ve güvenliğini sağlamak ciddi bir uzmanlık ister. Birçok ekip, ihtiyaç duymadığı bir karmaşıklığı erkenden üstlenip hız kaybeder.

Docker Compose büyük ihtimalle yeterli, eğer:

  • Uygulamanız tek bir sunucuya sığıyorsa,
  • Birkaç dakikalık planlı bakım kesintisi kabul edilebilirse,
  • Ekibinizde altyapıya tam zaman ayıracak biri yoksa.

Kubernetes'i düşünmeye başlayın, eğer:

  • Birden fazla sunucuya yayılmanız gerekiyorsa,
  • Kesintisiz güncelleme ve otomatik ölçekleme iş gereksinimiyse,
  • Onlarca mikroservisi farklı ekipler yönetiyorsa,
  • Yüksek erişilebilirlik (bir sunucu çökse bile hizmetin sürmesi) şartsa.

Arada bir yol da var: AWS EKS, Google GKE ya da Azure AKS gibi yönetilen Kubernetes servisleri, kontrol düzlemini sizin yerinize işletir. Tek sunucuda Kubernetes deneyimi isteyenler için k3s gibi hafif dağıtımlar da iyi bir başlangıç noktası.

Sıkça sorulan sorular

Docker öğrenmeden Kubernetes öğrenilir mi?

Önerilmez. Kubernetes, konteyner kavramını bildiğinizi varsayar. Önce Dockerfile yazmayı, imaj üretmeyi ve Compose ile birkaç servisi birlikte çalıştırmayı öğrenin; Kubernetes'in çözdüğü sorunları ancak o zaman gerçekten anlarsınız.

Kubernetes Docker'ın yerini mi aldı?

Hayır. Kubernetes çalışma zamanı olarak artık Docker Engine yerine containerd veya CRI-O kullanıyor, ama imaj üretmek ve yerelde geliştirmek için Docker hâlâ en yaygın araç. Docker ile üretilen imajlar Kubernetes'te sorunsuz çalışır.

Kubernetes pahalı mı?

Yazılımın kendisi açık kaynak ve ücretsiz. Maliyet; sunucular, yönetilen servis ücretleri ve en önemlisi onu işletecek insan emeğinden gelir. Küçük bir proje için bu maliyet çoğu zaman kazançtan fazladır.

Veritabanını da Kubernetes'te çalıştırmalı mıyım?

Mümkün ama dikkat ister. Veritabanları durum (veri) tutar ve pod'lar gibi rahatça silinip yeniden oluşturulamaz. Birçok ekip veritabanını yönetilen bir servise (ör. Amazon RDS) bırakıp yalnızca uygulamaları Kubernetes'te çalıştırmayı tercih eder.

Konteynerler, yazılımın nasıl paketlenip taşındığını kalıcı olarak değiştirdi. Doğru aracı doğru ölçekte seçmek ise bir mühendislik kararı. Projeniz için Docker, Compose ya da Kubernetes tabanlı bir altyapı kurmak isterseniz web uygulama geliştirme sayfamızdan bize ulaşabilirsiniz.

Kaynaklar

PaylaşLinkedInXWhatsApp
Bu konuda yardıma mı ihtiyacınız var?

Yazıda anlattıklarımızı kendi projenize uygulamak isterseniz birlikte bakalım.

Bize yazın
YE

EngerekTech’in kurucusu. İşletmeler için web, mobil ve kurumsal yazılım geliştiriyor; Angular, Spring Boot ve Flutter ile çalışıyor, KPSS Düello ve Kelime Kavanozu uygulamalarını geliştirdi. Blogda yapay zekâ araçlarını ve yazılım geliştirmeyi kendi projelerinde kullandığı haliyle anlatıyor.