vagrant(9)Provision配置例子
vagrant provision
是 Vagrant 的核心功能之一,帮你自动在虚拟机上应用配置,省去手动操作的麻烦。它支持多种 provisioner(Shell、Ansible、Chef 等),灵活性很高。无论你是想快速搭个开发环境,还是调试复杂的部署脚本,vagrant provision
都能派上用场。
1.内容
- Provision 简介:自动化配置虚拟机环境(如安装软件、配置服务)。
- 支持的 Provision 类型:
- Shell:最简单的脚本方式,支持内联和外部脚本。
- Ansible:使用 playbook 进行声明式配置。
- Puppet:通过 manifests 实现配置管理。
- Chef:使用 cookbooks 进行自动化部署。
- Docker:直接在虚拟机中运行 Docker 容器。
- File:将主机文件传输到虚拟机。
- 触发 Provision:控制自动化执行时机(首次启动、每次启动、手动触发)。
- 最佳实践:编写可复用、可维护的脚本。
provisioning support
2.使用 Shell 脚本
Shell 是最简单直接的 Provision 方式,适合快速配置或小型项目。
内联 Shell 脚本:
- 编辑
Vagrantfile
,安装 Apache 并启动:1
2
3
4
5
6
7
8
9
10
11Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "shell", inline: <<-SHELL
apt update
apt install -y apache2
systemctl start apache2
systemctl enable apache2
echo "<h1>Hello from Vagrant Shell Provision</h1>" > /var/www/html/index.html
SHELL
end - 启动虚拟机并运行 Provision:
1
vagrant up --provision
- 验证:主机浏览器访问
http://localhost:8080
,应显示自定义页面。
- 编辑
外部 Shell 脚本:
- 创建一个
setup.sh
文件:1
2
3
4
5
6
apt update
apt install -y nginx
systemctl start nginx
systemctl enable nginx
echo "<h1>Hello from Nginx</h1>" > /usr/share/nginx/html/index.html - 修改
Vagrantfile
:1
2
3
4
5Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "shell", path: "setup.sh"
end - 确保脚本可执行:
1
chmod +x setup.sh
- 启动并验证:
1
vagrant up --provision
- 主机浏览器访问
http://localhost:8080
,显示 Nginx 页面。
- 创建一个
3.使用 File Provision
File Provision 用于将主机文件传输到虚拟机,适合传输配置文件或静态文件。
传输单个文件:
- 创建一个
index.html
文件:1
<h1>Hello from File Provision</h1>
- 修改
Vagrantfile
,将文件传输到虚拟机并安装 Nginx:1
2
3
4
5
6
7
8
9
10
11
12Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "file", source: "index.html", destination: "/tmp/index.html"
config.vm.provision "shell", inline: <<-SHELL
apt update
apt install -y nginx
mv /tmp/index.html /usr/share/nginx/html/index.html
systemctl start nginx
systemctl enable nginx
SHELL
end - 启动并验证:
1
vagrant up --provision
- 主机浏览器访问
http://localhost:8080
,显示传输的页面。
- 创建一个
传输目录:
- 创建一个目录
web_content
并添加文件:1
2mkdir web_content
echo "<h1>Directory Provision</h1>" > web_content/index.html - 修改
Vagrantfile
:1
2
3
4
5config.vm.provision "file", source: "web_content", destination: "/tmp/web_content"
config.vm.provision "shell", inline: <<-SHELL
mv /tmp/web_content /usr/share/nginx/html/web_content
systemctl restart nginx
SHELL - 访问
http://localhost:8080/web_content/index.html
,验证传输。
- 创建一个目录
4.使用 Ansible
Ansible 是一种声明式配置管理工具,适合复杂环境配置。
- 安装 Ansible(主机):
- 在主机上安装 Ansible(以 Ubuntu 为例):
1
2sudo apt update
sudo apt install -y ansible
- 在主机上安装 Ansible(以 Ubuntu 为例):
- 创建 Ansible Playbook:
- 创建一个
playbook.yml
文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17- hosts: all
become: yes
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Start Nginx
service:
name: nginx
state: started
enabled: yes
- name: Copy custom index page
copy:
content: "<h1>Hello from Ansible</h1>"
dest: /usr/share/nginx/html/index.html
- 创建一个
- 配置 Vagrant 使用 Ansible:
- 修改
Vagrantfile
:1
2
3
4
5
6
7Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
end
end
- 修改
- 启动并验证:
- 启动虚拟机:
1
vagrant up --provision
- 主机浏览器访问
http://localhost:8080
,显示 Ansible 配置的页面。(本机须提前安装好ansible及配置好联通性)
- 启动虚拟机:
ansible
- ansible #本机ansible连接到虚机上执行任务
- ansible_local #在虚机内执行任务(须提前安装好ansible)
5.使用 Puppet
Puppet 是另一种配置管理工具,适合企业级自动化。
- 安装 Puppet Agent(虚拟机):
- Vagrant 会自动安装 Puppet Agent,无需手动操作。
- 创建 Puppet Manifest:
- 创建一个
manifests/default.pp
文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package { 'nginx':
ensure => installed,
}
service { 'nginx':
ensure => running,
enable => true,
require => Package['nginx'],
}
file { '/usr/share/nginx/html/index.html':
ensure => file,
content => '<h1>Hello from Puppet</h1>',
require => Package['nginx'],
}
- 创建一个
- 配置 Vagrant 使用 Puppet:
- 修改
Vagrantfile
:1
2
3
4
5
6
7
8Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "puppet" do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "default.pp"
end
end
- 修改
- 启动并验证:
- 启动虚拟机:
1
vagrant up --provision
- 主机浏览器访问
http://localhost:8080
,显示 Puppet 配置的页面。
- 启动虚拟机:
6.使用 Chef
Chef 使用 cookbooks 进行配置管理,适合复杂自动化需求。
- 安装 Chef DK(主机,推荐):
- 在主机上安装 Chef DK(以 Ubuntu 为例):
1
2wget https://packages.chef.io/files/stable/chefdk/4.13.3/ubuntu/20.04/chefdk_4.13.3-1_amd64.deb
sudo dpkg -i chefdk_4.13.3-1_amd64.deb
- 在主机上安装 Chef DK(以 Ubuntu 为例):
- 创建 Chef Cookbook:
- 使用
chef
命令生成 cookbook:1
chef generate cookbook cookbooks/myweb
- 编辑
cookbooks/myweb/recipes/default.rb
:1
2
3
4
5
6
7
8
9
10
11
12package 'nginx' do
action :install
end
service 'nginx' do
action [:enable, :start]
end
file '/usr/share/nginx/html/index.html' do
content '<h1>Hello from Chef</h1>'
action :create
end
- 使用
- 配置 Vagrant 使用 Chef:
- 修改
Vagrantfile
:1
2
3
4
5
6
7
8Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "chef_solo" do |chef|
chef.add_recipe "myweb::default"
chef.cookbooks_path = "cookbooks"
end
end
- 修改
- 启动并验证:
- 启动虚拟机:
1
vagrant up --provision
- 主机浏览器访问
http://localhost:8080
,显示 Chef 配置的页面。
- 启动虚拟机:
8.使用 Docker
Docker Provision 允许在虚拟机中直接运行 Docker 容器。
- 配置 Docker Provision:
- 修改
Vagrantfile
,安装 Docker 并运行一个 Nginx 容器:1
2
3
4
5
6
7
8
9Vagrant.configure("2") do |config|
config.vm.box = "Ubuntu/jammy64"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "docker" do |d|
d.run "nginx",
image: "nginx:latest",
args: "-p 80:80"
end
end
- 修改
- 启动并验证:
- 启动虚拟机:
1
vagrant up --provision
- 主机浏览器访问
http://localhost:8080
,显示 Nginx 容器页面。
- 启动虚拟机:
9.控制 Provision 触发
- 手动触发:
- 启动时不运行 Provision:
1
vagrant up --no-provision
- 手动运行:
1
vagrant provision
- 启动时不运行 Provision:
- 每次启动触发:
- 在
Vagrantfile
中设置:1
config.vm.provision "shell", path: "setup.sh", run: "always"
- 在
run: once,always,never
10.代码示例
- Shell 内联:
1
2
3
4
5config.vm.provision "shell", inline: <<-SHELL
apt update
apt install -y apache2
systemctl start apache2
SHELL - File Provision:
1
config.vm.provision "file", source: "index.html", destination: "/tmp/index.html"
- Ansible Playbook (
playbook.yml
):1
2
3
4
5
6
7- hosts: all
become: yes
tasks:
- name: Install Nginx
apt:
name: nginx
state: present - Puppet Manifest (
default.pp
):1
2
3package { 'nginx':
ensure => installed,
} - Chef Recipe (
default.rb
):1
2
3package 'nginx' do
action :install
end - Docker Provision:
1
2
3config.vm.provision "docker" do |d|
d.run "nginx", image: "nginx:latest", args: "-p 80:80"
end
11.错误处理
- Shell 脚本失败:
- 问题:语法错误或权限不足。
- 解决:
- 检查脚本语法。
- 确保外部脚本可执行(
chmod +x setup.sh
)。 - 添加调试输出:
set -x
或echo "Step X"
。 - 查看详细日志:
vagrant up --provision --debug
.
- File Provision 失败:
- 问题:文件未找到或权限不足。
- 解决:
- 确保源文件存在且路径正确。
- 检查主机文件权限(
chmod 644 index.html
)。
- Ansible 失败:
- 问题:Ansible 未安装或 playbook 错误。
- 解决:
- 确保主机已安装 Ansible。
- 检查 playbook 语法:
ansible-playbook playbook.yml --syntax-check
. - 确保虚拟机支持 SSH(默认即可)。
- Puppet 失败:
- 问题:Puppet Agent 安装失败或 manifest 语法错误。
- 解决:
- 检查 Puppet 版本兼容性。
- 使用
puppet parser validate default.pp
检查语法。
- Chef 失败:
- 问题:Chef DK 未安装或 recipe 错误。
- 解决:
- 确保主机已安装 Chef DK。
- 检查 recipe 语法:
chef-client --local-mode -z -r myweb::default
.
- Docker 失败:
- 问题:Docker 未安装或镜像拉取失败。
- 解决:
- 确保虚拟机网络正常。
- 检查 Docker 镜像是否存在:
docker pull nginx:latest
.