CI/CD Pipeline Nedir? Modern Yazılım Geliştirmede Sürekli Entegrasyon ve Dağıtım
Yazılım geliştirme dünyasında hızlı ve güvenilir yayınlamalar yapmak artık zorunluluk haline geldi. CI/CD Pipeline'ları, bu zorluk karşısında en etkili çözüm olarak karşımıza çıkıyor. Yazılımı manuel olarak derlemek, test etmek ve yayınlamak yerine, bu işlemleri otomatikleştirerek hız kazanıyoruz.
Bu yazıda, CI/CD Pipeline'ın ne olduğunu, nasıl çalıştığını, popüler araçlarını ve pratik implementasyonlarını inceleyeceğiz.
İçindekiler
- CI/CD Nedir ve Neden Önemlidir?
- Continuous Integration (CI) - Sürekli Entegrasyon
- Continuous Delivery ve Deployment (CD)
- CI/CD Pipeline Aşamaları
- Popüler CI/CD Araçları Karşılaştırması
- GitHub Actions ile Complete Pipeline
- GitLab CI/CD Kullanımı
- Jenkins Pipeline Konfigürasyonu
- Docker ve Kubernetes ile CI/CD
- DevSecOps: Pipeline'a Güvenlik Entegrasyonu
- Best Practices ve Optimizasyon
- Yaygın Hatalar ve Çözümleri
CI/CD Nedir ve Neden Önemlidir? {#cicd-nedir}
Tanım
CI/CD, yazılım geliştirme sürecini otomatikleştiren ve hızlandıran iki önemli pratiğin kombinasyonudur:
- Continuous Integration (CI): Geliştiricilerin kodlarını merkezi bir repository'ye sık sık merge etmeleri ve her merge'de otomatik testler çalıştırılması
- Continuous Delivery/Deployment (CD): Otomatik olarak derlenmiş ve test edilmiş kodun production ortamına yayınlanması
Geleneksel vs CI/CD Yaklaşımı
Geleneksel Deployment Süreci (Problemli):
- Geliştirici aylar boyunca kod yazıyor
- Tüm kod bir kez merge ediliyor (entegrasyon problemi)
- Manuel test çalıştırılıyor
- Manuel deployment yapılıyor
- Sorunlar production'da keşfediliyor
- Rollback yapmak zor oluyor
CI/CD Yaklaşımı (Modern):
- Geliştiriciler her gün kodu merge ediyor
- Otomatik testler anında çalışıyor
- Hata bulunursa anında feedback alınıyor
- Deployment otomatik ve güvenli
- Sorunlar hızlı çözülüyor
- Rollback operasyonları basit
İş Değeri ve Faydalar
CI/CD implementasyonunun kanıtlanmış faydaları:
| Metrik | İyileştirme |
|---|---|
| **Deployment Sıklığı** | Haftada birden günde birkaç kez |
| **Lead Time** | 3-6 aydan saatlere |
| **Mean Time to Recovery** | Saatlerden dakikalara |
| **Change Failure Rate** | %46'dan %15'e |
| **Development Verimliği** | %20-30 artış |
Bu metrikler DORA (DevOps Research and Assessment) tarafından şirkletlerin verilerine dayanarak hesaplanmıştır.
Continuous Integration (CI) - Sürekli Entegrasyon {#continuous-integration}
CI Prensipleri
Continuous Integration, aşağıdaki prensiplere dayanır:
- Sık Code Integration: Geliştiriciler en az günde bir kez kodlarını merge ederler
- Otomatik Build: Her merge'de otomatik olarak kod derlenir
- Otomatik Test: Birim, entegrasyon ve smoke testleri çalıştırılır
- Hızlı Feedback: Sorunlar dakikalar içinde rapor edilir
- Kontrol Mekanizmaları: Hata içeren kod merge edilmez
Workflow
Developer Code Push
↓
Trigger Pipeline
↓
Checkout Source Code
↓
Dependencies Install
↓
Lint & Code Quality
↓
Build
↓
Unit Tests
↓
Integration Tests
↓
Code Coverage Check
↓
Success/Failure Report
Source Control Integration
Modern CI sistemleri git repository'lere bağlanır:
- Webhook'lar: Repository'de push gerçekleşince otomatik tetiklenir
- Branch Protection: CI başarısız olursa merge yasaklanır
- Status Checks: GitHub/GitLab'da PR'lar CI sonucunu gösterir
Testing Stratejileri
CI Pipeline'da çalıştırılması gereken testler:
- Unit Tests - Tek fonksiyon/metod testleri (hızlı, ~2-5 dakika)
- Integration Tests - Modüller arası testler (orta hızlı, ~5-10 dakika)
- Code Quality - Linting, complexity analysis
- Security Scans - SAST araçlarıyla güvenlik taraması
- Smoke Tests - Kritik özellikler kontrol edilir
Continuous Delivery ve Deployment (CD) {#continuous-delivery}
Farklar
Continuous Delivery (CD):
- Kod her zaman production'a hazır
- Manual onay alındıktan sonra yayınlanır
- Kontrollü ve güvenli
- İnsan hatası riski minimum
Continuous Deployment:
- Her başarıyla tamamlanan CI production'a otomatik yayınlanır
- Manuel onay gerekmez
- En hızlı feedback süreci
- Daha yüksek risk
Çoğu kuruluş Continuous Delivery yaklaşımını tercih eder (manual approval).
Deployment Stratejileri
1. Blue-Green Deployment
- İki identik ortam: Blue (eski) ve Green (yeni)
- Trafik Blue'ya yönlendirilir
- Green test edilir
- Trafik Green'e switch edilir
- Sorun varsa Blue'ya geri dönülür
2. Canary Deployment
- Yeni versiyon küçük bir kullanıcı grubuna yayınlanır (örn: %5)
- Metrikler izlenir
- Sorun yoksa gradual olarak artırılır
- Rollback hızlıdır
3. Rolling Update
- Pod'lar sırasıyla güncellenir
- Hizmet kesintisi olmaz
- Kubernetes'in default stratejisi
4. Feature Flags
- Özellik kodda var ama disabled
- Production'da feature flag'i açıp kapatabilirsiniz
- Rollback gerek olmaz
Environment Management
Environments:
- Development: Geliştirici ortamı, sık deploy edilir
- Staging: Production kopyası, son test aşaması
- Production: Canlı ortam, manual approval gerekir
CI/CD Pipeline Aşamaları {#pipeline-asamalari}
Bir complete pipeline aşağıdaki aşamaları içerir:
1. Source Aşaması
- Kod repository'den checkout edilir
- Git history kontrol edilir
- Uygun branch'in kullanıldığı doğrulanır
2. Build Aşaması
- Bağımlılıklar indirilir
- Kod derlenir
- Artifacts (JAR, binary, Docker image vs.) oluşturulur
3. Test Aşaması
- Unit testler çalıştırılır
- Integration testler çalıştırılır
- Code coverage kontrol edilir
- Hata varsa pipeline durdurulur
4. Security Scan Aşaması
- SAST (Static Application Security Testing) - kaynak kod taraması
- Dependency scanning - kütüphanelerdeki vulnerabilities
- Secret scanning - sızıntılı credentials kontrol
- Container image scanning
5. Deploy Aşaması
- Artifacts container registry'ye push edilir
- Staging/Production ortamına deploy edilir
- Health checks çalıştırılır
6. Post-Deployment Aşaması
- Smoke tests çalıştırılır
- Metrikleri monitoring'e bağlanır
- Slack/Teams'e bildirim gönderilir
- Rollback hazırlığı yapılır
Popülar CI/CD Araçları Karşılaştırması {#populer-araçlar}
| Araç | Yerleşim | Kurulum | Kolaylık | Ölçeklenebilirlik | Fiyat |
|---|---|---|---|---|---|
| **GitHub Actions** | GitHub'ta | Çok kolay | ★★★★★ | İyi | Bedava/ücretli |
| **GitLab CI/CD** | GitLab'ta | Kolay | ★★★★★ | Çok iyi | Bedava/ücretli |
| **Jenkins** | Kendi sunucu | Zor | ★★★☆☆ | Mükemmel | Bedava |
| **CircleCI** | Cloud | Orta | ★★★★☆ | İyi | Ücretli |
| **Azure DevOps** | Cloud | Orta | ★★★★☆ | İyi | Ücretli |
| **Tekton** | Kubernetes | Zor | ★★★☆☆ | Mükemmel | Bedava |
Seçim Kriterleri
- GitHub Actions: GitHub kullanıyorsanız ve basit pipeline istiyorsanız
- GitLab CI: GitLab kullanıyorsanız veya advanced features istiyorsanız
- Jenkins: Kurumsal, kompleks ihtiyaçlar ve on-prem çözümleri için
- Tekton: Kubernetes-native, cloud-agnostic çözümler için
GitHub Actions ile Complete Pipeline {#github-actions}
GitHub Actions, GitHub'ta natively çalışan ve hiçbir kurulum gerektirmeyen güçlü bir CI/CD sistemidir.
Architecture
GitHub Repository
↓
Webhook (push/PR)
↓
Workflow Trigger
↓
Runner (Linux/Windows/macOS)
↓
Jobs & Steps
↓
Artifacts & Results
Tam Pipeline Örneği
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Run Prettier
run: npm run format:check
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x, 22.x]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm run test:unit
- name: Run integration tests
run: npm run test:integration
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/coverage-final.json
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
build:
needs: [lint, test, security]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Deploy to Kubernetes
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config
kubectl set image deployment/app app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} -n production
kubectl rollout status deployment/app -n production --timeout=5m
- name: Run smoke tests
run: |
curl -f https://api.example.com/health || exit 1
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{
"text": "Deployment ${{ job.status }}",
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Deployment Status:* ${{ job.status }}\n*Commit:* ${{ github.sha }}\n*Author:* ${{ github.actor }}"
}
}]
}
Temel Konseptler
- Workflows:
.github/workflows/*.ymldosyalarında tanımlanır - Jobs: Bir workflow'da paralel veya sequential çalışabilir
- Steps: Job'un içindeki individual komutlar
- Actions: Reusable workflow bileşenleri (GitHub Marketplace)
- Runners: Pipeline'ı çalıştıran compute instances
- Secrets: Krediler güvenli şekilde saklanan environment variables
GitLab CI/CD Kullanımı {#gitlab-ci}
GitLab CI, en kapsamlı ve kurumsal-ready CI/CD çözümlerinden biridir.
Architecture
GitLab Repository
↓
.gitlab-ci.yml (tanım dosyası)
↓
GitLab Runner (executor: docker/shell/kubernetes)
↓
Artifacts, Container Registry, Pages
↓
Deployment
Complete Pipeline Örneği
stages:
- build
- test
- security
- deploy
- rollback
variables:
REGISTRY: registry.gitlab.com
IMAGE_NAME: $CI_PROJECT_PATH
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
.docker_build_template: &docker_build
image: docker:latest
services:
- docker:dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
build:
<<: *docker_build
stage: build
script:
- docker build -t $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA .
- docker push $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA
artifacts:
reports:
dotenv: build.env
cache:
- key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
only:
- main
- develop
test:unit:
image: node:20
stage: test
script:
- npm ci
- npm run test:unit -- --coverage
coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
artifacts:
paths:
- coverage/
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
test:integration:
image: node:20
stage: test
services:
- postgres:15
- redis:7
variables:
POSTGRES_DB: test_db
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_pass
REDIS_URL: redis://redis:6379
script:
- npm ci
- npm run test:integration
timeout: 30 minutes
security:sast:
image: returntocorp/semgrep
stage: security
script:
- semgrep --config=p/security-audit --json -o sast-report.json .
artifacts:
reports:
sast: sast-report.json
security:container:
image: aquasec/trivy:latest
stage: security
script:
- trivy image --severity HIGH,CRITICAL --exit-code 1 $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA
allow_failure: true
security:dependency:
image: node:20
stage: security
script:
- npm ci
- npm audit --json > dependency-report.json || true
artifacts:
paths:
- dependency-report.json
deploy:staging:
image: bitnami/kubectl:latest
stage: deploy
environment:
name: staging
kubernetes_namespace: staging
script:
- kubectl set image deployment/app app=$REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n staging
- kubectl rollout status deployment/app -n staging --timeout=5m
only:
- develop
when: manual
deploy:production:
image: bitnami/kubectl:latest
stage: deploy
environment:
name: production
kubernetes_namespace: production
deployment_tier: production
script:
- kubectl set image deployment/app app=$REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n production
- kubectl rollout status deployment/app -n production --timeout=5m
only:
- main
when: manual
rollback:production:
image: bitnami/kubectl:latest
stage: rollback
environment:
name: production
kubernetes_namespace: production
script:
- kubectl rollout undo deployment/app -n production
- kubectl rollout status deployment/app -n production --timeout=5m
when: manual
only:
- main
GitLab Runner Setup
GitLab Pipeline'ları çalıştırmak için Runner gereklidir:
# Runner kurulumu
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash
sudo apt-get install gitlab-runner
# Runner register (Docker executor ile)
sudo gitlab-runner register \
--url https://gitlab.com/ \
--registration-token $RUNNER_TOKEN \
--executor docker \
--docker-image ubuntu:latest
Cache ve Artifacts
# Cache: İş arası paylaşılan veriler (npm modules vb.)
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .gradle/wrapper/
# Artifacts: İşin çıktısı (test reports, binaries vb.)
artifacts:
paths:
- dist/
- coverage/
when: always
expire_in: 30 days
Jenkins Pipeline Konfigürasyonu {#jenkins-pipeline}
Jenkins, kurumsal CI/CD çözümleri için en yaygın açık kaynak platformudur.
Declarative Pipeline Örneği
pipeline {
agent any
environment {
REGISTRY = 'docker.io'
IMAGE_NAME = 'tektik/app'
NODE_ENV = 'production'
SONARQUBE_URL = 'http://sonarqube:9000'
}
options {
timestamps()
timeout(time: 1, unit: 'HOURS')
buildDiscarder(logRotator(numToKeepStr: '10'))
}
triggers {
githubPush()
pollSCM('H/15 * * * *')
}
stages {
stage('Checkout') {
steps {
checkout scm
script {
sh '''
git log --oneline -1
echo "Current branch: $(git rev-parse --abbrev-ref HEAD)"
'''
}
}
}
stage('Install Dependencies') {
steps {
sh '''
node --version
npm --version
npm ci
'''
}
}
stage('Lint') {
parallel {
stage('ESLint') {
steps {
sh 'npm run lint -- --format json > eslint-report.json || true'
}
}
stage('SonarQube') {
steps {
sh '''
npm run build
sonar-scanner \
-Dsonar.projectKey=tektik \
-Dsonar.sources=src \
-Dsonar.host.url=$SONARQUBE_URL \
-Dsonar.login=$SONARQUBE_TOKEN
'''
}
}
}
}
stage('Unit Tests') {
steps {
sh '''
npm run test:unit -- --coverage --watchAll=false
'''
junit 'coverage/junit.xml'
publishHTML([
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: 'Coverage Report'
])
}
}
stage('Security Scans') {
parallel {
stage('Dependency Check') {
steps {
sh '''
npm audit --json > audit-report.json || true
'''
}
}
stage('Container Scan') {
steps {
sh '''
docker build -t $IMAGE_NAME:$BUILD_NUMBER .
trivy image --severity HIGH,CRITICAL $IMAGE_NAME:$BUILD_NUMBER
'''
}
}
stage('Secret Scan') {
steps {
sh '''
git secrets --scan
'''
}
}
}
}
stage('Build') {
steps {
sh '''
npm run build
docker build -t $REGISTRY/$IMAGE_NAME:$BUILD_NUMBER .
docker tag $REGISTRY/$IMAGE_NAME:$BUILD_NUMBER $REGISTRY/$IMAGE_NAME:latest
'''
}
}
stage('Push to Registry') {
when {
branch 'main'
}
steps {
sh '''
docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD $REGISTRY
docker push $REGISTRY/$IMAGE_NAME:$BUILD_NUMBER
docker push $REGISTRY/$IMAGE_NAME:latest
'''
}
}
stage('Deploy to Staging') {
when {
branch 'develop'
}
steps {
sh '''
kubectl set image deployment/app app=$REGISTRY/$IMAGE_NAME:$BUILD_NUMBER -n staging
kubectl rollout status deployment/app -n staging --timeout=5m
'''
}
}
stage('Smoke Tests') {
when {
branch 'main'
}
steps {
sh '''
sleep 10
curl -f http://app-service:3000/health || exit 1
'''
}
}
stage('Deploy to Production') {
when {
branch 'main'
}
input {
message 'Deploy to production?'
ok 'Deploy'
submitter 'devops-team'
}
steps {
sh '''
kubectl set image deployment/app app=$REGISTRY/$IMAGE_NAME:$BUILD_NUMBER -n production
kubectl rollout status deployment/app -n production --timeout=5m
'''
}
}
}
post {
always {
junit allowEmptyResults: true, testResults: '**/*.xml'
// Slack bildirimi
slackSend(
color: currentBuild.result == 'SUCCESS' ? 'good' : 'danger',
message: """
Jenkins Build ${currentBuild.number} ${currentBuild.result}
Job: ${env.JOB_NAME}
Branch: ${env.GIT_BRANCH}
Commit: ${env.GIT_COMMIT}
"""
)
// Cleanup
cleanWs()
}
failure {
emailext(
subject: "Jenkins Build Failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
Build Failed
Job: ${env.JOB_NAME}
Build Number: ${env.BUILD_NUMBER}
Build URL: ${env.BUILD_URL}
Error: Check console output at ${env.BUILD_URL}
""",
to: '${DEFAULT_RECIPIENTS}'
)
}
}
}
Jenkins Installation & Setup
# Docker ile Jenkins başlatma
docker run -d \
--name jenkins \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:lts
# Kubernetes üzerinde
kubectl create namespace jenkins
helm repo add jenkinsci https://charts.jenkins.io
helm install jenkins jenkinsci/jenkins -n jenkins
Docker ve Kubernetes ile CI/CD {#docker-kubernetes}
Multi-Stage Dockerfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci
# Copy source code
COPY . .
# Build application
RUN npm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
# Security: Run as non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
# Install production dependencies only
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# Copy built application from builder
COPY /app/dist ./dist
# Health check
HEALTHCHECK \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
# Expose port
EXPOSE 3000
# Switch to nodejs user
USER nodejs
# Start application
CMD ["node", "dist/server.js"]
Kubernetes Deployment & Rolling Update
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
namespace: production
labels:
app: app
spec:
replicas: 3
# Rolling update strategy
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Fazladan 1 pod
maxUnavailable: 0 # 0 pod unavailable (zero downtime)
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "3000"
prometheus.io/path: "/metrics"
spec:
# Pod scheduling
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- app
topologyKey: kubernetes.io/hostname
containers:
- name: app
image: registry.example.com/tektik/app:latest
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 3000
protocol: TCP
# Environment variables
env:
- name: NODE_ENV
value: "production"
- name: LOG_LEVEL
value: "info"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
# Resource management
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
# Readiness probe (ready mı?)
readinessProbe:
httpGet:
path: /health/ready
port: http
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
# Liveness probe (canlı mı?)
livenessProbe:
httpGet:
path: /health/live
port: http
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
# Startup probe (başlatılıyor mu?)
startupProbe:
httpGet:
path: /health/startup
port: http
failureThreshold: 30
periodSeconds: 10
# Graceful shutdown
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
# Security context
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1001
capabilities:
drop:
- ALL
# Volume mounts
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/.cache
# Service account
serviceAccountName: app
# Volumes
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
# Pod termination grace period
terminationGracePeriodSeconds: 30
DevSecOps: Pipeline'a Güvenlik Entegrasyonu {#devsecops-entegrasyon}
DevSecOps, güvenliği CI/CD pipeline'ın her aşamasına entegre etme yaklaşımıdır.
Security Stages Örneği
name: Security Pipeline
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
# 1. Dependency Vulnerability Scanning
- uses: actions/checkout@v4
- name: Dependency check with Snyk
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
# 2. Static Application Security Testing (SAST)
- name: SonarQube scan
uses: sonarsource/sonarqube-scan-action@master
env:
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# 3. Secret Scanning
- name: Scan for secrets
uses: gitleaks/gitleaks-action@v2
# 4. Container Image Scanning
- uses: actions/setup-docker@v1
- name: Build and scan image
run: |
docker build -t myapp:${{ github.sha }} .
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:${{ github.sha }}
# 5. License Compliance
- name: License check
run: |
npm install -g license-checker
license-checker --onlyAllow Apache-2.0,MIT,BSD --json > licenses.json
# 6. Infrastructure as Code Security
- name: Scan Terraform
uses: aquasecurity/tfsec-action@v1
with:
working_directory: 'infrastructure/'
DevSecOps Best Practices
- Shift Left: Güvenliği geliştirme başında (kod yazarken) kontrol edin
- Otomatikleştirin: Tüm güvenlik kontrolleri otomatik olmalı
- Fail Secure: Güvenlik testleri başarısız olursa deployment durmalı
- Audit & Logging: Tüm işlemler loglanmalı
- Secret Management: Credentials kodda olmamalı, Vault gibi araçlar kullanın
Best Practices ve Optimizasyon {#best-practices}
1. Fail Fast Prensibi
Hata erken bulunmalıdır:
stages:
- lint # Paralel çalışır (30 saniye)
- build # Lint başarısız olursa çalışmaz
- test # Build başarısız olursa çalışmaz
- deploy # Test başarısız olursa çalışmaz
2. Pipeline as Code
- Pipeline'ı kod olarak tanımlayın (YAML, Groovy vb.)
- Repository'de version control altında tutun
- Code review için PR process kullanın
- Infrastructure as Code gibi düşünün
3. Secret Management
# ❌ YANLIŞ - Secrets hardcoded
password: "super_secret_123"
# ✅ DOĞRU - Secrets environment variable
password: ${{ secrets.DATABASE_PASSWORD }}
# ✅ DAHA DOĞRU - Vault ile
password: vault kv get secret/prod/db_password
4. Caching Strategy
# NPM cache örneği
cache:
key:
files:
- package-lock.json # Hash'ine göre cache key
paths:
- node_modules/
# Docker layer cache
docker build --cache-from myapp:latest .
5. Parallel Execution
jobs:
test:
strategy:
matrix:
node-version: [18.x, 20.x, 22.x]
os: [ubuntu-latest, macos-latest]
# 3x2 = 6 parallel job
6. Monitoring ve Observability
Pipeline metriklerini takip edin:
- Build süresi (trend analizi)
- Success/failure rates
- Test coverage
- Deployment frequency
- Mean time to recovery (MTTR)
Yaygın Hatalar ve Çözümleri {#yaygın-hatalar}
1. Build Failures
Problem: Lokal'de çalışan kod, pipeline'da başarısız oluyor
Çözüm:
# Lock files kullanın
npm ci # npm install yerine (package-lock.json respects)
# Dockerfile ile konsistent environment
docker run --rm -v $(pwd):/app myapp:build npm test
# Exact versions belirtin
node_version: '20.13.0' # 20.x değil
2. Flaky Tests
Problem: Bazen geçen, bazen başarısız olan testler
Çözüm:
# Retry logic
- name: Run tests
run: npm test
timeout-minutes: 10
continue-on-error: true
- name: Retry failed tests
run: npm test -- --testPathPattern=previously-failed
if: failure()
# Test isolation
# Her test paralel çalışırken kendi database/Redis instance'ı kullanmalı
3. Slow Pipelines
Problem: Pipeline 30+ dakika sürüyor
Çözüm:
# Parallelization
jobs:
test:
parallel: 10 # 10 paralel worker
# Caching optimization
- uses: actions/cache@v3
with:
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
# Docker layer caching
- uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
4. Deployment Failures
Problem: Deployment başarılı ama application crash oluyor
Çözüm:
# Health checks
- name: Health check
run: |
for i in {1..30}; do
curl -f http://app:3000/health && exit 0
sleep 1
done
exit 1
# Readiness probes
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
# Automatic rollback
kubectl rollout status deployment/app --timeout=5m || kubectl rollout undo deployment/app
5. Secret Leakage
Problem: Sensitive bilgiler git history'ye committed oluyor
Çözüm:
# Secret scanning tools
- name: Detect secrets
uses: gitleaks/gitleaks-action@v2
# Environment variables maskleme (logs'ta görmez)
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
run: deploy.sh
# Pre-commit hooks
# .githooks/pre-commit: git secrets --scan
git config core.hooksPath .githooks
Sonuç ve Öneriler
CI/CD Pipeline'ları modern yazılım geliştirmenin temelini oluşturuyor. 2025'te, bir yazılım ekibinin CI/CD olmadan çalışması neredeyse imkansız hale geldi.
Temel Öneriler:
Başlangıç Adımları
- Basit bir pipeline ile başlayın (GitHub Actions önerilir)
- Linting ve testleri otomatikleştirin
- Container image oluşturmayı otomatikleştirin
Güvenlik Odaklı Yaklaşım
- DevSecOps'u baştan entegre edin
- Secret management araçları kullanın
- Dependency scanning ve SAST ekleyin
Ölçeklenebilirlik
- Infrastructure as Code kullanın
- GitOps patterns benimseyin
- Kubernetes üzerinde çalışmayı öğrenin
İzleme ve Optimizasyon
- Pipeline metriklerini takip edin
- Slow jobs'u identify ve optimize edin
- Deployment frequency artırın
Takım Kültürü
- "Deploy Day" mentality'nden kurtulun
- Fail fast ve quick recovery kültürü oluşturun
- Automation'u herkesin sorumluluk alanı yapın
İlgili Yazılar
- DevSecOps: Modern Güvenlik Yaklaşımı - DevSecOps detayları
- Kubernetes Best Practices - K8s deployment
- 2025 DevOps Trendleri - Platform Engineering & AIOps
Kaynaklar
- GitHub Actions Documentation
- GitLab CI/CD Documentation
- Jenkins Documentation
- DORA Metrics
- CNCF Landscape
TekTık Yazılım olarak, modern CI/CD mimarilerini tasarlayan ve uygulayan ekip olarak, organizasyonunuzun deployment süreçlerini optimize etmek ve DevOps maturitesini artırmak için size yardımcı olabilir. CI/CD transformation, Kubernetes migration veya DevSecOps implementasyonu hakkında danışmanlık hizmetimizden faydalanabilirsiniz.
İletişim: info@tektik.tr | https://tektik.tr