Ansible 自动化 Nginx 集群部署实战:动态 Inventory、滚动发布与 Role 工程化

Ansible 自动化 Nginx 集群部署实战:动态 Inventory、滚动发布与 Role 工程化

  • Ansible 简介与核心原理

Ansible 是红帽推出的 IT 自动化运维引擎,能够完成批量服务器初始化、应用部署、配置管理、持续发布等工作。 核心原理:控制节点通过 SSH 协议连接远端主机,临时传输 Python 模块到被控主机本地执行,执行完毕后自动清理临时文件;整个过程不需要常驻后台进程,执行模式简单安全,天然适合云服务器批量运维。

  • Ansible 核心组件
  1. Inventory(主机清单) 维护所有被控服务器列表、IP、分组、登录变量,用来区分负载均衡节点、Web 业务节点,支持多环境(测试 / 生产)隔离。
  2. Module(模块) Ansible 最小执行单元,系统内置大量原生模块,实现安装软件、创建目录、下发文件、启停服务等操作,无需手写 Shell 脚本。
  3. Playbook(剧本) 使用 YAML 语言编写的任务文件,把多条运维任务编排成一套完整流程,实现可重复执行、版本可控的自动化部署。
  4. Role(角色) 对 Playbook 进行封装复用的组件,把任务、模板、配置、触发器拆分管理,相同服务可以直接复用一套 Role,适合集群化部署。
  5. Handler(触发器) 只有配置文件发生变更时才会触发执行,例如修改 Nginx 配置后重载服务,避免无意义的重复重启。
  6. Template(Jinja2 模板) 支持动态渲染配置文件,可读取主机清单变量自动生成 Nginx upstream 后端列表,新增 Web 节点时无需手动修改负载均衡配置。

本文基于腾讯云 Ubuntu 24.04 CVM,搭建 Ansible 自动化 Nginx 集群,架构包含 1 台管控机、1 台负载均衡节点、3 台 Web 后端节点。

一、环境规划

主机名 角色 内网IP 公网IP 系统 配置
ansible Ansible跳板机 10.10.3.16 1.13.186.149 Ubuntu24.04 2C2G
lb1 Nginx负载均衡 10.10.3.12 175.27.143.43 Ubuntu24.04 2C2G
web01 Web后端 10.10.3.17 Ubuntu24.04 2C2G
web02 Web后端 10.10.3.2 Ubuntu24.04 2C2G
web03 Web后端 10.10.3.10 Ubuntu24.04 2C2G

环境说明:全部节点部署在腾讯云相同 VPC 与子网,内网互通

二、部署Ansible控制端

1、安装Ansible

登录ansible主机,修改主机名并安装 Ansible

bash 复制代码
sudo hostnamectl set-hostname ansible
sudo apt update
sudo apt install -y ansible

验证:

bash 复制代码
ansible --version

2、配置免密登录

ansible 服务器生成一套专门管理其他节点的 SSH 密钥:

复制代码
ssh-keygen -t ed25519 -f ~/.ssh/ansible_ed25519 -N ""

查看公钥:

bash 复制代码
cat ~/.ssh/ansible_ed25519.pub

把这段公钥 配置到 lb、web1、web2、web3ubuntu 用户中,可以用腾讯云【云服务器】------【自动化助手】批量执行以下命令:

bash 复制代码
PUBKEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpLiQbXlYlS9SY/edcN6iETPSocckghqX4aQ+X1IWdf ubuntu@ansible'

mkdir -p /home/ubuntu/.ssh
grep -qxF "$PUBKEY" /home/ubuntu/.ssh/authorized_keys 2>/dev/null ||
  echo "$PUBKEY" >> /home/ubuntu/.ssh/authorized_keys

chown -R ubuntu:ubuntu /home/ubuntu/.ssh
chmod 700 /home/ubuntu/.ssh
chmod 600 /home/ubuntu/.ssh/authorized_keys

选中要执行的主机点击【执行命令

3、测试免密登录

ansible 服务器批量测试:

bash 复制代码
for ip in 10.10.3.12 10.10.3.17 10.10.3.2 10.10.3.10; do
  ssh -o StrictHostKeyChecking=accept-new \
      -i ~/.ssh/ansible_ed25519 ubuntu@$ip hostname
done

成功返回各台主机名,则说明 SSH 免密和安全组配置正确

4、创建项目目录

bash 复制代码
sudo mkdir -p /data/ansible
sudo chown -R ubuntu:ubuntu /data/ansible
cd /data/ansible

mkdir -p inventories/{test,prod}/{group_vars,host_vars}
mkdir -p playbooks roles files templates vault

当前结构:

目录结构说明

ansible.cfg :项目独立配置文件

inventories :多环境服务器清单,维护主机与变量

playbooks :自动化任务执行剧本

roles: 可复用的部署角色组件

files :直接分发的静态资源文件

templates: jinja2动态配置模板

vault :ansible‑vault加密存放敏感凭证

5、创建生产环境主机清单

inventories/prod/hosts.ini

ini 复制代码
[lb] #负载均衡服务器组
lb1 ansible_host=10.10.3.12

[web] #Web 服务器组
web1 ansible_host=10.10.3.17
web2 ansible_host=10.10.3.2
web3 ansible_host=10.10.3.10

[nginx:children] #包含 lb 和 web 的父组
lb
web

6、创建公共变量

inventories/prod/group_vars/all.yml

yml 复制代码
ansible_user: ubuntu
ansible_ssh_private_key_file: /home/ubuntu/.ssh/ansible_ed25519
ansible_python_interpreter: /usr/bin/python3

这样就不需要在每台主机后面重复配置登录用户和私钥

7、创建Ansible配置

/data/ansible/ansible.cfg

bash 复制代码
[defaults]
inventory = ./inventories/prod/hosts.ini
roles_path = ./roles
host_key_checking = True
retry_files_enabled = False
forks = 20
timeout = 10

[ssh_connection]
ssh_args = -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/home/ubuntu/.ssh/known_hosts
pipelining = True

检查配置是否生效

bash 复制代码
ansible --version

确认输出中包含: /data/ansible/ansible.cfg

查看主机分组

bash 复制代码
ansible-inventory --graph

预期结果类似:

8、测试连接

bash 复制代码
#测试所有服务器:返回ping:pong
ansible all -m ping

#测试不同分组:返回ping:pong
ansible lb -m ping
ansible web -m ping

#测试命令执行:成功返回主机名
ansible all -a "hostname"

三、编写服务器初始化 Playbook

编写第一个 Playbook,统一初始化 4 台业务服务器,包括主机名、时区和基础工具

1、验证sudo权限

/data/ansible 下执行:

bash 复制代码
ansible all -b -a "whoami"

全部返回 root,说明 Ansible 可以使用 sudo。

2、创建初始化 Playbook

playbooks/init.yml

yml 复制代码
cat > playbooks/init.yml <<'EOF'
---
- name: 初始化服务器
  hosts: all
  become: true
  serial: 2

  tasks:
    - name: 设置主机名
      ansible.builtin.hostname:
        name: "{{ inventory_hostname }}"

    - name: 设置时区
      community.general.timezone:
        name: Asia/Shanghai

    - name: 更新软件索引
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600

    - name: 安装基础运维工具
      ansible.builtin.apt:
        name:
          - curl
          - wget
          - vim
          - git
          - unzip
          - jq
          - lsof
          - net-tools
        state: present
EOF

其中:

  • become: true:通过 sudo 获取 root 权限
  • serial: 2:每批处理两台服务器
  • inventory_hostname:使用 Inventory 中的 lb1、web1~web3 设置主机名

3、执行Playbook

(1)检查语法
bash 复制代码
ansible-playbook playbooks/init.yml --syntax-check
(2)预演变更
bash 复制代码
ansible-playbook playbooks/init.yml --check --diff

预演不会真正修改服务器

预演结果正常,且没有失败,说明 Playbook 可以正常执行

(3)正式执行
bash 复制代码
ansible-playbook playbooks/init.yml

执行完成后验证:

bash 复制代码
ansible all -a "hostname"
ansible all -a "timedatectl show -p Timezone --value"

四、使用 Role 批量部署 Web 节点 Nginx

这一步我们创建 nginx_web Role,在 web1~web3 批量安装 Nginx 并发布带有节点标识的页面。

1、创建Role 目录结构

bash 复制代码
cd /data/ansible
ansible-galaxy role init roles/nginx_web

2、 编写 Nginx 安装与配置任务

roles/nginx_web/tasks/main.yml

yml 复制代码
---
- name: 安装 Nginx
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true

- name: 创建网站根目录
  ansible.builtin.file:
    path: /data/www
    state: directory
    owner: www-data
    group: www-data
    mode: "0755"

- name: 下发首页
  ansible.builtin.template:
    src: index.html.j2
    dest: /data/www/index.html
    owner: www-data
    group: www-data
    mode: "0644"

- name: 下发 Nginx 配置
  ansible.builtin.template:
    src: default.conf.j2
    dest: /etc/nginx/sites-available/default
    owner: root
    group: root
    mode: "0644"
  notify: 重载 Nginx

- name: 启动并设置 Nginx 开机自启
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

3、创建首页模板

每台 Web 节点显示自己的主机名和 IP,方便后续验证负载均衡效果:

roles/nginx_web/templates/index.html.j2

html 复制代码
<!DOCTYPE html>
<html>
<head><title>{{ inventory_hostname }}</title></head>
<body>
<h1>Served by {{ inventory_hostname }}</h1>
<p>IP: {{ ansible_host }}</p>
<p>Time: {{ ansible_date_time.iso8601 }}</p>
</body>
</html>

4、创建NGINX配置模版

roles/nginx_web/templates/default.conf.j2

nginx 复制代码
server {
    listen 80;
    listen [::]:80;

    server_name _;
    root /data/www;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

5、创建Handler

roles/nginx_web/handlers/main.yml

yaml 复制代码
---
- name: 检查 Nginx 配置
  ansible.builtin.command: nginx -t
  changed_when: false
  listen: 重载 Nginx

- name: 重载 Nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded
  listen: 重载 Nginx

6、编写 Playbook 入口

playbooks/deploy_web.yml

yml 复制代码
---
- name: 部署 Web 节点 Nginx
  hosts: web
  become: true
  roles:
    - nginx_web

7、执行部署

bash 复制代码
ansible-playbook playbooks/deploy_web.yml --syntax-check
ansible-playbook playbooks/deploy_web.yml --check --diff

注意:执行 --check 预演模式时,Ansible 判断 Nginx"将被安装",但实际上没有安装,所以执行服务管理时找不到 nginx而报错,这不是 Playbook 配置错误

直接正式执行即可:

bash 复制代码
ansible-playbook playbooks/deploy_web.yml

8、验证NGINX状态

bash 复制代码
ansible web -a "systemctl is-active nginx"     #应全部返回:active
ansible web -a "curl -s http://localhost"   #三台服务器应分别显示 web1、web2、web3

五、部署 Nginx 负载均衡节点

lb1 安装 Nginx,将请求转发到 web1~web3

1、检查后端连通性

先确认 lb1 能访问三台 Web 节点:

bash 复制代码
ansible lb -a "curl -s --connect-timeout 3 http://10.10.3.17"
ansible lb -a "curl -s --connect-timeout 3 http://10.10.3.2"
ansible lb -a "curl -s --connect-timeout 3 http://10.10.3.10"

如果访问失败,需要检查 Web 服务器安全组:TCP 80 应允许来自 lb1 的内网 IP 10.10.3.12

2、创建Role

bash 复制代码
cd /data/ansible
ansible-galaxy role init roles/nginx_lb

3、编写部署任务

roles/nginx_lb/tasks/main.yml

yml 复制代码
---
- name: 安装 Nginx
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true

- name: 下发负载均衡配置
  ansible.builtin.template:
    src: default.conf.j2
    dest: /etc/nginx/sites-available/default
    owner: root
    group: root
    mode: "0644"
  notify: 重载 Nginx

- name: 启动并设置 Nginx 开机自启
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

4、创建负载均衡配置模板

roles/nginx_lb/templates/default.conf.j2

nginx 复制代码
upstream web_backend {
{% for host in groups['web'] %}
    server {{ hostvars[host].ansible_host }}:80;
{% endfor %}
}

server {
    listen 80;
    listen [::]:80;

    server_name _;

    location / {
        proxy_pass http://web_backend;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 3s;
        proxy_read_timeout 30s;
    }
}

模板会根据 Inventory 中的 web 分组自动生成:

nginx 复制代码
upstream web_backend {
    server 10.10.3.17:80;
    server 10.10.3.2:80;
    server 10.10.3.10:80;
}

以后增加 Web 节点时,只需要更新 Inventory,无需手动修改 Nginx 配置。

5、创建 Handler

roles/nginx_lb/handlers/main.yml

yml 复制代码
---
- name: 检查 Nginx 配置
  ansible.builtin.command: nginx -t
  changed_when: false
  listen: 重载 Nginx

- name: 重载 Nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded
  listen: 重载 Nginx

6、创建 Playbook

playbooks/deploy_lb.yml

yml 复制代码
---
- name: 部署 Nginx 负载均衡
  hosts: lb
  become: true

  roles:
    - nginx_lb

7、检查并执行

bash 复制代码
ansible-playbook playbooks/deploy_lb.yml --syntax-check
ansible-playbook playbooks/deploy_web.yml --check --diff
ansible-playbook playbooks/deploy_lb.yml

成功结果应满足:unreachable=0failed=0

8、验证负载均衡

连续访问 lb1:可以轮流返回三台web页面

bash 复制代码
for i in {1..6}; do
  curl -s http://10.10.3.12 | grep "Served by"
done

也可以通过 lb1 的公网 IP 访问:http://175.27.143.43(需要确保 lb1 安全组已开放 TCP 80)

通过以上测试,说明负载均衡部署成功。请求按照 Nginx 默认的轮询策略 依次分发到:web1 → web2 → web3

六、实现 Web 集群滚动发布与健康检查

本次按 web1 → web2 → web3 逐台发布。每台发布成功并通过健康检查后,才继续下一台;失败则回滚并停止发布。

1、创建Web组变量

inventories/prod/group_vars/web.yml

复制代码
---
release_version: "v2.0.0"
release_message: "Ansible rolling deployment"

2、修改首页模板

修改roles/nginx_web/templates/index.html.j2为以下内容

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>{{ inventory_hostname }}</title>
</head>
<body>
    <h1>Served by {{ inventory_hostname }}</h1>
    <p>IP: {{ ansible_host }}</p>
    <p>Version: {{ release_version }}</p>
    <p>Message: {{ release_message }}</p>
</body>
</html>

3、创建滚动发布 Playbook

playbooks/rolling_deploy_web.yml

yml 复制代码
---
- name: 滚动发布 Web 集群
  hosts: web
  become: true		# 在远程 Web 节点上使用特权提升(通常为 root)
  serial: 1			# 每次只发布一台节点,实现逐台滚动发布
  any_errors_fatal: true	# 任意节点发布失败时,停止整个 Play 后续节点的执行

  tasks:
    - name: 检查当前首页是否存在
      ansible.builtin.stat:
        path: /data/www/index.html
      register: current_index

    - name: 发布并执行健康检查
      block:
        - name: 备份当前首页
          ansible.builtin.copy:
            src: /data/www/index.html
            dest: /data/www/index.html.rollback
            remote_src: true
            owner: www-data
            group: www-data
            mode: "0644"
          when: current_index.stat.exists

        - name: 发布新首页
          ansible.builtin.template:
            src: ../roles/nginx_web/templates/index.html.j2
            dest: /data/www/index.html
            owner: www-data
            group: www-data
            mode: "0644"

        - name: 检查本机 Nginx 服务
          ansible.builtin.uri:
            url: http://127.0.0.1/
            return_content: true
            status_code: 200
          register: local_health
          retries: 3	# 健康检查失败时最多重试 3 次
          delay: 2		# 每次重试间隔 2 秒
          until:
            - local_health.status == 200
            - release_version in local_health.content

        - name: 从负载均衡节点检查当前 Web 节点
          ansible.builtin.uri:
            url: "http://{{ hostvars[inventory_hostname].ansible_host }}/"
            return_content: true
            status_code: 200
          delegate_to: lb1
          become: false
          register: lb_health
          retries: 3
          delay: 2
          until:
            - lb_health.status == 200
            - release_version in lb_health.content

        - name: 显示当前节点发布结果
          ansible.builtin.debug:
            msg: "{{ inventory_hostname }} 发布 {{ release_version }} 成功"

      rescue:
        - name: 回滚旧首页
          ansible.builtin.copy:
            src: /data/www/index.html.rollback
            dest: /data/www/index.html
            remote_src: true
            owner: www-data
            group: www-data
            mode: "0644"
          when: current_index.stat.exists

        - name: 发布失败并停止后续节点
          ansible.builtin.fail:
            msg: "{{ inventory_hostname }} 发布失败,已执行回滚"

4、执行滚动发布

bash 复制代码
ansible-playbook playbooks/rolling_deploy_web.yml --syntax-check
ansible-playbook playbooks/rolling_deploy_web.yml

执行顺序会分为三个批次:web1 发布并检查成功→ web2 发布并检查成功→ web3 发布并检查成功

5、验证

通过访问负载均衡节点,看三台节点是否升级到了v2.0.0

bash 复制代码
 for i in {1..3}; do
  curl -s http://10.10.3.12 |
    grep -E "Served by|Version"
done

从上面结果可以验证滚动发布和健康检查部署完成!

6、模拟发布失败并验证自动回滚

模拟发布失败的核心思路是:正常发布新版本,但故意设置一个永远无法满足的健康检查条件,让 Ansible 认为发布失败,从而触发回滚。

(1) 将版本升级到 v2.0.1
bash 复制代码
sed -i 's/v2.0.0/v2.0.1/' inventories/prod/group_vars/web.yml
(2)故意修改健康检查条件

修改Playbook中健康检查部分代码为以下:临时改成检查一个不存在的版本v9.9.9

yml 复制代码
until:
  - lb_health.status == 200
  - "'v9.9.9' in lb_health.content"
(3)执行滚动发布
bash 复制代码
ansible-playbook playbooks/rolling_deploy_web.yml

从日志可以看到web1 发布失败后成功回滚;web2、web3 没有继续发布;滚动发布和失败停止机制正常。

七、滚动发布时自动摘除和恢复节点

前面的滚动发布虽然逐台执行,但节点发布期间仍在负载均衡池中。

生产环境通常采用:从负载均衡摘除节点→ 发布并检查→ 恢复节点→ 继续下一台

1、修改负载均衡模版

编辑roles/nginx_lb/templates/default.conf.j2,修改为:

nginx 复制代码
upstream web_backend {
{% for host in groups['web'] %}
{% if host != (maintenance_host | default('')) %}  #maintenance_host 表示当前正在维护、需要临时摘除的节点。
    server {{ hostvars[host].ansible_host }}:80;
{% endif %}
{% endfor %}
}

server {
    listen 80;
    listen [::]:80;

    server_name _;

    location / {
        proxy_pass http://web_backend;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

2、修改Web组变量

修改inventories/prod/group_vars/web.yml中版本为v3.0.0

yml 复制代码
---
release_version: "v3.0.0"
release_message: "Ansible rolling deployment"

3、创建新的发布Playbook

playbooks/rolling_delop_lb_web.yml

yml 复制代码
---
- name: 带负载均衡摘除的滚动发布
  hosts: web
  become: true
  serial: 1
  any_errors_fatal: true

  tasks:
    - name: 检查当前首页
      ansible.builtin.stat:
        path: /data/www/index.html
      register: current_index

    - name: 执行滚动发布
      block:
        - name: 从负载均衡摘除当前节点
          ansible.builtin.template:
            src: ../roles/nginx_lb/templates/default.conf.j2
            dest: /etc/nginx/sites-available/default
            owner: root
            group: root
            mode: "0644"
          vars:
            maintenance_host: "{{ inventory_hostname }}"
          delegate_to: lb1

        - name: 检查负载均衡配置
          ansible.builtin.command: nginx -t
          changed_when: false
          delegate_to: lb1

        - name: 重载负载均衡
          ansible.builtin.service:
            name: nginx
            state: reloaded
          delegate_to: lb1

        - name: 备份当前首页
          ansible.builtin.copy:
            src: /data/www/index.html
            dest: /data/www/index.html.rollback
            remote_src: true
            owner: www-data
            group: www-data
            mode: "0644"
          when: current_index.stat.exists

        - name: 发布新首页
          ansible.builtin.template:
            src: ../roles/nginx_web/templates/index.html.j2
            dest: /data/www/index.html
            owner: www-data
            group: www-data
            mode: "0644"

        - name: 检查新版本
          ansible.builtin.uri:
            url: http://127.0.0.1/
            return_content: true
            status_code: 200
          register: health_result
          retries: 3
          delay: 2
          until:
            - health_result.status == 200
            - release_version in health_result.content

        - name: 将当前节点恢复到负载均衡
          ansible.builtin.template:
            src: ../roles/nginx_lb/templates/default.conf.j2
            dest: /etc/nginx/sites-available/default
            owner: root
            group: root
            mode: "0644"
          vars:
            maintenance_host: ""
          delegate_to: lb1

        - name: 检查并重载负载均衡
          ansible.builtin.shell: nginx -t && systemctl reload nginx
          changed_when: true
          delegate_to: lb1

        - name: 显示发布结果
          ansible.builtin.debug:
            msg: "{{ inventory_hostname }} 发布成功并已恢复流量"

      rescue:
        - name: 回滚旧首页
          ansible.builtin.copy:
            src: /data/www/index.html.rollback
            dest: /data/www/index.html
            remote_src: true
            owner: www-data
            group: www-data
            mode: "0644"
          when: current_index.stat.exists

        - name: 检查回滚后的服务
          ansible.builtin.uri:
            url: http://127.0.0.1/
            status_code: 200

        - name: 将回滚后的节点恢复到负载均衡
          ansible.builtin.template:
            src: ../roles/nginx_lb/templates/default.conf.j2
            dest: /etc/nginx/sites-available/default
            owner: root
            group: root
            mode: "0644"
          vars:
            maintenance_host: ""
          delegate_to: lb1

        - name: 检查并重载负载均衡
          ansible.builtin.shell: nginx -t && systemctl reload nginx
          changed_when: true
          delegate_to: lb1

        - name: 停止后续发布
          ansible.builtin.fail:
            msg: "{{ inventory_hostname }} 发布失败,已回滚并恢复流量"

4、执行发布

bash 复制代码
ansible-playbook playbooks/rolling_delop_lb_web.yml --syntax-check
ansible-playbook playbooks/rolling_delop_lb_web.yml

可以看到执行逻辑如下:

复制代码
摘除 web1 → 发布 web1 → 健康检查 → 恢复 web1
摘除 web2 → 发布 web2 → 健康检查 → 恢复 web2
摘除 web3 → 发布 web3 → 健康检查 → 恢复 web3

发布中的节点不会继续接收用户请求,而其他节点可以持续提供服务。

八、腾讯云动态 Inventory 管理主机

目前服务器 IP 手动写在 hosts.ini 中,服务器数量较多或频繁扩缩容时难以维护。动态 Inventory 将通过标签识别环境和服务器角色,避免手动维护 IP。

1、给腾讯云CVM添加标签

在腾讯云CVM控制台,给 5 台 CVM 添加以下标签:

CVM Environment Role ManagedBy
ansible prod control ansible
lb1 prod lb ansible
web1 prod web ansible
web2 prod web ansible
web3 prod web ansible

2、创建只读CAM子用户

该账号仅用于让 Ansible 查询腾讯云 CVM 和标签信息,不允许创建、修改或删除云资源。

(1)创建子用户

进入腾讯云控制台:【访问管理 CAM】------【用户】------【用户列表】------【新建用户】------【自定义创建】

创建以下用户以及权限:

用户名 访问方式 授予的只读权限
ansible-inventory 编程访问 QcloudCVMReadOnlyAccessQcloudTagReadOnlyAccess
(2)保存访问密钥

创建完成后会生成SecretIdSecretKey,请立即妥善保存,SecretKey 通常只完整显示一次。

(3)记录地域信息

我的 CVM 位于南京三区,对应地域通常是:ap-nanjing ,后面查询 CVM 时将使用这个地域。

3、安装腾讯云 SDK 并验证 CAM 权限

(1)创建Python虚拟环境

在 Ansible 控制服务器执行:

bash 复制代码
sudo apt install -y python3-venv

cd /data/ansible
python3 -m venv .venv
.venv/bin/pip install --upgrade pip
.venv/bin/pip install tencentcloud-sdk-python

验证 SDK:

bash 复制代码
.venv/bin/python -c "import tencentcloud; print('腾讯云 SDK 安装成功')"
(2)配置腾讯云 CAM 凭据

创建凭据文件

bash 复制代码
mkdir -p ~/.config/tencentcloud
chmod 700 ~/.config/tencentcloud
umask 077

安全输入凭据:

bash 复制代码
read -rsp "SecretId: " SID
echo
read -rsp "SecretKey: " SKEY
echo

输入时终端不会显示内容,输入完成后按回车即可。

将凭据写入配置文件:

bash 复制代码
printf 'export TENCENTCLOUD_SECRET_ID=%q\n' "$SID" \
  > ~/.config/tencentcloud/ansible.env

printf 'export TENCENTCLOUD_SECRET_KEY=%q\n' "$SKEY" \
  >> ~/.config/tencentcloud/ansible.env

设置文件权限并清理临时变量:

bash 复制代码
chmod 600 ~/.config/tencentcloud/ansible.env
unset SID SKEY

配置自动加载,将加载逻辑写入 .bashrc

bash 复制代码
grep -q 'tencentcloud/ansible.env' ~/.bashrc || cat >> ~/.bashrc <<'EOF'

# Tencent Cloud credentials for Ansible
if [ -f "$HOME/.config/tencentcloud/ansible.env" ]; then
    source "$HOME/.config/tencentcloud/ansible.env"
fi
EOF

立即加载

bash 复制代码
source ~/.bashrc
(3)验证配置

检查环境变量是否已加载,但不要直接输出密钥内容:

bash 复制代码
test -n "$TENCENTCLOUD_SECRET_ID" \
  && echo "SecretId 已加载" || echo "SecretId 未加载"

test -n "$TENCENTCLOUD_SECRET_KEY" \
  && echo "SecretKey 已加载" || echo "SecretKey 未加载"

检查文件权限:

bash 复制代码
ls -l ~/.config/tencentcloud/ansible.env  #预期权限为:-rw------- ubuntu ubuntu
(4)验证腾讯云 API
bash 复制代码
cd /data/ansible
.venv/bin/python scripts/test_tencentcloud.py

如果能够列出 CVM 实例,说明凭据已正确加载。以后重新登录服务器时,.bashrc 会自动加载凭据,无需再次手动输入。

4、创建腾讯云动态 Inventory

自动读取腾讯云 CVM,并根据 Role 标签生成 controllbweb 分组

(1)创建动态 Inventory 脚本
bash 复制代码
cd /data/ansible
mkdir -p inventories/dynamic

创建脚本:inventories/dynamic/tencent_cvm.py

python 复制代码
#!/data/ansible/.venv/bin/python

import json
import os
import sys

from tencentcloud.common import credential
from tencentcloud.cvm.v20170312 import cvm_client, models


# 腾讯云地域及实例标签筛选条件
REGION = "ap-nanjing"
ENVIRONMENT = "prod"
MANAGED_BY = "ansible"


def get_instances():
    """分页获取指定地域下的全部 CVM 实例。"""

    # 从环境变量读取 CAM API 凭据
    cred = credential.Credential(
        os.environ["TENCENTCLOUD_SECRET_ID"],
        os.environ["TENCENTCLOUD_SECRET_KEY"]
    )

    # 创建 CVM API 客户端
    client = cvm_client.CvmClient(cred, REGION)

    instances = []
    offset = 0
    limit = 100

    # 腾讯云 API 分页查询,每次最多获取 100 台
    while True:
        request = models.DescribeInstancesRequest()
        request.Offset = offset
        request.Limit = limit

        response = client.DescribeInstances(request)
        instances.extend(response.InstanceSet)

        # 已获取全部实例时退出循环
        if len(instances) >= response.TotalCount:
            break

        offset += limit

    return instances


def build_inventory():
    """根据腾讯云 CVM 标签生成 Ansible 动态 Inventory。"""

    # 保存每台主机的连接变量及自定义变量
    inventory = {
        "_meta": {
            "hostvars": {}
        }
    }

    for instance in get_instances():
        # 将标签列表转换为字典
        # 示例:{"env": "prod", "ManagedBy": "ansible", "Role": "web"}
        tags = {
            tag.Key: tag.Value
            for tag in (instance.Tags or [])
        }

        # 只纳管 env=prod 的实例
        if tags.get("env") != ENVIRONMENT:
            continue

        # 只纳管 ManagedBy=ansible 的实例
        if tags.get("ManagedBy") != MANAGED_BY:
            continue

        role = tags.get("Role")
        private_ips = instance.PrivateIpAddresses or []

        # 没有角色标签或内网 IP 时跳过
        if not role or not private_ips:
            continue

        # 使用腾讯云实例名称作为 Ansible 主机名
        hostname = instance.InstanceName

        # 根据 Role 标签生成主机组,如 web、lb、control
        group_name = role.lower()

        # 创建主机组并添加当前主机
        inventory.setdefault(group_name, {"hosts": []})
        inventory[group_name]["hosts"].append(hostname)

        # 设置主机连接参数和腾讯云信息
        inventory["_meta"]["hostvars"][hostname] = {
            "ansible_host": private_ips[0],
            "ansible_user": "ubuntu",
            "ansible_ssh_private_key_file":
                "/home/ubuntu/.ssh/ansible_ed25519",
            "ansible_python_interpreter": "/usr/bin/python3",

            # 自定义变量,可在 Playbook 中引用
            "tencent_instance_id": instance.InstanceId,
            "tencent_region": REGION,
            "tencent_role": role,
            "tencent_environment": tags.get("env")
        }

    # 对各主机组中的主机名排序,保证执行顺序稳定
    for group_data in inventory.values():
        if isinstance(group_data, dict) and "hosts" in group_data:
            group_data["hosts"].sort()

    return inventory

def main():
    """处理 Ansible 动态 Inventory 参数并输出 JSON。"""

    # 主机变量已放入 _meta.hostvars,因此 --host 返回空字典
    if len(sys.argv) == 2 and sys.argv[1] == "--host":
        print(json.dumps({}))
        return
    # 默认及 --list 模式返回完整 Inventory
    print(
        json.dumps(
            build_inventory(),
            ensure_ascii=False,
            indent=2
        )
    )

if __name__ == "__main__":
    main()

保存后验证:

bash 复制代码
chmod 750 inventories/dynamic/tencent_cvm.py

inventories/dynamic/tencent_cvm.py --list

ansible-inventory \
  -i inventories/dynamic/tencent_cvm.py \
  --graph

从上面的执行效果可以看到,动态 Inventory 已生成成功

(2)验证动态Inventory

测试业务节点连接

bash 复制代码
ansible 'lb:web' -i inventories/dynamic/tencent_cvm.py -m ping
(3)将原有静态 Inventory 切换为动态 Inventory

现在我们将动态 Inventory 脚本直接放到环境目录,统一管理生产主机清单、组变量和主机变量。

最终目录结构:

bash 复制代码
inventories/prod/
├── tencent_cvm.py		#从腾讯云动态获取生产服务器
├── group_vars/			#保存生产环境的组变量
├── host_vars/			#保存单台主机的专属变量
└── hosts.ini.bak		#原静态主机清单备份
  • 移动动态脚本
bash 复制代码
cd /data/ansible

mv inventories/dynamic/tencent_cvm.py inventories/prod/
chmod 750 inventories/prod/tencent_cvm.py
  • 备份静态 Inventory
bash 复制代码
mv inventories/prod/hosts.ini inventories/prod/hosts.ini.bak
  • 修改 ansible.cfg

将默认 Inventory 改为:

ini 复制代码
[defaults]
inventory = ./inventories/prod/tencent_cvm.py
roles_path = ./roles
host_key_checking = True
retry_files_enabled = False
forks = 20
timeout = 10

[ssh_connection]
ssh_args = -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/home/ubuntu/.ssh/known_hosts
pipelining = True
  • 验证配置
bash 复制代码
ansible-inventory --graph
ansible 'lb:web' -m ping
ansible-inventory --host web1

可以验证现有 Playbook 仍能识别目标主机:

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --list-hosts

动态 Inventory 切换完成,后续新增服务器,只需配置对应腾讯云标签,无需修改 hosts.ini

九、使用 Tags、Limit 和变量实现灰度发布

本章通过修改首页样式和发布版本,演示如何使用 Ansible 实现灰度发布。

发布目标:将首页升级为新的页面样式,并将版本从 v3.0.0 发布到 v4.0.0,先发布 web1 进行验证,验证成功后,再发布 web2web3

1、修改首页模版

将首页修改为新的页面样式:roles/nginx_web/templates/index.html.j2

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ inventory_hostname }}</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            min-height: 100vh;
            background: linear-gradient(135deg, #1f2937, #111827);
            font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #e5e7eb;
            padding: 20px;
        }

        .card {
            background-color: rgba(255, 255, 255, 0.05);
            border: 1px solid rgba(255, 255, 255, 0.1);
            border-radius: 16px;
            padding: 40px 48px;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
            text-align: center;
            min-width: 360px;
        }

        .host-title {
            font-size: 28px;
            font-weight: 600;
            color: #38bdf8;
            margin-bottom: 24px;
        }

        .item {
            font-size: 16px;
            margin: 12px 0;
        }

        .label {
            color: #9ca3af;
        }

        .value {
            color: #f9fafb;
            font-weight: 500;
        }

        .version-tag {
            display: inline-block;
            margin-top: 16px;
            padding: 6px 16px;
            background-color: #0ea5e9;
            border-radius: 999px;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="card">
        <div class="host-title">{{ inventory_hostname }}</div>

        <div class="item">
            <span class="label">节点 IP:</span>
            <span class="value">{{ ansible_host }}</span>
        </div>

        <div class="item">
            <span class="label">发布版本:</span>
            <span class="version-tag">{{ release_version }}</span>
        </div>

        <div class="item">
            <span class="label">备注信息:</span>
            <span class="value">{{ release_message }}</span>
        </div>
    </div>
</body>
</html>

模板中的变量会在发布时由 Ansible 自动替换:

bash 复制代码
{{ inventory_hostname }}  → 当前主机名
{{ ansible_host }}        → 当前主机 IP
{{ release_version }}     → 发布版本
{{ release_message }}     → 发布说明

2、修改发布版本

修改版本变量文件inventories/prod/group_vars/web.yml,内容修改为:

ini 复制代码
---
release_version: "v4.0.0"
release_message: "Ansible rolling deployment"

3、使用 Tags 区分任务

在 Playbook 中为任务添加标签:

Tags 作用
config 检查 Nginx 配置
deploy 执行完整发布流程
verify 执行健康检查和结果验证

修改playbooks/rolling_deploy_lb_web.yml代码:

yml 复制代码
---
- name: 带负载均衡摘除的滚动发布
  hosts: web
  order: sorted
  serial: 1
  become: true
  any_errors_fatal: true

  tasks:
    - name: 检查当前首页
      ansible.builtin.stat:
        path: /data/www/index.html
      register: current_index
      tags:
        - deploy

    - name: 执行滚动发布
      block:

        - name: 从负载均衡摘除当前节点
          ansible.builtin.template:
            src: ../roles/nginx_lb/templates/default.conf.j2
            dest: /etc/nginx/sites-available/default
            owner: root
            group: root
            mode: "0644"
          vars:
            maintenance_host: "{{ inventory_hostname }}"
          delegate_to: lb1
          tags:
            - deploy

        - name: 检查摘除后的 Nginx 配置
          ansible.builtin.command:
            cmd: nginx -t
          changed_when: false
          delegate_to: lb1
          become: true
          tags:
            - config
            - deploy

        - name: 重载摘除节点后的负载均衡配置
          ansible.builtin.service:
            name: nginx
            state: reloaded
          delegate_to: lb1
          become: true
          tags:
            - deploy

        - name: 备份当前首页
          ansible.builtin.copy:
            src: /data/www/index.html
            dest: /data/www/index.html.rollback
            remote_src: true
            owner: www-data
            group: www-data
            mode: "0644"
          when: current_index.stat.exists
          tags:
            - deploy

        - name: 发布新首页
          ansible.builtin.template:
            src: ../roles/nginx_web/templates/index.html.j2
            dest: /data/www/index.html
            owner: www-data
            group: www-data
            mode: "0644"
          tags:
            - deploy

        - name: 检查当前 Web 节点健康状态
          ansible.builtin.uri:
            url: http://127.0.0.1/
            return_content: true
            status_code: 200
          register: local_health
          retries: 3
          delay: 2
          until:
            - local_health.status == 200
            - release_version in local_health.content
          tags:
            - verify
            - deploy

        - name: 从负载均衡节点检查当前 Web 节点
          ansible.builtin.uri:
            url: "http://{{ hostvars[inventory_hostname].ansible_host }}/"
            return_content: true
            status_code: 200
          register: lb_health
          retries: 3
          delay: 2
          until:
            - lb_health.status == 200
            - release_version in lb_health.content
          delegate_to: lb1
          become: false
          tags:
            - verify
            - deploy

        - name: 将当前节点恢复到负载均衡
          ansible.builtin.template:
            src: ../roles/nginx_lb/templates/default.conf.j2
            dest: /etc/nginx/sites-available/default
            owner: root
            group: root
            mode: "0644"
          vars:
            maintenance_host: ""
          delegate_to: lb1
          become: true
          tags:
            - deploy

        - name: 检查恢复后的负载均衡配置
          ansible.builtin.command:
            cmd: nginx -t
          changed_when: false
          delegate_to: lb1
          become: true
          tags:
            - config
            - deploy

        - name: 重载恢复后的负载均衡配置
          ansible.builtin.service:
            name: nginx
            state: reloaded
          delegate_to: lb1
          become: true
          tags:
            - deploy

        - name: 显示发布结果
          ansible.builtin.debug:
            msg: "{{ inventory_hostname }} 发布 {{ release_version }} 成功并已恢复流量"
          tags:
            - verify
            - deploy

      rescue:

        - name: 回滚旧首页
          ansible.builtin.copy:
            src: /data/www/index.html.rollback
            dest: /data/www/index.html
            remote_src: true
            owner: www-data
            group: www-data
            mode: "0644"
          when: current_index.stat.exists
          tags:
            - deploy

        - name: 检查回滚后的 Web 服务
          ansible.builtin.uri:
            url: http://127.0.0.1/
            return_content: true
            status_code: 200
          register: rollback_health
          retries: 3
          delay: 2
          until: rollback_health.status == 200
          tags:
            - deploy

        - name: 将回滚后的节点恢复到负载均衡
          ansible.builtin.template:
            src: ../roles/nginx_lb/templates/default.conf.j2
            dest: /etc/nginx/sites-available/default
            owner: root
            group: root
            mode: "0644"
          vars:
            maintenance_host: ""
          delegate_to: lb1
          become: true
          tags:
            - deploy

        - name: 检查回滚后的负载均衡配置
          ansible.builtin.command:
            cmd: nginx -t
          changed_when: false
          delegate_to: lb1
          become: true
          tags:
            - config
            - deploy

        - name: 重载回滚后的负载均衡配置
          ansible.builtin.service:
            name: nginx
            state: reloaded
          delegate_to: lb1
          become: true
          tags:
            - deploy

        - name: 停止后续发布
          ansible.builtin.fail:
            msg: "{{ inventory_hostname }} 发布失败,已回滚并恢复流量"
          tags:
            - deploy

修改好后查看标签状态

bash 复制代码
#查看所有标签
ansible-playbook playbooks/rolling_deploy_lb_web.yml --list-tags

#查看指定标签对应的任务:config、deploy、verify
ansible-playbook playbooks/rolling_deploy_lb_web.yml --tags config --list-tasks
ansible-playbook playbooks/rolling_deploy_lb_web.yml --tags deploy --list-tasks
ansible-playbook playbooks/rolling_deploy_lb_web.yml --tags verify --list-tasks

4、使用limit限制目标主机

--limit 用于限制本次 Playbook 操作的服务器范围。

只操作 web1

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --limit web1 --tags deploy

操作 web2web3

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --limit 'web2:web3' --tags deploy

操作 web 组中除 web3 以外的主机:

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --limit 'web:!web3' --tags deploy

查看本次命令会匹配哪些主机:

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --limit web1 --list-hosts

5、灰度发布web1

先检查 Playbook 语法:

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --syntax-check

确认目标主机:

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --limit web1 --list-hosts

执行灰度发布:

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --limit web1 --tags deploy

6、验证web1

直接访问web1:

bash 复制代码
curl http://10.10.3.17

可以看到版本更新为了v4.0.0

7、发布剩余节点

确认 web1 正常后,发布 web2web3

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --limit 'web2:web3' --tags deploy

由于playbook中配置了:order: sortedserial: 1,发布执行顺序为 web2 → web3,如果某个节点发布失败,Playbook 会执行回滚,并停止后续发布。

8、验证全部节点

可以执行健康检查Tags:

bash 复制代码
ansible-playbook playbooks/rolling_deploy_lb_web.yml --tags verify

通过负载均衡节点访问:三个节点都返回最新版页面和版本号

十、Role 工程化变量管理

为什么要提取变量?

在最初的 Playbook 中,网站目录、Nginx 服务名、文件权限等配置可能直接写在任务和模板里。

ini 复制代码
path: /data/www
owner: www-data
group: www-data
mode: "0755"

这种写法存在以下问题:

  • 配置分散在多个文件中;
  • 修改目录或端口时需要查找多处;
  • 不同环境难以复用同一套 Role;
  • 容易出现修改遗漏或配置不一致。

因此,需要将固定配置提取为变量,实现:任务逻辑与配置分离,整套执行代码无需重复改动,仅通过变量即可适配开发、测试、生产等不同环境,既避免了漏改、错改的问题,也让配置集中清晰、维护更简单,大幅提升 Role 的通用性、规范性和可维护性,是 Ansible 工程化标准化的核心基础。

1、Role目录结构

其中:

  • defaults/main.yml:Role 默认变量;
  • tasks/main.yml:Role 执行任务;
  • handlers/main.yml:配置变化后的处理任务;
  • templates/:带变量的Jinja2 模板文件,运行时自动填充内容;
  • vars/main.yml:Role 变量,优先级较高,一般不放环境配置。

2、定义Role默认变量

编辑roles/nginx_web/defaults/main.yml,内容如下:

nginx 复制代码
---
# 网站根目录
web_root: /data/www

# Nginx 服务名称
nginx_service_name: nginx

# Nginx 网站配置文件
nginx_web_config: /etc/nginx/sites-available/default

# 网站文件所属用户和用户组
web_owner: www-data
web_group: www-data

# 网站目录和文件权限
web_dir_mode: "0755"
web_file_mode: "0644"

# Nginx 监听端口和域名
nginx_listen_port: 80
nginx_server_name: "_"

这些变量表示 Role 的默认配置,如果外部没有提供同名变量,Role 就使用这里的默认值。

3、修改tasks任务文件,引用变量

编辑roles/nginx_web/tasks/main.yml,将原本的内容:

改成如下:

yml 复制代码
---
- name: 安装 Nginx
  ansible.builtin.apt:
    name: "{{ nginx_service_name }}"
    state: present
    update_cache: true

- name: 创建网站根目录
  ansible.builtin.file:
    path: "{{ web_root }}"
    state: directory
    owner: "{{ web_owner }}"
    group: "{{ web_group }}"
    mode: "{{ web_dir_mode }}"

- name: 下发首页
  ansible.builtin.template:
    src: index.html.j2
    dest: "{{ web_root }}/index.html"
    owner: "{{ web_owner }}"
    group: "{{ web_group }}"
    mode: "{{ web_file_mode }}"

- name: 下发 Nginx 配置
  ansible.builtin.template:
    src: default.conf.j2
    dest: "{{ nginx_web_config }}"
    owner: root
    group: root
    mode: "{{ web_file_mode }}"
  notify: 重载 Nginx

- name: 启动并设置 Nginx 开机自启
  ansible.builtin.service:
    name: "{{ nginx_service_name }}"
    state: started
    enabled: true

任务文件只负责描述执行逻辑,不再直接写死具体配置。

4、修改 Nginx 配置模板

同样,修改roles/nginx_web/templates/default.conf.j2中参数为变量:

jinja2 复制代码
server {
    listen {{ nginx_listen_port }};
    listen [::]:{{ nginx_listen_port }};

    server_name {{ nginx_server_name }};

    root {{ web_root }};
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

模板变量会在执行时根据Role默认变量自动替换:

jinja2 复制代码
{{ nginx_listen_port }} → 80
{{ nginx_server_name }} → _
{{ web_root }}          → /data/www

5、配置环境变量

inventories/prod/group_vars/web.yml

当前可以只保存发布相关变量:

yml 复制代码
---
release_version: "v4.0.0"
release_message: "Ansible rolling deployment"

Role 会自动从 defaults/main.yml 获取其他默认变量。

如果需要针对当前环境修改配置,也可以在这里定义同名变量,例如修改网站目录:

yml 复制代码
---
release_version: "v4.0.0"
release_message: "Ansible rolling deployment"

web_root: /data/www/html
nginx_listen_port: 80
nginx_server_name: "_"

则当前 prod 环境中的 Web 节点会使用:

bash 复制代码
/data/www/html

而其他没有覆盖该变量的环境,仍然使用 Role 默认值。

变量优先级说明

Ansible 会根据约定自动加载变量:

【Role defaults】 < 【group_vars / host_vars】 < 【Playbook vars】 < 【命令行 -e】

6、检查并执行Role

检查 Playbook 语法:

bash 复制代码
ansible-playbook playbooks/deploy_web.yml \
  --syntax-check

预演变更:

bash 复制代码
ansible-playbook playbooks/deploy_web.yml \
  --check --diff

正式执行:

bash 复制代码
ansible-playbook playbooks/deploy_web.yml

7、验证部署结果

bash 复制代码
ansible web -a "ls -ld /data/www"
ansible web -a "curl -s http://localhost"
ansible web -b -a "nginx -t"

通过本次实践,我们从零搭建了 Ansible 控制端,并完成了腾讯云 CVM 服务器的自动化管理。整个过程涵盖了 SSH 免密登录、Inventory 主机清单、服务器初始化、Role 模块化、Nginx Web 集群部署、负载均衡、滚动发布、健康检查、失败回滚以及动态 Inventory 等内容。

在此基础上,我们还使用 TagsLimit 和变量覆盖实现了可控的灰度发布,并通过提取 Role 变量,将任务逻辑与环境配置分离,使同一套 Role 能够复用于不同环境。

相关推荐
跨境小彭2 小时前
Temu 广告投放实操:ROAS 底层逻辑与批量广告作业方案
大数据·人工智能·自动化·temu
吴佳浩 Alben2 小时前
走向 Memory OS:企业私有化 Agent 设计与实现
人工智能·深度学习·神经网络·语言模型·架构·自动化·ai编程
工业机器人视觉检测设备12 小时前
工序全流程自动化升级!云汇智能打造汽车天窗多机器人集成产线
机器人·自动化·汽车
宽海智能仓储物流14 小时前
航发自动化立体库异构系统改造:宽海智能30天联调技术全解析
运维·数据仓库·自动化
TomEval20 小时前
【接口自动化】13 - 接口数据驱动与报告
运维·windows·自动化
海宇数据21 小时前
零信任架构实战:基于海宇单人婚姻状态查询构建自动化KYC审核网关
运维·人工智能·架构·自动化
xhbh6661 天前
个人相册轻量化备份方案:自动增量备份落地实操
自动化·数据备份·文件备份·相册照片怎么备份·同步备份·文件夹自动备份
pt10431 天前
Cisco Splunk for AI Operations:数据处理原理与安全分析
运维·网络·自动化
子不语1801 天前
LabVIEW和PLC通过OPC通信
学习·自动化·plc