You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vagrant多SSH用户执行多Ansible Playbook配置问题

解决方案:分阶段配置两个Ansible Provisioner

我刚好处理过几乎一模一样的场景,核心思路就是把配置拆成两个独立的Ansible阶段:先用默认的vagrant用户完成新用户的创建和权限配置,再切换到新用户执行后续的核心配置(包括删除vagrant用户)。下面是具体的实现步骤和代码示例:

第一步:初始阶段 - 创建provisioner用户(以vagrant身份执行)

首先我们需要一个初始化Playbook(比如initial_setup.yml),用来创建provisioner用户、配置SSH密钥并赋予sudo权限:

# initial_setup.yml
- name: 创建provisioner用户并配置权限
  hosts: all
  become: yes
  tasks:
    - name: 创建provisioner用户
      user:
        name: provisioner
        shell: /bin/bash
        create_home: yes
        groups: sudo

    - name: 给provisioner用户配置免sudo权限
      lineinfile:
        path: /etc/sudoers.d/provisioner
        line: "provisioner ALL=(ALL) NOPASSWD: ALL"
        create: yes
        mode: 0440

    - name: 生成provisioner用户的SSH密钥对
      user:
        name: provisioner
        generate_ssh_key: yes
        ssh_key_bits: 2048
        ssh_key_file: .ssh/id_rsa

    - name: 复制provisioner的私钥到Vagrant主机(方便后续连接)
      fetch:
        src: /home/provisioner/.ssh/id_rsa
        dest: ./provisioner_key
        flat: yes
        mode: 0600

然后在Vagrantfile里配置第一个Ansible Provisioner,用默认的vagrant用户执行这个初始化脚本:

# Vagrantfile片段
Vagrant.configure("2") do |config|
  # 虚拟机基础配置(略)
  config.vm.box = "ubuntu/focal64"

  # 第一阶段:用vagrant用户执行初始化Playbook
  config.vm.provision "ansible_initial", type: "ansible" do |ansible|
    ansible.playbook = "initial_setup.yml"
    # 这里用默认的vagrant用户和密钥,不需要额外配置
  end

第二步:主配置阶段 - 切换到provisioner用户执行

接下来是核心配置的Playbook(比如main_config.yml),里面包含删除vagrant用户的任务:

# main_config.yml
- name: 执行系统核心配置
  hosts: all
  become: yes
  tasks:
    - name: 删除不安全的vagrant用户
      user:
        name: vagrant
        state: absent
        remove: yes

    # 其他系统配置任务...

然后在Vagrantfile里添加第二个Ansible Provisioner,显式指定用provisioner用户和刚才生成的私钥连接:

# Vagrantfile继续添加
  # 第二阶段:切换到provisioner用户执行主配置
  config.vm.provision "ansible_main", type: "ansible" do |ansible|
    ansible.playbook = "main_config.yml"
    # 指定新的SSH用户
    ansible.raw_arguments = ["--user=provisioner"]
    # 指定刚才复制到主机的私钥路径
    ansible.ssh_private_key_path = "./provisioner_key"
    # 关闭主机密钥检查(开发环境可选,生产环境不建议)
    ansible.raw_arguments << "-o StrictHostKeyChecking=no"
  end
end

关键细节提醒

  • 一定要确保provisioner用户有免sudo权限,不然执行删除vagrant用户这类需要root权限的任务会失败;
  • 私钥的权限必须是0600,不然SSH会拒绝使用;
  • 如果你的环境不允许把私钥复制到Vagrant主机,也可以在初始化阶段把你本地的公钥加到provisioner用户的authorized_keys里,然后指定本地的私钥路径;
  • 第二阶段的Provisioner必须在第一阶段之后执行,Vagrant会按配置顺序运行provisioner。

这样配置后,Vagrant会先以vagrant用户完成新用户的创建,再自动切换到provisioner用户执行核心配置,完美解决你的需求。

内容的提问来源于stack exchange,提问作者Rob Carpenter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:49:34