Nehany Kubernetes klasztert uzemeltetek bare metalon, Cluster API-val es BYOH (Bring Your Own Host) providerrel. Eddig minden upgrade ugyanarra a forgatokonyvre epult: node drain, machine torles, ujraprovisionalas, varakozas. Mukodik, de 40+ node es szuk tartalek kapacitas mellett ez brutal lassu.

A Cluster API v1.12 par hete jelent meg, es nekem az in-place update volt a legfontosabb ujdonsag. Nem kell minden valtozasnal uj gepeket epiteni, bizonyos modositasok mehetnek a mar futo machine-okra is. A mult heten ezt teszteltem a staging klaszterunkon, es meglepoen jo eredmenyt kaptam.

Hol faj az immutable rollout

Az immutable megkozelitest tovabbra is szeretem. A problema az ara bare metalon. Egy uj machine letrehozasa azt jelenti, hogy PXE boot, teljes OS telepites, klaszterhez csatlakozas, image-ek ujrahuzasa. Jo esetben is 15-20 perc node-onkent.

Ha csak egy kisebb valtozas kell, peldaul kubelet credential rotacio vagy egy cloud-init user modositas, ez mar tulzas. Mi is nyultunk Ansible side-channel megoldasokhoz, de ezzel pont a deklarativ mukodesbol engedunk.

Hogyan mukodik az in-place update v1.12-ben

Az egesz update extensionokra epul. Runtime SDK hookokat irsz, amikkel megmondod a CAPI-nak, hogy az adott diffet tudod helyben kezelni.

A folyamat roviden:

  1. Modositas tortenik a Machine specben, tipikusan KubeadmControlPlane vagy MachineDeployment oldalon.
  2. A CAPI ellenorzi, van-e regisztralt extension, ami kezeli ezt a diffet.
  3. Ha van, meghivja az extensiont, es a valtozas helyben lefut.
  4. Ha nincs, marad a klasszikus rollout.

Tehat nem az a kerdes, hogy mutable vagy immutable. Inkabb az, hogy a CAPI minden valtozashoz a jobb utat valasztja.

Beallitas

Eloszor kapcsold be a feature gate-eket a clusterctl configban vagy a CAPI controller deploymentben:

apiVersion: v1
kind: ConfigMap
metadata:
  name: capi-feature-gates
  namespace: capi-system
data:
  feature-gates: "InPlaceUpdates=true,RuntimeSDK=true"

Utana jon az update extension. En egy egyszeru verziot irtam credential rotaciora es metadata modositasokra. Minimum a BeforeUpdateMachine es UpdateMachine hook kell:

func (h *Handler) BeforeUpdateMachine(ctx context.Context, req *runtimehooksv1.BeforeUpdateMachineRequest) *runtimehooksv1.BeforeUpdateMachineResponse {
    resp := &runtimehooksv1.BeforeUpdateMachineResponse{}

    oldSpec := req.OldMachine.Spec
    newSpec := req.NewMachine.Spec

    // Csak a bizonyitottan biztonsagos valtozasokat kezeljuk helyben
    if onlyLabelsOrAnnotationsChanged(oldSpec, newSpec) {
        resp.RetryAfterSeconds = 0
        resp.Status = runtimehooksv1.ResponseStatusSuccess
        return resp
    }

    // Minden mas menjen rollouttal
    resp.Status = runtimehooksv1.ResponseStatusFailure
    return resp
}

Az extension regisztralasa egy ExtensionConfig objektummal tortenik:

apiVersion: runtime.cluster.x-k8s.io/v1alpha1
kind: ExtensionConfig
metadata:
  name: inplace-updater
spec:
  clientConfig:
    service:
      name: inplace-updater
      namespace: capi-system
      port: 8443
  namespaceSelector:
    matchLabels:
      cluster.x-k8s.io/managed: "true"

Mit teszteltem a gyakorlatban

Harom scenariot futtattam stagingen (12 node, BYOH provider, Ubuntu 22.04):

1. Worker label valtozas

Egy custom labelt modositottam a MachineDeployment templateben. A CAPI nem gorgette ujra a 8 workert, hanem helyben patchelte a labeleket. Osszesen kb. 3 masodperc volt. Korabban ugyanez tobb mint ket ora rolloutot jelentett.

2. Kubelet config frissites

A maxPods erteket 110-rol 150-re emeltem. Az extension SSH-val belepett a node-ra, atirta a kubelet configot, majd ujrainditotta a kubeletet. A node vegig klaszterben maradt, pod eviction nem tortent.

3. Control plane Kubernetes verzio update

A KubeadmControlPlane verziot 1.31.3-rol 1.31.4-re emeltem. A CAPI helyesen ugy dontott, hogy ezt nem szabad in-place modon kezelni, es standard rolling replacementet csinalt. Pont ezt vartam.

Lancolt upgrade

A masik eros ujitas a lancolt upgrade. ClusterClass mellett eleg a topologiaban verziot emelni, es a CAPI intezi a sorrendet: eloszor control plane, utana workerek.

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: staging
spec:
  topology:
    class: my-cluster-class
    version: v1.31.4  # csak ezt kell emelni
    controlPlane:
      replicas: 3
    workers:
      machineDeployments:
        - class: default-worker
          name: md-0
          replicas: 8

Verziot modositasz, apply, es a CAPI vegigviszi. Nalunk 1.31.3-rol 1.31.4-re tisztan lefutott: control plane node-ok egyesevel, utana workerek batchenkent a maxUnavailable szerint.

Buktatok

Feature gate-ek kellenek. Az InPlaceUpdates es a RuntimeSDK is legyen bekapcsolva.

Az extension legyen stabil. Ha feluton elszall, a machine rossz allapotban maradhat. Nincs automatikus rollback, ugyhogy idempotens lepesek es korrekt hibakezeles kell.

BYOH mellett marad egyedi munka. Egyszerubb metadata valtozasokra jo, de OS-szintu feladatokhoz jellemzoen sajat extension kell.

Nincs dry-run. Ma meg nincs olyan elonezet, ami megmondja, hogy adott diffre in-place vagy rollout lesz. Ezert staging teszteles kotelezo.

Megerte?

A mi bare-metal kornyezetunkben egyertelmuen igen. Mar csak a label valtozasokkal orakat nyerunk, a lancolt upgrade pedig rengeteg kezi koordinaciot vesz le a vallunkrol.

Cloudon, ahol 2-3 perc alatt jon uj node, kisebb a kulonbseg, de az in-place update ott is hasznos lehet alacsony kockazatu, nem diszruptiv valtozasoknal.

Nalam a tanulsag: konzervativan kell kezdeni. Ahol biztos a helyben frissites, ott hasznald, minden masnal nyugodtan maradjon a klasszikus rollout.

A kovetkezo lepes nalunk a tanusitvany rotacio es nehany kubelet flag kezelese lesz. Ha rendbe rakom a kodot, felteszem GitHubra.