kakakakakku blog

Weekly Tech Blog: Keep on Learning!

SRE Tech Talks #2 に参加してサービス運用の事例を聞いてきた

先週 SRE Tech Talks #2 に参加してきた.僕も仕事ではウェブオペレーションをメインで担当しているけど,他社の事例を聞くのは刺激になるし,まだまだできてないことが多くあるなと感じた.特に「オペレーションの効率化をソフトウェアエンジニアリングで実現する」という価値観が凄い良い表現で刺さった.

eventdots.jp

On-call Engineering @cubicdaiya

  • SRE のミッション
    • Operation(サービスの信頼性を向上させる)
    • Software Engineering(サービスをスケールさせるためのツールなどを開発する)
  • On-call
    • SRE でローテーションしている
    • 1週間毎に交代する
    • SRE 全員が電車通勤中であることを避けるために On-call 担当は自宅待機して時差出勤する
    • On-call 当番の負担は大きい
      • 精神的なプレッシャー
      • 同居人への負担
      • 深夜問わず
    • 振休や手当を支給している
    • Slack Bot を活用して PagerDuty 経由で電話をかけられるようにしている
    • Slack がダウンしている場合も考慮して Wiki にも電話番号をまとめている

質疑応答が大量に出てて,1番盛り上がっていた.「オンコール」という誰しも興味のあるテーマだったのも良かったんだと思う.

「オンコール」の運用としては,非常に徹底した運用をしているなと感じた.特に意図的に時差出勤をしているという話は今まで聞いたことがなかった.Slack と PagerDuty を活用してオンコールを自動化してるのは素晴らしくて,真似したいところ.質疑応答にもあったけど,各 SRE が全ての機能を把握できるわけではないため,困ったら他のメンバーに連絡して助けてもらうこともあるし,障害対応後にはドキュメントを整理して振り返ることができるようにしているとのことだった.

speakerdeck.com

cybozu.com のデータバックアップとリストア、それを活用したリハーサル @toshi_pp

  • サイボウズのアーキテクチャ
    • マルチテナント
    • マルチアプリケーション
    • マルチバックエンド
  • ミドルウェアに依存しないようにディスクを増分バックアップして管理している
  • アップデートのリハーサル
    • 実際にバックアップが必要になることが少なくてもリハーサルをする
    • 全ては安心のため

発表を聞いていたら「独自の…」「カスタマイズした…」といった部分が多くあるらしく,運用が大変そうだなぁと客観的に感じた.復旧手順をリハーサルするのは素晴らしいと思ったし,昔 SIer で働いていたときに様々なリハーサルをしたことを思い出した.特にディザスタリカバリ系のリハーサルは「本当に起きるのかねぇ」と半信半疑だったけど,正常にフェールオーバーできたり,リストアできることの安心感は重要だと思う.まさに数日前に GitLab の障害があって,バックアップ&リストアを見直した人も多そう.

www.slideshare.net

cookpad.com 全 HTTPS 化の軌跡 @kani_b

  • インフラストラクチャー部
    • SRE グループ
    • 社内 IT インフラグループ
    • データ基盤グループ
    • セキュリティグループ
  • 今までは http と https の混在環境
  • なぜ HTTPS 化したのか
    • セキュリティ
      • 保護できるならする
    • プラットフォーム
      • ATS (iOS)
      • 検索エンジンも HTTPS を優遇する
    • 新技術
      • HTTP/2
      • ServiceWorker
  • パフォーマンス
    • TLS Handshake と暗号化のオーバーヘッドは確実に存在する
    • ただ回線の高速化で体感できるほどの差ではない
  • 検索エンジン
    • 信じるしか無い
  • Mixed Content をひたすらに消していく
  • 全社にアナウンスをした
    • 何かあったらすぐにアラートしてくれる

「レシピサイトに暗号化が必要なのか?」という話は深かった.ユーザーがもしかしたら「閲覧したことを知られたくないかもしれない」なんて考えたことも無かったし.Windows XP も公式にサポートする姿も素晴らしかった.プラットフォームとして大きく成長して,ユーザーを第一に考えていることの証だなぁーと.

speakerdeck.com

SREグループができてこの半年間やってきたこと @isaoshimizu

  • XFLAG(主にモンストを運用している)
  • SRE はウェブオペレーション,デプロイ,モニタリングなどを担当する
  • オンコール当番は11名で2人ごとにローテーションしている
  • 年末年始の対策をした
  • innodb_io_capacity
    • レプリケーション遅延を緩和できるように
  • innodb_spin_wait_delay
    • os_waits を減らせた
  • Transparent HugePages 問題
    • OFF にすると良い

MySQL をカリカリにチューニングしている話で勉強になった.約1300台のサーバを管理しているって…モンストの規模大きいなぁ…!

speakerdeck.com

Arukasの運用事例と、末永くインフラ運用していくためのTips @uzyexe

  • “Hope is not a strategy”
  • 見積もっていた10倍の速度でサービスが成長しているため,運用が追い付かない
  • オンコールは PagerDuty を使っている
  • プロビジョニングは Chef や Ansible を使わずに Terraform for Sacloud + CoreOS + Cloud-Config を使っている
  • Mesos + Marathon でリソースの制御をしている
  • 99.999 %
    • 可用性における5番目の “9” はヒューマンエラー

最近知ったんだけど Arukas って逆から読むと Sakura なんだよなー!気付いたときは驚いた.見積もった10倍で成長してしまうのは厳しい気もするけど,最終的にはビジネス的に招待予約制を導入して,成長を抑える判断になっているのは,サービスの信頼性の観点でも良いと思った.Mesos + Marathon の話は知識がなくてよく理解できなかった.

www.slideshare.net

関連記事

タイミング良く無料公開となった SRE 本!まだ読めてないけど,必ず読もうと思う.SRE 本の輪読会やってる会社もあるらしく,良いなぁ!

MySQL on EC2 → Aurora にレプリケーションをしてみた

既にサービスで稼働している MySQL on EC2 を Aurora に移行するために,以下のようなレプリケーション環境を検証用に構築して試した.Percona Xtrabackup でリストアをすると高速にできるらしいけど,今回は環境の制約もあって mysqldump 経由でリストアをする設計を選んだ.

f:id:kakku22:20170203185237j:plain

レプリケーション環境を構築する手順は以下のドキュメントに詳しくまとまっていた.

バイナリログを出力する

今回は dbs on EC2 → Aurora Writer にレプリケーションをするため,スレーブ環境でもバイナリログを出力しておく必要があった.詳細は割愛するが /etc/my.cnflog-bin を追記して対応した.

mysqldump に --master-data=2 オプションを追加した

mysqldump で取得したバックアップをベースラインとしてレプリケーションをする場合に CHANGE MASTER TO で合わせるポジションを把握する必要がある.そのためには mysqldump に --master-data オプションが必要で,今回は CHANGE MASTER TO をコメント状態で出力するために --master-data=2 とした.--master-data のまま出力してしまうとリストア時に CHANGE MASTER TO も流れてしまうため --master-data=2 にしておくと良い.

-- Position to start replication or point-in-time recovery from
--

-- CHANGE MASTER TO MASTER_LOG_FILE='bin.000001', MASTER_LOG_POS=12345;

Aurora Writer でレプリケーションを開始するときに CHANGE MASTER TO は使えない

出力したバックアップを Aurora にリストアしたら,次はポジションを合わせてレプリケーションを開始する.ただし RDS では CHANGE MASTER TOSTART SLAVE が実行できないようになっていて,実行しようとすると,権限のエラーが出る.

mysql> CHANGE MASTER TO MASTER_HOST='xxx',
    -> MASTER_USER='replication',
    -> MASTER_PASSWORD='password',
    -> MASTER_LOG_FILE='bin.000001',
    -> MASTER_LOG_POS=12345;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation

mysql> START SLAVE;
ERROR 1045 (28000): Access denied for user 'xxx'@'%' (using password: YES)

どうするかと言うと,RDS 側に登録されているストアドプロシージャを使う必要がある.

実際に発行するコマンドとしては以下のようになる.ストアドプロシージャに与える値は CHANGE MASTER TO と同じなので,特に困ることは無いかと思う.ただ1点,ホスト名に Private IP を指定する必要があった.今の構成だと EC2 に hosts を配ってるため,ホスト名で参照できていたが,Aurora から見ると参照できなかった.

mysql> CALL mysql.rds_set_external_master ('1.2.3.4', 3306, 'replication', 'password', 'bin.000001', 12345, 0);
mysql> CALL mysql.rds_start_replication;
mysql> SHOW SLAVE STATUS\G

あとは Read_Master_Log_Pos あたりの値を見ながらモニタリングすれば大丈夫かと.ちなみに,レプリケーションを停止するときは,以下のストアドプロシージャを実行する.

Aurora Writer の Seconds_Behind_Master は CloudWatch で見れなかった

dbs on EC2 → Aurora Writer のレプリ遅延をモニタリングしたかったけど,CloudWatch では難しそうだった.Aurora では「Aurora バイナリログレプリカの遅延 : AuroraBinlogReplicaLag」メトリクスがあるけど,これは Aurora Writer → Aurora Reader のレプリ遅延のことで,Aurora Writer のメトリクスではなかった.よって,取り急ぎ Aurora Writer で SHOW SLAVE STATUS; を実行して,Seconds_Behind_Master の値を確認するようにしている.

CloudWatch で取得してるメトリクスに関しては,以下のドキュメントに詳しく載っている.

docs.aws.amazon.com

まとめ

稼働中の MySQL on EC2 を Aurora にレプリケーションする構成を簡単に構築できた.レプリケーションの階層は多いけど,特に気になるレプリ遅延は無かった.引き続き検証を続けていく!

Aurora のパラメータグループで max_connections の値が計算値と合わない

最近 Aurora の検証をしているので,今後は Aurora 関連の記事を書く機会が増えそう.

前提

  • RDS (Aurora MySQL)
  • インスタンスタイプ : db.t2.medium

DBInstanceClassMemory とは

RDS のパラメータグループでは,特定の変数と演算子を使った動的な値設定ができる.今回は変数 DBInstanceClassMemory に関して調べたことと,計算が合わずに困ったことを書いておこうと思う.

DBInstanceClassMemory は,名前だけを見るとインスタンスタイプごとに搭載されたメモリサイズのように思えるけど,実際には違っていて,RDS プロセスに割り当てられたメモリサイズのことを意味する.よって,搭載されたメモリサイズよりは確実に小さい値となる.その点はドキュメントにも書いてある.

DBInstanceClassMemory
現在の DB インスタンスに関連付けられている DB インスタンスクラスに割り当てられたメモリのバイト数を返します。このメモリは、インスタンスを管理する Amazon RDS プロセスによって使用されるメモリよりも小さくなります。 docs.aws.amazon.com

DBInstanceClassMemory を参照しているパラメータ

デフォルトのパラメータグループ "default.aurora5.6" で,以下の4パラメータが DBInstanceClassMemory を参照している.特に innodb_buffer_pool_sizemax_connections などは,ワークロードに応じてチューニングが必要なので,Aurora クラスタのデフォルト値を理解しておくことは重要だと考えている.

  • innodb_buffer_pool_size
  • max_connections
  • query_cache_size
  • thread_cache_size

f:id:kakku22:20170202172100j:plain

逆算して DBInstanceClassMemory を知る

まず,デフォルトのパラメータグループのまま起動したクラスターの Aurora Writer で,上記のパラメータの値を確認してみた.

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 1610612736 |
+-------------------------+------------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 90    |
+-----------------+-------+
1 row in set (0.01 sec)

mysql> SHOW VARIABLES LIKE 'query_cache_size';
+------------------+----------+
| Variable_name    | Value    |
+------------------+----------+
| query_cache_size | 89498624 |
+------------------+----------+
1 row in set (0.01 sec)

mysql> SHOW VARIABLES LIKE 'thread_cache_size';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| thread_cache_size | 2     |
+-------------------+-------+
1 row in set (0.00 sec)

まず最初に innodb_buffer_pool_size の値から逆算して DBInstanceClassMemory を調べてみた.db.t2.medium のメモリサイズは 4GB なので,以下の式に当てはめて逆算すると,DBInstanceClassMemory は 2GB だとわかった.よって db.t2.medium においては,メモリサイズの 50% が DBInstanceClassMemory に割り当てられていることがわかった.

innodb_buffer_pool_size = {DBInstanceClassMemory*3/4} = 2147483648 * 3 / 4 = 1610612736

ちなみに,この割合は固定値ではなく,インスタンスタイプが良くなればなるほど,上がっていく.以下の記事を見ると,最高スペックの db.r3.8xlarge だと 96.4% が DBInstanceClassMemory に割り当たっていることがわかる.

query_cache_sizethread_cache_size も同様に逆算する

同様に query_cache_sizethread_cache_size も値から逆算すると,DBInstanceClassMemory は 2GB だとわかった.よって,db.t2.medium だと DBInstanceClassMemory は 2GB だとほぼ断定できそう.

query_cache_size = {DBInstanceClassMemory/24} = 2147483648 / 24 = 89478485.3333333
thread_cache_size = {DBInstanceClassMemory/1005785088} = 2147483648 / 1005785088 = 2.135131723

あれれ max_connections の計算が合わないぞ?

やっと今回の本題に入る.max_connections の式は以下のようになっていて,GREATEST 関数に含まれてる値の中で,一番大きい値が割り当たるようになっている.

GREATEST({log(DBInstanceClassMemory/1073741824)*45},{log(DBInstanceClassMemory/8187281408)*1000})

よって DBInstanceClassMemory を 2GB だとすると,以下の計算となり,値は 45 だと推測できる.

{log(DBInstanceClassMemory/1073741824)*45} = log(2147483648/1073741824) * 45 = 45
{log(DBInstanceClassMemory/8187281408)*1000} = log(2147483648/8187281408) * 1000 = -1930

でも実際には 90 だった.計算が合わない.

mysql> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 90    |
+-----------------+-------+
1 row in set (0.01 sec)

デフォルトの式で max_connections を 90 にするには DBInstanceClassMemory が 4GB である必要があって,そうすると db.t2.medium に搭載されたメモリサイズと一致してしまう.となると,パラメータによって DBInstanceClassMemory の値が違う?そんなはずは無いだろう.うーん謎だ.

{log(DBInstanceClassMemory/1073741824)*45} = log(4294967296/1073741824) * 45 = 90

AWS サポートに問い合わせた

AWS サポートに問い合わせたところ,原因が判明した.

  • まず db.t2.mediumDBInstanceClassMemory は 2GB ではなく 2.0004 GB "程度" であること
    • innodb_buffer_pool_size の値から逆算すると気付けなかった
  • 2.0004 GB の前提で log 計算をすると log(2147913144.7296/1073741824) = 1.00028 となる
  • 1.00028 を 2.0 に "切り上げ" てから 45 を乗算するため 2 * 45 = 90 となる

結論として,ドキュメントに書かれていないロジックになっていて,逆算することは難しかった.今後 max_connections の計算式をもっと簡単にする予定があるらしく,今後に期待!(まぁ実際の運用を考えると max_connections をデフォルト値で運用することは無さそうなんだけど...)

Black Belt

www.slideshare.net

golang.tokyo #3 に参加してパフォーマンスの話を聞いてきた

先週 golang.tokyo #3 に参加した.抽選倍率2倍だったからダメかもなぁ…!と思って申し込んだら当たった.

テーマは「パフォーマンスチューニング」だったけど,「パフォーマンスチューニング」とは違うような話もあった.エウレカの話も聞きたかったから残念!

golangtokyo.connpass.com

Accelerating real applications in Go @cubicdaiya

  • GitHub - kazeburo/chocon
    • Golang 標準の net/http で簡単にプロキシサーバを立てられる
    • ただ細かくパラメータをチューニングするためには net/http/client.gonet/http/transport.go を使う
    • 特に MaxIdleConnsPerHost はデフォルト値 2 だから小さくなっている
  • GitHub - mercari/gaurun: General push notification server in Go
    • goroutine 数やチャネルのサイズをメトリクスとして取得できるようにしている
    • モニタリングできるようにしている

メルカリのプロダクション環境に導入されているソフトウェアの話で非常に深かった.パパあるあるだと思うけど「チョコン」って聞くと「コッシーの友達のチョコン」のことを考えてしまうので,発表中に変にニヤニヤしてしまった…w

PERFORMANCE OPTIMIZATIONS / Carlo Alberto Ferraris

  • サーバ費用より人を雇う方がコストが高い
  • オプティマイズするよりスケールアウトした方が良い
  • The Twelve-Factor App
  • 失敗する前提で考える

Golang の話ではなく,サービス開発の思想的な話だった.途中から Golang の話しになるのかなぁーと思って聞いてたらそのまま終わった.話は凄く面白かった.

Stream の扱い方 / jun06t

  • ioutil.ReadAll で全て []byte に変換するとメモリを食ってしまう
  • io.Readerio.Writer を引数としている場合は Stream のまま使うと良い
  • API リクエストを decode する場合 json.Unmarshal でなく json.NewDecoder を使うと高速になる

1番テーマに沿ってる気がした.実際に同じようなコードを書くときがあったら気を付けたい.今回 Slides ってサービスが多かったけど,人気なのかな?あまり見たことがなかった.

git-schemlex と ddl-maker を使った DB migration の紹介 @Konboi

タイミング良くマイグレーションツールの調査をしていたので参考になった.Golang 製だと Goose も人気かなと思うけど,既存スキーマに対してエクスポートができないという点に困ってて,うまく運用にハマる気がしてない.そうなると Ruby 製だけど GitHub - thuss/standalone-migrations: A gem to use Rails Database Migrations in non Rails projects かなぁ…と考えているところ.

speakerdeck.com

database/sql とコネクション / Talos208

  • database/sql を使う場合 db.Close() はするべきではない
  • 1度 Open したらそのままにして Open と Close のコストを下げることができる
  • ソースを追うとよくわかる
  • Golang 1.6 から入った SetConnMaxLifetime() で期限切れのコネクションを再利用しなくなった

www.slideshare.net

関連記事

既に参加者の記事が上がっていた!

kysnm.hatenablog.com

developers.cyberagent.co.jp

裏番組

mackerelio.connpass.com

実は裏番組で Mackerel Meetup #9 もあった.Mackerel 活用してるから参加したかったし,お世話になってる @ariarijp の LT も見たかったけど,golang.tokyo #3 を選んでしまった!たまたま抽選当たったから…w

ハッシュタグを見てたら「アノテーション機能」の話が流れてきて,あまりに待望の機能だったので,1人で興奮してた!

mackerel.io

次回の Mackerel Meetup は参加しまっす!

CloudWatch で ELB の「パーセンタイル統計」を可視化しよう

今日は CloudWatch の話を書こうと思う.既に活用してる人も多いと思うけど,2016年11月の新機能リリースで各種メトリクスの「パーセンタイル統計」を可視化できるようになった.

「パーセンタイル統計」は凄く重要で,平均値だけをモニタリングしていると気付きにくい異常値に気付くことができる.例えば,ELB の Latency をモニタリングしている場合に,リクエストの 1% が非常にパフォーマンスが悪いとしても,平均値で見ると値が丸まってしまって,通常より少し遅い程度にしか見えないという場合がある.そんなときに「パーセンタイル統計」を活用できる.

まだ全ての ELB に反映されていない

以下の記事を読むと,newly created ELB and ALB と書かれていて,新機能リリース以降に作成した ELB と ALB にしか対応していないように読み取れた.

Percentiles are supported for EC2, RDS, and Kinesis as well as for newly created Elastic Load Balancers and Application Load Balancers.

また別の記事を読むと,既に運用している ELB と ALB は will be available in the coming weeks であると書いてあった.ただし,数週間待っても反映されず,年を越してしまった.

Percentile metrics are available today for all new Application Load Balancers and can be accessed from the CloudWatch console, SDK and API. Support for existing Application Load Balancers and all Classic Load Balancers will be available in the coming weeks.

今週やっと ELB で「パーセンタイル統計」を可視化できるようになった

実は「パーセンタイル統計」が反映されたらすぐに気付けるように,以前から CloudWatch Dashboard にグラフを追加していたので,1/24 に「あ!反映された!」とすぐに気付くことができた(笑)

既に反映された ELB もあるし,まだ反映されてない ELB もある.リソースを作成した時期にもよりそう.

以下の例では,3種類の「パーセンタイル統計」を可視化している.特に p99 の値を見ると,異常値が検出できていることがわかる.

  • Latency p99
  • Latency p95
  • Latency p90

f:id:kakku22:20170127194516j:plain

グラフを作る Tips

ちなみに,グラフを作るときに「メトリクス追加」のようなボタンが無くて,どうやったら複数の「パーセンタイル統計」を表示できるのか全然わからなかった.適当にポチポチしてたら,右側にコピーアイコンがあることに気付いたけど,これは気付かないでしょう!ということで Tips も載せておく.

f:id:kakku22:20170127195918j:plain

まとめ

既に「パーセンタイル統計」が反映されている ELB と ALB も多そうなので,CloudWatch Dashboard で可視化しておくと,異常値に気付くことができて便利!

最近は Grafana が最高すぎるから,CloudWatch のダッシュボードも Grafana に移行しようと思ってる.

kakakakakku.hatenablog.com