SSH ile debug ettiğim her Kubernetes node'unda aynı üç sorun vardı: biri elle bir şey değiştirmişti, ne değiştirdiğini kimse bilmiyordu ve node bir dosyadan yeniden kurulamıyordu. Talos Linux bu üçüne de sebep olan aracı ortadan kaldırıyor. SSH yok, shell yok, paket yöneticisi yok; node'un tamamı tek bir YAML belgesiyle tanımlanıyor ve o belgeyi yalnızca kimlik doğrulamalı bir gRPC API üzerinden değiştirebiliyorsunuz.
Bu yazı Talos'u dizüstünde, iki Docker konteyneri olarak çalıştırıyor ve bir node'a gerçek hayatta yapılan dört şeyi yapıyor: oluşturmak, konfigürasyonunu değiştirmek, özel imaj üretmek, yükseltmek. Sonunda elinizde çalışan bir cluster, reboot'suz uyguladığınız bir machine config patch'i, Longhorn'un ihtiyaç duyduğu extension'ları taşıyan bir Image Factory imajı ve yaklaşık üç dakika süren bir Kubernetes 1.35 → 1.36 yükseltmesi olacak. Bunlardan hangilerini Docker'daki Talos'un yapamadığını ve en yeni Talos'un benim makinemde neden hiç boot etmediğini de göreceksiniz.
Aşağıdaki her bloğun kodu talos-linux-explained klasöründe.
Gerekenler
- Makinenizde Docker. Ben Apple Silicon Mac'te Colima 0.8 kullanıyorum, 4 CPU / 8 GB VM. Docker Desktop ve Linux da olur; iki fark var, ikisi de "Nerede patladı" bölümünde.
talosctl1.13,kubectl, GNU make. macOS'te:brew install talosctl kubectl make(Homebrewgmakeadıyla kurar).- Bu koşudaki sürümler: Talos imajı v1.13.10, talosctl v1.13.5, Kubernetes 1.35.8'den 1.36.4'e. Boşta yaklaşık 1 GB RAM, yükseltme sırasında 2 GB.
Talos bilgisi varsayılmıyor. Yazı tek başına okunur; önceki yazı gerekli değil.
Neden böyle
Bir Kubernetes node'unun ihtiyacı bir kernel, bir container runtime, bir kubelet ve konfigürasyonunu alacağı bir yol. Ubuntu + kubeadm bunların hepsini verir, üstüne 60.000 paket, bir login shell, cloud-init, unattended-upgrades ve genel amaçlı bir işletim sisteminin sahip olduğu her drift yolunu ekler. RKE2 ve k3s Kubernetes tarafını daraltır ama alttaki OS'i açık bırakır. Talos tam tersi bir pozisyon alıyor: OS Kubernetes node'unun kendisi, başka hiçbir şey değil. Eline geçen şu:
| Özellik | Node üzerinde anlamı |
|---|---|
| Değişmez (immutable) | Root dosya sistemi salt okunur squashfs, yükseltmede bütün olarak değişir. apt install edilecek bir şey yok. |
| API ile yönetilen | Her işlem 50000 portunda bir gRPC çağrısı, mTLS, rollerle (os:admin, os:operator, os:reader). |
| Tek machine config | Tek bir YAML belgesi kernel argümanlarını, ağı, kubelet bayraklarını, sysctl'leri, registry'leri, sertifikaları tutar. |
| Minimal | /usr/bin içinde 12 binary, çoğu nftables ve iptables. Shell yok, ls yok, cat yok. |
İlk temas için neden Docker'da? Çünkü asıl önemli özellik, "OS bir API'dir", container modunda eksiksiz mevcut: aynı machined, aynı apid, aynı machine config, aynı talosctl. Eksik olan kendi diski ve kendi kernel'i; yani OS yükseltmesi ve disk şifreleme dışarıda kalıyor. API'nin bunları reddettiğini de göreceğiz, bu da kendi başına öğretici.
Adım 1 — Tek komutla cluster
talosctl cluster create docker PKI üretir, her node için bir machine config yazar, node başına bir konteyner başlatır ve etcd'yi bootstrap eder. ~/.talos ve ~/.kube'e dokunulmaz; iki config de ./.lab altına gider. Üretim anında var olması gereken ayarlar yalnızca iki rolün de üzerinde anlaşması gerekenler ve control plane'in kendine ait olanlar.
# config/lab.patch.yaml — her node
cluster:
allowSchedulingOnControlPlanes: false
machine:
network:
extraHostEntries:
- ip: 10.5.0.2
aliases:
- registry.lab.internal
# config/controlplane.patch.yaml — yalnız control plane
cluster:
apiServer:
extraArgs:
event-ttl: 2h
machine:
nodeLabels:
topology.kubernetes.io/zone: lab-a
# cluster/create.sh (özü)
talosctl cluster create docker \
--name "$CLUSTER" --state "$LAB/state" \
--image "ghcr.io/siderolabs/talos:${TALOS_VERSION}" \
--kubernetes-version "$K8S_VERSION" \
--workers 1 \
--config-patch @config/lab.patch.yaml \
--config-patch-controlplanes @config/controlplane.patch.yaml \
--talosconfig-destination "$TALOSCONFIG"
$ make up
generating PKI and tokens
creating network talos-lab
creating controlplane nodes
creating worker nodes
waiting for Talos API (to bootstrap the cluster)
bootstrapping cluster
waiting for etcd to be healthy: OK
waiting for apid to be ready: OK
waiting for kubelet to be healthy: OK
waiting for all k8s nodes to report ready: OK
waiting for coredns to report ready: OK
Bu dizüstünde, 236 MB'lık imaj önceden çekilmişken, make up'tan CoreDNS'in hazır olmasına 109 saniye. İki konteyner, node başına bir tane; control plane Kubernetes API'sini (6443) ve Talos API'sini (50000) rastgele host portlarında yayınlıyor:
$ docker ps --format '{{.Names}}\t{{.Image}}\t{{.Ports}}'
talos-lab-worker-1 ghcr.io/siderolabs/talos:v1.13.10
talos-lab-controlplane-1 ghcr.io/siderolabs/talos:v1.13.10 0.0.0.0:52967->6443/tcp, 0.0.0.0:52968->50000/tcp
$ talosctl get members
NODE TYPE ID HOSTNAME MACHINE TYPE OS ADDRESSES
10.5.0.2 Member talos-lab-controlplane-1 talos-lab-controlplane-1 controlplane Talos (v1.13.10) ["10.5.0.2"]
10.5.0.2 Member talos-lab-worker-1 talos-lab-worker-1 worker Talos (v1.13.10) ["10.5.0.3"]
$ kubectl get nodes -o wide
NAME STATUS ROLES VERSION INTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
talos-lab-controlplane-1 Ready control-plane v1.35.8 10.5.0.2 Talos (v1.13.10) 6.8.0-50-generic containerd://2.2.7
talos-lab-worker-1 Ready <none> v1.35.8 10.5.0.3 Talos (v1.13.10) 6.8.0-50-generic containerd://2.2.7
Kernel sütununa dikkat. Container modunda Talos host'un kernel'i üzerinde çalışır, burada Colima'nın 6.8'i. "Nerede patladı"nın ilk maddesinin arkasında tek başına bu gerçek var.
İki konteyner var, refleks docker exec ile içine girmek:
$ docker exec talos-lab-worker-1 sh
OCI runtime exec failed: exec failed: unable to start container process: exec: "sh": executable file not found in $PATH: unknown
$ docker exec talos-lab-worker-1 ls
OCI runtime exec failed: exec failed: unable to start container process: exec: "ls": executable file not found in $PATH: unknown
Bu sıkılaştırılmış bir imaj ya da kapatılmış bir özellik değil. Binary'ler yok. İmajın entrypoint'i /sbin/init, o da machined; node'daki diğer her şey ya Talos'un kendi gönderdiği bir Go servisi ya da kubelet'in başlattığı bir konteyner.
Adım 2 — Shell yok, peki ne yazıyorsunuz
Her işlem talosctl üzerinden geçer; o da 50000 portundaki apid ile gRPC konuşur. Kimliğiniz talosconfig içindeki istemci sertifikası; rol sertifikanın içinde, dolayısıyla "bu node'a kim ne yapabilir" sorusunun cevabı /etc/sudoers'da değil PKI'da.
$ talosctl config info
Current context: talos-lab
Endpoints: 127.0.0.1:52478
Roles: os:admin
Certificate expires: 1 year from now (2027-09-18)
SSH alışkanlığından talosctl'ye tam tablo docs/api-vs-ssh.md içinde; her gün kullandıklarım:
| SSH alışkanlığı | talosctl |
|---|---|
systemctl status |
talosctl services |
journalctl -u kubelet -f |
talosctl logs kubelet -f |
dmesg |
talosctl dmesg |
cat /etc/hosts |
talosctl read /etc/hosts |
df -h |
talosctl mounts |
ss -tulpn |
talosctl netstat -l |
ps aux |
talosctl processes |
crictl ps |
talosctl containers -k |
top |
talosctl dashboard |
vim /etc/kubernetes/... |
dosya yok: talosctl patch mc |
İlk öğrenilecek olan talosctl services. Talos'un control plane'de yedi, worker'da beş sistem servisi var ve her biri durumunu ve sağlığını API üzerinden bildiriyor:
$ talosctl services
NODE SERVICE STATE HEALTH LAST CHANGE LAST EVENT
10.5.0.2 apid Running OK 1m48s ago Health check successful
10.5.0.2 containerd Running OK 1m49s ago Health check successful
10.5.0.2 cri Running OK 1m48s ago Health check successful
10.5.0.2 etcd Running OK 1m36s ago Health check successful
10.5.0.2 kubelet Running OK 1m40s ago Health check successful
10.5.0.2 machined Running OK 1m49s ago Health check successful
10.5.0.2 trustd Running OK 1m48s ago Health check successful
Bu arada iki containerd örneği var: biri system namespace'inde Talos'un kendi servisleri için, biri CRI için. talosctl containers apid ve kubelet'i, talosctl containers -k pod'ları göstermesinin sebebi bu.
Ve patch'teki extraHostEntries, API üzerinden geri okunmuş halde, çünkü başka bir okuma yolu yok:
$ talosctl read /etc/hosts --nodes 10.5.0.3
127.0.0.1 localhost
10.5.0.3 talos-lab-worker-1
10.5.0.2 registry.lab.internal
Adım 3 — Tek machine config, canlı patch
Machine config node'un tamamı. Worker'da talosctl get mc -o yaml 27 KB'lık bir belge döndürür: PKI, token'lar, kubelet ayarları, ağ, registry'ler, sysctl'ler, kernel modülleri, her şey. Başka bir doğruluk kaynağı yok; onun yerine düzenleyebileceğiniz bir dosya node'da mevcut değil.
Değiştirmek bir patch'tir. Worker patch'i bir kubelet bayrağı, iki sysctl ve bir node etiketi ekliyor. Her zaman önce dry-run yapıyorum, çünkü API SSH'ın hiç cevaplayamadığı soruyu cevaplıyor: bu değişiklik node'u reboot edecek mi?
# config/worker.patch.yaml
machine:
kubelet:
extraArgs:
max-pods: "200"
sysctls:
net.core.somaxconn: "65535"
fs.inotify.max_user_instances: "8192"
nodeLabels:
node.lab/pool: general
# scripts/patch.sh (özü)
talosctl patch mc --nodes 10.5.0.3 --patch @config/worker.patch.yaml --dry-run
talosctl patch mc --nodes 10.5.0.3 --patch @config/worker.patch.yaml
$ talosctl patch mc --nodes 10.5.0.3 --patch @config/worker.patch.yaml --dry-run
Dry run summary:
Applied configuration without a reboot (skipped in dry-run).
Config diff:
kubelet:
image: ghcr.io/siderolabs/kubelet:v1.35.8
+ extraArgs:
+ max-pods: "200"
...
+ sysctls:
+ fs.inotify.max_user_instances: "8192"
+ net.core.somaxconn: "65535"
...
+ nodeLabels:
+ node.lab/pool: general
"Without a reboot" ve node'un gerçekten çalıştırdığı config'e karşı diff. Şimdi gerçeği. Patch'ten önce kubelet PID 148, somaxconn 4096 idi:
$ talosctl patch mc --nodes 10.5.0.3 --patch @config/worker.patch.yaml
patched MachineConfigs.config.talos.dev/v1alpha1 at the node 10.5.0.3
Applied configuration without a reboot
$ talosctl get kubeletconfig --nodes 10.5.0.3 -o jsonpath='{.spec.extraArgs}'
{ "max-pods": { "values": [ "200" ] } }
$ talosctl read /proc/sys/net/core/somaxconn --nodes 10.5.0.3
65535
$ kubectl get nodes -l node.lab/pool=general
NAME STATUS ROLES AGE VERSION
talos-lab-worker-1 Ready <none> 33s v1.35.8
$ talosctl services --nodes 10.5.0.3
NODE SERVICE STATE HEALTH LAST CHANGE LAST EVENT
10.5.0.3 kubelet Running ? 0s ago Started task kubelet (PID 1022) for container kubelet
$ talosctl processes --nodes 10.5.0.3 | grep -o 'max-pods=[0-9]*'
max-pods=200
Kubelet yeni argümanla yeniden başlatıldı, sysctl canlı, etiket Node nesnesinin üzerinde. Reboot yok, drain yok, systemctl daemon-reload yok. "Config node'un kendisidir" cümlesinin satın aldığı şey bu: config'in her parçasının sahibi olan controller o parçadaki değişikliği nasıl uygulayacağını biliyor.
Peki hangi değişiklikler reboot ister? Talos canlı uygulanan alanları dokümante ediyor: .cluster, .machine.network, .machine.kubelet, .machine.kernel, .machine.time, etiketler, taint'ler ve daha fazlası. Cevabı kendi gözümle görmek için worker'a on beş patch'i dry-run ile denedim. Kernel modülleri, sysctl'ler, registry mirror'ları, kubelet extra mount'ları, NTP sunucuları, KubeSpan: hepsi "without a reboot". Aksini söyleyen tek alan, sistem servislerinin ortam değişkenleri olan ve boot'ta bir kez okunan machine.env oldu:
# config/needs-reboot.patch.yaml
machine:
env:
GRPC_GO_LOG_SEVERITY_LEVEL: info
$ talosctl patch mc --nodes 10.5.0.3 --patch @config/needs-reboot.patch.yaml --dry-run
Dry run summary:
Applied configuration with a reboot (skipped in dry-run).
Config diff:
+ env:
+ GRPC_GO_LOG_SEVERITY_LEVEL: info
Varsayılan --mode=auto'da bu patch uygulanır ve node reboot edilir. --mode=no-reboot ile reddedilir; --mode=staged ile yazılır ve sizin planladığınız bir sonraki reboot'ta uygulanır. Talos 1.14'te açık reboot modu kaldırıldı ve reboot ayrı bir adım oldu; doğru yön bu: API bir değişikliğin bedelini söylüyor, ne zaman ödeyeceğinize siz karar veriyorsunuz.
Adım 4 — İmaj bir build çıktısı
Gerçek donanımda çarptığınız ikinci şey şudur: CSI'ım host'ta iscsid istiyor ve paket yöneticisi yok. Talos'un cevabı Image Factory: imajı tarif edersiniz, o üretir; tarif Terraform'unuzun yanına commit ettiğiniz beş satırlık bir YAML'dır.
# factory/schematic.yaml
customization:
systemExtensions:
officialExtensions:
- siderolabs/iscsi-tools
- siderolabs/util-linux-tools
Bu ikisi Longhorn'un, ve iSCSI tabanlı her CSI'ın, node'da ihtiyaç duyduğu şey: iscsid ve blkid/nsenter/fstrim. Dosyayı POST edin, deterministik bir id alın; aynı YAML her zaman aynı id'yi verir, yani id imajın içerik hash'idir ve infra reponuza aittir:
# factory/schematic-id.sh (özü)
curl -s -X POST https://factory.talos.dev/schematics \
-H 'Content-Type: application/yaml' --data-binary @factory/schematic.yaml
{"id":"613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245", ...}
schematic id : 613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245
installer : factory.talos.dev/metal-installer/613e1592…961245:v1.13.10 # talosctl upgrade --image ...
hcloud : factory.talos.dev/hcloud-installer/613e1592…961245:v1.13.10 # Hetzner Cloud
metal iso : https://factory.talos.dev/image/613e1592…961245/v1.13.10/metal-arm64.iso
Hesap yok, kimlik doğrulama yok ve installer referansı talosctl upgrade'e verdiğiniz şey. Talos'ta "paket kurmak"ın bütün hikâyesi bu: schematic'i değiştir, yeni id al, node'u yeni imaja yükselt. Bu serideki Hetzner yazısında bu id bir Terraform değişkeni ve imaja dair başka hiçbir şey hiçbir yerde yok.
Adım 5 — İki yükseltme, iki komut
Talos Kubernetes yükseltmesini OS yükseltmesinden ayırıyor; kafanızda da ayrı tutmakta fayda var.
talosctl upgrade-k8s her node'un machine config'indeki Kubernetes imaj sürümlerini yeniden yazar ve controller'ların static pod'ları ve kubelet'leri, önce control plane olmak üzere, döndürmesine izin verir. Reboot yok ve Docker'da çalışıyor:
# scripts/upgrade.sh (özü)
talosctl upgrade-k8s --nodes 10.5.0.2 --to 1.36.4 --endpoint 127.0.0.1:52477
$ make upgrade
automatically detected the lowest Kubernetes version 1.35.8
discovered controlplane nodes ["10.5.0.2"]
discovered worker nodes ["10.5.0.3"]
> "10.5.0.2": Talos version 1.13.10 is compatible with Kubernetes version 1.36.4
> "10.5.0.3": Talos version 1.13.10 is compatible with Kubernetes version 1.36.4
checking for removed Kubernetes component flags
checking for removed Kubernetes API resource versions
> "10.5.0.2": pre-pulling registry.k8s.io/kube-apiserver:v1.36.4
> "10.5.0.2": pre-pulling ghcr.io/siderolabs/kubelet:v1.36.4
> "10.5.0.3": pre-pulling ghcr.io/siderolabs/kubelet:v1.36.4
updating "kube-apiserver" to version "1.36.4"
> "10.5.0.2": machine configuration patched
> "10.5.0.2": waiting for kube-apiserver pod update
< "10.5.0.2": successfully updated
updating "kube-controller-manager" to version "1.36.4"
< "10.5.0.2": successfully updated
updating "kube-scheduler" to version "1.36.4"
< "10.5.0.2": successfully updated
updating kube-proxy to version "1.36.4"
updating kubelet to version "1.36.4"
> "10.5.0.2": waiting for kubelet restart
< "10.5.0.2": successfully updated
> "10.5.0.3": waiting for kubelet restart
< "10.5.0.3": successfully updated
updating manifests
< configured DaemonSet/kube-system/kube-proxy
waiting for kubernetes objects to be fully reconciled
done
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
talos-lab-controlplane-1 Ready control-plane 22h v1.36.4
talos-lab-worker-1 Ready <none> 22h v1.36.4
Üç dakika on bir saniye, imajlar önceden çekilmiş halde. Sıraya bakın: önce uyumluluğu ve kaldırılmış bayrakları kontrol ediyor, hiçbir node registry beklerken yarı yolda kalmasın diye her imajı önden çekiyor, sonra control plane'i bileşen bileşen, kubelet'leri node node döndürüyor ve ancak ondan sonra manifest'lere dokunuyor. Her adım bir machine config patch'i; talosctl get staticpodstatus static pod sürümlerinin tek tek arttığını gösteriyor. Hiçbir şey reboot olmadı. Sürüm sapma kuralları hâlâ geçerli: Talos 1.13, Kubernetes 1.31'den 1.36'ya kadar destekliyor ve upgrade-k8s başlamadan önce cluster'daki en düşük sürümü kontrol ediyor. 1.37'ye ulaşmak için önce Talos'un kendisini 1.14'e yükseltirdim.
talosctl upgrade diğeri. Bir installer imajı çeker, iki sistem bölümünden diğerine yazar ve ona reboot eder; yeni sürüm kalkmazsa eskisi hâlâ diskte. Container modunda disk yok ve API bunu, imajı çektikten sonra, söylüyor:
$ talosctl upgrade --nodes 10.5.0.2 --image factory.talos.dev/metal-installer/613e1592…961245:v1.13.10
10.5.0.2: pulled image factory.talos.dev/metal-installer/613e1592…961245@sha256:5266bb0d…
error during upgrade: error from node 10.5.0.2: rpc error: code = FailedPrecondition desc = method is not supported in container mode
Stack trace değil, FailedPrecondition. reset ve disk şifreleme de aynı şekilde reddediliyor. Script talosctl get platformmetadata ile (platform: container) kontrol edip node döngüsünü atlıyor; metal üzerinde her node için sırayla talosctl upgrade --wait çalıştırıyor.
Nerede patladı
Beş şey; ilki en çok zamana mal oldu.
1. Talos 1.14, 6.8 kernel'de başlamıyor
İlk denemem güncel sürüm v1.14.1 ile oldu. talosctl cluster create waiting for Talos API (to bootstrap the cluster) yazdı ve bir daha ilerlemedi. Konteyner ayaktaydı, bakılacak tek yer konteyner logu:
$ docker logs talos-lab-controlplane-1
[talos] service[machined](Preparing): Creating service runner
[talos] controller runtime goroutine error: fatal controller runtime error: failed to set up /etc overlay:
failed to compose writable /etc overlay: openfs failed: failed to create root filesystem:
FSCONFIG_SET_FD failed: bad file descriptor: key="lowerdir+" fd=4
[talos] service[apid](Waiting): Waiting for api certificates, config to be ready
machined config yüklenmeden öldü, dolayısıyla apid sonsuza kadar bekledi, talosctl de öyle. Sebep Talos'un Haziran 2026'da 1.14 için merge edilen PR #13558'inde: /etc, alt katmanları kernel'e dosya tanımlayıcısı olarak verilen yazılabilir bir overlay oldu, fsconfig(FSCONFIG_SET_FD, "lowerdir+"). Kernel'in overlayfs dokümantasyonu bu özelliği "since kernel v6.13" diye veriyor. Colima 0.8'in Ubuntu VM'i 6.8 çalıştırıyor; lowerdir+'ı yol olarak biliyor ama tanımlayıcı olarak bilmiyor ve EBADF döndürüyor. Metal üzerinde bu olamaz, Talos kendi 6.18 kernel'ini taşıyor; Docker'da Talos sizin kernel'iniz üzerinde çalışıyor. Lab bu yüzden v1.13.10'a sabitlendi; güncel bir Docker Desktop'ta ya da 6.13+ bir Linux host'ta TALOS_VERSION=v1.14.1 make up çalışır.
2. talosctl docker context'i yok sayıyor
failed to connect to the docker API at unix:///var/run/docker.sock: dial unix /var/run/docker.sock: connect: no such file or directory
docker CLI Colima'yı bir context üzerinden buluyor; talosctl soket yolunu doğrudan çeviriyor. Talos dokümanı bir symlink öneriyor; ben /var/run'a dokunmamayı tercih ediyorum. Makefile soketi context'ten okuyup export ediyor:
# Makefile
export DOCKER_HOST ?= $(shell docker context inspect -f '{{.Endpoints.docker.Host}}' 2>/dev/null)
3. Flannel br_netfilter istiyor ve Talos bunu sizin yerinize yükleyemiyor
1.13.10 ile cluster bootstrap oldu ama make up waiting for coredns to report ready'de takıldı. İki CoreDNS pod'u ContainerCreating, iki kube-flannel pod'u CrashLoopBackOff:
$ talosctl logs kubelet --nodes 10.5.0.3 | tail -1
failed to setup network for sandbox: plugin type="flannel" failed (add):
failed to load flannel 'subnet.env' file: open /run/flannel/subnet.env: no such file or directory
$ kubectl logs -n kube-system -l k8s-app=flannel --tail=1
E0918 14:44:09.535929 main.go:289] Failed to check br_netfilter: stat /proc/sys/net/bridge/bridge-nf-call-iptables: no such file or directory
Gerçek bir Talos node'unda kernel modülü oradadır. Docker'da Talos, kendi göndermediği bir kernel üzerinde privileged bir konteyner ve host'a modprobe yapmıyor. Çözüm VM tarafında; modül yüklenince flannel kendi kendine toparlıyor:
colima ssh -- sudo modprobe br_netfilter
Altmış saniye sonra CoreDNS Running oldu ve make up bitti. Talos'un Docker sayfası bunu yazıyor; o kadar aşağı okumamıştım.
4. Kubeconfig, Mac'inizin ulaşamadığı bir adresi gösteriyor
$ kubectl get nodes
Unable to connect to the server: dial tcp 10.5.0.2:6443: i/o timeout
talosctl kubeconfig cluster'ın control plane endpoint'ini, https://10.5.0.2:6443, yazıyor; bu, Colima VM'inin içindeki Docker ağında konteynerin adresi. Docker o portu 127.0.0.1:52477'de yayınladı. Linux'ta ikisi de çalışır; macOS'te yalnızca yayınlanan olan. Aynı şey API sunucusuyla kendisi konuşan talosctl upgrade-k8s için de geçerli; tam bunun için bir --endpoint bayrağı var. Create script'i sunucuyu yeniden yazıyor ve talosctl cluster create API sunucusunun sertifikasına 127.0.0.1'i koyduğu için --insecure-skip-tls-verify gerekmiyor:
# cluster/create.sh (sonu)
talosctl kubeconfig "$KUBECONFIG" --force
PORT=$(docker port "${CLUSTER}-controlplane-1" 6443/tcp | head -1 | cut -d: -f2)
kubectl config set-cluster "$CLUSTER" --server="https://127.0.0.1:${PORT}"
5. "successfully updated" config hakkında, pod hakkında değil
Yükseltme boyunca kubectl get pods -n kube-system çıktısını on saniyede bir örnekledim. API sunucusu, static pod'u değiştirilirken yaklaşık otuz saniye erişilemezdi; tek control plane node'uyla beklenen bu. Beklenmeyen: upgrade-k8s tam kube-scheduler: successfully updated yazdıktan sonra scheduler üç kez yeniden başladı ve bir dakikaya yakın hazır olmadı; kubelet döndürülürken controller-manager de bir kez daha yeniden başladı. Yükseltme bunu hiç fark etmedi, çünkü beklediği şey static pod'daki config sürümü annotation'ı, hazır olma durumu değil. Sidero tam bunu anlatan #14227'yi "not planned" diye kapattı; #14152 ise API sunucusunun scheduler adımında neden ikinci kez yeniden başladığını açıklıyor: scheduler'ın config sürümü API sunucusunun annotation'ının da parçası.
Bu yükseltmeyi ilk koşturduğumda aynı scheduler yedi dakika CrashLoopBackOff'ta kaldı; her deneme KubePrism üzerinden API sunucusundan Retry-After alıyor, client-go'nun on denemesinden sonra vazgeçiyordu; sonra kendi kendine toparladı. Yukarıdaki temiz koşuda tekrar edemedim ve o sırada node'a paralel olarak tanı komutları koşturuyordum; bu yüzden suçu Talos'a atmayacağım. Ders her iki durumda da aynı: upgrade-k8s sonrası bitti demeden önce talosctl get staticpodstatus ve talosctl health çalıştırın, ve o çalışırken başka config patch'i uygulamayın; her cluster.* değişikliği bir static pod'u yeniden başlatıyor.
Doğrulama
talosctl get members # 2 üye, Talos (v1.13.10)
talosctl services --nodes 10.5.0.3 # 5 servis Running / OK
kubectl get nodes # 2 Ready, ikisi de v1.36.4
kubectl get nodes -l node.lab/pool=general # canlı patch'in etiketlediği worker
talosctl read /proc/sys/net/core/somaxconn --nodes 10.5.0.3 # 65535
docker exec talos-lab-worker-1 sh # executable file not found
make down # konteynerler, ağ ve ./.lab gider
NAME STATUS ROLES AGE VERSION
talos-lab-controlplane-1 Ready control-plane 10m v1.36.4
talos-lab-worker-1 Ready <none> 10m v1.36.4
$ talosctl get kubeletconfig --nodes 10.5.0.3 -o jsonpath='{.spec.image}'
ghcr.io/siderolabs/kubelet:v1.36.4
make down önce talosctl cluster destroy çalıştırır; iki konteyneri ve ağı kaldırır, sonra ./.lab'ı siler. Makinede başka hiçbir şeye dokunulmadı; hiç shell'i olmamış bir lab için bunu söylemek kolay.
Ne zaman Talos, ne zaman değil
Node yalnızca Kubernetes çalıştırmak için varsa ve node'un bir dosyanın fonksiyonu olmasını istiyorsanız Talos doğru varsayılan: çıplak metal, Hetzner, KubeVirt VM'leri, tamir etmek yerine yeniden kurduğunuz her şey. Node'un pod olmayan bir şey de çalıştırması gerekiyorsa yanlış seçim: güvenlik ekibinizin apt ile kurduğu bir ajan, /usr/local/bin bekleyen bir vendor aracı, bir NFS sunucusu, kutuda tcpdump alması gereken bir geliştirici (talosctl pcap var ama size teşekkür etmeyecekler). Bunlar için ve runbook'ları SSH üzerinden bash ile yazılmış olup bu çeyrek yeniden yazamayacak ekipler için Ubuntu + kubeadm ya da RKE2 daha iyi oturuyor. Dürüst test şu: bir node şu an bozulsa tamir mi edersiniz, değiştirir misiniz? Talos ikinci cevap için.
Bu seride
Önceki: Cluster API'yi Kurarak Anlamak: kind, Docker Provider ve 15 Dakikada Bir Workload Cluster · Sonraki: Cluster API Docker Provider Talos'u Neden Ayağa Kaldıramaz. O başlığın iki yarısını da artık gördünüz: CAPD içinde script koşturacağı systemd'li, shell'li, cloud-init'li bir node bekliyor; Talos'ta bunların hiçbiri yok, bilerek. Serinin ilerisinde Adım 4'teki aynı Image Factory id'si Terraform'dan 17 Hetzner node'unu sıfır SSH ile boot ediyor.
Bu yazının kodu: https://github.com/miraccan00/blog-wiki/tree/main/talos-linux-explained