CI/CD ile Veritabanı Yönetimi: Modern Otomasyon Rehberi
Yazar: Burak Balkı | Kategori: Database | Okuma Süresi: 10 dk
Bu derinlemesine incelemede, veritabanı yönetiminde CI/CD süreçlerinin nasıl kurgulanacağı, Liquibase ve Flyway gibi araçların kullanımı, güvenlik önlemleri ...
## CI/CD Nedir ve Veritabanı Dünyasındaki Önemi
**CI/CD (Continuous Integration / Continuous Deployment)**, yazılım geliştirme yaşam döngüsünü otomatize eden, kod değişikliklerinin sürekli olarak entegre edilmesini ve yayına alınmasını sağlayan bir metodolojidir. Uygulama kodları için standart hale gelen bu süreç, **veritabanı (Database)** dünyasında genellikle en büyük darboğazı oluşturur. Veritabanı CI/CD süreçleri, şema değişikliklerini (schema changes), veri göçlerini (data migrations) ve saklı prosedür güncellemelerini yazılım koduyla senkronize bir şekilde yönetmeyi amaçlar.
Veritabanı yönetimi, uygulama kodundan farklı olarak **stateful (durumsal)** bir yapıya sahiptir. Bir uygulama sunucusunu silip yenisini kurmak saniyeler sürerken, bir veritabanını silmek veri kaybı anlamına gelir. Bu nedenle, veritabanı CI/CD süreçleri "Migration-based" (Göç tabanlı) veya "State-based" (Durum tabanlı) yaklaşımlarla titizlikle kurgulanmalıdır.
## Veritabanı CI/CD Süreçlerinde Temel Yaklaşımlar
Veritabanı değişikliklerini otomatize etmek için kullanılan iki ana felsefe mevcuttur:
1. **Migration-based Approach (Göç Tabanlı Yaklaşım):** Her değişiklik, sıralı bir SQL dosyası veya kod parçacığı olarak kaydedilir. Veritabanı, bu dosyaların sırayla çalıştırılmasıyla bir versiyondan diğerine yükseltilir. En yaygın kullanılan yöntemdir.
2. **State-based Approach (Durum Tabanlı Yaklaşım):** İstenen son durum (desired state) tanımlanır. Bir karşılaştırma aracı (comparison tool), mevcut veritabanı ile hedef durumu kıyaslar ve aradaki farkı kapatacak script'i otomatik oluşturur.
> **Not:** Modern DevOps ekipleri, izlenebilirlik ve geri alınabilirlik (rollback) avantajları nedeniyle genellikle göç tabanlı yaklaşımı tercih ederler.
## Versiyon Kontrollü Veritabanı Yönetimi (Database Migration)
Veritabanı kodunun (SQL scriptleri, DDL, DML) uygulama kodu gibi **Git** üzerinde barındırılması gerekir. Bu, "Database as Code" prensibinin temelidir. Her şema değişikliği bir versiyon numarasına sahip olmalı ve pipeline üzerinde bu numara takip edilmelidir.
### Örnek 1: Temel SQL Migration Dosyası (V1__create_users_table.sql)
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
## CI/CD Boru Hattı (Pipeline) Kurulumu ve Araç Seçimi
Bir veritabanı CI/CD hattı oluştururken şu araçlar kritik rol oynar:
- **Versiyon Kontrol:** Git (GitHub, GitLab, Bitbucket)
- **Otomasyon Sunucusu:** GitHub Actions, GitLab CI, Jenkins
- **Migration Araçları:** Liquibase, Flyway, Prisma, Sequelize
- **Linting/Güvenlik:** SQLFluff, Checkov
### Örnek 2: GitHub Actions ile SQL Linting Kontrolü
```yaml
name: SQL Linting
on: [push]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install sqlfluff
run: pip install sqlfluff
- name: Lint migrations
run: sqlfluff lint migrations/ --dialect postgres
```
## Liquibase ile Veritabanı Otomasyonu ve Örnek Uygulama
**Liquibase**, veritabanı değişikliklerini XML, YAML, JSON veya SQL formatında tanımlamanıza olanak tanıyan güçlü bir araçtır. Değişiklik setleri (changelogs) üzerinden çalışır ve hangi değişikliğin hangi veritabanına uygulandığını `DATABASECHANGELOG` tablosunda tutar.
### Örnek 3: Liquibase YAML Changelog Örneği
```yaml
databaseChangeLog:
- changeSet:
id: 1
author: tech_writer
changes:
- createTable:
tableName: products
columns:
- column:
name: id
type: int
autoIncrement: true
constraints:
primaryKey: true
- column:
name: name
type: varchar(255)
```
### Örnek 4: Liquibase Rollback Komutu
```bash
# Belirli bir tarihe geri dönmek için
liquibase rollbackToDate 2023-10-27T10:00:00
# Belirli bir tag'e geri dönmek için
liquibase rollback v1.2.0
```
## Flyway Kullanarak Veritabanı Sürümlerini Yönetme
**Flyway**, sadeliğiyle bilinen bir migration aracıdır. SQL tabanlı çalışır ve dosya isimlendirme standartlarına (V1__description.sql) dayanır.
### Örnek 5: Flyway Konfigürasyon Dosyası (flyway.conf)
```properties
flyway.url=jdbc:postgresql://localhost:5432/mydb
flyway.user=admin
flyway.password=secure_password
flyway.locations=filesystem:./sql_migrations
flyway.schemas=public
```
### Örnek 6: Flyway Migration Komutu
```bash
flyway migrate -url=jdbc:postgresql://db_host:5432/prod -user=deploy_user -password=env_pass
```
## Veritabanı Test Otomasyonu: Unit ve Entegrasyon Testleri
Pipeline aşamasında, veritabanı değişikliklerinin mevcut verileri bozup bozmadığı test edilmelidir. **Docker** kullanarak geçici veritabanı konteynerları oluşturmak en iyi pratiktir.
### Örnek 7: Docker Compose ile Test Veritabanı Ayağa Kaldırma
```yaml
version: '3.8'
services:
db_test:
image: postgres:15-alpine
environment:
POSTGRES_DB: test_db
POSTGRES_PASSWORD: test_pass
ports:
- "5432:5432"
```
### Örnek 8: Python ile Basit Bir DB Health Check Scripti
```python
import psycopg2
import sys
try:
conn = psycopg2.connect("dbname=test_db user=admin password=pass host=localhost")
cur = conn.cursor()
cur.execute("SELECT 1")
print("Database is ready!")
sys.exit(0)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
```
## Pipeline Güvenliği ve Hassas Veri Yönetimi
Veritabanı şifreleri asla düz metin olarak kod içerisinde barındırılmamalıdır. **HashiCorp Vault**, **AWS Secrets Manager** veya **GitHub Secrets** kullanılmalıdır.
### Örnek 9: GitLab CI üzerinde Secret Kullanımı
```yaml
deploy_db:
stage: deploy
script:
- migrate -url $DB_URL -user $DB_USER -password $DB_PASSWORD
only:
- main
```
## Sıfır Kesinti (Zero-Downtime) İçin Deployment Stratejileri
Veritabanı değişikliklerinde kesintiyi önlemek için **Expand and Contract** stratejisi uygulanır. Bu stratejide bir kolon silinirken önce uygulama yeni kolona yazmaya başlar, sonra eski kolon okunmaz hale getirilir ve en son silinir.
| Adım | İşlem | Amacı |
| :--- | :--- | :--- |
| 1. Expand | Yeni kolon ekle | Eski kodun çalışmaya devam etmesini sağla |
| 2. Migrate | Verileri taşı | Eski verileri yeni kolona aktar |
| 3. Contract | Eski kolonu kaldır | Temizlik ve optimizasyon |
## Veritabanı CI/CD Süreçlerinde En İyi Uygulamalar (Best Practices)
- **Immutable Migrations:** Bir migration dosyası deploy edildikten sonra asla değiştirilmemelidir. Hata varsa yeni bir migration dosyası oluşturulmalıdır.
- **Idempotency:** Scriptler tekrar tekrar çalıştırıldığında aynı sonucu vermelidir (IF NOT EXISTS kullanımı).
- **Small Batches:** Büyük şema değişikliklerini küçük parçalara bölün.
- **Backup Before Migration:** Her deployment öncesi otomatik snapshot alın.
### Örnek 10: Idempotent SQL Yazımı
```sql
-- Hata almayı önlemek için kontrol ekleme
DO $
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_user_email') THEN
CREATE INDEX idx_user_email ON users(email);
END IF;
END $;
```
## Yaygın Hatalar ve Kaçınılması Gereken Durumlar
1. **Manuel Müdahale:** Prod veritabanına manuel SQL komutu girmek, pipeline ile veritabanı durumunun senkronizasyonunu bozar (Drift).
2. **Büyük Veri Setlerinde Kilitleme (Locking):** `ALTER TABLE` komutları büyük tablolarda tabloyu kilitler. `ONLINE` veya `CONCURRENTLY` opsiyonları kullanılmalıdır.
3. **Rollback Planı Olmaması:** Her migration'ın bir geri dönüş yolu olmalıdır.
## Performans İpuçları
- Migration scriptlerinde index oluşturma işlemlerini yoğun olmayan saatlere planlayın.
- `SELECT *` kullanımından kaçınan view güncellemeleri yapın.
- İstatistikleri (`ANALYZE`) büyük veri yüklemelerinden sonra güncelleyin.
## Sık Sorulan Sorular (FAQ)
1. **Veritabanı CI/CD'si neden uygulama CI/CD'sinden daha zordur?**
Veritabanları durum (state) tutar. Uygulamalar stateless olabilirken, veritabanında yapılan hatalı bir işlem kalıcı veri kaybına yol açabilir.
2. **Liquibase mi Flyway mi?**
Karmaşık projeler ve farklı veritabanı türleri (Oracle, DB2, Postgres) arasında taşınabilirlik için Liquibase; basitlik ve SQL odaklılık için Flyway tercih edilir.
3. **Production veritabanında migration hatası olursa ne yapmalıyım?**
Önceden hazırlanan rollback scripti çalıştırılmalı veya son alınan yedekten (Point-in-Time Recovery) geri dönülmelidir.
4. **Veritabanı şifrelerini pipeline'da nasıl saklamalıyım?**
Kesinlikle CI araçlarının (Jenkins, GitHub vb.) 'Encrypted Secrets' bölümlerinde saklanmalı, loglara yazdırılmamalıdır.
5. **Datalar çok büyükse migration süresi nasıl yönetilir?**
Büyük tablolar için 'Shadow Table' tekniği kullanılır; veri arka planda yeni tabloya taşınır ve son aşamada tabloların ismi değiştirilir.
## Özet ve Sonuç
Veritabanı CI/CD süreçleri, modern yazılım geliştirmenin ayrılmaz bir parçasıdır. **Database Migration** araçlarını kullanmak, şema değişikliklerini versiyonlamak ve pipeline süreçlerine testleri dahil etmek, hata payını minimize eder. Unutulmamalıdır ki; otomatikleştirilmeyen her veritabanı değişikliği, deployment sürecinde potansiyel bir risk noktasıdır.