company_banner

Обзор Skaffold для разработки под Kubernetes



    Полтора года назад, 5 марта 2018, компания Google выпустила первую альфа-версию своего Open Source-проекта для CI/CD под названием Skaffold, целью которого стало создание «простой и воспроизводимой разработки под Kubernetes», чтобы разработчики могли сфокусироваться именно на разработке, а не на администрировании. Чем может быть интересен Skaffold? Как оказалось, у него есть несколько козырей в рукаве, благодаря которым он может стать сильным инструментом для разработчика, а может — и инженера по эксплуатации. Познакомимся с проектом и его возможностями.

    NB: Кстати, мы уже рассказывали вкратце про Skaffold в нашем общем обзоре инструментов для разработчиков, жизнь которых связана с Kubernetes.

    Теория. Предназначение и возможности


    Итак, если говорить в общем, то Skaffold решает задачу автоматизации цикла CI/CD (на стадиях build, push, deploy), предлагая разработчику оперативную обратную связь, т.е. возможность быстро получать результат очередных изменений кода — в виде обновлённого приложения, работающего в кластере Kubernetes. А работать оно может в разных контурах (dev, stage, production…), для чего Skaffold помогает описывать соответствующие пайплайны для выката.

    Исходный код Skaffold написан на языке Go, распространяется на условиях свободной лицензии Apache License 2.0 (GitHub).

    Рассмотрим основные функции и особенности. К первым можно отнести следующие:

    • Skaffold предлагает инструментарий для создания CI/CD-пайплайнов.
    • Позволяет в фоновом режиме следить за изменениями в исходном коде и запускать автоматизированный процесс сборки кода в образы контейнеров, публикации этих образов в Docker Registry и их деплоя в кластер Kubernetes.
    • Синхронизирует файлы в репозитории с рабочим каталогом в контейнере.
    • Автоматически тестирует с помощью container-structure-test.
    • Пробрасывает порты.
    • Читает логи приложения, запущенного в контейнере.
    • Помогает в отладке приложений, написанных на Java, Node.js, Python, Go.

    Теперь — об особенностях:

    • У самого Skaffold нет компонентов на стороне кластера. То есть дополнительно настраивать Kubernetes для использования этой утилиты не требуется.
    • Разные пайплайны для вашего приложения. Нужно выкатывать код в локальный Minikube, пока ведете разработку, а после — на stage или production? Для этого предусмотрены профили и пользовательские конфигурации, переменные окружения и флаги, что позволяют описывать разные пайплайны для одного приложения.
    • CLI. Только консольная утилита и конфигурации в YAML. В сети можно найти упоминания попыток создания экспериментального GUI, однако на данный момент это скорее лишь означает, что он кому-то нужен, но не очень.
    • Модульность. Skaffold не является самостоятельным комбайном, а стремится использовать отдельные модули или уже существующие решения для конкретных задач.

    Иллюстрация последнего:

    • На стадии сборки можно использовать:
      • docker build локально, в кластере с помощью kaniko или в Google Cloud Build;
      • Bazel локально;
      • Jib Maven и Jib Gradle локально или в Google Cloud Build;
      • кастомные build-скрипты, запускаемые локально. Если вам нужно запускать другое (более гибкое/привычное/…) решение для сборки, оно описывается в скрипте, чтобы Skaffold запускал именно его (пример из документации). Это позволяет использовать вообще любой сборщик, который можно вызвать с помощью скрипта;
    • На стадии тестирования поддерживается уже упомянутый container-structure-test;
    • Для деплоя предусмотрены:
      • Kubectl;
      • Helm;
      • kustomize.

    Благодаря этому Skaffold можно назвать своеобразным фреймворком для построения CI/CD. Вот пример рабочего процесса при его использовании (из документации проекта):



    Как в общих чертах выглядит работа Skaffold?

    1. Утилита следит за изменениями в директории с исходным кодом. Если в файлы вносятся модификации, они синхронизируются с pod’ом приложения в кластере Kubernetes. Если это возможно — без повторной сборки образа. В ином случае — собирается новый образ.
    2. Собранный образ проверяется с помощью container-structure-test, тегируется и отправляется в Docker Registry.
    3. После этого образ деплоится — разворачивается в кластере Kubernetes.
    4. Если запуск был инициализирован с помощью команды skaffold dev, то мы начинаем получать логи от приложения, а Skaffold ожидает изменений, чтобы повторить все действия заново.



    Иллюстрация основных этапов работы Skaffold

    Практика. Пробуем Skaffold


    Для демонстрации использования Skaffold возьму пример из GitHub-репозитория проекта. Кстати, там же можно найти и множество других примеров, учитывающих различную специфику. Все действия буду выполнять локально в Minikube. Установка простая и займет несколько минут, а для начала работы понадобится kubectl.

    Установим Skaffold:

    curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
    chmod +x skaffold
    sudo mv skaffold /usr/local/bin
    skaffold version
    v0.37.1

    Склонируем себе репозиторий Skaffold'a с нужными примерами:

    git clone https://github.com/GoogleContainerTools/skaffold
    cd skaffold/examples/microservices

    Я выбрал пример с двумя pod’ами, каждый из которых содержит по одному маленькому приложению на Go. Одно приложение — фронтенд (leeroy-web), перенаправляющий запрос на второе приложение — бэкенд (leeroy-app). Посмотрим, как это выглядит:

    ~/skaffold/examples/microservices # tree
    .
    ├── leeroy-app
    │   ├── app.go
    │   ├── Dockerfile
    │   └── kubernetes
    │       └── deployment.yaml
    ├── leeroy-web
    │   ├── Dockerfile
    │   ├── kubernetes
    │   │   └── deployment.yaml
    │   └── web.go
    ├── README.adoc
    └── skaffold.yaml
     
    4 directories, 8 files

    leeroy-app и leeroy-web содержат код на Go и простые Dockerfiles для локальной сборки этого самого кода:

    ~/skaffold/examples/microservices # cat leeroy-app/Dockerfile
    FROM golang:1.12.9-alpine3.10 as builder
    COPY app.go .
    RUN go build -o /app .
     
    FROM alpine:3.10
    CMD ["./app"]
    COPY --from=builder /app .

    Код приложений приводить не буду — достаточно знать, что leeroy-web принимает запросы и проксирует их на leeroy-app. Поэтому в файлах Deployment.yaml существует Service только для app (для внутренней маршрутизации). Порт pod’а web мы будем прокидывать себе для быстрого доступа к приложению.

    Как выглядит skaffold.yaml:

    ~/skaffold/examples/microservices # cat skaffold.yaml
    apiVersion: skaffold/v1beta13
    kind: Config
    build:
      artifacts:
        - image: leeroy-web
          context: ./leeroy-web/
        - image: leeroy-app
          context: ./leeroy-app/
    deploy:
      kubectl:
        manifests:
          - ./leeroy-web/kubernetes/*
          - ./leeroy-app/kubernetes/*
    portForward:
      - resourceType: deployment
        resourceName: leeroy-web
        port: 8080
        localPort: 9000

    Здесь описываются все стадии, упомянутые выше. Кроме этого конфига есть и файл с глобальными настройками — ~/.skaffold/config. Его можно редактировать вручную или же через CLI — например, так:

    skaffold config set --global local-cluster true

    Эта команда установит глобальную переменную local-cluster в значение true, после чего Skaffold не будет пытаться за’push’ить образы в удаленный реестр. Если вы ведете разработку локально, можно воспользоваться этой командой, чтобы складывать образы так же локально.

    Вернемся к skaffold.yaml:

    • На стадии build мы указываем, что собрать и сохранить образ нужно локально. После того, как впервые запустится сборка, увидим следующее:

      // т.к. Minikube создает кластер в отдельной виртуальной машине,
      // придется проникнуть внутрь, чтобы найти образы
      # minikube ssh
      $ docker images
      REPOSITORY                                TAG                                                                IMAGE ID            CREATED             SIZE 
      leeroy-app                                7d55a50803590b2ff62e47e6f240723451f3ef6f8c89aeb83b34e661aa287d2e   7d55a5080359        4 hours ago         13MB 
      leeroy-app                                v0.37.1-171-g0270a0c-dirty                                         7d55a5080359        4 hours ago         13MB
      leeroy-web                                5063bfb29d984db1ff70661f17d6efcc5537f2bbe6aa6907004ad1ab38879681   5063bfb29d98        5 hours ago         13.1MB
      leeroy-web                                v0.37.1-171-g0270a0c-dirty                                         5063bfb29d98        5 hours ago         13.1MB

      Как видно, Skaffold самостоятельно протегировал образы. Кстати, поддерживается несколько политик тегирования.
    • Далее в конфиге указано context: ./leeroy-app/, т.е. задан контекст, в котором собирается образ.
    • На стадии деплоя определяется, что использовать будем kubectl и маску для нужных манифестов.
    • PortForward: аналогично тому, как мы обычно прокидываем порты с помощью kubectl port-forward, даём инструкции Skaffold для вызова этой команды. В данном случае — локальный порт 9000 пробрасывается на 8080 в Deployment’е с именем leeroy-web.

    Самое время запустить skaffold dev: команда создаст продолжающийся «цикл обратной связи», т.е. не только соберет все и задеплоит в кластер, но и расскажет о состоянии pod’ов в данный момент, будет следить за изменениями и обновлять состояние pod’ов.

    Вот результат запуска skaffold dev --port-forward при повторной сборке:



    Во-первых, видно, что используется кэш. Далее — приложение собирается, деплоится, пробрасываются порты. Поскольку указан --port-forward, Skaffold пробросил порт до web, как его просили, а вот app он пробросил по собственному усмотрению (выбрал ближайший свободный). После этого мы получаем первые логи от приложений.

    Проверим работоспособность?

    ~/skaffold/examples/microservices # kubectl get po
    NAME                          READY   STATUS    RESTARTS   AGE
    leeroy-app-6998dfcc95-2nxvf   1/1     Running   0          103s
    leeroy-web-69f7d47c9d-5ff77   1/1     Running   0          103s
    ~/skaffold/examples/microservices # curl localhost:9000
    leeroooooy app!!!

    Модифицируем файл leeroy-app/app.go — проходит несколько секунд… и:

    ~/skaffold/examples/microservices # kubectl get po
    NAME                          READY   STATUS    RESTARTS   AGE
    leeroy-app-ffd79d986-l6nwp    1/1     Running   0          11s
    leeroy-web-69f7d47c9d-5ff77   1/1     Running   0          4m59s
    ~/skaffold/examples/microservices # curl localhost:9000
    leeroooooy Habr!!!

    При этом сам Skaffold вывел в консоль то же самое, что и раньше, за исключением одного момента: он выкатил только leeroy-app, а не все сразу.

    Больше практики


    Стоит упомянуть и то, что при создании нового проекта конфиги для Skaffold можно за’bootstrap’ить с помощью команды init, что очень удобно. К тому же, можно написать несколько конфигов: вести разработку на конфиге по умолчанию, после чего выкатиться на stage командой run (тот же процесс, что и dev, только не следит за изменениями), воспользовавшись другим конфигом.

    На katacoda есть руководство с примером ещё проще. Зато там предлагается уже готовая песочница с Kubernetes, приложением и Skaffold. Отличный вариант, если вам интересно самостоятельно попробовать самые основы.

    Один из возможных вариантов использования Skaffold — ведение разработки на удаленном кластере. Не всем удобно запускать Minikube на собственном железе, после чего выкатывать приложение и ожидать его адекватного функционирования… В таком случае Skaffold отлично решает поставленную задачу, что могут подтвердить, например, инженеры Reddit, о чем мы уже писали в нашем блоге.

    А в этой публикации от Weaveworks можно найти пример создания пайплайна для production.

    Заключение


    Skaffold — удобный инструмент для построения пайплайнов, подразумевающих выкат приложений в Kubernetes и ориентированных в первую очередь на нужды разработки. С ним довольно просто создавать «короткий» пайплайн, учитывающий основные потребности разработчика, однако при желании можно организовывать и более масштабные процессы. В качестве одного из наглядных примеров применения Skaffold в CI/CD-процессах приводится такой тестовой проект из 10 микросервисов, использующих возможности Kubernetes, gRPC, Istio и OpenCensus Tracing.

    Skaffold уже получил почти 8000+ звезд на GitHub, разрабатывается Google и входит в состав GoogleContainerTools — в общем, на данный момент есть все основания полагать, что проект будет развиваться долго и счастливо.

    P.S.


    Читайте также в нашем блоге:

    • +29
    • 3,7k
    • 6
    Флант
    559,44
    Специалисты по DevOps и Kubernetes
    Поделиться публикацией

    Комментарии 6

      +1
      NorthDacota это не значит что проект werf будет закрыт?)
        +3
        Совсем нет, это всё-таки разные инструменты. Основное предназначение Skaffold — локальная разработка, а у werf — своя сборка и деплой (куда угодно, в т.ч. на production, конечно).

        Skaffold не предлагает свои реализации для сборки/выката — он предлагает некий фреймворк и использует готовые (уже существующие «на стороне») инструменты для этих задач. Цитируя одного из наших разработчиков werf: Skaffold по сути не привносит что-то новое в эти процессы, если речь не идёт конкретно о локальной разработке; он скорее является «альтернативной формой записи».

        Werf же начинался именно как сборщик и на сегодняшний день имеет богатую историю многочисленные продвинутые фичи в этом смысле. Потом добавился и деплой (да, на базе Helm, но его уже прямо-таки «встроили»…) и т.п.

        P.S. Вопросы развития werf для нужд локальной разработки стоят в обозримых планах проекта.
          +2

          А можно ожидать ключик или параметра werf в scaffold?

        0

        Ну честно говоря мало, наверное, разработчиков, которые могут разрабатывать что-то без подключения к интернету, тогда отпадает сам смысл, что-то запускать локально, а тем более воссоздавать среды кубера локально, ведь в большинстве случаев есть куча нюансов инфраструктуры, которые не воспроизвести локально и грузить ноут миникубером вообще напрягает (и так тормозит). У меня типовой билд микросервиса того-же node.js на не самом быстром сервере и нормальном интернете собирается больше двух минут, на ноутбуке приблизительно 8-10 минут. На а вообще особенно козырей не видно у инструмента, да ещё и времени нужно потратить на его изучение.
        Нет уж, лучше по старинке: Drone на сервере, пайплайны в нем с kubectl, там же тесты и git-sync (для того чтобы не пересобрать образ) в контейнер sidecarом, который можно дергать для синхронизации вебхуком.

          0

          Где речь идёт про разработку оффлайн исключительно? Может я не верно где-то выразился?
          Этот инструмент как раз отлично решает проблему размещения личной песочницы для разработки вне ноутбука, об этом несколько абзацев до заключения и ссылка на пример использования в Reddit. Локальная разработка на миникубе — пример для наглядности, кластер может быть любым.

          0
          Буквально на следующий день после публикации статьи, 8 ноября, Skaffold был объявлен «зрелым» (GA).

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое