İçeriğe geç

(B) DevOps

Redis'ten Valkey'e Geçiş: Kurulum, ACL ve Yükseltme

15 dk okuma

Redis 7.4 ile birlikte lisans BSD'den çıkıp kaynak-görünür bir modele döndü. Aynı koddan doğan, Linux Foundation altında toplanan ve BSD ile devam eden fork olan Valkey, o günden bu yana Redis'i kullanan sunucuların çoğunun gözünde sessizce ikame edildi. Protokol, RDB biçimi ve komut kümesi aynı kaldığı için çoğu kurulumda tek yapılan şey paket adını değiştirmek oluyor. Redis 8 ile lisansa AGPLv3 seçeneği de eklendi; yani hangi sürümü seçeceğiniz lisans koşulunu gözden geçirmek gerektiriyor.

Ne değişti, ne değişmedi

Valkey, Redis'in 7.2.4 sürümünden çekilen koddan doğdu. Yani elinizdeki veritabanı dosyası, kullandığınız istemci kütüphanesi ve komut satırı aynı şekilde çalışıyor. İkisi arasındaki farkı anlamak için INFO çıktısına bakmak yeterli: sunucu hem redis_version hem de valkey_version alanlarını dolduruyor, redis_version eski istemcilerin kırılmaması için 7.2.4 değerinde tutuluyor. Hangisinin ne anlama geldiğini bilmek, ileride bir monitoring ekranına bakanın kafasının karışmasını önler.

Uyumluluk tablosu bu uyumu sınırlıyor. Açık kaynak Redis 2.x'ten 7.2.x'e kadar olan sürümlerden Valkey tarafına geçilebiliyor. Redis Community Edition 7.4 ve sonrası ise bu tabloda karşılığı yok, çünkü veri dosyaları artık uyumlu değil. Buradaki tuzak şu: lisans değişikliğinden hemen sonra 7.4 kurmuş bir sunucuyu "önce 7.2'ye indir" diye geçiştirmek dosya kopyalamayla olmuyor. 7.4'ün RDB biçimi 7.2'de açılmıyor ve DUMP ile alınan yük de aynı sebeple RESTORE ya da MIGRATE ile taşınamıyor. Tek yol mantıksal taşıma: kaynakta SCAN ile anahtarlar gezilip TYPE ile tipleri öğreniliyor, her tip için okuma komutu kullanılıp hedefte karşılık yazan komutla yeniden yazılıyor. Hash, list, set, zset ve stream için bu komutlar birbirinden farklı. RIOT gibi bu iş için yazılmış araçlar tüm döngüyü otomatik yapıyor.

Destek takvimi geleneksel projelerden farklı işliyor: en güncel kararlı sürüm tam destekte, çıkmış bir minor sürüm birkaç yıl boyunca hata ve güvenlik yaması alıyor, her major sürümün en güncel minor'ı ise yalnızca güvenlik desteğiyle devam ediyor. Hangi sürümün ne kadar destek gördüğü projenin sürüm sayfasında duruyor; uzun ömürlü bir kurulumda o sayfayı kontrol etmek, tahmin yürütmekten iyi.

Paket adı dağıtımdan dağıtıma değişiyor

Tek bir "valkey paketini kur" cümlesi doğru değil, çünkü paket adı, systemd biriminin adı ve yapılandırma yolu dağıtımda değişiyor. Debian ve Ubuntu tarafında paketler valkey-server ve valkey-tools olarak ayrı ayrı geliyor; valkey adında tek bir paket aranmıyor. Kurulumdan sonra veri dizini, /etc/valkey/valkey.conf ve valkey-server.service birimi hazır geliyor, ayrıca bir şey derlemeye gerek yok. Komut satırı aracı ikinci pakette bulunduğu için ikisini birlikte kurmak gerekiyor, aksi halde CONFIG SET ile canlı ayar değiştirecek elinizde araç olmuyor.

sudo apt install -y valkey-server valkey-tools

Fedora ve RHEL tarafında dnf install -y valkey yeterli: valkey-cli bu paketin içinde geliyor, ayrı bir valkey-tools paketi yok. Birim de valkey.service adıyla kuruluyor, yani systemctl restart valkey-server yazmak hata veriyor. SUSE ise şablon birim kullanıyor: valkey@<instance>.service ve /etc/valkey/<instance>.conf eşleşiyor, ayrı bir servis dosyası yazmanız gerekmiyor. Hangi dağıtımda olduğunuzu bilmiyorsanız kurulumdan sonra systemctl list-unit-files 'valkey*' ile gerçek birim adını görmek en hızlı yol.

systemctl list-unit-files 'valkey*'

Redis komut adlarıyla çalışan yazılımlar varsa uyumluluk paketleri kurulabiliyor: Debian ve Ubuntu'da valkey-redis-compat, Fedora'da valkey-compat-redis. Bunlar redis-cli adına sembolik bağ sağlıyor, böylece betikleri değiştirmeden geçiş yapılabiliyor.

Yapılandırma dosyası

Dosya düzenlenmeye hazır geliyor ve satırlarının çoğu yorum satırı. Dinlenecek arayüz, port, arka planda çalışma, veritabanı sayısı, snapshot aralıkları, parola ve AOF ayarları aynı dosyada duruyor. Varsayılan snapshot eşikleri 3600 saniyede en az bir değişiklik, 300 saniyede en az 100 değişiklik ve 60 saniyede en az 10000 değişiklik. Yani eski Redis'teki 60 saniyelik kural hâlâ duruyor; değişen 900 değerinin 3600'a ve 10 eşiğinin 100'e çıkması.

bind 127.0.0.1 ::1
port 6379
databases 16
save 3600 1 300 100 60 10000
requirepass bir-parola
appendonly no
appendfsync everysec

Örnekte io-threads 4 satırı yorumda duruyor, varsayılan değer 1. Yani dört iş parçacığını açmadığınız sürece ağ okuma ve yazması tek iş parçacığında kalıyor. Valkey 8'de bu ayar yalnızca okuma ve yazmayı bölmekten ibaret değil, async I/O modeli de değişti; iş parçacığı sayısını yükseltmek kazancı etkiliyor ama eski sürümlerdeki gibi düz bir çarpan olarak düşünülmemeli.

Soket satırları da varsayılan yapılandırmada yorumda. Debian paketi ayrıca /run/valkey/valkey-server.sock yolunu kullanıyor, yerel bağlantıda TCP'ye gerek yoksa soket üzerinden gitmek de seçenek. Aynı makinede farklı kullanıcıların da erişmesi gerekiyorsa soketi valkey grubunun sahibi olduğu bir dizine taşıyıp izni 770 yapmak gerekiyor, o gruptaki kullanıcıları da eklemek unutulmamalı.

Dışarı açılan port

Paketle gelen yapılandırmada protected-mode yes yazılı. Bu mod yalnızca bind satırı yerel dışı bir adrese bağlıysa ve hiçbir parola tanımlanmamışsa devreye giriyor; yani güvenlik katmanı olarak tek başına yeterli değil, sadece yanlış kurulmuş bir sunucuyu kurtarıyor. Dışarıdan bağlanılması gereken bir kurulumda yapılması gerekenler sırayla şu: bind satırına sunucunun iç ağdaki adresini yazmak, parola koymak, ardından güvenlik duvarı ya da güvenlik grubunda yalnızca o ağa açmak. Ağ kenarında bırakılan açık port, içerideki paroladan daha belirleyicidir.

sudo ufw allow from 10.0.0.0/24 to any port 6379 proto tcp

Yerel ağdan ötesine açılan bir kurulumda parolanın kendisi de yetmiyor, çünkü açık metin olarak geçiyor. TLS'i etkinleştirmek gerekiyor: tls-port yönergesi 0'dan farklı bir değere alınınca sunucu TLS kabul ediyor, tls-cert-file ve tls-key-file ile sertifika veriliyor, tls-auth-clients no ile istemci sertifikası zorunluluğu kapatılabiliyor. İstemci tarafında tls --cacert ... ile bağlanıldığında trafiğin şifrelenmiş olduğundan emin olunuyor.

tls-port 6380
tls-cert-file /etc/valkey/tls/valkey.crt
tls-key-file /etc/valkey/tls/valkey.key
tls-auth-clients no

Parola değil, ACL

requirepass geriye dönük uyum katmanı: yalnızca varsayılan kullanıcının parolasını ayarlıyor. Birden fazla uygulama aynı sunucuyu paylaştığında her birine ayrı kullanıcı açmak daha doğru oluyor, her kullanıcı kendi anahtar önekine ve komut grubuna sınırlanabiliyor. Tanımları ayrı bir dosyada tutmak düzenli: aclfile /etc/valkey/users.acl satırı yeterli, dosya elle düzenlendikten sonra ACL LOAD ile okunuyor.

Buradaki en sık yapılan hata, aclfile tanımlıyken requirepass satırını da bırakmak. İkisi aynı anda varsa requirepass yok sayılıyor. Dahası, ACL dosyası tanımlıysa valkey.conf içinde satır içi user direktifleri kullanılamıyor; ikisi karışınca sunucu hiç açılmıyor. Bu ikisinden birini seçin, ikisini birden kullanmayın.

user default off
user onbellek on >parola ~cache:* &* +@connection +@read +@write
user kuyruk on >parola ~queue:* &* +@connection +@read +@write +@scripting

+@connection olmadan PING, HELLO ve CLIENT SETNAME reddediliyor, istemci kütüphanelerinin çoğu bağlanırken bunları çağırdığı için eksik bırakılan bir kullanıcı ilk elde bağlantı kuramıyor. Kuyruk kullanıcısına +@scripting de gerekli: Laravel queue ve Horizon Lua çalıştırıyor, yani EVAL ve EVALSHA çağırıyor. &* her kanala yayın izni veriyor; pub/sub kullanmıyorsanız resetchannels ile o izni kaldırıp resetchannels ya da gerekiyorsa tek bir kanal adı verin. +@read ve +@write zaten tüm veri tiplerini kapsadığı için ardından +@string, +@hash, +@list yazmak gereksiz; tip kısıtlaması yapmak istiyorsanız okuma ve yazma gruplarını kullanmayıp komutları tek tek vermeniz gerekiyor.

Parolalar sunucu tarafında SHA-256 ile saklanıyor, ACL LIST çıktısında düz metin yerine uzun bir onaltılık dizi görünüyor. Dosyada düz metin parola yazmak yerine # işaretinden sonra onaltılık özet yazılabiliyor, ama o zaman özeti siz üretmek zorundasınız. ACL GENPASS çalıştırmak 256 bitlik rastgele bir değer üretiyor. Parolayı dosyada düz metin tutmak zorunda değilseniz tutmayın; dosya okunabilir durumda duruyorsa üstelik yedekleme sistemine de sızıyor.

Yeni bir kullanıcı hiçbir kural verilmeden oluşturulursa kapalı, parolasız ve hiçbir komutu çalıştıramayacak şekilde geliyor; yani yeni kullanıcı zaten -@all ile doğuyor. Asıl risk mevcut bir kullanıcıya eklemeli çağrı yapmakta, çünkü ACL SETUSER üzerine ekliyor, hiçbir şeyi sıfırlamıyor. Bu yüzden bir kullanıcıyı sıfırdan kurarken reset anahtar kelimesiyle başlayın, sonra izinleri tek çağrıda verin.

ACL SETUSER yeniuygulama reset on '>#parola' '~app:*' '+@connection' '+@read' '+@write' '-@dangerous' '-@admin'

Uygulama hesaplarının FLUSHALL veya CONFIG komutlarına erişmemesini sağlayan şey ayrı bir yönetici kullanıcısı bırakmak değil, uygulama hesaplarına -@dangerous ve -@admin kurallarını vermek. Yönetici hesabı +@all ile kalır, uygulama hesapları kendi dar kurallarıyla çalışır.

Snapshot ile günlük defter arasında

İki kalıcılık yolu var ve ikisi birbirinin yerine geçmiyor. RDB, belirli bir anda alınmış ikili bir anlık görüntü: dosyası küçük, geri yüklemesi hızlı, yedek almak için ideal. Bedeli iki snapshot arasındaki değişikliklerin gitmesi. AOF ise her yazma komutunu diske ekleyip yeniden oynatarak veriyi geri kuruyor, kayıp penceresi çok daha dar.

AOF'yi açmak iki ayarla ilgili: appendonly anahtarı açıp kapatıyor, appendfsync ise her komutta (always), saniyede bir (everysec) ya da tamamen işletim sistemine (no) yazma sıklığını belirliyor. Saniyede bir pratikte en dengeli seçenek; fsync gecikirse en kötü ihtimalle yaklaşık iki saniyelik veri gidiyor, "bir saniye" değil.

appendonly yes değerini yapılandırma dosyasına yazıp servisi yeniden başlatmak veri kaybettirir. Sunucu açılışta AOF varsa onu yükler, dosya boşsa veritabanı boş gelir. Doğru sıra şu: sunucuyu RDB ile açık tutun, çalışırken CONFIG SET appendonly yes çalıştırın, INFO persistence çıktısında aof_rewrite_in_progress:0 görünene kadar bekleyin, sonra CONFIG REWRITE ile kalıcı dosyaya yazın. Bu sırada sunucu hem yazmaya devam ediyor hem de mevcut verinin tamamını yeni AOF'a aktarıyor.

Diskte sürekli büyüyen dosyayı auto-aof-rewrite-percentage 100 ve auto-aof-rewrite-min-size 64mb değerleri kontrol ediyor; dosya son yeniden yazımdan iki katına çıkarsa ve 64 megabaytı geçtiyse arka planda sıkıştırılıyor. Yeniden yazma sırasında AOF dosyasının başına RDB biçiminde bir temel yazılıyor, aof-use-rdb-preamble yes bunu açık tutan ayar ve paketle gelen yapılandırmada öyle bırakılmış. Yeni sürümlerde AOF tek bir dosya değil, manifest, bir temel ve birkaç artımlı dosyadan oluşan bir dizin olarak duruyor; yedek alırken o dizinin tamamını kopyalamak gerekiyor.

Bozuk dosyayla uğraşmak zorunda kalırsan valkey-check-aof --fix ve valkey-check-rdb işe yarıyor. Yedekten dönüş sırası şu: servisi durdur, AOF dizini açıksa RDB yok sayılıp AOF yükleneceği için hangisinin kullanılacağını bil, dir ile dbfilename değerlerinin doğru yeri gösterdiğinden emin ol, dosyaların sahipliğini chown valkey:valkey ile düzelt, sonra başlat. Yanlış sahiplik sunucunun açılmasını engelleyen en sık nedendir.

Bellek dolduğunda

maxmemory tavanı belirlenmezse sunucu büyümeye devam eder ve sonunda çekirdek onu öldürür. Tavanı fiziksel belleğin hemen altına koymak yanlış, çünkü pay bırakılması gereken yerler var: AOF yeniden yazma sırasında geçici dosya, RDB oluştururken fork'un kopyalama yükü, replika bağlantılarının tamponları ve bellek parçalanması. Pratikte RAM'in yüzde 60 ile 75'i civarı makul bir tavan.

Tavana ulaşıldığında ne olacağına maxmemory-policy karar veriyor. Varsayılanı noeviction, yani yazma reddediliyor; kuyruk veya sayaç tutan işler için doğru olan da budur. Önbellek için genel amaçlı seçim allkeys-lru, erişim dağılımı çarpık olan işlerde allkeys-lfu. volatile- önekiyle başlayanlar yalnızca süresi olan anahtarları hedef alıyor ve sistemde süreli anahtar yoksa noeviction gibi davranıyor.

LRU ve LFU tam hesap yapmıyor, örnekleme üzerinden çalışıyor. Örneklem sayısı maxmemory-samples 5 ve varsayılan olarak beşte kalmış. Artırmak hangi anahtarın atılacağı konusundaki kararı isabetli hâle getiriyor, gecikmeyi düşürmüyor; CPU maliyetiyle birlikte biraz daha yavaş çalışıyor. Yazma gecikmesi görüyorsanız bakılacak ayar lazyfree-lazy-eviction yes: anahtarın silinmesi ana iş parçacığının işi olmaktan çıkıyor.

Loglarda karşımıza çıkan uyarılar

"Transparent Huge Pages support enabled" uyarısı sayfa birleştirmenin gecikmeye yol açabileceğini söylüyor. Bu ayar sysctl değil, /etc/tmpfiles.d/ altına yazılan iki satırla never yapılıyor; ayrıca Valkey'de disable-thp yes varsayılan olduğu için süreç kendi adına kapatıyor, bu mesaj eski sürümlerden kalma.

"TCP backlog cannot be enforced" uyarısının kaynağı net.core.somaxconn. 5.4 ve sonrası çekirdeklerde varsayılan zaten 4096, yani mesaj çıktığında değeri kontrol edin; 128 gibi düşük bir değer eski çekirdeklerden kalma. Üçüncü uyarı, overcommit_memory is set to 0, düşük bellekte arka plan kaydının başarısız kalacağını söylüyor; vm.overcommit_memory değerini 1 yapmak gerekiyor.

Yükseltmenin dört yolu

En ucuz yol dosyayı kopyalamak. Redis tarafında önce aktif bağlantıları kesip INFO KEYSPACE ile anahtar sayısını not edin, CONFIG GET dir ve CONFIG GET dbfilename ile dosya konumunu öğrenin, BGSAVE çalıştırın, LASTSAVE zaman damgası değişene kadar bekleyin, servisi durdurup dump.rdb dosyasını Valkey veri dizinine koyun ve başlatın. Hedefte AOF açıksa ilk açılışta kapatılması gerekiyor, yoksa kopyalanan RDB içe aktarılmıyor. Veri eklendikten sonra AOF'yi yukarıdaki sırayla, yani CONFIG SET appendonly yes ve rewrite bekleyerek açın; anahtar sayısını karşılaştırmak doğrulama için yeterli.

Kapanma süresi sorunsa yeni sunucuyu eskisinin replikası yapın. Buradaki sıra kritik: REPLICAOF <ip> 6379 çalıştırıldığında yeni sunucu salt okunur, uygulamayı ona yazmaya çevirirseniz her yazma READONLY hatası alır. Doğru sıra şu: önce eski tarafta yazmaları durdurun, sonra iki tarafın master_repl_offset değerini INFO replication çıktısından karşılaştırıp eşitlendiğini görün, yeni tarafta REPLICAOF NO ONE ile bağı koparın, ancak ondan sonra uygulamayı yeni sunucuya çevirin. Kaynakta parola varsa replika tarafında masterauth, ACL kullanılıyorsa masteruser da tanımlı olmalı, yoksa bağlantı hiç kurulamıyor ve link hiçbir zaman up olmuyor.

Yalnızca belirli anahtarları taşımak gerekiyorsa MIGRATE kullanılıyor. Sözdizimi MIGRATE host port "" db timeout [COPY] [REPLACE] [AUTH parola | AUTH2 kullanici parola] KEYS anahtar.... Çoklu anahtarda anahtar alanına boş dize yazıp anahtarları KEYS anahtar kelimesinden sonra sıralamak gerekiyor, hedefte parola varsa AUTH ya da AUTH2 da ekleniyor. COPY bayrağı anahtarı kaynakta bırakıyor, REPLACE hedefte zaten varsa üzerine yazıyor.

Kümeli kurulumda yol biraz farklı: her Redis birinciline birer Valkey replikası ekleniyor. valkey-cli --cluster add-node <yeni> <eski> --cluster-slave --cluster-master-id <id> komutunda --cluster-master-id ekleme anında veriliyor, senkron bittikten sonra verilmiyor. Ardından senkron tamamlanan Valkey replikasının kendi istemcisinden CLUSTER FAILOVER çalıştırılıyor ve en son eski Redis düğümü --cluster del-node ile çıkarılıyor. CLUSTER FAILOVER yalnızca cluster modunda geçerli, standalone sunucuda bu komut yok. Düğümler tek tek değiştirilmeli; üç birincilin üçünü birden değiştirmeye çalışmak yarıda kalmış bir küme bırakıyor.

Valkey'i kendi başınıza bir veritabanı değil, hızlı ve geçici bir katman olarak kullanın. Kalıcılık ayarları bir güvenlik ağı; asıl kayıt yine ilişkisel veritabanında duruyor olmalı.

Açık kaynak

GitHub projeleri

Tümünü gör
wireguard-server-panel

WireGuard VPN sunucu paneli - İstemci yönetimi, QR kodları ve trafik istatistikleri için kendi sunucunuzda barındırılan web kullanıcı arayüzü (fork, aktif olarak geliştirilmekte)

Go

Laravel-NDFirewall

Rota Kapsamlı Laravel WAF - RCE, SQLi, XSS ve SSRF algılama özelliklerine sahip hafif bir Web Uygulaması Güvenlik Duvarı

PHP

Trustsslroot

Tek komutla çalışan özel PKI oluşturucu - Kendi kendini imzalayan kök CA ve sertifikaları anında oluşturun

Go

node_exporter

Hafif sistem metrikleri aktarıcısı - Güvenli erişim kontrolüne sahip, Linux için durum bilgisi barındırmayan tek ikili dosyalı izleme hizmeti

Rust

ipReconary

IP keşif ve alt ağ analiz aracı - Hızlı ağ taraması ve IP istihbarat toplama

Rust

Cloudfiltred

Cloudflare IP beyaz liste güvenlik duvarı - 80/443 numaralı bağlantı noktalarını yalnızca Cloudflare IP’leriyle sınırlayarak kaynak sunucunuzu doğrudan saldırılara karşı koruyun

Rust

LoadAlertTracker

Hafif sistem yükü izleme arka plan programı - Eşik değerleri aşıldığında Telegram, Discord ve Mattermost üzerinden gerçek zamanlı uyarılar

Rust

ctCertWatch

Sertifika Şeffaflığı günlüğü izleyicisi - Kimlik avı alan adlarını, marka taklitçiliğini ve yetkisiz SSL sertifikalarını gerçek zamanlı olarak tespit eder

Rust

DDNS-FW

Dinamik DNS Güvenlik Duvarı - DDNS aracılığıyla değişen IP adreslerini takip edin ve güvenli erişim kontrolü için güvenlik duvarı kurallarını otomatik olarak güncelleyin

Rust