LXD
Install
Install the package from AUR.
Add custom mapping for uid and gid.
echo "root:1000000:65536" | sudo tee -a /etc/subuid /etc/subgid
echo "lxd:1000000:65536" | sudo tee -a /etc/subuid /etc/subgid
Error: Failed container creation: Create container: Create LXC container: LXD doesn't have a uid/gid allocation. In this mode, only privileged containers are supported
when launching a container.
Start and enable the service.
Add yourself to the lxd group.
Initialize LXD
To create the default network, storage pool and profile. Run as root.
Basic commands
Create a container.
Create a new profile.
Create a new profile from another profile.
List containers.
List all local images.
List all available remote images. lxc remote list
.
Auto update remote images.
Create a conatiner
Launch a container from a remote image.
Launch an ephemeral container.
Information about a container.
Access the container.
Stop and start
Delete container.
Show storage pools.
Create a custom image based on a local container
Auto update remote images.
Push a file to a container.
Pull a file from a container.
Backup container
Backup image Source
lxc snapshot container backup
lxc publish container/backup --alias container-backup
lxc image export container-backup .
lxc image delete container-backup
lxc image import backup.tar.gz --alias container-backup
lxc launch container-backup new-container
lxc image delete container-backup
Start on boot
lxc config set {container} boot.autostart {true|false}
lxc config set {container} boot.autostart.priority integer
lxc config set {container} boot.autostart.delay integer
Network
Static IP.
Bridge br0
:
lxc profile copy default lan
lxc profile edit lan
---
...
devices:
eth0:
name: eth0
nictype: bridged
parent: br0
type: nic
...
Cloud-init
By default only works with images pulled from https://cloud-images.ubuntu.com/releases/ (Ubuntu).
Log available at /var/log/cloud-init.log
inside the container.
Create a new profile with ssh keys
Create or clone a new profile.
Edit the profile with lxc profile edit ssh
. Get the key with cat ~/.ssh/lxd.pub
. You can create the keys with ssh-keygen -t rsa -b 8128 -C "Keys for LXD"
.
config:
user.user-data: |
#cloud-config
users:
- name: yu
ssh-authorized-keys:
- ssh-rsa [...] == Keys for LXD
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: sudo
shell: /bin/bash
Launch a container.
And connect to it over ssh.
Container with custom config file instead of profile
Create a config file config.yml
.
#cloud-config
users:
- name: yu
ssh-authorized-keys:
- ssh-rsa ... == Keys for LXD
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: sudo
shell: /bin/bash
And create a new container.
And connect to it over ssh.
Distrobuilder
Any distro downloaded from https://images.linuxcontainers.org will NOT include cloud-init, so you have to create your own image; you can do it manually (do not) or you can use distrobuilder.
Install dependencies.
Build distrobuilder from source.
go get
gives an error but it works.
Create a folder.
Create a template. Examples available at $HOME/go/src/github.com/lxc/distrobuilder/doc/examples/
.
Under files:
add the following.
- name: meta-data.lxd
path: /var/lib/cloud/seed/nocloud-net/meta-data
generator: template
content: |-
instance-id: {{ container.name }}
local-hostname: {{ container.name }}
{{ config_get("user.meta-data", "") }}
- name: network-config.lxd
path: /var/lib/cloud/seed/nocloud-net/network-config
generator: template
content: |-
{% if config_get("user.network-config", "") == "" %}version: 1
config:
- type: physical
name: eth0
subnets:
- type: {% if config_get("user.network_mode", "") == "link-local" %}manual{% else %}dhcp{% endif %}
control: auto{% else %}{{ config_get("user.network-config", "") }}{% endif %}
- name: user-data.lxd
path: /var/lib/cloud/seed/nocloud-net/user-data
generator: template
content: |-
{{ config_get("user.user-data", properties.default) }}
# properties:
# default: |
# #cloud-config
# {}
- name: vendor-data.lxd
path: /var/lib/cloud/seed/nocloud-net/vendor-data
generator: template
content: |-
{{ config_get("user.vendor-data", properties.default) }}
# properties:
# default: |
# #cloud-config
# {}
And under - packages:
add the following.
And create the image for LXD.
Import the image.
Create a config file config.yml
.
#cloud-config
users:
- name: yu
ssh-authorized-keys:
- ssh-rsa ... Keys for LXD
sudo: ['%wheel ALL=(ALL) NOPASSWD: ALL']
groups: wheel
shell: /bin/bash
Create a container with a custom cloud-init file config.yml
.
And log into the container.
Everything I tested seems to work.
Ansible
Example Playbook for Ubuntu.
---
- hosts: localhost
connection: local
tasks:
- name: Create Ubuntu container in LXD
lxd_container:
name: ubuntu
architecture: x86_64
state: started
ephemeral: yes
config:
user.network_mode: "link-local"
raw.idmap: gid 1005 1000 ## Group id 1001 in the container will be 1005 in the host
boot.autostart: "true"
limits.cpu: "4"
limits.cpu.allowance: "50%"
user.user-data: |
#cloud-config
users:
- name: yu
ssh-authorized-keys:
- "{{ lookup('file', '/path/to/id_rsa.pub') }}"
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: sudo
shell: /bin/bash
devices:
folder:
source: "/path/in/host"
path: "/path/in/container"
type: disk
eth0:
ipv4.address: 10.10.10.57
name: eth0
nictype: bridged
parent: lxdbr0
type: nic
source:
type: image
mode: pull
server: https://cloud-images.ubuntu.com/releases/
protocol: simplestreams
alias: 18.04
profiles: ["default"]
Deploy with ansible-playbook playbook.yml
.
Ansible modules used for LXD:
Remote instances
Configure the remote server to be accessible.
lxc config set core.https_address 192.168.1.90:4567
lxc config set core.trust_password something-secure
Add a new remote.
List remote servers.
List remote containers.
Launch a remote container
nftables
sudo nft add rule inet filter INPUT iifname "lxdbr0" tcp dport { 53, 67, 68 \} counter accept
sudo nft add rule inet filter INPUT iifname "lxdbr0" udp dport { 53, 67, 68 \} counter accept
sudo nft add rule inet filter FORWARD iifname "lxdbr0" counter accept
sudo nft add rule inet filter FORWARD oifname "lxdbr0" counter accept
sudo nft add rule nat postrouting ip saddr 10.131.131.0/24 oif "enp3s0" snat 10.0.5.12
sudo nft add rule arp filter INPUT iifname "lxdbr0" counter accept
Xorg
Add the display to the container.
On the host allow anyone to connect to the local X11 instance.
PulseAudio. Source
Add to /etc/pulse/default.pa
Reload PulseAudio.
You may need this too.
Configure the container.
Links
-
https://www.cyberciti.biz/faq/run-commands-on-linux-instance-at-launch-using-cloud-init/
-
https://blog.simos.info/using-distrobuilder-to-create-container-images-for-lxc-and-lxd/
-
https://blog.simos.info/how-to-create-a-minimal-container-image-for-lxc-lxd-with-distrobuilder/
-
https://blog.simos.info/running-steam-in-a-lxd-system-container/
-
https://medium.com/@tcij1013/lxc-lxd-cheetsheet-effb5389922d