GCP GKE ile Kubernetes Cluster Kurulumu

Google Cloud Platform üzerinde Kubernetes cluster kurmak, ilk kez yapıyorsanız göz korkutucu görünebilir. Ama GKE (Google Kubernetes Engine), managed Kubernetes dünyasında en olgun ve en çok tercih edilen servislerden biri. Google’ın kendi altyapısında çalışıyor, otomatik node yönetimi, otomatik güvenlik yamaları, entegre load balancer desteği… Bunları elle kurmaya çalışsanız günler sürer. Bu yazıda sıfırdan üretim seviyesine yakın bir GKE cluster’ı nasıl kurarsınız, bunu adım adım ve gerçek hayattan örneklerle anlatacağım.

Ön Gereksinimler ve Ortam Hazırlığı

Başlamadan önce birkaç şeyi hazır etmeniz gerekiyor. GCP hesabınız olmalı ve faturalandırma aktif olmalı. Eğer yeni bir hesapsa $300 ücretsiz kredi ile başlıyorsunuz, bu kurulum için fazlasıyla yeterli.

Gerekli araçlar:

  • gcloud CLI: Google Cloud komut satırı aracı
  • kubectl: Kubernetes komut satırı aracı
  • helm (opsiyonel): Kubernetes paket yöneticisi

gcloud CLI kurulumu için:

# Linux için gcloud CLI kurulumu
curl https://sdk.cloud.google.com | bash
exec -l $SHELL

# Kurulumu doğrula
gcloud version

# macOS için Homebrew ile
brew install --cask google-cloud-sdk

Kurulum tamamlandıktan sonra hesabınıza giriş yapıyorsunuz:

# GCP hesabına giriş
gcloud auth login

# Proje oluştur veya mevcut projeyi seç
gcloud projects create my-gke-project-001 --name="GKE Demo Project"
gcloud config set project my-gke-project-001

# Fatura hesabını projeyle ilişkilendir
gcloud billing accounts list
gcloud billing projects link my-gke-project-001 
  --billing-account=XXXXXX-XXXXXX-XXXXXX

# Gerekli API'leri aktif et
gcloud services enable container.googleapis.com
gcloud services enable compute.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com

kubectl’i de kuralım:

# gcloud üzerinden kubectl kurulumu (en kolay yol)
gcloud components install kubectl

# veya doğrudan sisteme kur
curl -LO "https://dl.k8s.io/release/$(curl -L -s 
  https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

kubectl version --client

Network Altyapısını Kurmak

Prodüksiyona yakın bir kurulum için özel bir VPC ağı oluşturmanızı kesinlikle tavsiye ederim. Default VPC ile de çalışır ama özellikle multi-environment (dev, staging, prod) senaryolarında ayrı ağ yapısı hayat kurtarır.

# Özel VPC oluştur
gcloud compute networks create gke-vpc 
  --subnet-mode=custom 
  --bgp-routing-mode=regional

# GKE için subnet oluştur
# /20 node'lar için yeterli IP verir (4094 IP)
gcloud compute networks subnets create gke-subnet 
  --network=gke-vpc 
  --region=europe-west1 
  --range=10.0.0.0/20 
  --secondary-range pod-range=10.16.0.0/14,svc-range=10.20.0.0/20 
  --enable-private-ip-google-access

# Firewall kuralları
gcloud compute firewall-rules create gke-allow-internal 
  --network=gke-vpc 
  --allow=tcp,udp,icmp 
  --source-ranges=10.0.0.0/8

gcloud compute firewall-rules create gke-allow-health-checks 
  --network=gke-vpc 
  --allow=tcp:8080,tcp:443,tcp:80 
  --source-ranges=130.211.0.0/22,35.191.0.0/16

Secondary range’leri neden tanımladık? GKE’de VPC-native cluster kullanıyorsanız (ki kullanmalısınız), pod’lar ve servisler için ayrı IP aralıkları gerekiyor. Bu yapı, pod’lardan doğrudan diğer VPC servislerine erişimi kolaylaştırıyor ve Network Policy’lerin düzgün çalışmasını sağlıyor.

GKE Cluster Kurulumu

Şimdi asıl işe geliyoruz. Küçük bir dev cluster ile başlayıp ardından production-grade bir cluster oluşturacağız.

Basit Bir Test Cluster’ı

Eğer sadece öğrenmek ve denemek istiyorsanız:

# Basit tek zone cluster (dev/test için)
gcloud container clusters create gke-dev-cluster 
  --zone=europe-west1-b 
  --num-nodes=2 
  --machine-type=e2-medium 
  --disk-size=50GB 
  --disk-type=pd-standard 
  --no-enable-basic-auth 
  --network=gke-vpc 
  --subnetwork=gke-subnet

Bu cluster 2-3 dakikada hazır olur. Ama bunu production’da kullanmayın. Tek zone’da çalıştığı için zone’un herhangi bir sorunu yaşaması cluster’ınızı etkiler.

Production-Grade Cluster Kurulumu

Gerçek bir prodüksiyon ortamı için çok daha fazla parametre düşünmeniz gerekiyor:

gcloud container clusters create gke-prod-cluster 
  --region=europe-west1 
  --node-locations=europe-west1-b,europe-west1-c,europe-west1-d 
  --num-nodes=2 
  --machine-type=e2-standard-4 
  --disk-size=100GB 
  --disk-type=pd-ssd 
  --network=gke-vpc 
  --subnetwork=gke-subnet 
  --cluster-secondary-range-name=pod-range 
  --services-secondary-range-name=svc-range 
  --enable-ip-alias 
  --enable-private-nodes 
  --master-ipv4-cidr=172.16.0.0/28 
  --enable-master-authorized-networks 
  --master-authorized-networks=YOUR_IP/32 
  --enable-network-policy 
  --enable-shielded-nodes 
  --shielded-secure-boot 
  --shielded-integrity-monitoring 
  --workload-pool=my-gke-project-001.svc.id.goog 
  --enable-autoscaling 
  --min-nodes=1 
  --max-nodes=5 
  --enable-autorepair 
  --enable-autoupgrade 
  --maintenance-window-start=2024-01-01T02:00:00Z 
  --maintenance-window-end=2024-01-01T06:00:00Z 
  --maintenance-window-recurrence="FREQ=WEEKLY;BYDAY=SA,SU" 
  --addons=HorizontalPodAutoscaling,HttpLoadBalancing,GcePersistentDiskCsiDriver 
  --logging=SYSTEM,WORKLOAD 
  --monitoring=SYSTEM 
  --release-channel=regular

Bu komuttaki kritik parametreleri açıklayalım:

–enable-private-nodes: Node’ların public IP almadığı anlamına gelir. Bu büyük bir güvenlik kazanımı. Node’larınız internete doğrudan açık olmaz.

–enable-master-authorized-networks: Kubernetes API’sine sadece belirttiğiniz IP’lerden erişilir. Ofis IP’nizi veya VPN IP’nizi koyun buraya.

–workload-pool: Workload Identity aktif eder. Service account key dosyası olmadan pod’ların GCP servislerine erişmesini sağlar. Güvenlik açısından çok önemli.

–release-channel regular: Stabil ama çok eski olmayan versiyonları otomatik alırsınız. Rapid kanalı daha yeni özellikleri daha hızlı getirir ama daha az stabil olabilir.

–maintenance-window: Otomatik güncellemelerin hafta sonu gece yapılmasını sağlıyoruz. Bunu mutlaka ayarlayın, yoksa iş saatlerinde update yiyebilirsiniz.

kubectl Bağlantısını Yapılandırma

Cluster hazır olduğunda kubeconfig dosyanızı güncellemeniz gerekiyor:

# Cluster credentials'ını al
gcloud container clusters get-credentials gke-prod-cluster 
  --region=europe-west1 
  --project=my-gke-project-001

# Bağlantıyı test et
kubectl get nodes
kubectl get namespaces

# Cluster bilgilerini gör
kubectl cluster-info

# Context'leri listele (birden fazla cluster varsa)
kubectl config get-contexts

# Context değiştir
kubectl config use-context gke_my-gke-project-001_europe-west1_gke-prod-cluster

Private cluster kullanıyorsanız (ki kullanıyorsunuz) kubectl erişimi için VPN veya Cloud Shell gerekebilir. Alternatif olarak master authorized networks’e kendi IP’nizi ekleyebilirsiniz:

# Kendi IP'nizi öğrenin
MY_IP=$(curl -s ifconfig.me)

# Master authorized networks'e ekle
gcloud container clusters update gke-prod-cluster 
  --region=europe-west1 
  --enable-master-authorized-networks 
  --master-authorized-networks=${MY_IP}/32

Node Pool Yönetimi

GKE’nin güçlü özelliklerinden biri farklı tipte workload’lar için farklı node pool’ları kullanabilmek. Mesela web uygulamalarınız için genel amaçlı node’lar, ML işleri için GPU node’lar, batch işler için spot/preemptible node’lar kullanabilirsiniz.

# Spot instance node pool ekle (batch işler, maliyet optimizasyonu için)
gcloud container node-pools create spot-pool 
  --cluster=gke-prod-cluster 
  --region=europe-west1 
  --machine-type=e2-standard-4 
  --num-nodes=0 
  --enable-autoscaling 
  --min-nodes=0 
  --max-nodes=10 
  --spot 
  --node-taints=workload=batch:NoSchedule 
  --node-labels=workload=batch

# GPU node pool ekle (ML workload'ları için)
gcloud container node-pools create gpu-pool 
  --cluster=gke-prod-cluster 
  --region=europe-west1 
  --machine-type=n1-standard-4 
  --accelerator=type=nvidia-tesla-t4,count=1 
  --num-nodes=0 
  --enable-autoscaling 
  --min-nodes=0 
  --max-nodes=4 
  --node-taints=gpu=true:NoSchedule

# Node pool listele
gcloud container node-pools list 
  --cluster=gke-prod-cluster 
  --region=europe-west1

Spot instance pool’a workload schedule etmek için pod spec’inizde toleration tanımlamanız gerekiyor:

# Örnek deployment manifest'i oluştur
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: batch-worker
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: batch-worker
  template:
    metadata:
      labels:
        app: batch-worker
    spec:
      tolerations:
      - key: "workload"
        operator: "Equal"
        value: "batch"
        effect: "NoSchedule"
      nodeSelector:
        workload: batch
      containers:
      - name: worker
        image: busybox:latest
        command: ["sh", "-c", "echo Batch job running && sleep 300"]
        resources:
          requests:
            cpu: "500m"
            memory: "256Mi"
          limits:
            cpu: "1000m"
            memory: "512Mi"
EOF

Namespace ve RBAC Yapılandırması

Cluster’ınızı namespace’lere bölmek hem izolasyon hem de yönetim kolaylığı sağlar. Tipik bir kurumsal yapıda şöyle bir namespace organizasyonu kullanabiliriz:

# Namespace'leri oluştur
kubectl create namespace production
kubectl create namespace staging
kubectl create namespace monitoring
kubectl create namespace ingress-nginx

# Label ekle
kubectl label namespace production environment=production
kubectl label namespace staging environment=staging

# Ekip için service account ve role binding oluştur
kubectl create serviceaccount dev-team -n staging

kubectl create role staging-deployer 
  --namespace=staging 
  --verb=get,list,watch,create,update,patch,delete 
  --resource=deployments,pods,services,configmaps

kubectl create rolebinding dev-team-binding 
  --namespace=staging 
  --role=staging-deployer 
  --serviceaccount=staging:dev-team

# Namespace'e resource quota koy
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
  name: staging-quota
  namespace: staging
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "20"
    services: "10"
EOF

Ingress ve Load Balancer Kurulumu

NGINX Ingress Controller, GKE’de en yaygın kullanılan ingress çözümlerinden biri. Helm ile kurmak en pratik yol:

# Helm kur (eğer yoksa)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# NGINX Ingress Controller kur
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install ingress-nginx ingress-nginx/ingress-nginx 
  --namespace ingress-nginx 
  --create-namespace 
  --set controller.replicaCount=2 
  --set controller.nodeSelector."kubernetes.io/os"=linux 
  --set controller.service.type=LoadBalancer 
  --set controller.metrics.enabled=true 
  --set controller.podAnnotations."prometheus.io/scrape"="true" 
  --set controller.podAnnotations."prometheus.io/port"="10254"

# Load Balancer IP'sini bekle
kubectl get svc ingress-nginx-controller -n ingress-nginx -w

# Örnek Ingress kaynağı oluştur
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
EOF

Monitoring ve Logging

GKE, Cloud Monitoring ve Cloud Logging ile entegre geliyor. Ama çoğu ekip ayrıca Prometheus/Grafana stack’i de kuruyor. İkisini birlikte kullanmak en iyi sonucu veriyor:

# kube-prometheus-stack kur (Prometheus + Grafana + AlertManager)
helm repo add prometheus-community 
  https://prometheus-community.github.io/helm-charts
helm repo update

helm install kube-prometheus prometheus-community/kube-prometheus-stack 
  --namespace monitoring 
  --create-namespace 
  --set grafana.adminPassword=SecurePassword123 
  --set prometheus.prometheusSpec.retention=15d 
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName=standard-rwo 
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=50Gi

# Grafana'ya erişim için port-forward
kubectl port-forward -n monitoring svc/kube-prometheus-grafana 3000:80

# Prometheus metrics kontrol
kubectl port-forward -n monitoring svc/kube-prometheus-kube-prome-prometheus 9090:9090

GCP Cloud Monitoring için özel bir alert policy oluşturalım:

# Node CPU kullanım alerti (gcloud ile)
gcloud alpha monitoring policies create 
  --notification-channels=CHANNEL_ID 
  --display-name="GKE Node CPU High" 
  --condition-display-name="CPU above 80%" 
  --condition-filter='resource.type="k8s_node" AND metric.type="kubernetes.io/node/cpu/allocatable_utilization"' 
  --condition-threshold-value=0.8 
  --condition-threshold-comparison=COMPARISON_GT 
  --condition-duration=300s

Workload Identity ile GCP Servis Entegrasyonu

Pod’larınızın Cloud Storage, BigQuery veya başka GCP servislerine erişmesi gerekiyorsa Workload Identity kullanmanız şart. Service account JSON dosyası kullanmak güvenlik açığı yaratır.

# GCP Service Account oluştur
gcloud iam service-accounts create gke-app-sa 
  --display-name="GKE Application Service Account"

# Gerekli rolleri ver (örnek: Cloud Storage okuma)
gcloud projects add-iam-policy-binding my-gke-project-001 
  --member="serviceAccount:[email protected]" 
  --role="roles/storage.objectViewer"

# Kubernetes service account oluştur
kubectl create serviceaccount app-ksa -n production

# İki service account'ı birbirine bağla (Workload Identity binding)
gcloud iam service-accounts add-iam-policy-binding 
  [email protected] 
  --role=roles/iam.workloadIdentityUser 
  --member="serviceAccount:my-gke-project-001.svc.id.goog[production/app-ksa]"

# Kubernetes service account'a annotation ekle
kubectl annotate serviceaccount app-ksa 
  --namespace=production 
  iam.gke.io/gcp-service-account=gke-app-sa@my-gke-project-001.iam.gserviceaccount.com

# Artık pod'ları bu service account ile çalıştırın
# spec.serviceAccountName: app-ksa

Cluster Bakımı ve Güncelleme

GKE’de cluster versiyonunu güncel tutmak hem güvenlik hem de yeni özellikler açısından kritik. Release channel kullanıyorsanız GCP bunu otomatik yapıyor, ama manuel kontrol de önemli:

# Mevcut cluster versiyonunu ve uygun upgrade versiyonlarını gör
gcloud container clusters describe gke-prod-cluster 
  --region=europe-west1 
  --format="value(currentMasterVersion,currentNodeVersion)"

# Kullanılabilir versiyonları listele
gcloud container get-server-config 
  --region=europe-west1 
  --format="yaml(validMasterVersions[0:5])"

# Master'ı manuel upgrade et
gcloud container clusters upgrade gke-prod-cluster 
  --region=europe-west1 
  --master 
  --cluster-version=1.28.5-gke.1000

# Node pool upgrade et (rolling update yapar)
gcloud container clusters upgrade gke-prod-cluster 
  --region=europe-west1 
  --node-pool=default-pool

# Cluster'ı yeniden boyutlandır
gcloud container clusters resize gke-prod-cluster 
  --region=europe-west1 
  --node-pool=default-pool 
  --num-nodes=3

Maliyet optimizasyonu açısından önemli bir ipucu: Geliştirme ortamınızı geceleri ve hafta sonları kapatmak için aşağıdaki yaklaşımı kullanabilirsiniz:

# Dev cluster'ı node sayısını 0'a indir (cluster silinmez, sadece node'lar durur)
gcloud container clusters resize gke-dev-cluster 
  --zone=europe-west1-b 
  --node-pool=default-pool 
  --num-nodes=0

# Sabah tekrar ayağa kaldır
gcloud container clusters resize gke-dev-cluster 
  --zone=europe-west1-b 
  --node-pool=default-pool 
  --num-nodes=2

Bu işlemi Cloud Scheduler + Cloud Functions ile otomatize etmek mümkün ve aylık maliyetinizi ciddi ölçüde düşürür.

Yaygın Sorunlar ve Çözümleri

Gerçek hayatta en sık karşılaştığım birkaç sorunu paylaşayım:

Pod’lar Pending durumunda kalıyor: Çoğunlukla resource yetersizliği. kubectl describe pod POD_NAME komutunu çalıştırın, Events bölümüne bakın. Node’larda yeterli CPU/Memory yoksa cluster autoscaler devreye girmeli, girmiyorsa min/max node sayılarını kontrol edin.

ImagePullBackOff hatası: Private registry kullanıyorsanız imagePullSecrets tanımlamamışsınızdır. Workload Identity ile GCR veya Artifact Registry’ye erişim için node service account’a roles/artifactregistry.reader rolü verin.

DNS çözümleme sorunları: CoreDNS pod’larını kontrol edin, kubectl get pods -n kube-system | grep coredns. Yeniden başlatmak genellikle işe yarar ama kök nedeni araştırın.

Yüksek egress maliyeti: GKE’de pod’lar farklı zone’lardaki servislerle konuşunca inter-zone trafik ücreti oluşuyor. Topology Aware Routing aktif ederek bu maliyeti azaltabilirsiniz.

Sonuç

GKE, managed Kubernetes deneyimi açısından piyasadaki en olgun çözümlerden biri. Bu yazıda anlattığım adımları takip ederek hem güvenli hem de ölçeklenebilir bir cluster ortamı kurabilirsiniz.

Özetlemek gerekirse en önemli noktalar şunlar: Private cluster ve Workload Identity kullanarak güvenlik temelini sağlam atın. Node pool’ları workload tipine göre ayırarak hem maliyet hem de performans optimize edin. Maintenance window tanımlayın, release channel’ı regular olarak bırakın ve güncellemeleri GCP’nin otomatik yapmasına izin verin. Namespace’leri ve resource quota’ları ihmal etmeyin, bunlar büyüyen ekiplerde hayat kurtarıyor.

Bir sonraki adım olarak GitOps yaklaşımıyla Argo CD veya Flux kurulumuna, ya da Cloud Armor ile WAF entegrasyonuna bakabilirsiniz. GKE ekosistemi gerçekten çok geniş, her yazıda yeni bir katman keşfediyorsunuz.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir