refactor: 更新项目结构和文档,移除不再使用的配置文件
- 修改README.md,更新项目特性和目录结构说明 - 重命名基础设施代码目录为tofu,并添加Docker Swarm配置目录 - 移除不再使用的Docker Compose和Traefik配置文件 - 更新Terraform配置,专注于Oracle Cloud支持,移除华为云相关配置 - 清理开发环境变量和示例文件
This commit is contained in:
parent
7eb4a33523
commit
377f176501
64
README.md
64
README.md
|
|
@ -1,13 +1,13 @@
|
||||||
# 🏗️ 基础设施管理项目
|
# 🏗️ 基础设施管理项目
|
||||||
|
|
||||||
这是一个现代化的多云基础设施管理平台,集成 OpenTofu、Ansible、Docker Swarm 和 Gitea CI/CD。
|
这是一个现代化的多云基础设施管理平台,专注于 OpenTofu、Ansible 和 Docker Swarm 的集成管理。
|
||||||
|
|
||||||
## 🎯 项目特性
|
## 🎯 项目特性
|
||||||
|
|
||||||
- **🌩️ 多云支持**: Oracle Cloud, 华为云, Google Cloud, AWS, DigitalOcean
|
- **🌩️ 多云支持**: Oracle Cloud, 华为云, Google Cloud, AWS, DigitalOcean
|
||||||
- **🏗️ 基础设施即代码**: 使用 OpenTofu 管理云资源
|
- **🏗️ 基础设施即代码**: 使用 OpenTofu 管理云资源
|
||||||
- **⚙️ 配置管理**: 使用 Ansible 自动化配置和部署
|
- **⚙️ 配置管理**: 使用 Ansible 自动化配置和部署
|
||||||
- **🐳 容器编排**: Docker Swarm 集群管理
|
- **🐳 容器编排**: Docker Swarm 集群管理和服务编排
|
||||||
- **🔄 CI/CD**: Gitea Actions 自动化流水线
|
- **🔄 CI/CD**: Gitea Actions 自动化流水线
|
||||||
- **📊 监控**: Prometheus + Grafana 监控体系
|
- **📊 监控**: Prometheus + Grafana 监控体系
|
||||||
- **🔐 安全**: 多层安全防护和合规性
|
- **🔐 安全**: 多层安全防护和合规性
|
||||||
|
|
@ -17,23 +17,25 @@
|
||||||
```
|
```
|
||||||
mgmt/
|
mgmt/
|
||||||
├── .gitea/workflows/ # CI/CD 工作流
|
├── .gitea/workflows/ # CI/CD 工作流
|
||||||
├── infrastructure/ # OpenTofu 基础设施代码
|
├── tofu/ # OpenTofu 基础设施代码
|
||||||
│ ├── environments/ # 环境配置 (dev/staging/prod)
|
│ ├── environments/ # 环境配置 (dev/staging/prod)
|
||||||
│ ├── modules/ # 可复用模块
|
│ ├── modules/ # 可复用模块
|
||||||
│ ├── providers/ # 云服务商配置
|
│ ├── providers/ # 云服务商配置
|
||||||
│ └── shared/ # 共享配置
|
│ └── shared/ # 共享配置
|
||||||
|
├── swarm/ # Docker Swarm 配置
|
||||||
|
│ ├── stacks/ # Docker Stack 配置文件
|
||||||
|
│ ├── configs/ # Traefik 等基础设施配置
|
||||||
|
│ └── scripts/ # Swarm 管理脚本
|
||||||
├── configuration/ # Ansible 配置管理
|
├── configuration/ # Ansible 配置管理
|
||||||
│ ├── inventories/ # 主机清单
|
│ ├── inventories/ # 主机清单
|
||||||
│ ├── playbooks/ # 剧本
|
│ ├── playbooks/ # 剧本
|
||||||
│ ├── roles/ # 角色
|
│ ├── roles/ # 角色
|
||||||
│ └── group_vars/ # 组变量
|
│ └── group_vars/ # 组变量
|
||||||
├── containers/ # 容器化应用
|
|
||||||
│ ├── applications/ # 应用容器
|
|
||||||
│ ├── infrastructure/ # 基础设施容器
|
|
||||||
│ └── compose/ # Docker Compose 文件
|
|
||||||
├── monitoring/ # 监控配置
|
├── monitoring/ # 监控配置
|
||||||
├── scripts/ # 自动化脚本
|
├── scripts/ # 自动化脚本
|
||||||
├── docs/ # 文档
|
│ ├── setup/ # 环境设置脚本
|
||||||
|
│ └── utilities/ # 实用工具脚本
|
||||||
|
├── mgmt.sh # 项目管理主脚本
|
||||||
└── Makefile # 项目管理命令
|
└── Makefile # 项目管理命令
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -46,56 +48,60 @@ mgmt/
|
||||||
git clone <repository-url>
|
git clone <repository-url>
|
||||||
cd mgmt
|
cd mgmt
|
||||||
|
|
||||||
# 设置开发环境
|
# 检查环境状态
|
||||||
make setup
|
./mgmt.sh status
|
||||||
|
|
||||||
|
# 快速部署(适用于开发环境)
|
||||||
|
./mgmt.sh deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. 配置云服务商
|
### 2. 配置云服务商
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 复制配置模板
|
# 复制配置模板
|
||||||
cp infrastructure/environments/dev/terraform.tfvars.example infrastructure/environments/dev/terraform.tfvars
|
cp tofu/environments/dev/terraform.tfvars.example tofu/environments/dev/terraform.tfvars
|
||||||
|
|
||||||
# 编辑配置文件,填入你的云服务商凭据
|
# 编辑配置文件,填入你的云服务商凭据
|
||||||
vim infrastructure/environments/dev/terraform.tfvars
|
vim tofu/environments/dev/terraform.tfvars
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. 初始化基础设施
|
### 3. 初始化基础设施
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 初始化 OpenTofu
|
# 初始化 OpenTofu
|
||||||
make init
|
./mgmt.sh tofu init
|
||||||
|
|
||||||
# 查看执行计划
|
# 查看执行计划
|
||||||
make plan
|
./mgmt.sh tofu plan
|
||||||
|
|
||||||
# 应用基础设施变更
|
# 应用基础设施变更
|
||||||
make apply
|
cd tofu/environments/dev && tofu apply
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. 部署应用
|
### 4. 部署 Docker Swarm 服务
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 检查 Ansible 配置
|
# 初始化 Docker Swarm
|
||||||
make ansible-check
|
./mgmt.sh swarm init
|
||||||
|
|
||||||
# 部署应用
|
# 部署 Traefik 反向代理
|
||||||
make ansible-deploy
|
./mgmt.sh swarm deploy traefik swarm/stacks/traefik-swarm-stack.yml
|
||||||
|
|
||||||
|
# 部署示例服务
|
||||||
|
./mgmt.sh swarm deploy demo swarm/stacks/demo-services-stack.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🛠️ 常用命令
|
## 🛠️ 常用命令
|
||||||
|
|
||||||
| 命令 | 描述 |
|
| 命令 | 描述 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `make help` | 显示所有可用命令 |
|
| `./mgmt.sh status` | 显示项目状态总览 |
|
||||||
| `make setup` | 设置开发环境 |
|
| `./mgmt.sh deploy` | 快速部署所有服务 |
|
||||||
| `make init` | 初始化 OpenTofu |
|
| `./mgmt.sh cleanup` | 清理所有部署的服务 |
|
||||||
| `make plan` | 生成基础设施执行计划 |
|
| `./mgmt.sh swarm <cmd>` | Docker Swarm 管理命令 |
|
||||||
| `make apply` | 应用基础设施变更 |
|
| `./mgmt.sh tofu <cmd>` | OpenTofu 管理命令 |
|
||||||
| `make ansible-deploy` | 部署应用 |
|
| `swarm/scripts/swarm-manager.sh help` | Swarm 管理帮助 |
|
||||||
| `make docker-up` | 启动开发环境 |
|
| `scripts/setup/setup-opentofu.sh help` | OpenTofu 设置帮助 |
|
||||||
| `make test` | 运行测试 |
|
|
||||||
| `make clean` | 清理临时文件 |
|
|
||||||
|
|
||||||
## 🌩️ 支持的云服务商
|
## 🌩️ 支持的云服务商
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
---
|
||||||
|
- name: Gitea Runner Management
|
||||||
|
hosts: hcp
|
||||||
|
become: yes
|
||||||
|
vars:
|
||||||
|
gitea_runner_user: "gitea-runner"
|
||||||
|
gitea_runner_data_dir: "/var/lib/gitea-runner"
|
||||||
|
gitea_runner_log_dir: "/var/log/gitea-runner"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check gitea-runner service status
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
register: service_status
|
||||||
|
|
||||||
|
- name: Display service status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
Service: {{ service_status.status.ActiveState }}
|
||||||
|
Enabled: {{ service_status.status.UnitFileState }}
|
||||||
|
Main PID: {{ service_status.status.MainPID | default('N/A') }}
|
||||||
|
|
||||||
|
- name: Show recent logs
|
||||||
|
command: journalctl -u gitea-runner --no-pager -n 20
|
||||||
|
register: recent_logs
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Display recent logs
|
||||||
|
debug:
|
||||||
|
var: recent_logs.stdout_lines
|
||||||
|
|
||||||
|
- name: Check runner registration
|
||||||
|
stat:
|
||||||
|
path: "{{ gitea_runner_data_dir }}/.runner"
|
||||||
|
register: runner_registered
|
||||||
|
|
||||||
|
- name: Display registration status
|
||||||
|
debug:
|
||||||
|
msg: "Runner registered: {{ runner_registered.stat.exists }}"
|
||||||
|
|
||||||
|
- name: Show runner configuration (if registered)
|
||||||
|
command: cat {{ gitea_runner_data_dir }}/.runner
|
||||||
|
register: runner_config
|
||||||
|
become_user: "{{ gitea_runner_user }}"
|
||||||
|
when: runner_registered.stat.exists
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Display runner configuration
|
||||||
|
debug:
|
||||||
|
var: runner_config.stdout_lines
|
||||||
|
when: runner_registered.stat.exists
|
||||||
|
|
||||||
|
- name: Check Docker access for runner user
|
||||||
|
command: docker ps
|
||||||
|
become_user: "{{ gitea_runner_user }}"
|
||||||
|
register: docker_access
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display Docker access status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
Docker access: {{ 'OK' if docker_access.rc == 0 else 'FAILED' }}
|
||||||
|
{% if docker_access.rc != 0 %}
|
||||||
|
Error: {{ docker_access.stderr }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# 单独的任务用于管理服务
|
||||||
|
- name: Service Management Tasks
|
||||||
|
hosts: hcp
|
||||||
|
become: yes
|
||||||
|
tasks:
|
||||||
|
- name: Start gitea-runner service
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: started
|
||||||
|
when: ansible_run_tags is defined and 'start' in ansible_run_tags
|
||||||
|
|
||||||
|
- name: Stop gitea-runner service
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: stopped
|
||||||
|
when: ansible_run_tags is defined and 'stop' in ansible_run_tags
|
||||||
|
|
||||||
|
- name: Restart gitea-runner service
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: restarted
|
||||||
|
when: ansible_run_tags is defined and 'restart' in ansible_run_tags
|
||||||
|
|
||||||
|
- name: Reload gitea-runner service
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: reloaded
|
||||||
|
when: ansible_run_tags is defined and 'reload' in ansible_run_tags
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
---
|
||||||
|
- name: Setup Gitea Runner on HCP nodes
|
||||||
|
hosts: hcp
|
||||||
|
become: yes
|
||||||
|
vars:
|
||||||
|
gitea_runner_token: "vOrrQda6Qiet9YOj4waZVU5QgLig2J3rKp2RfoN7"
|
||||||
|
gitea_server_url: "http://gitea:3000"
|
||||||
|
gitea_runner_user: "gitea-runner"
|
||||||
|
gitea_runner_home: "/home/{{ gitea_runner_user }}"
|
||||||
|
gitea_runner_config_dir: "/etc/gitea-runner"
|
||||||
|
gitea_runner_data_dir: "/var/lib/gitea-runner"
|
||||||
|
gitea_runner_log_dir: "/var/log/gitea-runner"
|
||||||
|
gitea_runner_binary: "/usr/bin/act_runner"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check if gitea-runner binary exists
|
||||||
|
stat:
|
||||||
|
path: "{{ gitea_runner_binary }}"
|
||||||
|
register: runner_binary
|
||||||
|
|
||||||
|
- name: Fail if act_runner binary not found
|
||||||
|
fail:
|
||||||
|
msg: "Act runner binary not found at {{ gitea_runner_binary }}. Please install it first."
|
||||||
|
when: not runner_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Create gitea-runner user
|
||||||
|
user:
|
||||||
|
name: "{{ gitea_runner_user }}"
|
||||||
|
system: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
home: "{{ gitea_runner_home }}"
|
||||||
|
create_home: yes
|
||||||
|
comment: "Gitea Runner Service User"
|
||||||
|
|
||||||
|
- name: Create gitea-runner directories
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ gitea_runner_user }}"
|
||||||
|
group: "{{ gitea_runner_user }}"
|
||||||
|
mode: '0755'
|
||||||
|
loop:
|
||||||
|
- "{{ gitea_runner_config_dir }}"
|
||||||
|
- "{{ gitea_runner_data_dir }}"
|
||||||
|
- "{{ gitea_runner_log_dir }}"
|
||||||
|
|
||||||
|
- name: Create gitea-runner configuration file
|
||||||
|
template:
|
||||||
|
src: gitea-runner-config.yml.j2
|
||||||
|
dest: "{{ gitea_runner_config_dir }}/config.yml"
|
||||||
|
owner: "{{ gitea_runner_user }}"
|
||||||
|
group: "{{ gitea_runner_user }}"
|
||||||
|
mode: '0600'
|
||||||
|
notify: restart gitea-runner
|
||||||
|
|
||||||
|
- name: Create gitea-runner systemd service file
|
||||||
|
template:
|
||||||
|
src: gitea-runner.service.j2
|
||||||
|
dest: /etc/systemd/system/gitea-runner.service
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- reload systemd
|
||||||
|
- restart gitea-runner
|
||||||
|
|
||||||
|
- name: Create gitea-runner environment file
|
||||||
|
template:
|
||||||
|
src: gitea-runner.env.j2
|
||||||
|
dest: /etc/default/gitea-runner
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0600'
|
||||||
|
notify: restart gitea-runner
|
||||||
|
|
||||||
|
- name: Create runner registration script
|
||||||
|
template:
|
||||||
|
src: register-runner.sh.j2
|
||||||
|
dest: "{{ gitea_runner_home }}/register-runner.sh"
|
||||||
|
owner: "{{ gitea_runner_user }}"
|
||||||
|
group: "{{ gitea_runner_user }}"
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Check if runner is already registered
|
||||||
|
stat:
|
||||||
|
path: "{{ gitea_runner_data_dir }}/.runner"
|
||||||
|
register: runner_registered
|
||||||
|
|
||||||
|
- name: Register gitea runner
|
||||||
|
command: "{{ gitea_runner_home }}/register-runner.sh"
|
||||||
|
become_user: "{{ gitea_runner_user }}"
|
||||||
|
when: not runner_registered.stat.exists
|
||||||
|
register: registration_result
|
||||||
|
|
||||||
|
- name: Display registration result
|
||||||
|
debug:
|
||||||
|
var: registration_result.stdout_lines
|
||||||
|
when: registration_result is defined and registration_result.stdout_lines is defined
|
||||||
|
|
||||||
|
- name: Create runner startup script
|
||||||
|
template:
|
||||||
|
src: start-runner.sh.j2
|
||||||
|
dest: "{{ gitea_runner_home }}/start-runner.sh"
|
||||||
|
owner: "{{ gitea_runner_user }}"
|
||||||
|
group: "{{ gitea_runner_user }}"
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Create logrotate configuration for gitea-runner
|
||||||
|
template:
|
||||||
|
src: gitea-runner.logrotate.j2
|
||||||
|
dest: /etc/logrotate.d/gitea-runner
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Install Docker (required for runner)
|
||||||
|
package:
|
||||||
|
name: docker.io
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add gitea-runner user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ gitea_runner_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
|
||||||
|
- name: Start and enable Docker service
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Start and enable gitea-runner service
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
daemon_reload: yes
|
||||||
|
|
||||||
|
- name: Check gitea-runner service status
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
register: service_status
|
||||||
|
|
||||||
|
- name: Display service status
|
||||||
|
debug:
|
||||||
|
msg: "Gitea Runner service is {{ service_status.status.ActiveState }}"
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: reload systemd
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
|
||||||
|
- name: restart gitea-runner
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: restarted
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Gitea Runner Configuration
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
|
file: {{ gitea_runner_log_dir }}/runner.log
|
||||||
|
|
||||||
|
runner:
|
||||||
|
# Runner name (will be auto-generated if not specified)
|
||||||
|
name: "{{ inventory_hostname }}-runner"
|
||||||
|
|
||||||
|
# Runner capacity (number of concurrent jobs)
|
||||||
|
capacity: 2
|
||||||
|
|
||||||
|
# Runner timeout
|
||||||
|
timeout: 3600
|
||||||
|
|
||||||
|
# Runner labels (for job targeting)
|
||||||
|
labels:
|
||||||
|
- "ubuntu-latest:docker://ubuntu:22.04"
|
||||||
|
- "ubuntu-20.04:docker://ubuntu:20.04"
|
||||||
|
- "ubuntu-18.04:docker://ubuntu:18.04"
|
||||||
|
- "node:docker://node:18"
|
||||||
|
- "python:docker://python:3.11"
|
||||||
|
- "ansible:docker://quay.io/ansible/ansible-runner:latest"
|
||||||
|
- "opentofu:docker://opentofu/opentofu:latest"
|
||||||
|
|
||||||
|
cache:
|
||||||
|
enabled: true
|
||||||
|
dir: {{ gitea_runner_data_dir }}/cache
|
||||||
|
host: ""
|
||||||
|
port: 0
|
||||||
|
|
||||||
|
container:
|
||||||
|
# Docker network for runner containers
|
||||||
|
network: "gitea-runner"
|
||||||
|
|
||||||
|
# Enable privileged containers (needed for Docker-in-Docker)
|
||||||
|
privileged: false
|
||||||
|
|
||||||
|
# Container options
|
||||||
|
options: "--rm --pull=always"
|
||||||
|
|
||||||
|
# Valid platforms
|
||||||
|
valid_volumes:
|
||||||
|
- "/tmp"
|
||||||
|
- "{{ gitea_runner_data_dir }}"
|
||||||
|
|
||||||
|
docker_host: "unix:///var/run/docker.sock"
|
||||||
|
|
||||||
|
host:
|
||||||
|
workdir_parent: {{ gitea_runner_data_dir }}/work
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Gitea Runner Environment Variables
|
||||||
|
|
||||||
|
# Gitea server configuration
|
||||||
|
GITEA_INSTANCE_URL={{ gitea_server_url }}
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN={{ gitea_runner_token }}
|
||||||
|
|
||||||
|
# Runner configuration
|
||||||
|
GITEA_RUNNER_NAME={{ inventory_hostname }}-runner
|
||||||
|
GITEA_RUNNER_LABELS=ubuntu-latest,ubuntu-20.04,ubuntu-18.04,node,python,ansible,opentofu
|
||||||
|
|
||||||
|
# Docker configuration
|
||||||
|
DOCKER_HOST=unix:///var/run/docker.sock
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
GITEA_RUNNER_LOG_LEVEL=info
|
||||||
|
|
||||||
|
# Security
|
||||||
|
GITEA_RUNNER_SECURITY_PRIVILEGED=false
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{{ gitea_runner_log_dir }}/*.log {
|
||||||
|
daily
|
||||||
|
missingok
|
||||||
|
rotate 30
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
notifempty
|
||||||
|
create 644 {{ gitea_runner_user }} {{ gitea_runner_user }}
|
||||||
|
postrotate
|
||||||
|
systemctl reload gitea-runner || true
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Gitea Actions Runner
|
||||||
|
Documentation=https://docs.gitea.io/en-us/actions/
|
||||||
|
After=network.target docker.service
|
||||||
|
Wants=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User={{ gitea_runner_user }}
|
||||||
|
Group={{ gitea_runner_user }}
|
||||||
|
WorkingDirectory={{ gitea_runner_data_dir }}
|
||||||
|
ExecStart={{ gitea_runner_binary }} daemon --config {{ gitea_runner_config_dir }}/config.yml
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
KillMode=mixed
|
||||||
|
KillSignal=SIGINT
|
||||||
|
TimeoutStopSec=5
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
StartLimitInterval=0
|
||||||
|
|
||||||
|
# Security settings
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
ReadWritePaths={{ gitea_runner_data_dir }} {{ gitea_runner_log_dir }} /var/run/docker.sock
|
||||||
|
ProtectKernelTunables=yes
|
||||||
|
ProtectKernelModules=yes
|
||||||
|
ProtectControlGroups=yes
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
EnvironmentFile=-/etc/default/gitea-runner
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
StandardOutput=append:{{ gitea_runner_log_dir }}/gitea-runner.log
|
||||||
|
StandardError=append:{{ gitea_runner_log_dir }}/gitea-runner-error.log
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Gitea Runner Registration Script
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🚀 注册 Gitea Runner..."
|
||||||
|
|
||||||
|
# 配置变量
|
||||||
|
GITEA_URL="{{ gitea_server_url }}"
|
||||||
|
REGISTRATION_TOKEN="{{ gitea_runner_token }}"
|
||||||
|
RUNNER_NAME="{{ inventory_hostname }}-runner"
|
||||||
|
RUNNER_LABELS="ubuntu-latest,ubuntu-20.04,ubuntu-18.04,node,python,ansible,opentofu"
|
||||||
|
|
||||||
|
# 切换到数据目录
|
||||||
|
cd {{ gitea_runner_data_dir }}
|
||||||
|
|
||||||
|
# 检查是否已经注册
|
||||||
|
if [ -f ".runner" ]; then
|
||||||
|
echo "✅ Runner 已经注册"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📝 注册 Runner: $RUNNER_NAME"
|
||||||
|
echo "🔗 Gitea URL: $GITEA_URL"
|
||||||
|
echo "🏷️ Labels: $RUNNER_LABELS"
|
||||||
|
|
||||||
|
# 注册 Runner
|
||||||
|
{{ gitea_runner_binary }} register \
|
||||||
|
--instance "$GITEA_URL" \
|
||||||
|
--token "$REGISTRATION_TOKEN" \
|
||||||
|
--name "$RUNNER_NAME" \
|
||||||
|
--labels "$RUNNER_LABELS"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ Runner 注册成功!"
|
||||||
|
|
||||||
|
# 设置文件权限
|
||||||
|
chown {{ gitea_runner_user }}:{{ gitea_runner_user }} .runner .credentials
|
||||||
|
chmod 600 .runner .credentials
|
||||||
|
|
||||||
|
echo "📋 Runner 信息:"
|
||||||
|
cat .runner
|
||||||
|
else
|
||||||
|
echo "❌ Runner 注册失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Gitea Runner Startup Script
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🚀 启动 Gitea Runner..."
|
||||||
|
|
||||||
|
# 切换到数据目录
|
||||||
|
cd {{ gitea_runner_data_dir }}
|
||||||
|
|
||||||
|
# 检查注册状态
|
||||||
|
if [ ! -f ".runner" ]; then
|
||||||
|
echo "❌ Runner 未注册,请先运行注册脚本"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Runner 已注册,启动守护进程..."
|
||||||
|
|
||||||
|
# 启动 Runner
|
||||||
|
exec {{ gitea_runner_binary }} daemon --config {{ gitea_runner_config_dir }}/config.yml
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Gitea Runner Configuration
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
|
file: {{ gitea_runner_log_dir }}/runner.log
|
||||||
|
|
||||||
|
runner:
|
||||||
|
# Runner name (will be auto-generated if not specified)
|
||||||
|
name: "{{ inventory_hostname }}-runner"
|
||||||
|
|
||||||
|
# Runner capacity (number of concurrent jobs)
|
||||||
|
capacity: 2
|
||||||
|
|
||||||
|
# Runner timeout
|
||||||
|
timeout: 3600
|
||||||
|
|
||||||
|
# Runner labels (for job targeting)
|
||||||
|
labels:
|
||||||
|
- "ubuntu-latest:docker://ubuntu:22.04"
|
||||||
|
- "ubuntu-20.04:docker://ubuntu:20.04"
|
||||||
|
- "ubuntu-18.04:docker://ubuntu:18.04"
|
||||||
|
- "node:docker://node:18"
|
||||||
|
- "python:docker://python:3.11"
|
||||||
|
- "ansible:docker://quay.io/ansible/ansible-runner:latest"
|
||||||
|
- "opentofu:docker://opentofu/opentofu:latest"
|
||||||
|
|
||||||
|
cache:
|
||||||
|
enabled: true
|
||||||
|
dir: {{ gitea_runner_data_dir }}/cache
|
||||||
|
host: ""
|
||||||
|
port: 0
|
||||||
|
|
||||||
|
container:
|
||||||
|
# Docker network for runner containers
|
||||||
|
network: "gitea-runner"
|
||||||
|
|
||||||
|
# Enable privileged containers (needed for Docker-in-Docker)
|
||||||
|
privileged: false
|
||||||
|
|
||||||
|
# Container options
|
||||||
|
options: "--rm --pull=always"
|
||||||
|
|
||||||
|
# Valid platforms
|
||||||
|
valid_volumes:
|
||||||
|
- "/tmp"
|
||||||
|
- "{{ gitea_runner_data_dir }}"
|
||||||
|
|
||||||
|
docker_host: "unix:///var/run/docker.sock"
|
||||||
|
|
||||||
|
host:
|
||||||
|
workdir_parent: {{ gitea_runner_data_dir }}/work
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Gitea Runner Environment Variables
|
||||||
|
|
||||||
|
# Gitea server configuration
|
||||||
|
GITEA_INSTANCE_URL={{ gitea_server_url }}
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN={{ gitea_runner_token }}
|
||||||
|
|
||||||
|
# Runner configuration
|
||||||
|
GITEA_RUNNER_NAME={{ inventory_hostname }}-runner
|
||||||
|
GITEA_RUNNER_LABELS=ubuntu-latest,ubuntu-20.04,ubuntu-18.04,node,python,ansible,opentofu
|
||||||
|
|
||||||
|
# Docker configuration
|
||||||
|
DOCKER_HOST=unix:///var/run/docker.sock
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
GITEA_RUNNER_LOG_LEVEL=info
|
||||||
|
|
||||||
|
# Security
|
||||||
|
GITEA_RUNNER_SECURITY_PRIVILEGED=false
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{{ gitea_runner_log_dir }}/*.log {
|
||||||
|
daily
|
||||||
|
missingok
|
||||||
|
rotate 30
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
notifempty
|
||||||
|
create 644 {{ gitea_runner_user }} {{ gitea_runner_user }}
|
||||||
|
postrotate
|
||||||
|
systemctl reload gitea-runner || true
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Gitea Actions Runner
|
||||||
|
Documentation=https://docs.gitea.io/en-us/actions/
|
||||||
|
After=network.target docker.service
|
||||||
|
Wants=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User={{ gitea_runner_user }}
|
||||||
|
Group={{ gitea_runner_user }}
|
||||||
|
WorkingDirectory={{ gitea_runner_data_dir }}
|
||||||
|
ExecStart={{ gitea_runner_binary }} daemon --config {{ gitea_runner_config_dir }}/config.yml
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
KillMode=mixed
|
||||||
|
KillSignal=SIGINT
|
||||||
|
TimeoutStopSec=5
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
StartLimitInterval=0
|
||||||
|
|
||||||
|
# Security settings
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
ReadWritePaths={{ gitea_runner_data_dir }} {{ gitea_runner_log_dir }} /var/run/docker.sock
|
||||||
|
ProtectKernelTunables=yes
|
||||||
|
ProtectKernelModules=yes
|
||||||
|
ProtectControlGroups=yes
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
EnvironmentFile=-/etc/default/gitea-runner
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
StandardOutput=append:{{ gitea_runner_log_dir }}/gitea-runner.log
|
||||||
|
StandardError=append:{{ gitea_runner_log_dir }}/gitea-runner-error.log
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Gitea Runner Registration Script
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🚀 注册 Gitea Runner..."
|
||||||
|
|
||||||
|
# 配置变量
|
||||||
|
GITEA_URL="{{ gitea_server_url }}"
|
||||||
|
REGISTRATION_TOKEN="{{ gitea_runner_token }}"
|
||||||
|
RUNNER_NAME="{{ inventory_hostname }}-runner"
|
||||||
|
RUNNER_LABELS="ubuntu-latest,ubuntu-20.04,ubuntu-18.04,node,python,ansible,opentofu"
|
||||||
|
|
||||||
|
# 切换到数据目录
|
||||||
|
cd {{ gitea_runner_data_dir }}
|
||||||
|
|
||||||
|
# 检查是否已经注册
|
||||||
|
if [ -f ".runner" ]; then
|
||||||
|
echo "✅ Runner 已经注册"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📝 注册 Runner: $RUNNER_NAME"
|
||||||
|
echo "🔗 Gitea URL: $GITEA_URL"
|
||||||
|
echo "🏷️ Labels: $RUNNER_LABELS"
|
||||||
|
|
||||||
|
# 注册 Runner
|
||||||
|
{{ gitea_runner_binary }} register \
|
||||||
|
--instance "$GITEA_URL" \
|
||||||
|
--token "$REGISTRATION_TOKEN" \
|
||||||
|
--name "$RUNNER_NAME" \
|
||||||
|
--labels "$RUNNER_LABELS"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ Runner 注册成功!"
|
||||||
|
|
||||||
|
# 设置文件权限
|
||||||
|
chown {{ gitea_runner_user }}:{{ gitea_runner_user }} .runner .credentials
|
||||||
|
chmod 600 .runner .credentials
|
||||||
|
|
||||||
|
echo "📋 Runner 信息:"
|
||||||
|
cat .runner
|
||||||
|
else
|
||||||
|
echo "❌ Runner 注册失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Gitea Runner Startup Script
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🚀 启动 Gitea Runner..."
|
||||||
|
|
||||||
|
# 切换到数据目录
|
||||||
|
cd {{ gitea_runner_data_dir }}
|
||||||
|
|
||||||
|
# 检查注册状态
|
||||||
|
if [ ! -f ".runner" ]; then
|
||||||
|
echo "❌ Runner 未注册,请先运行注册脚本"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Runner 已注册,启动守护进程..."
|
||||||
|
|
||||||
|
# 启动 Runner
|
||||||
|
exec {{ gitea_runner_binary }} daemon --config {{ gitea_runner_config_dir }}/config.yml
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
# Consul + Terraform 集成指南
|
||||||
|
|
||||||
|
本指南介绍如何使用 Consul 安全地管理 Terraform 中的敏感配置信息,特别是 Oracle Cloud 的凭据。
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
我们使用 Consul 作为安全的密钥存储,避免在 Terraform 配置文件中直接暴露敏感信息。
|
||||||
|
|
||||||
|
## 架构
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||||
|
│ Terraform │───▶│ Consul │───▶│ Oracle Cloud │
|
||||||
|
│ │ │ (密钥存储) │ │ │
|
||||||
|
│ consul provider │ │ │ │ │
|
||||||
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 前提条件
|
||||||
|
|
||||||
|
1. Consul 集群正在运行
|
||||||
|
2. 可以访问 Consul API (默认: http://localhost:8500)
|
||||||
|
3. 已安装 curl 和 Terraform
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 启动 Consul 集群
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入 swarm 目录
|
||||||
|
cd swarm
|
||||||
|
|
||||||
|
# 启动 Consul 集群
|
||||||
|
docker-compose -f configs/traefik-consul-setup.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 设置 Oracle Cloud 配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用密钥管理脚本设置配置
|
||||||
|
./scripts/utilities/consul-secrets-manager.sh set-oracle
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本会提示你输入:
|
||||||
|
- 租户 OCID
|
||||||
|
- 用户 OCID
|
||||||
|
- API 密钥指纹
|
||||||
|
- 私钥文件路径
|
||||||
|
- 区间 OCID
|
||||||
|
|
||||||
|
### 3. 配置 Terraform
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 设置 Terraform Consul Provider
|
||||||
|
./scripts/utilities/terraform-consul-provider.sh setup
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 验证配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看存储在 Consul 中的配置
|
||||||
|
./scripts/utilities/consul-secrets-manager.sh get-oracle
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 运行 Terraform
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd infrastructure/environments/dev
|
||||||
|
|
||||||
|
# 初始化 Terraform
|
||||||
|
terraform init
|
||||||
|
|
||||||
|
# 规划部署
|
||||||
|
terraform plan
|
||||||
|
|
||||||
|
# 应用配置
|
||||||
|
terraform apply
|
||||||
|
```
|
||||||
|
|
||||||
|
## 详细说明
|
||||||
|
|
||||||
|
### Consul 密钥存储结构
|
||||||
|
|
||||||
|
```
|
||||||
|
config/
|
||||||
|
└── dev/
|
||||||
|
└── oracle/
|
||||||
|
├── tenancy_ocid
|
||||||
|
├── user_ocid
|
||||||
|
├── fingerprint
|
||||||
|
├── private_key
|
||||||
|
└── compartment_ocid
|
||||||
|
```
|
||||||
|
|
||||||
|
### 脚本功能
|
||||||
|
|
||||||
|
#### consul-secrets-manager.sh
|
||||||
|
|
||||||
|
- `set-oracle`: 设置 Oracle Cloud 配置到 Consul
|
||||||
|
- `get-oracle`: 从 Consul 获取配置信息
|
||||||
|
- `delete-oracle`: 删除 Consul 中的配置
|
||||||
|
- `generate-vars`: 生成临时 Terraform 变量文件
|
||||||
|
- `cleanup`: 清理临时文件
|
||||||
|
|
||||||
|
#### terraform-consul-provider.sh
|
||||||
|
|
||||||
|
- `setup`: 创建 Terraform Consul Provider 配置文件
|
||||||
|
|
||||||
|
### 安全特性
|
||||||
|
|
||||||
|
1. **敏感信息隔离**: 私钥等敏感信息只存储在 Consul 中
|
||||||
|
2. **临时文件**: 私钥文件只在 Terraform 运行时临时创建
|
||||||
|
3. **权限控制**: 临时私钥文件设置为 600 权限
|
||||||
|
4. **自动清理**: 提供清理脚本删除临时文件
|
||||||
|
|
||||||
|
## 环境变量
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Consul 地址
|
||||||
|
export CONSUL_ADDR="http://localhost:8500"
|
||||||
|
|
||||||
|
# Consul ACL Token (如果启用了 ACL)
|
||||||
|
export CONSUL_TOKEN="your-token"
|
||||||
|
|
||||||
|
# 环境名称
|
||||||
|
export ENVIRONMENT="dev"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### Consul 连接问题
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查 Consul 状态
|
||||||
|
curl http://localhost:8500/v1/status/leader
|
||||||
|
|
||||||
|
# 检查 Consul 服务
|
||||||
|
docker ps | grep consul
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 验证 Consul 中的配置
|
||||||
|
curl http://localhost:8500/v1/kv/config/dev/oracle?recurse
|
||||||
|
|
||||||
|
# 检查 Terraform 配置
|
||||||
|
terraform validate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 清理和重置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 清理临时文件
|
||||||
|
./scripts/utilities/consul-secrets-manager.sh cleanup
|
||||||
|
|
||||||
|
# 删除 Consul 中的配置
|
||||||
|
./scripts/utilities/consul-secrets-manager.sh delete-oracle
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
1. **定期轮换密钥**: 定期更新 Oracle Cloud API 密钥
|
||||||
|
2. **备份配置**: 定期备份 Consul 数据
|
||||||
|
3. **监控访问**: 监控 Consul 密钥访问日志
|
||||||
|
4. **环境隔离**: 不同环境使用不同的 Consul 路径
|
||||||
|
|
||||||
|
## 扩展其他云服务商
|
||||||
|
|
||||||
|
可以类似地为其他云服务商添加 Consul 集成:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 华为云配置路径
|
||||||
|
config/dev/huawei/access_key
|
||||||
|
config/dev/huawei/secret_key
|
||||||
|
|
||||||
|
# AWS 配置路径
|
||||||
|
config/dev/aws/access_key
|
||||||
|
config/dev/aws/secret_key
|
||||||
|
|
||||||
|
# Google Cloud 配置路径
|
||||||
|
config/dev/gcp/service_account_key
|
||||||
|
```
|
||||||
|
|
||||||
|
## 相关文件
|
||||||
|
|
||||||
|
- `infrastructure/environments/dev/terraform.tfvars` - Terraform 变量配置
|
||||||
|
- `scripts/utilities/consul-secrets-manager.sh` - Consul 密钥管理脚本
|
||||||
|
- `scripts/utilities/terraform-consul-provider.sh` - Terraform Consul Provider 配置脚本
|
||||||
|
- `swarm/configs/traefik-consul-setup.yml` - Consul 集群配置
|
||||||
|
|
||||||
|
## 支持
|
||||||
|
|
||||||
|
如有问题,请检查:
|
||||||
|
1. Consul 集群是否正常运行
|
||||||
|
2. 网络连接是否正常
|
||||||
|
3. 权限设置是否正确
|
||||||
|
4. 环境变量是否正确设置
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Oracle Cloud 凭据配置指南
|
||||||
|
|
||||||
|
## 凭据文件位置
|
||||||
|
|
||||||
|
### 1. OpenTofu 配置文件
|
||||||
|
**文件位置**: `infrastructure/environments/dev/terraform.tfvars`
|
||||||
|
|
||||||
|
这是主要的配置文件,需要填入你的 OCI 凭据:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
# Oracle Cloud 配置
|
||||||
|
oci_config = {
|
||||||
|
tenancy_ocid = "ocid1.tenancy.oc1..aaaaaaaa_你的租户ID"
|
||||||
|
user_ocid = "ocid1.user.oc1..aaaaaaaa_你的用户ID"
|
||||||
|
fingerprint = "aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp"
|
||||||
|
private_key_path = "~/.oci/oci_api_key.pem"
|
||||||
|
region = "ap-seoul-1"
|
||||||
|
compartment_ocid = "ocid1.compartment.oc1..aaaaaaaa_你的区间ID"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. OCI 私钥文件
|
||||||
|
**文件位置**: `~/.oci/oci_api_key.pem`
|
||||||
|
|
||||||
|
这是你的 API 私钥文件,内容类似:
|
||||||
|
|
||||||
|
```
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC...
|
||||||
|
你的私钥内容
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. OCI 配置文件 (可选)
|
||||||
|
**文件位置**: `~/.oci/config`
|
||||||
|
|
||||||
|
这是 OCI CLI 的配置文件,可以作为备用:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[DEFAULT]
|
||||||
|
user=ocid1.user.oc1..aaaaaaaa_你的用户ID
|
||||||
|
fingerprint=aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp
|
||||||
|
tenancy=ocid1.tenancy.oc1..aaaaaaaa_你的租户ID
|
||||||
|
region=ap-seoul-1
|
||||||
|
key_file=~/.oci/oci_api_key.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
## 设置步骤
|
||||||
|
|
||||||
|
### 步骤 1: 创建 .oci 目录
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.oci
|
||||||
|
chmod 700 ~/.oci
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 2: 保存私钥文件
|
||||||
|
```bash
|
||||||
|
# 将你的私钥内容保存到文件
|
||||||
|
nano ~/.oci/oci_api_key.pem
|
||||||
|
|
||||||
|
# 设置正确的权限
|
||||||
|
chmod 400 ~/.oci/oci_api_key.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 3: 编辑 terraform.tfvars
|
||||||
|
```bash
|
||||||
|
# 编辑配置文件
|
||||||
|
nano infrastructure/environments/dev/terraform.tfvars
|
||||||
|
```
|
||||||
|
|
||||||
|
## 安全注意事项
|
||||||
|
|
||||||
|
1. **私钥文件权限**: 确保私钥文件权限为 400 (只有所有者可读)
|
||||||
|
2. **不要提交到 Git**: `.gitignore` 已经配置忽略 `*.tfvars` 文件
|
||||||
|
3. **备份凭据**: 建议安全备份你的私钥和配置信息
|
||||||
|
|
||||||
|
## 验证配置
|
||||||
|
|
||||||
|
配置完成后,可以运行以下命令验证:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查配置
|
||||||
|
./scripts/setup/setup-opentofu.sh check
|
||||||
|
|
||||||
|
# 初始化 OpenTofu
|
||||||
|
./scripts/setup/setup-opentofu.sh init
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
# Oracle Cloud 配置指南
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
本指南将帮助你配置 Oracle Cloud Infrastructure (OCI) 以便与 OpenTofu 一起使用。
|
||||||
|
|
||||||
|
## 前提条件
|
||||||
|
|
||||||
|
1. Oracle Cloud 账户(可以使用免费层)
|
||||||
|
2. 已安装 OpenTofu
|
||||||
|
3. 已安装 OCI CLI(可选,但推荐)
|
||||||
|
|
||||||
|
## 步骤 1: 创建 Oracle Cloud 账户
|
||||||
|
|
||||||
|
1. 访问 [Oracle Cloud](https://cloud.oracle.com/)
|
||||||
|
2. 点击 "Start for free" 创建免费账户
|
||||||
|
3. 完成注册流程
|
||||||
|
|
||||||
|
## 步骤 2: 获取必要的 OCID
|
||||||
|
|
||||||
|
### 获取 Tenancy OCID
|
||||||
|
|
||||||
|
1. 登录 Oracle Cloud Console
|
||||||
|
2. 点击右上角的用户图标
|
||||||
|
3. 选择 "Tenancy: <your-tenancy-name>"
|
||||||
|
4. 复制 OCID 值
|
||||||
|
|
||||||
|
### 获取 User OCID
|
||||||
|
|
||||||
|
1. 在 Oracle Cloud Console 中
|
||||||
|
2. 点击右上角的用户图标
|
||||||
|
3. 选择 "User Settings"
|
||||||
|
4. 复制 OCID 值
|
||||||
|
|
||||||
|
### 获取 Compartment OCID
|
||||||
|
|
||||||
|
1. 在导航菜单中选择 "Identity & Security" > "Compartments"
|
||||||
|
2. 选择你要使用的 compartment(通常是 root compartment)
|
||||||
|
3. 复制 OCID 值
|
||||||
|
|
||||||
|
## 步骤 3: 创建 API 密钥
|
||||||
|
|
||||||
|
### 生成密钥对
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 创建 .oci 目录
|
||||||
|
mkdir -p ~/.oci
|
||||||
|
|
||||||
|
# 生成私钥
|
||||||
|
openssl genrsa -out ~/.oci/oci_api_key.pem 2048
|
||||||
|
|
||||||
|
# 生成公钥
|
||||||
|
openssl rsa -pubout -in ~/.oci/oci_api_key.pem -out ~/.oci/oci_api_key_public.pem
|
||||||
|
|
||||||
|
# 设置权限
|
||||||
|
chmod 400 ~/.oci/oci_api_key.pem
|
||||||
|
chmod 400 ~/.oci/oci_api_key_public.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
### 添加公钥到 Oracle Cloud
|
||||||
|
|
||||||
|
1. 在 Oracle Cloud Console 中,进入 "User Settings"
|
||||||
|
2. 在左侧菜单中选择 "API Keys"
|
||||||
|
3. 点击 "Add API Key"
|
||||||
|
4. 选择 "Paste Public Key"
|
||||||
|
5. 复制 `~/.oci/oci_api_key_public.pem` 的内容并粘贴
|
||||||
|
6. 点击 "Add"
|
||||||
|
7. 复制显示的 fingerprint
|
||||||
|
|
||||||
|
## 步骤 4: 配置 terraform.tfvars
|
||||||
|
|
||||||
|
编辑 `infrastructure/environments/dev/terraform.tfvars` 文件:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
# Oracle Cloud 配置
|
||||||
|
oci_config = {
|
||||||
|
tenancy_ocid = "ocid1.tenancy.oc1..aaaaaaaa_your_actual_tenancy_id"
|
||||||
|
user_ocid = "ocid1.user.oc1..aaaaaaaa_your_actual_user_id"
|
||||||
|
fingerprint = "aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp"
|
||||||
|
private_key_path = "~/.oci/oci_api_key.pem"
|
||||||
|
region = "ap-seoul-1" # 或你选择的区域
|
||||||
|
compartment_ocid = "ocid1.compartment.oc1..aaaaaaaa_your_compartment_id"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 步骤 5: 验证配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查配置
|
||||||
|
./scripts/setup/setup-opentofu.sh check
|
||||||
|
|
||||||
|
# 初始化 OpenTofu
|
||||||
|
./scripts/setup/setup-opentofu.sh init
|
||||||
|
|
||||||
|
# 生成计划
|
||||||
|
./scripts/setup/setup-opentofu.sh plan
|
||||||
|
```
|
||||||
|
|
||||||
|
## 可用区域
|
||||||
|
|
||||||
|
常用的 Oracle Cloud 区域:
|
||||||
|
|
||||||
|
- `ap-seoul-1` - 韩国首尔
|
||||||
|
- `ap-tokyo-1` - 日本东京
|
||||||
|
- `us-ashburn-1` - 美国弗吉尼亚州
|
||||||
|
- `us-phoenix-1` - 美国亚利桑那州
|
||||||
|
- `eu-frankfurt-1` - 德国法兰克福
|
||||||
|
|
||||||
|
## 免费层资源
|
||||||
|
|
||||||
|
Oracle Cloud 免费层包括:
|
||||||
|
|
||||||
|
- 2 个 AMD 计算实例(VM.Standard.E2.1.Micro)
|
||||||
|
- 4 个 Arm 计算实例(VM.Standard.A1.Flex)
|
||||||
|
- 200 GB 块存储
|
||||||
|
- 10 GB 对象存储
|
||||||
|
- 负载均衡器
|
||||||
|
- 数据库等
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 常见错误
|
||||||
|
|
||||||
|
1. **401 Unauthorized**: 检查 API 密钥配置
|
||||||
|
2. **404 Not Found**: 检查 OCID 是否正确
|
||||||
|
3. **权限错误**: 确保用户有足够的权限
|
||||||
|
|
||||||
|
### 验证连接
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装 OCI CLI(可选)
|
||||||
|
pip install oci-cli
|
||||||
|
|
||||||
|
# 配置 OCI CLI
|
||||||
|
oci setup config
|
||||||
|
|
||||||
|
# 测试连接
|
||||||
|
oci iam compartment list
|
||||||
|
```
|
||||||
|
|
||||||
|
## 安全最佳实践
|
||||||
|
|
||||||
|
1. 定期轮换 API 密钥
|
||||||
|
2. 使用最小权限原则
|
||||||
|
3. 不要在代码中硬编码凭据
|
||||||
|
4. 使用 compartment 隔离资源
|
||||||
|
5. 启用审计日志
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
- [Oracle Cloud Infrastructure 文档](https://docs.oracle.com/en-us/iaas/)
|
||||||
|
- [OCI Terraform Provider](https://registry.terraform.io/providers/oracle/oci/latest/docs)
|
||||||
|
- [Oracle Cloud 免费层](https://www.oracle.com/cloud/free/)
|
||||||
|
|
@ -1,8 +1,30 @@
|
||||||
# 开发环境主配置文件
|
# 开发环境主配置文件
|
||||||
|
|
||||||
# 引用共享配置
|
# 版本和提供商配置
|
||||||
module "shared" {
|
terraform {
|
||||||
source = "../../shared"
|
required_version = ">= 1.6"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
# Oracle Cloud Infrastructure
|
||||||
|
oci = {
|
||||||
|
source = "oracle/oci"
|
||||||
|
version = "~> 5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 后端配置
|
||||||
|
backend "local" {
|
||||||
|
path = "terraform.tfstate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Oracle Cloud 提供商配置
|
||||||
|
provider "oci" {
|
||||||
|
tenancy_ocid = var.oci_config.tenancy_ocid
|
||||||
|
user_ocid = var.oci_config.user_ocid
|
||||||
|
fingerprint = var.oci_config.fingerprint
|
||||||
|
private_key_path = var.oci_config.private_key_path
|
||||||
|
region = var.oci_config.region
|
||||||
}
|
}
|
||||||
|
|
||||||
# Oracle Cloud 基础设施
|
# Oracle Cloud 基础设施
|
||||||
|
|
@ -23,27 +45,8 @@ module "oracle_cloud" {
|
||||||
instance_size = "VM.Standard.E2.1.Micro" # 免费层
|
instance_size = "VM.Standard.E2.1.Micro" # 免费层
|
||||||
}
|
}
|
||||||
|
|
||||||
# 华为云基础设施 (可选)
|
|
||||||
module "huawei_cloud" {
|
|
||||||
source = "../../providers/huawei-cloud"
|
|
||||||
count = contains(var.cloud_providers, "huawei") ? 1 : 0
|
|
||||||
|
|
||||||
environment = var.environment
|
|
||||||
project_name = var.project_name
|
|
||||||
owner = var.owner
|
|
||||||
vpc_cidr = "10.1.0.0/16" # 不同的 CIDR 避免冲突
|
|
||||||
availability_zones = var.availability_zones
|
|
||||||
common_tags = var.common_tags
|
|
||||||
huawei_config = var.huawei_config
|
|
||||||
}
|
|
||||||
|
|
||||||
# 输出
|
# 输出
|
||||||
output "oracle_cloud_outputs" {
|
output "oracle_cloud_outputs" {
|
||||||
description = "Oracle Cloud 基础设施输出"
|
description = "Oracle Cloud 基础设施输出"
|
||||||
value = module.oracle_cloud
|
value = module.oracle_cloud
|
||||||
}
|
|
||||||
|
|
||||||
output "huawei_cloud_outputs" {
|
|
||||||
description = "华为云基础设施输出"
|
|
||||||
value = length(module.huawei_cloud) > 0 ? module.huawei_cloud[0] : null
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
oci usa
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDiDwCO56943GNv
|
||||||
|
rg2WYQCZTpdgA1YfdDcM6AXugzwGm6zQwuhuDdTABwJj0PfB7q5s0MZFqwpVW+MS
|
||||||
|
IkTQsk8r+8gBo9FBtH4nneBfXgqjiKhlHhcgqHWALXm8AzDq6MJ+lCDwjgi5PsID
|
||||||
|
5jbnBUBXRpVXlkEDMZj5yTNiRfLMlFZiqc4mv1j1RSIQeuptt7l2AnXhKSuW2FL3
|
||||||
|
aQNWspUylIs9IDXuC490r04/fZmX0Iw7Crb4yWWFem1e1x0g6qDiAizwpE3FF0No
|
||||||
|
AqkH+p+y3Qe7Pew2/UUS4VNRyoGBstpbBJMQ8dXRER9M4KTEdLnSG2EzdM5IGupj
|
||||||
|
Gwo9PnPPAgMBAAECggEAChaP+HtPvLMJH6NtfnfXEQBi3P6zyd+OfV2gC3mBJO0E
|
||||||
|
P09ovqXmB/5ywDBD05G/6EyWLJG/ek5eycu3CnaKoJ8x2RuNwRg5m7GooQOPXKZC
|
||||||
|
mDtJiO7mSia9YgM6caFFh2SQ5mtQPwQVSxtA+U+mBBRlocJWJbsBj/7HSOwaM8BC
|
||||||
|
wl19kZiW0aOkoGidxvjlJfkPiNer/jTy5RMNKruDpaF8PsF7xIMLwuxT5VQ/gyYA
|
||||||
|
frXsWfQp+sve/XfUg9/RGP9jJQHNppL56YWYPa8XusC2nJCym9RLDlK56jF9jhYM
|
||||||
|
iQThksG3TzOXjdGM7MP5Q/SfNckQWy0KTOu7h+N98QKBgQD9l7SFypX5Mgn2PC1A
|
||||||
|
U3lwiLCvviaKSNbzNXc6pnijbGEEvNpUGRyGwmjXItGLiEoAky0eu42Ipult6PB+
|
||||||
|
WsjCIGTGI0UBObrjbWfaj+vt6zCcI653tgvrQO97t+F6xTHiQyGRDqIlFQcE9ZKO
|
||||||
|
EJ+wuC+MbBFGPSc/Zw43/twpzQKBgQDkNGHiuoGvoSuRPpMIB82IsMmtOlzymk8B
|
||||||
|
ZZMNzHfxFyf7a/1NUhc3UvmZdE67MS4cmoY0LCY4HBW2zxxsnX0cA+vRNLFneJMC
|
||||||
|
oH2XgQs+mi1Dgem+N6EYO/5PJZqeyUJ5x5WFGrULvsL2GKcSeSp2o2nkFyKSHfhD
|
||||||
|
7zWSQyNICwKBgQD1lDZD4n3+BxFSndAMnUnbSuQgLPrRq9xNRpeh+piVWl1R4zlj
|
||||||
|
e7X+YsJ4pMVcZK2VhPGK84IKtekUgSJ0mqIULJ6qqnkmyKtNlyOdqwaFLt+yNXO9
|
||||||
|
hlRgjE/e9aGr7M90GCKngQ5Q7t4PVWmJnlunHZceW4EXDh217qz8WRkIeQKBgGV0
|
||||||
|
JFB4Ok+qh4P7HcLkNSwf7Ilm+QuiLp2gWtA3pts4QD42tFY7uLaP3Qer/ZSbOLTe
|
||||||
|
vetT9WnckorDaQ+gtI5P7/cCRhyKLlFsqGlCpY0fXiA1EYXPlX8ArP7i6OrO7w7U
|
||||||
|
/FRAm1ytYl+mdiBwXcCAxgLxhh0P1d/d6SMtVfIhAoGBALdQ9tPSkFsJiDJi+d1u
|
||||||
|
SwPauzmr8O0geaLuey9WxVAxm5DR7eTJTUswZJGqadAZlnDr/H+7YU6lEBRI224Q
|
||||||
|
0ApgIIeGpMsTZFetRsOq+TUoNQcGVCtspOckCbElW6NMSzuAlf7aI+VqKM3uwlAn
|
||||||
|
FiTDYcmZIE1yNjYi+uaD8vkU
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
OCI_API_KEY
|
||||||
|
|
||||||
|
oci kr
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCXpRaddq1RzS0J
|
||||||
|
cBAGHh94DJyqOBti+ASs6Abv1v3gyXu0ssNSe/g/ZBe+aDIIBisL/5nRLDZfeNZg
|
||||||
|
S5azKgPFPPlukTKVAfatQrgsaCC3uNm4D0NfGSINY90HcpZwX5GCZbUIFZuBZBac
|
||||||
|
33ze+RXoEo/QJFqniiUh/19A1R6mO2oJchgcXYv3+Fe8db35Fb9HDt6tg8+maO5R
|
||||||
|
8W149SpQUlU9JWCWuRV2cdKSXP1/z3JH3bq7hezD5qkZrcwt+4e+Pj9moYyA+O8i
|
||||||
|
n9Z9yQUeipp+HR3SdM++pzUhc1E/NNrgNTKQJi3OvrUx41jc00/5KwZUYyOtvJa3
|
||||||
|
/GBzycKNAgMBAAECggEAFiooGw3cmWc+3PFHNk2y1c4qG+slfZq4vDkRwn6PDwsE
|
||||||
|
DM5QJD9AcquDmO4L2gZkxlUuu1cV/3BfDSYfOcK7WFnoL1QDq6nkz0BAQSVbGt9m
|
||||||
|
2zNH6p92zbQ5+zuxZ21gjEmnYy4dU5U4hOdZjhGkNQ55fLfDlFdpxAVae9RqrWsp
|
||||||
|
8/9SiuD1G+fgNKbe8x+ASd8Y4rP9gjItDUCqmi2rnJJsR8i1PHMZiLC0S3FbcUo6
|
||||||
|
R7kwO0dGaXYFWtPUlMB/OPx172HM6yfE+lDmT6gKfWJ2dOKvu7mOtXTGSBIGMREV
|
||||||
|
MpC9ZhYBsk3jvZKlEju0sEATg3tdDBeX3xRNOkPFFQKBgQDVrmuAOS/Xrz5ZGzwl
|
||||||
|
nRzgtR02EjdQ+wJrfyJoufmJWZQlC6cAe3RyCBs8c7YiSyvTL773ZW/v9RoVln0R
|
||||||
|
WDaEdw7L+YLjdv51Dzy3KVY9A4HX1s+xhP5zG2C24Rp5ALwfS6Qf2JDGtAlm821J
|
||||||
|
z5kwEcY2sSOxGqL8MTA9gysmqwKBgQC1rXBNsW4BVhbqOXMC6ZpwQ/n6BEdHGl8g
|
||||||
|
1nNonznnZ6ECI/G/TBYA5Pb23FslpQAaFaYgg6pY1FisnIVUpjk23xKd193zY7P4
|
||||||
|
8Ah7D/gcAtloXeJ6sknaWjkBBYRRyZhlG3M428kKoIgxQveokGZiLvF4xB9/NBM3
|
||||||
|
oCepbq6bpwKBgQC8KWFEghcdCJYQhSkLvjQls5bLfHL1fnN9EXDNY6bXSehoTsB6
|
||||||
|
bjv2BillrEcgH62xxAOXet19IgocJG5xjYpET0raVxbpEmmzzv0aFO55v9Lgq6os
|
||||||
|
mf4ugldB8ysKjpkZvdQCrwOd1f/JhmYgbwxoBd7TXl0doWUQSog+QnkHDQKBgDMd
|
||||||
|
jDZf0GqR1TqrVT+hiDFD/uYoJAHOWqt7itcJzZnc30Eh6dd/ycUQpqeIEiECTogI
|
||||||
|
RUhqoxgBDr3p/910My7MDonYfXsIN0+4ATrWoGEJMDAcEiehWAQWVGmEKtl0FeuE
|
||||||
|
kKOTuvnBdvAdPl7v2c6QFKJ807vPZATHi8ExAfGLAoGBALuFCz/9Xlw5legmGJxP
|
||||||
|
IgbhcmSFCw9OmGRA6KdRZUN+Zsb6FVj9eCcF1My13iw359xFaYdhBD6hnbPIe3XS
|
||||||
|
bzVMczdiuRAI9LijXhzGWmw5hlkumaVDqZI3+Sy5lohLhOsV4Erss1vqL3R40zjk
|
||||||
|
fk2tnbktORYd6/Q0i0FJdO/H
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
OCI_API_KEY
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 项目管理主脚本
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# 项目根目录
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示项目状态
|
||||||
|
show_status() {
|
||||||
|
log_info "=== 项目状态总览 ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Docker Swarm 状态
|
||||||
|
log_info "Docker Swarm 状态:"
|
||||||
|
if docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
|
||||||
|
log_success "✓ Docker Swarm 已激活"
|
||||||
|
docker node ls 2>/dev/null | head -n 5
|
||||||
|
else
|
||||||
|
log_warning "✗ Docker Swarm 未激活"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# OpenTofu 状态
|
||||||
|
log_info "OpenTofu 状态:"
|
||||||
|
if command -v tofu &> /dev/null; then
|
||||||
|
local version=$(tofu version | head -n1)
|
||||||
|
log_success "✓ OpenTofu 已安装: $version"
|
||||||
|
else
|
||||||
|
log_warning "✗ OpenTofu 未安装"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 部署的堆栈
|
||||||
|
log_info "已部署的 Docker Stack:"
|
||||||
|
if docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
|
||||||
|
docker stack ls 2>/dev/null || log_warning "无堆栈部署"
|
||||||
|
else
|
||||||
|
log_warning "Swarm 未激活,无法查看堆栈"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 快速部署
|
||||||
|
quick_deploy() {
|
||||||
|
log_info "=== 快速部署 ==="
|
||||||
|
|
||||||
|
# 检查 Swarm
|
||||||
|
if ! docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
|
||||||
|
log_info "初始化 Docker Swarm..."
|
||||||
|
"${PROJECT_ROOT}/swarm/scripts/swarm-manager.sh" init
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 部署 Traefik
|
||||||
|
log_info "部署 Traefik 反向代理..."
|
||||||
|
"${PROJECT_ROOT}/swarm/scripts/swarm-manager.sh" deploy traefik "${PROJECT_ROOT}/swarm/stacks/traefik-swarm-stack.yml"
|
||||||
|
|
||||||
|
# 等待 Traefik 启动
|
||||||
|
log_info "等待 Traefik 启动..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# 部署示例服务
|
||||||
|
log_info "部署示例服务..."
|
||||||
|
"${PROJECT_ROOT}/swarm/scripts/swarm-manager.sh" deploy demo "${PROJECT_ROOT}/swarm/stacks/demo-services-stack.yml"
|
||||||
|
|
||||||
|
log_success "快速部署完成!"
|
||||||
|
echo ""
|
||||||
|
log_info "访问地址:"
|
||||||
|
echo " - Traefik Dashboard: http://localhost:8080"
|
||||||
|
echo " - 示例应用: 请查看 demo 堆栈的服务配置"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 清理环境
|
||||||
|
cleanup() {
|
||||||
|
log_info "=== 清理环境 ==="
|
||||||
|
|
||||||
|
# 停止所有堆栈
|
||||||
|
log_info "停止所有 Docker Stack..."
|
||||||
|
docker stack ls --format "{{.Name}}" 2>/dev/null | while read -r stack; do
|
||||||
|
if [[ -n "$stack" ]]; then
|
||||||
|
log_info "删除堆栈: $stack"
|
||||||
|
docker stack rm "$stack"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 等待服务清理
|
||||||
|
log_info "等待服务清理..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
log_success "环境清理完成"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示帮助
|
||||||
|
show_help() {
|
||||||
|
echo "项目管理脚本"
|
||||||
|
echo ""
|
||||||
|
echo "用法: $0 [命令]"
|
||||||
|
echo ""
|
||||||
|
echo "命令:"
|
||||||
|
echo " status - 显示项目状态总览"
|
||||||
|
echo " deploy - 快速部署所有服务"
|
||||||
|
echo " cleanup - 清理所有部署的服务"
|
||||||
|
echo " swarm - 打开 Swarm 管理工具"
|
||||||
|
echo " tofu - 打开 OpenTofu 管理工具"
|
||||||
|
echo " help - 显示此帮助信息"
|
||||||
|
echo ""
|
||||||
|
echo "子工具:"
|
||||||
|
echo " ./swarm/scripts/swarm-manager.sh - Docker Swarm 管理"
|
||||||
|
echo " ./scripts/setup/setup-opentofu.sh - OpenTofu 设置"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
case "${1:-help}" in
|
||||||
|
"status")
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
"deploy")
|
||||||
|
quick_deploy
|
||||||
|
;;
|
||||||
|
"cleanup")
|
||||||
|
cleanup
|
||||||
|
;;
|
||||||
|
"swarm")
|
||||||
|
exec "${PROJECT_ROOT}/swarm/scripts/swarm-manager.sh" "${@:2}"
|
||||||
|
;;
|
||||||
|
"tofu")
|
||||||
|
exec "${PROJECT_ROOT}/scripts/setup/setup-opentofu.sh" "${@:2}"
|
||||||
|
;;
|
||||||
|
"help"|*)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# OpenTofu 设置脚本
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查 OpenTofu 是否已安装
|
||||||
|
check_opentofu() {
|
||||||
|
log_info "检查 OpenTofu 安装状态..."
|
||||||
|
|
||||||
|
if command -v tofu &> /dev/null; then
|
||||||
|
local version=$(tofu version | head -n1)
|
||||||
|
log_success "OpenTofu 已安装: $version"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_error "OpenTofu 未安装"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查配置文件
|
||||||
|
check_config() {
|
||||||
|
log_info "检查配置文件..."
|
||||||
|
|
||||||
|
local config_file="tofu/environments/dev/terraform.tfvars"
|
||||||
|
|
||||||
|
if [[ ! -f "$config_file" ]]; then
|
||||||
|
log_error "配置文件不存在: $config_file"
|
||||||
|
log_info "请复制 terraform.tfvars.example 并填入实际配置"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查是否包含示例值
|
||||||
|
if grep -q "your_tenancy_id_here\|your_user_id_here\|your:key:fingerprint:here" "$config_file"; then
|
||||||
|
log_warning "配置文件包含示例值,请填入实际的 Oracle Cloud 配置"
|
||||||
|
log_info "需要配置以下项目:"
|
||||||
|
echo " - tenancy_ocid: Oracle Cloud 租户 OCID"
|
||||||
|
echo " - user_ocid: 用户 OCID"
|
||||||
|
echo " - fingerprint: API 密钥指纹"
|
||||||
|
echo " - private_key_path: 私钥文件路径"
|
||||||
|
echo " - compartment_ocid: 区间 OCID"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "配置文件检查通过"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 初始化 OpenTofu
|
||||||
|
init_opentofu() {
|
||||||
|
log_info "初始化 OpenTofu..."
|
||||||
|
|
||||||
|
cd tofu/environments/dev
|
||||||
|
|
||||||
|
# 清理旧的状态文件
|
||||||
|
if [[ -d ".terraform" ]]; then
|
||||||
|
log_info "清理旧的 .terraform 目录..."
|
||||||
|
rm -rf .terraform
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 初始化
|
||||||
|
if tofu init; then
|
||||||
|
log_success "OpenTofu 初始化成功"
|
||||||
|
else
|
||||||
|
log_error "OpenTofu 初始化失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd - > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# 验证配置
|
||||||
|
validate_config() {
|
||||||
|
log_info "验证 OpenTofu 配置..."
|
||||||
|
|
||||||
|
cd tofu/environments/dev
|
||||||
|
|
||||||
|
if tofu validate; then
|
||||||
|
log_success "配置验证通过"
|
||||||
|
else
|
||||||
|
log_error "配置验证失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd - > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成计划
|
||||||
|
plan_infrastructure() {
|
||||||
|
log_info "生成基础设施计划..."
|
||||||
|
|
||||||
|
cd tofu/environments/dev
|
||||||
|
|
||||||
|
if tofu plan -var-file="terraform.tfvars" -out=tfplan; then
|
||||||
|
log_success "计划生成成功"
|
||||||
|
log_info "计划文件已保存为 tfplan"
|
||||||
|
else
|
||||||
|
log_error "计划生成失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd - > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示帮助信息
|
||||||
|
show_help() {
|
||||||
|
echo "OpenTofu 设置脚本"
|
||||||
|
echo ""
|
||||||
|
echo "用法: $0 [选项]"
|
||||||
|
echo ""
|
||||||
|
echo "选项:"
|
||||||
|
echo " init - 初始化 OpenTofu"
|
||||||
|
echo " validate - 验证配置"
|
||||||
|
echo " plan - 生成执行计划"
|
||||||
|
echo " check - 检查环境和配置"
|
||||||
|
echo " help - 显示此帮助信息"
|
||||||
|
echo ""
|
||||||
|
echo "示例:"
|
||||||
|
echo " $0 check # 检查环境"
|
||||||
|
echo " $0 init # 初始化项目"
|
||||||
|
echo " $0 plan # 生成计划"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
case "${1:-help}" in
|
||||||
|
"check")
|
||||||
|
check_opentofu
|
||||||
|
check_config
|
||||||
|
;;
|
||||||
|
"init")
|
||||||
|
check_opentofu || exit 1
|
||||||
|
check_config || exit 1
|
||||||
|
init_opentofu
|
||||||
|
;;
|
||||||
|
"validate")
|
||||||
|
validate_config
|
||||||
|
;;
|
||||||
|
"plan")
|
||||||
|
check_opentofu || exit 1
|
||||||
|
check_config || exit 1
|
||||||
|
plan_infrastructure
|
||||||
|
;;
|
||||||
|
"help"|*)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# 运行主函数
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Consul 密钥管理脚本
|
||||||
|
# 用于安全地管理 Oracle Cloud 和其他云服务商的敏感配置
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 配置
|
||||||
|
CONSUL_ADDR="${CONSUL_ADDR:-http://localhost:8500}"
|
||||||
|
CONSUL_TOKEN="${CONSUL_TOKEN:-}"
|
||||||
|
ENVIRONMENT="${ENVIRONMENT:-dev}"
|
||||||
|
|
||||||
|
# 颜色输出
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查 Consul 连接
|
||||||
|
check_consul() {
|
||||||
|
log_info "检查 Consul 连接..."
|
||||||
|
if ! curl -s "${CONSUL_ADDR}/v1/status/leader" > /dev/null; then
|
||||||
|
log_error "无法连接到 Consul: ${CONSUL_ADDR}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Consul 连接正常"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 设置 Oracle Cloud 配置
|
||||||
|
set_oracle_config() {
|
||||||
|
log_info "设置 Oracle Cloud 配置..."
|
||||||
|
|
||||||
|
echo "请输入 Oracle Cloud 配置信息:"
|
||||||
|
|
||||||
|
read -p "租户 OCID: " tenancy_ocid
|
||||||
|
read -p "用户 OCID: " user_ocid
|
||||||
|
read -p "API 密钥指纹: " fingerprint
|
||||||
|
read -p "私钥文件路径: " private_key_path
|
||||||
|
read -p "区间 OCID: " compartment_ocid
|
||||||
|
|
||||||
|
# 验证私钥文件是否存在
|
||||||
|
if [[ ! -f "$private_key_path" ]]; then
|
||||||
|
log_error "私钥文件不存在: $private_key_path"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 读取私钥内容
|
||||||
|
private_key_content=$(cat "$private_key_path")
|
||||||
|
|
||||||
|
# 存储到 Consul
|
||||||
|
local base_path="config/${ENVIRONMENT}/oracle"
|
||||||
|
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/tenancy_ocid" -d "$tenancy_ocid" > /dev/null
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/user_ocid" -d "$user_ocid" > /dev/null
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/fingerprint" -d "$fingerprint" > /dev/null
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/private_key" -d "$private_key_content" > /dev/null
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/compartment_ocid" -d "$compartment_ocid" > /dev/null
|
||||||
|
|
||||||
|
log_success "Oracle Cloud 配置已存储到 Consul"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 获取 Oracle Cloud 配置
|
||||||
|
get_oracle_config() {
|
||||||
|
log_info "从 Consul 获取 Oracle Cloud 配置..."
|
||||||
|
|
||||||
|
local base_path="config/${ENVIRONMENT}/oracle"
|
||||||
|
|
||||||
|
echo "Oracle Cloud 配置:"
|
||||||
|
echo "租户 OCID: $(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/tenancy_ocid?raw" 2>/dev/null || echo "未设置")"
|
||||||
|
echo "用户 OCID: $(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/user_ocid?raw" 2>/dev/null || echo "未设置")"
|
||||||
|
echo "指纹: $(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/fingerprint?raw" 2>/dev/null || echo "未设置")"
|
||||||
|
echo "区间 OCID: $(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/compartment_ocid?raw" 2>/dev/null || echo "未设置")"
|
||||||
|
echo "私钥: $(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/private_key?raw" 2>/dev/null | head -1 || echo "未设置")"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 删除 Oracle Cloud 配置
|
||||||
|
delete_oracle_config() {
|
||||||
|
log_warning "删除 Oracle Cloud 配置..."
|
||||||
|
|
||||||
|
read -p "确定要删除所有 Oracle Cloud 配置吗?(y/N): " confirm
|
||||||
|
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
|
||||||
|
log_info "操作已取消"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local base_path="config/${ENVIRONMENT}/oracle"
|
||||||
|
|
||||||
|
curl -s -X DELETE "${CONSUL_ADDR}/v1/kv/${base_path}?recurse" > /dev/null
|
||||||
|
|
||||||
|
log_success "Oracle Cloud 配置已删除"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成 Terraform 变量文件
|
||||||
|
generate_terraform_vars() {
|
||||||
|
log_info "生成 Terraform 变量文件..."
|
||||||
|
|
||||||
|
local base_path="config/${ENVIRONMENT}/oracle"
|
||||||
|
local output_file="infrastructure/environments/${ENVIRONMENT}/terraform.tfvars.consul"
|
||||||
|
|
||||||
|
# 从 Consul 获取配置
|
||||||
|
local tenancy_ocid=$(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/tenancy_ocid?raw" 2>/dev/null || echo "")
|
||||||
|
local user_ocid=$(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/user_ocid?raw" 2>/dev/null || echo "")
|
||||||
|
local fingerprint=$(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/fingerprint?raw" 2>/dev/null || echo "")
|
||||||
|
local compartment_ocid=$(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/compartment_ocid?raw" 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if [[ -z "$tenancy_ocid" ]]; then
|
||||||
|
log_error "Consul 中没有找到 Oracle Cloud 配置"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 创建临时私钥文件
|
||||||
|
local temp_key_file="/tmp/oci_private_key_${ENVIRONMENT}.pem"
|
||||||
|
curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/private_key?raw" > "$temp_key_file"
|
||||||
|
chmod 600 "$temp_key_file"
|
||||||
|
|
||||||
|
# 生成 Terraform 变量文件
|
||||||
|
cat > "$output_file" << EOF
|
||||||
|
# 从 Consul 生成的 Oracle Cloud 配置
|
||||||
|
# 生成时间: $(date)
|
||||||
|
# 环境: ${ENVIRONMENT}
|
||||||
|
|
||||||
|
oci_config = {
|
||||||
|
tenancy_ocid = "$tenancy_ocid"
|
||||||
|
user_ocid = "$user_ocid"
|
||||||
|
fingerprint = "$fingerprint"
|
||||||
|
private_key_path = "$temp_key_file"
|
||||||
|
region = "ap-seoul-1"
|
||||||
|
compartment_ocid = "$compartment_ocid"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log_success "Terraform 变量文件已生成: $output_file"
|
||||||
|
log_warning "私钥文件位置: $temp_key_file"
|
||||||
|
log_warning "请在使用完毕后删除临时私钥文件"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 清理临时文件
|
||||||
|
cleanup_temp_files() {
|
||||||
|
log_info "清理临时文件..."
|
||||||
|
|
||||||
|
rm -f /tmp/oci_private_key_*.pem
|
||||||
|
rm -f infrastructure/environments/*/terraform.tfvars.consul
|
||||||
|
|
||||||
|
log_success "临时文件已清理"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示帮助信息
|
||||||
|
show_help() {
|
||||||
|
cat << EOF
|
||||||
|
Consul 密钥管理脚本
|
||||||
|
|
||||||
|
用法: $0 [选项]
|
||||||
|
|
||||||
|
选项:
|
||||||
|
set-oracle 设置 Oracle Cloud 配置到 Consul
|
||||||
|
get-oracle 从 Consul 获取 Oracle Cloud 配置
|
||||||
|
delete-oracle 从 Consul 删除 Oracle Cloud 配置
|
||||||
|
generate-vars 从 Consul 生成 Terraform 变量文件
|
||||||
|
cleanup 清理临时文件
|
||||||
|
help 显示此帮助信息
|
||||||
|
|
||||||
|
环境变量:
|
||||||
|
CONSUL_ADDR Consul 地址 (默认: http://localhost:8500)
|
||||||
|
CONSUL_TOKEN Consul ACL Token (可选)
|
||||||
|
ENVIRONMENT 环境名称 (默认: dev)
|
||||||
|
|
||||||
|
示例:
|
||||||
|
# 设置 Oracle Cloud 配置
|
||||||
|
$0 set-oracle
|
||||||
|
|
||||||
|
# 生成 Terraform 变量文件
|
||||||
|
$0 generate-vars
|
||||||
|
|
||||||
|
# 查看配置
|
||||||
|
$0 get-oracle
|
||||||
|
|
||||||
|
# 清理临时文件
|
||||||
|
$0 cleanup
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
case "${1:-help}" in
|
||||||
|
"set-oracle")
|
||||||
|
check_consul
|
||||||
|
set_oracle_config
|
||||||
|
;;
|
||||||
|
"get-oracle")
|
||||||
|
check_consul
|
||||||
|
get_oracle_config
|
||||||
|
;;
|
||||||
|
"delete-oracle")
|
||||||
|
check_consul
|
||||||
|
delete_oracle_config
|
||||||
|
;;
|
||||||
|
"generate-vars")
|
||||||
|
check_consul
|
||||||
|
generate_terraform_vars
|
||||||
|
;;
|
||||||
|
"cleanup")
|
||||||
|
cleanup_temp_files
|
||||||
|
;;
|
||||||
|
"help"|*)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,311 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Terraform Consul Provider 配置脚本
|
||||||
|
# 用于配置 Terraform 从 Consul 读取敏感配置
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ENVIRONMENT="${ENVIRONMENT:-dev}"
|
||||||
|
CONSUL_ADDR="${CONSUL_ADDR:-http://localhost:8500}"
|
||||||
|
|
||||||
|
# 颜色输出
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建 Terraform Consul Provider 配置
|
||||||
|
create_consul_provider() {
|
||||||
|
local tf_dir="infrastructure/environments/${ENVIRONMENT}"
|
||||||
|
|
||||||
|
log_info "创建 Terraform Consul Provider 配置..."
|
||||||
|
|
||||||
|
cat > "${tf_dir}/consul-provider.tf" << 'EOF'
|
||||||
|
# Consul Provider 配置
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
consul = {
|
||||||
|
source = "hashicorp/consul"
|
||||||
|
version = "~> 2.18"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "consul" {
|
||||||
|
address = var.consul_config.address
|
||||||
|
token = lookup(var.consul_config, "token", null)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 从 Consul 读取 Oracle Cloud 配置
|
||||||
|
data "consul_keys" "oracle_config" {
|
||||||
|
key {
|
||||||
|
name = "tenancy_ocid"
|
||||||
|
path = "config/${var.environment}/oracle/tenancy_ocid"
|
||||||
|
}
|
||||||
|
|
||||||
|
key {
|
||||||
|
name = "user_ocid"
|
||||||
|
path = "config/${var.environment}/oracle/user_ocid"
|
||||||
|
}
|
||||||
|
|
||||||
|
key {
|
||||||
|
name = "fingerprint"
|
||||||
|
path = "config/${var.environment}/oracle/fingerprint"
|
||||||
|
}
|
||||||
|
|
||||||
|
key {
|
||||||
|
name = "private_key"
|
||||||
|
path = "config/${var.environment}/oracle/private_key"
|
||||||
|
}
|
||||||
|
|
||||||
|
key {
|
||||||
|
name = "compartment_ocid"
|
||||||
|
path = "config/${var.environment}/oracle/compartment_ocid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建临时私钥文件
|
||||||
|
resource "local_file" "oci_private_key" {
|
||||||
|
content = data.consul_keys.oracle_config.var.private_key
|
||||||
|
filename = "/tmp/oci_private_key_${var.environment}.pem"
|
||||||
|
file_permission = "0600"
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [content]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 本地变量,用于构建完整的 OCI 配置
|
||||||
|
locals {
|
||||||
|
oci_config_from_consul = {
|
||||||
|
tenancy_ocid = data.consul_keys.oracle_config.var.tenancy_ocid
|
||||||
|
user_ocid = data.consul_keys.oracle_config.var.user_ocid
|
||||||
|
fingerprint = data.consul_keys.oracle_config.var.fingerprint
|
||||||
|
private_key_path = local_file.oci_private_key.filename
|
||||||
|
region = var.oci_config.region
|
||||||
|
compartment_ocid = data.consul_keys.oracle_config.var.compartment_ocid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log_success "Consul Provider 配置已创建: ${tf_dir}/consul-provider.tf"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建变量定义文件
|
||||||
|
create_variables() {
|
||||||
|
local tf_dir="infrastructure/environments/${ENVIRONMENT}"
|
||||||
|
|
||||||
|
log_info "更新 Terraform 变量定义..."
|
||||||
|
|
||||||
|
cat > "${tf_dir}/variables.tf" << 'EOF'
|
||||||
|
# 基本变量
|
||||||
|
variable "environment" {
|
||||||
|
description = "环境名称"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_name" {
|
||||||
|
description = "项目名称"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "owner" {
|
||||||
|
description = "项目所有者"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "cloud_providers" {
|
||||||
|
description = "要启用的云服务商"
|
||||||
|
type = list(string)
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "vpc_cidr" {
|
||||||
|
description = "VPC CIDR 块"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "availability_zones" {
|
||||||
|
description = "可用区列表"
|
||||||
|
type = list(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "common_tags" {
|
||||||
|
description = "通用标签"
|
||||||
|
type = map(string)
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Consul 配置
|
||||||
|
variable "consul_config" {
|
||||||
|
description = "Consul 配置"
|
||||||
|
type = object({
|
||||||
|
address = string
|
||||||
|
token = optional(string)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# Oracle Cloud 配置(基本信息)
|
||||||
|
variable "oci_config" {
|
||||||
|
description = "Oracle Cloud 基本配置"
|
||||||
|
type = object({
|
||||||
|
region = string
|
||||||
|
tenancy_ocid = optional(string, "FROM_CONSUL")
|
||||||
|
user_ocid = optional(string, "FROM_CONSUL")
|
||||||
|
fingerprint = optional(string, "FROM_CONSUL")
|
||||||
|
private_key_path = optional(string, "FROM_CONSUL")
|
||||||
|
compartment_ocid = optional(string, "FROM_CONSUL")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# 其他云服务商配置
|
||||||
|
variable "huawei_config" {
|
||||||
|
description = "华为云配置"
|
||||||
|
type = object({
|
||||||
|
access_key = string
|
||||||
|
secret_key = string
|
||||||
|
region = string
|
||||||
|
project_id = string
|
||||||
|
})
|
||||||
|
default = {
|
||||||
|
access_key = ""
|
||||||
|
secret_key = ""
|
||||||
|
region = "cn-north-4"
|
||||||
|
project_id = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "gcp_config" {
|
||||||
|
description = "Google Cloud 配置"
|
||||||
|
type = object({
|
||||||
|
project_id = string
|
||||||
|
region = string
|
||||||
|
zone = string
|
||||||
|
credentials_file = string
|
||||||
|
})
|
||||||
|
default = {
|
||||||
|
project_id = ""
|
||||||
|
region = "asia-northeast3"
|
||||||
|
zone = "asia-northeast3-a"
|
||||||
|
credentials_file = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "aws_config" {
|
||||||
|
description = "AWS 配置"
|
||||||
|
type = object({
|
||||||
|
region = string
|
||||||
|
access_key = string
|
||||||
|
secret_key = string
|
||||||
|
})
|
||||||
|
default = {
|
||||||
|
region = "ap-northeast-2"
|
||||||
|
access_key = ""
|
||||||
|
secret_key = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "do_config" {
|
||||||
|
description = "DigitalOcean 配置"
|
||||||
|
type = object({
|
||||||
|
token = string
|
||||||
|
region = string
|
||||||
|
})
|
||||||
|
default = {
|
||||||
|
token = ""
|
||||||
|
region = "sgp1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log_success "变量定义已更新: ${tf_dir}/variables.tf"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建示例 main.tf
|
||||||
|
create_main_tf() {
|
||||||
|
local tf_dir="infrastructure/environments/${ENVIRONMENT}"
|
||||||
|
|
||||||
|
log_info "创建示例 main.tf..."
|
||||||
|
|
||||||
|
cat > "${tf_dir}/main.tf" << 'EOF'
|
||||||
|
# 主要 Terraform 配置文件
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
oci = {
|
||||||
|
source = "oracle/oci"
|
||||||
|
version = "~> 5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Oracle Cloud Provider
|
||||||
|
provider "oci" {
|
||||||
|
tenancy_ocid = local.oci_config_from_consul.tenancy_ocid
|
||||||
|
user_ocid = local.oci_config_from_consul.user_ocid
|
||||||
|
fingerprint = local.oci_config_from_consul.fingerprint
|
||||||
|
private_key_path = local.oci_config_from_consul.private_key_path
|
||||||
|
region = local.oci_config_from_consul.region
|
||||||
|
}
|
||||||
|
|
||||||
|
# 示例:创建 VCN
|
||||||
|
resource "oci_core_vcn" "main" {
|
||||||
|
count = contains(var.cloud_providers, "oracle") ? 1 : 0
|
||||||
|
compartment_id = local.oci_config_from_consul.compartment_ocid
|
||||||
|
cidr_block = var.vpc_cidr
|
||||||
|
display_name = "${var.project_name}-${var.environment}-vcn"
|
||||||
|
|
||||||
|
freeform_tags = var.common_tags
|
||||||
|
}
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
output "vcn_id" {
|
||||||
|
description = "VCN ID"
|
||||||
|
value = try(oci_core_vcn.main[0].id, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
output "oci_config_source" {
|
||||||
|
description = "OCI 配置来源"
|
||||||
|
value = "consul"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log_success "示例 main.tf 已创建: ${tf_dir}/main.tf"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
case "${1:-help}" in
|
||||||
|
"setup")
|
||||||
|
create_consul_provider
|
||||||
|
create_variables
|
||||||
|
create_main_tf
|
||||||
|
;;
|
||||||
|
"help"|*)
|
||||||
|
cat << EOF
|
||||||
|
Terraform Consul Provider 配置脚本
|
||||||
|
|
||||||
|
用法: $0 [选项]
|
||||||
|
|
||||||
|
选项:
|
||||||
|
setup 创建 Terraform Consul Provider 配置
|
||||||
|
help 显示此帮助信息
|
||||||
|
|
||||||
|
环境变量:
|
||||||
|
ENVIRONMENT 环境名称 (默认: dev)
|
||||||
|
CONSUL_ADDR Consul 地址 (默认: http://localhost:8500)
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 简化版 OpenTofu 密钥上传脚本
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 配置
|
||||||
|
CONSUL_ADDR="${CONSUL_ADDR:-http://master:8500}"
|
||||||
|
ENVIRONMENT="${ENVIRONMENT:-dev}"
|
||||||
|
TFVARS_FILE="tofu/environments/${ENVIRONMENT}/terraform.tfvars"
|
||||||
|
|
||||||
|
# 颜色输出
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||||
|
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# 检查 Consul 连接
|
||||||
|
check_consul() {
|
||||||
|
log_info "检查 Consul 连接..."
|
||||||
|
if ! curl -s "${CONSUL_ADDR}/v1/status/leader" > /dev/null; then
|
||||||
|
log_error "无法连接到 Consul: ${CONSUL_ADDR}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Consul 连接正常"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 上传配置
|
||||||
|
upload_configs() {
|
||||||
|
local uploaded_count=0
|
||||||
|
|
||||||
|
log_info "开始解析并上传配置..."
|
||||||
|
|
||||||
|
# 直接解析 tfvars 文件
|
||||||
|
while IFS= read -r line; do
|
||||||
|
# 跳过注释和空行
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "${line// }" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 匹配变量赋值
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*\"([^\"]*)\"|^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*([^[:space:]#]+) ]]; then
|
||||||
|
local var_name="${BASH_REMATCH[1]:-${BASH_REMATCH[3]}}"
|
||||||
|
local var_value="${BASH_REMATCH[2]:-${BASH_REMATCH[4]}}"
|
||||||
|
|
||||||
|
# 跳过空值
|
||||||
|
if [[ -z "$var_value" || "$var_value" == "null" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 确定配置分类和路径
|
||||||
|
local consul_path=""
|
||||||
|
if [[ "$var_name" =~ ^oci_ ]]; then
|
||||||
|
consul_path="config/${ENVIRONMENT}/oracle/${var_name#oci_}"
|
||||||
|
elif [[ "$var_name" =~ ^huawei_ ]]; then
|
||||||
|
consul_path="config/${ENVIRONMENT}/huawei/${var_name#huawei_}"
|
||||||
|
elif [[ "$var_name" =~ ^aws_ ]]; then
|
||||||
|
consul_path="config/${ENVIRONMENT}/aws/${var_name#aws_}"
|
||||||
|
elif [[ "$var_name" =~ ^do_ ]]; then
|
||||||
|
consul_path="config/${ENVIRONMENT}/digitalocean/${var_name#do_}"
|
||||||
|
elif [[ "$var_name" =~ ^gcp_ ]]; then
|
||||||
|
consul_path="config/${ENVIRONMENT}/gcp/${var_name#gcp_}"
|
||||||
|
else
|
||||||
|
consul_path="config/${ENVIRONMENT}/general/${var_name}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 上传到 Consul
|
||||||
|
if curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${consul_path}" -d "$var_value" > /dev/null; then
|
||||||
|
log_info "上传: ${consul_path}"
|
||||||
|
((uploaded_count++))
|
||||||
|
else
|
||||||
|
log_error "上传失败: ${consul_path}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$TFVARS_FILE"
|
||||||
|
|
||||||
|
log_success "总共上传了 $uploaded_count 个配置项到 Consul"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 列出配置
|
||||||
|
list_configs() {
|
||||||
|
log_info "列出 Consul 中的配置..."
|
||||||
|
|
||||||
|
local keys=$(curl -s "${CONSUL_ADDR}/v1/kv/config/${ENVIRONMENT}/?keys" | jq -r '.[]' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if [[ -z "$keys" ]]; then
|
||||||
|
log_error "没有找到配置"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== 环境 ${ENVIRONMENT} 的配置 ==="
|
||||||
|
echo "$keys" | while read -r key; do
|
||||||
|
local value=$(curl -s "${CONSUL_ADDR}/v1/kv/${key}?raw" 2>/dev/null || echo "无法读取")
|
||||||
|
# 隐藏敏感信息
|
||||||
|
if [[ "$key" =~ (secret|key|token|password|ocid) ]]; then
|
||||||
|
echo "$key: [已隐藏]"
|
||||||
|
else
|
||||||
|
echo "$key: $value"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
if [[ ! -f "$TFVARS_FILE" ]]; then
|
||||||
|
log_error "找不到配置文件: $TFVARS_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_consul
|
||||||
|
|
||||||
|
case "${1:-upload}" in
|
||||||
|
"upload")
|
||||||
|
upload_configs
|
||||||
|
;;
|
||||||
|
"list")
|
||||||
|
list_configs
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "用法: $0 [upload|list]"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,495 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# OpenTofu 密钥上传脚本
|
||||||
|
# 用于将 terraform.tfvars 中的敏感配置批量上传到 Consul
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 配置
|
||||||
|
CONSUL_ADDR="${CONSUL_ADDR:-http://master:8500}"
|
||||||
|
CONSUL_TOKEN="${CONSUL_TOKEN:-}"
|
||||||
|
ENVIRONMENT="${ENVIRONMENT:-dev}"
|
||||||
|
TOFU_DIR="${TOFU_DIR:-tofu/environments/${ENVIRONMENT}}"
|
||||||
|
TFVARS_FILE="${TFVARS_FILE:-${TOFU_DIR}/terraform.tfvars}"
|
||||||
|
|
||||||
|
# 颜色输出
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查依赖
|
||||||
|
check_dependencies() {
|
||||||
|
local deps=("curl" "jq")
|
||||||
|
for dep in "${deps[@]}"; do
|
||||||
|
if ! command -v "$dep" &> /dev/null; then
|
||||||
|
log_error "缺少依赖: $dep"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查 Consul 连接
|
||||||
|
check_consul() {
|
||||||
|
log_info "检查 Consul 连接..."
|
||||||
|
if ! curl -s "${CONSUL_ADDR}/v1/status/leader" > /dev/null; then
|
||||||
|
log_error "无法连接到 Consul: ${CONSUL_ADDR}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Consul 连接正常"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查 tfvars 文件
|
||||||
|
check_tfvars_file() {
|
||||||
|
if [[ ! -f "$TFVARS_FILE" ]]; then
|
||||||
|
log_error "找不到 terraform.tfvars 文件: $TFVARS_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_info "找到配置文件: $TFVARS_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 解析 HCL 配置并转换为 JSON
|
||||||
|
parse_hcl_to_json() {
|
||||||
|
local tfvars_file="$1"
|
||||||
|
local temp_tf_file="/tmp/temp_config.tf"
|
||||||
|
local temp_json_file="/tmp/temp_config.json"
|
||||||
|
|
||||||
|
# 创建临时 .tf 文件,将变量赋值转换为输出
|
||||||
|
log_info "解析 HCL 配置..."
|
||||||
|
|
||||||
|
# 读取 tfvars 文件并转换为 output 格式
|
||||||
|
cat > "$temp_tf_file" << 'EOF'
|
||||||
|
# 临时配置文件,用于解析 tfvars
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 解析每个配置块
|
||||||
|
while IFS= read -r line; do
|
||||||
|
# 跳过注释和空行
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "${line// }" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 提取变量名和值
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*(.+)$ ]]; then
|
||||||
|
local var_name="${BASH_REMATCH[1]}"
|
||||||
|
local var_value="${BASH_REMATCH[2]}"
|
||||||
|
|
||||||
|
echo "output \"$var_name\" {" >> "$temp_tf_file"
|
||||||
|
echo " value = $var_value" >> "$temp_tf_file"
|
||||||
|
echo "}" >> "$temp_tf_file"
|
||||||
|
fi
|
||||||
|
done < "$tfvars_file"
|
||||||
|
|
||||||
|
# 使用 terraform 解析配置
|
||||||
|
if command -v terraform &> /dev/null; then
|
||||||
|
cd "$(dirname "$temp_tf_file")"
|
||||||
|
terraform init -backend=false > /dev/null 2>&1 || true
|
||||||
|
terraform output -json > "$temp_json_file" 2>/dev/null || {
|
||||||
|
log_warning "无法使用 terraform 解析,尝试手动解析..."
|
||||||
|
manual_parse_tfvars "$tfvars_file" "$temp_json_file"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_warning "未找到 terraform,使用手动解析..."
|
||||||
|
manual_parse_tfvars "$tfvars_file" "$temp_json_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$temp_json_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 手动解析 tfvars 文件
|
||||||
|
manual_parse_tfvars() {
|
||||||
|
local tfvars_file="$1"
|
||||||
|
local output_file="$2"
|
||||||
|
|
||||||
|
log_info "手动解析 tfvars 文件..."
|
||||||
|
|
||||||
|
# 创建基础 JSON 结构
|
||||||
|
echo "{" > "$output_file"
|
||||||
|
|
||||||
|
local first_item=true
|
||||||
|
local in_block=false
|
||||||
|
local block_name=""
|
||||||
|
local block_content=""
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
# 跳过注释和空行
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*# ]] || [[ -z "${line// }" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检测配置块开始
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*\{[[:space:]]*$ ]]; then
|
||||||
|
block_name="${BASH_REMATCH[1]}"
|
||||||
|
in_block=true
|
||||||
|
block_content=""
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检测配置块结束
|
||||||
|
if [[ "$in_block" == true && "$line" =~ ^[[:space:]]*\}[[:space:]]*$ ]]; then
|
||||||
|
if [[ "$first_item" == false ]]; then
|
||||||
|
echo "," >> "$output_file"
|
||||||
|
fi
|
||||||
|
echo " \"$block_name\": {" >> "$output_file"
|
||||||
|
echo "$block_content" >> "$output_file"
|
||||||
|
echo " }" >> "$output_file"
|
||||||
|
first_item=false
|
||||||
|
in_block=false
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 处理块内容
|
||||||
|
if [[ "$in_block" == true ]]; then
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*\"([^\"]*)\"|^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*([^[:space:]]+) ]]; then
|
||||||
|
local key="${BASH_REMATCH[1]:-${BASH_REMATCH[3]}}"
|
||||||
|
local value="${BASH_REMATCH[2]:-${BASH_REMATCH[4]}}"
|
||||||
|
|
||||||
|
if [[ -n "$block_content" ]]; then
|
||||||
|
block_content+=","
|
||||||
|
fi
|
||||||
|
block_content+="\n \"$key\": \"$value\""
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 处理简单变量
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*\"([^\"]*)\"|^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*=[[:space:]]*([^[:space:]]+) ]]; then
|
||||||
|
local var_name="${BASH_REMATCH[1]:-${BASH_REMATCH[3]}}"
|
||||||
|
local var_value="${BASH_REMATCH[2]:-${BASH_REMATCH[4]}}"
|
||||||
|
|
||||||
|
if [[ "$first_item" == false ]]; then
|
||||||
|
echo "," >> "$output_file"
|
||||||
|
fi
|
||||||
|
echo " \"$var_name\": \"$var_value\"" >> "$output_file"
|
||||||
|
first_item=false
|
||||||
|
fi
|
||||||
|
done < "$tfvars_file"
|
||||||
|
|
||||||
|
echo "}" >> "$output_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 上传配置到 Consul
|
||||||
|
upload_config_to_consul() {
|
||||||
|
local config_file="$1"
|
||||||
|
local uploaded_count=0
|
||||||
|
|
||||||
|
log_info "开始上传配置到 Consul..."
|
||||||
|
|
||||||
|
# 读取 JSON 配置
|
||||||
|
if [[ ! -f "$config_file" ]]; then
|
||||||
|
log_error "配置文件不存在: $config_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 上传 Oracle Cloud 配置
|
||||||
|
local oci_tenancy=$(jq -r '.oci_tenancy_ocid // empty' "$config_file")
|
||||||
|
local oci_user=$(jq -r '.oci_user_ocid // empty' "$config_file")
|
||||||
|
local oci_fingerprint=$(jq -r '.oci_fingerprint // empty' "$config_file")
|
||||||
|
local oci_private_key_path=$(jq -r '.oci_private_key_path // empty' "$config_file")
|
||||||
|
local oci_compartment=$(jq -r '.oci_compartment_ocid // empty' "$config_file")
|
||||||
|
local oci_region=$(jq -r '.oci_region // empty' "$config_file")
|
||||||
|
|
||||||
|
if [[ -n "$oci_tenancy" && "$oci_tenancy" != "null" && "$oci_tenancy" != "" ]]; then
|
||||||
|
=======
|
||||||
|
# 上传配置到 Consul
|
||||||
|
upload_config_to_consul() {
|
||||||
|
local config_file="$1"
|
||||||
|
local uploaded_count=0
|
||||||
|
|
||||||
|
log_info "开始上传配置到 Consul..."
|
||||||
|
|
||||||
|
# 读取 JSON 配置
|
||||||
|
if [[ ! -f "$config_file" ]]; then
|
||||||
|
log_error "配置文件不存在: $config_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 上传 Oracle Cloud 配置
|
||||||
|
local oci_tenancy=$(jq -r '.oci_tenancy_ocid // empty' "$config_file")
|
||||||
|
local oci_user=$(jq -r '.oci_user_ocid // empty' "$config_file")
|
||||||
|
local oci_fingerprint=$(jq -r '.oci_fingerprint // empty' "$config_file")
|
||||||
|
local oci_private_key_path=$(jq -r '.oci_private_key_path // empty' "$config_file")
|
||||||
|
local oci_compartment=$(jq -r '.oci_compartment_ocid // empty' "$config_file")
|
||||||
|
local oci_region=$(jq -r '.oci_region // empty' "$config_file")
|
||||||
|
|
||||||
|
if [[ -n "$oci_tenancy" && "$oci_tenancy" != "null" && "$oci_tenancy" != "" ]]; then
|
||||||
|
log_info "上传 Oracle Cloud 配置..."
|
||||||
|
local base_path="config/${ENVIRONMENT}/oracle"
|
||||||
|
|
||||||
|
local tenancy_ocid=$(jq -r '.oci_config.tenancy_ocid // empty' "$config_file")
|
||||||
|
local user_ocid=$(jq -r '.oci_config.user_ocid // empty' "$config_file")
|
||||||
|
local fingerprint=$(jq -r '.oci_config.fingerprint // empty' "$config_file")
|
||||||
|
local private_key_path=$(jq -r '.oci_config.private_key_path // empty' "$config_file")
|
||||||
|
local compartment_ocid=$(jq -r '.oci_config.compartment_ocid // empty' "$config_file")
|
||||||
|
local region=$(jq -r '.oci_config.region // "ap-seoul-1"' "$config_file")
|
||||||
|
|
||||||
|
# 上传非空配置
|
||||||
|
[[ -n "$tenancy_ocid" && "$tenancy_ocid" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/tenancy_ocid" -d "$tenancy_ocid" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$user_ocid" && "$user_ocid" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/user_ocid" -d "$user_ocid" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$fingerprint" && "$fingerprint" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/fingerprint" -d "$fingerprint" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$compartment_ocid" && "$compartment_ocid" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/compartment_ocid" -d "$compartment_ocid" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$region" && "$region" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/region" -d "$region" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
|
||||||
|
# 上传私钥文件内容
|
||||||
|
if [[ -n "$private_key_path" && "$private_key_path" != "null" && -f "$private_key_path" ]]; then
|
||||||
|
local private_key_content=$(cat "$private_key_path")
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/private_key" -d "$private_key_content" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Oracle Cloud 配置已上传"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 上传华为云配置
|
||||||
|
if jq -e '.huawei_config' "$config_file" > /dev/null 2>&1; then
|
||||||
|
log_info "上传华为云配置..."
|
||||||
|
local base_path="config/${ENVIRONMENT}/huawei"
|
||||||
|
|
||||||
|
local access_key=$(jq -r '.huawei_config.access_key // empty' "$config_file")
|
||||||
|
local secret_key=$(jq -r '.huawei_config.secret_key // empty' "$config_file")
|
||||||
|
local region=$(jq -r '.huawei_config.region // "cn-north-4"' "$config_file")
|
||||||
|
local project_id=$(jq -r '.huawei_config.project_id // empty' "$config_file")
|
||||||
|
|
||||||
|
[[ -n "$access_key" && "$access_key" != "null" && "$access_key" != "" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/access_key" -d "$access_key" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$secret_key" && "$secret_key" != "null" && "$secret_key" != "" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/secret_key" -d "$secret_key" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$region" && "$region" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/region" -d "$region" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$project_id" && "$project_id" != "null" && "$project_id" != "" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/project_id" -d "$project_id" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success "华为云配置已上传"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 上传 AWS 配置
|
||||||
|
if jq -e '.aws_config' "$config_file" > /dev/null 2>&1; then
|
||||||
|
log_info "上传 AWS 配置..."
|
||||||
|
local base_path="config/${ENVIRONMENT}/aws"
|
||||||
|
|
||||||
|
local access_key=$(jq -r '.aws_config.access_key // empty' "$config_file")
|
||||||
|
local secret_key=$(jq -r '.aws_config.secret_key // empty' "$config_file")
|
||||||
|
local region=$(jq -r '.aws_config.region // "ap-northeast-2"' "$config_file")
|
||||||
|
|
||||||
|
[[ -n "$access_key" && "$access_key" != "null" && "$access_key" != "" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/access_key" -d "$access_key" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$secret_key" && "$secret_key" != "null" && "$secret_key" != "" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/secret_key" -d "$secret_key" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$region" && "$region" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/region" -d "$region" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success "AWS 配置已上传"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 上传 DigitalOcean 配置
|
||||||
|
if jq -e '.do_config' "$config_file" > /dev/null 2>&1; then
|
||||||
|
log_info "上传 DigitalOcean 配置..."
|
||||||
|
local base_path="config/${ENVIRONMENT}/digitalocean"
|
||||||
|
|
||||||
|
local token=$(jq -r '.do_config.token // empty' "$config_file")
|
||||||
|
local region=$(jq -r '.do_config.region // "sgp1"' "$config_file")
|
||||||
|
|
||||||
|
[[ -n "$token" && "$token" != "null" && "$token" != "" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/token" -d "$token" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$region" && "$region" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/region" -d "$region" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success "DigitalOcean 配置已上传"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 上传 Google Cloud 配置
|
||||||
|
if jq -e '.gcp_config' "$config_file" > /dev/null 2>&1; then
|
||||||
|
log_info "上传 Google Cloud 配置..."
|
||||||
|
local base_path="config/${ENVIRONMENT}/gcp"
|
||||||
|
|
||||||
|
local project_id=$(jq -r '.gcp_config.project_id // empty' "$config_file")
|
||||||
|
local region=$(jq -r '.gcp_config.region // "asia-northeast3"' "$config_file")
|
||||||
|
local zone=$(jq -r '.gcp_config.zone // "asia-northeast3-a"' "$config_file")
|
||||||
|
local credentials_file=$(jq -r '.gcp_config.credentials_file // empty' "$config_file")
|
||||||
|
|
||||||
|
[[ -n "$project_id" && "$project_id" != "null" && "$project_id" != "" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/project_id" -d "$project_id" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$region" && "$region" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/region" -d "$region" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
[[ -n "$zone" && "$zone" != "null" ]] && {
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/zone" -d "$zone" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
}
|
||||||
|
|
||||||
|
# 上传凭证文件内容
|
||||||
|
if [[ -n "$credentials_file" && "$credentials_file" != "null" && -f "$credentials_file" ]]; then
|
||||||
|
local credentials_content=$(cat "$credentials_file")
|
||||||
|
curl -s -X PUT "${CONSUL_ADDR}/v1/kv/${base_path}/credentials" -d "$credentials_content" > /dev/null
|
||||||
|
((uploaded_count++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Google Cloud 配置已上传"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "总共上传了 $uploaded_count 个配置项到 Consul"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 列出 Consul 中的配置
|
||||||
|
list_consul_configs() {
|
||||||
|
log_info "列出 Consul 中的配置..."
|
||||||
|
|
||||||
|
local base_path="config/${ENVIRONMENT}"
|
||||||
|
|
||||||
|
echo "=== Consul 中的配置 ==="
|
||||||
|
|
||||||
|
# 获取所有配置键
|
||||||
|
local keys=$(curl -s "${CONSUL_ADDR}/v1/kv/${base_path}/?keys" | jq -r '.[]' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if [[ -z "$keys" ]]; then
|
||||||
|
log_warning "Consul 中没有找到配置"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$keys" | while read -r key; do
|
||||||
|
local value=$(curl -s "${CONSUL_ADDR}/v1/kv/${key}?raw" 2>/dev/null || echo "无法读取")
|
||||||
|
# 隐藏敏感信息
|
||||||
|
if [[ "$key" =~ (secret|key|token|password) ]]; then
|
||||||
|
echo "$key: [已隐藏]"
|
||||||
|
else
|
||||||
|
echo "$key: $value"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 清理 Consul 配置
|
||||||
|
cleanup_consul_configs() {
|
||||||
|
log_warning "清理 Consul 配置..."
|
||||||
|
|
||||||
|
read -p "确定要删除环境 '$ENVIRONMENT' 的所有配置吗?(y/N): " confirm
|
||||||
|
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
|
||||||
|
log_info "操作已取消"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local base_path="config/${ENVIRONMENT}"
|
||||||
|
curl -s -X DELETE "${CONSUL_ADDR}/v1/kv/${base_path}?recurse" > /dev/null
|
||||||
|
|
||||||
|
log_success "环境 '$ENVIRONMENT' 的配置已清理"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示帮助信息
|
||||||
|
show_help() {
|
||||||
|
cat << EOF
|
||||||
|
OpenTofu 密钥上传脚本
|
||||||
|
|
||||||
|
用法: $0 [选项]
|
||||||
|
|
||||||
|
选项:
|
||||||
|
upload 上传 terraform.tfvars 中的配置到 Consul
|
||||||
|
list 列出 Consul 中的配置
|
||||||
|
cleanup 清理 Consul 中的配置
|
||||||
|
help 显示此帮助信息
|
||||||
|
|
||||||
|
环境变量:
|
||||||
|
CONSUL_ADDR Consul 地址 (默认: http://localhost:8500)
|
||||||
|
CONSUL_TOKEN Consul ACL Token (可选)
|
||||||
|
ENVIRONMENT 环境名称 (默认: dev)
|
||||||
|
TOFU_DIR OpenTofu 目录 (默认: tofu/environments/\${ENVIRONMENT})
|
||||||
|
TFVARS_FILE 变量文件路径 (默认: \${TOFU_DIR}/terraform.tfvars)
|
||||||
|
|
||||||
|
示例:
|
||||||
|
# 上传配置到 Consul
|
||||||
|
$0 upload
|
||||||
|
|
||||||
|
# 列出 Consul 中的配置
|
||||||
|
$0 list
|
||||||
|
|
||||||
|
# 清理配置
|
||||||
|
$0 cleanup
|
||||||
|
|
||||||
|
# 指定不同环境
|
||||||
|
ENVIRONMENT=production $0 upload
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
check_dependencies
|
||||||
|
|
||||||
|
case "${1:-help}" in
|
||||||
|
"upload")
|
||||||
|
check_consul
|
||||||
|
check_tfvars_file
|
||||||
|
|
||||||
|
log_info "解析配置文件: $TFVARS_FILE"
|
||||||
|
local config_json=$(manual_parse_tfvars "$TFVARS_FILE" "/tmp/parsed_config.json")
|
||||||
|
upload_config_to_consul "/tmp/parsed_config.json"
|
||||||
|
|
||||||
|
# 清理临时文件
|
||||||
|
rm -f /tmp/parsed_config.json /tmp/temp_config.tf
|
||||||
|
;;
|
||||||
|
"list")
|
||||||
|
check_consul
|
||||||
|
list_consul_configs
|
||||||
|
;;
|
||||||
|
"cleanup")
|
||||||
|
check_consul
|
||||||
|
cleanup_consul_configs
|
||||||
|
;;
|
||||||
|
"help"|*)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Docker Swarm 管理脚本
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查是否在 Swarm 模式
|
||||||
|
check_swarm_mode() {
|
||||||
|
if docker info --format '{{.Swarm.LocalNodeState}}' | grep -q "active"; then
|
||||||
|
log_success "Docker Swarm 模式已激活"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_error "Docker Swarm 模式未激活"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 初始化 Swarm
|
||||||
|
init_swarm() {
|
||||||
|
log_info "初始化 Docker Swarm..."
|
||||||
|
|
||||||
|
if docker swarm init; then
|
||||||
|
log_success "Docker Swarm 初始化成功"
|
||||||
|
log_info "要添加工作节点,请在其他主机上运行:"
|
||||||
|
docker swarm join-token worker
|
||||||
|
else
|
||||||
|
log_error "Docker Swarm 初始化失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 部署堆栈
|
||||||
|
deploy_stack() {
|
||||||
|
local stack_name="$1"
|
||||||
|
local compose_file="$2"
|
||||||
|
|
||||||
|
log_info "部署堆栈: $stack_name"
|
||||||
|
|
||||||
|
if [[ ! -f "$compose_file" ]]; then
|
||||||
|
log_error "Compose 文件不存在: $compose_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker stack deploy -c "$compose_file" "$stack_name"; then
|
||||||
|
log_success "堆栈 $stack_name 部署成功"
|
||||||
|
else
|
||||||
|
log_error "堆栈 $stack_name 部署失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 列出堆栈
|
||||||
|
list_stacks() {
|
||||||
|
log_info "当前部署的堆栈:"
|
||||||
|
docker stack ls
|
||||||
|
}
|
||||||
|
|
||||||
|
# 查看堆栈服务
|
||||||
|
show_stack_services() {
|
||||||
|
local stack_name="$1"
|
||||||
|
|
||||||
|
log_info "堆栈 $stack_name 的服务:"
|
||||||
|
docker stack services "$stack_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 删除堆栈
|
||||||
|
remove_stack() {
|
||||||
|
local stack_name="$1"
|
||||||
|
|
||||||
|
log_info "删除堆栈: $stack_name"
|
||||||
|
|
||||||
|
if docker stack rm "$stack_name"; then
|
||||||
|
log_success "堆栈 $stack_name 删除成功"
|
||||||
|
else
|
||||||
|
log_error "堆栈 $stack_name 删除失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示节点信息
|
||||||
|
show_nodes() {
|
||||||
|
log_info "Swarm 节点信息:"
|
||||||
|
docker node ls
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示帮助信息
|
||||||
|
show_help() {
|
||||||
|
echo "Docker Swarm 管理脚本"
|
||||||
|
echo ""
|
||||||
|
echo "用法: $0 [命令] [参数]"
|
||||||
|
echo ""
|
||||||
|
echo "命令:"
|
||||||
|
echo " init - 初始化 Docker Swarm"
|
||||||
|
echo " deploy <stack> <compose-file> - 部署堆栈"
|
||||||
|
echo " list - 列出所有堆栈"
|
||||||
|
echo " services <stack> - 查看堆栈服务"
|
||||||
|
echo " remove <stack> - 删除堆栈"
|
||||||
|
echo " nodes - 显示节点信息"
|
||||||
|
echo " check - 检查 Swarm 状态"
|
||||||
|
echo " help - 显示此帮助信息"
|
||||||
|
echo ""
|
||||||
|
echo "示例:"
|
||||||
|
echo " $0 init # 初始化 Swarm"
|
||||||
|
echo " $0 deploy traefik stacks/traefik-swarm-stack.yml"
|
||||||
|
echo " $0 deploy demo stacks/demo-services-stack.yml"
|
||||||
|
echo " $0 list # 列出堆栈"
|
||||||
|
echo " $0 services traefik # 查看 traefik 堆栈服务"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
case "${1:-help}" in
|
||||||
|
"init")
|
||||||
|
init_swarm
|
||||||
|
;;
|
||||||
|
"deploy")
|
||||||
|
if [[ $# -lt 3 ]]; then
|
||||||
|
log_error "部署命令需要堆栈名称和 compose 文件"
|
||||||
|
echo "用法: $0 deploy <stack-name> <compose-file>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
check_swarm_mode || exit 1
|
||||||
|
deploy_stack "$2" "$3"
|
||||||
|
;;
|
||||||
|
"list")
|
||||||
|
check_swarm_mode || exit 1
|
||||||
|
list_stacks
|
||||||
|
;;
|
||||||
|
"services")
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
log_error "需要指定堆栈名称"
|
||||||
|
echo "用法: $0 services <stack-name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
check_swarm_mode || exit 1
|
||||||
|
show_stack_services "$2"
|
||||||
|
;;
|
||||||
|
"remove")
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
log_error "需要指定堆栈名称"
|
||||||
|
echo "用法: $0 remove <stack-name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
check_swarm_mode || exit 1
|
||||||
|
remove_stack "$2"
|
||||||
|
;;
|
||||||
|
"nodes")
|
||||||
|
check_swarm_mode || exit 1
|
||||||
|
show_nodes
|
||||||
|
;;
|
||||||
|
"check")
|
||||||
|
check_swarm_mode
|
||||||
|
;;
|
||||||
|
"help"|*)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# 运行主函数
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
consul:
|
||||||
|
image: consul:latest
|
||||||
|
hostname: consul-ash3c
|
||||||
|
command: >
|
||||||
|
sh -c "
|
||||||
|
IP=$$(hostname -i | awk '{print $$1}');
|
||||||
|
consul agent -server -bootstrap-expect=2
|
||||||
|
-datacenter=dc1 -data-dir=/consul/data
|
||||||
|
-node=consul-ash3c -bind=$$IP -advertise=100.116.80.94 -client=0.0.0.0
|
||||||
|
-retry-join=100.117.106.136
|
||||||
|
-ui
|
||||||
|
-log-level=INFO
|
||||||
|
"
|
||||||
|
ports:
|
||||||
|
- "8500:8500"
|
||||||
|
- "8600:8600/udp"
|
||||||
|
volumes:
|
||||||
|
- consul_data:/consul/data
|
||||||
|
networks:
|
||||||
|
- consul-net
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.hostname == ash3c
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 5s
|
||||||
|
max_attempts: 3
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
consul_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
consul-net:
|
||||||
|
driver: overlay
|
||||||
|
attachable: true
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
consul-master:
|
||||||
|
image: consul:latest
|
||||||
|
hostname: consul-master
|
||||||
|
command: >
|
||||||
|
sh -c "
|
||||||
|
IP=$$(hostname -i | awk '{print $$1}');
|
||||||
|
consul agent -server -bootstrap-expect=2
|
||||||
|
-datacenter=dc1 -data-dir=/consul/data
|
||||||
|
-node=consul-master -bind=$$IP -advertise=$$IP -client=0.0.0.0
|
||||||
|
-ui
|
||||||
|
-log-level=INFO
|
||||||
|
"
|
||||||
|
ports:
|
||||||
|
- "8500:8500"
|
||||||
|
- "8600:8600/udp"
|
||||||
|
volumes:
|
||||||
|
- consul_master_data:/consul/data
|
||||||
|
networks:
|
||||||
|
consul-net:
|
||||||
|
aliases:
|
||||||
|
- consul-master
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.hostname == master
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 5s
|
||||||
|
max_attempts: 3
|
||||||
|
|
||||||
|
consul-ash3c:
|
||||||
|
image: consul:latest
|
||||||
|
hostname: consul-ash3c
|
||||||
|
command: >
|
||||||
|
sh -c "
|
||||||
|
IP=$$(hostname -i | awk '{print $$1}');
|
||||||
|
consul agent -server -bootstrap-expect=2
|
||||||
|
-datacenter=dc1 -data-dir=/consul/data
|
||||||
|
-node=consul-ash3c -bind=$$IP -advertise=$$IP -client=0.0.0.0
|
||||||
|
-retry-join=consul-cluster_consul-master
|
||||||
|
-ui
|
||||||
|
-log-level=INFO
|
||||||
|
"
|
||||||
|
ports:
|
||||||
|
- "8501:8500"
|
||||||
|
- "8601:8600/udp"
|
||||||
|
volumes:
|
||||||
|
- consul_ash3c_data:/consul/data
|
||||||
|
networks:
|
||||||
|
consul-net:
|
||||||
|
aliases:
|
||||||
|
- consul-ash3c
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.hostname == ash3c
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 5s
|
||||||
|
max_attempts: 3
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
consul_master_data:
|
||||||
|
consul_ash3c_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
consul-net:
|
||||||
|
driver: overlay
|
||||||
|
attachable: true
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
consul:
|
||||||
|
image: consul:latest
|
||||||
|
hostname: consul-master
|
||||||
|
command: >
|
||||||
|
sh -c "
|
||||||
|
IP=$$(hostname -i | awk '{print $$1}');
|
||||||
|
consul agent -server -bootstrap-expect=2
|
||||||
|
-datacenter=dc1 -data-dir=/consul/data
|
||||||
|
-node=consul-master -bind=$$IP -advertise=100.117.106.136 -client=0.0.0.0
|
||||||
|
-ui
|
||||||
|
-log-level=INFO
|
||||||
|
"
|
||||||
|
ports:
|
||||||
|
- "8500:8500"
|
||||||
|
- "8600:8600/udp"
|
||||||
|
volumes:
|
||||||
|
- consul_data:/consul/data
|
||||||
|
networks:
|
||||||
|
- consul-net
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.hostname == master
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 5s
|
||||||
|
max_attempts: 3
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
consul_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
consul-net:
|
||||||
|
driver: overlay
|
||||||
|
attachable: true
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
consul:
|
||||||
|
image: consul:latest
|
||||||
|
hostname: consul
|
||||||
|
command: >
|
||||||
|
consul agent -server -bootstrap-expect=1
|
||||||
|
-datacenter=dc1 -data-dir=/consul/data
|
||||||
|
-node=consul -client=0.0.0.0
|
||||||
|
-ui
|
||||||
|
-log-level=INFO
|
||||||
|
ports:
|
||||||
|
- "8500:8500"
|
||||||
|
- "8600:8600/udp"
|
||||||
|
volumes:
|
||||||
|
- consul_data:/consul/data
|
||||||
|
networks:
|
||||||
|
- consul-net
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
delay: 5s
|
||||||
|
max_attempts: 3
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.consul.rule=Host(`consul.local`)"
|
||||||
|
- "traefik.http.services.consul.loadbalancer.server.port=8500"
|
||||||
|
- "traefik.docker.network=consul-net"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
consul_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
consul-net:
|
||||||
|
driver: overlay
|
||||||
|
attachable: true
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
# 开发环境主配置文件
|
||||||
|
|
||||||
|
# 引入共享版本配置
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 1.6"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
# Oracle Cloud Infrastructure
|
||||||
|
oci = {
|
||||||
|
source = "oracle/oci"
|
||||||
|
version = "~> 5.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 华为云
|
||||||
|
huaweicloud = {
|
||||||
|
source = "huaweicloud/huaweicloud"
|
||||||
|
version = "~> 1.60"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 其他常用提供商
|
||||||
|
random = {
|
||||||
|
source = "hashicorp/random"
|
||||||
|
version = "~> 3.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
tls = {
|
||||||
|
source = "hashicorp/tls"
|
||||||
|
version = "~> 4.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
local = {
|
||||||
|
source = "hashicorp/local"
|
||||||
|
version = "~> 2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 后端配置
|
||||||
|
backend "local" {
|
||||||
|
path = "terraform.tfstate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Oracle Cloud 提供商配置
|
||||||
|
provider "oci" {
|
||||||
|
tenancy_ocid = var.oci_config.tenancy_ocid
|
||||||
|
user_ocid = var.oci_config.user_ocid
|
||||||
|
fingerprint = var.oci_config.fingerprint
|
||||||
|
private_key_path = var.oci_config.private_key_path
|
||||||
|
region = var.oci_config.region
|
||||||
|
}
|
||||||
|
|
||||||
|
# 华为云提供商配置 (仅在需要时配置)
|
||||||
|
provider "huaweicloud" {
|
||||||
|
access_key = var.huawei_config.access_key
|
||||||
|
secret_key = var.huawei_config.secret_key
|
||||||
|
region = var.huawei_config.region
|
||||||
|
alias = "huawei"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Oracle Cloud 基础设施
|
||||||
|
module "oracle_cloud" {
|
||||||
|
source = "../../providers/oracle-cloud"
|
||||||
|
|
||||||
|
# 传递变量
|
||||||
|
environment = var.environment
|
||||||
|
project_name = var.project_name
|
||||||
|
owner = var.owner
|
||||||
|
vpc_cidr = var.vpc_cidr
|
||||||
|
availability_zones = var.availability_zones
|
||||||
|
common_tags = var.common_tags
|
||||||
|
oci_config = var.oci_config
|
||||||
|
|
||||||
|
# 开发环境特定配置
|
||||||
|
instance_count = 1
|
||||||
|
instance_size = "VM.Standard.E2.1.Micro" # 免费层
|
||||||
|
|
||||||
|
providers = {
|
||||||
|
oci = oci
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 华为云基础设施 (可选)
|
||||||
|
module "huawei_cloud" {
|
||||||
|
source = "../../providers/huawei-cloud"
|
||||||
|
count = contains(var.cloud_providers, "huawei") ? 1 : 0
|
||||||
|
|
||||||
|
environment = var.environment
|
||||||
|
project_name = var.project_name
|
||||||
|
owner = var.owner
|
||||||
|
vpc_cidr = "10.1.0.0/16" # 不同的 CIDR 避免冲突
|
||||||
|
availability_zones = var.availability_zones
|
||||||
|
common_tags = var.common_tags
|
||||||
|
huawei_config = var.huawei_config
|
||||||
|
|
||||||
|
providers = {
|
||||||
|
huaweicloud = huaweicloud.huawei
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
output "oracle_cloud_outputs" {
|
||||||
|
description = "Oracle Cloud 基础设施输出"
|
||||||
|
value = module.oracle_cloud
|
||||||
|
}
|
||||||
|
|
||||||
|
output "huawei_cloud_outputs" {
|
||||||
|
description = "华为云基础设施输出"
|
||||||
|
value = length(module.huawei_cloud) > 0 ? module.huawei_cloud[0] : null
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# 华为云提供商配置
|
# 华为云模块
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_providers {
|
required_providers {
|
||||||
|
|
@ -9,13 +9,6 @@ terraform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 华为云提供商配置
|
|
||||||
provider "huaweicloud" {
|
|
||||||
access_key = var.huawei_config.access_key
|
|
||||||
secret_key = var.huawei_config.secret_key
|
|
||||||
region = var.huawei_config.region
|
|
||||||
}
|
|
||||||
|
|
||||||
# 获取可用区
|
# 获取可用区
|
||||||
data "huaweicloud_availability_zones" "zones" {}
|
data "huaweicloud_availability_zones" "zones" {}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
# 华为云提供商变量定义
|
||||||
|
|
||||||
|
variable "environment" {
|
||||||
|
description = "环境名称"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_name" {
|
||||||
|
description = "项目名称"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "owner" {
|
||||||
|
description = "项目所有者"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "vpc_cidr" {
|
||||||
|
description = "VPC CIDR 块"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "availability_zones" {
|
||||||
|
description = "可用区列表"
|
||||||
|
type = list(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "common_tags" {
|
||||||
|
description = "通用标签"
|
||||||
|
type = map(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "huawei_config" {
|
||||||
|
description = "华为云配置"
|
||||||
|
type = object({
|
||||||
|
access_key = string
|
||||||
|
secret_key = string
|
||||||
|
region = string
|
||||||
|
project_id = string
|
||||||
|
})
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_count" {
|
||||||
|
description = "实例数量"
|
||||||
|
type = number
|
||||||
|
default = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_size" {
|
||||||
|
description = "实例规格"
|
||||||
|
type = string
|
||||||
|
default = "s6.small.1"
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Oracle Cloud Infrastructure 提供商配置
|
# Oracle Cloud Infrastructure 模块
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_providers {
|
required_providers {
|
||||||
|
|
@ -9,15 +9,6 @@ terraform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# OCI 提供商配置
|
|
||||||
provider "oci" {
|
|
||||||
tenancy_ocid = var.oci_config.tenancy_ocid
|
|
||||||
user_ocid = var.oci_config.user_ocid
|
|
||||||
fingerprint = var.oci_config.fingerprint
|
|
||||||
private_key_path = var.oci_config.private_key_path
|
|
||||||
region = var.oci_config.region
|
|
||||||
}
|
|
||||||
|
|
||||||
# 获取可用域
|
# 获取可用域
|
||||||
data "oci_identity_availability_domains" "ads" {
|
data "oci_identity_availability_domains" "ads" {
|
||||||
compartment_id = var.oci_config.tenancy_ocid
|
compartment_id = var.oci_config.tenancy_ocid
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Oracle Cloud 提供商变量定义
|
||||||
|
|
||||||
|
variable "environment" {
|
||||||
|
description = "环境名称"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_name" {
|
||||||
|
description = "项目名称"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "owner" {
|
||||||
|
description = "项目所有者"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "vpc_cidr" {
|
||||||
|
description = "VPC CIDR 块"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "availability_zones" {
|
||||||
|
description = "可用区列表"
|
||||||
|
type = list(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "common_tags" {
|
||||||
|
description = "通用标签"
|
||||||
|
type = map(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "oci_config" {
|
||||||
|
description = "Oracle Cloud 配置"
|
||||||
|
type = object({
|
||||||
|
tenancy_ocid = string
|
||||||
|
user_ocid = string
|
||||||
|
fingerprint = string
|
||||||
|
private_key_path = string
|
||||||
|
region = string
|
||||||
|
compartment_ocid = string
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_count" {
|
||||||
|
description = "实例数量"
|
||||||
|
type = number
|
||||||
|
default = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_size" {
|
||||||
|
description = "实例规格"
|
||||||
|
type = string
|
||||||
|
default = "VM.Standard.E2.1.Micro"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue