Popolni Kubernetes od nič na Raspberry Pi

Popolni Kubernetes od nič na Raspberry Pi

Nedavno je jedna poznata kompanija objavila da prebacuje svoju liniju laptopa na ARM arhitekturu. Kada sam čuo tu vest, setio sam se: dok sam još jednom pregledavao cene EC2 na AWS-u, primetio sam Graviton procesore sa vrlo atraktivnom cenom. U toj situaciji, naravno, postojala je caka, jer je to ARM. Tada mi nije padalo na pamet da je ARM zapravo vrlo ozbiljna stvar...

Ova arhitektura mi je uvek bila rezervisana za mobilne i razne IoT uređaje. "Pravi" serveri na ARM-u deluju nekako neobično, čak i ekstremno... Međutim, nova ideja mi se uvučila u glavu, pa sam jednog vikenda odlučio da proverim što se danas može pokrenuti na ARM-u. I za to sam odlučio da počnem sa nečim bliskim i poznatim — Kubernetes klasterom. Pri tome ne govorim o nekakvom uslovnom "klasteru", već o pravom, da bude što sličniji onome što sam navikao da viđam u produkciji.

Moj plan je bio da klaster bude dostupan sa interneta, da pokreće neku web aplikaciju i takođe da ima bar osnovni nadzor. Za realizaciju ove ideje biće mi potrebno nekoliko (ili više) Raspberry Pi uređaja, modela 3B+. Mesto za eksperimentisanje moglo bi biti i AWS, ali su me zapravo zanimali upravo "malini" (koji su, ionako, stajali neiskorišćeni). Tako ćemo na njima postaviti Kubernetes klaster sa Ingress-om, Prometheus-om i Grafana-om.

Priprema "malina"

Instalacija OS-a i SSH

Sa izborom OS-a za instalaciju nisam se previše opterećivao: jednostavno sam uzeo najnoviji Raspberry Pi OS Lite sa službene stranice. Tamo je dostupna dokumentacija za instalaciju, sve radnje koje treba izvršiti na svim čvorovima budućeg klastera. Zatim je potrebno izvršiti sledeće radnje (takođe na svim čvorovima).

Povezivanje monitora i tastature, potrebno je prethodno podesiti mrežu i SSH:

  1. Za rad klastera, master mora imati statičku IP adresu, dok radni čvorovi mogu imati po izboru. Ja sam odabrao statične adrese svuda zbog lakšeg podešavanja.
  2. Statičku adresu možete konfigurisati u OS-u (u datoteci /etc/dhcpcd.conf ima adekvatan primer) ili fiksiranjem lease-a na DHCP serveru korišćenog (u mom slučaju — domaćem) ruteru.
  3. ssh-server se jednostavno uključuje u raspi-config (interfacing options → ssh).

Nakon toga se možete ulogovati putem SSH-a (podrazumevani korisnički naziv je pi, a lozinka je raspberry ili ona koju ste promenili) i nastaviti sa podešavanjima.

Druge postavke

  1. Nastavimo ime hosta. U mom primeru koristićemo pi-control in pi-worker.
  2. Proverimo da li je datotečni sistem proširen na celu disk (df -h /). U slučaju potrebe, može se proširiti pomoću raspi-config.
  3. Promenićemo zadatu lozinku korisnika u raspi-config.
  4. Isključićemo swap-fajl (to je zahtev Kubernetes-a; ako vas zanimaju detalji o ovoj temi, pogledajte issue #53533):
    dphys-swapfile swapoff
    systemctl disable dphys-swapfile
  5. Ažuriraćemo pakete na najnovije verzije:
    apt-get update && apt-get dist-upgrade -y
  6. Instaliraćemo Docker i dodatne pakete:
    apt-get install -y docker docker.io apt-transport-https curl bridge-utils iptables-persistent

    Tokom instalacije iptables-persistent biće potrebno sačuvati postavke iptables za ipv4, a u datoteci /etc/iptables/rules.v4 — dodati pravila u lanac FORWARD, tako:

    # Generated by xtables-save v1.8.2 on Sun Jul 19 00:27:43 2020
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A FORWARD -s 10.1.0.0/16  -j ACCEPT
    -A FORWARD -d 10.1.0.0/16  -j ACCEPT
    COMMIT
  7. Preostaje samo da se ponovo pokrene.

Sada je sve spremno za instalaciju Kubernetes klastera.

Instalacija Kubernetes-a

U ovoj fazi namerno sam odložio svu moju i našu korporativnu obradu automatizacije instalacije i konfiguracije K8s klastera. Umesto toga, koristićemo zvaničnu dokumentaciju sa kubernetes.io (malo dopunjenom komentarima i skraćenicama).

Dodajemo repozitorij Kubernetes-a:

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update

Dalje u dokumentaciji predlaže se instalacija CRI (interfejs za izvršavanje kontejnera). Pošto je Docker već instaliran, idemo dalje i instaliramo glavne komponente:

sudo apt-get install -y kubelet kubeadm kubectl kubernetes-cni

Na koraku instalacije glavnih komponenti odmah sam dodao kubernetes-cni, koji je neophodan za rad klastera. I ovde postoji važna stvar: paket kubernetes-cni iz nekog razloga ne stvara podrazumevanu direktoriju za postavke CNI interfejsa, pa sam je morao kreirati ručno:

mkdir -p /etc/cni/net.d

Za rad network-bekenda, o kojem će biti reči u nastavku, potrebno je dodatno instalirati CNI plugin. Izabrao sam poznati i razumljiv meni plugin portmap (ceo njihov spisak pogledajte u dokumenti):

curl -sL https://github.com/containernetworking/plugins/releases/download/v0.7.5/cni-plugins-arm-v0.7.5.tgz | tar zxvf - -C /opt/cni/bin/ ./portmap

Nastavitev Kubernetes

Čvor sa kontrolnim planom

Instalacija samog klastera odvija se prilično jednostavno. A da bismo ubrzali ovaj proces i proverili da li su Kubernetes imidži dostupni, možemo prethodno izvršiti:

kubeadm config images pull

Sada sprovodimo samu instalaciju — inicijalizujemo control plane klastera:

kubeadm init --pod-network-cidr=10.1.0.0/16 --service-cidr=10.2.0.0/16 --upload-certs

Upoštevajte, da se omrežja za storitve in pod-e ne smejo prekrivati med seboj in z obstoječimi omrežji.

Na koncu bomo prejeli sporočilo, da je vse v redu, in nam povedali, kako povezati delovne vozlišča s kontrolno enoto:

Vaša kontrolna enota Kubernetes je uspešno inicializirana!
Za začetek dela s svojim grozdom morate kot navaden uporabnik izvesti naslednje:
 mkdir -p $HOME/.kube
 sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
 sudo chown $(id -u):$(id -g) $HOME/.kube/config
Zdaj morate razporediti omrežje podov v grozd.
Zaženite "kubectl apply -f [podnetwork].yaml" z eno od možnosti, navedenih na:
 https://kubernetes.io/docs/concepts/cluster-administration/addons/
Zdaj lahko na kontrolno enoto povežete poljubno število vozlišč z izvajanjem naslednjega ukaza na vsakem kot root:
 kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 
   --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050 
   --contrl-plane --certificate-key 72a3c0a14c627d6d7fdade1f4c8d7a41b0fac31b1faf0d8fdf9678d74d7d2403
Upoštevajte, da ključ certifikata daje dostop do občutljivih podatkov grozda, zato ga hranite v tajnosti!
Kot zaščita se naloženi certifikati izbrišejo v dveh urah; po potrebi lahko uporabite
"kubeadm init phase upload-certs --upload-certs" za ponovno nalaganje certifikatov.
Nato lahko na delovna vozlišča povežete poljubno število vozlišč tako, da na vsakem izvedete naslednje kot root:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 
   --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050

Izvedimo priporočila za dodajanje konfiguracije za uporabnika. Priporočam tudi, da takoj dodate samodejno dopolnjevanje za kubectl:

 kubectl completion bash > ~$HOME/.kube/completion.bash.inc
 printf "
 # Dopolnjevanje lupine Kubectl
 source '$HOME/.kube/completion.bash.inc'
 " >> $HOME/.bash_profile
 source $HOME/.bash_profile

Na tej točki lahko že vidite prvo vozlišče v grozdu (res je, da še ni pripravljeno):

root@pi-control:~# kubectl get no
IME         STATUS     ROLI    STAROST   VERZIJA
pi-control   NotReady   master   29s   v1.18.6

Konfiguracija omrežja

Nato, kot je bilo omenjeno v sporočilu po namestitvi, bo potrebno v grozd namestiti omrežje. V dokumentaciji ponujajo izbiro med Calico, Cilium, contiv-vpp, Kube-router in Weave Net… Tukaj sem odstopil od uradne navodila in izbral bolj znano in razumljivo možnost: flannel v načinu host-gw (več o razpoložljivih backendih glejte v dokumentaciji projekta).

Namestitev v grozd je precej enostavna. Na začetku — prenesemo manifeste:

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Nato v nastavitvah spremenimo tip z vxlan na host-gw:

sed -i 's/vxlan/host-gw/' kube-flannel.yml

… in podomrežje podov — iz privzete vrednosti na tisto, ki je navedena pri inicializaciji grozda:

sed -i 's#10.244.0.0/16#10.1.0.0/16#' kube-flannel.yml

Po tem ustvarimo vire:

kubectl create -f kube-flannel.yml

Končano! Čez nekaj časa bo prvo vozlišče K8s prešlo v stanje Ready:

IME         STATUS   ROLI    STAROST   VERZIJA
pi-control   Ready    master   2m    v1.18.6

Dodajanje delovnega vozlišča

Sedaj lahko dodate delavca. To storite tako, da na njem — po namestitvi samega Kubernetes po scenariju, opisanem zgoraj — preprosto izvedete prej pridobljeno ukaz:

kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 
    --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050

S tem lahko štejemo, da je grozd pripravljen:

root@pi-control:~# kubectl get no
NAME         STATUS   ROLES    AGE    VERSION
pi-control   Ready    master   28m    v1.18.6
pi-worker    Ready       2m8s   v1.18.6

Imel sem na voljo samo dve Raspberry Pi, zato mi ni bilo ljubše, da bi eno od njih le da bi postala del kontrolnega vozlišča. Zato sem s pomočjo ukaza odstranil samodejno nameščen taint na vozlišču pi-control:

root@pi-control:~# kubectl edit node pi-control

… in izbrisal vrstice:

 - effect: NoSchedule
   key: node-role.kubernetes.io/master

Napolnitev grozda z minimalnimi zahtevami

Najprej potrebujemo Helm. Seveda, vse to lahko naredite tudi brez njega, a Helm omogoča, da nekaterih komponent praktično ne spreminjate, ampak jih nastavljate po svoji izbiri. Po dejanskem stanju gre preprosto za izvršljivo datoteko, ki „ne prosi za hrano“.

Torej, odprete spletno stran helm.sh v razdelku docs/installation in izvedete ukaz od tam:

curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash

Po tem dodamo repo za grafe:

helm repo add stable https://kubernetes-charts.storage.googleapis.com/

Zdaj namestimo infrastrukturne komponente v skladu z načrtom:

  • Ingress kontroler;
  • Prometheus;
  • Grafana;
  • cert-manager.

Ingress kontroler

Prva komponenta — Ingress kontroler — se namestiti precej enostavno in je pripravljena za uporabo „iz škatle“. Za to zadostuje, da se prijavite v razdelek bare-metal na spletni strani in izvedete ukaz za namestitev od tam:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml

Vendar pa je v tem trenutku „malina“ začela obremenjevati in trčiti ob diskovni IOPS. Gre za to, da z Ingress kontrolerjem namestimo veliko število virov, se opravijo številna API povpraševanja in posledično se zapiše veliko podatkov v etcd. Na splošno, bodisi je SD kartica razreda 10 ne zelo zmogljiva, bodisi preprosto pomnilniške kartice ne zadoščajo za takšno obremenitev. Kljub temu se je po približno 5 minutah vse zagnalo.

Ustvarjen je bil namespace in v njem se je pojavil kontroler ter vse, kar je potreboval:

root@pi-control:~# kubectl -n ingress-nginx get pod
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-2hwdx        0/1     Completed   0          31s
ingress-nginx-admission-patch-cp55c         0/1     Completed   0          31s
ingress-nginx-controller-7fd7d8df56-68qp5   1/1     Running     0          48s

Prometheus

Naslednji dva komponenta sta precej enostavna za namestitev preko Helma iz chart repozitorija.

Najdemo Prometheus, ustvarimo namespace in ga namestimo:

helm search repo stable | grep prometheus
kubectl create ns monitoring
helm install prometheus --namespace monitoring stable/prometheus --set server.ingress.enabled=True --set server.ingress.hosts={"prometheus.home.pi"}

Privzeto Prometheus zahteva 2 diska: enega za podatke samega Prometheusa in drugega za podatke AlertManagerja. Ker v grozdu ni ustvarjen storage class, diski ne bodo zahtevani in podi se ne bodo zagnali. Za bare metal namestitve Kubernetes običajno uporabljamo Ceph rbd, vendar je v primeru Raspberry Pi to očitno preveliko breme.

Zato bomo ustvarili enostavno lokalno shrambo na hostpath. Manifesti PV (persistent volume) za prometheus-server in prometheus-alertmanager so združeni v datoteki prometheus-pv.yaml u Git-repozitoriji s primeri za članek. Direktorij za PV je treba vnaprej ustvariti na disku tistega vozlišča, na katerega želimo povezati Prometheus: v primeru je navedeno nodeAffinity po hostname pi-worker inna in na njem so ustvarjeni direktoriji /data/localstorage/prometheus-server in /data/localstorage/prometheus-alertmanager.

Prenesemo (kloniramo) manifest in ga dodamo v Kubernetes:

kubectl create -f prometheus-pv.yaml

V tem koraku sem se prvič srečal s težavo ARM arhitekture. Kube-state-metrics, ki je privzeto nameščen v chartu Prometheus, se ni zagnal. Vračal je napako:

root@pi-control:~# kubectl -n monitoring logs prometheus-kube-state-metrics-c65b87574-l66d8
standard_init_linux.go:207: exec user process caused "exec format error"

Gre za to, da za kube-state-metrics uporabljamo sliko projekta CoreOS, ki je ne izdelujejo za ARM:

kubectl -n monitoring get deployments.apps prometheus-kube-state-metrics -o=jsonpath={.spec.template.spec.containers[].image}
quay.io/coreos/kube-state-metrics:v1.9.7

Moral sem malo poiskati in najti, na primer, to sliko. Da jo uporabimo, bomo posodobili izdajo in navedli, katero sliko uporabiti za kube-state-metrics:

helm upgrade prometheus --namespace monitoring stable/prometheus --set server.ingress.enabled=True --set server.ingress.hosts={"prometheus.home.pi"} --set kube-state-metrics.image.repository=carlosedp/kube-state-metrics --set kube-state-metrics.image.tag=v1.9.6

Preverimo, da se je vse zagnalo:

root@pi-control:~# kubectl -n monitoring get po
NAME                                             READY   STATUS              RESTARTS   AGE
prometheus-alertmanager-df65d99d4-6d27g          2/2     Running             0          5m56s
prometheus-kube-state-metrics-5dc5fd89c6-ztmqr   1/1     Running             0          5m56s
prometheus-node-exporter-49zll                   1/1     Running             0          5m51s
prometheus-node-exporter-vwl44                   1/1     Running             0          4m20s
prometheus-pushgateway-c547cfc87-k28qx           1/1     Running             0          5m56s
prometheus-server-85666fd794-z9qnc               2/2     Running             0          4m52s

Grafana in cert-manager

Za grafikone in nadzorne plošče namestimo Grafana:

helm install grafana --namespace monitoring stable/grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"}

Na koncu izhoda nam bodo pokazali, kako pridobiti geslo za dostop:

kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

Za naročilo certifikatov bomo namestili cert-manager. Za njegovo namestitev se obrnemo na dokumenti, ki ponuja ustrezna ukaza za Helm:

helm repo add jetstack https://charts.jetstack.io

helm install 
  cert-manager jetstack/cert-manager 
  --namespace cert-manager 
  --version v0.16.0 
  --set installCRDs=true

Za samo-podpisane certifikate za domačo uporabo je to povsem dovolj. Če pa želite pridobiti enakega Let’s Encrypt, potem je potrebno nastaviti še cluster issuer. Podrobnosti o tem lahko najdete v našem članku „SSL certifikati od Let’s Encrypt z cert-manager v Kubernetes».

Sam sem se odločil za različico iz primerov v dokumentaciji, saj sem se odločil, da bo staging različica LE zadostovala. Spremenimo e-poštni naslov v primeru, shranimo v datoteko in dodamo v kluster (cert-manager-cluster-issuer.yaml):

kubectl create -f cert-manager-cluster-issuer.yaml

Zdaj lahko naročimo certifikat, na primer, za Grafano. Za to bo potreben domena in dostop do klustra z zunanje strani. Domena imam, promet pa sem konfiguriral z usmerjanjem vrat 80 in 443 na domačem usmerjevalniku v skladu z ustvarjeno storitvijo ingress-controller:

kubectl -n ingress-nginx get svc
IME                                 VRSTA        CLUSTER-IP     ZUNANJI-IP   VRATA                      STAROST
ingress-nginx-controller             NodePort    10.2.206.61            80:31303/TCP,443:30498/TCP   23d

80. vrata se v tem primeru prenašajo na 31303, 443 pa na 30498. (Vrata so generirana naključno, zato boste imeli drugačna.)

Tukaj je primer certifikata (cert-manager-grafana-certificate.yaml):

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: grafana
  namespace: monitoring
spec:
  dnsNames:
    - grafana.home.pi
  secretName: grafana-tls
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt-staging

Dodamo ga v kluster:

kubectl create -f cert-manager-grafana-certificate.yaml

Po tem se bo pojavil vir Ingress, preko katerega bo potekala validacija Let’s Encrypt:

root@pi-control:~# kubectl -n monitoring get ing
IME                        RAZRED    GOSTITELJI                        NASLOV         VRATA   STAROST
cm-acme-http-solver-rkf8l      grafana.home.pi      192.168.88.31   80      72s
grafana                        grafana.home.pi      192.168.88.31   80      6d17h
prometheus-server              prometheus.home.pi   192.168.88.31   80      8d

Ko bo validacija končana, bomo videli, da je vir certificate pripravljen, v navedeni skrivnosti pa grafana-tls je certifikat in ključ. Takoj lahko preverite, kdo je izdal certifikat:

root@pi-control:~# kubectl -n monitoring get certificate
NAME      READY   SECRET        AGE
grafana   True    grafana-tls   13m

root@pi-control:~# kubectl -n monitoring get secrets grafana-tls -ojsonpath="{.data['tls.crt']}" | base64 -d | openssl x509 -issuer -noout
issuer=CN = Fake LE Intermediate X1

Vrátíme se k Grafaně. Budeme muset mírně upravit její Helm release, aby se nastavení pro TLS shodovalo se vytvořeným certifikátem.

K tomu stáhneme chart, upravíme a aktualizujeme z lokálního adresáře:

helm pull --untar stable/grafana

Upravujeme v souboru grafana/values.yaml parametry TLS:

  tls:
    - secretName: grafana-tls
      hosts:
        - grafana.home.pi

Zde si také můžeme okamžitě nastavit nainstalovaný Prometheus jako datasource:

datasources:
  datasources.yaml:
    apiVersion: 1
    datasources:
    - name: Prometheus
      type: prometheus
      url: http://prometheus-server:80
      access: proxy
      isDefault: true

Nyní z lokálního adresáře aktualizujeme chart Grafana:

helm upgrade grafana --namespace monitoring ./grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"}

Ověřujeme, že v Ingress grafana byl přidán port 443 a je zde přístup přes HTTPS:

root@pi-control:~# kubectl -n monitoring get ing grafana
NAME CLASS HOSTS ADDRESS PORTS AGE
grafana  grafana.home.pi 192.168.88.31 80, 443 63m

root@pi-control:~# curl -kI https://grafana.home.pi
HTTP/2 302
server: nginx/1.19.1
date: Tue, 28 Jul 2020 19:01:31 GMT
content-type: text/html; charset=utf-8
cache-control: no-cache
expires: -1
location: /login
pragma: no-cache
set-cookie: redirect_to=; Path=/; HttpOnly; SameSite=Lax
x-frame-options: deny
strict-transport-security: max-age=15724800; includeSubDomains

Pro demonstraci Grafany v akci můžete stáhnout a přidat dashboard pro kube-state-metrics. Takto to vypadá:

Popolni Kubernetes od nič na Raspberry Pi

Doporučuji také přidat dashboard pro node exporter: detailně ukáže, co se děje s "malinami" (zatížení CPU, využití paměti, sítě, disku atd.).

Po tom považuji, že klastr je připraven přijímat a spouštět aplikace!

Poznámka o sestavení

Pro sestavení aplikací pro ARM architekturu existují minimálně dvě možnosti. Zaprvé, lze sestavovat na ARM zařízení. Nicméně, po zhlédnutí aktuálního využití dvou Raspberry Pi jsem zjistil, že ani sestavování by nepřežily. Proto jsem si objednal novou Raspberry Pi 4 (je silnější a má rovnou 4 GB paměti) - plánuji na ní sestavovat.

Druhá možnost - sestavení multi-architekturového Docker obrazu na výkonnějším stroji. K tomu existuje rozšíření docker buildx. Če je aplikacija v kompiliranem jeziku, bo potrebna prevodna kompilacija za ARM. O opisovanju vseh nastavitev za to pot ne bom, ker bi to zahtevalo poseben članek. Z uresničitvijo takega pristopa lahko dosežete "univerzalne" slike: Docker, ki teče na ARM strojni opremi, bo samodejno nalagal ustrezno arhitekturo slike.

Zaključek

Izvedeni eksperiment je presegel vsa moja pričakovanja: [vsaj] "vanilni" Kubernetes s potrebno bazo se dobro obnaša na ARM, med njegovo konfiguracijo pa so se pojavili le nekateri manjši problemi.

Sami Raspberry Pi 3B+ obdržijo obremenitev na CPU, vendar so njihove SD-kartice očitno ožji del. Kolegi so mi povedali, da v nekaterih različicah obstaja možnost zagona z USB, kamor lahko priključite SSD: takrat se bo verjetno situacija izboljšala.

Tukaj je primer obremenitve CPU pri namestitvi Grafane:

Popolni Kubernetes od nič na Raspberry Pi

Za eksperimente in "za preizkusiti" se mi zdi, da Kubernetes-kluster na "malinah" veliko bolje posreduje občutke uporabe kot isti Minikube, ker so vsi sestavni deli klustra tako nameščeni kot tudi delujejo "kot je treba".

V prihodnosti imam idejo dodati k klstru celoten cikel CI/CD, izveden popolnoma na Raspberry Pi. Prav tako bom vesel, če mi kdo deli svoje izkušnje s konfiguracijo K8s na AWS Gravitonih.

P.S. Da, "production" je morda bližje, kot sem mislil:

Popolni Kubernetes od nič na Raspberry Pi

P.P.S.

Preberite tudi na našem blogu:

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster