Ana içeriğe atla

Genel Bakış

Bu kılavuz, modern bir CI/CD pipeline’ı kullanarak API’lerinizi otomatik olarak Apinizer’a nasıl deploy edeceğinizi gösterir. Örnek senaryo, GitHub Actions ile Docker image oluşturma, Jenkins ile Kubernetes deployment ve Apinizer üzerinde API proxy yönetimini kapsar.

Kullanılan Teknolojiler ve Versiyonlar

TeknolojiVersiyon
Jenkinsjenkins/jenkins:lts
Apinizerv2026.01.5
GitHub Actions
KubernetesOrtamınıza bağlı

Pipeline Akışı

GitHub Push → GitHub Actions (Build & Tag) → Jenkins Trigger → 
Kubernetes Deploy → Health Check → Apinizer API Proxy Sync → Apinizer Deploy

Mimari Genel Bakış

Bu entegrasyon senaryosu şu bileşenleri kullanır:
  • GitHub Actions: Docker image build ve versiyonlama işlemleri GitHub tarafında yürütülür.
  • Jenkins: Orchestration ve deployment yönetimi Jenkins sunucunuzda gerçekleşir.
  • Kubernetes: Container orchestration cluster’ınızda çalışır.
  • Apinizer: API Gateway ve API proxy yönetimi Apinizer instance’ınız üzerinden yapılır.

1. GitHub Actions Workflow

GitHub Actions, her main branch’e push işleminde otomatik olarak:
  • Yeni bir semantic version oluşturur
  • Docker image build eder ve Docker Hub’a push eder
  • Jenkins pipeline’ını tetikler

Workflow Dosyası

Workflow dosyası, projenizin GitHub reposunda yer almalıdır. Yerel geliştirme ortamınızda (IDE veya metin editörü) aşağıdaki dosya yolunda oluşturun ve reponuza push edin: .github/workflows/docker-build-push.yml
name: Docker Build & Push
on:
  push:
    branches: [ "main" ]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
        with:
          fetch-depth: '0'
      
      # Otomatik versiyon oluşturma
      - name: Bump version and push tag
        id: tag_version
        uses: anothrNick/github-tag-action@1.64.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          WITH_V: true
          DEFAULT_BUMP: patch
      
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      # Docker build ve push
      - name: Build and Push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            ${{ secrets.DOCKERHUB_USERNAME }}/YOUR_IMAGE_NAME:latest
            ${{ secrets.DOCKERHUB_USERNAME }}/YOUR_IMAGE_NAME:${{ steps.tag_version.outputs.new_tag }}
      
      # Jenkins tetikleme
      - name: Trigger Jenkins Pipeline
        run: |
          curl -X POST ${{ secrets.JENKINS_URL }}/job/${{ secrets.JENKINS_JOB_NAME }}/buildWithParameters \
            --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \
            --data IMAGE_TAG=${{ steps.tag_version.outputs.new_tag }}

GitHub Secrets Yapılandırması

Repository Settings > Secrets and Variables > Actions bölümünden şu secret’ları ekleyin:
SecretAçıklama
DOCKERHUB_USERNAMEDocker Hub kullanıcı adınız
DOCKERHUB_TOKENDocker Hub access token
JENKINS_URLJenkins instance URL’iniz
JENKINS_JOB_NAMEJenkins job adı
JENKINS_USERJenkins kullanıcı adı
JENKINS_TOKENJenkins API token

2. Jenkins Pipeline Yapılandırması

Jenkins pipeline, aşağıdaki aşamaları gerçekleştirir:
  1. K8s Deploy: Yeni Docker image’ı Kubernetes’e deploy eder
  2. Health Check: API’nin sağlıklı çalıştığını doğrular
  3. Sync Apinizer API Proxy: API Proxy’yi günceller veya oluşturur
  4. Deploy to Apinizer: Proxy’yi belirtilen environment’a deploy eder

Jenkinsfile

Jenkins pipeline’ı, Jenkins arayüzünden yeni bir Pipeline job oluşturularak tanımlanabilir. Aşağıdaki içeriği Jenkins UI’daki Pipeline script alanında kullanabilirsiniz. Jenkinsfile
pipeline {
    agent any
    
    parameters {
        string(name: 'IMAGE_TAG', defaultValue: 'latest', description: 'Docker image tag from GitHub Actions')
    }
    
    environment {
        // Kubernetes yapılandırması
        NAMESPACE = "YOUR_NAMESPACE" 
        DEPLOYMENT_NAME = "YOUR_DEPLOYMENT_NAME"
        CONTAINER_NAME = "YOUR_CONTAINER_NAME" 
        DOCKER_IMAGE = "YOUR_DOCKERHUB_USERNAME/YOUR_IMAGE_NAME"
        KUBECTL_PATH = "/usr/local/bin/kubectl"
        
        // API bilgileri
        API_BACKEND_URL = "YOUR_BACKEND_URL"
        API_HEALTH_ENDPOINT = "${API_BACKEND_URL}/health"
        API_SPEC_URL = "${API_BACKEND_URL}/api/v1/openapi.json"
        
        // Apinizer yapılandırması
        APINIZER_BASE_URL = "YOUR_APINIZER_URL"
        APINIZER_GATEWAY_URL = "YOUR_APINIZER_GATEWAY_URL"
        APINIZER_PROJECT = "YOUR_PROJECT_NAME"
        APINIZER_ENVIRONMENT = "YOUR_ENVIRONMENT_NAME"
        APINIZER_PROXY_NAME = "YOUR_PROXY_NAME"
        APINIZER_PROXY_PATH = "YOUR_PROXY_RELATIVE_PATH"
    }
    
    stages {
        stage('K8s Deploy') {
            steps {
                echo "Deploying ${DOCKER_IMAGE}:${params.IMAGE_TAG} to K8s..."
                sh """
                    ${KUBECTL_PATH} set image deployment/${DEPLOYMENT_NAME} \
                        ${CONTAINER_NAME}=${DOCKER_IMAGE}:${params.IMAGE_TAG} \
                        -n ${NAMESPACE}
                    
                    ${KUBECTL_PATH} rollout status deployment/${DEPLOYMENT_NAME} -n ${NAMESPACE}
                """
            }
        }
        
        stage('Health Check') {
            steps {
                echo "Checking API health at ${API_HEALTH_ENDPOINT}..."
                sh """
                    sleep 10
                    curl -f ${API_HEALTH_ENDPOINT}
                """
            }
        }
        
        stage('Sync Apinizer API Proxy') {
            steps {
                withCredentials([string(credentialsId: 'APINIZER_TOKEN', variable: 'TOKEN')]) {
                    script {
                        echo "Checking if API proxy exists..."
                        
                        def proxyCheckCode = sh(
                            script: """
                                curl -s -o /dev/null -w '%{http_code}' \
                                    -H 'Authorization: Bearer ${TOKEN}' \
                                    '${APINIZER_BASE_URL}/apiops/projects/${APINIZER_PROJECT}/apiProxies/${APINIZER_PROXY_NAME}/'
                            """,
                            returnStdout: true
                        ).trim()
                        
                        echo "Proxy check returned: ${proxyCheckCode}"
                        def proxyExists = (proxyCheckCode == '200')
                        
                        if (proxyExists) {
                            echo "API proxy exists, updating spec..."
                            sh """
                                curl -X PUT \
                                    '${APINIZER_BASE_URL}/apiops/projects/${APINIZER_PROJECT}/apiProxies/url/' \
                                    -H 'Authorization: Bearer ${TOKEN}' \
                                    -H 'Content-Type: application/json' \
                                    -d '{
                                        "apiProxyName": "${APINIZER_PROXY_NAME}",
                                        "apiProxyCreationType": "OPEN_API",
                                        "specUrl": "${API_SPEC_URL}",
                                        "clientRoute": {
                                            "relativePathList": ["${APINIZER_PROXY_PATH}"]
                                        },
                                        "reParse": true,
                                        "deploy": false
                                    }'
                            """
                        } else {
                            echo "API proxy doesn't exist, creating..."
                            sh """
                                curl -X POST \
                                    '${APINIZER_BASE_URL}/apiops/projects/${APINIZER_PROJECT}/apiProxies/url/' \
                                    -H 'Authorization: Bearer ${TOKEN}' \
                                    -H 'Content-Type: application/json' \
                                    -d '{
                                        "apiProxyName": "${APINIZER_PROXY_NAME}",
                                        "apiProxyDescription": "Auto-generated proxy",
                                        "apiProxyCreationType": "OPEN_API",
                                        "specUrl": "${API_SPEC_URL}",
                                        "clientRoute": {
                                            "relativePathList": ["${APINIZER_PROXY_PATH}"]
                                        },
                                        "routingInfo": {
                                            "routingAddressList": [
                                                {
                                                    "address": "${API_BACKEND_URL}",
                                                    "weight": 100
                                                }
                                            ]
                                        },
                                        "deploy": false,
                                        "reParse": false
                                    }'
                            """
                        }
                    }
                }
            }
        }
        
        stage('Deploy to Apinizer') {
            steps {
                withCredentials([string(credentialsId: 'APINIZER_TOKEN', variable: 'TOKEN')]) {
                    echo "Deploying API proxy to Apinizer ${APINIZER_ENVIRONMENT}..."
                    sh """
                        curl -X POST \
                            '${APINIZER_BASE_URL}/apiops/projects/${APINIZER_PROJECT}/apiProxies/${APINIZER_PROXY_NAME}/environments/${APINIZER_ENVIRONMENT}/' \
                            -H 'Authorization: Bearer ${TOKEN}'
                    """
                }
            }
        }
    }
    
    post {
        success {
            echo "✅ Pipeline completed! API deployed to K8s and Apinizer successfully."
        }
        failure {
            echo "❌ Pipeline failed! Check logs above."
        }
    }
}

Jenkins Credentials Yapılandırması

Jenkins’de Manage Jenkins > Credentials bölümünden şu credential’ı ekleyin:
Credential IDTipAçıklama
APINIZER_TOKENSecret textApinizer API token
Apinizer API token oluşturma hakkında detaylı bilgi için Token Alma Yöntemleri dokümanını inceleyebilirsiniz.

3. Pipeline Aşamalarının Detayları

Stage 1: Kubernetes Deployment

Bu aşama Jenkins sunucusunda çalışır. GitHub Actions tarafından oluşturulan Docker image Kubernetes cluster’ına deploy edilir. kubectl set image komutu kullanılarak deployment güncellenir ve rollout durumu kontrol edilir.
${KUBECTL_PATH} set image deployment/${DEPLOYMENT_NAME} \
    ${CONTAINER_NAME}=${DOCKER_IMAGE}:${params.IMAGE_TAG} \
    -n ${NAMESPACE}

${KUBECTL_PATH} rollout status deployment/${DEPLOYMENT_NAME} -n ${NAMESPACE}

Stage 2: Health Check

API’nin başarıyla deploy edildiğini doğrulamak için health endpoint’i kontrol edilir. Bu adım, Apinizer’a deploy etmeden önce API’nin çalışır durumda olduğundan emin olmak için kritiktir. API_HEALTH_ENDPOINT değişkeni, pipeline’ı uyguladığınız uygulamanın health check endpoint’ini belirtir. Bu adres uygulamanıza özgüdür; örnek:
https://YOUR_BACKEND_URL/health
Uygulamanızın farklı bir health check endpoint’i varsa API_HEALTH_ENDPOINT değişkenini buna göre güncelleyin.

Stage 3: Apinizer API Proxy Senkronizasyonu

Bu kritik aşamada:
  1. Proxy Kontrolü: İlgili API Proxy’nin var olup olmadığı kontrol edilir
  2. Güncelleme veya Oluşturma:
    • Proxy varsa: OpenAPI spec’i güncellenir (PUT request)
    • Proxy yoksa: Yeni proxy oluşturulur (POST request)

Proxy Güncelleme (PUT)

Mevcut bir proxy’yi güncellerken reParse: true parametresi ile OpenAPI specification yeniden parse edilir:
{
  "apiProxyName": "YOUR_PROXY_NAME",
  "apiProxyCreationType": "OPEN_API",
  "specUrl": "YOUR_BACKEND_URL/api/v1/openapi.json",
  "clientRoute": {
    "relativePathList": ["YOUR_PROXY_RELATIVE_PATH"]
  },
  "reParse": true,
  "deploy": false
}
Detaylı bilgi için Update API Proxy API referansını inceleyebilirsiniz.

Yeni Proxy Oluşturma (POST)

Yeni proxy oluştururken backend routing bilgileri de tanımlanır:
{
  "apiProxyName": "YOUR_PROXY_NAME",
  "apiProxyDescription": "Auto-generated proxy",
  "apiProxyCreationType": "OPEN_API",
  "specUrl": "YOUR_BACKEND_URL/api/v1/openapi.json",
  "clientRoute": {
    "relativePathList": ["YOUR_PROXY_RELATIVE_PATH"]
  },
  "routingInfo": {
    "routingAddressList": [
      {
        "address": "YOUR_BACKEND_URL",
        "weight": 100
      }
    ]
  },
  "deploy": false
}
Detaylı bilgi için Create API Proxy from URL API referansını inceleyebilirsiniz.
deploy: false parametresi ile proxy otomatik olarak deploy edilmez. Bu, bir sonraki stage’de kontrollü deployment yapılmasını sağlar.

Stage 4: Apinizer Environment’a Deploy

Son aşamada, güncellenen veya yeni oluşturulan proxy belirtilen environment’a deploy edilir. Bu işlem Apinizer’ın deployment API’si kullanılarak gerçekleştirilir:
POST /apiops/projects/{projectName}/apiProxies/{proxyName}/environments/{environmentName}/
Detaylı bilgi için Deploy API Proxy API referansını inceleyebilirsiniz.

Konfigürasyon Parametreleri

Environment Variables

Pipeline’da kullanılan temel environment variable’lar:
DeğişkenAçıklamaÖrnek Değer
APINIZER_BASE_URLApinizer platform URL’iYOUR_APINIZER_URL
APINIZER_PROJECTApinizer proje adıYOUR_PROJECT_NAME
APINIZER_ENVIRONMENTDeploy edilecek environmentYOUR_ENVIRONMENT_NAME
APINIZER_PROXY_NAMEAPI Proxy adıYOUR_PROXY_NAME
APINIZER_PROXY_PATHGateway’deki relative pathYOUR_PROXY_RELATIVE_PATH
API_SPEC_URLOpenAPI specification URL’iYOUR_BACKEND_URL/openapi.json

Apinizer API Endpoints

Bu pipeline’da kullanılan Apinizer API endpoint’leri:
İşlemEndpoint
Proxy KontrolüGET /apiops/projects/{project}/apiProxies/{proxyName}/
Proxy GüncellemePUT /apiops/projects/{project}/apiProxies/url/
Proxy OluşturmaPOST /apiops/projects/{project}/apiProxies/url/
Environment DeployPOST /apiops/projects/{project}/apiProxies/{proxyName}/environments/{env}/
Apinizer Management API hakkında detaylı bilgi için API Genel Bakış dokümanını inceleyebilirsiniz.

Kendi Pipeline’ınızı Uyarlamak

Bu örnek senaryo, Kubernetes üzerinde çalışan bir API için tasarlanmıştır. Kendi altyapınıza göre uyarlamak için:
1

Deployment Mekanizması

Kubernetes yerine farklı bir orchestrator veya doğrudan VM deployment kullanıyorsanız, K8s Deploy stage’ini kendi deployment metodunuza göre değiştirin.
2

Health Check

API’nizin farklı bir health check mekanizması varsa, API_HEALTH_ENDPOINT değişkenini ilgili endpoint ile güncelleyin.
3

OpenAPI Spec

API’nizin OpenAPI specification’ının erişilebilir bir URL’de olduğundan emin olun. Bu URL Apinizer tarafından erişilebilir olmalıdır.
4

Environment

Apinizer’da kullanmak istediğiniz environment’ı (dev, test, prod vb.) APINIZER_ENVIRONMENT değişkeninde belirtin.
5

Security

Credential’larınızı Jenkins Credentials Manager üzerinden yönetmeniz, pipeline güvenliği açısından daha uygun bir yaklaşım olacaktır.

Sonuç

Bu kılavuz, GitHub Actions, Jenkins ve Apinizer’ı kullanarak tam otomatik bir CI/CD pipeline’ının nasıl kurulacağını göstermiştir. Her kod değişikliği otomatik olarak build edilir ve Apinizer’a deploy edilir. Bu yaklaşım, manuel işlemleri minimize ederek deployment sürecinizi hızlandırır ve hata olasılığını azaltır.