なんかかきたい

プログラミングなどの個人的なメモやサークル「ゆきいろパラソル」の情報を載せてます

AWSでAZ障害が起きたので困ったことを書いておく

前にも似たようなこと書いたなと思ったけどもう一年半も前のことになるのか

t-cyrill.hatenablog.jp

ご存知の通り昨日 2021/02/19 23:20頃 AWSにて東京リージョンの一つ apne-az1 にて大規模な障害が発生。多くのAWSを利用していたサービスで影響があった。

そんな私はいつものように アラストリリィ アサルトリリィ ラストバレット というゲームを呑気にプレイしていたのだけど、23:25 から緊急メンテに入ってしまった。

どうしたんだろうと思っていたら、社内SlackにてAWSを利用しているサービスがたまに応答しなくなる、Elasticacheが切り替わったなどなどの報告が入り、もしかすると面倒ごとかなと思いながら対応することになった。

起きていたこと

既にAWSからも公開されていることであるが、今回は2019年8月に起きた障害と類似するタイプの障害だった。 東京のAZの一つ、apne-az1 にてサーバ冷却装置の電力供給にトラブルがあり、EC2の機能が縮退したというもので、影響を受けたのはEC2とEC2に乗っている多くのサービスであった。 前回、ブログにてAZ障害が起きた場合のことについて呑気に書いていたが、今回の対応ではこのタイプのAZ障害では困ったことが起きることがわかった。

一番困ったのは、EC2が縮退しているのに、アラートが上がってこないことだった。 AWSで構築しているサービスはEC2やEC2を使って組まれたサービスに乗っているものが多く、例えば最近だとECSをFargateで動かして、ALBを使ってサービス提供する、みたいな構成をとっている。

Fargateは自動的にサービスを起動する仕組みを持っていたり、ALBもマネージドなロードバランサーでよしなに動いてくれると思っていたが、今回のトラブルではAWS側の仕組みではうまく切り離しができていなかったように思える。要はAZは死んでいるにも関わらず、サービスとしてはまだ「生きている」判定がされており、切り離しがうまくいっていないような動作をしていた。

これは大変困った。普段利用しているCloudwatchなどでは死んだサーバやサービスが判別ができず、ALBについては自分たちの管理下ではないので、死んだALBに当たることを避けるのは容易ではなかった。

仕方がないので、 apne-az1 に属しているすべてのEC2ベースで動いている、と思われるサービスを使わないようにしていくしかなかった。 しかしこれは全くもって簡単ではなかった。というのはAZ障害の場合は当然綺麗に自動切り離しが行われる前提で設計をしていたので、今回みたいに自動的に切り離しができないことを想定していなかった。

これはTerraformやCloudFormationを使っていたとしても容易ではないと思う。切り離し方がサービスによってかなり違うので多くのリソースを使っているほどきり替えが難しかったはず。 ALBなどはSubnetを指定する設定があるし、Fargate は placement constraints を設定する必要があった。また、ENIなどもZoneに依存している。RDSはMaster昇格をする?それは大変だ。 もちろん一気にすべてのリソースがパタパタ切り替わったらそれはそれで困ったかもしれないが、死んでいるのか生きてるのか判別かつかないというのは相当参った。中途半端に生きているサービスを綺麗に切り替えるは相当難しい。

今回の反省

サービスは綺麗に死ぬとは限らないことを見落としていたこと

AWSで構築するときにはMulti-AZ構成を取っていたし、自動で切り替える仕組みも設定していたが、自動で切り替わらない場合にどう切り離すかまで考慮していなかった。 Terraformで構築は自動化していたが、AZの一つだけを切り離すにはどうすればよいか、俯瞰して見ていたわけでもなく、実際の切り離し作業にはかなり手間取ってしまった。 というより、AZの一つが死んだ場合にTerraformなどで隔離できるように書いておくというのはかなり難しい気がしている。 これはまだ考えていないが、多分今更書き直すのは難しい気がしている。最初から切り離せるように書いておかないと難しいが、そんなところまで考えてはなかったというのが正直なところだ。

マイクロサービス化を進める過程でアカウントを分割したことで対応が煩雑になった

これはそれはそうだろうという話だが、権限やコスト分割の観点からアカウント分割をしてきたことで、分割したアカウントの数だけ同じことをする羽目になってしまった。 アカウント単位で閉じない、広範囲のトラブルに対しては複数アカウントに分けたことで対応箇所がばらけてしまい、設定反映に手間取ることになった。 実際このようなケースを想定してすべてのアカウントに対してAZを切り替えられるように設定を書くのはかなり困難と思われるが、毎年起こるような問題であれば対応しなければならない。

終わりに

前回書いた記事でいうと「問題がおきたマシンの切り離しの仕組みがうまく動かない」ケースに該当して大変な目にあった。 こう一年半に一回くらいの確率で起きる問題だと、対処できるようにしておかないといけないし、今回の件を踏まえて自動切り離しとは別の観点で手動でAZ切り離しができるように仕組み化していく必要があるかもしれない。

今回AZ障害だからMultiAZだから影響がないっていうのは間違いで、中途半端に死んだ結果切り離しがうまく行かず、MultiAZ構成を取っていても影響が出てしまうというトラブルだったということだけ書いておきたい。

死ぬときは綺麗に死んでくれないってのは物理時代もスイッチやNICでよくあったし、こういうのが一番困るね。やれやれ

おまけ

プリンセス・プリンシパル Crown Handler 超良作だから観てね

pripri-anime.jp

MySQLの証明書をローテーションする方法を書いておく

前書き

MySQL certificate rotate とかでググってもよくわからなかったので書いた。 RDSの情報はあるが、ネットにはあまり書いてない話題かもしれない。

サマリー

  • 再起動またはMaster昇格が必要
  • 影響を最小限にするためクライアントの証明書を現Masterと新Masterの両方で使えるようにしておく
  • 全てのクライアントの証明書を切り替えた上でサーバの証明書を切り替える
続きを読む

Jenkins Configrations as Code と Groovy サンドボックス

サマリー

  • JenkinsにはGroovyを実行する機能があるが、任意のコードの実行を防ぐため、実行できるメソッドを制限する Groovy Sandbox という仕組みがある。
  • Groovy Sandbox を有効にするには、Authorize Project plugin で特定のユーザ権限で動作させる必要がある
    • cronのように自動起動するジョブは SYSTEM として実行され Sandbox で実行できないため
  • Sandboxで実行する場合、許可するメソッドを事前に設定しておき、意図しないメソッドの呼び出しに気付けるようにする運用になる
  • JCasC には Authorize Project plugin と Script Security Plugin の scriptApproval を設定する方法がない
  • とはいえ、この設定は一度設定したら変更することもないはずなので、Jenkins起動前に事前にXMLを入れておけばいいよという話

Authorize Project plugin

  • プロジェクトごとに特定のユーザの権限でジョブを実行させる設定ができるようになるプラグイン
    • QueueItemAuthenticator が追加され、各プロジェクトで実行ユーザの指定ができる
    • cronのように自動実行されるジョブは SYSTEM として実行される
    • SYSTEM で動くと Sandbox 実行されないが、このプラグインで実行ユーザを指定すると Sandbox の対象になる
    • Groovy SandBox を使う場合、このプラグインと組み合わせることが重要になる
  • このプラグインの設定を JCasC で行うことができない (今後対応されるかもしれないが)
    • 現状最も簡単な設定方法はJenkins起動前に JENKINS_HOME/jenkins.security.QueueItemAuthenticatorConfiguration.xml を作っておく方法
    • DockerイメージのJenkinsを使う場合も JENKINS_HOME は外部のボリュームをマウントすることが多いので、そちらのおいておくか、エントリーポイントのスクリプト内でコピーする

設定例

<?xml version='1.1' encoding='UTF-8'?>
<jenkins.security.QueueItemAuthenticatorConfiguration>
  <authenticators>
    <org.jenkinsci.plugins.authorizeproject.ProjectQueueItemAuthenticator plugin="authorize-project@1.3.0">
      <strategyEnabledMap>
        <entry>
          <string>org.jenkinsci.plugins.authorizeproject.strategy.SpecificUsersAuthorizationStrategy</string>
          <boolean>true</boolean>
        </entry>
        <entry>
          <string>org.jenkinsci.plugins.authorizeproject.strategy.TriggeringUsersAuthorizationStrategy</string>
          <boolean>false</boolean>
        </entry>
        <entry>
          <string>org.jenkinsci.plugins.authorizeproject.strategy.SystemAuthorizationStrategy</string>
          <boolean>false</boolean>
        </entry>
        <entry>
          <string>org.jenkinsci.plugins.authorizeproject.strategy.AnonymousAuthorizationStrategy</string>
          <boolean>false</boolean>
        </entry>
      </strategyEnabledMap>
    </org.jenkinsci.plugins.authorizeproject.ProjectQueueItemAuthenticator>
  </authenticators>
</jenkins.security.QueueItemAuthenticatorConfiguration>

Script Security Plugin

  • Jenkinsで実行されるGroovyスクリプトを任意実行できないように呼び出せるメソッドの制限ができるプラグイン
  • Job DSL plugin などでGroovyを実行する際にも適用されるため、このプラグインを入れている場合、Groovy Sandbox で実行する必要が出てくる
  • 許可するメソッドは scriptApproval のWebUI上で設定できるが、Administrator権限が必要。
    • Administrator権限を持っているとJenkinsを任意に操作できるため、scriptApprovalのためだけにAdministrator権限を与えたくないと思う
  • scriptApprovalは単なるXMLの設定であり、事前にどのメソッドの呼び出しを許すかわかっているのであれば、同じくJENKINS_HOMEにおいておけば良い。
<?xml version='1.1' encoding='UTF-8'?>
<scriptApproval plugin="script-security@1.66">
  <approvedScriptHashes/>
  <approvedSignatures>
    <string>staticField groovy.io.FileType DIRECTORIES</string>
  </approvedSignatures>
  <aclApprovedSignatures>
    <string>method groovy.lang.GroovyObject getProperty java.lang.String</string>
    <string>method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object</string>
  </aclApprovedSignatures>
  <approvedClasspathEntries/>
  <pendingScripts/>
  <pendingSignatures/>
  <pendingClasspathEntries/>
</scriptApproval>

Qiitaを退会しました

昔のQiitaは技術情報を共有する場でしたが、今では技術情報のノイズとなっている惨状。

Googleの検索でも -qiita で検索することが多くなっていて、そういえばQiitaって開いてないなという状況が長く続いていました。

事実上使っていないサービスですが、アカウントを削除するのも面倒で残しておりました。 しかし昨日、閲覧記事の傾向を表示するという機能が追加されたと聞いて、アカウントの削除を決めました。

Qiita、読んだ記事の傾向を合意無しに表示して炎上 批判受け機能停止中

https://www.itmedia.co.jp/news/articles/2003/26/news087.html

嫌なら使わなくてよいという潔い判断です。自分の記事の質もとても良いものとはいえず、Qiitaのディスクスペースを圧迫するだけと思いましたので綺麗に消すことにしました。 一部の有用な情報はgistなどに置くかもしれません。自分が見直すメモ書き程度に。

昔は良かったな...というお気持ちの表明です。

AWSでAZ障害が起きたのでなるべく影響を受けない構成の考えを書いておく

AZ障害は受け入れるしかないクラウド時代のインフラ

ただの日記。 今日の昼、AWSを利用している人たちは大変だったところもあると思う。 AZの一つが丸々機能しなくなる大きなAWSの障害があり、AWSを利用して運用されていたサービスは多かれ少なかれ影響を受けることになった。

完全に雰囲気で書いてしまうが、今回のAZ障害で影響を受けたサービスは思ったより多かったように感じる。 というのもAWSではアベイラビリティーゾーンの障害は発生するものと考え、本番運用するのであれば、マルチAZ構成を取るのがベストプラクティスとされているので、 マルチAZ構成を取っていれば影響なんてないんじゃないの普通、と思ってしまうと思う。 インフラ屋さんでもそう思ってしまうし、インフラ屋さん以外ならなおさらなんで重くなるのかわからないと思う。

幸い自分の運用しているサービスでは影響が軽微だったので、完全に想像にはなってしまうけど、起こりがちなケースを考えてみる。

続きを読む