How to upgrade LXD VMs powered by Ubuntu/Debian or CentOS Linux

Posted on in Categories , , , , last updated July 11, 2017

I run over 10+ LXD VMs powered by CentOS Linux 7 and Debian/Ubuntu Linux. How do I upgrade all VMs automatically or on demand using Ansible tool?

lxd-vm-upgradeThere are two ways to upgrade your LXD (Linux containers) VMs. Both methods depend upon the use of the /usr/bin/lxc command.

Method 1 – Update using a shell script

The syntax is pretty simple:
/usr/bin/lxc exec vmNameHere -- command
/usr/bin/lxc exec vmNameHere -- /usr/bin/apt-get -y upgrade
/usr/bin/lxc exec vmNameHere -- /usr/bin/apt-get -y upgrade
/usr/bin/lxc exec vmNameHere -- /usr/bin/yum -y update

Next you can create a shell script as follows:

#!/bin/bash
# Purpose: Run given command inside the LXD vm 
# Note: Must be run from host. Only tested on Ubuntu 16.04 LTS
# Author: Vivek Gite { https://www.cyberciti.biz } under GPL v2.x+
# -----------------------------------------------------------------
cmd="$@"
for i in vm1 vm2 vm3 vm10
do 
  echo "[*** $i ***]"
  /usr/bin/lxc exec $i -- $cmd
done

Now all you have to do is run command for a Debian or Ubuntu Linux based vm i.e. pass the apt-get command/apt command to update VM:
$ ~/bin/script-name /usr/bin/apt-get update
$ ~/bin/script-name /usr/bin/apt-get -y upgrade

If you are using a CentOS 7 based VM pass the yum command:
$ ~/bin/script-name /usr/bin/apt-get /usr/bin/yum -y update

Method 2 – Update LXD VMs using Ansible devops/sysadmin automation tool

You can create a lxd-update.yml ansible playbook file as follows:

          #
          # Update host running on Debian/Ubuntu
          #
          - name: Updating host using apt
            apt:
                    update_cache: yes
                    upgrade: dist
          #
          # Now update VMs powered by Debian/Ubuntu Linux
          #
          - name: Run lxc to update debian/ubuntu vms repo
            command: /usr/bin/lxc exec {{ item }} -- /usr/bin/apt-get -y update 
            with_items:
                    - ubuntuvm1
                    - debianvm2
                    - ubuntuvm3
 
          - name: Run lxc to upgrade debian/ubuntu vms pacakges
            command: /usr/bin/lxc exec {{ item }} -- /usr/bin/apt-get -y upgrade 
            with_items:
                    - ubuntuvm1
                    - debianvm2
                    - ubuntuvm3
          #
          # Now update VMs powered by CentOS 7 Linux
          #
          - name: Run lxc to upgrade centos vms
            command: /usr/bin/lxc exec {{ item }} -- /usr/bin/yum -y update
            with_items:
                    - centosvm4
                    - centosvm5
                    - centosvm6

You can run it as follows using the ansible-playbook command:
$ ansible-playbook -i my-hosts lxd-update.yml
The last method is easy to use and easy to extend too. Hence, I recommend that you use the Ansible playbooks to update your LXD powered VMs.

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on Twitter, Facebook, Google+.

3 comment

  1. Btw. /usr/bin/lxc is not available on CentOS7 (to my knowledge).

    When I update my containers I normally do something like;

    I normally do something like this.
    lxc-ls –active | while read l ; do
    lxc-attach -n $l — apt-get update
    lxc-attach -n $l — apt-get -y upgrade
    lxc-stop -n $l
    lxc-start -n $1 -d
    done

  2. Hi,
    There is another solution which is, IMHO, more “ansible way”.
    You can use the LXD connection type in your inventory (or in your playbook) and access directly to your containers and use standard ansible module like apt, yum or package instead of command.

    So, in your inventory, list your containers as:
    [MyContainers]
    ubuntuvm1 ansible_connection=lxd
    debianvm2 ansible_connection=lxd
    ubuntuvm3 ansible_connection=lxd

    And in your playbook,

    – name: Update containers
    hosts: all

    tasks:
    – name: update containers
    apt:
    update_cache: yes
    cache_valid_time: 3600

    And because of ansible_connection=lxd, Ansible access directly to the container, even if there is no ssh server in containers. I use a lot the methode to test my Ansible roles on my laptop.

Leave a Comment