【参考訳】Vault 0.6

09.07.2016  in Vault using tags HashiCorp , Vault , translation

概要

6月14日に、HashiCorp の blog にVault 0.6 のリリースに関する解説記事がありました。こちらも例によって訳しましたので、参考程度にどうぞ。

※ 今回は Vault 独特の用語が多く、翻訳内容には通常よりも多くの意訳箇所があります。そのため、普段より “日本語(英語)” のように、原文併記している箇所が多く読みづらい所がありますが、ご容赦願います。 この意図は、HasihCorp の Vault について、話題に上げたり議論できる人を増やしたいなぁという思いからです。そのため、内容について気になる箇所がありましたら、随時ご指摘いただけますと幸いです。

Vault 0.6

私たちは Vault 0.6 のリリースを誇りに思います。Vault はシークレット(secret)管理用のツールです。API 鍵や暗号化された細心の注意を払うべきデータを、完全な内部認証局(CA)を持つ Vault に置けます。つまり、シークレット管理に必要な全ての解決策(solution)を Vault が提供します。

今回のリリースでは、重要な新機能をいくつか追加しました。ほかにも、新しいセキュア・ワークフローの拡張や、多くの改良、バグ修正を行いました。特に集中したのはトークン管理(token management)とトークン/認証ワークフローです。

詳細:

概要

  • Codebase Audit(コードベースの監査)
  • Integrated Consul Health Checks(Consulヘルスチェック統合)
  • Lisner Certificate Reloading(リスナー証明書の再読み込み)
  • MSSQL Credential Generation(MSSQL 証明書生成)
  • Azure Data Store(Azureデータ・ストア)
  • Swift Data Store(Swiftデータ・ストア)

(いくつかの機能は 0.5.1 と 0.5.2 で搭載したものですが、これまでブログに解説を投稿していませんでした。)

変更に関する全ての詳細は Vault 0.6 CHANGELOG をご覧ください。さらに、この投稿の最後に書いた更新に関する情報は必ずお読みください。

いつもの通り、アイディア、バグ報告、プルリクエストをいただいた私たちのコミュニティに対して、大変感謝を申しあげます。

Vault 0.6 の主な新機能について学ぶには、このまま読み進めてください。

Token Accessors

トークンの作成時、2つの値を返します。トークン自身と認証機構(accessor;アクセッサ)です。

$ vault token-create -policy=default
Key             Value
---             -----
token           82c5fb97-da1b-1d2c-cfd5-23fa1dca7c85
token_accessor  dd256e17-b9d9-172d-981b-a70422e12cb8
token_duration  2592000
token_renewable true
token_policies  [default]

トークンに対する知識がなくても、トークンの表示(lookup)や無効化(revocation)の処理を認証機構で行えます。使うには auth/token/lookup-accessor /auth/token/revoke-accessor を通すか、各 CLI コマンドで -accessor フラグを指定します。認証機構で表示機能を使っても、トークン ID を返しません。

認証機構を持つクライアントを識別するための情報を保管するため、他のクライアントが作成したサービス用トークンに関する情報の表示や、必要があれば後でトークンを無効化できます。たとえば、トークンを作成した従業員が会社を辞めたとします。認証機構を使えば、保管されているトークン ID がなくてもトークンを無効化できます。

これを簡単に行えるだけでなく、トークン・ストアを直接使わずに作成したトークンのワークフローにも便利です。また、認証機構(accessor)値の HMAC (ハッシュ・ベースのメッセージ認証符号)化をオプション設定を無効にもできます。(デフォルトの HMAC 化は、認証機構の値にアクセス可能な誰もが、トークンでの認証を無効化するサービス拒否攻撃を行えてしまいます。そして、たいていのログは厳密に管理されていません。) 監査バックエンド(audit backend)を有効にしている場合は、設定オプションで hmac_accessor=false を指定すると、この挙動が有効になります。

Token Authentication Backend Roles

トークン認証バックエンド(Token Authentication Backend) はロール(役割)の概念を取り入れました。ロールが提供するのは管理度(degree of administrative)の柔軟さであり、許可されたユーザがトークンの作成時、ユニークな属性(properties)や他の behalf を含められます。

トークン・アクセス機構と一緒にこれらのロールを有効にすると、直接トークンを作成するよりも優れたワークフローになります。管理者は上限(limit)や機能(capabilities)を指定するためにロールを設定できます。そして、信頼するユーザやサービスに対してはトークンを作成できるロールを割り当て可能です。サービスごとにトークンを指定できるので、認証機構の値(accessor)は監査ログ(audit logs)に文字列(plaintext)で書き込めます。たとえば、無効化(revocation)が必要であれば、認証機構を通して特定のトークンの無効化や、特定のロールが発行したトークンを全て無効化できます。

もう1つ書き加えておきます。 auth/token/create でトークンを直接作成する時、再利用性(renewability)と最大 TTL の明示も制御できます。

Response Wrapping

トークン認証バックエンド・ロールとトークン認証機構は、きめ細かな権限の管理を可能にします。しかし、生成したトークンを安全に配布する問題は解決していません。安全な導入が難しい課題です。その理由の1つは、高度に安全な通信経路の確保が大変だからです。

Vault 0.6 でレスポンス・ラッピング(response wrapping)を導入しました。これはセキュリティ・プリミティブ(訳者注:セキュリティ上の構造、の意味)です。Vault が生成したトークンを配布するだけでなく、簡単かつ安全に行えるようにします。

詳細な仕組みを説明する前に、読者の皆さんには Cubbyhole 認証パラダイム に関する投稿をあらかじめお読みになったほうが良いかもしれません。以降の段落に関する概要を説明していますが、全くのオプションです。ですが、レスポンス・ラッピングはパラダイムの一部を完全に実装したものであり、より優れたセキュリティを提供します。そのためには、スタンドアロンのプロセスが tempperm トークンを管理します。この実装の詳細については先の投稿の通りであり、 /sys のパスを除き、レスポンス・ラッピングは Vault に到達するあらゆる応答に使えます。

レスポンス・ラッピングは以下の通りに動作します。ここで想定するシナリオは、クライアントが Vault からシークレットを取得するにあたり、利用可能なシークレットしか表示できないように制限します。

  1. クライアントのリクエストに、応答をラッピングするためのラッピング・トークン(wrapping token)の適用期間を指定します。CLI 上で使うには、グローバル・クライアント・フラグの -wrap-ttl を指定します。

  2. Vault はリクエストを通常通り処理します。ですが、通常通りに応答するのではなく、JSON シリアル化(JSON-serialize)した応答をします。この応答には、新しいトークンの cubbyhole を含みます。新しいトークンを使うのは、クライアントで指定した TTL の間のみであり、延長できません。

  3. Vault は新しいレスポンスを生成して応答します。ここでラッピングする情報には、ラッピング・トークン ID とラッピング・トークンの有効期間です。

  4. クライアントは対象のターゲットに対し、ラッピング・トークンを渡します。

  5. 対象のターゲットは、トークンを使い unwrap (ラッピングされていない)処理をします。水面下で行っているのは、をトークンの cubbyhole が既知の場所から、オリジナルの応答単に受け取るだけです。そして JSON でパースし、通常通り応答します。API や CLI を透過するだけであり、Vault から直接応答を得るのと、ラッピング・トークンから読み込みパースするのと、両者に差違はありません。

  6. 対象のターゲットが権限がないと拒否された場合、トークンの TTL と作成時間を比較し、有効期間を超えていないか確認します(対象のターゲットから取得するには、おそらく時間がかかるでしょう)。もしも有効期限が切れていなければ、ターゲットはセキュリティ警告をあげます。警告の内容は、応答がラッピングされていない可能性と、シークレットが意図しない第三者に漏洩している可能性です。

この流れを説明するため、以下では CLI コマンド token-create を2回実行します。1つは正常ですが、もう片方はラッピングされていない処理です。

#
# 通常の token-create コマンド
#

$ vault token-create -policy=default
Key             Value
---             -----
token           ff999148-077e-2629-8d9a-cb0a7b97e811
token_accessor  8c243823-5820-ff8f-f641-6999290c60c0
token_duration  2592000
token_renewable true
token_policies  [default]

#
# レスポンス・ラッピングに対応した token-create コマンド
#

$ vault token-create -policy=default -wrap-ttl=60s
Key                             Value
---                             -----
wrapping_token:                 7a39125a-2001-be9b-e363-3ba85a16c311
wrapping_token_ttl:             60
wrapping_token_creation_time:   2016-06-14 06:02:11.171558903 +0000 UTC
wrapped_accessor:               ed96a7ae-dfdb-3c09-0a60-a02b53dfe6b2

#
# ラッピングしていない応答
#

$ vault unwrap 7a39125a-2001-be9b-e363-3ba85a16c311
Key             Value
---             -----
token           d878b2ed-564e-0790-4154-67bcf7386268
token_accessor  ed96a7ae-dfdb-3c09-0a60-a02b53dfe6b2
token_duration  2592000
token_renewable true
token_policies  [default]

#
# 無効なトークン(使用済み)の検出
#

$ vault unwrap 7a39125a-2001-be9b-e363-3ba85a16c311
error reading cubbyhole/response: Error making API request.

URL: GET https://127.0.0.1:8200/v1/cubbyhole/response
Code: 400. Errors:

* permission denied

この例でご覧の通り、ラッピングした応答にトークンを含む場合、トークン認証機構はラッピング情報を提供します。これにより、特権を持つ実行者(privileged caller;訳者注、管理者の意味)が生成したトークンにより、そのクライアントが対象とした認証機構の追跡を簡単にします。これは万が一の時にトークンを無効化するためです。

レスポンス・ラッピングは Vault リクエストのほとんどで利用可能です。そのため、あらゆるシークレットに対し、転送時のセキュリティ拡張をもたらします。

#
# K/V (generic) バックエンド
#

$ vault write secret/foo bar=baz
Success! Data written to: secret/foo

$ vault read -wrap-ttl=60s secret/foo
Key                             Value
---                             -----
wrapping_token:                 3a63ff9f-1c38-af43-0a85-dc1155f2469d
wrapping_token_ttl:             60
wrapping_token_creation_time:   2016-06-10 13:46:14.155857566 -0400 EDT

$ vault unwrap 3a63ff9f-1c38-af43-0a85-dc1155f2469d
Key                     Value
---                     -----
refresh_interval        2592000
bar                     baz

#
# Transit バックエンド
#

$ echo "bar" | base64 | vault write transit/encrypt/foo plaintext=-
Key             Value
---             -----
ciphertext      vault:v1:j4Z1/6WLK+snlhIyooxa1zW0yEmBqFSfZTL88bN/Qt4=


$ vault write -wrap-ttl=60s transit/decrypt/foo ciphertext="vault:v1:j4Z1/6WLK+snlhIyooxa1zW0yEmBqFSfZTL88bN/Qt4="
Key                             Value
---                             -----
wrapping_token:                 e93a78ec-cced-dc94-d1f8-d71e84faddde
wrapping_token_ttl:             60
wrapping_token_creation_time:   2016-06-07 15:59:18.251657838 -0400 EDT

$ vault unwrap -field=plaintext e93a78ec-cced-dc94-d1f8-d71e84faddde | base64 -d
bar

AWS EC2 Authentication Backend

AWS EC2 認証バックエンド は、 EC2 インスタンスの自動的な Vault 認証と Vault トークンの取得を可能にします。対応クライアントでの AMI 操作は、ユーザ側の調整や設定変更を行わずに認証できます。

バックエンドは AWS を信頼できるサード・パーティとして扱います。特に AWS のインスタンスが提供するのは、秘密鍵で署名されたメタデータと、確認可能な公開済みの公開鍵です。ハイレベルでは、バックエンドは与えられたメタデータの整合性を確認します。具体的には、インスタンス ID が過去に使われていないか(TOFU あるいは Trust On First Use =間違いなく初めて使う、の原則として知られています。)と、そのインスタンスが実行中の状態かです。また、バックエンドはクライアントが指定した一時的な値も受け付けます。たとえば、初期のトークンの有効期限が切れたら、新しいトークンの取得に使います。そして、他のクライアントがメタデータを再利用しようと試みても、それを拒否します。

ローレベルでは、セキュリティ・ポリシーと組織における広範囲のワークフローに一致するよう、様々な制限(modification)をサポートしています。詳細についてはドキュメントをご覧ください。

インスタンスを認証するには、インスタンス内で動作するクライアントが Vault と通信し、Vault の API を通して必要な情報を渡す必要があります。Vault Enterprise をご利用のお客さまには、デプロイのワークフローを簡単にするため、HashiCorp が構築したスタンドアロンのバイナリを提供しています。クライアントは与えられたトークンを更新し続けます。トークンの有効期限が切れれば、再認証して新しいトークンを取得します。

Vault Enterprise クライアント・バイナリは単純にバックエンド API を使うだけです。しかし、Vault 内部の挙動はオープンソースで公開されているものとは異なります。Vault Enterprise をお使いではない組織でも、必要があれば自分でクライアントを構築できます。あるいは HashiCorp に Vault Enterprise に関する情報をお訊ねください

他の機能

今回のリリースでは、多くの新機能追加と改良を施しました。その中でも、いくつかの重要な項目を紹介します:

  • Codebase Audit(コードベースの監査) … Vault 0.5 のソースコード群は iSEC パートナによって監査済みです(私たちには監査内容の一般公開が許されていません)。
  • Integrated Consul Health Checks(Consulヘルスチェック統合) … Consul データ・ストア自動的に vaule サービスを登録し、Consul でヘルスチェックを実施します。デフォルトでは、アクティブなノードは active.vault.service.consul から確認できます。また、スタンバイ・ノードは standby.vaule.service.consul から確認できます。デフォルトの Consul のサービス・ディスカバリでは、封印済みの(sealed) vault を critical(クリティカル)と認識するため、一覧に表示しません。詳細は ドキュメントをご覧ください。
  • Lisner Certificate Reloading(リスナー証明書の再読み込み) … Vault の設定リスナーは、Vault が SIGHUP を送ると TLS 証明書を秘密鍵を再読み込みします。これにより、Vault 証明書の再読み込みにあたり、Vault の停止や封印解除(unseal)の作業が不要になります。
  • MSSQL Credential Generation(MSSQL 証明書生成) … Vault が既にサポートしてる Postgres や MySQL と同様、証明書を生成するバックエンドに MSSQL が使えます。
  • Azure Data Store(Azureデータ・ストア) … Vault が既にサポートしている S3 と同様、Vault の物理データ・ストアとして Azure blob オブジェクト・ストレージが使えます。
  • Swift Data Store(Swiftデータ・ストア) … Vault が既にサポートしている S3 と同様、Vault の物理データ・ストアとして Swift オブジェクト・ストレージが使えます。

更新の詳細

Vault 0.6 は大規模な変更を伴うため、更新する前に様々な理解が必要です。一般的な更新手順だけでなく、バージョン固有の手順もご覧ください。ご注意いただきたいのは、扱っているのは 0.5.x からのバージョンアップです。さらに前のバージョンから更新する場合は、それぞれのリリースに関するブログの投稿をご覧ください。

私たちが推奨するのはいつもの通り、独立した環境でテストした後、更新を試みてください。もし何らかの問題があれば、GitHub の Vault の issue トラッカーVault メーリングリスト にお訊ねください。

それでは、Vault 0.6 をお楽しみください!

原文


【参考訳】Nomad 0.4

02.07.2016  in Nomad using tags HashiCorp , Nomad , translation

概要

6月28日に、HashiCorp から Nomad 0.4 バージョン 0.4 がリリースされました。新しい nomad plan コマンドのサポート、リソース調査機能、Consul との一部機能統合が行われています。HashiCorp の blog にリリースに関する解説記事がありましたので、例によって訳してみました。参考程度にどうぞ。

Nomad 0.4

私たちは Nomad 0.4 をリリースしました。Nomad は分散型の高い可用性を持つクラスタ・マネージャとスケジューラであり、マイクロサービスとバッチ作業の両方に対応する設計です。

Nomad 0.4 に備わっている新機能が焦点を当てているのは、ツール運用面での改良です。主な機能は次の項目です。

  • Nomad Plan
  • ライブ・リソース使用量(Live Resource Utilization)
  • クラスタリングを簡単に(Simpler Clustering)

Nomad Plan

nomad plan を実行して表示されるのは、ジョブに対する変更についてと、Nomad がジョブをクラスタ上に割り当て可能かどうかです。これにより、システムに対してどのような変更を行うかと、ジョブが適切に割り当てられるかを確認できるようにします。

Terraform とは異なり、nomad plan は割り当ての成功を保証しません。nomad plan は変更するリソースを予約(reserve)しません。確認するのは、その時点で割り当てが成功するかです。この情報を元に、作業者は対象となる場所でジョブを実行するかどうか、詳細な情報を得た上で決断できます。

Nomad は宣言型システム(declarative system)です。「何」を実行するか宣言したら、Nomad は「どのように」実行するか決めます。どのサーバ上でジョブを実行するか、いつ実行するかなど、Nomad に対して詳細を伝える必要はありません。これがクラスタ・マネージャにとって重要な所です。たとえば、Nomad はリソースを効率的に使えるようにし、障害時には自動的にワークロードの移行などをします。

一方、マイナス面として、ジョブを発行後の挙動については分かりません。作業者であれば、何点か気に掛けることがあるでしょう。ジョブの実行に十分なリソースがあるだろうか? ジョブを更新するには? 既存のジョブのダウンタイムやローリング・アップデートは? などです。

nomad plan は作業を確かなものにするため、その時点において Nomad が何をするか表示します。次の plan は、ジョブを更新する例です:

$ nomad plan example.nomad
+/- Job: "example"
+/- Task Group: "cache" (3 create/destroy update)
  +/- Task: "redis" (forces create/destroy update)
    +/- Config {
        args[0]: "--port ${NOMAD_PORT_db}"
      + args[1]: "--loglevel verbose"
        command: "redis-server"
    }

Scheduler dry-run:
- All tasks successfully allocated.
- Rolling update, next evaluation will be in 10s.

Job Modify Index: 7

出力はジョブに対する変更を表示します(この例では、コマンドに新しい引数を追加します)。ここで出力されるのは、ジョブの作成/破棄、更新といった処理(タスク)で、どのように変わるかです。

あとは、下の方に「scheduler dry-run」(スケジューラ・ドライ・ラン)と表示があります。ここではジョブが割り当て可能であるのと、ローリング・アップデートは 10 秒間隔のポリシーでデプロイできそうです。

新しいジョブや既存のジョブに対し、nomad plan が使えます。クラスタの状態には変更を加えませんので、安全に実行できます。nomad plan の詳細はドキュメントをご覧ください。

ライブ・リソース使用量(Live Resource Utilization)

Nomad はタスクとノードに割り当てられた実際のリソースを報告できるようになりました。

Nomad 上のすべてのジョブは、どれだけのリソースが必要かの宣言が必須です。リソースとは、CPU、メモリ、ネットワーク等です。通常、処理の要求時点で、どれだけのリソースが必要かを知るのは大変です。これまで、実際に必要なリソース使用量を決めるのは困難でした。Nomad 0.4 からは、ジョブ、タスク、ノードのリソース使用量を簡単に調べられます。

次の例はタスクのリソース使用量を表示します。

$ nomad alloc-status abcd1234
Task: "www"
CPU     Memory MB  Disk MB  IOPS  Addresses
100/250   212/256     300      0

Nomad 0.3 までは、CPU とメモリはジョブで指定した要求値を簡単に表示するだけでした。Nomad 0.4 からは、実際に現在割り当て中の値を表示します。

ノードの状態では、より詳細な情報を表示します。

$ nomad node-status -stats abcd1234
...

Detailed CPU Stats
CPU    = cpu0
User   = 1.03%
System = 0.00%
Idle   = 98.97%

CPU    = cpu1
User   = 1.00%
System = 2.00%
Idle   = 93.00%

Detailed Memory Stats
Total     = 2.1 GB
Available = 1.9 GB
Used      = 227 MB
Free      = 1.4 GB

Detailed Disk Stats
Device         = /dev/mapper/ubuntu--1404--vbox--vg-root
MountPoint     = /
Size           = 41 GB
Used           = 3.4 GB
Available      = 36 GB
Used Percent   = 8.14%
Inodes Percent = 4.94%

これらの情報は常に更新されるため、ジョブの調整作業を行いやすくし、適切な挙動をしていないアプリケーションの発見などに使えます。

クラスタリングを簡単に(Simpler Clustering)

Nomad 0.4 は、クラスタの作成と操作を簡単にするため、2つの重要な変更を行いました。 Consul を使えば、クラスタの作成は自動的です。Nomad サーバとクライアントは、Consul のサービスとヘルスチェックに自動登録されます。Consul デプロイとの統合は、Nomad サーバが自動的にリージョン間を統合するのを意味します!

クラスタの安定性だけでなく、サーバの更新もシンプルになります。Nomad サーバには、サーバとクライアント間をハートビート(heartbeats)を通す一式を備えました。ハートビートを約 30 秒ごとに行い、Nomad サーバがリージョン上で現在把握しているノード情報を提供します。これにより、Nomad サーバはクライアント側の設定を変更しなくても、イミュータブル(訳者注:システムの状態を変えずに)に更新を行えるようにします。

これまで Nomad サーバを更新するには、新しいサーバを準備し、Raft 複製が発生する前に古いものを廃止していました。そして、クライアントは新しいサーバを参照するするよう、設定ファイルを書き換える必要があったのです。この更新手順は厄介であり、間違いやすい傾向がありました。

Nomad 0.4 のサーバ、はクライアントに対して利用可能なサーバ一覧を通知します。つまり、クライアント側の設定を変えなくても、Nomad サーバの入れ替えを可能とします。

まとめ

まだ Nomad は非常に若いプロジェクトです。しかし、導入と成長、そして、Nomad がプロダクションのワークロードを実行する様子はエキサイティングです。Nomad 0.3 は 100 万コンテナのスケーラビリティ をもたらしました。Nomad 0.4 で集中するべく選んだ機能は、操作における信頼性の改善でした。

さらに前進するため、私たちは複数の重要な機能を計画しています。ネイティブな Vault 統合、さらなる Consul 統合などです。正確なロードマップを近々リリースする予定です。

Nomad のサイトに移動し、詳細を学びましょう。

原文



概要

 Docker Engine 1.12 RC1 から、Docker Engine に swarm モードが搭載されています。また、機能として Ingress オーバレイ・ネットワークが標準で利用でき、負荷分散機能も使えます。このトピックでは新しい用語や概念の整理をし、実際のクラスタを作成と、nginx サービスとしてのコンテナを実行するまでの手順を整理します。

「swarm」 は「クラスタ」の意味

 Docker Engine に swarm モードは、従来の Docker Engine のクラスタを管理する Docker Swarm が Docker Engine に機能統合されたものです。これまで Docker Engine のクラスタを作るためには、 Swarm コンテナswarm バイナリをセットアップする必要がありました。ですが、今後は SwarmKit という内蔵機能に統合されているため、追加セットアップなしに docker コマンドでクラスタを管理できます。

 そして、Docker Engine でこのバージョンから Docker Engine のクラスタを swarm と呼びます。swarm は「群れ」の意味があります。そして swarm クラスタを扱うには、Docker Engine の swarm モード(swarm mode) を利用します。

Docker 1.12 RC をセットアップ

 現時点で swarm モードを使えるのは RC (リリース候補)版のみです。そのため、通常のセットアップ方法とは異なります。バイナリは GitHub の releases から入手できます。あるいは、次のコマンドを実行し、自動的に RC 版をセットアップすることもできます( Ubuntu 14.04, 16.04, CentOS 7.2 で動作確認)。

$ curl -fsSL https://test.docker.com/ | sh

 CentOS 7.2 では Docker Engine が自動起動しないため、 systemctl で起動する必要があります。

# systemctl start docker

 起動後の動作確認は、 docker version コマンドを実行します。正常に動作していれば、クライアントとサーバの両方のバージョンを表示できます。

# docker version
Client:
 Version:      1.12.0-rc2
 API version:  1.24
 Go version:   go1.6.2
 Git commit:   906eacd-unsupported
 Built:        Fri Jun 17 21:21:56 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.0-rc2
 API version:  1.24
 Go version:   go1.6.2
 Git commit:   906eacd-unsupported
 Built:        Fri Jun 17 21:21:56 2016
 OS/Arch:      linux/amd64

ノード

 ここでは3台の Docker Engine でクラスタを作成します。

  • node-01 192.168.39.1 … マネージャ・ノード兼ワーカ・ノード
  • node-02 192.168.39.2 … ワーカ・ノード
  • node-03 192.168.39.3 … ワーカ・ノード

 3台のサーバで Docker Engine ( dockerd デーモン )を動かします。このクラスタ内の Docker Engine を、それぞれ swarm の ノード(node) と呼びます。そして、このノードには2つの役割があります。

  1つは マネージャ・ノード(manager node) であり、ここで サービス(service) の期待状態(desired state)を定義します。サービスとは「 nginx コンテナを3つ動作する」といった状態を指します。また、swarm クラスタ全体を管理する docker node <命令> コマンドを処理できるのもマネージャ・ノードです。

 もう1つは ワーカ・ノード(worker node) です。マネージャ・ノードで定義されたサービスがこのワーカ・ノードに送られ、コンテナを実行・停止などの処理を行います。また、ワーカ・ノードは自分の状態をマネージャ・ノードに伝える役割もあります。

 なお、デフォルトではマネージャ・ノードはワーカーノードの役割も兼ねます。オプションの設定で、マネージャのみの役割で動作させることもできます。

サービスとタスクについて

 swarm クラスタ上で何らかのコンテナを実行するには、サービスを定義します。このサービス定義に従って実際にコンテナを起動するのが タスク(task) です。タスクはコンテナの最小スケジューリング単位です。スケジューリングとは、どのノードでどのコンテナを実行するのかを検討し、実際に起動する処理を指します。

 そして、サービスには2種類あります。

  • 複製サービス(replicated service) … マネージャが各ノードに対し、指定した数の複製タスクを作成します。
  • グローバル・サービス(global service) … あるタスクをクラスタ内の全ノード上で実行します。

 複製サービスが適しているのは、ウェブなどのスケールさせる必要があるタスクです。グローバル・サービスは全ノード上で実行しますので、監視やログ収集などのタスク実行に適していると考えられます。

swarm の初期化

 ここからは、実際にクラスタを構築します。swarm モードを使うためには、まず、swarm クラスタの初期化をします。初期化のためには docker swarm init コマンドを使います(init = initialize = 初期化)。 --lissten-addr <ホスト>:<ポート> で、swam マネージャが利用するインターフェースとポート番号を指定します。

$ docker swarm init --listen-addr 192.168.39.1:2377

 swarm クラスタ上のノード一覧を確認するには docker node ls コマンドを使います。

$ docker node ls
ID                           NAME     MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
dhrbvl6o9xqvprsq2uzq8o9ev *  node-01  Accepted    Ready   Active        Leader

 docker swarm init コマンドを実行した node-01 ノードの情報が表示されます。 MANAGER STATUS の部分に何らかの表示があれば、マネージャとして動作しています。ここでは初めて実行したマネージャのため、 Leader (リーダ)の役割です。

swarm クラスタに他のノードを追加

 次は残りの2台をクラスタに追加します。クラスタに追加するには、 node-02 node-03 の各ノード上で docker swarm join <マネージャ> コマンドを実行します。ここでは、次のコマンドを実行します。

$ docker swarm join 192.168.39.1:2377

 それから、 node-01 上で docker node ls コマンドを実行したら、各ノードが swarm に追加されているのが確認できます。

docker@node-01:~$ docker node ls
ID                           NAME     MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
6puvbl7tgxislfha5iaha40jm    node-03  Accepted    Ready   Active
9zj16or3durdh5i7c6khlench    node-02  Accepted    Ready   Active
dhrbvl6o9xqvprsq2uzq8o9ev *  node-01  Accepted    Ready   Active        Leader

 この情報はとは別に、クラスタの情報は docker info でも確認できます。

$ docker info
(省略)
Swarm: active
 NodeID: dhrbvl6o9xqvprsq2uzq8o9ev
 IsManager: Yes
 Managers: 1
 Nodes: 3

 マネージャは1つ、ノードが3つあることが分かります。

 これでサービスを実行する準備が整いました。

nginx サービスの定義と実行

 次は nginx コンテナを実行するサービスを定義します。サービスの定義は docker service create コマンドを使います。ここでは web という名前のサービスで(--name web )、コンテナを1つ実行( --replicas 1 )します。また、サービス側のポート 80 をコンテナ内のポート 80 に割り当て( -p 80:80 )します。

$ docker service create --replicas 1 –name web -p 80:80 nginx
f218o6xshkyt7zzxujhnz1a2h

 実行後の文字列 f218o6xshkyt7zzxujhnz1a2h はサービス ID と呼ばれるものです。サービス名かサービス ID を使い、サービスの停止・更新・削除などの操作時に使います。

 そして、サービスの状況を確認するには docker service ls コマンドを使います。

docker@node-01:~$ docker service ls
ID            NAME  REPLICAS  IMAGE  COMMAND
13765buws9fr  web   0/1       nginx

 ここでは REPLICAS (レプリカ)の表示が 0/1 になっているのに注目します。先ほど指定した --replicas 1 とは、タスク(コンテナ)の期待数が 1 でした。しかし、実際には 0 、つまり、まだタスク(としてのコンテナ)が起動しちていない状態です。

 この時、スケジューリング処理が行われています。3つのワーカのうち、どこでタスク(としてのコンテナ)を実行するか決め、その後、 nginx イメージのダウンロードと Docker コンテナを起動します。この状態を確認するには docker service tasks <サービス名> コマンドを実行します。

$ docker service tasks web
ID                         NAME   SERVICE  IMAGE  LAST STATE             DESIRED STATE  NODE
emjve46lgwjx22o6pxpbetfed  web.1  web      nginx  Running About an hour  Running        node-02

 ここでは node-02nginx イメージを使ったコマンドが実行中だと分かります。状況はリアルタイムに変わりますので、 watch コマンドを組みあわせると、状況の監視に便利です(例: watch -n 1 'docker service tasks web' )。

 タスク起動後にサービスの一覧を確認したら、今度は 1/1 に切り替わります。

docker@node-01:~$ docker service ls
ID            NAME  REPLICAS  IMAGE  COMMAND
13765buws9fr  web   1/1       nginx

ingress オーバレイ・ネットワークと負荷分散

 インターネット側など、外部のネットワークからコンテナにアクセスするには、ポート 80 に接続します。接続は、 node-02 の IP アドレス 192.168.39.2 でアクセス可能なだけではありません。swarm モードで動作しているノードであれば、どこからでもアクセス可能です。

 これは、各ノード上では ingress という名前のオーバレイ・ネットワーク(overlay network)が作成されているからです。 docker network ls コマンドを実行し、ノード上の Docker ネットワーク一覧を表示します。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
bbb5e37b01e8        bridge              bridge              local
6550c72b075f        docker_gwbridge     bridge              local
84baeb90cbb2        host                host                local
9i5hmgqr20jh        ingress             overlay             swarm
7ab4c321bbe5        none                null                local

 注目すべきは ingress という名前のネットワークです。これは swarm モードで自動作成されるオーバレイ・ネットワークです。これは複数のノード間がつながっている共有ネットワークです。そして SCOPE には localswam があります。 local はノードの中でのみ有効なネットワーク、 swarm は swarm モードのクラスタで有効なネットワークです。

 そして、 ingress ネットワークの特長として、このネットワーク上で公開しているポートは、どのノードへアクセスがあっても、タスクを実行しているノードに自動ルーティングしてくれます。

 さらに Ingress ネットワークには負荷分散機能も入っています。この負荷分散はタスクに応じて自動的に処理されます。つまり、swarm モードではサービスとして公開しているポートが分かれば、どのノードにアクセスしても、自動的に対象となるタスク(コンテナ)に到達可能です。内部では自動的にタスクの監視を行うため、スケールアップ・スケールダウンによりコンテナが増減しても、外部から内部の状況を意識する必要がなくなります。

 これを応用したら、この Ingress Load Balancing の上にロードバランサやプロキシを置くなり、あるいは DNS ラウンドロビンなどで可用性を高めるサービスが作られるかもしれません。実際には性能面での検証は必要と思われますが、Nginx などリバース・プロキシをたてなくても、良い感じで分散してくれる仕組みは、使いどころがありそうだと感じています。

サービスの更新

 次は、サービスの数を3つに増やします。状態を変更するのは docker service update コマンドです。

$ docker service update --replicas 3 web
web

 サービス一覧を確認したら、期待数が 3 になっているのが分かります。

$ docker service ls
ID            NAME  REPLICAS  IMAGE  COMMAND
13765buws9fr  web   2/3       nginx

 タスクの一覧で状況を確認してみます。

$ docker service tasks web
ID                         NAME   SERVICE  IMAGE  LAST STATE           DESIRED STATE  NODE
emjve46lgwjx22o6pxpbetfed  web.1  web      nginx  Running 2 hours      Running        node-02
8owd8swtc99coag9evqz4j0dx  web.2  web      nginx  Running 8 seconds    Running        node-01
6z7svrkbpjyfp7gme4r1c2qh4  web.3  web      nginx  Preparing 8 seconds  Running        node-03

 ここでは3台のノードに分散して nginx コンテナを起動しようとしています。 node-01 node-02Running (稼働中)と分かりますが、 node-03Preparing (準備中)です。そのため、 docker service lsREPLICAS2/3 でした。

 もうしばらくしてから docker service ls を実行したら、最終的に3つのタスクが実行中になります。

$ docker service ls
ID            NAME  REPLICAS  IMAGE  COMMAND
13765buws9fr  web   3/3       nginx

 なお3つのノードに分散してスケジューリングされたのは、デフォルトでは Spread (スプレッド)というコンテナをノードに分散配置するストラテジが適用されているからです。

 次はまたタスクの数を減らしましょう。

$ docker service update --replicas 1 web
web
$ docker service tasks web
ID                         NAME   SERVICE  IMAGE  LAST STATE         DESIRED STATE  NODE
6z7svrkbpjyfp7gme4r1c2qh4  web.3  web      nginx  Running 4 minutes  Running        node-03

 このように、再び docker service update コマンドを実行するだけで、スケールダウンも可能です。

 最後にサービスを削除するには docker service rm コマンドを使います。

$ docker service rm web
web
$ docker service ls
ID  NAME  REPLICAS  IMAGE  COMMAND

 これでサービスの削除完了です。

 このように、docker service コマンドでサービスを定義したら、 docker コマンドを使わなくても、swarm クラスタ上でコンテナの起動・更新・停止が可能になります。

 なお、この検証を行った Docker 1.12RC2 はリリース候補版のため、実際の Docker 1.12 では仕様が変わる可能性もありますのでご了承ください。現段階では開発中ですが、色々と評価してみる分には、面白いのではないかと思います。

参考



概要

DockerCon 2016 のキーノートで、新しい Docker 1.12 の機能に関する説明がありました。また、その発表に合わせるように blog への投稿 “Docker 1.12: Now with Built-in Orchestration!” もありました。例によって日本語訳を作成しましたので、内容把握の参考程度にどうぞ。

図版は省略しました。原文をおたどりください。なお、自分の整理用に以前のバージョンの比較用画像を作りましたので、こちらも参考程度にどうぞ。

Docker 1.12: ついにオーケストレーションを組み込み!

 3年前、Docker は難解な Linux カーネル技術をコンテナ化(containerization)と呼ぶシンプルで誰もが利用しやすいものにしました。今日、私たちはコンテナのオーケストレーションも同じ様にします。

 単一ホスト上にコンテナを個々にデプロイしている状態から、複雑な複数のコンテナを多くのマシンにデプロイするスタイルに移行するために、コンテナ・オーケストレーション(container orchestration)が求められています。そのためにはインフラから独立した分散プラットフォームを必要とします。つまりアプリケーションのライフタイム(存続期間)全てにわたってオンラインを維持し、ハードウェア障害やソフトウェア更新時も生存し続けるようにします。今日のオーケストレーションは、3年前のコンテナ化と同じステージです。ここには2つの選択肢があります。1つは、あなたが技術の専門部隊と共に、複雑なアドホック・システムを作り上げること。そうでなければ、多くの専門家がいる会社を信頼するかです。専門家は、あなたの代わりに全てのハードウェア、サービス、サポート、ソフトウェアを購入し、全てを管理するのです。この状態を表す言葉があります。ロックイン(lock-in)と呼ばれます。

 Docker ユーザは他のオプションを受け入れ可能かどうか、私たちとずっと共有してきました。皆さんが必要なのは、オーケストレーションを誰もが使えるプラットフォームであり、ロックインがないものです。コンテナ・オーケストレーションは実行が簡単であり、よりポータブルであり、安全、弾力的(resilient)、そしてより速いことです。たとえ、プラットフォームに組み込まれていたとしてもです。

 Docker 1.12 から Docker Engine のコアに機能を追加し始めました。機能とは、マルチ・ホストとマルチ・コンテナのオーケストレーションを簡単にします。私たちは新しい API オブジェクトを追加しました。サービス(Service)とノード(Node)です。これは swarm と呼ばれる Docker Engine のグループ上で、アプリケーションのデプロイと管理に Docker API を使います。Docker 1.12 があれば、Docker をオーケストレートする最も良い方法こそが Docker なのです!

<図>

 Docker 1.2 は4つの原則をベースにしています。

  • シンプルでありながら強力(Simple Yet Powerful) - 最近の分散アプリケーションにおいて、オーケストレーションは中核部分です。そして、その中心にあたるものは、私たちが Docker Engine のコアへシームレスに組み込みました。私たちの手法はオーケストレーションでも私たちのコンテナに対する哲学を適用することです。哲学とは、セットアップ不要であり、シンプルな概念を学ぶのは最小限であり、そして「とにかく動く」(it just work)というユーザ経験です。

  • 弾力性(Resilient) - マシンは常に落ちます。最近のシステムではこれらの障害を予測すべきであり、恒常的に存在し続け、アプリケーションのダウンタイム(停止時間)なしに適用できることです。それが単一障害点(single-point-of-failure)をゼロにする設計が必要な理由です。

  • 安全(Secure) - デフォルトで安全であるべきです。強力なセキュリティの防壁のためには、証明書の生成(certificate generation)、そのために PKI の理解が必要だったのですが、不要になるべきです。しかし、高度なユーザであれば、これまで通り全ての証明書への署名と発行を制御・監査し続けるべきでしょう。

  • オプション機能と後方互換性 - 100 万人ものユーザがいるため、Docker Engine の後方互換性維持は必須です。新しい全ての機能はオプションであり、使わなければオーバヘッド(メモリや CPU に対する)を被る心配はありません。Docker Engine のオーケストレーションは私たちのプラットフォームの内蔵電池(batteries included)ですが、交換可能にしています。そのため、ユーザはサードパーティ製のオーケストレータを Docker Engine 上で使い続けられます。

 それでは Docker 1.12 で動く新しい機能を見ていきましょう。

1つの分散構築ブロックで Swarm を作る

 始めるためには swarm (訳者注:「群れ」の意味で、Docker Engine のクラスタを指す言葉)を作成します。swarm は Engine を自己組織化(self-organizing)でき、自己修復グループ(self-healing group)します。ノードの立ち上げ(bootstrap)は次のようにシンプルです。

docker swarm init

 このフードの下では Raft コンセンサス・グループ(合意グループ)のノードを1つ作成しています。この1つめのノードはマネージャ(manager)の役割(role)を持っています。つまり、コマンドを受け付け、タスクをスケジュールします。swarm にさらにノードを追加したら、デフォルトではワーカ(worker)になります。ワーカとはマネージャが命令したコンテナを単純に実行します。オプションで、他にもマネージャ・ノードを追加可能です。マネージャ・ノードは Raft コンセンサス・グループの一部になり得ます。私たちは最適化した Raft ストアを使います。スケジューリング性能を高速にするため、メモリを直接読み込み処理します。

サービスの作成とスケール

 docker run でコンテナを1つ実行しておけば、 Engine の swarm (クラスタ)上で docker service を使いプロセスの複製、分散、負荷分散を始められます。

docker service create --name frontend --replicas 5 -p 80:80/tcp nginx:latest

 このコマンドは nginx コンテナの期待状態(desired state)が5つであると宣言します。swarm 上のノードのポート 80 へのアクセスは、内部ロード・バランサ・サービスを通して、いずれかのコンテナに到達します。この動作の仕組みは Linux IPVS を使ったカーネル内のレイヤ4マルチ・プロトコル・ロードバランサです。これは Linux カーネルに 15 年以上も前からあるものです。IPVS ルーティング・パケットはカーネル内であり、swarm のルーティングは高性能なコンテナ検出負荷分散(container-aware load-balancing)をもたらします。

 サービスの作成時、オプションで複製サービス(replicated services)かグローバル・サービス(global services)を作成できます。複製サービスとは、利用可能なホスト上に広くコンテナを多く展開する意味です。対照的にグローバル・サービスとは、sawrm 上の各ホストに同じコンテナを1つずつスケジュールします。

 それでは Docker が提供する弾力性について考えて見ましょう。Swarm モードは engine を自己組織化(self organizing)と自己修復(self healing)ができるようにします。つまり、engine は自分が定義した通りにアプリケーションに注意を払います。そのためには、継続的なチェックや、engine がどこかに行った時は調整を担います。たとえば、nginx インスタンスを実行中のマシンの電源コードを抜いても、別のノードで新しいコンテナが復活します。ネットワーク・スイッチから swarm クラスタ上の半分のマシンを引き抜いても、他のノードが引き継ぎ、残ったノードでコンテナを再分配します。更新時には、既存のサービスを変更するため、柔軟に再デプロイ(re-deploy)できます。swarm 上のコンテナはローリング(rolling)もしくは並列に更新できます。

 100 インスタンスにスケールアップしたいですか? 次のように簡単です。

docker service scale frontend=100

 典型的な2ティア(web+db)アプリケーションは次のように作成できます。

docker network create -d overlay mynet
docker service create --name frontend --replicas 5 -p 80:80/tcp \
    --network mynet mywebapp
docker service create --name redis --network mynet redis:latest

 これはこのアプリケーションの基本アーキテクチャです。

<図>

セキュリティ

 Docker 1.12 の中心にある原則は、設定しなくてもデフォルトで安全であり、Docker プラットフォームをすぐに使えるように作ることです。管理者が度々直面する主な課題の1つは、プロダクションで実行中のアプリケーションを安全にデプロイすることです。Docker 1.12 では管理者がデモ用クラスタを確実にセットアップできるようにします。つまり、安全なプロダクションのクラスタをセットアップできるでしょう。

 セキュリティは後から締め直せるようなものではありません。それゆえ、 Docker 1.12 では難しい設定を行わなくても、 swarm 上の全てのノードが相互に TLS 認証が可能であり、認証し、暗号化通信を可能とするのです。

 1つめのマネージャを起動したら、Docker Engine は新しい認証機関(CA; Certificate Authority)を作成し、自分用の初期証明書セットを作成します。この初期ステップ以降は、swarm に参加する各ノードは、ランダムに生成した ID で自動的に新しい証明書を作成し、swarm (マネージャかワーカ)の各ロールに適用します。これらの証明書は swarm 上にノードが参加している間中、ノードを安全に暗号化して認識するために使います。そしてまた、マネージャが安全にタスクやその他の更新を伝えるためにも使います。

<図>

 TLS 採用の最も大きな障壁の1つは、公開鍵基盤(PKI; Public Key Infrastructure)の作成・設定・管理に必要なのが大変な点です。Docker 1.12 では全てが安全にセットアップされているだけでなく、設定済みです。そして、もう1つ TLS 証明書を扱う上で最もつらい証明書の更新も自動化しました。

 フードの下では、swarm に参加する各ノードは定期的に証明書を確実に更新します。そのため、潜在的な流出や、設定の妥協はもうありません。証明証の入れ替え(rotate)設定は、ユーザによって変更できます。最小間隔は30分です。

 自分の認証機関(Certificated Authority)を使いたい場合は、私たちは外部 CA モード(external-CA mode)もサポートしています。これは swarm にノードがリモート URL から参加する時、マネージャはノードの証明書署名要求(CSR; Certificate Signing Request)を単純に信頼しようとします。

Bundle(バンドル)

 Docker 1.12 は Distributed Application Bundle という新しいファイル形式を導入しました( experimental ビルドのみ)。Bundle (荷物のあつまり、束の意味)はフルスタック・アプリケーション上のサービスに集中した新しい抽象化です。

 Docker Bundle ファイルは宣言型のサービス・セットの仕様書です。仕様には次の命令があります。

  • 何のイメージのリビジョンを実行するか
  • 何の名前のネットワークを作成するか
  • どのようにこれらサービスのコンテナを、どのネットワーク上で実行するか

 Bundle ファイルは完全にポータブルであり、ソフトウェア・デリバリのパイプラインにおいて、アーティファクト(訳者注:最終成果物の意味)の完全なデプロイをもたらします。これは、複数コンテナを Docker アプリとして記述した全てを移動し、バージョン化できるからです。

 Bundle ファイルの仕様はシンプルかつオープンです。必要であれば自分が欲しいバンドルを作成できます。使い始めるには、Docker Compose は bundle ファイルの作成に実験的に対応しました。そして Docker 1.12 の swarm モードを有効化したら、bundle ファイルをデプロイできます。

 Bundle は開発者のノート PC から CI を通したプロダクションに、複数サービスのアプリケーションを効率的に移動する仕組みです。実験的機能であり、私たちはコミュニティからのフィードバックをお待ちしています。

Dokcer 1.12 のフードの下

 フードの下を見ますと、Docker 1.12 では他にも多くの面白い技術を使っています。ノード間通信には gRPC を使っており、これにより HTTP/2 の多重接続やヘッダ圧縮のような利点を得られます。私たちのデータ構造は protobufs の効果的な移植です、感謝します。

 Docker 1.12 のリソースについては、他もご覧ください。

原文


open the next

20.06.2016  in site using tags Hugo

Hey world!

Close the world, open the next...

旧サイト の情報整理のため、サイトの移行と情報整理をします。技術系の情報は、今後こちらに集約する予定です。とはいえ、予定は未定。