Kubernetes bedste praksis

Jeg chatte med en tidligere Googler SRE, som (korrekt) påpegede, at Kubernetes udvikler sig meget hurtigt (for hurtigt til at opretholde valuta), bruger (mange) nye koncepter, og at der er (for) mange måder at løse det samme problem.

Meget af dette er sandt og ikke nødvendigvis en dårlig ting eller nødvendigvis anderledes end nogen anden teknologi. Hvor jeg er uenig, er, at disse faktorer har afskrækket hans vedtagelse af Kubernetes. Jeg vil opfordre dig til at dykke i. Kubernetes er den succes, det er * trods * disse (rimelige) bekymringer, fordi det er så meget meget godt.

I dette indlæg vil jeg give dig nogle rudimentære bedste fremgangsmåder, som jeg håber, vil hjælpe dig med at få fat i denne teknologi ved dens containere og dykke ned.

I ingen særlig rækkefølge:

  1. Lad en anden gøre arbejde!

Brug en Kubernetes-tjeneste som Kubernetes Engine. Medmindre du er intellektuelt nysgerrig, kan en udvikler, der arbejder på Kubernetes, eller du er en platformudbyder, der har kunder, der beder om en Kubernetes-tjenester, gemme besværet og bruge en Kubernetes-service. Byggede du dit eget hjem og din bil? Eller kan du lide at sove et sted, som ulven ikke kan sprænge og køre i en bil, der pålideligt fører dig fra A-til-B?

Så hvis du har læst nogle af mine andre indlæg, anbefaler jeg også at evaluere regionale klynger, og så ser du på noget i retning af:

gcloud beta-containerklynger opretter $ {CLUSTER} ...
gcloud beta-containerklynger få-legitimationsoplysninger $ {CLUSTER} ...

Og så er du klar til at gå med:

kubectl gælder - filnavn = marvels.yaml

2. Prøv at tænke “Kubernetes”

Dette * kan * være mere en udfordring med Kubernetes Engine end på andre platforme, men på Google Cloud Platform er du tvunget til at opretholde en forståelse af staten for dine ressourcer i Kubernetes (f.eks. Noder, Ingresser) og på samme tid , de underliggende ressourcer i Compute Engine (f.eks. VM'er, HTTP / S Load Balancers). Dette partikelbølgedualitetsproblem er uheldigt. Tak til Dale H. for først at have formuleret dette for mig.

Hvor det er muligt, skal du prøve at holde sig til tankerne med hensyn til Kubernetes 'ressourcer og se bort fra de underliggende GCE-ressourcer. Da jeg nu har brugt mere end et år på at forspænde mit arbejde til Kubernetes, er det blevet lettere at tænke rent udtrykt som ”et antal” pods, der er eksponeret af Services (og Ingresses).

3. Navneområder, Navneområder, Navneområder

Opdatering: Tak til Michael Hausenblas for at have uddannet mig til den bedste praksis med at * ikke * henvise til navneområder inden for Kubernetes YAML-filer. Mens du altid skal bruge navneområder, giver specificering af disse, når du anvender filen, større fleksibilitet og muligheden for at bruge de samme YAML-filer imod, f.eks. forskellige landskaber. Se Michaels artikel her.

Mike Altarace og jeg bloggerede måner siden om navneområder i Kubernetes, og hvor du skulle bruge dem. Siden da ignorerede jeg temmelig mine egne råd, da jeg tænkte, at mine anvendelsessager var så små, at brugen af ​​navneområder ville blive overspændt. Jeg tog fejl. Brug altid navneområder.

Da containere skal processer, er navneområdet Kubernetes-projekter. Bortset fra den sikkerhedsgrænse, som navneområder overfører, er de en fremragende måde at opdele dit arbejde på, og de giver en fremragende måde at nulstille eller slette:

kubectl slet navneområde / $ WORKING_PROJECT

Den eneste ulempe er, at når du bruger ikke-standardnavnet, skal du specificere dit arbejdsnavneområde - navnspace = $ WORKING_PROJECT på kubectl-kommandoer, som efter min mening kan være en god beskyttelsespraksis. Du kan dog altid - alle navneområder eller indstille et andet navneområde som din standard (link).

4. For mange måder at løse et problem på

Dette er en nedslående bekymring. Jeg synes, det er sandsynligvis usandt, men fraværende god vejledning og bedste praksis, ser det ud til, at der er for mange lignende måder at løse det samme problem på. Jeg har et almindeligt mønster, som jeg bruger, som jeg sammenfatter her for at tilskynde til diskussion:

  • YAML-filer er viden inden for kold opbevaring (se nr. 5)
  • Dine containere skal gøre en ting godt (se "mistillid")
  • Implementér altid implementeringer (se nr. 6)
  • Hvis du vil have L7 alias HTTP / S Load-Balancing, brug Ingress (se nr. 7 - ha!)
  • Administrer legitimationsoplysninger sikkert ved hjælp af Secrets (link)

5. Bias til kubectl gælder - filnavn over alternativer

Det er let at få et hurtigt hit med kubectl create namespace / $ {WORKING_DIR}, men efter flere sådanne kommandoer kan du undre dig over, hvordan du nåede den aktuelle tilstand og - endnu vigtigere - hvordan du genskaber denne tilstand. Jeg opfordrer dig til at oprette YAML-filer til at beskrive dine ressourcer snarere end den ækvivalente kub ectl create-kommando.

Jeg opfordrer dig til at blive fortrolig med * fremragende * Kubernetes API-dokumentation (link, link og 1.10), som er udtømmende, nøjagtige og lette at navigere (måske den perfekte dokumentation !?). Men selv med dette magtfulde værktøj er det undertiden lidt udfordrende at tage en kubectl-kommando, der fungerer for dig og konvertere den til YAML. Det er ikke:

kubectl get distribution / $ {MY_DEPLOYMENT} --output = yaml
kubectl get service / $ {MY_SERVICE} --output = yaml
kubectl få noget / $ {MY_ANYTHING} --output = yaml

Rør resultaterne til en fil, hvis du vil, men brug disse som grundlag for ækvivalent (!) YAML-fil. Du skal droppe alle forekomstreferencer.

Når du har lavet mesterværk.yaml, opfordrer jeg dig til altid at ansøge om at udføre den oprindelige oprettelse, ansøge om at udføre eventuelle efterfølgende opdateringer og, hvis du skal slette. Det er det!

kubectl Apply - filnavn = mesterværk.yaml
kubectl delete - filnavn = masterpiece.yaml

Mindre indsigt: Du behøver ikke at trække YAML-filer lokale for at kunne implementere. Du kan også angive kubectl-anvendelse - filnavn med URL'er, og så længe afhængige filer er lokale referencer, fungerer installationen.

Mindre indsigt: det eneste sted, jeg ser dette bruges, er i Kubernetes-land, men det er en legitim praksis, du kan kombinere flere YAML-filer i en YAML-fil med --- og ... filseparatorer. Så i stedet for et navneområde YAML, en implementering YAML og en service YAML, har du muligvis en mega-YAML, der konsoliderer alle tre filer til en.

Dette er gyldigt YAML (kopier og indsæt det i f.eks. YAML Lint). Det er * ugyldigt * Kubernetes spec | YAML, fordi hver spec er ufuldstændig, men hvis hver blev afsluttet, er dette helt fint YAML og en god måde at holde ressourcer tilknyttet.

Se #B (Xsonnet) for en kritik.

6. Brug distributioner

Der er en masse magt i implementeringer, tilstrækkelig min vejledning til at sige: brug implementeringer hele tiden, hver gang. Selv når du implementerer din første single podnginx. Implementeringer er "First Class" -rejser til prisen for Coach, du kan falde ind i rullende implementeringer, du laver en fejl, anvender igen, og Kubernetes tager sig af at dræbe de frække bælter og erstatte dem med velopdragne.

7. LoadBalancer og Ingress

Disse skaber forvirring. I mit sind (og jeg kan have forkert), når jeg opretter tjenester ved hjælp af --type = LoadBalancer, vil jeg | få et netværk LB. Hvis jeg vil have HTTP / S (niveau 7) Load-Balancing, skal jeg oprette en Ingress. Ingress er en forvirrende Kubernetes-ressource. Det er tilstrækkeligt at sige, L7 == Ingress (og masser af konfigurationsstyrke som et resultat).

Kubernetes Engine manifesterer Ingress-ressourcer som GCE HTTP / S Load-Balancers. Christopher Grant gør et meget godt stykke arbejde med at afmystificere Ingress i sine stillinger (her og her).

8. NodePorts

Jeg har ikke (nogensinde?) Direkte oprettet et ClusterIP. Jeg har gjort ting over for Kubernetes, som resulterede i, at tjenester blev eksponeret af ClusterIPs. Oftest (!) Oprettede jeg NodePorts, eller jeg laver ting (f.eks. Oprette Ingress-ressourcer), der bruger NodePorts.

NodePorts er forbundet med Kubernetes-noder, og de er porte. Den kraftfulde facilitet, de leverer, er, at * hver * knude i klyngen (eller er det denne NodePool? [[TODO]]) udsætter den samme service på den samme (node) port.

Hvis jeg opretter en service, der er eksponeret på NodePort X, kan jeg være sikker på, at hvis jeg får adgang til denne port på * en hvilken som helst * knude i klyngen, får jeg adgang til tjenesten. Dette danner grundlaget for Kubernetes 'belastningsbalanceringsfunktioner, fordi klyngen er i stand til at rute indgående anmodninger om tjenesten til denne port på enhver knude.

Google Cloud SDK (også kaldet gcloud) inkluderer en ssh-klient, der gør det trivielt at oprette forbindelse til Compute Engine VMs (som du husker Kubernetes Cluster Nodes). ssh-klient inkluderer en port-videresendelse kapacitet. Så hvis vi ønsker at oprette forbindelse til en Kubernetes-tjeneste, og vi kan slå op på tjenestens NodePort, så kan vi trivialt (!) Portvideresende til denne tjeneste ved portvideresendelse (ved hjælp af gcloud eller en hvilken som helst ssh-klient) til porten på en hvilken som helst Node.

Følgende eksempel bruger kubectl til at gribe den node node i klyngen. Kubernetes Engine Node-navn er det samme som Compute Engine VM-navnet. Givet en service kaldet $ {MY_SERVICE} i et navneområde kaldet $ {MY_NAMESPACE}, bestemmer vi tjenestens NodePort. Derefter skifter vi til gcloud og bruger dets indbyggede ssh til port-frem (ved hjælp af --ssh-flag = "- L XXXX: localhost: XXXX).

NODE_HOST = $ (\
  kubectl få noder \
  --output = jsonpath = "{. elementer [0] .metadata.name}")
NODE_PORT = $ (\
  kubectl get services / $ {MY_SERVICE} \
  --namespace = $ {MY_NAMESPACE} \
  --output = jsonpath = "{. spec.ports [0] .nodePort}")
ekko $ {NODE_PORT}
gcloud beregne ssh $ {NODE_HOST} \
--ssh-flag = "- L $ {NODE_PORT}: localhost: $ {NODE_PORT}" \
--project = $ {YOUR_PROJECT}

Hvad er så magtfuldt ved dette? Nu får du muligvis adgang til tjenesten, som om den var lokal og uden at skulle slå hullerne i en firewall.

NodePorts er højnumrede porte (~ 30.000–32.767).

9. Hacking af kubectl-brug JSON

Googles Cloud SDK (alias gcloud) er virkelig fremragende, men kubectl (Kubernetes CLI) er mere bedre (sic). En kraftfuld funktion er formatering og filtrering af output. Dette tillader ikke-kodende (ikke-API-krænkende) måder til at udvide scripts og andre værktøjer med information fra Kubernetes-klynger.

Alle Kubernetes ressurstilstand er tilgængelig gennem f.eks. kubectl get (efter min erfaring mere nyttigt til dette formål end kubectl beskriver) kommandoer. Derefter er alt, hvad der er tilbage, at finde nålen i det, der kan være en høstak af JSON.

Tricket er at:

kubectl get [resource] / [resource-name] --output = JSON

Og derefter øjeeplet resultatet for at begynde at opbygge en forespørgselsstreng:

kubectl get [resource] / [resource-name] --output = jsonpath = ". elementer [*]"

og iterativt forfine det nedsatte resultat, indtil du har det eller de elementer, du søger. Her er et eksempel, der skal fungere med enhver klynge:

kubectl få noder --output = json
kubectl få noder --output = jsonpath = "{. elementer [*]}
kubectl få noder --output = jsonpath = "{. elementer [0]}
kubectl få noder --output = jsonpath = "{. elementer [0] .metadata.name}

Endelig er der et anstændigt argument (og en tælling i * nix) for at lære et JSON-parsingværktøj og anvende dette værktøj til alle JSON-parsingbehov. Er der i dette tilfælde nogen rimelig konkurrent til jq? Jeg formoder ikke.

Plus jq har en fremragende legeplads (jqplay.org).

A. Brug etiketter

Det har været længe, ​​men alle slags softwaretjenester understøtter nu konceptet med vilkårlig mærkning af ressourcer (normalt nøgleværdipar). Årsagen til at dette er magtfuldt er, at denne metadata giver en åben, helt brugerdefineret måde at forespørge ressourcer på. Kubernetes bruger dette princip iboende; det er en iboende evne og ikke en eftertanke | bolt-on.

En Kubernetes-service udsætter et vilkårligt antal Kubernetes Pods. A Services eksponerer * ikke * pods kaldet “Henry” eller pods, der indeholder et ReplicaSet. I stedet udsætter en tjeneste pods, hvis etiketter opfylder kriterier, der er defineret under tjenestens specifikation, og disse labels er naturligvis brugerdefineret.

NB I ovenstående eksempel bruger vi et navneområde kaldet projekt-x, og dette navneområde-specifikationer vises i navneområdet (når det oprettes), implementeringen til at definere, hvor implementeringen findes, og i tjenesten. Deployment (som kaldes microservice-y) opretter et ReplicaSet (implicit specificeret her; det er hvad Deployments opretter), der opretholder 100 Pods. Hver pod har en etiket-app: publicname-a og indeholder en container kaldet grpc-proxy baseret på et billede kaldet image-grpc-proxy. Tjenesten kaldes service-p. Af afgørende betydning vælger tjenesten (!) Bælg (kun i projekt-x-navneområdet), der har en etiket-app: publicname-a. Tjenesten vælger en hvilken som helst Pod (i projekt-x-navneområdet), der har denne etiket (nøgle: værdi) -par * ikke * kun de Pods, der er oprettet i denne installation. Tjenesten henviser ikke til bælg med deres navn (som er baseret på distributionsnavnet), deres beholdernavn eller beholderbilledsnavnet, kun de etiketter, der er knyttet til boden.

NB Dette er * ikke * en god praksis, men det beviser poenget. Hvis du skulle køre en konfiguration, der ligner ovenstående og derefter separat oprette f.eks. en Pod, der kører Nginx (i projekt-x-navneområdet), og derefter tilføjede du etiketten app: publicname-a til den, den vil hurtigt blive inkorporeret i det sæt Pods, der aggregeres af service-p-tjenesten. Hvis du skulle fjerne etiketten fra nogen af ​​de pods, der blev aggregeret af tjenesten, ville pod'en stoppe med at blive inkluderet.

Denne funktion eksemplificeres ved at rulle opdateringer, hvor implementeringen opretter et nyt ReplicaSet, der indeholder nye Pods til version X ', adskilt fra ReplicaSet og Pods til version X. Tjenesten kan defineres til at afsløre skæringspunktet mellem Pods, der kører på tværs af begge disse versioner, fordi det er ikke defineret i form af ReplicaSets eller specifikke Pods, men af ​​brugerdefinerede etiketter (“vælgere”), der anvendes af dig, når Pods oprettes.

Det er meget magtfuldt!

B. Brug Jsonnet, muligvis Ksonnet

To udfordringer med alle (!?) Strukturerede formater (YAML, JSON, XML, CSV ;-) er selvreferencer og variabler. Når du fremstiller specifikationer for marvellous.yaml til din Kubernetes-installation, vil du let støde på dette problem. Du finder dig selv ved hjælp af bogstaver (f.eks. Til billednavne og fordøjelser) og, selv med de ansete implementeringer, gentage navne og vælgere.

Der er ingen løsning på disse problemer, hvis du begrænser dig til YAML og JSON. Google oprettede delvist Jsonnet for at løse disse problemer. De smarte Heptio-folk har udvidet Jsonnet til Kubernetes med ... Ksonnet.

Begge er templerende sprog, der løser de ovenfor beskrevne problemer (og mere). Jeg opfordrer dig til at overveje Jsonnet. Som med min anbefaling om at overveje at bruge jq, skal du lære Jsonnet en gang og anvende det overalt, hvor du bruger JSON. Ksonnet er specifikt for Kubernetes, og - i min begrænsede (!) Erfaring - fandt jeg, at fordelene ved denne specificitet ikke blev opvejet af læringskurven.

C. YAML eller JSON

Kubernetes behandler YAML og JSON stort set ens. Personligt synes jeg YAML foretrækkes for konfigurationsfiler, som jeg kubectl - anvendelig fordi YAML er mere kortfattet end JSON. Selvom jeg synes YAML er vanskeligere at skrive.

Når det kommer til forståelse af struktur og parsing foretrækker jeg imidlertid - output = JSON og også fordi - output = JSONPATH. Jeg er en stor Golang-fan, men Go-skabeloner er ikke så intuitive, og jeg bruger dem ikke.

mindre indsigt: YAML er et supersæt af JSON (link)… vent! hvad?

D. Downward Dog API og config

"Nedadgående API" for at give det sit korrekte, omend ikke mindre forvirrende navn, er en facilitet i Kubernetes, hvor Pods kan få en fornemmelse af klyngen omkring dem. Jeg antager, at den normale strøm er fra omverdenen op i Pod og dens containere * men * der er tidspunkter, hvor det er nyttigt for en container (!) At få information om dens miljø, f.eks. dens nodenavn | IP, podens navn (mellemrum) | IP.

Nedadgående API-værdier præsenteres for beholderen gennem miljøvariabler. Miljøvariabler bruges (som andre steder) til at give containere konfigur eller anden tilstand. En meget flot konsekvens af at bruge miljøvariabler og implementeringen af ​​Downward API (med et mindre advarsel) er, at containeren forbliver frakoblet fra Kubernetes.

Her er et eksempel fra min kompis - Sal Rashid - der bruger Downward API til at samle Node og Pod-tilstand og præsentere disse for brugeren:

https://github.com/salrashid123/istio_helloworld/blob/master/all-istio.yaml

NB Se afsnittene, der begynder på linjer 76, 80, 84, 88, hvor Pod-navn, navneområde, IP og Nodenavn leveres ved kørsel af Downward API til den beholder, der hedder myapp-container.

Downward API er den eneste, praktiske måde at indsamle disse data til en container. Så det er mere en "eneste praksis" snarere end "bedste praksis".

Når jeg bygger løsninger til Kubernetes i mange af mine indlæg, tester jeg processen lokalt og uden for en container, derefter i en container (angiver miljøvariabler) og derefter på en Kubernetes-klynge. De containermekanismer er ensartede (se nedenfor), selvom en normalt kører på Docker og en på Kubernetes.

I et indlæg, som jeg for nylig skrev om Googles Container-Optimized OS, demonstrerer jeg en container, der kører lokalt under Docker, eksternt under Container-Optimized OS og derefter på Kubernetes.

Her kører lokalt under Docker. Bemærk, hvordan miljøvariablerne (- env) bruges til at give config til gcr.io/${PROJECT}/datastore.

docker run \
- interaktiv \
- smukke \
- public = 127.0.0.1: 8080: 8080 \
--env = GCLOUD_DATASET_ID = $ {PROJECT} \
--env = GOOGLE_APPLICATION_CREDENTIALS = / tmp / $ {ROBOT} .key.json \
- Volume = $ PWD / $ {ROBOT} .key.json: / tmp / $ {ROBOT} .key.json \
gcr.io/${PROJECT}/datastore

Her er det samme resultat, der indpakker implementeringen i oprettelsen af ​​en Containeroptimeret VM. Denne gang tjek værdierne leveret til containeren-env-flag:

gcloud beta beregne forekomster create-with-container $ {INSTANCE} \
--zone = $ {ZONE} \
- image-family = cos-stable \
--image-project = cos-cloud \
--container-image=gcr.io/${PROJECT}/${IMAGE}@${DIGEST} \
--container-restart-policy = altid \
--container-env = \
GCLOUD_DATASET_ID = $ {PROJEKT}, \
GOOGLE_APPLICATION_CREDENTIALS = / tmp / $ {ROBOT} .key.json \
--container-mount-vært-path = \
mount-path = / tmp, \
host-path = / tmp, \
tilstand = rw \
--project = $ {PROJECT}

Og endelig, her er YAML-kodestykket for Deployment for Kubernetes:

beholdere:
      - navn: datastore
        image: gcr.io/${PROJECT}/datastore
        imagePullPolicy: Altid
        volumeMounts:
          - navn: datastore
            mountPath: / var / secrets / google
        env:
        - navn: GOOGLE_APPLICATION_CREDENTIALS
          værdi: /var/secrets/google/datastore.key.json
        - navn: GCLOUD_DATASET_ID
          værdi: $ {PROJECT}
        havne:
        - navn: http
          containerPort: 8080

Jeg finder således anvendelse af miljøvariabler til config til at være temmelig klodset. Der er ingen klar forsætlig binding af specifikke miljøvariabler til specifikke processer, og du er klar over, at de ikke er konfigureret korrekt, når ting går i stykker. Det er let at forestille sig miljøvariabler, der er i konflikt med et ikke-containeret miljø, selvom dette er et mindre problem med containere, fordi vi som ovenfor angiver eksplicit værdier for en bestemt container.

Alt det sagt, ved at bruge miljøvariabler på denne måde er den bedste praksis.

E. Sidecars, og hvorfor Pods ikke altid er synonyme med containere

5 cl cognac
2 cl triple sec
2 cl citronsaft
Forberedelse Hæld alle ingredienser i cocktail shaker fyldt med is. Ryst godt og sil i cocktailglas.

Meget af tiden opretter du Kubernetes Pods, der indeholder enkelt containere, og du vil spekulere på, hvorfor der er al overhead på en Pod, når du kun har brug for en container. Pods er mere analoge med et værtsmiljø, der kan køre mange containere. Der er mange gange, som du så overvejer at køre flere containere i en pod…

... og kun en gang, du skal :-)

Sandsynligvis mere end én, men lad os holde os til kun én gang.

Antimønsteret (ikke gør dette) er at forestille dig din nuværende konfiguration (lad os antage en webserver og en databasebackend) og fastklemme begge sider i en Pod. Dette er * ikke * en god idé *, medmindre * hver web-server-instans skal være uløseligt og for evigt tilsluttet en bestemt database-instans. Dette er usandsynligt.

Hvad der er mere sandsynligt, er, at dine web-server-forekomster skaleres efter den samlede frontend-belastning, og at dine database-instanser skal skaleres (uafhængigt af dette og) baseret på deres samlede evne til at håndtere frontend-belastningen. Når du ser samlet, tænk Tjeneste, og når du tænker Tjeneste, så prøv at forestille sig et vilkårligt antal pods (fordi det betyder noget for din regning, men for de fleste andre formål er det ligegyldigt, hvor mange pods der er behov for, så længe nummeret er helt rigtigt til betjening af arbejdsmængden).

Hvornår skal du overveje flere containere pr. Pod? Den ene gang, hvor dette * altid * giver mening, er, når du ønsker at komplementere, udvide eller berige opførslen af ​​den primære Pod i en container. Lad os se webserver- og databaseeksemplet ovenfra. I dette scenarie er du forhåbentlig nu overbevist om, at du distribuerer to tjenester (og to implementeringer), en til frontend og en til backend.

Det er en god og almindelig praksis at fronte dit web-server-eksempel med en reverse-proxy. Almindeligvis ville dette være enten Nginx eller HAProxy, og det bliver stadig mere almindeligt at bruge Envoy (jeg anbefaler, hvis du ser på fuldmægtige, at overveje Envoy; se #F Istio). En reverse-proxy giver konsistens (vi bruger kun fx Envoy), selvom du bruger forskellige webservere (f.eks. Apache, Tomcat w / Java osv.), Selvom du har en blanding af HTTP, gRPC, Web Sockets osv. Trafik. , selvom du ønsker at dirigere noget trafik til din webserver og nogle trafik til en cache (f.eks. Lakker).

I alle de foregående scenarier ville det være fornuftigt at anvende “sidevogn” -modellen. I denne model har den primære beholder (din web-server) supplerende, komplementære containere (udsending-proxy, lakeret cache osv.). Disse skal være tæt koblet til en bestemt webserverforekomst * og * funktionelt, kombinationen er "enheden".

Det er meget almindeligt at se logning, overvågning, spor og andre infrastrukturelle komponenter leveret som sidevogne også. En motivation her er at adskille bekymringer. At give udviklere et ensartet krav, der producerer kode, der er 'håndterbar' og giver SRE fleksibilitet til at vælge foretrukne værktøjer, vel vidende om, at al kode på tværs af flåden vil logge, udsende målinger, være sporbar, anvende autor konsekvent osv. Dette er et mønster som danner grundlaget for servicemasker (se #F Istio). Dette er den endelige bedste, om end begynnende praksis.

F. Brug Istio

Brug Istio omhyggeligt.

Istio (og andre servicemasker) er relativt nye teknologier, der er født fra virksomheder (inklusive Google), der har kørt containere i massiv skala. Servicemasker placerer trivielt en universel (i Istios tilfælde, udsending) proxy i hver Pod i hver Deployment i hvert navneområde i hver klynge.

Resultatet er et konsistent administrationssubstrat, der tillader løs kobling af styring (vi bruger Stackdriver Trace i dag, men der er plan for at migrere til Jaeger, vi har rullet vores Prometheus-overvågning) og kontroltjenester (vi ved, at alle vores tjenester er sikre, vi dirigerer 10% af trafikken til den kanariske bygning af tjenesterne A, B og C).

Jeg rådgiver "omhyggeligt", fordi disse teknologier er nye, har ru kanter og udvikler sig med et hurtigt klip. Men fordelene (fleksibilitet, smidighed, fremtidssikring) -metoden giver dig sandsynligvis langt større end omkostningerne. Det vigtigste er, at du bruger servicemesh som din model med Kubernetes, selvom du endnu ikke ønsker at anvende en af ​​servicemesh-teknologierne.

Det var alt folkens!