From 69bb3d3dada19a2e8e8c115d07ecfddb8516d63b Mon Sep 17 00:00:00 2001 From: cloudneutral Date: Sun, 14 Dec 2025 14:57:27 +0800 Subject: [PATCH] Make optional S3FS config opt-in --- .../roles/vhosts/common/defaults/main.yml | 84 +++++++------------ .../vhosts/common/tasks/configure_s3fs.yml | 73 +++++++++------- playbooks/roles/vhosts/common/tasks/main.yml | 31 ++++++- .../roles/vhosts/common/tasks/packages.yml | 29 +++++-- .../roles/vhosts/common/tasks/repo_setup.yml | 47 +++++++---- 5 files changed, 153 insertions(+), 111 deletions(-) diff --git a/playbooks/roles/vhosts/common/defaults/main.yml b/playbooks/roles/vhosts/common/defaults/main.yml index bddd51d..23006e7 100644 --- a/playbooks/roles/vhosts/common/defaults/main.yml +++ b/playbooks/roles/vhosts/common/defaults/main.yml @@ -18,60 +18,36 @@ journald_log_rotation: # 启用 journald 日志管理 # 总开关 enable_common: true -# 子开关 -repo_setup: false # 是否配置仓库/keys -enable_universe: false # Ubuntu 是否启用 universe 仓库 -install_packages: true # 是否安装软件包 -auto_update_cache: true # 是否在 repo_setup 后自动 apt update -# keyring 目录 -apt_key_dir: /etc/apt/keyrings +repo: + apt: + enabled: false # 是否配置仓库/keys + enable_universe: false # Ubuntu 是否启用 universe 仓库 + auto_update_cache: true # 是否在 repo_setup 后自动 apt update + key_dir: /etc/apt/keyrings # keyring 目录 + keyrings: [] # 自定义 keyring 定义(由调用方传入) + legacy_paths: # 清理的遗留路径 + - /etc/apt/sources.list.d/hashicorp.sources + - /usr/share/keyrings/hashicorp-archive-keyring.gpg + entries: [] # 声明式仓库定义 + yum: + enabled: false # 预留 RPM 系列配置 + entries: [] + cleanup_paths: [] -# 自定义 keyring 定义(由调用方传入) -apt_keyrings: [] - -# 清理的遗留路径 -apt_repo_legacy: - - /etc/apt/sources.list.d/hashicorp.sources - - /usr/share/keyrings/hashicorp-archive-keyring.gpg - -# 要安装的软件包 packages: - - auditd - - uidmap - - fuse-overlayfs - -# S3FS 挂载配置(可选) -s3fs_enable: false -s3fs_config: - bucket: "" # S3 存储桶名称 - mount_point: "" # 挂载点路径,例如:/data/update-server/ - access_key: "" # AWS Access Key ID - secret_key: "" # AWS Secret Access Key - url: "https://s3.amazonaws.com" # S3 端点 URL - region: "us-east-1" # S3 区域 - passwd_file: "~/.passwd-s3fs" # 密码文件路径 - use_path_request_style: true # 是否使用路径请求样式 - allow_other: true # 是否允许其他用户访问 - nonempty: false # 是否允许挂载到非空目录 - - - #config_temp: - # k8s-node: - # dns_servers: - # - "8.8.8.8" - # - "114.114.114.114" - # swap_off: true - # ip_forward: true - # disk: - # - name: /dev/sdb1 - # mount: /mnt - # - name: /var/lib/containerd - # mount: /mnt/lib/containerd - # type: bind - # - name: /var/log/deepflow - # mount: /mnt/log/deepflow - # type: bind - # selinux_enable: false - # ssh_auth: - # key: /root/.ssh/id_rsa.pub + apt: + enabled: true # 是否安装软件包 + base_dependencies: # APT 前置依赖(避免未规范化源时更新) + - ca-certificates + - gnupg + list: # 要安装的软件包 + - auditd + - uidmap + - fuse-overlayfs + yum: + enabled: true + list: + - audit + - uidmap + - fuse-overlayfs diff --git a/playbooks/roles/vhosts/common/tasks/configure_s3fs.yml b/playbooks/roles/vhosts/common/tasks/configure_s3fs.yml index 7655ec9..5861689 100644 --- a/playbooks/roles/vhosts/common/tasks/configure_s3fs.yml +++ b/playbooks/roles/vhosts/common/tasks/configure_s3fs.yml @@ -1,85 +1,98 @@ --- +- name: "S3FS | 合并默认配置" + ansible.builtin.set_fact: + normalized_s3fs_config: "{{ { + 'bucket': '', + 'mount_point': '', + 'access_key': '', + 'secret_key': '', + 'url': 'https://s3.amazonaws.com', + 'region': 'us-east-1', + 'passwd_file': '~/.passwd-s3fs', + 'use_path_request_style': true, + 'allow_other': true, + 'nonempty': false + } | combine(s3fs_config | default({}), recursive=True) }}" + - name: "S3FS | 检查 s3fs 配置" - fail: + ansible.builtin.fail: msg: "S3FS 需要配置 s3fs_config.bucket 和 s3fs_config.mount_point" when: - - s3fs_config.bucket | length == 0 - - s3fs_config.mount_point | length == 0 + - normalized_s3fs_config.bucket | length == 0 or normalized_s3fs_config.mount_point | length == 0 - name: "S3FS | 检查 AWS 凭证" - fail: + ansible.builtin.fail: msg: "S3FS 需要配置 s3fs_config.access_key 和 s3fs_config.secret_key" when: - - s3fs_config.access_key | length == 0 - - s3fs_config.secret_key | length == 0 + - normalized_s3fs_config.access_key | length == 0 or normalized_s3fs_config.secret_key | length == 0 - name: "S3FS | 安装 s3fs 软件包" - apt: + ansible.builtin.apt: name: s3fs state: present - become: yes + become: true when: ansible_facts.os_family == 'Debian' - name: "S3FS | 安装 s3fs 软件包 (CentOS/RHEL)" - yum: + ansible.builtin.yum: name: s3fs-fuse state: present - become: yes + become: true when: ansible_facts.os_family == 'RedHat' - name: "S3FS | 创建密码文件" - copy: - content: "{{ s3fs_config.access_key }}:{{ s3fs_config.secret_key }}" - dest: "{{ s3fs_config.passwd_file | expanduser }}" + ansible.builtin.copy: + content: "{{ normalized_s3fs_config.access_key }}:{{ normalized_s3fs_config.secret_key }}" + dest: "{{ normalized_s3fs_config.passwd_file | expanduser }}" mode: '0600' owner: root group: root - when: s3fs_config.access_key | length > 0 and s3fs_config.secret_key | length > 0 + when: normalized_s3fs_config.access_key | length > 0 and normalized_s3fs_config.secret_key | length > 0 - name: "S3FS | 创建挂载点目录" - file: - path: "{{ s3fs_config.mount_point }}" + ansible.builtin.file: + path: "{{ normalized_s3fs_config.mount_point }}" state: directory mode: '0755' owner: root group: root - name: "S3FS | 检查是否已挂载" - shell: "mount | grep -q '{{ s3fs_config.mount_point }}' && echo 'mounted' || echo 'not mounted'" + ansible.builtin.shell: "mount | grep -q '{{ normalized_s3fs_config.mount_point }}' && echo 'mounted' || echo 'not mounted'" register: s3fs_mount_check changed_when: false failed_when: false - name: "S3FS | 挂载 S3 存储桶" - command: > - s3fs {{ s3fs_config.bucket }} {{ s3fs_config.mount_point }} - -o passwd_file={{ s3fs_config.passwd_file | expanduser }} - {% if s3fs_config.allow_other %}-o allow_other{% endif %} - -o url={{ s3fs_config.url }} - {% if s3fs_config.use_path_request_style %}-o use_path_request_style{% endif %} + ansible.builtin.command: > + s3fs {{ normalized_s3fs_config.bucket }} {{ normalized_s3fs_config.mount_point }} + -o passwd_file={{ normalized_s3fs_config.passwd_file | expanduser }} + {% if normalized_s3fs_config.allow_other %}-o allow_other{% endif %} + -o url={{ normalized_s3fs_config.url }} + {% if normalized_s3fs_config.use_path_request_style %}-o use_path_request_style{% endif %} args: - creates: "{{ s3fs_config.mount_point }}/.s3fs_configured" + creates: "{{ normalized_s3fs_config.mount_point }}/.s3fs_configured" when: s3fs_mount_check.stdout == 'not mounted' - name: "S3FS | 创建挂载标记文件" - copy: + ansible.builtin.copy: content: "S3FS mounted at {{ ansible_date_time.iso8601 }}" - dest: "{{ s3fs_config.mount_point }}/.s3fs_configured" + dest: "{{ normalized_s3fs_config.mount_point }}/.s3fs_configured" mode: '0644' owner: root group: root when: s3fs_mount_check.stdout == 'not mounted' - name: "S3FS | 验证挂载" - shell: "mount | grep '{{ s3fs_config.mount_point }}'" + ansible.builtin.shell: "mount | grep '{{ normalized_s3fs_config.mount_point }}'" register: s3fs_verify_mount changed_when: false failed_when: true - name: "S3FS | 显示挂载信息" - debug: + ansible.builtin.debug: msg: | S3 存储桶已成功挂载! - 存储桶: {{ s3fs_config.bucket }} - 挂载点: {{ s3fs_config.mount_point }} + 存储桶: {{ normalized_s3fs_config.bucket }} + 挂载点: {{ normalized_s3fs_config.mount_point }} 状态: {{ s3fs_verify_mount.stdout }} diff --git a/playbooks/roles/vhosts/common/tasks/main.yml b/playbooks/roles/vhosts/common/tasks/main.yml index 8343bea..1397ce1 100644 --- a/playbooks/roles/vhosts/common/tasks/main.yml +++ b/playbooks/roles/vhosts/common/tasks/main.yml @@ -23,22 +23,47 @@ when: - enable_common | bool - ansible_facts.os_family == 'Debian' + vars: + apt_repo_config: "{{ repo.apt | default({}) }}" + apt_package_config: "{{ packages.apt | default({}) }}" block: - name: "Common | Repo & keys" ansible.builtin.include_tasks: repo_setup.yml - when: repo_setup | bool + when: apt_repo_config.enabled | default(false) | bool + vars: + repo_config: "{{ apt_repo_config }}" tags: [repo, baseline] - name: "Common | Packages" ansible.builtin.include_tasks: packages.yml - when: install_packages | bool + when: apt_package_config.enabled | default(false) | bool + vars: + package_config: "{{ apt_package_config }}" + package_manager: apt tags: [pkgs, baseline] - name: "Common | S3FS 挂载" ansible.builtin.include_tasks: configure_s3fs.yml - when: s3fs_enable | bool + when: s3fs_enable | default(false) | bool + vars: + s3fs_config: "{{ s3fs_config | default({}) }}" tags: [s3fs, mount] +- name: "Common | Run on RedHat family only" + when: + - enable_common | bool + - ansible_facts.os_family == 'RedHat' + vars: + yum_package_config: "{{ packages.yum | default({}) }}" + block: + - name: "Common | Packages" + ansible.builtin.include_tasks: packages.yml + when: yum_package_config.enabled | default(false) | bool + vars: + package_config: "{{ yum_package_config }}" + package_manager: dnf + tags: [pkgs, baseline] + #- name: Include GPU Configuration # include_tasks: include_gpu.yaml # when: (ansible_facts['distribution'] == "Ubuntu") or (ansible_facts['distribution'] == "Debian") diff --git a/playbooks/roles/vhosts/common/tasks/packages.yml b/playbooks/roles/vhosts/common/tasks/packages.yml index d4b8ed9..5d94edb 100644 --- a/playbooks/roles/vhosts/common/tasks/packages.yml +++ b/playbooks/roles/vhosts/common/tasks/packages.yml @@ -1,22 +1,39 @@ --- +- name: Normalize package config + ansible.builtin.set_fact: + normalized_package_list: "{{ package_config.list | default([], true) }}" + normalized_base_dependencies: "{{ package_config.base_dependencies | default([], true) }}" + # 基础依赖(不在此处 update_cache,避免读取未规范化源) - name: Ensure base APT deps (no update now) ansible.builtin.apt: - name: - - ca-certificates - - gnupg + name: "{{ normalized_base_dependencies }}" state: present update_cache: false + when: + - package_manager == 'apt' + - normalized_base_dependencies | length > 0 become: true # 实际安装 -- name: Install packages +- name: Install packages via apt ansible.builtin.apt: - name: "{{ packages | default([]) }}" + name: "{{ normalized_package_list }}" state: present environment: DEBIAN_FRONTEND: noninteractive APT_LISTCHANGES_FRONTEND: none - when: (packages | default([])) | length > 0 + when: + - package_manager == 'apt' + - normalized_package_list | length > 0 + become: true + +- name: Install packages via dnf + ansible.builtin.dnf: + name: "{{ normalized_package_list }}" + state: present + when: + - package_manager == 'dnf' + - normalized_package_list | length > 0 become: true diff --git a/playbooks/roles/vhosts/common/tasks/repo_setup.yml b/playbooks/roles/vhosts/common/tasks/repo_setup.yml index 879f60d..be0a7dd 100644 --- a/playbooks/roles/vhosts/common/tasks/repo_setup.yml +++ b/playbooks/roles/vhosts/common/tasks/repo_setup.yml @@ -1,8 +1,19 @@ --- +- name: Normalize apt repo config + ansible.builtin.set_fact: + apt_repo_config: "{{ { + 'key_dir': '/etc/apt/keyrings', + 'enable_universe': false, + 'auto_update_cache': true, + 'keyrings': [], + 'legacy_paths': [], + 'entries': [] + } | combine(repo_config | default({}), recursive=True) }}" + # 0) 统一 keyring 路径 - name: Ensure keyring dir exists ansible.builtin.file: - path: "{{ apt_key_dir }}" + path: "{{ apt_repo_config.key_dir }}" state: directory owner: root group: root @@ -20,14 +31,14 @@ # 0.2) 声明式 keyring 管理 - name: "Manage declared apt keyrings" ansible.builtin.include_tasks: manage_keyring.yml - when: (apt_keyrings | default([])) | length > 0 - loop: "{{ apt_keyrings | default([]) }}" + when: (apt_repo_config.keyrings | default([])) | length > 0 + loop: "{{ apt_repo_config.keyrings | default([]) }}" loop_control: loop_var: apt_keyring label: "{{ apt_keyring.name | default(apt_keyring.dest | default('custom-keyring')) }}" vars: - keyring_dest: "{{ apt_keyring.dest | default(apt_key_dir ~ '/' ~ apt_keyring.name ~ '.gpg') }}" - keyring_ascii: "{{ apt_keyring.asc_path | default(apt_key_dir ~ '/' ~ apt_keyring.name ~ '.asc') }}" + keyring_dest: "{{ apt_keyring.dest | default(apt_repo_config.key_dir ~ '/' ~ apt_keyring.name ~ '.gpg') }}" + keyring_ascii: "{{ apt_keyring.asc_path | default(apt_repo_config.key_dir ~ '/' ~ apt_keyring.name ~ '.asc') }}" keyring_state: "{{ apt_keyring.state | default('present') }}" tags: [repo, baseline] @@ -36,7 +47,7 @@ ansible.builtin.file: path: "{{ item }}" state: absent - loop: "{{ apt_repo_legacy | default([]) }}" + loop: "{{ apt_repo_config.legacy_paths | default([]) }}" become: true # 2) Ubuntu 可选 universe @@ -47,17 +58,17 @@ filename: "ubuntu-{{ ansible_distribution_release }}-universe" when: - ansible_facts.distribution == 'Ubuntu' - - enable_universe | bool + - apt_repo_config.enable_universe | default(false) | bool become: true # 3) 每个仓库:下载 key(可选)→ dearmor(可选)→ 添加 .list(含 signed-by) - name: "Fetch ASCII key (if key_url provided)" ansible.builtin.get_url: url: "{{ repo.key_url }}" - dest: "{{ apt_key_dir }}/{{ repo.name }}.asc" + dest: "{{ apt_repo_config.key_dir }}/{{ repo.name }}.asc" mode: '0644' when: repo.key_url is defined and repo.key_url | length > 0 - loop: "{{ repos | default([]) }}" + loop: "{{ apt_repo_config.entries | default([]) }}" loop_control: loop_var: repo label: "{{ repo.name }}" @@ -65,10 +76,10 @@ - name: "Dearmor key" ansible.builtin.command: - cmd: "gpg --dearmor -o {{ apt_key_dir }}/{{ repo.name }}.gpg {{ apt_key_dir }}/{{ repo.name }}.asc" - creates: "{{ apt_key_dir }}/{{ repo.name }}.gpg" + cmd: "gpg --dearmor -o {{ apt_repo_config.key_dir }}/{{ repo.name }}.gpg {{ apt_repo_config.key_dir }}/{{ repo.name }}.asc" + creates: "{{ apt_repo_config.key_dir }}/{{ repo.name }}.gpg" when: repo.key_url is defined and repo.key_url | length > 0 - loop: "{{ repos | default([]) }}" + loop: "{{ apt_repo_config.entries | default([]) }}" loop_control: loop_var: repo label: "{{ repo.name }}" @@ -76,13 +87,13 @@ - name: "Ensure keyring permission" ansible.builtin.file: - path: "{{ (repo.signed_by | default(apt_key_dir ~ '/' ~ repo.name ~ '.gpg')) }}" + path: "{{ (repo.signed_by | default(apt_repo_config.key_dir ~ '/' ~ repo.name ~ '.gpg')) }}" owner: root group: root mode: '0644' state: file when: (repo.key_url is defined and repo.key_url | length > 0) or (repo.signed_by is defined) - loop: "{{ repos | default([]) }}" + loop: "{{ apt_repo_config.entries | default([]) }}" loop_control: loop_var: repo label: "{{ repo.name }}" @@ -91,7 +102,7 @@ - name: "Cleanup repo specific paths" when: repo.cleanup is defined and (repo.cleanup | length > 0) become: true - loop: "{{ repos | default([]) }}" + loop: "{{ apt_repo_config.entries | default([]) }}" loop_control: loop_var: repo label: "{{ repo.name }}" @@ -107,12 +118,12 @@ - name: "Add classic .list repo with signed-by" ansible.builtin.apt_repository: repo: >- - deb [signed-by={{ repo.signed_by | default(apt_key_dir ~ '/' ~ repo.name ~ '.gpg') }}] + deb [signed-by={{ repo.signed_by | default(apt_repo_config.key_dir ~ '/' ~ repo.name ~ '.gpg') }}] {{ repo.uri }} {{ repo.suite }} {{ (repo.components | default(['main'])) | join(' ') }} filename: "{{ repo.name }}" state: "{{ (repo.enabled | default(false) | bool) | ternary('present','absent') }}" when: repo.enabled | default(false) | bool - loop: "{{ repos | default([]) }}" + loop: "{{ apt_repo_config.entries | default([]) }}" loop_control: loop_var: repo label: "{{ repo.name }}" @@ -122,5 +133,5 @@ - name: Update apt cache after repo setup ansible.builtin.apt: update_cache: true - when: auto_update_cache | bool + when: apt_repo_config.auto_update_cache | default(false) | bool become: true