はじめに
みなさん、Alpine Linux 使ってますか?
雪餅のインフラ環境では、あらゆるサービスが docker-compose による複数 Docker コンテナの組み合わせにより構築されています。それらのコンテナ内は、 scratch
や alpine
ベースのイメージを多用しているのですが、ホスト OS に何を採用するか長い間悩んでいました。
VPS を効率よく Docker コンテナホストに仕立てあげるために、以下のポイントから Alpine Linux を採用してみた記録です。
- ディストリビューションに必要なディスク容量が少ない
- パッケージマネージャが高速でリポジトリのソフトウェアが新しい
- 常駐サービスが既定で最小限
- Ansible での環境構築が可能(容易)
- Docker が公式リポジトリに存在
- x86-64 と aarch64 で同様に構築可能
Alpine Linux とは
軽量でシンプルな Linux ディストリビューションで、セキュリティを重視した方法でカーネルがビルドされています。
Alpine Linux is an independent, non-commercial, general purpose Linux distribution designed for power users who appreciate security, simplicity and resource efficiency.
iso イメージは、 カーネル内のデバイスドライバや同梱されるアプリケーションによって分けられています。 VPS で利用する場合、無駄の少ない VIRTUAL
を利用することになると思います。 また、Raspberry Pi 向けのイメージもあります。
インストール
iso イメージからブートし、 root でログインし、 setup-alpine
コマンドを利用します。ウィザードにしたがえば、ものの 2 分ほどでインストールは終わります。
環境構築
Alpine Linux は、パッケージ管理に apk
, init に OpenRC
, libc に musl-libc
を採用しています。init と libc はあまり一般的でないものですが、リポジトリが比較的豊富なのでインストールやビルドが必要になって困ることは少ないでしょう。また、apk
は yum
や apt
よりもきわめて高速で、依存関係の解決がシンプルです。
python のインストール
Ansible でセットアップするために python は手動で入れておきます。
apk add python
Ansible で環境構築する。
Alpine で Ansible playbook するときのポイント
- Alpine Linux のはまりポイントを避けるためのパッケージ群
coreutils
– GNU 製の utils。 Alpine Linux でコマンドを提供する busybox は仕様が異なり、Ansible の各種 module と互換性がないことが多いため。curl
–get_url
module を使いたい場合は入れておく。shadow
– useradd などのユーザー操作系の多くのコマンドを Alpine Linux で利用できるようにする。user
module を使いたい場合は入れておく。docker
– Alpine Linux の Community Repository からは、比較的新しい Docker を利用できるのでそのまま使います。py-pip
–docker-compose
をpip
module でインストールするために入れておきます。docker-compose
公式で提供されている pyInstall 版のシングルバイナリは、 glibc 向けにビルドされており使えません。
playbook 例
basic.yml
(環境構築)
tasks:
-
lineinfile:
line: "http://dl-cdn.alpinelinux.org/alpine/v3.8/community"
path: /etc/apk/repositories
state: present
name: "Community ベースのリポジトリを有効にします。"
-
apk:
name: "python,py-pip,sudo,coreutils,curl,git,htop,rsync,shadow,docker"
state: present
update_cache: true
name: "パッケージの導入 python py-pip sudo coreutils curl git htop rsync shadow docker"
-
name: "{{ username }} ユーザーを作成し、 wheel グループに所属させる。"
user:
append: true
groups: wheel
home: "/home/{{ username }}"
name: "{{ username }}"
password: hogefuga
shell: /bin/sh
uid: 1000
-
authorized_key:
key: "{{ item }}"
state: present
user: "{{ username }}"
name: "{{ username }} に SSH 公開鍵を登録する。"
with_file:
- public_keys/hogefuga.pub
-
lineinfile:
backrefs: true
line: "%wheel ALL=(ALL) NOPASSWD: ALL"
path: /etc/sudoers
regexp: "^#?\\s%wheel ALL\\=\\(ALL\\) NOPASSWD"
state: present
name: "パスワードなし sudo を wheel に許可させる。"
-
lineinfile:
backrefs: true
dest: /etc/ssh/sshd_config
line: "{{ item.line }}"
regexp: "{{ item.regexp }}"
state: present
name: "sshd_config を編集する。"
notify:
- "restart sshd"
with_items:
-
line: "PermitRootLogin prohibit-password"
regexp: "^#?\\s*PermitRootLogin"
-
line: "PasswordAuthentication no"
regexp: "^#?\\s*PasswordAuthentication yes"
-
line: "PubkeyAuthentication yes"
regexp: "^#?\\s*PubkeyAuthentication"
-
name: "dockerd を有効化させる。"
service:
enabled: true
name: docker
state: started
-
name: "docker-compose をインストールする。"
pip:
name: docker-compose
handlers:
-
name: "sshd の再起動をする。"
service:
enabled: true
name: sshd
state: restarted
mackerel-agent を使う
監視として mackerel-agent を使う場合、公式で公開されているバイナリは glibc 向けにビルドされているため動きません。
静的ビルドされた mackerel-agent を得るには、 Windows で 環境変数 GOOS=linux
, GOARCH=amd64
or GOARCH=arm64
を与えて、 go get github.com/mackerelio/mackerel-agent
するのが一番簡単だと思います。
OpenRC 向けの init スクリプトも必要となります。
playbook 例
openrc-init/mackerel-agent
##!/sbin/openrc-run
## Copyright 2014 Shota Fukumori (sora_h) <her@sorah.jp>
## Distributed under the terms of the MIT License
## $Header: $
LOGFILE=${LOGFILE:-/var/log/mackerel-agent.log}
pidfile=${PIDFILE:-/var/run/mackerel-agent.pid}
CONFIG=${CONFIG:-/etc/mackerel-agent/mackerel-agent.conf}
ROOT=${ROOT:-/var/lib/mackerel-agent}
if [ -n "$BASIC" ]; then
APIBASE=${APIBASE:="https://${BASIC}@mackerel.io"}
else
APIBASE=${APIBASE:="https://mackerel.io"}
fi
command=/usr/bin/mackerel-agent
command_args="--apibase=$APIBASE --conf=$CONFIG --pidfile=$pidfile"
command_background=true
start_stop_daemon_args="-1 ${LOGFILE} -2 ${LOGFILE}"
amd64-bin/mackerel-agent
amd64 向け静的ビルド mackerel-agent バイナリ
amd64-bin/mackerel-agent
arm64 向け静的ビルド mackerel-agent バイナリ
mackerel-agent.yml
tasks:
-
copy:
dest: /usr/bin/mackerel-agent
mode: 493
src: amd64-bin/mackerel-agent
name: "mackerel-agent static をインストールする。"
-
name: "mackerel-agent config の存在確認を行う。"
register: _mackerel_conf
stat:
path: /etc/mackerel-agent/mackerel-agent.conf
-
file:
mode: 493
path: /etc/mackerel-agent
state: directory
when: "not _mackerel_conf.stat.exists"
-
file:
mode: 420
path: /etc/mackerel-agent/mackerel-agent.conf
state: touch
when: "not _mackerel_conf.stat.exists"
-
command: "/usr/bin/mackerel-agent init -apikey <Your Mackerel API key>"
name: "mackerel-agent conf の初期化を行う。"
when: "not _mackerel_conf.stat.exists"
-
copy:
dest: /etc/init.d/mackerel-agent
mode: 493
src: openrc-init/mackerel-agent
name: "mackerel-agent の OpenRC 向け init スクリプトを設定する。"
-
name: "mackerel-agent を有効化する。"
service:
enabled: true
name: mackerel-agent
state: started
評価
最小環境のディスク利用量
格安 VPS の一つ Vultr では、カスタム iso インストールで Alpine Linux をサポートしています。この環境へインストールした際の ディスク・メモリ使用量を記したものが以下の通りです。
- Vultr 1-CPU 512MB-RAM 20GB-SSD での検証
- インストール直後
- 実行中のプロセス (参考)
PID USER TIME COMMAND 1 root 0:00 /sbin/init 1845 root 0:00 udhcpc -b -p /var/run/udhcpc.eth0.pid -i eth0 -x hostname:localhost 1917 root 0:00 /sbin/syslogd -Z 1971 root 0:00 /sbin/acpid 2000 chrony 0:00 /usr/sbin/chronyd -f /etc/chrony/chrony.conf 2027 root 0:00 /usr/sbin/crond -c /etc/crontabs 2059 root 0:00 /usr/sbin/sshd 2063 root 0:00 /sbin/getty 38400 tty1 2064 root 0:00 /sbin/getty 38400 tty2 2067 root 0:00 /sbin/getty 38400 tty3 2069 root 0:00 /sbin/getty 38400 tty4 2072 root 0:00 /sbin/getty 38400 tty5 2076 root 0:00 /sbin/getty 38400 tty6 2120 root 0:00 /usr/lib/ssh/sftp-server
- ディスク使用量
Filesystem Size Used Available Use% Mounted on /dev/vda1 92.8M 12.6M 73.3M 15% /boot /dev/vda3 18.5G 112.8M 17.4G 1% /
- mackerel-agent まで導入
- ディスク使用量
Filesystem Size Used Avail Use% Mounted on /dev/vda1 93M 13M 74M 15% /boot /dev/vda3 19G 388M 18G 3% /
- インストール直後
ディスク使用量は、Docker インストール済みの状態で 388MB に収まります。これによって、 VPS のディスクを最大限にアプリケーションに使うことができ、コストを抑えられます。
Mastodon Worker の運用事例 (メモリ使用量)
Vultr 1-CPU 2048MB-RAM 40GB-SSD において、Mastodon on debian w/ jemalloc 5.1.0 の Docker コンテナ Sidekiq (並行数設定 50) を 4 コンテナ実行していた環境でのメモリ利用量です。
- CoreOS Beta 1939.2.1 利用時約 1.55 GB
- Alpine Linux 3.8.1 利用時約 1.15 GB
原因はわかっていませんが、 CoreOS 1939.2.1 環境と比較して 400MB ほどメモリ利用量を抑えることができています。
その他
Scaleway について
Scaleway で Alpine Linux を使う場合、 x86-64 であれば公式のイメージ選択から選ぶことができます。ARM64 の場合は、 scaleway/image-builder と scaleway/image-alpine を用いて DockerHub の alpine:3.8 を Scaleway 用のイメージに変換することができます。
感想
今回、 CoreOS をベースにしていたすべての環境を Alpine Linux に置き換えました。もともと、 k8s の導入が見送りになっていたために、 CoreOS は無駄に不便を強いる存在になっていたということでもあります。 Alpine Linux は、もともと入っているパッケージが少なく、 apk も高速であるため Ansible で様々な VPS を跨いで管理するにも楽で良いなと思っています。
みなさんもぜひ、 Alpine Linux を Docker ホストに使ってみませんか?情報が少ないため、トラブルの保証は致しかねますが、ぜひ試してみてください!