あらしおブログ

技術ネタ中心の粗削りブログ

Docker コンテナ起動時にエラー System error: write /sys/fs/cgroup/devices/...: no such device がでたときの対処法

CentOS 7 + Docker 1.9 で以下のようなエラーがでて、コンテナがたまに起動できなくなることがありました。 そのときの対処法をまとめておきます。

Error response from daemon: Cannot start container 479acdbe53fc117178f9797bce1eaf3a4c3b68021f22df2f3e0f95bd28afdb6b: [8] System error: write /sys/fs/cgroup/devices/system.slice/docker-479acdbe53fc117178f9797bce1eaf3a4c3b68021f22df2f3e0f95bd28afdb6b.scope/cgroup.procs: no such device

原因

CentOS 7 の systemd によるリソース管理と Docker の相性が悪く、このようなエラーが発生する場合があるようです。 障害報告を見ると、 それ以外のディストリビューションでの報告はないので、RedHat 7 系 + systemd 固有の問題なのかもしれません。

Docker ではリソース管理ドライバとして、この systemd または、 Docker 独自のドライバである cgroupfs を使うことができます。 Docker 1.9 系ではデフォルトで systemd を使うようになっています。

回避策

Docker の起動オプションに --exec-opt native.cgroupdriver=cgroupfs を追記することで解決しました。 起動オプションの設定は /etc/sysconfig/docker にあります。

OPTIONS='--exec-opt native.cgroupdriver=cgroupfs  ... '

再起動で設定を反映

sudo systemctl restart docker

なお、Docker 1.10 以降はデフォルトで cgroupfs を使うようになったので、Docker のアップデートで解決することもできるようです。

参考: Random "Cannot start container" Errors on 1.9.0-rc5 CentOS7 · Issue #17653 · docker/docker · GitHub

Bitnami Redmine の MySQL がクラッシュしたときのデータ復旧方法

Bitnami RedmineMySQL でデータ破損などでクラッシュして、MySQL が起動できなった場合のデータ復旧手順です。

以下で /path/to/redmine は、Bitnami Redmine のインストール先に読み替えてください。

1. Bitnami Redmine を停止
sudo service bitnami-redmine stop
2. データをバックアップ

これは万が一のためです。データ復旧が成功すれば特に使いません。

cp -ra /path/to/redmine/mysql /tmp/mysql.backup
3. 強制リカバリオプションを指定

/path/to/redmine/mysql/my.cnf で innodb_force_recovery オプションを指定します。

[mysqld]
innodb_force_recovery=1

オプションの詳細はリファレンスマニュアルを参照してください。 基本的には innodb_force_recovery の値をまずは 1 に設定し、mysqld が起動するか確認します。 起動しない場合は徐々に数字を上げていきます。 最大は 6 で、4以上はデータ破損の可能性があり危険と言われています。必ずバックアップをとっておきましょう。 また強制リカバリモードで起動すると、データベースは読み取り専用になっています。

以下はリファレンスマニュアルからの抜粋です。

innodb_force_recovery は、デフォルトでは 0 です (リカバリが強制的に実行されない通常の起動)。innodb_force_recovery の許可される 0 以外の値は 1 から 6 までです。大きい方の値には、小さい方の値の機能が含まれています。たとえば、3 の値には、値 1 と 2 のすべての機能が含まれています。

3 以下の innodb_force_recovery 値を使用してテーブルをダンプできる場合は、破損した個々のページ上の一部のデータしか失われないため、比較的安全です。4 以上の値は、データファイルが永続的に破損する場合があるため、危険であるとみなされます。6 の値は、データベースページが廃止された状態のままになり、それによって B ツリーやその他のデータベース構造にさらに多くの破損が導入される可能性があるため、きわめて危険であるとみなされます。

安全策として、innodb_force_recovery が 0 より大きい場合、InnoDB は INSERT、UPDATE、または DELETE 操作を回避します。MySQL 5.6.15 の時点では、4 以上の innodb_force_recovery 設定は InnoDB を読み取り専用モードにします。

4. mysqld を起動
sudo service bitnami-redmine start mysql

ここで、もし起動に失敗する場合は、3 に戻り、innodb_force_recovery のレベルを上げて再度起動を試みます。

5. データベースをダンプする
/path/to/redmine/mysql/bin/mysqldump -uroot -p --quote-names --flush-logs --all-databases > /tmp/dump.sql
6. データベースファイルを削除する
sudo service bitnami-redmine stop mysql
sudo rm -rf /path/to/redmine/mysql/data/*

また /path/to/redmine/my.cnf でさきほど設定した innodb_force_recovery を削除します。

7. データベースを初期化
/path/to/redmine/mysql/scripts/myscript.sh /path/to/redmine/mysql
8. mysqld を起動
sudo service bitnami-redmine start mysql
9. データベースをリストア
/path/to/redmine/mysql/mysql -uroot < /tmp/dump.sql
sudo service bitnami-redmine restart mysql
10. Bitnami Redmine を起動
sudo service bitnami-redmine start
11. mysqld のログを確認

/path/to/redmine/mysql/data/mysqld.log を確認しエラーが発生していなければ成功です。

Jenkins 2 にしたら Parameterized Trigger Plugin が動かなくなった

Jenkins 1.62 から Jenkins 2.23 にアップデートしてみました。 既存のジョブで動作確認したところ、 Parameterized Trigger Plugin というプラグインで、上流プロジェクトから下流プロジェクトに パラメータを渡せなくなっていました。日本語の記事がなかなか見つからなかったので 原因や回避策についてまとめました。

原因

原因は Jenkins のセキュリティポリシーが変更されたためでした。 Jenkins の公式ブログによると、セキュリティ上の理由から、 あるプロジェクトで未定義のパラメータを、上流プロジェクトなど外部から渡すことが できなくなったようです。 これってかなりインパクトがある変更だと思うのですが さらっとやってしまうのですね・・・。

このセキュリティポリシーの変更は以下のバージョンから影響を受けます。

  • Jenkins 1.651.2 以降
  • Jenkins 2.3 以降

影響があるプラグイン

影響を受けるプラグインは Parameterized Trigger Plugin だけではありません。 公式 wiki にまとめられているので、 Parameterized Trigger Plugin 以外にも使っているプラグインがないか確認しておきましょう。 ざっと見た感じでは GitHub pull request builder plugin なども利用者が多いようです。

ちなみに Parameterized Trigger Plugin の場合、パラメータが下流のプロジェクトに 渡らないので、下流プロジェクトでパラメータを参照しても空文字になっています。 空文字の場合ジョブ自体がエラーになるようなジョブ設計の場合はまだ良いのですが、 「空文字なら特定の値を代入する」などの処理があると、エラーにもならずジョブは成功するのに 全然違うものをビルドしていたりするので注意が必要です。

回避策

セキュリティ上のリスクを許容した上で、 今までのプロジェクトの設定を変えずに手っ取り早く回避するには、 システムプロパティでこのセキュリティポリシーを無効にする方法があります。 Jenkins 起動時の JAVA オプションで -Dhudson.model.ParametersAction.keepUndefinedParameters=true を渡してやればよいです。

以下は CentOS での具体例です。  

  1. /etc/sysconfig/jenkins で、JENKINS_JAVA_OPTIONS にシステムプロパティを追記
    JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Dhudson.model.ParametersAction.keepUndefinedParameters=true"
  2. Jenkins を再起動
    sudo service jenkins restart