
For nylig meddelte et kendt selskab, at de vil overføre deres serie af bærbare computere til ARM-arkitekturen. Da jeg hørte denne nyhed, kom jeg i tanker om, at jeg under endnu en gennemgang af priserne på EC2 i AWS lagde mærke til Gravitons med en meget attraktiv pris. Problemet var selvfølgelig, at det er ARM. Dengang havde jeg ikke engang overvejet, at ARM er noget alvorligt...
For mig har denne arkitektur altid været forbeholdt mobile enheder og andre IoT-sager. "Rigtige" servere på ARM — det virker lidt usædvanligt, nærmest vildt... Men en ny tanke fik fat i mig, så en weekend besluttede jeg mig for at undersøge, hvad man overhovedet kan køre på ARM i dag. Og derfor besluttede jeg mig for at starte med noget, jeg kender godt — et Kubernetes-kluster. Desuden ikke bare et hvilket som helst "kluster", men helt professionelt, så det skulle være så tæt på, som jeg er vant til at se det i produktionen.
Jeg forestillede mig, at klustret skulle være tilgængeligt fra internettet, der skulle køre en webapplikation, og der skulle være mindst overvågning. For at realisere denne idé vil jeg have brug for et par (eller flere) Raspberry Pi, ikke lavere end model 3B+. Et muligt eksperimenteringssted kunne også være AWS, men jeg var specifikt interesseret i "hindbærne" (som alligevel bare stod stille). Så vi vil opsætte et Kubernetes-kluster på dem med Ingress, Prometheus og Grafana.
Forberedelse af "hindbærne"
Installation af OS og SSH
Jeg har ikke gjort mig for mange anstrengelser med valget af OS til installationen: jeg tog bare den nyeste Raspberry Pi OS Lite fra . Her er der også tilgængelig , som skal følges på alle noder i det fremtidige kluster. Derefter skal følgende handlinger udføres (også på alle noder).
Når jeg har tilsluttet skærm og tastatur, er det nødvendigt at konfigurere netværket og SSH på forhånd:
- For at klustret kan fungere, skal der være en statisk IP-adresse på masteren, mens det er valgfrit på de arbejdstagende noder. Jeg foretrak statiske adresser overalt af hensyn til nemmere konfiguration.
- Den statiske adresse kan konfigureres i OS (i filen
/etc/dhcpcd.confer der et passende eksempel) eller ved at fastlåse lease i DHCP-serveren på den anvendte (i mit tilfælde — hjemme) router. - ssh-serveren aktiveres blot i raspi-config (interfacing options → ssh).
Efter dette kan du logge ind via SSH (standard login — pi, og adgangskoden — raspberry eller den, du har ændret til) og fortsætte med konfigurationen.
Andre indstillinger
- Lad os indstille værtsnavnet. I mit eksempel bruges
pi-contrologpi-worker. - Lad os tjekke, at filsystemet er udvidet til hele disken (
df -h /). Om nødvendigt kan det udvides ved hjælp af raspi-config. - Vi ændrer standardbrugerens adgangskode i raspi-config.
- Vi deaktiverer swap-filen (det er et krav fra Kubernetes; hvis du er interesseret i detaljer om dette, se ):
dphys-swapfile swapoff systemctl disable dphys-swapfile - Vi opdaterer pakkerne til de nyeste versioner:
apt-get update && apt-get dist-upgrade -y - Vi installerer Docker og ekstra pakker:
apt-get install -y docker docker.io apt-transport-https curl bridge-utils iptables-persistentVed installationen
iptables-persistentskal bruges til at gemme iptables-indstillingerne for ipv4, og i filen/etc/iptables/rules.v4— tilføje regler til kædenFORWARD, sådan her:# 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 - Det er kun tilbage at genstarte.
Nu er alt klar til installation af Kubernetes-klusteret.
Installation af Kubernetes
På dette stadium har jeg bevidst udsat alle mine og vores virksomheders erfaringer med automatisering af installationen og konfigurationen af K8s-klusteret. I stedet vil vi bruge den officielle dokumentation fra (let suppleret med kommentarer og forkortelser).
Lad os tilføje Kubernetes-repositoriet:
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 updateDernæst foreslår dokumentationen at installere CRI (container runtime interface). Da Docker allerede er installeret, går vi videre og installer støttekomponenterne:
sudo apt-get install -y kubelet kubeadm kubectl kubernetes-cni Ved installationen af støttekomponenterne tilføjede jeg straks kubernetes-cni, som er nødvendig for at klusteret kan fungere. Her er et vigtigt punkt: pakken kubernetes-cni af en eller anden grund ikke opretter standardmappen til CNI-interfaceindstillinger, så jeg måtte oprette den manuelt:
mkdir -p /etc/cni/net.dFor at netværks-backenden, som jeg vil tale om nedenfor, skal fungere, er det nødvendigt at installere en plugin til CNI. Jeg valgte den velkendte plugin portmap (se hele listen i ):
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/ ./portmapKubernetes konfiguration
Noden med kontrolplanen
Installation af selve klusteret er ret enkel. For at fremskynde denne proces og kontrollere, at Kubernetes-billederne er tilgængelige, kan vi først udføre:
kubeadm config images pullNu gennemfører vi selve installationen — vi initialiserer kontrolplanen for klusteret:
kubeadm init --pod-network-cidr=10.1.0.0/16 --service-cidr=10.2.0.0/16 --upload-certsBemærk, at subnetværk til tjenester og pods ikke må overlappe hinanden eller eksisterende netværk.
Til sidst viser systemet en besked om, at alt er i orden, og giver samtidig viden om, hvordan man tilslutter arbejdsnoder til kontrolplanet:
Dit Kubernetes kontrolplan er blevet initialiseret med succes! For at begynde at bruge dit cluster skal du køre følgende som almindelig bruger: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config Du skal nu implementere et pod-netværk til clustret. Kør "kubectl apply -f [podnetwork].yaml" med et af de valgmuligheder, der er nævnt på: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Du kan nu tilslutte et vilkårligt antal kontrolplanenoder ved at køre følgende kommando på hver som root: kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050 --contrl-plane --certificate-key 72a3c0a14c627d6d7fdade1f4c8d7a41b0fac31b1faf0d8fdf9678d74d7d2403. Bemærk venligst, at certifikatnøglen giver adgang til følsomme data i clustret, skal opbevares hemmeligt! Som et sikkerhedstiltag vil uploadede certifikater blive slettet om to timer; hvis nødvendigt kan du bruge "kubeadm init phase upload-certs --upload-certs" for at genindlæse certifikaterne bagefter. Derefter kan du tilslutte et vilkårligt antal arbejdsnoder ved at køre følgende på hver som root: kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050Lad os følge anbefalingerne til at tilføje konfigurationen for brugeren. Og jeg anbefaler også at tilføje autoudfyldelse for kubectl:
kubectl completion bash > $HOME/.kube/completion.bash.inc printf "
# Kubectl shell completion
source '$HOME/.kube/completion.bash.inc'
" >> $HOME/.bash_profile source $HOME/.bash_profilePå dette tidspunkt kan man allerede se den første node i clustret (dog er den endnu ikke klar):
root@pi-control:~# kubectl get no NAME STATUS ROLES AGE VERSION pi-control NotReady master 29s v1.18.6Netværkskonfiguration
Derefter, som nævnt i beskeden efter installationen, skal der installeres netværk i clustret. Dokumentationen tilbyder valg mellem Calico, Cilium, contiv-vpp, Kube-router og Weave Net… Her har jeg valgt et mere kendt og forståeligt alternativ: i mode host-gw (læs mere om de tilgængelige backends i ).
At installere det i clustret er ganske enkelt. Først downloader vi manifesterne:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml Derefter ændrer vi indstillingerne fra type vxlan og få en fungerende kommando. host-gw:
sed -i 's/vxlan/host-gw/' kube-flannel.yml… og podnetsubnettet — fra standardværdien til den, der blev angivet ved initialiseringen af clustret:
sed -i 's#10.244.0.0/16#10.1.0.0/16#' kube-flannel.ymlEfter dette opretter vi ressourcerne:
kubectl create -f kube-flannel.yml Færdig! Efter lidt tid vil den første K8s-node skifte til status Klar:
NAME STATUS ROLES AGE VERSION pi-control Ready master 2m v1.18.6Tilføjelse af en arbejdsnode
Nu kan du tilføje en worker. For at gøre dette skal du — efter installationen af Kubernetes i henhold til det ovenfor beskrevne scenarie — blot udføre den tidligere modtagne kommando:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4
--discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050På dette punkt kan vi betragte klyngen som klar:
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.6Jeg havde kun to Raspberry Pi ved hånden, så jeg ville ikke give en af dem kun til kontrolplanet. Derfor fjernede jeg den automatisk tildelte taint fra noden pi-control ved at køre:
root@pi-control:~# kubectl edit node pi-control… og fjernede linjerne:
- effect: NoSchedule
key: node-role.kubernetes.io/masterUdfyldning af klyngen med det nødvendige minimum
I første omgang har vi brug for Helm. Selvfølgelig kan man gøre alt uden det, men Helm gør det muligt at konfigurere nogle komponenter uden at redigere filer. Og i virkeligheden er det bare en binær fil, der "ikke kræver meget".
Så lad os gå til i sektionen docs/installation og udføre kommandoen derfra:
curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bashDerefter tilføjer vi chart-repositoriet:
helm repo add stable https://kubernetes-charts.storage.googleapis.com/Nu installerer vi infrastrukturkomponenterne i henhold til planen:
- Ingress controller;
- Prometheus;
- Grafana;
- cert-manager.
Ingress controller
Den første komponent — Ingress controller — installeres temmelig enkelt og er klar til brug "out of the box". For at gøre dette skal du blot gå til og udføre installationskommandoen derfra:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yamlMen på dette tidspunkt begyndte "hindbæret" at knirke og stødte på diskens IOPS. Problemet er, at der med Ingress-controlleren installeres en stor mængde ressourcer, mange API-anmodninger kører, og mange data skrives til etcd. Kort sagt, enten er det 10. klasses hukommelseskort ikke særlig effektivt, eller SD-kortet er generelt utilstrækkeligt til en sådan belastning. Alligevel blev alt startet op efter cirka 5 minutter.
Der blev oprettet et namespace, og der dukkede en controller op i det med alt, hvad den havde brug for:
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
De følgende to komponenter er ret nemme at installere via Helm fra chart repo.
Find Prometheus, vi opretter et namespace og installerer det i det:
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"}Som standard bestiller Prometheus 2 diske: til selve Prometheus-data og til AlertManager-data. Da der ikke er oprettet en storage class i klyngen, vil diske ikke blive bestilt, og pod'erne vil ikke starte. For bare metal-installationer af Kubernetes bruger vi typisk Ceph rbd, men i tilfælde af Raspberry Pi er dette åbenlyst overkill.
Derfor vil vi oprette en simpel lokal storage på hostpath. Manifesterne PV (persistent volume) for prometheus-server og prometheus-alertmanager er samlet i filen prometheus-pv.yaml i . Biblioteket til PV skal oprettes på forhånd på disken af den node, vi ønsker at binde Prometheus til: i eksemplet er der angivet nodeAffinity efter hostname pi-worker og der er oprettet biblioteker /data/localstorage/prometheus-server og /data/localstorage/prometheus-alertmanager.
Downloader (kloner) manifestet og tilføjer det til Kubernetes:
kubectl create -f prometheus-pv.yamlPå dette stadium stødte jeg for første gang på problematikken med ARM-arkitektur. Kube-state-metrics, som som standard installeres i Prometheus-chartet, nægtede at starte. Det gav en fejl:
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"Problemet er, at kube-state-metrics bruger et billede fra CoreOS-projektet, som ikke bygges til 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.7Jeg var nødt til at google lidt og finde for eksempel . For at bruge det vil vi opdatere udgivelsen og angive, hvilket billede der skal bruges til 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.6Lad os kontrollere, at alt er startet:
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 og cert-manager
Til grafer og dashboards installerer vi Grafana:
helm install grafana --namespace monitoring stable/grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"}Til sidst vil vi vise, hvordan man får adgangskoden:
kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echoFor at bestille certifikater, lad os installere cert-manager. For installationen skal vi kontakte , som tilbyder de relevante kommandoer til 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=trueTil selvsignerede certifikater til hjemmebrug er dette helt tilstrækkeligt. Hvis man derimod ønsker at få samme Let’s Encrypt, er det nødvendigt at konfigurere en cluster issuer. Detaljer om dette kan findes i vores artikel «».
Jeg valgte selv varianten fra , da jeg mente, at staging-varianten LE ville være tilstrækkelig. Vi ændrer e-mail i eksemplet, gemmer det i en fil og tilføjer det til klyngen ():
kubectl create -f cert-manager-cluster-issuer.yamlNu kan vi bestille et certifikat, for eksempel til Grafana. For dette kræves der et domæne og adgang til klyngen udefra. Jeg har et domæne, og jeg har konfigureret portforwarding af porte 80 og 443 på min hjemme-router i overensstemmelse med den oprettede ingress-controller-tjeneste:
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 videresendes i dette tilfælde til 31303, og 443 til 30498. (Portene genereres tilfældigt, så jeres vil være andre.)
Her er et eksempel på et certifikat ():
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-stagingVi tilføjer det til klyngen:
kubectl create -f cert-manager-grafana-certificate.yamlDerefter vil der blive oprettet en Ingress-ressource, gennem hvilken validering vil finde sted af 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 Når valideringen er gennemført, vil vi se, at ressourcen certificate er klar, og i den nævnte hemmelighed grafana-tls er certifikatet og nøglen. Man kan straks kontrollere, hvem der har udstedt certifikatet:
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 X1Lad os vende tilbage til Grafana. Vi skal lave et par justeringer til dens Helm-udgivelse ved at ændre indstillingerne for TLS i overensstemmelse med det oprettede certifikat.
For at gøre dette downloader vi chartet, redigerer det og opdaterer fra den lokale mappe:
helm pull --untar stable/grafana Vi redigerer i filen grafana/values.yaml TLS-parametre:
tls:
- secretName: grafana-tls
hosts:
- grafana.home.pi Her kan vi også konfigurere den installerede Prometheus som datasource:
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus-server:80
access: proxy
isDefault: trueNu opdaterer vi Grafana-chartet fra den lokale mappe:
helm upgrade grafana --namespace monitoring ./grafana --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"} Vi kontrollerer, at Ingress grafana har fået tilføjet port 443 og har adgang over 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; includeSubDomainsFor at demonstrere Grafana i aktion kan man downloade og tilføje . Sådan ser det ud:

Jeg anbefaler også at tilføje et dashboard til node exporter: det vil detaljeret vise, hvad der sker med "hindbærerne" (CPU-belastning, hukommelsesforbrug, netværk, disk osv.).
Efter dette mener jeg, at klusteret er klar til at tage imod og køre applikationer!
Bemærkning om opbygning
Der er mindst to muligheder for at bygge applikationer til ARM-arkitektur. For det første kan man bygge på en ARM-enhed. Men efter at have set på den nuværende udnyttelse af de to Raspberry Pi, indså jeg, at de ikke engang vil kunne klare bygningen. Derfor har jeg bestilt en ny Raspberry Pi 4 (den er kraftigere og har hele 4 GB hukommelse) — jeg planlægger at bygge på den.
Den anden mulighed er at bygge et multi-arkitekturs Docker-billede på en kraftigere maskine. Til dette findes der . Hvis applikationen er skrevet i et kompilérbart sprog, vil der være behov for kryds-kompilering til ARM. Jeg vil ikke beskrive alle indstillinger for denne proces, da det ville kræve en særskilt artikel. Ved at implementere denne tilgang kan man opnå "universelle" billeder: Docker, der kører på en ARM-maskine, vil automatisk downloade det passende arkitektur-billede.
Konklusion
Det udførte eksperiment overgik alle mine forventninger: [mindst] "vanilla" Kubernetes med den nødvendige database fungerer ganske godt på ARM, og jeg stødte kun på et par nuancer under konfigurationen.
Raspberry Pi 3B+ kan håndtere CPU-belastningen, men deres SD-kort er et klart flaskehals. Mine kolleger nævnte, at nogle versioner har mulighed for at starte fra USB, hvor man kan tilslutte SSD: så bliver situationen sandsynligvis bedre.
Her er et eksempel på CPU-belastning under installationen af Grafana:

Til eksperimenter og "for at prøve", synes jeg, at et Kubernetes-kluster på "Raspberry Pi" giver en meget bedre oplevelse end den samme Minikube, fordi alle klusterkomponenterne både installeres og fungerer "professionelt".
Der er en idé om at tilføje hele CI/CD-cyklussen til klusteret, helt implementeret på Raspberry Pi. Jeg vil også være glad, hvis nogen deler deres erfaring med opsætning af K8s på AWS Graviton.
P.S. Ja, "produktion" kan være tættere på, end jeg troede:

P.P.S.
Læs også på vores blog:
- «».
Kilde: habr.com
