feat: 集成 OpenTofu + Ansible + Gitea CI/CD

- 重构项目目录结构
- 添加 OpenTofu 多云支持
- 配置 Ansible 自动化部署
- 集成 Gitea Actions CI/CD 流水线
- 添加 Docker Swarm 管理
- 完善监控和安全配置
This commit is contained in:
2025-09-20 10:48:41 +00:00
parent d755f237a0
commit 7eb4a33523
55 changed files with 3745 additions and 1921 deletions

View File

@@ -0,0 +1,138 @@
version: '3.8'
services:
# Traefik 负载均衡器
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8080:8080" # Traefik Dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./certs:/certs:ro
environment:
- CONSUL_ENDPOINTS=consul1:8500,consul2:8500,consul3:8500
depends_on:
- consul1
- consul2
- consul3
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.local`)"
- "traefik.http.routers.dashboard.service=api@internal"
# Consul 集群节点 1
consul1:
image: consul:1.16.1
container_name: consul1
hostname: consul1
restart: unless-stopped
ports:
- "8500:8500"
volumes:
- consul1_data:/consul/data
command: >
consul agent -server -bootstrap-expect=3
-datacenter=dc1 -data-dir=/consul/data
-node=consul1 -bind=0.0.0.0 -client=0.0.0.0
-retry-join=consul2 -retry-join=consul3
-ui-config='{"enabled": true}'
-log-level=INFO
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.consul.rule=Host(`consul.local`)"
- "traefik.http.services.consul.loadbalancer.server.port=8500"
# Consul 集群节点 2
consul2:
image: consul:1.16.1
container_name: consul2
hostname: consul2
restart: unless-stopped
volumes:
- consul2_data:/consul/data
command: >
consul agent -server -bootstrap-expect=3
-datacenter=dc1 -data-dir=/consul/data
-node=consul2 -bind=0.0.0.0 -client=0.0.0.0
-retry-join=consul1 -retry-join=consul3
-log-level=INFO
networks:
- traefik-net
# Consul 集群节点 3
consul3:
image: consul:1.16.1
container_name: consul3
hostname: consul3
restart: unless-stopped
volumes:
- consul3_data:/consul/data
command: >
consul agent -server -bootstrap-expect=3
-datacenter=dc1 -data-dir=/consul/data
-node=consul3 -bind=0.0.0.0 -client=0.0.0.0
-retry-join=consul1 -retry-join=consul2
-log-level=INFO
networks:
- traefik-net
# 示例 Web 应用
web-app:
image: nginx:alpine
container_name: web-app
restart: unless-stopped
volumes:
- ./web-content:/usr/share/nginx/html:ro
environment:
- CONSUL_URL=http://consul1:8500
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`app.local`)"
- "traefik.http.services.web.loadbalancer.server.port=80"
- "traefik.http.routers.web.middlewares=web-auth"
- "traefik.http.middlewares.web-auth.basicauth.users=admin:$$2y$$10$$..."
# 示例 API 应用
api-app:
image: node:18-alpine
container_name: api-app
restart: unless-stopped
working_dir: /app
volumes:
- ./api:/app
command: ["node", "server.js"]
environment:
- CONSUL_URL=http://consul1:8500
- NODE_ENV=production
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.local`) && PathPrefix(`/api`)"
- "traefik.http.services.api.loadbalancer.server.port=3000"
- "traefik.http.routers.api.middlewares=api-cors"
- "traefik.http.middlewares.api-cors.headers.accesscontrolallowmethods=GET,POST,PUT,DELETE"
- "traefik.http.middlewares.api-cors.headers.accesscontrolalloworigin=*"
volumes:
consul1_data:
consul2_data:
consul3_data:
networks:
traefik-net:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16

View File

@@ -0,0 +1,60 @@
# Traefik 配置文件
api:
dashboard: true
insecure: true # 仅开发环境,生产环境请使用 HTTPS
# 入口点配置
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
# 提供者配置
providers:
# Docker 标签发现
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
watch: true
# Consul 服务发现
consul:
endpoints:
- "consul1:8500"
- "consul2:8500"
- "consul3:8500"
watch: true
# 文件配置提供者
file:
filename: /etc/traefik/dynamic.yml
watch: true
# 证书解析器Let's Encrypt
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /certs/acme.json
httpChallenge:
entryPoint: web
# 日志配置
log:
level: INFO
filePath: "/var/log/traefik.log"
accessLog:
filePath: "/var/log/access.log"
# 指标配置
metrics:
prometheus:
addEntryPointsLabels: true
addServicesLabels: true
# 全局配置
global:
checkNewVersion: false
sendAnonymousUsage: false