Skip to content

Infrastructure Services CI/CD #9

Infrastructure Services CI/CD

Infrastructure Services CI/CD #9

name: Infrastructure Services CI/CD
on:
workflow_dispatch:
inputs:
environment:
type: choice
description: "Deployment environment"
options:
- prod
- staging
- debug
default: "prod"
action:
type: choice
description: "Action to perform"
options:
- deploy
- restart
- start
- stop
- status
default: "restart"
service:
type: choice
description: "Target service"
options:
- all
- kafka
- zookeeper
- redis
- kafka-cli
default: "all"
clean_data:
type: boolean
description: "⚠️ TEHLİKE: Volume'ları temizle (tüm veriler silinir!)"
default: false
jobs:
deploy-infrastructure:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: List repository contents
run: |
echo "Working Directory: $(pwd)"
echo "Repository Contents:"
ls -la .
echo "Infrastructure Directory:"
ls -la ./infrastructure || echo "Infrastructure directory not found"
- name: Deploy to VPS
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
command_timeout: "10m"
script: |
echo "==== Altyapı Servisleri Yönetimi Başlatılıyor ===="
set -e
# Infrastructure dizinini oluştur
sudo mkdir -p /opt/craftpilot/infrastructure
sudo chown -R $USER:$USER /opt/craftpilot/infrastructure
cd /opt/craftpilot/infrastructure || exit 1
# Docker ağını oluştur
docker network create craftpilot-network || true
# Önceki container'ları temizle
echo "==== Eski container'ları temizleme ===="
# İlk olarak konteynerlerin varlığını doğrudan kontrol et ve varsa kaldır
echo "==== Mevcut konteynerler kontrol ediliyor ve zorla kaldırılıyor ===="
for CONTAINER_NAME in redis zookeeper kafka kafka-tools; do
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Konteyner ${CONTAINER_NAME} bulundu, kaldırılıyor..."
docker rm -f ${CONTAINER_NAME} || true
fi
done
# Varsa docker-compose projesi olarak da kaldırma işlemi yap
docker-compose -f docker-compose.infra.yml -p craftpilot-infra down --remove-orphans || true
docker system prune -f
# İlgili volume'ları koşullu olarak temizle
if [ "${{ github.event.inputs.clean_data }}" == "true" ]; then
echo "==== ⚠️ TEHLİKE: Volume'lar siliniyor! Tüm veriler kaybolacak! ===="
docker volume rm zookeeper-data zookeeper-log kafka-data redis-data || true
echo "==== Volume'lar temizlendi ===="
else
echo "==== Volume'lar korunuyor, mevcut veriler saklanacak ===="
fi
# Docker compose dosyasını oluştur
cat > docker-compose.infra.yml << 'EOL'
version: '3.8'
services:
zookeeper:
image: confluentinc/cp-zookeeper:7.3.0
container_name: zookeeper
restart: unless-stopped
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
ZOOKEEPER_INIT_LIMIT: 5
ZOOKEEPER_SYNC_LIMIT: 2
ports:
- "2181:2181"
volumes:
- type: volume
source: zookeeper-data
target: /var/lib/zookeeper/data
- type: volume
source: zookeeper-log
target: /var/lib/zookeeper/log
networks:
- craftpilot-network
healthcheck:
test: echo stat | nc localhost 2181 || exit 1
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
kafka:
image: confluentinc/cp-kafka:7.3.0
container_name: kafka
restart: unless-stopped
depends_on:
- zookeeper
ports:
- "9092:9092"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
volumes:
- type: volume
source: kafka-data
target: /var/lib/kafka/data
networks:
- craftpilot-network
healthcheck:
test: kafka-topics --bootstrap-server localhost:9092 --list || exit 1
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
kafka-tools:
image: confluentinc/cp-kafka:7.3.0
container_name: kafka-tools
restart: unless-stopped
depends_on:
- kafka
entrypoint: ["/bin/bash"]
tty: true
stdin_open: true
command: -c "echo 'Kafka CLI tools ready.' && sleep infinity"
networks:
- craftpilot-network
redis:
image: redis:7.0-alpine
container_name: redis
restart: unless-stopped
ports:
- "6379:6379"
command: redis-server --requirepass 13579ada --maxmemory 800mb --maxmemory-policy volatile-lru --appendonly yes --appendfsync everysec --no-appendfsync-on-rewrite yes
volumes:
- type: volume
source: redis-data
target: /data
networks:
- craftpilot-network
healthcheck:
test: redis-cli -a 13579ada ping || exit 1
interval: 5s
timeout: 3s
retries: 3
start_period: 10s
volumes:
zookeeper-data:
zookeeper-log:
kafka-data:
redis-data:
networks:
craftpilot-network:
external: true
EOL
# Dosya oluşturulduğunu kontrol et
if [ ! -f docker-compose.infra.yml ]; then
echo "HATA: docker-compose.infra.yml dosyası oluşturulamadı!"
exit 1
fi
# Docker compose geçerliliğini kontrol et
if ! docker-compose -f docker-compose.infra.yml config > /dev/null; then
echo "HATA: docker-compose.infra.yml dosyası geçersiz!"
exit 1
fi
ACTION="${{ github.event.inputs.action }}"
SERVICE="${{ github.event.inputs.service }}"
ENV="${{ github.event.inputs.environment }}"
# Servis parametresine göre işlem yapılacak servis(ler)i belirle
if [ "$SERVICE" == "all" ]; then
SERVICE_PARAM=""
else
SERVICE_PARAM="$SERVICE"
fi
# Environment değişkenlerini ayarla
export ENV=$ENV
# Docker ve docker-compose'un çalıştığından emin ol
if ! docker info >/dev/null 2>&1; then
echo "HATA: Docker servisine erişilemiyor!"
exit 1
fi
if ! command -v docker-compose >/dev/null 2>&1; then
echo "HATA: docker-compose bulunamadı!"
exit 1
fi
# Docker daemon'ın çalıştığından emin ol ve yeniden başlatmayı dene
if ! systemctl is-active --quiet docker; then
echo "Docker servisi yeniden başlatılıyor..."
sudo systemctl restart docker
sleep 10
fi
# Retry mekanizması ekle
retry_count=0
max_retries=3
while [ $retry_count -lt $max_retries ]; do
case "$ACTION" in
deploy|restart|start)
echo "==== Servisler başlatılıyor (Deneme $((retry_count + 1))/$max_retries) ===="
# Her denemeden önce mevcut konteynerleri kontrol et ve kaldır
for CONTAINER_NAME in redis zookeeper kafka kafka-tools; do
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Konteyner ${CONTAINER_NAME} hala mevcut, zorla kaldırılıyor..."
docker rm -f ${CONTAINER_NAME} || true
fi
done
if docker-compose -f docker-compose.infra.yml -p craftpilot-infra up -d $SERVICE_PARAM; then
echo "==== Servislerin başlaması bekleniyor ===="
sleep 30
# Servis durumlarını kontrol et
if docker-compose -f docker-compose.infra.yml -p craftpilot-infra ps | grep -q "Up"; then
echo "==== Servisler başarıyla başlatıldı ===="
break
fi
fi
echo "==== Başlatma başarısız, yeniden deneniyor ===="
# Volume'ları koruyarak yeniden başlat (--volumes parametresi kaldırıldı)
docker-compose -f docker-compose.infra.yml -p craftpilot-infra down
sleep 10
retry_count=$((retry_count + 1))
;;
*)
# Diğer eylemler için mevcut mantığı kullan
docker-compose -f docker-compose.infra.yml -p craftpilot-infra $ACTION $SERVICE_PARAM
break
;;
esac
done
if [ $retry_count -eq $max_retries ]; then
echo "==== HATA: Maksimum yeniden deneme sayısına ulaşıldı ===="
echo "==== Mevcut Docker Konteyner Durumu ===="
docker ps -a
echo "==== Docker Konteyner Detayları ===="
for CONTAINER_NAME in redis zookeeper kafka kafka-tools; do
echo "Konteyner ${CONTAINER_NAME} detayları:"
docker inspect ${CONTAINER_NAME} 2>/dev/null || echo "Konteyner bulunamadı"
done
docker-compose -f docker-compose.infra.yml -p craftpilot-infra logs
exit 1
fi
# İstenen eylemi gerçekleştir
case "$ACTION" in
deploy)
echo "==== Servisler durduruluyor: $SERVICE ===="
# Volume'ları koruyarak durdur
docker-compose -f docker-compose.infra.yml -p craftpilot-infra down $SERVICE_PARAM || true
echo "==== Servisler yeniden oluşturuluyor: $SERVICE ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra up -d $SERVICE_PARAM
sleep 10 # Servislerin başlaması için bekle
echo "==== Servis durumu kontrol ediliyor ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra ps
;;
restart)
echo "==== Servisler yeniden başlatılıyor: $SERVICE ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra restart $SERVICE_PARAM
echo "==== Servis durumu kontrol ediliyor ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra ps
;;
start)
echo "==== Servisler başlatılıyor: $SERVICE ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra up -d $SERVICE_PARAM
echo "==== Servis durumu kontrol ediliyor ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra ps
;;
stop)
echo "==== Servisler durduruluyor: $SERVICE ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra stop $SERVICE_PARAM
echo "==== Servis durumu kontrol ediliyor ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra ps
;;
status)
echo "==== Servis durumu kontrol ediliyor ===="
docker-compose -f docker-compose.infra.yml -p craftpilot-infra ps
# Redis durumu kontrolü
if [ "$SERVICE" == "all" ] || [ "$SERVICE" == "redis" ]; then
echo ""
echo "==== Redis Durumu ===="
if docker exec -t redis redis-cli -a 13579ada ping | grep -q 'PONG'; then
echo "Redis çalışıyor"
echo "Bilgiler:"
docker exec -t redis redis-cli -a 13579ada info | grep connected
docker exec -t redis redis-cli -a 13579ada info memory | grep used_memory_human
docker exec -t redis redis-cli -a 13579ada info keyspace
else
echo "Redis yanıt vermiyor veya çalışmıyor!"
fi
fi
# Kafka durumu kontrolü
if [ "$SERVICE" == "all" ] || [ "$SERVICE" == "kafka" ] || [ "$SERVICE" == "kafka-cli" ]; then
echo ""
echo "==== Kafka Durumu ===="
if docker exec -t kafka bash -c "kafka-topics --bootstrap-server localhost:9092 --list" > /dev/null 2>&1; then
echo "Kafka çalışıyor"
echo "Topics:"
docker exec -t kafka kafka-topics --bootstrap-server localhost:9092 --list
echo ""
echo "Consumer Grupları:"
docker exec -t kafka kafka-consumer-groups --bootstrap-server localhost:9092 --list
else
echo "Kafka yanıt vermiyor veya çalışmıyor!"
fi
fi
# Zookeeper durumu kontrolü
if [ "$SERVICE" == "all" ] || [ "$SERVICE" == "zookeeper" ]; then
echo ""
echo "==== Zookeeper Durumu ===="
if docker exec -t zookeeper bash -c "echo ruok | nc localhost 2181" | grep -q 'imok'; then
echo "Zookeeper çalışıyor"
else
echo "Zookeeper yanıt vermiyor veya çalışmıyor!"
fi
fi
;;
*)
echo "Geçersiz işlem: $ACTION"
exit 1
;;
esac
# Başarı durumunu kontrol et
if [ $? -eq 0 ]; then
echo "==== Altyapı Servisleri Yönetimi Başarıyla Tamamlandı ===="
else
echo "==== HATA: Altyapı Servisleri Yönetiminde Sorun Oluştu ===="
exit 1
fi
- name: Kafka CLI Kullanım Kılavuzu
if: ${{ github.event.inputs.action == 'status' && (github.event.inputs.service == 'kafka' || github.event.inputs.service == 'all' || github.event.inputs.service == 'kafka-cli') }}
run: |
echo "==== Kafka CLI Kullanım Kılavuzu ===="
echo ""
echo "Topic Listeleme:"
echo " docker exec -t kafka-tools kafka-topics --bootstrap-server kafka:9092 --list"
echo ""
echo "Topic Detayları:"
echo " docker exec -t kafka-tools kafka-topics --bootstrap-server kafka:9092 --describe --topic [TOPIC_ADI]"
echo ""
echo "Bir Topic'teki Mesajları İzleme:"
echo " docker exec -it kafka-tools kafka-console-consumer --bootstrap-server kafka:9092 --topic [TOPIC_ADI] --from-beginning"
echo ""
echo "Bir Topic'e Mesaj Gönderme:"
echo " docker exec -it kafka-tools kafka-console-producer --broker-list kafka:9092 --topic [TOPIC_ADI]"
echo ""
echo "Consumer Gruplarını Listeleme:"
echo " docker exec -t kafka-tools kafka-consumer-groups --bootstrap-server kafka:9092 --list"
echo ""
echo "Consumer Grup Detayları:"
echo " docker exec -t kafka-tools kafka-consumer-groups --bootstrap-server kafka:9092 --describe --group [GRUP_ADI]"
echo ""
echo "Örnek Topic İzleme (user-events):"
echo " docker exec -it kafka-tools kafka-console-consumer --bootstrap-server kafka:9092 --topic user-events --from-beginning"