Küme mimarisi ve API sunucusu
- Kubernetes'te her istek API sunucusundan geçer; kimlik, yetki ve kabul kararları orada verilir, küme durumu ise etcd'de durur.
- Küme durumu etcd'de tutulur ve sırlar orada varsayılan olarak şifrelenmez.
- Yönetim düzlemini genel internete açmak ilk daraltılacak ayardır.
Puan bütün etkinlikleri cevaplayınca hesaba yazılır. Bu dersi tamamlayınca +50 XP alacaksın. Giriş yapmadan ilerlersen puan yalnız bu tarayıcıda durur.
Bir kümeyi güvenlik gözüyle devraldığında ilk iki soru şudur: kararları kim veriyor, durum nerede duruyor. Kubernetes'te iki cümle bu haritayı çizer.
Her istek API sunucusundan geçer ve küme durumu etcd'de durur. Bu iki cümleyi aklında tutarsan, kümenin geri kalanı yerine oturur. Bu derste önce bileşenleri tanırsın, sonra bir isteğin geçtiği üç aşamayı izlersin, en sonda kümeyi daraltmanın ilk adımlarını uygularsın. Komutları kendi laboratuvar kümende çalıştırabilirsin; hepsi okuma amaçlıdır ve kümeye zarar vermez.
Küme bileşenleri
Kümenin karar veren katmanı denetim düzlemidir ve dört parçadan kurulur. API sunucusu tüm isteklerin geçtiği tek kapıdır; kubectl de, kubelet de, denetleyiciler de aynı kapıyı çalar. Zamanlayıcı yeni podu kaynak durumuna ve kurallara bakarak uygun düğüme yerleştirir.
Denetleyici yöneticisi istenen durumla gerçek durumu sürekli yaklaştırır; bir pod ölürse yerine yenisini açan mantık buradadır. etcd ise kümenin bütün durumunu tutan anahtar değer deposudur. Bu dört parça çoğu kurulumda ayrı bir denetim düzlemi katmanında koşar ve iş yüklerinden yalıtılır.
Düğüm tarafında üç parça çalışır. kubelet düğümdeki konteynerleri ayakta tutar ve her birinin durumunu API sunucusuna bildirir; düğümün sözcüsü odur. Konteyner çalışma ortamı imajı indirir ve süreci başlatır. kube-proxy ya da onun yerini alan ağ eklentisi servis trafiğini doğru poda yönlendirir.
Ağ eklentisi, yani CNI, podlara IP verir ve podlar arası trafiği taşır. kube-proxy ve ağ eklentisi çoğu kurulumda birer pod olarak koşar. kubelet ve çalışma ortamı ise düğümde doğrudan sistem hizmeti olarak çalışır. Pod olarak koşan parçaları da aynı araçlarla listeleyip inceleyebilirsin.
Küme altyapısı kube-system ad alanında durur. DNS çözümleyici, ağ eklentisi ve ölçüm toplayıcısı burada sıradan pod olarak koşar. Yönetilen bir hizmette denetim düzlemini sağlayıcı işletir. Bu yüzden API sunucusunu, zamanlayıcıyı ve etcd'yi bu listede göremezsin.
Sağlayıcı onları ayrı, görünmez bir katmanda tutar ve sana yalnız sonucunu sunar. kubeadm gibi bir araçla kendin kurduğun kümede ise bu parçalar da senin sorumluluğundadır ve aynı ad alanında birer pod olarak görünür. Bu ayrımı bilmek, bir komutun çıktısını yanlış okumanı önler; eksik görünen bir bileşen her zaman bir arıza değildir.
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE coredns-7c9b8d4f-2wq8x 1/1 Running 0 20d coredns-7c9b8d4f-h5p9n 1/1 Running 0 20d cilium-4m2kd 1/1 Running 0 20d cilium-operator-6f8c5 1/1 Running 0 20d metrics-server-5d7c9 1/1 Running 0 20d
Çıktıyı satır satır oku. İki coredns podu küme içi ad çözümünü yapar; servis adlarını IP'ye bu podlar çevirir. cilium ve cilium-operator ağ eklentisidir; podlara IP verir ve ağ politikasını uygular.
metrics-server kaynak ölçümlerini toplar. Bu listede bir API sunucusu podu görmemen küme bozuk olduğu anlamına gelmez; yönetilen hizmette denetim düzlemi görünmez bir katmandadır. kubeadm ile kurulmuş bir kümede ise aynı komut kube-apiserver, kube-scheduler, kube-controller-manager ve etcd podlarını da gösterir. Yani bu tek komut, kümenin yönetilen bir hizmet mi yoksa kendi kurulumun mu olduğunu bile ele verir.
Etkinlik 1 / 5
Bu komut hangi bileşenlerin durumunu okur?
Önce kodu oku, sonra çıktıyı seç.
$ kubectl get pods -n kube-system
etcd ve sır deposu
etcd kümenin tek doğruluk kaynağıdır. Pod tanımları, yapılandırmalar, ServiceAccount nesneleri ve Secret nesneleri orada durur; bir nesneyi oluşturduğunda aslında etcd'ye bir satır yazmış olursun. Bir sorun burada başlar: Secret değeri API'de yalnız base64 ile kodlanmış görünür ve etcd'ye varsayılan olarak şifresiz yazılır.
Kodlama şifreleme değildir. base64 bir metni geri çevrilebilir bir biçime sokar, hiçbir anahtar kullanmaz ve herkes geri çevirebilir. Yani etcd'nin diskine ya da yedeğine erişen kişi, kümenin bütün parolalarını ve jetonlarını okur. Bu yüzden bir etcd yedeği, en az içindeki en gizli sır kadar hassastır.
Bunu kendi laboratuvar kümende görmek kolaydır. etcd'den bir Secret'ın ham değerini okursun ve içeriği neredeyse düz metin olarak çıkar. Aşağıdaki dökümde uretim ad alanındaki bir veritabanı sırrının anahtar adı da, değeri de okunabilir durumda.
Döküm, dinlenmede şifreleme açık değilken etcd yedeğinin neden tek başına bir sızıntı sayıldığını gösterir. Bir denetimde böyle bir yedeği şifresiz bir kovada bulursan, bulgunun ciddiyeti kovanın erişim ayarından değil, içindeki sırların değerinden gelir.
$ ETCDCTL_API=3 etcdctl get --print-value-only /registry/secrets/uretim/db-sifre | hexdump -C 00000000 6b 38 73 00 0a 0c 0a 02 76 31 12 06 53 65 63 72 |k8s.....v1..Secr| 00000010 65 74 12 20 0a 08 64 62 2d 73 69 66 72 65 0a 06 |et. ..db-sifre..| 00000020 70 61 72 6f 6c 61 12 0c 53 31 66 72 65 39 78 4b |parola..S1fre9xK| 00000030 61 72 67 6f 1a 06 4f 70 61 71 75 65 |argo..Opaque|
Dökümü oku: Secret tipi Opaque, veri anahtarı parola, değeri ise sağ sütunda düz metin olarak görünür. Hiçbir çözme adımı gerekmedi, çünkü değer şifreli değil. Çözüm, Secret'ı etcd'ye yazılmadan önce şifrelemektir.
API sunucusuna bir şifreleme yapılandırması verirsin; o andan sonra her Secret diske şifreli yazılır ve değerin başında k8s:enc: öneki durur. Önek, o kaydın hangi sağlayıcıyla şifrelendiğini söyler; aşağıdaki ikinci dökümde aynı sır artık okunamaz. Böylece etcd diskini ya da yedeğini ele geçiren kişi, anahtar olmadan sır değerini çözemez.
$ ETCDCTL_API=3 etcdctl get --print-value-only /registry/secrets/uretim/db-sifre | hexdump -C 00000000 6b 38 73 3a 65 6e 63 3a 61 65 73 63 62 63 3a 76 |k8s:enc:aescbc:v| 00000010 31 3a 61 6e 61 68 74 61 72 2d 32 30 32 36 3a e7 |1:anahtar-2026:.| 00000020 ee e7 61 5e f3 5f 30 e4 9b 48 2e 15 ca e7 50 07 |..a^._0..H....P.|
Şifreleme açıldığında eski Secret'lar hemen şifrelenmez; yalnız o andan sonra yazılanlar şifreli durur. Var olan sırları da kapsamak için hepsini bir kez yeniden yazdırırsın. kubectl get secrets -A -o json çıktısını kubectl replace ile geri yazarsın. Her Secret bir kez yeniden yazılır ve şifreli hale gelir.
Yönetilen hizmette etcd'yi sağlayıcı işletir ve sen ona doğrudan dokunmazsın. Bazı hizmetler küme verisini artık varsayılan olarak bir bulut anahtar servisiyle zarf şifrelemesinden geçirir, bazılarında bu ayrı bir ayardır. Kendi yönettiğin bir anahtarı kullanmak ise çoğu hizmette ayrıca seçilir. Bu yüzden bir bulut kümesini denetlerken sağlayıcının varsayılanını belgeden doğrular, anahtarın kimde durduğunu not edersin.
Etkinlik 2 / 5
etcd'nin yedeğinin şifresiz bir kovada durması neden kritik bir bulgudur?
Derinleş:Dinlenmede şifreleme nasıl kurulur
API sunucusuna --encryption-provider-config bayrağıyla bir EncryptionConfiguration dosyası verilir. Dosyada hangi kaynakların (secrets, configmaps) hangi sağlayıcıyla şifreleneceği yazar. Sağlayıcı listesi sıralıdır: listedeki ilk sağlayıcı yeni yazılan veriyi şifreler, ötekiler yalnız okumada denenir.
identity sağlayıcısı şifrelemez. Listenin sonunda durursa eski şifresiz kayıtlar okunmaya devam eder; başta durursa şifreleme fiilen kapalıdır. Yerel sağlayıcıların sınırları vardır.
Resmî belge aescbc'yi CBC modunun dolgu kâhini (padding oracle) zayıflığı yüzünden önermez; aesgcm ise anahtarın her 200.000 yazmada döndürülmesini ister. Üstelik yerel anahtar denetim düzlemi makinesinin diskinde durur. Üretimde önerilen yol KMS sağlayıcısıdır.
KMS zarf şifrelemesi kullanır: veri bir veri şifreleme anahtarıyla (DEK) şifrelenir, DEK ise uzak anahtar servisindeki bir anahtar şifreleme anahtarıyla (KEK) sarılır. Böylece ana anahtar kümeye hiç inmez. KMS v2 Kubernetes 1.29'dan beri kararlıdır.
Üç aşama: kimlik, yetki, kabul
API sunucusuna gelen her istek üç aşamadan sırayla geçer. Önce kimlik doğrulanır: istek kimin, bunu kanıtla. Sonra yetkilendirme kararı verilir: bu kimlik bu işlemi bu kaynakta yapabilir mi.
En sonda kabul denetleyicileri çalışır: isteği değiştirir ya da reddeder. Bir politika uygulamak istediğinde onu bu üç aşamadan birine oturtursun; soru her zaman aynıdır, hangi aşama bu kuralın yeri. Varsayılan güvenli bağlantı noktası 6443'tür ve trafik TLS ile korunur, yani kimlik kontrolünden önce bağlantının kendisi şifrelenir.
Kimlik aşaması istemci sertifikası, taşıyıcı jeton ya da ServiceAccount için JSON Web Token kabul eder. Geçersiz bir jeton taşıyan istek 401 Unauthorized ile reddedilir. Hiç kimlik bilgisi taşımayan istek ise anonim erişim açıksa anonim sayılır; kullanıcı adı system:anonymous, grubu system:unauthenticated olur.
Anonim erişim bir yetki kuralıyla eşleşmezse zaten reddedilir, ama --anonymous-auth=false ile onu büsbütün kapatmak sertleştirme listesinin ilk maddelerindendir. CIS ölçütü de kubelet ve API sunucusu için anonim erişimin kapalı olmasını ayrı birer madde olarak denetler.
Yetki aşamasında çoğu küme RBAC kullanır. Kimlik, istenen fiil ve hedef kaynak birlikte değerlendirilir; üçü de eşleşmezse istek reddedilir. Kabul aşamasında ise iki tür denetleyici vardır: değiştiren denetleyici isteği düzeltir (eksik bir alanı doldurur, bir etiket ekler), doğrulayan denetleyici ise kabul eder ya da reddeder.
Önemli bir sınır vardır: kabul denetleyicileri yalnız yazma, silme ve bağlanma isteklerine bakar, salt okuma isteklerine dokunmaz. Bu yüzden okuma denetimi RBAC'in işidir; bir kaynağın okunmasını kabul katmanıyla engelleyemezsin, yetki katmanıyla engellersin.
Şema bir isteğin tüm yolunu gösterir. kubectl isteği API sunucusuna gider, üç aşamadan geçer ve kabul edilirse etcd'ye yazılır. Zamanlayıcı yeni podu bir düğüme atar, o düğümdeki kubelet tanımı okur ve konteyneri başlatır.
Dikkat et: kubelet kararı vermez, yalnız kendisine düşen tanımı uygular; yetki sorusu çoktan API sunucusunda yanıtlanmıştır. Bu yüzden sertleştirmenin ağırlığı o kapıdadır. Düğüme ya da kubelet'e güvenerek yetki kontrolü yapmaya kalkmak yanlış katmanı korumaktır; doğru yer isteğin ilk geçtiği API sunucusudur.
Etkinlik 3 / 5
Kubernetes bileşenini görevi ile eşleştir.
Erişimi daraltma
Küme erişimini daraltmak ilk işlerden biridir. API sunucusunun genel uç noktasını kapatıp özel erişime geçmek, yönetim düzlemini sanal ağ sınırına çeker; erişim VPN ya da sıçrama makinesi üstünden yürür. Yönetilen hizmetlerin çoğunda uç nokta kurulumda genel internete açıktır ve erişim yalnız kimlikle korunur, bu yüzden özele geçmek bilinçli bir karar ister.
Genel uç nokta kapatılamıyorsa en azından kaynak adres listesi daraltılır; yalnız bilinen ağlardan gelen istek kabul edilir, kalanı ağ katmanında düşer. Böylece internetten gelen sürekli deneme trafiği uç noktaya hiç ulaşmaz.
Sürüm yönetimi de güvenlik konusudur. Kubernetes yılda yaklaşık üç küçük sürüm çıkarır ve her sürüm kabaca bir yıl yama desteği alır. Destek dışına düşen bir sürümde yeni açıklar için düzeltme gelmez; o kümede bilinen bir açık kapatılamaz hale gelir.
Bir kümeyi geç yükseltmek, acil durumda birden çok sürüm atlamayı zorunlu kılar ve bu hem riskli hem pahalıdır. Yükseltme takvimini baştan planlamak, destek penceresinin içinde kalmana yardımcı olur ve her yükseltmeyi küçük, öngörülebilir bir adıma indirger.
Denetim günlüğü küme tarafında ayrıca açılır ve varsayılan olarak kapalıdır. API sunucusuna bir denetim politikası dosyası verirsin ve hangi kimliğin hangi kaynağa ne yaptığı bir günlüğe yazılır. Yetkisiz denemeler, olağandışı sır okumaları ve beklenmedik rol değişiklikleri bu kayıttan çıkarılır.
Denetim günlüğü olmadan bir olaydan sonra kümede ne olduğunu geriye dönük anlatmak çok zorlaşır; elinde yalnız şu anki durum kalır, oraya nasıl gelindiği kaybolur. Bu yüzden günlüğü açmak, bir olaydan önce verilmesi gereken bir karardır.
İnsanlara erişim verirken de aynı disiplin geçerlidir. Herkese küme yöneticisi vermek başta hızlı görünür, sonra geri alınamaz bir yayılma olur. Doğru yol kurum kimlik sağlayıcısıyla federasyon kurmak ve rolleri ekip bazında tanımlamaktır; ayrılan çalışanın erişimi o zaman tek yerden kapanır.
Kümeyi elle tıklayarak değil kod olarak kurmak da bir güvenlik kararıdır. Kod olarak tanımlı küme gözden geçirilir, tekrar kurulabilir ve iki ortam arasındaki fark tek bir karşılaştırmayla görünür. CIS Kubernetes ölçütü bileşen ayarlarını denetlemek için somut bir başlangıç listesi verir ve çoğu bulguyu daha ilk turda ortaya çıkarır.
Etkinlik 4 / 5
Doğru mu, yanlış mı?
Kimlik doğrulama açık olduğu sürece API sunucusunun uç noktasını internete açık bırakmak, özel uç noktaya geçmek kadar güvenlidir.
Derinleş:Denetim günlüğü seviyeleri
Denetim politikası her kural için bir seviye belirler. None o isteği hiç yazmaz. Metadata yalnız üstveriyi tutar: kim, ne zaman, hangi fiil, hangi kaynak; istek ve yanıt gövdesi kaydedilmez.
Request üstveriye ek olarak istek gövdesini de yazar. RequestResponse ise istek ve yanıt gövdesini birlikte tutar. Sır içeren kaynaklarda bilinçli bir denge gerekir: Secret okumalarını RequestResponse ile tutarsan sırların kendisi günlüğe düşer ve günlük yeni bir sızıntı yüzeyi olur. Bu yüzden secrets ve configmaps için önerilen seviye Metadata'dır; kimin eriştiğini bilirsin ama sır değerini günlüğe yazmazsın.
Politika kuralları sırayla okunur ve isteğe uyan ilk kural seviyeyi belirler. Bu yüzden dar kurallar başa, her şeyi yakalayan genel kural sona yazılır. omitStages alanıyla RequestReceived gibi gereksiz aşamaları atlarsın ve günlük hacmi düşer. Olaylar bir dosyaya ya da bir webhook arka ucuna gönderilir; günlüğü kümenin dışında saklamak, kümeyi ele geçiren birinin izini silmesini zorlaştırır.
Yetki kararı nerede verilir
Bir kümede ne olduğunu anlamak için önce API sunucusuna bakarsın. Yetki orada verilir, durum etcd'de durur, iş yükü düğümde koşar. Bir sorunu kovalarken bu haritayı izlersin ve her soruyu doğru katmana sorarsın.
API sunucusunun sağlığını denemeden önce kümeye doğru bakıp bakmadığını da bilmek istersin. Sağlık uçları bunun için vardır ve okunması zararsızdır; hiçbir nesneyi değiştirmez, yalnız bileşenlerin o anki durumunu döner, bu yüzden bir denetimin ilk komutlarından biri olur.
$ kubectl get --raw '/readyz?verbose' [+]ping ok [+]log ok [+]etcd ok [+]poststarthook/rbac/bootstrap-roles ok [+]poststarthook/bootstrap-controller ok readyz check passed
Çıktıyı oku: her satır bir kontrolün geçtiğini söyler. etcd satırı API sunucusunun veri deposuna ulaşabildiğini gösterir; bu satır başarısızsa küme yazma isteği alamaz ve çoğu komut takılır. rbac/bootstrap-roles satırı yerleşik rollerin yüklendiğini bildirir.
En alttaki readyz check passed, API sunucusunun trafik almaya hazır olduğunu söyler. livez ucu ise bileşenin canlı olup olmadığını ayrı anlatır. Eski healthz ucu 1.16'dan beri kullanımdan kalkmış sayılır; yerini daha ayrıntılı livez ve readyz uçları aldı. Yeni kontroller bu iki uç üstünden kurulur ve hangi alt kontrolün takıldığını tek tek gösterir.
Etkinlik 5 / 5
Kümeye gelen bir kubectl isteğinde yetkilendirme kararının verildiği noktayı seç.
Diyagramda doğru kutuyu tıkla.
Okumayı istediğin sırayla sürdürebilirsin. Ders, bütün etkinlikleri cevapladığında tamamlanır.