294 lines
8.1 KiB
Go
Executable file
294 lines
8.1 KiB
Go
Executable file
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()
|
||
}
|