DevOps инфраструктура на Proxmox с Docker и Ansible

Въведение
В съвременния свят на разработката, способността да изграждаш, тествaш и внедряваш приложения бързо и надеждно е ключова. DevOps културата трансформира начина, по който работят екипите, но професионалните cloud решения често са скъпи за експериментиране и обучение. Тук на сцената излиза Proxmox VE – мощна, безплатна виртуализационна платформа, която може да се превърне във ваш личен DevOps playground или дори production environment.
В тази статия ще изградим цялостна DevOps инфраструктура, която включва:
- Git repository management (Gitea)
- CI/CD pipeline (Jenkins)
- Container registry
- Автоматизирано внедряване с Ansible
- Monitoring и logging
Независимо дали сте студент, който иска да научи DevOps практики, или професионалист, търсещ self-hosted решение, тази статия ще ви покаже пътя от нула до production-ready система.
Защо Proxmox за DevOps?
Преди да се потопим в техническите детайли, нека разберем защо Proxmox е идеалният избор:
1. Хибридна виртуализация Proxmox поддържа както KVM виртуални машини, така и LXC контейнери. Това ви дава гъвкавостта да изберете оптималното решение – VM за изолация или LXC за ефективност.
2. Web-базиран интерфейс Цялото управление става през интуитивен браузър интерфейс. Никакви сложни команди за начинаещите, но и пълен API достъп за автоматизация.
3. Open Source и безплатен За разлика от VMware или Hyper-V, Proxmox е напълно безплатен. Перфектен за learning и home lab setup.
4. Enterprise features Clustering, high availability, backup, migration – всичко това идва out of the box.
5. Отлична интеграция с automation tools Terraform providers, Ansible modules, REST API – автоматизацията е first-class citizen.
Архитектура на нашата система
Преди да започнем, нека визуализираме какво ще изградим:
graph TB
subgraph Proxmox Host
subgraph DevOps VM
A[Gitea - Git Server]
B[Jenkins - CI/CD]
C[Docker Registry]
D[Traefik - Reverse Proxy]
end
subgraph Production VM
E[Docker Swarm Manager]
F[App Containers]
end
subgraph Monitoring VM
G[Prometheus]
H[Grafana]
I[Loki - Logs]
end
end
J[Developer] -->|git push| A
A -->|webhook| B
B -->|build & push| C
B -->|deploy| E
E --> F
G -->|scrape metrics| F
H -->|visualize| G
I -->|collect logs| F
D -->|route traffic| A
D -->|route traffic| B
D -->|route traffic| H
Обяснение на компонентите:
- Gitea: Self-hosted Git сървър (алтернатива на GitHub)
- Jenkins: Automation server за CI/CD pipelines
- Docker Registry: Частен registry за Docker images
- Traefik: Reverse proxy с автоматичен SSL (Let's Encrypt)
- Prometheus & Grafana: Monitoring и визуализация
- Loki: Централизиран log aggregation
Prerequisite: Подготовка на Proxmox
Преди да започнем, нуждаете се от:
- Hardware: Минимум 16GB RAM, 4 CPU cores, 200GB storage
- Proxmox VE: Инсталиран и конфигуриран (версия 8.x)
- Network: Конфигуриран bridge (обикновено vmbr0)
- Достъп: SSH и web UI достъп до Proxmox
Първоначална конфигурация
SSH към вашия Proxmox host и изпълнете:
# Update системата
apt update && apt upgrade -y
# Инсталирай необходимите tools
apt install -y git ansible python3-pip
# Конфигурирай network bridge (ако не е готов)
cat >> /etc/network/interfaces << EOF
auto vmbr1
iface vmbr1 inet static
address 10.0.0.1/24
bridge-ports none
bridge-stp off
bridge-fd 0
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o vmbr0 -j MASQUERADE
EOF
# Restart networking (внимавайте с SSH сесията!)
systemctl restart networking
Стъпка 1: Създаване на DevOps VM с Cloud-Init
Вместо ръчно да инсталираме всяка VM, ще използваме Cloud-Init template за автоматизация.
Създаване на Ubuntu Cloud-Init template
# Изтегли Ubuntu cloud image
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
# Създай VM template
qm create 9000 --name ubuntu-cloud-template --memory 2048 --net0 virtio,bridge=vmbr0 --cores 2
# Import на диска
qm importdisk 9000 jammy-server-cloudimg-amd64.img local-lvm
# Attach диска
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0
# Cloud-Init drive
qm set 9000 --ide2 local-lvm:cloudinit
# Boot order
qm set 9000 --boot c --bootdisk scsi0
# Serial console
qm set 9000 --serial0 socket --vga serial0
# Добави SSH key (замени с твоя)
qm set 9000 --sshkey ~/.ssh/id_rsa.pub
# Конвертирай във template
qm template 9000
echo "✓ Template създаден успешно!"
Клониране на VM за DevOps
# Създай DevOps VM от template
qm clone 9000 100 --name devops-main --full
# Конфигурирай ресурси
qm set 100 --memory 8192 --cores 4
# Увеличи диска
qm resize 100 scsi0 +50G
# Cloud-Init конфигурация
qm set 100 --ipconfig0 ip=10.0.0.10/24,gw=10.0.0.1
qm set 100 --nameserver 8.8.8.8
# Стартирай VM
qm start 100
echo "⏳ Изчакай 30-60 секунди за boot..."
sleep 60
# Тествай SSH достъп
ssh [email protected] "echo 'VM е готова!'"
Стъпка 2: Автоматизирана инсталация с Ansible
Сега идва магията – ще автоматизираме цялата инсталация на DevOps stack с Ansible.
Инсталация на Ansible (на Proxmox host)
pip3 install ansible
ansible-galaxy collection install community.docker
Ansible Inventory
Създай файл inventory.ini:
[devops]
devops-main ansible_host=10.0.0.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa
[production]
prod-01 ansible_host=10.0.0.11 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa
[monitoring]
monitor-01 ansible_host=10.0.0.12 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa
[all:vars]
ansible_python_interpreter=/usr/bin/python3
domain=devops.localMaster Playbook
Създай deploy-devops.yml:
---
- name: Setup DevOps Infrastructure
hosts: all
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Install prerequisites
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
- python3-pip
state: present
- name: Add Docker GPG key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repository
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Install Docker
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
- name: Start Docker service
systemd:
name: docker
state: started
enabled: yes
- name: Add user to docker group
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
- name: Install Docker SDK for Python
pip:
name: docker
state: present
- name: Deploy DevOps Stack
hosts: devops
become: yes
vars:
stack_dir: /opt/devops-stack
tasks:
- name: Create stack directory
file:
path: "{{ stack_dir }}"
state: directory
mode: '0755'
- name: Create Docker networks
docker_network:
name: "{{ item }}"
state: present
loop:
- devops-network
- monitoring-network
- name: Deploy Docker Compose stack
copy:
dest: "{{ stack_dir }}/docker-compose.yml"
content: |
version: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- devops-network
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik/traefik.yml:/traefik.yml:ro
- ./traefik/acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.{{ domain }}`)"
- "traefik.http.routers.traefik.service=api@internal"
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
networks:
- devops-network
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:22"
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitea.rule=Host(`git.{{ domain }}`)"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
restart: unless-stopped
networks:
- devops-network
volumes:
- jenkins-data:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
environment:
- JENKINS_OPTS=--prefix=/jenkins
labels:
- "traefik.enable=true"
- "traefik.http.routers.jenkins.rule=Host(`jenkins.{{ domain }}`)"
- "traefik.http.services.jenkins.loadbalancer.server.port=8080"
registry:
image: registry:2
container_name: docker-registry
restart: unless-stopped
networks:
- devops-network
volumes:
- registry-data:/var/lib/registry
labels:
- "traefik.enable=true"
- "traefik.http.routers.registry.rule=Host(`registry.{{ domain }}`)"
- "traefik.http.services.registry.loadbalancer.server.port=5000"
networks:
devops-network:
external: true
volumes:
gitea-data:
jenkins-data:
registry-data:
- name: Create Traefik configuration
file:
path: "{{ stack_dir }}/traefik"
state: directory
- name: Configure Traefik
copy:
dest: "{{ stack_dir }}/traefik/traefik.yml"
content: |
api:
dashboard: true
entryPoints:
web:
address: :80
websecure:
address: :443
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
- name: Create acme.json for SSL
file:
path: "{{ stack_dir }}/traefik/acme.json"
state: touch
mode: '0600'
- name: Start Docker Compose stack
community.docker.docker_compose:
project_src: "{{ stack_dir }}"
state: present
- name: Deploy Monitoring Stack
hosts: monitoring
become: yes
vars:
monitor_dir: /opt/monitoring
tasks:
- name: Create monitoring directory
file:
path: "{{ monitor_dir }}"
state: directory
- name: Deploy monitoring stack
copy:
dest: "{{ monitor_dir }}/docker-compose.yml"
content: |
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- "9090:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
loki:
image: grafana/loki:latest
container_name: loki
restart: unless-stopped
ports:
- "3100:3100"
volumes:
- loki-data:/loki
volumes:
prometheus-data:
grafana-data:
loki-data:
- name: Create Prometheus config
copy:
dest: "{{ monitor_dir }}/prometheus.yml"
content: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'docker'
static_configs:
- targets: ['10.0.0.10:9323']
- name: Start monitoring stack
community.docker.docker_compose:
project_src: "{{ monitor_dir }}"
state: present
Изпълнение на Ansible
# Тествай connectivity
ansible all -i inventory.ini -m ping
# Изпълни playbook
ansible-playbook -i inventory.ini deploy-devops.yml
# След 5-10 минути всичко ще е готово!
Стъпка 3: Конфигурация на DevOps Stack
След успешното deployment, нека конфигурираме всеки компонент.
Gitea Setup
- Отвори браузър:
http://10.0.0.10:3000 - Първоначална настройка:
- Database: SQLite3
- Server Domain:
git.devops.local - SSH Port: 2222
- Admin Account: създай потребител
Jenkins Setup
- Достъп:
http://10.0.0.10:8080 - Вземи initial password:
ssh [email protected] "sudo docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword"
- Инсталирай suggested plugins
- Инсталирай допълнително:
- Docker Pipeline
- Gitea Plugin
- Ansible Plugin
Създаване на CI/CD Pipeline
Ето пример на Jenkinsfile за автоматизирано внедряване:
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'registry.devops.local'
APP_NAME = 'myapp'
VERSION = "${env.BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://git.devops.local/user/myapp.git'
}
}
stage('Build') {
steps {
script {
docker.build("${DOCKER_REGISTRY}/${APP_NAME}:${VERSION}")
}
}
}
stage('Test') {
steps {
sh 'docker run --rm ${DOCKER_REGISTRY}/${APP_NAME}:${VERSION} npm test'
}
}
stage('Push to Registry') {
steps {
script {
docker.withRegistry("http://${DOCKER_REGISTRY}") {
docker.image("${DOCKER_REGISTRY}/${APP_NAME}:${VERSION}").push()
docker.image("${DOCKER_REGISTRY}/${APP_NAME}:${VERSION}").push('latest')
}
}
}
}
stage('Deploy to Production') {
steps {
ansiblePlaybook(
playbook: 'deploy-app.yml',
inventory: 'inventory.ini',
extraVars: [
app_version: "${VERSION}",
app_name: "${APP_NAME}"
]
)
}
}
}
post {
success {
echo "✓ Deployment successful! Version: ${VERSION}"
}
failure {
echo "✗ Deployment failed!"
}
}
}
Deployment Playbook
Създай deploy-app.yml:
---
- name: Deploy Application
hosts: production
become: yes
vars:
registry: registry.devops.local
tasks:
- name: Pull latest image
docker_image:
name: "{{ registry }}/{{ app_name }}:{{ app_version }}"
source: pull
- name: Stop old container
docker_container:
name: "{{ app_name }}"
state: stopped
ignore_errors: yes
- name: Remove old container
docker_container:
name: "{{ app_name }}"
state: absent
ignore_errors: yes
- name: Start new container
docker_container:
name: "{{ app_name }}"
image: "{{ registry }}/{{ app_name }}:{{ app_version }}"
state: started
restart_policy: unless-stopped
ports:
- "80:3000"
networks:
- name: devops-network
Стъпка 4: Bash скрипт за бърза автоматизация
За случаите, когато искате бързо да deploy-нете без Ansible:
#!/bin/bash
# deploy-quick.sh - Бърз deployment скрипт
set -e
APP_NAME="myapp"
VERSION="${1:-latest}"
REGISTRY="registry.devops.local"
PROD_HOST="10.0.0.11"
echo "🚀 Starting deployment of ${APP_NAME}:${VERSION}"
# Build image
echo "📦 Building Docker image..."
docker build -t ${REGISTRY}/${APP_NAME}:${VERSION} .
# Push to registry
echo "⬆️ Pushing to registry..."
docker push ${REGISTRY}/${APP_NAME}:${VERSION}
# Deploy to production
echo "🎯 Deploying to production..."
ssh ubuntu@${PROD_HOST} << EOF
docker pull ${REGISTRY}/${APP_NAME}:${VERSION}
docker stop ${APP_NAME} 2>/dev/null || true
docker rm ${APP_NAME} 2>/dev/null || true
docker run -d \
--name ${APP_NAME} \
--restart unless-stopped \
-p 80:3000 \
${REGISTRY}/${APP_NAME}:${VERSION}
EOF
echo "✅ Deployment completed successfully!"
echo "🌐 Application available at: http://${PROD_HOST}"
Направи го executable и използвай:
chmod +x deploy-quick.sh
./deploy-quick.sh v1.0.0
Стъпка 5: Monitoring и Observability
Grafana Dashboards
- Достъп до Grafana:
http://10.0.0.12:3001 - Login: admin/admin
- Добави Prometheus data source:
- URL:
http://prometheus:9090
- URL:
- Import готов dashboard:
- ID: 1860 (Node Exporter Full)
- ID: 179 (Docker Monitoring)
Loki за логове
Инсталирай Promtail на production VM:
ssh [email protected] << 'EOF'
sudo docker run -d \
--name promtail \
--restart unless-stopped \
-v /var/log:/var/log:ro \
-v /var/lib/docker/containers:/var/lib/docker/containers:ro \
grafana/promtail:latest \
-config.file=/etc/promtail/config.yml
EOF
Best Practices и Production Tips
1. Security Hardening
# Firewall на Proxmox host
ufw allow 22/tcp
ufw allow 8006/tcp # Proxmox Web UI
ufw enable
# SSH key-based authentication only
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
# Docker security
echo '{"live-restore": true, "userland-proxy": false}' > /etc/docker/daemon.json
systemctl restart docker
2. Backup Strategy
# Automated VM backups
cat > /usr/local/bin/backup-vms.sh << 'EOF'
#!/bin/bash
vzdump 100 --mode snapshot --storage local --compress zstd
vzdump 101 --mode snapshot --storage local --compress zstd
vzdump 102 --mode snapshot --storage local --compress zstd
EOF
chmod +x /usr/local/bin/backup-vms.sh
# Cron job за нощни backups
echo "0 2 * * * /usr/local/bin/backup-vms.sh" | crontab -
3. Resource Management
Мониторинг на ресурсите:
# CPU и RAM usage на VM
qm status 100 --verbose
# Resize VM resources динамично
qm set 100 --memory 16384
qm set 100 --cores 8
4. Network Optimization
# Enable jumbo frames за по-добра performance
ip link set vmbr0 mtu 9000
# TCP tuning
cat >> /etc/sysctl.conf << EOF
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
EOF
sysctl -p
Troubleshooting
Проблем: VM не стартира
# Проверка на status
qm status 100
# Проверка на logs
tail -f /var/log/pve/qemu-server/100.log
# Ръчно стартиране с verbose output
qm start 100 --verbose
Проблем: Docker контейнер не се стартира
# SSH към VM
ssh [email protected]
# Logs на контейнера
docker logs jenkins --tail 100
# Inspect на контейнера
docker inspect jenkins
# Resource usage
docker stats
Проблем: Ansible connection timeout
# Test connectivity
ansible all -i inventory.ini -m ping -vvv
# Test SSH manual
ssh -vvv [email protected]
# Check firewall
sudo ufw status
Проблем: Registry push/pull failures
# Check registry status
curl http://10.0.0.10:5000/v2/_catalog
# Docker daemon insecure registry (за testing)
cat > /etc/docker/daemon.json << EOF
{
"insecure-registries": ["registry.devops.local:5000"]
}
EOF
systemctl restart docker
Заключение и Next Steps
Честито! Изградихте функционална DevOps инфраструктура на Proxmox. Сега имате:
✅ Self-hosted Git server
✅ Automated CI/CD pipeline
✅ Private container registry
✅ Production deployment automation
✅ Monitoring и logging
Какво следва?
За начинаещи:
- Експериментирайте с различни приложения
- Разберете Jenkins pipelines задълбочено
- Научете Docker networking и volumes
- Практикувайте Git workflows
За напреднали:
- Имплементирайте Kubernetes вместо Docker Swarm
- Добавете GitOps с ArgoCD
- Infrastructure as Code с Terraform
- Service mesh с Istio
- Security scanning (Trivy, SonarQube)
- High Availability setup с Proxmox clustering
Полезни ресурси
Финални мисли
DevOps не е просто набор от tools – това е култура на автоматизация, collaboration и continuous improvement. Тази инфраструктура е вашата playground за експериментиране и учене. Не се страхувайте да чупите нещата – всеки failure е learning opportunity.
Proxmox ви дава свободата да изграждате, тествате и внедрявате без constraints на cloud costs. Използвайте го максимално!
Автор бележка: Всички конфигурации в тази статия са тествани и работят. За production use, задължително имплементирайте SSL certificates, proper authentication и regular backups.
Въпроси? Експериментирайте, гледайте логове, четете документация. DevOps е journey, не destination! 🚀
Благодарим ви за прочитането на статията! Ако намерихте информацията за полезна, можете да дарите посредством бутоните по-долу:
Donate ☕️ Дарете с PayPalDonate 💳 Дарете с Revolut










