Skip to content

Latest commit

 

History

History
745 lines (642 loc) · 31.5 KB

README.md

File metadata and controls

745 lines (642 loc) · 31.5 KB

Intro to Podman

2 days, 8 ac.hrs, 7 as.hrs.

Знакомство

  1. Роль
  2. Текущий уровень с Linux: 0–3
  3. Текущий уровень с Docker/Podman: 0–3
  4. Как поймете, что тренинг дал Вам ценность?

Prerequisites

  • Virtual machine for practice @ vra8: IT Academy Training Group, HDD 50Gb, OS AlmaLinux + local ssh client
  • Доступен git repo с данным руководством {{ git-repo }} https://github.com/eugene-krivosheyev/podman
  • Доступен {{ registry-host }}
  • Доступ учетной записи {{ registry-account }} на {{ registry-host }}
  • Установлен Podman и зависимости
sudo dnf update
sudo dnf install -y podman
sudo dnf install -y slirp4netns # for rootless containers
sudo dnf install -y bash-completion
source <(podman completion bash)
sudo podman completion -f /etc/bash_completion.d/podman bash

Intro to containerization and Podman 30 мин

Задачи контейнеризации

  • Переносимость ПО: запуск на разных окружениях – dev, test, prod
  • исполняемые файлы нашего ПО
  • зависимости
  • конфигурация
  • аргументы командной строки
  • порты
  • побочные эффекты

Контейнеризация vs виртуализация

  • место на диске для гостевой ОС
  • время запуска гостевой ОС
  • overhead операций гостевой ОС

Ключевые термины контейнеризации

puml
@startuml
node "image\nregistry" {
    database "disk\nimage" as disk_image
}

node "host" {
    rectangle "pod" {
        rectangle "infra\ncontainer"
        rectangle "container" {
            component "application"
            database "container\nlayer" as layer
        }
    }
    database "disk" {
        database "image"
        file "volume"
        folder "shared\nfolder" as folder
        disk_image - image
    }
    image --layer
    volume -# container
    folder -# container
    volume -# pod
    folder -# pod
}

pod #--# host : "port\nmapping"
container #--# host : "port\nmapping"
@enduml

Podman vs другой популярный стиральный порошок

  • pod

  • bunch of containers

  • infra container

  • localhost

  • port mappings

  • mounts

  • daemonless

  • rootfull and rootless modes

Hands-on practice quest #00: Prerequisites sound-check and tools install 20 мин парной практики + 10 мин дебриф

Given

  • Пары участников с чередованием ролей в паре
  • Форк данного руководства для собственных пометок
  • Все команды запускаются из-под суперпользователя
sudo

или

su -
  • Как описать сценарий использования команд?
- каоманды перевода системы в нужное состояние
- команды действия
- команды проверки успешности и корректности действия 
  • Hints
  • при работе в терминале используйте Tab и для автоподстановки значений
  • синонимы команд cli
  • ... --help
  • podman cli reference

When участники именуют сценарии, выполняют команды и анализируют их вывод и поведение

  • Сценарий "Как посмотреть версию подмана/информацию о хостовой ОС/занятое место?"
podman version # TODO: собственные пометки участников для будущего использования в проектах
podman system info
podman system df
  • Сценарий "Как подключить корпоративный репозиторий?"
podman logout {{ registry-host }}
podman login {{ registry-host }}
  • Сценарий "Как найти нужный образ в registry?" Залогиниться браузером по адресу {{ registry-host }}, в поиске найти нужный образ и скопировать полное символьное имя (включая сетевой адрес хоста).

  • Сценарий "Как скачать образ из корпоративного репозитория?"

podman image pull {{ registry-host }}/{{ os-images-path }}/alpine:3.14
podman system df
  • Сценарий "Как запустить контейнер?"
podman container run hello

podman container run --name demo -it {{ registry-host }}/{{ os-images-path }}/alpine:3.14
/# cat /etc/os-release
/# exit 
  • Сценарий "Как посмотреть запущенные контейнеры [все] и удалить контейнер?"
podman container ls [--all]
podman container rm demo

Then участники отвечают на вопросы

  • Как назвали сценарии?
  • Успешна ли сконфигурирована система для использования Podman?
  • Откуда взялся образ диска?
  • Сколько места занимает образ?
  • Сколько места занимает контейнер?
  • Какая версия образа скачивается по умолчанию?
  • Какая гостевая команда запускается при запуске контейнера?

Жизненный цикл готового образа 30

Зачем нужен образ

  • Задача среды исполнения контейнеров: изоляция нашего ПО от хоста
  • Отображение диска контейнера на диск хоста: образ

Что хранит образ

  • Что должно быть на диске для запуска и работы контейнеризованного приложения?
  • Состав образа диска (от scratch до prod-ready)
  • OS libraries
  • OS package manager (для удобной установки зависимостей, нужен на этапе сборки образа)
  • OS commands (для отладки, мониторинга и траблшутинга контейнеров на этапе эксплуатации)
  • Application libraries
  • Application executables
  • Config files
  • Data files
$ podman run --rm -it alpine:3.14 ls
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var

Как идентифицируется образ

$ podman images
REPOSITORY                TAG         IMAGE ID      CREATED       SIZE
quay.io/podman/hello      latest      577bf902f284  9 hours ago   85.1 kB
<none>                    <none>      4f391b4bf86f  3 days ago    85.1 kB
docker.io/library/alpine  3.14        376ba31ae3da  2 months ago  5.63 MB
docker.io/library/alpine  latest      a6215f271958  2 months ago  5.58 MB
  • id как хеш образа
  • хост/группа/имя как имя репозитория
  • хост/группа/имя:тег как полное символьное имя

Как создается образ

  • podman container run + side effects > podman container commit > podman image push # редко используемый "ручной" ЖЦ
  • podman image build > podman image push # штатный автоматизированный ЖЦ
  • Overlay FS
$ podman image history quay.io/podman/hello
ID            CREATED       CREATED BY                                     SIZE        COMMENT
577bf902f284  10 hours ago  /bin/sh -c #(nop) LABEL "org.opencontainer...  0 B         FROM d2f3fdcf80a2
<missing>     10 hours ago  /bin/sh -c #(nop) LABEL "org.opencontainer...  0 B         FROM cc07153b17e6
<missing>     10 hours ago  /bin/sh -c #(nop) LABEL "org.opencontainer...  0 B         FROM d45976f9036e
<missing>     10 hours ago  /bin/sh -c #(nop) CMD ["/usr/local/bin/pod...  0 B         FROM aeedbc3e44e3
<missing>     10 hours ago  /bin/sh -c #(nop) COPY file:d246003209ea6b...  80.9 kB     FROM a796bd9429dc
<missing>     10 hours ago  /bin/sh -c #(nop) USER 1000                    0 B         FROM 190f78d5a9fb
<missing>     10 hours ago  /bin/sh -c #(nop) LABEL artist="Máirín N...    0 B         FROM 78ab72a99b9f
<missing>     10 hours ago  /bin/sh -c #(nop) LABEL maintainer="Podman...  0 B
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nate/dockviz images -t
├─<missing> Virtual Size: 5.6 MB
│ └─<missing> Virtual Size: 5.6 MB
│   └─<missing> Virtual Size: 5.6 MB
│     └─<missing> Virtual Size: 19.8 MB
│       └─<missing> Virtual Size: 19.8 MB
│         └─<missing> Virtual Size: 19.8 MB
│           └─<missing> Virtual Size: 116.7 MB
│             └─<missing> Virtual Size: 116.7 MB
│               ├─<missing> Virtual Size: 116.7 MB
│               │ └─<missing> Virtual Size: 116.7 MB
│               │   └─<missing> Virtual Size: 116.7 MB
│               │     └─<missing> Virtual Size: 136.7 MB
│               │       └─<missing> Virtual Size: 136.7 MB
│               │         └─3c1355b22f16 Virtual Size: 136.7 MB Tags: training-docker/ekr-stub:1.0.0
│               └─<missing> Virtual Size: 116.7 MB
│                 └─<missing> Virtual Size: 116.7 MB
│                   └─<missing> Virtual Size: 116.7 MB
│                     └─<missing> Virtual Size: 116.7 MB
│                       └─e96641ea7cdf Virtual Size: 182.6 MB Tags: training-docker/ekr-backend:1.0.0
  • Как управлять образами c Crane

Hands-on practice quest #01: Pre-built disk image lifecycle 20 + 10

Given

  • пары участников

When участники именуют сценарии, выполняют команды и анализируют их вывод и поведение

  • Сценарий "Как посмотреть список образов?"
podman image ls # TODO: собственные пометки участников для будущего использования в проектах
  • Сценарий "Как скачать образ из репы?"
podman image pull {{ registry-host }}/{{ os-images-path }}/alpine:3.14
podman image ls
  • Сценарий "Как посмотреть историю создания образа и его описание (слои)?"
podman image history {{ registry-host }}/{{ os-images-path }}/alpine:3.14
podman image inspect {{ registry-host }}/{{ os-images-path }}/alpine:3.14 [| jq]
  • Сценарий "Как посмотреть изменения в контейнере и сохранить их?"
podman container run --name demo -it {{ registry-host }}/{{ os-images-path }}/alpine:3.14 # run = pull + start
/# touch side-effect.txt
/# exit
podman container diff demo # используется нотация Git
podman container commit demo {{ registry-host }}/container-training-docker/{{ registry-account }}/demo # фиксируем изменения и получаем новый образ
podman image ls
  • Сценарий "Как повесить тэг на образ?"
podman image tag {{ registry-host }}/container-training-docker/{{ registry-account }}/demo:latest {{ registry-host }}/container-training-docker/{{ registry-account }}/demo:1.0.0 # нужно указывать целиком символьное имя
podman image ls
  • Сценарий "Как опубликовать образ в репу?"
podman image push {{ registry-host }}/container-training-docker/{{ registry-account }}/demo:1.0.0
  • Сценарий "Как удалить контейнер / удалить образ из репы?"
podman image ls
podman container rm demo # удаляем контейнер
podman image prune  # удаляем "подвисшие" образы -> образы, которые не имеют имени и тэга 
podman image ls
podman image rm {{ registry-host }}/container-training-docker/{{ registry-account }}/demo:1.0.0 # untag = unlink в Linux
podman image ls
podman image rm {{ registry-host }}/container-training-docker/{{ registry-account }}/demo:latest
podman image ls
podman image prune --all # удаляем неиспользуемые(!) образы = нет запущенного контейнера и нет остановленного контейнера

Then участники делятся проблемами и отвечают на вопросы

  • Как назвали сценарии?
  • Какой тег у образа по умолчанию?
  • В чем физический смысл удаления образа командой rm?
  • Всегда ли удаляется образ по команде rm?
  • Что делает prune?
  • Что такое dangling image?

Жизненный цикл пода и контейнера 30

  • container = running process + container data (container layer)

  • Что значит "запуск" контейнера? Что именно там запускается?

  • Сколько по времени будет работать контейнер?

  • Как можно доопределить команду, запускаемую в контейнере?

  • Что нужно определить для запуска контейнера?

  • disk image

  • меппинг (форвардинг) портов

  • имя контейнера (+defaults)

  • virtual network

  • folder | volume mapping

  • guest environment variables

  • command line (image entrypoint override)

  • command line arguments (image cmd override)

  • Экстернализация конфигурации приложения

  • Задачи экстернализации конфигурации приложения

  • Способы: --env и аргументы командной строки

  • Жизненный цикл контейнера

  • podman container create + podman container start = podman container run [args]

  • podman container commit

  • podman container ls [--all]

  • podman container logs

  • podman container stop & podman container kill

  • podman container rm

  • Запуск контейнера в интерактивном и фоновом режимах:

  • -i vs -d

  • -t

  • Жизненный цикл пода

  • podman pod create & podman container run --pod [new:]

  • podman pod ps

  • podman pod ls

  • podman pod logs

  • podman pod stop

  • podman pod rm

Hands-on practice quest #02: Pod and Container lifecycle 20 + 10

Given

  • пары участников

When участники именуют сценарии, формируют свои сценарии и проверяют их вывод и поведение

  • Сценарий "Как посмотреть список работающих и остановленных контейнеров?"
podman container ls --all
  • Сценарий "Как запустить 'одноразовый' контейнер?"
podman container run --rm -it {{ registry-host }}/{{ os-images-path }}/alpine:3.14 # note `--rm`
/# exit
podman container ls --all
  • Сценарий "Как запустить контейнер в фоновом режиме?"
podman container run --detach --name proxy --publish 8080:80 {{ registry-host }}/{{ software-images-path }}/nginx:1.19.4 # note `--detach` or `-d`
podman container ls
curl localhost:8080
  • Сценарий "Как 'подключиться' к работающему контейнеру?"
podman container logs proxy

podman container attach --sig-proxy=false proxy # otherwise detach key `ctrl-c` will stop container 

podman container top proxy

podman container exec -it proxy /bin/sh # run additional process `sh` within _running_ container
  • Сценарий "Как посмотреть свойства контейнера?"
podman container port proxy
podman container inspect proxy [| jq]
  • Сценарий "Как остановить и перезапустить работающий контейнер?"
podman container stop ... # send SIGTERM, and then SIGKILL after grace period
podman container kill ... # send SIGKILL, or specified signal

podman container start ...
podman container restart ...
  • Сценарий "Как удалить работающий контейнер?"
podman container rm --force
  • Сценарий "Как удалить остановленный контейнер?"
podman container rm ...
podman container prune ...
  • Сценарий "Как создать под?"
podman ...
  • Сценарий "Как запустить контейнер с добавлением его в под?"
podman ...
  • Сценарий "Как посмотреть список подов?"
podman ...
  • Сценарий "Как посмотреть список контейнеров в поде?"
podman pod ps
podman ps -a --pod
podman pod inspect ...
  • Сценарий "Как посмотреть логи контейнеров в поде?"
podman logs --latest ...
  • Сценарий "Как сгенерировать k8s manifest из готового пода?"
podman generate kube ...
  • Сценарий "Как остановить под?"
podman ...

Then участники делятся проблемами и отвечают на вопросы

  • Какие способы идентификации контейнера?
  • Какое имя у контейнера по умолчанию?
  • Где можно определить конфигурацию сети (например, меппинг портов) – для контейнера или для пода?
  • Что за логи наблюдаются для контейнера и пода?
  • В чем физический смысл удаления контейнера?
  • В чем физический смысл удаления пода?
  • Что делает container prune?
  • Что такое k8s manifest?

Контейнеризация простого сервиса: автоматическая сборка образа 40

Задачи автоматических сборщиков

  • На выходе бинарный файл образа
  • На входе дескриптор сборки образа Containerfile/Dockerfile
  • Что должно быть в этом дескрипторе?

Как собрать с Containerfile и Buildah под капотом

podman container run [--entrypoint Dockerfile's ENTRYPOINT override] IMAGE [Dockerfile's CMD defaults override] 
FROM alpine
ENTRYPOINT ["echo", "Hello"]
CMD ["World"] # 'default parameters to ENTRYPOINT' form
...
$ podman build --tag test .
...
$ podman run --rm test
Hello World
...
$ podman run --rm test Alpine
Hello Alpine
  • Системные образы для базы VS прикладные образы с приложениями

  • Кратко по оптимизации сборки:

  • Сборка FROM scratch, "пинцетный метод"

  • Использование легковесных базовых образов

alpine 5.33MB
registry.access.redhat.com/ubi8/ubi-micro 51.6MB
debian:stable-slim 74.3MB
  • Понятие build context и кеширование при сборке (+ .dockerignore)
  • Изменение порядка директив в Dockerfile, чтобы максимально повторно использовать кеш builder
  • Объединение директив, чтобы снизить количество слоёв образа
  • Multi-stage build, чтобы не тащить в итоговый образ инфраструктуру сборки
  • Объединение слоёв образа в один слой

Hands-on practice quest #03: Simple java application containerization with Buildah 30 + 10

Given

  • Склонирован git repo c приложением
application
└── backend
    ├── Containerfile
    └── dbo-1.0-SNAPSHOT.jar
  • Задана рабочая папка
cd application
  • Проведена аутентификация консольного Podman CLI в Registry
podman login ...

When участники именуют сценарии, формируют свои команды и проверяют их вывод и поведение

  • Сценарий "Как собрать образ на основе Containerfile?"
vi backend/Containerfile # Replace base image with one that suitable for corporate image registry
podman image build \
  --tag {{ registry-host }}/container-training-docker/{{ registry-account }}/app:1.0.0 \ # set up symbolic name for image
  ./backend # folder where Containerfile located

podman image ls
  • Сценарий "Как запустить 'одноразовый' контейнер на базе своего образа с приложением?"
podman container run \
 --name backend \
 --rm \ # одноразовый: удалится после остановки
 --detach \ # -d
 --publish 8080:8080 \ # -p [host address:]8080:8080
 --env SPRING_PROFILES_ACTIVE=qa \ # -e: в контейнере действует переменная окружения
 {{ registry-host }}/container-training-docker/{{ registry-account }}/app:1.0.0 \ #  имя и тег
  --spring.profiles.active=qa # параметры командной строки
  • Сценарий "Как протестировать запущенное в контейнере приложение?"
podman container ls --all # Check for status

curl localhost:8080/dbo/actuator/health
open http://localhost:8080/dbo/swagger-ui/
  • Сценарий "Как мягко остановить приложение средствами самого приложения?"
curl -X POST localhost:8080/dbo/actuator/shutdown
  • Сценарий "Как опубликовать проверенный образ в репозитории?"
podman image push ...

Then участники делятся проблемами и отвечают на вопросы

  • В каком порядке выполнялись директивы Dockerfile?
  • Сколько новых layers добавила сборка к базовому образу?
  • Когда и по какой причине остановился контейнер?
  • Что происходит с процессом приложения, когда останавливаем контейнер?
  • Сколько раз вы столкнулись с настройкой экстернализированной конфигурации приложения?

Изоляция данных 20

  • Что происходит с изменениями в образе при остановке контейнера?
  • Как зафиксировать изменения в образе?
  • Как откатить изменения в образе?
  • Как можно сохранять изменения на диске вне образа? (stateful containers): mounts
  • tmpfs
podman container run 
 --tmpfs /tmp
 --tmpfs /var/log
 --tmpfs /dbo/log 
  • shared folders
podman container run --volume "$(pwd)"/folder/file:/folder/file:ro # пути у folder абсолютные, начинаются с "/"
  • volumes
podman container run --volume my_volume:/folder/file:ro # имя volume не начинается с "/"
  • Логи
  • консольные логи: stdout/stderr
  • собираются и упаковываются в выбранный формат (определяется log driver)
podman logs [--until=10s] ...

Hands-on practice quest #04: Simple stateful application containerization 20 + 10

Given

  • Собран образ с приложением

When участники именуют сценарии, формируют свои команды и проверяют их вывод и поведение

  • Сценарий "Как запустить stateful container c пробросом на хостовую папку?"
podman container run \
 -- ... \ # TODO имя контейнера
 -- ... \ # TODO одноразовый: удалится после остановки
 -- ... \ # TODO фоновой режим
 -- ... \ # TODO проброс порта на хост
 -- ... \ # TODO профиль конфигурации Spring 'qa'
 --volume $(pwd)/log:/dbo/log \ # -v: папка в конейнере /dbo/log отображена на папку на хосте /current-path/log. Windows caution for $()!
 {{ registry-host }}/container-training-docker/{{ registry-account }}/app:1.0.0

cat $(pwd)/log/dbo.log

Then участники делятся проблемами и отвечают на вопросы

  • В данных сценариях какой тип mount лучше подойдет? tmpfs, shared folder, volume?

Оркестрация 40

Задачи оркестраторов

Управление группой контейнеров с Podman Compose

cd application
podman-compose up --detach

podman-compose ps
podman-compose logs

podman-compose down

Hands-on practice quest #05: Multi-component stateful application containerization with Compose 30 + 10

Given

  • Установлен Podman Compose
sudo dnf install -y pip
pip3 install https://github.com/containers/podman-compose/archive/devel.tar.gz

When

  • Сценарий "Как запустить группу контейнеров под управлением Compose?"
cd application
podman-compose up --detach
  • Сценарий "Как наблюдать контейнеры под управлением Compose?"
cd application
podman-compose ps
podman-compose port
podman-compose logs
  • Сценарий "Как остановить и удалить контейнеры?"
cd application
podman-compose down

Then участники делятся проблемами и отвечают на вопросы

  • Можно ли наблюдать контейнеры средствами podman, а не Compose?

Рекомендуемые практики 30

  1. Используйте минимальные образы: быстрее и меньше зависимостей + меньше рисков
  2. Запуск в rootless mode
  3. Подписывать образы и проверять подписи
  4. Сканеры уязвимостей для образов docker scan --dependency-tree <image>
  5. Линтеры для Dockerfile
  6. COPY вместо ADD + .dockerignore
  7. Фиксированные теги для идентификации образов (Semantic versioning or Unique tags)
  8. Multi-Stage Build в том числе для того, чтобы в итоговый образ не утекли чувствительные данные
  9. Хранение и передача конфигурации и чувствительных данных: Secrets