PunchPolice deny misconduct over viral video of suspect arrested in OyoRTP DesportoEstrela da Amadora supera Fazendense com `bis` de Tom MoustierESPNWeek 7 live: Richard TD run puts Indiana ahead of Ohio State in Big Ten showdownESPN DeportesHaaland se viste de héroe para darle el triunfo al City Premier LeagueThe Jerusalem PostEgypt's Sisi seeks parliament's backing to help defend Saudi Arabia if askedZDF heuteAktuelle Pressemitteilungen des ZDFVanguardTinubu scraps recruitment waiver for federal universities, strengthens autonomyColliderThe 6 Best Sci-Fi Books Released Since 2020, RankedSRF News«Wir haben die Schnauze voll» – Schwere Ausschreitungen bei frankreichweiten ProtestenPremium TimesGunmen kill four vigilantes in Plateau communityNOSPolitie houdt verdachte aan na explosie bij kapperszaak in VlaardingenInteriaZełenski traci nadzieję, mówi bez złudzeń. "Ta decyzja to dopiero początek"
The Daily Newsstand · Free, Always
Saturday, October 17, 2026

Kubernetes без Kubernetes: запускаем Pod с помощью Podman

Translate

Представим, что у нас есть Kubernetes-манифест с двумя контейнерами. Первый запускает Nginx, а второй периодически обновляет HTML-страницу. При этом оба контейнера должны использовать общий каталог и обращаться друг к другу через localhost

Обычно мы можем поднять локальный кластер с помощью kind, выполнить kubectl apply и проверить, что получилось.

Но нужен ли нам целый Kubernetes-кластер, если мы просто хотим посмотреть, как работают контейнеры внутри одного Pod?

Нет.

Есть Podman - инструмент, который умеет запускать привычные контейнеры, как Docker, но при этом поддерживает Pod и даже понимает некоторые Kubernetes-манифесты.

Сегодня попробуем запустить такой Pod без Kubernetes, проверим общую сеть и том, а заодно разберёмся, где заканчиваются возможности Podman и начинается настоящая оркестрация.

Что такое Podman?

Для начала познакомимся с инструментом.

Podman позволяет запускать контейнеры, собирать образы, создавать сети и тома. Если вы когда-нибудь работали с Docker, большая часть команд будет знакомой.

Например, через Docker Nginx запускается так:

docker run -d \
  --name nginx \
  -p 127.0.0.1:8080:80 \
  nginx:alpine

А через Podman:

podman run -d \
  --name nginx \
  -p 127.0.0.1:8080:80 \
  docker.io/library/nginx:alpine

Практически одно и то же. Сборка образов и просмотр контейнеров тоже выглядят привычно:

podman build -t myapp .
podman ps

Есть даже практика установки алиаса podman’у - docker, в таком случае использование этой утилиты почти идентично последнему, а переучиваться на него становится вовсе не нужно.

Есть и отличия. К примеру, в классическом варианте Docker CLI обращается к постоянно работающему демону dockerd. Podman для обычного запуска контейнеров такого центрального демона не требует.

Нас интересует другое.

Podman умеет создавать не только отдельные контейнеры, но и Pod. А ещё он может прочитать Kubernetes YAML и запустить описанные в нём контейнеры локально

Получается довольно любопытное сочетание: привычные задачи Docker и часть модели, с которой мы обычно сталкиваемся в Kubernetes.

Картинка №1

Картинка №1

Давайте разберёмся, как это устроено.

Вспомним, что такое Pod

В Kubernetes Pod - минимальная единица развёртывания. Внутри него может находиться один контейнер или несколько, если им нужно работать вместе.

Например, один контейнер запускает веб-сервер, а второй подготавливает для него файлы.

У контейнеров одного Pod есть важная особенность - они разделяют сетевое пространство имён. Поэтому оба используют общий IP-адрес Pod и могут обращаться друг к другу через localhost.

А вот файловые системы контейнеров сами по себе остаются отдельными. Чтобы обмениваться файлами, нужно подключить общий volume

Картинка №2

Картинка №2

Получается, Pod - это не просто список контейнеров. Это группа контейнеров с определёнными настройками изоляции и общими ресурсами

Но ведь сетевые пространства имён и тома - механизмы Linux и контейнерных движков. Обязательно ли запускать весь Kubernetes, чтобы ими воспользоваться?

Нет. И сейчас мы в этом убедимся.

Устанавливаем Podman

Для лабораторной будем использовать Linux. Например, Ubuntu или Fedora.

На debian-подобных системах:

sudo apt update
sudo apt install -y podman

Для менеджера пакетов dnf:

sudo dnf install -y podman

Проверим, что всё установилось:

podman --version
podman info

Дальше будем выполнять команды от обычного пользователя, без sudo.

Создадим отдельный каталог:

mkdir podman-kube-lab
cd podman-kube-lab

Теперь можно перейти к первому эксперименту

Почему два контейнера не могут общаться через localhost?

Прежде чем создавать Pod, давайте попробуем обойтись без него.

Запустим обычный Nginx:

podman run -d \
  --name test-nginx \
  docker.io/library/nginx:alpine

Теперь из второго контейнера попробуем обратиться к 127.0.0.1:80:

podman run --rm \
  docker.io/library/alpine:3.21 \
  wget -qO- http://127.0.0.1:80

Что произойдёт?

Скорее всего, увидим ошибку подключения. Хотя Nginx запущен и слушает порт 80.

Всё дело в localhost.

Каждый контейнер в таком запуске находится в отдельном сетевом пространстве имён. Когда второй контейнер обращается к 127.0.0.1, он обращается к самому себе, а не к первому контейнеру.

Картинка №3

Картинка №3

Конечно, это не означает, что обычные контейнеры не умеют общаться друг с другом. Для этого можно использовать общую сеть и DNS-имена.

Но нас интересует именно поведение Kubernetes Pod, где localhost общий.

Удалим тестовый контейнер:

podman rm -f test-nginx

И попробуем другой способ.

Пишем Kubernetes YAML

Создадим файл pod.yaml.

В нём будут два контейнера:

  • web - Nginx, который отдаёт HTML-страницу;

  • sidecar - Alpine, который каждые пять секунд обновляет эту страницу и проверяет Nginx по localhost.

Для обмена файлами добавим emptyDir.

Показать YAML манифест Pod
apiVersion: v1
kind: Pod
metadata:
  name: pod-lab

spec:
  containers:
    - name: web
      image: docker.io/library/nginx:alpine
      ports:
        - containerPort: 80
      volumeMounts:
        - name: site
          mountPath: /usr/share/nginx/html

    - name: sidecar
      image: docker.io/library/alpine:3.21
      command: ["/bin/sh", "-c"]
      args:
        - |
          while true; do
            date -u > /site/index.html

            if wget -qO- http://127.0.0.1:80 > /dev/null; then
              echo "nginx is responding"
            else
              echo "nginx is not ready"
            fi

            sleep 5
          done
      volumeMounts:
        - name: site
          mountPath: /site

  volumes:
    - name: site
      emptyDir: {}

Первый контейнер запускает Nginx, а второй каждые пять секунд записывает текущую дату в файл /site/index.html.

Оба контейнера используют один том site, но подключают его в разные каталоги. Для Nginx это /usr/share/nginx/html, а для sidecar - /site.

То есть sidecar записывает файл, который Nginx затем отдаёт по HTTP.

И ещё один момент: sidecar обращается к Nginx по адресу 127.0.0.1:80. Пока мы просто описали нужное поведение в Kubernetes YAML.

Самое интересное - для запуска этого файла мы не будем использовать kubectl.

Запускаем Pod без Kubernetes

Выполним:

podman kube play \
  --publish 127.0.0.1:8080:80 \
  pod.yaml

Команда podman kube play читает Kubernetes YAML и создаёт Pod и контейнеры из поддерживаемых полей манифеста.

Параметр --publish открывает Nginx на 127.0.0.1:8080 нашего компьютера

Проверим результат:

podman pod ps
podman ps --pod

Мы должны увидеть Pod pod-lab, два наших контейнера и служебный infra-контейнер. Последний помогает Podman организовать общие пространства имён.

А где же Kubernetes?

Его нет. Мы не запускали API Server, Scheduler или kubelet. Podman самостоятельно создал контейнеры на текущем хосте.

Теперь посмотрим, ведут ли они себя так, как мы ожидаем от Kubernetes Pod.

Проверяем общий volume

Подождём несколько секунд, чтобы sidecar успел записать файл, и отправим запрос:

curl http://127.0.0.1:8080

В ответ должна прийти дата, например:

Sat Oct 17 12:00:00 UTC 2026

Точная дата, конечно, будет другой.

Откуда Nginx взял этот файл? Ведь мы не собирали собственный образ и ничего в него не копировали.

Его создал sidecar. Общий emptyDir позволил одному контейнеру записать файл, а другому - прочитать.

Подождём ещё немного:

sleep 6
curl http://127.0.0.1:8080

Время должно измениться.

Итак, контейнеры обмениваются данными через общий том. При этом их файловые системы не стали одной общей файловой системой. Они разделяют только тот каталог, который мы явно подключили

Проверяем localhost

Вспомним эксперимент с двумя независимыми контейнерами. Тогда второй контейнер не мог обратиться к Nginx через 127.0.0.1.

Но в нашем YAML sidecar выполняет точно такой же запрос:

wget -qO- http://127.0.0.1:80

Посмотрим его сообщения:

podman pod logs pod-lab

Среди логов должны появляться строки:

nginx is responding

В самом начале можно увидеть и nginx is not ready. Это нормально - sidecar мог сделать запрос раньше, чем веб-сервер начал принимать подключения.

Почему теперь всё работает?

Потому что оба контейнера находятся в одном Pod и разделяют сетевое пространство имён. Для них 127.0.0.1 указывает на одну и ту же сетевую среду.

Картинка №4

Картинка №4

Получается, мы воспроизвели сразу два важных свойства Kubernetes Pod - общий localhost и совместное использование тома.

И всё это без Kubernetes-кластера

А разве Docker не умеет так же?

Умеет, и об этом важно сказать.

Через Docker Compose можно создать два контейнера с общим volume. А если нужен именно общий сетевой namespace, для второго сервиса существует настройка:

network_mode: "service:web"

Поэтому само по себе взаимодействие двух контейнеров не является уникальной возможностью Podman.

Но у нашего эксперимента есть одна важная деталь.

Мы взяли обычный Kubernetes-манифест и запустили его без kubectl, без kind и без собственного Kubernetes-кластера.

Нам не пришлось переписывать описание в Docker Compose или вручную создавать Pod из отдельных команд.

И вот здесь Podman начинает выглядеть интереснее обычной замены команды docker на podman.

Он решает привычные контейнерные задачи, но одновременно позволяет работать с Pod и некоторыми ресурсами Kubernetes. Что-то вроде промежуточного инструмента между контейнерным движком и отдельными возможностями Kubernetes

Но можно ли пойти дальше и полностью заменить им кластер?

Где заканчивается Podman и начинается Kubernetes?

Пока мы запускали один Pod, всё выглядело довольно похоже.

Но Kubernetes нужен не только для запуска контейнеров. Важная часть его работы - поддержание желаемого состояния приложения.

Например, мы можем создать Deployment с тремя репликами. Если один из управляемых Pod исчезнет, Kubernetes создаст новый, чтобы снова получить нужное количество реплик.

Попробуем проверить, что будет у нас.

Удалим наш Pod:

podman kube down pod.yaml

Проверим:

podman pod ps

Pod исчез. Если немного подождать и повторить проверку, сам по себе он не появится.

Причина проста: podman kube play создал контейнеры по YAML, но не запустил контроллеры Kubernetes, которые постоянно следят за желаемым состоянием.

Правда, здесь есть важная тонкость.

Если создать в Kubernetes обычный Pod напрямую, без Deployment или другого контроллера, после удаления он тоже не восстановится автоматически. Новые Pod создаёт именно контроллер, а не сам факт запуска в Kubernetes.

Podman поддерживает некоторые Kubernetes-ресурсы, включая Deployment, но это не означает, что на машине появился полноценный Deployment Controller. Он не выполняет постоянное согласование состояния, как настоящий кластер.

Картинка №5

Картинка №5

Именно здесь проходит граница между запуском контейнеров и оркестрацией.

Podman может создавать Pod и управлять их контейнерами на одном хосте. Kubernetes добавляет контроллеры, планирование по нодам, сервисы, реплики, обновления и другие механизмы полноценного кластера.

Тогда для чего использовать Podman?

Вернёмся к вопросу из начала статьи.

Podman интересен не потому, что якобы заменяет Docker и Kubernetes одновременно. Это было бы слишком громким обещанием.

Скорее он позволяет использовать один инструмент в нескольких сценариях:

  • запустить обычный контейнер или собрать образ привычными командами;

  • объединить несколько контейнеров в Pod;

  • проверить поддерживаемый Kubernetes-манифест без запуска кластера;

  • изучить общую сеть и тома Pod на локальной машине.

Но когда понадобятся настоящие Service, Deployment Controller, планирование между нодами или полноценная проверка поведения Kubernetes API, лучше использовать кластер. Например, локальный kind

И ещё одна оговорка: podman kube play поддерживает не все поля и ресурсы Kubernetes. Поэтому любой попавшийся YAML нельзя считать гарантированно совместимым с Podman.

Заключение

Сегодня мы запустили Kubernetes Pod без Kubernetes.

С помощью Podman создали два контейнера из обычного YAML-манифеста, проверили работу общего тома и разобрались, почему контейнеры одного Pod могут обращаться друг к другу через localhost.

Но заодно выяснили ещё одну вещь.

Podman - это не просто альтернативная команда для запуска Docker-образов. Он умеет работать и с отдельными контейнерами, и с Pod, и с частью Kubernetes-манифестов.

Однако создавать Pod и управлять целым Kubernetes-кластером - разные задачи. Podman может пригодиться для локального эксперимента или проверки простой конфигурации, но полноценные механизмы оркестрации он не заменяет.

Получается довольно удобный инструмент: когда нужен один контейнер - запускаем контейнер, когда хотим посмотреть на Pod - создаём Pod, а когда требуется настоящий Kubernetes - поднимаем кластер

А вы использовали podman kube play или для таких экспериментов обычно сразу запускаете kind?

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.