Pierwsze zabawy z Kubernetes – część 1 Docker

wpis w: chmura, konteneryzacja, migawka | 0

Konteneryzacja aplikacji wykorzystująca Dockera i ich orkiestracja  za pomocą Kubernetes  przebojem zdobywają coraz większą grupę zwolenników. Postanowiłem zmierzyć się z tymi produktami.

Założyłem, ze wykorzystam jakieś darmowe środowisko, które pozwoli mi na pierwsze zabawy, bez zbędnej instalacji oprogramowania na stacji roboczej.  Powtarzalne operacje zostaną zapisane w plikach na Githubie.

Niniejszy wpis wykorzystuje https://labs.play-with-k8s.com/ .

Uruchomienie środowiska wymaga zalogowania się na konto GitHub lub na konto DockerHuba. Wybrałem tę drugą opcję.

Po podaniu naszych poświadczeń i po naciśnięciu zielonego przycisku Start mamy do dyspozycji uruchomione gotowe środowisko do testów, które zostaje powołane na czas czterech godzin.

Na początku musimy dodać pierwszą instancję. Po krótkiej chwili mamy już gotowe środowisko z dostępem do shella.

Pierwsze polecenie uname -a

Linux node1 4.4.0-127-generic #153-Ubuntu SMP Sat May 19 10:58:46 
UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Mamy dostęp do schowka
Shift + insert = kopiuj
Ctrl + insert = wklej

Co więcej możemy doinstalować sobie potrzebne pakiety, np. edytor nano, midnight commander i inne cuda…

yum install mc nano lynx

Spróbujmy uruchomić prostą aplikację w kontenerze z gotowego publicznego repozytorium Docker Hub.

Na początku uruchomimy pusta aplikacje www opartą o popularny serwer apache2.

docker run -d -p 80 httpd:2.4

Polecenie to uruchamia obraz o nazwie httpd w wersji 2.4 z wystawiony portem tcp 80 od strony kontenera, port hosta zostanie zmapowany automatycznie. Za chwile zobaczymy na jaką wartość. Obrazu tego nie było do tej pory lokalnie, stąd komunikat “unable to find image”.  Przed budową zostanie on ściągnięty z repozytorium Docker Huba.

Otrzymany wynik:

Unable to find image 'httpd:2.4' locally
2.4: Pulling from library/httpd
f17d81b4b692: Pull complete
06fe09255c64: Pull complete
0baf8127507d: Pull complete
07b9730387a3: Pull complete
6dbdee9d6fa5: Pull complete
Digest: sha256:90b34f4370518872de4ac1af696a90d982fe99b0f30c9be994964f49a6e2f421
Status: Downloaded newer image for httpd:2.4
46da2648c3cb1b8a1354c488a6fac06036b1dfa388758bba0badf646ea775bdb

Sprawdźmy listę naszych obrazów

docker images

Otrzymany wynik:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
httpd               2.4                 55a118e2a010        2 days ago          132MB

Sprawdzamy, które obrazy są uruchomione.

docker ps

Otrzymany wynik:

 CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                   NAMES
46da2648c3cb        httpd:2.4           "httpd-foreground"   32 seconds ago      Up 29 seconds       0.0.0.0:32768->80/tcp   jolly_engelbart
>80/tcp   jolly_engelbart

Port 80 tcp kontenera zostaje zmapowany na port 32768 hosta.

Pojawia się niebieskie łącze o nazwie wystawionego portu. Po kliknięciu mamy stronę z napisem

It works!

Wykorzystując gotowe obrazy, które  można traktować jako bazę, mamy możliwość tworzenia na ich podstawie bardziej skomplikowanych funkcjonalnie aplikacji. W tym celu możemy wykorzystać plik konfiguracyjny, tak zwany Dockerfile.

Przykładowy Dockerfile:

# base image...
FROM phusion/baseimage

# author
MAINTAINER djkormo

RUN apt-get clean -qy
RUN apt-get update -qy

# install packages
RUN apt-get install apache2 git -qy

# clone content of sample app
RUN git clone https://github.com/djkormo/simple-chess-ai

# copy content to apache root directory
RUN cd simple-chess-ai && cp -R .  /var/www/html/ && cd .. && rm -r  simple-chess-ai/
RUN chmod a+x -R /var/www/html/

# running apache
ENTRYPOINT ["/usr/sbin/apache2ctl","-D","FOREGROUND"]

# exposing 80 port
EXPOSE 80

# Utwórzmy dedykowany katalog
mkdir containers
cd containers
mkdir chess-ai
cd chess-ai
touch Dockerfile

Uzupełniamy zawartość pustego pliku Dockerfile i budujemy nasz kontener.

docker build -t chess-ai .

Uruchamiamy nasz kontener

docker run -p 80 -d chess-ai

docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTSNAMES
c4bae941f8d5 chess-ai "/usr/sbin/apache2ct…" 7 seconds ago Up 6 seconds 0.0.0.0:32770->80/tcp

Jak widać kontener nasłuchuje na porcie 32770 hosta

Można tę informację pobrać w bardziej elegancji sposób:

PORT="$(docker ps|grep chess-ai|sed 's/.*0.0.0.0://g'|sed 's/->.*//g')"
echo $PORT
32770

Na górze powinien pojawić się niebieski link z takim numerem portu.
Po uruchomieniu
http://ip172-18-0-22-bf4df2mn5ugg00cc6t5g-32770.direct.labs.play-with-k8s.com/

Mamy widoczną naszą aplikację.

Warto zapamiętać budowę linku:

http://ip<hyphen-ip>-<session_jd>-<port>.direct.labs.play-with-k8s.com

A naszym przypadku był to

http://ip172-18-0-22-bf4df2mn5ugg00cc6t5g-32770.direct.labs.play-with-k8s.com/

Warto pamiętać o kilku zasadach, które pomagają budować obrazy kontenerowe w sposób efektywny

  1. Wybieramy obraz, z najbardziej optymalną  funkcjonalnością, czyli np. taki który zawiera tylko potrzebne oprogramowanie i nic więcej.
  2. Instalujemy tylko potrzebne oprogramowanie.
  3. Niepotrzebne pliki tymczasowe, które powstają podczas instalacji oprogramowania powinny zostać usunięte.
  4. Każde polecenie RUN tworzy nowa warstwę w obrazie, eliminujmy ich liczbę. Stad często widoczne jest sklejanie poleceń przez &&.
  5. Każdy projekt powinien mieć własny plik .dockerignore, w którym zawarte są reguły wykluczające pliki i katalogi w procesie budowania.

Wykonajmy prosty eksperyment.

Przygotowałem dwie wersje pliku DockerFile,

jeden to obraz ubuntu:16.04,

https://github.com/djkormo/ContainersSamples/blob/master/Docker/chess-ai/ubuntu/Dockerfile

drugi to alpine:3.7.

https://github.com/djkormo/ContainersSamples/tree/master/Docker/chess-ai/alpine/Dockerfile

# pobierzmy pliki z repozytorium GitHub.
git clone https://github.com/djkormo/ContainersSamples.git

Otrzymany wynik:

Cloning into 'ContainersSamples'...
remote: Enumerating objects: 84, done.
remote: Counting objects: 100% (84/84), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 84 (delta 13), reused 81 (delta 10), pack-reused 0
Unpacking objects: 100% (84/84), done.

Wchodzimy do podkatalogów

cd ContainersSamples/
cd Docker/
cd chess-ai/

W podkatalogu mamy trzy wersje plików Dockeffile

W każdym z podkatalogów budujemy lokalna wersje obrazu, tu dla przykładu dla obrazu pochodzącego z dystrybucji alpine.

docker build -t local/chess-ai-alpine .

Dla obrazu Ubuntu

docker build -t local/chess-ai-ubuntu .

Po zbudowaniu tych dwóch obrazów , możemy porównać ich rozmiar

docker images

Otrzymujemy następujące wartości:

REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
local/chess-ai-alpine   latest              b9ab394052a6        18 seconds ago      28.3MB
local/chess-ai-ubuntu   latest              db929792894c        58 seconds ago      275MB
ubuntu                  16.04               4a689991aa24        8 days ago          116MB
alpine                  3.7                 34ea7509dcad        6 weeks ago         4.2MB

To co widać od razu, z obrazu bazowego alpine:3.7 o wielkości 4.2MB powstał obraz local/chess-ai-alpine o wielkości 28.3MB. Natomiast z bazowego obrazu ubuntu:16.04 o wielkości 116MB powstał obraz localhost/chess-ai-ubuntu o wielkości 275MB. Funkcjonalność obu aplikacji, czyli prosta gra w szachy napisania w Javascript, jest taka sama, a różnica w wielkości jest dziesięciokrotna.

Literatura:

https://medium.com/@marcosnils/introducing-pwk-play-with-k8s-159fcfeb787b

https://github.com/play-with-docker/play-with-docker/issues/259

http://phusion.github.io/baseimage-docker/

Kubernetes Hands-on Lab #1 – Setting up 5-Node K8s Cluster

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.