Подготовка инфраструктуры

Требования

  • GitLab;

  • Хост для установки GitLab Runner, имеющий:

Установка GitLab Runner

Установите GitLab Runner на выделенный для него хост, следуя официальным инструкциям.

Настройка окружения для сборки с Buildah

(Для Ubuntu 23.10 и выше) на хосте GitHub Runner запустите:

{ echo "kernel.apparmor_restrict_unprivileged_userns = 0" && echo "kernel.apparmor_restrict_unprivileged_unconfined = 0";} | sudo tee -a /etc/sysctl.d/20-apparmor-donotrestrict.conf && sudo sysctl -p /etc/sysctl.d/20-apparmor-donotrestrict.conf

Регистрация GitLab Runner

Для регистрации GitLab Runner в GitLab следуйте официальным инструкциям, указав Docker в качестве executor’а и любой образ в качестве image (например, alpine).

Настройка GitLab Runner

На хосте GitLab Runner’а откройте его конфигурационный файл config.toml и добавьте зарегистрированному ранее GitLab Runner’у следующие опции:

[[runners]]
  name = "<имя зарегистрированного Runner'а>"
  [runners.docker]
    security_opt = ["seccomp:unconfined", "apparmor:unconfined"]
    volumes = ["/home/build/.werf"]

Если хост GitLab Runner’а имеет версию ядра Linux 5.12 или ниже, то установите на хост fuse и добавьте в файл config.toml ещё одну опцию:

[[runners]]
  name = "<имя зарегистрированного Runner'а>"
  [runners.docker]
    devices = ["/dev/fuse"]

При желании произведите дополнительную конфигурацию GitLab Runner’а.

Конфигурация container registry

Включите сборщик мусора вашего container registry.

Подготовка системы к кроссплатформенной сборке (опционально)

Данный шаг требуется только для сборки образов для платформ, отличных от платформы системы, где запущен werf.

Регистрируем в системе эмуляторы с помощью образа qemu-user-static:

docker run --restart=always --name=qemu-user-static -d --privileged --entrypoint=/bin/sh multiarch/qemu-user-static -c "/register --reset -p yes && tail -f /dev/null"

Настройка проекта

Настройка проекта GitLab

  • Создайте и сохраните access token для очистки ненужных образов из container registry со следующей конфигурацией:

    • Token name: werf-images-cleanup;

    • Role: developer;

    • Scopes: api.

  • В переменных проекта добавьте следующие переменные:

    • Access token для очистки ненужных образов:

      • Key: WERF_IMAGES_CLEANUP_PASSWORD;

      • Value: <сохранённый "werf-images-cleanup" access token>;

      • Protect variable: yes;

      • Mask variable: yes.

  • Добавьте плановое задание на каждую ночь для очистки ненужных образов в container registry, указав ветку main/master в качестве Target branch.

Конфигурация CI/CD проекта

Так может выглядеть репозиторий, использующий werf для сборки и развертывания:

.helm
app
.gitlab-ci.yml
werf.yaml
stages:
  - prod
  - cleanup

default:
  image:
    name: "registry.werf.io/werf/werf:2-stable"
    pull_policy: always
  before_script:
    - source "$(werf ci-env gitlab --as-file)"
  tags: ["<GitLab Runner tag>"]

prod:
  stage: prod
  script:
    - werf converge
  environment:
    name: prod
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "schedule"
      when: manual

images:cleanup:
  stage: cleanup
  script:
    - werf cr login -u nobody -p "${WERF_IMAGES_CLEANUP_PASSWORD:?}" "${WERF_REPO:?}"
    - werf cleanup
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule"

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
      - name: app
        image: {{ .Values.werf.image.app }}

apiVersion: v1
kind: Service
metadata:
  name: app
spec:
  selector:
    app: app
  ports:
  - name: app
    port: 80

FROM node

WORKDIR /app
COPY . .
RUN npm ci

CMD ["node", "server.js"]

{
  "name": "app",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "app",
      "version": "1.0.0"
    }
  }
}

{
  "name": "app",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  }
}

const http = require('http');

const hostname = '127.0.0.1';
const port = 80;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

configVersion: 1
project: myproject
---
image: app
dockerfile: Dockerfile
context: ./app

Дополнительно:

  • Добавьте для werf cleanup опции авторизации в container registry, следуя инструкциям.