Kubernetes — это управляющий механизм общего назначения, который прекрасно подходит не только для запуска приложений, но и для создания образов контейнеров. Паттерн Image Builder (Построитель образов) объясняет, почему имеет смысл создавать образы контейнеров в кластере и какие методы создания образов существуют сегодня в Kubernetes.
Все паттерны, представленные выше в этой книге, касались работы приложений в Kubernetes. Мы узнали, как разрабатывать и подготавливать наши приложения для работы в облачном окружении. Но как собираются сами приложения? Классический подход заключается в создании образов контейнеров вне кластера, добавлении их в реестр и использовании ссылок на них в описаниях развертываний Deployment. Однако сборка образов контейнеров внутри кластера имеет несколько преимуществ.
Если экономическая политика компании позволяет иметь только один кластер для всего, тогда сборка и запуск приложений в одном месте могут значительно снизить затраты на обслуживание. Это также упрощает планирование емкости и снижает затраты на потребление ресурсов.
Как правило, для сборки образов используются системы непрерывной интеграции (Continuous Integration, CI), такие как Jenkins. Сборка с помощью CI-системы — это задача планирования, эффективного поиска свободных вычислительных ресурсов для заданий на сборку. В основе
Непривилегированная сборка
Когда сборка выполняется в Kubernetes, кластер полностью контролирует ее процесс, но ему также нужны более высокие стандарты безопасности, поскольку сборка выполняется не изолированно. Для сборки в кластере важно, чтобы она запускалась без привилегий root. К счастью, в настоящее время существует множество способов организовать сборку в так называемом непривилегированном режиме, когда не требуется повышенных привилегий.
Проект Docker достиг больших успехов в массовом распространении контейнерных технологий благодаря своим непревзойденным возможностям. Docker основан на архитектуре клиент-сервер с демоном Docker, работающим в фоновом режиме и получающим инструкции от клиента через REST API. Привилегии root нужны этому демону в основном для управления сетью и томами. К сожалению, такой подход создает угрозу безопасности, поскольку злоумышленник может просочиться в контейнеры ненадежных процессов и получить контроль над всем хостом. Эта проблема относится не только к выполнению контейнеров, но и к их сборке, потому что сборка также происходит внутри контейнера, когда демон Docker выполняет произвольные команды.
Со временем было создано множество проектов с целью дать возможность выполнять сборку в Docker без привилегий root и сузить круг возможностей для злоумышленников. Некоторые из них (например, Jib) запрещают запускать команды во время сборки, другие используют иные методы. На момент написания этой книги самыми известными инструментами создания образов без повышенных привилегий были img, buildah и Kaniko. Кроме того, система S2I, описанная в разделе «Из исходного кода в образ» ниже, также выполняет сборку образов без привилегий root.
Kubernetes лежит очень сложный планировщик, который идеально подходит для такого рода задач.
При использовании методологии непрерывной доставки (Continuous Delivery, CD), когда требуется организовать переход от создания образов к работающим контейнерам, если сборка происходит в том же кластере, оба этапа используют одну и ту же инфраструктуру, что упрощает переход. Например, предположим, что в образе, используемом в качестве основы для всех приложений, обнаружена новая уязвимость. Когда ваша команда исправит эту проблему, вам придется пересобрать все образы приложений, которые зависят от этого базового образа, и заменить запущенные приложения новыми образами. В случае, если реализован паттерн Image Builder (Построитель образов), кластер будет знать, как собрать образ и как его развернуть, и сможет автоматически выполнить повторное развертывание после изменения базового образа. Ниже, в разделе «Сборка в OpenShift», я расскажу, как такая автоматизация реализуется в OpenShift.
А теперь, выяснив, какие преимущества дает сборка образов внутри платформы, посмотрим, какие существуют методы создания образов в кластере Kubernetes.
Один из первых и наиболее зрелых способов сборки образов в кластере Kubernetes основан на использовании подсистемы сборки в OpenShift. Она поддерживает несколько вариантов сборки образов. Один из них — сборка образа из исходных кодов (Source-to-Image, S2I) — консервативный способ организации сборки с использованием так называемых построителей образов. Мы подробнее рассмотрим S2I и способ сборки образов в OpenShift в разделе «Сборка в OpenShift» ниже.
Другой механизм сборки образов внутри кластера основан на использовании Knative Build. Этот инструмент работает поверх Kubernetes и сетки служб Istio и является одной из основных частей Knative (https://cloud.google.com/knative/), платформы для создания, развертывания и управления бессерверными приложениями. На момент написания этой книги Knative все еще считался очень молодым проектом и продолжал быстро развиваться. В разделе «Knative Build» я кратко расскажу о проекте Knative и приведу примеры сборки образов в кластере Kubernetes с помощью Knative Build.
Начнем знакомство с механизмами сборки с OpenShift.
Red Hat OpenShift — это корпоративный дистрибутив Kubernetes. Кроме поддержки всего того, что поддерживает Kubernetes, он добавляет несколько дополнительных функций, востребованных на предприятиях, таких как интегрированный реестр образов контейнеров, поддержка единой службы авторизации и новый пользовательский интерфейс, а также добавляет в Kubernetes возможность создания собственных образов. Для сообщества открытого программного обеспечения выпускается дистрибутив OKD (https://www.okd.io/) — ранее известный как OpenShift Origin, — поддерживающий все возможности OpenShift.
Дистрибутив OpenShift стал первым предложившим интегрированную в кластер возможность сборки образов под управлением Kubernetes. Он поддерживает несколько стратегий создания образов:
Принимает исходный код приложения и создает выполняемый артефакт с помощью построителя образа S2I для конкретного языка, а затем помещает образы в интегрированный реестр.
Использует Dockerfile плюс каталог контекста и создает образ, как это сделал бы демон Docker.
Представляет процесс сборки в виде серии заданий, выполняющихся под управлением сервера Jenkins, позволяя пользователю настроить конвейер Jenkins на свой лад.
Дает полный контроль над процессом сборки образов. В этом случае вы должны сами создать образ в контейнере для сборки и отправить его в реестр.
Данные для сборки могут извлекаться из разных источников.
Репозиторий, откуда извлекаются исходные данные, определяется в виде URL.
Файл Dockerfile, который доступен непосредственно, как часть ресурса конфигурации сборки.
Образ другого контейнера, из которого извлекаются файлы для текущей сборки. Поддержка этого типа источников дает возможность выполнять конвейерную сборку, как будет показано в листинге 25.2.
Этот ресурс можно использовать для передачи конфиденциальной информации в процесс сборки.
Источник этого типа предназначен для передачи данных извне, которые должны быть подготовлены перед началом сборки.
Выбор того или иного типа источника зависит от стратегии сборки. Двоичные данные и Git являются взаимоисключающими типами источников. Источники всех остальных типов можно объединять или использовать по отдельности. Ниже, в листинге 25.1, я покажу, как это делается.
Вся информация о сборке определяется в центральном объекте ресурса BuildConfig. Этот ресурс можно создать напрямую, применив его к кластеру, или с помощью клиента командной строки oc, который является эквивалентом kubectl в OpenShift. Клиент oc поддерживает команду build, с помощью которой можно определить настройки сборки и запустить ее.
Прежде чем взглянуть на BuildConfig, мы должны разобраться с двумя дополнительными понятиями, характерными для OpenShift.
ImageStream — это ресурс OpenShift, который ссылается на один или несколько образов контейнеров. Он имеет некоторое сходство с репозиторием Docker, который также содержит несколько образов с разными тегами. OpenShift отображает фактический образ с тегом в ресурс ImageStreamTag так, что ImageStream (репозиторий) получает список ссылок на ресурсы ImageStreamTag (образы с тегами). Зачем нужна эта дополнительная абстракция? Она позволяет OpenShift генерировать события для ImageStreamTag при обновлении образа в реестре. Образы создаются во время сборки или когда образ помещается во внутренний реестр OpenShift. При таком подходе механизм сборки или развертывания получает возможность прослушивать эти события и запускать новую сборку или развертывание.
Для подключения ImageStream к развертыванию вместо Kubernetes-ресурса Deployment OpenShift использует ресурс DeploymentConfig, который может содержать только ссылки на образы контейнеров. Тем не менее в OpenShift все равно можно использовать ресурсы Deployment, если не планируется использовать ресурсы ImageStream.
Другое понятие — триггер, который можно рассматривать как обработчик событий. Одним из возможных триггеров является imageChange, который реагирует на события, публикуемые при изменении ImageStreamTag. В качестве реакции такой триггер может, например, запустить повторную сборку другого образа или повторное развертывание подов, основанных на этом образе. Узнать больше о триггерах и их разновидностях можно в документации OpenShift (https://red.ht/2FrDIDj).
Давайте кратко рассмотрим, как выглядит построитель образов S2I. Не вдаваясь в детали, отметим, что построитель образов S2I — это стандартный образ контейнера с набором сценариев S2I, которому мы должны предоставить две обязательные команды:
Сценарий, который вызывается в момент запуска сборки. Его задача — получить исходный код из источников, определяемых настройками, скомпилировать, если необходимо, и скопировать получившиеся артефакты в соответствующие местоположения.
Используется как точка входа для этого образа. OpenShift вызывает этот сценарий при развертывании образа. Сценарий run использует сгенерированные артефакты для запуска приложения.
При желании вы также можете создать сценарий для вывода сообщения о порядке использования, сохраняющий сгенерированные артефакты для так называемых инкрементальных сборок, которые будут доступны сценарию assemble в последующих запусках сборки, или добавляющий некоторые проверки.
Рассмотрим поближе механизм сборки S2I, изображенный на рис. 25.1. Он состоит из двух компонентов: построителя образов и средства ввода исходного кода. Оба объединяются системой сборки S2I в момент, когда происходит запуск сборки — либо триггером, после получения события, либо вручную. Когда сборка образа завершится, например, путем компиляции исходного кода, контейнер копируется в образ и передается в сконфигурированный ImageStreamTag. Этот образ содержит скомпилированные и подготовленные артефакты и сценарий run в качестве точки входа.
Рис. 25.1. Система сборки S2I с источником входных данных Git
В листинге 25.1 показано простое описание сборки с использованием образа построителя Java. Это описание определяет процесс сборки, который получает исходный код и образ построителя, создает выходной образ и передает его в ImageStreamTag. Он может запускаться вручную, командой oc start-build, или автоматически, при изменении образа построителя.
Листинг 25.1. Сборка S2I с использованием образа построителя Java
apiVersion: v1
kind: BuildConfig
metadata:
name: random-generator-build
spec:
source:
git:
uri: https://github.com/k8spatterns/random-generator
strategy:
sourceStrategy:
from:
kind: DockerImage
name: fabric8/s2i-java
output:
to:
kind: ImageStreamTag
name: random-generator-build:latest
triggers:
- type: ImageChange
Ссылка на исходный код, который требуется извлечь; в данном случае он извлекается из репозитория на GitHub.
sourceStrategy включает режим S2I, и образ построителя извлекается непосредственно из Docker Hub.
Определяется ImageStreamTag для передачи сгенерированного образа. Передача выполняется контейнером построителя после выполнения сценария assemble.
Настройка автоматического запуска сборки при изменении образа построителя.
S2I — это надежный механизм для создания образов приложений. Он безопаснее простых механизмов сборки Docker, поскольку процесс сборки протекает под полным контролем проверенных образов построителей. Тем не менее этот подход имеет некоторые недостатки.
S2I может работать очень медленно, особенно когда собирается сложное приложение со множеством зависимостей. В отсутствие какой-либо оптимизации механизм S2I заново загружает все зависимости для каждой сборки. Если Java-приложение собирается с помощью Maven, кэширование не выполняется, как при локальной сборке. Чтобы не загружать зависимости из интернета снова и снова, рекомендуется настроить в кластере внутренний репозиторий Maven, который служит кэшем, а также настроить образ построителя, чтобы он обращался к этому внутреннему репозиторию, а не загружал артефакты из удаленных репозиториев.
Другой способ уменьшить время сборки — использовать инкрементальные сборки с S2I, позволяющие повторно использовать артефакты, созданные или загруженные в предыдущей сборке S2I. Однако из-за того, что большая часть данных копируется из ранее созданного образа в текущий собираемый контейнер, выигрыш в производительности получается небольшим по сравнению с использованием локального кэша в кластере, где хранятся зависимости.
Другой недостаток S2I заключается в том, что сгенерированный образ содержит также все окружение сборки. Это не только увеличивает размер образа, но и расширяет круг возможностей для потенциальной атаки, поскольку инструменты разработчика также могут иметь уязвимости.
Чтобы избавиться от ненужных инструментов сборки, таких как Maven, OpenShift предлагает использовать прием конвейерной сборки, когда из результатов сборки S2I создается уменьшенный образ со средой выполнения. Подробнее этот прием мы рассмотрим в разделе «Конвейерная сборка» ниже.
OpenShift поддерживает также сборку средствами Docker. Такая сборка выполняется путем монтирования сокета демона Docker непосредственно в сборочный контейнер, который затем используется командой docker build. Источником данных для сборки средствами Docker является Dockerfile и каталог контекста. Также можно использовать источник Image, ссылающийся на произвольный образ, откуда извлекаются файлы и копируются в каталог контекста. Как уже говорилось, этот метод вместе с триггерами можно использовать для конвейерной сборки.
Кроме того, есть возможность использовать стандартный многоступенчатый Dockerfile для разделения этапов сборки и среды выполнения. В нашем репозитории с примерами (http://bit.ly/2CxnnuX) вы найдете действующий пример такой многоступенчатой сборки средствами Docker, создающий точно такой же образ, что и конвейерная сборка, описанная в следующем разделе.
Механика конвейерной сборки показана на рис. 25.2. Процесс конвейерной сборки включает этап начальной сборки S2I, на котором создается выполняемый артефакт, например двоичный выполняемый файл. Затем, на втором этапе, обычно выполняемом средствами Docker, этот артефакт извлекается из сгенерированного образа.
Рис. 25.2. Конвейерная сборка с использованием S2I для компиляции и Docker для сборки образа приложения
В листинге 25.2 показана конфигурация второго этапа сборки, который использует файл JAR, сгенерированный в листинге 25.1. Образ, который в конечном итоге передается в ImageStream random-generator-runtime, можно использовать в DeploymentConfig для запуска приложения.
Обратите внимание, что в листинге 25.2 используется триггер, который следит за результатами сборки S2I. Этот триггер автоматически вызывает повторную сборку образа времени выполнения после каждой сборки S2I, поэтому оба ImageStream всегда синхронизированы.
Листинг 25.2. Сборка средствами Docker для создания образа приложения
apiVersion: v1
kind: BuildConfig
metadata:
name: runtime
spec:
source:
images:
- from:
kind: ImageStreamTag
name: random-generator-build:latest
paths:
- sourcePath: /deployments/.
destinationDir: "."
dockerfile: |-
FROM openjdk:8-alpine
COPY *.jar /
CMD java -jar /*.jar
strategy:
type: Docker
output:
to:
kind: ImageStreamTag
name: random-generator:latest
triggers:
- imageChange:
automatic: true
from:
kind: ImageStreamTag
name: random-generator-build:latest
type: ImageCh
Источник ссылается на образ в ImageStream, содержащий результаты сборки S2I, и определяет каталог в образе, где находится скомпилированный архив JAR.
Dockerfile для сборки средствами Docker, который копирует архив JAR из ImageStream, сгенерированного сборкой S2I.
Стратегия, включающая режим сборки средствами Docker.
Повторная сборка запускается автоматически, если результат сборки S2I — ImageStream — изменится и благополучно будет создан новый архив JAR.
Регистрация приемника событий, связанных с изменением образа, и выполнение повторного развертывания после добавления обновленного образа в ImageStream.
Полный пример с инструкциями по установке можно найти в нашем репозитории (http://bit.ly/2CxnnuX).
Как уже упоминалось, сборка в OpenShift, включая наиболее известный режим S2I, является одним из ранних и наиболее зрелых способов безопасной сборки образов контейнеров в кластере Kubernetes.
Теперь рассмотрим другой способ сборки образов контейнеров в кластере Kubernetes без всяких расширений.
В 2018 году компания Google запустила проект Knative с целью привнести в Kubernetes дополнительные возможности, имеющие прямое отношение к приложениям.
Основой для Knative стала сетка служб Istio (https://istio.io/), которая предлагает готовые инфраструктурные службы для управления трафиком, наблюдения и поддержания безопасности. Сетки служб используют паттерн Sidecars (Прицеп) для передачи приложениям новых инфраструктурных возможностей.
Кроме сетки служб, проект Knative предлагает дополнительные службы, в первую очередь предназначенные для разработчиков приложений:
Для поддержки масштабирования до нуля приложений, которые могут использоваться, например, на платформах FaaS (Function-as-a-Service — функция как служба). Наряду с паттерном, описанным в главе 24 «Эластичное масштабирование», и поддержкой сетки служб, Knative Serving позволяет также масштабировать от нуля до произвольного числа реплик.
Для доставки по каналам событий из источников в приемники. События могут запускать службы Service, используемые в роли приемников и масштабируемые от нуля.
Для компиляции исходного кода приложений в образах контейнеров внутри кластера Kubernetes. Продолжением этой службы стал проект Tekton Pipelines, который в конечном итоге заменит Knative Build.
Оба проекта, Istio и Knative, реализованы по паттерну Operator (Operator) и используют определения нестандартных ресурсов (CustomResourceDefinition, CRD) для объявления своих предметных ресурсов.
В оставшейся части этого раздела мы сфокусируем свое внимание на Knative Build реализации паттерна Image Builder (Построитель образов) в Knative.
Проект Knative Build в первую очередь предназначен для разработчиков инструментов, стремящихся предоставить конечному пользователю удобный пользовательский интерфейс и скрыть от него сам процесс сборки. Здесь мы лишь в общих чертах рассмотрим строительные блоки Knative Build. Проект быстро развивается, и в будущем его могут даже заменить последующим проектом, таким как Tekton Pipelines, но основная механика, скорее всего, останется прежней. Однако некоторые детали могут измениться, поэтому обращайтесь к примерам кода (http://bit.ly/2CxnnuX), которые мы постоянно обновляем по мере появления новых версий проектов Knative.
Проект Knative создавался с целью предоставить строительные блоки для интеграции с существующими решениями CI/CD. Это не решение CI/CD для создания образов контейнеров. Ожидается, что со временем будет появляться все больше и больше таких решений, но сейчас давайте посмотрим, какие строительные блоки оно реализует.
Ресурс Build является основой Knative Build. Он определяет конкретные шаги, которые должен выполнить оператор Knative Build. Ниже перечислены основные ингредиенты, использованные в листинге 25.3:
• Параметр source определяет местоположение исходного кода приложения. Исходный код может храниться в репозитории Git, как в листинге 25.3, в других удаленных хранилищах, таких как Google Cloud Storage, или даже в произвольном контейнере.
• Параметр steps описывает шаги, которые нужно выполнить, чтобы превратить исходный код в образ контейнера. Каждый шаг ссылается на образ построителя, используемый для его выполнения. Каждый шаг имеет доступ к тому, смонтированному в каталог /workspace, который содержит исходный код и используется для обмена данными между шагами.
Роль исходного кода в этом примере снова играет наш пример Java-проекта, который размещается в GitHub и собирается с помощью Maven. Образ построителя — это образ контейнера, содержащего Java и Maven. Сборка образа выполняется инструментом Jib (https://github.com/GoogleContainerTools/jib) без привлечения демона Docker и отправляется в реестр.
Листинг 25.3. Сборка Java-проекта в Knative с использованием Maven и Jib
apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: random-generator-build-jib
spec:
source:
git:
url: https://github.com/k8spatterns/random-generator.git
revision: master
steps:
- name: build-and-push
image: gcr.io/cloud-builders/mvn
args:
- compile
- com.google.cloud.tools:jib-maven-plugin:build
- -Djib.to.image=registry/k8spatterns/random-generator
workingDir: /workspace
Имя объекта-построителя.
Ссылка на источник исходного кода с URL репозитория GitHub.
Этапы сборки.
Образ с Java и Maven, который используется на этом этапе сборки.
Аргументы для передачи в контейнер построителя, который запускает Maven для компиляции, создает и пересылает образ контейнера с помощью jib-maven-plugin.
Каталог /workspace — общий для всех этапов сборки.
Также интересно заглянуть внутрь, чтобы узнать, как оператор Knative Build выполняет сборку.
Рис. 25.3. Сборка в Knative с использованием init-контейнеров
На рис. 25.3 показано, как нестандартный ресурс сборки Build превращается в простые ресурсы Kubernetes. Ресурс Build превращается в под, а этапы сборки — в цепочку init-контейнеров, которые вызываются один за другим. Init-контейнеры создаются неявно. В нашем примере один из них предназначен для инициализации учетных данных, необходимых для взаимодействий с внешними репозиториями, второй init-контейнер реализует извлечение исходных кодов из GitHub и третий init-контейнер просто реализует шаги, осуществляющие сборку. Когда все init-контейнеры завершатся, основному контейнеру не останется ничего, как просто завершиться.
Листинг 25.3 определяет только один шаг сборки, но обычно сборка состоит из нескольких шагов. Для определения шагов, многократно используемых в аналогичных сборках, можно использовать ресурс макета сборки BuildTemplate.
Один из таких макетов показан в листинге 25.4. Он определяет три шага:
1. Создание JAR-файла с помощью пакета mvn.
2. Создание Dockerfile, который копирует этот JAR-файл в образ контейнера и запускает его командой java -jar.
3. Создание и отправка образа контейнера с помощью построителя Kaniko. Kaniko — это инструмент, разработанный в компании Google, который предназначен для сборки образов контейнеров из Dockerfile внутри контейнера с помощью локального демона Docker в пространстве пользователя.
Макет BuildTemplate напоминает ресурс Build, но, в отличие от последнего, поддерживает параметры, которые заполняются в момент использования макета. В этом примере используется единственный параметр IMAGE. С его помощью определяется целевой образ.
Листинг 25.4. Макет сборки Knative, использующий Maven и Kaniko
apiVersion: build.knative.dev/v1alpha1
kind: BuildTemplate
metadata:
name: maven-kaniko
spec:
parameters:
- name: IMAGE
description: The name of the image to create and push
steps:
- name: maven-build
image: gcr.io/cloud-builders/mvn
args:
- package
workingDir: /workspace
- name: prepare-docker-context
image: alpine
command: [ .... ]
- name: image-build-and-push
image: gcr.io/kaniko-project/executor
args:
- --context=/workspace
- --destination=${IMAGE}
Список параметров макета.
Этап компиляции и упаковки приложения на Java с помощью Maven.
Этап создания Dockerfile для копирования и запуска сгенерированного JAR-файла. Детали реализации здесь опущены, но вы сможете найти их в примерах на сайте GitHub.
Этап, вызывающий Kaniko для сборки и отправки контейнера.
Адрес отправки образа определяется параметром ${IMAGE}.
Этот макет можно указать в ресурсе Build вместо списка шагов, как показано в листинге 25.5. Как видите, макету достаточно передать параметр с именем образа контейнера приложения, который требуется создать, и его можно использовать для создания различных приложений.
Листинг 25.5. Определение сборки в Knative Build с использованием макета
apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: random-generator-build-chained
spec:
source:
git:
url: https://github.com/k8spatterns/random-generator.git
revision: master
template:
name: maven-kaniko
arguments:
- name: IMAGE
value: registry:80/k8spatterns/random-generator
Определение источника с исходным кодом.
Ссылка на макет, объявленный в листинге 25.4.
Описание образа для передачи в макет в виде параметра.
Множество предопределенных паттернов можно найти в репозитории Knative build-templates.
Этот пример завершает наш краткий тур по Knative Build. Как уже упоминалось, этот проект еще очень молодой и детали его реализации еще могут измениться, но основные механизмы, описанные здесь, должны остаться прежними.
Итак, мы познакомились с двумя способами создания образов контейнеров в кластере. Система сборки OpenShift демонстрирует одно из главных преимуществ, которые дает сборка и запуск приложения в одном кластере. С помощью триггеров ImageStream, реализованных в OpenShift, можно не только связывать вместе несколько сборок, но и повторно развертывать приложение, если в процессе сборки обновится образ контейнера вашего приложения. Это особенно удобно, когда за этапом сборки обычно следует этап развертывания. Интеграция сборки и развертывания — это шаг вперед к святому Граалю технологии непрерывного развертывания. Сборка в OpenShift с помощью S2I — проверенная и доказавшая свою надежность технология, но в настоящее время S2I можно использовать только в дистрибутиве OpenShift платформы Kubernetes.
Knative Build — еще одна реализация паттерна Image Builder (Построитель образов). Основная цель Knative Build — преобразовать исходный код в готовый образ контейнера и передать его в реестр, чтобы потом его можно было загрузить с помощью развертывания Deployment. Эти шаги выполняются построителями образов, специализированными для поддержки разных технологий. Knative Build не зависит от конкретных этапов сборки, но управляет жизненным циклом сборки и ее планированием.
Knative Build — это еще довольно молодой проект (по состоянию на 2019 год), который предлагает строительные блоки для сборки образов в кластере. Он не представляет особого интереса для конечного пользователя и в основном ориентирован на разработчиков инструментов. Можно предположить, что новые и существующие инструменты будут поддерживать Knative Build или другие проекты, основанные на нем, поэтому вы наверняка увидите еще немало реализаций паттерна Image Builder (Построитель образов).
• Примеры построителей паттернов (http://bit.ly/2FpCkkL).
• Jib (https://github.com/GoogleContainerTools/jib).
• Img (https://github.com/genuinetools/img).
• Buildah (https://github.com/projectatomic/buildah).
• Kaniko (https://github.com/GoogleContainerTools/kaniko).
• Описание системы сборки в OpenShift (http://bit.ly/2HILD0E).
• Многоступенчатый Dockerfile (http://bit.ly/2YfUY63).
• Конвейерная сборка с S2I (https://red.ht/2Jqzlw9).
• Триггеры сборки (https://red.ht/2FrDIDj).
• Описание сборки образов из исходных кодов Source-to-Image (https://github.com/openshift/source-to-image).
• Инкрементальные сборки с S2I (https://red.ht/2TSGxp9).
• Knative (https://cloud.google.com/knative/).
• Сборка образов контейнеров в кластере Kubernetes с помощью Knative Build (http://bit.ly/2YJuZUC).
• Knative Build (https://github.com/knative/build).
• Tekton Pipelines (https://github.com/knative/build-pipeline).
• Knative: сборка бессерверной службы (https://red.ht/2Oew8Pj).
• Введение в Knctl: простейший способ использования Knative (https://ibm.co/2Hwnmvw).
• Интерактивное руководство по Knative Build (http://bit.ly/2OewLZb).
• Макеты в Knative Build (https://github.com/knative/build-templates).
Continuous integration/continuous delivery — непрерывная интеграция и развертывание (доставка). — Примеч. пер.