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

按照适当站点的安装指南进行操作:

创建所有必要的文件和目录

此示例基于原始海报文件

创建vagrantansible 文件夹来存储所有配置文件和目录。它的结构可能如下所示:

  • 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.cfginsecure_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