インフラ設計時に気をつけていること（基本編）

古木です。

この記事は[iRidge Advent Calendar 2019](https://qiita.com/advent-calendar/2019/iridge) 22日目の記事です。

今まで、AWSでのインフラ設計・構築をやってきましたが、ある程度パターン化されてきておりサービス運営を考えた際に、インフラ設計の基本に立ち返って必ず意識する点を初心に返ってお話したいと思います。

## 設計時に意識している指標

RASIS というシステム評価指標があります。
5つの項目（信頼性（Reliability）、可用性（Availability）、保守性（Serviceability）、完全性（Integrity）、機密性（Security））の頭文字を取っています。
2008年に発売された[サーバー/インフラを支える技術](https://www.amazon.co.jp/dp/B07JHRVXGT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)という私の好きな本でも、この辺りの概念が記載されており（ただし、RASISという用語は出てきません）、サーバー/インフラでの用語から、今は広義に解釈されるようになってきている印象があります（個人的な意見ですが）。

## 各指標を達成するために意識している一例

### `1.信頼性（Reliability）`
　障害のおきにくさ
　指標：平均故障間隔　Mean Time Between Failures=MTBF　が使われる

##### A. 事前把握などが可能な障害監視
- 通常の監視に加えてAWSだと料金やメンテナンス情報などの外部要因も監視した方が良いです。

##### B. CI/CD（Continuous Delivery）を意識した構築
- （障害は、リリース作業時に起きる確率が高いという統計をどこかで読んだことがあります。）継続的なインテグレーションや人に依存しない継続的なデリバリーが必要です。

##### C. テスト計画およびテスト手法
- 単一の自動テストでプログラムバグは防げても、仕様バグやサービス障害を防げないケースがあります。
- 私の会社ではアプリ開発を主としてますので、アプリからの自動テストおよび内部結合テスト・外部結合テスト・受入テストなどその時の改修ボリュームなどに応じて、スケジュールを勘案し、実施していく必要があります。

##### D. 本番同等環境でのテスト（環境に対する設計）
- 開発環境などデータ状態が本番を想定できていないとテストをして問題ないけど、本番で起きちゃいましたが発生します。事前に本番同等環境を用意するなどの計画を立て、実施する必要があります。

### `2.可用性（Availability）` 
　サービスの止まりにくさ
　指標： 稼働率　MTBF ÷ (MTBF + MTTR)

##### A. 単一障害点（single point of failure、SPOF）をなくすように設計
- AWSを使う上で、単一障害点は発生しにくいですが、漏れやすい部分でいうと、
    - アベイラビリティーゾーンがちゃんと分かれているか
    - バッチ処理や外部連携処理などでリカバリ・リトライが可能（冪等性を意識している）かなどがあると思います。
    
##### B. 負荷に耐えられる設計
- 負荷対策は深い話になるので、今回は割愛しますが、サイジングに基づく負荷試験の実施やAutoScalingなど拡張性を持たせた設計が必要になります。

### `3.保守性（Serviceability）` 
　障害復旧のしやすさ
　指標：平均修理時間　Mean Time To Repair、MTTR　が使われる
　
##### A. コーディング規約やコメントルールや開発設計手法などが周知されている
- 同じプロジェクトでも、箇所によってコードの書きっぷりが全く異なることがあります。
- 一人での対応には限界があるので、チームでサポートもしくは引き継げる状況を作っておくことも大事だと思います。

##### B. 障害対応におけるフローや既知のものなどが共有、周知されているか
- プロジェクトをまたいで、過去にあった障害などがドキュメント化され共有されていると気がつきやすいです。障害時対応には一時対応や恒久対応などありますので復旧を優先すべきかの判断をしてから対応を心がけるなども必要になってくると思います。

##### C. エラーログの設計
- 共通のフォーマットになっていたり、見やすい内容になっているだけで障害調査の対応は格段に早くなります。いつ、どこで、誰に対して、どういったことが起こっているのかがわかることが重要です。
- だいたいこの辺りの整備はあと回しになりがちですが、はじめに共通functionを通してもらうなどのルールを作ってしまった方が後々、キレイにいきます。

### `4.完全性（Integrity）` 
　データの保証および一貫性

##### A. サービスのニーズを把握する
- 一貫性というとRDBMSを私は想像してしまいますが、サービスによって一貫性の捉え方も変わってくると思います。atomic なトランザクション管理をしないといけないケースと、トランザクションが途中で失敗した場合でも、イニシャルから再処理することで一貫性が保てるケースもあるかと思いますので、その考慮が必要です。

##### B. 排他制御を意識する
- トランザクション管理は意識できても、排他制御が漏れるケースがあります。特に座席予約やポイント付与などがそれにあたるかと思います。データにロックをかけるもしくはメッセージングサービス（キュー）などを利用し、二重処理をしないように意識する必要があります。

##### C. テーブル設計はレビューしてもらう
- 後々、直しが効かない大事なところですので、設計コストをかけるべきです。また、誰かに見てもらうことで盲点に気がつく事が多いです。

### `5.機密性（Security）` 
　許可されたユーザーしか情報を閲覧出来ない、第三者に漏洩しない

##### A. 暗号化する、ハッシュ化する
- SSLなどの通信暗号化およびAPI通信時の認証フローなどが重要になってくると思います。OAuth2のように期限付きの認証アルゴリズムの検討および、暗号化やハッシュ化アルゴリズムに関しては単純に使うとそのアルゴリズムの脆弱性が露呈すると終わりますので、より機密性が求められるものは、独自情報を付加した方が良いです。

##### B. ログイン時の２段階認証やパズル認証などの検討
- 総当たりでパスワードが漏洩するケースもありますので、パズル認証や2段階認証は効果的です。

##### C. システム管理者や管理PCのデータ管理を徹底する
- 人的な漏洩もあるので、サーバーの操作履歴を取る、AWSでの操作履歴（AWS CloudTrailなど）を導入すると良いです。

## 設計時によくあるライトなやり取り
この辺りも指標などに照らし合わせながら、ちゃんと考えていきたいところ

- `1.信頼性（Reliability）: 障害を減らして欲しい`
    - （回答）クロスチェックします。
- `2.可用性（Availability）: 性能面は大丈夫？`
    - （回答）AWSですぐに拡張出来るんで大丈夫です。
- `3.保守性（Serviceability）: 対応が遅いんだけど?`
    - （回答）すぐ反応出来るように待機します。 
- `4.完全性（Integrity）: ...`
    - （回答）（聞かれないので説明しない・考えない）
- `5.機密性（Security）: セキュリティは大丈夫？`
    - （回答）AWSを使っているので大丈夫です。

## 参考記事
・[Wikipedia - RASIS -](https://ja.wikipedia.org/wiki/RASIS)
・[業務でWebサービス開発をする際に気をつけたいこと（新卒向け） - Qiita](https://qiita.com/zaru/items/71900d0e4b2afaaa955b)