awsサービス cloudformationからlambdaをキックさせる

cloudformationでインスタンスなどが立ち上げ終わった後に、マネジメントコンソールで管理しているlambdaを叩きたいなと思って実行したものです。

カスタムリソース

カスタムリソースというのが用意されています。これを使います。

こいつは何か?

AWSのCloudFormationのリソースタイプとして使用できないリソースを含める必要があるときに、それらのリソースは、カスタムリソースを使用して含めることができるらしい。つまりこの方法によりすべての関連リソースを1つのスタックで管理できるという優れものです。
今回だとて使用できないリソースとしてlambdaが当たりますがSQSとかもそうらしいです。以下のような感じで記述できます。Test1、Test2のように任意の文字列も渡せます。

"CustomResource" : {
  "Type" : "AWS::CloudFormation::CustomResource",
    "Properties" : {
        "ServiceToken": "指定のARN",
        "Test1": {"Ref": "InstanceName"},
        "Test2": {"Ref": "TargetGroupName"}
    }
}

使い方

lambdaをcloudformatinで使うにはあるものを呼ばないといけないらしい。それがcfn-responseモジュールと呼ばれるものだ。そしてこれを使うときの注意書きとして以下が記述してあります。

cfn-response モジュールは、ZipFile プロパティを使用してソースコードを作成した場合にのみ使用できます。S3 バケットに保存されたソースコードには使用できません。S3 バケットのコードでは、独自の関数を作成してレスポンスを送信する必要があります。

どういうことかというとcloudformationでlambdaを使うときは以下のようにコードを直書きしないと使えませんよということ。

"ZipFile": { "Fn::Join": ["", [
  "var response = require('cfn-response');",
  "exports.handler = function(event, context) {",
  "  var input = parseInt(event.ResourceProperties.Input);",
  "  var responseData = {Value: input * 5};",
  "  response.send(event, context, response.SUCCESS, responseData);",
  "};"

あれ??マネジメントコンソールですでに記述したやつを使いたかったのに・・・・
github調べてみたら出てきた

https://github.com/LukeMizuhashi/cfn-response/blob/c5bb51ada6110f4e84d7a8bad7799fd90e0b440d/index.js#L11

解決方法

実際に書いた。githubのほぼコピペなので迷うことありません。

cloudformation側

"CustomResource" : {
  "Type" : "AWS::CloudFormation::CustomResource",
    "Properties" : {
        "ServiceToken": "lambdaのARN",
        "Test1": {"Ref": "InstanceName"},
        "Test2": {"Ref": "TargetGroupName"}
    }
}

そうすると”lambdaのARN”で指定したlambdaを叩きに行く。そしてlambda側で以下を入れておく。

lambda側

var SUCCESS = "SUCCESS";
var FAILED = "FAILED";

var cfnResponse = function(event, context, responseStatus, responseData, physicalResourceId) {

    var responseBody = JSON.stringify({
        Status: responseStatus,
        Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
        PhysicalResourceId: physicalResourceId || context.logStreamName,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        Data: responseData
    });

    console.log("Response body:n", responseBody);

    var https = require("https");
    var url = require("url");

    var parsedUrl = url.parse(event.ResponseURL);
    var options = {
        hostname: parsedUrl.hostname,
        port: 443,
        path: parsedUrl.path,
        method: "PUT",
        headers: {
            "content-type": "",
            "content-length": responseBody.length
        }
    };

    var request = https.request(options, function(response) {
        console.log("Status code: " + response.statusCode);
        console.log("Status message: " + response.statusMessage);
        context.done();
    });

    request.on("error", function(error) {
        console.log("send(..) failed executing https.request(..): " + error);
        context.done();
    });

    request.write(responseBody);
    request.end();
}

exports.handler = (event, context, callback) => {
    // TODO implement
    if(event['RequestType'] == 'Delete'){
        cfnResponse(event, context, SUCCESS, {});
    }
    console.log(event);
    cfnResponse(event, context, SUCCESS, {});
};

これをlambda側に書いていないとインプログレスのまま一時間くらい止まってしまい、立ち上げ直さないといけない感じになる。

結果

cloudformationで環境を作った後に、lambdaを使うことに成功した。
その時にカスタマーリソールなるものを用いた、ちゃんとS3のcloudformationのタスクのレスポンスとして結果を返さないといけないので注意しましょ!!!

続きを読む

aws周りのメモ2

postgresqlを使う

RDSへpostgresqlをいれて立ち上げ

認証と接続

import-key-pair — AWS CLI 1.11.87 Command Reference
http://docs.aws.amazon.com/cli/latest/reference/ec2/import-key-pair.html

cd $HOGE
openssl genrsa -out my-key.pem 2048
openssl rsa -in my-key.pem -pubout > my-key.pub
# IAMのコンパネで*.pubを入力
# 多分、権限があれば以下でもいける
# aws iam upload-ssh-public-key

【AWS 再入門】EC2 + RDS によるミニマム構成なサーバー環境を構築してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-minimum-vpc-server-environment/

便利

無料枠

無料のクラウドサービス | AWS 無料利用枠
https://aws.amazon.com/jp/free/

AMI

AWS Marketplace: Search Results
https://aws.amazon.com/marketplace/search/results?x=14&y=18&searchTerms=&page=1&ref_=nav_search_box

CFテンプレート

サンプルコード & テンプレート – AWS CloudFormation | AWS
https://aws.amazon.com/jp/cloudformation/aws-cloudformation-templates/

ec2 ami tool & ec2 api tool

Mac で Amazon EC2 API Toolsを設定する – サーバーワークスエンジニアブログ
http://blog.serverworks.co.jp/tech/2013/01/31/mac-amazon-ec2-api-tools-setup/

ec2 api toolは若干心配。

VPCを使う

接続の際に、sshを経由したい。sslでもいいけどなんかsshがいいなと。
パスワードよりkeyのほうがセキュアだからかな。

0から始めるAWS入門①:VPC編 – Qiita
http://qiita.com/hiroshik1985/items/9de2dd02c9c2f6911f3b

導入

Amazon VPC とは? – Amazon Virtual Private Cloud
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Introduction.html

公式のいろいろ

料金 – Amazon VPC | AWS
https://aws.amazon.com/jp/vpc/pricing/

基本は無料だけどNATとVPNは別課金。

【AWS 再入門】VPC 環境に踏み台サーバーを構築して SSH 接続してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-bastion-host-vpc/#i-3

ec2(Bastion)を配置する必要がありそう。

【AWS 再入門】EC2 + RDS によるミニマム構成なサーバー環境を構築してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-minimum-vpc-server-environment/

VPC に推奨されるネットワーク ACL ルール – Amazon Virtual Private Cloud
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Appendix_NACLs.html

vpcでのネットワークのポリシーの例

Default VPC

AWSのDefault VPCを削除して困った話 – MikeTOKYO Developers
http://blog.miketokyo.com/post/49939300091/aws-default-vpc

デフォルトvpcは削除したらダメか。使い分けがわからん。

Amazon EC2 と Amazon Virtual Private Cloud – Amazon Elastic Compute Cloud
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-vpc.html

基本の機能はデフォルトとそうじゃないvpcは同じだけど、
デフォルトvpcがないとちゃんと機能しない。
デフォルトの属性によって、指定がないとipを紐付けたりする。

VPCネットワーク設計

これだけ押さえておけば大丈夫!Webサービス向けVPCネットワークの設計指針 | eureka tech blog
https://developers.eure.jp/tech/vpc_networking/

ネットワークは一度稼働させると移行が大変なので、初期設計が非常に重要になります。

わかりやすい。図が特に。

  • Bastion
  • NAT
  • Security Group

ENI

インフラエンジニアに贈るAmazon VPC入門 | シリーズ | Developers.IO
http://dev.classmethod.jp/series/vpcfor-infra-engineer/

サブネットで指定したIPアドレスのうち、先頭4つと末尾の1つはVPCで予約されるため使用できません。

VPCでは常にDHCP有効とするのがポイントです。

また、DHCPサービスで伝えられる情報(DHCPオプション)は、変更することもできます。

仮想マシンにひもづくENIにより、DHCPサーバーから毎回同じMACアドレス、IPアドレスが付与されます。これは、仮想マシンの状態に依存しないため、仮想マシンを再起動しようと、一旦シャットダウンしてしばらくしてから起動した場合でも必ず同じアドレスが付与されます。

ENI(Elastic Network Interface)か。。なるほど。でも、使うことはなさそうだな。

NAT

IPマスカレードが使えないVPC
NATは、Static(静的・サーバー用途)とElastic(仮想・クライアント用途)がある。
個人的には、このNATインスタンスの実装は、あまり好きではありません。動きがややこしいですし、ユーザーが自分でNATインスタンスの管理をしなければならないのも煩雑な印象を受けます。VPCのネットワークサービスの一つとして提供される機能であれば、ユーザーからはなるべく抽象化され仮想マシンとして意識されないようにするべきと考えます。
ただ、ユーザーから仮想マシンとして見える分、機能・実装が具体的に把握できる点やカスタマイズ性が高い点は良いとも思っています。

NAT インスタンスと NAT ゲートウェイの比較 – Amazon Virtual Private Cloud
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-nat-comparison.html

なるほど。。

Bastion

AWSで最低限セキュアな構成を組む – Qiita
http://qiita.com/ausuited/items/09b626fa5264f0c650fd

パブリックSubnetにEC2インスタンス(踏み台サーバーとして)
NATインスタンスを作成した要領で、パブリックSubnetにEC2インスタンスを作成する。Security groupは新規に作成してSSHをAnywhereに。Key pairは厳重に管理。尚、踏み台サーバーは、使用する時以外はStoppedにしておく事で、さらにセキュアな状態とする。このデザインパターンをOn Demand Bastionパターンと呼ぶらしい。

詳しい。「On Demand Bastionパターン」か。なるほど。

vpcへの踏み台サーバー
ポートフォワーディング、トンネルなどと同じ意味。

Network ACL

インスタンス単位じゃなくサブネット単位でより制限してセキュアにしたい場合に使うのかな。

安全なVPC設計 — Commerce Hack
http://tech.degica.com/ja/2016/01/07/designing-vpc-and-subnets/


結局どうするのか、、ひとまずNATはつかわずに、Bistionをつくってみる感じかな。

アベイラビリティーゾーン

リージョンごとでの、障害などで全部やられないように物理的にセグメントされた範囲の単位かな。
RDSではセグメントグループに2つ以上のゾーンを含める。でも、一つしか使わなくていい。ということか。s

RDSのVPC間の移動

サブネットグループの関連付けを変えればいいらしい。間違って設定したので移動した。

【小ネタ】知っていましたか?RDSを別のVPCに移動できることを | Developers.IO
http://dev.classmethod.jp/cloud/aws/rds_can_move_to_another_vpc/

Bastion作成作業をしてみる

主に下記を参考。

【AWS 再入門】EC2 + RDS によるミニマム構成なサーバー環境を構築してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-minimum-vpc-server-environment/

  • サブネットってなんだっけとか復習。
  • ストレージはどうするのか。
    • とりあえずssdにしたけどマグネティックでよかったかなあ。

      • ssd:$0.12 : 1 か月にプロビジョニングされたストレージ 1 GB あたり
      • マグネティック: 0.05 USD/GB-月
  • public IPは設定必要だよね
  • market placeからamiを取得した方がいいの?
    • とりあえず公式のウィザードを使ったけど。
  • 認証にIAMが追加されていたので使ってみた
    • これとは別にキーペアは必要ってことかな。
  • CFnテンプレート(CloudFormationテンプレート)というのがあるらしい。。
    • これでつくりなおそうかな。。
  • サブネットとかいろいろネットワーク系の設定
    • なんだかんだいっていろいろあった
  • セキュリティグループ
    • エイリアスみたいなセキュリティグループにできたらいいのに。タグや名前で明示化かな。
    • bastionは22をあけて、rdsは5432をbastionからのみあける
  • ログイン
  • DNS
    • あれ、パブリックDNSがうまく割り振ってないな。。
      AWSでPublic DNS(パブリックDNS)が割り当てられない時の解決法 – Qiita
      http://qiita.com/sunadoridotnet/items/4ea689ce9f206e78a523
    • RDSのDNS
      • nslookupしたら内部ipがかえってくるのね。接続できないけどなんか気持ち悪いな。これかな。。
        外部からdnsを引けることを気にしている人は見かけなくて便利だからって話なのかね。
        【AWS】VPC内でPrivate DNSによる名前解決 – Qiita
        http://qiita.com/y_takeshita/items/2eb5e6abb5eb5516d1de

やってるうちはいいけど、しばらくやらないと設定の方法とか忘れそう。。こういうのは学習コストだけじゃないな。

PlantUMLで図にしておく

Kobito.hQIwJs.png

VPC内のRDSへLambdaから接続。。

しまった!アンチパターンだそうだ。。

Lambda+RDSはアンチパターン – Qiita
http://qiita.com/teradonburi/items/86400ea82a65699672ad

Lambda + RDS benchmark – Qiita
http://qiita.com/taruhachi/items/3f95ae3e84f56edb3787

新し目の記事でIAM認証でクリアできそうな。。

【全世界待望】Public AccessのRDSへIAM認証(+ SSL)で安全にLambda Pythonから接続する – サーバーワークスエンジニアブログ
https://blog.serverworks.co.jp/tech/2017/04/27/rds-iam-auth-lambda-python/


セキュアに接続するのと速度のトレードオフになっていたのが
IAM認証のおかげで両方可能になったということっぽい。
でも、ネットのスループット、コネクション数(料金・負荷)、など、、ほかにも気にすることが出て来そうで若干不安。
非同期でよければキューイングして一回投げっぱなしすればどうだろう。
もしくは、似てるけど、Lambdaから一回値を返してもらってからRDSへ投げ直す。
これでいっかなあ。。Lambdaの意味がなくなる?うーん。

今後

  • 疑問としてrdsなど内部向けのdnsを外から見れなくできないものか。
  • というか、rdsのエンドポイントって再起動したら変わったりしないかね。ipは固定されるのか。
    • たぶん、サブネット内でdhcpになるのでipは変動するけどエンドポイントは固定。。じゃないかしら。

posgresqlをつかうための情報

Amazon RDS 上の PostgreSQL – Amazon Relational Database Service
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.SSL

続きを読む

Amazon ECSを用いたDocker本番運用の実現

はじめに

現在お手伝いしているアカウンティング・サース・ジャパンにて、ECSを使ったDockerの本番運用を始めたので、その一連の流れについてまとめました。

税理士向け会計システムを扱うアカウンティング・サース・ジャパンでは最近Scalaでの新規プロジェクトが立ち上がってきており、既存のプロジェクトはJavaであったり、Erlangであったりと様々な言語が用いられていますが、インフラ人員が少ないということもあり、なるべくシンプルなインフラ構成を実現する必要がありました。

そういった中、各アプリケーションをDocker化することでインフラとしては共通基盤としてのDockerクラスタのみの管理になり、運用コストが下がるのではないかという仮説からDocker化を進めることになりました。クラスタを実現するに辺りKubenatesなどの選択肢もありましたが、今回はECSを選択し、下記のようにAWSのマネージドサービスを最大限に活用しています。

  • オーケストレーションツール: Amazon EC2 Container Service (ECS)
  • サービスディスカバリ: Application Load Balancer (ALB)
  • Dockerレジストリ: Amazon ECR
  • ログ、メトリクス収集: CloudWatch, CloudWatch Logs
  • 監視: CloudWatch Alarms
  • Infrastructure as Code: CloudFormation
  • CIツール: Jenkins

各技術の選定理由

今回Docker化を行うに辺り、下記を優先的に技術選定を行いました。

  • 運用が楽であること
  • 構成がシンプルで、技術の学習コストが低いこと

まずは、オーケストレーションツールの選定です。候補に上がったのは、Docker Swarm、Kubernetes、ECSです。

DockerのSwarm modeは本番での運用例が技術選定時点であまり見当たらなかったので候補から落としました。次にKubernetesとECSですが、海外の事例などではどちらも多く使われているようです。

今回は多機能さよりも運用に手間がかからない方が良いと考え、マネージドサービスであるECSが第一候補にあがりました。ここは詳細に調査したというよりも、ある種勢いで決めています。その上でやりたいことが実現できるかどうか一つ一つ技術検証を行った上で導入判断を行いました。

同じようにマネージドサービスを優先的に使ったほうが良いという考えで、ログなどでもCloudWatchを使っています。

AWSインフラをコードで記述するものとしてはTerraformが良く取り上げられている気がしますが、個人的にはいくつかの理由でCloudFormationを推しているのでこちらを使っています。

CIツールですが、社内の標準であるJenkinsをそのまま使うことにしました。

全体構成

下記のような構成になっています。

スクリーンショット 2017-05-21 12.46.39.png

ざっくりと説明すると、developmentブランチにプッシュするとGithub HookでJenkinsがDockerイメージをビルドして、ECRにPushします。ユーザはJenkinsでDeployジョブを実行(あるいはBuildの後続ジョブとして自動実行)し、CloudFormationにyamlファイルを適用することでTask, Service, ALB, Route53設定, CloudWatch設定を一通り実行します。またECSのClusterはあらかじめCloudFormationテンプレートを作成して作っておきます。

Task/Serviceの更新についてはCloudFormationを経由しない方がシンプルかとは思いまいしたが、Service毎に管理するRoute53やCloudWatchと合わせて一つのテンプレートにしてしまうのが良いと判断しました。

ここまでやるなら専用のデプロイ管理ツールを作った方がとも思ったのですが、業務委託という立場で自分しかメンテができないものを残すものは躊躇されたため、あくまでAWSとJenkinsの標準的な機能を組み合わせて実現しています。

CloudFormationテンプレートの解説

上記の流れが全てなので理解は難しくないと思いますが、一連の処理で重要なポイントとなるのはCloudFormationテンプレートなのでこれについてだけ触れておきます。長いテンプレートなのでざっくりとだけ雰囲気を掴んでもらえればと思います。

ECSクラスタのテンプレート

cluster作成用のCloudFormationテンプレートは下記のようになっています。

gist:cluster.yaml

一見複雑に見えますが、Amazon EC2 Container Service テンプレートスニペットを参考に作ると簡単に作成できると思います。

(あまりそのまま書くと会社に怒られそうなため)省略していますが、実際にはここにECSクラスタの監視を行うCloudWatch Alarmなどを設定することで、監視設定までこのテンプレートだけで完了します。

ECSクラスタはインフラチーム側であらかじめ用意しておき、リソースが足りなくなったときなどには適宜インスタンス数を変更したりクラスタ自体を別途作ったりしていきます。オートスケーリングを導入すればそれすら必要なくなります(今回はDocker運用が初めてだったので知見がたまるまで手動での対応にしています)。

インフラ側としての責務はここまでで、下記のテンプレートで定義される個別のサービスについてはアプリ開発者側の責務として明確に責任境界を分けました。(もちろん実際にはサポートはかなりの部分でしています。)

これにより全員が今までよりインフラに近い領域まで意識するように個人の意識が変わっていくことを期待しています。

個別サービス用テンプレート

開発環境、ステージング環境、プロダクション環境などそれぞれで同一のテンプレートを使うようにし、パラメータを使用します。そのパラメータをJenkinsのジョブ内で注入することで実現します。VPCなどの環境で決まる値はJenkinsジョブで実行するスクリプト内で定義し、アプリケーションごとの値は environment.yaml というファイルを用意してスクリプトから読み込みます。

environment.yamlは例えば下記のようになっています。アプリケーション開発者は、特殊なことをしない限りは service.yaml をインフラチームが用意したservice.yamlをコピーして、environment.yamlだけ編集すれば良い形になっています。DSLですら無いのでアプリ側のメンバーも心理的な抵抗が少ないようで良かったです。

environment.yaml
images:
- xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hoge-image
parameters:
  default:
    TaskMemory: 512
    TaskMaxMemory: 990
    ImageRepositoryUrl: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hoge-image
    ServiceDesiredCount: 1
  dev:
    ClusterName: dev-default
    JavaOpts: "-Xmx256MB"
  stg:
    ClusterName: stg-default
    JavaOpts: "-Xmx256MB"
  prod:
    ClusterName: default
    JavaOpts: "-Xmx1500MB -Xms1500MB"
    TaskMemory: 1990
    TaskMaxMemory: 1990
    ServiceDesiredCount: 2

そして service.yaml は下記のようなファイルです。

gist:service.yaml

これもAmazon EC2 Container Service テンプレートスニペットから作ればすぐにできるのではないかと思います。(もちろん全てのパラメータは一つ一つ値を検討します。)

こちらもCloudWatch周りや重要でないところは削除しています。色々と手で削ってるのでコピペだと動かない可能性大ですが雰囲気だけ掴んで貰えればと思います。

このファイルは全アプリケーションで同一ファイルを使うのではなく、アプリケーションごとにコピー/編集して利用します。全体の変更を行うときには全プロジェクトのファイルを更新しなければいけませんが、共通基盤がアプリケーション側を制約しないように、プロジェクト毎のyamlファイル管理としています。ファイルの配置場所は各Gitリポジトリに配置するのが理想ですが、現状ではDocker運用になれてくるまで全てのyamlファイルを管理するリポジトリを作成してインフラチーム側が主に編集する形を取っています。

デプロイ

あとは、このservice.yamlとenvironment.yamlを組み合わせてデプロイするRubyスクリプトでもJenkinsのPipelineのコードでも適当に書いてJenkinsのJobを登録すれば完了です。(environment.yamlファイルを読み込んで aws cloudformation create-stack でservice.yamlと共にパラメータとして渡すだけなので簡単です!)

新規アプリ開発時も社内標準のservice.yamlとenvironment.yamlをファイルを持ってきて、environment.yamlを修正した上で、Jenkinsにジョブを登録すればすぐにDockerクラスタへのデプロイ準備が整います。しかも、上記のテンプレート例では割愛していますが、テンプレートには監視項目/通知設定まで書かれているので、インフラ側で設定を行う必要もなく監視が開始されます。CloudFormation最高ですね。

おわりに

実際の運用ではミッションクリティカルなアプリケーションならではの品質管理のために、JenkinsのPipeline機能を利用して開発→検証→リリースまでのデプロイメントパイプラインを実現しています。

アプリケーションのSECRETなどコミットしない情報をどう管理するかも検討する必要がありますが、これは管理の仕方はチームによって異なると思ったため割愛しています。

また、ログ解析としてはS3に出されたALBのログをRedash+Amazon Athenaでエラー率やアクセス数を分析できるようにし、CPU使用率やメモリ使用率などのパフォーマンス状況をCloudWatchの内容をGrafanaで可視化しています。これによりログ収集の基盤などを作らずに必要な可視化を実現することができました。ベンチャーでは分析基盤の運用も大きなコストになってしまうため、こういった工夫も必要です。(もちろん重要なKPIについては別途分析する仕組みが整っています。)

今回の構成が最高とは思いませんが、ある程度満足行くところまではできたかなと思います。もっとよくできるよ!とか一緒にやりたいな!とかもっと詳細聞きたいな!いう方はぜひ @miyasakura_ までご一報ください。

続きを読む

[AWS] 積年の夢の終焉…?:リージョン間VPN接続 (powered by VyOS 1.1.7)

プロローグ

[AWS] 積年の夢の実現:リージョン間VPN接続 (powered by SoftEther)
[AWS] 積年の夢の続き:リージョン間VPN接続 (powered by Windows Server 2012 R2)
と歩を進めてきた、三部作(勝手に後付け♪)のファイナルw VyOS編。

  • VyOSがSoftEther/Windowsより優れているのは、VPN Connection接続(下記【a】)もPeer-to-Peer接続(下記【b】)もMobileアプリからのL2TP/IPSec接続(下記【c】)も可能なこと(と思っている)。
    ⇒SoftEtherは【a】不可、Windowsはそりゃ頑張ればナンでもできるでしょうが。。
    OVERVIEW_20170516.jpg

  • 。。。と思っていたところ、VPN ConnectionでVyOS(Vyatta)用のconfigをDLできなくなった???一昔前はできたはず…(・・;)
    ⇒なんと、RegionによってVPNCがサポートしているルータが異なることを発見!!(VyOS(Vyatta)は、N.Virginiaにはあるが、N.Californiaにはない、といった具合)

  • 半面、VyOSのDisadvantageは、学習コストが(少なくともCCNAしか持っていないヲレには)高い、という点か。
    ※SoftEtherもWindowsも、自動化とか欲張らなければ、GUIでも設定可能

    • といいつつ、VyOSもLinuxベース(vbash?)なので、そこまではぢめまして感はなく。
    • 「configure~commit/save」は、Cisco IOSの「configure terminal」と似ていると感じたよ。
    • その後、VyOSも、接続するまでなら、そんなに敷居が高くない(低くはない)ことを識る(いわゆる「知らないから怖い」&「食わず嫌い」)

⇒いや、やはりVyOSの敷居は高かった。。。CentOS等と似て非なり。Cisco IOSと非なりて似る。

構成オプション、どん!

VyOSは、様々なインストール方法・様々なVPN接続方法がある(♬そしてワタシはツブされる…(@_@))

  • VyOSインストール方法
     【1】 AWSのAMIを利用してEC2インスタンスとして作成
     【2】 オンプレミスにVirtualBox上に仮想マシンとして作成
     【3】 VirtualBox上のDockerホストにてDockerコンテナとして作成【Dockerでルータをコンテナ化してみた】
     【4】 あらゆるDockerホストにてDockerコンテナとして動作
        ⇒ そしてマルチクラウドへ。。。(【VyOSを使ってSoftLayerとAWSをIPSecVPN接続】

  • VPN接続方法
     【a】 AWSのCustomer Gateway(CGW)/VPC Connection(VPNC)/Virtual Private Gateway(VGW)を利用 [//]
     【b】 VyOS同士の直接接続(Site-to-Site接続)[]
     【c】 Windows10やAndroidから接続(Point-to-Site接続) [/]

【1】AMIを利用してEC2インスタンスとして作成

  • VyOS AMIのビルトインユーザは、「ec2-user」でなく「vyos」
  • rootユーザにパスワードを設定。。。passwdコマンドではできない。。。!?【保留中】
  • ログインユーザ作成【保留中】
$ configure
# set system login user 《管理者ユーザ》 authentication plaintext-password 《管理者ユーザのパスワード》
# commit
# save
# exit
  • 「vyos」の公開鍵を、《管理者ユーザ》にコピー【保留中】
$ sudo cp /home/vyos/.ssh/authorized_keys /home/《管理者ユーザ名》/.ssh/
  • ビルトインユーザ「vyos」削除 ※「vyos」以外のユーザでログインし直した上で
    【保留中】VyOSサーバを再起動したら、作成した管理者ユーザでSSHログインできなくなった (・・;)
$ configure
# delete system login user vyos
# commit
# save
# exit
  • 2枚目のENI(Private側)にプライベートIPアドレスをアサイン

※EC2を作成するCloudFormationにおいて、Public側ENIをIndex0、Private側ENIをIndex1と指定済み
OR
※ENI 1枚挿しのEC2インスタンスを起動した後で、2枚目ENIを手動でAttach済み

$ configure
# set interfaces ethernet eth1 address '10.100.12.100/24'
# commit
# save
# exit
$ sudo ifconfig
《eth1にプライベートIPアドレス「10.100.12.100」が割り当たっていることを確認》 

※ifconfigやroute等のNW系コマンドはrootでのみ実行可能

【1】を使ってAWS上で【a】でツナぐずら

(韓国(KR)のVyOSサーバと、USのVGWをVPN Connectionで接続)

  • 【US】VyOSサーバ持つEIPを使って、CSGを作成

    • BGPのAS番号を「65000」と指定
  • 【US】VPCとVPNCを作成

    • VPCのRouteTableにおいて「Propagated=yes」
      ⇒KRへのルーティング情報が、VGW経由で、US側のRouteTableに動的に追加されるようになる!
  • 【US】VPNCから「VyOS用config」をDL・・・少なくとも「N.Virginia」なら可能

  • 【KR】「VyOS用config」の一部を手動で書き換え:

    • local-address

      • VyOSサーバのパブリック側プライベートIPアドレス(10.100.11.100)に書き換え
        NAT-Tを利用するため、EIPではなくてプライベートIPアドレスと理解)
    • BGPのアドバタイズ情報
      • 10.100.11.0/24, 10.100.12.0/24
      • このBGPアドバタイズが中々できずにハマる。。。「10.100.12.0/24」をVyOSが認識していないためと推理(後述)
  • 【KR】「VyOS用config」を投入!!

    • AWSからDLしたスクリプトを一部書き換え後に愚直に実行すると、BGPアドバタイズの行で「Already exists」のエラーが発生★ そりゃそうなので無視~
  • 【KR】BGPアドバタイズ情報の追加

$ configure
# set protocols static route 10.100.12.0/24 next-hop 10.100.12.1
# set protocols bgp 65000 network 10.100.12.0/24
# commit
# save
# exit

【とっても素敵な参考情報】BGPアドバタイズするネットワーク設定の追加

  • 【US】ルーティング情報の確認

    • VGWのTunnel(2本)がUpしていることを確認
    • KR側のVPCサブネットに関するルーティング情報が、BGPによって動的にUS側RouteTableに反映されていることを確認する。
  • 【KR】疎通確認
    ①KR側のVyOSサーバからUS側にPingを送って確認

vyos@VyOS-AMI:~$ ping 172.16.12.200 interface 10.100.11.100
PING 172.16.12.200 (172.16.12.200) from 10.100.11.100 : 56(84) bytes of data.
64 bytes from 172.16.12.200: icmp_req=1 ttl=254 time=196 ms
64 bytes from 172.16.12.200: icmp_req=2 ttl=254 time=196 ms
64 bytes from 172.16.12.200: icmp_req=3 ttl=254 time=196 ms
・・・

VyOS上の送信IF(Public側)を明示的に指定する必要がある模様

②KR側のプライベートEC2からUS側にPingを送って確認

ping 172.16.12.200
  • 【US】疎通確認

    • US側からKR側にPingを送って確認

【閑話休題】BGPアドバタイズでハマった考察

疎通できた後で振り返ってみれば単純なことだが、めっちゃハマったのは、BGPによる動的ルーティング情報交換

  1. VyOS EC2の2枚目のENIの(プライベート)IPアドレスが、いつの間にか外れていた…
    ⇒最初ifconfigで設定していたから、再起動中に消失?VyOS設定「set interfaces ethernet eth1 address~」なら永続的?

  2. VyOSサーバに対して、KR側プライベートサブネットへのStatic Routeが必要だった。
    ⇒これは…自力では思いつかない…
    【再掲】BGPアドバタイズするネットワーク設定の追加

  3. BGPのルーティング情報伝達(コンバージェンス?)に、設定投入~環境反映の間のタイムラグがある?
    ⇒KR側のVyOSへのBGP設定投入後、US側のVGWからRouteTableへの伝達に少し時間がかかることを知らず、設定ミスだと思いこんでいた…

【2】オンプレミスのVirtualBox上に仮想マシンとして作成

VyOSは、一般的にはISOファイルで提供されているのか(AWSならAMIで提供)。
ISOファイルをDLし、VirtualBoxの起動時の「Optical Device」として指定してあげると、VyOSのインストールプロセス開始☆
格闘中…)

【1】と【2】を【b】でツナぐもな

(オンプレミスのVirtualBox仮想マシンと、VyOS-EC2を、VyOS機能で直接通信)

【1】と【3】を【c】でツナぐだなも

(Windows10/Android端末と、VyOS-EC2を、IPSec/L2TPで通信)

エピローグ

AWSリージョン間接続について、SoftEther/Windows/VyOSをひととおりやってみた。
まだまだ試したいこと・課題はあるけど、ひとまずおなかいっぱい。

続きを読む

CloudFormation で Cognito

これまで

Amazon CognitoAWS CloudFormation でのリソース作成と管理に対応しておらず、リソース作成を自動化したい場合は AWS CLIAWS SDK を使った自作スクリプトを使う必要がありました。

しかし、この方法で冪等性を担保するのは難しく、 CloudFormation Custom Resource を作った猛者もいました。

また、 IAM Role の Assume Policy に Identity Pool の ID を含めないといけない点が特に面倒でした。

これから

2017年4月28日、 Cognito の各種リソースが CloudFormation で作成・管理できるようになりました。

これが待ち望んでいたものです。

User Pool 内のユーザーやグループまでリソースとして用意されているのが面白いですね。

IAM Role も同じスタック内で作ってしまえば Assume Policy の中で Identity Pool の ID も参照できるので、手動で ID をコピペする手間が省けて最高です。

テンプレート例

AWSTemplateFormatVersion: "2010-09-09"
Description: "Example template including Cognito Identity Pool and User Pool."
Parameters:
  EmailIdentityArn:
    Type: String
Resources:
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: 
        Fn::Join:
          - ""
          - - Ref: AWS::StackName
            - Users
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: false
      AliasAttributes:
      - email
      - preferred_username
      AutoVerifiedAttributes:
      - email
      EmailConfiguration:
        SourceArn:
          Ref: EmailIdentityArn
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: false
          RequireUppercase: true
      Schema:
      - Name: email
        AttributeDataType: String
        DeveloperOnlyAttribute: false
        Mutable: true
        Required: true
      - Name: preferred_username
        AttributeDataType: String
        DeveloperOnlyAttribute: false
        Mutable: true
        Required: false
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      ClientName: 
        Fn::Join:
          - ""
          - - Ref: AWS::StackName
            - Users-client
      GenerateSecret: false
      RefreshTokenValidity: 7
      UserPoolId:
        Ref: UserPool
  IdentityPool:
    Type: AWS::Cognito::IdentityPool
    Properties:
      AllowUnauthenticatedIdentities: true
      IdentityPoolName: 
        Fn::Join:
          - ""
          - - Ref: AWS::StackName
            - Users
      CognitoIdentityProviders:
      - ClientId:
          Ref: UserPoolClient
        ProviderName:
          Fn::Join:
          - ""
          - - cognito-idp.
            - Ref: "AWS::Region"
            - .amazonaws.com/
            - Ref: UserPool
  UnauthenticatedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: Allow
          Action:
          - mobileanalytics:PutEvents
          - cognito-sync:*
          Resource:
          - "*"
  UnauthenticatedRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: Allow
          Action: "sts:AssumeRoleWithWebIdentity"
          Principal:
            Federated: cognito-identity.amazonaws.com
          Condition:
            StringEquals:
              "cognito-identity.amazonaws.com:aud":
                Ref: IdentityPool
            ForAnyValue:StringLike:
              "cognito-identity.amazonaws.com:amr": unauthenticated
      ManagedPolicyArns:
      - Ref: UnauthenticatedPolicy
  AuthenticatedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: Allow
          Action:
          - mobileanalytics:PutEvents
          - cognito-sync:*
          - cognito-identity:*
          Resource:
          - "*"
  AuthenticatedRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: Allow
          Action: "sts:AssumeRoleWithWebIdentity"
          Principal:
            Federated: cognito-identity.amazonaws.com
          Condition:
            StringEquals:
              "cognito-identity.amazonaws.com:aud":
                Ref: IdentityPool
            ForAnyValue:StringLike:
              "cognito-identity.amazonaws.com:amr": authenticated
      ManagedPolicyArns:
      - Ref: AuthenticatedPolicy
  RoleAttachment:
    Type: AWS::Cognito::IdentityPoolRoleAttachment
    Properties:
      IdentityPoolId:
        Ref: IdentityPool
      Roles:
        unauthenticated:
          Fn::GetAtt:
          - UnauthenticatedRole
          - Arn
        authenticated:
          Fn::GetAtt:
          - AuthenticatedRole
          - Arn
Outputs:
  UserPool:
    Value:
      Ref: UserPool
  UserPoolClient:
    Value:
      Ref: UserPoolClient
  IdentityPool:
    Value:
      Ref: IdentityPool
  UnauthenticatedRole:
    Value:
      Ref: UnauthenticatedRole
  AuthenticatedRole:
    Value:
      Ref: AuthenticatedRole

その他の活用方法

Serverless Framework は CloudFormation のリソーステンプレートを埋め込めるので、 User Pool のトリガーで使う Lambda ファンクションを同時作成するのにうってつけです。

その場合は AWS::Cognito::UserPool の LambdaConfig プロパティ を指定してトリガーを設定します。また、 AWS::Lambda::Permission も忘れずに作る必要があります(Principalcognito-idp.amazonaws.com)。

続きを読む

AWS Lambdaデプロイ方法を求めて:Serverlessフレームワーク

このドキュメントレベル:初めて学ぶ人向け

Lambdaの良いデプロイフローはないかと思って調べた記録です。
Lambdaのデプロイにはいくつか種類があるようです。

  • Serveless
  • Apex
  • Lamvery
  • LambCI
  • CodeShip

今回は「Serverless」について、どんなものかを触りだけ調べています。

Serverless

サーバーレスなアーキテクチャを容易に作成、管理できるフレームワークです
AWS Lambda, Apache OpenWhisk, Microsoft Azureなどをサポートしているようです。

デプロイイメージをつかむ

  • このnode.jsのサンプルを実際にやってみると感じがよくわかります。事前のAWSのCredentialsの設定をやっておきましょう

Hello World Node.js Example

Serverless Framework – AWS Lambda Guide – Credentials

豊富なサンプルコード

gutHubにサンプルコードがアップされているので、これを実行するだけでも感じがつかめます

serverless/examples: Serverless Examples – A collection of boilerplates and examples of serverless architectures built with the Serverless Framework and AWS Lambda

例)aws-node-rest-api-with-dynamodb/

cloneしてきて、deployしてみます

14:45:35 aws-node-rest-api-with-dynamodb/  $ ls
README.md   package.json    serverless.yml  todos


14:46:01 aws-node-rest-api-with-dynamodb/  $ npm install
aws-rest-with-dynamodb@1.0.0 /Users/bohebohechan/devel/src/gitlab.com/FirstFourNotes/serverless/aws-node-rest-api-with-dynamodb
└── uuid@2.0.3

npm WARN aws-rest-with-dynamodb@1.0.0 No repository field.

11:23:44 aws-node-rest-api-with-dynamodb/  $ sls deploy
Serverless: Packaging service...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (22.45 KB)...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
......................................................................................................
Serverless: Stack update finished...
Service Information
service: serverless-rest-api-with-dynamodb
stage: dev
region: us-east-1
api keys:
  None
endpoints:
  POST - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/todos
  GET - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/todos
  GET - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/todos/{id}
  PUT - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/todos/{id}
  DELETE - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/todos/{id}
functions:
  create: serverless-rest-api-with-dynamodb-dev-create
  list: serverless-rest-api-with-dynamodb-dev-list
  get: serverless-rest-api-with-dynamodb-dev-get
  update: serverless-rest-api-with-dynamodb-dev-update
  delete: serverless-rest-api-with-dynamodb-dev-delete
11:25:19 aws-node-rest-api-with-dynamodb/  $

RestAPIができてしまったようです。

AWSコンソールで確認

実際にコンソールで確認してみましょう

> Lambda

lambda.png

> DynamoDB

キャプチャ撮り忘れたので割愛・・・

> API Gateway

apigateway.png

> S3

s3.png

> CloudFormation

cloudformation.png

> CloudWatch Logs

cloudwatchlogs.png

PostmanでAPIを実行してみます

> Post

postman-post.png

> Get

postman-list.png

後片付け

消しておきましょう

11:44:47 aws-node-rest-api-with-dynamodb/  $ sls remove
Serverless: Getting all objects in S3 bucket...
Serverless: Removing objects in S3 bucket...
Serverless: Removing Stack...
Serverless: Checking Stack removal progress...
..............................................................
Serverless: Stack removal finished...

このようなサンプルをカスタマイズしていくことで、自分の欲しい機能を簡単に作っていけそうです。

serverless.yml

先ほどの例)aws-node-rest-api-with-dynamodb/を参考にして、serverless.ymlの中身を紐解いてみましょう
解説はざっくりなので、詳細は公式ページで確認のことです。

AWSをプロバイダーにセットしたときに有効となるプロパティ一覧が載っています
Serverless Framework – AWS Lambda Guide – Serverless.yml Reference

  • service

プロジェクト名

  • frameworkVersion

フレームワークの対応バージョン

service: serverless-rest-api-with-dynamodb

frameworkVersion: ">=1.1.0 <2.0.0"
  • provider

AWS CloudFormation stack
サービスがデプロイされる対象について書きます。ここでは、AWSですよね 
 
– iamRoleStatements
How it works iamRoleStatements configuration section? – Serverless Framework – Serverless Forums

Lambda Functionで、AWSのリソースにアクションする際の許可をAWS IAM Roleで記述します。
「provider.iamRoleStatements」のプロパティに必要となる許可ステートメントを設定します。
今回は、Lambdaからdynamodbへの許可が必要ですね。

provider:
  name: aws
  runtime: nodejs6.10
  environment:
    DYNAMODB_TABLE: ${self:service}-${opt:stage, self:provider.stage}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"

-Functions

Lambdaに作成するFunctionの定義を書きます

  • Events

Lambda Function の起動するトリガーを書きます
S3バケットへのアップロードや、SNSトピック受信や、HTTPのエンドポイントですね

サポートしているイベントの一覧はこちら
Serverless – AWS Lambda – Events

functions:
  create:
    handler: todos/create.create
    events:
      - http:
          path: todos
          method: post
          cors: true

  list:
    handler: todos/list.list
    events:
      - http:
          path: todos
          method: get
          cors: true

  get:
    handler: todos/get.get
    events:
      - http:
          path: todos/{id}
          method: get
          cors: true

  update:
    handler: todos/update.update
    events:
      - http:
          path: todos/{id}
          method: put
          cors: true

  delete:
    handler: todos/delete.delete
    events:
      - http:
          path: todos/{id}
          method: delete
          cors: true
  • Resources

AWS CloudFormation stackに追加することができます。
以下では、TodosDynamoDbTableを追加しています。
特定のCloudFormationのリソースに対して、値を上書きすることもできます

resources:
  Resources:
    TodosDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        AttributeDefinitions:
          -
            AttributeName: id
            AttributeType: S
        KeySchema:
          -
            AttributeName: id

ワークフロー

Serverless Framework Guide – AWS Lambda – Workflow

Development Workflowとして以下の手順で回しましょう、といったことが書かれています。

  1. Write your functions
  2. Use serverless deploy only when you’ve made changes to serverless.yml and in CI/CD systems.
  3. Use serverless deploy function -f myFunction to rapidly deploy changes when you are working on a specific AWS Lambda Function.
  4. Use serverless invoke -f myFunction -l to test your AWS Lambda Functions on AWS.
  5. Open up a separate tab in your console and stream logs in there via serverless logs -f myFunction -t.
  6. Write tests to run locally.

参考になるドキュメント

続きを読む

AWS LambdaでDynamoDBから取得した値に任意の集計をかける

前回書いた記事「AWS LambdaでDynamoDBから取得した値の最新レコードを取得する」を、以下の集計にも対応させてみました。

  • 最新値 (latest)
  • 最大値 (max)
  • 最小値 (min)
  • 平均値 (avg)
  • 合計値 (sum)
  • 件数 (count)

前提&仕様

以下を前提&仕様として作成しました。

  1. DynamoDBのハッシュキーにID(文字列)、レンジキーに時刻(文字列)を指定しているものとする。
  2. データは時系列に格納されているものとする。
  3. 指定したカラムの集計を取るようにする。
  4. 集計の時間を指定できるようにする。
  5. 集計の種類は指定可能とする。
  6. ID、集計期間、集計対象のカラム、集計の種類はそれぞれJSONのインプットで指定可能とする。

結果

こちらに登録してあります。

https://github.com/kojiisd/lambda-dynamodb-aggregator

サンプルデータ

以下のデータをDynamoDBに入れました。これについて色々と操作をしようと思います。

スクリーンショット 2017-05-03 11.49.57.png

使い方

インプットデータの準備

以下のインプットデータが必要になります。

カラム名 内容
label_id DynamoDBで指定しているハッシュキー名
label_range DynamoDBで指定しているレンジキー名
id 集計したいIDの値
aggregator 集計種別。種別は最初に書いた6種類に対応
time_from 集計対象期間(開始)
time_to 集計対象期間(終了)
params [個別]集計時必要になるパラメータ

インプットデータの準備(個別部)

上述の「params」に該当する部分は以下の様なパラメータの準備が必要になります。

集計種別 必要な値
最新値(latest) range: レンジキー名(共通部で指定していますが、一応他に体裁を合わせました)
最大値(max) score: 集計対象のカラム名
最小値(min) score: 集計対象のカラム名
平均値(avg) score: 集計対象のカラム名
合計値(sum) score: 集計対象のカラム名
件数(count) score: 集計対象のカラム名

こんな感じで指定すれば実行可能になります。

とりあえず実行してみる

とりあえず動かしてみたい人は以下の様な感じで実行すれば結果が見れます。今回はSERVERLESS FRAMEWORK上で動かしています。

「sensor1」に対して指定した時間の中での:

最新値(latest)
$ sls invoke local -f run -d '{"label_id": "id", "label_range": "timestamp", "id": "sensor1", "aggregator": "latest", "time_from": "2017-04-30T22:00:00.000", "time_to": "2017-04-30T22:05:00.000", "params": {"range": "timestamp"}}'
"{"timestamp": "2017-04-30T22:05:00.000", "score": 0.0, "id": "sensor1"}"
最大値(max)
$ sls invoke local -f run -d '{"label_id": "id", "label_range": "timestamp", "id": "sensor1", "aggregator": "max", "time_from": "2017-04-30T22:00:00.000", "time_to": "2017-04-30T22:05:00.000", "params": {"score": "score"}}'
"{"timestamp": "2017-04-30T22:04:00.000", "score": 1.0, "id": "sensor1"}"

(同じ値がヒットした場合は新しい方のデータを取得する様にしています。)

最小値(min)
$ sls invoke local -f run -d '{"label_id": "id", "label_range": "timestamp", "id": "sensor1", "aggregator": "min", "time_from": "2017-04-30T22:00:00.000", "time_to": "2017-04-30T22:05:00.000", "params": {"score": "score"}}'
"{"timestamp": "2017-04-30T22:05:00.000", "score": 0.0, "id": "sensor1"}"
平均値(avg)
$ sls invoke local -f run -d '{"label_id": "id", "label_range": "timestamp", "id": "sensor1", "aggregator": "avg", "time_from": "2017-04-30T22:00:00.000", "time_to": "2017-04-30T22:05:00.000", "params": {"score": "score"}}'
"0.3333333333333333"
合計値(sum)
$ sls invoke local -f run -d '{"label_id": "id", "label_range": "timestamp", "id": "sensor1", "aggregator": "sum", "time_from": "2017-04-30T22:00:00.000", "time_to": "2017-04-30T22:05:00.000", "params": {"score": "score"}}'
"2.0"
件数(count)
$ sls invoke local -f run -d '{"label_id": "id", "label_range": "timestamp", "id": "sensor1", "aggregator": "count", "time_from": "2017-04-30T22:00:00.000", "time_to": "2017-04-30T22:05:00.000", "params": {"score": "score"}}'
"6"

仕組み

最新値

以前の記事と同様、指定したレンジキーの最大値を取るようにしただけです。

max(data, key=(lambda x:x[params['range']]))

最大値 / 最小値

max関数とmin関数が使えるようにこんな実装にしています。

max_aggregator.py
max(data, key=(lambda x:x[params['score']]))
min_aggregator.py
min(data, key=lambda x: x[params['score']])

平均値

後述の合計値と件数を使っての計算になります。

sum(map(lambda x: x['score'], data)) / len(map(lambda x: x['score'], data))

合計値

sum関数使ってサクッと計算したかったのでこんな感じです。

sum(map(lambda x: x['score'], data))

件数

対象カラムの長さをとっただけです。

len(map(lambda x: x['score'], data))

AWS Lambdaでも動くのか?

現状のserverless.ymlには権限周りの設定が足りなかったようなのですが、とりあえずデプロイ後に手動で権限を正しくセットしたらうまくいきました。

とりあえずデプロイは何も問題なく完了。

$ sls deploy 
Serverless: Packaging service...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (10.19 KB)...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...............
Serverless: Stack update finished...
Service Information
service: lambda-dynamodb-aggregator
stage: dev
region: us-east-1
api keys:
  None
endpoints:
  None
functions:
  run: lambda-dynamodb-aggregator-dev-run

スクリーンショット 2017-05-03 12.20.13.png

動きはしました。(件数を取得しています)

スクリーンショット 2017-05-03 12.38.32.png

続きを読む

ユーザデータを利用して、Windowsインスタンスの時刻を東京標準時に設定する

はじめに AWSチームのすずきです。 AWSが提供するAMIを利用して起動したWindowsインスタンス、デフォルトではOSのタイムゾーンはUTCとなります。 このタイムゾーンを東京標準時に変更する設定方法については下記 […] 続きを読む

【AWS】ELB(CLB)

はじめに

タダです。
AWS認定資格の試験勉強のためにELBの情報をまとめた自分用メモになります。
あくまで個人用のメモになるので、その点はご了承ください。
※違う内容書いているなどありましたらご指摘いただけると幸いです。
※本記事では、Classic Load Balancerの情報をまとめていきます。
※随時アップデートがあれば更新していきます。

サービス概要

ELBは2つのタイプに分けられる

  • Classic Load Balancer

    • アプリまたはネットワークレベルのいずれかの情報に基づいてルーティングする
    • 複数のEC2インスタンス間でシンプルなトラフィックのルーティングに適する
  • Application Load Balancer
    • リクエストパスまたはホストベースでルーティングする
    • 複数のサービスにルーティングしたり、同じEC2インスタンスの複数のポート間で負荷分散するのに適する

特徴

  • スケーラブル

    • ELB自体も負荷に応じてスケールアウト
  • 可用性向上
    • 複数AZへの振り分け、インスタンスのヘルスチェック
  • マネージドサービス
  • ルーティング方式
    • 基本はラウンドロビン
  • コネクションタイムアウト
    • クライアントからの無通信状態が続くと接続を自動で切断する(デフォルト60秒)
  • ELB自体のスケーリング
    • じんわりとしたトラフィックの増加には対応できる

      • 逆に急激なトラフィックの増加にはスケーリング対応できないため、事前にPre-Warming(暖機運転)の申請をAWSに行う
  • スティッキーセッション
    • 同じユーザーから来たリクエストをすべて同じEC2に送信
    • アプリケーションでのセッション情報、一時ファイルなどをEC2が保持する構成の場合に必要
    • HTTP/HTTPSでのみ利用可能
    • EC2の増減を柔軟に管理できるようセッション情報は別のDBやキャッシュサーバに保持させるのが好ましい
  • Connection Draining
    • EC2インスタンスとELB間の登録解除、ヘルスチェック失敗した時にルーティングを中止して、処理中のリクエスト終わるまで一定期間まつ
  • X-Forwarded-For
    • HTTPまたはHTTPSロードバランサーを使用する場合に、クライアントの IP アドレスを識別するのに役立つ
  • Proxy Protocol
    • ELBはProxy Protocolバージョン1をサポートしている
    • Proxy Protocolヘッダーはバックエンド接続用にTCPを使う場合、クライアントのIPアドレスを識別するのに役立つ
    • 有効化する場合の前提条件は以下の通り
      • ELBの背後にプロキシサーバがいないこと
      • インスタンスでProxy Protocol情報を処理できるか確認する
      • リスナー設定でProxy Protocloがサポートされているかを確認する
  • 他のサービスとの連携機能
    • AutoScaling
    • Route53
    • CloudFormation
    • OpsWorks
    • Elastic Beanstalk
    • CloudWatch
    • EC2
    • S3など

サポートプロトコル

Classic Load Balancerのサポートプロトコルは、以下の通り

  • HTTP
  • HTTPS
  • SSL(セキュアTCP)
  • TCP

ロードバランサーのタイプ

ロードバランサーのタイプとして、外向けロードバランサーと内向けロードバランサーがある

  • 外向けロードバランサー : インターネットからアクセスできるELB
  • 内向けロードバランサー : VPC内やオンプレ環境からのみアクセスできるELB

モニタリング

ELBの監視を行う場合は以下の方法がある

  • CloudWatchメトリクス
  • ELBのアクセスログ
    • ELBへのリクエストの詳細情報をキャプチャしているので、確認する
  • CloudTrailログ

トラブルシューティング

よくELBのトラブルシューティングでHTTPステータスから設定不足を確認することがあるので、ドキュメントの情報をまとめる

  • HTTP 400: BAD_REQUEST

    • 原因:クライアントが誤ったリクエストをしてしまったため発生
    • 解決策:直接インスタンスに接続し、クライアントリクエストの詳細をキャプチャする
  • HTTP 405: METHOD_NOT_ALLOWED
    • 原因:リクエストヘッダー内のメソッドの長さが127文字を超える
    • 解決策:メソッドの長さを確認する
  • HTTP 408: Request Timeout
    • 原因:指定されたコンテンツのサイズが実際に創始されたコンテンツサイズと一致しないや、クライアントとの接続が閉じているため発生
    • 解決策:リクエストを生成しているコードを調べ、リクエストをより詳細に調べることのできる登録済みインスタンスに直接送信する、レスポンスが送信される前にクライアントが接続を閉じないようにする
  • HTTP 502: Bad Gateway
    • 原因:インスタンスからの応答の形式が適切でないか、ロードバランサーに問題がある
    • 解決策:インスタンスから送信された応答が HTTP 仕様に準拠していることを確認する
  • HTTP 503: Service Unavailable
    • 原因:ロードバランサーにリクエストを処理する能力が不足または、登録されたインスタンス(正常なインスタンス)が存在しない
    • 解決方法:前者の場合は一時的な問題のため、一旦放置氏それでも解決しない場合はAmazon Web Servicesサポートへ問い合わせ
    • 後者の場合、正常なインスタンスを登録する
  • HTTP 504: Gateway Timeout
    • 原因:アプリケーションの応答が、設定されているアイドルタイムアウトよりも長くかかっているまたは、録されたインスタンスがELBへの接続を終了させている
    • 解決策:前者は、ELB側のアイドル接続のタイムアウト設定を伸ばす
    • 後者の場合は、MWのKeepAlive設定を有効にしてELBのタイムアウト設定よりも大きい値を定義する

参考

更新日時

2017/05/01 初回投稿

続きを読む

【AWS】OpsWorks スタック

はじめに

タダです。
AWS認定資格の試験勉強のためにCloudFormationの情報をまとめた自分用メモになります。
あくまで個人用のメモになるので、その点はご了承ください。
※違う内容書いているなどありましたらご指摘いただけると幸いです。
※随時アップデートがあれば更新していきます。
※本記事では、OpsWorks スタック中心のまとめになります。

サービス概要

  • OpsWorksはChefを使ったAWSリソース(EC2、ELB、RDSなど)やEC2上のアプリケーションの設定・管理を行うためのサービス
  • Chefサーバーは不要で、OpsWorksスタックは、インスタンスのヘルスチェックをモニタリングし、自動復旧および Auto Scaling を使用して、必要な場合に新しいインスタンスをプロビジョニングする
  • Chefのcookbookレシピを使って、インフラの管理を自動化、アプリケーションの継続的なインストール、構成、管理、デプロイ、スケールが可能なのがChef Automate
    • Chefサーバありきだが、管理はAWS

OpsWorksエージェント

  • OpsWorksスタックで必要

    • OpsWorksの一連のコマンドを取得し、エージェントがChef Clientのローカルモードでレシピを実行

利用メリット

アプリケーションのモデル化とサポート
管理作業を自動化

CloudFormation/Elastic Beastalkとの違い

  • OpsWorksは、DevOps環境を提供することを目的におき、デプロイ、モニタリング、自動スケーリング、自動化の主要なアクティビティに対して統一された設定管理を行う
  • CloudFormationはAWSリソースのプロビジョニングと管理をJSON/YAMLで行うことを目的とする
  • Elastic BeastalkはJava、.NET、PHP、Node.js、Python、Ruby、Go、Docker で開発されたウェブアプリケーションとウェブサービスをデプロイおよびスケーリングする

制限

デフォルトでは、最大40スタックを作成できる
最大40のレイヤー、最大40のインスタンス、最大40のアプリケーションを保持できる
 

専門用語

  • スタック

    • OpsWorksの管理対象をまとめたコンポーネントで、属する全員インスタンスの構成を管理する
  • レイヤー
    • 1つ以上の Layer を追加することにより、スタックのコンポーネントを定義する
    • レイヤーは、アプリケーションへのサービス提供やデータベースサーバーのホストのような特定の目的を果たす一連のEC2インスタンスを表す
  • インスタンス
    • インスタンスのスケーリングタイプは3つある

      • 24/7インスタンス(常時稼働)
      • load-basedインスタンス
        • 負荷に対してサーバを起動することができる
        • メトリックスの閾値は次のものを定義し、インスタンスの増減をコントールできる
          • [Average CPU] – Layer の平均 CPU 使用率 (合計に対する割合)
          • [Average memory] – Layer の平均メモリ使用率 (合計に対する割合)
          • [Average load] – Layer の平均負荷
      • time-basedインスタンス
        • 時間ベースのスケーリングにより指定したスケジュールでインスタンスを起動、停止できる
        • 特定の時間または特定の曜日にレイヤーによりオンラインにされるインスタンス数を制御できる
  • App
    • アプリケーショサーバにデプロイするアプリケーション
  • レシピ
    • Chefレシピを実行して、アプリケーションの設定、アプリケーションのデプロイ、スクリプトの実行などを行う

スタックコマンド

スタック全体の構成を変更・管理するためのコマンドで以下のようなものがある
実行方法はAWSマネジメントコンソールやCLI、SDKなど

  • Update Custom Cookbook

    • リポジトリにある更新されたCookbookをそれぞれのインスタンスに展開する
  • Execute Recipes
    • 指定したレシピを指定したインスタンス上で実行する
  • Setup
    • Setupのレシピを実行する
  • Configure
    • Configureのレシピを実行する
  • Upgrade Operationg System
    • (Linuxのみ)Amazon Linuxを最新バージョンにアップグレードする

ライフサイクル

OpsWorksのインスタンスで自動的に行う処理をさす

  • Setup : 新しいインスタンスが正常にブートした後に発生する

    • ex: ロードバランサーをインストール、アプリケーションサーバをインストール、データベースをインストール
  • Configure : インスタンスがオンライン状態に移行したときとオンライン状態から移行した時にスタックのすべてのインスタンスで発生する
    • ex: アプリケーションサーバのIPをアップデート、DB接続先をアップデートして再起動、アプリケーションサーバのIPのACLをアップデート
  • Deploy : ユーザーがアプリケーションをデプロイする時に発生する
    • ex:アプリケーションコードをアップデートして再起動
  • Undeploy : アプリケーションを削除する時に発生する
    • ex:アプリケーションを削除して再起動
  • Shutdown : インスタンスの終了
    • コネクションをDrainする、ログを保存、スナップショットの保存

Opsworksと他サービスとの連携

モニタリング

スタックは次の方法で監視可能

  • CloudWatchによるスタックのインスタンスごとに詳細モニタリング
  • CloudTrailによるAPI監視
  • CloudWatch Logsでスタックのシステム・アプリケーション・カスタムログを監視する

セキュリティおよびアクセス許可

  • VPC内に展開可能
  • AWSリソースにアクセスするためのACLやインスタンスへの接続管理はIAM(ユーザー、許可、ロール)で行う

参考

更新日時

  • 2017/05/01 初回投稿

続きを読む