37
No SSH KMC関東例会 at Cybozu 野島 裕輔 (@nojima)

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

  • Upload
    -

  • View
    777

  • Download
    1

Embed Size (px)

Citation preview

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

No SSHKMC関東例会 at Cybozu

野島 裕輔 (@nojima)

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

自己紹介

@nojima (Yusuke Nojima)

blog: nojima.hatenablog.com

github: github.com/nojima

twitter: twitter.com/nojima

Cybozu でインフラエンジニアをやっています。

元競プロ勢。

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

インフラの自動化について話します

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

そもそも何で自動化しないといけないのか?

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

前提:

サービスが成長していく

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

サービスが成長していくと…

• 使用するメモリ量、ディスクIO、CPU使用量などが

増加していく。

• そして、いつかサーバーの物理的な限界に到達する。

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

スケーリング

• スケールアップ

• より強いサーバーを投入することで、より多くの計算資源を確保する。

• 一定の性能を超えると、性能あたりの値段が指数関数的に増大する。

• スケールアウト

• サーバーを大量に並べることで、必要な計算資源を確保する。

• 値段は全体の性能に比例する。

• 大量のサーバーを並べることになるので、管理が大変

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

サーバー管理

• サーバーの投入のために、サーバーの役割に応じて

パッケージのインストールや設定の配置を行う。

• サービスのリリースのために、APサーバーの

ローリングアップデートを行う。

• 脆弱性対応のために、インストールされたパッケージを

更新する。

• などなど

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

サーバー職人の朝は早い

• 感覚的には、サーバーが10台ぐらいなら手動でも管理できる。

• しかし、サーバーが1000台になると、手動では絶対に無理。

• したがって、スケールアウトには自動化が必須。

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

どうやって自動化する?

ナイーブなやり方:

1. 手動での手順を確立する。

2. (Optional) 手順を手順書に起こす。

3. 手順をシェルスクリプトやPythonで書く。

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

DB

例1: AP のローリングアップデート

• アプリケーションの新しいバージョンをリリースしたい。

• アプリケーションは次のような3層構成になっているとする。

nginx

nginx

AP

AP

AP

User

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

# 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

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

例2: ロードバランサの更新

• 脆弱性対応とかでロードバランサに入っている

パッケージを更新したいとする。

• Ubuntu の場合は apt dist-upgrade した後にサーバーを

再起動する手順になる。

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

# ロードバランサの更新を行う# (本当は 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

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

この調子で自動化していけば

いくらでもスケールアウトできる?

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

残念ながら

No

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

例: APとLBの並列更新

オペレータAがAPをローリングアップデートしている最中に、

別のオペレータBがロードバランサを更新しようとしたとする。

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

# 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

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

単体では問題なく実施できるオペレーションでも

並列に実行すると壊れる場合がある

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

どうすればいい?

• 同時に実行しないように人が注意する

⇐ チームの規模が大きくなってくると無理

• 2つのスクリプトは「ロードバランサ」という共有リソースを

操作していた。

• 同時に実行してはいけない操作が競合し、問題となった。

• じゃあ排他すればいいじゃん!!

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

(

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

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

( flock -x 9 ... ) 9> /var/lock/nginx-operation って何?

( ... )

サブシェル。

別のプロセスを起動して、その中で括弧の中のコマンドを実行する。

9> filename

リダイレクト。

この場合、filename を書き込みモードで open し、9番の FD に割り当てる。

flock -x 9

9番の FD を使って排他ロックを行う。

ロックはファイルが閉じられるまで保持される。

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

• これで、AP の更新スクリプトとロードバランサの

更新スクリプトが衝突する系を救えた。

• しかし、ロードバランサに対して行う操作は他にもある。

• static コンテンツのアップロード

• nginx 設定ファイルの更新

• SSL証明書の更新

• …

• 全部調停しないといけない

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

調停による依存関係の爆発

Operation5

nginx

nginx

Operation 1

Operation4

Operation3

Operation2

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

どうすればよかったのか?

• 各スクリプト同士を直接調停させようとすると、

依存関係により破綻する。

• よって、サービスを提供する側(この場合は nginx)で

調停すべき。

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

やりたいことのイメージ

Operation5

nginx

nginx

Operation 1

Operation4

Operation3

Operation2

nginxoperatorservice

ここで調停

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

しかし、現在のシェルスクリプトには、

調停者を差し込む余地がない。

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

# ロードバランサの更新を行う# (本当は 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

どうしようもない

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

No SSH

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

# 再起動

ssh ${nginx} sudo reboot

そもそも、ここがダメなのでは?

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

ssh はカプセル化を破壊する

• ssh するとリモートサーバー上のあらゆるファイルを読み書きできる。

• ssh するとリモートサーバー上のあらゆるデーモンを起動・停止できる。

• ssh するとリモートサーバー上のあらゆる状態を取得できる。

ssh は OOP において private 変数を直接読み書きしているようなもの!!

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

ssh を許可すると、

そのサーバーのあらゆる実装上の詳細を

クライアントに露呈させることになる

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

ssh をやめて、インターフェイスで会話しよう

• ssh によるオペレーション自動化を禁止。

• 代わりに、サービスを管理するためのエージェントを作る。

• エージェントの API が、そのサービスの公開インターフェイスとなる。

• オペレーションスクリプトは、公開されたインターフェイスを

叩くだけにする。

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

インターフェイスをどう設計するか

• 実装上の詳細ができるだけ露呈しないようにする。

• そのサービスを構成するサーバーのリスト、

サーバーのファイルシステムのレイアウト、

そのサービスの実装が利用している外部サービスの仕様

などをクライアントが意識しなくてもよいようにする。

• クライアント同士で調停しなくてもいいようにする。

• 共有リソースの操作はサービス側で適切に排他して行う。

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

nginx の例だと…

• 「APの切り離し」や「ロードバランサの更新」などが

公開 API になる。

• API を提供するエージェントは Virtual IP などを使って

真の IP アドレスを隠蔽しておく。

• オペレーションの並列度を制御するために、queue + worker

方式で nginx に対するオペレーションを行う。

• 並列度の制御方法はいろいろあるので、別の方法でもいい。

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

こんな感じ

nginx

nginx

Operation 1

Operation2

nginxoperatorservice

公開インターフェイスでオペレーションを依頼

queue worker

なんかいい感じにやる

Virtual IP でサービスを提供

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

まとめ

ssh に頼らず

インターフェイスでオペレーションしよう!!