TECH PLAY

Wedding Park/ウエディングパーク

Wedding Park/ウエディングパーク の技術ブログ

206

こんにちは。 Photorait エンジニアのヒエイです。 Photoraitではサービスのエラー監視に Sentry を導入しています。 Sentryとは エラー収集・可視化ツール サイトで発生させたエラーをこのツールに送信しツール画面上からエラー詳細を確認でき、エラー解決に役立てることができます。 Sentryを導入してしばらく経ちましたが、運用上の問題を抱えていました。 明確な監視体制がない どんなエラーが出ていて、どれだけのエラー数があるのか把握しきれていない。 エラー数に関してはSentryツール上を見れば確認できる事ではありますが、サイト運営者自身がエラー数と内訳を定期的に観測できるようにする体制が必要でした。 今回は エラー数と内訳を監視できるようにした 話を主に書きます。 方針 以下の内容で 集計スクリプト を作成します。 SentryApiを使って集計を行う。 集計はGoogle App Scriptを使用 直近一週間以内に上がったissue一覧を取得。issue数を集計。 issueのエラー文、エラー詳細、エラー数、sentryリンクも一覧化する。 集計結果はGoogle SpreadSheetに排出。エラー数をslackに通知。 この集計自動化により、エラーissue数の定点観測と内訳を可視化し監視体制に役立てたいと思います。   集計スクリプト作成 Sentry Apiを使用 List a Project’s Issues を使います。 エンドポイントは /api/0/projects/{organization_slug}/{project_slug}/issues/ sentry側で auth token を発行し、curlを例に以下のようにリクエストを投げます。 curl https://sentry.io/api/0/projects/{organization_slug}/{project_slug}/issues/?query=is:unresolved&statsPeriod=14d \ -H 'Authorization: Bearer <auth_token>'  query=is:unresolved unresilvedステータスのリストを取得。 statsPeriod=14d 24h、14dが選択できます。7日間分欲しいので14dに設定。 レスポンスの形が こちら になります。 エラー数を取得する レスポンスにstatsというパラメータがあります。 stats: { 14 d: [ ...... [ 1608076800, 1 ], [ 1608163200, 0 ] ] } それぞれの配列に timestamp エラー数 という形で日付ごとのエラー数が格納されているので 直近7日間分 のエラー数を加算する集計をさせる事にしました。 エラーリストの作成とデータ排出 スプレッドシートに 集計シート 、 エラー数集計 という名前でがあらかじめシート用意されている前提とします。 集計した結果を上記シートに書き込みます。 const ss = SpreadsheetApp.getActiveSpreadsheet(); const issueSheet = ss.getSheetByName('集計シート'); // あらかじめ用意していたエラー数用シート取得 const issueCountSheet = ss.getSheetByName('エラー数集計'); // ここでList a Project'sのエンドポイントからエラーリスト取得のメソッド呼び出し例 const list = Sentryapi.getWeeklyErrorList(); const issueList = JSON.parse(list); const sumCount = [ ['php', 0], ['js', 0], ]; issueList.forEach(issue => { let errNum = 0; // 7日前から集計日前日までのエラー数を取得 for (let i = 6; i <= 12; i++) { if (issue.stats['14d'][i][1] > 0) { // エラー数を加算 errNum += issue.stats['14d'][i][1]; } } // エラー数が0ならスキップ if (errNum < 1) { return; } // スプレッドシートにissueデータインサート issueSheet.appendRow([ issue.title, issue.metadata.value, issue.platform, Math.floor(errNum), issue.permalink ]); // issue数を種類ごとに加算 sumCount[issue.platform]++; }); // 集計したissue数を書き込み sumCount.forEach(platformCount => { issueCountSheet.appendRow(platformCount); }); webpack、docker、claspを使い、 「チーム活性化と、GASでGaroonスケジュールをSlack通知」 のようにGASにデプロイしています。 通知 集計したissue数をslackに通知するようにしました。毎週決められた曜日に直近1週間分エラーとして通知されます。 以下画像内のプロジェクト名と件数は仮です。 基本的にクリティカルなエラーはすぐに解消対応をしている体制でいましたが、サイトに影響の無い軽微なエラーが多く件数として上がっていました。   監視と体制 ルールとフロー 詳細に関しては伏せますが対応優先度や対応フローをまとめたルールブックを作成しました。 開発陣主導の活性化活動も始めました。営業やディレクターもいるPhotoraitチーム全体の定例会議で活動内容や数値面の共有と、Sentryとエラーの付き合い方について 紙芝居 にした説明を実施しています。(自宅で子供に絵本を読んでいる習慣が活かされました) 改善活動 毎週上がったissue数を確認し、作成されたエラー一覧から原因と対策方針を決め修正実対応をしています。 サービス毎のissue数をグラフ化し、観測できる状態を作りました。 週毎に発生した issue数を指標 として設定しました。エラー数は障害などで急激に数値が跳ねる可能性もあるため、あくまで対応優先度を決める値とし、監視する指標はissue数として定点観測しています。 フェーズを設定 活動開始当初は、監視体制を作る・エラーの多いissueを減らしてゆく、という方針で活動していましたが段々エラーを潰してゆくとニッチなエラーが残されてゆき、これはエラーと呼べるものか、何を持って対応すべきエラーとするかという対応への向き合い方が変わってくると考えました。 そこで活動フェーズを作成し、状況により活動方針を変更する予定です。   さいごに まだまだ駆け出しの段階だと思いますが、いざ体制を作って改善対応を始めるとチームで楽しく活動できている思います。今後もサービスクオリティ改善に向けて対策活動を続けていきます。
アバター
こんにちは!前撮りなど結婚写真の撮影スタジオ・サロンを検索できる情報サイト「 Photorait 」のメインデザイナーをしています、内田( @PANbooooo )です。 Photoraitチーム唯一のデザイナーとして、今Qは「デザイナーのアピール」をテーマに新しいことに取り組んできました。今回のブログでは、その取り組みと効果についてご紹介したいと思います。 きっかけは「デザイナーって何やってるの?」問題 デザイナーのアピールに目を向けたきっかけは、 「デザイナーの業務内容が、営業さんに伝わりにくい」 と思ったからです。多分、多くの会社やチームでこの問題は存在すると思います。同じチームなのに何をやっているか分からないって、勿体ないと思いませんか? では何故、デザイナーの業務内容が伝わらないのか。私は開発フローに目を向けました。 私が所属するPhotoraitでは以下のような流れで開発業務を行ってます。 多分、多くの会社でこのようなフローで開発を進めているのではないかと思います。 この図、何かと似てませんか??私は運動会のリレーを思い出しました。 小学生の頃の運動会って、スタートを切る人とゴールを切るアンカーはスーパースター的な注目をされていたと思います。ですが12番目に走る人とか6番目に走る人とか、真ん中の人ってあまり注目されませんよね。 これと同じことが開発フローにも言えるのかなと思います。 コンテンツの企画と設計をして、案件のスタートを切るディレクターと、リリース作業を行い案件のラストを決めるエンジニアは注目されやすいと思います。ですが、真ん中のデザイナーはディレクターとエンジニアと比べると、自然と注目されにくくなると思います。と言うか、この開発フローの図だけ見ると、最後はもう存在感すらありませんね。 これは正直、開発フローを変えない限り根本的な解決にならないかもしれません。ですが、根付いた開発フローを変えることはかなりリスキーです。 では、この開発フローのままデザイナーが着目されるためにはどうすればいいか。 色々と考え、たどり着いたのが 「箱根駅伝」 です。箱根駅伝は、マクロ視点で見れば1区がスタートを切り、10区がゴールを切るリレーのように思えますが、ミクロ視点で見ると各々の区間に「区間賞」というスーパースターが存在します。そこで私は開発フローを変えることなく、リレー形式から箱根駅伝形式に内容を変える工夫をしました。 実際にやってみたデザイナーアピールのための取り組み 開発フローを変えずにリレー形式から箱根駅伝形式に変えるためには何をすればいいのか。色々考えた挙句、私は「デザインの過程を見せよう」ということを閃きました。 これが最適な解かは分かりませんが、箱根駅伝では2区には2区なりの見せ所、3区には3区なりの見せ所があります。この箱根駅伝の見せ方を現在の開発フローに落とし込み、デザイナーの見せ所を知ってもらうことで、少しはスーパースターに近づけるのかなと思います。 そこで、以下のような取り組みを始めました。 取り組み1:slackでデザインの過程や意図を魅せる! まず、弊チームで利用しているコミュニケーションツール「slack」に、デザイナーチャンネルというものを作りました。 このチャンネルの更新は以下のように進めています。 – – – – – – – – – – – – – – – – – – – – – – – – – – – ・案件のリリース時には、そのデザインの意図を具現化し、チームメンバーにしっかりと伝える。 ・デザインのボツ案をしっかりと見せて、1つのデザイン決定案にたどり着くまでの過程を見せる。 – – – – – – – – – – – – – – – – – – – – – – – – – – – 今までデザイナーの気持ちを発信する場所が無かったせいか、このチャンネルは結構好評でした。実際に営業さんからも、「デザイナーが今どんな案件に携わっているのかが分かりやすい」と言う声も頂けました。 また、ボツ案を投稿することで、「こっちのデザイン案もいい」など、デザインそのものに興味を持って頂くきっかけにもなりました。 実際にそのやり取りの画面をご覧ください。 このslackのチャンネルは、 「デザイナーがどんな気持ちで何を考えてこのデザインを採用したのか」 を伝える大切な場となっています。 取り組み2:「行列のできるデザイン相談所」の開設 上記で紹介したslackチャンネルは、「デザイナーが作ったものを見てもらう」ための方法でした。ですが、もっと近くで体験してもらうことで、よりデザイナーのことを知ってもらえるのでは無いかと考えました。 そこで始めたのが「行列のできるデザイン相談所」です。(みなさんお察しの通り「行列のできる法律相談所」という番組のパロディ風にしました。) Photoraitでは営業さんやディレクターさんがクライアントに向けた資料を作成したり、全社に向けた資料を作成することが多々あります。資料の中にある円グラフや棒グラフ、画像や文字の色や位置など、資料を作成したことがある人であれば、誰もがちょっとした見せ方、デザインに迷った経験はあると思います。 そのような「デザインの迷い」を一緒に解決していくのが「行列のできるデザイン相談所」です。 フローとしてはこんな感じです。 誰もが簡単に気軽に相談しやすいような仕組みになっています。 実際にデザイナーが作ったものを見るだけでなく、「ちょっとしたデザインでこんなに変わるのか!」を体験してもらうことで、よりデザインの必要性や、今まで気付くことの出来なかったデザインの奥深さを知ってもらえるのでは無いかと思います。 さいごに 今回紹介した2つの取り組みは思いつきで始めたこともあり、まだまだ改善すべき箇所があると思います。ですが、この2つの取り組みを行ったことで、確実に以前よりも、デザイナーがアピールしやすい環境に変わってきたと感じています。 今後も色々と試しながら、改善と挑戦を繰り返して、デザイナーの存在感を強く出していきたいと思います。
アバター
こんにちは、インフラエンジニアの綿引です。 CloudWatch Alarm で監視したいが、設定が面倒と感じる方も多いのではないでしょうか? そこで今回は CloudWatch Alarm を AWS CloudFormation で作成したいと思います。 対象の方は以下のような方でしょうか。   CloudWatch Alarm を手動で作りたくない 監視の内製化を検討している   テンプレートファイルの作成 ではテンプレートファイルを作成していきます。 今回も yaml で作成していきます。 前提 その前にまず前提です。 CloudWatch Alarm にて監視するサービスは以下です。   EC2 EC2 ミドルウェアプロセス ALB RDS (Aurora)   また今回「プロセス監視」と「アラームを SNS を使って通知させる」ということをやっているため、以下も前提とさせていただきます。   CloudWatch エージェント を EC2 に導入済みである Amazon SNS を設定済みである   CloudWatch エージェントのインストール方法は以下に書いてあるので、よろしければご覧ください。 ・CloudWatch で EC2 のメモリ・ディスク使用率を監視する SNS の設定は以下を参考に実施いただければ、Slack まで通知可能です。 もちろんメールだけでも良ければ SNS だけ設定すれば OK です。 ・Amazon CloudWatch + Amazon SNS + AWS Chatbot を使ってアラームを Slack に通知してみる 監視項目とメトリクス一覧 今回 Alarm を設定するメトリクスを一覧にしました。 監視項目(自分で勝手につけました)と対応するメトリクス、名前空間を記載しています。 どのサービスの監視項目かは名前空間を見て頂ければと思います。 監視項目 名前空間 監視メトリクス EC2 ステータスチェック AWS/EC2 StatusCheckFailed EC2 CPU クレジットバランス AWS/EC2 CPUCreditBalance EC2 CPU 使用率 AWS/EC2 CPUUtilization EC2 メモリ 使用率 CWAgent mem_used_percent EC2 DISK 使用率 CWAgent disk_used_percent amazon-cloudwatch-agent プロセス CWAgent procstat_lookup_pid_count amazon-ssm-agent プロセス CWAgent procstat_lookup_pid_count chronyd プロセス CWAgent procstat_lookup_pid_count crond プロセス CWAgent procstat_lookup_pid_count Apache プロセス CWAgent procstat_lookup_pid_count rsyslogd プロセス CWAgent procstat_lookup_pid_count sshd プロセス CWAgent procstat_lookup_pid_count postfix_master プロセス CWAgent procstat_lookup_pid_count sssd プロセス CWAgent procstat_lookup_pid_count td-agent プロセス CWAgent procstat_lookup_pid_count ALB 正常ターゲット数 AWS/ApplicationELB HealthyHostCount ALB 接続エラー数 (ALB 最大接続超過) AWS/ApplicationELB RejectedConnectionCount ALB 接続エラー数 (LB – ターゲット間) AWS/ApplicationELB TargetConnectionErrorCount ALB TLS接続エラー数 (LB – ターゲット間) AWS/ApplicationELB TargetTLSNegotiationErrorCount Aurora CPU クレジットバランス AWS/RDS CPUCreditBalance Aurora DatabaseConnections AWS/RDS DatabaseConnections Aurora デットロック回数 AWS/RDS Deadlocks Aurora 空きメモリ容量 AWS/RDS FreeableMemory Aurora CPU 使用率 AWS/RDS CPUUtilization 構成や環境などによって監視したいメトリクスも異なるかとは思いますので、必要なメトリクスがなかったり、不要なメトリクスがある場合は、任意でカスタマイズして頂ければと思います。 テンプレートファイル 次は実際のテンプレートファイルです。 各種設定を共通化するため「Parameters」を使用しているので、以下の「XXXXXXXX」の部分だけ、ご自身の環境に合わせて変更頂ければ Alarm の設定が可能になっています。 「Parameters」の一番上で定義している「SystemName」だけは、CloudWatch アラームのマネジメントコンソールから見やすいように追加した、必須ではないパラメータなので、もし不要であれば任意で外してしまってください。 ※ 外した場合は「Resources」の「!Sub ${SystemName}」も全て消してください。 他にも閾値や閾値超過回数、欠如データの扱いなどもご自身の環境に合わせて変更いただけると良いかと思います。 変更点・注意点を以下に記載しますのでご確認ください。   環境に合わせて「Parameters」の XXXX 部分を変更 閾値 (Threshold) や、閾値超過回数 (EvaluationPeriods) などは任意で変更   以下がソースになります。 AWSTemplateFormatVersion: "2010-09-09" Description: CloudWatch Alarm ##################################################################### # Parameters 設定 ##################################################################### Parameters: SystemName: Description: EnvironmentName or ServerName Type: String Default: EnvironmentName # 環境名やサーバ名を記載 Ec2InstanceId: Description: Ec2 InstanceId Type: AWS::EC2::Instance::Id Ec2ImageId: Description: Ec2 ImageId (AMIID) Type: String Default: ami-XXXXXXXXXXXX # EC2 の ImageId を記載 Ec2InstanceType: Description: Ec2 InstanceType Type: String Default: XXXXXX # インスタンスタイプを記載 AlbLoadBalancer: Description: AlbLoadBalancer Type: String Default: app/XXXXXX/XXXXXXXXXXX # ALB の ARN を記載 AlbTargetGroup: Description: ALB TargetGroup Type: String Default: targetgroup/XXXXXX/XXXXXXXXXXX # ターゲットグループの ARN を記載 RdsDBInstanceIdentifier: Description: RDS DBInstanceIdentifier Type: String Default: XXXXXX # DB クラスター識別子を記載 SNSTopicName: Description: SNS Topic Name Type: String Default: arn:aws:sns:XXXXXXXXXXX # SNS トピック ##################################################################### # Resources 設定 ##################################################################### Resources: # CloudWatchアラームの定義 ##################################################################### # EC2 のアラーム設定 ##################################################################### EC2StatusCheckFailedAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} EC2 ステータスチェック MetricName: StatusCheckFailed Namespace: AWS/EC2 Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 0 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanThreshold # 閾値より大きい Dimensions: - Name: InstanceId Value: !Ref Ec2InstanceId EC2CPUCreditBalanceAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} EC2 CPU クレジットバランス MetricName: CPUCreditBalance Namespace: AWS/EC2 Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 200 # 閾値 TreatMissingData: notBreaching # 欠落データは良好 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanOrEqualToThreshold # 閾値以下 Dimensions: - Name: InstanceId Value: !Ref Ec2InstanceId EC2CPUUtilizationAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} EC2 CPU 使用率 MetricName: CPUUtilization Namespace: AWS/EC2 Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 2 # 閾値超過回数 Threshold: 95 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanOrEqualToThreshold # 閾値以上 Dimensions: - Name: InstanceId Value: !Ref Ec2InstanceId EC2MemUsedPercentAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} EC2 メモリ 使用率 MetricName: mem_used_percent Namespace: CWAgent Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 95 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanOrEqualToThreshold # 閾値以上 Dimensions: - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: InstanceType Value: !Ref Ec2InstanceType EC2DiskUsedPercentAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} EC2 DISK 使用率 MetricName: disk_used_percent Namespace: CWAgent Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 80 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanOrEqualToThreshold # 閾値以上 Dimensions: - Name: path Value: / # 環境に合わせて変更 - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: InstanceType Value: !Ref Ec2InstanceType - Name: device Value: nvme0n1p1 # 環境に合わせて変更 - Name: fstype Value: xfs # 環境に合わせて変更 ##################################################################### # EC2 ミドルウェアプロセスのアラーム設定 ##################################################################### ProcessAmazonCloudwatchAgentAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} amazon-cloudwatch-agent プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: amazon-cloudwatch-agent - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessAmazonSsmAgentAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} amazon-ssm-agent プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: amazon-ssm-agent - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessChronydAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} chronyd プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: chronyd - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessCrondAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} crond プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: crond - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessHttpdAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} Apache プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: httpd - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessRsyslogdAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} rsyslogd プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: rsyslogd - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessSshdAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} sshd プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: sshd - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessPostfixMasterAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} postfix_master プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: master - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessSssdAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} sssd プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: sssd - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ProcessTdAgentAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} td-agent プロセス MetricName: procstat_lookup_pid_count Namespace: CWAgent Statistic: Maximum # 最大 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: exe Value: td-agent - Name: InstanceId Value: !Ref Ec2InstanceId - Name: ImageId Value: !Ref Ec2ImageId - Name: pid_finder Value: native - Name: InstanceType Value: !Ref Ec2InstanceType ##################################################################### # ALB のアラーム設定 ##################################################################### ALBHealthyHostCountFtAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} ALB 正常ターゲット数 MetricName: HealthyHostCount Namespace: AWS/ApplicationELB Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 1 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanThreshold # 閾値未満 Dimensions: - Name: TargetGroup Value: !Ref AlbTargetGroup - Name: LoadBalancer Value: !Ref AlbLoadBalancer - Name: AvailabilityZone Value: ap-northeast-1a ALBRejectedConnectionCountFtAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} ALB 接続エラー数 (ALB 最大接続超過) MetricName: RejectedConnectionCount Namespace: AWS/ApplicationELB Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 0 # 閾値 TreatMissingData: notBreaching # 欠落データは良好 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanThreshold # 閾値より大きい Dimensions: - Name: LoadBalancer Value: !Ref AlbLoadBalancer ALBTargetConnectionErrorCountFtAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} ALB 接続エラー数 (LB - ターゲット間) MetricName: TargetConnectionErrorCount Namespace: AWS/ApplicationELB Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 0 # 閾値 TreatMissingData: notBreaching # 欠落データは良好 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanThreshold # 閾値より大きい Dimensions: - Name: LoadBalancer Value: !Ref AlbLoadBalancer ALBTargetTLSNegotiationErrorCountFtAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} ALB TLS接続エラー数 (LB - ターゲット間) MetricName: TargetTLSNegotiationErrorCount Namespace: AWS/ApplicationELB Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 0 # 閾値 TreatMissingData: notBreaching # 欠落データは良好 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanThreshold # 閾値より大きい Dimensions: - Name: LoadBalancer Value: !Ref AlbLoadBalancer ##################################################################### # RDS (Aurora) のアラーム設定 ##################################################################### RDSCPUCreditBalanceAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} Aurora CPU クレジットバランス MetricName: CPUCreditBalance Namespace: AWS/RDS Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 3 # 閾値超過回数 Threshold: 200 # 閾値 TreatMissingData: notBreaching # 欠落データは良好 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanOrEqualToThreshold # 閾値以下 Dimensions: - Name: DBClusterIdentifier Value: !Ref RdsDBInstanceIdentifier RDSDatabaseConnectionsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} Aurora DatabaseConnections MetricName: DatabaseConnections Namespace: AWS/RDS Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 100 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanOrEqualToThreshold # 閾値以上 Dimensions: - Name: DBClusterIdentifier Value: !Ref RdsDBInstanceIdentifier RDSDeadlocksAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} Aurora デットロック回数 MetricName: Deadlocks Namespace: AWS/RDS Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 0 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanThreshold # 閾値より大きい Dimensions: - Name: DBClusterIdentifier Value: !Ref RdsDBInstanceIdentifier RDSFreeableMemoryAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} Aurora 空きメモリ容量 MetricName: FreeableMemory Namespace: AWS/RDS Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 104857600 # 閾値 (100MB) TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: LessThanOrEqualToThreshold # 閾値以下 Dimensions: - Name: DBClusterIdentifier Value: !Ref RdsDBInstanceIdentifier RDSCPUUtilizationAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmActions: - !Ref SNSTopicName # アラーム時のアクション AlarmName: !Sub ${SystemName} Aurora CPU 使用率 MetricName: CPUUtilization Namespace: AWS/RDS Statistic: Average # 平均 Period: 60 # 期間[s] EvaluationPeriods: 1 # 閾値超過回数 Threshold: 90 # 閾値 TreatMissingData: breaching # 欠落データは不良 OKActions: - !Ref SNSTopicName # 復旧時のアクション ComparisonOperator: GreaterThanOrEqualToThreshold # 閾値以上 Dimensions: - Name: DBClusterIdentifier Value: !Ref RdsDBInstanceIdentifier 実際のソース ソースは以下 GitHub に上げておきましたので宜しければお使いください。 GitHub : CloudFormation-Templates CloudWatch-Alarm ※ 随時更新しているため上記記載の内容とは若干異なる場合があります 最後に 今回は CloudFormation を使って CloudWatch Alarm を作成しました。 今まで CloudWatch 系のブログをいくつか書いてきましたが、一旦の集大成です。 よろしければお使いください。
アバター
こんにちは、インフラエンジニアの綿引です。 今回は AWS CloudWatch で EC2 の Linux プロセスを監視する方法を記載したいと思います。 対象の方は以下のような方でしょうか。 監視運用を導入するまでアラートをウォッチしてしておきたい コストを抑えるためスモールスタートで監視を実施したい 監視の項目に EC2 のプロセス監視も加えたい また CloudWatch での監視にご興味のある方は、過去の CloudWatch 関連記事のリンクを貼っておきますので、こちらもよろしければご覧ください。 ・Amazon CloudWatch + Amazon SNS + AWS Chatbot を使ってアラームを Slack に通知してみる ・CloudWatch で EC2 のメモリ・ディスク使用率を監視する プロセス監視の実装 では早速プロセス監視の実装をしていきます。 今回使用するサービスは以下です。 使用サービス 用途 CloudWatch メトリクス プロセス監視のカスタムメトリクスを作成 CloudWatch Alarm プロセス監視のカスタムメトリクスを監視 EC2 CloudWatch エージェントの procstat プラグインでメトリクスを収集 Systems Manager Run Command EC2 の CloudWatch エージェントにパラメータストアの内容を適用 Systems Manager パラメータストア procstat プラグインの設定を保存 なお、OS は CentOS7 となっております。 前提 まず前提として、対象の EC2 に「CloudWatch エージェント」がインストールされている必要があります。 今回、プロセス監視には CloudWatch エージェントの「 procstat プラグイン 」で収集できる「 pid_count 」というメトリクスを使用しているためです。 procstat プラグインの情報は公式の以下に記載されています。 ・procstat プラグインでプロセスメトリクスを収集する CloudWatch エージェントのインストールがまだの場合は、まずインストールを行って頂ければと思います。 インストール方法は以下に書いてあるので、よろしければご覧ください。 ・CloudWatch で EC2 のメモリ・ディスク使用率を監視する Systems Manager パラメータストアの設定 次は CloudWatch エージェントに適用する procstat の設定をパラメータストアに記載します。 マネジメントコンソールから「AWS Systems Manager」→「パラメータストア」→「パラメータの作成」を選択して設定を入力していきます。 名前や説明は任意ですので適宜変更してください。 設定項目 設定値 名前 CloudWatch-Alarm-Process-Check 説明 CloudWatch-Alarm-Process-Check 利用枠 標準 タイプ 文字列 データ型 text 値 ※ 以下参照 値に関しては、メトリクスに追加するプロセスが httpd でメトリクス収集間隔を 60秒 にしています。 { "metrics": { "metrics_collected": { "procstat": [ { "exe": "httpd", "measurement": [ "pid_count" ], "metrics_collection_interval": 60 } ] } } } もし複数のプロセスを監視したい場合は以下のように設定を可能です。 { "metrics": { "metrics_collected": { "procstat": [ { "exe": "httpd", "measurement": [ "pid_count" ], "metrics_collection_interval": 60 }, { "exe": "sshd", "measurement": [ "pid_count" ], "metrics_collection_interval": 60 }, { "exe": "crond", "measurement": [ "pid_count" ], "metrics_collection_interval": 60 } ] } } } パラメータストアの設定が完了したら、Run Command を使って CloudWatch エージェントに適用します。 Systems Manager Run Commandの実行 こちらもマネジメントコンソールから「AWS Systems Manager」→「Run Command」→「Run Command」を選択して設定を入力していきます。 基本デフォルトですが、以下のみ変更します。 設定項目 設定値 コマンドドキュメント AmazonCloudWatch-ManageAgent Action Configure (append) Optional Configuration Location ※ パラメータストアで作成した「名前」の部分 ターゲット ※ 任意の EC2 最後に「実行」を選択し、正常終了すればOKです。 私の場合、何回か繰り返していたら「実行」が失敗するようになってしまったのですが、古い設定が残っていたのが原因だったようです。 以下ディレクトリ配下のファイルを消してみたら正常に終了するようになりました。 /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/ ここまで完了すれば CloudWatch メトリクス にプロセスのメトリクスが追加されているはずです。 CloudWatch メトリクスの確認 マネジメントコンソールから「CloudWatch」→「メトリクス」→「CWAgent」を選択すると、「ImageId,InstanceId,InstanceType,exe,pid_finder」という項目が増えていました。 これを選択すると、先ほどパラメータストアで設定したプロセスのメトリクスが追加されているはずです。 ※ 以下の画像はいろいろなプロセスを監視追加した場合のものです。 後は、CloudWatch Alarm で「プロセスが 0 になったら」や「プロセスが2以下になったら」など、適宜条件をつけて頂ければ監視が可能になります。 監視の設定方法については、上記のように手動でも設定可能ですが CloudFormation の方が楽なので、別記事で書こうと思います。 宜しければそちらもご覧ください。 最後に 今回 はAWS CloudWatch でプロセス監視を実施してみました。 設定自体は楽ですがサーバによって監視するプロセスが異なると思いますので、後はどこまで自動化できるかが大事かなと思いました。 次はまた CloudFormation に戻って、CloudWatch ダッシュボードの作成や、今回のプロセス監視を含めた CloudWatch Alarm の設定を書きたいと思います。
アバター
こんにちは、インフラエンジニアの綿引です。 今回は AWS CloudFormation で EC2・ALB・RDS (Aurora) の CloudWatch ダッシュボードを作成したいと思います。 CloudWatch ダッシュボードでモニタリングを行いたが、「監視したいメトリクスが多い」や「環境毎に設定するのが面倒」という理由で敬遠されている方も多いのではないでしょうか? 私も上記の理由でなかなか手を出せずにいたのですが、今回 CloudFormation を用いることでこれを解決できましたので、宜しければ参考にして頂ければと思います。 対象の方は以下のような方でしょうか。   EC2・ALB・RDS (Aurora)を CloudWatch ダッシュボード でモニタリングしたい CloudWatch ダッシュボードを手動で作りたくない 監視の内製化を検討している   テンプレートファイル作成 では早速テンプレートファイルを作成していきます。 改めてモニタリング対象のサービスは以下です。   EC2 ALB RDS (Aurora)   以下にソースを記載しますが、もし「EC2 だけでいい」や「ALB と RDS (Aurora) だけでいい」などあれば不要部分を削って頂ければと思います。 監視項目とメトリクス一覧 今回監視するメトリクスを一覧にしました。 監視項目(自分で勝手につけました)と対応するメトリクス、名前空間を記載しています。 どのサービスの監視項目かは名前空間を見て頂ければと思います。 監視項目 名前空間 監視メトリクス EC2 CPU 使用率 AWS/EC2 CPUUtilization EC2 CPU クレジットバランス AWS/EC2 CPUCreditBalance EC2 メモリ使用率 CWAgent mem_used_percent EC2 swap 使用率 CWAgent swap_used_percent EC2 ディスク読み取り回数 CWAgent diskio_reads EC2 ディスク書き込み回数 CWAgent diskio_writes EC2 ディスクI/O 時間 CWAgent diskio_io_time EC2 ディスク使用率 CWAgent disk_used_percent EC2 ステータスチェック失敗 AWS/EC2 StatusCheckFailed “ “ StatusCheckFailed_Instance “ “ StatusCheckFailed_System ALB 正常ターゲット数 AWS/ApplicationELB HealthyHostCount ALB リクエスト数 AWS/ApplicationELB RequestCount ALB ターゲットの応答時間 (秒) AWS/ApplicationELB TargetResponseTime ALB 有効接続数 AWS/ApplicationELB ActiveConnectionCount ALB 新規接続数 AWS/ApplicationELB NewConnectionCount ALB プロセスされたバイト数 AWS/ApplicationELB ProcessedBytes ALB 接続エラー数 (ALB 最大接続超過) AWS/ApplicationELB RejectedConnectionCount ALB 接続エラー数 (LB – ターゲット間) AWS/ApplicationELB TargetConnectionErrorCount ALB TLS接続エラー数 (クライアント – LB間) AWS/ApplicationELB ClientTLSNegotiationErrorCount ALB TLS接続エラー数 (LB – ターゲット間) AWS/ApplicationELB TargetTLSNegotiationErrorCount ALB ELB 3XX (カウント) AWS/ApplicationELB HTTPCode_ELB_3XX_Count ALB ELB 4XX (カウント) AWS/ApplicationELB HTTPCode_ELB_4XX_Count ALB ELB 5XX (カウント) AWS/ApplicationELB HTTPCode_ELB_5XX_Count Aurora CPU 使用率 AWS/RDS CPUUtilization Aurora DatabaseConnections AWS/RDS DatabaseConnections Aurora 空きメモリ容量 AWS/RDS FreeableMemory Aurora CPU クレジットバランス AWS/RDS CPUCreditBalance Aurora クエリ実行回数 (秒) AWS/RDS Queries Aurora デットロック回数 (秒) AWS/RDS Deadlocks Aurora Select レイテンシー AWS/RDS SelectLatency Aurora Insert レイテンシー AWS/RDS InsertLatency Aurora Update レイテンシー AWS/RDS UpdateLatency Aurora Commit レイテンシー AWS/RDS CommitLatency Aurora Delete レイテンシー AWS/RDS DeleteLatency 構成や環境などによって監視したいメトリクスも異なるかとは思いますので、必要なメトリクスがなかったり、不要なメトリクスがある場合は、任意でカスタマイズして頂ければと思います。 また「EC2 ステータスチェック失敗」のみ、インスタンスステータスチェックと、システムステータスチェックのどちらで失敗しているかを把握したかったため、複数の監視メトリクスを指定しています。 テンプレートファイル 次は実際のテンプレートファイルです。 今回も yaml で記載しています。 基本的に可変部分は「Parameters」を用いることで共有化しているため、Parameters 部分を環境に合わせて変更いただければ問題ないと思います。 また念のため、CloudFormation 側が成功しても、ダッシュボード側で問題なくメトリクスが表示されているかを確認いただけると間違いないかと思います。 変更点・注意点を以下に記載しますのでご確認ください。   環境に合わせて「Parameters」の XXXX 部分を変更 「EC2 ディスク」関連項目の name,device の「nvme0n1」と、fstype の「xfs」は必要に応じて変更 CloudFormation 成功後にダッシュボード側をちゃんと確認   AWSTemplateFormatVersion: '2010-09-09' Description: CloudWatch Dashboard ##################################################################### # Parameters 設定 ##################################################################### Parameters: Ec2InstanceId: Description: Ec2 InstanceId Type: AWS::EC2::Instance::Id Ec2ImageId: Description: Ec2 ImageId (AMIID) Type: String Default: ami-XXXXXXXXXXXX # EC2 の ImageId を記載 Ec2InstanceType: Description: Ec2 InstanceType Type: String Default: XXXXXX # インスタンスタイプを記載 AlbLoadBalancer: Description: AlbLoadBalancer Type: String Default: app/XXXXXX/XXXXXXXXXXX # ALB の ARN を記載 AlbTargetGroup: Description: ALB TargetGroup Type: String Default: targetgroup/XXXXXX/XXXXXXXXXXX # ターゲットグループの ARN を記載 RdsDBInstanceIdentifier: Description: RDS DBInstanceIdentifier Type: String Default: XXXXXX # DB クラスター識別子を記載 ##################################################################### # Resources 設定 ##################################################################### Resources: # CloudWatchダッシュボードの定義 ##################################################################### # ダッシュボード設定 ##################################################################### CWDashboard: Type: AWS::CloudWatch::Dashboard Properties: DashboardName: !Sub '${AWS::StackName}' DashboardBody: !Sub | { "widgets": [ { "type": "metric", "x": 0, "y": 0, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/EC2", "CPUUtilization", "InstanceId", "${Ec2InstanceId}" ] ], "region": "ap-northeast-1", "yAxis": { "left": { "min": 0, "max": 100 } }, "title": "EC2 CPU 使用率" } }, { "type": "metric", "x": 12, "y": 0, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/EC2", "CPUCreditBalance", "InstanceId", "${Ec2InstanceId}" ] ], "region": "ap-northeast-1", "title": "EC2 CPU クレジットバランス" } }, { "type": "metric", "x": 0, "y": 6, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "CWAgent", "mem_used_percent", "InstanceId", "${Ec2InstanceId}", "ImageId", "${Ec2ImageId}", "InstanceType", "${Ec2InstanceType}" ] ], "region": "ap-northeast-1", "yAxis": { "left": { "min": 0, "max": 100 } }, "title": "EC2 メモリ使用率" } }, { "type": "metric", "x": 12, "y": 6, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "CWAgent", "swap_used_percent", "InstanceId", "${Ec2InstanceId}", "ImageId", "${Ec2ImageId}", "InstanceType", "${Ec2InstanceType}" ] ], "region": "ap-northeast-1", "title": "EC2 swap 使用率" } }, { "type": "metric", "x": 0, "y": 12, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "CWAgent", "diskio_reads", "InstanceId", "${Ec2InstanceId}", "ImageId", "${Ec2ImageId}", "name", "nvme0n1", "InstanceType", "${Ec2InstanceType}" ] ], "region": "ap-northeast-1", "title": "EC2 ディスク読み取り回数" } }, { "type": "metric", "x": 12, "y": 12, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "CWAgent", "diskio_writes", "InstanceId", "${Ec2InstanceId}", "ImageId", "${Ec2ImageId}", "name", "nvme0n1", "InstanceType", "${Ec2InstanceType}" ] ], "region": "ap-northeast-1", "title": "EC2 ディスク書き込み回数" } }, { "type": "metric", "x": 12, "y": 18, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "CWAgent", "diskio_io_time", "InstanceId", "${Ec2InstanceId}", "ImageId", "${Ec2ImageId}", "name", "nvme0n1", "InstanceType", "${Ec2InstanceType}" ] ], "region": "ap-northeast-1", "title": "EC2 ディスクI/O 時間" } }, { "type": "metric", "x": 0, "y": 18, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "CWAgent", "disk_used_percent", "path", "/", "InstanceId", "${Ec2InstanceId}", "ImageId", "${Ec2ImageId}", "InstanceType", "${Ec2InstanceType}", "device", "nvme0n1p1", "fstype", "xfs" ] ], "region": "ap-northeast-1", "yAxis": { "left": { "label": "", "max": 100, "min": 0 } }, "title": "EC2 ディスク使用率" } }, { "type": "metric", "x": 0, "y": 24, "width": 24, "height": 6, "properties": { "view": "timeSeries", "stacked": true, "metrics": [ [ "AWS/EC2", "StatusCheckFailed", "InstanceId", "${Ec2InstanceId}" ], [ ".", "StatusCheckFailed_Instance", ".", "." ], [ ".", "StatusCheckFailed_System", ".", "." ] ], "region": "ap-northeast-1", "title": "EC2 ステータスチェック失敗" } }, { "type": "metric", "x": 0, "y": 30, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "HealthyHostCount", "TargetGroup", "${AlbTargetGroup}", "LoadBalancer", "${AlbLoadBalancer}", "AvailabilityZone", "ap-northeast-1a" ] ], "region": "ap-northeast-1", "title": "ALB 正常ターゲット数" } }, { "type": "metric", "x": 12, "y": 30, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "RequestCount", "TargetGroup", "${AlbTargetGroup}", "LoadBalancer", "${AlbLoadBalancer}", "AvailabilityZone", "ap-northeast-1a" ] ], "region": "ap-northeast-1", "title": "ALB リクエスト数" } }, { "type": "metric", "x": 0, "y": 42, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", "${AlbLoadBalancer}", "AvailabilityZone", "ap-northeast-1a" ] ], "region": "ap-northeast-1", "title": "ALB ターゲットの応答時間 (秒)" } }, { "type": "metric", "x": 0, "y": 36, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "ActiveConnectionCount", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB 有効接続数" } }, { "type": "metric", "x": 12, "y": 36, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "NewConnectionCount", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB 新規接続数" } }, { "type": "metric", "x": 12, "y": 42, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "ProcessedBytes", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB プロセスされたバイト数" } }, { "type": "metric", "x": 0, "y": 48, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "RejectedConnectionCount", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB 接続エラー数 (ALB 最大接続超過)" } }, { "type": "metric", "x": 12, "y": 48, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "TargetConnectionErrorCount", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB 接続エラー数 (LB - ターゲット間)" } }, { "type": "metric", "x": 12, "y": 54, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "ClientTLSNegotiationErrorCount", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB TLS接続エラー数 (クライアント - LB間)" } }, { "type": "metric", "x": 0, "y": 54, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "TargetTLSNegotiationErrorCount", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB TLS接続エラー数 (LB - ターゲット間)" } }, { "type": "metric", "x": 0, "y": 60, "width": 6, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "HTTPCode_ELB_3XX_Count", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB ELB 3XX (カウント)" } }, { "type": "metric", "x": 6, "y": 60, "width": 6, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "HTTPCode_ELB_4XX_Count", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB ELB 4XX (カウント)" } }, { "type": "metric", "x": 12, "y": 60, "width": 6, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/ApplicationELB", "HTTPCode_ELB_5XX_Count", "LoadBalancer", "${AlbLoadBalancer}" ] ], "region": "ap-northeast-1", "title": "ALB ELB 5XX (カウント)" } }, { "type": "metric", "x": 0, "y": 66, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "CPUUtilization", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora CPU 使用率" } }, { "type": "metric", "x": 0, "y": 72, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "DatabaseConnections", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora DatabaseConnections" } }, { "type": "metric", "x": 12, "y": 72, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "FreeableMemory", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora 空きメモリ容量" } }, { "type": "metric", "x": 12, "y": 66, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "CPUCreditBalance", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora CPU クレジットバランス" } }, { "type": "metric", "x": 0, "y": 78, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "Queries", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora クエリ実行回数 (秒)" } }, { "type": "metric", "x": 12, "y": 78, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "Deadlocks", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora デットロック回数 (秒)" } }, { "type": "metric", "x": 0, "y": 84, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "SelectLatency", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora Select レイテンシー" } }, { "type": "metric", "x": 12, "y": 84, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "InsertLatency", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora Insert レイテンシー" } }, { "type": "metric", "x": 12, "y": 90, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "UpdateLatency", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora Update レイテンシー" } }, { "type": "metric", "x": 0, "y": 90, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "CommitLatency", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora Commit レイテンシー" } }, { "type": "metric", "x": 0, "y": 96, "width": 12, "height": 6, "properties": { "view": "timeSeries", "stacked": false, "metrics": [ [ "AWS/RDS", "DeleteLatency", "DBClusterIdentifier", "${RdsDBInstanceIdentifier}" ] ], "region": "ap-northeast-1", "title": "Aurora Delete レイテンシー" } } ] } 実際のソース ソースは以下 GitHub に上げておきましたので宜しければお使いください。 GitHub : CloudFormation-Templates CloudWatch-Dashboard ※ 随時更新しているため上記記載の内容とは若干異なる場合があります 最後に 今回は CloudFormation を使って CloudWatch のダッシュボードを作成しました。 ソースはちょっと長いですが、CloudWatch ダッシュボードは個別に用意することがしんどいので CloudFormation でできると非常に嬉しいです。 今回は「プロセス監視」の部分はダッシュボードに含めませんでしたが、今後加えようかなと思っております。 次は CloudWatch Alarm を作ってみようと思います。
アバター
こんにちは、インフラエンジニアの綿引です。 前回に引き続き、今回も AWS CloudFormation について記載したいと思います。 今回は「WAF のルール」を作成しようと思いますが、最初に以下ご注意ください。   Web ACLs や Conditions の作成ではなく Rules の作成である AWS WAF v2 ではなく AWS WAF Classic の設定である   対象の方は以下のような方でしょうか。   CloudFormation 初心者の方 WAF のルールを手動で作りたくない   テンプレートファイル作成 では早速テンプレートファイルを作成していきます。 今回は以下のテンプレートを作成していくのですが、「Global (CloudFront)」と「Regional WAF Resource」でテンプレートが異なりますのでご注意ください。 CloudFront に設定したかったら Global 用のテンプレートで、ALB などにつけたい場合は Regional 側のテンプレートですね。 作成するテンプレートファイル 内容 WAF-generic-detect-sqli-rules-Regional.yaml SQLインジェクション対策用のルールを作成 (Regional) WAF-generic-detect-sqli-rules.yaml SQLインジェクション対策用のルールを作成 (Global) WAF-generic-detect-xss-rules-Regional.yaml XSS対策用のルールを作成 (Regional) WAF-generic-detect-xss-rules.yaml XSS対策用のルールを作成 (Global) WAF-ip-block-rules-Regional.yaml IP ベースのブロックルールを作成 (Regional) WAF-ip-block-rules.yaml IP ベースのブロックルールを作成 (Global) WAF-ua-block-rules-Regional.yaml UserAgent ベースのブロックルールを作成 (Regional) WAF-ua-block-rules.yaml UserAgent ベースのブロックルールを作成 (Global) まずは Global と Regional のソースの違いです。 Global と Regional のソースの違い 違いとしては Type が「WAF」か「WAFRegional」かの違いです。 ・Global 用 AWSTemplateFormatVersion: "2010-09-09" Resources: SqlInjDetection: Type: "AWS::WAF::SqlInjectionMatchSet" ・Regional 用 Resources: SqlInjDetection: Type: "AWS::WAFRegional::SqlInjectionMatchSet" # ここの真ん中が異なる テンプレート内の後の記載は一緒なので、以下には「Global」側のみ記載いたします。 SQLインジェクション対策用のルールを作成 設定内容としては以下です。   ルール名は「generic-detect-sqli」 Filter の設定は Header cookie・Query string・URI に HTML decode と URI decode SqlInjDetection の部分で「conditions」を作成し、SqlInjRule で「ルール」を作成 ルール作成の DataId の部分で、上部で定義した「conditions」を指定   ソースは以下になります。 AWSTemplateFormatVersion: "2010-09-09" Resources: SqlInjDetection: Type: "AWS::WAF::SqlInjectionMatchSet" Properties: Name: "generic-detect-sqli" SqlInjectionMatchTuples: - FieldToMatch: Type: URI TextTransformation: URL_DECODE - FieldToMatch: Type: URI TextTransformation: HTML_ENTITY_DECODE - FieldToMatch: Type: QUERY_STRING TextTransformation: URL_DECODE - FieldToMatch: Type: QUERY_STRING TextTransformation: HTML_ENTITY_DECODE - FieldToMatch: Type: HEADER Data: cookie TextTransformation: URL_DECODE - FieldToMatch: Type: HEADER Data: cookie TextTransformation: HTML_ENTITY_DECODE SqlInjRule: Type: "AWS::WAF::Rule" Properties: Name: "generic-detect-sqli-rules" MetricName: "SqlInjRule" Predicates: - DataId: Ref: "SqlInjDetection" Negated: false Type: "SqlInjectionMatch" XSS対策用のルールを作成 こちらはSQLインジェクション対策用のルールとほぼ同様なので、ソースだけ以下に記載します。 AWSTemplateFormatVersion: "2010-09-09" Resources: DetectXSS: Type: "AWS::WAF::XssMatchSet" Properties: Name: "generic-detect-xss" XssMatchTuples: - FieldToMatch: Type: URI TextTransformation: URL_DECODE - FieldToMatch: Type: URI TextTransformation: HTML_ENTITY_DECODE - FieldToMatch: Type: QUERY_STRING TextTransformation: URL_DECODE - FieldToMatch: Type: QUERY_STRING TextTransformation: HTML_ENTITY_DECODE - FieldToMatch: Type: HEADER Data: cookie TextTransformation: URL_DECODE - FieldToMatch: Type: HEADER Data: cookie TextTransformation: HTML_ENTITY_DECODE XSSRule: Type: "AWS::WAF::Rule" Properties: Name: "generic-detect-xss-rules" MetricName: "XSSRule" Predicates: - DataId: Ref: "DetectXSS" Negated: false Type: "XssMatch" IP ベースのブロックルールを作成 こちら「Properties」の項目は少し異なりますが形式はほぼ同じです。「Value」部分にブロックしたい IP を記載しています。 AWSTemplateFormatVersion: "2010-09-09" Resources: MyIPSetBlacklist: Type: "AWS::WAF::IPSet" Properties: Name: "ip-block-list" IPSetDescriptors: - Type: "IPV4" Value: "XXX.XXX.XXX.XXX/32" # 拒否したい IP を記載 - Type: "IPV4" Value: "XXX.XXX.XXX.XXX/32" # 拒否したい IP を記載 MyIPSetRule: Type: "AWS::WAF::Rule" Properties: Name: "ip-block-rules" MetricName: "MyIPSetRule" Predicates: - DataId: Ref: "MyIPSetBlacklist" Negated: false Type: "IPMatch" UserAgent ベースのブロックルールを作成 こちらもほぼ同様です。「TargetString」部分にブロックしたい文字列を記載しています。 今回は例として IE6 を拒否するような形で書いておりますが、「TargetString」の部分を変更いただければご指定の文字列で拒否できるようになります。 (その際 Name なども設定内容に合うよう変更すると良いかと思います。) AWSTemplateFormatVersion: "2010-09-09" Resources: BlockStringSetUAIE6: Type: "AWS::WAF::ByteMatchSet" Properties: Name: "restrict-user-agent-IE6" ByteMatchTuples: - FieldToMatch: Type: "HEADER" Data: "User-Agent" TargetString: "Mozilla/4.0 (compatible; MSIE 6.0;" TextTransformation: "NONE" PositionalConstraint: "CONTAINS" BlockStringRules: Type: "AWS::WAF::Rule" Properties: Name: "ua-block-rules" MetricName: "BlockStringRules" Predicates: - DataId: Ref: "BlockStringSetUAIE6" Negated: false Type: "ByteMatch" 実際のソース ソースは以下 GitHub に上げておきましたので宜しければお使いください。 GitHub : CloudFormation-Templates WAF ※ 随時更新しているため上記記載の内容とは若干異なる場合があります   最後に 今回は CloudFormation を使って WAF のルールを作成しました。 WebACL の作成でも良かったのですが、ルールの方が使いやすいかなと思い、今回はルール作成にしております。 もちろん conditions だけの作成もできるので、ご自身の環境に応じてカスタマイズいただければと思います。 次は CloudWatch ダッシュボードのルールも作ってみます。
アバター
こんにちは、インフラエンジニアの綿引です。 今回は AWS CloudFormation について記載したいと思います。 CloudFormation は今まで敬遠してきたのですが、実際に触ってみたら非常に有能でした。。 そこで手始めにセキュリティグループを作ってみたので共有したいと思います。 対象の方は以下のような方でしょうか。   CloudFormation 初心者の方 セキュリティグループを手動で作りたくない   テンプレートファイル作成 では早速テンプレートファイルを作成していきます。 今回は json ではなく、yaml で以下の2つのテンプレートを作成します。   SG-http-https-public.yaml : http と https を許可するセキュリティグループを作成 SG-base.yaml : 拠点 IP のみ許可するセキュリティグループを作成   http と https を許可セキュリティグループを作成 まずソースとしては以下になります。 AWSTemplateFormatVersion: "2010-09-09" Resources: WebSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "http,https public" GroupName: http-https-public # セキュリティグループの名前 を記載 SecurityGroupIngress: - IpProtocol: tcp FromPort : 80 ToPort : 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort : 443 ToPort : 443 CidrIp: 0.0.0.0/0 VpcId: vpc-XXXXXXXXXXX # VPC ID を記載 Properties の各項目の説明は以下です。 項目 内容 GroupDescription セキュリティグループの説明 GroupName セキュリティグループの名前 SecurityGroupIngress インバウンドルールを宣言 IpProtocol IP プロトコル FromPort ポート範囲の開始番号 FromPort ポート範囲の終了番号 CidrIp IPv4 範囲 VpcId VPC の ID VpcId だけはお使いの環境によりますので、 vpc-XXXXXXXXXXX を変更いただければと思います。 拠点 IP のみ許可するセキュリティグループを作成 次のソースはこれです。 AWSTemplateFormatVersion: "2010-09-09" Resources: WebSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "base ip list" GroupName: base # セキュリティグループの名前 を記載 SecurityGroupIngress: - IpProtocol: -1 # 全てのプロトコルを許可 CidrIp: XXX.XXX.XXX.XXX/32 # 許可したい IP を記載 Description: base1 - IpProtocol: -1 # 全てのプロトコルを許可 CidrIp: XXX.XXX.XXX.XXX/32 # 許可したい IP を記載 Description: base2 VpcId: vpc-XXXXXXXXXXX # VPC ID を記載 基本的に1つ目のものと変わりませんが「IpProtocol」を「-1」にすることで全てのプロトコルを許可しています。 また「CidrIp」には許可したい IP に変更してください。サブネットも /24 や /29 など自由に変えられます。 他にも「Description」は「説明」になりますので、許可IP が何に該当するかを記載しておくとわかりやすいと思います。 あとは CloudFormation で実行するだけです。実行方法については他にもわかりやすい記事がたくさんあるので割愛したいと思います。 実際のソース ソースは以下 GitHub に上げておきましたので宜しければお使いください。 GitHub : CloudFormation-Templates SecurityGroup ※ 随時更新しているため上記記載の内容とは若干異なる場合があります 最後に 今回は CloudFormation を使ってセキュリティグループを作成しました。 IP をいちいち登録する手間がなく非常に楽だったので、今後使っていきたいと思いました。 次は WAF のルールも作ってみます。
アバター
こんにちは、インフラエンジニアの綿引です。 最近弊社サービスで急なスパイクアクセスがあり、データベースにかなりの負荷がかかってしまいました。。 そこで解決策として「Aurora のオートスケーリング」を導入しました。 今回は導入にあたって検証を行ったので、その際の設定方法と検証結果を記載していきたいと思います。 対象の方は以下のような方でしょうか。 急なスパイクアクセスに備えて Aurora にオートスケーリングの設定を入れておきたい スパイクアクセスに備えてあまり使ってない Aurora レプリカを追加している Aurora AutoScaling とは Aurora Auto Scaling とは「スケーリングポリシー」を設定することで Aurora のレプリカ数を自動で増やすことができる機能です。 Aurora MySQL だけでなく Aurora PostgreSQL でも使用できます。 オートスケーリングさせるトリガーは以下となります。 Aurora レプリカの平均 CPU 使用率 Aurora レプリカの平均接続数 また Auto Scaling で増えたレプリカに関しては負荷や接続数が減ると自動で削除もしてくれます。 トリガーも CPU 使用率・接続数と設定しやすいですし、自動で削除まで行ってくれるのはコスト的にもありがたいですね。 設定方法と検証 構成について 今回は以下の構成で実施していきます。 クラスタ名 : autoscaling-test DBインスタンス1 : autoscaling-test-instance-1 DBインスタンス2 : autoscaling-test-instance-2 DBインスタンスが2つある理由としては「プライマリインスタンスと、少なくとも1つの Aurora レプリカが必要」という Auto Scaling の制約があるからです。 DBインスタンスが1つの状態でも Auto Scaling の設定はできますが、設定後に自動でAurora レプリカが1台作成されます。 スケーリングポリシーの設定 では早速設定を行なっていきます。 まずは Amazon RDS のコンソールから対象のクラスタを選択して「アクション」→「レプリカの Auto Scaling の追加」を選択します。 次にスケーリングポリシーを設定していきます。今回はテスト用に「ターゲット値」を 1% にして以下の設定値にしました。 実際に設定する時は 80% や 90%などになるかと思います。 項目 設定値 ポリシー名 autoscaling-test IAM ロール ※ デフォルト ターゲットメトリクス Aurora レプリカの平均 CPU 使用率 ターゲット値 1 % (※ テストのため) スケールイン 有効 スケールインクールダウン期間 60 スケールアウトクールダウン期間 60 最小キャパシティー 1 最大キャパシティー 3 実際の画面はこのような形です。 上記の設定が終わったら最後に「ポリシーの追加」を押下します。 テスト ではテストしていきます。 ポリシーの追加後、早速2台「application-autoscaling-XXXXXXXX」という名前で作成されました。 次はポリシーの設定を変更して、追加されたレプリカが削除されるか確認します。 項目 設定値 ターゲット値 1 % → 90 % ポリシーの変更後、まず2台あったうちの1台のステータスが「削除中」となりましたが、もう一台は「利用可能」のままです。 削除されないのか?と思ったのですが、上記の「削除中」のものが完全に削除されたら、もう一台の方が「削除中」のステータスに変わりました。 仕様なのか1台ずつ削除されるようです。 これで Aurora の AutoScaling の挙動も確認できました!これなら急なスパイクアクセスが来ても大丈夫そうですね! 最後に 今回は Aurora AutoScaling を検証しました。 非常に楽で特殊な制約もなく実現できたので、個人的にはどんどん導入していきたいなと感じました。 次は EC2 の AutoScaling もやってみます。
アバター
こんにちは、インフラエンジニアの綿引です。 Webサーバー側で接続元 IP を取得したかったけどよく見ると ELB やプロキシサーバの IP だった、、 という経験をされた方もいらっしゃるのではないでしょうか。 そこで今回は Apache と Nginx で接続元 IP を取得する方法を記載したいと思います。 対象の方は以下のような方でしょうか。 ELB などを使用して運用している 前段にプロキシサーバを配置している Apache の設定方法 環境 環境は以下で検証しております。 CentOS 7 Apache 2.4 実装方法 Apache では mod_remoteip というモジュールを使用します。 Apache 2.4 からは標準で導入されていますが、それ以前のバージョンだと入っていないため Github などからクローンする必要があるようです。 まずは mod_remoteip が組み込まれているか確認しましょう。 以下のコマンドで remoteip_module (shared) と表示されていれば大丈夫です。 $ httpd -M | grep "remoteip" remoteip_module (shared) 次に httpd.conf に以下を記載します。 RemoteIPHeader x-forwarded-for 後はログフォーマットを変更します。 デフォルトの combined や common などを使用している場合 「%h」 のリモートホスト名が記載されているため、 「%a」 のアクセス元のIPアドレスに変更、または追加します。 以下は combined を例として記載しております。 変更前 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 変更後 LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 最後に Apache の再起動をして完了です。 # systemctl status httpd # systemctl reload httpd # systemctl status httpd これでアクセスログに接続元 IP が出力されるようになります。 次に Nginx です。 Nginx の設定方法 環境 環境は以下で検証しております。 CentOS 7 Nginx 1.16.1 実装方法 Nginx では ngx_http_realip_module というモジュールを使用します。 ngx_http_realip_module は現在 Nginx を使用されていればデフォルトで使用できるかと思います。 今回は Nginx 1.16.1 で検証しましたが、1.10 系のものでも使用できました。 設定方法は nginx.conf に以下を追加します。 set_real_ip_from XXX.XXX.XXX.XXX/XX; real_ip_header X-Forwarded-For; set_real_ip_from の XXX 部分には信頼できる IP アドレスのレンジを記載します。 例えば ALB などを使用している場合は VPC のセグメントで良いと思いますし、プロキシサーバがある場合はそのサーバの IP で良いかと思います。 ログフォーマットに関しては、 $remote_addr が接続元 IP になります。 こちらに関しては使用されている方が大半だと思いますので、特に変更はいらないかと思います。 最後に Nginx の再起動をして完了です。 # systemctl status nginx # systemctl reload nginx # systemctl status nginx 最後に 今回は Apache と Nginx で接続元 IP を取得する方法を記載しました。 地味に必要となるケースが多いかと思いますので、是非参考にしていただければと思います。
アバター
こんにちは。 サーバーサイドエンジニア兼QAエンジニアの福山です。 QAチームでは、生産性高く、高品質なサービスを安定して提供するために テスト自動化基盤の構築を進めてきました。 自動テストのツール選定 自動テストの開発 自動テストの運用 の3本立てで、これまでに、自動テストのツール選定と開発についての記事を書かせていただきました。 QAチームの自動テスト推進 〜自動テストのツール選定編〜 QAチームの自動テスト推進 〜自動テストの開発編〜 自動テストのツール選定の結果、弊社では、 Bucky を使うことに決定しました。 本日は、3. 自動テストの運用についてです。 以下の流れで説明します。 ① どのように運用しているか ② 運用にのせるにあたり工夫したこと ③ 導入効果 ④ 運用でチューニングしたこと ⑤ 認証認可の対応 ⑥ 今後の課題 ① どのように運用しているか 自動テストの定期実行 現状は、前回の ブログ で記載した上記のシステム構成図のように、 Jenkinsの定期実行により、定時でSTG環境へスクレイピングし、エラーがあればSlack通知をしています。 運用時間は平日の9~18時の間に複数回、弊社の運用している複数サイトに対して、PCおよびスマートフォンで、リンクチェックとE2Eをコマンドを分けて、適切な時間を開けて実行しています。 エラー検知と確認 自動テストのSlack通知はQAエンジニアが確認しています。 エラーが出ると以下のような、メッセージが通知されます。 エラー発生時は、詳細を確認し、まずは偽陽性結果(テストデータなどによる誤検出)かどうかを判断し、バグが原因と判定したら、開発チームにエラーを報告して修正してもらう、という流れで運用しています。 DEV環境での自動テスト実行 基本的には、STG環境で日次で自動テストが動いています。ただし、影響範囲が広く開発工数が大きい開発案件の場合については、DEV環境での自動テスト実行ができるように、手動でJenkinsを実行できるコマンドも用意しています。開発案件のオリエン時に、QA担当とDEV環境でPukcy実行しましょう、と決まれば、DEV環境での開発完了後DEV環境での案件テストに入る前に自動テストPuckyの実行を開発担当のエンジニアにお願いしています。 自動テストのアップデート 自動テストでテスト実行している箇所について、ディレクターにもわかるようにリンクチェックしているURLとE2Eでチェックしているコンテンツをサイトマップに書き起こしています。 新しい案件で、URLが変更になったり、新たなURLが追加になったり、URLが無くなったりした場合には、このサイトマップをディレクターに更新してもらい、開発のオリエン時にQA担当に伝えてもらい、QAエンジニアが随時自動テストの更新をしています。 ② 運用にのせるにあたり工夫したこと 自動テストの愛称を『Pucky』に 社内での愛称をウエディングパーク(ウエパ)のBucky(バッキー)なので、『Pucky(パッキー)』とチームメンバーが命名してくれて、WPの自動テストを『Pucky』と呼びました。 ちょうどたまたま、開発期にライフルホームズとの コラボキャンペーン をやっていたこともあり、 Buckyの開発元LIFULLのキャラクターホームズくんとWPのキャラクター、ウエパちゃんを合わせた写真をPuckyのイメージ画像として印象に残りやすくしました。 ディレクターとエンジニア向けに説明会を複数回実施 自動テストはQAのエンジニアが開発しましたが、ディレクターにも案件を進める上で自動テストの理解をして欲しいので、ディレクター向けにも複数回、自動テストPuckyの説明会を実施しました。 Puckyとは何か、何をしているテストか、Puckyが担保しているものは具体的に何かということや、リンクチェックは手動でやった場合と自動テストでやった場合の動画を見せながら、説明しました。 初回の説明会では、中身の詳細まで把握できてないけど、自動テスト=Puckyという名前が社内のエンジニア&ディレクター間で知れ渡りました。 後半では、Puckyを案件開発でどのように活用していくかを中心に、説明会を実施しました。 また、エンジニア向けには、Puckyの中身が何をしているか(リンクチェックとE2Eの詳細)とエラーの見方を共有して、エラーを実際に探すというハンズオン勉強会を実施しました。 実際の開発案件で、DEV環境でPuckyを実行する事例も作りました。 このようにして、社内で自動テストPukcyの名が広まり、PHPバージョンアップなど影響範囲が広いリリースの際などにも活用していこうという動きも出てきました。 各所で使われることにより、価値のある自動テストになっていったと思います。 ③ 導入効果 実際にBuckyを使った自動テストを運用にのせてみて、見つかったエラーは以下のようなものがあります。 ・リンク切れの検知が多数 ・時間帯に応じて変わる仕様の検知 ・パフォーマンスが悪く、500エラーになるページ STGリリース後、本番リリース前に気付けた404エラーもありますし、 自動テスト導入したことで、あまり見られていないページでエラーを見つけられたケースもありました。 自動テストが定期的に回っていることで、新たに404になっていまうページが見つけやすくなったことで、 サイトの品質向上に大いに役立っていると思います。 ④ 運用でチューニングしたこと サーバーの負荷などにより処理中断が起きました。 スレッド数を調整したり、定期実行の時間をうまく調整することで、対処しました。 ⑤ 認証認可の対応 管理画面の認証系の対応については、 E2Eのテストで、 通常のユーザーと同じように、IDとパスワードでBuckyにログインを実行させ、 ページを開き、固定の文言をチェックする、というようなリンクチェック方式で実行することにしました。 ⑥ 今後の課題 自動テストは基本的にテスト環境(STG/DEV環境)で実行しているため、本番環境からのデータコピーによってデータが変わってしまったり、期間を持っているデータが古くなるなどで、自動テストでエラーになってしまう誤検知も多数あります。 ここは現状、気付いた時にデータを更新する対応をしています。 今後は、このテストデータの保持をどうしていくかの課題を解決していきたいと考えています。 まとめ 自動テストの最終章、最後までお読みいただきありがとうございます。 弊社の自動テストは1サイトから開発し、複数サイトへ広がり、チェックしているリンクも不足があれば拡充し、と半年ほどで大きく成長してきました。 優秀なチームメンバーに囲まれて、社内のディレクター・エンジニアの協力もあり、チームで自動テストPuckyをしっかり運用にのせることができ、サイトの品質を守っていける存在になれたことを私自身、とても嬉しく思います。 まだまだ課題はありますが、さらなる貢献のポテンシャルがあるので、引き続きQAチームで育てていきます。
アバター
はじめまして! Photorait のエンジニアをしていますヒエイです。 所属している社長室(新規事業チーム)で私が 定刻大臣 として行った、GaroonスケジュールのSlack通知機能導入をした話を紹介します。 「定刻大臣」について チーム活性化と定刻大臣 社長室ではエヴミニ(Everyone Minister〜全員大臣〜)というチーム活性化活動を行なっています。 室長除いた社長室全員が〇〇大臣となり、組織課題や活性化について改善・向上させる活動です。 詳しくは こちら でも紹介されてますので見てみてください! 私は、会議が時間通り始まらない、集まりが悪い、という課題に着眼して 定刻大臣 となりました。 ミッションは会議の定刻スタートを促進すること。 はじめは会議開始前に口頭で呼びかけをおこなっていましたが、あまり効果を感じられませんでした。 エンジニアとしてチームの活性化に貢献できる事は、エンジニアリングで返す事。 そこで、スケジュール管理をサイボウズGaroonで行なっている事に着眼して、以下施策を行うことにしました。 Garoon通知機能に関して Garoonのスケジュールを会議が始まる前に通知する機能を作ろうと考えました。 仕様として Garoonスケジュールの◯分前に、slackで通知する 簡単に導入できる(タスクの合間に開発作業ができる) 実行環境を用意したく無い メンバーのGaroonパスは私が管理しない。 などとして Google App Script を使った開発を進めました。 準備編 スプレッドシートとの連携 garoon_user_id garoon_password slack_channel slack_mention_user_id GaroonのユーザーID記載 Garoonのパスワード記載 通知するslackチャンネル メンションするslackユーザーのID こちらの形式でシート作成 作成したスプレッドシートの ツール → スクリプトエディタ でGASを開く URLの以下の部分をメモしておく 2020年9月現在 は、 script.google.com/a/〜〜〜/d/XXXX・・・/edit  の XXXX・・・ 文字列です。 slack app設定 https://api.slack.com/app でslack appを作成 作成したappの OAuth & Permissions で以下の権限を設定 Bot Token Scopes chat:write chat:write.public 作成したbotを テストツール でメッセージが送れるか確認 Basic Information の Display Information でアプリ名とアイコンを設定 App name お好きな名前 App icon & Preview お好きなアイコンを背定 最後に Installed App にて Bot User OAuth Access Token をメモする 実装 gas-clasp-starter を使うとtypescriptで開発可能で、ESLintやJestテストも入っているので便利です! spreadsheetの情報取得 const sheet = SpreadsheetApp.getActive().getSheetByName('シート名'); return sheet.getRange(2, 1, sheet.getLastRow() - 1, 4).getValues(); Garoon予定取得 const paramsArray = [ 'rangeStart=' + encodeURIComponent(Utilities.formatDate(date, 'JST', "yyyy-MM-dd'T'HH:mm:ssXXX")), 'orderBy=' + encodeURIComponent('start asc') ]; const paramsString = paramsArray.join('&'); const token = Utilities.base64Encode('GaroonのUserId' + ':' + 'Garoonのパスワード'); const url: string = 'https://' + 'Garoonのサブドメイン' + '.cybozu.com/g/api/v1/schedule/events?' + paramsString; const requestOptions = { method: 'get', headers: { 'X-Cybozu-Authorization': token } }; return JSON.parse(UrlFetchApp.fetch(url, requestOptions)); // この後ごにょごにょ通知対象ではないスケジュール等を除いて通知リストを作成 slackへ通知 const sendDetail = { text: 'メッセージ内容', channel: '通知先チャンネル', token: '上記で作成したslack token' }; const options: object = { method: 'post', payload: sendDetail }; UrlFetchApp.fetch('https://slack.com/api/chat.postMessage', options); dockerデプロイ 開発環境・GASへデプロイ用にdocker環境を用意します。 Dockerfile clasp を用意 FROM node:13.0-alpine WORKDIR /app RUN apk update RUN npm i @google/clasp -g CMD ["sh"] docker-compose.yml 特に変わったことはなし version: "3" services: app: build: context: ./ volumes: - ./:/app networks: - nw networks: nw: driver: bridge 以下のコマンドでGASにソースコードをアップロードします。 claspログイン ブラウザでパスを開き、GASのコード(上記でメモしたGASのパスXXXX〜)を設定 docker-compose run --rm app sh -c "clasp login --no-localhost;" clasp push コードをスプレッドシート連携しているgasにプッシュ npm run push はgas-clasp-starterの こちら が実行のイメージ。 docker-compose run --rm app sh -c "npm run push;" GAS側でソースコード確認。 トリガー設定 GASを開き、 編集 → 現在のプロジェクトのトリガー を開く トリガーを追加 をクリック 以下のように設定して保存 以上で、自動でGaroon予定をslack通知できる形になります。 実装後 定刻通知 アカウント管理 Garoonのアカウント情報はコーポレートIT室(情報システム部門)の方で管理してもらっています。 つまり、アカウント情報を記載したスプレッドシート・GASごとコーポレートIT室の方で管理してもらい、ソースコードだけそちらのGASにデプロイしています。 チーム活性化とエンジニア 社長室は全員でチームを盛り上げようと、お祭り気分も使いつつ、そしてフランクにお互いを尊敬し合い切磋琢磨しています。 エンジニアリングで活性化活動を という部分は最初は不安にも感じていました。 なぜなら私自身入社して間も無いタイミングでもあったことと、今まで行なってきた習慣を変えようと提案する事に反発は無いのだろうかと。 しかし社長室だけじゃなく全社的に相手の意見を受け入れる事、褒め称える文化があり、 導入サポートに対しても親身に対応していただき(実際には実装の他にGaroon権限管理やslack導入など他部署の協力もありました)、全てが滞りなく導入できました。 活性化として個人でやりたいと提案したものが、実導入までの早いという事が一番の驚きでした。 エンジニアならではの、 チーム活性化はエンジニアリングで を実践できる事、これはなかなか楽しいものです。
アバター
こんにちは。前撮りなど結婚写真の撮影スタジオ・サロンを検索できる情報サイト「Photorait」のエンジニアリングマネージャーをしている武田( @takedajs )です。 サイト運営している上で新規開発や既存機能の改修は必須ですが、リリース後に時間が経って発生する不具合にはみなさん頭を悩ませていると思います。 所属しているPhotoraitチームでは、開発中やリリース後に自動と手動を合わせて数種類の不具合を発見する仕組みを導入しています。また、Photoraitチームは専属のQAがいないので、開発メンバーが手動テストを実施しています。 今回は、既存の不具合を見つけるために実施している手動テストの1つである「回帰テスト」について紹介します。 回帰テストについて チームでは前から当たり前のように回帰テストと言っていたのですが、改めて、一般的な回帰テストの意味を調べてみました。 回帰テストとは、コンピュータプログラムに手を加えたことによる影響を確認するテスト操作のことである。 プログラムが大規模化で複雑化になってくると、何も関係がないかのように見えるプログラムが相互に関係しあっているのを見落とす場合も少なくない。ある箇所を改善しようとして加えた修正が、思いもよらない部分に影響してバグを呼び起こしてしまう、といった場合も珍しくない。 バグフィックスやリビジョンアップなどが行われた場合、システム全体のチェック作業に立ち返って(回帰して)コード改変の影響が確認される。想定外の異常が発生していないかを調べるためテストに立ち返るテストは、ほとんど必要不可欠な作業であるといえる。 回帰テストの意味や定義 Weblio辞書 なるほど、用語の意味としては理解していたのと同じっぽいですね。 Photoraitチームでは、案件のリリース後に影響範囲を手動テストしていますが、次から紹介する回帰テストでは、リリース後の手動テストで見落としてしまった不具合を発見する役割も担っています。 実施している回帰テストの概要 Photoraitチームでは以下の内容で回帰テストを実施しています。 実施頻度は月1回 開発メンバーが全員参加(ディレクター、サーバサイドエンジニア、デザイナー) サイトのページ一覧表を作成し、1人ずつにテストする担当ページを割り振る 担当ページをPCとスマホ両方で表示や機能をテスト テスト項目はなく、各自の視点でテスト 見つけた不具合とサイトをより良くするための改善点をスプレッドシートに記述 実施時間は1回につき2時間 (1時間30分で担当ページをテスト、残り30分でZoomに集まり不具合や改善点を共有) 不具合と改善点を記述しているスプレッドシート(例) 実施する時に工夫してる点 1. 不具合だけでなく改善点もシートに記述 せっかく表示や機能を時間をかけて確認するので、サイトをより良くするための改善点もシートに記述してもらってます。 不具合は毎回発見されませんが、改善点は毎回多く出ます。 午前中に回帰テストを行い、午後に優先度の高い改善点を修正リリースすることが多いです。 2. 不具合を多く発見した人を称える 「不具合を自分達で見つけることは良いことだ!」という文化を作りたいと思い、回帰テストを実施する毎に、一番多く不具合を発見した人にベスト回帰テスト賞を授与してます。 不具合が発見されない場合は、改善点を一番多く発見した人が対象です。 受賞者にはささやかなインセンティブを渡していて、インセンティブがあるのとないとでは参加者のモチベーションが変わるのでおすすめです笑 3. 広く浅くではなく、狭く深くテスト 簡単に見つかる不具合なら通常の開発時でも発見できるので、時間をかけて細かくテストしないと見つけられないような不具合を発見できるように、回帰テスト実施時の1人に対しての担当ページは限りなく少なくしています。 前回の回帰テストの一例を上げると、以下の2ページのPCとスマホページを1時間30分1人でがっつりテストしてもらいました。 エリア検索ページ https://www.photorait.net/search/area エリア検索結果ページ https://www.photorait.net/search/area/tokyo 実施するメリット 1. チーム内で不具合を発見 不具合発生はサイトの信頼に関わってきます。 ただ、開発する上で不具合を0にすることは不可能なので、不具合を発生させない仕組みと発生した不具合を発見する仕組み作りが大事になってきます。 不具合を発見する仕組みの一つとして回帰テストが機能しています。 2. 仕様の理解 不具合発見のために実施していますが、時間をかけてテストすることでサイトの仕様を理解するのにも役に立っているという声をよく聞きます。 過去に開発をしたことがあるページは仕様を理解しているので、あえてできるだけ開発をしたことがないページが担当になるように割り振っています。 3. テストについての学び 不具合や改善点を共有するので、他メンバーのテストの視点や方法を学ぶことができます。 回帰テストを繰り返すことでテストのナレッジがチームに蓄積され、各メンバーのテストの質が上がっているように感じます。 課題点 1. テスト自動ツール導入 発見した不具合が今後起きないように、定期的に自動で確認してくれる仕組みが作れていません。 不具合を発見した人がテスト自動ツールに定期確認の設定ができるのが理想なので、エンジニア以外のメンバーでも利用できる、プログラミングが不要なテスト自動化ツールの導入を検討しています。 2. 開発環境のデータを最新にする仕組み 回帰テストは開発環境で実施しています。 本番と同じデータでテストすることでしか見つけられない不具合もあるので、開発環境に本番データを反映しているのですが、今は手動でやっているのでさくっと自動化しちゃいたいです。 3. 改善点を修正する工数確保 回帰テストを実施する度に、たくさんの改善点が出てきます。 すぐに修正した方がいい改善点が多く出ますが、現状なかなか工数が割けておらず対応が後回しになっています。 改善点を修正する期間を定期的に設けて、改善点を放置しない仕組み作りを検討しています。 最後に Photoraitチームで実践している回帰テストについて紹介しました。 既存の不具合検知の仕組みの一つとして実施し始めましたが、今では仕様の理解やテストの学びなどにも役立つ取り組みになっています。 一方、まだまだ自動化できることも多いので、費用対効果の高い仕組みになるように改善していきます。 ウエディングパークでは、一緒に技術のウエディングパークを創っていただける仲間(エンジニア)を募集しています。興味のある方はぜひ一度気軽にお話ができたら嬉しいです! 株式会社ウエディングパークの会社情報 – Wantedly https://www.wantedly.com/companies/weddingpark
アバター
こんにちは。 サーバーサイドエンジニア兼QAエンジニアの福山です。 QAチームでは、生産性高く、高品質なサービスを安定して提供するために テスト自動化基盤の構築を進めてきました。 自動テストのツール選定 自動テストの開発 自動テストの運用 の3本立てで、前回、自動テストのツール選定についての記事を書かせていただきました。 QAチームの自動テスト推進 〜自動テストのツール選定編〜 自動テストのツール選定の結果、弊社では、 Bucky を使うことに決定しました。 本日は、2. 自動テストの開発についてです。 以下の流れで説明します。 ① システム構成 ② ローカルの環境構築 ③ リンクチェックの実装 ④ E2Eで重要コンテンツの存在チェックの実装 Buckyの開発は、こちらの記事( 自動テストフレームワーク「Bucky」入門 )を参考に進めました。 ① システム構成 現状のアーキテクチャは上の図の通りです。 QAサーバーにBucky-coreとBucky-managementをインストールし、 Jenkinsからテスト実行コマンドのシェルを叩き、STG環境/DEV環境へスクレイピングして、 エラーがあれば、slackに通知する、というシステムを構築しました。 日次でSTG環境で継続的に自動テストを実行することで、 自動テストでエラーが出れば、リリース前に、すぐに見つけられるようになりました!! その構築と実装を②〜④で説明します。 ② ローカルの環境構築 # プロジェクト用ディレクトリ作成 $ mkdir bucky # プロジェクト用ディレクトリ直下へ $ cd bucky # bucky-coreをgit cloneでローカルへ落としてくる $ git clone https://github.com/lifull-dev/bucky-core.git # .dev抜きにリネーム $ cp docker-compose.dev.yml docker-compose.yml Dockerがなければダウンロード(↓MACのPCの場合) https://hub.docker.com/editions/community/docker-ce-desktop-mac Docker desktop にログイン # dockerを諸々立ち上げ(-dだとバックグラウンド実行) $ docker-compose up -d ## コンテナが起動してるかどうか見るときは $ docker-compose ps # 立ち上げ終わったら下記で該当サーバログイン $ docker-compose exec bucky-core bash # www.weddingpark.net というプロジェクトを作ります bucky new www.weddingpark.net # プロジェクトディレクトリに移動 cd www.weddingpark.net # notificationというサービスを作ります bucky make service notification (その他、 大きな機能毎(概ねURLの第一階層毎)にサービスを作りました。) # notificationというページを作成(PC) (※名称はここでは仮です) $ bucky make page notification --service notification --device pc # notificationというページを作成(SP) (※名称はここでは仮です) $ bucky make page notification --service notification --device sp ローカルには、bucky-core 配下の  .sample フォルダとdocker上のファイルが同期されます。 ③ リンクチェックの実装 # notificationサービスにリンクチェックのディレクトリ作成 $ mkdir -p services/notification/pc/scenarios/linkstatus $ mkdir -p services/notification/sp/scenarios/linkstatus # テストスイート名「notification」のファイルを作成 $ touch services/notification/pc/scenarios/linkstatus/notification.yml $ touch services/notification/sp/scenarios/linkstatus/notification.yml テストコードを追加します。 以下に記載の例では1つのファイルに1つのcaseしかありませんが、 1つのサービス内に、複数の異なる作りのページが存在するときは、その全てをcasesの中に実装しました。 ## services/notification/pc/scenarios/linkstatus/notification.yml # Describe for this test suite desc: お知らせページのリンクチェック device: pc service: notification priority: high test_category: linkstatus labels: - www # You can exclude url that you don't want to check exclude_urls: cases: - case_name: notification desc: Check お知らせページ urls: - <%= ENV['BUCKY_FQDN'] %>/notification/XXXX ## services/notification/sp/scenarios/linkstatus/notification.yml # Describe for this test suite desc: お知らせページのリンクチェック device: sp service: notification priority: high test_category: linkstatus labels: - s # You can exclude url that you don't want to check exclude_urls: cases: - case_name: notification desc: Check お知らせページ urls: - <%= ENV['BUCKY_FQDN'] %>/notification/XXXX リンクチェック実行時のコマンド $ BUCKY_FQDN={STG環境のドメイン} bucky run -t linkstatus -d 基本的にはSTG環境でテストを定期実行しているのですが、 影響範囲が広い開発では、DEV環境でも自動テストを実行したい要件が出てきたため、 urls:のURLに環境変数を使うように途中から変更しました。 ④ E2Eで重要コンテンツの存在チェックの実装 サイト内で、重要なコンテンツがちゃんと表示されているかをチェックするE2Eを実装しました。 ※重要コンテンツ・・・絶対にバグを出してはいけない大事なコンテンツ ## services/notification/pc/parts/notification.yml # お知らせページのXXX(←対象のコンテンツ) xxxxx: - xpath - //*[contains(., "{XXXの表示名}")] 以下に記載の例でも1つのファイルに1つのcaseしかありませんが、 1つのサービス内に、複数の異なる作りのページが存在するときは、その全てをcasesの中に実装しました。 また、複数の重要コンテンツがあれば、それらを parts に記載し、テストケースで1つ1つチェックしました。 ## services/notification/pc/scenarios/e2e/notification.yml # Describe for this test suite desc: お知らせページのXXX表示 device: pc service: notification priority: high test_category: e2e labels: - www cases: # You should create test case name as {test suite name + _ + number} - case_name: notification_XXX func: XXX表示 desc: お知らせページを開き、XXX表示の確認をする procs: - proc: Open notification page exec: operate: go url: <%= ENV['BUCKY_FQDN'] %>/notification/XXXX - proc: Search XXX exec: verify: assert_exist_part page: notification part: xxxxx (SPは省略) E2E実行時のコマンド $ BUCKY_FQDN={STG環境のドメイン} bucky run -t e2e -d E2Eはユーザから見える外部の振る舞いに着目して行うテストなので、内部処理の都合でidなどが変更されてもテストが通るように、外から見える要素の情報でテストを行うために、このようなチェック方法にしました。 verifyの assert_exist_part は、要素がページに存在することを検証しています。 他の検証リストはこちら( Verification List )。 まとめ 自動テストができたことで、重要なバグを未然に防げるようになったことはもちろん、 開発案件のテストの際も、より案件に集中してテストをして、回帰テストは自動テストに任せることができるようになりました。 自動テストをしっかり運用していくことで、開発全体の生産性の向上に寄与していると思います。 次回、最終章の運用編でどのように運用しているかをお伝えします。
アバター
こんにちは!前撮りなど結婚写真の撮影スタジオ・サロンを検索できる情報サイト「Photorait」のメインデザイナーをしています、内田( @PANbooooo )です。 Photoraitチームでは、チームメンバー全員でペルソナ設計ワークを行いました。 今回はそのペルソナ設計ワークから学んだ難しかったことや、やって良かったことを紹介したいと思います。 ワークの概要 ワークをやろうと思ったきっかけ ものづくりをする上で大切なのは「誰に向けているのか」というターゲットを理解することだと思います。せっかく作ったプロダクトも、使う人がいなければただの置き物状態です。 そこで、コロナによって生活様式がガラリと変わった今、サービスに関わる人全員で「誰が、どんな問題を解決したくて、どのタイミングで利用してくれるのか」を改めてしっかりと理解する必要があると思いました。 ワークの参加メンバー 営業/ディレクター/エンジニア/デザイナー、チームメンバー全員で行いました。 ネットで似たようなワークについて書かれている記事を見ると、「開発メンバーのみ」で行っていることが多いですが、チーム全員が共通の認識を持ってサービスを運営していくことで、サービスのコンセプトのブレを軽減させることに繋がると思いましたため、チーム全員参加となりました。 あえて「営業」も加わることで、開発メンバーには持ってない視点での意見を出してくれたりと、ワーク全体の視野が広がった感じがしました。 また、普段クライアントさんと関わることが多い営業メンバーにとっては、ユーザーのことを知る機会はなかなか無いと思いますが、「このワークをきっかけにユーザー目線について考えるようになった」という営業メンバーの声をいただきました。 ワークの内容について ワークは合計4つ行いました。 1:WhoDoワーク 誰が何を解決するためにサービスを利用するのかを明確にするためのワークです。 Photoraitというサービスが、どんな問題を持ってる人に使われていて、その問題をしっかりと解決できているのか、また解決するためには何をすればいいのかを考えるためのワークです。 実際にワークで使用した表になります。 左側に「想定するサービス利用者」を記入し、右側に「想定する利用者がPhotoraitというサービスで何をしたいのか」を記述します。 そこで書いた「したいこと」が提供できていれば、サービスとしての価値はあることになりますし、「したいこと」が提供できていない場合は提供できるように改善しなくてはいけません。 2:ペルソナ設計ワーク 1のワークを元に「もっと訴求したいユーザー像」をピックアップし、ペルソナを作成するワークです。ターゲットユーザーの詳細を明確にすることが狙いとなっています。 実際にワークで使用した表になります。 一見、顔写真という項目は意味の無いように思われますが、項目の中に顔写真を入れることで、よりチーム内での認識が揃うようになります。 3:ユーザージャーニーマップ作成ワーク 2のワークを元にターゲットユーザーがどのタイミングでサービスに出会うのかを明確にするワークです。Photoraitに出会うまでにユーザーはどんなサービスに触れるのか、そして自分たちがまだ起こしていないアクションで、提案できることはあるのかを知ることができます。 実際にワークで使用した表になります。 ユーザーのフローを視覚化することで、自分たちのサービスがどの状況でどんな風に使用されているのかが分かりやすくなります。 4:感性の共通化ワーク 実際にPhotorait内に掲載されている写真を用いて、キーワードごとに振り分けることで、チームメンバーの感性を揃えようというワークです。 「ナチュラル」「かわいい」「クール」「アーティスティック」「ヴィンテージ」「モダン」「クラシック」という、実際に Photoraitのフォト検索 で使用されているキーワードに写真を振り分けていきます。 実施にあたってやってよかったこと 事前のワーク説明会 ワークの開催に向けて事前に参加者にワークの説明会を行いました。 もちろん、ワークの当日にも各々の意図を伝える時間はありましたが、当日は時間が限られてしまうため、その前に疑問点や不明瞭な部分を解消するべく、事前に説明会をすることにしました。 また、事前の説明会を設けることで、当日までに各々のメンバーがワークに沿った課題等を意識出来、意見等を考える時間になったと思います。 少人数グループでの話し合い 今回の4つのワークのうち「WhoDoワーク」と「ペルソナ設計ワーク」と「ユーザージャーニーマップ作成ワーク」をグループワークとして行いました。 1グループ4人という少人数グループでの話し合いにすることで、1人の発言量が自然と多くなり、全体を通して見ても誰もが積極的にワークに参加出来たと思います。 スプレッドシートを利用した見える化 ワークは全てスプレッドーシート( スプレッドシートとは )で行いました。 当日使用するシートには一応事前に例を2つほど準備しておいて、迷った時のヒントを設けておいたのですが、シートを利用することで、他のグループがどんな意見を出しているかが全員がリアルタイムで確認できるため、「誰かが書き足すことで自然と例が増えていく」ことに繋がり、より意見が出しやすくなったのでは無いかと思います。 事前にある程度ルールを決めておく ワークを進める上で、必ず守ってほしいルールをいくつか決めました。 「相手の意見は否定しない」や「時間を守ってワークに励む」等のルールを決めることで、ゴールが明確化され、スムーズにワークを進めることができました。 また、「相手の意見は否定しない」というルールを設けることで、全員が発言しやすい環境が作れたと思います。 難しかったこと オンラインならではの事故 ワークではzoom( zoomとは )を利用しました。 初めてのオンラインワークということもあり、接続が途中で切れてしまったり、声が途切れてしまうなどの一部ハプニングがありました。 各々のWi-Fi環境等をしっかりと把握しておくべきだったと思います。 成果・感想 今回はユーザーのペルソナ作成が目標のワークでしたが、クライアントと接することが多い営業メンバーにとっては難しかったのでは無いかと思っています。 ですが、いざ終わってみると、営業メンバーから「新たな視点での提案ができそう」という前向きな意見をいただきました。 また、チーム全体で見ても、自分たちのターゲットユーザーを改めて知ることで、新たな提案に繋がったり、サービスに対する視野が広がった感じがします。デザイナーとしてはバナーの作成等、デザインイメージを作成しやすくなりました。 チーム全員で作ったこのペルソナを、届けたい人にしっかりと届くよう、しっかりと活かしていきたいと思います。
アバター
こんにちは、エンジニアの久保です。 普段開発で使っているMacの調子が悪くなりました。負荷がかかるとディスプレイが砂嵐になります。つらいです。 使いやすい機種でだいぶ気に入っていたのですが、流石に業務に支障がでてきたので新しいMacに移行しました。 移行のときにやることは、そう、環境構築です。 開発で必要なツールを1つずつインストールしていって、今と同じ環境を構築するのはなかなかの手間がかかります。 毎回困るので、最近は環境を作り込まずほぼデフォルトの状態で使うようにしていたのですが、それでも時間がかかります。 今回は、macOS用のパッケージマネージャ Homebrew の bundle コマンドを使って、ソフトウェアとライブラリのインストールを行ってみました。 Homebrew Bundle Homebrew Bundle( brew bundle )を使うと、パッケージを Brewfile で管理できます。 Homebrew Bundle Homebrew Documentation インストール済のパッケージから Brewfile を作成する brew bundle dump で、brewコマンドでインストール済のパッケージを Brewfile に書き出せます。 brew bundle dump --global --force ここで、 --global で ~/.Brewfile に書き出し、 --force で既にファイルが存在していても上書きする、です。 お引越しの場合は古いMacで実行すると良いでしょう。 今回の環境の場合は次の内容になりました。 普段の環境が丸見えですね。 今回は Brewfile を書き換えて、 cask で slack や zoomus などのアプリケーションも導入できるようにしてみています。 mas を使うと Mac App Store からもインストールできるのですが、今回は試していません。 今後この .Brewfile を gist で管理して育てていこうと思います。 Brewfile からパッケージをインストールする 新しいMacの ~/ 配下に先程の .Brewfile を配置します。 Homebrew をインストールし、次のコマンドを実行します。 brew bundle --global パッケージのダウンロードインストールが始まります。待つだけです。簡単ですね。 まとめ Homebrew Bundle( brew bundle )を使って、ソフトウェアとライブラリのインストールを行ってみました。 今回のような開発環境の移行で役立つほか、他の開発メンバーと環境を揃えたい場合や、キッティングなどで環境を揃えたい場合にも大いに役立ちそうです。
アバター
こんにちは、インフラエンジニアの綿引です。 EC2 運用時に いつのまにかディスク使用率が 100% に、、 という経験がある方もいらっしゃるのでないでしょうか。 そこで今回は EC2 の EBS ボリュームを拡張したので、方法を共有したいと思います。 対象の方は以下のような方でしょうか。 EC2 のディスク使用率がそろそろ危ない、、 実施方法 では早速実施していきます。拡張対象の EC2 の情報は以下です。 OS : CentOS 7 拡張対象 : ルートパーティション そしてやる前に 必ずバックアップ を取得しておきましょう。 EBS ボリュームの拡張 まずは EBS ボリュームの拡張を行なっていきます。 マネジメントコンソールの EBS の画面から、拡張対象の EBS ボリュームを選択し 「アクション」 → 「ボリュームの変更」 を選択します。 そして画面遷移後、ボリュームタイプ・サイズを任意のものにして「変更」を押下します。 今回は 200GB → 400GB に変更しました。 変更が開始されると、画面の下部に進捗が表示されますので 100% になるまで待ちます。 パーティションとファイルシステムの拡張 EBS のボリューム拡張が完了したら、次は OS 側にてパーティションとファイルシステムの拡張をしていきます。 まずブロックデバイスが拡張されているか lsblk コマンドで確認します。 [root@ebs-test 02:30:58 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 400G 0 disk └─xvda1 202:1 0 200G 0 part / df コマンドでも確認してみます。 [root@ebs-test 02:31:01 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 200G 188G 13G 94% / ルートボリュームの xvda は先ほどの EBS のボリューム拡張にて 400GB になっていますが、ルートパーテーションの xvda1 はまだ 200GB のままです。 ではパーティションの拡張を growpart コマンドで行います。 [root@ebs-test 02:31:22 ~]# growpart /dev/xvda 1 CHANGED: partition=1 start=2048 old: size=419428319 end=419430367 new: size=838858719 end=838860767 これで xvda1 パーティションが 200GB から 400GB に拡張されました。 [root@ebs-test 02:31:25 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 400G 0 disk └─xvda1 202:1 0 400G 0 part / 次にファイルシステムの拡張を xfs_growfs コマンドで行います。 [root@ebs-test 02:32:00 ~]# xfs_growfs /dev/xvda1 meta-data=/dev/xvda1 isize=512 agcount=9, agsize=6553536 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0 spinodes=0 data = bsize=4096 blocks=52428539, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal bsize=4096 blocks=12799, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 data blocks changed from 52428539 to 104857339 ファイルシステムの拡張も完了したので、最後に df コマンドで確認してみます。 [root@ebs-test 02:32:28 ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 400G 188G 213G 47% / これで OS 側の拡張も完了です。 注意点 注意点としてはファイルシステムによって、パーティション拡張コマンドが異なることです。 xfs_growfs : XFS resize2fs : ext2・ext3・ext4 CentOS7 以上ですとファイルシステムが XFS ですので上記手順の xfs_growfs コマンドで問題ないですが、CentOS6 以下をお使いの方は resize2fs コマンドを使っていただければと思います。 最後に 今回は EC2 インスタンスの EBS ボリュームを拡張してみましたが、オンラインでできたのは良かったです。 EBS ボリュームの拡張時間としては 200GB 増やして 5〜6時間 ほどでした。 その間パフォーマンスが劣化するとのことだったので、実施タイミングだけ気をつけたいです。 また EBS を拡張すると、 EBS ボリューム分のコスト が発生する点も気にしておきたいですね。 エンジニア募集中 Wedding Parkでは一緒に技術のウエディングパークを創っていくエンジニアを募集しています。 興味のある方はぜひ一度気軽に話を聞いてみてください。 株式会社ウエディングパークwantedly
アバター
こんにちは、インフラエンジニアの綿引です。 複数の AWS アカウントを管理する際に AWS Organizations って便利ですよね。 弊社でも使用しているのですが、私自身はあまり使ったことがありませんでした。 そこで今回は 新規 AWS アカウントを AWS Organizations を使って追加 してみたので共有させていただこうと思います。 対象の方は以下のような方でしょうか。 AWS Organizations を導入しようか検討している AWS Organizations を使用しているが子アカウントを追加したことがない AWS Organizations とは AWS Organizations は 複数の AWS アカウントを統合するためのアカウント管理サービス です。 アカウントがたくさんあると、各アカウントの管理や請求面などが非常に面倒になります。 それを解消してくれるのが、AWS Organizations です。 主な機能としては以下のようなものがあります。 AWS アカウントのすべての一元管理ができる 子アカウントを含めた一括請求が可能 子アカウントをグループ化し、異なるアクセスポリシーをアタッチすることができる 他にも機能があるので、詳細は以下のリンク先をご参照ください。 参考 : AWS Organizations とは何ですか? Organizations からアカウントを作成するメリット まず AWS Organizations で AWS アカウントを管理する (組織に参加させる) には、以下の2つの方法があります。 既に作成済みの AWS アカウントを追加する方法 AWS Organizations から AWS アカウントを新規作成する方法 今回は2つ目の方を試していきますが、メリットとしては AWS アカウントを作成する際に クレジットカード情報や住所などを入力する必要がない点です。 通常、 AWS アカウントを作成する際には上記の入力が必要なので、「面倒だな・・」 と思っていた私には朗報でした。 楽に AWS アカウントが作成でき、かつ AWS Organizations で管理できるのはありがたいですね。 アカウント追加をやってみる では早速アカウントを追加していきます。 まずは AWS Organizations のコンソール画面から 「アカウントの追加」 を選択します。 画面遷移後、「アカウントの招待」 か 「アカウントの作成」 が選べるので、 「アカウントの作成」 を選択します。 すると画面下に AWS アカウント名などを入力できる項目が出てくるので、これを入力後、作成ボタンを選択します。 今回、アカウント名は 「watahiki_test」 にしました。(消し忘れると恥ずかしい、、) これで終了です。 びっくりの楽さですね。 AWS Organizations のコンソール画面から見てみましょう。 ちゃんと追加されています。 AWS Single Sign-On を使用している場合は、権限をセットして上げればもうログインができます。 ありがとうございます。助かります。 最後に AWS Organizations を使い AWS アカウントを追加してみましたが、非常に簡単にできました。 開発環境やステージング環境、サービスによって AWS アカウントを分けている方も多いと思うので、もしまだ AWS Organizations を使ったことないという方がいらっしゃれば、一度試してみてはいかがでしょうか。 エンジニア募集中 Wedding Parkでは一緒に技術のウエディングパークを創っていくエンジニアを募集しています。 興味のある方はぜひ一度気軽にオフィスに遊びにいらして頂ければと思います。 株式会社ウエディングパークwantedly
アバター
こんにちは。 サーバーサイドエンジニア兼QAエンジニアの福山です。 QAチームでは、生産性高く、高品質なサービスを安定して提供するために テスト自動化基盤の構築を進めてきました。 チームの意義目標 (※1) は、『品質でサービスの信頼残高を爆上げする』として、QAマネージャー、Webディレクター、サーバーサイドエンジニア( (※2) SET兼務)のメンバーで日々品質改善に取り組んでいます。 ※1 意義目標…最終的に実現したい抽象的な状態や影響を示した目標のこと。 ※2 SET…( S oftware  E ngineer in T est) その中で、開発段階での障害検知と重要機能の継続的な品質担保のために、 E2Eの自動テストを運用にのせることができたので、 自動テストのツール選定 自動テストの開発 自動テストの運用 の3本立てでお話したいと思います。 本日は、 1. 自動テストのツール選定  についてです。 弊社でどのように自動テストのツール選定をしたのか、 その進め方と、選定したツールはどんなテストにお勧めか をお話ししたいと思います。 ① 自動テストの前提の認識合わせ ② E2E自動テストの要件洗い出し ③ ツールの検証&選定 の流れで決めました。 ① 自動テストの前提の認識合わせ 初めに、チームでキックオフをして、自動テストの以下のような前提条件をブレストし、認識合わせをしました。 ■何のテストをするか ・E2EでHTTPステータスコードのチェック ・サイト内での重要なコンテンツ(特定のボタン)が画面上表示されているかのチェック ■ドメイン まずメインの1サイトのみを対象とする ■対象面 検索面など主要ページをメインに ■対象環境 ステージング環境 で実施。 → 開発フェーズでの検知を目的 とするので、本番環境の手前でテスト実施。 その他、計測するスクレイピングツール、可視化方法、運用ルール、実行頻度、システム構成、データI/O、実行場所などもブレストしました。 ② E2E自動テストの要件洗い出し 前提を元に、ツール選定のため、E2E自動テストに必要な要件をまとめていきました。 要件は以下のように決めました。(●Must、○Want) テスト観点 ●cURLベースのHTTPリクエストとステータスが取得できること ○DOM要素の取得ができること ○画像キャプチャが取れること ○画像の差分比較ができること 開発 ●URLの追加/削除ができること ●全てのソースがバージョン管理できること(git) ●Docker上で動作可能なこと(実行環境に大きく依存しない) ●QAチームで保守できる範囲のフレームワーク/言語であること ○ブラウザベース/ヘッドレスで動作できること 保守運用/通知 ●URLの追加/削除ができること(エンジニアが) ○URLの追加/削除ができること(ディレクターが) ●異常検知の条件制御ができること(XX回失敗したらfail) ●エンジニアが確認して、修正アクションが取れるログを出せること Saas連携 ●slackへの通知が可能であること ●GitLabCIとの連携が可能であること ●jenkinsからキックできること ○メール送信が可能であること ○GoogleDocument系との連携が可能であること 計測メトリクス ●総実行テストケース数 ●成功テストケース数 ●失敗したテストケース数 ●実行時間 テストレポート/可視化 ○メトリクスをグラフィカルに表示できること パフォーマンス ●1分/1000URLの速度が出せること ●1回/2hの運用に耐えうること ③ ツールの検証&選定 弊社開発メンバーはPHPが一番馴染みがあるため、PHPをベースにしているスクレイピングツールである、 guzzle、goutte、LaravelDuskの3つを検証することにしました。 途中から、rubyをベースにしているのですが、 Bucky という自動テストツールの検証も追加で実施しました。 BuckyはQA界隈で、OSS化してリリースされた際に こちらの記事 で話題になり、実装も結果もYAML形式で簡単に実装できそうということで、追加検証をすることになりました。 テスト自動化カンファレンスというイベントでQAマネージャーとBuckyの開発会社の方と登壇者同士で繋がりができたのもきっかけとなりました。 ②で決めた要件を元に、標準機能でできるか、ある程度コーディングorプラグイン/ライブラリを入れればできそうか、できないかを表にマッピングしていきました。 HTTPリクエストとステータス取得や、DOM要素取得などはある程度どれもできたのですが、 Buckyの実装が簡単で、標準機能で、計測メトリクス、テストレポート/可視化があること(他のツールにはなかったこと)から、 Buckyで自動テストを開発することに決めました。 Buckyの良いところ ・YAML形式でテストコードを書けるので、rubyに馴染みがなくても開発しやすい ・Buckyの記事、 自動テストフレームワーク「Bucky」入門 が公開されていて、最初の導入がスムーズ ・bucky-managementという可視化ツールもあり、テスト結果の一覧や詳細、全体のレポートが簡単に見れる こんな自動テストを開発したいならBuckyがお勧めです! ・以下のリンクチェックとDOM要素チェックを簡単に実装したい。  ① 特定(複数のディレクトリ可)のページ配下に存在する全てのリンクをチェックして、404エラー、5XX系エラーになっていないかチェックしたい。  ② DOM要素を使って、以下のようなチェックをしたい。   ページタイトルのチェック、要素のテキストの値をチェック(一致or含まれるか)など   チェックできる内容は こちら(Verification list) を参照。 ・さらに、それらの結果をレポート画面で簡単に表示したい。(以下の画像参照) では、次回の自動テスト開発編をお楽しみに。
アバター
こんにちは、SREチーム エンジニアの綿引です。 最新情報のキャッチアップって重要ですよね。 私も意識的に行なっているつもりなのですが、以下のような悩みがありました。 日々のタスクに追われ時間が取れず継続が難しい 個人だけでなくチームのキャッチアップ力・インプット力を伸ばしたい そこで今回、上記を解決するため SRE チームで 「トレンド情報共有ミーティング」 を始めてみたので、その感想をお話したいと思います。 トレンド情報共有会とは チームメンバーが最新・トレンド情報を持ち寄って定期的に共有するミーティングのことです。 割と一般的だと思いますので、すでに実施されている方もいらっしゃる方々もいらっしゃるのではないでしょうか。 色々なやり方があるかと思いますが、我々のやり方としては以下で実施しています。 週次で実施 自身で集めた情報を共通のスプレッドシートにまとめる 各情報に優先度(A・B・C)をつけ、時間をオーバーしないようにしている チケット化の項目をつけ、やろう!となったものは忘れずにチケット化する 技術だけなくチームビルディング関連の情報も共有項目に含めている イメージはこのような感じです。 改めて見てみると割とアナログなやり方をしてますね、、 これからブラッシュアップしていきたい、、 上記のチケット化に関して、弊社ではタスクを Redmine で管理しているので、Redmine のチケット化を意味しています。 トレンド情報共有ミーティング中に実施しよう!と話が出た情報があったとしても、ミーティングの進行に集中してしまったり、情報が多いとそのタスクを忘れ去られてしまったりするので、タスクの風化防止で入れています。 技術だけでなくチームビルディング関連も共有項目に含めている理由としては、自身も含めてですが SRE チームとしてまだまだ経営目線やチームビルディングの意識を強くしたいと思ったためです。 まだ具体的な効果は出ていませんが、技術以外の情報を共有しあうことで、個人的にはチームに経営目線などの意識がより強化されたと思っております。 やってみた結果 実際に実施してみて感じたメリット・デメリットは以下でしょうか。 メリット 定例ミーティングのためそれまで情報を集めなければならず、結果的に継続が可能 チームのキャッチアップ力・インプット力が強化される 新しい施策が次々発案される リモート下でのコミュニケーション不足解消にも使える デメリット 時間・工数がかかる 失敗談 開始直後の失敗談ですが、気合いを入れ過ぎて共有事項が多くなりすぎてしまい予定の時間を大幅にオーバーしてしまったという失敗がありました。 これに関しては、各情報に優先度をつけたり、情報一つあたりの共有時間を短くするために 「一言で伝えたいこと」 の項目を作ってみたりなどで、現在は解消しています。 最後に 今回は SRE チームで実施している トレンド情報共有会 について共有させていただきました。 今まで情報のキャッチアップなのは個人の責任になっていたのですが、チームでやるのもメリットがあっていいなと感じました。 もし取り入れてみたいという方がいらっしゃれば、参考にして頂けると幸いです。 エンジニア募集中 Wedding Parkでは一緒に技術のウエディングパークを創っていくエンジニアを募集しています。 興味のある方はぜひ一度気軽にオフィスに遊びにいらして頂ければと思います。 株式会社ウエディングパークwantedly
アバター
こんにちは、インフラエンジニアの綿引です。 従量課金が多い AWS ではコストを常にチェックしておきたいですよね。 そこで今回は AWS Budgets を使って、一定の料金を越えたら Slack に通知をさせる、ということをやってみたいと思います。 対象の方は以下のような方でしょうか。 AWS のコストは監視しておきたいが毎回見るのは面倒 コストアラートを Slack に通知させたい AWS Budgets とは AWS Budgets は コストまたは使用量が予算額や予算量を超えたときにアラートを発信できるサービス です。 また他にも以下のような機能もあります。 現時点で予想請求額(使用量)から月末に発生する課金額を予測できる RI(リザーブドインスタンス)の使用状況などをモニタリングする 詳細は以下のリンク先をご参照ください。 参考 : AWS Budgets を使用したコストの管理 実装 では早速実装していきます。使用するサービスは以下です。 Amazon SNS Slack AWS Chatbot AWS Budgets Amazon SNS まずは SNS トピックを作成してします。 設定はデフォルトで作成し、トピック名は 「CostAlert_Test」 にしました。 作成が完了したら、 ARN をメモしておきます。 次に 「編集」 を選択し、アクセスポリシーを変更していきます。 アクセスポリシーの JSON エディタより以下を追加します。 追加する場所は “Statement” の下の行です。 { "Sid": "AWSBudgets-notification-1", "Effect": "Allow", "Principal": { "Service": "budgets.amazonaws.com" }, "Action": "SNS:Publish", "Resource": "Insert-ARN-here" ← ここに先ほどメモした SNS の ARN を記載 }, “Insert-ARN-here” は先ほどメモした ARN に変更します。 これで SNS の設定は完了です。 Slack 次は Slack です。 コストアラート通知用に channel を作っておきましょう。 今回は 「alert-cost_alert」 という channel 名にしました。 AWS Chatbot 次は AWS Chatbot の設定を行なっていきます。 余談ですが、Chatbot はついに beta 版がなくなって一般提供が開始されましたね。 前から使っていたので嬉しい限りです。 Chatbot ではまず 「クライアントの設定」 から、通知を行いたい Slack ワークスペースと Chatbot を連携させます。 次に 「新しいチャネルを設定」 を選択し、先ほど作成した SNS トピックなどを登録していきます。 設定名や付与する IAM ロールの設定などは任意です。 「Slack チャネル」 には先ほど作成した channel を設定します。 「SNS トピック」 も同様に、先ほど作成した SNS トピックを設定します。 設定が完了したら保存します。 これで Chatbot の設定も完了しました。 AWS Budgets 最後に Budgets の設定です。 AWS Budgets の画面を開き、 「予算を作成する」 を選択します。 「予算タイプの選択」 では 4つの選択肢から選ぶことができますが、今回は一定の料金を越えたら Slack に通知をさせる、ということをやりたいので 「コスト予算」 を選択します。 次の 「予算の設定」 では、予算に関する詳細の設定を入れていきます。 名前、間隔(月、四半期など)、予算額などを任意で入力します。 最後に 「アラートの設定」 です。 「アラートのしきい値」 には、先ほど入力した予算額の何%でアラートを通知させたいかを入力し、 「Amazon Simple Notification Service (SNS) トピックを通じて通知」 にチェックをつけて、先ほど作成した SNS トピックの ARN を入力します。 これで Slack への通知設定ができたので、他の設定が終わったら 「完了」 を押下します。 これで AWS Budgets の設定も完了しました。 この段階で設定した閾値を越えていたら、Slack に以下のような通知が届きます。 最後に 今回はAWS Budgets のコストアラートを Slack に通知してみましたが、非常に簡単にできました。 モニタリングしておかなければならないコストを、Chat に流すことで楽に見れるようになったのは嬉しいです。 尚、今回は Slack にのみ通知する設定を入れましたが、SNS 側でサブスクリプションの設定を追加すれば、メールなどにも同時に通知が可能ですのでご興味あればお試しください。 エンジニア募集中 Wedding Parkでは一緒に技術のウエディングパークを創っていくエンジニアを募集しています。 興味のある方はぜひ一度気軽にオフィスに遊びにいらして頂ければと思います。 株式会社ウエディングパークwantedly
アバター