Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
No SSH
KMC関東例会 at Cybozu
野島 裕輔 (@nojima)
自己紹介
@nojima (Yusuke Nojima)
blog: nojima.hatenablog.com
github: github.com/nojima
twitter: twitter.com/nojima
Cybozu でインフ...
インフラの自動化について話します
そもそも何で自動化しないといけないのか?
前提:
サービスが成長していく
サービスが成長していくと…
• 使用するメモリ量、ディスクIO、CPU使用量などが
増加していく。
• そして、いつかサーバーの物理的な限界に到達する。
スケーリング
• スケールアップ
• より強いサーバーを投入することで、より多くの計算資源を確保する。
• 一定の性能を超えると、性能あたりの値段が指数関数的に増大する。
• スケールアウト
• サーバーを大量に並べることで、必要な計算資源を確...
サーバー管理
• サーバーの投入のために、サーバーの役割に応じて
パッケージのインストールや設定の配置を行う。
• サービスのリリースのために、APサーバーの
ローリングアップデートを行う。
• 脆弱性対応のために、インストールされたパッケージ...
サーバー職人の朝は早い
• 感覚的には、サーバーが10台ぐらいなら手動でも管理できる。
• しかし、サーバーが1000台になると、手動では絶対に無理。
• したがって、スケールアウトには自動化が必須。
どうやって自動化する?
ナイーブなやり方:
1. 手動での手順を確立する。
2. (Optional) 手順を手順書に起こす。
3. 手順をシェルスクリプトやPythonで書く。
DB
例1: AP のローリングアップデート
• アプリケーションの新しいバージョンをリリースしたい。
• アプリケーションは次のような3層構成になっているとする。
nginx
nginx
AP
AP
AP
User
# AP サーバをローリングアップデートする
for ap in ${AP_SERVERS}; do
# ロードバランシング対象から外す
for nginx in ${NGINX_SERVERS}; do
ssh ${nginx} sudo d...
例2: ロードバランサの更新
• 脆弱性対応とかでロードバランサに入っている
パッケージを更新したいとする。
• Ubuntu の場合は apt dist-upgrade した後にサーバーを
再起動する手順になる。
# ロードバランサの更新を行う
# (本当は L4LB からの切り離しを行うべきだけど煩雑なので省略)
for nginx in ${NGINX_SERVERS}; do
# パッケージの更新
ssh ${nginx} sudo apt upd...
この調子で自動化していけば
いくらでもスケールアウトできる?
残念ながら
No
例: APとLBの並列更新
オペレータAがAPをローリングアップデートしている最中に、
別のオペレータBがロードバランサを更新しようとしたとする。
# AP をローリングアップデートする
for ap in ${AP_SERVERS}; do
# ロードバランシング対象から外す
for nginx in ${NGINX_SERVERS}; do
ssh ${nginx} ...
done
...
単体では問題なく実施できるオペレーションでも
並列に実行すると壊れる場合がある
どうすればいい?
• 同時に実行しないように人が注意する
⇐ チームの規模が大きくなってくると無理
• 2つのスクリプトは「ロードバランサ」という共有リソースを
操作していた。
• 同時に実行してはいけない操作が競合し、問題となった。
• じゃ...
(
flock -x 9
# AP サーバをローリングアップデートする
for ap in ${AP_SERVERS}; do
# ロードバランシング対象から外す
for nginx in ${NGINX_SERVERS}; do
ssh ${...
( flock -x 9 ... ) 9> /var/lock/nginx-operation って何?
( ... )
サブシェル。
別のプロセスを起動して、その中で括弧の中のコマンドを実行する。
9> filename
リダイレクト。
この...
• これで、AP の更新スクリプトとロードバランサの
更新スクリプトが衝突する系を救えた。
• しかし、ロードバランサに対して行う操作は他にもある。
• static コンテンツのアップロード
• nginx 設定ファイルの更新
• SSL証明...
調停による依存関係の爆発
Operation
5
nginx
nginx
Operation
1
Operation
4
Operation
3
Operation
2
どうすればよかったのか?
• 各スクリプト同士を直接調停させようとすると、
依存関係により破綻する。
• よって、サービスを提供する側(この場合は nginx)で
調停すべき。
やりたいことのイメージ
Operation
5
nginx
nginx
Operation
1
Operation
4
Operation
3
Operation
2
nginx
operator
service
ここで調停
しかし、現在のシェルスクリプトには、
調停者を差し込む余地がない。
# ロードバランサの更新を行う
# (本当は L4LB からの切り離しを行うべきだけど煩雑なので省略)
for nginx in ${NGINX_SERVERS}; do
# パッケージの更新
ssh ${nginx} sudo apt upd...
No SSH
# 再起動
ssh ${nginx} sudo reboot
そもそも、ここがダメなのでは?
ssh はカプセル化を破壊する
• ssh するとリモートサーバー上のあらゆるファイルを読み書きできる。
• ssh するとリモートサーバー上のあらゆるデーモンを起動・停止できる。
• ssh するとリモートサーバー上のあらゆる状態を取得できる...
ssh を許可すると、
そのサーバーのあらゆる実装上の詳細を
クライアントに露呈させることになる
ssh をやめて、
インターフェイスで会話しよう
• ssh によるオペレーション自動化を禁止。
• 代わりに、サービスを管理するためのエージェントを作る。
• エージェントの API が、そのサービスの公開インターフェイスとなる。
• オペレ...
インターフェイスをどう設計するか
• 実装上の詳細ができるだけ露呈しないようにする。
• そのサービスを構成するサーバーのリスト、
サーバーのファイルシステムのレイアウト、
そのサービスの実装が利用している外部サービスの仕様
などをクライアント...
nginx の例だと…
• 「APの切り離し」や「ロードバランサの更新」などが
公開 API になる。
• API を提供するエージェントは Virtual IP などを使って
真の IP アドレスを隠蔽しておく。
• オペレーションの並列度を...
こんな感じ
nginx
nginx
Operation
1
Operation
2
nginx
operator
service
公開インターフェイスで
オペレーションを依頼
queue worker
なんかいい感じにやる
Virtual IP...
まとめ
ssh に頼らず
インターフェイスでオペレーションしよう!!
Upcoming SlideShare
Loading in …5
×

No SSH (@nojima; KMC関東例会)

1,223 views

Published on

2017-09-02 KMC関東例会 at Cybozu
インフラの自動化の辛さと ssh について

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

No SSH (@nojima; KMC関東例会)

  1. 1. No SSH KMC関東例会 at Cybozu 野島 裕輔 (@nojima)
  2. 2. 自己紹介 @nojima (Yusuke Nojima) blog: nojima.hatenablog.com github: github.com/nojima twitter: twitter.com/nojima Cybozu でインフラエンジニアをやっています。 元競プロ勢。
  3. 3. インフラの自動化について話します
  4. 4. そもそも何で自動化しないといけないのか?
  5. 5. 前提: サービスが成長していく
  6. 6. サービスが成長していくと… • 使用するメモリ量、ディスクIO、CPU使用量などが 増加していく。 • そして、いつかサーバーの物理的な限界に到達する。
  7. 7. スケーリング • スケールアップ • より強いサーバーを投入することで、より多くの計算資源を確保する。 • 一定の性能を超えると、性能あたりの値段が指数関数的に増大する。 • スケールアウト • サーバーを大量に並べることで、必要な計算資源を確保する。 • 値段は全体の性能に比例する。 • 大量のサーバーを並べることになるので、管理が大変
  8. 8. サーバー管理 • サーバーの投入のために、サーバーの役割に応じて パッケージのインストールや設定の配置を行う。 • サービスのリリースのために、APサーバーの ローリングアップデートを行う。 • 脆弱性対応のために、インストールされたパッケージを 更新する。 • などなど
  9. 9. サーバー職人の朝は早い • 感覚的には、サーバーが10台ぐらいなら手動でも管理できる。 • しかし、サーバーが1000台になると、手動では絶対に無理。 • したがって、スケールアウトには自動化が必須。
  10. 10. どうやって自動化する? ナイーブなやり方: 1. 手動での手順を確立する。 2. (Optional) 手順を手順書に起こす。 3. 手順をシェルスクリプトやPythonで書く。
  11. 11. DB 例1: AP のローリングアップデート • アプリケーションの新しいバージョンをリリースしたい。 • アプリケーションは次のような3層構成になっているとする。 nginx nginx AP AP AP User
  12. 12. # AP サーバをローリングアップデートする for ap in ${AP_SERVERS}; do # ロードバランシング対象から外す for nginx in ${NGINX_SERVERS}; do ssh ${nginx} sudo detach-from-load-balancer ${ap} done # APサーバの更新 cat ${ARTIFACT_TGZ} | ssh ${ap} sudo tar -z -x -C / ssh ${ap} sudo systemctl restart ap-service # ロードバランシング対象に戻す for nginx in ${NGINX_SERVERS}; do ssh ${nginx} sudo attach-to-load-balancer ${ap} done done
  13. 13. 例2: ロードバランサの更新 • 脆弱性対応とかでロードバランサに入っている パッケージを更新したいとする。 • Ubuntu の場合は apt dist-upgrade した後にサーバーを 再起動する手順になる。
  14. 14. # ロードバランサの更新を行う # (本当は L4LB からの切り離しを行うべきだけど煩雑なので省略) for nginx in ${NGINX_SERVERS}; do # パッケージの更新 ssh ${nginx} sudo apt update ssh ${nginx} sudo apt dist-upgrade -y # 再起動 ssh ${nginx} sudo reboot (${nginx} が起動するまで待つ) done
  15. 15. この調子で自動化していけば いくらでもスケールアウトできる?
  16. 16. 残念ながら No
  17. 17. 例: APとLBの並列更新 オペレータAがAPをローリングアップデートしている最中に、 別のオペレータBがロードバランサを更新しようとしたとする。
  18. 18. # AP をローリングアップデートする for ap in ${AP_SERVERS}; do # ロードバランシング対象から外す for nginx in ${NGINX_SERVERS}; do ssh ${nginx} ... done # APサーバの更新 cat ${ARTIFACT} | ssh ${ap} ... ssh ${ap} sudo systemctl ... # ロードバランシング対象に戻す for nginx in ${NGINX_SERVERS}; do ssh ${nginx} ... done done # ロードバランサの更新を行う for nginx in ${NGINX_SERVERS}; do # パッケージの更新 ssh ${nginx} sudo apt update ssh ${nginx} sudo apt dist-upgrade # 再起動 ssh ${nginx} sudo reboot (${nginx} が起動するまで待つ) done
  19. 19. 単体では問題なく実施できるオペレーションでも 並列に実行すると壊れる場合がある
  20. 20. どうすればいい? • 同時に実行しないように人が注意する ⇐ チームの規模が大きくなってくると無理 • 2つのスクリプトは「ロードバランサ」という共有リソースを 操作していた。 • 同時に実行してはいけない操作が競合し、問題となった。 • じゃあ排他すればいいじゃん!!
  21. 21. ( flock -x 9 # AP サーバをローリングアップデートする for ap in ${AP_SERVERS}; do # ロードバランシング対象から外す for nginx in ${NGINX_SERVERS}; do ssh ${nginx} sudo ... done # APサーバの更新 cat ${ARTIFACT_TGZ} | ssh ${ap} ... ssh ${ap} sudo ... # ロードバランシング対象に戻す for nginx in ${NGINX_SERVERS}; do ssh ${nginx} sudo ... done done ) 9> /var/lock/nginx-operation ( flock -x 9 # ロードバランサの更新を行う for nginx in ${NGINX_SERVERS}; do # パッケージの更新 ssh ${nginx} sudo apt update ssh ${nginx} sudo apt dist-upgrade # 再起動 ssh ${nginx} sudo reboot (${nginx} が起動するまで待つ) done ) 9> /var/lock/nginx-operation
  22. 22. ( flock -x 9 ... ) 9> /var/lock/nginx-operation って何? ( ... ) サブシェル。 別のプロセスを起動して、その中で括弧の中のコマンドを実行する。 9> filename リダイレクト。 この場合、filename を書き込みモードで open し、9番の FD に割り当てる。 flock -x 9 9番の FD を使って排他ロックを行う。 ロックはファイルが閉じられるまで保持される。
  23. 23. • これで、AP の更新スクリプトとロードバランサの 更新スクリプトが衝突する系を救えた。 • しかし、ロードバランサに対して行う操作は他にもある。 • static コンテンツのアップロード • nginx 設定ファイルの更新 • SSL証明書の更新 • … • 全部調停しないといけない
  24. 24. 調停による依存関係の爆発 Operation 5 nginx nginx Operation 1 Operation 4 Operation 3 Operation 2
  25. 25. どうすればよかったのか? • 各スクリプト同士を直接調停させようとすると、 依存関係により破綻する。 • よって、サービスを提供する側(この場合は nginx)で 調停すべき。
  26. 26. やりたいことのイメージ Operation 5 nginx nginx Operation 1 Operation 4 Operation 3 Operation 2 nginx operator service ここで調停
  27. 27. しかし、現在のシェルスクリプトには、 調停者を差し込む余地がない。
  28. 28. # ロードバランサの更新を行う # (本当は L4LB からの切り離しを行うべきだけど煩雑なので省略) for nginx in ${NGINX_SERVERS}; do # パッケージの更新 ssh ${nginx} sudo apt update ssh ${nginx} sudo apt dist-upgrade -y # 再起動 ssh ${nginx} sudo reboot (${nginx} が起動するまで待つ) done どうしようもない
  29. 29. No SSH
  30. 30. # 再起動 ssh ${nginx} sudo reboot そもそも、ここがダメなのでは?
  31. 31. ssh はカプセル化を破壊する • ssh するとリモートサーバー上のあらゆるファイルを読み書きできる。 • ssh するとリモートサーバー上のあらゆるデーモンを起動・停止できる。 • ssh するとリモートサーバー上のあらゆる状態を取得できる。 ssh は OOP において private 変数を直接読み書きしているようなもの!!
  32. 32. ssh を許可すると、 そのサーバーのあらゆる実装上の詳細を クライアントに露呈させることになる
  33. 33. ssh をやめて、 インターフェイスで会話しよう • ssh によるオペレーション自動化を禁止。 • 代わりに、サービスを管理するためのエージェントを作る。 • エージェントの API が、そのサービスの公開インターフェイスとなる。 • オペレーションスクリプトは、公開されたインターフェイスを 叩くだけにする。
  34. 34. インターフェイスをどう設計するか • 実装上の詳細ができるだけ露呈しないようにする。 • そのサービスを構成するサーバーのリスト、 サーバーのファイルシステムのレイアウト、 そのサービスの実装が利用している外部サービスの仕様 などをクライアントが意識しなくてもよいようにする。 • クライアント同士で調停しなくてもいいようにする。 • 共有リソースの操作はサービス側で適切に排他して行う。
  35. 35. nginx の例だと… • 「APの切り離し」や「ロードバランサの更新」などが 公開 API になる。 • API を提供するエージェントは Virtual IP などを使って 真の IP アドレスを隠蔽しておく。 • オペレーションの並列度を制御するために、queue + worker 方式で nginx に対するオペレーションを行う。 • 並列度の制御方法はいろいろあるので、別の方法でもいい。
  36. 36. こんな感じ nginx nginx Operation 1 Operation 2 nginx operator service 公開インターフェイスで オペレーションを依頼 queue worker なんかいい感じにやる Virtual IP でサービスを提供
  37. 37. まとめ ssh に頼らず インターフェイスでオペレーションしよう!!

×