feat: ansible use Docker for process isolation

This commit is contained in:
wangruidong
2026-06-03 18:04:05 +08:00
committed by 老广
parent a1708f7e21
commit c1a44cc202
12 changed files with 1505 additions and 1212 deletions

1
.gitignore vendored
View File

@@ -49,3 +49,4 @@ apps.iml
*.db
*.mmdb
*.ipdb
context

View File

@@ -7,6 +7,10 @@ timeout = 65
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
# Docker 隔离下 ControlMaster 在 bind mount 上无法创建 mux socketmacOS 尤其明显)
ssh_args = -o ControlMaster=no -o ControlPersist=no
pipelining = True
[persistent_connection]
[accelerate]
[selinux]

View File

@@ -14,6 +14,13 @@ from ..utils import get_ansible_log_verbosity
__all__ = ['AdHocRunner', 'PlaybookRunner', 'SuperPlaybookRunner', 'UploadFileRunner']
def prepare_isolated_ansible_cfg(project_dir):
"""Copy ansible.cfg into job dir so the EE container picks up SSH settings."""
src = os.path.join(settings.APPS_DIR, 'libs', 'ansible', 'ansible.cfg')
dst = os.path.join(project_dir, 'ansible.cfg')
shutil.copyfile(src, dst)
class AdHocRunner:
cmd_modules_choices = ('shell', 'raw', 'command', 'script', 'win_shell')
need_local_connection_modules_choices = ("mysql", "postgresql", "sqlserver", "huawei")
@@ -60,7 +67,12 @@ class AdHocRunner:
if os.path.exists(private_env):
shutil.rmtree(private_env)
prepare_isolated_ansible_cfg(self.project_dir)
interface.run(
process_isolation=True,
process_isolation_executable='docker',
container_image='company-ee:1.0',
timeout=self.timeout if self.timeout > 0 else None,
extravars=self.extra_vars,
envvars=self.envs,
@@ -108,12 +120,13 @@ class PlaybookRunner:
if os.path.exists(private_env):
shutil.rmtree(private_env)
kwargs = dict(kwargs)
if self.isolate and not is_macos():
kwargs['process_isolation'] = True
kwargs['process_isolation_executable'] = 'bwrap'
prepare_isolated_ansible_cfg(self.project_dir)
kwargs = dict(kwargs)
interface.run(
process_isolation=True,
process_isolation_executable='docker',
container_image='company-ee:1.0',
private_data_dir=self.project_dir,
inventory=self.inventory,
playbook=self.playbook,

View File

@@ -152,6 +152,7 @@ dependencies = [
"pyhttpsig==1.3.0",
"telnetlib3==4.0.2",
"defusedxml>=0.7.1",
"ansible-builder>=3.1.1",
]
[project.urls]

View File

@@ -0,0 +1,8 @@
[defaults]
forks = 10
host_key_checking = False
library = /opt/jumpserver/apps/libs/ansible/modules:./modules
timeout = 65
[ssh_connection]
ssh_args = -o ControlMaster=no -o ControlPersist=no
pipelining = True

View File

@@ -0,0 +1,20 @@
# RPM packages for JumpServer ansible playbooks and custom modules.
# ansible-builder 只支持 dnf/microdnf不支持 Debian apt。
# freetds-devel / sshpass 需配合 execution-environment.yml 中 EPEL 启用步骤。
gcc [platform:rpm]
pkgconf-pkg-config [platform:rpm]
python3.11-devel [platform:rpm]
openssh-clients [platform:rpm]
sshpass [platform:rpm]
iputils [platform:rpm]
nmap [platform:rpm]
telnet [platform:rpm]
mariadb-connector-c-devel [platform:rpm]
postgresql-devel [platform:rpm]
freetds-devel [platform:rpm]
krb5-devel [platform:rpm]
openldap-devel [platform:rpm]
cyrus-sasl-devel [platform:rpm]
libX11-devel [platform:rpm]
ca-certificates [platform:rpm]
glibc-langpack-en [platform:rpm]

40
utils/ansible_executor/build.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Build EE image with China-friendly defaults (mirrors + cache).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR"
IMAGE_TAG="${IMAGE_TAG:-company-ee:1.0}"
EE_FILE="${EE_FILE:-execution-environment.yml}"
GITHUB_MIRROR="${GITHUB_MIRROR:-https://ghfast.top/}"
USE_CHINA_MIRROR="${USE_CHINA_MIRROR:-1}"
if ! command -v ansible-builder >/dev/null 2>&1; then
echo "ansible-builder not found. Install: pip install ansible-builder" >&2
exit 1
fi
# Optional: rewrite GitHub zip URLs via mirror (speed up ansible-core / ansible-runner download).
# 临时 EE 必须放在 SCRIPT_DIRansible-builder 按 EE 文件所在目录解析 requirements-python.txt 等相对路径。
WORK_EE="$EE_FILE"
if [ "$USE_CHINA_MIRROR" = "1" ] && [ -n "$GITHUB_MIRROR" ]; then
WORK_EE="$(mktemp "${SCRIPT_DIR}/.execution-environment.XXXXXX.yml")"
sed \
-e "s|https://github.com/|${GITHUB_MIRROR}https://github.com/|g" \
"$EE_FILE" > "$WORK_EE"
trap 'rm -f "$WORK_EE"' EXIT
fi
export DOCKER_BUILDKIT=1
echo "==> image: $IMAGE_TAG"
echo "==> ee file: $WORK_EE"
echo "==> github mirror: ${GITHUB_MIRROR:-disabled}"
echo "==> tip: configure Docker Desktop registry mirrors for quay.io / docker.io"
ansible-builder build \
-f "$WORK_EE" \
-t "$IMAGE_TAG" \
--container-runtime docker \
"$@"

View File

@@ -0,0 +1,81 @@
---
# JumpServer Ansible Execution Environment
#
# 国内加速构建(推荐):
# cd utils/ansible_executor
# chmod +x build.sh
# ./build.sh
#
# 手动构建:
# ansible-builder build -f execution-environment.yml -t company-ee:1.0 --container-runtime docker
#
# 加速要点:
# 1. pip: 清华源 (files/pip.conf)
# 2. dnf/epel: 阿里云 (files/use-china-mirrors.sh)
# 3. GitHub zip: build.sh 默认走 ghfast.top 镜像
# 4. 重复构建: PKGMGR_PRESERVE_CACHE=always 保留 dnf 缓存
# 5. Docker Desktop -> Settings -> Docker Engine 配置 registry-mirrors
version: 3
build_arg_defaults:
# 重复 build 时保留 dnf 缓存,显著加快二次构建
PKGMGR_PRESERVE_CACHE: always
images:
# ansible-builder 仅支持 RPM 系镜像 (dnf),不能用 python:3.11-slim 等 Debian 镜像
base_image:
name: quay.io/centos/centos:stream9
dependencies:
python_interpreter:
package_system: python3.11
python_path: /usr/bin/python3.11
# 与 pyproject.toml [tool.uv.sources] 保持一致,不要用 PyPI 官方包
ansible_core:
package_pip: https://github.com/jumpserver-dev/ansible/archive/refs/tags/v2.14.1.7.zip
ansible_runner:
package_pip: https://github.com/jumpserver-dev/ansible-runner/archive/refs/tags/2.4.0.1.zip
galaxy:
collections:
- name: community.postgresql
version: "2.4.0"
- name: community.mysql
- name: community.mongodb
- name: community.windows
- name: ansible.windows
python: requirements-python.txt
system: bindep.txt
additional_build_files:
- src: files/pip.conf
dest: configs/
- src: files/use-china-mirrors.sh
dest: scripts/
- src: ../../apps/libs/ansible/
dest: jumpserver-ansible/
- src: ansible.cfg
dest: configs/
additional_build_steps:
prepend_base:
# pip 镜像需在 base 阶段最早注入,后续各 stage 的 pip install 都会走国内源
- COPY _build/configs/pip.conf /etc/pip.conf
- COPY _build/scripts/use-china-mirrors.sh /tmp/use-china-mirrors.sh
- RUN chmod +x /tmp/use-china-mirrors.sh && /tmp/use-china-mirrors.sh centos
# freetds-devel、sshpass 等在 EPELpostgresql-devel 等开发包常需 CRB
- RUN $PKGMGR config-manager --set-enabled crb
- RUN $PKGMGR install -y epel-release
- RUN /tmp/use-china-mirrors.sh epel && $PKGMGR makecache -y
append_final:
- RUN mkdir -p /opt/jumpserver/apps
- COPY _build/jumpserver-ansible/ /opt/jumpserver/apps/libs/ansible/
- COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg
- ENV PYTHONPATH=/opt/jumpserver/apps
- ENV ANSIBLE_LIBRARY=/opt/jumpserver/apps/libs/ansible/modules
- ENV ANSIBLE_FORCE_COLOR=True
- ENV LC_ALL=C.UTF-8
- ENV LANG=C.UTF-8

View File

@@ -0,0 +1,7 @@
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn
timeout = 120
[install]
trusted-host = pypi.tuna.tsinghua.edu.cn

View File

@@ -0,0 +1,67 @@
#!/bin/bash
# Switch CentOS Stream / EPEL repos to Aliyun mirrors (for builds in China).
set -euo pipefail
mirror_centos() {
for f in /etc/yum.repos.d/centos*.repo; do
[ -f "$f" ] || continue
sed -i \
-e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org|baseurl=https://mirrors.aliyun.com|g' \
-e 's|^#baseurl=https://mirror.centos.org|baseurl=https://mirrors.aliyun.com|g' \
"$f"
done
}
mirror_epel() {
# epel-release 默认只有 metalinksed 改 baseurl 会失效;直接覆盖为阿里云固定地址
cat > /etc/yum.repos.d/epel.repo <<'EOF'
[epel]
name=Extra Packages for Enterprise Linux 9 - $basearch
baseurl=https://mirrors.aliyun.com/epel/9/Everything/$basearch
enabled=1
gpgcheck=1
countme=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
[epel-debuginfo]
name=Extra Packages for Enterprise Linux 9 - $basearch - Debug
baseurl=https://mirrors.aliyun.com/epel/9/Everything/$basearch/debug
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
[epel-source]
name=Extra Packages for Enterprise Linux 9 - $basearch - Source
baseurl=https://mirrors.aliyun.com/epel/9/Everything/source/tree
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
EOF
# epel-next 在阿里云 aarch64 上常 404且 freetds-devel/sshpass 在 epel 主仓库即可
rm -f /etc/yum.repos.d/epel-next.repo
# 禁用可能仍指向官方源的其他 epel 附属 repo
for f in /etc/yum.repos.d/epel*.repo; do
case "$(basename "$f")" in
epel.repo) ;;
*)
sed -i 's/^enabled=1/enabled=0/g' "$f" || true
;;
esac
done
}
case "${1:-all}" in
centos) mirror_centos ;;
epel) mirror_epel ;;
all)
mirror_centos
mirror_epel
;;
*)
echo "usage: $0 [centos|epel|all]" >&2
exit 2
;;
esac

View File

@@ -0,0 +1,10 @@
# Aligned with JumpServer pyproject.toml ansible-related Python deps.
paramiko==3.2.0
sshtunnel==0.4.0
pywinrm==0.4.3
python-nmap==0.7.1
mysqlclient==2.2.4
pymssql==2.3.4
pymongo==4.6.3
oracledb==1.4.0
pyfreerdp==0.0.2

2457
uv.lock generated

File diff suppressed because it is too large Load Diff