k8s と bosh で運用者はどっちが楽なのか
SRE として 2年間ほど働いていると、「あー、運用楽になんないかなー」と常日頃から思うようになります。
一般的な運用の流れ
DevOps の世界では、リリース・運用について、いくつかのステージに分けられます。 参考:Defining Day-2 Operations - DZone Agile
最初に DevOps のイメージを掴むため、一般的な流れを記述します。
Day 0 (運用以前。が、統一された定義はなさそう)
- 要件定義
- 設計
- 実装
- QA、テスト
Day 1 (プロダクトが稼働する日。開発陣はこのあと打ち上げすることが多い)
- インストール
- セットアップ
- 初期設定
Day 2 (運用者のつらみの始まり。賽は投げられた) - Day N
- 監視
- メンテナンス
- トラブルシュート
- パッチのリリース
bosh が解決する Day X の課題
bosh の説明については ozzozz さんの BOSH 101 winter 2018 - Speaker Deck に委ねるとして、僕自身は SRE するなら、bosh (のようなシステム) がないと、運用したくないよ と思えるほど、bosh は優秀です。
Day 1 について
bosh は bosh-release という形でプロダクトを開発することにより、bosh director が作成した VM にプロダクトをデプロイすることが可能です。
$ bosh generate-package my-bosh-release
# from : https://bosh.io/docs/create-release/
$ tree .
.
├── blobs
│ ├── libyaml_0.1.4
│ │ └── yaml-0.1.4.tar.gz
│ └── ruby_1.9.3
│ ├── bundler-1.2.1.gem
│ ├── ruby-1.9.3-p484.tar.gz
│ └── rubygems-1.8.24.tgz
├── config
│ ├── blobs.yml
│ └── final.yml
├── jobs
│ ├── bg_worker
│ │ ├── monit
│ │ └── ...
│
├── packages
│ ├── ardo_app
│ │ ├── packaging
│ └── ...
└── src
└── ardo_app
├── Gemfile
├── Gemfile.lock
├── app.rb
...
で release を作成し、その中に、blob あるいは src という形で job のもととなるパッケージやソースコードを追加します。 (blob はその名のとおり、バイナリや tgz などを release に追加するのですが、実態としては、s3 のオブジェクトストレージにアップロードし、そのシグネチャだけ release では管理します)
また、spec を定義することで、どのような設定を行うかを deployment という形で与えることができます。
イメージ的には、teraform と ansible があわさった感じでしょうか。
Day 2 (監視, メンテナンス)
bosh は VM のオーケストレーションツールであり、bosh を経由してデプロイされた VM には bosh-agent が稼働します。
bosh-agent は Monit を利用しており、開発者が作成した bosh-release の monit の定義をもとに、job のプロセス監視を行ってくれます。 そして、
これにより、プロセスに異常があった場合に勝手にプロセスを再起動をすることが可能です。
また、VM 自体の CPU, MEM, ディスク がどれほど使われているかを cloudfoundry/gosigar を経由して取得しています。
bosh-agent からの health 情報を director 内の bosh-monitor (BOSH のドキュメントでは HealthMonitor) が受け取り、VM を再起動したりします。
参考:
- Monitoring - Cloud Foundry BOSH
- Process Monitoring with Monit - Cloud Foundry BOSH
- Components of BOSH - Cloud Foundry BOSH
Day 2 (トラブルシュート)
bosh の強力な仕組みの1つとして、bosh release としてデプロイされたものは VM 上で勝手に log rotation の設定をしてくれ、さらに
bosh logs
コマンドで VM 単位、さらに job 単位でログを取得できます。これはかなり強力で、どこかのコンポーネントで問題があったときに、そのコンポーネントのログをまとめて取得するなど、統一的なログの閲覧が可能になります。
teraform と ansible で個別に作られた VM のログを閲覧するとなると、だいたい /var/log 以下にログが落ちているとはいえ、それを作るのは開発者に委ねられているため、あるコンポーネントは /usr/local/component/log に吐いている可能性があります。そのログを見つけるのに苦労したことがあるオペレーターもいるのではないでしょうか?
さらに、syslog addon という形で、bosh vm に syslog forwarder という job を追加することで、bosh-agent から syslog.go 経由でログを転送することが可能です。
外部に設置した syslog サーバから、Splunk や ElasticSearch にログを転送することで、オペレーターは簡単にログの閲覧と調査が行なえます。僕の持論ですが、オペレーターで最も重要なものは時間短縮です。ログを見るというだけに時間をかけていては意味がありません。
bosh-release という形である程度、プロダクトに制約をもたせることで、こういった恩恵が受けられるのは示唆に富みますね。
参考:
Day 2 (パッチのリリース)
bosh-release の仕組みになりますが、
bosh create-release
を実行すると、bosh-release 内の final ファイルが更新され、バージョンがインクリメントされます。これを director が読み込むことにより下記のように
# from : https://bosh.io/docs/cli-v2/#release-mgmt
Using environment '192.168.56.6' as client 'admin'
Name Version Commit Hash
capi 1.21.0* 716aa812
cf-mysql 34* e0508b5
cf-smoke-tests 11* a6dad6e
cflinuxfs2-rootfs 1.52.0* 4827ef51+
consul 155* 22515a98+
...
と release のバージョンを確認しながら、オペレーションが行えます。ちょうど、最近 ソフトバンクの通信障害、エリクソン製交換機が原因と公表–海外11カ国でも同様の障害 - CNET Japan の事故がありましたが、ソフトウェアをロールバックして復旧を行ったそうです。
bosh も deployment でバージョンを指定すれば、アップデートもロールバックも簡単に行なえます。
k8s が解決する Day X の課題
さて、bosh のどのような機能が Day 2 - Day N 運用を簡単にしてくれるか説明しました。次に、k8s ではどのように運用が楽にできるのでしょうか?
Day 1 と Day 2 (パッチのリリース) について
k8s にも deployment があるが、これは bosh の deployment とは粒度が異なる。
bosh の場合は、deployment で複数の bosh-release を同梱するのに対し、k8s の deployment は Pod をどのような DockerImage で、どれほどデプロイするかなどを定義します。 Pod の単位でスケールやロールバックなどを行うことができるのですが、Pod の集まりを定義するベストプラクティスはいまも議論されているようです。
Helm を使うことで bosh-release と同じようにデプロイを行うことができ、実際、bosh-release として提供されていた Concourse も charts/stable/concourse が作られていたりします。
Day 2 (監視とメンテナンス)
Monitor Node Health - Kubernetes にあるように
Currently Kubernetes won’t take any action on the node conditions and events generated by node problem detector
k8s では node の健全性について、まだ何も行ったりはしません。つまり、CPU, MEM がしきい値をこえたらアラートを出したり、node を再起動するような bosh ができる機能を提供できていません。
しかし、kubernetes/node-problem-detector が開発中であり、将来的には node の健全性のチェックと自動でプロセスを再起動するような仕組みも検討されているようです。
Day 2 (トラブルシュート)
ログやメトリクスについてはどうでしょうか?
- Logging Architecture - Kubernetes
- Debug Pods and ReplicationControllers - Kubernetes に記載されているようにログについては、
kubectl exec cassandra -- cat /var/log/cassandra/system.log
とデプロイしているものに応じて、ログの場所を選択して閲覧する形となります。 (問題が起こる前にオペレーターはログの場所を把握しているはずなので、パスがわからないというような問題にはならないとは思いますが)
そして、それを forwarding する仕組みとしては、
While Kubernetes does not provide a native solution for cluster-level logging, there are several common approaches you can consider.
k8s として提供されている方法はないものの、node-level logging を利用するのが一般的です。
node-level logging では、Pod (Application Container) のログを node (多くの場合 VM) で収集して、それを転送するという形を取ります。 つまり、その設定や forwarding agent (fluentd など) を k8s のオペレーターは気にする必要があるということになります。
メトリクスも同様で、Core metrics pipeline - Kubernetes の metrics server をデプロイするが推奨されてはいるものの、Metrics Server API はまだ alpha とされており、
The API is in alpha and there is a plan to graduate it to beta (and later to GA), but it’s out of the scope of this document.
k8s としてサポートしているわけではなさそうです。
参考:
Day 2 の補足
もちろん、k8s は un-opinionated な PF であり、作り込みをすればそういった機能を追加できます。そこが k8s の良いところです。
しかし、自分の職場を見ていても思うのですが、作り込んだ PF は OSS のアップデートに伴い、自分たちでアップデート対応する必要があり、そこでバグが生まれる可能性もあります。 Day 2 を楽にするはずが、加えたアラートやロギングの機能の保守でいっぱいいっぱいでは意味がありません。
僕のチームでは、bosh から受け取った大量のログやメトリクスを Prometheus や Splunk などに転送していますが、こうしたプラットフォーム自体の安定性が保たれないと、Day 2 もままなりません。 -> マイクロサービスの運用について考えたこと – Think Abstract そのため、k8s 上のアプリケーションを運用するというだけで、ロギングやメトリクスのエージェントについて工夫しないといけないのは、やや大変そうに見えます。
結論
SRE エンジニアとして、Day 2 で何をするのかという点を見ていると、k8s はまだ PF として追加してほしいことが標準サポートされていない印象があります。
bosh はその点では先に行っている感じがしますが、bosh-release というフォーマットがもっと普及しない限りは、「ああ、CF のやつらが使っているやつね」程度で終わってしまいます。
僕としては k8s の標準として Day 2 のための機能追加 (Addon という形でも)、あるいは、bosh と bosh-release の普及を期待したいところです。現状では SRE として見るべき点が少ないというので bosh のほうが運用が楽そうだなと思いました(それに伴う学習コストはあるにせよ)
Cloud Foundry Advent Calendar 2018 - Qiita の記事です。Happy Christmas!