lost and found ( for me ? )

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


Ubuntu 16.04 : run Docker private registry within LXD container

Reference
https://docs.docker.com/registry/deploying/
https://stgraber.org/2016/04/13/lxd-2-0-docker-in-lxd-712/

LXD host : Ubuntu 16.04

[ LXD profiles ]

This profile is to use docker within LXD containers.
$ lxc profile show docker
config:
 linux.kernel_modules: overlay, nf_nat
 security.nesting: "true"
description: Profile supporting docker in containers
devices:
 aadisable:
   path: /sys/module/apparmor/parameters/enabled
   source: /dev/null
   type: disk
 fuse:
   path: /dev/fuse
   type: unix-char
name: docker

This profile configures network.
$ lxc profile show g-net
config:
 security.nesting: "true"
 security.privileged: "true"
description: ""
devices:
 eth0:
   name: eth0
   nictype: bridged
   parent: g-net
   type: nic
name: g-net

[ install docker and set up private registry ]

Start a container.
$ lxc launch xenial -p g-net -p docker xenial01

$ lxc exec xenial01 bash
root@xenial01:~# apt update

root@xenial01:~# apt install docker.io -y

root@xenial01:~# docker version
Client:
Version:      1.12.6
API version:  1.24
Go version:   go1.6.2
Git commit:   78d1802
Built:        Tue Jan 31 23:35:14 2017
OS/Arch:      linux/amd64

Server:
Version:      1.12.6
API version:  1.24
Go version:   go1.6.2
Git commit:   78d1802
Built:        Tue Jan 31 23:35:14 2017
OS/Arch:      linux/amd64

root@xenial01:~# systemctl status docker | grep -i active
  Active: active (running) since Thu 2017-05-14 06:11:31 UTC; 51s ago

Before getting an docker image, I changed MTU to 1400 from 1500.
In my environment, I can not download docker images when MTU is 1500.
I am not sure why…
root@xenial01:~# ifconfig eth0 mtu 1400

Or

you can define MTU in LXD profile as below.
devices:
 eth0:
   mtu: "1400"
   name: eth0
   nictype: bridged
   parent: g-net
   type: nic

Start registry
root@xenial01:~# docker run -d -p 5000:5000 --restart=always --name registry   -v `pwd`/data:/var/lib/registry registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
79650cf9cc01: Pull complete
70ce42745103: Pull complete
77edd1a7fa4d: Pull complete
432773976ace: Pull complete
3234a47fe5a9: Pull complete
Digest: sha256:a3551c422521617e86927c3ff57e05edf086f1648f4d8524633216ca363d06c2
Status: Downloaded newer image for registry:2
d641a6975ac5df1e63435394f09d015b1665cc3bff51423ffb81545977d1516f
root@xenial01:~#

root@xenial01:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
d641a6975ac5        registry:2          "/entrypoint.sh /etc/"   2 minutes ago       Up 2 minutes        0.0.0.0:5000->5000/tcp   registry

get an Ubuntu image from docker hub.
root@xenial01:~# docker pull ubuntu

Tag it to my registry and push to the registry
root@xenial01:~# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              ebcd9d4fca80        2 days ago          117.9 MB
registry            2                   9d0c4eabab4d        7 days ago          33.17 MB
root@xenial01:~# docker tag ubuntu localhost:5000/Ubuntu

root@xenial01:~# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
localhost:5000/ubuntu   latest              ebcd9d4fca80        2 days ago          117.9 MB
ubuntu                  latest              ebcd9d4fca80        2 days ago          117.9 MB
registry                2                   9d0c4eabab4d        7 days ago          33.17 MB
root@xenial01:~#
root@xenial01:~# docker push localhost:5000/ubuntu


Check a remote host can pull an image from the private registry.

on another machine(xenial02), pull an image from xenial01.
root@xenial02:~# docker pull `dig xenial01 +short`:5000/ubuntu
Using default tag: latest
Error response from daemon: Get https://192.168.156.18:5000/v1/_ping: http: server gave HTTP response to HTTPS client

error..

edit docker.service file
root@xenial02:~# systemctl edit --full docker

root@xenial02:~# systemctl cat docker | grep -i execstart
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS --insecure-registry 192.168.156.18:5000

root@xenial02:~# systemctl restart docker

root@xenial02:~# docker pull `dig xenial01 +short`:5000/ubuntu
Using default tag: latest
latest: Pulling from ubuntu
22ecafbbcc4a: Pull complete
580435e0a086: Pull complete
8321ffd10031: Pull complete
08b8f28a13c2: Pull complete
2b401702069a: Pull complete
Digest: sha256:98b0d4821e10fcf32c099eb89ce57db0ee31b8cf818c3f874d381cc937022d6f
Status: Downloaded newer image for 192.168.156.18:5000/ubuntu:latest
root@xenial02:~#

root@xenial02:~# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
192.168.156.18:5000/ubuntu   latest              ebcd9d4fca80        2 days ago          117.9 MB
root@xenial02:~#

run the docker container.
root@xenial02:~# docker run -it 192.168.156.18:5000/ubuntu
root@bd6b87438514:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@bd6b87438514:/# exit
root@xenial02:~#