Kümeyi Kurmak: Ready Yazması Kümenin Çalıştığı Anlamına Gelmez
- Murat Akpınar
- Kubernetes öğrenme yolculuğu
- 29 Ağustos 2026
İçindekiler
Önceki yazıda kurulmuş bir kümenin kapağını açtık: bileşenlerin birbirini hiç aramadığını, hepsinin yalnızca API sunucusunu okuyup yazdığını gördük. Orada bir söz vermiştik — o kümeyi nasıl kurduğumuz bir sonraki başlıktı. Şimdi argo-cp01, argo-w01 ve argo-w02‘yi sıfırdan ayağa kaldırıyoruz.
Kurulum rehberlerinin çoğu aynı satırda biter: kubectl get nodes çıktısında bütün düğümler Ready. O satır kümenin kurulduğunu kanıtlar, çalıştığını değil. Ready yazan bir kümede bir düğümdeki pod diğer düğümdekine hiç ulaşamıyor, DNS çözülmüyor ve Service’e giden trafik boşluğa düşüyor olabilir. Çünkü Ready, kubelet’in “çalışma zamanım ayakta, ağ eklentim kendini başlattı” demesinden ibarettir; trafiğin iki düğüm arasında fiilen aktığını hiçbir yerde iddia etmez.
Bu yazıda iki ayrı küme kuracağız. Önce kind ile beş dakikada tek komutluk bir öğrenme kümesi — kavramları denemek için. Sonra üç Debian düğüm üzerinde kubeadm ile gerçek kümeyi: düğüm hazırlığı, containerd, CNI, join ve kubeconfig. Aralarda dağıtım seçeneklerini karşılaştıracak, kurulumda en sık batılan beş yeri tek tek göstereceğiz. En sonunda da Ready satırının kanıtlamadığı şeyi kanıtlayan bir doğrulama seti çalıştıracağız.
Aşağıdaki sunucu adları, IP’ler, UUID’ler, MAC adresleri ve token’lar kurgusaldır; sizin ortamınızda farklı olacak. Sürüm numaralarını da kendi kümenize göre güncelleyin. Komutlar, çıktı biçimleri ve davranışlar gerçektir. Uzun çıktılarda sütunlar okunabilirlik için kısaltılmıştır.
Yazı boyunca geçen terimlerin kısa karşılıkları için sondaki terimler sözlüğüne bakabilirsiniz.
İki Küme, İki Amaç: Neden Önce kind, Sonra kubeadm?
Kubernetes öğrenirken en çok kaybedilen zaman, öğrenme kümesiyle üretim kümesini aynı şey sanmaktan çıkar. İkisi farklı sorulara cevap verir.
Öğrenme kümesi tek soruya hizmet eder: “bu nesne nasıl davranıyor?” Deployment’ın kopyaları nasıl ayakta tuttuğunu, Service’in trafiği nasıl dağıttığını, ConfigMap’in pod’a nasıl bağlandığını görmek için üç fiziksel düğüme ihtiyacınız yok. kind bunu dizüstü bilgisayarınızda, tek komutla, silmesi de kurması kadar ucuz biçimde verir.
Kurulum kümesi ise bambaşka bir soruya cevap verir: “bu küme neyden yapılmış?” Takasın neden kapatıldığını, cgroup sürücüsünün neden eşleşmesi gerektiğini, CNI kurulmadan düğümün neden Ready olmadığını ancak elinizle kurarken öğrenirsiniz. Bu bilgi bir gün sizi 03:00’te ayağa kaldıran arızanın çözüm süresini belirler.
Sıra bu yüzden önemli: kind ile ne yapmak istediğinizi öğrenin, kubeadm ile bunun altında ne olduğunu.
flowchart TB
A["1 · Düğüm hazırlığı<br/>takas kapalı · br_netfilter · ip_forward"] --> B["2 · containerd<br/>CRI eklentisi açık · SystemdCgroup = true"]
B --> C["3 · kubeadm init<br/>control plane statik pod'ları başlar"]
C --> D{"kubectl get nodes"}
D -->|"NotReady · cni plugin not initialized"| E["4 · CNI kurulumu<br/>pod ağı ve düğümler arası yönlendirme"]
E --> F["5 · kubeadm join<br/>worker'lar kümeye katılır"]
F --> G{"Hepsi Ready"}
G -->|"Bu satır yalnızca kurulumu kanıtlar"| H["6 · Doğrulama<br/>düğümler arası pod trafiği · DNS · readyz"]
classDef adim fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef kapi fill:#fef3c7,stroke:#d97706,color:#78350f
classDef dogru fill:#dcfce7,stroke:#16a34a,color:#14532d
class A,B,C,E,F adim
class D,G kapi
class H dogru
Beş Dakikada Öğrenme Kümesi: kind
kind (Kubernetes IN Docker) kümenin düğümlerini sanal makine olarak değil, konteyner olarak çalıştırır. Her düğüm, içinde systemd, kubelet ve containerd barındıran tek bir Docker konteyneridir. Bu yüzden bir küme saniyeler içinde kurulur ve saniyeler içinde silinir.
Kurulumu bu yazıda argo-lab01 (192.168.30.11) üzerinde yapıyoruz — 47 numaralı yazıda konteynerleri incelediğimiz Debian 12 makinesi. Ön koşul tek şey: çalışan bir Docker (veya Podman).
Tek Düğüm: kind create cluster
KIND_SURUM=v0.29.0 # güncel sürüm: https://github.com/kubernetes-sigs/kind/releases
curl -Lo ./kind "https://kind.sigs.k8s.io/dl/${KIND_SURUM}/kind-linux-amd64"
chmod +x ./kind && sudo mv ./kind /usr/local/bin/kind
kind version
Düğüm imajı etiketini kind’in kendi yayım notlarından alın: kind her Kubernetes yama sürümü için düğüm imajı yayımlamaz. Rastgele bir v1.33.x etiketi yazarsanız docker pull 404 döner. Bu yazıda v1.33.1 kullanıyoruz — kubeadm kümemizin v1.33.4 olması sorun değil, ikisi ayrı kümeler.
kind create cluster --name ogrenme --image kindest/node:v1.33.1
Creating cluster "ogrenme" ...
✓ Ensuring node image (kindest/node:v1.33.1)
✓ Preparing nodes
✓ Writing configuration
✓ Starting control-plane
✓ Installing CNI
✓ Installing StorageClass
Set kubectl context to "kind-ogrenme"
Dikkat edilecek iki satır var: Installing CNI ve Installing StorageClass. kind bunları sizin yerinize kurar (kindnetd ve local-path-provisioner). Birazdan kubeadm ile kuracağımız kümede o iki satır yok — ve düğüm tam olarak bu yüzden NotReady başlayacak.
kubectl get nodes
NAME STATUS ROLES AGE VERSION
ogrenme-control-plane Ready control-plane 41s v1.33.1
Çok Düğümlü kind: Düğümler Aslında Konteyner
Tek düğüm, “pod hangi düğüme yerleşti” sorusunu soramaz. Üç düğüm için bir yapılandırma dosyası yeter:
# kind-uc-dugum.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: ogrenme
nodes:
- role: control-plane
- role: worker
- role: worker
kind delete cluster --name ogrenme
kind create cluster --config kind-uc-dugum.yaml --image kindest/node:v1.33.1
docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}'
CONTAINER ID NAMES STATUS
b7c1e93a4d02 ogrenme-control-plane Up 47 seconds
5f2a80d6b1c9 ogrenme-worker Up 47 seconds
e34c7b19f80a ogrenme-worker2 Up 47 seconds
Önceki yazıda düğümün içinde crictl ile konteynerlere bakmıştık. Burada da aynısını yapabilirsiniz — sadece önce konteynere girmeniz gerekiyor:
docker exec -it ogrenme-worker crictl ps
kind’in Gösteremedikleri
kind hızlı olduğu için sınırlarını bilmeden kullanmak kolay. Dördü öğrenme sırasında mutlaka karşınıza çıkar:
- Yereldeki imajınız düğümde yoktur.
docker buildile ürettiğiniz imaj host’un imaj deposundadır, düğüm konteynerinin değil. PodErrImagePullverir. Çözümkind load docker-image ornek/api:1.4.2 --name ogrenme. LoadBalancertüründeki Service sonsuza kadar<pending>kalır. Adresi dağıtacak bir bulut denetleyicisi yoktur;cloud-provider-kindveya MetalLB kurmadan o alan dolmaz. NodePort ve port-forward çalışır.- Düğüm arızası tatbikatı gerçekçi değildir.
docker stop ogrenme-workerdüğümü kaybettirir ama üç “düğüm” de aynı çekirdeği paylaşır; çekirdek düzeyinde bir arızayı ya dasysctlfarkını düğüm bazında sınayamazsınız. - Küme silindiğinde veri de gider. Kalıcı birimler düğüm konteynerinin içindedir;
kind delete clusterhepsini siler.
Alternatif: Tek Binary ile k3s
Docker’la uğraşmak istemiyorsanız veya kümeyi gerçek bir sanal makinede istiyorsanız k3s tek satırdır:
curl -sfL https://get.k3s.io | sh -
sudo k3s kubectl get nodes
k3s tek bir binary’nin içinde containerd, Flannel CNI, Traefik ingress, ServiceLB ve local-path depolama sınıfını birlikte getirir; veri deposu olarak da varsayılan kurulumda etcd yerine SQLite kullanır. Her biri --disable ile kapatılabilir.
Bir tuzağı var: kubeconfig /etc/rancher/k3s/k3s.yaml yolunda ve yalnızca root okuyabilir. Sıradan kullanıcıyla kubectl çalıştırınca permission denied alırsınız. Doğrusu dosyayı kopyalamaktır, izinlerini gevşetmek değil:
mkdir -p ~/.kube
sudo install -o "$(id -u)" -g "$(id -g)" -m 600 /etc/rancher/k3s/k3s.yaml ~/.kube/k3s.yaml
Dağıtım Seçenekleri: kubeadm, k3s, RKE2 ve Yönetilen Servisler
“Kubernetes kurmak” tek bir iş değil; hangi parçayı kendinizin kuracağına karar vermektir.
| kubeadm | k3s | RKE2 | Yönetilen (EKS/AKS/GKE) | |
|---|---|---|---|---|
| Kim kurar | Yukarı akış referans aracı | Rancher / SUSE | Rancher / SUSE | Bulut sağlayıcı |
| Çalışma zamanı | Siz kurarsınız | Gömülü containerd | Gömülü containerd | Sağlayıcı |
| Varsayılan CNI | Yok — siz seçersiniz | Flannel | Canal (Calico + Flannel) | Sağlayıcının eklentisi |
| Veri deposu | etcd | SQLite (tek sunucu) veya gömülü etcd | etcd | Sağlayıcıda, erişiminiz yok |
| Control plane | Sizin düğümünüzde statik pod | Tek süreç | Statik pod | Sağlayıcıda |
| Sertleştirme | Elle | Elle | CIS profili hazır gelir | Sağlayıcının varsayılanı |
| Nerede yerinde | Öğrenmek, CKA, özel altyapı | Homelab, kenar, geliştirme | Kurumsal şirket içi, denetime tabi ortam | Ekip küçük, bulut zaten kullanımda |
Üç şey karara girmeli:
- kubeadm hiçbir şeye karar vermez, hepsini size bırakır. CNI, ingress, depolama, izleme — hepsi ayrı adımdır. Öğrenmek için en iyisi bu, çünkü her parçayı elinizle takarsınız. Aynı sebeple en yavaşıdır.
- k3s ve RKE2 kararları sizin yerinize verir. Hızlı ayağa kalkar ama varsayılanı beğenmediğinizde geri sökmeniz gerekir. RKE2’yi Ansible ile kurmayı 30 numaralı yazıda adım adım ele almıştım.
- Yönetilen serviste control plane sizin değildir. etcd’ye bakamaz, apiserver bayraklarını değiştiremez, yükseltme takvimini seçemezsiniz — ama etcd yedeğini de siz almazsınız. Küme başına saatlik bir ücret ödersiniz; asıl fatura genellikle worker düğümlerinden gelir.
Bundan sonrası kubeadm. Sebep şu: kubeadm ile kurulan bir kümede hangi bileşenin neden orada olduğunu görebilirsiniz. k3s ile başlarsanız kümeniz beş dakikada ayağa kalkar, ama bir yıl sonra Flannel’ın oraya nasıl geldiğini bilmezsiniz.
Kurulumdan Önce: Düğümleri Hazırlamak
Üç Debian 12 düğümümüz var. Hepsinde aşağıdaki adımlar aynen çalıştırılacak — control plane ile worker arasında bu aşamada fark yok.
| Düğüm | IP | Rol | MAC | product_uuid |
|---|---|---|---|---|
argo-cp01 |
192.168.30.21 |
control plane | 52:54:00:a3:1f:0b |
f2a9c1d4-7b3e-4a58-9c06-1d8e5b2f37a4 |
argo-w01 |
192.168.30.22 |
worker | 52:54:00:c7:2d:14 |
3b7e0c92-45af-4d1e-8a63-2f9c04d17e58 |
argo-w02 |
192.168.30.23 |
worker | 52:54:00:6e:8b:39 |
a1d63f08-92c5-4b7e-b304-6e8f215c9d7b |
Gateway 192.168.30.1. Pod ağı için 10.244.0.0/16 seçtik; niçin bu blok olduğunu birazdan göreceğiz.
Kimlik: Aynı Şablondan Klonlanan Düğüm Kümeye Giremez
Kubernetes düğümü adıyla tanır: Node nesnesinin adı düğümün hostname’idir. Bu yüzden şablondan klonlanmış üç sanal makineyi hostname değiştirmeden kümeye katarsanız ikinci düğüm birincinin kaydını devralır, üçüncüsü de ikincininkini — üç makineniz olur, tek düğümünüz.
kubeadm bunu kendi başına yakalayamaz: kubeadm join çalıştığı anda diğer düğümlerin ne olduğunu bilmez. Denetim sizin işiniz, ve üç düğümde de şunu çalıştırmak yeterlidir:
hostnamectl --static
ip -o link show | awk '$2 !~ /lo:/ {print $2, $(NF-2)}'
sudo cat /sys/class/dmi/id/product_uuid
cat /etc/machine-id
Klonlanmış bir şablonda çıktı tipik olarak şöyle görünür — hostname ve MAC ayrı, kimliklerin geri kalanı ortak:
argo-w01
enp1s0: 52:54:00:c7:2d:14
3b7e0c92-45af-4d1e-8a63-2f9c04d17e58
a4f18c2b7e0d4956bd31c07f95e2a8d3
argo-w02
enp1s0: 52:54:00:6e:8b:39
3b7e0c92-45af-4d1e-8a63-2f9c04d17e58 ← argo-w01 ile aynı
a4f18c2b7e0d4956bd31c07f95e2a8d3 ← argo-w01 ile aynı
Hostname ve MAC farklı, ama product_uuid ve /etc/machine-id aynı. kubeadm belgeleri hostname, MAC ve product_uuid‘nin her düğümde benzersiz olmasını ön koşul sayar; machine-id ise systemd tarafında DHCP istemci kimliği olarak kullanıldığı için iki düğüme aynı IP’nin dağıtılmasına yol açabilir. Şablondan klonluyorsanız düzeltmesi tek satır:
sudo truncate -s 0 /etc/machine-id && sudo systemd-machine-id-setup && sudo reboot
product_uuid sanal makinenin SMBIOS kimliğinden gelir; Proxmox’ta VM’in smbios1 ayarında, vSphere’de uuid.bios alanındadır. Disk imajını elle kopyaladıysanız hipervizör tarafında yeni bir UUID atamanız gerekir. Bölüm başındaki tabloda yazan değerler bu düzeltmeden sonraki hâldir — argo-w02‘nin product_uuid‘si orada a1d63f08-… olarak görünüyor.
Takas, Çekirdek Modülleri ve sysctl
Takas kapalı olacak. kubelet varsayılan olarak takas açıkken başlamayı reddeder, kubeadm init de ön koşul denetiminde [ERROR Swap] verip durur. Kubernetes 1.28’den beri beta olan NodeSwap özelliği cgroup v2 üzerinde Burstable sınıfındaki pod’lara sınırlı takas kullandırabiliyor, ama bu bilinçli olarak açılan bir özelliktir; öğrenme kümesinde takası kapalı tutmak doğru varsayılandır.
sudo swapoff -a
sudo sed -i '/\sswap\s/ s/^/#/' /etc/fstab
swapon --show # çıktı boş olmalı
Takas /etc/fstab yerine bir systemd birimiyle tanımlıysa (*.swap) yukarıdaki sed ona dokunmaz ve takas ilk yeniden başlatmada geri gelir. Birimi bulup kapatın:
systemctl list-units --type=swap
sudo systemctl mask dev-vda3.swap
Sonra çekirdek modülleri ve yönlendirme ayarları:
cat <<'EOF' | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
Sıra burada önemli. net.bridge.bridge-nf-call-iptables diye bir sysctl anahtarı, br_netfilter modülü yüklenmeden var olmaz. Modülü yüklemeden sysctl dosyasını yazıp sysctl --system çalıştırırsanız komut cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory diyerek düşer. Önce modprobe, sonra sysctl:
cat <<'EOF' | sudo tee /etc/sysctl.d/99-kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
Doğrulama — üç düğümde de aynı iki satır çıkmalı:
lsmod | grep -E '^(overlay|br_netfilter)'
sysctl net.ipv4.ip_forward net.bridge.bridge-nf-call-iptables
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
Açık Kalması Gereken Portlar
Güvenlik duvarını kapatmak bir çözüm değil, sorunu ertelemektir. Kubernetes’in ihtiyaç duyduğu portlar sayılıdır:
| Düğüm | Port | Protokol | Kullanan |
|---|---|---|---|
| Control plane | 6443 | TCP | kube-apiserver — bütün düğümler ve kubectl buraya bağlanır |
| Control plane | 2379-2380 | TCP | etcd istemci ve eş (peer) trafiği |
| Control plane | 10250 | TCP | kubelet API — kubectl logs, exec, metrik toplama |
| Control plane | 10257 | TCP | kube-controller-manager |
| Control plane | 10259 | TCP | kube-scheduler |
| Worker | 10250 | TCP | kubelet API |
| Worker | 10256 | TCP | kube-proxy sağlık kontrolü |
| Tüm düğümler | 30000-32767 | TCP | NodePort Service aralığı |
Bu tablo eksiktir ve eksik olduğunu bilmek önemlidir: CNI kendi trafiğini ekler ve bu trafik seçtiğiniz kapsülleme moduna göre değişir. Calico VXLAN modunda 4789/UDP, IPIP modunda IP protokol numarası 4, BGP eşleşmesi için 179/TCP kullanır. Birazdan kuracağımız yapılandırmada mod VXLANCrossSubnet — yani yalnızca farklı alt ağlardaki düğümler arasında kapsülleme yapar. Üç düğümümüz de 192.168.30.0/24 üzerinde olduğu için bizim lab’imizde kapsülleme devreye girmez; düğümler arasında geçmesi gereken şey doğrudan 10.244.0.0/16 hedefli yönlendirilmiş trafiktir.
Fark pratikte şuraya çıkar: düğümlerinizi farklı alt ağlara yaydığınız gün 4789/UDP kapalıysa küme kurulur, bütün düğümler Ready görünür, pod’lar Running durur — ve düğümler arası pod trafiği sessizce ölür. Doğrulama bölümünde bunu fiilen sınayacağız.
Konteyner Çalışma Zamanı: containerd ve İki Ayarın Tuzağı
Debian’ın kendi deposundaki containerd paketi 1.6 serisinde kalıyor; kümemizin sürümü olan 1.7.24 için Docker deposunu ekliyoruz:
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update && sudo apt-get install -y containerd.io
containerd --version
containerd containerd.io 1.7.24
Şimdi iki ayar. İkisi de atlanabilir görünür, ikisi de kümeyi yıkar.
Birincisi: paketin getirdiği yapılandırmada CRI eklentisi kapalıdır. containerd.io paketi /etc/containerd/config.toml dosyasını disabled_plugins = ["cri"] satırıyla kurar. Kubernetes containerd ile yalnızca CRI üzerinden konuşur; bu satır dururken kubelet çalışma zamanına hiç bağlanamaz. Çözüm dosyayı düzenlemek değil, varsayılanı baştan üretmektir:
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
İkincisi: cgroup sürücüsü kubelet ile eşleşmeli. kubeadm, 1.22’den beri kubelet’i cgroupDriver: systemd ile yapılandırır. containerd 1.x’in varsayılanı ise cgroupfs. İkisi farklı kaldığında düğümün cgroup ağacını iki ayrı yazıcı yönetir — cgroup v2’nin tek yazıcı kuralının ihlali. kubeadm belgeleri bu eşleşmeyi zorunlu tutar; uyuşmazlık kubelet’in gördüğü kaynak kullanımını gerçeklikten kopardığı için düğüm baskı altında beklenmedik biçimde davranır.
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo containerd config dump | grep -i 'systemdcgroup'
SystemdCgroup = true
Yukarıdaki sed containerd 1.7 yapılandırmasına göre yazılmıştır. containerd 2.0 ile yapılandırma biçimi version = 3‘e geçti, çalışma zamanı eklentisinin anahtarı io.containerd.grpc.v1.cri yerine io.containerd.cri.v1.runtime oldu ve SystemdCgroup‘un varsayılanı da true‘ya çevrildi. 2.x kullanıyorsanız aynı sed sessizce hiçbir şeyi değiştirmez — komuttan önce containerd --version ile sürümünüzü doğrulayın, sonra containerd config dump çıktısından okuyarak teyit edin.
Son bir ayrıntı: containerd config default çıktısındaki sandbox_image etiketi kümenin beklediğinden eski olabilir. kubeadm init bunu ön koşul denetiminde uyarı olarak bildirir ve beklediği etiketi yazar; config.toml‘daki satırı o değere eşitleyip containerd’yi yeniden başlatın.
Kubernetes Paketleri: Depo Adresi Minör Sürüme Bağlıdır
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
İki nokta:
- İnternette bulacağınız eski rehberlerin çoğu
apt.kubernetes.ioveyapackages.cloud.google.comadreslerini gösterir. O depolar dondurulup kapatıldı; yerlerine topluluk tarafından işletilenpkgs.k8s.iogeldi. Eski adresi kullanan bir rehber 2024’ten kalmadır veapt-get update403 ile döner. - Depo adresi minör sürüme özeldir (
v1.33). 1.34’e yükselirken önce bu satırı düzenlemeniz gerekir.apt-mark holdde tam bu yüzden var: sıradan birapt upgradesizi habersiz bir minör sürüme taşımasın. Kubernetes’te minör sürüm atlamak (1.33’ten 1.35’e) desteklenmez.
Control Plane’i Ayağa Kaldırmak: kubeadm init
Kurulumdan önce control plane’e sabit bir ad veriyoruz. DNS sunucunuz varsa oraya, yoksa üç düğümün /etc/hosts dosyasına:
echo '192.168.30.21 argo-api.k8s-lab.local' | sudo tee -a /etc/hosts
Sonra yalnızca argo-cp01 üzerinde:
sudo kubeadm init \
--apiserver-advertise-address=192.168.30.21 \
--control-plane-endpoint=argo-api.k8s-lab.local:6443 \
--pod-network-cidr=10.244.0.0/16 \
--kubernetes-version=v1.33.4
Üç bayrağın üçü de sonradan düzeltilmesi zor kararlardır:
--apiserver-advertise-addressyazılmazsa kubeadm varsayılan yönlendirme (default route) hangi arayüzden geçiyorsa onun adresini seçer. Düğümde ikinci bir NIC varsa — depolama ağı, yedekleme ağı, NAT arayüzü — apiserver kendini yanlış adresten duyurur ve o adres worker’lardan erişilemez olur.--control-plane-endpointileride ikinci bir control plane eklemek isterseniz kurulum anında verilmiş olmalıdır. kubeadm, bu bayrak olmadan kurulmuş bir kümeye sonradan control plane düğümü katmayı desteklemez. Buraya düğümün kendi IP’sini yazmak da bir işe yaramaz — kazanç, adresin sonradan bir yük dengeleyiciye ya da sanal IP’ye taşınabilmesinden gelir. Tek düğümlü kurulumda bile bir ad yazmak, sonraki yılın işini kolaylaştıran ücretsiz bir karardır.--pod-network-cidrbirazdan kuracağımız CNI’ın yapılandırmasıyla aynı olmalı. Ayrıca yerel ağınızla çakışmamalı;10.244.0.0/16seçmemizin sebebi lab ağımızın192.168.30.0/24olması.
kubeadm’ın kendi kuru çalıştırma kipi var ve kurulum öncesi denetimi ona bırakmak, aşağıdaki hataların çoğunu düğüme hiç dokunmadan yakalar:
sudo kubeadm init --dry-run \
--apiserver-advertise-address=192.168.30.21 \
--control-plane-endpoint=argo-api.k8s-lab.local:6443 \
--pod-network-cidr=10.244.0.0/16
Bu kip ön koşul denetimlerini gerçekten çalıştırır, üreteceği sertifikaları ve manifestleri geçici bir dizine yazar, sisteme kalıcı hiçbir şey bırakmaz. kubeadm join de aynı bayrağı kabul eder.
Kuru çalıştırma temizse gerçeğini başlatın. Çıktının sonundaki join satırını saklayın:
Your Kubernetes control-plane has initialized successfully!
kubeadm join argo-api.k8s-lab.local:6443 --token 7t9x2k.q3m8vzp1r4bnc0ld \
--discovery-token-ca-cert-hash sha256:9f4c1e7b3a082d65f1c9e40b7d2a83f6c5b1e947a0d38c26f9b415e703a8d2c4
kubeconfig’i kendi kullanıcınıza alın:
mkdir -p "$HOME/.kube"
sudo cp -i /etc/kubernetes/admin.conf "$HOME/.kube/config"
sudo chown "$(id -u):$(id -g)" "$HOME/.kube/config"
Control plane bileşenleri statik pod olarak çalışıyor — önceki yazıda kubelet’in API sunucusuna sormadan başlattığı pod türü. Manifestleri görebilirsiniz:
ls /etc/kubernetes/manifests/
etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yaml
Ve düğüm:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
argo-cp01 NotReady control-plane 62s v1.33.4
NotReady. Bu bir hata değil, beklenen durum — sebebini kendisi söylüyor:
kubectl describe node argo-cp01 | grep -A2 'Ready '
Ready False KubeletNotReady container runtime network not ready:
NetworkReady=false reason:NetworkPluginNotReady
message:Network plugin returns error: cni plugin not initialized
CNI Kurulmadan Düğüm Ready Olmaz
Kubernetes pod ağını bilerek boş bırakır: hangi CNI eklentisini kullanacağınıza siz karar verirsiniz, kubelet de eklenti kendini /etc/cni/net.d altına yazana kadar düğümü hazır saymaz. Burada Calico kuruyoruz — Flannel’dan farkı, ilerideki NetworkPolicy başlığında ihtiyacımız olacak politika desteğini getirmesi.
CALICO_SURUM=v3.29.1 # Kubernetes sürümünüzle uyumlu olanı Calico'nun sürüm notlarından seçin
kubectl create -f "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_SURUM}/manifests/tigera-operator.yaml"
Komutun apply değil create olması bilerek: tigera-operator.yaml içindeki CRD’ler, kubectl apply‘ın nesneye eklediği last-applied-configuration açıklamasının 262144 baytlık sınırını aşacak kadar büyük. apply ile kurmayı denerseniz metadata.annotations: Too long hatası alırsınız.
Şimdi pod ağını tanımlayan kaynak dosyasını indirip CIDR’ı düzeltiyoruz:
curl -sSLO "https://raw.githubusercontent.com/projectcalico/calico/${CALICO_SURUM}/manifests/custom-resources.yaml"
Dosyadaki cidr satırının varsayılanı 192.168.0.0/16‘dır. Bu değeri olduğu gibi bırakmak, ev ve ofis ağlarının büyük çoğunluğunda kümeyi kendi yerel ağınızla çakıştırır — bizim lab ağımız 192.168.30.0/24 de o bloğun içinde. kubeadm init‘e verdiğimiz değerle eşitliyoruz:
calicoNetwork:
ipPools:
- name: default-ipv4-ippool
blockSize: 26
cidr: 10.244.0.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
kubectl create -f custom-resources.yaml
kubectl -n calico-system get pods -w
Pod’lar Running‘e geçtikten sonra düğüm hazır olur:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
argo-cp01 Ready control-plane 6m14s v1.33.4
Ayrıca kube-system altında CNI kurulana kadar Pending bekleyen CoreDNS pod’ları da şimdi ayağa kalkar — CNI’nın gerçekten çalıştığının ilk ve en ucuz işareti budur:
kubectl -n kube-system get deploy coredns
NAME READY UP-TO-DATE AVAILABLE AGE
coredns 2/2 2 2 6m02s
Bu iki kopya şu an control plane düğümünde çalışıyor: kubeadm control plane’i node-role.kubernetes.io/control-plane:NoSchedule ile işaretler, CoreDNS dağıtımı da o işareti tolere eden birkaç bileşenden biridir. Worker’lar katıldıktan sonra mevcut pod’lar kendiliğinden taşınmaz; yeniden yerleştirmek isterseniz dağıtımı yeniden başlatmanız gerekir.
Worker’ları Katmak: kubeadm join ve Token’ın 24 Saatlik Ömrü
argo-w01 ve argo-w02 üzerinde, kubeadm init çıktısındaki satırı çalıştırıyoruz:
sudo kubeadm join argo-api.k8s-lab.local:6443 \
--token 7t9x2k.q3m8vzp1r4bnc0ld \
--discovery-token-ca-cert-hash sha256:9f4c1e7b3a082d65f1c9e40b7d2a83f6c5b1e947a0d38c26f9b415e703a8d2c4
Komuttaki iki parça iki ayrı yöne güven kuruyor: token kümeye “bu düğüm katılmaya yetkili” der, CA sertifika özeti ise düğüme “bu gerçekten benim kümemin API sunucusu” der. İkincisi olmadan düğüm, araya giren herhangi bir sunucuyu control plane sanabilirdi.
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP CONTAINER-RUNTIME
argo-cp01 Ready control-plane 14m v1.33.4 192.168.30.21 containerd://1.7.24
argo-w01 Ready <none> 2m51s v1.33.4 192.168.30.22 containerd://1.7.24
argo-w02 Ready <none> 2m19s v1.33.4 192.168.30.23 containerd://1.7.24
ROLES sütununda <none> yazması bir eksiklik değil: kubeadm worker düğümlerine rol etiketi koymaz. Yalnızca görsel bir düzen istiyorsanız kendiniz koyabilirsiniz; bu etiketin zamanlamaya ya da yetkilendirmeye hiçbir etkisi yoktur.
kubectl label node argo-w01 argo-w02 node-role.kubernetes.io/worker=
Token’ın varsayılan ömrü 24 saattir. Ertesi gün dördüncü düğümü katmaya kalktığınızda join şu hatayla düşer:
error execution phase preflight: couldn't validate the identity of the API Server:
could not find a JWS signature in the cluster-info ConfigMap for token ID "7t9x2k"
Panik gerektirmez; yeni token üretmek tek komuttur ve join satırının tamamını yeniden basar:
sudo kubeadm token list
sudo kubeadm token create --print-join-command
CA özetini de kaybettiyseniz control plane üzerinde yeniden hesaplayabilirsiniz:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt \
| openssl rsa -pubin -outform der 2>/dev/null \
| openssl dgst -sha256 -hex | sed 's/^.* //'
kubeconfig ve Bağlam: Birden Fazla Kümeyle Çalışmak
Artık iki kümeniz var: kind ile kurduğunuz ogrenme ve kubeadm ile kurduğunuz gerçek küme. kubectl hangisine bağlanacağını bağlam (context) üzerinden bilir.
kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO
kind-ogrenme kind-ogrenme kind-ogrenme
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
kubeadm’ın ürettiği bağlam adı her kümede aynıdır: kubernetes-admin@kubernetes. Üç kümeniz olduğunda bu isim hiçbir şey anlatmaz — daha kurulum gününde yeniden adlandırın:
kubectl config rename-context kubernetes-admin@kubernetes argo-lab
kubectl config use-context argo-lab
kubectl config set-context --current --namespace=uygulama
Birden fazla kubeconfig dosyasını birleştirmek için KUBECONFIG değişkenini iki nokta ile ayrılmış liste olarak verip düzleştirebilirsiniz:
KUBECONFIG=~/.kube/config:~/.kube/k3s.yaml kubectl config view --flatten > ~/.kube/birlesik
mv ~/.kube/birlesik ~/.kube/config
Üç şeye dikkat:
KUBECONFIGlistesinde yalnızca ilk dosya yazılabilir. Birden çok dosyayı birleştirmiş bir kabuktakubectl config use-contextçalıştırdığınızda değişiklik listenin ilk dosyasına yazılır. Bağlamı ikinci dosyada tanımlı sanıp orada arayan bir sonraki kişi (çoğunlukla siz) değişikliği bulamaz.admin.confbir yönetici anahtarıdır, ekiple paylaşılmaz. Kubernetes 1.29’dan beri kubeadm bu dosyayısystem:mastersyerinekubeadm:cluster-adminsgrubuna bağlar ve RBAC ile kısıtlanabilir hale getirir; RBAC’ın devre dışı kaldığı acil durumlar için ayrıcasuper-admin.confüretir ve o dosya control plane düğümünde kalır. Ekip erişimi için doğru yol ayrı ServiceAccount ve Role tanımlamaktır.admin.confiçindeki istemci sertifikası bir yıl geçerlidir. Süre dolduğundakubectlher komutta yetkilendirme hatası verir. Yenileme komutunu doğrulama bölümünde göreceğiz.
kubectl hangi kümede olduğunuzu asla sormaz. Bir delete komutu yanlış bağlamda çalıştığında geri alma yoktur; kabuk isteminize aktif bağlamı yazdırmak, kurulumdan sonra yapılacak en ucuz güvenlik önlemidir.
Yanlış Yapılırsa: Kurulumda En Sık Batılan Beş Yer
1. Takas açık bırakmak. kubeadm init daha başlamadan durur:
[ERROR Swap]: swap is supported for cgroup v2 only. The kubelet must be properly configured
to use swap. Please refer to https://kubernetes.io/docs/concepts/architecture/nodes/#swap-memory
Bu hatanın iyi tarafı görünür olması. Kötü tarafı, --ignore-preflight-errors=Swap ile susturulabilir olması — ve o zaman sorun kurulumda değil, aylar sonra bir düğüm bellek baskısı altında tuhaf davrandığında ortaya çıkar.
2. cgroup sürücüsünü eşitlememek. Bu hata hiç hata vermez: küme kurulur, düğüm Ready olur, pod’lar çalışır. kubelet systemd ağacına, containerd cgroupfs ağacına yazar; iki muhasebe birbirini tutmaz. Denetimi kurulum gününde yapın, çünkü sonradan bulmak zordur:
sudo containerd config dump | grep -i systemdcgroup
sudo grep cgroupDriver /var/lib/kubelet/config.yaml
SystemdCgroup = true
cgroupDriver: systemd
3. Pod CIDR’ını yerel ağla çakıştırmak. Calico’nun varsayılanını değiştirmeden kurarsanız pod ağınız 192.168.0.0/16 olur ve lab ağımız 192.168.30.0/24 bu bloğun içinde kalır. Bu arızanın tehlikeli yanı hemen ortaya çıkmamasıdır: Calico havuzdan düğümlere /26‘lık bloklar dağıtır, ilk gün dağıtılan bloklar 192.168.30.0/24 aralığına düşmeyebilir ve küme haftalarca sorunsuz çalışır. Bir gün bir düğüme 192.168.30.64/26 bloğu düştüğünde o bloktaki pod’lar yerel ağınızdaki gerçek makinelerle aynı adresi taşımaya başlar; düğüm yerel ağdaki bir adresi pod sanıp trafiği CNI’a yönlendirir. Belirti “ağ bazen çalışıyor” olur — teşhisi en pahalı arıza türü. kubeadm init‘e verdiğiniz --pod-network-cidr ile CNI yapılandırmasındaki cidr birbirinin aynısı ve yerel ağınızdan ayrık olmalı.
4. Token’ı beklemek. 24 saat sonra elinizdeki join satırı geçersizdir. Kurulum belgenize join komutunu kopyalayıp saklamak yerine kubeadm token create --print-join-command komutunu yazın; ilki bir gün sonra yalan söyler, ikincisi her zaman doğrudur.
5. Yanlış NIC’ten duyurmak. Düğümde ikinci bir arayüz varsa — bizim lab’de yedekleme ağı için 10.50.0.21 — ve ne --apiserver-advertise-address ne de --control-plane-endpoint verilirse kubeadm varsayılan yönlendirmenin çıktığı arayüzü seçer. Hata init sırasında değil, çıktısında görünür:
kubeadm join 10.50.0.21:6443 --token ...
Kurulum başarıyla biter, kubectl get nodes control plane’i Ready gösterir. Ama 192.168.30.0/24 üzerindeki worker’lar o adrese hiç ulaşamaz ve join zaman aşımına düşer. Adresi elle düzeltmek de kurtarmaz: API sunucusu sertifikasının SAN listesi de aynı yanlış adrese göre üretilmiştir, 192.168.30.21 üzerinden bağlanan istemci sertifika doğrulamasında takılır. Düzeltmesi kubeadm reset ile geri dönüp kurulumu doğru bayraklarla tekrarlamaktır.
Ready’nin Ötesi: Küme Gerçekten Çalışıyor mu?
Şimdi yazının açılışındaki iddiayı sınıyoruz. Üç düğüm de Ready. Bu satır neyi kanıtlıyor, neyi kanıtlamıyor?
Kontrol Düzlemi Kendini Ne Kadar Sağlıklı Görüyor?
API sunucusu kendi hazırlık denetimlerini tek tek raporlar:
kubectl get --raw='/readyz?verbose'
[+]ping ok
[+]log ok
[+]etcd ok
[+]etcd-readiness ok
[+]informer-sync ok
[+]poststarthook/start-kube-apiserver-admission-initializer ok
[+]shutdown ok
readyz check passed
Bu çıktı arızalı senaryoda aynı görünmez. etcd cevap vermiyorsa satır [-]etcd failed: reason withheld olur ve komut HTTP 500 ile döner. kubectl get nodes ise o anda hâlâ önbellekten cevap veriyor olabilir.
Asıl Test: Düğümler Arası Pod Trafiği
Bir düğümdeki pod’un diğer düğümdeki pod’a ulaşabildiğini gösteren tek şey, o trafiği fiilen geçirmektir. İki nginx pod’unu nodeName ile ayrı düğümlere sabitliyoruz:
# capraz-trafik.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-w01
labels:
app: capraz-test
spec:
nodeName: argo-w01
containers:
- name: web
image: nginx:1.27-alpine
---
apiVersion: v1
kind: Pod
metadata:
name: web-w02
labels:
app: capraz-test
spec:
nodeName: argo-w02
containers:
- name: web
image: nginx:1.27-alpine
---
apiVersion: v1
kind: Service
metadata:
name: capraz-test
spec:
selector:
app: capraz-test
ports:
- port: 80
kubectl apply -f capraz-trafik.yaml
kubectl get pods -o wide
NAME READY STATUS IP NODE
web-w01 1/1 Running 10.244.113.65 argo-w01
web-w02 1/1 Running 10.244.36.193 argo-w02
Pod adresleri düğüm başına düzgün bir /24 gibi görünmüyor — bu doğru davranış. Calico yapılandırmasında blockSize: 26 yazdığımız için havuzdan her düğüme /26‘lık bloklar dağıtılır; üçüncü sekizli düğüm numarasını değil, o düğüme düşen bloğu gösterir.
Şimdi trafiği iki yönde de geçiriyoruz. Tek yön yetmez: güvenlik duvarı kuralları asimetrik yazılabilir ve yalnızca bir yönü açık bir küme, tek yönlü testte sağlıklı görünür.
kubectl exec web-w01 -- wget -qO- -T3 http://10.244.36.193 | head -1
kubectl exec web-w02 -- wget -qO- -T3 http://10.244.113.65 | head -1
<!DOCTYPE html>
<!DOCTYPE html>
Ready satırının kanıtlamadığı şey budur. Düz 192.168.30.0/24 lab’imizde VXLANCrossSubnet kapsülleme yapmadığı için pod trafiği düğümler arasında düz yönlendirilmiş IP paketleri olarak gider; onu susturmak için FORWARD zincirini DROP politikasına çeken tek bir güvenlik duvarı kuralı yeter. Düğümleri farklı alt ağlara yaydığınızda aynı sessizliği 4789/UDP’yi kapatmak üretir. Her iki durumda da iki pod Running görünür, iki düğüm Ready kalır, kubectl describe hiçbir olay üretmez ve yalnızca yukarıdaki wget şu satırla düşer:
wget: download timed out
command terminated with exit code 1
DNS ve Service: kube-proxy’yi de Sınamak
Pod IP’sine doğrudan gitmek CNI’yı sınar, ama gerçek uygulamalar Service adı kullanır. Bir istemci pod’u ile üç katmanı birden sınıyoruz — CoreDNS, Service ClusterIP’si ve kube-proxy kuralları:
kubectl run dnstest --image=busybox:1.28 --restart=Never -- sleep 3600
kubectl exec dnstest -- nslookup capraz-test
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: capraz-test
Address 1: 10.96.214.83 capraz-test.default.svc.cluster.local
İmaj etiketi busybox:1.28 bilerek sabitlendi: daha yeni busybox imajlarındaki nslookup, küme DNS’i ile denendiğinde yanıltıcı sonuçlar üretiyor ve Kubernetes belgeleri DNS teşhisi için bu etiketi öneriyor.
kubectl exec dnstest -- wget -qO- -T3 http://capraz-test | head -1
kubectl get endpointslices -l kubernetes.io/service-name=capraz-test
<!DOCTYPE html>
NAME ADDRESSTYPE PORTS ENDPOINTS
capraz-test-7xk2m IPv4 80 10.244.113.65,10.244.36.193
ENDPOINTS sütununda iki adres olması, Service’in her iki düğümdeki pod’u da tanıdığını gösteriyor. Tek adres görüyorsanız etiket seçici ile pod etiketleri uyuşmuyor demektir — pod Running olduğu halde trafiğin bir kısmı hiç ona gitmez.
Test bitince temizleyin; bu pod’lar kalıcı olmamalı:
kubectl delete -f capraz-trafik.yaml
kubectl delete pod dnstest
Sertifikaların Ömrü: Bir Yıl Sonra Kendiliğinden Duran Küme
Kurulum gününde bakılması gereken son şey, kurulumla hiç ilgisi yokmuş gibi görünür:
sudo kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
admin.conf Aug 29, 2027 07:41 UTC 364d no
apiserver Aug 29, 2027 07:41 UTC 364d no
apiserver-kubelet-client Aug 29, 2027 07:41 UTC 364d no
controller-manager.conf Aug 29, 2027 07:41 UTC 364d no
etcd-server Aug 29, 2027 07:41 UTC 364d no
scheduler.conf Aug 29, 2027 07:41 UTC 364d no
CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME
ca Aug 27, 2036 07:41 UTC 9y
etcd-ca Aug 27, 2036 07:41 UTC 9y
İstemci sertifikaları bir yıl, CA on yıl geçerlidir. kubeadm bu sertifikaları küme yükseltmesi sırasında kendiliğinden yeniler; bir yıl boyunca yükseltilmeyen küme ise günün birinde, hiçbir şey değişmemişken kendiliğinden durur. Elle yenileme:
sudo kubeadm certs renew all
sudo systemctl restart kubelet
Statik pod’ların yeni sertifikaları okuması için control plane bileşenlerinin de yeniden başlaması gerekir; kubelet manifest dosyalarına dokunulduğunda bunu kendisi yapar. admin.conf yenilendiğinde ~/.kube/config kopyasını da güncellemeyi atlamayın — eski kopya elinizde kaldığı sürece kubectl yetkilendirme hatası vermeye devam eder.
Sonuç
Readykubelet’in kendisi hakkındaki beyanıdır, kümenin çalıştığının kanıtı değildir. Bir düğümdeki pod’dan diğerindekine iki yönlü trafik geçirmeden kurulumu tamamlanmış saymayın; CNI’ın düğümler arası yolunu kesen tek bir güvenlik duvarı kuralı, bütüngetçıktılarını sağlıklı gösterir.- kubeadm hiçbir varsayılan seçmez, bu yüzden öğretir. CNI’sız düğümün neden
NotReadykaldığını, cgroup sürücüsünün neden eşleşmesi gerektiğini elinizle kurmadan öğrenmenin yolu yok — k3s ve RKE2 aynı kararları sizin yerinize verir, bu da onları üretimde hızlı, öğrenmede sessiz yapar. - Kurulum anında verilen üç karar sonradan düzeltilemez:
--apiserver-advertise-addresssertifika SAN listesini,--control-plane-endpointikinci bir control plane ekleyebilme hakkınızı,--pod-network-cidrde pod ağının yerel ağınızla çakışıp çakışmayacağını belirler. - Kümenin en sessiz sayacı sertifika süresidir. İstemci sertifikaları bir yıl geçerlidir ve yükseltilmeyen bir küme, hiçbir şey değiştirilmemişken kendiliğinden durur.
Küme ayakta ve doğrulandı. Sıradaki yazıda üzerinde çalışmaya başlıyoruz: kubectl ile nesne modeli — pod tam olarak nedir, get ile describe neyi farklı gösterir, namespace ve etiketler kümeyi nasıl bölümler. Serinin tamamı için Kubernetes Öğrenme Yolculuğu sayfasına bakabilirsiniz.
Ek: Terimler Sözlüğü
| Terim | Karşılığı |
|---|---|
| kubeadm | Kubernetes’in referans küme kurma aracı. Control plane’i statik pod olarak kurar; CNI, ingress ve depolamayı size bırakır. |
| kind | Düğümleri Docker konteyneri olarak çalıştıran yerel küme aracı. CNI ve depolama sınıfını kendisi kurar. |
| k3s / RKE2 | Rancher’ın tek binary dağıtımları. k3s hafiflik, RKE2 sertleştirilmiş varsayılanlar için tasarlandı. |
| CNI | Container Network Interface. Pod ağını kuran eklenti arayüzü; eklenti kurulmadan kubelet düğümü Ready saymaz. |
| Pod CIDR | Pod’lara adres dağıtılan blok. kubeadm init bayrağı ile CNI yapılandırması aynı değeri taşımalıdır. |
| Service CIDR | ClusterIP adreslerinin dağıtıldığı blok. kubeadm varsayılanı 10.96.0.0/12, küme DNS’i 10.96.0.10. |
| cgroup sürücüsü | kubelet ve çalışma zamanının cgroup ağacını yönetme biçimi (systemd veya cgroupfs). İkisi eşleşmelidir. |
| Statik pod | kubelet’in /etc/kubernetes/manifests/ dizininden, API sunucusuna sormadan başlattığı pod. Control plane bileşenleri böyle çalışır. |
| Bootstrap token | kubeadm join sırasında düğümün kümeye kimliğini kanıtladığı geçici anahtar. Varsayılan ömrü 24 saat. |
| CA sertifika özeti | --discovery-token-ca-cert-hash değeri. Katılan düğümün, bağlandığı API sunucusunun gerçekten kendi kümesi olduğunu doğrulamasını sağlar. |
| Bağlam (context) | kubeconfig’de küme, kullanıcı ve namespace üçlüsüne verilen ad. kubectl hangi kümeye gideceğini buradan bilir. |
| EndpointSlice | Bir Service’in arkasındaki hazır pod adreslerinin listesi. Boş kalması, seçici ile pod etiketlerinin uyuşmadığını gösterir. |