sbtでJavaプロジェクトを簡単に作るためのテンプレートを作った

sbt new コマンドでJavaプロジェクトがすぐ作れるようにしてみました。

java-seed.g8

作ったものはこれ。

github.com

ほとんどsbt/scala-seed.g8と同じ構成。

github.com

これでもJavaプロジェクトは作れるんですが、Scala用のパッケージがついてきたり、パッケージにバージョンが入ったり、ライブラリ足さないとJUnitが動かなかったりするので、これをベースにちょこっと設定等足した感じです。

使い方

Ubuntu16.04での例です。他の環境でもsbtさえ動けば一緒かなと。ただし、sbt0.13.13以降でしかこの方法は対応していません。

Java, sbtのインストール

ubuntu@c01:~$ echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
ubuntu@c01:~$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
ubuntu@c01:~$ sudo apt update
ubuntu@c01:~$ sudo apt install openjdk-8-jdk sbt

ubuntu@c01:~$ sbt sbt-version
Getting org.scala-sbt sbt 0.13.13 ...
downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt/0.13.13/jars/sbt.jar ...
        [SUCCESSFUL ] org.scala-sbt#sbt;0.13.13!sbt.jar (3942ms)
downloading https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.10.6/scala-library-2.10.6.jar ...
(省略...)
[info] Set current project to ubuntu (in build file:/home/ubuntu/)
[info] 0.13.13

sbtコマンドを初めて打った時だけ初期化に時間がかかりますが、我慢。

他の環境でのセットアップ方法はこちら。 sbt Reference Manual — sbt のインストール

sbtでJavaプロジェクトを作る

プロジェクトを作りたいディレクトリで、 sbt new kurochan/java-seed.g8 を実行。 kurochan/java-seed.g8Javaプロジェクトのテンプレート。他にも色々テンプレートがあります。

giter8 templates · foundweekends/giter8 Wiki · GitHub

こちらも省略だけ少し時間が掛かりますが待ちましょう。

ubuntu@c01:~$ sbt new kurochan/java-seed.g8
[info] Set current project to ubuntu (in build file:/home/ubuntu/)
[info] Resolving com.github.scopt#scopt_2.10;3.5.0 ...
[info] downloading https://repo1.maven.org/maven2/org/scala-sbt/sbt-giter8-resolver/sbt-giter8-resolver_2.10/0.1.0/sbt-giter8-resolver_2.10-0.1.0.jar ...

(省略…)

Minimum Scala build.

name [My Something Project]: java-project-sample

Template applied in ./java-project-sample

生成されたプロジェクト

これでベースのプロジェクトの生成ができました。プロジェクトのファイル構成はこんな感じ。

build.sbtとprojectディレクトリ以下がビルド設定で、srcディレクトリ以下がアプリケーションのコードです。

ubuntu@c01:~$ cd java-project-sample/
ubuntu@c01:~/java-project-sample$ tree -a -L 5
.
├── build.sbt
├── .gitignore
├── project
│   ├── build.properties
│   └── Dependencies.scala
└── src
    ├── main
    │   └── java
    │       └── example
    │           └── Hello.java
    └── test
        └── java
            └── example
                └── HelloTest.java

コンパイルする

プロジェクトのルートディレクトリでsbtを起動して、compileコマンドを打つ。 sbt compileと打つとsbtのコンソールに入らずに直接コンパイルできます。

ubuntu@c01:~/java-project-sample$ sbt
[info] Loading project definition from /home/ubuntu/java-project-sample/project
[info] Updating {file:/home/ubuntu/java-project-sample/project/}java-project-sample-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /home/ubuntu/java-project-sample/project/target/scala-2.10/sbt-0.13/classes...
[info] 'compiler-interface' not yet compiled for Scala 2.10.6. Compiling...
[info]   Compilation completed in 9.911 s
[info] Set current project to Hello (in build file:/home/ubuntu/java-project-sample/)
> compile
[info] Updating {file:/home/ubuntu/java-project-sample/}root...
[info] Resolving org.sonatype.oss#oss-parent;9 ...
[info] downloading https://repo1.maven.org/maven2/junit/junit/4.12/junit-4.12.jar ...
(省略…)
[info] Compiling 1 Java source to /home/ubuntu/java-project-sample/target/classes...
[success] Total time: 14 s, completed Mar 25, 2017 10:47:58 AM
>
>
> compile
[success] Total time: 0 s, completed Mar 25, 2017 10:48:12 AM
>

差分コンパイルが効いているのでコードに変更を加えずに2回目に compile と打っても一瞬で終わる。テストコードを含めて全部コンパイルするときはcompileの代わりにtest:compileと打ちましょう。

ソースコードの変更を検知してコンパイル

毎回compileと打たなくてもソースコードが書き換わったのを監視して差分コンパイルしてくれる機能もあって ~compile と頭にチルダをつけるだけ。

> ubuntu@c01:~/java-project-sample$ sbt
[info] Loading project definition from /home/ubuntu/java-project-sample/project
[info] Set current project to Hello (in build file:/home/ubuntu/java-project-sample/)
> ~compile
[success] Total time: 0 s, completed Mar 25, 2017 10:51:59 AM
1. Waiting for source changes... (press enter to interrupt)
[info] Compiling 1 Java source to /home/ubuntu/java-project-sample/target/classes...
[success] Total time: 1 s, completed Mar 25, 2017 10:52:43 AM
2. Waiting for source changes... (press enter to interrupt)

実行

run でアプリケーションが起動できる。

ubuntu@c01:~/java-project-sample$ sbt run
[info] Loading project definition from /home/ubuntu/java-project-sample/project
[info] Set current project to Hello (in build file:/home/ubuntu/java-project-sample/)
[info] Running example.Hello
Hello World
[success] Total time: 0 s, completed Mar 25, 2017 10:54:49 AM

テスト

テンプレートプロジェクトにはJUnitのテストケースが書かれていて、それが実行される。

ubuntu@c01:~/java-project-sample$ sbt
[info] Loading project definition from /home/ubuntu/java-project-sample/project
[info] Set current project to Hello (in build file:/home/ubuntu/java-project-sample/)
> test
[info] Compiling 1 Java source to /home/ubuntu/java-project-sample/target/test-classes...
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 1 s, completed Mar 25, 2017 10:55:53 AM
>
>
> test
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 0 s, completed Mar 25, 2017 10:56:03 AM

こちらはコンパイルの時と違って、コマンドを打ったら全部テストが走る。

差分テスト

変更があったクラスのテストだけ実行するには testQuick と打ちます。

ubuntu@c01:~/java-project-sample$ sbt
[info] Loading project definition from /home/ubuntu/java-project-sample/project
[info] Set current project to Hello (in build file:/home/ubuntu/java-project-sample/)
> testQuick
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for test:testQuick
[success] Total time: 0 s, completed Mar 25, 2017 11:00:07 AM

差分がなければテストは走らない。 ~testQuick と頭にチルダをつけておけば、ソースコードの変更を監視して、必要なテストだけ走るのでローカルで開発するときに便利。

REPL機能

ScalaのREPLですが、ビルドしたアプリケーションのクラスを呼び出したりできます。補完も効く。

ubuntu@c01:~/java-project-sample$ sbt
[info] Loading project definition from /home/ubuntu/java-project-sample/project
[info] Set current project to Hello (in build file:/home/ubuntu/java-project-sample/)
> console
[info] 'compiler-interface' not yet compiled for Scala 2.12.1. Compiling...
[info]   Compilation completed in 12.547 s
[info] Starting scala interpreter...
[info]
Welcome to Scala 2.12.1 (OpenJDK 64-Bit Server VM, Java 1.8.0_121).
Type in expressions for evaluation. Or try :help.

scala> import example.Hello
import example.Hello

scala> Hello.main(Array())
Hello World!

scala> Hello.
echo   join   main

scala> Hello.join("hoge", "fuga")
res2: String = hogefuga

他にも便利な機能はたくさんあるのでJavaプロジェクトでもsbtは結構使えるんじゃないかなぁと。

sbt Reference Manual — 始める sbt

クラウドネイティブ世代の新卒2年目が「進化する銀行システム」を読んだ

クラウドネイティブ世代

自分で適当に思いついた言葉だったんですが、どうやら既出だったようです。

https://image.slidesharecdn.com/20150731cloudnative-150731102613-lva1-app6892/95/-11-638.jpg?cb=1438338435 *1 クラウドネイティブ世代がインフラに触れるということ

入社して配属されてから今までほぼ100% AWSを使っている環境ですし、社会人になるまでサービス運用はしたことがなかったので、僕はクラウドネイティブ世代と言っていいでしょう。

クラウド

クラウドネイティブ世代はどんな感じかといいますと、いくらクラウドとはいえど最初はおそるおそる使っていたんですが、すぐに慣れてしまい、一時的に必要な性能を見積もって1時間だけだし2500円くらいか、と思ってボタンを押したらCPUを400コアくらい使っていた感じです。自分でも「これがクラウド脳か」と思いました。サーバをラックマウントしてくれる人の苦労も忘れたらいけない。圧倒的感謝🙏

反動

クラウド時代を表す言葉として「ペットから家畜へ」*2 という言葉が有名で、この言葉を借りると、僕は家畜しか飼った事がないことになります。家畜(クラウド)は1個体1個体の細かいコンディションを気にしてはいられませんし、全体としてのパフォーマンスや効率を求めます。

家畜と戯れていると、ペットが欲しくなります。これが反動です。

「進化する銀行システム」の見本を頂いた

こんな環境(?)で働いているのですが、クラウドと正反対の環境としてまず思い浮かぶのがメインフレームであり、その代表例が銀行等のシステムでした。 メインフレームは、実物を目にしたことはなく、信頼性とお値段が桁違い、というイメージはあるものの、どんな使われ方をしているかは知りませんでした。

参考: *3 メインフレームサーバーの凄さについて

そんな時に、今月発売された「進化する銀行システム 24時間365日動かすメインフレームの設計思想」の見本を技評さんにいただきました。

Kindle版もありますよ。

ここからはこの本の概要や読んで思ったことを書いていきます。

この本の概要

タイトルを見て銀行システムについての内容がほとんどかと思ったのですが、銀行システムについてが1/3くらいで、2/3はメインフレームについてです。 銀行システムもメインフレームも前知識はほぼない状態で読んだのですが、何も知らなくてもわかるように丁寧に解説されています。ただ、Linux等のなんとなくな知識はあった方が何が違うのか?という点について考えながら読むことができて面白いかなと思います。

銀行の勘定系オンラインシステムの特徴と歴史

全てが手作業だった時代からオンライン化がはじまり、それが当たり前になったからこそ社会的な責任が大きくなり、「止められないシステム」になっていった流れがわかりやすかったです。銀行システムには世代があって、今はポスト第三世代と呼ばれているんですね。経営統合によるシステム統合、全銀システムを経由した送金の処理等々、止められない分歴史的経緯が絡んで難しくなっているのかなぁという印象を受けました。

メインフレームのハードウェア, ソフトウェア

メインフレームといえば大きくていかつい見た目を想像していましたが、やはりそうなんですね。ハードウェアのあらゆる部分が二重化されていて、特定の処理をするための専用モジュールが多く搭載されているようです。IBMのz/OSというOSが生誕50周年を超えているそうで、50年以上同じアーキテクチャのものが開発されて運用され続けてるのはすごいですね。

それとは別に、開発やテストはどういった環境で行うのかが疑問でした。メインフレームは高価でしょうから、手元のPCでテストコードを回したりできるのでしょうか。あと、リリース前の確認とか調査をするためのステージング環境とかも用意しているのでしょうか。

システムの安定性, 性能を高める技術

災害対策、いわゆるディザスタリカバリですが、災害時にシステムが切り替わる先を災害対策センタと呼ぶようです。システムを切り替えるにもそれまでレプリケーションされていたトランザクションのログのロード方法やリカバリ方法が色々あるようです。性能面ではDBとトランザクションについての記述が多かったです。専門用語が多かったのでまだ理解しきれていませんが、銀行なのでDBとトランザクションは肝ですよね。

メインフレームLinuxより優れているのか?

11章で、オープン系(Linuxとか)ではなく、なぜメインフレームが選ばれ続けているのかについて書かれているところが一番印象に残っています。メインフレームが選ばれる理由として

  1. 信頼性に優れている
  2. 可用性に優れている
  3. 互換性に優れている
  4. 拡張性に優れている
  5. 業務全体の処理効率が優れている
  6. I/O処理の効率が優れている

の6つがあり、その他実績等を総合してメインフレームが選ばれると書かれています。

今日においても本当にそうでしょうか?

全てに置いてハードウェアが二重化されている物と比べれば信頼性は劣りますが、ソフトウェアによって可用性が担保できますし、ハードウェアが安価な分、量でカバーできるはずなので問題にはならなさそうです。 互換性は、Linuxで20年後も全く同じ状態のソフトウェアが動くかと言われると怪しいですが、CI/CDといった手法によってメンテナンスされれば動くことは保証されますし、最新の状態に追従できているソフトウェア資産の方が価値が高いはずです。拡張性はスケールアウトしかありませんし、処理効率はソフトウェアで改善ができます。I/Oはどうなのでしょう?ソフトウェアのアーキテクチャから工夫をすれば対抗できるかもしれません。ただ外部入出力にあたるネットワークは変わらないはずなのでそこがボトルネックになれば同じ条件かもしれません。

読んでいるうちに6つの要素について、昨今の技術ならLinuxでも満たす事はできそうだし、実は 実績 が一番の理由なのではないかと思い始めました。

クラウドメインフレーム

f:id:kuro_m88:20170222011934p:plain

この写真は、ラスベガスで開催されたAWSのre:invent 2016*4でJames Hamilton氏が"A toast to the death of the mainframe!“ (メインフレームの死へ乾杯!)と言ってステージ上で乾杯を始めた時に撮った写真なのですが、この発表では、メインフレームを数十年間使い続けた企業がAWSに移行した例が出てきました。ここ最近でこういった例が増えてきているようです。 メインフレームの顧客をクラウドが奪うという意味では対立していますが、この本を読んで技術的に対立/対抗している物ではなさそうだという印象を受けました。

そこで思いついたのが、クラウドは「超巨大なメインフレーム」なんじゃないかという説です。 AWSで例を挙げると、柔軟な計算リソースはEC2、信頼性、可用性、拡張性に優れたストレージとしてS3、シームレスに拡張できるDBとしてDynamoDBがあります。GCPだと最近発表されたCloud Spanner*5が熱いですね。それぞれ別々のサービスとしてではなく、全部入りの一つの巨大なシステムを多数のユーザで共有してると考えるとメインフレームが超巨大になっただけに見えてきます。ユーザごとに見れば必要なだけリソースをスケールアウト/インさせていますが、実際のクラウド事業者のデータセンタ(メインフレームの箱)のサイズは変わらないですからね。新しいメインフレームが出て、要件が見合った企業は移行しているイメージでしょうか。 自分はこの説で今の流れがなんとなくしっくり来た気がします。

これだけ規模が大きくなれば実績が積まれるのは時間の問題ですし、自分も実績を作って行きたいですね💪

メインフレームの本当のところは仕事で関わってみないとわからないと思うのですが、今のところ関わる事がなさそうなので、想像だけしてみました。面白かった。

紹介した本

左右分離型のキーボードMistel Barocco MD600が販売再開されたみたいなので買った

Mistelの左右分離型キーボード、Baroccoが昨年末に欲しいと思って注文しようとしたら、ずっと品切れで、最近ようやく販売再開したみたいです。ようやく買うことに成功しました。

Baroccoとは

詳細はレビューしている記事があるのでこちらをどうぞ。

www.gdm.or.jp

特徴をまとめると、

  • 左右分離型メカニカルキーボード
  • スイッチにはCherry MX採用
  • (左右合わせると)HHKBくらいのサイズ
  • キーボード単体でキーの入れ替えやマクロの設定が可能

といった感じ。左右分離型のカスタマイズ可能なキーボードというと、ErgoDoxが有名ですが、ErgoDoxが約3万7千円程度に対してBaroccoは約1万6千円とだいぶ安い(?)です。

左右分離式のキーボードは肩がこりにくそうでいいなぁと思って前から注目していたのですが、ErgoDoxほどのカスタマイズ性はいらないし、慣れるかどうか不安だったのでもうすこし安いものを探していたので手に入ってよかったです。

今まではHHKBを使ってたので、似たような使い心地かなと思い、Baroccoの茶軸モデルを買いました。

届いたので使うための準備

左右を接続するためのUSBケーブルとか、キーキャップの引き抜き工具も付属しています。

左右接続ケーブル

左右を接続するためのケーブルは付属品だと短いので、離して使いたい場合は自分でケーブルを用意する必要があります。 このケーブルは両端がUSB MicroBという少し変わったケーブルなので、たぶん手元にある人は少ないのではないかなと思います。

スマホの充電や通信用に持っていたのはUSB A - USB Micro Bのケーブルだったので、これに USB A(メス) - USB - MicroB(オス) の変換アダプタをつけてキーボードの左右を接続するケーブルを作りました。

僕が試したところ、変換アダプタは、キーボードの左側に接続しないと認識してくれないようでした。

静音リング

そのままでも特に問題はないのですが、Cherryスイッチの底打ちした時の硬い感じがあまり好きじゃなかったので、静音リング(ただのOリング)をキーの軸にはめることでクッションの役割をさせています。静音にもなるらしいです。

f:id:kuro_m88:20170211114902j:plain

こんな感じでキーキャップの裏にはめます。ピンセットで奥まで押し込んだ方がいいです。

音の比較動画撮ってみました。体感的にはまぁまぁ静かになるかなといった感じです。

www.youtube.com

最上段のキーなどはOリングを1つはめただけだと効果がなかったので2つはめたりしています。このあたりは実際に打ってみて1つはめるところと2つはめるところ調節してみるのがいいです。

リストレスト

しばらく使っていると、上段のキーが届きにくい気がしてきたのでリストレストを買ってみました。特にこだわりはなかったのでエレコムの400円のやつを買いました。

普通のキーボード用のリストレストだと長いので、マウス用のリストレストを2個買うのがよさそうです。

キーの入れ替え設定

HHKBを使っていたので、それと近い感じにするために以下の入れ替え設定をしました。

  • 左alt → 左Command
  • 右alt → 右Command
  • CapsLock → 左Ctrl
  • Win → Alt
  • BackSpace → |
  • | → BackSpace

設定方法は↓がわかりやすかったです。

qiita.com

感想

ThinkPadキーボード → HHKB → Baroccoと買い替えて来て、左右分離式は慣れるか不安があったのですが、タイピングソフトでしばらく練習していたらすぐ慣れました。 あとは仕事でしばらく使ってみて、肩こりが減るかどうか次第ですね!

紹介したものたち

LXDを本番導入するときに気をつけるべき事

本番導入しようとして困った

某コンテストの予選の環境にLinuxコマンドの使えるホストが50個ほど必要だったので、LXD/LXCでまかなうことにした。

Failed to allocate directory watch: Too many open files とか Failed to allocate directory watch: Too many open files とかエラーが出て困っている人向け。

実験

環境

構築

$ sudo apt -y install software-properties-common
$ sudo add-apt-repository ppa:ubuntu-lxc/lxd-stable
$ sudo apt update && sudo apt dist-upgrade
$ sudo apt -y install lxd zfs
$ newgrp lxd
$ sudo lxd init

LXDのコンテナを20個立ち上げてみる

手動で20回コマンド打つのはつらいのでスクリプト書いたほうが速いかもしれない。

ubuntu@lxd01:~$ lxc launch ubuntu:16.04 c01
Creating c01
Starting c01
ubuntu@lxd01:~$ lxc launch ubuntu:16.04 c02
Creating c02
Starting c02
...
ubuntu@lxd01:~$ lxc launch ubuntu:16.04 c20
Creating c20
Starting c20

立ち上がったコンテナを確認

ubuntu@lxd01:~$ lxc list
+------+---------+----------------------+------+------------+-----------+
| NAME |  STATE  |         IPV4         | IPV6 |    TYPE    | SNAPSHOTS |
+------+---------+----------------------+------+------------+-----------+
| c01  | RUNNING | 10.58.243.4 (eth0)   |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c02  | RUNNING | 10.58.243.10 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c03  | RUNNING | 10.58.243.124 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c04  | RUNNING | 10.58.243.145 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c05  | RUNNING | 10.58.243.2 (eth0)   |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c06  | RUNNING | 10.58.243.174 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c07  | RUNNING | 10.58.243.252 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c08  | RUNNING | 10.58.243.218 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c09  | RUNNING | 10.58.243.247 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c10  | RUNNING | 10.58.243.93 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c11  | RUNNING | 10.58.243.189 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c12  | RUNNING | 10.58.243.13 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c13  | RUNNING | 10.58.243.90 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c14  | RUNNING | 10.58.243.177 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c15  | RUNNING | 10.58.243.71 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c16  | RUNNING | 10.58.243.248 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c17  | RUNNING |                      |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c18  | RUNNING |                      |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c19  | RUNNING |                      |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c20  | RUNNING |                      |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+

なんかおかしい

16個くらいコンテナを立ち上げたあたりからIPアドレスが振られていない。 c16とc17のプロセスの状態を比較してみる。

ubuntu@lxd01:~$ lxc exec c16 -- ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.2  37396  2552 ?        Ss   04:07   0:01 /sbin/init
root        46  0.0  0.1  33436  1652 ?        Ss   04:07   0:00 /lib/systemd/systemd-journald
root       214  0.0  0.0  16128    80 ?        Ss   04:09   0:00 /sbin/dhclient -1 -v -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df
root       306  0.0  0.1  26068  1096 ?        Ss   04:09   0:00 /usr/sbin/cron -f
root       308  0.0  0.1  20100  1268 ?        Ss   04:09   0:00 /lib/systemd/systemd-logind
root       310  0.0  0.3 436792  3176 ?        Ssl  04:09   0:00 /usr/lib/accountsservice/accounts-daemon
daemon     311  0.0  0.0  26044   880 ?        Ss   04:09   0:00 /usr/sbin/atd -f
syslog     313  0.0  0.1 186900  1428 ?        Ssl  04:09   0:00 /usr/sbin/rsyslogd -n
message+   314  0.0  0.1  42896  1552 ?        Ss   04:09   0:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root       324  0.0  0.2  65520  2724 ?        Ss   04:09   0:00 /usr/sbin/sshd -D
root       325  0.0  0.7 263660  7796 ?        Ssl  04:09   0:00 /usr/lib/snapd/snapd
root       340  0.0  0.1  12844  1056 console  Ss+  04:09   0:00 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 linux
root       363  0.0  0.3 277080  3292 ?        Ssl  04:09   0:00 /usr/lib/policykit-1/polkitd --no-debug
root       666  0.0  0.1  34424  1892 ?        Rs+  04:17   0:00 ps aux

ubuntu@lxd01:~$ lxc exec c17 -- ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  37264   808 ?        Ss   04:07   0:00 /sbin/init
root       203  0.0  0.1  34424  1596 ?        Rs+  04:17   0:00 ps aux

c17以降はsystemdが立ち上がっていないことがわかった。

試しにc17でsshdを起動してみる。

root@c18:~# systemctl start ssh
Failed to allocate directory watch: Too many open files
Job for ssh.service canceled.

コンテナ側ではほとんどファイルを開いていないので、ホスト側の全体でのリソースの制限に引っかかってしまったようだ。 Failed to allocate directory watch: Too many open files とか Failed to allocate directory watch: Too many open files とか出たら同様の現象の可能性がある。

ドキュメントをよく読むと

LXDの公式リポジトリを見ていたら production-setup.md にちゃんと本番導入する時に考慮しないといけないことが書いてあった。

github.com

対策

/etc/security/limits.conf に以下の内容を追記

*               soft    nofile          1048576
*               hard    nofile          1048576
root            soft    nofile          1048576
root            hard    nofile          1048576
*               soft    memlock         unlimited
*               hard    memlock         unlimited

/etc/sysctl.conf に以下の内容を追記

fs.inotify.max_queued_events = 1048576
fs.inotify.max_user_instances = 1048576
fs.inotify.max_user_watches = 1048576
vm.max_map_count = 262144

上記2点の作業をしたら再起動。

確認

どのコンテナもちゃんとプロセスが動いている事を確認。

ubuntu@lxd01:~$ lxc list
+------+---------+----------------------+------+------------+-----------+
| NAME |  STATE  |         IPV4         | IPV6 |    TYPE    | SNAPSHOTS |
+------+---------+----------------------+------+------------+-----------+
| c01  | RUNNING | 10.58.243.4 (eth0)   |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c02  | RUNNING | 10.58.243.10 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c03  | RUNNING | 10.58.243.124 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c04  | RUNNING | 10.58.243.145 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c05  | RUNNING | 10.58.243.2 (eth0)   |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c06  | RUNNING | 10.58.243.174 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c07  | RUNNING | 10.58.243.252 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c08  | RUNNING | 10.58.243.218 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c09  | RUNNING | 10.58.243.247 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c10  | RUNNING | 10.58.243.93 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c11  | RUNNING | 10.58.243.189 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c12  | RUNNING | 10.58.243.13 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c13  | RUNNING | 10.58.243.90 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c14  | RUNNING | 10.58.243.177 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c15  | RUNNING | 10.58.243.71 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c16  | RUNNING | 10.58.243.248 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c17  | RUNNING | 10.58.243.36 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c18  | RUNNING | 10.58.243.184 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c19  | RUNNING | 10.58.243.211 (eth0) |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+
| c20  | RUNNING | 10.58.243.23 (eth0)  |      | PERSISTENT | 0         |
+------+---------+----------------------+------+------------+-----------+


ubuntu@lxd01:~$ lxc exec c18 -- ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.3  0.1  37396  1184 ?        Ss   04:39   0:00 /sbin/init
root        45  0.1  0.1  33436  1172 ?        Ss   04:39   0:00 /lib/systemd/systemd-journald
root        50  0.0  0.0  41724   208 ?        Ss   04:39   0:00 /lib/systemd/systemd-udevd
root       240  0.0  0.0  16120    52 ?        Ss   04:40   0:00 /sbin/dhclient -1 -v -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df
message+   312  0.0  0.0  42896   616 ?        Ss   04:40   0:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root       317  0.0  0.0  20100   392 ?        Ss   04:40   0:00 /lib/systemd/systemd-logind
root       319  0.1  0.0 198124     0 ?        Ssl  04:40   0:00 /usr/lib/snapd/snapd
root       322  0.0  0.0  27728   148 ?        Ss   04:40   0:00 /usr/sbin/cron -f
daemon     323  0.0  0.0  26044   264 ?        Ss   04:40   0:00 /usr/sbin/atd -f
root       324  0.1  0.0 634952   404 ?        Ssl  04:40   0:00 /usr/lib/accountsservice/accounts-daemon
syslog     325  0.0  0.0 186900   580 ?        Ssl  04:40   0:00 /usr/sbin/rsyslogd -n
root       326  0.0  0.0  65520   212 ?        Ss   04:40   0:00 /usr/sbin/sshd -D
root       348  0.0  0.0  14476   312 console  Ss+  04:40   0:00 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 linux
root       376  0.0  0.0 277180   368 ?        Ssl  04:41   0:00 /usr/lib/policykit-1/polkitd --no-debug
root       466  0.0  0.1  34424  1648 ?        Rs+  04:42   0:00 ps aux

めでたしめでたし。