How to add an LXD container on another machine and copy Ansible's public keys to the container?

638 views
Skip to first unread message

Greg K

unread,
Jun 26, 2017, 10:17:35 PM6/26/17
to Ansible Project
I am looking to use Ansible running on one machine to create a container on another machine and exchange ssh keys with it.

I am new to Ansible and have been trying different things based off a playbook I found on github
---

- name: Ensure lxd is started
  service
:
    name
: lxd
    state
: started

- name: Setup SSH for LXD
  blockinfile
:
    marker
: "# {mark} ANSIBLE BOOT LXD MANAGED BLOCK"
    dest
: '{{ ssh_home }}/config'
    block
: |
     
Host *.lxd
         
# No need for security for disposable test containers
         
UserKnownHostsFile /dev/null
         
StrictHostKeyChecking no
         
User root

- name: Start lxd container
  lxd_container
:
    name
: '{{ item.split(".")[0] }}'
    state
: started
    source
:
      type
: image
      mode
: pull
      server
: https://images.linuxcontainers.org
      protocol
: lxd
     
alias: '{{ hostvars[item].get("lxd_alias", "ubuntu/xenial/amd64") }}'
    profiles
: ['default']
    wait_for_ipv4_addresses
: true
 
when: item.split('.')[-1] == 'lxd'
  with_items
: '{{ groups["all"] }}'

- name: Add lxd host with lxd connection to setup python & ssh
  add_host
:
    name
: 'novafloss.boot-lxd-{{ item.split(".")[0] }}'
    ansible_ssh_host
: '{{ item.split(".")[0] }}'
    ansible_connection
: lxd
   
group: 'novafloss.boot-lxd'
 
when: item.endswith('.lxd')
  with_items
: '{{ groups["all"] }}'

- name: Wait for containers to be connected
  shell
: lxc exec {{ item.replace('.lxd', '') }} -- getent hosts google.com
 
when: item.endswith('lxd')
  with_items
: '{{ groups["all"] }}'
  retries
: 30
  delay
: 1

- name: Refresh packages
  raw
: if hash apt-get; then apt-get update; elif hash apk; then apk update; fi
  become
: no
  delegate_to
: '{{ item }}'
  with_items
: '{{ groups.get("novafloss.boot-lxd", []) }}'
  retries
: 70

- name: Install sshd
  raw
: if ! hash sshd; then if hash apt-get; then apt-get install -y openssh-server; elif hash apk; then apk add openssh; fi; fi
  become
: no
  delegate_to
: '{{ item }}'
  with_items
: '{{ groups.get("novafloss.boot-lxd", []) }}'
  retries
: 70

- name: Install python in container
  raw
: if ! hash python2; then if hash apt-get; then apt-get install -y python; elif hash apk; then apk add python; fi; fi
  become
: no
  delegate_to
: '{{ item }}'
  with_items
: '{{ groups.get("novafloss.boot-lxd", []) }}'
  retries
: 70

- name: Gather facts
  setup
:
  become
: no
  delegate_to
: '{{ item }}'
  with_items
: '{{ groups.get("novafloss.boot-lxd", []) }}'
 
register: setup

- name: Start and enable sshd
  service
:
    name
: sshd
    state
: started
    enabled
: yes
  become
: no
  delegate_to
: '{{ item }}'
  with_items
: '{{ groups.get("novafloss.boot-lxd", []) }}'
 
register: sshd
  ignore_errors
: yes

- debug: var=item
  with_items
: '{{ sshd.results }}'

- name: Start and enable OpenSSH (for when the above failed)
  service
:
    name
: ssh
    state
: started
    enabled
: yes
  become
: no
  delegate_to
: '{{ item["item"] }}'
  with_items
: '{{ sshd.results }}'
 
register: openssh
 
when: "{{ item|failed }}"
  ignore_errors
: yes
  failed_when
: "item|failed and openssh|failed"

- name: Add your ssh key to the container
  authorized_key
:
    key
: '{{ lookup("file", ssh_public_key ) }}'
    path
: /root/.ssh/authorized_keys
    user
: root
  become
: no
  delegate_to
: '{{ item }}'
  with_items
: '{{ groups.get("novafloss.boot-lxd", []) }}'

- name: Install sudo in container
  raw
: if hash apt-get; then apt-get install -y sudo; elif hash apk; then apk add sudo; fi
  become
: no
  delegate_to
: '{{ item }}'
  with_items
: '{{ groups.get("novafloss.boot-lxd", []) }}'
  retries
: 70

- name: Wait for containers to start sshd
  wait_for
:
    host
: '{{ item }}'
    port
: 22
    search_regex
: OpenSSH
 
when: item.endswith('lxd')
  with_items
: '{{ groups["all"] }}'

One of the code variations I tried was:
- hosts: '{{ node }}'
  vars:
    node
: 'machine'
    container_name: 'test123'
  tasks:
   
- name: Start lxd container
      lxd_container
:
        name
: '{{ container_name }}'
        state: started
        source
:
          type
: image
          mode
: pull
          server
: https://images.linuxcontainers.org
          protocol
: lxd
         
alias: ubuntu/xenial/amd64
        profiles
: ['default']
        wait_for_ipv4_addresses
: true
        timeout
: 600

    - name: Add lxd host with lxd connection to setup python & ssh
      add_host
:
        name
: '{{ container_name }}'
        ansible_ssh_host: '{{ container_name }}'
        ansible_connection: lxd
       
group: 'lxd'

    - name: Install python in container
      raw
: if ! hash python2; then if hash apt-get; then apt-get install -y python; elif hash apk; then apk add python; fi; fi
      become: no
      delegate_to
: '{{ container_name }}'

    - name: Add your ssh key to the container
      authorized_key
:
        key
: '{{ lookup("file", "/root/.ssh/id_rsa.pub" ) }}'
        path: /root/.ssh/authorized_keys
        user
: root
      become
: no
      delegate_to
: '{{ node }}'

I can successfully create the container however I have been struggling to add Ansible's public key to the container.

How to can I add Ansible's public key to a container which is running on another machine?

Pshem Kowalczyk

unread,
Jun 26, 2017, 11:07:30 PM6/26/17
to Ansible Project
Hi,

Depending on the distro you run in the container you might be able to use cloud-init for it. This is what I do with ubuntu inside the container:

#Create a profile

- name: create a bootstrap profile
  lxd_profile:
    name: bootstrap
    description: "used for bootstrapping of containers"
    state: present
    config: { "user.user-data": "#cloud-config\nssh_authorized_keys:\n  - ssh-rsa AAAAXXXXX== root@ponga\npackages:\n  - openssh-server"}
    devices:
      eth0:
       name: eth0
       nictype: bridged
       parent: vlan2
       type: nic


And then I spin up the container using that profile:

- name: create containers
  register: lxds
  lxd_container:
    name: "{{ item }}"
    state: started
    source:
      type: image
      properties:
        os: "ubuntu"
        release: "xenial"
        architecture: "amd64"
    profiles: ["bootstrap"]
    timeout: 600
    wait_for_ipv4_addresses: true
  with_items: "{{ hosts[inventory_hostname] }}"

Once I have the IP  I added to local inventory:

- name: update local inventory
  delegate_to: 127.0.0.1
  connection: local
  become: false
  copy: content="[{{ item.item }}]\n{{ item.addresses.eth0[0] }} type=lxc" dest="./inventory/dyn-{{ item.item }}"
  with_items: "{{ lxds.results }}"

- meta: refresh_inventory
- pause: seconds=60

This gives me a running container with running ssh (and an entry in the inventory).

kind regards
Pshem




--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/6d6e71c5-c2a1-4e82-b90c-5e35abafa70c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages