Tekton: cloud-native CI/CD пайплайны в Kubernetes

Tekton: CI/CD нативный для Kubernetes

Tekton — open-source фреймворк для CI/CD пайплайнов, который живёт прямо внутри Kubernetes как набор CRD (Custom Resource Definitions). Главное отличие от Jenkins или GitLab CI: те запускают контейнеры поверх кластера, как бы снаружи, а Tekton — полноценный нативный компонент самого кластера. Разница, казалось бы, тонкая, но на практике это меняет всё.

Несколько базовых концепций, без которых работа с Tekton просто не пойдёт:

  • Step — минимальная единица работы. Одна команда, один контейнер.
  • Task — набор Steps, которые выполняются последовательно внутри одного Pod
  • Pipeline — собирает Tasks вместе: можно гонять их параллельно или строго по порядку
  • PipelineRun — конкретный запуск Pipeline с вашими параметрами и данными
  • Trigger — запускает Pipeline автоматически по событию, чаще всего по webhook
  • Workspace — общее хранилище, через которое Tasks передают данные друг другу

Почему вообще стоит смотреть в сторону Tekton? Вот что реально выделяет его на фоне других инструментов:

  • Каждый шаг — изолированный контейнер. Никакого «соседи мешают» между степами.
  • Пайплайны описываются декларативно в YAML — всё в Git, всё прозрачно
  • Масштабирование берёт на себя Kubernetes — вы просто не думаете об этом
  • Tekton Hub — готовый каталог Tasks, не нужно изобретать велосипед каждый раз
  • Работает с любым Git-провайдером через Triggers: GitHub, GitLab, Bitbucket — без разницы

Установка Tekton в кластер Kubernetes

Tekton — это несколько отдельных компонентов. Ставим их по очереди, не пытаясь запустить всё сразу:

# Tekton Pipelines (ядро)
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

# Tekton Triggers (запуск по событиям)
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml

# Tekton Dashboard (веб-интерфейс)
kubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml

После установки сразу проверяем, что всё поднялось корректно:

kubectl get pods -n tekton-pipelines
kubectl get pods -n tekton-pipelines-resolvers

Ставим CLI-утилиту tkn — без неё отлаживать пайплайны будет заметно больнее:

# Linux
curl -LO https://github.com/tektoncd/cli/releases/latest/download/tkn_Linux_x86_64.tar.gz
tar xzf tkn_Linux_x86_64.tar.gz
sudo mv tkn /usr/local/bin/

# Проверка
tkn version

Открываем Dashboard и смотрим, что происходит в кластере:

kubectl port-forward -n tekton-pipelines svc/tekton-dashboard 9097:9097
# Доступен по http://localhost:9097

Создание Tasks: базовые строительные блоки

Task — это основная рабочая единица Tekton. Каждая Task поднимается в отдельном Pod. Начнём с простого и нужного — Task для клонирования Git-репозитория:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: git-clone
  namespace: ci
spec:
  params:
    - name: repo-url
      type: string
      description: URL Git-репозитория
    - name: revision
      type: string
      default: main
  workspaces:
    - name: source
      description: Workspace для исходного кода
  steps:
    - name: clone
      image: alpine/git:2.43.0
      script: |
        git clone $(params.repo-url) $(workspaces.source.path)/repo
        cd $(workspaces.source.path)/repo
        git checkout $(params.revision)
        echo "Cloned $(params.repo-url) at $(git rev-parse HEAD)"

Теперь Task для сборки Docker-образа через Kaniko. Это важно: Kaniko работает без Docker daemon, что в Kubernetes-среде критично для безопасности:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: kaniko-build
  namespace: ci
spec:
  params:
    - name: image
      type: string
      description: Полное имя образа с тегом
    - name: dockerfile
      type: string
      default: Dockerfile
  workspaces:
    - name: source
    - name: docker-config
      description: Docker registry credentials
  steps:
    - name: build-push
      image: gcr.io/kaniko-project/executor:latest
      args:
        - --dockerfile=$(params.dockerfile)
        - --context=$(workspaces.source.path)/repo
        - --destination=$(params.image)
        - --cache=true
        - --cache-ttl=24h
      volumeMounts:
        - name: docker-config
          mountPath: /kaniko/.docker/

Task для запуска тестов. Без неё пайплайн — просто красивая автоматизация деплоя, а не CI/CD:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: run-tests
  namespace: ci
spec:
  workspaces:
    - name: source
  steps:
    - name: unit-tests
      image: golang:1.22
      workingDir: $(workspaces.source.path)/repo
      script: |
        go test ./... -v -coverprofile=coverage.out
        go tool cover -func=coverage.out
    - name: lint
      image: golangci/golangci-lint:latest
      workingDir: $(workspaces.source.path)/repo
      script: |
        golangci-lint run ./...

Сборка Pipeline из Tasks

Pipeline — это то, где Tasks складываются в осмысленную последовательность с зависимостями между шагами. Собираем полноценный CI/CD пайплайн:

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-deploy
  namespace: ci
spec:
  params:
    - name: repo-url
      type: string
    - name: revision
      type: string
      default: main
    - name: image
      type: string
    - name: namespace
      type: string
      default: production
  workspaces:
    - name: shared-workspace
    - name: docker-credentials
  tasks:
    # 1. Клонирование
    - name: fetch-source
      taskRef:
        name: git-clone
      params:
        - name: repo-url
          value: $(params.repo-url)
        - name: revision
          value: $(params.revision)
      workspaces:
        - name: source
          workspace: shared-workspace

    # 2. Тесты (после клонирования)
    - name: test
      taskRef:
        name: run-tests
      runAfter:
        - fetch-source
      workspaces:
        - name: source
          workspace: shared-workspace

    # 3. Сборка образа (после тестов)
    - name: build-image
      taskRef:
        name: kaniko-build
      runAfter:
        - test
      params:
        - name: image
          value: $(params.image)
      workspaces:
        - name: source
          workspace: shared-workspace
        - name: docker-config
          workspace: docker-credentials

    # 4. Деплой (после сборки)
    - name: deploy
      taskRef:
        name: kubectl-deploy
      runAfter:
        - build-image
      params:
        - name: image
          value: $(params.image)
        - name: namespace
          value: $(params.namespace)

И Task для деплоя в Kubernetes — финальное звено цепочки:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: kubectl-deploy
  namespace: ci
spec:
  params:
    - name: image
      type: string
    - name: namespace
      type: string
  steps:
    - name: deploy
      image: bitnami/kubectl:latest
      script: |
        kubectl set image deployment/myapp \
          myapp=$(params.image) \
          -n $(params.namespace)
        kubectl rollout status deployment/myapp \
          -n $(params.namespace) \
          --timeout=300s

Запуск Pipeline: PipelineRun и Workspaces

PipelineRun — это уже не абстракция, а конкретный запуск вашего Pipeline с реальными параметрами, секретами и Workspaces. Именно здесь Pipeline оживает.

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: build-deploy-run-
  namespace: ci
spec:
  pipelineRef:
    name: build-deploy
  params:
    - name: repo-url
      value: https://github.com/company/myapp.git
    - name: revision
      value: main
    - name: image
      value: registry.company.ru/myapp:v1.2.3
    - name: namespace
      value: production
  workspaces:
    - name: shared-workspace
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 1Gi
          storageClassName: fast-ssd
    - name: docker-credentials
      secret:
        secretName: docker-registry-creds

Сначала создаём секрет для Docker registry, иначе push образа просто упадёт:

kubectl create secret docker-registry docker-registry-creds \
  --docker-server=registry.company.ru \
  --docker-username=ci-bot \
  --docker-password='P@ssw0rd' \
  -n ci

Запускаем и сразу следим за ходом выполнения через CLI:

# Запуск
kubectl create -f pipelinerun.yaml

# Или через tkn
tkn pipeline start build-deploy \
  -p repo-url=https://github.com/company/myapp.git \
  -p image=registry.company.ru/myapp:latest \
  -w name=shared-workspace,claimName=ci-workspace \
  -w name=docker-credentials,secret=docker-registry-creds \
  --showlog

# Просмотр логов
tkn pipelinerun logs build-deploy-run-xyz -f

# Список запусков
tkn pipelinerun list

Tekton Triggers: автоматический запуск по webhook

Triggers — это про автоматизацию. Получили webhook от GitHub, GitLab или Bitbucket — Pipeline стартует сам, без вашего участия.

# EventListener — принимает webhook
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: github-listener
  namespace: ci
spec:
  serviceAccountName: tekton-triggers-sa
  triggers:
    - name: github-push
      interceptors:
        - ref:
            name: github
          params:
            - name: secretRef
              value:
                secretName: github-webhook-secret
                secretKey: token
            - name: eventTypes
              value: ["push"]
      bindings:
        - ref: github-push-binding
      template:
        ref: build-deploy-template

TriggerBinding вытаскивает нужные данные из тела webhook — ветку, коммит, репозиторий:

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: github-push-binding
  namespace: ci
spec:
  params:
    - name: repo-url
      value: $(body.repository.clone_url)
    - name: revision
      value: $(body.after)
    - name: image
      value: "registry.company.ru/myapp:$(body.after)"

TriggerTemplate берёт эти данные и создаёт PipelineRun с правильными параметрами:

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: build-deploy-template
  namespace: ci
spec:
  params:
    - name: repo-url
    - name: revision
    - name: image
  resourcetemplates:
    - apiVersion: tekton.dev/v1
      kind: PipelineRun
      metadata:
        generateName: triggered-run-
      spec:
        pipelineRef:
          name: build-deploy
        params:
          - name: repo-url
            value: $(tt.params.repo-url)
          - name: revision
            value: $(tt.params.revision)
          - name: image
            value: $(tt.params.image)
        workspaces:
          - name: shared-workspace
            volumeClaimTemplate:
              spec:
                accessModes: [ReadWriteOnce]
                resources:
                  requests:
                    storage: 1Gi
          - name: docker-credentials
            secret:
              secretName: docker-registry-creds

EventListener нужно выставить наружу через Ingress или LoadBalancer, после чего прописать URL в настройках webhook на стороне GitHub.

Мониторинг и обслуживание

Повседневная работа с пайплайнами через CLI tkn — и не забывайте чистить старые запуски, иначе кластер постепенно засоряется:

# Статус текущих запусков
tkn pipelinerun list -n ci
tkn taskrun list -n ci

# Логи конкретного запуска
tkn pipelinerun logs build-deploy-run-abc -n ci

# Удаление старых PipelineRun (старше 7 дней)
tkn pipelinerun delete --keep 10 -n ci

# Или через CronJob для автоочистки
apiVersion: batch/v1
kind: CronJob
metadata:
  name: tekton-cleanup
  namespace: ci
spec:
  schedule: "0 3 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: tekton-cleanup-sa
          containers:
            - name: cleanup
              image: bitnami/kubectl:latest
              command:
                - /bin/sh
                - -c
                - |
                  kubectl get pipelinerun -n ci \
                    --sort-by=.metadata.creationTimestamp \
                    -o name | head -n -20 | xargs -r kubectl delete -n ci
          restartPolicy: OnFailure

По мониторингу: Tekton сам экспортирует метрики Prometheus на порту 9090 контроллера. Добавьте ServiceMonitor — и сбор метрик пойдёт автоматически:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: tekton-pipelines
  namespace: tekton-pipelines
spec:
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
  endpoints:
    - port: metrics
      interval: 30s

Часто задаваемые вопросы

Нас часто спрашивают: что выбрать, Tekton или ArgoCD? Если честно, это неправильный вопрос — они решают разные задачи. Tekton закрывает весь CI/CD цикл: сборка, тесты, деплой. ArgoCD — это GitOps-контроллер, заточенный под непрерывную доставку. На практике мы чаще всего видим их в паре: Tekton делает CI-часть (собрал, протестировал, запушил образ), ArgoCD берёт CD (синхронизировал манифесты из Git в кластер). Работает очень слаженно.

Секреты в пайплайнах — больная тема. Правило одно и жёсткое: никогда не передавайте их через параметры Pipeline, они попадут в логи и будут видны всем. Используйте Kubernetes Secrets, подключая их как Workspaces или volumeMounts. Если нужен серьёзный уровень защиты — интегрируйте HashiCorp Vault через External Secrets Operator или Vault Agent Injector.

Нет, Tekton работает исключительно в Kubernetes — он завязан на CRD и контроллеры кластера, без них просто нечего запускать. Если Kubernetes в вашей инфраструктуре нет, смотрите в сторону Jenkins, GitLab CI или GitHub Actions.

Ресурсы ограничивайте на уровне каждого Step через resources.requests и resources.limits. Для глобальных ограничений на весь namespace — LimitRange и ResourceQuota. И обязательно ставьте таймауты: зависший пайплайн без таймаута может занять ресурсы на часы. Делается просто: spec.timeouts.pipeline: 1h на уровне Task или Pipeline.

Не пишите Tasks с нуля — сначала загляните в Tekton Hub. Там уже есть готовые решения для git-clone, kaniko, helm-upgrade и десятков других сценариев. Если нужен собственный каталог, заведите его в Git-репозитории и подключайте Tasks через Tekton Resolvers: taskRef: resolver: git с указанием URL и пути к нужной Task.

Нужна помощь с настройкой?

Если нужна помощь с внедрением и настройкой Tekton — команда АйТи Фреш занимается этим уже 15+ лет. Обслуживание от 15 000 ₽/мес.

📞 Связаться с нами
#Tekton#CI/CD#Kubernetes#пайплайн#cloud-native#DevOps#автоматизация деплоя#Tekton Pipelines
Комментарии 0

Оставить комментарий

загрузка...