
Celkom nedávno jedna známa spoločnosť oznámila, že prechádza na ARM architektúru pre svoju radu notebookov. Po vypočutí tejto správy som si spomenul: keď som znova prehliadal ceny EC2 na AWS, všimol som si Graviton s veľmi lákavou cenou. Samozrejme, háčik bol v tom, že to je ARM. Vtedy ma ani nenapadlo, že ARM môže byť naozaj vážne...
Pre mňa bola táto architektúra vždy doménou mobilných zariadení a rôznych IoT vecí. „Pravé“ servery na ARM sa zdajú byť akési nezvyčajné, v niečom až zvláštne... Avšak nová myšlienka mi zostala v hlave, takže v jeden víkend som sa rozhodol preskúmať, čo všetko sa dá dnes spustiť na ARM. A preto som sa rozhodol začať s niečím, čo mi je blízke a známe — s Kubernetes klastrom. A nie s nejakým hypotetickým „klastrom“, ale úplne „naplno“, aby bol maximálne podobný tomu, čo som zvyknutý vidieť v produkcii.
Podľa mojej predstavy by mal byť klaster prístupný z internetu, mal by v ňom bežať nejaká webová aplikácia a tiež by mal byť minimálne monitoring. Na realizáciu tejto myšlienky bude potrebné pár (alebo viac) Raspberry Pi modelu 3B+. Experimentálna platforma by mohla byť aj AWS, ale zaujímali ma presne „maliny“ (ktoré aj tak stáli nevyužité). Takže na nich nainštalujeme klaster Kubernetes s Ingress, Prometheus a Grafana.
Príprava „malín“
Inštalácia OS a SSH
Pri výbere OS na inštaláciu som sa veľmi nestaral: jednoducho som vzal najnovšie Raspberry Pi OS Lite s . Tam je tiež dostupná , všetky kroky, ktoré je potrebné vykonať na všetkých uzloch budúceho klastrom. Následne treba vykonať nasledujúce manipulácie (tiež na všetkých uzloch).
Po pripojení monitora a klávesnice je potrebné predtým nastaviť sieť a SSH:
- Pre fungovanie klastru musí mať master statickú IP adresu, zatiaľ čo na pracovných uzloch je to na uvážení. Ja som uprednostnil statické adresy všade kvôli pohodlnosti nastavení.
- Statickú adresu možno nakonfigurovať v OS (v súbore
/etc/dhcpcd.confje vhodný príklad) alebo fixovaním lease v DHCP serveri používaného (v mojom prípade domáceho) routera. - ssh-server sa jednoducho zapína v raspi-config (interfacing options → ssh).
Po tom sa už môžete prihlásiť cez SSH (predvolene je prihlásenie — pi, a heslo — raspberry alebo to, na ktoré ste ho zmenili) a pokračovať v nastaveniach.
Ďalšie nastavenia
- Nastavíme názov hostiteľa. V mojom príklade sa budú používať
pi-controlapi-worker. - Skontrolujeme, či je súborový systém rozšírený na celý disk (
df -h \/). V prípade potreby ho môžete rozšíriť pomocou raspi-config. - Zmeníme predvolené heslo používateľa v raspi-config.
- Vypneme swap súbor (to je požiadavka Kubernetes; ak máte záujem o podrobnosti k tomuto, pozrite sa na ):
dphys-swapfile swapoff systemctl disable dphys-swapfile - Aktualizujeme balíky na najnovšie verzie:
apt-get update && apt-get dist-upgrade -y - Nainštalujeme Docker a ďalšie balíky:
apt-get install -y docker docker.io apt-transport-https curl bridge-utils iptables-persistentPri inštalácii
iptables-persistentbude potrebné uložiť nastavenia iptables pre ipv4, a do súboru/etc/iptables/rules.v4— pridať pravidlá do reťazcaFORWARD, takto:# 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 - Ostáva sa len reštartovať.
Teraz je všetko pripravené na inštaláciu klastru Kubernetes.
Inštalácia Kubernetes
V tejto fáze som zámerne odložil všetky svoje a naše firemné skúsenosti s automatizáciou inštalácie a konfigurácie klastru K8s. Namiesto toho použijeme oficiálnu dokumentáciu na (mierne doplnenú poznámkami a skráteniami).
Pridáme repozitár Kubernetes:
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Ďalej dokumentácia navrhuje nainštalovať CRI (container runtime interface). Keďže Docker už je nainštalovaný, posunieme sa ďalej a nainštalujeme základné komponenty:
sudo apt-get install -y kubelet kubeadm kubectl kubernetes-cni Na kroku inštalácie základných komponentov som hneď pridal kubernetes-cni, ktorý je potrebný pre fungovanie klastru. A tu je dôležitý bod: balík kubernetes-cni z nejakých dôvodov nevytvára predvolený adresár pre nastavenia CNI rozhraní, preto som ho musel vytvoriť ručne:
mkdir -p /etc/cni/net.dPre prácu sieťového backendu, o ktorom sa bude hovoriť nižšie, je potrebné doinštalovať plugin pre CNI. Vybral som si známy a jasný plugin portmap (úplný zoznam nájdete v ):
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/ ./portmapNastavenie Kubernetes
Uzol s control plane
Inštalácia samotného klastru sa robí pomerne jednoducho. A na urýchlenie tohto procesu a skontrolovanie, či sú obrazy Kubernetes dostupné, je možné najprv vykonať:
kubeadm config images pullTeraz vykonáme samotnú inštaláciu — inicializujeme control plane klastru:
kubeadm init --pod-network-cidr=10.1.0.0/16 --service-cidr=10.2.0.0/16 --upload-certsUpozorňujeme, že podsiete pre služby a pody sa nesmú prekrižovať navzájom ani s existujúcimi sieťami.
Na konci nám zobrazia správu, že všetko je v poriadku, a zároveň nám poradia, ako pripojiť pracovné uzly k ovládaciemu uzlu:
Váš ovládací uzol Kubernetes bol úspešne inicializovaný!
Na začiatok používania vášho klastru musíte spustiť nasledujúce príkazy ako bežný používateľ:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Teraz by ste mali nainštalovať sieť podov do klastru.
Spustite "kubectl apply -f [podnetwork].yaml" s jednou z možností uvedených na:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Teraz sa môžete pripojiť k akémukoľvek počtu ovládacích uzlov spustením nasledujúceho príkazu na každom z nich ako root:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4
--discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050
--control-plane --certificate-key 72a3c0a14c627d6d7fdade1f4c8d7a41b0fac31b1faf0d8fdf9678d74d7d2403
Upozorňujeme, že certifikát kľúč poskytuje prístup k citlivým údajom klastru, uchovávajte ho v tajnosti!
Ako opatrenie zabezpečenia budú nahraté certifikáty odstránené za dve hodiny; Ak je to potrebné, môžete použiť
"kubeadm init phase upload-certs --upload-certs" na nahranie certifikátov neskôr.
Potom sa môžete pripojiť k akémukoľvek počtu pracovných uzlov spustením nasledujúceho príkazu na každom z nich ako root:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4
--discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050Splníme odporúčania na pridanie konfigu pre používateľa. A zároveň odporúčam hneď pridať automatické doplňovanie pre kubectl:
kubectl completion bash > ~$HOME/.kube/completion.bash.inc
printf "
# Automatické doplňovanie shell pre Kubectl
source '$HOME/.kube/completion.bash.inc'
" >> $HOME/.bash_profile
source $HOME/.bash_profileV tejto fáze už môžete vidieť prvý uzol v klastri (aj keď ešte nie je pripravený):
root@pi-control:~# kubectl get no
NAME STATUS ROLES AGE VERSION
pi-control NotReady master 29s v1.18.6Konfigurácia siete
Ako bolo uvedené v správe po inštalácii, je potrebné nainštalovať sieť do klastru. V dokumentácii ponúkajú výber z Calico, Cilium, contiv-vpp, Kube-router a Weave Net… Tu som sa odklonil od oficiálnych pokynov a vybral som si pre mňa známejší a zrozumiteľnejší variant: v režime host-gw (viac informácií o dostupných backendových technológiách nájdete v ).
Inštalácia do klastru je pomerne jednoduchá. Najprv — stiahneme manifesty:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml Potom zmeníme v nastaveniach typ z vxlan na host-gw:
sed -i 's/vxlan/host-gw/' kube-flannel.yml… a podsieť podov — zo základnej hodnoty na tú, ktorá bola uvedená pri inicializácii klastru:
sed -i 's#10.244.0.0/16#10.1.0.0/16#' kube-flannel.ymlPo tom vytvoríme zdroje:
kubectl create -f kube-flannel.yml Hotovo! O chvíľu prvý uzol K8s prejde do stavu Pripravené:
NAME STATUS ROLES AGE VERSION
pi-control Ready master 2m v1.18.6Pridanie pracovného uzla
Teraz môžete pridať worker-a. Na to je potrebné po inštalácii samotného Kubernetes podľa vyššie opísaného scenára jednoducho vykonať predtým získaný príkaz:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4
--discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050Na tomto mieste môžeme považovať, že klastra je pripravený:
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.6Mal som na dosah len dve Raspberry Pi, preto som nechcel odovzdať jednu z nich iba pre control plane. Preto som odstránil automaticky nastavený taint z uzla pi-control spustením:
root@pi-control:~# kubectl edit node pi-control… a odstránil riadky:
- effect: NoSchedule
key: node-role.kubernetes.io/masterNaplnienie klastra nevyhnutným minimom
Najprv potrebujeme Helm. Samozrejme, všetko môžeme robiť aj bez neho, ale Helm umožňuje bez úpravy súborov prispôsobiť niektoré komponenty podľa svojich predstáv. A v skutočnosti je to len binárny súbor, ktorý "nežaduje").
Takže ideme na v sekcii docs/installation a vykonáme príkaz odtiaľ:
curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bashPo tomto pridáme repozitár chartov:
helm repo add stable https://kubernetes-charts.storage.googleapis.com/Teraz nainštalujeme infraštruktúrne komponenty podľa plánu:
- Ingress controller;
- Prometheus;
- Grafana;
- cert-manager.
Ingress controller
Prvý komponent — Ingress controller — sa inštaluje veľmi jednoducho a je pripravený na použitie „z krabice“. Na to stačí ísť do a vykonať príkaz na inštaláciu odtiaľ:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yamlAvšak v tomto okamihu začala "malina" namáhať a naraziť na diskový IOPS. Vec je taká, že spolu s Ingress-kontrolérom sa inštaluje veľké množstvo zdrojov, vykonáva sa množstvo požiadaviek na API a, samozrejme, sa zapisuje veľa dát do etcd. V skratke, buď karta pamäte triedy 10 nie je veľmi výkonná, alebo SD-kartám proste chýba na takú záťaž. Napriek tomu sa po piatich minútach všetko spustilo.
Bol vytvorený namespace a v ňom sa objavil kontrolér a všetko, čo 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 48sPrometheus
Nasledujúce dva komponenty je pomerne jednoduché nainštalovať cez Helm z chart repo.
Nájdeme Prometheus, vytvoríme namespace a nainštalujeme do neho:
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"}Predvolene Prometheus požaduje 2 disky: jeden pre údaje samotného Promethea a druhý pre údaje AlertManagera. Keďže v klastre nebol vytvorený storage class, disky nebudú objednané a pod’y sa nespustia. Pre inštalácie na bare metal v Kubernetes zvyčajne používame Ceph rbd, ale v prípade Raspberry Pi je to jasný prehnaný krok.
Preto vytvoríme jednoduché lokálne úložisko na hostpath. Manifesty PV (persistent volume) pre prometheus-server a prometheus-alertmanager sú zlúčené v súbore prometheus-pv.yaml v . Adresár pre PV je potrebné vopred vytvoriť na disku toho uzla, na ktorý chceme pripojiť Prometheus: v príklade je uvedené nodeAffinity podľa hostname pi-worker a na ňom sú vytvorené adresáre /data/localstorage/prometheus-server a /data/localstorage/prometheus-alertmanager.
Stiahneme (sklonujeme) manifest a pridáme do Kubernetes:
kubectl create -f prometheus-pv.yamlV tomto štádiu som sa prvýkrát stretol s problémom architektúry ARM. Kube-state-metrics, ktorý sa predvolene inštaluje v charte Prometheus, odmietol bežať. Zobrazila sa chyba:
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"Ide o to, že pre kube-state-metrics sa používa obrázok z projektu CoreOS, ktorý nie je zostavený pre 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.7Musel som trochu googliť a nájsť napríklad . Aby sme ho mohli využiť, aktualizujeme release, pričom uvedieme, aký obrázok použiť pre 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.6Skontrolujeme, či sa všetko spustilo:
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 4m52sGrafana a cert-manager
Pre grafy a dashboardy inštalujeme Grafana:
helm install grafana --namespace monitoring stable/grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"}Na konci výstupu nám ukážu, ako získať heslo na prístup:
kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echoNa objednanie certifikátov nainštalujeme cert-manager. Na jeho inštaláciu sa obrátime na , ktorá ponúka zodpovedajúce príkazy pre 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=truePre samopodpisované certifikáty na domáce používanie je to celkom dostatočné. Ak však potrebujete získať rovnaký Let’s Encrypt, je potrebné nastaviť ešte cluster issuer. Podrobnosti o tom nájdete v našom článku „».
Sám som sa zastavil na variante z , rozhodol som sa, že staging variant LE bude postačujúci. Zmeníme v príklade e-mail, uložíme do súboru a pridáme do klasteru ():
kubectl create -f cert-manager-cluster-issuer.yamlTeraz môžeme objednať certifikát, napríklad pre Grafana. K tomu budeme potrebovať doménu a prístup do klasteru zvonka. Doménu mám, a traffic som nastavil presmerovaním portov 80 a 443 na domácom routeri podľa vytvoreného servisu ingress-controller’a:
kubectl -n ingress-nginx get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.2.206.61 80:31303/TCP,443:30498/TCP 23d80. port sa v tomto prípade premieta na 31303 a 443 na 30498. (Porty sú generované náhodne, takže u vás budú iné.)
Tu je príklad certifikátu ():
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-stagingPridávame ho do klasteru:
kubectl create -f cert-manager-grafana-certificate.yamlPo tomto sa objaví zdroj Ingress, cez ktorý bude prebiehať validácia Let’s Encryptom:
root@pi-control:~# kubectl -n monitoring get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
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 Po tom, čo validácia prebehne, uvidíme, že zdroj certificate je pripravený, a v uvedenom vyššie tajomstve grafana-tls — certifikát a kľúč. Môžete okamžite skontrolovať, kto certifikát vydal:
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 X1Vráťme sa k Grafane. Budeme musieť trochu upraviť jej Helm vydanie, zmenou nastavení pre TLS podľa vytvoreného certifikátu.
Na to si stiahneme chart, upravíme a aktualizujeme z lokálneho adresára:
helm pull --untar stable/grafana Upravujeme v súbore grafana/values.yaml nastavenia TLS:
tls:
- secretName: grafana-tls
hosts:
- grafana.home.pi Tu si môžeme hneď nastaviť aj nainštalovaný Prometheus ako datasource:
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus-server:80
access: proxy
isDefault: trueTeraz z lokálneho adresára aktualizujeme chart Grafana:
helm upgrade grafana --namespace monitoring ./grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"} Kontrolujeme, že v Ingress grafana pribudol port 443 a je prístup cez 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; includeSubDomainsPre demonštráciu Grafany v akcii si môžete stiahnuť a pridať . Takto to vyzerá:

Odporúčam aj pridať dashboard pre node exporter: podrobne ukáže, čo sa deje s "malinami" (vyťaženosť CPU, využitie pamäte, siete, disku atď.).
Po tomto si myslím, že klaster je pripravený prijímať a spúšťať aplikácie!
Poznámka o zostavení
Na zostavenie aplikácií pre ARM architektúru existujú minimálne dve možnosti. Po prvé, môžete zostavovať na ARM zariadení. Avšak, keď som sa pozrel na aktuálne vyťaženie dvoch Raspberry Pi, pochopil som, že ešte aj zostavovanie nevydržia. Preto som si objednal novú Raspberry Pi 4 (je silnejšia a má až 4 GB pamäte) — plánujem zostavovať na nej.
Druhá možnosť — zostavenie multiarchitektonického obrazu Docker na výkonnejšom stroji. Na to existuje . Ak je aplikácia v kompilovanom jazyku, bude potrebná krížová kompilácia pre ARM. Nebudem popisovať všetky nastavenia pre tento proces, pretože by to vyžadovalo samostatný článok. Pri implementácii takéhoto prístupu je možné dosiahnuť "univerzálne" obrazy: Docker, spustený na ARM stroji, automaticky načíta obraz zodpovedajúci architektúre.
Záver
Usmernený experiment prekonal všetky moje očakávania: [minimálne] "vanilkový" Kubernetes so základnou inštaláciou sa na ARM cíti celkom dobre, a pri jeho konfigurácii sa objavili len pár nuansí.
Sami Raspberry Pi 3B+ zvládajú záťaž na CPU, avšak ich SD karty sú jasným úzkym hrdlom. Kolegovia naznačili, že v niektorých verziách je možnosť bootovať z USB, kam sa dá pripojiť SSD: v takom prípade by sa situácia mohla zlepšiť.
Tu je príklad záťaže CPU pri inštalácii Grafana:

Na experimenty a "na vyskúšanie" sa podľa môjho názoru Kubernetes klaster na "malinách" omnoho lepšie prenáša pocity z používania v porovnaní s tým istým Minikube, pretože všetky komponenty klasteru sú inštalované a fungujú "dospelým" spôsobom.
V budúcnosti je plán pridať ku klasteru celý cyklus CI/CD, realizovaný úplne na Raspberry Pi. Taktiež budem rád, ak sa niekto podelí o svojich skúsenostiach s nastavením K8s na AWS Gravitonoch.
P.S. Áno, "produkcia" môže byť bližšie, než som si myslel:

P.P.S.
Prečítajte si tiež na našom blogu:
- «».
Zdroj: habr.com
