LXD basic usage note

Introduction

LXD is an extended version of LXC (LinuX Container). LXD prvoides REST API and easy-to-use interface to control containers. LXD is written by go and uses LXC share library (liblxc) directly. LXD can provoide live migration with criu (LXC can not).

The major purpose of LXD/ LXC is to provide VM-like environment. You can control container just like you control VM before. Unlike Docker, you can use systemd in the lxd container. LXD also provides well-defined networking interface.

Install lxd

I test the lxd in ubuntu 16.04 and 16.10. The versions of ubuntu 16.04 and 16.10 are 2.0.7 and 2.4.0. The latest version (2017/03/06) is 2.10. After LXD 2.3.0, it has new commands lxd network. You can get more details from the article. If you have need to use lxd network command, you can build lxd by yourself. It's not difficult to build. Otherwise you can just use package from package manager.

You can install lxc and lxc both since the two command line interfaces are independent. The commands of LXD are lxc and lxd. The commands of LXD is started wtih lxc-. It's uneeded to use them in the same time.

Install from package

  • In ubuntu 16.04 and 16.10
    sudo apt install -y lxd
    # sudo apt install -y criu  # Support live migration.
    sudo lxd init
    

Install from source

  • Environment: Ubuntu 16.04.2
  • Ref: LXD - build from source

  • Assume these environment variables and add to .bashrc or .zshrc

    export GOPATH=$HOME/usr/go
    export PATH=$PATH:$GOPATH/bin
    #export LXD_DIR=/home/yen3/usr/lxd/server
    #export LXD_CONF=/home/yen3/usr/lxd/config
    
  • Install prerequesties

    sudo apt-get install software-properties-common
    sudo add-apt-repository ppa:ubuntu-lxc/lxd-git-master
    sudo apt-get update
    sudo apt-get install acl dnsmasq-base git golang liblxc1 \
        lxc-dev make pkg-config rsync squashfs-tools \
        tar xz-utils
    
  • Build from source

    mkdir -p $GOPATH
    go get github.com/lxc/lxd
    cd $GOPATH/src/github.com/lxc/lxd
    make
    
  • Save the script to /etc/init.d/launch-my-lxd

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #!/bin/sh
    
    ### BEGIN INIT INFO
    # Provides:          launch-my-lxd
    # Required-Start:    $all
    # Required-Stop:     $all
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Start my lxd
    # Description:       Start the latest lxd build by myself
    ### END INIT INFO
    
    set -e
    
    export GOPATH=/home/yen3/usr/go
    #export LXD_DIR=/home/yen3/usr/lxd/server
    #export LXD_CONF=/home/yen3/usr/lxd/config
    
    case "$1" in
      start)
          $GOPATH/bin/lxd --group lxd &
          ;;
      restart)
          /etc/init.d/launch-my-lxd stop
          /etc/init.d/launch-my-lxd start
          ;;
      stop)
          killall lxd
          ;;
      *) echo "Usage: $0 {start|stop|restart}" >&2; exit 1 ;;
    esac
    
    exit 0
    
  • Start the lxd daemon

    /etc/init.d/launch-my-lxd start
    
  • Init the lxd

    $GOPATH/bin/lxd init
    
  • Check the lxd dameon executing successfully.

    $ lxc list
    +------+-------+------+------+------+-----------+
    | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
    +------+-------+------+------+------+-----------+
    
    $ lxc --version
    2.10.1
    
  • (Optional) Lauch the lxd daemon after reboot automatically.

    sudo systemctl enable launch-my-lxd
    
  • (Memo) Stop the lxd daemon

    sudo systemctl stop launch-my-lxd
    

Commands

  • Command memo
    sudo lxd init                          # Init LXD environment
    
    lxc profile show default               # Show default profile
                                           # The current content of default profile is to define a network adapter
    
    lxc launch ubuntu:16.04 yen3-ubuntu    # Init and start the container named `yen3-ubuntu`.
    # lxc launch ubuntu:16.04 yen3-ubuntu -p default -p yen3
                                           # As the bellow but with `default` and `yen3` two profiles.
    lxc init ubuntu:16.04 yen3-ubuntu      # Init the container but not start
    
    lxc list                               # List the status of all containers.
    
    lxc start yen3-ubuntu                  # Start the container
    lxc stop yen3-ubuntu                   # Shutdown the container
    lxc stop yen3-ubuntu --stateful        # Stop the container and save the state (need to `sudo apt install -y criu`).
                                           # The function maybe not work.
    lxc restart yen3-ubuntu                # Restart the container
    lxc delete yen3-ubuntu                 # Delete the container
    
    lxc file push source.file target.file  # Copy host's file to the container
    lxc exec yen3-ubuntu -- apt update     # Run command under the container directly
    
    lxc info yen3-ubuntu                   # Show the container info
    lxc config show yen3-ubuntu            # Show config
    lxc config edit yen3-ubuntu            # Edit config
    lxc config show default                # Show default config.
    
    lxc config device add yen3-ubuntu homedir disk source=/home/yen3 path=/home/ubuntu
                                           # Share host's folder to container
    
    # The configuation document: https://github.com/lxc/lxd/blob/master/doc/configuration.md
    

NIC

Before use the lxd, I only have a little knowledge about network setting. If you are very familar with network setting, you can ignore the section. After LXD 2.3, LXD provoides lxd network command, you can read the article to get more details. I would not discuss how to use the command here. I just learn and write the basic usage.

The default networking setting of LXD container is bridge mode. Beside the mode, LXD provides physical, vlan and macvlan modes.

  • bridge (default): LXD create a NIC and connect the bridge (the bridge is created in sudo lxd init. It also run dnsmasq to prvoid DHCP service.)
  • physical: Use the host NIC directly.
  • vlan: I have no idea how to use vlan Xd.
  • macvlan: Simulate a different mac address based on a host NIC. The NIC conntects to host directly.

I take examples to use physical and macvlan.

  • physical mode

    • Assume the container's name is c1 and the enp0s8 NIC is unused in the host.
    • Add a NIC named eth1 to use enp0s8 and restart it.

      lxc launch ubuntu:16.04 c1
      lxc config device add c1 eth1 nic nictype=physical parent=enp0s8
      lxc restart c1
      
    • Exec lxc exec 1 -- ip addr to check the setting is successfully.

      3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
      
    • (Optional) Assume the outer network setting is DHCP, I just set eth1 with DHCP and restart networking service.

      • Add the code segement to /etc/network/interface

        auto eth1
        iface eth1 inet dhcp
        
      • Restart the networking service and check the NIC setting.

        sudo systemctl restart networking
        ip addr
        
  • macvlan mode

    • I setup a VirtualBox VM to practice the mode.
    • The NIC has to allow all connection or it is not valid after setting.

    vb_setting_lxd_macvlan

    • Assume the container's name is c1 and the enp0s3 is in the host.
    • Add a macvlan NIC for the container based on enp0s3

      lxc launch ubuntu:16.04 c1
      lxc config device add c1 eth1 nic nictype=macvlan parent=enp0s3
      lxc start c1
      
    • (Optional) We can also set the NIC with DHCP as the below to check the status of NIC.

      16: eth1@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
      link/ether 00:16:3e:4f:38:d1 brd ff:ff:ff:  ff:ff:ff link-netnsid 0
      inet 192.168.1.115/24 brd 192.168.1.255 scope global eth1
         valid_lft forever preferred_lft forever
      inet6 fe80::216:3eff:fe4f:38d1/64 scope link
         valid_lft forever preferred_lft forever
      

REST API

local (unix socket)

  • API spec: rest_api.md
  • Get container list
    $ curl --unix-socket /var/lib/lxd/unix.socket \
        -H "Content-Type: application/json" \
        -X GET \
        lxd/1.0/containers
    {"type":"sync","status":"Success","status_code":200,"operation":"","error_code":0,"error":"","metadata":["/1.0/containers/fire7617-centos","/1.0/containers/testlxc","/1.0/containers/yen3-ubuntu"]}
    
    # Pretty print with `python -m json.tool`
    $ curl --unix-socket /var/lib/lxd/unix.socket \
        -H "Content-Type: application/json" \
        -X GET \
        lxd/1.0/containers | python3 -m json.tool
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   197  100   197    0     0   9244      0 --:--:-- --:--:-- --:--:--  9380
    {
        "type": "sync",
        "status": "Success",
        "status_code": 200,
        "operation": "",
        "error_code": 0,
        "error": "",
        "metadata": [
            "/1.0/containers/fire7617-centos",
            "/1.0/containers/testlxc",
            "/1.0/containers/yen3-ubuntu"
        ]
    }
    

TCP (https)

  • Ref: Directly interacting with the LXD API
  • Run these command first time

    $ sudo apt install -y jq
    $ lxc config set core.trust_password <some_password>
    $ curl -s -k --cert ~/.config/lxc/client.crt --key ~/.config/lxc/client.key https://127.0.0.1:8443/1.0/certificates -X POST -d '{"type": "client", "password": "some_password"}'
    $ curl -s -k --cert ~/.config/lxc/client.crt --key ~/.config/lxc/client.key https://127.0.0.1:8443/1.0 | jq .metadata.auth
    "trusted"
    
  • List all containers

    $ curl -s -k --cert ~/.config/lxc/client.crt --key ~/.config/lxc/client.key https://127.0.0.1:8443/1.0/containers | jq .
    {
      "type": "sync",
      "status": "Success",
      "status_code": 200,
      "operation": "",
      "error_code": 0,
      "error": "",
      "metadata": [
        "/1.0/containers/fire7617-centos",
        "/1.0/containers/testlxc",
        "/1.0/containers/yen3-ubuntu"
      ]
    }
    

Reference

Comments

Comments powered by Disqus