s_tajima:TechBlog

渋谷で働くインフラエンジニアのTechブログです。

CentOS7の検証: Dockerを一般ユーザーで管理できるようにする。

※ 2016/08/18追記

0.9.0 (2014-03-10) にて -G オプションが追加されたので本記事の対応は不要になりました。

docker/CHANGELOG.md at master · docker/docker · GitHub

Add a -G option to specify the group which unix sockets belong to.

追記終わり。


Dockerのsocketファイルは/var/run/docker.sockに配置されている。

[root@c7-client01 system]# ll /var/run/docker.sock
srw-rw---- 1 root contentsuser 0 Jan 10 18:06 /var/run/docker.sock

このsocketのOwner, Permissionを変更することで、
一般ユーザーでDockerを管理できるようにしたいと思ったのが今回の話。
環境は以下の通り。

CentOS Linux release 7.0.1406 (Core)
docker-1.2.0-1.8.el7.centos.x86_64
systemd-208-11.el7_0.5.x86_64

/lib/systemd/system/docker.socket を見ると

SocketUser=root
SocketGroup=docker

という記述がありここを編集すればsocketファイルのOwnerを変更できそうである。
実際に編集してDockerを再起動してみたが、socketファイルのOwnerは変更されない。

調べてみるとそれらしき情報を見つけた。
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=752555

# These are only available in systemd 214+
#SocketUser=root
#SocketGroup=docker

ということらしい。
上の情報の通り、

ExecStartPost=/bin/chown root:<another group> /var/run/docker.sock

の記述を/lib/systemd/system/docker.serviceに追加してみたがうまくいかない。

docker.socketでsocketが作られた後、
docker.serviceの
ExecStart=/usr/bin/docker -d $OPTIONS $DOCKER_STORAGE_OPTIONS
でdockerが起動するときにデフォルトの設定に上書きされてしまうようである。

最終的に
/lib/systemd/system/docker.serviceExecStartPost=/bin/chown~
の記述を追記することで回避。

CentOS7の検証: httpd2.4を起動しようとすると "Invalid command 'User', perhaps misspelled or defined by a module not included in the server configuration"

CentOS7環境でhttpd2.4をインストールし、起動しようとしたところ以下のエラーが。

Invalid command 'User', perhaps misspelled or defined by a module not included in the server configuration

詳しい環境は以下の通り。

CentOS Linux release 7.0.1406 (Core)
httpd-2.4.6-18.el7.centos.x86_64

原因は不要そうなmoduleの読み込みをしないようにしていたことだった。 以下のmoduleの読み込みが必要。

LoadModule unixd_module modules/mod_unixd.so

ドキュメントにもよくあるエラーとして書いてあった。
http://httpd.apache.org/docs/2.4/upgrading.html

Invalid command 'User', perhaps misspelled or defined by a module not included in the server configuration - load module mod_unixd

dockerの検証: docker registryが起動しない

docker registry(https://github.com/docker/docker-registry)の検証のため、
Quick startに書かれている通り docker runをしてみた。

# docker run -e SETTINGS_FLAVOR=s3 \
>         -e AWS_REGION=ap-northeast-1 \
>         -e AWS_BUCKET=<MY_BUCKET_NAME> \
>         -e STORAGE_PATH=/registry \
>         -e AWS_KEY=XXX \
>         -e AWS_SECRET=XXX \
>         -e LOGLEVEL=debug \
>         -p 5000:5000 \
>         registry
2014-11-27 05:51:49,409 WARNING: Cache storage disabled!
2014-11-27 05:51:49,410 WARNING: LRU cache disabled!
2014-11-27 05:51:49,760 DEBUG: Will return docker-registry.drivers.s3.Storage
2014-11-27 05:51:49,774 DEBUG: Using access key provided by client.
2014-11-27 05:51:49,774 DEBUG: Using secret key provided by client.
2014-11-27 05:51:49,776 DEBUG: path=/
2014-11-27 05:51:49,776 DEBUG: auth_path=/<MY_BUCKET_NAME>/
2014-11-27 05:51:49,777 DEBUG: Method: HEAD
2014-11-27 05:51:49,777 DEBUG: Path: /
2014-11-27 05:51:49,777 DEBUG: Data:
2014-11-27 05:51:49,778 DEBUG: Headers: {}
2014-11-27 05:51:49,779 DEBUG: Host: <MY_BUCKET_NAME>.s3-ap-northeast-1.amazonaws.com
2014-11-27 05:51:49,779 DEBUG: Port: 443
2014-11-27 05:51:49,779 DEBUG: Params: {}
2014-11-27 05:51:49,780 DEBUG: establishing HTTPS connection: host=<MY_BUCKET_NAME>.s3-ap-northeast-1.amazonaws.com, kwargs={'port': 443, 'timeout': 70}
2014-11-27 05:51:49,781 DEBUG: Token: None
2014-11-27 05:51:49,781 DEBUG: StringToSign:
HEAD

Thu, 27 Nov 2014 05:51:49 GMT
/<MY_BUCKERT_NAME>/
2014-11-27 05:51:49,782 DEBUG: Signature:
AWS SIGNATURE

この状態で、ホストマシンからcurlをしてみるもEmpty reply.

# curl http://localhost:5000/v1/_ping
curl: (52) Empty reply from server

docker-registryを動かしているgunicornがLISTENしているところまでいっていない模様。
この時利用しているdocker image IDは "e42d15ec8417"
docker-registryのversionは"0.8.0"

調べてみるとこんなIssueがあった。

S3 Region · Issue #400 · docker/docker-registry · GitHub

Following is the problem I noticed with 0.7.0 When I specify s3_region as us-west-2 in my config, registry is up but I cannot pull or push.

If I comment out s3_region then everything is fine. I have confirmed on S3 that the region of my bucket is us-west-2

s3_regionを指定しているとうまく動かないらしい。
このIssueを読み進めていくと、状況としては似たようなことになっている。

色々と議論がされているが、結論としては

This looks like a gevent bug dealing with unicode.

Fixes issue with s3/boto/gevent hanging. by chuegle · Pull Request #670 · docker/docker-registry · GitHub
このコミットで解消している模様。
取り急ぎはここに書いてあるsed

# sed -i 's/import gevent.monkey/u"test".encode("idna")\nimport gevent.monkey/' /usr/local/lib/python2.7/dist-packages/docker_registry/drivers/s3.py

の通りに対応して回避。

re:Invent 2014 参加レポート

ラスベガスで行われたre:invent 2014に参加してきました。

参加したSessionやイベントのまとめです。(Sessionはスライドと動画が順次公開されると思うので簡単に。)
KeyNoteについてはすでに日本語でも英語でも情報が多く出回っているので割愛。

GameDay (11/11)

GameDay(https://reinvent.awsevents.com/gameday.html)とは、
AWS上で以下の3つのフェーズに分かれた作業を行い、
その中で後述する観点で優れた対応(優れた攻撃, 一番早い復旧, おもしろいエピソード)
をとったチームが表彰される競技です。

  1. 指定された手順にある通りにシステムを構築

    • テーマは画像変換のQueueシステム。
    • EC2(VPC), S3, SQS, SNSあたりのコンポーネントを組み合わせ、オートスケールするQueueシステムを構築します。
  2. 他のチームが構築したシステムを攻撃

    • 会場内のどこかのチームが発行したIAMユーザー(PowerUserの権限)を渡されて、これを使って攻撃をします。
  3. 他のチームに攻撃された自分たちのシステムを修復

    • 最初に構築したシステムを復旧し、運営から発行されたリクエストを正しく処理できる状態にします。

去年のre:Inventや、日本でも実施されているので競技自体を知っている方は多いとおもいます。
参加前に色々と調べていた感じだと、テーマ(構築するシステム)は今まで開催されていたものと同じだったのかなと思います。

チーム分けは会場(300人弱くらいかな...?)で適当に周りの人と組んでくれと言われます。
日本人も数名いたようですが、せっかくなので日本人以外の人と組みました。
僕達のチームがやったのは以下のような対応でした。

  • Breaking
    • Disable CloudTrail.
    • Use remote code execution to...
      • Modify their processing script
      • Add more sleep statements
      • Make it pull nyancat every time
      • Overlay text saying “You got pwn3d”
    • Shuffle Instance name. (Switch Master and NAT Instance)
    • Change the instance startup script to pull our version in before starting
    • Screw with their security groups
    • Rotate their Master access & secret keys
    • Blow away their AMI image
    • Fiddle with the iAM policies
  • Hardening
    • Enable CloudTrail and keep enabling them.
    • Use CloudFormation & CloudFormer
    • Remove 2 sleep statements from processing script, and re-snapshot
    • Copy AMI to another region
    • Copy AMI to another account
    • Use AWS instance termination protection
    • Fixed security issues in the application

チームを組んだ @GeneticGenesis (zen)はできたできたとよろこんでました。
https://twitter.com/GeneticGenesis/status/532328652369698817

一番はやい復旧をしていたのはAnsibleとCloudFormationを使って復旧していたチーム,
おもしろいエピソードは(おそらく対戦相手の?)AWSのクレデンシャルをGitHubにアップロードしたチームでした。
(結果発表の頃には完全に集中力が切れていて最も優れた攻撃がなんだったのかは聞き逃しました...)

入賞はできなかったですが日本語の通じない環境でエンジニアリングをするというとてもいい経験になりました。
僕のような拙い英語力でも、出てくる単語がAWSやシステムに関するものなのでなんとかなったのかなという感想です。

SEC201 - AWS Security Keynote Address (11/12)

(Keynoteの後展示ブースを回っていたら開始時間過ぎてたので途中から参加)

  • keynoteで発表されたAWS Config, AWS Key Management Service(KMS)の話
    • 実際の設定の仕方をManagement Consoleの画面を含めての解説など。
    • 別にセッションがあるので、技術的に深い仕様の説明はなかった。
  • NASDAQがオンプレからAWSに移行した話。
    • オンプレミス環境のキャパシティの問題で、短期間で移行をしなければいけない状況。
    • AWSが鍵まわりの取り扱いの問題をうまく解決できたので成功したよという話。
  • Amazonのセキュリティ周りのカルチャーについて
    • 問題の本質を捉えましょうね。Howではなく、Whyを繰り返しましょう。
    • しっかりとテストしようね。
    • 権限移譲とスピード感のバランス。

SDD408 - Amazon Route 53 Deep Dive: Delivering Resiliency, Minimizing Latency

  • Route53によるサイトフェイルオーバや Geo Routing等の話を、実際のRoute53の設定を示しての説明
    • 平常時は2つのエンドポイントを用意し、片方が落ちている時はもう片方のレコードを返すパターン
    • Geo Routingを階層的にしたパターン
    • DNSのキャッシュ対策として、Wildcardを用いる方法
    • CloudWatchを用いた動的なWeightの変更の方法

SEC302 - Delegating Access to Your AWS Environment

  • DelegationとFederationの違い
    • Delegationは他のAWSアカウントのユーザ(もしくはリソース)に対して、あなたのリソースへの権限を与えるもの
    • Federationはその他の認証機構のユーザに対して、あなたのリソースへの権限を与えるもの
  • AWSアカウントに対する権限付与について、Delegationの方法をユースケース毎に説明
    • 同一アカウント内での権限付与
    • クロスアカウントでの権限付与
    • AWSリソースに対する権限付与
  • ドキュメントに書いてある内容の範囲内だったので、個人的には目新しい話はあまりなかった印象
  • とはいえ現状このあたりを適切に運用できていないのも確かなのでうまいやり方を見つけたい。
  • (SEC304) Bring Your Own Identities – Federating Access to Your AWS Environment のほうが聞きたかった内容を話してくれていた模様。

SDD403 - Amazon RDS for MySQL Deep Dive

APP309 - Running and Monitoring Docker Containers at Scale

  • Dockerのインスタンスユースケースについて
  • Dockerのモニタリング項目について
    • Memory: page fault, RSS, Swap
    • CPU: user, system
    • Block I/O: bikio.io_service_bytes, bikio.io_queued
    • Network: tx/rx_errors, tx/rx_dropped, tx/rx_bytes
  • メトリクスの集取はcAdvisor(https://github.com/google/cadvisor)を使います。
  • tag-baseの監視をしましょう。
  • Application, コンテナ, ホスト等、レイヤーを分けたメトリクスを取りましょう。

WEB401 - Optimizing Your Web Server on AWS

  • AWSでのHTTPサーバの最適化の話
  • よいパフォーマンスとはスループットが高い, レイテンシが少ない, 安価?であること。
  • 計測, ログングをしましょうという話。
  • ログのローテート. 圧縮, Ship(ログ転送のこと?初めて知った。)をしましょう。
  • net.* あたりの各種カーネルパラメータの説明
  • オフロードや、Route53 latency-basedルーティングも使いましょう。

ADV402 - Beating the Speed of Light with Your Infrastructure in AWS

  • 60 Billion requests/dayのリクエストをいかに捌くかという話。
  • 1%のdowntimeが$1Millionの損失に。
  • DynamoDB選択の理由を他のミドルウェアとの比較を出して説明
    • 候補はCassandra, Redis, memcache, Hbase
  • 各リージョンのDynamoのデータ同期の方法をどう実現しているかの話。

WEB306 - UI, Load, and Performance Testing Your Websites on AWS

  • UIテストの話
    • なぜテストをするのか? なぜ自動化するのか?
    • テストの範囲は?
      • Unitテスト, サービスレベル, UIテストの担当範囲
    • ImageMagickを使って、Beta環境とProduaction環境の比較をするUIテストの話
    • Seleniumを使ったログイン画面のUIテストの例
    • Selenium Gridを使ったクロスブラウザUIテストの話
  • LOAD
    • AWSのいいところは、本番環境のコピーが簡単に構築できる
    • それぞれのレイヤーがスケーラブルであるかを確認する
    • ELB, ClouFront, AutoScalingそれぞれに対するテスト
    • ELBに対してテストをする場合の注意点
      • ELBのIPではなくHostnameに対して行う
      • アプリケーションがIPのキャッシュを持たないことを確認する
      • Stickey Sessionが有効だとトラフィックが偏ることがある
    • 注意点
    • ツール: Apache Bench, curl-loader, Siege, Bees with Machene Guns
    • アプリケーションのモニタリング

DEV301-R - Advanced Usage of the AWS CLI (Repeat Session)

  • aws configureのsubcommandを使いましょう。
  • profileで設定を分けられるよ
  • 設定ファイルの説明
    • .aws/credentials
      • すべてのAWS SDKがサポート
      • クレデンシャル情報のみ
    • .aws/config
      • CLIのみサポート
      • クレデンシャル以外の情報(regionの設定とか)を含められる
  • --queryオプションを使いましょう
  • EC2のステート遷移について
    • 起動後, runningになるまでsleepをloopさせるようなプログラムは適切につくるのが大変。
    • aws ec2 waitなら簡単にできる。
  • --cli-input-json, --generate-cli-skeltonによるjsonでの設定
  • credentialの優先順位
    • 環境変数 -> credentials -> config -> AssumeRole -> IAM Role
  • S3 streaming

Pub Crawl, re:Play Party

カンファレンス開催中、毎晩のようにPartyが開催されていました。
どの会も大音量の音楽がかかった空間でご飯とお酒が振る舞われていました。

JAPAN Night

日本からツアーできている人たちにまじって(僕はツアー参加ではなかったので)
JAPAN Nightに参加しました。
日本でAWSのサポート部署にいる方とお話にいろいろな話を聞けたのがよかったです。
あと肉がおいしかった。

以上、簡単ですがre:Invent2014の参加レポートでした。

CentOS7の検証: nscdの起動がうまくいかない件

nscd-2.17-55.el7.x86_64での話。

nscdのパッケージをインストールし、起動しようとしても
そのままコマンドが止まってしまう。

# systemctl start nscd

/var/log/messagesを見てみると、

Aug 6 17:44:26 c7-build01 systemd: PID file /run/nscd/nscd.pid not readable (yet?) after start.

と言われている。
確かに/run/nscdというディレクトリは存在しない。

# rpm -ql nscd
# rpm -q --scripts nscd

を見ても作成されている様子がない。

/usr/lib/systemd/system/nscd.service
のを以下のように修正。

- PIDFile=/run/nscd/nscd.pid
+ PIDFile=/var/run/nscd/nscd.pid

こんな初歩的な不整合のままリリースされていていいのか
と思ったけどこんなレガシーパッケージ使ってないでsssd使えってことか。

CentOS7の検証: CA証明書の管理方針が変更に

概要

CentOS7の検証をしていると、ca-bundle.crtがシンボリックリンクになっていることに気がついた。

$ ll /etc/pki/tls/certs/ca-bundle.crt
lrwxrwxrwx 1 root root 49  7月 16 17:04 /etc/pki/tls/certs/ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem

/etc/pki/ca-trust/という見覚えのないディレクトリがある。
/etc/pki/ca-trust/READMEを見ると

This directory /etc/pki/ca-trust is used by a system of consolidated CA certificates.
Please refer to the update-ca-trust(8) manual page for additional information.

とのこと。
どうやらCentOS7から、CA証明書の管理方針が変わっているらしいので調べてみた。

update-ca-trustとは

$ man update-ca-trust
を確認してみた。詳しいことはここに全て書かれているので大事そうなところだけ抜粋。

update-ca-trust(8) is used to manage a consolidated and dynamic configuration feature of Certificate Authority (CA) certificates and associated trust.

CAの証明書を動的に管理する仕組みらしい。

In order to enable legacy applications, that read the classic files or access the classic module, to make use of the new consolidated and dynamic
configuration feature, the classic filenames have been changed to symbolic links. The symbolic links refer to dynamically created and consolidated
output stored below the /etc/pki/ca-trust/extracted directory hierarchy.

ca-bundle.crtに貼られていたシンボリックリンクは、古いアプリケーションとの互換のためらしい。

Files in subdirectories below the directory hierarchy /usr/share/pki/ca-trust-source/ contain CA certificates and trust settings in the PEM file
format. The trust settings found here will be interpreted with a low priority.

Files in subdirectories below the directory hierarchy /etc/pki/ca-trust/source/ contain CA certificates and trust settings in the PEM file format.
The trust settings found here will be interpreted with a high priority.

独自にCAの証明書を追加したい場合は、/usr/share/pki/ca-trust-source/もしくは/etc/pki/ca-trust/source/にPEM形式の証明書を置く必要があるらしい。
また、両ディレクトリの違いはその優先順位とのこと。

ざっと見た感じCA証明書のリストを常に最新の物に保てるよ。
という仕組みではなく、(すくなくとも現状では)任意のCA証明書を手で入れるときのやり方が変わったよという話しらしい。

実際に使ってみた

(まだ一般ユーザの設定をしていないのでrootユーザでの検証)

  • 現在のCA証明書を退避。
# cp /etc/pki/tls/certs/ca-bundle.crt /var/tmp/ca-bundle.crt
  • 証明書の作成
# vim /etc/pki/ca-trust/source/anchors/test-additional.crt
# cat /etc/pki/ca-trust/source/anchors/test-additional.crt
-----BEGIN CERTIFICATE-----
MIIDPTCCAqagAwIBAgIJAISdA7ceQY8cMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV
.. snip ..
n+1tqoJSHZpCSBEkjha0ncE=
-----END CERTIFICATE-----
  • update-ca-trustの実行
# update-ca-trust extract
  • 証明書が追加されていることを確認
# diff /etc/pki/tls/certs/ca-bundle.crt /var/tmp/ca-bundle.crt
2,21d1
< MIIDPTCCAqagAwIBAgIJAISdA7ceQY8cMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV
 .. snip ..
< n+1tqoJSHZpCSBEkjha0ncE=
< -----END CERTIFICATE-----
< -----BEGIN CERTIFICATE-----

所感

  • 先日騒がれていたような、ルートCA証明書の期限切れ問題に対する解決策なのかと思ったけどそうではない模様。
  • いままであまり良くない気がしていたca-bundle.crtの直接編集をしなくてよくなるのはよさそう。
    • ca-certificates-20XX.X.X-XX.el7.noarchのUpdateがしやすくなるので。

Puppet3.6環境でPackageを定義するとWarningが

Puppet3.6環境で、

package {
  "openssl":
    ensure  => installed,
}

のように、packageの定義を記載すると、puppet適用時に

Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false.
(at /usr/share/ruby/vendor_ruby/puppet/type.rb:816:in `set_default')

という警告が表示される。

allow_virtualというオプションの説明をみると
http://docs.puppetlabs.com/references/3.6.latest/type.html#package-attribute-allow_virtual
> Specifies if virtual package names are allowed for install and uninstall.
とのこと。

virtual packageについての説明はこちら。
http://www.rpm.org/max-rpm/s1-rpm-depend-manual-dependencies.html

RPMのprovidesに記載された名前でパッケージ名をインストールすることができるようになる仕組みの事らしい。

例えば

$ rpm -qp --provides  varnish-3.0.3-1.el6.x86_64.rpm
config(varnish) = 3.0.3-1.el6
libvarnish.so()(64bit)
libvarnishcompat.so()(64bit)
libvcl.so()(64bit)
libvgz.so()(64bit)
libvmod_std.so()(64bit)
varnish = 3.0.3-1.el6
varnish(x86-64) = 3.0.3-1.el6

となっているvarnishのパッケージを

$ sudo yum install "config(varnish)"

でインストールできる仕組み。
この挙動自体は知っていたがvirtual packageという名前なのは初めて知った。

allow_virtual parameter will be changing its default value from false to true in a future release.

とのことなので、将来的にallow_virtualのデフォルト値がfalseからtrueになるよとの警告。

もっときれいな対応があるのかもしれないが、
以下の記述を設定に追加して、allow_virtualを明示的に指定することで出力を抑止。

# avoid allow_virtual warnings.
Package { allow_virtual => true }