AWS | AI tech studio https://cyberagent.ai AI事業本部は、サイバーエージェントグループのデジタルマーケティング分野におけるサービス開発を行う組織です。 Mon, 13 Sep 2021 08:53:22 +0000 ja hourly 1 https://wordpress.org/?v=5.3.26 AirTrack 内定者アルバイト 「広告ログ集計基盤をSnowflakeへの移行による集計プロセスの改善」 https://cyberagent.ai/blog/pr/intern/15344/ Tue, 31 Aug 2021 03:06:24 +0000 https://ai-blog-admin.cyberagent.ai/?post_type=blog&p=15344 はじめに

初めまして、22卒エンジニア職内定者の松岡穂高と申します。

2021年6月1日から3ヶ月間、サイバーエージェントのAI事業本部にあるAirTrackという部署で、サーバーサイドの内定者アルバイトをさせていただきました。

今回は振り返りの意味も兼ねて、取り組んだ内容と学んだ事や知見について書き記したいと思います。

AirTrackとは

AirTrackとはAI事業本部の小売DX本部に位置し、スマートフォン端末から取得できる位置情報を活用し来店計測や広告配信を行うサービスを展開しているプロダクトです。位置情報を使って顧客属性を推測しターゲティングを行なっており、「人を動かす広告をつくる」ことを目指しています。

今回は、DSPと呼ばれる広告主向けの広告配信プラットフォームの開発に携わりました。DSP及びアドテクに関する詳しい解説はこちらの記事に書かれています。興味のある方はぜひご覧ください。

今回の目標

まず、今回AirTrackで働くにあたって成し遂げたいことは以下でした。

  • 大規模なデータを扱い、パフォーマンスチューニングができるようになりたい
  • 何かしらのビジネスインパクトを与えたい

学生レベルでは、どうしても事業目線で開発・運用を行う機会はないので、この内定者アルバイトではできる限り社員の方々と同じような視座を持つことを意識して取り組みました。

開発言語に関しては自分自身、特にこだわりはなく、プロダクトに適した言語を選定し利用できるのが望ましいと考えています。理由としては、サーバーサイドの言語はトレンドが激しく、現在使用している言語が必ずしも将来のデファクトスタンダードであり続けるとは限らないからです。そのため、一つの言語に固執したくない、今まで触れてこなかった技術にも触りたいと思い、Scalaでのサーバーサイドやインフラレイヤーの実装に挑戦しました。

AirTrackで行ったこと

今回私がメインとして行ったことは、既存の広告ログ集計のシステム基盤をSnowflakeに移行するというタスクでした。SnowflakeとはSnowflake社が提供するクラウド型データウェアハウスです。この移行によって、運用コストの削減、集計プロセスの安定化、より信頼性の高いモニタリングや精度の高いCTR予測が可能になり、もともと私が成し遂げたかった「大規模データを触りたい」「ビジネスインパクトを与えたい」という目標が達成できると考えました。テーブルの移行自体はクエリを書くだけで簡単でしたが、移行したテーブルが元のテーブルと同等の内容になっているか(join や where などの集計処理が等しいものになっているか)という精度の評価で苦戦し自身の成長にもつながる部分でした。この検証の部分に力を入れていたのでこのブログで紹介していきます。

精度検証と評価

まずは、試験的にSnowflakeで新しいテーブルを作成し、既存のものと同等の精度であるかを検証します。両者のテーブルから8月の1ヶ月間でデータを絞り込み、1日ごとにグループ化します。そして、既存テーブルと今回作成した新規テーブルから日ごとのidの数を算出し、抽出したcount数から両者の差分の割合を算出します。

WITH new AS (
  SELECT
    DATE_TRUNC(DAY, requested_at) AS date, 
    COUNT(id) AS count
  FROM
    new_table_log
  WHERE
   requested_at BETWEEN '2021-08-01' AND '2021-09-01'
  GROUP BY 1 
  ORDER BY 1
), 
old AS (
  SELECT 
    DATE_TRUNC(DAY, requested_at) AS date, 
    COUNT(id) AS count 
  FROM
    old_table_log
  WHERE 
   requested_at BETWEEN '2021-08-01' AND '2021-09-01'
  GROUP BY 1 
  ORDER BY 1
) 
SELECT
  old.date, 
  old.count AS old_count, 
  new.count AS new_count, 
  new_count / old_count AS rate,
  new_count - old_count AS difference
FROM 
  new 
  FULL OUTER JOIN old ON new.date = old.date 
ORDER BY 1
;

以下は、SnowsightというSnowflakeのデータ結果をグラフで可視化するツールを使用し、検証結果をグラフ化したものになります。この結果から、ほとんどの差分率が1.0に近い範囲に収まり、既存のデータと新しく作成したデータがほとんど一致している事が示されました。

新旧のレコード数の差分率を表したグラフ(8月)

実装

検証結果を評価した後は実装に入ります。試験的に作成したクエリが先程の検証で精度的に適正であることが証明されたので、これを定常的に作動させます。今回は、CloudWatch Eventsで定刻になればECSタスクを実行するようにしました。また、インフラ構築はAWS CDKを用いてクラウドアプリケーションリソースを定義しました。

学び

技術力も含めて設計力の大切さ

まず何よりもこの内定者アルバイトで学んだことは、設計の大切さです。AirTrackに来てまず驚いたことは、要件定義・システム設計のドキュメントの多さでした。私自身、これまでシステム設計を行わずに最初から実装ということが多々あったため、設計に対するスキルは皆無でした。実際に設計のレビューを社員の方々に見てもらい、改めて認識の齟齬があったり、より効率的で効果的な実装方法を提案してくださったりしていただきました。実現したい事を達成するために、どのような技術を用いて、どのように課題解決へとアプローチするかという方法を考え、文書に落とし込むことは簡単そうに見えてとても難しかったです。

仮説検証の重要性

次に学んだことは、仮説検証の大切さです。実装したものが果たして、どのような効果をもたらし、何がボトルネックであるかを明確にする必要がありました。

今回は特にSQLを使ってデータを集計することがメインでした。既存のものと刷新したデータベーステーブルを比較し、レコード数やデータの欠損率を計測。そして仮説検証を行い原因追求の繰り返し行う。そのようにして課題解決を行なっていくという経験ができたのは、私自身にとって大きな成果だと思います。少ないデータ量であれば、数字を出さなくとも、実際目で見て比較すれば良い話ですが、億を超えるレコード数を扱うため、欲しい結果を得るためのクエリを書くことは難しかったです。大規模なデータを扱えるのはとても楽しく、広告事業ならではの醍醐味だと感じました。

さいごに

このメインのタスク以外にも、サーバーサイドの開発ではScalaに挑戦しました。関数型言語は扱ったことがなく、慣れない概念が多くて難しかったですが、エンジニアとしてのレベルをより一層高めることができたと思います。また、個人開発ではなかなか使用する機会がないAWSのサービスを扱えたのも貴重な経験だと思います。

今回は、私自身初めて内定者アルバイトをさせていただきました。参画当初はとても不安でチームの力になれるか心配でしたが、AirTrackの皆さんはとても優しく働きやすい環境でした。また、わからない質問に対しては自分の成長を考えた受け答えをしていただきとても学びになりました。しっかりアウトプットを出せたのも、自分一人の力ではなくメンターさんや先輩の社員の方々のおかげであり、とても感謝しています。そして、この3ヶ月で身につけたことや学んだことはこれからも活かして自分の成長に繋げたいと思います。短い間でしたがお世話になりました。本当にありがとうございました。

 

]]>
AWS SageMakerのハンズオンを実施していただきました! https://cyberagent.ai/blog/tech/seminar/13460/ Fri, 03 Jul 2020 01:02:29 +0000 https://ai-blog-admin.cyberagent.ai/?post_type=blog&p=13460 こんにちは!
AI事業本部 小売DXセンター AirTrackの宗政 一舟(ムネマサ イッシュウ)です。

先月6月18日(木)にSagemakerハンズオンをAWS様にオンラインで開催していただきました。
AirTrack用にカスタマイズされたハンズオンで、チームのデータサイエンティスト・サーバーサイドエンジニア皆で参加しました!

当日の様子と内容をブログにさせていただきます☆

はじめに

機械学習は実世界のサービスで広く活用されるようになってきました。
しかし、データサイエンティストやMLエンジニアの開発した学習モデルをいざサービスに導入しようとした時に
機械学習特有の課題に直面することがあると思います。

学習に用いたデータによって出力される値が変化するため、学習モデルのテストをすることが難しい点や
出力値に異常が存在したことが分かってもデータ、学習アルゴリズム、前処理等のプログラムの
どこに問題があったのかを突き止めることはとても大変です。

リリース時だけでなく、サービスで正常に動作させる運用面の課題もあります。

例えば
時間の経過とともに性能劣化する可能性のある学習モデルを定期的に更新できる状態にしておくこと
オフラインでの評価が良くても本番環境で暴走してしまう恐れがあるため、学習モデルの出力値をモニタリングできるようにしておくこと
などなど。。。

ここ数年で「MLOps」という言葉がでてきたように
機械学習の開発/運用は多くの企業で取り組まれるようになっています。

今回のハンズオンでは、そんな機械学習システムの開発/運用をしていく上で大事な要素の一つである
学習モデルの性能劣化への対応を題材に行っていただきました!

テーマ

AirTrackは位置情報を用いた来訪計測や広告配信を行うことのできるプロダクトです。
来訪見込みの高さを考慮して広告を配信するサービスがAirTrackにはあり、来訪を予測する機械学習モデルを採用しています。
このモデルの性能の劣化が確認されたときに、更新を行える機械学習パイプラインの作成を目指しました。

このハンズオンで想定している状況としては
「old期間中のデータ」で作成した来訪予測モデルが現在本番環境で動いているものとして
「new期間中のデータ」が揃っタイミングで、new期間のモデルとold期間のモデルとの性能を比較し
劣化が確認されたとき本番で動作しているモデルを入れ替えるものになります。

AirTrackサービスに基づいたハンズオンを用意していただいたので、実務を意識して取り組むことができました。

ハンズオンのダイジェスト

作成した機械学習パイプラインのアーキテクチャになります。

「モデルの学習」や「推論の部分」は Amazon SageMakerで作成し
old期間中で作成したモデルとnew期間中で作成したモデルの性能比較をAWS Lambdaで行うような構成で
ワークフローの作成にはStep Functionsを使っています。

 

開発環境の準備

Amazon SageMakerのコンソールからノートブックインスタンスを作成しました。
起動したいインスタンスタイプを設定すると、JupyterまたはJupyterLabで開けるようになります。

 

ノートブックの環境構築が簡単なことに加えて、必要なリソースを選択して開発者が各々で起動できるのは便利ですね☆

 

学習モデルの開発

来訪予測モデル作成にXGBoostを用いました。
AWS Sagemakerでは組み込みのアルゴリズムや独自のアルゴリズムを使うものなど、モデルのトレーニングを定義するのにいくつか方法があるみたいですが
今回はAWS Sagemakerが提供しているXGBoostのフレームワークを利用しました。

以下の xgb_script_mode_estimator の部分で

  •  学習用のpythonのスクリプト
  • 学習が動作するインスタンスサイズ、インスタンスの数
  • ハイパーパラメータ
  • 作成された学習モデルの保存先(S3のパス)

を渡してあげるとXGBoostが使用できるコンテナが呼び出されます。

続いてfit関数で学習の実行します。
この時、train用のデータやvalidation用のデータが置いてあるS3のパスを引数で渡すと
置いてあるデータを読み込みモデルのトレーニングをしてくれます。

学習の状況については
ノートブックインスタンスのセルや

CloudWatch Logsから確認できました。

モデルの開発者は「学習用のデータ」と「学習用のコード」を準備すれば
ノートブックからインスンタンスサイズと数を指定してモデルのトレーニングを実行できるようになるので、本番同様の環境での動作確認がかなりラクになると思いました。

また立ち上がったインスタンスはジョブが終了したら勝手に落ちてくれるので、お金まわりでも嬉しさがあるかもしれません☆

 

実行フローの作成

StepFunctionsに各処理を実行するためのワークフローを定義していきます。
以下のようなワークフローを目指しました。

StepFunctionsでの実行の流れとしては
まず新しいデータに対してモデルのトレーニングジョブ行います。
続いてnew期間中で作成された学習モデルでバッチ推論ジョブold期間中で作成された学習モデルでバッチ推論ジョブの実行。
最後にnew学習モデルとold学習モデルをAUCで評価して、良かった方を採用といったものになります。

 

StepFunctionsの各プロセス(step)の作成

StepFunctionsのビジュアルワークフローのModel Trainingの部分の例です。

trainining_stepにプロセスの名前やestimator、学習に用いるデータのS3パスを渡してTrainingStepを定義します。
ステートマシン図を書かなくてもpythonのSDKからプロセスを定義できるみたいです。
またノートブック上で動作の確認ができていればStepFunctionsのワークフローに乗せられるので、モデル開発者が本番環境のリソースやパッケージのバージョンを気にする負担は減らせるのかなと思いました。

 

StepFunctionsの各プロセス(step)を連結

training_stepのように、その他のプロセスについても定義した後
独立して定義されたプロセスを連結させてあげます。

作成したワークフローはノートブック上で可視化して確認することができます。

またノートブック上からStepFuncsionsをキックし、その実行状況もセルに出力することができました。

ノートブックインスタンス環境から色々なAWSのサービスを使えるようにするためのIAMの設定が必要になりますが
今回のハンズオンで作成した「SageMakerとStepFunctionsを用いた更新フロー」の開発はノートブック上で完結するものになっていました☆
3時間という短い時間で開発環境構築から機械学習パイプライン作成までできてしまうのは衝撃的でした。

最後に

実際のAirTrackサービスを意識した機械学習のパイプラインを作成するハンズオンをAWS様に開催していただきました。
機械学習サービスに携わったことのあるメンバーだけでなく初めて触れるメンバーも参加し、とても良い機会だったと思います。
また早速今回の知見を業務内で活かせる場面もあったりと、収穫の多いハンズオンでした。
オフライン開催の厳しい時世の中、急遽オンライン開催で対応していただき本当にありがとうございました!

ハンズオンの様子です☆

会社に来ていたメンバーで自席以外で作業したいメンバーは少し広めの部屋から参加しました☆

最後まで読んでいただきありがとうございます!

]]>
Direct Connect Gateway を利用した海外リージョンとの接続 https://cyberagent.ai/blog/no_use/network/4162/ Tue, 31 Jul 2018 09:00:51 +0000 https://cyberagent.ai/techblog/?p=4162 こんにちは。アドテクスタジオでネットワークエンジニアをしている山本 孔明です。

Direct Connect について

以前に VPCエンドポイントを使ったS3プライベートアクセスのススメ でも触れましたが、弊社ではプライベートクラウドと AWS を Direct Connect で接続しています。
日本の Equinix を経由しているため、AWS 東京リージョンとの接続に利用しています。ちなみに、 Direct Connect って何だろう?という人は以下の公式ページを参照してください。

https://docs.aws.amazon.com/ja_jp/directconnect/latest/UserGuide/Welcome.html

イメージ図としては以下の通りなのですが、(構成にもよりますが) ざっくり言うと閉域網で AWS Direct Connect endpoint と Customer Router を BGP で接続して、AWS のVPC へ作成した Subnet を内部ネットワークとして扱うものです。

※ 公式ページより引用

 

公式ページも記載がありますが、満たすべきネットワーク要件の一つに以下があり、東京( Equinix TY2, Tokyo, Japan )経由で接続を行っている場合は、AWS Direct Connect Endpoint として東京リージョンを選択することとなります。

ネットワークが既存している AWS Direct Connect ロケーションと同じ場所にある。利用可能な AWS Direct Connect ロケーションの詳細については、「AWS Direct Connect 製品の詳細」を参照してください。

Direct Connect Gateway とは?

従来の構成の Virtual Private Gateway と AWS Direct Connect Endpoint との間に入る仮想デバイスです。それで何が意味あるの?ってところなのですが、

Direct Connect Gateway を利用することで以下のメリットがあります。

  • 複数の VGW (仮想プライベートゲートウェイ)を接続することが可能
  • 作成すると複数のリージョンに Direct Connect Gateway が複製され、そのリージョンの VGWを接続することが可能

つまりこの Direct Connect Gateway を利用することで、海外のリージョンとプライベートクラウドを東京の Direct Connect 契約の上で実現することが可能となります。

US ので例になりますが、以下の図がイメージしやすいかと思います。

※ 公式ページより引用

 

弊社でも既に半年程度の利用実績があり安定して稼働しています。今までは VPC ピアリングと NAT の組み合わせや VPN 接続をする必要がありましたが、シンプルな構成で作成できる点や VPN に比べてオーバヘッドが少ない点が大きなメリットと感じています。

Direct Connect Gateway の作成方法

作成方法は非常に簡単です。

1. Direct Connect Gateway の作成

Direct Connect を契約しているロケーションで作成してください。
名前と ASN 番号を入力するのみです。後々、VGW や VIF を接続していくための仮想デバイスです。

2. Virtual Interface の作成

自身のアカウントに Direct Connect 接続も対象の VPC も存在する場合は、My AWS Account を選ぶと、Direct Connect Gatewayを VIF 作成時に接続することが可能です。
※ マスターアカウントを持って、VIF を他のアカウントに作成する場合は、そちらのアカウントで VIF の作成を承諾する際に Direct Connect Gateway と接続することができます。

3. Direct Connect Gateway に VGW を接続

Direct Connect Gateway の設定画面から該当のデバイスを選択して、アクション -> 仮想プライベートゲートウェイの関連付けを選択します。
VGW には VPC を紐付けておく必要があります

4. ルートテーブルに VGW からのルート伝播

ルートテーブル -> ルート伝播 -> 仮想プライベートゲートウェイの伝播を「はい」に設定する

このあたりの手順は頻度によっては GUI で実施する必要はないかなと思います。自動化しておくと良いと思います。

まとめ

海外リージョンでも Direct Connect Gateway が見えますので、該当リージョンで 3 と 4 の手順を繰り返すことで東京の Direct Connect 接続に紐付いた Direct Connect Gateway に海外リージョンの VGW(VPC)を接続することが可能となります。

簡単に Ping を打ってみただけですが、都内の某所からバージニアまで140 から 150 msec 程度でした。

海外にシステム構築をしても社内の LDAP や共通システムなどを変えずに利用したいなどのニーズに容易に答えることが可能になりました。

]]>
AWS Kinesis Firehoseとkinesis-agentを利用してログをs3に収集する https://cyberagent.ai/blog/tech/aws/3921/ Thu, 11 Jan 2018 09:51:05 +0000 https://cyberagent.ai/techblog/?p=3921 こんにちは、アドテク本部でインフラエンジニアをしております山下といいます。

去年の話にはなりますが、2017年8月末、待ちに待っていた Kinesis Firehose が東京リージョンでも利用可能になりました。

利用可能になってすぐFirehoseの導入を行い現在運用している状態なので、溜まったノウハウを書いていきたいと思います。

 

Kinesis Firehoseとは

これまでAWS東京リージョンでKinesisと言えば、唯一利用できていたサービスは Kinesis Stream でした。

Streamに対してデータを流し、別途ワーカーを用意してデータをStreamから出してデータを加工したり

Redshiftに投入したり、そのままs3にputすることで保存を行うといった使い方をされていたかと思います。

8月に利用が可能になったKinesis Firehose は Delivery Stream というデータの受け口にデータをPUTし、その後設定した出力先に対してデータをストアしてくれます。

つまりシンプルにデータを置きたいだけであればワーカーを用意する必要がなくなります。

決められた出力先は以下の4種類です。

  • s3
  • Redshift
  • AWS ElasticSearch
  • Splunk

Splunkは最近追加されたようです。

データを加工する必要が無く、s3やRedshiftに保存したいといった場合には最適かと思います。

データの加工やデータの中身によって何かしら行いたい場合にはこれまで通り Kinesis Stream を選択する方が良いのかなと思います。

 

kinesis-agentを使った送信

Firehoseへデータを送信するにあたり、td-agentを使う方法もありましたが、ログをtailして送信するだけの用途なので

よりシンプルなAmazon謹製のkinesis-agentを使ってみることにしました。

インストールについてや各種設定パラメータ等はドキュメントがあります。

http://docs.aws.amazon.com/ja_jp/streams/latest/dev/writing-with-agents.html

ドキュメントのタイトルの通り、このドキュメントはKinesis Streamへの送信が前提に書かれていますのであくまで参考ですね。

AmazonLinuxの場合、yumでインストールができます。

またgithub上にソースコードもあります。
https://github.com/awslabs/amazon-kinesis-agent

パラメータについては公式ドキュメントがStreamのものなので、載っていなかった

firehose.endpoint
  やスレッド周りの細かい挙動の設定など、以下のgithubのsampleファイルにしか無いものもチラホラ見受けられます。

https://github.com/awslabs/amazon-kinesis-agent/blob/830ef04971c7b50a63ff99ca60cf1974ea080be7/tst/com/amazon/kinesis/streaming/agent/config/agentconfig1.json

基本的な設定としては

/etc/aws-kinesis/agent.json
  に以下のように書くとログを読み込んで送信まで行われます。

またkinesis-agentの機能として送信時のエラーなどのメトリクスをCloudWatchに記録することもできます。

{
  "cloudwatch.emitMetrics": true,
  "cloudwatch.endpoint": "monitoring.ap-northeast-1.amazonaws.com",
  "firehose.endpoint": "https://firehose.ap-northeast-1.amazonaws.com",
  "flows": [
    {
      "filePattern": "/var/log/syslog*",
      "deliveryStream": "fh-sample01",
    }
  ]
}

送信に失敗した場合、バッファを再送用のキューに溜める挙動となっており、再送処理は行われますが

このキューのサイズはデフォルトで100となっており、この値を超えて送信に失敗すると送信できないデータが発生します。

(キューに入らずdropされる)

デフォルトのログレベルではこの事象の発生を確認する方法はありませんが

ログレベルを

TRACE
 まで落とすと送信できないデータが発生した際にロギングすることができます。

https://github.com/awslabs/amazon-kinesis-agent/blob/51c60e07b7f2069a1424aa651fa09a2b46fdc721/src/com/amazon/kinesis/streaming/agent/tailing/SimplePublisher.java#L160

ログレベルの設定は

/etc/sysconfig/aws-kinesis-agent
  内に
AGENT_LOG_LEVEL="TRACE"
  とすることで設定できます。

 

運用してみて

kinesis-agentのヒープサイズに注意する

kinesis-agentはjavaで作られており、デフォルトのヒープサイズが512MBとなっているのですが、

大きなログファイルを読み込みパースする際にエラーとなる場合があります。

サイズが大きなログファイルを送信することが見えている場合は

/usr/bin/start-aws-kinesis-agent
  を編集して先にヒープサイズを上げておくのが無難です。

JAVA_START_HEAP=${JAVA_START_HEAP:-32m}
JAVA_MAX_HEAP=${JAVA_MAX_HEAP:-512m}

デフォルトでは上記のようになっていますので、この部分を適当な値に変更しプロセスを再起動します。

 

Firehoseのキャパシティに注意する

こちらのドキュメントにもあるように、Firehoseの配信ストリームが受け付けられるキャパシティには制限があり、

送信するログの量に応じて順次制限を緩和していく必要があります。

Firehoseの制限緩和ができていない状態で、大量の送信を行うとPUTをなかなか受け付けてくれず、

ログ送信がクライアント側(agent側)で遅延が発生します。

制限緩和については他のAWSサービス同様、サポートケースより行うことができます。

緩和を行う量にもよりますが、緩和までに要する時間はおおよそ 3-4営業日(またはそれ以上)見ておいた方が無難です。

ログのサイズによって計画的に利用する必要があります。

 

kinesis-agentの状態を確認する(チェックポイントを確認する)

kinesis-agentは自身が読んだファイル名、i-node、オフセット値、チェックポイントの最終更新日時をsqliteで保存しています。

上述のようなキャパシティ不足による遅延が起きた場合にこのチェックポイントを確認して遅延状況を把握します。

デフォルトの保存先は

/var/run/aws-kinesis-agent/checkpoints
です。

チェックポイントが最新データと乖離してくるとagentのログファイルに以下のようなログが出るようになります。

[WARN] Agent: Tailing is 54.503906 MB (57151716 bytes) behind.

このbehind値が大きくなる一方の場合、Firehose側の制限緩和が必要な状態になっている可能性が高いです。

 

トラフィックに注意

Firehoseのエンドポイントへの送信は、インターネットへのアウトバウンド通信となります。

もしNAT Gatewayを経由して大量のログを送信した場合、通常発生するアウトバウンド通信の費用とは別に

以下の通りNAT Gatewayで処理されたトラフィック 1GBにつき費用が発生します。
https://aws.amazon.com/jp/vpc/pricing/

この構成のままログのサイズが増えていくとNAT Gatewayの費用が高騰してしまうため、注意が必要です。

回避策として、ログ送信元のEC2をプライベートサブネットからパブリックサブネットへ移し

EIPを付けることでNAT Gatewayを経由しなくする方法が考えられます。

 

まとめ

Firehoseを実際に使用してみていくつか注意する点があることが分かりました。

先に挙げた注意点以外にも、Firehoseのキャパシティに対して現状どれくらい使っているかという部分が見えづらく

自分たちで計算・確認を行う点が辛かったりします。

しかし、td-agentのサーバを複数台立ててサービスの規模に合わせて拡張・運用していくことを考えると、

データを送ってさえしまえば適宜保存まで行ってくれるFirehoseは便利なサービスだなと感じています。

今後より使いやすく便利になることを期待します。

 

]]>
AWSルートユーザの管理とKibana (Watcher)を使った利用検知 https://cyberagent.ai/blog/tech/aws/10213/ Tue, 12 Dec 2017 03:13:38 +0000 https://cyberagent.ai/techblog/?p=3909 こんにちは、アドテクスタジオでセキュリティエンジニアをしている岡崎です。

今回は、「AWSルートユーザの管理とKibana (Watcher)を使った利用検知」について、紹介させていただきます。

 

アドテクスタジオではAWS利用において、ルートユーザの利用を制限しています。
ルートユーザはAWSの中でとても強い権限を持ち、AWSの解約もできてしまうほどです。
また、ルートユーザのように一意のユーザに紐付かないアカウント(共用アカウント)は、セキュリティ事故のときに「誰が操作したか、分からない」という事態に陥ることがあります。

 

そのため、アドテクスタジオではルートユーザはセキュリティチームが管理し、利用者にはフェデレーションユーザでのログインを推奨しています。

 

*詳しくは、前回のブログを参照してください。
AWS Management ConsoleへのSSO ー PingFederateのインストール編

https://cyberagent.ai/techblog/archives/2811

AWS Management ConsoleへのSSO ー PingFederateの設定編

https://cyberagent.ai/techblog/archives/2822

 

 

 

ですが、以下のようにルートユーザでないと、できないこともあります。

・ルートユーザーの詳細の変更。これには、ルートユーザーのパスワードの変更が含まれます。

・AWS のサポートプランの変更。

・支払オプションの変更、または削除。

・アカウントの請求情報の参照。IAM ユーザーの請求へのアクセスを有効にする方法についての詳細は、「請求情報およびコスト管理コンソールへのアクセスのアクティベート」を参照してください。

・AWS アカウントの解約。

・GovCloud へのサインアップ。

・Amazon EC2 リクエストの逆引き DNS を送信します。リクエストを送信するためのページ上の「このフォーム」のリンクは、ルートユーザー認証情報でサインインする場合にのみ動作します。

・CloudFront のキーペアの作成。

・AWS 作成の X.509 署名証明書の作成。(IAM ユーザー用に自己作成証明書を作成することはできます。)

・Amazon Route 53 ドメインを別の AWS アカウントに転送。

・長いリソース ID の Amazon EC2 設定の変更。ルートユーザーとしてこの設定を変更すると、アカウントのすべてのユーザーとロールに影響します。IAM ユーザーまたは IAM ロールとして変更すると、そのユーザーまたはロールにのみ影響します。

・AWS インフラストラクチャで侵入テストを実行するリクエストを送信します。

・AWS サポートケースを開き、[Regarding: Account and Billing Support] を指定します。

・EC2 インスタンスでのポート 25 による E メールのスロットリングの削除をリクエストします。

・AWS アカウントの正規ユーザー ID を検索します。

参考:  http://docs.aws.amazon.com/ja_jp/general/latest/gr/aws_tasks-that-require-root.html

 

上記の中でも、アドテクスタジオでは以下の操作時にルートユーザを使うことが多いです。
・AWS のサポートプランの変更。
・Amazon Route 53 ドメインを別の AWS アカウントに転送。
・AWS インフラストラクチャで侵入テストを実行するリクエストを送信します。

上記のような操作のときにルートユーザが利用されたかが「わかるように」なっている仕組みが必要です。

そこで、アドテクスタジオでも利用しているKibanaのWatcher機能を活用した検知とアラート送信を簡単に説明します。

 

以下は、大まかな流れになります。
*AWS CloudTrailからElasticSearchへのログ転送は、今回は詳細な説明は割愛します。

 

Kibanaの新規サービスX-Packのひとつの機能である「Watcher」の活用を中心に説明させていただきます。
X-Packとは、ElasticSearchとKibanaにさらに利用しやすくしてくれるオプションになります。
Security・Alerting・Monitoring・Reporting・Graph・Machine Learningような様々な機能があり、今回はAlerting (Watcher 経由)の活用になります。

 

X-Packインストール
*ElasticSearchとKibanaはインストールされているものとします

# 一時、サービス停止
systemctl stop elasticsearch
systemctl stop kibana

*データ量によっては時間が時間がかかります
/usr/share/elasticsearch/bin/elasticsearch-plugin install x-pack
…………
systemctl restart elasticsearch

/usr/share/kibana/bin/kibana-plugin install x-pack
systemctl restart kibana
* 初期ユーザーはユーザー名がelastic、パスワードがchangemeです。


*セキュリティ(ログインが不要)の場合は、無効にする。有効になっていると、ElasticSearchにデータをPOSTする際にも認証が必要になります。
# vi /etc/elasticsearch/elasticsearch.yml
xpack.security.enabled: false
*xpack.security.enabledのsecurityをmonitoring、graph、watcher、reportingにすることでそれぞれの機能を無効化設定することができます。

 

Kibana – WatcherからのSlackへのアラート通知のため、Webhook URLの設定

*対象Slackのチャンネルを作りWebhook URLを準備してください。

# vi /etc/elasticsearch/elasticsearch.yml
〜省略〜
xpack.notification.slack:
 account:
   このWebhookURLの名称:
     url: https://hooks.slack.com/services/xxxxxxxxxxxxxxxxxxxxxxxx

*ElasticSearchを再起動してください

これで下準備は完了になります。

 

続いて、ルートアカウントでのAWSマネジメントコンソールへのログインを検知し、アラート通知したい場合の設定

Watcherの例

{
 "trigger": {
   "schedule": {
     "interval": "5m"    // チェック間隔
   }
 },
 "input": {
  "search": {
    "request": {
      "search_type": "query_then_fetch",
      "indices": [
        "aws-cloudtrail-log"     // 対象のログ
      ],
      "types": [],
      "body": {
        "query": {
          "query_string": {
            "fields": [
              "Username",     // 対象のフィールド名
              "EventName"
            ],
            "query": "root AND ConsoleLogin"    // 条件値
          }
        }
      }
    }
  }
 },
 "condition": {
   "compare": {
     "ctx.payload.hits.total": {
       "gt": 0   // 1回以上でアラート
     }
   }
 },
 "actions": {
   "notify-slack": {
     "throttle_period_in_millis": 600000,
     "slack": {
       "account": "monitoring",   // elasticsearch.ymlで設定した値
       "message": {
         "from": "watcher",
         "to": [
           "#channelname"
         ],
         "text": " ルートユーザでログインされました。 "   //Slackに投稿するメッセージ
       }
     }
   }
 }
}

*inputの条件の書き方はさまざまですので、色々試してみてください。

参考:

https://www.elastic.co/guide/en/elasticsearch/reference/5.5/watcher-api-put-watch.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html

https://www.elastic.co/guide/en/x-pack/5.5/actions-slack.html

 

上記の設定により、AWSにマネジメントコンソールにルートアカウントで1回以上ログインされるとSlackにアラートが通知されます。

ぜひ、お試しください。

 

おまけ

今回、Route53のログが取得できないので調べていたところ、以下のような条件があることに気づきました。

Route53などのCloudTrailは「米国東部(バージニア北部)us-east-1」に保存されるので、注意しましょう。

Amazon Route 53 向けの CloudTrail の設定

AWS アカウントによって行われた API リクエストに関する情報をキャプチャするように CloudTrail を設定するときは、まずリージョンを選択します。Amazon Route 53 の場合、リージョンとして [米国東部(バージニア北部)] を選択する必要があります。そうしないと、Amazon Route 53 API リクエストのログエントリを取得できません。

参考: http://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/logging-using-cloudtrail.html#cloudtrail-configuring-for-route-53

 

おわりに

今回は、「AWSルートユーザの管理とKibana (Watcher)を使った利用検知」について、紹介させていただきました。
Watcherの設定はJSONでの記述のため、多少クセがあります。。。こちら改善されることを願ってます。

アドテクスタジオでは複数のAWSを一括で管理する必要があるため、すべてのCloudTrailのデータを集約し可視化するため、このような方法を取っています。

同様の要領でGCPのAudit Logに対しても、有効な方法だと思いますので、今度はそちらにも試してみようと考えてます。

 

]]>
AWS SSOと外部サービスを連携(Slack編) https://cyberagent.ai/blog/tech/aws/10212/ Mon, 11 Dec 2017 06:54:41 +0000 https://cyberagent.ai/techblog/?p=3894 はじめに

こんにちは、アドテクスタジオでセキュリティエンジニアをしている岡崎です。

先日、「AWS re:Invent」が開催されましたね。AWSの機能がどんどん増えていきますね。

*参考: https://reinvent.awsevents.com/

 

さらに12/7に「AWS re:Invent」では発表されなかった「AWS Single Sign-On」が突如発表されました。

参考:「Announcing AWS Single Sign-On (SSO)」

https://aws.amazon.com/jp/about-aws/whats-new/2017/12/announcing-aws-single-sign-on–sso/

 

早速、Slackとの連携を試してみました。

 

ちなみに費用は無料のようです。*AWS側にMicrosoft ADを構築必要があるので、完全無料というわけではなさそうです。

There is no additional cost to enable AWS SSO. It is now available in the US East (N. Virginia) Region.

参考: https://aws.amazon.com/jp/about-aws/whats-new/2017/12/announcing-aws-single-sign-on–sso/

*「SAMLの設定の流れ」は先日紹介した「AWS Management ConsoleへのSSO ー PingFederateの設定編」を参考にしてください。  https://cyberagent.ai/techblog/archives/2822

 

AWS Single Sign-Onの設定

「AWS Single Sign-On」を「有効」にするは以下のように条件があるようです。

・You must have first set up the AWS Organizations service and have All features set to enabled. You must also have access to the AWS Organizations master account credentials. These credentials are required to enable AWS SSO. For more information, see Creating and Managing an AWS Organizations in the AWS Organizations User Guide.

・You must have an existing Microsoft Active Directory (AD) set up in AWS Directory Service that you can connect to AWS SSO. This AWS Microsoft AD directory determines which pool of users has SSO access to the user portal. You can connect only one AWS Microsoft AD directory at a time. However, you can change it to a different AWS Microsoft AD directory at any time. For more information, see Create a Microsoft AD Directory in the AWS Directory Service Administration Guide.

・Your connected directory must be in the US East (N. Virginia) (us-east-1) Region where AWS SSO is also available. AWS SSO stores the assignment data in the same region as the directory. To administer AWS SSO, you must be in the us-east-1 region. Also, note that AWS SSO’s user portal uses the same access URL as your connected directory.

参考: http://docs.aws.amazon.com/ja_jp/singlesignon/latest/userguide/prereqs.html

 

簡単に説明しますと、

・AWS Organizationsが「ENABLE ALL FEATURES」になっている必要があります。

 *AWSマネジメントコンソールログイン後、以下のURLから確認できます。  https://console.aws.amazon.com/organizations/home#/organization/overview

・Directoryとして、Microsoft Active Directory(AD)が必要になります。

・そして、AWS Directory Serviceは、米国東部:us-east-1 (バージニア北部)にあることが必要です。

 *Microsoft Active Directory(AD)を操作する際は、Windows OSが必要になります。

 *Microsoft Active Directory(AD)の操作はwindows専用の管理ツール「リモートサーバ管理ツール」で行います。  https://support.microsoft.com/ja-jp/help/2693643/remote-server-administration-tools-rsat-for-windows-operating-systems

 

 

条件を満たしていない画面:

 

条件を満たした画面:

 

Slackとの連携

Slackとの連携には、AWS SSO側にインテグレーションが用意されており、容易に連携が可能です。

また、AWS SSO側に詳細な手順が発行され、その手順に則って、Slack側のSAML設定をするだけで、完了になります。

*SlackとのSSO連携にはSlack「プラス」が必要になります。  https://slack.com/pricing

 

「AWS SSO」> 「Applications」 > 「Slack」と進み、「View instructions」をクリックすると、詳細な設定手順が表示されます。

 

[AWS SSOとSlack連携手順]

*自AWS側の値が入っているので、とても親切です。

 

[AWS SSOの設定]

上記の内容をもとにSlack側のSAML設定をしましょう。

参考:Slack側のSAML設定  https://get.slack.help/hc/ja/articles/203772216-SAML-%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%82%B5%E3%82%A4%E3%83%B3%E3%82%AA%E3%83%B3

 

ユーザに対して、Slackを利用権限の付与は、AWS SSO管理画面にて、グループまたはユーザレベルで設定します。

 

Slack以外にもさまざまなインテグレーションが準備されていました。

 

おわりに

ついにAWSでのSSOがリリースされました。

AWSとMicrosoft Active Directory(AD)を活用されている企業では、「AWS SSO」を利用することにより、アカウント管理が強化されることでしょう。

現在、AWS SSOの「Directory Service」は「Microsoft Active Directory(AD)」にしか、対応してませんが、今後、LDAPなどにも対応することを期待してます。

 

今後もAWSの追加機能が楽しみですね。

]]>
AWS Guard Dutyをさっそく活用 https://cyberagent.ai/blog/tech/aws/10210/ Tue, 05 Dec 2017 02:20:06 +0000 https://cyberagent.ai/techblog/?p=3810 はじめに

こんにちは、アドテクスタジオでセキュリティエンジニアをしている岡崎です。

先日、「AWS re:Invent」が開催されましたね。AWSの機能がどんどん増えていきますね。

*参考: https://reinvent.awsevents.com/

 

その中で、セキュリティ関連で大きな機能追加がされました。

「re:InventのTuesday Night Live」というセッションで、「Amazon GuardDuty」が公開されました。

*参考: https://aws.amazon.com/jp/blogs/news/amazon-guarduty-continuous-security-monitoring-threat-detection/

 

Amazon GuardDutyとは

Amazon GuardDuty は、VPC フローログおよび AWS CloudTrail イベントログを分析および処理する継続的なセキュリティモニタリングサービスです。GuardDuty は、セキュリティロジックと AWS の使用統計を使用して、AWS 環境内の予期しない、未承認および悪意のあるアクティビティの可能性を特定します。

参考: http://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/what-is-guardduty.html

 

簡単に言うと、AWS内のセキュリティ問題点をピックアップしてくれるようです。

 

「これは、便利!!!」と、思ったので早速、利用してみたいと思います。

 

と、その前に、、、料金表のチェックを忘れずに!!

 

[利用料金]

Amazon GuardDuty is priced along two dimensions. The dimensions are based on the quantity of AWS CloudTrail Events analyzed (per 1,000,000 events) and the volume of Amazon VPC Flow Log and DNS Log data analyzed (per GB).

イベント件数とデータ量により、費用が変わるようですね。

*30日間は無料のようです。

参考: https://aws.amazon.com/jp/guardduty/pricing/

 

無料期間もあるということで、早速利用してみました。

 

[Amazon GuardDutyの有効の仕方]

AWSマネジメントコンソールにログインし、「セキュリティ、 アイデンティティ、 コンプライアンス 」>「GuardDuty」を選択します。

あとは、「GuardDutyの有効化」をクリックするだけです。

*「GuardDutyの有効化」しますと、「AWSServiceRoleForAmazonGuardDuty」というロールが自動で作成されます。

「AWSServiceRoleForAmazonGuardDuty」にアタッチされたポリシー

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Effect": "Allow",
           "Action": [
               "ec2:DescribeInstances",
               "ec2:DescribeImages"
           ],
           "Resource": "*"
       }
   ]
}

 

有効にし、数分すると、、、早速、予め仕込んでおいたEC2の問題点が表示されました。

* 例:
Unprotected port on EC2 instance i-0xxxxxx is being probed.
Unprotected port on EC2 instance i-0yyyyyy is being probed.
Unprotected port on EC2 instance i-0zzzzzz is being probed.
Unprotected port on EC2 instance i-0aaaaaa is being probed.

 

「ポート22がインターネットに公開されている」と指摘を受けました。

 

 

結果を活用

結果は、AWS CLIでも取得できるので、JSON形式で取得したデータを分析・加工して表示が簡単に行なえます。

結果取得のために必要なコマンドをいくつか紹介します。

 

1,AWSアクセスキーを発行し、「AmazonGuardDutyReadOnlyAccess 」を付与します。

「AmazonGuardDutyReadOnlyAccess 」のポリシー

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Sid": "AllowAllUsersToViewAndManageThisGroup",
           "Effect": "Allow",
           "Action": [
               "guardduty:GetDetector",
               "guardduty:ListDetectors",
               "guardduty:GetIPSet",
               "guardduty:ListIPSets",
               "guardduty:GetThreatIntelSet",
               "guardduty:ListThreatIntelSets",
               "guardduty:GetFindings",
               "guardduty:GetFindingsStatistics",
               "guardduty:ListFindings",
               "guardduty:GetMembers",
               "guardduty:ListMembers",
               "guardduty:GetMasterAccount",
               "guardduty:ListInvitations",
               "guardduty:GetInvitationsCount"
           ],
           "Resource": "*"
       }
   ]
}

 

2,「aws guardduty」コマンドを利用するためにawscliのアップデート

pip install awscli --upgrade --user

aws --version
aws-cli/1.14.2 Python/2.7.10 Darwin/17.2.0 botocore/1.8.6

 

3,「aws guardduty」の確認

aws guardduty help

(省略)
AVAILABLE COMMANDS
(省略)
      o get-detector
      o get-findings
      o get-findings-statistics
      o get-invitations-count
      o get-ip-set
      o get-master-account
      o get-members
      o get-threat-intel-set
      o help
      o invite-members
      o list-detectors
      o list-findings
      o list-invitations
      o list-ip-sets
      o list-members
      o list-threat-intel-sets
(省略)

参考: http://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_api_ref.html

 

4,詳細を取得する

[aws guardduty list-detectors]

Detector IDを取得します。

aws --profile projectA guardduty list-detectors

{
   "DetectorIds": [
       "deb0012345678901234567890"
   ]
}

 

[aws guardduty list-findings]

上記のDetector IDを利用し、Finding IDを取得します。

*Finding IDが「GuardDuty」の結果で表示された項目になります。

aws --profile projectA guardduty list-findings --detector-id deb0012345678901234567890

{
   "FindingIds": [
       "11111111111111111111111111111111",
       "22222222222222222222222222222222",
       "33333333333333333333333333333333",
       "44444444444444444444444444444444"
   ]
}

 

[aws guardduty get-findings]

Findingの詳細を取得

aws --profile projectA guardduty get-findings --detector-id deb0012345678901234567890 --finding-id 11111111111111111111111111111

{
   "Findings": [
       {
           "Resource": {
               "ResourceType": "Instance",
               "InstanceDetails": {
                   "ProductCodes": [],
                   "AvailabilityZone": "ap-northeast-1a",
                   "Tags": [
                       {
                          (省略)
                       },
                       {
                          (省略)
                       }
                   ],
                   "InstanceId": "i-bbbb",
                   "InstanceState": "running",
                   "ImageId": "ami-bbbb",
                   "LaunchTime": 17000,
                   "InstanceType": "m4.xlarge",
                   "NetworkInterfaces": [
                       {
                           "VpcId": "vpc-1111",
                           "PrivateIpAddresses": [
                               {
                                   "PrivateDnsName": "ip-xxxxxx.ap-northeast-1.compute.internal",
                                   "PrivateIpAddress": "x.x.x.x"
                               }
                           ],
                           "PublicDnsName": "ec2-xxxx.ap-northeast-1.compute.amazonaws.com",
                           "PublicIp": "y.y.y.y",
                           "PrivateDnsName": "ip-yyyy.ap-northeast-1.compute.internal",
                           "SecurityGroups": [
                               {
                                  (省略)
                               },
                               {
                                  (省略)
                               }
                           ],
                           "Ipv6Addresses": [],
                           "SubnetId": "subnet-eaaa",
                           "PrivateIpAddress": "c.c.c.c"
                       }
                   ]
               }
           },
           "Description": "EC2 instance has an unprotected port which is being probed by a known malicious host.",
           "Service": {
               "Count": 10,
               "Archived": false,
               "ServiceName": "guardduty",
               "EventFirstSeen": "2017-12-04T02:21:31Z",
               "ResourceRole": "TARGET",
               "EventLastSeen": "2017-12-04T03:53:29Z",
               "DetectorId": "deb0012345678901234567890",
               "Action": {
                   "ActionType": "PORT_PROBE"
               }
           },
           "Title": "Unprotected port on EC2 instance i-xxxxxx is being probed.",
           "Type": "Recon:EC2/PortProbeUnprotectedPort",
           "Region": "ap-northeast-1",
           "Partition": "aws",
           "Arn": "arn:aws:guardduty:ap-northeast-1:12345:detector/deb0012345678901234567890/finding/111111111111111111111111",
           "UpdatedAt": "2017-12-04T04:03:02.890Z",
           "SchemaVersion": "2.0",
           "Severity": 2.0,
           "Id": "c1111111111111111",
           "CreatedAt": "2017-12-04T02:33:02.886Z",
           "AccountId": "1111111"
       }
   ]
}

 

[aws guardduty get-findings-statistics]

重大度の取得

aws --profile projectA guardduty get-findings-statistics --detector-id deb0012345678901234567890 --finding-statistic-type COUNT_BY_SEVERITY

{
   "FindingStatistics": {
       "CountBySeverity": {
           "2.0": 4
       }
   }
}

上記の場合は、「2.0(低)が4件」存在することがわかります。

参考: http://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_findings.html#guardduty_findings-severity

 

 

おわりに

今まで、さまざまなツールを利用し、AWSのセキュリティ情報を収集してきましたが、「AWS GuardDuty」を利用することにより、さらにAWSのセキュリティ強化ができそうです。

CloudWatchとも連携できるので、今後はそちらも試していこうと思ってます。

 

今後もAWSの追加機能が楽しみですね。

 

]]>
Amazon EC2 コンピューティング最適化インスタンスC5でベンチマーク https://cyberagent.ai/blog/tech/aws/10205/ Wed, 08 Nov 2017 09:10:00 +0000 https://cyberagent.ai/techblog/?p=3578 アドテク本部インフラエンジニアの加藤です。

Amazon EC2 の新しいハイパーバイザを採用したコンピューティング最適化インスタンスC5が、バージニア北部、オレゴン、アイルランドの 3リージョンで利用可能になったようです。

C4インスタンスはローンチ直後から東京リージョンで使えたことを考えると少し残念ですが、早速 バージニア北部リージョンに ローンチされたばかりのC5インスタンスを作成してベンチマークを行いたいと思います。

C5インスタンスについては、Amazon Web Services ブログ に説明があります。

 

C5インスタンスベンチ結果

早速ですが、 C5インスタンス全6インスタンスのベンチマークの結果です。

Amazon Linux AMI 2017.09.1 (HVM), SSD Volume Type – ami-6057e21a と汎用 SSD(GP2) 40GBの構成で、UnixBench 5.1.3での計測しました。

1 parallel
System Benchmarks Index Values c5.large c5.xlarge c5.2xlarge c5.4xlarg c5.9xlarg c5.18xlarge
Dhrystone 2 using register variables 3610.1 3612.1 3605.4 3610.3 3705 3704.5
Double-Precision Whetstone 743.2 745 745.8 746.5 713.6 717.2
Execl Throughput 1725 1289.1 1278.3 1327.4 1234.1 806.1
File Copy 1024 bufsize 2000 maxblocks 3444.6 3474.2 3075.6 3444.7 3479.1 3540.2
File Copy 256 bufsize 500 maxblocks 2347.7 2393.2 2362.1 2378 2443.2 2450.9
File Copy 4096 bufsize 8000 maxblocks 3884.6 5193.4 4411 5924.1 6472.2 6505.1
Pipe Throughput 2375.7 2383.3 2383.8 2390.8 2446.2 2443.4
Pipe-based Context Switching 269.8 230.7 210.6 234.5 398.8 398.5
Process Creation 1480.8 942.5 1040.7 1095.3 1231.5 742.1
Shell Scripts (1 concurrent) 2491.7 2465.7 2553.1 2649.4 2385 1934.5
Shell Scripts (8 concurrent) 2796.2 4663.2 7367.3 9218 9271.1 8266.7
System Call Overhead 3046.2 3030.5 3021.9 3016 3112.5 3123.6
System Benchmarks Index Score 1944.9 1932 1962.9 2111.5 2226.5 2010.6

 

2 parallel 4 parallel 8 parallel 16 parallel
System Benchmarks Index Values c5.large c5.xlarge c5.2xlarge c5.4xlarg c5.9xlarg c5.18xlarge
Dhrystone 2 using register variables 4520.8 8978.6 18040.9 36123.9 57776 57756.7
Double-Precision Whetstone 1601.8 3183.6 6382.9 12801.6 11925.4 11923.7
Execl Throughput 2679 3943 7038.8 11781.5 13948.8 11471.5
File Copy 1024 bufsize 2000 maxblocks 4237.9 2433.9 2259.2 2255.3 2541.7 1563.5
File Copy 256 bufsize 500 maxblocks 2791.5 1595.7 1426.2 1458.6 1699.6 1075.2
File Copy 4096 bufsize 8000 maxblocks 8161.7 4979.5 4395 4777.6 5432.5 3609.9
Pipe Throughput 3166.6 6301.9 12620 25226.8 37952.6 37913.5
Pipe-based Context Switching 1662.5 3323.5 6948.8 13753.4 5018.7 5649.2
Process Creation 2599.1 3494.6 5323.3 8494.1 9817.2 8300
Shell Scripts (1 concurrent) 2847.5 5324.2 9668.9 18837.9 30006.1 31711.3
Shell Scripts (8 concurrent) 2739.2 5179.9 9327.9 18128.2 37960.8 49635.7
System Call Overhead 4751.5 5283.1 5186.6 5091.7 3560.3 2482.8
System Benchmarks Index Score 3148.7 4110.2 6070.9 9336.6 10457.4 9124.5

C5 世代で新しく使えるようになった c5.18xlarge  は、ベンチマークの並列数の問題か Total Score がc5.9xlarg より低い値になってしまいましたが、Shell Scripts (8 concurrent) を見ると c5.9xlarg と比べて1.3倍になっています。

処理速度だけではなく 72 GiB RAM  10Gbps Networkのc5.9xlarg に比べてc5.18xlarge は 144 GiB RAM  25Gbps Network が使える点もポイントになるかと思います。

 

C4 vs C5

続いてC4インスタンスと比べて、どの程度の性能が上がっているか、同じvCPU数ののc5.2xlarge/c4.2xlarge で確認したいと思います。

こちらもAmazon Linux AMI 2017.09.1 (HVM), SSD Volume Type – ami-6057e21a と汎用 SSD(GP2) 40GBの構成で、UnixBench 5.1.3での計測しました。

1parallel 8 parallel
System Benchmarks Index Values c5.2xlarge c4.2xlarge c5.2xlarge c4.2xlarge
Dhrystone 2 using register variables 3605.4 3256.6 110.71% 18040.9 14734.9 122.44%
Double-Precision Whetstone 745.8 839 88.89% 6382.9 5837.7 109.34%
Execl Throughput 1278.3 1192.4 107.20% 7038.8 6195 113.62%
File Copy 1024 bufsize 2000 maxblocks 3075.6 3540.7 86.86% 2259.2 2549.1 88.63%
File Copy 256 bufsize 500 maxblocks 2362.1 2279.8 103.61% 1426.2 1597.1 89.30%
File Copy 4096 bufsize 8000 maxblocks 4411 7127.3 61.89% 4395 5584.3 78.70%
Pipe Throughput 2383.8 2308.6 103.26% 12620 10331.4 122.15%
Pipe-based Context Switching 210.6 134.5 156.58% 6948.8 5029.6 138.16%
Process Creation 1040.7 897.8 115.92% 5323.3 4919.4 108.21%
Shell Scripts (1 concurrent) 2553.1 2405.5 106.14% 9668.9 9060.1 106.72%
Shell Scripts (8 concurrent) 7367.3 6771.8 108.79% 9327.9 8800 106.00%
System Call Overhead 3021.9 2665.6 113.37% 5186.6 6592.1 78.68%
System Benchmarks Index Score 1962.9 1903.9 103.10% 6070.9 5856.4 103.66%

C4/C5では、CPU世代の進化だけでなく、KVMベースの 新ハイパーバイザが採用されたようなので、期待値が高かったのですが、今回の条件では微増という結果になりましたが、東京リージョン提供後に改めて比較したいと思います。

 

おまけプライベートクラウド vs パブリッククラウド

 

おまけで、アドテクスタジオにおいて、OpenStack ocata を採用/構築したプライベートクラウド IZANAMI で利用可能なフレーバーからコア数/RAMの似通ったar1-standard-8との比較を行います。

プライベートクラウドではAmazon Linuxの利用ができないため、ar1-standard-8のみCentOS7.4で計測しています。

1 parallel 8 parallel
System Benchmarks Index Values c5.2xlarge ar1-standard-8 c5.2xlarge ar1-standard-8
Dhrystone 2 using register variables 3605.4 2523.8 142.86% 18040.9 20138.7 89.58%
Double-Precision Whetstone 745.8 668.3 111.60% 6382.9 5345.3 119.41%
Execl Throughput 1278.3 813.7 157.10% 7038.8 6698.6 105.08%
File Copy 1024 bufsize 2000 maxblocks 3075.6 2392.4 128.56% 2259.2 3222.6 70.10%
File Copy 256 bufsize 500 maxblocks 2362.1 1518.3 155.58% 1426.2 2056.7 69.34%
File Copy 4096 bufsize 8000 maxblocks 4411 5234.3 84.27% 4395 6862.1 64.05%
Pipe Throughput 2383.8 1185.5 201.08% 12620 9463.1 133.36%
Pipe-based Context Switching 210.6 754 27.93% 6948.8 6013.7 115.55%
Process Creation 1040.7 766.3 135.81% 5323.3 4849.4 109.77%
Shell Scripts (1 concurrent) 2553.1 1734.2 147.22% 9668.9 9009.7 107.32%
Shell Scripts (8 concurrent) 7367.3 5867.4 125.56% 9327.9 9621 96.95%
System Call Overhead 3021.9 1487 203.22% 5186.6 3980 130.32%
System Benchmarks Index Score 1962.9 1594.7 123.09% 6070.9 6183.1 98.19%

手前味噌ではありますが Skylake 世代の C5 インスタンスに比べて、IZANAMI は2世代前のHaswell(E5-2680 v3)を利用した環境にもかかわらず、Total Scoreは肉薄した(8 parallel は負けてない) 結果となりました。

 

最後に

アドテクスタジオでは 、パブリッククラウド、プライベートクラウドを要件によって使い分けたり、ダイレクトコネクトを利用したハイブリッドクライドとして運用しています。

C5インスタンスのように、高性能高コストパフォーマンスのインスタンスの、東京リージョンで使える日がまちどおしいですね。

]]>
アドテクスタジオのAWSにおけるセキュリティグループ整理術とScout2 https://cyberagent.ai/blog/tech/aws/2966/ Fri, 18 Aug 2017 05:30:35 +0000 https://cyberagent.ai/techblog/?p=2966  こんにちは。アドテクスタジオでセキュリティエンジニアをしている岡崎です。

 前回は、「AWS Management ConsoleへのSSO」について、紹介させていただきました。

 今回は、「アドテクスタジオのAWSにおけるセキュリティグループの整理の仕方」と「Scout2を使った可視化」をしてみたことについて、紹介させていただきます。

 

 今まで、ネットワークのセキュリティ設定「ファイアウォール」などはネットワークエンジニアが行っていました。しかし、AWSなどのパブリッククラウドを利用し始めてからは開発エンジニアがファイアウォール(AWSのセキュリティグループ)設定をする機会が増えており、今までファイアウォールの設定を経験をしていない開発エンジニアとっては設定に困ると思います。

 そんな中、見様見真似でセキュリティグループの設定をすると、、、あとあと、
「あれ、これはなんの設定?」
「このソースIPは、どこの顧客・パートナーのだろう?」
など、どんどんセキュリティグループやポリシーが増えていき、、、
 何が何だか分からなくなることありませんか。

セキュリティグループの設定が次第に煩雑になり、困ってませんか?

 

[よくある問題]

・似たようなポリシーが複数ある
例: port22 を 特定IPで許可
   port全部を 特定IPで許可

・どこのソースIPか、なんのためのポート許可か分からなくなってしまう
例: port 22を特定IPで許可したが、この特定IPは提携先のA社の?

・セキュリティグループのアタッチ状態がぐちゃぐちゃ
例: このセキュリティグループを整理しようにも、このポリシーを削除したら、あっちのインスタンスに影響出ないかな、、、

など

よって、設定を変更するのが怖くなる。
その為、インスタンスによっては通常閉じておくべきポートが空いており、攻撃されることがあります。

 

アドテクスタジオ内では下記のようなセキュリティグループのパターンを活用しています。
[セキュリティグループの4つのパターン]

1、VPCの「default」のセキュリティグループの設定する
2、環境(本番・テスト・開発)ごとにセキュリティグループを設定する
3、ロール(インスタンスの役割)ごとにセキュリティグループを設定する
4、ミドルウェア(Apache httpd, MySQL, Node.jsなど)ごとにセキュリティグループを設定する
*セキュリティの強度は、1ー>2ー>3ー>4の順に高くなってます。
*この中では、4が一番セキュリティ強度は高いですが、設定は煩雑になりがちです。

 

[4つのパターンの詳細]

パターン1:VPCの「default」のセキュリティグループの設定する
*defaultはVPCを作成すると必ず作成される為、有効活用します。
主に会社の固定IPやデータセンターのIPなど、どのインスタンスに対しても共通で許可設定をします。

セキュリティグループ名 内容
default 会社の拠点IPなどの接続許可設定

 

パターン2:環境(本番・テスト・開発)ごとにセキュリティグループを設定する
・パターン1に加えて、本番・テスト・開発などの環境ごとにセキュリティグループを分ける考え方です。

セキュリティグループ名 内容
prod 本番環境に必要な許可設定
default 会社の拠点IPなどの接続許可設定

 

パターン3:ロール(インスタンスの役割)ごとにセキュリティグループを設定する
・パターン2に加えて、加えてフロント側・バックエンド側やシステム(バッチ処理系など)ごと、機能(メールサーバなど)ごとにセキュリティグループを分ける考え方です。

セキュリティグループ名 内容
frontend フロント側に必要な許可設定
prod 本番環境に必要な許可設定
default 会社の拠点IPなどの接続許可設定

 

パターン4:ミドルウェア(Apache httpd, MySQL, Node.jsなど)ごとにセキュリティグループを設定する
・
パターン3に加えて、ロールよりさらに細かいミドルウェアごとにセキュリティグループを分ける考え方です。

セキュリティグループ名 内容
mysql MySQLに必要な許可設定
backend フロント側に必要な許可設定
dev 開発環境に必要な許可設定
default 会社の拠点IPなどの接続許可設定

 

アドテクスタジオでは、このようにセキュリティの強度により4つに分けて、適切なパターンを利用していただいてます。

 

[上記以外のセキュリティグループ設定]

パターン サンプル
顧客拠点からのアクセス許可 $(顧客名)-$(日付) from_partnerA-20170815
緊急対応の為一時的な許可 temp-$(接続元)-$(社員番号または氏名)-$(日付) temp-from_mobile-userA-20170401

 

[Tagの活用]

セキュリティグループ名は初回にしか設定できない為、検索利便性向上のために既存のものにはTagを活用しましょう。

タグ名 内容 サンプル
Env 開発、テスト、ステージング、本番などの環境 prod

test

Role どのような役割なのか frontweb

mysql

Owner 作成した方の社員番号または氏名 userA
CreateDate 作成日 20170815

 

どうぞ、セキュリティグループを整理するときは、ぜひ参考にしてください。

 

[Scout2を使った可視化]

既存のセキュリティグループを整理するには、可視化するオープンソース「Scout2」というものもあります。弊社でもScout2を活用し、不要なセキュリティグループ・ポリシーを洗い出しに利用してます。

 

Scout2ホームページ:
https://nccgroup.github.io/Scout2/
https://github.com/nccgroup/Scout2

Scout2 のインストール方法

git clone https://github.com/nccgroup/Scout2
cd Scout2
pip install -r requirements.txt
python setup.py install

#実行
/usr/local/bin/Scout2 --profile productA --report-dir /home/scout2/www/productA/ --force

*実行するには、対象のAWSのReadOnlyロールが必要になります。

*Scout2ホームページの画像を参照

 

[利用しているセキュリグループの確認方法]

「Compute > EC2 > Security group」 の 各セキュリティグループ項目の「Usage」にて、どのインスタンスにアタッチされているか、または利用されていないかがわかります。

 

[その他のセキュリティグループ可視化ツール]

有料になりますが、以下のも見やすかったです。
・http://cloudcheckr.com/
・https://www.hava.io/
試用期間もあるので、ぜひお試しください。

 

まとめ

実際にScout2を利用し、不要なセキュリティグループの洗い出しを行って見ましたところ、かなりの量のセキュリティグループが利用されておらず、残っていることがわかりました。
その後、不要なものに関しては削除し、スッキリいたしました。
Scout2はインストールも簡単ですので、ぜひご活用ください。

今回セキュリティグループに関してまとめていく中で、AWS社様への要望が見つかりました。
「セキュリティグループのポリシー項目ごとにコメント欄を実装してくれると嬉しいです。」

]]>
うるう秒の検証はしましたか?エンジニアが安心して年を越すために https://cyberagent.ai/blog/tech/aws/10190/ Tue, 27 Dec 2016 09:00:05 +0000 https://cyberagent.ai/techblog/?p=2471 Dynalystの黒崎です。
今年も残すところあと5日となり、あっという間でしたね。

ご存知の方がほとんどかとは思いますが、来年2017年1月1日にうるう秒が挿入される事が決まっています。
参考: 「うるう秒」挿入のお知らせ ~ 来年の元日はいつもより1秒長い日となります ~

簡単に言うと、原子時計に基づく時刻と天文時に基づく時刻のずれを調節するために、JSTで言うところの2017年の1月1日8時59分59秒と9時00分00秒の間に「8時59分60秒」が挿入されるというものです。
直近だと2015年7月1日にうるう秒の調整が行われました。

2015年におおよそのトラブルとなるような要因は修正されたかと思いますが、今回はUTCで年をまたぐ時の調整ですし、安心して年を越すために検証方法を確認しておきましょう。

検証環境

AWSのt2.microインスタンスを2台つかって実験しました。
OSはAmazon Linux 2016.09.1.20161221です。

AWSのうるう秒の対応状況については事前にご確認ください – AWSでのうるう秒対応【更新】が詳しいです。

EC2インスタンス上で動くAmazonLinuxのサーバに関してはうるう秒に対して特別な対応はされていないので、UTCで23時59分59秒が2回繰り返されます。

SNTPサーバ

うるう秒を再現するにあたって、うるう秒前後の時刻情報を配信してくれるNTPサーバが必要です。

NICTの日本標準時グループのサイトにあるうるう秒テスト用のスクリプトを使いました。 うるう秒とコンピュータクロック

2005年のうるう秒の検証用になっているので、2016年用に書き換えたものが以下です。

#!/usr/bin/perl -wT

use strict;
use Socket;
use Time::HiRes qw( gettimeofday );
use Time::Local;

my ( $rb, $sb, $vn, $client, $sec, $msec, $proto, $paddr );
my ( $NTP_LI, $NTP_LEAP, $MODE, $FLAG, $STR, $POLL, $PREC );
my ( $USO_LEAP, $USO_OFFSET );

$NTP_LI = timegm( 0, 0, 0, 31, 12-1, 16 ); # 2016/12/31 00:00:00 UTC
$NTP_LEAP = timegm( 0, 0, 0, 1, 1-1, 17 ); # 2017/01/01 00:00:00 UTC

$USO_LEAP = timegm( 0, 0, 10, 27, 12-1, 16 ); # 現在時刻より20分くらい前に設定するとよいです
$USO_OFFSET = $NTP_LEAP - $USO_LEAP;

$MODE = 4; # mode = 4 (server)
$STR = 1; # stratum 1
$POLL = 6; # poll interval = 2^6 sec
$PREC = -16; # precision = 2^-16 sec

$proto = getprotobyname('udp');
socket(NTP, PF_INET, SOCK_DGRAM, $proto) or die "socket: $!";
$paddr = sockaddr_in( 123, INADDR_ANY );
bind(NTP, $paddr) or die "bind: $!";

$sb = "\0" x 48;

while ("You hate leapseconds") {
  ($client = recv(NTP, $rb, 256, 0)) or next;
  ( length($rb) >= 48 ) or next;
  ($sec, $msec) = gettimeofday;
  $sec += $USO_OFFSET;
  $FLAG = $MODE | ( unpack("C",substr($rb,0,1)) & 0x38 ); # version
  if(($sec >= $NTP_LI) && ($sec <= $NTP_LEAP)) { $FLAG |= 0x40; }
  if(($sec > $NTP_LEAP)) { $sec -= 1; } # offset
  substr($sb, 0, 4) = pack("CCCc", $FLAG, $STR, $POLL, $PREC);
  substr($sb, 4, 4) = pack("N", 0); # delay
  substr($sb, 8, 4) = pack("N", 0); # dispersion
  substr($sb,12, 4) = "LOCL"; # Ref ID
  substr($sb,16, 4) = pack("N", $sec + 0x83AA7E80);
  substr($sb,20, 4) = pack("N", 0 );
  substr($sb,24, 8) = substr($rb,40, 8);
  substr($sb,32, 4) = pack("N", $sec + 0x83AA7E80);
  substr($sb,36, 4) = pack("N", ($msec/500000) * 0x80000000 );
  ($sec, $msec) = gettimeofday;
  $sec += $USO_OFFSET;
  if(($sec > $NTP_LEAP)) { $sec -= 1; }
  substr($sb,40, 4) = pack("N", $sec + 0x83AA7E80);
  substr($sb,44, 4) = pack("N", ($msec/500000) * 0x80000000 );

  send(NTP, $sb, 0, $client);
}

ハイライトした15行目の”$USO_LEAP = timegm( 0, 0, 10, 27, 12-1, 16 );”ですが、実験を行う実時間に合わせて書き換えてください。
現在時刻が2016/12/27 09:00 (UTC)だったとして、2016/12/27 10:00 (UTC)にうるう秒を発生させたい場合はこの例のような設定になります。
5分後にうるう秒が発生するようにして実験したところ、うまくいかなかったので余裕を見て20分くらい後に発生するようにすると良いです。

実験用サーバ

うるう秒による影響を確認したいアプリケーションを動作させておきます。
ここでは、単純にタイムスタンプを出力し続けるアプリケーションを作成しました。

#!/usr/bin/ruby
require 'time'
STDOUT.sync = true

loop do
  sleep 0.1
  puts Time.now.iso8601(3)
end

実験

SNTPサーバを起動します。
SNTPサーバを起動するためにはntpdを止める必要があるので、ntpdは事前に止めます。

[ec2-user@ip-10-0-0-10 ~]$ sudo service ntpd stop
Shutting down ntpd:                                        [  OK  ]
[ec2-user@ip-10-0-0-10 ~]$ sudo ./sntp.pl

もう一方のサーバでNTPサーバの参照先を書き換えます。

# server 0.amazon.pool.ntp.org iburst
# server 1.amazon.pool.ntp.org iburst
# server 2.amazon.pool.ntp.org iburst
# server 3.amazon.pool.ntp.org iburst
restrict 10.0.0.10
server 10.0.0.10 iburst

serverの項目でAWSのNTPサーバが指定されているのでそれを全てコメントアウトして、下の二行を書き足します。IPアドレスはSNTPサーバのものを指定してください。

[ec2-user@ip-10-0-0-11 ~]$ sudo service ntpd stop && sudo ntpdate 10.0.0.10 && sudo service ntpd start
Shutting down ntpd: [ OK ]
31 Dec 23:37:13 ntpdate[4171]: step time server 10.0.0.10 offset -7798.967246 sec
Starting ntpd: [ OK ]
[ec2-user@ip-10-0-0-11 ~]$ date
Sat Dec 31 23:37:20 UTC 2016

 

時刻がうるう秒が発生する約20分前になったのがわかります。一足早く年越し気分が味わえますね。

時刻同期の確認をするコマンドを打ちます。

[ec2-user@ip-10-0-0-11 ~]$ ntpq -c rv
associd=0 status=4614 leap_add_sec, sync_ntp, 1 event, freq_mode,
version="ntpd 4.2.6p5@1.2349-o Thu Jul 28 22:19:51 UTC 2016 (1)",
processor="x86_64", system="Linux/4.4.35-33.55.amzn1.x86_64", leap=01,
stratum=2, precision=-23, rootdelay=0.573, rootdisp=12.258,
refid=10.0.0.10, reftime=dc12c319.609db8db  Sat, Dec 31 2016 23:51:53.377,
clock=dc12c334.0a8c4c50  Sat, Dec 31 2016 23:52:20.041, peer=52002, tc=6,
mintc=3, offset=-0.081, frequency=0.000, sys_jitter=0.000,
clk_jitter=3.664, clk_wander=0.000


[ec2-user@ip-10-0-0-11 ~]$ ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ip-10-0-0-10.ap .LOCL.           1 u   19   64   17    0.573  -10.445   8.992

 

一つ目のコマンドでleap=01となっていればうるう秒が発生するというフラグを受信できていることになります。
この状態でアプリケーションを起動して、挙動の確認をおこないます。

[ec2-user@ip-10-0-0-11 ~]$ ruby ./time.rb | tee time.log
~省略~
2016-12-31T23:59:58.756+00:00
2016-12-31T23:59:58.857+00:00
2016-12-31T23:59:58.957+00:00
2016-12-31T23:59:59.057+00:00
2016-12-31T23:59:59.158+00:00
2016-12-31T23:59:59.258+00:00
2016-12-31T23:59:59.358+00:00
2016-12-31T23:59:59.459+00:00
2016-12-31T23:59:59.559+00:00
2016-12-31T23:59:59.660+00:00
2016-12-31T23:59:59.760+00:00
2016-12-31T23:59:59.860+00:00
2016-12-31T23:59:59.961+00:00
2016-12-31T23:59:59.067+00:00
2016-12-31T23:59:59.167+00:00
2016-12-31T23:59:59.267+00:00
2016-12-31T23:59:59.368+00:00
2016-12-31T23:59:59.468+00:00
2016-12-31T23:59:59.569+00:00
2016-12-31T23:59:59.669+00:00
2016-12-31T23:59:59.769+00:00
2016-12-31T23:59:59.870+00:00
2016-12-31T23:59:59.970+00:00
2017-01-01T00:00:00.071+00:00
2017-01-01T00:00:00.171+00:00
2017-01-01T00:00:00.271+00:00
2017-01-01T00:00:00.372+00:00

 

1回目の59分59秒が訪れたあとに、もう一度59分59秒が記録されています。
ちなみに、うるう秒によって1秒挿入された場合は/var/log/messagesにログが出ます。

[ec2-user@ip-10-0-0-11 ~]$ sudo cat /var/log/messages | grep -e ntpd -e kernel | tail
Dec 31 23:37:00 ip-10-0-0-11 ntpd[3863]: ntpd 4.2.6p5@1.2349-o Thu Jul 28 22:19:51 UTC 2016 (1)
Dec 31 23:37:00 ip-10-0-0-11 ntpd[3864]: proto: precision = 0.101 usec
Dec 31 23:37:00 ip-10-0-0-11 ntpd[3864]: 0.0.0.0 c01d 0d kern kernel time sync enabled
Dec 31 23:37:00 ip-10-0-0-11 ntpd[3864]: Listen and drop on 0 v4wildcard 0.0.0.0 UDP 123
Dec 31 23:37:00 ip-10-0-0-11 ntpd[3864]: Listen normally on 1 lo 127.0.0.1 UDP 123
Dec 31 23:37:00 ip-10-0-0-11 ntpd[3864]: Listen normally on 2 eth0 10.0.0.11 UDP 123
Dec 31 23:37:00 ip-10-0-0-11 ntpd[3864]: Listening on routing socket on fd #19 for interface updates
Dec 31 23:59:59 ip-10-0-0-11 kernel: [ 4417.088504] Clock: inserting leap second 23:59:60 UTC
Jan  1 00:02:48 ip-10-0-0-11 ntpd[3864]: kernel reports leap second has occurred

 

時間遡行とかタイムリープと聞くとかっこよさそうですが、どう考えてもやっかいですね。
この状況でアプリケーションが正常に動作して特に問題が起きなさそうであれば何も対策する必要はありません。
アプリケーション内にタイムスタンプの前後関係を利用している処理があると意図しない動作が起きる可能性があるので、許容できるものなのかをきちんと検討した方がよさそうです。

対策

もし困る事がある場合はNTPサーバの参照先をtime.google.comに向けるとよさそうです。
今年からGoogleが誰でも使えるNTPサーバを公開しています。https://developers.google.com/time/
このNTPサーバはうるう秒を発生させずに、徐々に時間をずらして差を埋める実装がされており、利用者はうるう秒の事を気にしなくてよいようになっています。

外部のNTPサーバが参照できない場合は、ntpdの設定(/etc/sysconfig/ntpd)のOPTIONSに”-x”というオプションを足すことで、うるう秒が追加されずに、徐々に時刻を修正するSLEWモードで動作してくれるので、時間遡行が発生しません。

[ec2-user@ip-10-0-0-11 ~]$ cat /etc/sysconfig/ntpd
# Command line options for ntpd
OPTIONS="-g -x"

SLEWモードで動作させた場合は/var/log/messageに

Jan  1 00:00:00 ip-10-0-10-11 ntpd[4188]: Ignoring leap second

といううるう秒を無視するよ、というログがUTCで年をまたぐ時に出力されます。

これでうるう秒に関しては気にせず正月が過ごせますね。
それではよい年越しを!

]]>