lost and found ( for me ? )

Ubuntu 16.04: run KVM(qemu-kvm) in LXD container

LXD host
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.2 LTS
Release:        16.04
Codename:       xenial

$ lxd --version
2.0.9

enable nested on LXD host.
$ cat /sys/module/kvm_intel/parameters/nested
Y

launch a container
$ lxc launch xenial xenial01

set “security.netsting true”, “security privileged” to the container.
add two unix-char devices to run KVM.
$ lxc config set xenial01 security.nesting true
$ lxc config set xenial01 security.privileged true

$ lxc config device add xenial01 kvm unix-char path=/dev/kvm
Device kvm added to xenial01

$ lxc config device add xenial01 tun unix-char path=/dev/net/tun
Device tun added to xenial01

access to the container and install uvtool to confirm I can run qemu-kvm in LXD container.
$ lxc exec xenial01 bash

root@xenial01:~# apt update
root@xenial01:~# apt install uvtool -y

root@xenial01:~# kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used

root@xenial01:~# uvt-simplestreams-libvirt sync release=xenial arch=amd64

Run a VM and access to the VM.
root@xenial01:~# uvt-kvm create test01 release=xenial
Warning: u'/root/.ssh/id_rsa.pub' not found; instance will be started with no ssh access by default.

root@xenial01:~# uvt-kvm list
test01
root@xenial01:~# uvt-kvm destroy test01
root@xenial01:~#

root@xenial01:~# ssh-keygen

root@xenial01:~# uvt-kvm create test01 release=xenial

root@xenial01:~# uvt-kvm list
test01

root@xenial01:~# uvt-kvm ip test01
192.168.122.227

root@xenial01:~# uvt-kvm ssh test01
uvt-kvm: error: ssh access with host key verification is not implemented. Use --insecure iff you trust your network path to the guest.

root@xenial01:~# uvt-kvm ssh test01 --insecure
ubuntu@test01:~$ exit

ubuntu@test01:~$ logout
Connection to 192.168.122.227 closed.
root@xenial01:~# virsh list
Id    Name                           State
----------------------------------------------------
2     test01                         running

You can define a profile to run KVM in LXD container as below.
$ lxc profile show default-kvm
config:
 security.nesting: "true"
 security.privileged: "true"
description: ""
devices:
 eth0:
   name: eth0
   nictype: bridged
   parent: lxdbr0
   type: nic
 kvm:
   path: /dev/kvm
   type: unix-char
 tun:
   path: /dev/net/tun
   type: unix-char
name: default-kvm

Run a container with that profile
$ lxc launch xenial -p default-kvm xenial01


Manage LXD containers with Ansible lxd_container

Here are sample playbooks to manage LXD container with Ansible.

Referecne
https://docs.ansible.com/ansible/lxd_container_module.html

install ansible
$ sudo apt install -y virtualenv build-essential python-dev libffi-dev libssl-dev
$ mkdir env01
$ cd env01/
$ virtualenv venv
$ source venv/bin/activate
$ pip install git+https://github.com/ansible/ansible
$ ansible --version
ansible 2.4.0

ansible.cfg
$ cat ansible.cfg
[defaults]
inventory = hosts

hosts
$ cat hosts
[mycontainer]
f-cent01 ansible_connection=lxd
f-cent02 ansible_connection=lxd

two containers are running
$ lxc list f- -cn4
+----------+--------------------+
|   NAME   |        IPV4        |
+----------+--------------------+
| f-cent01 | 10.0.105.33 (eth0) |
+----------+--------------------+
| f-cent02 | 10.0.105.89 (eth0) |
+----------+--------------------+

run playbook
$ ansible-playbook test.yml

PLAY [mycontainer] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [f-cent02]
ok: [f-cent01]

TASK [debug] **************************************************************************************************************
ok: [f-cent01] => {
   "msg": "ipv4_address=10.0.105.33"
}
ok: [f-cent02] => {
   "msg": "ipv4_address=10.0.105.89"
}

PLAY RECAP ****************************************************************************************************************
f-cent01                   : ok=2    changed=0    unreachable=0    failed=0
f-cent02                   : ok=2    changed=0    unreachable=0    failed=0

- restart an existing container

$ cat restart.yml
---
- hosts: localhost
 connection: local
 tasks:
   - name: Restart a container
     lxd_container:
       name: f-cent01
       state: restarted

$ ansible-playbook restart.yml

- delete a container

$ cat delete_container.yml
---
- hosts: localhost
 connection: local
 tasks:
   - name: delete a container
     lxd_container:
       name: f-cent02
       state: absent

- create containers

$ cat create-container.yml
---
- hosts: localhost
 connection: local
 tasks:
   - name: Create a started container
     lxd_container:
       name: my-container01
       state: started
  source:
       type: image
       mode: pull
       server: https://images.linuxcontainers.org
       protocol: lxd
       alias: centos/7/amd64
       profiles: ["default"]
       wait_for_ipv4_addresses: true
       timeout: 600

$ ansible-playbook create-container.yml

$ lxc list my-container01
+----------------+---------+------+------+------------+-----------+
|      NAME      |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+----------------+---------+------+------+------------+-----------+
| my-container01 | RUNNING |      |      | PERSISTENT | 0         |
+----------------+---------+------+------+------------+-----------+

- create a container and install some packages via yum

(venv) hattori@ubuntu05:~/Ansible_works/env01$ cat ansible.cfg
[defaults]
inventory = hosts

(venv) hattori@ubuntu05:~/Ansible_works/env01$ cat hosts
[mycontainer]
f-cent01 ansible_connection=lxd
my-container01 ansible_connection=lxd
[test]
f-test01 ansible_connection=lxd

(venv) hattori@ubuntu05:~/Ansible_works/env01$ cat test01.yml
---
- hosts: localhost
 connection: local
 tasks:
   - name: Create a started container
     lxd_container:
       name: f-test01
       state: started
       source:
         type: image
         alias: cent7
       profiles: ["default"]
       wait_for_ipv4_addresses: true
       timeout: 600
- hosts: test
 remote_user: root
 tasks:
   - name: install httpd
     yum:
       name: httpd
       state: present

$ lxc exec f-test01 bash
[root@f-test01 ~]# rpm -qa | grep http
httpd-2.4.6-45.el7.centos.4.x86_64
httpd-tools-2.4.6-45.el7.centos.4.x86_64

- transfer a file from a localhost to an existing container

$ cat copy-a-file.yml
---
- hosts:
   - test
 remote_user: root
 tasks:
  - copy:
     src: /etc/hosts
     dest: /tmp/hosts
     owner: root
     group: root
     mode: 0664

$ cat ansible.cfg
[defaults]
inventory = hosts

$ cat hosts
[mycontainer]
f-cent01 ansible_connection=lxd
my-container01 ansible_connection=lxd
[test]
f-test01 ansible_connection=lxd

$ ansible-playbook create-container-install.yml

$ lxc exec f-test01 -- ls /tmp/
hosts