Help us understand the problem. What is going on with this article?

Ubuntu18.04でLXD3.18をビルドからコンテナのデプロイまで

はじめに

このエントリーは,CyberAgent20新卒エンジニアAdvent Calendar 2019の2日目の記事です.
大学院の研究でLXDを取り扱っているので,LXDのビルドからコンテナのデプロイまでを紹介します.
興味があったら,ぜひやってみてください.

目次

  1. CRIUのビルドとインストール
  2. LXCのビルドとインストール
  3. LXDのビルドとインストール
  4. LXD起動の準備とコンテナのデプロイ

1. CRIUのビルドとインストール

LXDのコンテナライブマイグレーションを行うためには,LinuxのプロセスマイグレーションツールであるCRIUが必要です.そのため,CRIUのビルドとインストールを行います.

CRIUのビルド準備(必要なパッケージのインストールとソースコードの取得)

ここはほとんど,公式ページの「Installing build dependencies」情報とおりです.

何行かに分かれていたり,私の環境では足りなかったりするパッケージがあったりと面倒なので,全部インストールするコマンドを記載します

sudo apt install make gcc libprotobuf-dev libprotobuf-c0-dev \
protobuf-c-compiler protobuf-compiler python-protobuf \
pkg-config python-ipaddress libbsd-dev iproute2 libcap-dev libnl-3-dev \
libnet-dev libaio-dev asciidoc

続いて,ソースコードを取得します.GitHubからCloneするので,gitがない場合はインストールしてください.
ソースコードはこのリポジトリから取得できます.

ビルドとインストール

ビルドとインストールも公式ページの「Building the tool」,「Installing」のとおりです.
ただ,criuリポジトリのデフォルトブランチでは動作が不安なので,リリースを確認して直近のタグにチェックアウトしてからビルドすることをおすすめします.ここでは3.13とします.

make
sudo make install

正常にビルドされインストールも完了したことを確認するため,以下のコマンドを実行します.
CRIUのバージョンやgitのcommit id等の情報が表示されれば,ひとまず安心です.

sudo criu --version

2. LXCのビルドとインストール

LXDは内部でLXCをコンテナランタイムとして利用することで,コンテナの作成や削除を行っています.そのため,LXCのビルドとインストールを行います.

LXCのビルド準備(必要なパッケージのインストールとソースコードの取得)

LXCのビルドには,いくつかのビルドツールが必要なのでそれらをインストールします.それぞれのパッケージについては詳しく説明しません(私も理解していないため).

sudo apt install libtool automake docbook m4

続いて,ソースコードの取得です.
このリポジトリからソースコードをクローンします.CRIUと同様にデフォルトのブランチでは動作が不安なため,直近のリリースタグにチェックアウトしておくと安心です.ここでは,3.1.0とします.

ビルドとインストール

このリポジトリのREADMEにかかれているとおりです.以下のコマンドを実行しましょう.

./autogen.sh #configureの生成
./configure #Makefileの生成
make #ビルド
sudo make install #インストール

3. LXDのビルドとインストール

ようやくLXDのビルドとインストールを行います.

LXDのビルド準備(必要なパッケージのインストールとソースコードの取得)

必要なパッケージはこのリポジトリのREADMEに記述されていますが,lxcのライブラリに関してはビルドしたライブラリを利用するため,インストールしません.ここでGo言語もインストールされています.

sudo apt install acl autoconf dnsmasq-base \
git golang libacl1-dev libcap-dev \
libtool libuv1-dev make pkg-config rsync squashfs-tools \
tar tcl xz-utils ebtables
#liblxc1 liblxc-dev これらはインストールしない 

セキュリティに係るパッケージをインストールします.

sudo apt install libapparmor-dev libseccomp-dev libcap-dev

LXDのストレージ用パッケージをインストールします

sudo apt install lvm2 thin-provisioning-tools btrfs-tools

テスト用パッケージをインストールします.(LXDの開発者でなければ必要ないでしょう)

sudo apt install curl gettext jq sqlite3 uuid-runtime bzr socat

続いて,ソースコードの取得を行います.LXDはGo言語で実装されているので,Goのお作法でソースコードを取得するのが良いです.

go get github.com/lxc/lxd

依存ライブラリのビルド

まずは,依存するライブラリのビルドです.
その前に,やはりデフォルトのブランチでは動作が不安なため,直近のリリースタグにチェックアウトします.ここでは,3.18とします.
go getで取得したソースコードは${GOPATH}/src/github.com/lxc/lxdにあります.

make deps

エラーなくライブラリのビルドが終了すると,以下のような情報が表示されるはずです.

export CGO_CFLAGS="${CGO_CFLAGS} -I${GOPATH}/deps/sqlite/ -I${GOPATH}/deps/dqlite/include/ -I${GOPATH}/deps/raft/include/ -I${GOPATH}/deps/libco/"
export CGO_LDFLAGS="${CGO_LDFLAGS} -L${GOPATH}/deps/sqlite/.libs/ -L${GOPATH}/deps/dqlite/.libs/ -L${GOPATH}/deps/raft/.libs -L${GOPATH}/deps/libco/"
export LD_LIBRARY_PATH="${GOPATH}/deps/sqlite/.libs/:${GOPATH}/deps/dqlite/.libs/:${GOPATH}/deps/raft/.libs:${GOPATH}/deps/libco/:${LD_LIBRARY_PATH}"

ビルドしたライブラリをOSに共有ライブラリとして登録する

CGO_CFLAGSとCGO_LDFLAGSはそのまま,.bashrcなどに記述すればよいのですが,LD_LIBRARY_PATHに関しては少し工夫が必要です.

後の話なのですが,ビルドしたLXDのバイナリはsudoで実行する必要があります.そのため,そのままLD_LIBRARY_PATHを.bashrcに記述するとsudoで実行する場合,ビルドしたライブラリが見えません.

この問題を解決するため,共有ライブラリとしてOSに登録する必要があります.

Ubuntu18.04の場合,/ld.so.conf.d/配下にライブラリが配置されているパスが記述されている設定ファイルを配置することで,そのパスを見て共有ライブラリを登録してくれます.

そのため,以下のファイルを作成します.
${GOPATH}の部分は,環境に合わせて変更された内容が依存ライブラリビルド時に表示されているはずなので,その内容と読み替えてください.

/ld/so.conf.d/lxd-lib.conf
${GOPATH}/deps/sqlite/.libs/
${GOPATH}/deps/dqlite/.libs/
${GOPATH}/deps/raft/.libs
${GOPATH}/deps/libco/

追加した設定ファイルの内容をOSに知らせるために,以下のコマンドを実行します.

sudo ldconfig

LXDのビルドとインストール

続いて,LXD本体のビルドを行います.ビルドはとっても簡単です.

make

ビルドが正常に終了した場合,${GOPATH}/bin配下にlxdlxcというバイナリが配置されているはずです.
そのため,特にインストール操作はありません.

LXDビルドのトラブルシューティング(go-dqliteのエラー対処)

簡単なはずなのですが,私の環境ではLXDが利用するGo言語のパッケージであるgo-dqliteでエラーが発生しました.そのエラーは以下です.

use of internal package not allowed

これは,LXDが利用しているパッケージがgithub.com/CanonicalLtd/go-dqliteであるにも関わらず,そのgithub.com/CanonicalLtd/go-dqlitegithub.com/canonical/go-dqliteというパッケージの複製なので,ソースコード内のimport分が以下の様になってしまっていることが原因です.

import (
    github.com/canonical/go-dqlite/internal/bindings
    //本当は github.com/CanonicalLtd/go-dqlite/internal/bindings であるべき
)

なので,この様な状態になってしまっているファイルをすべて修正します.
具体的には,github.com/canonical/go-dqliteになっている部分をgithub.com/CanonicalLtd/go-dqliteに変更します.

これで,上記のエラーは解消できました.

4. LXD起動の準備とコンテナのデプロイ

LXD起動の準備をします.

subuid/subgidの設定

ここに記述されている通り,LXDでコンテナのデプロイをするためには,以下の操作が必要です.

echo "root:1000000:65536" | sudo tee -a /etc/subuid /etc/subgid

lxdグループの作成と,ユーザの追加

sudoなしでコマンドを実行できるようにします.
まず,以下のコマンドでlxdグループを作成します.

sudo groupadd lxd

その後,以下のコマンドでlxdを操作したいユーザをlxdに追加します.

sudo usermod -aG lxd $USER

LXDの実行と初期化

まず以下のコマンドで,LXDを起動します.
--group オプションではsudoなしでlxcコマンドを実行できるようにするgroupを指定します.
logfileオプションは,ログを吐き出す場所を指定します.

sudo $GOPATH/bin/lxd --group lxd --logfile=/var/log/lxd/lxd.log

一度実行が確認できたら,systemdに自動起動してもらうようにします.
以下のserviceファイルを/lib/systemd/system配下に作成します.

/lib/systemd/system/lxd.service
[Unit]
Description=LXD - main daemon

[Service]
ExecStart=/home/yota/go/bin/lxd --debug --group lxd --logfile=/var/log/lxd/lxd.log

[Install]
WantedBy=multi-user.target

続いて,以下のコマンドでLXDの設定を初期化します.
LXDをお好みに設定してください.
ただし,外部公開は必ずしてください.

sudo $GOPATH/bin/lxd init

参考までに,私はこの様な感じです

Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: yes
Name of the new storage pool [default=default]: 
Name of the storage backend to use (btrfs, dir, lvm) [default=btrfs]: 
Create a new BTRFS pool? (yes/no) [default=yes]: 
Would you like to use an existing block device? (yes/no) [default=no]: 
Size in GB of the new loop device (1GB minimum) [default=100GB]: 
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like LXD to be available over the network? (yes/no) [default=no]: yes
Address to bind LXD to (not including port) [default=all]: 
Port to bind LXD to [default=8443]: 
Trust password for new clients: 
Again: 
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: yes

コンテナのデプロイ

以下のコマンドで軽量なalpineイメージでコンテナをデプロイします.

sudo $GOPATH/bin/lxc launch images:alpine/3.9 hoge 
# hogeはコンテナの名前

コマンドの実行

以下のコマンドで起動したコンテナのashに入って色々操作できます.

lxc exec hoge /bin/ash

おわりに

いかがでしょうか?
Docker以外のコンテナランタイム使ってみたいなと思った方はぜひLXD使ってみてください.

ところで...

CyberAgentで21卒の本選考がはじまりました!
選考についてはこちらを御覧ください!!

早期エントリーには就業型インターンシップの特典があるそうです.
このインターンではエンジニアとして個人で勉強していたり大学で勉強しているだけでは獲得できない経験が得られました!
それだけでなく,社内エンジニアの人の良さを知ることもでき会社の様子を知るのにも最適でした!
少しでも気になっている方は,ぜひエントリーを考えてみてください!!!!

fun-ac
2000年に開学した公立大学です。「プロジェクト型学習」など、実践的な教育を全国に先駆けて導入しています。
https://www.fun.ac.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした