CI/CD - Pytania Rekrutacyjne dla DevOps Engineer [2026]
CI/CD to serce każdego nowoczesnego procesu wytwarzania oprogramowania. Na rozmowie DevOps rekruterzy sprawdzają nie tylko znajomość konkretnych narzędzi (GitHub Actions, GitLab CI, Jenkins), ale przede wszystkim zrozumienie zasad automatyzacji, strategii deploymentu i best practices. Ten przewodnik zawiera 60+ pytań rekrutacyjnych z odpowiedziami, które pomogą Ci przygotować się do rozmowy.
Podstawy CI/CD
Czym różni się Continuous Integration od Continuous Delivery i Continuous Deployment?
Odpowiedź w 30 sekund:
- CI (Continuous Integration) - automatyczne budowanie i testowanie każdej zmiany
- Continuous Delivery - automatyczne przygotowanie do deploymentu, ale manual approval przed produkcją
- Continuous Deployment - pełna automatyzacja, każda zmiana przechodzi od commit do produkcji bez interwencji
Odpowiedź w 2 minuty:
Najlepiej zobrazować różnice na schemacie przepływu pracy:
CI (Continuous Integration):
commit → build → test → ✅ merge to main
Continuous Delivery:
commit → build → test → deploy staging → 🔘 manual approval → deploy prod
Continuous Deployment:
commit → build → test → deploy staging → auto tests → deploy prod
Continuous Delivery jest bezpieczniejsze - masz kontrolę przed produkcją. Continuous Deployment wymaga dojrzałych testów i monitoringu, ale przyspiesza delivery.
Jakie są główne korzyści z implementacji CI/CD?
Odpowiedź w 30 sekund:
- Szybsze wykrywanie błędów - feedback w minutach, nie dniach
- Mniejsze ryzyko wdrożeń - małe, częste zmiany zamiast wielkich release'ów
- Krótszy time-to-market - od commit do produkcji w godzinach
- Lepsza jakość kodu - automatyczne testy i review
Odpowiedź w 2 minuty:
Bez CI/CD typowy deployment wygląda tak: developer kończy feature, czeka na QA, QA testuje manualnie, deployment w piątek wieczorem, weekend on-call. Z CI/CD: merge to main → automatyczne testy → deploy staging → smoke tests → deploy prod. Całość zajmuje minuty.
Dodatkowe korzyści:
- Reproducibility - każdy build jest deterministyczny
- Visibility - wszyscy widzą status pipeline
- Documentation - pipeline jako kod dokumentuje proces
- Confidence - deweloperzy nie boją się deployować
Co to jest pipeline CI/CD i z jakich etapów się składa?
Odpowiedź w 30 sekund:
Pipeline to zdefiniowany przepływ pracy wykonywany automatycznie. Typowe etapy:
- Source - checkout kodu
- Build - kompilacja, bundling
- Test - unit, integration, e2e
- Security - SAST, dependency scan
- Deploy - staging, production
Odpowiedź w 2 minuty:
Poniżej znajduje się typowa struktura pipeline z wszystkimi kluczowymi etapami:
# Przykład struktury pipeline
stages:
- build # kompilacja, tworzenie artefaktów
- test # testy jednostkowe, integracyjne
- security # skanowanie bezpieczeństwa
- deploy-stg # deployment na staging
- e2e # testy end-to-end
- deploy-prod # deployment na produkcję
Każdy stage może mieć wiele jobs wykonywanych równolegle. Pipeline jest triggerowany przez:
- Push do branch
- Pull request
- Schedule (cron)
- Manual trigger
- External webhook
Artefakty są przekazywane między stages. Pipeline kończy się sukcesem tylko gdy wszystkie kroki przejdą.
Czym są artefakty w kontekście CI/CD?
Odpowiedź w 30 sekund:
Artefakty to pliki wygenerowane podczas pipeline, które są:
- Przekazywane między stages (build output → test input)
- Archiwizowane do późniejszego użycia (Docker image, package)
- Dostępne do pobrania (test reports, coverage)
Odpowiedź w 2 minuty:
Oto przykład jak w GitHub Actions przekazujemy artefakty między job'ami:
# GitHub Actions
- name: Build
run: npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
# W następnym job
- uses: actions/download-artifact@v4
with:
name: dist
Typowe artefakty:
- Docker images (pushowane do registry)
- Pakiety npm/Maven/NuGet
- Raporty testów i coverage
- Binaries i executables
- Deployment manifests
Dobre praktyki:
- Ustawiaj retention period (nie przechowuj w nieskończoność)
- Taguj artefakty wersją/commit SHA
- Używaj immutable storage (Docker registry, S3)
GitHub Actions
Wyjaśnij strukturę workflow GitHub Actions
Odpowiedź w 30 sekund:
name: CI Pipeline
on: [push, pull_request] # triggers
jobs:
build: # job name
runs-on: ubuntu-latest # runner
steps: # kroki w job
- uses: actions/checkout@v4
- run: npm install
Odpowiedź w 2 minuty:
Poniżej pełny przykład workflow pokazujący wszystkie kluczowe elementy:
name: Complete CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
workflow_dispatch: # manual trigger
env:
NODE_VERSION: '20' # global env
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20] # matrix build
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
build:
needs: test # dependency
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build
path: dist/
deploy:
needs: build
if: github.ref == 'refs/heads/main' # condition
runs-on: ubuntu-latest
environment: production # protected env
steps:
- run: echo "Deploying..."
Kluczowe koncepty:
- Workflow - cały plik YAML
- Job - zbiór steps na jednym runnerze
- Step - pojedyncza akcja lub komenda
- Action - reusable unit (marketplace lub custom)
Jak działają GitHub Actions runners i jakie są różnice między hosted a self-hosted?
Odpowiedź w 30 sekund:
- GitHub-hosted - zarządzane przez GitHub, czyste VM, płacisz za minuty
- Self-hosted - Twoja infrastruktura, pełna kontrola, bez limitów
Odpowiedź w 2 minuty:
Porównanie obu opcji w praktyce:
| Aspekt | GitHub-hosted | Self-hosted |
|---|---|---|
| Setup | Zero | Wymaga instalacji |
| Maintenance | GitHub | Ty |
| Cost | Per minute | Twoja infra |
| Clean env | Każdy run | Opcjonalnie |
| Hardware | Standardowe | Custom |
| Network | Public | Prywatna sieć |
# GitHub-hosted
runs-on: ubuntu-latest
runs-on: windows-2022
runs-on: macos-14
# Self-hosted
runs-on: self-hosted
runs-on: [self-hosted, linux, gpu] # labels
Kiedy self-hosted:
- Potrzebujesz dostępu do prywatnej sieci
- Custom hardware (GPU, ARM)
- Duże repo/artifacts (limity bandwidth)
- Compliance/security requirements
- Cost optimization przy dużym użyciu
Jak zarządzać sekretami w GitHub Actions?
Odpowiedź w 30 sekund:
steps:
- run: docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_TOKEN }}
Sekrety definiujesz w Settings → Secrets → Actions. Są maskowane w logach.
Odpowiedź w 2 minuty:
GitHub oferuje trzy poziomy sekretów z różnym zakresem dostępu:
- Repository secrets - dostępne tylko w tym repo
- Environment secrets - dostępne tylko w określonym environment
- Organization secrets - współdzielone między repos
jobs:
deploy:
environment: production # wymaga approval
steps:
- run: |
echo "Using ${{ secrets.PROD_API_KEY }}"
Best practices:
- Używaj environment protection rules dla prod
- OIDC zamiast long-lived tokens do cloud:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456:role/GitHubActions
aws-region: eu-west-1
- Rotuj sekrety regularnie
- Nigdy nie loguj sekretów (są automatycznie maskowane, ale uważaj z base64)
Jak zrobić cache dependencies w GitHub Actions?
Odpowiedź w 30 sekund:
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
Cache przyspiesza build poprzez przechowywanie zależności między runami.
Odpowiedź w 2 minuty:
Oto różne strategie cache w GitHub Actions, od najprostszej do zaawansowanej:
# npm z automatycznym cache
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # automatyczny cache
# Manual cache z restore-keys
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
npm-
# Docker layer cache
- uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
Strategia cache:
-
key- exact match -
restore-keys- fallback prefix match - Cache jest per-branch, ale PR może używać cache z base branch
Limity:
- 10 GB per repo
- Cache niewykorzystany przez 7 dni jest usuwany
Jak uruchomić jobs równolegle i jak zdefiniować zależności między nimi?
Odpowiedź w 30 sekund:
jobs:
test:
runs-on: ubuntu-latest
lint:
runs-on: ubuntu-latest
# test i lint równolegle
build:
needs: [test, lint] # czeka na oba
Odpowiedź w 2 minuty:
Przykład pipeline z testami równoległymi i zależnościami między stages:
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- run: npm test
integration-tests:
runs-on: ubuntu-latest
steps:
- run: npm run test:integration
e2e-tests:
runs-on: ubuntu-latest
steps:
- run: npm run test:e2e
build:
needs: [unit-tests, integration-tests, e2e-tests]
runs-on: ubuntu-latest
steps:
- run: npm run build
deploy-staging:
needs: build
runs-on: ubuntu-latest
steps:
- run: deploy-staging.sh
deploy-prod:
needs: deploy-staging
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- run: deploy-prod.sh
Kluczowe:
- Jobs bez
needsuruchamiają się równolegle -
needs: [a, b]czeka na wszystkie - Można przekazywać outputs między jobs
-
if: failure()- uruchom gdy poprzedni failed -
if: always()- uruchom zawsze
Co to jest matrix strategy i kiedy jej używać?
Odpowiedź w 30 sekund:
Matrix tworzy wiele wariantów job'a z różnymi kombinacjami parametrów:
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
# = 6 jobów
Odpowiedź w 2 minuty:
Zaawansowany przykład matrix z exclude, include i kontynuacją po błędzie:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false # kontynuuj pozostałe gdy jeden fail
max-parallel: 4 # limit równoległości
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20]
include:
- os: ubuntu-latest
node: 22
experimental: true
exclude:
- os: macos-latest
node: 18
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm test
continue-on-error: ${{ matrix.experimental }}
Przypadki użycia:
- Testowanie na wielu wersjach Node/Python/Java
- Cross-platform builds (Linux, Windows, macOS)
- Testowanie z różnymi bazami danych
- Różne konfiguracje (z feature flag, bez)
GitLab CI
Wyjaśnij strukturę .gitlab-ci.yml
Odpowiedź w 30 sekund:
stages:
- build
- test
- deploy
build-job:
stage: build
script:
- npm install
- npm run build
Odpowiedź w 2 minuty:
Kompletny przykład konfiguracji GitLab CI z globalnymi ustawieniami i wszystkimi etapami:
# Global configuration
default:
image: node:20
before_script:
- npm ci
variables:
NODE_ENV: production
stages:
- build
- test
- deploy
# Jobs
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
test:
stage: test
script:
- npm test
coverage: '/Coverage: \d+\.\d+%/'
deploy-staging:
stage: deploy
environment:
name: staging
url: https://staging.example.com
script:
- deploy.sh staging
only:
- develop
deploy-prod:
stage: deploy
environment:
name: production
url: https://example.com
script:
- deploy.sh production
only:
- main
when: manual # requires click
Kluczowe różnice vs GitHub Actions:
-
stagesdefiniowane globalnie -
only/exceptzamiaston -
when: manualdla approval - Wbudowane Auto DevOps
Jak działają GitLab Runners i jak je skonfigurować?
Odpowiedź w 30 sekund:
GitLab Runners wykonują jobs. Typy:
- Shared runners - dostarczane przez GitLab
- Group runners - dla grupy projektów
- Project runners - dedykowane dla projektu
Odpowiedź w 2 minuty:
Proces instalacji i konfiguracji self-hosted runnera w GitLab:
# Instalacja self-hosted runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt install gitlab-runner
# Rejestracja
sudo gitlab-runner register \
--url https://gitlab.com \
--registration-token $TOKEN \
--executor docker \
--docker-image node:20
Executors:
- Shell - bezpośrednio na hoście
- Docker - każdy job w kontenerze
- Kubernetes - job jako Pod
- Docker Machine - auto-scaling
# Wybór runnera przez tagi
deploy:
tags:
- production
- aws
script:
- deploy.sh
Best practices:
- Docker executor dla izolacji
- Tagi do routingu jobs
- Autoscaling dla zmiennego load
Jak używać cache i artifacts w GitLab CI?
Odpowiedź w 30 sekund:
- Cache - przyspiesza jobs (dependencies)
- Artifacts - przekazuje pliki między stages
cache:
paths:
- node_modules/
artifacts:
paths:
- dist/
Odpowiedź w 2 minuty:
Przykłady konfiguracji cache i artifacts w GitLab CI pokazujące różne strategie:
# Cache per-branch
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
policy: pull-push # lub pull, push
# Artifacts między stages
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 hour
test:
stage: test
dependencies:
- build # pobiera artifacts z build
script:
- npm test -- --coverage
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura.xml
Różnice:
| Aspekt | Cache | Artifacts |
|---|---|---|
| Cel | Speedup | Data passing |
| Dostępność | Ten sam job | Między jobs |
| Retention | LRU | expire_in |
| Download | Automatyczny | Opcjonalny |
Co to jest GitLab Auto DevOps?
Odpowiedź w 30 sekund:
Auto DevOps to predefiniowany pipeline, który automatycznie:
- Builduje aplikację (autodetect języka)
- Uruchamia testy
- Skanuje bezpieczeństwo
- Deployuje do Kubernetes
Odpowiedź w 2 minuty:
Auto DevOps można włączyć na dwa sposoby - przez konfigurację lub ustawienia projektu:
# .gitlab-ci.yml
include:
- template: Auto-DevOps.gitlab-ci.yml
Albo w Settings → CI/CD → Auto DevOps.
Co zawiera:
- Auto Build - buduje Docker image
- Auto Test - uruchamia testy (Herokuish)
- Auto Code Quality - Code Climate
- Auto SAST - Static security testing
- Auto Dependency Scanning - CVE check
- Auto Container Scanning - skan obrazu
- Auto Review Apps - preview per MR
- Auto Deploy - do Kubernetes
Customizacja:
variables:
AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED: "true"
POSTGRES_ENABLED: "true"
TEST_DISABLED: "true" # wyłącz testy
Dobre dla: szybki start, standardowe aplikacje Złe dla: custom workflows, nietypowe stacki
Jenkins
Wyjaśnij różnicę między Declarative i Scripted Pipeline w Jenkins
Odpowiedź w 30 sekund:
- Declarative - prostszy, strukturalny, recommended
- Scripted - pełna moc Groovy, legacy
// Declarative
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'npm build'
}
}
}
}
Odpowiedź w 2 minuty:
Oto kompletny przykład obu stylów pipeline w porównaniu:
// Declarative Pipeline (recommended)
pipeline {
agent any
environment {
NODE_ENV = 'production'
}
stages {
stage('Build') {
steps {
sh 'npm ci'
sh 'npm run build'
}
}
stage('Test') {
parallel {
stage('Unit') {
steps { sh 'npm test' }
}
stage('E2E') {
steps { sh 'npm run e2e' }
}
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
sh './deploy.sh'
}
}
}
post {
always { cleanWs() }
failure { slackSend "Build failed!" }
}
}
// Scripted Pipeline (Groovy)
node {
stage('Build') {
checkout scm
sh 'npm ci'
sh 'npm run build'
}
stage('Test') {
try {
sh 'npm test'
} catch (e) {
currentBuild.result = 'UNSTABLE'
}
}
if (env.BRANCH_NAME == 'main') {
stage('Deploy') {
sh './deploy.sh'
}
}
}
Różnice:
- Declarative ma walidację składni
- Scripted daje pełną kontrolę (pętle, warunki)
- Declarative:
when {}, Scripted:if {}
Jak zarządzać credentials w Jenkins?
Odpowiedź w 30 sekund:
pipeline {
environment {
DOCKER_CREDS = credentials('docker-hub')
}
stages {
stage('Push') {
steps {
sh 'docker login -u $DOCKER_CREDS_USR -p $DOCKER_CREDS_PSW'
}
}
}
}
Odpowiedź w 2 minuty:
Jenkins obsługuje pięć głównych typów credentials dla różnych zastosowań:
- Username/Password
- Secret text
- Secret file
- SSH key
- Certificate
// W pipeline
pipeline {
stages {
stage('Deploy') {
steps {
withCredentials([
usernamePassword(
credentialsId: 'aws-creds',
usernameVariable: 'AWS_ACCESS_KEY',
passwordVariable: 'AWS_SECRET_KEY'
),
string(
credentialsId: 'slack-token',
variable: 'SLACK_TOKEN'
),
file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG'
)
]) {
sh 'kubectl apply -f deployment.yaml'
}
}
}
}
}
Zarządzanie:
- Manage Jenkins → Credentials
- Folders dla izolacji
- Credentials Binding Plugin
- HashiCorp Vault plugin dla external secrets
Co to jest Jenkins Shared Library?
Odpowiedź w 30 sekund:
Shared Library to reusable Groovy code współdzielony między pipelines:
@Library('my-shared-lib') _
pipeline {
stages {
stage('Deploy') {
steps {
deployToKubernetes(env: 'production')
}
}
}
}
Odpowiedź w 2 minuty:
Shared Library ma określoną strukturę katalogów z trzema głównymi folderami:
(root)
├── vars/
│ └── deployToKubernetes.groovy
├── src/
│ └── org/example/Utils.groovy
└── resources/
└── templates/deployment.yaml
// vars/deployToKubernetes.groovy
def call(Map config = [:]) {
def env = config.env ?: 'staging'
sh """
kubectl config use-context ${env}
kubectl apply -f k8s/
"""
}
Konfiguracja:
- Manage Jenkins → Configure System → Global Pipeline Libraries
- Lub w Jenkinsfile:
@Library('lib@main')
Korzyści:
- DRY - jedna definicja, wiele pipelines
- Wersjonowanie (tag/branch)
- Testowanie biblioteki osobno
- Standaryzacja praktyk w organizacji
Strategie Deploymentu
Wyjaśnij różnice między Rolling, Blue-Green i Canary deployment
Odpowiedź w 30 sekund:
| Strategia | Opis | Rollback |
|---|---|---|
| Rolling | Stopniowa wymiana instancji | Wolny |
| Blue-Green | Dwa środowiska, switch | Instant |
| Canary | % ruchu na nową wersję | Szybki |
Odpowiedź w 2 minuty:
Zobaczmy każdą strategię na przykładach, zaczynając od Rolling Update:
Rolling Update:
t0: [v1] [v1] [v1] [v1]
t1: [v2] [v1] [v1] [v1]
t2: [v2] [v2] [v1] [v1]
t3: [v2] [v2] [v2] [v1]
t4: [v2] [v2] [v2] [v2]
# Kubernetes
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
Blue-Green:
Blue (active): [v1] [v1] [v1] ← traffic
Green (idle): [v2] [v2] [v2]
# switch
Blue (idle): [v1] [v1] [v1]
Green (active): [v2] [v2] [v2] ← traffic
Wymaga podwójnych zasobów, ale instant rollback.
Canary:
t0: 100% → [v1] [v1] [v1] [v1]
t1: 90% → [v1] [v1] [v1]
10% → [v2]
t2: 50% → [v1] [v1]
50% → [v2] [v2]
t3: 100% → [v2] [v2] [v2] [v2]
# Istio VirtualService
http:
- route:
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: myapp
subset: v2
weight: 10
Wybór:
- Rolling: prosty, domyślny
- Blue-Green: krytyczne systemy, instant rollback
- Canary: testowanie na produkcji, feature flags
Jak zaimplementować Blue-Green deployment?
Odpowiedź w 30 sekund:
- Masz dwa identyczne środowiska (Blue i Green)
- Blue jest active, Green idle
- Deploy nowej wersji na Green
- Testuj Green
- Switch traffic na Green
- Blue staje się idle (backup)
Odpowiedź w 2 minuty:
Implementacja Blue-Green w Kubernetes wykorzystuje dwa deployment i przełączanie Service selector:
# Kubernetes z Service selector
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
template:
metadata:
labels:
app: myapp
version: blue
# ...
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
version: blue # ← switch to green
ports:
- port: 80
# Deploy green
kubectl apply -f green-deployment.yaml
# Test green
kubectl run test --rm -it --image=curlimages/curl -- curl http://app-green
# Switch traffic
kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}'
# Rollback if needed
kubectl patch service myapp -p '{"spec":{"selector":{"version":"blue"}}}'
Z AWS ALB:
# Zmień target group weight
aws elbv2 modify-listener --listener-arn $ARN \
--default-actions Type=forward,ForwardConfig='{
"TargetGroups": [
{"TargetGroupArn": "'$GREEN_TG'", "Weight": 100},
{"TargetGroupArn": "'$BLUE_TG'", "Weight": 0}
]
}'
Jak zaimplementować Canary deployment?
Odpowiedź w 30 sekund:
Canary to stopniowe kierowanie coraz większego % ruchu na nową wersję, monitorując metryki. Przy problemach - rollback.
Odpowiedź w 2 minuty:
Canary deployment z Istio pozwala kontrolować routing ruchu między wersjami aplikacji:
# Z Istio
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp
spec:
hosts:
- myapp
http:
- route:
- destination:
host: myapp
subset: stable
weight: 90
- destination:
host: myapp
subset: canary
weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp
spec:
host: myapp
subsets:
- name: stable
labels:
version: v1
- name: canary
labels:
version: v2
Automatyczny Canary z Flagger:
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: myapp
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
progressDeadlineSeconds: 600
service:
port: 80
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
threshold: 99
- name: request-duration
threshold: 500
Flagger automatycznie:
- Zwiększa traffic co 1 min o 10%
- Monitoruje success rate i latency
- Rollback gdy metryki poniżej threshold
Co to jest GitOps i jak się różni od tradycyjnego CI/CD?
Odpowiedź w 30 sekund:
GitOps to praktyka gdzie Git jest single source of truth dla infrastruktury. Operator (ArgoCD, Flux) ciągle synchronizuje klaster z repozytorium.
Odpowiedź w 2 minuty:
Porównajmy oba podejścia na schematach przepływu deploymentu:
Traditional CI/CD (Push):
Code repo → CI build → CI push → Deploy to cluster
↓
CD pushuje
GitOps (Pull):
Code repo → CI build → Push to config repo
↓
Config repo ← ArgoCD pulls ← Cluster
Kluczowe różnice:
| Aspekt | Traditional | GitOps |
|---|---|---|
| Trigger | CI push | Git commit |
| State | Cluster | Git repo |
| Rollback | Re-deploy | Git revert |
| Audit | CI logs | Git history |
| Access | CI needs kubectl | Operator only |
ArgoCD example:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
spec:
source:
repoURL: https://github.com/org/config
path: apps/myapp
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
Korzyści GitOps:
- Git jako audit log
- Declarative, reproducible
- Mniejsza powierzchnia ataku (operator wewnątrz klastra)
- Łatwiejszy rollback (git revert)
Security w CI/CD
Jak skanować bezpieczeństwo w pipeline CI/CD?
Odpowiedź w 30 sekund:
Typy skanowania:
- SAST - Static Application Security Testing (kod)
- DAST - Dynamic Testing (running app)
- Dependency scanning - CVE w bibliotekach
- Container scanning - CVE w obrazach
Odpowiedź w 2 minuty:
Kompletny pipeline security scanningów w GitHub Actions obejmuje cztery rodzaje testów:
# GitHub Actions z security scanning
name: Security Pipeline
on: [push, pull_request]
jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Semgrep SAST
uses: semgrep/semgrep-action@v1
with:
config: auto
dependency-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: npm audit
run: npm audit --audit-level=high
- name: Snyk check
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
container-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Trivy scan
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
exit-code: '1'
severity: 'HIGH,CRITICAL'
secrets-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Gitleaks
uses: gitleaks/gitleaks-action@v2
Best practices:
- Fail pipeline przy HIGH/CRITICAL
- Scan na każdy PR (shift left)
- Regularny scan produkcji
- Integracja z ticket system
Jak bezpiecznie przechowywać i używać sekretów w CI/CD?
Odpowiedź w 30 sekund:
- Nigdy w kodzie
- Używaj wbudowanych secret managers (GitHub Secrets, GitLab CI Variables)
- Dla zaawansowanych: HashiCorp Vault, AWS Secrets Manager
- OIDC zamiast long-lived credentials
Odpowiedź w 2 minuty:
Najlepszą praktyką jest używanie OIDC zamiast long-lived credentials - oto przykład dla AWS:
# GitHub Actions + OIDC (bez sekretów!)
jobs:
deploy:
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456:role/GitHubActionsRole
aws-region: eu-west-1
# Teraz masz AWS credentials bez żadnych sekretów!
HashiCorp Vault:
steps:
- uses: hashicorp/vault-action@v2
with:
url: https://vault.example.com
method: jwt
role: ci-role
secrets: |
secret/data/prod DB_PASSWORD | DB_PASSWORD
- run: psql -h db -U app -c "SELECT 1"
env:
PGPASSWORD: ${{ steps.vault.outputs.DB_PASSWORD }}
Zasady:
- Minimalne uprawnienia (least privilege)
- Krótki czas życia tokenów
- Rotacja sekretów
- Audit log dostępu
- Osobne sekrety per environment
- Masked w logach
Jak zabezpieczyć deployment na produkcję?
Odpowiedź w 30 sekund:
- Protected branches
- Required reviews
- Environment protection rules
- Manual approval gates
- Deployment windows
Odpowiedź w 2 minuty:
W GitHub Actions używamy protected environments z approval gates dla deploymentów produkcyjnych:
# GitHub Actions - protected environment
jobs:
deploy-prod:
environment:
name: production
url: https://example.com
steps:
- run: deploy.sh
GitHub Environment protection:
- Required reviewers
- Wait timer (e.g., 30 min delay)
- Deployment branches (only main)
GitLab:
deploy-prod:
stage: deploy
environment:
name: production
when: manual
only:
- main
allow_failure: false
Protected environments w GitLab:
- Settings → CI/CD → Protected Environments
- Wymagaj approval od maintainers
Dodatkowe zabezpieczenia:
- Deployment windows (nie w piątek!)
- Feature flags dla gradual rollout
- Automated rollback przy alertach
- Smoke tests po deployment
- Canary analysis przed full rollout
Troubleshooting i Best Practices
Pipeline jest wolny - jak go przyspieszyć?
Odpowiedź w 30 sekund:
- Cache dependencies
- Parallel jobs
- Skip unnecessary steps
- Smaller Docker images
- Selective triggers
Odpowiedź w 2 minuty:
Oto pięć konkretnych technik optymalizacji pipeline z przykładami kodu:
# 1. Aggressive caching
- uses: actions/cache@v4
with:
path: |
~/.npm
~/.cache
node_modules
key: deps-${{ hashFiles('**/package-lock.json') }}
# 2. Parallelization
jobs:
test:
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- run: npm test -- --shard=${{ matrix.shard }}/4
# 3. Conditional execution
on:
push:
paths:
- 'src/**'
- 'tests/**'
paths-ignore:
- '*.md'
- 'docs/**'
# 4. Skip CI for docs
# [skip ci] w commit message
# 5. Smaller images
FROM node:20-alpine # zamiast node:20
# 6. Docker layer cache
- uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
Metryki do monitorowania:
- Total pipeline time
- Time per stage
- Queue wait time
- Cache hit rate
Jak debugować failing pipeline?
Odpowiedź w 30 sekund:
- Czytaj logi (od końca!)
- Sprawdź exit codes
- Reprodukuj lokalnie
- SSH do runner (jeśli dostępne)
- Dodaj debug output
Odpowiedź w 2 minuty:
Techniki debugowania pipeline w GitHub Actions z pełnym logowaniem i możliwością SSH:
# GitHub Actions debug
env:
ACTIONS_STEP_DEBUG: true
ACTIONS_RUNNER_DEBUG: true
# Verbose output
steps:
- run: |
set -x # bash debug mode
npm test 2>&1 | tee test.log
- uses: actions/upload-artifact@v4
if: failure()
with:
name: logs
path: test.log
# Tmate for SSH access
- uses: mxschmitt/action-tmate@v3
if: failure()
GitLab:
test:
script:
- npm test
after_script:
- cat npm-debug.log || true
artifacts:
when: on_failure
paths:
- npm-debug.log
Checklist:
- Czy działa lokalnie?
- Czy dependencies są aktualne?
- Czy environment variables ustawione?
- Czy secrets nie wygasły?
- Czy runner ma dostęp do external services?
- Czy jest rate limiting?
Jakie są best practices dla pipeline CI/CD?
Odpowiedź w 30 sekund:
- Fast feedback (fail fast)
- Reproducible builds
- Security scanning
- Infrastructure as Code
- Monitoring i alerting
Odpowiedź w 2 minuty:
Poniżej kompletny przykład pipeline implementujący wszystkie kluczowe best practices:
# Best practices in action
name: Production Pipeline
on:
push:
branches: [main]
env:
# Pin versions
NODE_VERSION: '20.10.0'
DOCKER_BUILDKIT: 1
jobs:
# 1. Fast feedback - lint first
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
# 2. Parallel tests
test:
needs: lint # fail fast
strategy:
fail-fast: true
matrix:
shard: [1, 2, 3]
steps:
- run: npm test -- --shard=${{ matrix.shard }}/3
# 3. Security scan
security:
needs: lint
steps:
- uses: snyk/actions/node@master
# 4. Reproducible build
build:
needs: [test, security]
steps:
- run: |
docker build \
--build-arg VERSION=${{ github.sha }} \
--label git-commit=${{ github.sha }} \
-t app:${{ github.sha }} .
# 5. Staged deployment
deploy-staging:
needs: build
environment: staging
steps:
- run: deploy.sh staging
# 6. E2E on staging
e2e:
needs: deploy-staging
steps:
- run: npm run test:e2e
# 7. Production with approval
deploy-prod:
needs: e2e
environment:
name: production
url: https://example.com
steps:
- run: deploy.sh production
# 8. Post-deploy verification
smoke-test:
needs: deploy-prod
steps:
- run: curl -f https://example.com/health
Dodatkowe:
- Wersjonuj pipeline (jako kod)
- Dokumentuj custom steps
- Regularny przegląd i cleanup
- Monitoring pipeline metrics
Zobacz też
- Kompletny Przewodnik - Rozmowa DevOps Engineer - pełny przewodnik przygotowania do rozmowy
- Docker - Pytania Rekrutacyjne - 42 pytania o konteneryzację
- Kubernetes - Pytania Rekrutacyjne - 60+ pytań o orkiestrację
- Linux - Pytania Rekrutacyjne - 50+ pytań o komendy i bash
- AWS - Pytania Rekrutacyjne - 55+ pytań o cloud
Ten artykuł jest częścią serii przygotowującej do rozmów rekrutacyjnych na stanowisko DevOps Engineer. Sprawdź nasze fiszki z pytaniami rekrutacyjnymi: DevOps Interview Questions.
Chcesz więcej pytań rekrutacyjnych?
To tylko jeden temat z naszego kompletnego przewodnika po rozmowach rekrutacyjnych. Uzyskaj dostęp do 800+ pytań z 13 technologii.
