Tek Bir Apply ile Uğraşmak Yerine Terraform'u Neden İkiye Böldüm
GKE altyapısını Kubernetes bootstrap'ten ayırmak bir workaround olarak başladı, sonunda faydalı bir state sınırına dönüştü.
Tüm altyapıyı tek bir Terraform root’unda toplamak cazip geliyor.
Tek dizin. Tek terraform apply. VPC, GKE, node pool, namespace’ler, Secret’lar, ConfigMap’ler—bitti.
CairnOps için de ilk içgüdüm buydu.
Sonunda ikiye böldüm.
“Oluşturuldu” ile “hazır” her zaman aynı an değildi
İlk aşama, fiziksel altyapıyı oluşturmak için Google provider’ını kullanıyor.
İkincisi, yeni cluster’ın içindeki kaynakları yapılandırmak için Kubernetes provider’ını kullanıyor.
Can sıkıcı olan kısım, Kubernetes provider’ının işe yarar bir şey yapabilmeden önce çalışan bir Kubernetes API endpoint’ine ihtiyaç duyması.
Pratikte, GKE’nin cluster’ın oluşturulduğunu bildirmesi ile Kubernetes API’sinin bağlantıları güvenilir şekilde kabul etmeye hazır olması arasında bazen küçük bir zamanlama açığına denk geliyordum.
Sürekli bir hata değildi. Bu durumu daha kötü yaptı, daha iyi değil. Aralıklı altyapı hataları güven duyulması zor şeylerdir.
Bu yüzden bağımlılığı dizin yapısında açıkça belirttim:
infra/terraform/
├── 01-infrastructure/
│ ├── VPC
│ ├── GKE cluster
│ ├── node pool
│ ├── Neon
│ ├── Upstash
│ └── Qdrant
└── 02-kubernetes-bootstrap/
├── Namespace
├── Secret
├── ConfigMap
└── ServiceAccount
İş akışı sıkıcılaştı, ki altyapıdan tam olarak istediğim şey de bu:
cd 01-infrastructure
terraform apply
gcloud container clusters get-credentials cairnops ...
kubectl get nodes
cd ../02-kubernetes-bootstrap
terraform apply
get-credentials erişimi kuruyor. kubectl get nodes ise Stage 2 başlamadan önce cluster’ın gerçekten yanıt verdiğini gösteren kontrol.
Remote state, arayüz haline geldi
İki aşama ayrıldıktan sonra bile Stage 2, Stage 1’den gelen değerlere ihtiyaç duyuyordu: cluster endpoint’i, CA certificate, database URL’leri, Redis URL’i, Qdrant URL’i ve benzerleri.
Ayrı GCS tabanlı state’ler kullandım ve sadece Stage 2’nin ihtiyaç duyduğu output’ları dışarı açtım.
Sonra Stage 2 bunları terraform_remote_state üzerinden okudu.
Bu kurulumda hoşuma giden şey, Stage 2’nin Stage 1’in cluster’ı nasıl oluşturduğuyla ilgilenmemesi. Sadece Stage 1’in dışarı açmayı vaat ettiği değerlerle ilgileniyor.
Bu da output’ları “Terraform borulaması” gibi değil, iki altyapı katmanı arasındaki bir arayüz gibi hissettiriyor.
Destroy süreci beni bu yapıyı korumaya ikna etti
Bu ayrım, ortamı kaldırırken daha da faydalı hale geldi.
Ters sırayla destroy ediyorum:
cd 02-kubernetes-bootstrap
terraform destroy
cd ../01-infrastructure
terraform destroy
Önce GKE cluster’ını silersem, Kubernetes provider’ı o cluster’ın içindeki kaynakları kaldırmak için ihtiyaç duyduğu API’yi kaybediyor.
State’i ayırmak yaşam döngüsünü netleştiriyor.
Ayrıca normal değişikliklerin etki alanını daraltıyor. Bir Namespace veya Secret’ı güncellemek VPC state’ine dokunmayı gerektirmiyor. Cluster’ı değiştirmek otomatik olarak her bootstrap kaynağına karışmıyor.
İki aşamayı başlangıçta bir zamanlama sorununu önlemek için getirdim.
Onları koruma sebebim, altyapıya iki net yaşam döngüsü kazandırmalarıydı.
Bu, tek ve etkileyici bir terraform apply’a sahip olmaktan daha değerli çıktı.