Introduksjon til Docker og Kubernetes

Stort distribuerte systemer laget av flere samarbeidende tjenester blir stadig viktigere. Disse systemene kjøres på klynger av hundrevis, tusenvis eller flere servere. Utvikling, implementering og vedlikehold av disse systemene effektivt og økonomisk er en høy ordre.

Virtualisering og nyere containerisering muliggjør fleksibel deling og styring av ressurser. Docker gjort containerisering populær. Sjekk ut denne Envato Tuts + artikkelen for en flott introduksjon: The Hitchhiker's Guide to Docker and Modulus.

Google har kjørt sin enorme programvare og datasentre på containerisering i årevis og akkumulert a mye av erfaring og knowhow. Kubernetes er et open source-prosjekt av Google som bringer all den kunnskapen til massene.

I denne artikkelen vil jeg utforske Docker kort og dykke dypt inn i Kubernetes. Jeg vil som et løpende eksempel bruke en Python 3 quote REST API-tjeneste. La oss hoppe inn.

The Quote Service

Sitat tjenesten er en REST API som lar deg legge til sitater og få en liste over alle sitater. Det er implementert som en Python 3 webtjeneste ved hjelp av det gode klembiblioteket. Den avslører et enkelt endepunkt som kalles / sitater. Du kan få alle sitater eller legge inn et nytt tilbud. La oss legge til noen anførselstegn:

krølle http: // localhost: 8000 / quote -d "quote = TV er tyggegummi for øynene. ~ Frank Lloyd Wright" krøll http: // localhost: 8000 / quotes -d "quote = Det er bedre å dø på din føtter enn live på knærne. ~ Emiliano Zapata "krøll http: // localhost: 8000 / quotes -d" quote = Vi må være veldig forsiktige når vi gir råd til yngre mennesker: Noen ganger følger de det! ~ Edsger W. Dijkstra "

Hvis du blar til http: // localhost: 8000 / sitater du vil få: ["TV er tyggegummi for øynene." Frank Lloyd Wright "," Det er bedre å dø på føttene enn å leve på knærne. "Emiliano Zapata", "Vi må være veldig forsiktige når vi gir råd til yngre mennesker: noen ganger følger de det! ~ Edsger W. Dijkstra "] Hvis du bare vil se HUGs automatisk generert dokumentasjon, blar du til: http: // localhost: 8000

"404": "API-samtalen du prøvde å lage, var ikke definert. Her er en definisjon av APIen som hjelper deg med å gå :)", "Dokumentasjon": "/ quotes": "GET" "" ["http: // localhost: 8000 / quotes"], "outputs": "content_type": "søknad / json", "format": "JSON (Javascript seriellisert objektnotasjon)", "POST" : "outputs": "content_type": "application / json", "format": "JSON (Javascript Serialized Object Notation)" strengverdi"

Docker Grunnleggende

Jeg vil ikke forklare for mye om Docker og bare bruke den på tilbudstjenesten.

Dockerisering av en Python App

Først trenger vi en Dockerfile. Det utfører følgende trinn:

  1. Basert på det nyeste ubuntu-bildet
  2. Installerer Python 3 og noen andre avhengigheter
  3. Kopier opplysningstjenesten
  4. Installer avhendingsavhengighetene fra requirement.txt-filen
  5. Utsetter 8000-porten
  6. Start tilbudstjenesten via klem

Fra ubuntu: Siste HANDLER Gigi Sayfan "[email protected]" Kjør apt-get update -y RUN apt-install-python3 python3-pip python3-dev build-essential COPY. / quote-service WORKDIR / quote-service RUN pip3 installer -r krav.txt EXPOSE 8000 ENTRYPOINT klem -f app.py

Bygg et bilde

Det neste trinnet er å bygge et Docker-bilde. Dette er så enkelt som:

dockerbygg .

Jeg liker også å merke bilder:

docker-tag 715624b7e22a g1g1 / quote-service

g1g1 er brukernavnet mitt på Docker Hub.

For å bekrefte at bildet ble bygget, ble det skrevet inn:

docker ps --all 

Du bør se det nye bildet:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 715624b7e22a g1g1 / quote-service "/ bin / sh-c 'hug -f a" 4 timer siden Opp 35 minutter 0.0.0.0:8000->8000/tcp agitated_northcutt

Skyve et bilde til Docker Hub

Når du oppretter et bilde, kan du også skyve det til Docker Hub, slik at det kan brukes av andre mennesker (eller deg selv på en annen maskin).

docker push g1g1 / quote-service

Merk at du må opprette en konto på Docker Hub og logge inn lokalt ved å bruke:

docker login

Kjører en dockerisert app

Ok. La oss kjøre sitattjenestebildet og avsløre port 8000 til verten.

docker-run -i -t -p 8000 g1g1 / quote-service

Du bør se: / ################################################# #########. "" ------- ... ".----. : / ::::: -: ---------: - ::::: // ... + :::: ---- ## / - / oo +: - ## - --- :::: // '// :: ------- / oosoo ------- ::: //. ############# .-: ------./++ o / o -.------ :: - ' ## ## ## ## ## ----.-./ + O +: ... ----. .: ///. ############# '----.- :::::: ------' .- :::: //. ##############: // ::--. -:... ----- ... ": - :::::: -. ' ############: / ::::::::: -:- ". :::::-. ############## .--::::::: ... :::."... :: ... :: EMBRACE DE FREMTIDS APIENE :: -.: - - :: :: - VERSION 1.9.6 :: - - :: -::- -:: --############################## ############ Copyright (C) 2015 Timothy Edmund Crosley Under MIT-lisensen

Ser på port 8000 ... "Dette er ganske kult. Før du prøver å få tilgang til den fantastiske tilbudstjenesten på port 8000, må du kanskje utføre litt ekstra arbeid, avhengig av miljøet ditt.

Hvis du kjører på Mac OS X ved hjelp av VirtualBox og docker-maskin, må du kanskje publisere port 8000 på VirtualBox for å gjøre den tilgjengelig på verten..

Forutsatt at du prøvde å bla til http: // localhost: 8000 / sitater. Å nei. Intern server feil! Hva skjedde?

La oss se på koden:

redis_host = os.environ.get ('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis (vert = redis_host, port = 6379, db = 0)

Sitattjenesten prøver å koble til en redis-server. Vertsadressen kan konfigureres som en miljøvariabel, og hvis den ikke er angitt, vil den bli standard til localhost. Dessverre er Redis ikke installert som standard, og det kjører ikke inne i beholderen. La oss fikse det midlertidig. For å få shell tilgang i containeren, skriv inn følgende kommando:

docker exec-en 715624b7e22a / bin / bash

Da får du shell-tilgang til containeren, og du kan installere redis:

root @ 715624b7e22a: / quote-service # apt-get install redis-server

Endelig kjør redis: root @ 715624b7e22a: / quote-service # redis-server [25] 29 Nov 00: 14: 24.546 # Advarsel: Ingen konfigurasjonsfil oppgitt, bruk standardkonfigurasjonen. For å spesifisere en konfigurasjonsfil, bruk redis-server / path /to/redis.conf _._ _.- "__" -._ _.- ". '_." -._ Redis 2.8.4 (00000000 / 0) 64 bit .- ".-."\ / .,"-._ (' , .- | , ) Kjører i frittstående modus |-._-... - __ ... -.-._ |' .-'| Havn: 6379 | -._ . / .-'| PID: 25 -._ -. -./ _.- '_.-' |-.-._ -..-'_.-'_.-' | | -._-._ _.-'_.- '| http://redis.io -._ -._-.__.-'_.- '_.-' |-._-._ -..-'_.-'.-'| | -._-._ .-'.-'| -._ -.-.__.-'_.- '_.-' -. -.__.- '_.-' -._ _.- "-.__.- '

[25] 29 Nov 00: 14: 24.547 # Server startet, Redis versjon 2.8.4 [25] 29 Nov 00: 14: 24.547 # ADVARSEL overcommit_memory er satt til 0! Bakgrunnsbeskyttelse kan mislykkes under lav minnetilstand. For å fikse dette problemet legger du til 'vm.overcommit_memory = 1' til /etc/sysctl.conf og start deretter om eller kjør kommandoen 'sysctl vm.overcommit_memory = 1' for dette får virkning. 29 november 00: 14: 24.547 * DB lastet fra disk: 0.000 sekunder [25] 29 Nov 00: 14: 24.547 * Serveren er nå klar til å akseptere tilkoblinger på port 6379 "Nå kan du begynne å legge til sitater og få sitater gjennom http: // localhost: 8000 / sitater endepunkt.

Plassering av applikasjonen (sitat service) og databasen (redis) fungerer i en klemme for en server. Men, åpenbart det ikke skaleres. Skriv inn Kubernetes.

Kubernetes Grunnleggende

Kubernetes, a.k.a. k8s, er et påtatt rammeverk for styring og orkestrering av flere containere. Den har sin egen måte å gjøre ting på, som vanligvis er veldig bra. Den er fortsatt under utvikling, så det er fortsatt noen få skarpe kanter her og der. Kubernetes har mange konsepter og er veldig fleksibel. Jeg vil forklare og demonstrere konseptene ved å bruke dem på tilbudstjenesten.

Sette opp en klase

Det er mange måter å sette opp en Kubernetes-klynge på. Kubernetes kan kjøre på bare metall, på Google Container-motor, på AWS, på bare metall (med Linux), og lokalt på alle operativsystemer ved hjelp av virtuelle maskiner. I denne artikkelen har jeg opprettet en klynge av en mester og to minions ved hjelp av CoreOS OSX GUI k8s Cluster. På Mac OS X er det en fin liten meny der du kan få tilgang til mange verktøy for administrasjon av klynger.

Følg instruksjonene, og du vil være god til å gå på kort tid.

Hvis du ikke bruker Mac OSX eller bare ikke bryr meg mye om GUI, kan du bruke dette prosjektet til å sette opp en testklynge i en Vagrant VM.

Jeg vil bruke kommandolinjen fra nå av.

Kubectl Command-Line Tool

kubectl er den sveitsiske hærens kniv av kubernetes. Du kan fullt ut kontrollere og administrere klyngen din fra komforten på konsollen din, uten å bruke noe annet enn kubectl.

Her er listen over kommandoer: få Vis en eller flere ressurser beskrive Vis detaljer om en bestemt ressursopprett Opprett en ressurs etter filnavn eller stdin-oppdatering Oppdater en ressurs etter filnavn eller stdin. slett Slett en ressurs etter filnavn, stdin, ressurs og ID, eller av ressurser og etikettvelger. namespace SUPERCEDED: Sett og vis gjeldende Kubernetes namespace log Skriv ut loggene for en container i en pod. rullende oppdatering Utfør en rullende oppdatering av den oppgitte ReplicationController. endre størrelse Angi en ny størrelse for en replikeringskontroller. exec Utfør en kommando i en beholder. port-forward Videresend en eller flere lokale porter til en pod. proxy Utfør en proxy til Kubernetes API-server-run-container Kjør et bestemt bilde på klyngen. stop Gracefully stenge en ressurs med ID eller filnavn. avslør Ta et gjengitt søknad og avslør det som Kubernetes Service label Oppdater etikettene på en ressurskonfigurasjonskonfigurasjon modifiserer kubeconfig-filer cluster-info Vis klyngeinfo api-versjoner Skriv ut tilgjengelige API-versjoner. versjon Skriv ut klienten og serverversjonsinformasjonen. hjelp hjelp om noen kommandoer

Du kan bruke hjelpekommandoen eller dokumentasjonen til å undersøke hva hver enkelt gjør. Mange av dem brukes til å utføre manuelle operasjoner som er bedre gjort ved hjelp av konfigurasjonsfiler i et stort, skalerbart, distribuert system, men det er uunnværlig for rask leting og feilsøking. De vanligste kommandoene jeg skal bruke mye er: Få, lag, slett og start.

pods

En pod er den grunnleggende enheten for distribusjon og ledelse i Kubernetes. En pod er en gruppe av en eller flere beholdere. Du kan spesifisere en pod ved hjelp av en dedikert YAML-fil eller som en del av en Kubernetes-tjeneste (se nedenfor). En pod er alltid distribuert på en enkelt vert, og alle containene i en pod kan få tilgang til hverandre via localhost. Alle podens containere er alltid startet, stoppet og skalert sammen.

For å sjekke ut alle bøssene i klyngen, skriv:

kubectl få pods

Resultatet blir noe som: NAME READY STATUS RESTARTS ALDRI quote-frontend-4kyns 1/1 Kjører 0 1h quote-frontend-v4xk1 1/1 Kjører 0 1h quote-store-controller-y4ya1 1/1 Kjører 0 23h ### Volumer

Beholdere er ikke ment å opprettholde vedvarende tilstand. Når en beholder krasjer eller starter på nytt, slettes det lokale filsystemet. Hvis du vil beholde vedvarende tilstand, bør du bruke vedvarende volumer. Siden alt i Kubernetes er basert på pods, må du også definere volumer i en pod. Her er en poddefinisjonsfil med et vedvarende volum: apiVersion: v1 type: Podmetadata: navn: quote-store etiketter: app: quote-api rolle: vedvarende-storage spec: containere: - navn: redis bilde: redis volumeMounts: - navn: quote-store-volume mountPath: / data / redis volumer: - navn: sitat-butikk-volum emptyDir: Merk at vedvarende volumer er begrenset til noden og vil overleve beholderen krasjer og starter på nytt, men ikke nod / vertsfeil. Du må fortsatt gjøre jobben med å kopiere og sikkerhetskopiere viktige data.

Replikasjonskontrollere

En av de viktigste funksjonene i Kubernetes er evnen til å håndtere og enkelt skalere opp og ned antall pods. Vanligvis har du forskjellige typer pods i systemet ditt, og du vil kunne spesifisere hvor mange boller av hver type skal være oppe.

Hils deg til replikasjonsstyringsenheter. En replikeringsregulator har en podmal som definerer en gruppe containere, et sett med etiketter for å identifisere disse podene, og antall ønskede pods. Replikeringsregulatoren sørger for at antall løpebøyler identifisert av etikettene alltid samsvarer med ønsket nummer. Hvis en pod avsluttes, vil replikasjonskontrolleren umiddelbart opprette en ny.

Det er flere interessante brukstilfeller som støttes av replikeringsstyringsledere, som høy tilgjengelighet, elastisk skalering og rullende oppdateringer. For eksempel kan du legge til og fjerne pods fra dominionen til en replikeringsregulator ved å endre etiketten.

Replikasjonsregulatorer er selvfølgelig angitt i en YAML-fil. Her er et eksempel: "apiVersion: v1 type: ReplicationController

metadata: navn: quote-frontend spec: replikas: 2 # selector identifiserer settet av Pods at denne # replikasjonsregulatoren er ansvarlig for å administrere selector: app: quote-api rolle: frontend # podTemplate definerer "cookie cutter" som brukes til å skape # nye pods når nødvendig mal: Metadata: Etiketter: # Viktig: Disse etikettene må samsvare med velgeren over # Api-serveren håndhever denne begrensningen. app: quote-api rolle: frontend spec: containere: - navn: quote-service bilde: g1g1 / quote-service env: - navn: GET_HOSTS_FROM # verdi: dns verdi: env porter: - containerPort: 8000 "Malen er spesifikke for quote-service container bruker g1g1 / quote-service bildet jeg presset tidligere til Docker Hub. Merk på env avsnitt der informasjon deling på tvers av pods kan oppstå gjennom enten DNS eller miljøvariabler.

For å opprette en replikeringsregulator, skriv inn:

kubectl opprette -f

For å vise de gjeldende replikasjonsregulatorene i klyngen, skriv:

kubectl få rc

Du bør se noe som: CONTROLLER CONTAINER (S) BILDE (ER) SELECTOR REPLICAS AGE quote-frontend quote-tjeneste g1g1 / quote-service app = quote-api, roll = frontend 2 1h quote-store-controller master redis app = quote-api, rolle = vedvarende -størrelse 1 1d ### Tjenester

En tjeneste utsetter sin pod til resten av klyngen og muligens eksternt via enten miljøvariabler eller DNS. Sitatstjenesten er for eksempel laget av to typer bøtter: en redis-butikk og en front-end pod. Front-end-beholderen skal kunne finne butikkbeholderen, og klienter bør kunne slå et enkelt offentlig sluttpunkt for å få tilgang til tjenesten.

Kubernetes-tjenesten er implementert i enda en YAML-fil. Hver komponent i systemet ditt som må åpnes av andre komponenter, skal ha sin egen tjenestefil. Her er de to tjenestefilene for tilbudstjenestekomponentene:

srv-sitat-frontend.yaml

apiVersion: v1 type: Service metadata: navn: quote-frontend spec: type: NodePort porter: - port: 8000 # porten som denne tjenesten skal tjene på # beholderen på hver pod for å koble til, kan være et navn # 'www') eller et nummer (f.eks. 80) targetPort: 80 protokoll: TCP # akkurat som väljeren i replikasjonsregulatoren, # men denne gangen identifiserer det settet av pods for å laste saldo # trafikk til. selector: app: quote-api rolle: frontend #### srv-quote-store.yaml apiVersion: v1 type: Service metadata: navn: quote-store spec: port: - port: 6379 # porten som denne tjenesten skal tjene på targetPort: 6379 # akkurat som väljeren i replikeringsregulatoren, # men denne gangen identifiserer den sett med pods for å laste balanse # trafikk til. selector: app: quote-api rolle: vedvarende lagring Verten og porten til hver tjeneste blir gjort tilgjengelig for hver container i klyngen. Hvis du for eksempel kjører et interaktivt skall på en av frontendbeholdere:

kubectl sitat-frontend-4 ex exec -i -t bash

Deretter kan du bekrefte at miljøet inneholder nødvendig verts- og portinformasjon for å koble til sitatbutikken. root @ quote-frontend-4:: / quote-service # env | grep STORE QUOTE_STORE_PORT_6379_TCP_ADDR = 10.100.234.192 QUOTE_STORE_PORT_6379_TCP_PROTO = tcp QUOTE_STORE_SERVICE_PORT = 6379 QUOTE_STORE_PORT_6379_TCP_PORT = 6379 QUOTE_STORE_PORT = tcp: //10.100.234.192: 6379 QUOTE_STORE_PORT_6379_TCP = tcp: //10.100.234.192: 6379 QUOTE_STORE_SERVICE_HOST = 10.100.234.192 Bare for å oppdatere minnet ditt, er dette akkurat hva frontenden gjør: redis_host = os.environ.get ('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis (vert = redis_host, port = 6379, db = 0) ## Konklusjon

Docker og Kubernetes er spennende teknologier. Denne artikkelen knapt riper overflaten av det som er mulig. Fordelene er enorme, men infrastrukturen, verktøy og beste praksis er fortsatt i utvikling. Hvis du selv er eksternt koblet til store distribuerte systemer, oppfordrer jeg deg til å holde deg på toppen av disse teknologiene, og ideelt sett dyppe tærne inn og faktisk prøve å bruke dem. Det er mange måter å eksperimentere og lære uten total migrering av hele produksjonsinfrastrukturen.

Så langt som Kubernetes går, er det noen andre alternativer for multi-containerhåndtering og orkestrasjon, for eksempel den etablerte Mesos og Dockers egen komponent. Jeg tror Kubernetes er mer arkitektonisk lyd, har mye fart, og er bedre enn alternativene.