Ответ
При организации CI/CD для трех команд я фокусируюсь на балансе между автономностью команд и стандартизацией процессов. Вот как я строю такую систему:
Архитектура:
Git Repositories (GitLab/GitHub)
├── Team A Repo
├── Team B Repo
└── Team C Repo
└── .gitlab-ci.yml
CI/CD Pipeline (GitLab CI/GitHub Actions/Jenkins)
├── Shared Templates Library
├── Team-Specific Configs
└── Artifact Registry
GitOps (ArgoCD/Flux)
├── Git Repo: k8s-configs
│ ├── teams/team-a/
│ ├── teams/team-b/
│ └── teams/team-c/
└── Production Clusters
Monitoring (Prometheus/Grafana)
└── Team Dashboards
1. Git стратегия и репозитории
- Каждая команда работает в своем репозитории или в монорепозитории с четкими границами
- Использую GitFlow или Trunk-Based Development в зависимости от зрелости команд
- Protected branches + mandatory code review
2. CI Pipeline (на примере GitLab CI)
Общие шаблоны в .gitlab-ci-templates.yml:
# Общий template для всех команд
.base_template: &base_template
image: docker:latest
services:
- docker:dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
.build_template: &build_template
<<: *base_template
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
artifacts:
paths:
- docker-image.txt
Конфигурация команды A в .gitlab-ci.yml:
include:
- project: 'infrastructure/ci-templates'
file: '/templates/.gitlab-ci-templates.yml'
variables:
TEAM: team-a
K8S_NAMESPACE: team-a-${CI_ENVIRONMENT_NAME}
stages:
- test
- build
- security-scan
- deploy-dev
- deploy-staging
- deploy-prod
unit-tests:
stage: test
image: node:18
script:
- npm ci
- npm test
coverage: '/Statementss*:s*([^%]+)/'
build-image:
<<: *build_template
variables:
DOCKER_BUILD_ARGS: --build-arg TEAM=$TEAM
security-scan:
stage: security-scan
image: aquasec/trivy:latest
script:
- trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
deploy-to-dev:
stage: deploy-dev
image: bitnami/kubectl:latest
script:
- kubectl apply -f k8s/overlays/dev/
- kubectl rollout status deployment/${TEAM}-app -n ${K8S_NAMESPACE}
environment:
name: dev
url: https://dev.team-a.company.com
deploy-to-prod:
stage: deploy-prod
image: bitnami/kubectl:latest
script:
- kubectl apply -f k8s/overlays/prod/
- kubectl rollout status deployment/${TEAM}-app -n ${K8S_NAMESPACE}
environment:
name: production
url: https://team-a.company.com
when: manual
only:
- main
3. CD с GitOps (ArgoCD)
Структура GitOps репозитория:
kubernetes-configs/
├── base/ # Базовые манифесты
│ ├── team-a/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── kustomization.yaml
├── overlays/
│ ├── dev/ # Конфигурация для dev
│ │ ├── team-a/
│ │ │ ├── kustomization.yaml
│ │ │ └── patch-replicas.yaml
│ │ └── team-b/
│ ├── staging/
│ └── production/
└── applicationsets/ # ArgoCD ApplicationSets
├── team-a.yaml
├── team-b.yaml
└── team-c.yaml
ArgoCD ApplicationSet для команды A:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: team-a-apps
spec:
generators:
- git:
repoURL: https://github.com/company/kubernetes-configs.git
revision: HEAD
directories:
- path: overlays/dev/team-a
- path: overlays/staging/team-a
- path: overlays/production/team-a
template:
metadata:
name: '{{path.basename}}-{{path[-2]}}'
spec:
project: team-a
source:
repoURL: https://github.com/company/kubernetes-configs.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: 'team-a-{{path[-2]}}'
syncPolicy:
automated:
selfHeal: true
prune: true
syncOptions:
- CreateNamespace=true
4. Инфраструктура как код (Terraform)
# Модуль для команды
module "team_a_infra" {
source = "../modules/team-infra"
team_name = "team-a"
environment = var.environment
# Ресурсы команды
vpc_id = data.aws_vpc.main.id
subnet_ids = data.aws_subnets.private.ids
# CI/CD интеграция
github_repo = "company/team-a-app"
container_registry = aws_ecr_repository.team_a.repository_url
# Мониторинг
prometheus_endpoint = data.aws_prometheus_workspace.main.prometheus_endpoint
}
# RBAC для доступа команды к своим ресурсам
resource "kubernetes_role" "team_a_dev" {
metadata {
name = "team-a-developer"
namespace = "team-a-${var.environment}"
}
rule {
api_groups = ["", "apps"]
resources = ["pods", "deployments", "services"]
verbs = ["get", "list", "watch", "create", "update", "patch"]
}
}
5. Общие сервисы и стандарты
- Общий Container Registry с пространствами имен по командам
- Единая система мониторинга (Prometheus + Grafana) с дашбордами по командам
- Централизованное логирование (Loki + Elasticsearch)
- Security Scanning (Trivy, Snyk) на всех этапах
- Cost Management тегирование всех ресурсов по командам
6. Процессы и governance
- Еженедельные sync-митинги по улучшению CI/CD процессов
- Общие метрики: Deployment Frequency, Lead Time, Change Failure Rate, MTTR
- Автоматические approval-воркфлоу для production-деплоев
- Ротация on-call duty между командами
Такая система позволяет командам работать автономно, но в рамках единых стандартов безопасности и качества.