Introductie van Docker en Kubernetes

Grootschalige gedistribueerde systemen gemaakt van meerdere samenwerkende diensten worden steeds belangrijker. Deze systemen draaien op clusters van honderden, duizenden of meer servers. Het efficiënt en economisch ontwikkelen, implementeren en onderhouden van deze systemen is een grote opdracht.

Virtualisatie en meer recent containerisatie maken flexibel delen en beheren van bronnen mogelijk. Docker maakte containerisatie populair. Bekijk dit Envato Tuts + -artikel voor een geweldige introductie: de Hitchhidershandleiding voor docker en modulus.

Google beheert al jarenlang zijn immense software en datacenters over containerisatie en heeft er een verzameld lot van ervaring en knowhow. Kubernetes is een open-sourceproject van Google dat al die kennis bij de massa brengt.

In dit artikel zal ik Docker kort verkennen en daarna diep in Kubernetes duiken. Ik gebruik als voorbeeld een Python 3-quote REST API-service. Laten we erin springen.

De offerteservice

De offerteservice is een REST-API waarmee u offertes kunt toevoegen en een lijst met alle aanhalingstekens kunt krijgen. Het is geïmplementeerd als een Python 3-webservice met behulp van de uitstekende knuffelbibliotheek. Er wordt een enkel eindpunt genoemd / aanhalingstekens weergegeven. U kunt alle offertes ophalen of een nieuw citaat plaatsen. Laten we een paar citaten toevoegen:

krul http: // localhost: 8000 / quotes -d "quote = TV is kauwgom voor de ogen. ~ Frank Lloyd Wright" krul http: // localhost: 8000 / quotes -d "quote = Het is beter om te sterven op uw voeten dan op je knieën leven ~ Emiliano Zapata "krul http: // localhost: 8000 / quotes -d" quote = We moeten heel voorzichtig zijn als we jongere mensen advies geven: soms volgen ze het! ~ Edsger W. Dijkstra "

Als u bladert naar http: // localhost: 8000 / quotes je krijgt: ["TV is kauwgom voor de ogen. ~ Frank Lloyd Wright", "Het is beter om dood te gaan dan op je knieën te leven. ~ Emiliano Zapata", "We moeten heel voorzichtig zijn als we jongere mensen adviseren: soms volgen ze het! ~ Edsger W. Dijkstra "] Als u alleen de automatisch gegenereerde documentatie van HUG wilt zien, bladert u naar: http: // localhost: 8000

"404": "De API-aanroep die u probeerde te maken was niet gedefinieerd. Hier is een definitie van de API om u op gang te helpen :)", "documentation": "/ quotes": "GET": "voorbeelden ": [" http: // localhost: 8000 / quotes "]," outputs ": " content_type ":" application / json "," format ":" JSON (JavaScript Serialized Object Notation) "," POST " : "outputs": "content_type": "application / json", "format": "JSON (Javascript Serialized Object Notation)", "inputs": "quote": "type": "Basistekst / tekenreekswaarde"

Docker Basics

Ik zal niet te veel uitleggen over Docker en het alleen toepassen op de offerteservice.

Dockeriseren van een Python-app

Eerst hebben we een Docker-bestand nodig. Het voert de volgende stappen uit:

  1. Gebaseerd op de nieuwste ubuntu-afbeelding
  2. Installeert Python 3 en een paar andere afhankelijkheden
  3. Kopieer de citaat-servicemap
  4. Hiermee installeert u de afhankelijkheden tussen offerteservices uit het bestand requirement.txt
  5. Toont de 8000-poort
  6. Start de quote-service via knuffel

VAN ubuntu: nieuwste MAINTAINER Gigi Sayfan "[email protected]" RUN apt-get update -y RUN apt-get installeer -y python3 python3-pip python3-dev build-essentiële COPY. / quote-service WORKDIR / quote-service RUN pip3 install -r requirements.txt EXPOSE 8000 ENTRYPOINT knuffel -f app.py

Een afbeelding bouwen

De volgende stap is het bouwen van een Docker-afbeelding. Dit is zo simpel als:

docker build .

Ik vind het ook leuk om afbeeldingen te taggen:

docker-tag 715624b7e22a g1g1 / quote-service

g1g1 is mijn gebruikersnaam op Docker Hub.

Ga als volgt te werk om te controleren of de afbeelding is gemaakt:

koppelaar ps - alles 

Je zou de nieuwe afbeelding moeten zien:

CONTAINER ID IMAGE COMMAND GECREëERDE STATUS POORTSNAMEN 715624b7e22a g1g1 / quote-service "/ bin / sh -c 'knuffel -f a" 4 uur geleden Omhoog 35 minuten 0.0.0.0: 8000->8000/tcp geschud_northcutt

Een afbeelding naar Docker Hub duwen

Wanneer u een afbeelding maakt, kunt u deze ook naar Docker Hub duwen, zodat deze door andere mensen (of uzelf op een andere machine) kan worden gebruikt.

docker push g1g1 / quote-service

Let op: u moet een account aanmaken op Docker Hub en u lokaal aanmelden met:

dokwerk-login

Een gemarginaliseerde app uitvoeren

OK. Laten we de afbeelding van de offertedienst uitvoeren en poort 8000 aan de host ontmaskeren.

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

Je zou moeten zien: / ################################################# ###################### \ '.---- "... ------- ..." .----. : / ::::: -: ---------: - ::::: ... + :::: ---- ## / - / oo +: - ## - --- :::: // '// :: ------- / oosoo ------- ::: //. ## ## ## ## ##### .-: ------./++ o / o -.------ :: - ' ## ## ## ## ## ----.-./ + O +: ... ----. .: ///. ######## ## ## ## '----.- :::::: ------' .- :::: //. ## ## ## ## ######: // ::--. -:... ----- ... ": - :::::: -. ' ## ## ## ## ## ##: / ::::::::: -:- ". :::::-. ## ## #### ###### .--::::::: ... :::."... :: ... :: EMBRACE DE API's VAN DE TOEKOMST :: -.: - - :: :: - VERSIE 1.9.6 :: - - :: -::- -:: - ####################### ######################### Copyright (C) 2015 Timothy Edmund Crosley onder de MIT-licentie

Serveren op poort 8000 ... "Dit is best gaaf. Voordat je toegang probeert te krijgen tot je geweldige offerteservice op poort 8000, moet je misschien wat extra werk doen, afhankelijk van je omgeving..

Als u op Mac OS X draait met behulp van VirtualBox en docker-machine, moet u mogelijk poort 8000 op VirtualBox publiceren om het toegankelijk te maken op de host.

Ervan uitgaande dat je hebt geprobeerd te browsen http: // localhost: 8000 / quotes. Oh nee. Interne Server Fout! Wat is er gebeurd?

Laten we de code eens bekijken:

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

De offerteservice probeert verbinding te maken met een redisserver. Het hostadres kan worden geconfigureerd als een omgevingsvariabele en als dit niet is ingesteld, wordt het standaard ingesteld op localhost. Helaas is redis niet standaard geïnstalleerd en loopt het niet in de container. Laten we het tijdelijk repareren. Typ de volgende opdracht om shell-toegang tot de container te krijgen:

koppelaar exec -it 715624b7e22a / bin / bash

Dan krijg je shell-toegang tot de container en kun je redis installeren:

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

Redis tenslotte: root @ 715624b7e22a: / quote-service # redis-server [25] 29 nov 00: 14: 24.546 # Waarschuwing: geen configuratiebestand opgegeven met behulp van de standaardconfiguratie. Om een ​​configuratiebestand te specificeren, gebruikt u redis-server /path/to/redis.conf _._ _.- "__" -._ _.- ". '_." -._ Redis 2.8.4 (00000000 / 0) 64 bit .- ".-."\ / .,"-._ (' , .- | , ) Lopen in stand-alone modus |-._-... - __ ... -.-._ |' .-'| Poort: 6379 | -._ . / .-'| PID: 25 -._ -. -./ _.- '_.-' |-.-._ -..-'_.-'_.-' | | -._-._ _.-'_.- '| http://redis.io -._ -._-.__.-'_.- '_.-' |-._-._ -..-'_.-'.-'| | -._-._ .-'.-'| -._ -.-.__.-'_.- '_.-' -. -.__.- '_.-' -._ _.- "-.__.- '

[25] 29 nov 00: 14: 24.547 # server gestart, Redis-versie 2.8.4 [25] 29 nov 00: 14: 24.547 # WARNING overcommit_memory is ingesteld op 0! Het opslaan op de achtergrond kan mislukken als er weinig geheugen beschikbaar is. Om dit probleem op te lossen, voegt u 'vm.overcommit_memory = 1' toe aan /etc/sysctl.conf en start u vervolgens opnieuw op of voert u de opdracht 'sysctl vm.overcommit_memory = 1' uit om dit effect te krijgen. [25] 29 nov 00: 14: 24.547 * DB geladen vanaf schijf: 0.000 seconden [25] 29 nov 00: 14: 24.547 * De server is nu klaar om verbindingen op poort 6379 te accepteren. "Nu kunt u beginnen met het toevoegen van offertes en het krijgen van citaten door de http: // localhost: 8000 / quotes eindpunt.

Het plaatsen van de applicatie (offerteservice) en de database (redis) werkt in een mum van tijd voor één server. Maar dat schaalt natuurlijk niet. Voer Kubernetes in.

Basisbeginselen van Kubernetes

Kubernetes, a.k.a. K8S, is een eigenzinnig raamwerk voor het beheren en orkestreren van meerdere containers. Het heeft zijn eigen manier om dingen te doen, wat meestal heel goed is. Het is nog in ontwikkeling, dus hier en daar zijn nog steeds een paar ruige kanten. Kubernetes heeft veel concepten en is zeer flexibel. Ik zal de concepten uitleggen en demonstreren door ze toe te passen op de offerteservice.

Een cluster opzetten

Er zijn veel manieren om een ​​Kubernetes-cluster op te zetten. Kubernetes kunnen op bare metal draaien, op Google Container engine, op AWS, op bare metal (met Linux) en lokaal op elk besturingssysteem met behulp van virtuele machines. Voor dit artikel heb ik een cluster van één master en twee minions gemaakt met behulp van de CoreOS OSX GUI k8s-cluster. Op Mac OS X biedt het een leuk klein menu waarin je toegang hebt tot veel clusterbeheertools.

Volg de instructies en je zult snel klaar zijn.

Als u Mac OSX niet gebruikt of u zich niet druk maakt om GUI, kunt u dit project gebruiken om een ​​testcluster in een Vagrant VM in te stellen.

Ik zal vanaf nu de commandolijn gebruiken.

Het kubectl Command-Line Tool

Kubectl is het Zwitserse zakmes van Kubernetes. U kunt uw cluster volledig bedienen en beheren vanuit uw console, met niets anders dan Kubectl.

Hier is de lijst met opdrachten: get Display een of veel bronnen beschrijven Details van een specifieke resource tonen maken Maak een resource op basis van bestandsnaam of stdin update Werk een resource bij op bestandsnaam of stdin. verwijderen Een resource verwijderen op basis van bestandsnaam, stdin, resource en ID, of op bronnen en labelselectie. namespace SUPERCEDED: instellen en bekijken van het huidige Kubernetes namespace-logboek Print de logs voor een container in een pod. rolling-update Voer een rolling update uit van de opgegeven ReplicationController. formaat wijzigen Een nieuw formaat instellen voor een replicatiecontroller. exec Voer een opdracht uit in een container. port-forward Stuur een of meer lokale poorten naar een pod. proxy Voer een proxy uit naar de Kubernetes API-server run-container Voer een bepaalde afbeelding uit op het cluster. stop Gracefully stop een resource op id of bestandsnaam. blootleggen Neem een ​​gerepliceerde toepassing en stel deze bloot als Kubernetes Servicelabel Werk de labels bij op een bron config config wijzigt kubeconfig-bestanden cluster-info Toon clusterinformatie api-versies Druk beschikbare API-versies af. versie Druk de informatie over de client- en serverversie af. help over elke opdracht

Voel je vrij om de help-opdracht of de documentatie te gebruiken om te onderzoeken wat elk doet. Velen van hen worden gebruikt voor het uitvoeren van handmatige bewerkingen die beter worden gedaan met behulp van configuratiebestanden in een grootschalig, schaalbaar, gedistribueerd systeem, maar het is onmisbaar voor een snelle verkenning en probleemoplossing. De meest voorkomende commando's die ik veel gebruik zijn: krijgen, maken, verwijderen en starten.

Pods

Een pod is de basiseenheid voor implementatie en beheer in Kubernetes. Een pod is een groep van een of meer containers. U kunt een pod opgeven met een speciaal YAML-bestand of als onderdeel van een Kubernetes-service (zie hieronder). Een pod wordt altijd ingezet op een enkele host en alle containers in een pod kunnen via localhost toegang krijgen tot elkaar. Alle containers van de pod worden altijd gestart, gestopt en geschaald.

Als u alle pods in het cluster wilt bekijken, typt u:

Kubectl krijg pods

Het resultaat zal iets zijn als: NAAM KLAAR STATUS RESTARTS LEEFTIJD quote-frontend-4kyns 1/1 draait 0 1 uur quote-frontend-v4xk1 1/1 draait 0 1 uur quote-store-controller-y4ya1 1/1 draait 0 23 uur ### Volumes

Het is niet de bedoeling dat containers persistente toestand behouden. Wanneer een container crasht of opnieuw start, wordt het lokale bestandssysteem weggevaagd. Als u de persistente status wilt behouden, moet u persistente volumes gebruiken. Omdat alles in Kubernetes is gebaseerd op pods, moet u ook volumes in een pod definiëren. Hier is een poddefinitiebestand met een persistent volume: apiVersion: v1 kind: Pod metadata: naam: quote-store labels: app: quote-api rol: persistent-storage spec: containers: - naam: roodis afbeelding: redis volumeMounts: - naam: quote-store-volume mountPath: / data / redis volumes: - naam: quote-store-volume emptyDir: Houd er rekening mee dat persistente volumes beperkt zijn tot het knooppunt en dat deze container crasht en opnieuw opstart, maar niet knooppunt / host-fouten. U moet nog steeds het werk doen van het repliceren en back-uppen van belangrijke gegevens.

Replicatiecontrollers

Een van de belangrijkste kenmerken van Kubernetes is de mogelijkheid om het aantal pods te beheren en eenvoudig op te schalen. Normaal gesproken heeft u verschillende soorten pods in uw systeem en u wilt kunnen aangeven hoeveel pods van elk type actief moeten zijn.

Zeg hallo tegen replicatiecontrollers. Een replicatiecontroller heeft een podsjabloon die een groep containers definieert, een set labels om deze pods te identificeren en het aantal gewenste pods. De replicatiecontroller zorgt ervoor dat het aantal actieve pods dat wordt aangegeven door de labels altijd overeenkomt met het gewenste aantal. Als een pod wordt beëindigd, maakt de replicatiecontroller onmiddellijk een nieuwe pod.

Er zijn verschillende interessante gebruikscasussen die worden ondersteund door replicatiecontrollers, zoals hoge beschikbaarheid, elastische schaling en rolling updates. U kunt bijvoorbeeld pods toevoegen en verwijderen uit het domein van een replicatiecontroller door hun label te wijzigen.

Replicatiecontrollers worden uiteraard in een YAML-bestand gespecificeerd. Hier is een voorbeeld: "apiVersion: v1 kind: ReplicationController

metadata: naam: quote-frontend spec: replica's: 2 # selector identificeert de set pods die deze # replicatiecontroller verantwoordelijk is voor het beheren van de selector: app: quote-api role: frontend # podTemplate definieert de 'cookie cutter' die wordt gebruikt voor het maken van # nieuwe pods indien nodig sjabloon: metadata: labels: # Belangrijk: deze labels moeten overeenkomen met de selector hierboven # De api-server dwingt deze beperking af. app: quote-api rol: frontend spec: containers: - naam: quote-service afbeelding: g1g1 / quote-service env: - naam: GET_HOSTS_FROM # waarde: dns waarde: env-poorten: - containerPort: 8000 "De sjabloonspecificatie voor de quote-service container gebruikt de g1g1 / quote-service afbeelding die ik eerder naar Docker Hub heb gepusht env sectie waar het delen van informatie tussen pods kan plaatsvinden via DNS of omgevingsvariabelen.

Als u een replicatiecontroller wilt maken, typt u:

kubectl create -f

Als u de huidige replicatiecontrollers in het cluster wilt weergeven, typt u:

Kubectl krijgt rc

Je zou zoiets als moeten zien: CONTROLLER CONTAINER (S) IMAGE (S) SELECTOR REPLICAS AGE quote-frontend quote-service g1g1 / quote-service app = quote-api, role = frontend 2 1h quote-store-controller master redis-app = quote-api, role = persistent -opslag 1 1d ### Diensten

Een service stelt zijn pod bloot aan de rest van het cluster en mogelijk extern via omgevingsvariabelen of DNS. De offerteservice bestaat bijvoorbeeld uit twee soorten pods: een redis-winkel-pod en een front-end-pod. De front-end-container moet de winkelcontainer kunnen vinden en clients moeten in staat zijn om één openbaar eindpunt te raken om toegang te krijgen tot de service..

De Kubernetes-service is geïmplementeerd in nog een ander YAML-bestand. Elk onderdeel van uw systeem dat moet worden geopend door andere componenten moet een eigen servicebestand hebben. Dit zijn de twee servicebestanden voor de citaatservicecomponenten:

srv-quote-frontend.yaml

apiVersion: v1 type: Service metadata: naam: quote-frontend spec: type: NodePort-poorten: - poort: 8000 # de poort waarop deze service zou moeten worden gebruikt # de container op elke pod waarmee verbinding kan worden gemaakt, kan een naam # zijn (bijv. 'www') of een nummer (bijv. 80) targetPort: 80 protocol: TCP # net als de selector in de replicatiecontroller, # maar deze keer identificeert het de set van pods om balans # verkeer naar te laden. selector: app: quote-api role: frontend #### srv-quote-store.yaml apiVersion: v1 type: Service metadata: naam: quote-store spec: ports: - port: 6379 # de poort die deze service moet gebruiken op targetPort: 6379 # net als de selector in de replicatiecontroller, # maar deze keer identificeert deze de set pods om balans # verkeer naar te laden. selector: app: quote-api role: persistent-storage De host en poort van elke service worden beschikbaar gemaakt voor elke container in het cluster. Als u bijvoorbeeld een interactieve shell uitvoert op een van de frontend-containers:

kubectl quote-frontend-4kyns exec -i -t bash

Vervolgens kunt u controleren of die omgeving de benodigde host- en poortinformatie bevat om verbinding te maken met de offertewinkel. root @ quote-frontend-4kyns: / 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 = 6379 QUOTE_STORE_PORT_6379_TCP_PORT 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 Gewoon, om je geheugen op te frissen, dit is precies wat de frontend doet: redis_host = os.environ.get ('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis (host = redis_host, poort = 6379, db = 0) ## Conclusie

Docker en Kubernetes zijn opwindende technologieën. Dit artikel kraste nauwelijks het oppervlak van wat mogelijk is. De voordelen zijn enorm, maar de infrastructuur, tooling en beste praktijken evolueren nog steeds. Als je zelfs maar op afstand verbonden bent met grootschalige gedistribueerde systemen, moedig ik je aan om op zijn minst deze technologieën te volgen en idealiter je tenen in te dompelen en ze daadwerkelijk te gebruiken. Er zijn veel manieren om te experimenteren en te leren zonder groothandelmigratie van uw volledige productie-infrastructuur.

Wat Kubernetes betreft, zijn er nog een paar andere alternatieven voor multi-container management en orkestratie, zoals de bestaande compositie van Mesos en Docker. Ik geloof dat Kubernetes architectonisch beter klinkt, veel vaart heeft en beter is dan de alternatieven.