
Nedavno je jedna poznata kompanija najavila da prelazi svoju liniju laptopa na ARM arhitekturu. Kada sam čuo ovu vest, setio sam se: pregledavajući ponovo cene na EC2 u AWS-u, obratio sam pažnju na Graviton-e sa veoma primamljivom cenom. Naravno, caka je bila u tome što je to ARM. Tada mi nije padao na pamet da je ARM zapravo prilično ozbiljna stvar…
Za mene je ova arhitektura oduvek bila rezervisana za mobilne i razne IoT uređaje. "Pravi" serveri na ARM-u - to je nekako neobično, u nekim stvarima čak i divlje… Međutim, nova misao se uvukla u moj um, pa sam odlučio da tokom jednog vikenda proverim šta se danas može pokrenuti na ARM-u. I odlučio sam da počnem sa nečim bliskim i poznatim - Kubernetes klastra. Ne samo da neki uslovni "klaster", već sve "ozbiljno", da bude što sličnije onome što sam navikao da viđam u proizvodnji.
Prema mojoj zamisli, klaster bi trebao biti dostupan preko interneta, u njemu bi trebala da radi neka web aplikacija i takođe bi trebala postojati barem neka vrsta nadgledanja. Za realizaciju ove ideje biće potrebno nekoliko (ili više) Raspberry Pi uređaja, ne nižih od modela 3B+. Eksperimentalna platforma bi mogla biti i AWS, ali mene su interesovali baš "malini" (koji su ionako stajali neiskorišćeni). Tako da ćemo na njima postaviti Kubernetes klaster sa Ingress-om, Prometheus-om i Grafanom.
Priprema "malina"
Instalacija OS-a i SSH
Nisam se previše zadržavao na izboru OS-a za instalaciju: jednostavno sam uzeo najnoviji Raspberry Pi OS Lite sa . Tamo se takođe nalazi , sve radnje koje treba izvršiti na svim čvorovima budućeg klastera. Zatim će biti potrebno izvršiti sledeće manipulacije (takođe na svim čvorovima).
Povezavši monitor i tastaturu, potrebno je unapred postaviti mrežu i SSH:
- Za rad klastera na masteru, obavezno mora biti statička IP adresa, a na radnim čvorovima — po izboru. Preferirao sam statične adrese svuda iz razloga praktične konfiguracije.
- Statičku adresu možete konfigurisati u OS-u (u datoteci
/etc/dhcpcd.confima odgovarajući primer) ili putem fiksiranja lease-a na DHCP serveru koji se koristi (u mom slučaju — kućnom) usmerivaču. - ssh-server se jednostavno aktivira u raspi-config-u (interfacing options → ssh).
Nakon toga, već možete da se prijavite putem SSH-a (podrazumevano korisničko ime je pi, a lozinka je raspberry ili ona koju ste promenili) i nastavite sa konfiguracijom.
Ostale postavke
- Postavit ćemo ime hosta. U mom primjeru koristit ćemo
pi-controlipi-worker. - Provjerit ćemo je li datotečni sustav proširen na cijeli disk (
df -h /). Po potrebi ga možemo proširiti pomoću raspi-config. - Promijenit ćemo zadanu lozinku korisnika u raspi-config.
- Isključit ćemo swap datoteku (to je zahtjev Kubernetes-a; ako vas zanimaju detalji o ovoj temi, pogledajte ):
dphys-swapfile swapoff systemctl disable dphys-swapfile - Ažurirat ćemo pakete na najnovije verzije:
apt-get update && apt-get dist-upgrade -y - Instalirat ćemo Docker i dodatne pakete:
apt-get install -y docker docker.io apt-transport-https curl bridge-utils iptables-persistentPrilikom instalacije
iptables-persistentbiće potrebno sačuvati postavke iptables za ipv4, a u datoteci/etc/iptables/rules.v4— dodati pravila u lanacFORWARD, ovako:# 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 - Preostaje samo restartati.
Sada je sve spremno za instalaciju Kubernetes klastera.
Instalacija Kubernetes-a
U ovoj fazi namjerno sam odgodio sve svoje i naše korporativne radne procese za automatizaciju instalacije i konfiguracije K8s klastera. Umjesto toga, koristit ćemo službenu dokumentaciju s (malo dopunjenu komentarima i skraćenicama).
Dodajemo Kubernetes repozitorij:
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 updateDalje dokumentacija predlaže instalaciju CRI (container runtime interface). Budući da 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 potreban za rad klastera. I tu postoji važna točka: paket kubernetes-cni iz nekih razloga ne stvara zadani direktorij za postavke CNI sučelja, pa sam ga morao stvoriti ručno:
mkdir -p /etc/cni/net.dZa rad network backenda, o kojem će biti riječi kasnije, potrebno je dodatno instalirati plugin za CNI. Odabrao sam poznati i razumljiv plugin portmap (cijeli njihov popis pogledajte u ):
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/ ./portmapPostavka Kubernetes-a
Čvor s control plane-om
Instalacija samog klastera je prilično jednostavna. A kako bi se ubrzao ovaj proces i provjerilo da su Kubernetes slike dostupne, prethodno možete izvršiti:
kubeadm config images pullSada provodimo samu instalaciju — inicijaliziramo control plane klastera:
kubeadm init --pod-network-cidr=10.1.0.0/16 --service-cidr=10.2.0.0/16 --upload-certsObratite pažnju da podmreže za servise i podove ne bi trebale preklapati jedna s drugom i s postojećim mrežama.
Na kraju ćemo vidjeti poruku da je sve u redu i uz to će nam pokazati kako povezati radne čvorove s kontrolnom ravni:
Vaša Kubernetes kontrolna ravnina je uspješno inicijalizirana!
Da biste počeli koristiti svoj klaster, trebate pokrenuti sljedeće kao običan korisnik:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Sada biste trebali implementirati pod mrežu u klaster.
Pokrenite "kubectl apply -f [podnetwork].yaml" s jednom od opcija navedenih na:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Sada se možete pridružiti bilo kojem broju čvorova kontrolne ravni pokretanjem sljedeće naredbe na svakom kao root:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4
--discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050
--contrl-plane --certificate-key 72a3c0a14c627d6d7fdade1f4c8d7a41b0fac31b1faf0d8fdf9678d74d7d2403
Imajte na umu da certifikat daje pristup osjetljivim podacima klastera, čuvajte ga u tajnosti!
Kao zaštita, preneseni certifikati će biti izbrisani za dva sata; Ako je potrebno, možete koristiti
"kubeadm init phase upload-certs --upload-certs" za ponovno učitavanje certifikata nakon toga.
Nakon toga se možete pridružiti bilo kojem broju radnih nodova pokretanjem sljedeće naredbe na svakom kao root:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4
--discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050Slijedimo preporuke za dodavanje konfiguracije za korisnika. Također, preporučujem da odmah dodate automatsko dovršavanje za kubectl:
kubectl completion bash > ~/\.kube/completion.bash.inc
printf "
# Dovršavanje kubectl ljuske
source '$HOME/\.kube/completion.bash.inc'
" >> $HOME/\.bash_profile
source $HOME/\.bash_profileU ovoj fazi već možemo vidjeti prvi čvor u klasteru (iako još nije spreman):
root@pi-control:~# kubectl get no
IME STATUS ULOGE STAROST VERZIJA
pi-control NotReady master 29s v1.18.6Konfiguracija mreže
Dalje, kao što je navedeno u poruci nakon instalacije, potrebno je instalirati mrežu u klaster. U dokumentaciji se predlaže izbor između Calico, Cilium, contiv-vpp, Kube-router i Weave Net… Ovdje sam se povukao od službene upute i odabrao opciju koja mi je poznatija i lakša za razumjeti: u načinu rada host-gw (više o dostupnim backendovima pogledajte u ).
Instalirati ga u klaster je prilično jednostavno. Prvo — preuzimamo manifeste:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml Zatim mijenjamo u postavkama tip s vxlan na host-gw:
sed -i 's/vxlan/host-gw/' kube-flannel.yml… i podmrežu podova — sa zadane vrijednosti na onu koja je navedena prilikom inicijalizacije klastera:
sed -i 's#10.244.0.0/16#10.1.0.0/16#' kube-flannel.ymlNakon toga kreiramo resurse:
kubectl create -f kube-flannel.yml Gotovo! Nakon nekog vremena prvi čvor K8s će preći u status Spremno:
IME STATUS ULOGE STAROST VERZIJA
pi-control Spreman master 2m v1.18.6Dodavanje radnog čvora
Sada možete dodati worker. Da biste to učinili, nakon instalacije Kubernetes-a prema gornjem scenariju, jednostavno izvršite prethodno dobivenu naredbu:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4
--discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050Time je za zaključiti da je klaster spreman:
root@pi-control:~# kubectl get no
IME STATUS ULOGE STAROST VERZIJA
pi-control Spreman master 28m v1.18.6
pi-worker Spreman 2m8s v1.18.6Imam samo dva Raspberry Pi, pa nisam htio dati jedan od njih samo za kontrolnu ploču. Stoga sam uklonio automatski postavljeni taint s čvora pi-control pokretanjem:
root@pi-control:~# kubectl edit node pi-control… i uklonio sljedeće redove:
- effect: NoSchedule
key: node-role.kubernetes.io/masterPopunjavanje klastera potrebnim minimumom
Prvo, trebat će nam Helm. Naravno, sve se može raditi i bez njega, ali Helm omogućava konfiguraciju nekih komponenti prema vašim vlastitim potrebama bez uređivanja datoteka. I zapravo, to je samo binarna datoteka koja "ne traži ništa".
Dakle, idemo na u odjeljak docs/installation i izvršite naredbu odatle:
curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bashNakon toga dodajemo repozitorij grafikon:
helm repo add stable https://kubernetes-charts.storage.googleapis.com/Sada instaliramo infrastrukturne komponente prema zamisli:
- Ingress kontroler;
- Prometheus;
- Grafana;
- cert-manager.
Ingress kontroler
Prva komponenta — Ingress kontroler — instalira se prilično jednostavno i spremna je za upotrebu "iz kutije". Da biste to učinili, dovoljno je otići na i izvršiti naredbu instalacije odatle:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yamlMeđutim, u tom trenutku "malina" počela je opterećivati i boriti se sa IOPS-om diska. Činjenica je da zajedno s Ingress kontrolerom dolazi mnogo resursa, izvršava se mnogo zahtjeva prema API-ju i, shodno tome, puno podataka se zapisuje u etcd. Ukratko, ili karta pamćenja 10. razreda nije dovoljno brza, ili SD kartice jednostavno nisu dovoljne za takvo opterećenje. Ipak, nakon otprilike 5 minuta, sve je pokrenuto.
Stvoren je namespace i u njemu se pojavio kontroler i sve što mu je potrebno:
root@pi-control:~# kubectl -n ingress-nginx get pod
IME SPREMAN STATUS RESTARTI STAROST
ingress-nginx-admission-create-2hwdx 0/1 Završen 0 31s
ingress-nginx-admission-patch-cp55c 0/1 Završen 0 31s
ingress-nginx-controller-7fd7d8df56-68qp5 1/1 Radi 0 48sPrometheus
Sljedeća dva komponenta lako se instaliraju putem Helma iz chart repozitorija.
Pronalaženje Prometheus, kreiranje namespacea i instalacija u njega:
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"}Prema zadanim postavkama, Prometheus naručuje 2 diska: jedan za podatke samog Prometheusa i jedan za podatke AlertManagera. Budući da u klasteru nije kreirana storage class, diskovi se neće naručiti i podovi se neće pokrenuti. Za bare metal instalacije Kubernetes obično koristimo Ceph rbd, no u slučaju Raspberry Pi-a to je očigledno pretjerano.
Stoga ćemo kreirati jednostavno lokalno spremište na hostpath. Manifesti PV (persistent volume) za prometheus-server i prometheus-alertmanager spojeni su u datoteci prometheus-pv.yaml u . Direktorij za PV potrebno je unaprijed stvoriti na disku onog čvora kojem želimo pridružiti Prometheus: u primjeru je naveden nodeAffinity prema hostnameu pi-worker i na njemu su kreirane direktorije /data/localstorage/prometheus-server i /data/localstorage/prometheus-alertmanager.
Preuzimamo (kloniramo) manifest i dodajemo u Kubernetes:
kubectl create -f prometheus-pv.yamlU ovoj fazi prvi put sam se susreo s problemom ARM arhitekture. Kube-state-metrics, koji se prema zadanim postavkama instalira u chartu Prometheus, odbio je pokretanje. Izdao je grešku:
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"Naime, za kube-state-metrics koristi se slika projekta CoreOS, koja nije pravljena 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.7Morao sam malo pretraživati i pronaći, na primjer, . Da bismo je iskoristili, nadogradit ćemo izdanje, navodeći koju sliku koristiti 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.6Provjeravamo je li sve pokrenuto:
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 i cert-manager
Za grafikone i nadzorne ploče instaliramo Grafana:
helm install grafana --namespace monitoring stable/grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"}Na kraju će nam pokazati kako dobiti lozinku za pristup:
kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echoZa naručivanje certifikata postavićemo cert-manager. Za njegovu instalaciju obratimo se , koja nudi odgovarajuće naredbe 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=trueZa samopotpisane certifikate u kućnoj upotrebi toga je sasvim dovoljno. Ako je potrebno dobiti isti Let’s Encrypt, potrebno je postaviti i cluster issuer. Detalje o tome možete pronaći u našem članku "».
Osobno sam se odlučio za opciju iz , smatrajući da će staging verzija LE biti dovoljna. Promijenimo u primjeru e-mail, spremimo u datoteku i dodamo u klaster ():
kubectl create -f cert-manager-cluster-issuer.yamlSada možemo naručiti certifikat, na primjer, za Grafanu. Za to će vam trebati domena i pristup klasteru izvana. Domenu imam, a promet sam postavio prosljeđivanjem portova 80 i 443 na kućnom usmjerivaču prema službi ingress-controller:
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 23dPort 80 se u ovom slučaju prosljeđuje na 31303, a 443 na 30498. (Portovi se nasumično generiraju, tako da će kod vas biti drugi.)
Evo primjer certifikata ():
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-stagingDodajemo ga u klaster:
kubectl create -f cert-manager-grafana-certificate.yamlNakon toga pojavit će se resurs Ingress, kroz koji će se vršiti validacija od strane Let’s Encrypt:
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 Nakon što se validacija završi, vidjet ćemo da je resurs certificate spreman, a u gore navedenom tajnom grafana-tls je certifikat i ključ. Možete odmah provjeriti tko je izdao 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 X1Vratimo se na Grafanu. Trebat će nam malo prilagoditi njezin Helm release, mijenjajući postavke za TLS u skladu s kreiranim certifikatom.
Za to preuzimamo chart, uređujemo i ažuriramo iz lokalne direktorije:
helm pull --untar stable/grafana Uređujemo u datoteci grafana/values.yaml TLS parametri:
tls:
- secretName: grafana-tls
hosts:
- grafana.home.pi Ovdje također možemo odmah postaviti instalirani Prometheus kao datasource:
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus-server:80
access: proxy
isDefault: trueSada iz lokalne direktorije ažuriramo Grafana chart:
helm upgrade grafana --namespace monitoring ./grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"} Provjeravamo da li je u Ingress grafana dodana 443 port i postoji pristup putem HTTPS-a:
root@pi-control:~# kubectl -n monitoring get ing grafana
IME KLASA DOMENE ADRESA PORTOVI STARENJE
grafana <none> 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; includeSubDomainsZa demonstraciju Grafane u akciji možete preuzeti i dodati . Ovako to izgleda:

Također preporučujem dodavanje dashboarda za node exporter: detaljno će prikazati što se događa s 'mališima' (opterećenje CPU-a, korištenje memorije, mreže, diska itd.).
Nakon toga smatram da klaster može primati i pokretati aplikacije!
Napomena o izradi
Za izradu aplikacija za ARM arhitekturu postoji najmanje dvije opcije. Prva je izrada na ARM uređaju. Međutim, gledajući trenutnu iskorištenost dva Raspberry Pi, shvatio sam da ne bi izdržali ni izradu. Stoga sam naručio novu Raspberry Pi 4 (jača je i ima čak 4 GB memorije) — planiram raditi na njoj.
Druga opcija je izrada multi-arhitekturnog Docker imidža na moćnijem računalu. Za to postoji . Ako je aplikacija napisanja na kompiliranom jeziku, bit će potrebna križna kompilacija za ARM. Neću opisivati sve postavke za takav put, jer bi to zahtijevalo poseban članak. Implementacijom ovog pristupa može se postići "univerzalne" slike: Docker, pokrenut na ARM mašini, automatski će preuzimati odgovarajuću arhitekturu slike.
Zaključak
Provedeni eksperiment nadmašio je moja očekivanja: [najmanje] "vanilasti" Kubernetes s potrebnom bazom dobro se ponaša na ARM-u, a prilikom njegove konfiguracije pojavila su se samo neka sitna pitanja.
Sami Raspberry Pi 3B+ drže opterećenje na CPU-u, no njihove SD kartice su očigledna uska grla. Kolege su sugerirale da u nekim verzijama postoji mogućnost pokretanja s USB-a, gdje se može priključiti SSD: tada će situacija vjerojatno biti bolja.
Evo primjera opterećenja CPU-a prilikom instalacije Grafane:

Za eksperimentiranje i "za probati", smatram da Kubernetes klaster na "malinama" mnogo bolje prenosi osjećaje od korištenja nego isti Minikube, jer svi dijelovi klastera se instaliraju i rade "profesionalno".
U perspektivi postoji ideja dodati cijeli CI/CD ciklus klasteru, potpuno realiziran na Raspberry Pi. Također, bio bih zahvalan ako netko podijeli svoje iskustvo po pitanju podešavanja K8s na AWS Graviton-ima.
P.S. Da, "produkcija" može biti bliža nego što sam mislio:

P.S.
Pročitajte i na našem blogu:
- «».
Izvor: habr.com
