Nasza strona używa cookies. Dowiedz się więcej o celu ich używania i zmianie ustawień w przeglądarce. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Narzędzia nowej generacji do budowania kontenerów

O narzędziach do budowania kontenerów, które pozwalają w pełni wykorzystać możliwości Dockera.
Pzu

Technologie kontenerowe szturmem podbiły cały świat. Dają korzyści dwóm tradycyjnym obszarom IT jednocześnie — zarówno Dev, jak i Ops, wspaniale wspomagając budowanie nowoczesnej kultury DevOps w organizacjach. Z jednej strony dają developerom uniwersalność, przenaszalność i łatwość wejścia w temat dzięki kuszącej prostocie Dockera, a z drugiej zapewniają działom utrzymaniowym zmniejszenie kosztów w porównaniu do maszyn wirtualnych. Umożliwiają upakowanie większej liczby aplikacji per serwer oraz jeszcze większą swobodę żonglowania zasobami.

Wymagania co do uruchamiania aplikacji w kontenerach szybko przerosły to, co może zaoferować sam docker run. Dlatego taką popularnością cieszą się orkiestratory takie jak Kubernetes, Docker Swarm, Mesos i ich chmurowe odpowiedniki: Amazon ECS, Azure Container, Google Container Engine. Prymat na rynku zdaje się wieść Kubernetes, którego używamy również my w PZU.


Budowanie obrazów kontenerów

Wolniej do tej pory rozwijały się jednak narzędzia konkurencyjne do Dockera, służące nie do uruchamiania gotowych kontenerów, a do budowania ich obrazów. Do niedawna wszyscy znali tylko jedną prostą metodę docker build i to, co można opisać w pliku Dockerfile. Pojawiają się ostatnio nowe, ciekawe narzędzia. My wykorzystaliśmy je w procesie automatycznego budowania oprogramowania.

Do zbudowania aplikacji potrzeba czasami nawet gigabajtów powiązanych bibliotek, frameworków, kompilatorów, narzędzi testujących. Współczesna aplikacja zbudowana jako mikroserwis i opakowana w kontener to produkt końcowy, podobnie jak gotowa potrawa na stole. Do jej przygotowania potrzeba jednak czasami niemałej kuchni.

W PZU używamy Atlassian Bamboo jako automatycznego systemu Continuous Integration do budowania i testowania aplikacji. Jest ono świetnie zintegrowane z całym stosem Atlassiana (Bitbucket, Jira, Confluence), co znacząco ułatwia pracę. Deweloperzy bezpośrednio widzą swoje commity z Bitbucketa. Release Managerowie i dział utrzymania mają wgląd co, gdzie i na jakie środowiska zostało wdrożone. Bamboo obsługuje u nas dziesiątki systemów, zarówno małych, jak i dużych. Mamy dużą różnorodność języków programowania i technologii takich jak Java, Maven, Gradle, Node.js, Typescript, PL/SQL, PHP czy aplikacje mobilne. Na jakie niedostatki docker build/Dockerfile można się natknąć w takim środowisku i przy takiej skali?

Niedostatki docker build

Po pierwsze: bezpieczeństwo i wydajność. Popatrzmy na taki koncepcyjny Dockerfile:

FROM ...
COPY id_rsa ~/.ssh
RUN git clone ssh://...
RUN wget https://.../instalka_java_180MB
RUN rm –f instalka_java_180MB
RUN rm –f ~/.ssh/id_rsa


Tak zbudowany obraz będzie miał na zawsze zapisany tajny plik z kluczem w jednej z warstw obrazu. Co prawda nie będzie widoczny, ale można go ręcznie odczytać. Gotowy obraz to przecież tak naprawdę zwykły plik tar.gz.

Również wszelkie paczki instalacyjne powiększą nam obraz, pomimo ich skasowania. Przy nietrywialnych kontenerach te megabajty dają się we znaki. Problem trochę łagodzi używanie plików Multi-stage Dockerfile, ale to rodzi inne kłopoty. Jest trudniejsze w utrzymaniu i nie zapewnia równoległości.

Kolejny problem to słabe keszowanie. Zmiana jednej linii w Dockerfile powoduje przebudowę wszystkich linii poniżej. Trzeba mocno pilnować kolejności instrukcji, stosować sztuczki z łączeniem poleceń i szpikowaniem pliku ampersandami. Docker nie pozwala operować kontenerem z zewnątrz.

Niemożliwe jest też budowanie kontenerów wewnątrz innego kontenera. Chyba, że udostępnimy kontenerowi unix socket /var/run/docker.sock. To niestety jest równoznaczne z przekazaniem pełnej kontroli nad demonem Dockera osobie budującej kontener, co z kolei należy traktować jak przekazanie praw root-a na całym serwerze.

Narzędzia nowej generacji - Buildah

Na te problemy starają się odpowiedzieć autorzy narzędzi nowej generacji do budowy obrazów. W ostatnim czasie pojawiło się kilka interesujących projektów: Buildah i skopeo, runC, umoci, orca-build, kaniko, BuildKit, img. Każdy ma swoją specyfikę. W PZU wybraliśmy narzędzie Buildah od RedHata. Jakie kryteria były ważne przy wyborze?

  1. Bezpośrednie i proste zastąpienie docker build jednym poleceniem: buildah build-using-dockerfile -f Dockerfile
  2. Możliwość modyfikowania i operowania obrazem kontenera z zewnątrz zamiast z wewnątrz
  3. Możliwość budowania kontenera w kontenerze (bez pełnych praw roota na hoście)
  4. Budowanie obrazów od zupełnego zera (base images from scratch)
  5. Stabilna wersja dostępna już teraz i dołączona do RHEL 7.5
  6. Dostępne komercyjne wsparcie od RedHat
  7. Możliwość budowania obrazów na klastrze Kubernetes lub w Cloud, np. AWS


Poniższy skrypt ilustruje część możliwości tego narzędzia. Skrypt buduje tzw. base image z Centosem. Całkowicie od zera.

#!/bin/bash
# Minimal Centos 
#
set -o errexit

# ta linia inicjuje pusty obraz kontenera
newcontainer=$(buildah from scratch)

# montujemy root filesystem kontenera w katalogu tymczasowym
scratchmnt=$(buildah mount $newcontainer)

# install centos
yum install bash coreutils --installroot $scratchmnt --releasever 7\
  --setopt install_weak_deps=false --setopt=tsflags=nodocs\
  --setopt=override_install_langs=en_US.utf8 -y
ln -sf "/usr/share/zoneinfo/Europe/Warsaw"  $scratchmnt/etc/localtime 

# dodatkowe pakiety
yum install less --installroot $scratchmnt --releasever 7\
  --setopt install_weak_deps=false --setopt=tsflags=nodocs\
  --setopt=override_install_langs=en_US.utf8 -y

yum clean all -y --installroot $scratchmnt --releasever 7
rm -rf $scratchmnt/var/cache/yum


buildah config --cmd '/bin/bash' $newcontainer

REL=$(head -n1 $scratchmnt/etc/centos-release | awk '{print $4}')
buildah commit --squash $newcontainer docker://registry.yourdomain/centos-mini:$REL


Buildah umożliwia poleceniu yum operowanie na kontenerze z zewnątrz. Skrypt musi być jednak uruchomiony na hoście z CentOS lub w kontenerze bazującym na CentOS. Tak zbudowany kontener nie będzie nawet zawierał w sobie polecenia yum, ponieważ taki pakiet nie był instalowany, ani uruchamiany wewnątrz kontenera. Komenda buildah commit … zapisuje kontener, sprasowuje wszystkie warstwy i od razu wysyła go do rejestru.

Narzędzia nowej generacji - Skopeo

Kolejnym narzędziem, które uważam za wielce przydatne, jest Skopeo. W połączeniu z jq (parserem JSONa) jest szwajcarskim scyzorykiem do zdalnego operowania po API Docker Registry. Jest niezależne i nie wymaga Dockera.

Do czego jest nieocenione?

  1. Do kasowania obrazów kontenerów.
  2. Do kopiowania i przenoszenia obrazów między różnymi repozytoriami.
  3. Opatrzenia wieloma tagami tego samego obrazu. Bez przesyłania danych. Wirtualnie można kopiować i przenosić ten sam obraz. Jeśli przechodzi testy na środowiskach, może być promowany na inne tylko przez zmianę tagu :dev :sit :uat :preprod :prod


Możemy dowiedzieć się sporo o obrazie bez ściągania go ze zdalnego serwera.

$ skopeo inspect docker://registry.yourdomain/centos-test:latest
{
    "Name": " registry.yourdomain/library/centos-test ",
    "Digest": "sha256:a86ed9ca70f7f9afa6eac830d0ca25aa0743d066570e50e275ff93bcde94b6f2",
    "RepoTags": [
        "7.5.1804",
        "dev.21",
        "dev.22",
        "dev.23",
        “latest”,
        "7"
   ],
    "Created": "2018-10-07T00:22:27.287686764Z",
    "DockerVersion": "17.06.2-ce",
    "Labels": null,
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:0a50f429aee790930bc0869ac8caaa0a8e7456c09604d5c1acbb5ab251af8bce"
    ]
}


Jak widać, zapytanie było o konkretną nazwę i tag. Skopeo dodatkowo pokazuje w polu RepoTags wszystkie tagi i obrazy, jakie są dostępne w rejestrze. Można to wykorzystać na wiele sposobów. Poniżej poglądowy skrypt, który skasuje wszystkie obrazy zawierające w tagu słowo „dev”.

NAZWA=registry.yourdomain/centos-test
LISTA=($(skopeo inspect docker://${NAZWA}:latest | jq -r ' .RepoTags[] | select ( contains( "dev." )) '))
   for TAG in "${LISTA[@]}"
   do
     skopeo delete docker://${NAZWA}:${TAG}
   done

 

Podsumowanie

Korzystanie z tego typu narzędzi umożliwiło nam znaczące usprawnienie naszego systemu CI/CD. Jak większość takich systemów, Bamboo działa w ten sposób, że jest jeden centralny serwer i flota agentów (czasami zwanych też workerami) dookoła niego. Serwer wszystkim zarządza. Zleca pracę i zbiera raporty od agentów, wysyła listę zadań do wykonania. Skąd należy pobrać kod źródłowy, biblioteki i zleca budowanie lub testowanie.

Tradycyjnie jako agentów używa się maszyn wirtualnych. Rozbudowa i dokładanie zasobów trwa czasem długo, a śledzenie zmian jest problematyczne, stąd zdecydowaliśmy się przejść na kontenery.

Stworzyliśmy obrazy kontenerów z agentami Bamboo, używając Buildah. Zawierają one cały potrzebny software do budowania różnych aplikacji. Teraz cała konfiguracja i historia zmian jest w Git. Agent w kontenerze potrafi budować różne aplikacje, np. Node.js dla Androida czy projekt Java/Maven i to — jeśli potrzeba — dla różnych wersji Javy. Robimy też kontenerową incepcję, czyli budujemy kontenery wewnątrz kontenerów.

To tylko mały fragment tego, jak wykorzystujemy kontenery i nowoczesne technologie w PZU. Jeśli chcesz dowiedzieć się więcej, jakich jeszcze narzędzi używamy, zachęcam do przejrzenia oferty pracy w PZU lub wejścia na naszą stronę. Robimy też cyklicznie warsztaty, gdzie dzielimy się wiedzą, które czasem są otwarte dla osób spoza firmy. Jeśli masz interesujące pytanie odnośnie kontenerów lub CI/CD, wyślij do mnie maila (pkapczuk@pzu.pl). Polecam też dostępny online, darmowy kurs Buildah.

 

https://github.com/containers/buildah
https://github.com/containers/skopeo
https://www.katacoda.com/courses/containers-without-docker/building-container-images-with-buildah

Zobacz kogo teraz szukają