- 投稿日:2019-11-15T22:34:20+09:00
【AWS/RDS】今夜勝ちたいスロークエリログ出力
AWSにapi作ったんだけど(非公開)、相当数の同時接続時に速さが足りないと言われたんで、
とりま原因究明のためにRDS(MariaDB)からスロークエリログを吐き出してCloudWatchで眺めてみた。
その軌跡です。深奥まで知る必要はないけどとりあえず今夜勝ちたい人向けです。
環境
本記事はAWS RDS(MariaDB10.2)で試しています。
以降はこの前提で進めますがバージョン違いやMysqlでも基本同じな模様。
Auroraは若干微妙に違うので他の記事をご参照下さい。作業工程
やることは大きく2つ。
- パラメータグループの設定(DBエンジンのパラメータ設定)
- ログエクスポートの設定(CloudWatchへの出力設定)
tips
RDSでは新しくデータベースを作成する際に、エンジン毎にデフォルトで用意されているパラメータ&オプショングループを選択できます。
できますが下記理由からオリジナルを作ることをお勧めします。(特にパラメータ)
- デフォルトグループは設定値が変更不可
- グループの付け替えは再起動が必要
パラメータグループの設定
「RDS > パラメータグループ > パラメータグループの作成」より
- パラメータグループを作成
- 作成したパラメータグループを選択
- パラメータの編集で以下の値を設定
- slow_query_log = 1 (スロークエリ出力の有無)
- long_query_time = 1 (スロークエリと判定する秒数。お好みで)
- log_output = FILE (ログの出力方法)
グループ作成時のパラメータグループファミリーには使用するDBエンジンを指定。
他は適当でおk。(嘘、あとでわかりやすい名前を設定して)デフォルトではslow_query_log=0(false)なのでスロークエリは出力されません。
また、log_output = TABLEの場合、DB接続して下記でログは参照可能です。select * from mysql.slow_logちなみにここで設定した値は適用タイプがdynamicなので即時適用されます。
ここがstaticのパラメータはDBの再起動が必要です。ログエクスポートの設定
新規DB作成:「RDS > データベース > データベースの作成」より
既存DB変更:「RDS > データベース > {当該DB} > 変更」よりどちらの場合も下記を設定します。
- DBパラメータグループ = 作成したパラメータグループ
- ログのエクスポート > スロークエリログ = ON
新規作成の場合、追加設定というところに折り畳まれてるんで見逃してそのまま作成しないように気をつけてください。
俺はやった。結果
これで「CloudWatch > ログ」に/aws/rds/instance/{DB名}/slowquery
というログが出力されるようになるはずです。あとはスロークエリから遅延の原因を探すだけです!やったね!
僕はクエリが原因ではなさそうと判定されたので来週も戦い続けます。
- 投稿日:2019-11-15T21:32:37+09:00
【AWS EC2】bundler -v -bash: bundler: コマンドが見つかりません
エラー文はこんな感じですか?
[ec2-user@ip-XXX-XX-XX-XX chat-space2]$ bundler -v -bash: bundler: コマンドが見つかりませんbundlerが入ってない場合
まずはbundlerをいれましょう。
$ gem install bundler -v 2.0.1
$ bundle install
バージョンはご自身のものに合わせて。rbenvが入ってない場合
$ rbenv install 2.5.1 $ rbenv global 2.5.1 $ rbenv rehash #rehashを行う $ ruby -v # バージョンを確認こちらも、バージョンはご自身のものに合わせて。
なぜこんな初歩的なミスの記事を書いたか
単純なことなのですが、初めてのことで
「EC2は失敗すると1から作り直すんだぞ!変なことすると重課金になるんだぞ!」
みたいな脅しも色々聞いてきたので、焦って難しく考えすぎてエラーの解決ができませんでした。スクールに通う身で、この解決に取り組んでいただいたメンターさんにも「ちゃんとカリキュラム読もうね!(げんなり)」というようなありがたいお言葉(涙)
こんな簡単なことでも、解決策が検索で引っかかれば、
凡ミスはもっと早く解決できると思うんです。
なので私は恥をさらす。絶対にだ!
- 投稿日:2019-11-15T19:31:47+09:00
Amazon Linux2 にdockerをインストールしようとしたらはまった話
Amazon Linuxはちょっと違うので備忘録。
2019/11/15日時点での対応Amazon Linux2にDockerのインストールを試みる
ちょっと簡単に開発環境を作りたかったので、EC2上にDockerをインストールしようとしました。
DockerはいつもCentOS方式でインストールしてましたんで、ここを参照しながらインストール。$ sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo sudo yum install docker-ce docker-ce-cli containerd.io sudo systemctl start dockerすると、依存性の関係でエラーが発生
$ sudo yum install docker-ce docker-ce-cli containerd.io 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd docker-ce-stable | 3.5 kB 00:00:00 (1/2): docker-ce-stable/x86_64/updateinfo | 55 B 00:00:00 (2/2): docker-ce-stable/x86_64/primary_db | 37 kB 00:00:00 依存性の解決をしています --> トランザクションの確認を実行しています。 〜 略 〜 エラー: パッケージ: containerd.io-1.2.10-3.2.el7.x86_64 (docker-ce-stable) 要求: container-selinux >= 2:2.74 エラー: パッケージ: 3:docker-ce-19.03.5-3.el7.x86_64 (docker-ce-stable) 要求: container-selinux >= 2:2.74 問題を回避するために --skip-broken を用いることができます。 これらを試行できます: rpm -Va --nofiles --nodigestoh。マジか。どうやらcontainer-selinuxのバージョンが合わないよ、とのこと。
助けてGoogle先生
ということで色々漁ってみた結果、CentOSのリポジトリから対象のバージョンをダウンロードするも、今度selinux-policyの依存性でエラーが。
$ sudo yum install ftp://bo.mirror.garr.it/1/slc/centos/7.1.1503/extras/x86_64/Packages/container-selinux-2.74-1.el7.noarch.rpm 〜 略 〜 エラー: パッケージ: 2:container-selinux-2.74-1.el7.noarch (/container-selinux-2.74-1.el7.noarch) 要求: selinux-policy-base >= 3.13.1-216.el7 インストール: selinux-policy-targeted-3.13.1-192.amzn2.6.noarch (installed) selinux-policy-base = 3.13.1-192.amzn2.6 利用可能: selinux-policy-minimum-3.13.1-166.amzn2.5.noarch (amzn2-core) selinux-policy-base = 3.13.1-166.amzn2.5 利用可能: selinux-policy-minimum-3.13.1-166.amzn2.9.noarch (amzn2-core) selinux-policy-base = 3.13.1-166.amzn2.9 利用可能: selinux-policy-minimum-3.13.1-192.amzn2.6.noarch (amzn2-core) selinux-policy-base = 3.13.1-192.amzn2.6 利用可能: selinux-policy-mls-3.13.1-166.amzn2.5.noarch (amzn2-core) selinux-policy-base = 3.13.1-166.amzn2.5 利用可能: selinux-policy-mls-3.13.1-166.amzn2.9.noarch (amzn2-core) selinux-policy-base = 3.13.1-166.amzn2.9 利用可能: selinux-policy-mls-3.13.1-192.amzn2.6.noarch (amzn2-core) selinux-policy-base = 3.13.1-192.amzn2.6 利用可能: selinux-policy-targeted-3.13.1-166.amzn2.5.noarch (amzn2-core) selinux-policy-base = 3.13.1-166.amzn2.5 利用可能: selinux-policy-targeted-3.13.1-166.amzn2.9.noarch (amzn2-core) selinux-policy-base = 3.13.1-166.amzn2.9 エラー: パッケージ: 2:container-selinux-2.74-1.el7.noarch (/container-selinux-2.74-1.el7.noarch) 要求: selinux-policy-targeted >= 3.13.1-216.el7 インストール: selinux-policy-targeted-3.13.1-192.amzn2.6.noarch (installed) selinux-policy-targeted = 3.13.1-192.amzn2.6 利用可能: selinux-policy-targeted-3.13.1-166.amzn2.5.noarch (amzn2-core) selinux-policy-targeted = 3.13.1-166.amzn2.5 利用可能: selinux-policy-targeted-3.13.1-166.amzn2.9.noarch (amzn2-core) selinux-policy-targeted = 3.13.1-166.amzn2.9 エラー: パッケージ: 2:container-selinux-2.74-1.el7.noarch (/container-selinux-2.74-1.el7.noarch) 要求: selinux-policy >= 3.13.1-216.el7 インストール: selinux-policy-3.13.1-192.amzn2.6.noarch (installed) selinux-policy = 3.13.1-192.amzn2.6 利用可能: selinux-policy-3.13.1-166.amzn2.5.noarch (amzn2-core) selinux-policy = 3.13.1-166.amzn2.5 利用可能: selinux-policy-3.13.1-166.amzn2.9.noarch (amzn2-core) selinux-policy = 3.13.1-166.amzn2.9 問題を回避するために --skip-broken を用いることができます。 これらを試行できます: rpm -Va --nofiles --nodigestめんどくせえ・・・orz
回り回って公式にたどり着いた
んで、どうしたもんかなと。
依存性の解決をいちいちやりたくないなー・・・、かといってECS使う程ガチな環境じゃないんだよなー・・・とか思ってECSのページを見ると、Amazon LinuxへのDockerインストールマニュアルが偶然見つかりました。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html$ sudo yum update -yパッケージをアップデートして・・・
$ sudo amazon-linux-extras install dockerExtraリポジトリからdockerをインストールして・・・
$ sudo service docker startサービスを起動
$ sudo service docker start Redirecting to /bin/systemctl start docker.service $ ps -ef |grep docker root 12642 1 1 10:25 ? 00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --default-ulimit nofile=1024:4096 ec2-user 12818 3438 0 10:25 pts/0 00:00:00 grep --color=auto dockerこんな簡単やったんか・・・orz
教訓
困ったら公式を読め
- 投稿日:2019-11-15T17:25:22+09:00
Deeplearning on AWS をやってみたの巻き
目的
Deep Learning を学ぶ
目標
よくある犬の学習をやってみる
学習させてみる
Deep Learning 周辺ツールを使ってみる結果
sage maker を使うと学習効率がいいね!
機械学習を学びたい人にとって、環境設定やAPI 連携などの"機械学習を使うための環境構築" は、障壁になりそう。
最初は、AWS トレーニング等を通じて、1回教えてもらうと学びたいところへジャンプしやすそう。周辺ツールとして、
コンテナ やLambda などのオンプレミスサーバ構築と比べ、高速化を実感しながら、機械学習を体験できた。
今までより、OS起動、OS設定でつまずかない分、気楽でした!できたこと
やったこと
サンプル画像とサンプルコードで、コンテナ作ったり、機械学習のトレーニングと推論を実際にやってみた。
CPU と GPU の応答速度の差を体験できたのも良かったかも。GPU だと3分でもCPUだと20分ぐらいかかっちゃう。
- 投稿日:2019-11-15T17:02:00+09:00
CloudFormation Resource Importで既存のスタックをリファクタリング!
はじめに
CloudFormation で全世界待望?のリソースインポート機能がリリースされました。
AWS CloudFormation Launches Resource Import
https://aws.amazon.com/jp/about-aws/whats-new/2019/11/aws-cloudformation-launches-resource-import/CloudFormationで管理されていないリソースをスタックに取り込むことができるようになったわけですが、
このリソースインポート機能を活用することで既存のスタック間でリソースを移動したり
複雑化したスタックのリファクタリングを行ったりすることもできます。スタック分割を例に考える
既存のスタックを分割しようとする場合、概ね以下のような流れとなります。
- ソーステンプレート内の分割対象のリソースに対し
DeletionPolicy: Retain
を指定し、適用する- 分割対象のリソースをソーステンプレートから削除し、ターゲットテンプレートに追加する
- 既存スタックを更新して分割対象のリソースを削除(管理対象外)にする
- ターゲットテンプレートを使用して、管理対象外となった分割対象リソースをインポートする
ソーステンプレート: 既存スタックのテンプレート
ターゲットテンプレート: 分割する新しいスタックのテンプレートやってみる
1つのテンプレートでVPCとEC2を一緒に管理していて、それぞれを別スタックに分割する例を考えてみます。
検証目的であるため、ここでは以下のようなシンプルなテンプレートで試してみます。source.yamlAWSTemplateFormatVersion: '2010-09-09' Description: split stack test Parameters: pLatestAmiId: Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' pInstanceType: Type: String Default: 't3.micro' Resources: # Create VPC rMyVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true InstanceTenancy: default Tags: - Key: Name Value: test-vpc # Create Public RouteTable rPublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref rMyVPC Tags: - Key: Name Value: test-pubric-route # Create Public Subnet rPublicSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref rMyVPC CidrBlock: 10.0.0.0/24 AvailabilityZone: !Select [ 0, !GetAZs "" ] MapPublicIpOnLaunch: true Tags: - Key: Name Value: test-public-subnet rRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref rPublicSubnet RouteTableId: !Ref rPublicRouteTable # Create InternetGateway rInternetGateway: Type: "AWS::EC2::InternetGateway" Properties: Tags: - Key: Name Value: test-igw rAttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref rMyVPC InternetGatewayId: !Ref rInternetGateway # Route for InternetGateway rRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref rPublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref rInternetGateway # Create EC2 Secuirty Group rSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref rMyVPC GroupDescription: Security Group for EC2 Instance SecurityGroupIngress: - CidrIp: 0.0.0.0/0 FromPort: 443 IpProtocol: tcp ToPort: 443 Tags: - Key: Name Value: test-sg # Create EC2 Instance rMyEC2: Type: AWS::EC2::Instance Properties: ImageId: !Ref pLatestAmiId InstanceType: !Ref pInstanceType SecurityGroupIds: - !Ref rSecurityGroup SubnetId: !Ref rPublicSubnet Tags: - Key: Name Value: test-ec2以降、前述の手順1~4に沿って順番にやっていきます。
手順1
EC2およびセキュリティグループを別スタックに分割するため、ソーステンプレートで
DeletionPolicy: Retain
を追加します。
既存のスタックで既に設定されている場合はスキップ可能な作業です。rSecurityGroup: Type: AWS::EC2::SecurityGroup + DeletionPolicy: Retain Properties: rMyEC2: Type: AWS::EC2::Instance + DeletionPolicy: Retain Properties:
編集後のソーステンプレート
source.yamlAWSTemplateFormatVersion: '2010-09-09' Description: split stack test add Deletion Policy Parameters: pLatestAmiId: Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' pInstanceType: Type: String Default: 't3.micro' Resources: # Create VPC rMyVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true InstanceTenancy: default Tags: - Key: Name Value: test-vpc # Create Public RouteTable rPublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref rMyVPC Tags: - Key: Name Value: test-pubric-route # Create Public Subnet rPublicSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref rMyVPC CidrBlock: 10.0.0.0/24 AvailabilityZone: !Select [ 0, !GetAZs "" ] MapPublicIpOnLaunch: true Tags: - Key: Name Value: test-public-subnet rRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref rPublicSubnet RouteTableId: !Ref rPublicRouteTable # Create InternetGateway rInternetGateway: Type: "AWS::EC2::InternetGateway" Properties: Tags: - Key: Name Value: test-igw rAttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref rMyVPC InternetGatewayId: !Ref rInternetGateway # Route for InternetGateway rRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref rPublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref rInternetGateway # Create EC2 Secuirty Group rSecurityGroup: Type: AWS::EC2::SecurityGroup DeletionPolicy: Retain Properties: VpcId: !Ref rMyVPC GroupDescription: Security Group for EC2 Instance SecurityGroupIngress: - CidrIp: 0.0.0.0/0 FromPort: 443 IpProtocol: tcp ToPort: 443 Tags: - Key: Name Value: test-sg # Create EC2 Instance rMyEC2: Type: AWS::EC2::Instance DeletionPolicy: Retain Properties: ImageId: !Ref pLatestAmiId InstanceType: !Ref pInstanceType SecurityGroupIds: - !Ref rSecurityGroup SubnetId: !Ref rPublicSubnet Tags: - Key: Name Value: test-ec2※クリックで展開
編集後のソーステンプレートを既存スタックに反映させます。
Change Set上は、変更なしでアップデートが完了します。
手順2
セキュリティグループおよびEC2インスタンスに関連する記述をソーステンプレートから削除します。
また分割先のスタックからVPCやSubnetの情報を参照できるように、リソースIDをExportしておきます。- Parameters: - pLatestAmiId: - Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> - Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' - pInstanceType: - Type: String - Default: 't3.micro' - - rSecurityGroup: - Type: AWS::EC2::SecurityGroup - DeletionPolicy: Retain - Properties: - VpcId: !Ref rMyVPC - GroupDescription: Security Group for EC2 Instance - SecurityGroupIngress: - - CidrIp: 0.0.0.0/0 - FromPort: 443 - IpProtocol: tcp - ToPort: 443 - Tags: - - Key: Name - Value: test-sg - - rMyEC2: - Type: AWS::EC2::Instance - DeletionPolicy: Retain - Properties: - ImageId: !Ref pLatestAmiId - InstanceType: !Ref pInstanceType - SecurityGroupIds: - - !Ref rSecurityGroup - SubnetId: !Ref rPublicSubnet - Tags: - - Key: Name - Value: test-ec2 + +Outputs: + rMyVPC: + Value: !Ref rMyVPC + Export + Name: rMyVPC + rPublicSubnet: + Value: !Ref rPublicSubnet + Export: + Name: rPublicSubnet
編集後のソーステンプレート
source.yamlAWSTemplateFormatVersion: '2010-09-09' Description: split stack test add vpc only Resources: # Create VPC rMyVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true InstanceTenancy: default Tags: - Key: Name Value: test-vpc # Create Public RouteTable rPublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref rMyVPC Tags: - Key: Name Value: test-pubric-route # Create Public Subnet rPublicSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref rMyVPC CidrBlock: 10.0.0.0/24 AvailabilityZone: !Select [ 0, !GetAZs "" ] MapPublicIpOnLaunch: true Tags: - Key: Name Value: test-public-subnet rRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref rPublicSubnet RouteTableId: !Ref rPublicRouteTable # Create InternetGateway rInternetGateway: Type: "AWS::EC2::InternetGateway" Properties: Tags: - Key: Name Value: test-igw rAttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref rMyVPC InternetGatewayId: !Ref rInternetGateway # Route for InternetGateway rRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref rPublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref rInternetGateway Outputs: rMyVPC: Value: !Ref rMyVPC Export: Name: rMyVPC rPublicSubnet: Value: !Ref rPublicSubnet Export: Name: rPublicSubnet※クリックで展開
分割するセキュリティグループとEC2に関する記載はターゲットテンプレートとして新規作成します。
VPCIDおよびSubnetIDはクロススタック参照させています。
インポートするリソースにもテンプレートで DeletionPolicy 属性を指定する必要があります。target.yamlAWSTemplateFormatVersion: '2010-09-09' Description: split stack test ec2 only Parameters: pLatestAmiId: Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' pInstanceType: Type: String Default: 't3.micro' Resources: # Create EC2 Secuirty Group rSecurityGroup: Type: AWS::EC2::SecurityGroup DeletionPolicy: Retain Properties: VpcId: !ImportValue rMyVPC GroupDescription: Security Group for EC2 Instance SecurityGroupIngress: - CidrIp: 0.0.0.0/0 FromPort: 443 IpProtocol: tcp ToPort: 443 Tags: - Key: Name Value: test-sg # Create EC2 Instance rMyEC2: Type: AWS::EC2::Instance DeletionPolicy: Retain Properties: ImageId: !Ref pLatestAmiId InstanceType: !Ref pInstanceType SecurityGroupIds: - !Ref rSecurityGroup SubnetId: !ImportValue rPublicSubnet Tags: - Key: Name Value: test-ec2手順3
更新したソーステンプレートを使用して、既存のスタックを Update します。
DeletionPolicyにより、リソース自体の削除はスキップされますが、
この時点でセキュリティグループおよび、EC2は既存スタックの管理対象外となります。
手順4
ターゲットテンプレートを使用して、管理対象外となったEC2とセキュリティグループをインポートします。
スタックの作成で 既存のリソースを使用 を選択します。
テンプレートの指定で、ターゲットテンプレートをアップロードして次に進みます。
リソースを識別で、インポート対象のEC2とセキュリティグループのリソースIDを指定します。
スタックの詳細を指定で、新たに作成するスタックの名前を設定します。
インポートが完了し、既存のEC2とセキュリティグループが新しいスタックの
管理対象となっていることを確認します。
まとめ
移動するリソースに削除ポリシーを追加し、ソーススタックから削除&ターゲットスタックに
インポートすることでスタック間でのリソースの移動を簡単に行うことができます。
だだし、現地時点でインポートに対応しているリソースは限られているのでご注意ください。Resources that Support Import Operations
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html
Moving Resources Between Stacks
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/refactor-stacks.html以上です。
参考になれば幸いです。
- 投稿日:2019-11-15T16:59:13+09:00
AWSソリューションアーキテクトアソシエイトに不合格だったので勉強法をまとめます
本記事の結論
・始めて試験を受けるのであればどんな問題がでるか確認のためAWS模擬試験を受けてみる。
・模擬試験を参考にどの教材があっているか決める教材
・Udemy-これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(初心者向け21時間完全コース)
・AWS模擬試験学習方法
・通勤時間を使って毎日Udemyの模擬試験を10問解く
Udemyではハンズオンもありましたがハンズオンを行わずに模擬試験のみを2か月した。
Udemyの模擬試験が90%程とれるようになったのでAWSの模擬試験を受ける・AWS模擬試験を受けたがスコアが思うようにならなかった。
Udemyの模擬試験とAWSの模擬試験にレベルの違いがあった。
↓AWS模擬試験の結果総合スコア: 52% トピックレベルスコア: 1.0 Design Resilient Architectures: 44% 2.0 Define Performant Architectures: 71% 3.0 Specify Secure Applications and Architectures: 33% 4.0 Design Cost-Optimized Architectures: 50% 5.0 Define Operationally-Excellent Architectures: 100%本試験
AWS模擬試験が52%で不安だったがとりあえず本試験を受けてみた。
結果は不合格受験者スコア: 612 結果: 不合格
合格に必要な最低スコアは 720 なので半分ぐらいはとれたイメージ
やっておけばよかったと思ったこと
勉強をどのようにすればよいかわからないのでとりあえずUdemyをやったが問題を覚えて解けるようになったという感じです。
問題を解くだけでは試験は厳しいと感じました。
始めて試験を受けるのであればどんな問題がでるか確認のためAWS模擬試験を受けてみてテストのイメージを掴んでいたほうが良いと思います。
AWS模擬試験に似たような問題が教材にあればそれを中心に勉強をすれば良いですね。
- 投稿日:2019-11-15T16:47:52+09:00
AWS Elastic Beanstalkで定期処理実行(cron)
Heroku Schedulerでできたことを、Elastic Beanstalkでも行いたい
運用しているRailsアプリの本番環境を、HerokuからElastic Beanstalkに移行させました。
その際タスクの定期処理を行う方法で少し苦労したので、メモ的にシェアしておきます。以前はHeroku Schedulerでrakeコマンドを呼び出せましたが、EBでそれを行うにはEC2内でcronを使うか、ワーカー環境でPOSTメソッドを呼び出す方法があるみたいです。今回は安く済ませたいので、前者を選びました。
後者の方法はこちらが参考になります。
https://qiita.com/tomoeine/items/38a9b2123e3afa1d5cd0方法
このファイルを.ebextensionsに置くだけでOKです。あとは
eb deploy
すれば、自動でcronのファイルを作成し自動実行してくれます。
eb ssh
で/etc/cron.dを確認してみてください。.ebextensions/cron-sample.configfiles: # filesは、EC2上にファイルを作成する。パスはアプリのルートではなくLinuxのルート。 "/etc/cron.d/hello_world": mode: "000644" owner: root group: root content: | 0 4 * * * root /usr/local/bin/hello_world.sh # 指定した頻度で、↓で作成するシェルスクリプトを実行。これは毎日午前4時 "/usr/local/bin/hello_world.sh": mode: "000755" owner: root group: root content: | #!/bin/bash . /opt/elasticbeanstalk/support/envvars # アプリの環境変数読み込み cd /var/app/current /opt/rubies/ruby-2.5.7/bin/bundle exec /opt/rubies/ruby-2.5.7/bin/rake hello_world >> /var/log/hello_world.log 2>&1 # rakeコマンド打つ。例ではhello_worldというrakeメソッドをすでに定義しているとする。 # ログも出力。 exit 0 commands: remove_old_cron: command: "rm -f /etc/cron.d/hello_world.bak" # バックアップを削除参考
Linux サーバーでのソフトウェアのカスタマイズ
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/customize-containers-ec2.html#linux-filesRuby on Railsの環境構築をElastic Beanstalkで行う
https://qiita.com/yuyasat/items/4d93b4ad4f86a6e13d50#cron%E3%81%A7rails-runner%E3%82%84rake%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%92%E5%8B%95%E3%81%8B%E3%81%99
- 投稿日:2019-11-15T16:28:26+09:00
各種 PaaS FaaS 実行環境 (プログラミング言語とバージョン) まとめ (2019年11月15日現在)
概要
- 各種 PaaS FaaS で使える実行環境 (プログラミング言語とそのバージョン) をまとめる
- 公式ドキュメントも資料によってバージョン番号が明示されていなかったり異なっていることがあるので細かいバージョンについての正確さは期待できない
各種 PaaS で使える実行環境 (プログラミング言語とそのバージョン)
AWS Elastic Beanstalk Azure App Service Google App Engine .NET Core .NET Core 2.2.7, 3.0.0 .NET Core 1.0, 1.1, 2.0, 2.1, 2.2 .NET Core Go Go 1.13 なし Go 1.9, 1.10, 1.11, 1.12, 1.13 Java Java 7, 8 Java 8 Java 8, 11 Node.js Node.js 4, 5, 6, 8 Node.js 4, 6, 8, 9, 10 Node.js 10, 12 PHP PHP 7.2.19 PHP 5.6, 7.0, 7.2, 7.3 PHP 5.5, 5.6, 7.0, 7.1, 7.2 Ruby Ruby 2.4, 2.5, 2.6 Ruby 2.3, 2.4, 2.5, 2.6 Ruby 2.5 Python Python 3.6.8 Python 2.7, 3.6, 3.7 Python 2.7, 3.6, 3.7 参考資料:
- AWS Elastic Beanstalk Supported Platforms - AWS Elastic Beanstalk
- App Service on Linux の概要 - Azure | Microsoft Docs
- App Engine Standard Environment Runtimes | App Engine Documentation | Google Cloud
- App Engine Flexible Environment | Google App Engine flexible environment docs | Google Cloud
- 各種クラウド PaaS (Platform as a Service) 実行環境 (プログラミング言語とバージョン) まとめ (2019年11月15日現在) - Qiita
各種 FaaS で使える実行環境 (プログラミング言語とそのバージョン)
AWS Lambda Azure Functions Google Cloud Functions Firebase Functions .NET Core .NET Core 2.1 .NET Core 2.2, 3.x なし なし Go Go 1.x なし Go 1.11 なし Java Java 8 Java 8 なし なし Node.js Node.js 8, 10 Node.js 6, 8, 10 Node.js 8, 10 Node.js 8, 10 PHP なし なし なし なし Ruby Ruby 2.5 なし なし なし Python Python 2.7, 3.6, 3.7 Python 3.7 Python 3.7 なし 参考資料:
- AWS Lambda Runtimes - AWS Lambda
- Supported languages in Azure Functions | Microsoft Docs
- Cloud Functions Execution Environment | Cloud Functions Documentation | Google Cloud
- Manage functions deployment and runtime options | Firebase
- 各種クラウド FaaS (Function as a Service) 実行環境 (プログラミング言語とバージョン) まとめ (2019年8月22日現在) - Qiita
- 投稿日:2019-11-15T16:12:49+09:00
AWS CDKのDynamoデプロイ時に、Cannot update GSI's properties other than Provisioned Throughput. You can create a new GSI with a different name のエラーが出たときのメモ
事象
DynamoDBをCloudFormationでデプロイしているが、GSIの設定をアップデートするときに、以下のエラーが発生した。
Cannot update GSI's properties other than Provisioned Throughput. You can create a new GSI with a different name解決策
「更新」はできないので、「削除」してから「作成」する。
new dynamoDb.CfnTable(scope, '[tableName]', { tableName: tableName, attributeDefinitions: [...], keySchema: [], billingMode: ..., tags: ..., });GSI設定を除いたものをデプロイする。
new dynamoDb.CfnTable(scope, '[tableName]', { tableName: tableName, attributeDefinitions: [...], keySchema: [], globalSecondaryIndexes: [], billingMode: ..., tags: ..., });GSI設定を含めたものをデプロイする。
- 投稿日:2019-11-15T16:10:46+09:00
Laravel 6.x(またはLumen 6.x)でDynamoDBに接続する
SDKのインストール
AWS SDK for PHPをLaravelに取り込みましょう。
プロジェクトルートで下記コマンドを実行します。$ composer require aws/aws-sdk-php
これでvendor配下にSDKがインストールされます。
DynamoDBに接続する
AWS SDK for PHPでつなぐにはこのようにします。
下記の例ではクレデンシャルを含めていますが、この方法は推奨されていないので注意してください
ハードコードされた認証情報の使用use Aws\Sdk; $awsSdk = new Sdk([ 'credentials' => [ 'key' => アクセスキー, 'secret' => シークレットキー, ], 'endpoint' => 'エンドポイント', 'region' => 'リージョン', 'version' => 'バージョン' ]); $dynamo = $awsSdk->createDynamoDb();以上。
Laravelらしくしよう
と、まあこれじゃあちょっとLaravelらしくないよね、ってことでDIしてみます。new禁止。
envに登録
dotEnv便利ですよね。
.envAWS_DYNAMO_KEY=アクセスキー AWS_DYNAMO_SECRET=シークレットキー AWS_DYNAMO_ENDPOINT=エンドポイント AWS_DYNAMO_REGION=リージョン AWS_DYNAMO_VERION=バージョンServiceProviderを記述
LaravelでDIといえばServiceProviderですよね。
app/Providers/DynamoDbServiceProvider.php<?php declare(strict_types=1); namespace App\Providers; use Aws\DynamoDb\DynamoDbClient; use Aws\Sdk; use Illuminate\Support\ServiceProvider; class DynamoServiceProvider extends ServiceProvider { /** * Dynamo AWS-SDK接続 */ public function register() { $this->app->singleton(DynamoDbClient::class, function () { $awsSdk = new Sdk([ 'credentials' => [ 'key' => env('AWS_DYNAMO_KEY'), 'secret' => env('AWS_DYNAMO_SECRET'), ], 'endpoint' => env('AWS_DYNAMO_ENDPOINT'), 'region' => env('AWS_DYNAMO_REGION'), 'version' => env('AWS_DYNAMO_VERSION') ]); return $awsSdk->createDynamoDb(); }); } }Laravelなら config/app.phpのproviders に登録。
config/app.php'providers' => [ App\Providers\DynamoServiceProvider::class,Lumenならbootstrap/app.phpに登録します。
bootstrap/app.php$app->register(App\Providers\DynamoServiceProvider::class);コンストラクタインジェクション
ここまでできたら、お好きな場所でインジェクションできます。Facadeにしてもいいかもですね。
/** * @var DynamoDbClient */ private $client; /** * constructor. * @param DynamoDbClient $client */ public function __construct(DynamoDbClient $client) { $this->client = $client; }Eloquentっぽくしよう
Dynamoにアクセスするのに毎回
$this->client->putItem($paramertes);とかって書くのめんどいですよね。
普段使い慣れているEloquentやQueryBuilderっぽく、find()とかsave()とかdestory()とか使いたいです。じゃあ、EloqentModelに変わる基底クラスを作っちゃいましょう。
DynamoModelを作る
たとえばこんな感じでしょうか。
<?php declare(strict_types=1); namespace App\Models\Dynamo; use Aws\DynamoDb\DynamoDbClient; use Aws\DynamoDb\Exception\DynamoDbException; use Aws\DynamoDb\Marshaler; use Aws\Result; use Illuminate\Support\Str; /** * Class DynamoModel * @package App\Models\Dynamo */ class DynamoModel { /** * @var string */ protected $primaryKey = 'id'; /** * @var string|null */ protected $table = null; /** * @var DynamoDbClient */ private $client; /** * @var Marshaler */ private $marshaler; /** * DynamoModel constructor. * @param DynamoDbClient $client * @param Marshaler $marshaler */ public function __construct(DynamoDbClient $client, Marshaler $marshaler) { $this->client = $client; $this->marshaler = $marshaler; } /** * @return string */ public function getTable(): string { $tableName = $this->table ?? Str::snake(Str::pluralStudly(class_basename($this))); return env('APP_ENV', 'local') . '_' . $tableName; } /** * DynamoにINSERT * @param array $attributes * @return Result */ public function save(array $attributes): Result { $marshalItem = $this->marshaler->marshalItem($attributes); $dynamoParameters = [ 'TableName' => $this->getTable(), 'Item' => $marshalItem ]; try { return $this->client->putItem($dynamoParameters); } catch (DynamoDbException $exception) { throw $exception; } } /** * Dynamoからレコード削除 * @param array $ids */ public function destroy(array $ids): void { foreach ($ids as $id) { $deleteParameter = [$this->primaryKey => $id]; $marshalItem = $this->marshaler->marshalItem($deleteParameter); $dynamoParameters = [ 'TableName' => $this->getTable(), 'Key' => $marshalItem ]; try { $this->client->deleteItem($dynamoParameters); } catch (DynamoDbException $exception) { throw $exception; } } } /** * Dynamoから1件レコードを取得 * @param int $id * @return array|null */ public function find(int $id): ?array { $idParameter = [$this->primaryKey => $id]; $marshalItem = $this->marshaler->marshalItem($idParameter); $dynamoParameters = [ 'TableName' => $this->getTable(), 'Key' => $marshalItem ]; try { $awsResult = $this->client->getItem($dynamoParameters)->get('Item'); if (is_null($awsResult)) { return null; } return $this->marshaler->unmarshalItem($awsResult); } catch (DynamoDbException $exception) { throw $exception; } } }あとはこれを継承したModelをつかえば、EloquentみたいにDynamoにアクセスできるようになります。
必要に応じで、findOrFail()でもupdateOrCreate()でもはやしていけばいいのかなーと思います。
- 投稿日:2019-11-15T14:56:48+09:00
ElasticBeanstalkにアップロードするファイルを.gitignoreとは別に.ebignoreで指定する
ElasticBeanstalkでは
eb deploy [環境名]とすると実行したディレクトリの.gitignoreを元にプロダクトコードがzipされS3にアップロードされてebの環境に上がります。
CircleCIなどのCIツールを使っていると.gitignoreで除外したい部分とアップロードしたい部分がずれてきて別々になってきます。
そういったときは
.ebignore
というファイルを使って指定することができます。記法は.gitignoreと同じです。
- 投稿日:2019-11-15T14:39:00+09:00
Session Manager で SSH/SCP をトンネリングして EC2 接続
今更ながらこれやってみる
セッションマネージャーが SSH と SCP のトンネリングサポートを開始
これができることで
セキュリティグループで SSH 22番ポートを開ける必要がなくなり、踏み台も不要、 EIP も不要になるので、コスト削減につながりますよね。
前提
今回の手順は Client: Mac, Server: Amazon Linux 2 で実施する場合。
Client
- awscli 1.16.12 以上
- Session Manager Plugin 1.1.23.0 以上
- Session Manager のエンドユーザーポリシー権限を持った IAM User
Server
- ssm agent 2.3.672.0以上
AmazonEC2RoleforSSM
の IAM Role がインスタンスにアタッチされていることClient の設定
awscli
適宜、前提バージョンの awscli をインストール/アップデートする。
Session Manager Plugin
バージョン確認
$ session-manager-plugin --versionインストール/アップデート
curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip" unzip sessionmanager-bundle.zip sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin(オプション) AWS CLI 用の Session Manager Plugin をインストールする
SSH ファイルの設定
適当に名前つけて設定入れる。
~/.ssh/configHost matsu-test Hostname i-XXXXXXXXXXXX User ec2-user IdentityFile ~/.ssh/matsu-test.pem ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"Server の設定
SSM エージェントをインストールする
SSM エージェント プリインストールされた AMI
SSM エージェント は、次の Amazon マシンイメージ (AMI) にデフォルトで事前インストールされています。とのこと。
- 2016 年 11 月以降に公開された Windows Server 2003-2012 R2 AMI
- Windows Server 2016 および 2019
- Amazon Linux
- Amazon Linux 2
- Ubuntu Server 16.04
- Ubuntu Server 18.04
手動でインストールするなら
ssm-agent がインストール可能な下記の Linux OS
- Amazon Linux および Amazon Linux 2
- Ubuntu Server
- Red Hat Enterprise Linux (RHEL)
- CentOS
- SUSE Linux Enterprise Server (SLES) 12
- Raspbian
Amazon EC2 Linux インスタンスに SSM エージェント を手動でインストールする
SSM エージェントをアップデートする
バージョン確認
$ rpm -qi amazon-ssm-agent起動時にインターネットにアクセスできるインスタンスなら
userdata に入れちゃう。
userdata#!/bin/bash yum update -y yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm手動でアップデートするならこれだけ。
$ yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpmセキュリティグループ
SSH 22番ポートを開けなくて良い。
SSH してみる
$ ssh matsu-test The authenticity of host 'i-06a06ac4cebcc5301 (<no hostip for proxy command>)' can't be established. ECDSA key fingerprint is SHA256:3ZAr+OF/DACbhOWrOUxzjmwM/OFOhTQHUwxAAwVbDaI. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'i-06a06ac4cebcc5301' (ECDSA) to the list of known hosts. __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ [ec2-user@ip-10-4-2-202 ~]$SCP でファイル転送
普通にできる。
$ scp test.txt matsu-test:~/ test.txt 100% 0 0.0KB/s 00:00 $ ssh matsu-test Last login: Fri Nov 15 02:40:28 2019 from localhost __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ $ ll 合計 0 -rw-r--r-- 1 ec2-user ec2-user 0 11月 15 02:46 test.txtPostgreSQL にポートフォワード
RDS PostgreSQL に対してポートフォワードし、ローカル環境から PostgreSQL に接続してみる。
RDS エンドポイントの 5432 ポートを ローカルの 9999 ポートに向ける。
$ ssh matsu-test -L 9999:matsuki-postgre.XXXXXXXXX.ap-northeast-1.rds.amazonaws.com:5432ローカル環境から PostgreSQL に接続してみる。
$ psql -h 127.0.0.1 -p 9999 -U postgres Password for user postgres: psql (11.5) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. postgres=>OK
Private なインスタンスの場合
Private Subnet に配置されたインスタンスはインターネット接続できないため、 Session Manager を利用できないが、 NAT GW を作成することで、インターネット向けの通信を通すことができるのでこれでいける。
NAT GWがなくても VPC エンドポイントがあればいける
VPC の設定確認
VPC の
DNS 解決
およびDNS ホスト名
を有効化する。VPC エンドポイントを作成
以下を作成。
- com.amazonaws.ap-northeast-1.ssm
- com.amazonaws.ap-northeast-1.ssmmessages
- com.amazonaws.ap-northeast-1.ec2messages
セキュリティグループ設定
インスタンスから VPC エンドポイントの SG への https (443) アクセスを許可する。
※VPC エンドポイントの SG をインスタンスと同じ SG で作成していれば、該当 SG 自身を全て許可するように設定すれば良い。
- 投稿日:2019-11-15T14:35:02+09:00
ELB切り替え時の動作確認 (hostsファイルを編集する)
これはなんですか
- DNSのレコード登録が済んでないALBに対してリスナールールの動作確認をした時のメモです
- hostファイルを編集して名前解決する方法です。
先にまとめ
- hostsファイルはローカルで名前解決するためのもの
- macOSのhostsファイルは
/private/etc/hosts
にある- Windowsの場合は
C:\Windows\System32\drivers\etc\hosts
にある- DNSレコード登録前にLBの動作確認がしたければ、hostsファイルにLBのIPと対象のHostを書いて名前解決の動作をエミュレートすればよい
- HTTP接続するだけなら
curl -H 'Host:example.com' 'http://xxx................'
とした方が楽だが、HTTPS接続がしたければhostsを使う必要があるhosts ファイルとは
ローカルで名前を解決してくれるやつです。以下ざっくり説明です。
https://wa3.i-3-i.info/word16969.htmlmac環境のhostsファイルの置き場所は
/private/etc/hosts
にあります。Windows環境のhostsファイルの置き場所は
C:\Windows\System32\drivers\etc\hosts
にあります。
http://onocom.net/blog/windows-hosts-file/#hostsWindowsやってみた
ALB の準備
- (主にACMで) 証明書発行
- ALB作成
- ALBデフォルトのDNS名(Aレコード)を控えておく
- ターゲットグループ作成&配下のターゲットへの紐づけ
- リスナールール 設定
- 証明書をリスナーに紐づけておく
デフォルトのDNS Nameにクエリする
ALBのIPを確認する
$ dig example-xxxxxxxxxxx.ap-northeast-1.elb.amazonaws.com +short 54.250.192.xx 52.196.88.yyy
hosts ファイルを編集する
$ cat /private/etc/hosts ## # Host Database # # localhost is used to configure the loopback interface # when the system is booting. Do not change this entry. ## 127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost ### (略) ### ALBのIPを登録 52.196.88.yyy example.comcurl する
IPがALBに向いていることを確認する
$ curl -I https://example.com/healthcheck.html -v * Trying 52.196.88.yyy... * TCP_NODELAY set * Connected to emd-dev.watashi-move.com (52.196.88.yyy) port 443 (#0) ... < HTTP/1.1 200 OK HTTP/1.1 200 OK < Date: Mon, 07 Oct 2019 06:23:58 GMT Date: Mon, 07 Oct 2019 06:23:58 GMT ...ALBログを確認する
ログが残っていればok。
余談: digはシステムのDNSリゾルバを使わない
hostsを編集した後digしてもhostsに書いた内容が反映されなかったので調べたらこんな記事が。
https://qiita.com/kakipo/items/71f091ecd1fa27fde2eddig, nslookup, そして host コマンドは /etc/hosts を参照しない。
- 投稿日:2019-11-15T14:31:50+09:00
aws cloud9 ruby on rails migration 後にしたこと
まずは
bundle install
mysql が動かない。
sudo apt-get install libmysqlclient-dev
して mysql を入れる- bundle installを再実行.. ok
- c9 の 設定のままだと、 root@local.host につながらない、とかなった。
- db に root接続して、user を作り (user をつくるところは、https://www.lucidar.me/en/aws-cloud9/install-mysql-and-phpmyadmin-on-aws-cloud9/ を参考にした)
- その情報をもとに database.yml を設定変更
username: <%=ENV['C9_USER']%> # password: <%=ENV['C9_USER']%>もともとこんな感じになってたので、設定変更。
これで、 rails db:create, db:migrate ... okrails server を動かす IP とか若干違った
before
rails server -b $IP -p $PORT
after
rails s -b 0.0.0.0
app が error 出す
ruby の version が 変わってた。gem とか 大幅アップデートとか嫌だったので、昔のsetupでいく方針 (live app だったので)
lvm list
で状況確認して
rvm install 2.3
した (live 環境 2.3.x だったので)
rvm default 2.3.X
この状態で も一度rails s -b 0.0.0.0
...ok
- 投稿日:2019-11-15T13:46:19+09:00
AWS DynamoDBをjsでいじるときに非同期処理で詰まった話
AWS DynamoDBをjsでいじるときに非同期処理で詰まった話
初めに
このお話は、単に私がJavaScriptの非同期処理を理解していなかっただけなので、プロの皆さんでしたら余裕で回避できる問題だと思います。
私みたいな初学者で、同じようなことに詰まっている方がこの記事を見て解決していただけたら幸いです。
私がやりたかったこと
DynamoDBのCRUD操作を関数内で行い、実行結果を戻り値として受け取る といったことをしたかったのですが、戻り値に値が入っていない状態で返されてしまいました。
// 問題のあるコード function getHoge(){ let hoge; let params = { TableName: 'table', Key:{ "id": "01" } }; documentClient.put(params, function(err, data){ if(err){ console.log(err); }else { console.log(data); // {} hoge = data; } }); return hoge; } exports.handler = function (event) { let hoge = getHoge(); console.log(hoge); // undifind }PHPのようなノリで書いてしまったため、undifindの原因がわからずに悩みまくってましたが、ようやっと非同期処理のせいだ!って気づいたため、以下のように書き直しました
書き直した
// ちゃんと動くやつ async function getUser() { let hoge; let params = { TableName: 'table', Key:{ "id": "01" } }; try { // hogeにデータが入るまで待つ hoge = await documentClient.get(params).promise(); } catch (e) { console.log(e); } return hoge; } exports.handler = async (event) => { let hoge = await getUser(); console.log(hoge); // {jsonデータが見れる!} };はい、解決。
公式ドキュメントを見てみると、、、
DynamoDB DocumentClient get-propaty
var params = { TableName : 'Table', Key: { HashKey: 'hashkey' } }; var documentClient = new AWS.DynamoDB.DocumentClient(); documentClient.get(params, function(err, data) { if (err) console.log(err); else console.log(data); });コールバックで書かれてるので、JS初心者には自力での解決キツイっす。。。
最後に言いたいこと
非同期むづかしい
- 投稿日:2019-11-15T11:30:46+09:00
別のAWSアカウントのSNSに通知を飛ばす方法
背景・やりたいこと
何かある度に(例えば、ヘルスチェックのエラーだったり、負荷が高くなったり、オートスケールが走ったり)
管理用のメールアドレスに通知を飛ばしたかったりする。
もちろんそういう場合はCloudWatchなどで監視して、SNSに通知を飛ばし、そこからメールを飛ばす構成が一般である。SNSにアクセスして、新しくトピックを作成し、更にそこに新しいサブスクリプションを追加し、
送信したいメールアドレスを追加して、認証メールを受け取って承認すれば、
このトピックあての通知は設定したメールに通知されるようになる。
後はCloudWatchのアラームが上がったときなどにこのトピックあてに通してあげればよいわけだ。
しかし、アカウントがひとつの場合は、ここまでの設定でやりたいことが解決するのだが
AWSアカウントを様々な事情で複数持っていると、特に2桁を超えてくると厄介である。
例えばメール通知したいアドレスが変わったり、増えたりしたら、すべてのアカウントに入って
その都度設定しなおさなければならない。
しかも受け取り側に、認証メールが何十通も届くことになる。
そこで、1つのAWSアカウントを代表アカウントとして、
その中で構築したSNSに対して、他のアカウントの通知を送り付けたくなる。
ということで、そんなことができるよう設定してみる。
設定方法
トピックをAWSマネジメントコンソールにて新規作成する場合、
トピックお作成 > アクセスポリシー - オプション
より
設定項目 選択する値 メソッドの選択 基本 トピックにメッセージを発行できるユーザーを定義します 全員 このトピックにサブスクライブできるユーザーを定義します トピック所有者のみ とすることで、他のAWSアカウントから通知を受け取れるようになる。
既存のトピックを共有したい場合は、アクセスポリシーを直接いじることになる。
初期のなにもいじっていないポリシーの場合"Statement":[ {"Sid": "__default_statement_ID", "Effect": "Allow", ... }, ]という値が入っているはずなので、このリストに以下の内容を追加する。
{ "Sid": "__console_pub_0", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "SNS:Publish", "Resource": "arn:aws:sns:<<使用リージョン名>>:<<AWSアカウントID>>:<<SNS名>>" }※<<使用リージョン名>> <<AWSアカウントID>> <<SNS名>>は適宜値を入れ替えてください
セキュリティ的にすべてのAWSアカウントより通知を受け取るのがまずいという場合は{ "AWS": "*" }を
{ "AWS": [ "111111111111", "22222222222222", ... , "777777777777" ] }の様に書き換えると、リストに指定したAWSアカウント以外からの通知をはじくようになる。
後は他のAWSアカウントで、上記で設定したSNSを通知する先に設定してあげればよい。
設定する場合はARNを用いることになるので、確認をしておこう。まとめ
想像以上に簡単に設定できました。
boto3でCloudwatchのアラームを自動生成する(後日執筆予定)時に指定するSNSとしても最適ですね。
- 投稿日:2019-11-15T10:47:23+09:00
AWS ACM で com.amazon.coral.service.InternalFailure エラーが出る
ACM で証明書のリクエストを行ったら、
com.amazon.coral.service.InternalFailure
エラーが表示された。実行していた IAM ユーザは、AdministratorAccess ポリシーと下記のように
NotIpAddress
による IP 制限ポリシーをアタッチしていた。https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_aws_deny-ip.html
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": "*", "Resource": "*", "Condition": { "NotIpAddress": { "aws:SourceIp": [ "xxx.xxx.xxx.xxx/32" ] } } } ] }一旦、この IP 制限をかけていたポリシーを外すと正常に動作した。
ACM 設定が終わってから、IP 制限を戻す予定。
- 投稿日:2019-11-15T10:19:49+09:00
AWS IoT エラー AMQJS0008I Socket closed
- 投稿日:2019-11-15T10:08:09+09:00
Amazon RDS for MySQL でスナップショットから復元したDBにアクセスする
某案件で Amazon RDS for MySQL を利用しています。
追加開発で既存テーブルにカラム追加をしてAPIを新設してほしいという作業依頼がきました。追加対象のテーブルの現在のレコード数を聞くと、7桁レベルのレコードがあるようです。
そこへ ALTER TABLE 〜 を流すと、どのくらい時間がかかるのだろうか? リリース時、本番環境で流せるレベルだろうか?ふと気になったので先輩に相談し、スナップショットからデータベースを復元し、検証用のデータベースを作成して試してみることにしました。
スナップショットは毎晩深夜に自動取得されているものを使います。Amazon RDS > スナップショット で表示される一覧から、復元したいスナップショットを選択して 「スナップショットから復元」を選択します。
データベース名の入力が必須、インスタンスタイプがデフォルトで本番環境と異なったものが選択されていたので、選択し直しました。
これは本番環境のインスタンスタイプが "旧世代のインスタンスタイプ" という扱いになってしまったからかもしれません。それと念の為、本番環境とは別のVPCを選択して起動することにしました。
最後に 「DBインスタンスの復元」 ボタンを押して数分待つと復元されたデータベースを使えるようになります。
さて、どうやって接続してSQLを流そうか?
データベースを復元した先と同じVPCにEC2インスタンスを1つ立てました。これをSSHの踏み台サーバーとして使います。
RDSについているセキュリティーグループでEC2インスタンスのIPから MySQL/Auroraのアクセスを許可する設定を追加しました。さてこれで接続できるはず・・・!
MySQLクライアントとして、TablePlus というアプリを使います
https://tableplus.com/ここで気がつきました、DB復元時にユーザー名やパスワードの設定が何もしていません。
「RDS 復元 パスワード」 いろいろググった結果、これだという情報にたどり着けませんでした。もしや元のデータベースと同じ情報ではないか・・・と試してみると無事接続できました!
大事なことなのでもう一度、
スナップショットから復元したデータベースは、元のデータベースと同じユーザ名・パスワード を使ってアクセスできます。
結果
TablePlusから目的の SQL文を流して、おおよその実行時間が判明しました。
結果、数十秒 という単位で終わることがわかり、先輩に報告です。このくらいであれば、無理な負荷ではない、ただしリリース時はメンテナンス状態にしてアクセスをなくした状態で行うのが良さそう
といった相談をしました。負荷が気になったときは、実際に同等の環境を作って動かして検証するのが確実ですね。
そんな話を、別な先輩が書いた Amazon Web Services負荷試験入門 っていう本で読んだことを思い出しました。最後に
検証用に立てたデータベースインスタンスはそれなりのサイズなので、料金もそれなりにかかってきます。
検証が終わったあとは忘れずに削除しましょう。EC2インスタンスも忘れずに。
- 投稿日:2019-11-15T09:51:25+09:00
CloudFormation Resource Importで、実体と違うテンプレートを使うとどうなるのか
概要
CloudFormationに待望のリソースインポート機能がリリース1
使い方は、例によってクラメソさんが記事化しているので2、気になったところを追加で確認する。気になっていること
対象のリソースが存在していなければならない、などいくつかの必須条件はドキュメントにも記載済み3。
では、インポートするリソースと、違うパラメータ設定のテンプレートを使うとどうなるのか。置換されたり、上書きされたりする?実験
対象はS3 Bucket:
hogehoge-fugafuga-poyopoyo
全てデフォルト設定。テストその1:ユニークキーとなるBucketNameが違うテンプレート
取り込むバケット名とBucketNameが異なる。
AWSTemplateFormatVersion: '2010-09-09' Resources: S3Bucket: Type: 'AWS::S3::Bucket' DeletionPolicy: 'Retain' Properties: BucketName: 'piyopiyo-foo-bar'失敗。
テストその2:デフォルト値と異なるテンプレート
バージョニングはデフォルトで無効。
AWSTemplateFormatVersion: '2010-09-09' Resources: S3Bucket: Type: 'AWS::S3::Bucket' DeletionPolicy: 'Retain' Properties: BucketName: 'hogehoge-fugafuga-poyopoyo' VersioningConfiguration: Status: 'Enabled'インポートは成功。バージョニングは無効化のまま。
どうやら、反映はされないよう。
その後、テンプレート側をDisabled / Enabledと変更しつつ反映したところちゃんと更新された。まとめ
リソースインポートによって既存リソースが取り込めるようになってとても便利になった。
取り込みと設定更新は同時に行われないようなので、
1. 必須項目だけを記述したテンプレートで取り込み
2. 任意項目を追加の方が安全そう。
- 投稿日:2019-11-15T09:10:45+09:00
クラウド開発環境構築(メモ)
はじめに
本記事は、「Webサービス開発のため」の仮想マシン構築(AWS)~クラウド開発環境構築(Cloud9)までの手順を自分用にまとめたものです。
前提条件
- クライアントはWindows環境
- クラウドはAWS利用(AWSアカウント作成済み)
- AWSの基礎知識有
基礎知識が足りない場合
@Futo23
さんの記事が大変参考になりましたのでそちらを参照してください。手順
仮想マシン構築
管理コンソールサイトへアクセス
( マネージメントコンソール)
管理コンソールへログイン
テンプレートから仮想マシンを作成
- 「ソリューション構築」>「仮想マシンを起動する」を選択
- 「Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type」を選択
- 「確認と作成」を選択
- 「新しいキーペア名」を入力して「キーペアのダウンロード」を選択
- 「インスタンスの作成」を選択
インターネット利用のためのIPアドレス割当
- 「サービス」>「EC2」を選択
- 「ネットワーク&セキュリティ」>「Elstatic IP」を選択
- 「新しいアドレスの割当」を選択
- 「IPv4 アドレスプール」を「Amazonプール」に設定(デフォルト)
- 「割り当て」を選択
- 「閉じる」を選択
- 「アクション」>「アドレスの関連付け」を選択
- 対象の「インスタンス」と「プライベートIPアドレス」を設定して「関連付け」を選択
- 「閉じる」を選択
アクセス制限
- 「ネットワーク&セキュリティ」>「セキュリティグループ」を選択
- 仮想マシンと関連付けられている「セキュリティグループ」を選択して「アクション」>「インバウンドのルールの編集」を選択
- 「ルール追加」を選択
- 「カスタムTCP」を「HTTP」へ変更して「保存」を選択
- 「ルール追加」を選択
- 「カスタムTCP」の「ポート」に「20022」を入力して「保存」を選択
SSH接続確認
- ターミナルソフト起動(TeraTerm、Putty等)
- SSH接続:
「Elastatic IP」、「新しいキーペア」
を指定- 結果確認
IAM設定
- 「サービス」>「IAM」を選択
- 「ダッシュボード」>「ユーザー」を選択
- 「ユーザーを追加」を選択
- 「ユーザー名」の入力と「プログラムによるアクセス」にチェックを入れて「次のステップ:アクセス権限」を選択
- 「既存のポリシーを直接アタッチ」を選択
- 「AdministratorAccess」にチェックを入れて「次のステップ:タグ」を選択
- 「キー名」を入力して「次のステップ:確認」を選択
- 「ユーザーの作成」を選択
- 「アクセスキーID」「シークレットアクセスキー」をメモに控える
仮想マシン起動後の初期設定
ソフトウェアの最新化
$ sudo yum update -yタイムゾーンの変更(日本時間)
$ sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtimeタイムゾーンの結果を確認(UTC→JST)。
$ date Tue Nov 12 13:23:56 JST 2019再起動後も日本時間にする。
/etc/sysconfig/clockファイルの修正$ vim /etc/sysconfig/clock 【変更前】 ZONE="UTC" UTC=true 【変更後】 ZONE="Asia/Tokyo" UTC=false 【注意事項:読取り専用のため強制的に保存する】 :w !sudo tee % :q!日本語環境へ変更
/etc/sysconfig/i18nファイルの修正$ sudo sh -c "echo 'LANG=ja_JP.UTF-8' > /etc/sysconfig/i18n" $ sudo yum install -y man-pages-ja 【日本語表示反映の為、一旦再起動】 $ sudo shutdown -r now
root
のパスワード設定(セキュリティ強化)$ sudo su - $ passwd ユーザー root のパスワードを変更。 新しいパスワード: 新しいパスワードを再入力してください: passwd: すべての認証トークンが正しく更新できました。
ec2-user(デフォルト)
の代替ユーザー作成(セキュリティ強化)ユーザー作成# useradd -g wheel ユーザー名sudo権限付与# echo 'ユーザー名 ALL = NOPASSWD: ALL' >> /etc/sudoers.d/cloud-init 【注意事項】 「NOPASSWD」設定により、sudo実行時にパスワード入力が不要となります。 セキュリティ上のリスクがあるのでお気を付けください。authorized_keysのコピーとパーミッション設定# rsync -a ~ec2-user/.ssh/authorized_keys ~ユーザー名/.ssh/ # chown -R ユーザー名:wheel ~ユーザー名/.ssh # chmod -R go-rwx ~ユーザー名/.ssh新しいユーザーで
sshログイン
とsudo権限
が利用できる事を確認したら削除します。sudo動作確認$ sudo -sec2-user削除$ sudo userdel ec2-user不要コンソール起動を無効化(サーバー資源節約)
/etc/sysconfig/initファイルの修正# vim /etc/sysconfig/init 【変更前】 ACTIVE_CONSOLES=/dev/tty[1-6] 【変更後】 ACTIVE_CONSOLES=/dev/tty1SSHのデフォルトポート変更(セキュリティ強化)
/etc/ssh/sshd_configファイルの修正$ sudo vim /etc/ssh/sshd_config 【追加】 Port 22 Port 22022設定ファイル再読み込み$ sudo service sshd reload sshd を再読み込み中: [ OK ]20022ポートの確認$ sudo netstat -anp | grep sshd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 15543/sshd tcp 0 0 0.0.0.0:20022 0.0.0.0:* LISTEN 15543/sshdAWSコマンド利用準備
インストール確認$ aws --version aws-cli/1.16.102 Python/2.7.16 Linux/4.14.146-93.123.amzn1.x86_64 botocore/1.12.92アクセスキー等の設定$ aws configure AWS Access Key ID [None]: XXXXXXXXXXXX AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXX Default region name [None]: ap-northeast-1 Default output format [None]: jsonAWS Access Key ID [None]:アクセスキーID
AWS Secret Access Key [None]: シークレットアクセスキー
Default region name [None]: Tokyoリージョン(ap-northeast-1)
Default output format [None]: "text","json","table"のどれかを指定アクセスキー等の設定$ aws ec2 describe-instance-status { "InstanceStatuses": [ { "InstanceId": "i-0c7f2cff2082514c9", "InstanceState": { "Code": 16, "Name": "running" }, "AvailabilityZone": "ap-northeast-1a", "SystemStatus": { "Status": "ok", "Details": [ { "Status": "passed", "Name": "reachability" } ] }, "InstanceStatus": { "Status": "ok", "Details": [ { "Status": "passed", "Name": "reachability" } ] } } ] }Cloud9用の環境インストール(Python、Node.js)
pythonインストール状況確認$ python --version Python 2.7.16node.jsインストール状況確認$ node -v -bash: node: command not foundnode.jsインストール下準備$ sudo yum -y install gcc-c++ git 【メッセージ省略】 Installed: gcc-c++.noarch 0:4.8.5-1.22.amzn1 git.x86_64 0:2.14.5-1.60.amzn1 Dependency Installed: cpp48.x86_64 0:4.8.5-28.142.amzn1 gcc.noarch 0:4.8.5-1.22.amzn1 gcc48.x86_64 0:4.8.5-28.142.amzn1 gcc48-c++.x86_64 0:4.8.5-28.142.amzn1 glibc-devel.x86_64 0:2.17-260.175.amzn1 glibc-headers.x86_64 0:2.17-260.175.amzn1 kernel-headers.x86_64 0:4.14.146-93.123.amzn1 libgcc48.x86_64 0:4.8.5-28.142.amzn1 libgomp.x86_64 0:6.4.1-1.45.amzn1 libmpc.x86_64 0:1.0.1-3.3.amzn1 libstdc++48.x86_64 0:4.8.5-28.142.amzn1 mpfr.x86_64 0:3.1.1-4.14.amzn1 perl-Error.noarch 1:0.17020-2.9.amzn1 perl-Git.noarch 0:2.14.5-1.60.amzn1 perl-TermReadKey.x86_64 0:2.30-20.9.amzn1 Complete!nvmダウンロード$ git clone https://github.com/creationix/nvm.git ~/.nvm remote: Enumerating objects: 24, done. remote: Counting objects: 100% (24/24), done. remote: Compressing objects: 100% (20/20), done. remote: Total 7573 (delta 7), reused 16 (delta 4), pack-reused 7549 Receiving objects: 100% (7573/7573), 2.51 MiB | 2.56 MiB/s, done. Resolving deltas: 100% (4779/4779), done.nvmへのパス設定$ source ~/.nvm/nvm.shnvmコマンドへのパス設定$ vim ~/.bash_profile 【追記】 # nvm if [[ -s ~/.nvm/nvm.sh ]] ; then source ~/.nvm/nvm.sh ; fiNode.jsインストール$ nvm install node Downloading and installing node v13.1.0... Downloading https://nodejs.org/dist/v13.1.0/node-v13.1.0-linux-x64.tar.xz... ######################################################################### 100.0% Computing checksum with sha256sum Checksums matched! Now using node v13.1.0 (npm v6.12.1) Creating default alias: default -> node (-> v13.1.0)Node.jsのバージョン確認$ node -v v13.1.0Node.jsの使用バージョン指定$ nvm use v13.1.0 Now using node v13.1.0 (npm v6.12.1)Node.jsのバイナリパス控え$ which node ~/.nvm/versions/node/v13.1.0/bin/nodecloud9用のルートディレクトリ作成$ mkdir ~/cloud9クラウド開発環境構築(Cloud9)
AWS Cloud9
- 「サービス」>「Cloud9」を選択
- 「Create environment」を選択
- 「Name」を入力して「Next Step」を選択
「Environment type」を「Connect and run in remote server (SSH)」に変更して下記を入力して「Next Step」を選択
入力項目名 説明 User SSH接続ユーザー名 Host EC2のグローバルIPアドレス Port 20022 Environment path - Optional ~/cloud9 Node.js binary path - Optional ~/.nvm/versions/node/v13.1.0/bin/node AWSの仮想マシンにログイン
「Copy key to clipboard」を選択(クリップボードへコピー)
公開鍵の登録
キーファイルへの追記$ vim ~.ssh/authorized_keys 【追記内容例:クリップボードの内容】 ssh-rsa AAAAB3NzaC1yc2EAAAADAQA(省略)XXXXXXXXXXXX== XXXXXXXX@cloud9.amazon.com「Next step」を選択
「Create Environment」を選択
「Next」を選択
「Next」を選択
「y」を入力して「Enter」実行
「Next」を選択
- 投稿日:2019-11-15T09:03:15+09:00
gsutil、aws s3での基本的なファイル操作(Google Cloud Storage、S3)
aws s3
コマンドはS3しか操作できませんが、Google Cloud Storage(GCS)のCLIであるgsutil
コマンドはGCSだけでなくS3に対しても同じように操作できます。ファイルのアップロード(ローカルからクラウド)
$ gsutil cp dir/foo.txt gs://xxx-bucket/dir/ $ gsutil cp dir/foo.txt s3://yyy-bucket/dir/ $ aws s3 cp dir/foo.txt s3://yyy-bucket/dir/※
g3://xxx-bucket/dir/foo.txt
またはs3://yyy-bucket/dir/foo.txt
にファイルができますローカルでのパイプからのアップロード
$ cat dir/foo.txt | gsutil cp - gs://xxx-bucket/dir/foo.txt $ cat dir/foo.txt | gsutil cp - s3://yyy-bucket/dir/foo.txt $ cat dir/foo.txt | aws s3 cp - s3://yyy-bucket/dir/foo.txt※Google Cloud Storage上でContent-Typeがapplication/octed-streamになってしまう
※コピー先はファイル名まで指定が必要
gsutil cp
やaws s3 cp
の-
は標準入力の意味です。いずれの方法でもアップロード先に指定のディレクトリがない場合は自動で作られるかのように振る舞います。
正確にはGoogle Cloud StorageもS3もオブジェクトストレージで、ファイルシステムとは異なり、ディレクトリもしくはフォルダの概念は本来はありません。以下の記事がわかりやすいです。
Amazon S3における「フォルダ」という幻想をぶち壊し、その実体を明らかにする | Developers.IO
Google Cloud StorageのファイルのContent-Typeを変更するには以下のようにします。
$ gsutil setmeta -h "Content-Type:text/plain" gs://xxx-bucket/dir/foo.txt※
-h
オプションはgsのファイルパスよりも先に指定する必要ありコピー時にContent-Typeを指定するには以下のようにします。
$ cat dir/foo.txt | gsutil -h "Content-Type:text/plain" cp - gs://xxx-bucket/dir/foo.txt※
-h
オプションはcp
よりも前に指定する必要ありファイルの一覧表示(ローカルおよびクラウド)
$ ls -l dir/ $ gsutil ls -l gs://xxx-bucket/dir/ $ gsutil ls -l s3://yyy-bucket/dir/ $ aws s3 ls s3://yyy-bucket/dir/※
aws s3
コマンドには-l
オプションがありません参考
gsutil ls
はS3にも対応している件
Google Cloud StorageとAWS S3との間でファイルをコピーするにはファイルの表示(ローカルおよびクラウド)
プレーンテキストのファイルをターミナル上に表示する方法です。ローカルのファイルに対する
cat
コマンドに相当するものです。$ cat dir/foo.txt $ gsutil cp gs://xxx-bucket/dir/foo.txt - $ gsutil cp s3://yyy-bucket/dir/foo.txt - $ aws s3 cp s3://yyy-bucket/dir/foo.txt -
gsutil cp
やaws s3 cp
の-
は標準出力の意味です。ファイルのダウンロード(クラウドからローカル)
$ gsutil cp gs://xxx-bucket/dir/foo.txt dir/ $ gsutil cp s3://yyy-bucket/dir/foo.txt dir/ $ aws s3 cp s3://yyy-bucket/dir/foo.txt dir/ファイル名の変更(ローカルおよびクラウド)
$ mv dir/foo.txt dir/bar.txt $ gsutil mv dir/foo.txt dir/bar.txt $ gsutil mv gs://xxx-bucket/dir/foo.txt gs://xxx-bucket/dir/bar.txt $ gsutil mv s3://yyy-bucket/dir/foo.txt s3://yyy-bucket/dir/bar.txt $ aws s3 mv s3://yyy-bucket/dir/foo.txt s3://yyy-bucket/dir/bar.txt
gsutil mv
はGoogle Cloud Storage(GCS)だけでなくS3やローカルのファイルの名前も変更できます。また、
gsutil mv
はローカルからGCS、GCSからローカル、GCSの異なるバケット間、ローカルからS3、S3からローカル、S3の異なるバケット間、GCSからS3、S3からGCSの移動もできます。
aws s3 mv
はローカルからS3、S3からローカル、S3の異なるバケット間の移動もできます。ファイルの削除(ローカルおよびクラウド)
$ rm dir/foo.txt $ gsutil rm gs://xxx-bucket/dir/foo.txt $ gsutil rm s3://yyy-bucket/dir/foo.txt $ aws s3 rm s3://yyy-bucket/dir/foo.txtGoogle Cloud StorageもS3もファイルシステムではなくオブジェクトストレージなので、
dir/foo.txt
を削除した結果、dir
の中に1つもオブジェクトがなくなればdir
自体も自動で削除されるかのように振る舞います。ディレクトリの容量確認(ローカルおよびクラウド)
$ du -sh dir/ $ gsutil du -sh gs://xxx-bucket/dir/ $ gsutil du -sh s3://yyy-bucket/dir/ $ aws s3 ls --human --recursive --sum s3://yyy-bucket/dir/
- 投稿日:2019-11-15T09:00:16+09:00
Amazon CloudWatch LogsのログをAWS CLIでいい感じに取得する
Amazon CloudWatch LogsにあるログをAWS CLIでいい感じに取得する方法を毎回忘れている気がするのでメモ。
コマンド
とある環境でUnixBenchを走らせた際のログがあったのでそれを取得してみました。
ポイントは--query "events[].[message]"
でログだけを抽出して、--output text
でテキスト形式にします。> aws logs get-log-events \ --log-group-name <ロググループ名> \ --log-stream-name <ストリーム名> \ --query "events[].[message]" \ --output text # # # # # # # ##### ###### # # #### # # # # ## # # # # # # # ## # # # # # # # # # # # ## ##### ##### # # # # ###### # # # # # # ## # # # # # # # # # # # # ## # # # # # # # ## # # # # #### # # # # # ##### ###### # # #### # # Version 5.1.3 Based on the Byte Magazine Unix Benchmark Multi-CPU version Version 5 revisions by Ian Smith, Sunnyvale, CA, USA January 13, 2011 johantheghost at yahoo period com 1 x Dhrystone 2 using register variables 1 2 3 4 5 6 7 8 9 10 1 x Double-Precision Whetstone 1 2 3 4 5 6 7 8 9 10 1 x Execl Throughput 1 2 3 1 x File Copy 1024 bufsize 2000 maxblocks 1 2 3 1 x File Copy 256 bufsize 500 maxblocks 1 2 3 1 x File Copy 4096 bufsize 8000 maxblocks 1 2 3 1 x Pipe Throughput 1 2 3 4 5 6 7 8 9 10 1 x Pipe-based Context Switching 1 2 3 4 5 6 7 8 9 10 1 x Process Creation 1 2 3 1 x System Call Overhead 1 2 3 4 5 6 7 8 9 10 1 x Shell Scripts (1 concurrent) 1 2 3 1 x Shell Scripts (8 concurrent) 1 2 3 2 x Dhrystone 2 using register variables 1 2 3 4 5 6 7 8 9 10 2 x Double-Precision Whetstone 1 2 3 4 5 6 7 8 9 10 2 x Execl Throughput 1 2 3 2 x File Copy 1024 bufsize 2000 maxblocks 1 2 3 2 x File Copy 256 bufsize 500 maxblocks 1 2 3 2 x File Copy 4096 bufsize 8000 maxblocks 1 2 3 2 x Pipe Throughput 1 2 3 4 5 6 7 8 9 10 2 x Pipe-based Context Switching 1 2 3 4 5 6 7 8 9 10 2 x Process Creation 1 2 3 2 x System Call Overhead 1 2 3 4 5 6 7 8 9 10 2 x Shell Scripts (1 concurrent) 1 2 3 2 x Shell Scripts (8 concurrent) 1 2 3いい感じじゃない例
オプション指定なし
JSON形式で、ログメッセージ以外の項目があります。また
nextForwardToken
、nextBackwardToken
でページングしつつ取得することになります。
ローカルの`jq`コマンドを使って加工するならこの状態でも良いかもです。> aws logs get-log-events \ --log-group-name <ロググループ名> \ --log-stream-name <ストリーム名> { "nextForwardToken": "f/35067999245249879332392031329876277123727621361937743943", "events": [ { "ingestionTime": 1572499609423, "timestamp": 1572499604566, "message": "gcc -o ./pgms/arithoh -DTIME -Wall -pedantic -ansi -O2 -fomit-frame-pointer -fforce-addr -ffast-math -Wall -Darithoh ./src/arith.c" }, { "ingestionTime": 1572499609423, "timestamp": 1572499604652, "message": "gcc -o ./pgms/register -DTIME -Wall -pedantic -ansi -O2 -fomit-frame-pointer -fforce-addr -ffast-math -Wall -Ddatum='register int' ./src/arith.c" }, { "ingestionTime": 1572499609423, "timestamp": 1572499604691, "message": "gcc -o ./pgms/short -DTIME -Wall -pedantic -ansi -O2 -fomit-frame-pointer -fforce-addr -ffast-math -Wall -Ddatum=short ./src/arith.c" }, (略)改行がない
--query
指定をミスってる例。惜しいんですがちょっと違う。> aws logs get-log-events \ --log-group-name <ロググループ名> \ --log-stream-name <ストリーム名> \ --query "events[].message" \ --output text # # # # # # # ##### ###### # # #### # # # # ## # # # # # # # ## # # # # # # # # # # # ## ##### ##### # # # # ###### # # # # # # ## # # # # # # # # # # # # ## # # # # # # # ## # # # # #### # # # # # ##### ###### # # #### # # Version 5.1.3 Based on the Byte Magazine Unix Benchmark Multi-CPU version Version 5 revisions by Ian Smith, Sunnyvale, CA, USA January 13, 2011 johantheghost at yahoo period com 1 x Dhrystone 2 using register variables 1 2 3 4 5 6 7 8 9 10 1 x Double-Precision Whetstone 1 2 3 4 5 6 7 8 9 10 1 x Execl Throughput 1 2 3 1 x File Copy 1024 bufsize 2000 maxblocks 1 2 3 1 x File Copy 256 bufsize 500 maxblocks 1 2 3 1 x File Copy 4096 bufsize 8000 maxblocks 1 2 3 1 x Pipe Throughput 1 2 3 4 5 6 7 8 9 10 1 x Pipe-based Context Switching 1 2 3 4 5 6 7 8 9 10 1 x Process Creation 1 2 3 1 x System Call Overhead 1 2 3 4 5 6 7 8 9 10 1 x Shell Scripts (1 concurrent) 1 2 3 1 x Shell Scripts (8 concurrent) 1 2 3 2 x Dhrystone 2 using register variables 1 2 3 4 5 6 7 8 9 10 2 x Double-Precision Whetstone 1 2 3 4 5 6 7 8 9 10 2 x Execl Throughput 1 2 3 2 x File Copy 1024 bufsize 2000 maxblocks 1 2 3 2 x File Copy 256 bufsize 500 maxblocks 1 2 32 x File Copy 4096 bufsize 8000 maxblocks 1 2 3 2 x Pipe Throughput 1 2 3 4 5 6 7 8 9 10 2 x Pipe-based Context Switching 1 2 3 4 5 6 7 8 9 10 2 x Process Creation 1 2 3 2 x System Call Overhead 1 2 3 4 5 6 7 8 9 10 2 x Shell Scripts (1 concurrent) 1 2 3 2 x Shell Scripts (8 concurrent) 1 2 3
- 投稿日:2019-11-15T08:52:38+09:00
AWS無料枠内だと思ってたら料金発生してた話
EC2のt2.microは月750時間までは無料とういことで早速使ってみたんですが、いきなり料金発生してる!なんで?ってなったのでメモ
▼AWS ドキュメント » Amazon EC2 » Linux インスタンス用ユーザーガイド » ネットワークとセキュリティ » Elastic IP アドレス
なるほど、
- Elastic IP アドレスが実行中のインスタンスに関連付けられていない場合
- Elastic IP アドレスが停止しているインスタンスやアタッチされていないネットワークインターフェイスに関連付けられている場合
にも料金が発生するようです
今回はElastic IPに関連付けられているインスタンスを停止させていたせいでした
使ってないときは停止しといた方がいいかなーってな感じで停止させていたのですが、
24時間起動していても1インスタンス月750時間は超えないので、常時起動させとくのがいいですね
- 投稿日:2019-11-15T08:49:00+09:00
各種クラウド PaaS (Platform as a Service) 実行環境 (プログラミング言語とバージョン) まとめ (2019年11月15日現在)
概要
- AWS Elastic Beanstalk, Azure App Service, Google App Engine について実行環境 (プログラミング言語とバージョン) の情報をまとめる
AWS Elastic Beanstalk (Amazon Web Services: AWS)
- AWS Elastic Beanstalk Supported Platforms - AWS Elastic Beanstalk
- Packer 1.0.3
- Docker
- Go 1.13
- Java 8, 7
- .NET Core 3.0.0, 2.2.7
- Node.js 10, 8, 6, 5, 4
- PHP 7.2.19
- Python 3.6.8
- Ruby 2.6, 2.5, 2.4
Azure App Service (Microsoft Azure)
- App Service on Linux の概要 - Azure | Microsoft Docs
- Node.js 4, 6, 8, 9, 10
- Java 8
- PHP 5.6, 7.0, 7.2, 7.3
- Python 2.7, 3.6, 3.7
- .NET Core 1.0, 1.1, 2.0, 2.1, 2.2
- Ruby 2.3, 2.4, 2.5, 2.6
Google App Engine (Google Cloud Platform: GCP)
App Engine Standard Environment Runtimes | App Engine Documentation | Google Cloud
First generation
- Python 2.7
- Java 8
- PHP 5.5
- Go 1.11
Second generation
- Python 3.7, 3.8
- Java 11
- Node.js 10, 12
- PHP 7.2, 7.3
- Ruby 2.5 (beta)
- Go 1.12, 1.13
App Engine Flexible Environment | Google App Engine flexible environment docs | Google Cloud
- Python 2.7, 3.6
- Java 8
- Node.js
- Go 1.9, 1.10, 1.11
- Ruby
- PHP 5.6, 7.0, 7.1, 7.2
- .NET Core
- 投稿日:2019-11-15T00:05:33+09:00
【Amazon SES】C#でメール一括送付するツールを作成してみた
概要
以前にGASでQRCodeを一括でメール送付する仕組みを作成しました。これはこれで便利なのですが1日に送信できるメールが限られているのが弱点でした。そこで今回は社内でAWSをお試しで使っているので、SESを使ってメールを一括送付する仕組みを作成しました。
■GoogleSpread(GAS)でQRCodeを一括で送付する
構成
主にC#のフォームで作成しました。C#でのSESの利用についてはSDKを使う方法とSMTPを使用した方法がサンプルとしてあるので、今回はSMTPを使用する方法を採用しました。C#のフォームアプリでSMTPインターフェイスからEメールを送信する仕組みを作成します。フォームアプリについてはSMTPの設定値や送信アドレスなどを設定できるようにし、SESの設定ができていればアプリから一括でメール送信が可能です。
■AWS SDK for .NETを使用してEメールを送信する
まずは Amazon SES の設定
送信するだけなら結構シンプルに設定できます。今回は送付用アドレスにGmailのメールを使用しました。ちなみに外部へのメール送信についてはサンドボックスの外への移動する必要があります。
いきなりイミワカメで困りますが、何もしていないと不正使用や悪用を防止し、送信者としての評判を保つため、新しい Amazon SES アカウントには一定の制限が適用されている状態になっています。それらの制限の解除をサポートセンターにお願いして解除してもらいます。SESの設定については以下に記載します。
AWS-SESの設定方法
このツールを使用するにあたり、AWS側の設定が必要になります。要はAWS-SESで送信用のメールアドレスやSMTPの設定などを行います。以降の手順の参考としてスクリーンショットを取得しました。ただし画像の一部にモザイクなどの加工する部分がありますのでご了承ください。
【AWS-SES】マネジメントコンソールを開く
まずはAWSマネジメントコンソールを開きSESと入力してSimple Email Serviceの画面を開きます。
【AWS-SES】送信用のアドレスを設定する
まずは送信用のメールアドレスを設定します。こちらに設定するメールアドレスは基本的には何でも大丈夫なはずです。メールアドレスを設定すると設定したメールアドレスにAWSから認証のメールが届きます。AWSからメールを承認(Verify)することで送信用のメールアドレスとして設定できます。
■ 設定したメールアドレスはC#フォームアプリの「送信アドレス」に設定します
【AWS-SES】サンドボックスの外への移動
SESの画面からSending Statisticsの画面を開きます。
SESはデフォルトだとサンドボックスと呼ばれる試用環境?の状態で制限が掛かっています。以下のスクリーンショットのように「Request a Sending Limit increase」と表示されている場合は、まだサンドボックスの状態で外部へのメール送信ができません。表示されている「Request a Sending Limit increase」をクリックしてサポートセンターへのページに遷移しサンドボックスの制限解除を依頼します。
ここで個人的に詰まったのがオレゴン以外のリージョンだといくら待っても制限が解除されませんでした。オレゴンのリージョンに選択しなおし制限解除の依頼をするとすぐに対応してくれました。まだ、アジアのリージョンもそこまで用意されていないのでオレゴンを選択した方がイイかもしれません。
なお、サンドボックスの制限解除はリージョンごとに設定する必要があるため、他のリージョンに切り替えているとRequest a Sending Limit increase」のボタンが表示されます。
【AWS-SES】SMTPの設定
最後にSMTPの設定を行います。SMTPの「Server Name」などは同じ設定だと思うので、サンプルのコードと同じであることを確認してください。確認後「Create My SMTP Credentials」をクリックするとIAMの画面に切り替わります。
IAMの画面に切り替わりIAMのユーザーを作成します。
SMTPでメールを送付する場合はIAM Userにメール送付用の専用のユーザーを作成します。作成されると以下のような「認証情報のダウンロード」ボタンからSMTP USERとSMTP PASSWORDが記載されたCSVをダウンロードできます。
もしこの画面を閉じてしまってもIAMにはユーザーが登録されており、そのユーザーの認証情報から発行し直すことができます。
最悪、もう一度「Create My SMTP Credentials」で作り直しても大丈夫です。作り直した場合はIAMで必要のないIAMのユーザーは整理しましょう。
■ ダウンロードしたCSVの情報を元にC#フォームアプリの「SMTP_USERNAME」と「SMTP_PASSWORD」を設定します
IAMの画面では先ほど作成したSMTPのユーザーが表示されているはずです。実は認証情報のアクセスキーがSMTPのユーザーに該当します。ここではパスワードを確認することができません。ただしアクセスキーを発行し直しSMTPのユーザーとパスワードを取得しなおすことはできそうです。
C#によるフォームアプリの作成
上記のAWS-SESが完了したらC#フォームで送る準備をします。ツールを使う場合は上記のSMTPユーザーなどを設定すれば一括でメールを送付することができます。
なおAWSの設定情報のどの項目を設定すべきかはAWS手順の画像の下に■の記号で補足している部分を参考にしていただけると助かります。
それでは実装した機能を記載していこうと思います。【C#フォーム】プロパティによる設定値の保存
入力した設定値についてはプロパティに保存され次回起動したときにも設定値を維持するようにします。
保存する値がセキュアなモノである場合は、暗号化して保存するようにしています。これは以前にプロパティではなくリソースを使っていたときにEXEのバイナリから読み取れてしまうことがあったので、念のために暗号化の処理を挟むことにしました。
【C#フォーム】Excelから送付リストの取り込み
DataGridViewに表示する内容についてはExcelファイルから取り込めるようにしました。外部のデータベースに接続して利用することも可能ですが、データベース自体が決まっていないので、とりあえずClosedXMLを使用してExcelファイルを読み込むようにしました。
ClosedXMLを使用すればExcelがインストールされてなくても処理できるので便利ですね。Office Interopでも読み込めますが後処理とかちゃんとしないとイケないんで少し面倒です。
取り込んだ後のDataGridViewでは列項目で絞り込めるようにしています。
【C#フォーム】テキストの置換
3つの項目だけですが自分で設定したテキストの内容と取り込んだExcelファイルの列項目に対応して置換するようにしました。文章にするとわかりづらいため設定画面も日本語でわかりやすくしてみたつもりです。
【C#フォーム】AWSの設定
AWSで設定したSMTPなどを設定できます。AWS側の設定については後段で説明します。
【C#フォーム】メールの設定
メールの件名や本文の設定ができます。上記のテキストの置換に合わせて本文を置換することができます。
【C#フォーム】ログ出力
送信後に本当に送信されたかどうか不安だと思うのでログを出力するようにしました。
送信結果
捨てメアド【メルアドぽいぽい】というサービスでメールアドレスを作成して試しに送ってみました。
テキストの置換も上手く機能しています。
リンク先を確認するとちゃんと社員番号のQRコードが生成されています。
総評
AWS-SESとC#のフォームアプリで一括で送付する仕組みができました。別にメールで送付するならGASでもイイじゃんとなりそうですが、GASはGASで送付エラーのときが若干怖かったりします。
作成したC#のフォームアプリでは送付後にログも出力するので正しく送付されたかどうか確認できます。もし送付できていなかった場合でもログから拾うことができ、もう一度再送してあげることもできます。
今回、作成したC#フォームアプリは以下の場所に格納しましたのでAWS-SESの設定をした上でご試用いただければ幸いです。
- 投稿日:2019-11-15T00:05:33+09:00
【AWS-SES】C#でメール一括送付するツールを作成してみた
概要
以前にGASでQRCodeを一括でメール送付する仕組みを作成しました。これはこれで便利なのですが1日に送信できるメールが限られているのが弱点でした。そこで今回は社内でAWSをお試しで使っているので、SESを使ってメールを一括送付する仕組みを作成しました。
■GoogleSpread(GAS)でQRCodeを一括で送付する
構成
主にC#のフォームで作成しました。C#でのSESの利用についてはSDKを使う方法とSMTPを使用した方法がサンプルとしてあるので、今回はSMTPを使用する方法を採用しました。C#のフォームアプリでSMTPインターフェイスからEメールを送信する仕組みを作成します。フォームアプリについてはSMTPの設定値や送信アドレスなどを設定できるようにし、SESの設定ができていればアプリから一括でメール送信が可能です。
■AWS SDK for .NETを使用してEメールを送信する
まずは Amazon SES の設定
送信するだけなら結構シンプルに設定できます。今回は送付用アドレスにGmailのメールを使用しました。ちなみに外部へのメール送信についてはサンドボックスの外への移動する必要があります。
いきなりイミワカメで困りますが、何もしていないと不正使用や悪用を防止し、送信者としての評判を保つため、新しい Amazon SES アカウントには一定の制限が適用されている状態になっています。それらの制限の解除をサポートセンターにお願いして解除してもらいます。SESの設定については以下に記載します。
AWS-SESの設定方法
このツールを使用するにあたり、AWS側の設定が必要になります。要はAWS-SESで送信用のメールアドレスやSMTPの設定などを行います。以降の手順の参考としてスクリーンショットを取得しました。ただし画像の一部にモザイクなどの加工する部分がありますのでご了承ください。
【AWS-SES】マネジメントコンソールを開く
まずはAWSマネジメントコンソールを開きSESと入力してSimple Email Serviceの画面を開きます。
【AWS-SES】送信用のアドレスを設定する
まずは送信用のメールアドレスを設定します。こちらに設定するメールアドレスは基本的には何でも大丈夫なはずです。メールアドレスを設定すると設定したメールアドレスにAWSから認証のメールが届きます。AWSからメールを承認(Verify)することで送信用のメールアドレスとして設定できます。
■ 設定したメールアドレスはC#フォームアプリの「送信アドレス」に設定します
【AWS-SES】サンドボックスの外への移動
SESの画面からSending Statisticsの画面を開きます。
SESはデフォルトだとサンドボックスと呼ばれる試用環境?の状態で制限が掛かっています。以下のスクリーンショットのように「Request a Sending Limit increase」と表示されている場合は、まだサンドボックスの状態で外部へのメール送信ができません。表示されている「Request a Sending Limit increase」をクリックしてサポートセンターへのページに遷移しサンドボックスの制限解除を依頼します。
ここで個人的に詰まったのがオレゴン以外のリージョンだといくら待っても制限が解除されませんでした。オレゴンのリージョンに選択しなおし制限解除の依頼をするとすぐに対応してくれました。まだ、アジアのリージョンもそこまで用意されていないのでオレゴンを選択した方がイイかもしれません。
なお、サンドボックスの制限解除はリージョンごとに設定する必要があるため、他のリージョンに切り替えているとRequest a Sending Limit increase」のボタンが表示されます。
【AWS-SES】SMTPの設定
最後にSMTPの設定を行います。SMTPの「Server Name」などは同じ設定だと思うので、サンプルのコードと同じであることを確認してください。確認後「Create My SMTP Credentials」をクリックするとIAMの画面に切り替わります。
IAMの画面に切り替わりIAMのユーザーを作成します。
SMTPでメールを送付する場合はIAM Userにメール送付用の専用のユーザーを作成します。作成されると以下のような「認証情報のダウンロード」ボタンからSMTP USERとSMTP PASSWORDが記載されたCSVをダウンロードできます。
もしこの画面を閉じてしまってもIAMにはユーザーが登録されており、そのユーザーの認証情報から発行し直すことができます。
最悪、もう一度「Create My SMTP Credentials」で作り直しても大丈夫です。作り直した場合はIAMで必要のないIAMのユーザーは整理しましょう。
■ ダウンロードしたCSVの情報を元にC#フォームアプリの「SMTP_USERNAME」と「SMTP_PASSWORD」を設定します
IAMの画面では先ほど作成したSMTPのユーザーが表示されているはずです。実は認証情報のアクセスキーがSMTPのユーザーに該当します。ここではパスワードを確認することができません。ただしアクセスキーを発行し直しSMTPのユーザーとパスワードを取得しなおすことはできそうです。
C#によるフォームアプリの作成
上記のAWS-SESが完了したらC#フォームで送る準備をします。ツールを使う場合は上記のSMTPユーザーなどを設定すれば一括でメールを送付することができます。
なおAWSの設定情報のどの項目を設定すべきかはAWS手順の画像の下に■の記号で補足している部分を参考にしていただけると助かります。
それでは実装した機能を記載していこうと思います。【C#フォーム】プロパティによる設定値の保存
入力した設定値についてはプロパティに保存され次回起動したときにも設定値を維持するようにします。
保存する値がセキュアなモノである場合は、暗号化して保存するようにしています。これは以前にプロパティではなくリソースを使っていたときにEXEのバイナリから読み取れてしまうことがあったので、念のために暗号化の処理を挟むことにしました。
【C#フォーム】Excelから送付リストの取り込み
DataGridViewに表示する内容についてはExcelファイルから取り込めるようにしました。外部のデータベースに接続して利用することも可能ですが、データベース自体が決まっていないので、とりあえずClosedXMLを使用してExcelファイルを読み込むようにしました。
ClosedXMLを使用すればExcelがインストールされてなくても処理できるので便利ですね。Office Interopでも読み込めますが後処理とかちゃんとしないとイケないんで少し面倒です。
取り込んだ後のDataGridViewでは列項目で絞り込めるようにしています。
【C#フォーム】テキストの置換
3つの項目だけですが自分で設定したテキストの内容と取り込んだExcelファイルの列項目に対応して置換するようにしました。文章にするとわかりづらいため設定画面も日本語でわかりやすくしてみたつもりです。
【C#フォーム】AWSの設定
AWSで設定したSMTPなどを設定できます。AWS側の設定については後段で説明します。
【C#フォーム】メールの設定
メールの件名や本文の設定ができます。上記のテキストの置換に合わせて本文を置換することができます。
【C#フォーム】ログ出力
送信後に本当に送信されたかどうか不安だと思うのでログを出力するようにしました。
送信結果
捨てメアド【メルアドぽいぽい】というサービスでメールアドレスを作成して試しに送ってみました。
テキストの置換も上手く機能しています。
リンク先を確認するとちゃんと社員番号のQRコードが生成されています。
総評
AWS-SESとC#のフォームアプリで一括で送付する仕組みができました。別にメールで送付するならGASでもイイじゃんとなりそうですが、GASはGASで送付エラーのときが若干怖かったりします。
作成したC#のフォームアプリでは送付後にログも出力するので正しく送付されたかどうか確認できます。もし送付できていなかった場合でもログから拾うことができ、もう一度再送してあげることもできます。
今回、作成したC#フォームアプリは以下の場所に格納しましたのでAWS-SESの設定をした上でご試用いただければ幸いです。