O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×

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

Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Carregando em…3
×

Confira estes a seguir

1 de 37 Anúncio
Anúncio

Mais Conteúdo rRelacionado

Diapositivos para si (20)

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

Anúncio

Mais de 京大 マイコンクラブ (20)

Mais recentes (20)

Anúncio

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 に頼らず インターフェイスでオペレーションしよう!!

×