2016年10月30日日曜日

小さな会社で一人で監視サーバ立てて運用して一年以上たったのでそのまとめ


MECE目指して書き始めたけど全然無理でした。多分、初心者向けです。
仕事で書いたドキュメントの流用です。
会社にはインフラでズバッと意見を出す人がいないので、こういう割と広いこと見れてそうな入門ドキュメントを会社のドキュメントとしてためておくことで、将来誰か監視システムを刷新するときとかの方向性になれればという考えです。

持つべきか、もたざるべきか

まず大枠の設計として、監視システムを持つべきか、持たざるべきかという点について考える必要があると思います。
これは監視をするかしないかという意味ではなく、監視システムのサーバを持つかどうかという意味を指します。
つまりZabbixやmuninといった監視サーバを構築して運用していくのか、それともMackerelやNew Relicといった SaaS監視システムにお金を払って利用するのか、という監視システム運用の方向性の問題です。
私の場合は、会社でインフラエンジニアが私一人だったので、私の興味からZabbixを立てることにしました。
Zabbixに惹かれたのは主に「ネット上に先人の記事がそれなりに上がってる」「カスタムスクリプト書けばなんでもできる」「成長したイケてるベンチャーも使ってて実はダサくない」という3点で、とくにスクリプトを書けばなんでもできそうというのは、私自身のコーディング経験の足しにもできるし、アプリケーションエンジニアにも説明すれば監視業務にコミットしてもらえそうという期待からでした。
 CTOは新しくてイケてるSaaSを使うのが大好きだったので、実はすでにNew Relicが入っていました。しかし有料プランは結構高く、財布事情が許してくれなかったので、私の提案をしぶしぶ飲んで、Zabbixとの並行運用になりました。
そしていま運用して一年ちょいになりますが、Zabbixでできることが増えてきたので、New Relicはほとんど見ていません。
エージェント自体は残っているけど…。

監視システムに欲しい機能

監視システムには下にあげる機能が基本的に存在しているでしょう。
一部の特化型システムにはないものもあるかもしれないですが…。
そして、それらができるだけ自動化されていることが望ましいです。
ここでいう自動化とは、少ない手作業で必要な多くの作業をこなしてくれるという意味を含みます。 
  • 監視対象サーバ登録削除編集
  • 監視対象サーバの監視有効無効化
  • 監視項目追加削除編集
  • 閾値に応じたアラートの登録削除編集
    • 監視システムの画面上で表示
    • メール通知
    • 電話通知
    • スマートフォンアプリケーション通知(チャットとか)
  • 監視結果のグラフ表示
  • 複数のサーバのグラフを一元表示
  • カスタム(自作)スクリプト実行
  • カスタム(自作)監視項目追加削除編集
  • ユーザ複数作成と各ユーザの利用権限編集
  • 監視結果グラフをパッと見れるダッシュボード

やっておきたい連携

メール連携

原始的だけど社会人だったら誰でも理解できる説明がもっとも容易な連携。 
私の場合はZabbixのサーバにPostfixを入れて運用する様にしてしまったけれど、今から作り直すならSESのスタック立ててZabbixはそこを使う様にするかな…。
ついでにACMも認証させてSSL証明書もゲットしておくと尚よし。

チャットシステムとの連携

具体的には、Slack、HipChat、ChatWorkなど。
私の勤務先ではSlackを使っており、かつ有料プランになっているので、メール連携が使えたのでそれを使っています。
コードを書かずに連携できて超ラクです。ありがたや。
設定を行うとSlackからメールアドレスが発行されるので、それをZabbixでアラート通知用メールアドレスとして使用するだけです。
かんたん。
 障害、復旧、閾値オーバー、レスポンス速度悪化、バッチジョブ開始、バッチジョブ完了、サーバ新規追加、などをメール連携でSlackに飛ばす様にしていますが、開発チームみんなに全部投げるのもアレなので、何個かチャンネル分けて、たとえばたくさんの人がみる監視チャンネルには障害やジョブ失敗のアラートのみを投げる様にしています。
そんで、ジョブ成功とかは私だけが入ってるチャンネルを作ってそこに流したり。
半日単位とかでガーっとスクロールして流し見したりします。

電話連携

実はできていません…。
データセンターがメルアドを持っているので、そこにメール送って電話させようぜという人力電話連携構想が社内で湧いており、とりあえずそれでいっかな…。
そのうちTwillio連携とかさせたい。
優先度低い。

分けられる要素はできるだけ別インスタンスにしたい

たとえば私の場合はAWS上にZabbixを立てたわけですが、DBはRDSを利用しています。
その方がDBで心配する確率が減っていいです。
同様にメールサーバもZabbix内に立てるのではなく、SESなどを使った方がいいです。
その辺はケチったところで運用のための監視サーバのための運用がつらくなるだけなので、ある程度お金を使わせていただきたい…。

インフラエンジニア以外に使ってもらうにはお膳立て必須

  • ログインしてぱぱっと問題ないかを確認するまでの手順
  • 全体の状況を一覧で見れるダッシュボードへのアクセス手順
  • そういうダッシュボードの作成
  • チャットアプリに飛んでくるメッセージの意味と対処方法
  • よくある障害の内容と復旧方法
私の場合は多分まだ全然足りてなくて、10割オペレーションが7.5割に減ったくらいかな…。
マネージャーの上司にZabbixのスクリーンを教えたら自分でグラフ組み立てて性能レポート画面作ってたのはいい結果だったかなと思います。
障害対応とかはアプリケーションエンジニアにも少しずつシェアできると万々歳なんだけどそもそもPCを持ち帰っていないとか色々あるので私が対応…といってもサーバ多めにしてたりするので正統派なシステムダウンはもう全然起こっていません。
平日に利用者からくるアプリケーション不具合やデータ不整合に関する問い合わせ調査なんかはむしろ他のエンジニアにやってもらっているので、多分それでバランスはとれています…。

監視項目や検知内容は育てる前提で

監視項目はググって引っ張ってきていいと思いますが、まずは基本的に
  • CPU使用率
  • メモリ使用率
  • ロードアベレージ
を見ておけばいいのかなと思います。そしてそれらの使用率高騰のアラートを設定しておく。
DBは上記に加えて、
  • コネクション数
  • ストレージ残容量
なども必要ですね。気づいたらディスクがいっぱいでDB停止からのサービス停止とか怖いですね。
Webサーバのプロセス処理方式が Prefork の場合には
  • 稼働プロセス数
も監視しておいた方がいいですね。利用者が増えてくるとそこがボトルネックになることもあると思います。
それから運用しているWebサービスの主要エンドポイント(URL)の
  • レスポンスタイム
  • レスポンスコード
を見ておきましょう。
POSTが送れる場合はテストユーザでのログインとかをZabbixにやらせることもできると思いますので、そこでエラーコードが帰ってきたらログイン機能がトラブル!?みたいな検知もできるかなと思います。

手に入れた値はCloudWatchに寄せるのか、監視スステムに寄せるのか

AWS特有の悩みです。どっちかに決めるしかないです。悩ましいことにどっちもお互いにインポートすることができます。
私の場合は、CloudWatchは課金しないと2週間分しかログが残ってくれないので、一年単位でのトレンド分析とかそういうのには向いてなさそう…という理由でZabbix側に寄せることにしました。
つまり、CloudWatchが持ってる値のうち欲しいものをスクリプト書いてそいつに持ってこさせます。
するとZabbix側で好きにアラートやアクションを設定していろいろ処理することができます。
というかそういうことやらないとわざわざZabbix立てる意味はない…。

プロセス自動復旧

Zabbixの場合は、ダウンを検知したらZabbixからコマンド実行命令を出して復旧させることで自動復旧が実現できます。
私の場合はまだまだ導入が少ないので増やしていきたいところ…。

Mackerel使わないの?

なんか料金とインベントリ数だったかグラフ数だったか外形監視数だったかのコスパを考えると見合わないかなぁと思って検討をやめました。
プログラマフレンドリーっぽいので私がいなくなったらアプリエンジニアたちが乗り換えるかもしれません??


以上。
ある程度監視項目とか増えてきて回り始めると他のことに時間を取られて監視システムの成長が鈍化するのがつらいところ。
仲間が欲しい。

2016年10月18日火曜日

一部のユーザだけ NET::ERR_CERT_REVOKED でサイトにアクセスできない

一部のユーザから、HTTPSのURLにアクセスできなくなったという連絡を受けました。
なんでも攻撃される恐れのあるサイトですとかなんとか…。

ブラウザのスクリーンショットをもらってみたら、こんな表示が。













Google Chromeでも同じ感じのエラーメッセージが表示されていました。(サイト名が出るので省略…)
Chromeの方のエラーメッセージをよく見ると、 NET::ERR_CERT_REVOKED と書かれています。ファッ!?証明書が失効している…!?

そんな馬鹿なと思い手元でアクセスしてみたら普通に繋がる…HTTPSできてるよ?なんで?何が起こってるんだろう…。

結論を言うと、SSL証明書業者が手違いで中間CA証明書を失効させてしまったことにより、私たちが購入して使っている証明書が一時的に利用不可能になり、そのネガティブキャッシュをユーザが参照している、というお話でした。

解消のための新しい中間CA証明書が公開されていたので、そちらを使って更新してみると、問題は解消されました。
ただ、自社が買っていたのはクイックSSL証明書だとばかり思っていたので、更新に失敗しまくって時間がかかりました。違うやつだった…。

SSL証明書とかドメインの周りのメンテナンスは多くても年に数回とかっていう頻度なので、いろいろ思い出すのに苦労しますね。
ていうか、そういうことあるんですね、中間証明書間違って消しちゃった!とか。
レジストラのDNSサーバダウンと合わせて、「うちのせいじゃないんだけどご迷惑をおかけしてごめんなさい案件」って感じで覚えておきたい…。



2016年9月16日金曜日

ElasticBeanstalkの速習にチャレンジ

あー、なんか環境一式作ってくれるやつねー知ってるー使ったことないけどー…。
え?新しいアプリをElasticBeanstalkでローンチするの?それの運用やれ?
アプリはもうできている…??
ということで速習にチャレンジ。
これを社内ドキュメントシステムにも残して、他のメンバーにも運用させる目論見…w


Environment Type(環境タイプ)

  • Webサーバ と ワーカーがある
  • WebサーバタイプはHTTPポートを解放して外部からアクセスを受けるようなシステム全て。ユーザがブラウザでアクセスするタイプのソースコードを動かす場合は全部これ。
  • ワーカーはバックエンドのアプリのこと。SQSを使って他アプリというかシステムのワークフロー上の前後の機能とやりとりする。

DBの構築

  • RDSのインスタンスをElasticBeanstalkの構成の一部として起動することができる
  • アプリを消すとDBも自動的に削除される。もちろん最終スナップショットは取れる
  • 既存のRDSのスナップショットからRDSインスタンスを作成してそれをElasticBeanstalkアプリのDBにすることもできる
  • ElasticBeanstalkの構成の一部としないDBを作成することもできる。その場合は、ElasticBeanstalkアプリを削除してもDBが残る。作り方は多分RDSインスタンスを普通に作り、ElasticBeanstalkからそこへ接続する。
  • その他のDBに関する仕様はRDSを参照

VPC内への構築

  • 自分の既存のVPC内に構築することができる
  • Elastic Beanstalk は、Linux プロキシ設定(HTTP_PROXY、HTTPS_PROXY および NO_PROXY)をサポートしていない。
  • 直接インターネットからアクセスさせる(外部公開)するかNAT経由にする必要がある
  • VPC全般に言えるがUDP123番ポートを利用してNTPで時刻同期している。なのでNTPが利用できるように解放しておく必要がある。
  • 明示的にVPCを指定しないと自分のVPCを作ってそこに生まれる。

サービスロール、インスタンスプロファイル、ユーザーポリシー

  • サービスロール は 1個のサービスを正常に動かすために必要なポリシーをまとめたもの
  • ElasticBeanstalkサービスロールとは、Elastic Beanstalkが正常に動くために必要な各種権限が含まれたポリシーの集合体。
  • インスタンスプロファイル はElasticBeanstalkアプリを稼働させるEC2に付与するIAMロールのこと。
  • ユーザーポリシー はユーザIAMに適用できるElasticBeanstalkの権限ポリシーのこと。AWSユーザ側の話。

アプリのデプロイ

  • 基本的にアプリケーション全体をZipファイルにしてそれをアップロードすることでデプロイが行われる。
  • Webサーバのドキュメントルートに丸ごと置かれるとイメージしてよい?
  • 過去のバージョンのソースコードをはダウンロードできる。バージョンを戻すこともできる。

ebextensionsによるインフラ構築のカスタマイズ

  • アプリケーションのパッケージ(Zipファイル)のルートディレクトリに .ebextensions ディレクトリを作って、その中に filename.config の名前で yaml を書くと、ルールにしたがってインフラの構成変更を行ってくれる。
  • yum などから必要なプログラムをダウンロードしたり、決まった内容でファイルを生成したり、デーモンの起動停止設定を変更したりくらいはできる。
  • ebextension のファイル配布では、URLダウンロードか、インライン記述しかできない模様。つまり、アプリケーション内部の特定ファイルを指定してそれを配布することができない(ほんとに?)

CLIから構築すると圧倒的楽感が得られる

  • eb cli というコマンドラインツールがある。 awsコマンドの拡張的な位置づけで、awsコマンドとは別にインストールが必要
  • pip install awsebcli
  • eb cli は最新バージョンが3.x系となっていて、前のバージョン2.6とは非互換なところがある。今から始めるのであれば3.x系を使えば良い。
  • gitリポジトリを使うことが前提になっている。デプロイしたいアプリのリポジトリディレクトリのルートで eb init を実行する。
  • eb もリポジトリのように init してからそのディレクトリに Elastic Beanstalk アプリケーションの概念を植えてから作業を行っていく。
  • eb init は アプリケーション構築枠をElasticBeanstalkに確保した状態。枠だけなのでまだネットワークも構築されていないしEC2インスタンスも存在しない。
  • eb init で すでに存在している ElasticBeanstalkアプリケーションをカレントディレクトリのGitリポジトリと紐付けることもできる。アプリをシステム丸ごと移管された場合や、既存のシステムの開発に途中から参加する場合に使うと思う。
  • eb create で 「環境」を作る。「開発環境」とか「本番環境」などの「環境」のことだと思えばいい。システムの一式が作られる。つまり、ネットワーク、ELB、EC2が構築され、リポジトリのソースコードがデプロイされる。
  • eb create 実行時は対話でいろいろ聞かれる。構築するリージョンやアプリケーションの言語やELBの種類など。
  • eb create はオプションであらかじめ指定しないと、自分専用のVPCを作ってしまい、他のEC2らがローンチされている統合的なVPCで管理したいという思惑からそれてしまう。
  • eb cli の環境さえ整ってしまえば、あとは圧倒的に楽な感じがする。
  • eb cli のコマンドリファレンスは ここ をみると良い。そんなに種類は多くない。

DNSとSSL

  • ELBみたいに、Elastic BeanstalkアプリケーションにはAWSからDNS名が発行されるので、それをCNAMEレコードとしてDNSサーバに追加することができる。
  • Route53が利用できる場合はAレコードのエイリアスとして登録できる。そちらの方が良い。新規ドメインでのアプリ開発の場合はRoute53利用を前提にしたい。
  • SSL証明書は ACM(Amazon Certificate Manager)から発行される無料の証明書が利用できるので、それを適用できる。楽。

その他気づいたこと

  • Golang 1.5 でサンプルアプリを立ち上げてみたがSNSトピックが勝手にできた。承認URLが書かれたメールが飛んできた。SNSも使う想定で構築してくれる模様。
  • Elastic Beanstalk の公式ドキュメントは他のプロダクトより説明が抽象的で具体的にどうすればいいかわかりにくい印象。エンジニア向けかと思ったら経営層向けのような表現が出てきたり…。
  • Git使ったことない人は先にそっちを覚えたほうがいい。とりあえずは init して status して add して commit して push できるだけでよい。
  • とりあえず臆せずサンプルアプリを立ち上げて、管理画面がどうなっているのかとか、どのタイミングでEC2が生まれるのかとかの挙動を観察してからドキュメント読み込みに入ったほうが理解が早いかも。

次は

  • ebextensions という yaml群 を使うことでアプリのデプロイと一緒にインフラの設定変更やミドルウェアの追加などが可能となっている。自動で構築してくれる。それのやり方とか。
  • Zabbixエージェントとfluentdのインストールを自動化したい。
  • デプロイ時の挙動が選べるけどその辺どうすべき?とか

参考

AWS公式ドキュメント、クラスメソッドさんのブログ、Qiitaの順で漁りました。

2016年9月2日金曜日

PHPで書き込みができないからSELinuxを停止してと言われた

凄く短いコマンドだけどすぐ忘れちゃうのでメモ。知人から、SELinuxを停止してほしい、できれば指定するフォルダの部分だけ停止してほしい、という依頼を受けました。

話を聞いてみると、どうやらPHPを動かしたいディレクトリがあり、SELinuxのせいで権限エラーになっているようでした。
こういう時はSELinuxを停止するのではなく、設定を変更しましょう。 コンテキストと呼ばれています。

まず今どんなコンテキストになっているのかを確認します。

ls -Z

すると、 「system_u:object_r:httpd_sys_r_content_t:s0」 になっていました。 
これだと書き込みができないみたいなので、変更します。

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/app/*"
restorecon -R /var/www/html/app

このあと確認してみると、 「system_u:object_r:httpd_sys_rw_content_t:s0」 に変わってました。

これでphpのエラーが消えました。
どうやらCakePHPでアプリを作るようです。
 俺もやろっかなCake。



2016年8月4日木曜日

監視の種類とカバーできる範囲について考えてみた

昔なんかそれっぽい表が必要だったので、書いてみたやつが、チケット整理してたら出てきた。どっかで使いそうなので、備忘録とします。

監視の種類死活確認症状確認傾向確認
ログ監視
性能監視
バッチ監視
レスポンス監視
プロセス監視×

監視の種類としては
  • ログ監視
  • 性能監視
  • バッチ監視
  • レスポンス監視
  • プロセス監視
の5種類あれば、システムの一通りの状態確認が可能なのかな、と思いました。
で、確認すべき状態ってなんだ?ということになりますが、これは、死活の確認、症状(トラブルの程度)の確認、傾向(リソースの利用量)の確認を行うという方向性で考えればいいのかなと。


2016年6月29日水曜日

ウェブサイトを HTTPS + CloudFront + S3 の環境に移行したのでその振り返り

先日、Apacheで配信していたWebサイトをS3+CloudFrontの環境に移行しました。そのときにやったことを備忘録としてまとめました。
個人的にハマって悩んだところや大事だなと思ったところは太字にしています。

0. 前提条件

  • 一通り構成を組んだ後でのテストでは、キャッシュがしぶとくてコンテンツ更新後の状況が再現できないことがあるので、Invalidationしまくったり、ブラウザキャッシュを削除しまくったりする必要がある。
  • 適当なテストドメインを用意できると良い。たとえば、 www.example.com について構築しようとしているのであれば、 www2.example.com などをテスト用として確保するとよい。
  • phpやrubyは動きません、Javascriptは動きます、Basic認証はできません、会員登録はできません(phpやrubyが必要なページは動かない)、などの制約事項があるので、非Techの関係者にネゴっとく必要がある。

1. S3の基本的な設定

  • なんでもいいのでバケットを作る。バケット直で自分が持っているドメインを紐付けようと思うなら、ドメイン名と全く同じバケット名(www.example.comのサイトを作りたい場合は、バケット名をwww.example.comにする。ドットは入力できないとエンジニアの直感でなんとなく思いがちだけど、普通に入力できる…。)にする必要があるが、多分不要。(未検証、今回はドメインと同じバケット名にしました…。)
  • 静的ウェブサイトホスティングを有効にする。
  • インデックスドキュメントはindex.html(他任意のファイル名でもOK)、エラードキュメントはerror.html(他任意ry)にする。
  • バケットに、html, access-logs, cf-logs のディレクトリを作成する。htmlがコンテンツ置き場、access-logがS3が直接ロギングするログ置き場、cf-logsがCloudFrontがロギングするログ置き場にする。
  • コンテンツを突っ込んでみて、静的ウェブサイトホスティング用のURLにアクセスして、コンテンツが表示されるかを確認する。

2. CloudFrontの基本的な設定

  • 基本的にはググって出てくるサイトを参考にしてよい。
  • Alternate Domain Names には、テスト用に確保しておいたドメインを入れる
  • Default Root Objectには index.html(もしくは特別な要件があればそれ)を入れる
  • LoggingはOnにして、コンテンツをホストするS3バケットと同じものを指定して、Log Prefixに cf-logs/ を入力する。
  • Origin Domain Name は S3バケット名ではなく、S3バケットの静的コンテンツWebホスティング用のエンドポイントにする。つまり、 www.example.com ではなくて、 www.example.com.s3-website-ap-northeast-1.amazonaws.com にする。
  • Origin Pathを /html にする。
  • Origin Protocol Policy は  HTTP Only にする。それ以外にするとS3内のコンテンツにアクセスできなくなって死ぬ。S3はHTPSをサポートしていない。HTTPSはCloudFrontがなんとかやるので、S3へはHTTPでアクセスさせてよい。
  • Viewer Protocol Policy を Redirect HTTP to HTTPS にする。これで、httpでアクセスしてきた人たちをhttpsに送らせることができる。
  • Object Cachingは明確なキャッシング作戦を用意している場合以外は、デフォルトでよい。
  • Forward HeadersやForward Cookies、Forward Cookiesはとくにそれを使ってやりたいことがなければNoneにする。
  • Compress Objects Automatically は Yesにする。gzip圧縮未サポートの端末はサポートを諦めて速度を取る。

3. DNS

  • CloudFrontのエンドポイントをドメインのCNAMEとして登録する。

4. S3によるリダイレクト

  • リダイレクトはS3の静的ウェブサイトホスティングの項目のところにXMLで入力する。
  • ルールは公式ページ他ググって付ける
  • 404時などにリダイレクトする場合は、エラーステータスによるリダイレクトを行う。書き方は公式ドキュメント参照。
  • 自サイト内でのリダイレクトは、同じドメインに対する別ホストリダイレクトみたいな書き方で定義する。
  • 上記があるため、本番切り替え直前まで、自サイト内リダイレクトには、CloudForntのホスト名を記述する必要がある。
  • なので、テスト用の一時的なドメインがあると便利。

5. CloudFrontによるHTTPS対応

  • SSL証明書はAWS-CLIよりIAMのSSL証明書置き場に送信する。
      aws --profile ebisol iam upload-server-certificate --server-certificate-name 画面に表示させたい証明書名 \
           --path /cloudfront/ \
           --certificate-body file://証明書ファイルのファイルシステム上のフルパス \
           --private-key file://秘密鍵ファイルのファイルシステム上のフルパス \
           --certificate-chain file://中間CA証明書ファイルのファイルシステム上のフルパス
  • ELBの置き場とは別物なので、すでにELB用にSSL証明書を登録してあったとしても、CloudFront用に再度登録する必要がある。
  • 登録できたら、General設定画面の [SSL Certificate]-[Custom SSL Certificate] がクリッカブルになるので、そこを変更する。

6. リリース作業

  • CloudFrontのAlternate Domain Namesをテスト用ドメインから本番用ドメインに変更する。
  • S3に記述したリダイレクトルールのうち、HostNameにテスト用ドメインを記述している箇所を全て本番用ドメインに書き換える。
  • DNSのCNAMEレコードをテスト用ドメインから本番用ドメインに切り替える。
  • 各種ページやリダイレクトルールについて表示確認を行う。変更前の状況が再現される場合は、CloudFrontから /* に対してInvalidationを行い、自分のブラウザのキャッシュも削除して、Invalidationが完了したあと再度確認する。
  • Invalidationが完了するまで確認しない。我慢できない気持ちが高まってくるけど、頑張って我慢する。
  • いろいろ考えると3時間ぐらい時間をネゴって確保しておいた方が良い。
  • あと、もし失敗した場合、2〜3日調査と改善に時間がかかる場合があるということも伝えたほうがいい。

7. AWS Lambda を利用した自動 Invalidation

  • このQiitaの記事内で公開されているLambda関数を自分のAWSでも動かす。(お世話になりました。)
  • ただLambdaにソースをアップロードするだけではだめで、IAMロールとポリシーを作る必要があるし、SNSトピックとサブスクライバも登録する必要がある。でもSNSはそんなに難しくない。
  • IAMロールは s3_CloudFront_Invalidator という名前で作成し、標準で用意されている AWSLambdaExecute というポリシーと、カスタムした CloudFrontInvalidation という自作ポリシーの2つを適用した。
  • CloudFrontInvalidation ポリシーはこんな感じにしたら動いた。
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Action": [
                      "cloudfront:Get*",
                      "cloudfront:List*",
                      "cloudfront:CreateInvalidation",
                      "iam:ListServerCertificates"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
              },
              {
                  "Action": [
                      "s3:GetBucketLocation",
                      "s3:GetObject",
                      "s3:GetObjectAcl",
                      "s3:ListBucket",
                      "s3:GetBucketWebsite"
                  ],
                  "Effect": "Allow",
                  "Resource": [
                      "arn:aws:s3:::*"
                  ]
              }
          ]
      }
  • 設定画面で、ConfigurationタブのHandlerが、デフォルトではindex.handler みたいになっていると思うので、jsファイル名に合わせる。 丸パクリでいくなら、「s3-invalidation.handler」を入力する。



2016年6月28日火曜日

ELBのHTTPS暗号化方式から弱い方式を除外する方法

概要


暗号スイートという、暗号化技術の利用セットみたいな概念があります。HTTPS(SSL/TLS)通信では、複数の暗号スイートからクライアントとサーバが利用可能なものを自動で選択して利用します。
しかし、場合によっては、弱い暗号化方式を使われてしまい、セキュリティ強度が下がる場合があります。
また、攻撃者はそのような選択が可能な場合、攻撃プログラムに故意にそういう暗号スイートを選択させるようにしたりします。
今回は、セキュリティ強化のために、ELBが、弱い暗号化方式である3DESを利用しないようにします。

しっかり理解したい方は、解説されている方がいらっしゃいますので、そういうブログや、セキュリティ系の書籍等をご覧ください。


理解してるつもりの SSL/TLS でも、もっと理解したら面白かった話 · けんごのお屋敷 http://tkengo.github.io/blog/2015/12/01/https-details/


手順

  1. ロードバランサーの画面を開きます
  2. 対象のロードバランサータグを選択し、リスナータグを開きます。
  3. HTTPSの行の「暗号」をクリックし、カスタムセキュリティポリシーを選択します。
  4. 「SSL暗号」というリストの中から、「DES-CBC3-SHA」を外します。
  5. 「保存」をクリックすると反映されます。
  6. DESを利用した暗号化方式がリストアップされないことを確認します。
    以下の記事を参考にさせていただきました。
    【小ネタ】cipherscan で対象サイトの SSL cipher suite を確認する
    https://blog.cloudpack.jp/2014/07/29/cipherscan-ssl-cipher-suite/


ELBの暗号設定画面では、暗号化プロトコルも選択できます。
たとえばTLS1.2以外は使わせたくないぜ!という場合には、
同様にカスタムセキュリティポリシーの画面を開き、SSL プロトコル」から

これで、またひとつシステムがセキュアになりました。


2016年6月11日土曜日

条件判定値を引数にそのまま流用できないかを考える

自分向けのプログラミングTipsメモです。大した内容ではありません。
Gistにサンプルコードを書いてみたので、まずそれを貼りたいと思います。


コードは、AWSを操作するための Python版 AWS SDK(Boto3)を利用したプログラムの一部です。
仕事で書いているBoto3プログラムで、こういう場面がありました。
  • 取得した配列のある要素の値がTrueかFalseかで後続で実行する関数の引数を変えたい。
  • 関数の引数にはTrueかFalseを用いる

当たり前といえば当たり前ですが、条件判定しているTureかFalseを、そのまま関数の引数として与えれば、条件判定する必要がないんですよね。
こういう小さな省力化(短いコードで書く努力)を積み重ねることで、一個のサービスが出来上がった時に体感できるような差が生まれるのかなぁなどと思いました。

普段はサーバ管理みたいな仕事が多いので、こういう風にプログラミングに対して自分で「おっ、こうした方がいいじゃん?」みたいな思考ができたこと自体がなんだかとても嬉しくなりました。
こういう気持ちはたとえ小さくてもきちんと表現したり記録しておくことが精神衛生上、そして今後の技術力向上のモチベーション管理上も良いのかなぁと思って、ブログに書いておこうと思った次第です。

こういうTipsがまとまった本とか、あるのかな、普通にありそうだな。
プログラミングをもっと業務でできるようになりたいです。



スマートPythonプログラミング: Pythonのより良い書き方を学ぶ

2016年6月5日日曜日

転職して1年経ったので振り返ってみた2016年5月

今の会社に2015年5月に入社してから1年経ちました。
あっという間だった気もするし、すごく長かった気もします。
自分がどのくらいの仕事をして、何が新しくできるようになったのかを整理したいと思い、箇条書き形式でまとめてみました。
今の会社ではAWSを使っていて、AWSを使ったインフラ全般の構築運用を行うエンジニアとして働いています。
入社前はAWSもEC2をちょっと触ったことがあるぐらいで、インフラの知識もそんなに自信がない状態でした。(今もないですが…w)
AWSエンジニアとしてはまだまだジュニアだと思いますが、1年前には何もできなかったことを考えると、少しはできることが増えてきたなぁと思います。
会社の体制も大分変わり、1年前はエンジニアがCTOとインターンのみでしたが、私の他複数名のエンジニアが採用され、エンジニアチームができ、外部委託している部分を大幅に巻き取って、自分たちのプロダクトを自分たちで責任を持って育てる土壌ができたのかなと思います。

できるようになったこと

日々の設定変更作業

  • Ansibleの初歩的な利用法を学び、初歩的にAnsibleを導入して設定業務が効率化された。
    • サーバ新規構築時のエンジニアのアカウント作成、公開鍵配布、sudo可能化、個人ファイル配布がAnsibleで自動実行できるようになった。
  • Python AWS SDK (Boto3) を利用して、AWSの管理効率化スクリプトを幾つか作成できた。
    • 毎日すべてのEC2のAMIを自動バックアップ
    • 指定した世代より古いAMIとEBS Snapshotを自動削除
    • 各ELBに紐付いているEC2インスタンスの表示名、Public IP、ヘスルステータスを表示
    • ELBに紐付いているサーバを切り離したり、紐付いていいないサーバを接続させる
    • 指定したEC2のAMIを取得し、そのAMIから任意の台数のEC2インスタンスを作成

監視

  • Zabbixを導入し、一元的な監視が可能になった。
  • Zabbixが検知したトリガーをSlackに流し、タイムリーに社内に報告される体制ができた。
  • 一部のエラーに対してはZabbixで検知した障害をトリガーに復旧スクリプトを実行して自動復旧をすることができた。
  • Zabbixのグラフやスクリーン機能を利用することにより、プロダクトマネージャの上司が提携先に性能監視状況を説明することができるようになった。

スケーリング・パフォーマンスチューニング

  • クラウドMSPに連絡しないとサーバがスケールアウト出来ない状況だったが、手元のスクリプトで任意に手動スケールアウトできるようになった。
  • Prefork駆動のAPIサーバをWorker駆動に変更し、サーバ1台あたりの処理量が大幅に増加した(5倍以上)。
  • 多数のサーバの仮想化方式をPVからHVMに変更し、m4などの新しいインスタンスタイプが選択できるようになった。拡張ネットワーキングも自動で適用され、たぶん処理スピードも向上した。
  • と同時に、ステージング環境や開発環境の最小インスタンスサイズにt2.microが選べるようになった。それまでt1しか選べなかった。

開発環境

  • ステージング環境を本番環境と同様の構成にして、コンポーネント間の動作確認がきちんと行えるようになった。
  • ステージング環境のDBのデータを本番と同様にすることができた。
  • Let's Encryptを導入し、ステージング環境のHTTPS接続を無料で実装することができた。

コスト

  • クラウドMSPのパッケージング契約から請求代行に移行し、月額費用の削減が出来た
  • 顧客企業のキャンペーンでバーストして対応した際に、スケールアウトによる追加費用を計測し、社内に共有できるようになった

自分の成果ではないがエンジニアチームができるようになったこと

  • Circle CIを使って、一部の領域で楽勝デプロイができるようになった。GithubのPull RequestをマージしたらCIが実行され、決まったテストを自動で行い、問題ない場合にデプロイされる。
  • リリース時にリリース内容、リリース順序、リリース手順を明記して社内に掲示することができるようになった。
  • アプリケーションの開発を外部に委託していたが巻き取り、自主性の確保とコストダウンを行うことができた。
  • re:dash によるデータ分析を営業などの非Tech系のチームに提供できるようになった

できていないこと、やりたいこと

挙げればキリが無いので、手をつけたところでできていないところをいくつか…。
  • 残っているPV型のEC2インスタンスをすべてHVM型で置き換え
  • 複数役割を持っているEC2インスタンスの完全退役
  • オートスケーリング
  • Zabbixの状態異常検知をトリガーとした自動復旧機能をもっと増やす
  • スポットインスタンスの実践活用
  • インフラ系ドキュメントの充実
  • ログ集約、分析システム(fluentd,ElasticSearch等)の導入


読んだ本について

AWSの本は入社前の休暇に、これらの本を精読しました。今振り返ると2冊しか読んでませんでした…。
それ以降アップデートできていないので、お財布と相談して新しい本を読んでみたいと思います。
でもAWSはネット上にたくさん情報があるから、それが自分で整理さえできれば、本を買わなくてもなんとかなる気もしますが、まぁ「読んだぞ!」という気持ちは大事ですよね。

挑戦意欲を育んでくれたり、達成感をもたらしてくれたりしますので。
ちなみに下の本は発売当時としてはかなり良書だったのかと思いますが、情報が少し古いので、現在の状況との差分を念頭に置きつつ読むか、他の本で代替することをお勧めします。


Amazon Web Services クラウドデザインパターン実装ガイド 改訂版


よくわかるAmazonEC2/S3入門 ―AmazonWebServicesクラウド活用と実践 (Software Design plusシリーズ)

2016年3月28日月曜日

AWS EC2 の インスタンスIDにマッチする正規表現が欲しかったので試行錯誤した結果

得られた正規表現

'^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$'



背景


今の勤務先ではAWS系インフラエンジニアとしてAWSの管理全般を行っています。
昨今のクラウド全盛期においては運用業務の各種自動化が大事ということで、Python + AWS SDK(Boto3)で、AWS管理自動化プログラミングを少しずつ進めています。
AWSの操作はEC2に関するものが多く、EC2のインスタンスIDを引数に与えるものが多くなっているので、インスタンスIDが正しく入力に与えられているかをバリデーションできたらいいなと思い、ちょっと探してみた結果、以下のような正規表現を得ることができました。もっといい案がありましたら教えてください。
数ヶ月前に、インスタンスID及びAMI IDの文字数拡張がアナウンスされています。なので、「i-(英数字8桁)」の場合と、「i-(英数字17桁)」の場合に対応する必要がありました。今回はそれに対応できるようになりました。

得られた正規表現をPythonで使いたい


Pythonで使う時には、標準で用意されている re というモジュールをインポートして、 search() を使うことで、与えられた文字列が正規表現にマッチしているかどうかを確認することができます。
「i-」の後ろが8桁の英数字か、17文字の英数字の時のみ、オブジェクトが返ってくるので、そのオブジェクトの存在を確認すれば、インスタンスIDが実在するかはどうであれ、少なくとも形式に沿った値であるということがわかります。

>>> 
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-0')                                                                                                                                          
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-03')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033a')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag6')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h')
<_sre .sre_match="" 10="" match="i-033ag67h" object="" span="(0,">
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8r')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rb')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0t')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx')
<_sre .sre_match="" 19="" match="i-033ag67h8rbm1l0tx" object="" span="(0,">
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx0')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx05')
>>> re.search('^i-([a-zA-Z0-9A0-zZ9]{8}|[a-zA-Z0-9A0-zZ9]{17})$', 'i-033ag67h8rbm1l0tx05f')
>>> 
>>> 

書いている時に思ったけど…

describe-instance みたいな、インスタンスIDを引数にEC2の情報を取得する関数があるんだから、それを与えられたインスタンスIDで実行してみればいいだけのような気もしますね。でもその場合はAWS APIへの通信が1往復増えるため、繰り返し件数が多いバッチなどを書く時には処理合計時間が大きくなってしまうネックはありますね。

2016年1月26日火曜日

AWSでPostgreSQLを前から使っている方はアップグレードメンテナンスが必要です

AWSのサポートからこんなメールが届きました。

Dear Amazon RDS Customer,
A system update is now available for any Amazon RDS PostgreSQL database instances you created before 13 October 2015. We recommend installing this update to take advantage of several performance improvements and security fixes. You may choose to install this update immediately, or during your next scheduled maintenance window. After approximately six weeks, your RDS instance will be automatically upgraded during your maintenance window. To learn more about scheduling or installing an upgrade, please refer to the RDS documentation: http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.OSUpgrades.html.
Installing this update will have an availability impact for a few minutes on your RDS instance (60-120 seconds for Multi-AZ instances). To reduce downtime, you may consider converting your Single-AZ instances to Multi-AZ. If you have any questions or concerns, please contact your TAM or AWS Support.
Sincerely,
The Amazon RDS Team
Amazon Web Services, Inc. is a subsidiary of Amazon.com, Inc. Amazon.com is a registered trademark of Amazon.com, Inc. This message was produced and distributed by Amazon Web Services Inc., 410 Terry Ave. North, Seattle, WA 98109-5210

同様の内容がフォーラムにも投稿されています。

2015/10/13 より前に作成したPostgreSQLインスタンスは、セキュリティ修正と少々のパフォーマンス向上のために、アップデートを適用しなければいけないそうです。
アップデートにはダウンタイムが発生するため、DBを利用中のアプリケーションが停止してしまいます。
Multi-AZの場合は、AZ切り替えに必要な時間である1〜2分程度のダウンで済むそうですが、Single-AZの場合はどうなんでしょう…メールには記載されていませんが、再起動が行われそうな気がするので、通常のRDSインスタンス再起動と同程度かそれ以上のダウンが発生すると考えておいて良いと思います。

メンテナンスは以下のスケジュールから選択できるようです。

  • 猶予期限内で任意のメンテナンスウィンドウ
  • 即時(手動)
  • 猶予期限が切れた直後のメンテナンスウィンドウ

猶予期限は「After approximately six weeks」と書いてあるので、おそらくフォーラムの投稿日である1月15日から6週間くらいだと思います。サポートに入っている人は確認してみてください。

メンテナンス実施の手順は、前回のMySQLのメンテナンスの時の内容を記事にしてくださっている方がいらっしゃいましたので、その記事を参考にしたいと思います。
[AWS] RDS の OS アップグレードのメンテナンスを実施する。 | LexTech http://tech.lexues.co.jp/archives/1864

さて、自分が管理しているRDSインスタンスを確認したら、確かに対象のインスタンスの「メンテナンス」列が「必須」に変更されていました。


上記4つのインスタンスは全部PostgreSQLですが、一番下の最近作ったやつだけメンテナンス対象外になっています。

運用中のアプリによってはダウンタイムの調整に時間がかかるかと思いますので、事前にしっかり確認して対応していきましょう…と自分に言い聞かす。