rubric/modules/devopsmodules/devops_cicd.go

294 lines
8.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package devopsmodules
import (
"rubric/utils"
)
var CicdModule = Module{
Key: "cicd",
Aliases: []string{"ci", "cd", "pipeline"},
Title: "CI/CD — непрерывная интеграция и доставка",
Description: "GitHub Actions, GitLab CI, Jenkins, принципы CI/CD",
Run: showCicd,
}
func showCicd() {
utils.Header("DevOps — CI/CD")
utils.Section("Принципы CI/CD")
utils.Code(`CI (Continuous Integration) — непрерывная интеграция:
- Разработчики часто коммитят в общую ветку
- Автоматически запускаются: сборка, тесты, линтинг
- Быстрая обратная связь (< 10 минут)
CD (Continuous Delivery) — непрерывная доставка:
- Код всегда готов к деплою
- Деплой в staging автоматически
- В продакшн — одним кликом или автоматически
Типичный пайплайн:
Коммит → Lint → Test → Build → Security scan → Deploy staging → Deploy prod
Метрики:
Lead time — время от коммита до продакшна
Deploy freq — частота деплоев
MTTR — среднее время восстановления
Change fail % — процент неудачных деплоев`)
utils.Section("GitHub Actions")
utils.Code(`# .github/workflows/ci.yml
name: CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: secret
options: >-
--health-cmd pg_isready
--health-interval 10s
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- name: Run tests
run: go test -v -race -coverprofile=coverage.out ./...
- name: Upload coverage
uses: codecov/codecov-action@v4
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: golangci/golangci-lint-action@v4
build-and-push:
needs: [test, lint]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Log in to registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build-and-push
runs-on: ubuntu-latest
environment: production # требует ручного подтверждения
steps:
- name: Deploy to Kubernetes
uses: azure/k8s-deploy@v4
with:
manifests: k8s/
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}`)
utils.Println(utils.ColorBold + "GitHub Actions — ключевые концепции:" + utils.ColorReset)
utils.Code(`Workflow — файл в .github/workflows/*.yml
Job — набор шагов, запускается на runner
Step — команда или action
Runner — виртуальная машина (ubuntu/windows/macos)
Action — переиспользуемый step (uses: actions/checkout@v4)
Secret — зашифрованные переменные (Settings → Secrets)
Environment — защищённая среда с approval (production, staging)
Matrix — параллельный запуск с разными параметрами:
strategy:
matrix:
go: ['1.21', '1.22']
os: [ubuntu-latest, macos-latest]`)
utils.Section("GitLab CI/CD")
utils.Code(`# .gitlab-ci.yml
stages:
- test
- build
- deploy
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
test:
stage: test
image: golang:1.22
script:
- go test ./...
- go vet ./...
coverage: '/coverage: \d+\.\d+%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
build:
stage: build
image: docker:24
services:
- docker:24-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
only:
- main
deploy_staging:
stage: deploy
script:
- kubectl set image deployment/myapp myapp=$DOCKER_IMAGE
environment:
name: staging
url: https://staging.example.com
only:
- main
deploy_prod:
stage: deploy
script:
- kubectl set image deployment/myapp myapp=$DOCKER_IMAGE
environment:
name: production
url: https://example.com
when: manual # ручной запуск
only:
- main`)
utils.Println(utils.ColorBold + "Встроенные переменные GitLab CI:" + utils.ColorReset)
utils.Code(`CI_COMMIT_SHA — полный SHA коммита
CI_COMMIT_SHORT_SHA — короткий SHA
CI_COMMIT_BRANCH — ветка
CI_COMMIT_TAG — тег (если есть)
CI_REGISTRY — адрес реестра (registry.gitlab.com)
CI_REGISTRY_IMAGE — полный путь образа
CI_PROJECT_NAME — имя проекта
CI_ENVIRONMENT_NAME — имя окружения`)
utils.Section("Jenkins")
utils.Code(`// Jenkinsfile (Declarative Pipeline):
pipeline {
agent any
environment {
DOCKER_CREDS = credentials('docker-hub')
KUBECONFIG = credentials('kubeconfig-prod')
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Test') {
steps {
sh 'go test ./...'
}
post {
always {
junit 'test-results.xml'
}
}
}
stage('Build') {
steps {
sh """
docker build -t myapp:${env.BUILD_NUMBER} .
docker tag myapp:${env.BUILD_NUMBER} myrepo/myapp:latest
"""
}
}
stage('Push') {
steps {
sh """
echo $DOCKER_CREDS_PSW | docker login -u $DOCKER_CREDS_USR --password-stdin
docker push myrepo/myapp:${env.BUILD_NUMBER}
"""
}
}
stage('Deploy') {
when { branch 'main' }
steps {
input message: 'Деплоить в продакшн?'
sh "kubectl set image deployment/myapp myapp=myrepo/myapp:${env.BUILD_NUMBER}"
}
}
}
post {
failure {
slackSend channel: '#alerts', message: "FAILED: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
}
success {
slackSend channel: '#deployments', message: "DEPLOYED: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
}
}
}`)
utils.Section("ArgoCD — GitOps")
utils.Code(`GitOps — Git как единственный источник истины для инфраструктуры.
ArgoCD наблюдает за Git-репозиторием и синхронизирует кластер.
# Установка:
kubectl create namespace argocd
kubectl apply -n argocd -f \
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# CLI:
argocd login argocd.example.com
# Создать приложение:
argocd app create myapp \
--repo https://github.com/user/myapp \
--path k8s/ \
--dest-server https://kubernetes.default.svc \
--dest-namespace production \
--sync-policy automated \
--auto-prune
argocd app list
argocd app sync myapp
argocd app rollback myapp 3`)
utils.Footer()
}