2019年3月21日木曜日

Docker コンテナが [!!!!!!] Failed to early mount API filesystems, freezing. と言って死ぬときの回避策

TL;DR

コンテナを init で起動すると死ぬ。

$ docker run -it ubuntu:16.04 init
[!!!!!!] Failed to early mount API filesystems, freezing.

--cap-add=SYS_ADMIN-v /sys/fs/cgroup:/sys/fs/cgroup:ro を付けたら行けた。

$ docker run -it --cap-add=SYS_ADMIN -v /sys/fs/cgroup:/sys/fs/cgroup:ro ubuntu:16.04 init
systemd 229 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN)
Detected virtualization vm-other.
Detected architecture x86-64.

Welcome to Ubuntu 16.04.5 LTS!

 ...

何か起きたか

ansiblesystemd 辺りをセットアップする playbook を書いたため検証しようと思ったが、わざわざ仮想マシンを起こすのもめんどくさかった。
ので、コンテナの中で systemd を、ひいては init を起こした。

docker run -it ubuntu:16.04 init

すると、 [!!!!!!] Failed to early mount API filesystems, freezing. と出力して死んだ。

何が問題だったか

どうやらコンテナ起動コマンドを init にすると、諸々の権限が足りず起動に失敗するらしい。
( 詳細までは元気が足りず調べられていない )

解決策 or 回避策

docker run するときに capability SYS_ADMIN を追加した上で、/sys/fs/cgroup を読み込み専用でマウントしてやると起動できた。

docker run -it --cap-add=SYS_ADMIN -v /sys/fs/cgroup:/sys/fs/cgroup:ro ubuntu:16.04 init

備考

最初に Google 先生に聞いてみたときには、 docker run するときに --privileged オプションを付けて特権モードで起動しろなどという恐ろしい助言が出てきたが、試してみると確かに init は起こせた。

しかし、複数のコンテナを --privileged で起動すると謎の CPU の高騰に悩まされた。
( 確か。結構昔のことなので正確に覚えていない。 )

できることなら特権を与えるなんて危険なことはしたくなかったので、もうちょっと権限を絞りたいと思って色々試したところ、↑な感じで行けた。

SYS_ADMIN よりも細かく capabilities を絞ってできるかどうかは試せていない。


参考

2019年3月16日土曜日

tcpdump を時限開始して自動で停止させる

tcpdump を時間を指定して実行したいけど、 わざわざ cron を設定したくなかった。

以下例では、 2019 年 3 月 16 日 10:00 AM に tcpdump を開始し、 300 秒後に終了する。

while sleep 0.1; do
  if [ $(date +%Y%m%d%H%M) -ge 201903161000 ]; then
    sudo tcpdump -G300 -W1 -vvv -n -p -s 65535 -w "$(uname -n)_%Y%m%dT%H%M%S.pcap"
    break
  fi
done
  • tcpdump
    • -G {数字}: {数字}秒間実行する
    • -W {数字}: {数字}回ローテートする
    • -n: IPアドレスやポートをそのまま表示する
    • -p: プロミスキャスモード を有効にしない
    • -s: キャプチャするサイズを指定する ( MTUより大きくすれば OK )

2019年3月15日金曜日

バージョニングが有効化されている S3 バケットを削除したい

バージョニングが有効化されている S3 バケットを削除したいと思ったのですが、aws s3api に見当たらなかったので boto3 で簡単に書きました。

以下を delete-bucket.py などとして実行します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import boto3
from boto3.session import Session

boto3.set_stream_logger()

session = Session(profile_name='YOUR_AWS_PROFILE_NAME')
s3 = session.resource('s3')
bucket = s3.Bucket('YOUR_S3_BUCKET_NAME')

# 全オブジェクトの削除
bucket.object_versions.delete()

# バケットの削除
bucket.delete()

実行するときの注意

上のまま実行すると、標準出力に大量のログ(削除したオブジェクトのバージョンの一覧)が出力されるので、以下のようにして実行することをおすすめします。

$ python ./delete-bucket.py | gzip -c >./delete-bucket_$(date +%Y%m%d_%H%M%S).log.gz

参考

2019年3月13日水曜日

diff コマンドに色をつけたいけど colordiff みたいな別のコマンドはインストールしたくない

色付き diff が見たいたいけど colordiff みたいな別のコマンドはインストールしたくないシーンがあったので、 プレーンな diff コマンドに bash で、というか主に sed で、無理やり色をつけました。
ssh先 ( 最近だと kubectl exec ですかね ) のサーバーで色付き diff が欲しい時に重宝します。

difff() {(R=$(printf '\e[31m');G=$(printf '\e[32m');B=$(printf '\e[36m');W=$(printf '\e[1m');N=$(printf '\e[0m');diff -u "$@"|sed $(uname -s|grep -q '^Darwin'&&printf -- -E||printf -- -r) "s/^(@@.+@@|@@.+@@)$/$B\1$N/g;s/^(\+.*)$/$G\1$N/g;s/^(\-.*)$/$R\1$N/g;s/^[^\+\-]*((\+{3}|-{3}) [^ ].*)/$W\1/g;")}

実行例はこちら。

$ difff A.txt B.txt

git diff で見慣れた感じで出すようにしています。

Ubuntu 16.04, 同 18.04, CentOS 7, Alpine Linux (2019-03-12 時点で latest で降ってきたやつ) 辺りで動作確認済み。

-r オプションないし -E オプションがある sed + POSIX な環境であれば動くんじゃないかなと思います。

production 環境で apt install colordiff とか yum install colordiff とか apk --add colordiff なんて罪深いことはやりたくないです。