Vagrant:运行 在所有 VM 启动后进行 Ansible 配置,Ansible 无法连接到所有主机
Vagrant: running Ansible provisioning after all VMs booted, Ansible cannot connect to all hosts
我正在尝试弄清楚如何以正确的方式将 Ansible 与 Vagrant 一起使用。默认情况下,Vagrant 似乎正在隔离每个框的 Ansible 执行,并在每个框之后部分执行剧本,因为它适用于循环中的单个框。我发现这非常适得其反,我曾尝试在所有主机启动后欺骗 Vagrant 在所有主机上执行剧本,但它似乎是 Ansible,从 Vagrant 启动时一次只看到一个盒子。
编辑:这些是我正在使用的版本:
流浪者:2.2.6
可靠的:2.5.1
虚拟机:6.1
当我运行它在主机出现后独立于ansible-playbook可执行文件时,itsef的剧本(带有hosts.ini)执行没有问题,所以问题出在我身上流浪的文件。我就是想不通。
这是 Vagrant 文件:
# -*- mode: ruby -*-
# vi: set ft=ruby :
IMAGE_NAME = "ubuntu/bionic64"
Vagrant.configure("2") do |config|
config.ssh.insert_key = false
config.vm.box = IMAGE_NAME
# Virtualbox configuration
config.vm.provider "virtualbox" do |v|
v.memory = 4096
v.cpus = 2
#v.linked_clone = true
end
# master and node definition
boxes = [
{ :name => "k8s-master", :ip => "192.168.50.10" },
{ :name => "k8s-node-1", :ip => "192.168.50.11" }
]
boxes.each do |opts|
config.vm.define opts[:name] do |config|
config.vm.hostname = opts[:name]
config.vm.network :private_network, ip: opts[:ip]
if opts[:name] == "k8s-node-1"
config.vm.provision "ansible_local" do |ansible|
ansible.compatibility_mode = "2.0"
ansible.limit = "all"
ansible.config_file = "ansible.cfg"
ansible.become = true
ansible.playbook = "playbook.yml"
ansible.groups = {
"masters" => ["k8s-master"],
"nodes" => ["k8s-node-1"]
}
end
end
end
end
end
ansible.cfg
[defaults]
connection = smart
timeout = 60
deprecation_warnings = False
host_key_checking = False
inventory = hosts.ini
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes
hosts.ini
[masters]
k8s-master ansible_host=192.168.50.10 ansible_user=vagrant
[nodes]
k8s-node-1 ansible_host=192.168.50.11 ansible_user=vagrant
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key
playbook.yml
- hosts: all
become: yes
tasks:
- name: Update apt cache.
apt: update_cache=yes cache_valid_time=3600
when: ansible_os_family == 'Debian'
- name: Ensure swap is disabled.
mount:
name: swap
fstype: swap
state: absent
- name: Disable swap.
command: swapoff -a
when: ansible_swaptotal_mb > 0
- name: create the 'mobile' user
user: name=mobile append=yes state=present createhome=yes shell=/bin/bash
- name: allow 'mobile' to have passwordless sudo
lineinfile:
dest: /etc/sudoers
line: 'mobile ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
- name: set up authorized keys for the mobile user
authorized_key:
user: mobile
key: "{{ lookup('pipe','cat ssh_keys/*.pub') }}"
state: present
exclusive: yes
- hosts: all
become: yes
tasks:
- name: install Docker
apt:
name: docker.io
state: present
update_cache: true
- name: install APT Transport HTTPS
apt:
name: apt-transport-https
state: present
- name: add Kubernetes apt-key
apt_key:
url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
state: present
- name: add Kubernetes' APT repository
apt_repository:
repo: deb http://apt.kubernetes.io/ kubernetes-xenial main
state: present
filename: 'kubernetes'
- name: install kubelet
apt:
name: kubelet=1.17.0-00
state: present
update_cache: true
- name: install kubeadm
apt:
name: kubeadm=1.17.0-00
state: present
- hosts: masters
become: yes
tasks:
- name: install kubectl
apt:
name: kubectl=1.17.0-00
state: present
force: yes
- hosts: k8s-master
become: yes
tasks:
- name: check docker status
systemd:
state: started
name: docker
- name: initialize the cluster
shell: kubeadm init --apiserver-advertise-address 192.168.50.10 --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt
args:
chdir: $HOME
creates: cluster_initialized.txt
- name: create .kube directory
become: yes
become_user: mobile
file:
path: $HOME/.kube
state: directory
mode: 0755
- name: copy admin.conf to user's kube config
copy:
src: /etc/kubernetes/admin.conf
dest: /home/mobile/.kube/config
remote_src: yes
owner: mobile
- name: install Pod network
become: yes
become_user: mobile
shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml >> pod_network_setup.txt
args:
chdir: $HOME
creates: pod_network_setup.txt
- hosts: k8s-master
become: yes
gather_facts: false
tasks:
- name: get join command
shell: kubeadm token create --print-join-command 2>/dev/null
register: join_command_raw
- name: set join command
set_fact:
join_command: "{{ join_command_raw.stdout_lines[0] }}"
- hosts: nodes
become: yes
tasks:
- name: check docker status
systemd:
state: started
name: docker
- name: join cluster
shell: "{{ hostvars['k8s-master'].join_command }} >> node_joined.txt"
args:
chdir: $HOME
creates: node_joined.txt
剧本试图针对 k8s-master 执行的那一刻,它失败了:
fatal: [k8s-master]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname k8s-master: Temporary failure in name resolution", "unreachable": true}
主机已启动。 SSH 有效。
谁能帮我解决这个问题?
谢谢!
我已经成功地在 Vagrant 中使用了 Ansible。
以下是我为使其工作所做的工作:
重现步骤:
- 安装 Vagrant、Virtualbox
- 创建所有必要的文件和目录
- ansible.cfg
- playbook.yml
- 主机
- insecure_private_key
- Vagrant 文件
- 测试
安装 Vagrant、Virtualbox
按照适当站点的安装指南进行操作:
创建所有必要的文件和目录
此示例基于原始海报文件。
创建vagrant
和ansible
文件夹来存储所有配置文件和目录。它的结构可能如下所示:
vagrant
- 目录
- Vagrantfile - 具有主要配置的文件
ansible
- 目录
- ansible.cfg - Ansible的配置文件
- playbook.yml - 包含 Ansible 执行步骤的文件
- hosts - 包含有关主机信息的文件
- insecure_private_key - 创建机器的私钥
Ansible
文件夹是一个单独的目录,将被复制到 k8s-node-1
。
默认情况下,Vagrant 共享一个 vagrant
文件夹,权限为 777
。它允许所有者、组和其他人可以完全访问其中的所有内容。
手动登录到虚拟机和vagrant
目录中的运行ning ansible-playbook
命令将输出与权限相关的错误。它会使 ansible.cfg
和 insecure_private_key
无用。
Ansible.cfg
Ansible.cfg
是Ansible的配置文件。下面使用的示例:
[defaults]
connection = smart
timeout = 60
deprecation_warnings = False
host_key_checking = False
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes
在 ansible
目录中创建 ansible.cfg
。
Playbook.yml
示例 playbook.yml
是一个包含 Ansible 执行步骤的文件。
它将检查连接并测试组是否配置正确:
- name: Check all connections
hosts: all
tasks:
- name: Ping
ping:
- name: Check specific connection to masters
hosts: masters
tasks:
- name: Ping
ping:
- name: Check specific connection to nodes
hosts: nodes
tasks:
- name: Ping
ping:
在 ansible
目录中创建 playbook.yml
。
Insecure_private_key
要成功连接到虚拟机,您需要 insecure_private_key
。您可以通过在 vagrant
目录中调用命令:$ vagrant init
来创建它。
它将在 HOME_DIRECTORY/.vagrant.d
中的物理机中创建 insecure_private_key
。
将其复制到 ansible
文件夹。
主机
下面的hosts
文件负责将有关主机的信息传递给Ansible:
[masters]
k8s-master ansible_host=192.168.50.10 ansible_user=vagrant
[nodes]
k8s-node-1 ansible_host=192.168.50.11 ansible_user=vagrant
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=/ansible/insecure_private_key
在 ansible
目录中创建 hosts
文件。
具体请看: ansible_ssh_private_key_file=/ansible/insecure_private_key
这是 Ansible 使用前面提到的密钥的声明。
流浪汉
Vagrant
文件为主配置文件:
# -*- mode: ruby -*-
# vi: set ft=ruby :
IMAGE_NAME = "ubuntu/bionic64"
Vagrant.configure("2") do |config|
config.ssh.insert_key = false
config.vm.box = IMAGE_NAME
# Virtualbox configuration
config.vm.provider "virtualbox" do |v|
v.memory = 4096
v.cpus = 2
#v.linked_clone = true
end
# master and node definition
boxes = [
{ :name => "k8s-master", :ip => "192.168.50.10" },
{ :name => "k8s-node-1", :ip => "192.168.50.11" }
]
boxes.each do |opts|
config.vm.define opts[:name] do |config|
config.vm.hostname = opts[:name]
config.vm.network :private_network, ip: opts[:ip]
if opts[:name] == "k8s-node-1"
config.vm.synced_folder "../ansible", "/ansible", :mount_options => ["dmode=700", "fmode=700"]
config.vm.provision "ansible_local" do |ansible|
ansible.compatibility_mode = "2.0"
ansible.limit = "all"
ansible.config_file = "/ansible/ansible.cfg"
ansible.become = true
ansible.playbook = "/ansible/playbook.yml"
ansible.inventory_path = "/ansible/hosts"
end
end
end
end
end
具体请看:
config.vm.synced_folder "../ansible", "/ansible", :mount_options => ["dmode=700", "fmode=700"]
config.vm.synced_folder
会将 ansible
目录复制到 k8s-node-1
,其中包含所有文件。
它将设置完全访问权限仅对所有者(流浪用户)。
ansible.inventory_path = "/ansible/hosts"
ansible.inventory_path
会告诉 Vagrant 为 Ansible 提供 hosts
文件。
测试
要从 vagrant
目录检查 运行 以下命令:
$ vagrant up
负责 Ansible 的输出部分应如下所示:
==> k8s-node-1: Running provisioner: ansible_local...
k8s-node-1: Installing Ansible...
k8s-node-1: Running ansible-playbook...
PLAY [Check all connections] ***************************************************
TASK [Gathering Facts] *********************************************************
ok: [k8s-master]
ok: [k8s-node-1]
TASK [Ping] ********************************************************************
ok: [k8s-master]
ok: [k8s-node-1]
PLAY [Check specific connection to masters] ************************************
TASK [Gathering Facts] *********************************************************
ok: [k8s-master]
TASK [Ping] ********************************************************************
ok: [k8s-master]
PLAY [Check specific connection to nodes] **************************************
TASK [Gathering Facts] *********************************************************
ok: [k8s-node-1]
TASK [Ping] ********************************************************************
ok: [k8s-node-1]
PLAY RECAP *********************************************************************
k8s-master : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
k8s-node-1 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
我正在尝试弄清楚如何以正确的方式将 Ansible 与 Vagrant 一起使用。默认情况下,Vagrant 似乎正在隔离每个框的 Ansible 执行,并在每个框之后部分执行剧本,因为它适用于循环中的单个框。我发现这非常适得其反,我曾尝试在所有主机启动后欺骗 Vagrant 在所有主机上执行剧本,但它似乎是 Ansible,从 Vagrant 启动时一次只看到一个盒子。
编辑:这些是我正在使用的版本:
流浪者:2.2.6 可靠的:2.5.1 虚拟机:6.1
当我运行它在主机出现后独立于ansible-playbook可执行文件时,itsef的剧本(带有hosts.ini)执行没有问题,所以问题出在我身上流浪的文件。我就是想不通。
这是 Vagrant 文件:
# -*- mode: ruby -*-
# vi: set ft=ruby :
IMAGE_NAME = "ubuntu/bionic64"
Vagrant.configure("2") do |config|
config.ssh.insert_key = false
config.vm.box = IMAGE_NAME
# Virtualbox configuration
config.vm.provider "virtualbox" do |v|
v.memory = 4096
v.cpus = 2
#v.linked_clone = true
end
# master and node definition
boxes = [
{ :name => "k8s-master", :ip => "192.168.50.10" },
{ :name => "k8s-node-1", :ip => "192.168.50.11" }
]
boxes.each do |opts|
config.vm.define opts[:name] do |config|
config.vm.hostname = opts[:name]
config.vm.network :private_network, ip: opts[:ip]
if opts[:name] == "k8s-node-1"
config.vm.provision "ansible_local" do |ansible|
ansible.compatibility_mode = "2.0"
ansible.limit = "all"
ansible.config_file = "ansible.cfg"
ansible.become = true
ansible.playbook = "playbook.yml"
ansible.groups = {
"masters" => ["k8s-master"],
"nodes" => ["k8s-node-1"]
}
end
end
end
end
end
ansible.cfg
[defaults]
connection = smart
timeout = 60
deprecation_warnings = False
host_key_checking = False
inventory = hosts.ini
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes
hosts.ini
[masters]
k8s-master ansible_host=192.168.50.10 ansible_user=vagrant
[nodes]
k8s-node-1 ansible_host=192.168.50.11 ansible_user=vagrant
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key
playbook.yml
- hosts: all
become: yes
tasks:
- name: Update apt cache.
apt: update_cache=yes cache_valid_time=3600
when: ansible_os_family == 'Debian'
- name: Ensure swap is disabled.
mount:
name: swap
fstype: swap
state: absent
- name: Disable swap.
command: swapoff -a
when: ansible_swaptotal_mb > 0
- name: create the 'mobile' user
user: name=mobile append=yes state=present createhome=yes shell=/bin/bash
- name: allow 'mobile' to have passwordless sudo
lineinfile:
dest: /etc/sudoers
line: 'mobile ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
- name: set up authorized keys for the mobile user
authorized_key:
user: mobile
key: "{{ lookup('pipe','cat ssh_keys/*.pub') }}"
state: present
exclusive: yes
- hosts: all
become: yes
tasks:
- name: install Docker
apt:
name: docker.io
state: present
update_cache: true
- name: install APT Transport HTTPS
apt:
name: apt-transport-https
state: present
- name: add Kubernetes apt-key
apt_key:
url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
state: present
- name: add Kubernetes' APT repository
apt_repository:
repo: deb http://apt.kubernetes.io/ kubernetes-xenial main
state: present
filename: 'kubernetes'
- name: install kubelet
apt:
name: kubelet=1.17.0-00
state: present
update_cache: true
- name: install kubeadm
apt:
name: kubeadm=1.17.0-00
state: present
- hosts: masters
become: yes
tasks:
- name: install kubectl
apt:
name: kubectl=1.17.0-00
state: present
force: yes
- hosts: k8s-master
become: yes
tasks:
- name: check docker status
systemd:
state: started
name: docker
- name: initialize the cluster
shell: kubeadm init --apiserver-advertise-address 192.168.50.10 --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt
args:
chdir: $HOME
creates: cluster_initialized.txt
- name: create .kube directory
become: yes
become_user: mobile
file:
path: $HOME/.kube
state: directory
mode: 0755
- name: copy admin.conf to user's kube config
copy:
src: /etc/kubernetes/admin.conf
dest: /home/mobile/.kube/config
remote_src: yes
owner: mobile
- name: install Pod network
become: yes
become_user: mobile
shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml >> pod_network_setup.txt
args:
chdir: $HOME
creates: pod_network_setup.txt
- hosts: k8s-master
become: yes
gather_facts: false
tasks:
- name: get join command
shell: kubeadm token create --print-join-command 2>/dev/null
register: join_command_raw
- name: set join command
set_fact:
join_command: "{{ join_command_raw.stdout_lines[0] }}"
- hosts: nodes
become: yes
tasks:
- name: check docker status
systemd:
state: started
name: docker
- name: join cluster
shell: "{{ hostvars['k8s-master'].join_command }} >> node_joined.txt"
args:
chdir: $HOME
creates: node_joined.txt
剧本试图针对 k8s-master 执行的那一刻,它失败了:
fatal: [k8s-master]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname k8s-master: Temporary failure in name resolution", "unreachable": true}
主机已启动。 SSH 有效。
谁能帮我解决这个问题?
谢谢!
我已经成功地在 Vagrant 中使用了 Ansible。
以下是我为使其工作所做的工作:
重现步骤:
- 安装 Vagrant、Virtualbox
- 创建所有必要的文件和目录
- ansible.cfg
- playbook.yml
- 主机
- insecure_private_key
- Vagrant 文件
- 测试
安装 Vagrant、Virtualbox
按照适当站点的安装指南进行操作:
创建所有必要的文件和目录
此示例基于原始海报文件。
创建vagrant
和ansible
文件夹来存储所有配置文件和目录。它的结构可能如下所示:
vagrant
- 目录- Vagrantfile - 具有主要配置的文件
ansible
- 目录- ansible.cfg - Ansible的配置文件
- playbook.yml - 包含 Ansible 执行步骤的文件
- hosts - 包含有关主机信息的文件
- insecure_private_key - 创建机器的私钥
Ansible
文件夹是一个单独的目录,将被复制到 k8s-node-1
。
默认情况下,Vagrant 共享一个 vagrant
文件夹,权限为 777
。它允许所有者、组和其他人可以完全访问其中的所有内容。
手动登录到虚拟机和vagrant
目录中的运行ning ansible-playbook
命令将输出与权限相关的错误。它会使 ansible.cfg
和 insecure_private_key
无用。
Ansible.cfg
Ansible.cfg
是Ansible的配置文件。下面使用的示例:
[defaults]
connection = smart
timeout = 60
deprecation_warnings = False
host_key_checking = False
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes
在 ansible
目录中创建 ansible.cfg
。
Playbook.yml
示例 playbook.yml
是一个包含 Ansible 执行步骤的文件。
它将检查连接并测试组是否配置正确:
- name: Check all connections
hosts: all
tasks:
- name: Ping
ping:
- name: Check specific connection to masters
hosts: masters
tasks:
- name: Ping
ping:
- name: Check specific connection to nodes
hosts: nodes
tasks:
- name: Ping
ping:
在 ansible
目录中创建 playbook.yml
。
Insecure_private_key
要成功连接到虚拟机,您需要 insecure_private_key
。您可以通过在 vagrant
目录中调用命令:$ vagrant init
来创建它。
它将在 HOME_DIRECTORY/.vagrant.d
中的物理机中创建 insecure_private_key
。
将其复制到 ansible
文件夹。
主机
下面的hosts
文件负责将有关主机的信息传递给Ansible:
[masters]
k8s-master ansible_host=192.168.50.10 ansible_user=vagrant
[nodes]
k8s-node-1 ansible_host=192.168.50.11 ansible_user=vagrant
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_user=vagrant
ansible_ssh_private_key_file=/ansible/insecure_private_key
在 ansible
目录中创建 hosts
文件。
具体请看: ansible_ssh_private_key_file=/ansible/insecure_private_key
这是 Ansible 使用前面提到的密钥的声明。
流浪汉
Vagrant
文件为主配置文件:
# -*- mode: ruby -*-
# vi: set ft=ruby :
IMAGE_NAME = "ubuntu/bionic64"
Vagrant.configure("2") do |config|
config.ssh.insert_key = false
config.vm.box = IMAGE_NAME
# Virtualbox configuration
config.vm.provider "virtualbox" do |v|
v.memory = 4096
v.cpus = 2
#v.linked_clone = true
end
# master and node definition
boxes = [
{ :name => "k8s-master", :ip => "192.168.50.10" },
{ :name => "k8s-node-1", :ip => "192.168.50.11" }
]
boxes.each do |opts|
config.vm.define opts[:name] do |config|
config.vm.hostname = opts[:name]
config.vm.network :private_network, ip: opts[:ip]
if opts[:name] == "k8s-node-1"
config.vm.synced_folder "../ansible", "/ansible", :mount_options => ["dmode=700", "fmode=700"]
config.vm.provision "ansible_local" do |ansible|
ansible.compatibility_mode = "2.0"
ansible.limit = "all"
ansible.config_file = "/ansible/ansible.cfg"
ansible.become = true
ansible.playbook = "/ansible/playbook.yml"
ansible.inventory_path = "/ansible/hosts"
end
end
end
end
end
具体请看:
config.vm.synced_folder "../ansible", "/ansible", :mount_options => ["dmode=700", "fmode=700"]
config.vm.synced_folder
会将 ansible
目录复制到 k8s-node-1
,其中包含所有文件。
它将设置完全访问权限仅对所有者(流浪用户)。
ansible.inventory_path = "/ansible/hosts"
ansible.inventory_path
会告诉 Vagrant 为 Ansible 提供 hosts
文件。
测试
要从 vagrant
目录检查 运行 以下命令:
$ vagrant up
负责 Ansible 的输出部分应如下所示:
==> k8s-node-1: Running provisioner: ansible_local...
k8s-node-1: Installing Ansible...
k8s-node-1: Running ansible-playbook...
PLAY [Check all connections] ***************************************************
TASK [Gathering Facts] *********************************************************
ok: [k8s-master]
ok: [k8s-node-1]
TASK [Ping] ********************************************************************
ok: [k8s-master]
ok: [k8s-node-1]
PLAY [Check specific connection to masters] ************************************
TASK [Gathering Facts] *********************************************************
ok: [k8s-master]
TASK [Ping] ********************************************************************
ok: [k8s-master]
PLAY [Check specific connection to nodes] **************************************
TASK [Gathering Facts] *********************************************************
ok: [k8s-node-1]
TASK [Ping] ********************************************************************
ok: [k8s-node-1]
PLAY RECAP *********************************************************************
k8s-master : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
k8s-node-1 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0