- 投稿日:2020-11-24T23:23:17+09:00
【Android】ObjectMetadata.setContentEncoding で文字化け【AWS】
AWS(s3) の Android サンプルコードを試していたのですが、
アップロードしたファイルの文字化けで手間取ったのでメモ。文字化けしたコードObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("text/plain"); metadata.setContentEncoding("UTF-8"); // "utf-8"も"UTF8"も試したけどダメうまくいったコードObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("text/plain;charset=utf-8");setContentEncodingなんて、期待しちゃうにきまってるじゃないですか。
- 投稿日:2020-11-24T21:53:14+09:00
【AWS】SysOpsアドミニストレーター-アソシエイト(SOA)合格記
はじめに
AWS認定試験-SysOpsアドミニストレーター-アソシエイト(SOA)に合格した(2020-08-10)ので、合格までの道のりを残しておこうと思います。
CLF合格記は以下をご覧ください。
【AWS】クラウドプラクティショナー(CLF)合格記SAA合格記は以下をご覧ください。
【AWS】ソリューションアーキテクト-アソシエイト(SAA)合格記SOAはSAA合格後すぐに勉強を始めました。
What's SOA?
まずは、SOA試験について
AWS 認定 SysOps アドミニストレーター – アソシエイト上記サイトによると、認定によって検証される能力は以下のようです。
- スケーラブルで、高可用性および高耐障害性を備えたシステムを AWS でデプロイ、管理、運用する
- AWS との間のデータフローを実装および制御する
- コンピューティング、データ、セキュリティ要件に基づく適切な AWS のサービスを選択する
- AWS 運用のベストプラクティスの適切な使用方法を識別する
- AWS の使用コストを予測し、運用コストコントロールメカニズムを識別する
- オンプレミスワークロードを AWS に移行する
SOAはSAAよりも運用を重視した問題が多かった印象です。
ログ監視や、移行設計(snowballかDirectconnectか等)が問題としては出ました。
難易度的にはSAAよりも簡単だった印象があります。試験に向けて
基本的にはSAAと同じ手法をとっていきました。(研修への参加はしていません。)
試験に向けて
公式サンプル問題
これはCLFと変わらず事前に受けて現状のレベルの確認をします。
私は60%ほどの出来でした。ホワイトペーパーを読む
CLFと同じくホワイトペーパーを読みました。
Black Beltを読む
こちらもCLFと同じくBlack Beltを読みました。
問題を解く
こちらのサイトは一問ごとに解説が表示され、都度確認ができ、BlackBeltやホワイトペーパーへのリンクもあるので、勉強しやすかったです。
試験当日
上記対策を計2週間(延べ20時間程度)行い、試験に臨みました。
結果は、731点(720点以上で合格)で合格でした。
感想
SAAよりも移行関係や、データセンターとの接続方法、コストに関する問題が多めでした。
基本的に出題されるサービスに関して、SAAから新しいものがあるとは言えませんので、SAAの勉強の流れで運用に重点を置いた解答を選べるようになればいいと思います。問題集などで試験に応じた解答を選択できるようになれば良いかと思います。
- 投稿日:2020-11-24T21:37:12+09:00
【原因と対策】An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.
AWS-CLIで
An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.
というエラーが出た時の備忘録。
原因
そのままGoogle翻訳にぶち込んでみる。
GetCallerIdentity操作の呼び出し中にエラーが発生しました(InvalidClientTokenId):要求に含まれているセキュリティトークンが無効です。セキュリティトークンが無効だとおっしゃっている。
では「aws configure list」を入力してアクセスキーとシークレットキーを確認してみよう。
Name Value Type Location ---- ----- ---- -------- profile <not set> None None access_key ****************hoge shared-credentials-file secret_key ****************fuga shared-credentials-file region ap-northeast-1 config-file ~/.aws/configおそらく上記エラーが出ている場合、意図したアクセスキー、シークレットキーの値と異なっているはず。
なぜか?AWS-CLIを導入した際に「aws configure」を設定したと思うが、その時の設定が残っているからである。
私の場合は、AWSの練習でIAMユーザーをちょくちょく作ったり消したりしていたので、以前作ったIAMユーザーのアクセスキー、シークレットキーが反映された状態になっていた。
おそらくほとんどのケースがこんな感じなのではないかと思う。解決策
もう一度
aws configure --profile IAMユーザー名を実行して、意図しているアクセスキーとシークレットキーに設定し直す。
ターミナルで別タブを開いて、再度「aws configure list」を入力。
アクセスキー、シークレットアクセスキーが意図したものに変更されていればOK。
参考
- 投稿日:2020-11-24T19:34:45+09:00
AWS Step Functions 値の受け渡しについて
こんにちは。GxPの2年目の伊藤です。
この記事はグロースエクスパートナーズ アドベントカレンダーの6日目の記事となります。「今年の学び」がテーマということで、僕は今年の4月から案件が変わりAWSへ移行する案件に就くことになりました。AWSについてほとんど知識のない状態でしたが、仕事を通してAWSについてだけではなく多くのことを学ばせてもらいました。
今回の記事はTerraformで管理しているStep FunctionsでECS Taskを実行したときに値を渡したかったのですが、そのやり方で詰まったのでその方法の紹介になります。構成
CloudWatch Eventsから直接ECS Taskを起動することもできますが、監視をしやすくするためにStep Functionsを挟んでいます。
バージョン
Terraform: 0.12.20
aws provider: 3.13.0Step Functionsから値を受け渡す
上記の構成だったのですが、ECS Task実行時に値を渡す必要が出てきました。そこで、Step Functionsから値を受け渡して実行できるようにしなくてはなりませんでした。
僕たちの案件ではAWSのリソースをTerraformで管理していたため、Step Functionsだと実行時のポップアップのJSONがECS Taskに値を渡す場所になりますが、Terraformだとどのように書くのかわからず詰まってしまいました。こちらでStepFunctionsの入出力制御について丁寧に説明されています。
参考にするとState InputがStep Functions実行時のポップアップのJSONに当たります。今回はここから値を入れてあげたいのですが、どうやればよいのか分からなかったという話です。
Step Functionsの定義
StepFunctionsでECSを操作についてのAWSのドキュメントを参考にするとOverridesを使うとStep FunctionsからECSへ値を渡せるようでした。そこで以下のようにStep Functionsのoverridesを定義することで環境変数を設定することができました。
StepFunctionsの定義"Parameters":{ "Overrides":{ "ContainerOverrides":[ { "Environment":[ { "Name":"hoge", "Value.$":"$.VALUE" } ], "Name":"hoge-task" } ] },これによりECS Taskにhogeという名前でState Inputから受け取ったVALUEの値を環境変数として設定し、値を渡すことができるようになります。$.を使うことによって実行中のJSONの値を取り出すことができます。
注意1:渡し先のECS TaskのNameもちゃんと設定してあげないとエラーになります。
注意2:.$を使う場合はダブルクォーテーションで括ってあげないとちゃんと認識してもらえませんでした。
注意3:StepFunction定義のキーに .$を使って値をパス解決させた場合、実行時にJson-pathが表すキーが存在しないとエラーになります。つまり、State Inputにキーを与えないといけません。
CloudWatch Eventsの定義
このままではCloudWatch Eventsから実行したときにJson-pathが表すキーが存在しないため、CloudWatch EventsからStepFunctionsに渡すinputを設定しました。
Step FunctionsにVALUEという名前で値を渡してくれます。CloudWatchEventsresource "aws_cloudwatch_event_target" "cloudwatch_event" { ... input = "{\"VALUE\" : \"\"}" }確認
Step Functionsの手動実行時のポップアップのJSONに画像のようにキーを設定し、実行後TaskSubmittedのjsonのEnvironmentのNameとValueが設定されていればECS Taskに値を渡すことができるています。
TaskSubmitted"Overrides": { "ContainerOverrides": [ { "Command": [], "Environment": [ { "Name": "hoge", "Value": "" } ], "EnvironmentFiles": [], "Name": "hoge-task", "ResourceRequirements": [] } ], "InferenceAcceleratorOverrides": [] }今回の学び
ほとんど分からなかった状態からチームメンバーの助けを借りつつも自分で調べて解決することができたので自信を付けることが出来ました。
AWSのドキュメントは難解なところはありましたが、ちゃんと読み解くと欲しい情報は結構書いてあったりするので他の記事を参考にしつつも頑張って読むことが大切だなと思いました。
これからも多くのことに触れて学びを増やしていこうと思います。
- 投稿日:2020-11-24T18:00:31+09:00
CloudFrontでアクセスログを有効にするとS3のACLに見慣れない外部アカウントの権限がつくのでビビった話
長いですが題の通りです。
起きた事
AWSの設定を見ていたら、S3のACL(権限周りの設定ね)に見慣れない外部アカウントに対して権限がついている!これはセキュリティにやばいのでは(゚A゚;)ゴクリ
種明かし
CloudFrontでLogの出力先をS3にすると、自動でこうなります。なので安全です。大丈夫です。
CloudFrontのログは
awslogsdelivery
というAWSアカウント(!)を経由して出力される仕組みになっています。で、このawslogsdelivery
のアカウントIDがc4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0
なのです。ディストリビューションを作成または更新してロギングを有効にすると、CloudFront はこれらのアクセス許可を使用してバケットの ACL を更新し、awslogsdelivery アカウントに FULL_CONTROL のアクセス許可を付与します。awslogsdelivery アカウントはログファイルをバケットに書き込みます。
やっかいなのが、この設定をCloudFrontでLogの設定をした時に自動でやってくれるため、S3の設定としては意識されない事です。よって、知らないうちに変なIDが追加されてる!という状況が発生します。怖いですね。
c4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0
というIDを見たら、
?「あ、これはawslogsdelivery
のアカウントIDだな」
と思い出してくださいね(無理でしょ)参考
- 投稿日:2020-11-24T16:53:19+09:00
Amazon SageMakerとAzure MLにおける機械学習モデルのサービング技術比較(後編)
初版: 2020年11月24日
著者: 橋本恭佑、柿田将幸, 株式会社 日立製作所はじめに
本連載では、ストリーム型の機械学習システムをサービングする技術について、
Amazon SageMakerとAzure Machine Learningを比較した結果を紹介しています。
後編では、実際にストリーム型の機械学習システムを両クラウドでサービングして、本投稿で紹介した違いが現れること、
また、SEがAmazon SageMakerとAzure Machine Learningのいずれかの利用を、どのような基準で選択するべきかについて議論します。
なお、本連載に記載のAmazon SageMakerまたはAzure MLの情報は2020年9月末日現在のものであり、今後のアップデート等によって内容が変わることがあります。投稿一覧
- Amazon SageMakerとAzure MLにおける機械学習モデルのサービング技術比較(前編)
- Amazon SageMakerとAzure MLにおける機械学習モデルのサービング技術比較(後編)・・・本投稿
パブリッククラウドにおけるサービング実機検証と検証項目
Amazon SageMakerとAzure MLでランタイムを作成し、前編で示した相違点を実機で比較します。
ランタイムは次の手順で作成されます。
1. パブリッククラウドが提供するOSSの入ったコンテナイメージを指定する
2. モデル、前処理、後処理コードを呼び出す
3. 1と2をコンテナとしてコンテナ基盤上にデプロイする検証項目は以下の通りです。
1. 前処理コードや後処理コードの実装方法の違い
2. ランタイム作成時のOSS追加可否
3. ランタイム作成時のコンテナ基盤指定有無検証1: 前処理コードと後処理コードの実装方法の比較
Amazon SageMakerでは前処理や後処理を別の関数で書くため、可読性が高くランタイム作成後のコード変更が容易と考えられます。
一方でAzure MLは前処理と後処理を1つの関数に書くため、モデル訓練時の実装に近く、訓練時のコードを流用しやすいと考えられます。検証2: ランタイム作成時のOSS追加可否
Azure MLではランタイム作成時にpipやcondaを利用してOSSを追加できます。
モデル訓練には不要だが推論システム作成には必要なOSSがある場合に、それらをすぐに追加できます。
したがって、最初の推論システムを作成するのに要する時間が短いと考えられます。検証3: ランタイム作成時のコンテナ基盤指定有無
Azure MLではランタイム作成先のコンテナ基盤を別途用意して指定する必要があり、コンテナ基盤(AKS)の知識が必要です。
実機検証を通したAmazon SageMakerとAzure MLの特徴考察
Amazon SageMakerには以下の特徴があり、推論システム作成時に問題が起こりにくいと考えられます。
- 前処理コードや後処理コードの可読性が高く、コードの誤りに気づきやすい
- 用意したコンテナイメージにないOSSはランタイムにインストールできない
- コンテナ基盤を意識せずにランタイムを作成できる
一方でAzure MLにも以下の特徴があります。
- モデル訓練には不要だが推論システム作成には必要なOSSがある場合に、すぐにそれらを追加できるため、 モデル訓練後からランタイム作成までのリードタイムが短く、顧客がすぐに推論システムを利用しやすいと考えられます。
- 訓練時の前処理や後処理コードを推論システムに流用しやすい
- ランタイム作成時に独自にOSSを追加できる
こうしたAmazon SageMakerとAzure MLの特徴をとらえて、いずれのベンダを利用するか検討すべきといえます。
おわりに
本投稿ではAmazon SageMakerとAzure MLにおける機械学習システムのサービング技術を比較しました。
実機検証を通して、Azure MLはモデル訓練後から推論システム構築までのリードタイムを短くしたい場合に有効であること、
それ以外の場合はAmazon SageMakerが有効である可能性が高いことを確認しました。
- 投稿日:2020-11-24T16:51:47+09:00
The security token included in the request is expiredとなった時の対応方法
事象 : Secrets Managerからシークレット値を取得しようとしたら怒られた
- 環境
- AWS Cloud9
- Python 3.6.12
はじめてSecrets Managerにシークレット値を設定してCloud9からシークレット値を取得しようとした。
取得するコードは超親切にシークレット値を設定した時に表示されるのでほぼコピペで使った・・・がExpiredTokenException
・・・def get_backlog_api_key(): secret_name = 'シークレットの名前' session = boto3.session.Session() client = session.client( service_name='secretsmanager', region_name='リージョン' ) try: get_secret_value_response = client.get_secret_value( SecretId=secret_name ) except ClientError as e: print(e.response['Error']) raise e else: if 'SecretString' in get_secret_value_response: secret = get_secret_value_response['SecretString'] else: decoded_binary_secret = base64.b64decode(get_secret_value_response['SecretBinary']){'Message': 'The security token included in the request is expired', 'Code': 'ExpiredTokenException'}原因 : Lambdaに権限がないから
権限の存在を忘却していた。
Minimum permissions
To run this command, you must have the following permissions:
secretsmanager:GetSecretValue
GetSecretValue - AWS Secrets Manager対応 : 権限を付与する
- 投稿日:2020-11-24T14:32:38+09:00
Code PipelineでJekyllをビルドしてS3+CloudFrontで静的配信する
はじめに
概要
Civichat(https://civichat.jp)をJekyllに変更し、S3+CloudFrontで配信するために調べていた時に記事が昔すぎ(2016年とか...)or英語だったのでせっかくだしCodePipelineやり方をまとめようと思った次第です
Civichatとは:あなたにぴったりの助成金などの公共制度がLINEでわかるサービスです。
https://civichat.jp/
Jekyllってなに?
Jekyllは、個人、プロジェクト、または組織のサイト向けの、シンプルなブログ対応の静的サイトジェネレーターです。 GitHubの共同創設者であるTom Preston-WernerによってRubyで書かれ、オープンソースのMITライセンスで配布されています。 (by Wikipedia)
要するにRubyでできた静的サイト生成ツールですね(Markdownで記事が書ける)
最近だと@Nuxt/Content とか Gatsby.js みたいな感じですね。なぜAWS? なぜCode Pipeline? なぜCode Build?
多分 Netlify とか Vercel とかでもできるはず....
今回はAWSに請求まとめたりしたいのと、AWSを使いたかったのでAWSです。手順
すでにGitHub上にJekyllのコード自体が存在して、ローカルで
jekyll build
で_site
に出力されることを確認しているものとして書きますS3のバケットを用意する
普通にバケットを作りますが、パブリックアクセスのブロックは外しておきます。
Code Pipelineでパイプラインを作る
パイプラインの設定
ここではパイプライン名を設定します
(このパイプライン名は変えられなくなるので注意)
GitHubとの接続
今回はGithubのコミットをトリガーにするのでソースプロバイダーに
GitHub(バージョン2)
を選択します。
GitHubに接続するをクリックし接続名を入力し、GitHubにAWS Connector
をインストールします
その後、インストールしたGitHubからリポジトリが取得できるようになるので、リポジトリ名とブランチ名を設定します。
(ねんのため塗りつぶしています)
CodeBuildの設定
プロバイダにAWS CodeBuildを指定するとプロジェクトを作成するというボタンが出るのでクリック
するとCodeBuildの設定ページが表示されるので、以下のように設定します。プロジェクトの設定
プロジェクト名は適当に...
環境
せっかくなのでAmazon Linux 2を使いましょう
特権付与のチェックは今回は必要ないので外しておきます。
Buildspec
もしBuildspec.ymlをルートディレクトリに置けない場合にはその場所を指定してあげてください
バッチ設定・ログ設定
基本的にはそのままでよいはず
すべて設定が終わったらCodePipelineに戻るをクリックして戻ります。
戻るとAWSが自動的にプロジェクト名を入れてくれています(素敵!!)
デプロイの設定
デプロイプロバイダにAmazon S3を選択するとバケットの選択ができるようになるので、初めに作成したバケットを選択します。
また、この時デプロイする前にファイルを抽出する
にチェックをつけ忘れるとS3にビルドされたファイルがZipで出てしまうのでつけ忘れないようにしましょう
作成前の確認
いろいろまずそうなのは塗りつぶしてますが....
大事なのはFullRepositoryId
が正しいこと・Extract
がTrue
であることなのでそれを確認しましょう
確認したらパイプラインを作成するをクリックしてパイプラインを作ります。
buildspec.ymlを作成する
今のままだとなんの処理をすればいいかをCodeBuildに伝えていないので、接続したリポジトリのルートディレクトリにbuildspec.ymlというのを作成し、以下の内容を記述します
buildspec.ymlversion: 0.2 phases: pre_build: commands: - export LC_ALL="en_US.utf8" - bundle install build: commands: - bundle exec jekyll build artifacts: base-directory: '_site' files: - '**/*'普通に
bundle install
してjekyll build
しているだけですが、
export LC_ALL="en_US.utf8
でUTF-8に固定してあげないとjekyllがエラーを吐いてしまうのでお気をつけください。これらをCommit & Pushすると自動でPipelineが走って
このようになれば成功です!
成果物を確認する
最初に確認したバケットを見ると以下のようにいろいろとファイルがあるはずです!
これでCDについては完成です!
CloudFront + S3の設定
Create Distributionをクリックし、WebのGet Startedを選択します
Origin Settings
- Origin Domain Name : 最初に作成したS3のを選択
- Restrict Bucket Access : Yes
- Origin Access Identity : Create a New Identity
- Grant Read Permissions on Bucket : Yes, Update Bucket Policy ↑でS3バケットへのアクセス設定を変更しています
Default Cache Behavior Settings
お好みで (私はいつも
Viewer Protocol Policy
をRedirect HTTP to HTTPS
にしています)Distribution Settings
- Price Class : お好み(Use U.S., Canada, Europe, Asia, Middle East and Africaで十分な気が)
- Alternate Domain Names(CNAMEs) : 必要なら
- SSL Certificate : 必要なら
- Default Root Object : index.html
- Standard Logging : 必要なら
設定後 Create Distribution をクリックして完了
StatusがIn Progress
からDeployed
になったらDomain Nameに書いてある xxxxxxxxxxxxxxxx.cloudfront.netにアクセスしてみて、接続できれば全設定完了です。お疲れさまでした
この方法でbuildspec.ymlを変えてあげればNuxtだったり、Gatsbyでもできますが、その話はまた今度...機会があれば...ということで。
皆さんもぜひやってみてください!!
ではではー
- 投稿日:2020-11-24T13:57:42+09:00
【備忘録】AWSでCakePHP4の環境構築
1. EC2のインスタンス作成 ~ PHP7.4インストール
「EC2立ち上げ→Apacheインストール→PHP7.4インストール」の流れはこちらの記事を参考にしました。
AWS(EC2)を立ち上げてPHPを動かす話2. PHP拡張モジュールのインストール
$ sudo yum -y --enablerepo=remi-php74 install php74-php-intl php74-php-mbstring php74-php-pdoapache再起動
$ sudo systemctl restart httpd3. composerのインストール
$ curl -sS https://getcomposer.org/installer | sudo php $ sudo mv composer.phar /usr/local/bin/composer $ sudo ln -s /usr/local/bin/composer /usr/bin/composer4. cakephp4のインストール
phpのバージョンが7.2以上ならcakephpのバージョンを指定しなくても自動的にversion4がインストールされると思います。
$ composer create-project --prefer-dist cakephp/app my-app5. Apacheの設定
vimでapacheの設定ファイルを開きます。
$ sudo vim /etc/httpd/conf/httpd.confDocumentRootを"/var/www/html"から先ほどインストールしたcakephpディレクトリのwebrootに変更します。
.htaccessでの設定の上書きを許可するよう、AllowOverride を All に設定します。DocumentRoot "/var/www/html/my-app/webroot" <Directory "/var/www/html"> Options FollowSymLinks AllowOverride All </Directory>その後、apacheを再起動
6. 完了
- 投稿日:2020-11-24T13:35:54+09:00
CDKでクロスアカウントアクセス可能なS3バケットを作成しようとしてハマったので解決方法
ハマった流れ
- CDKでのインフラ構成に初挑戦
- S3バケットを作成、別のAWSアカウントからの書き込みを許可したい
- できたと思ったら、別アカウントからアクセスできない事態が発生
- ブロックパブリックアクセスをオフにした→アクセスできたが、セキュリティ面に不安
- 公式doc見る限り、ブロックパブリックアクセスをオンにしたままクロスアカウントアクセス許可できるはず…
- バケット作成した→できた。
- そのS3バケットを
Bucket.fromBucketName(...)
で利用し、別サービスをデプロイしたら、クロスアカウントアクセスがまた不可に。
- 見ると、バケットポリシーが消えている
addToResourcePolicy
で再付与 → できない- 混乱
ブロックパブリックアクセスをオンにしたままクロスアカウントアクセス許可する方法
- ブロックパブリックアクセスについては、全てオンでOK(CDKだと
BlockPublicAccess.BLOCK_ALL
は設定してOK)- バケットポリシーでクロスアカウントアクセスを許可するのだが、公式ドキュメントの「パブリック」の意味にしたがって、「非パブリックのポリシー」とみなされる書き方をしないと、ブロックパブリックアクセスが優先されてアクセス不可になるので注意。
というわけで今回はここの問題ではなかった。
CDKによるS3バケットの作成と利用について
new Bucket(...)
で作成したS3バケットにaddToResourcePolicy
でバケットポリシーを付与可能Bucket.fromBucketName(...)
で呼び出したS3バケットにはaddToResourcePolicy
等の操作ができないが、2020/11/24現在エラーは出ない。(対応するGitHubのissue)
- 別スタックやCloudFormationで管理されていないリソースの改変を防ぐための仕様、とのこと
そのため、既存のS3バケットを利用する際、同じStackで作成済みのS3バケットを利用するとクロスアカウントアクセス可能なバケットポリシー設定がうまくいかない。
Bucket.fromBucketName(...)
で呼び出したS3バケットにaddToResourcePolicy
で権限設定
- 不可。
.fromBucketName(...)
で呼び出すとaddToResourcePolicy
が使えない。new Bucket(...)
でバケット作成した時点でaddToResourcePolicy
で権限設定済みのバケットをBucket.fromBucketName(...)
で呼び出す。
- できそうだが不可。同じスタック内でバケットポリシーを付与していて、その記述がコードから消えるので、スタックで管理されているバケットポリシーが消される。
じゃあどうするか?
- S3バケットのスタックだけ分ける
- アリだが、そもそも分けたスタック内でのアップデートがうまく行かないならCDKでやるメリットってないような。
- S3は手動で管理する
- 正直アリな気もする。イケてないけど。
CfnBucket
で管理する
- あ、コレできそう、と思った記事
- コレが一番良さそう。調査しながら追記していきます。
最終的なソースコード
- (あとで追記します。)
- 投稿日:2020-11-24T12:51:34+09:00
AWS S3に保存しているオブジェクトを1度に1000件削除する。
やりたいこと
削除するオブジェクトのキー名が記載されたファイルを読み込んで、ポチッと実行するだけで、削除できるようにしたい。
方針
・削除するオブジェクトのキーがかかれたファイルを用意する。
・S3のAPI(delete_objects)を利用して、ループしながらキーを指定削除する。参考リンク
・S3の削除について
・pythonのdelete_objects APIについてやったこと
・削除するオブジェクトのキーリストを作成する。
削除するオブジェクトのキーリストhoge/fuga/hoge.jpg hoge/fuga/hoge.png hoge/hoge/hoge.gif hoge/hoge/fuga.png ・・・ fuga/fuga/fuga.png・削除プログラムを実行する
delete_objectsは1度に1000件しか指定できないので、読み込んだキーリストを1000件単位のリストに再分割する。分割した単位でDELETE APIを叩き、ループ実行する。
削除プログラム.pyimport boto3 import re import json MY_REGION = 'リージョン名'; MY_BUCKET = 'バケット名'; client = boto3.client('s3', region_name=MY_REGION) request_list = [] img_path_list = '' def split_list(l): for idx in range(0, len(l), 1000): yield l[idx:idx + 1000] # 削除データを読み込む with open('削除するオブジェクトのキーリスト.text') as f: img_path_list = f.readlines() # データ末尾の改行を削除してリストに追加する for path in img_path_list: path = path.replace('\n','') request_list.append({'Key': path}) # リストを1000件ごとに分ける # devide_list = [[0,...,999],[1000,...,1999],...,[n,...,n+999]] devide_list = list(split_list(request_list)) # DELETE APIを実行する for key_list in devide_list: response = client.delete_objects( Bucket = MY_BUCKET, Delete = { 'Objects': key_list } ) # 削除結果を記録する with open('log/削除結果.txt', mode='a') as f: for res in response['Deleted']: f.write(json.dumps(res)) f.write('\n')・削除が成功していれば、結果は下記のようになる。
削除結果.text{"Key": "hoge/fuga/hoge.jpg", "DeleteMarker": true, "DeleteMarkerVersionId": "hogehoge1"} {"Key": "hoge/fuga/hoge.png", "DeleteMarker": true, "DeleteMarkerVersionId": "hogehoge2"} {"Key": "hoge/hoge/hoge.gif", "DeleteMarker": true, "DeleteMarkerVersionId": "hogehoge3"} {"Key": "hoge/hoge/fuga.png", "DeleteMarker": true, "DeleteMarkerVersionId": "hogehoge4"} {"Key": "fuga/fuga/fuga.png", "DeleteMarker": true, "DeleteMarkerVersionId": "hogehoge5"}その他
削除するリストと削除しないリストを用意して、両方のリストに存在するキーがあるか確認する
・Pythonで複数のリストに共通する・しない要素とその個数を取得2つのリストに存在する要素を表示する.pyinput_urls = '' not_delete_urls = '' # リストデータを読み込む with open('入力リスト.txt') as f: input_urls = f.readlines(); with open('削除しないリスト.txt') as f: not_delete_urls = f.readlines(); duplicate_urls = set(input_urls) & set(not_delete_urls) # set型からlist型に変更する list_duplicate_urls = list(duplicate_urls) list_duplicate_urls.sort() # 共通要素の件数と要素を表示する print(len(list_duplicate_urls)) for elem in list_duplicate_urls: print(elem, end='')注意事項
- S3は少なくとも1秒間に3500リクエストできるので、削除APIを連続で叩く際に特にsleepは設けていませんが、実際に本プログラムを使って大量削除される方は、sleepを入れるかどうか自己責任で判断してください。
- 投稿日:2020-11-24T12:40:19+09:00
AWS認定試験の合格特典を紹介してみた
前書き
意外とQiita上ではAWS認定試験の特典に関する記事が見受けられなかったので記してみます。
なお、自分が受かったのはSAA(ソリューションアーキテクトアソシエイト)となります。
よければこちらの合格体験の記事もご参考に!特典内容
①認定デジタルバッジの取得
ざっくり合格の証ですね。(バッジと聞くとなんかテンション上がりますよね・・・!)
現在は、Acclaim (アクレーム)というサービス上で付与されるようです。※Acclaim:様々な資格に関するデジタルバッジを管理するサービス(?)、LinkedInなどの別SNSと連携できるので、このサービスでより簡単に資格の証明を共有できるようになったみたいです。
②AWS認定の本試験料金の半額クーポン
めちゃくちゃでかいですね。
アソシエイトレベルで税込16,500円、プロフェッショナルで税込33,000円とかするので。。③AWS認定の模擬試験料金の無料クーポン
こちらも大きい特典ですね。
模擬試験も種類によって2000〜4000円くらいかかるので、助かります。④LinkedInのAWS認定グローバルコミュニティへ参加できる
LinkedInの、認定者しか入れないコミュニティへ参加することができます。
正直あんまり有用性を感じていませんが、、、特別感あってなんか良いです!⑤AWS認定ストアを使える
AWSの公式グッズが買えます。
※2020/11/24時点でのラインナップ、調べると全然内容出てくるので載せてみます。
パーカーカッコいい・・・!!
でも現在はアメリカ内の住所にしか届けられないよう。。(コロナの影響かな。)
⑥AWS Certification SME Programへの参加資格が得られる。
一緒に試験の問題を作れたりするらしいです。
詳細はこちらの記事が参考になります!
まとめ
とりあえず、認定試験に合格すれば、
- ①認定デジタルバッジの取得
- ②AWS認定の本試験料金の半額クーポン
- ③AWS認定の模擬試験料金の無料クーポン
がもらえるんだ〜と認識いただければよいのかなと思います。
パーカー欲しかったなあ。
- 投稿日:2020-11-24T12:26:12+09:00
【AWSアカウント不要】ローカル環境でAWS CDKのデプロイ&動作確認をするチュートリアル
1. はじめに
1-1. この記事で行うこと
- LocalStackコンテナをセットアップし、動作確認
- Node.js環境コンテナ内にAWS CDKプロジェクトを作成
- AWS CDKプロジェクトをLocalStackへデプロイし、動作確認
1-2. この記事の対象者
- AWS CDKを本物のAWSを使わずに動かしたい方
- AWS CDKをすぐに捨てられる環境で色々と試してみたい方
- AWS CDKをブラウザのみで気軽に始めてみたい方
1-3. 動作環境
このチュートリアルはブラウザだけでDockerを使用可能なPlay with Dockerを使用しております。詳細な説明は以下の記事をご参考ください。
Docker 入門にはインストールなしで使える「Play with Docker」がいいと思うまた、Play with DockerではなくてもDockerが動く環境ならおそらく同じようにチュートリアル可能だと思います (が、この記事では手順等ございませんのでご了承ください)。
- 共通して必要なもの
- Docker Hubアカウント
- Play with Dockerで試す場合、必要なもの
- Play with Dockerを操作可能なブラウザ
- Play with Docker以外で試す場合、必要なもの
- Dockerをセットアップ済のPC等
1-4. 各種のバージョン
2020年11月24日時点で動作確認済のバージョンは以下の通りです。
- docker
- Docker version 19.03.11, build 42e35e61f3
- localstack
- 0.12.2
- aws-cli
- aws-cli/2.1.3 Python/3.7.3 Linux/4.4.0-189-generic docker/x86_64.amzn.2
- aws-cdk
- 1.74.0
- aws-cdk-local
- 1.65.0
2. チュートリアル
このチュートリアルではLocalStackというローカルでAWSを擬似的に使用できるツールを用います。詳しい説明は以下の記事をご参考ください。
LocalStack を使って無料で AWS を学ぶこのLocalStackのDockerコンテナ内に擬似的なAWS環境を立て、そこへAWS CDKをデプロイし、動作確認を行っていきます。
2-1. 最終的なファイル構成
いきなりですが、このチュートリアルが完了した状態のファイル構成です。
以下の「▶︎ 詳細」をクリックしてご確認ください。
$ tree -L 5 -I node_modules . ├── localstack │ ├── CHANGELOG.md │ ├── Dockerfile │ ├── LICENSE.txt │ ├── MANIFEST.in │ ├── Makefile │ ├── README.md │ ├── bin │ │ └── 略 │ ├── doc │ │ └── 略 │ ├── docker-compose.yml │ ├── localstack │ │ └── 略 │ ├── requirements.txt │ ├── setup.py │ └── tests │ └── 略 ├── node_workdir │ ├── Dockerfile │ ├── app │ │ └── sample │ │ ├── README.md │ │ ├── bin │ │ │ ├── sample.d.ts │ │ │ ├── sample.js │ │ │ └── sample.ts │ │ ├── cdk.json │ │ ├── cdk.out │ │ │ ├── SampleStack.template.json │ │ │ ├── cdk.out │ │ │ ├── manifest.json │ │ │ └── tree.json │ │ ├── jest.config.js │ │ ├── lib │ │ │ ├── sample-stack.d.ts │ │ │ ├── sample-stack.js │ │ │ └── sample-stack.ts │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── test │ │ │ ├── sample.test.d.ts │ │ │ ├── sample.test.js │ │ │ └── sample.test.ts │ │ └── tsconfig.json │ └── docker-compose.yml └── s3.txt
2-2. LocalStackのセットアップ
2-2-1. LocalStackをダウンロードする
[node1] (local) root@192.168.0.18 ~ $ git clone https://github.com/localstack/localstack Cloning into 'localstack'... remote: Enumerating objects: 44, done. remote: Counting objects: 100% (44/44), done. remote: Compressing objects: 100% (39/39), done. remote: Total 14028 (delta 15), reused 13 (delta 5), pack-reused 13984 Receiving objects: 100% (14028/14028), 5.75 MiB | 9.78 MiB/s, done. Resolving deltas: 100% (9762/9762), done.2-2-2. LocalStackコンテナを起動する
[node1] (local) root@192.168.0.18 ~ $ cd localstack [node1] (local) root@192.168.0.18 ~/localstack $ docker-compose up -d WARNING: The TMPDIR variable is not set. Defaulting to a blank string. Pulling localstack (localstack/localstack:)... latest: Pulling from localstack/localstack 1cff8f8f4790: Pull complete Digest: sha256:0e85ea6d44e3bf69a415298e72be46d06500ac038faebd98ea7bd9bcbcaab614 Status: Downloaded newer image for localstack/localstack:latest Creating localstack_main ... done [node1] (local) root@192.168.0.18 ~/localstack $ cd ..2-2-3. LOCALHOST_IP_ADDRESS変数を設定する
[node1] (local) root@192.168.0.18 ~ $ LOCALHOST_IP_ADDRESS=192.168.0.18 # 各自の環境によって異なります!後ほど、様々なコンテナ内からホストのIPアドレスを使用することになるので、先に変数として
LOCALHOST_IP_ADDRESS
を設定しておきます。
Play with Dockerの場合、root@192.168.0.18
の@
以降の192.168.0.18
を設定します (Play with Dockerでも毎回IPアドレスが固定ではないのでお気をつけください)。
それ以外の環境で試されている方は、各自で調べていただけると幸いです。2-2-4. LocalStackのステータスを確認する
[node1] (local) root@192.168.0.18 ~ $ curl "http://${LOCALHOST_IP_ADDRESS}:4566" {"status": "running"}https://github.com/localstack/localstack
2020-09-15: A major (breaking) change has been merged in PR #2905 - starting with releases after v0.11.5, all services are now exposed via the edge service (port 4566) only! Please update your client configurations to use this new endpoint.
(DeepLによる翻訳)
PR #2905 に主要な (壊すような) 変更がマージされました - v0.11.5 以降のリリースから、すべてのサービスがエッジサービス (ポート 4566) のみを介して公開されるようになりました! この新しいエンドポイントを使用するために、クライアントの設定を更新してください。公式githubにport 4566のみで動いてると書いてあるので、curlのポートに
:4566
を指定しています。
上手く動いていると{"status": "running"}
が返ってきます。2-2-5. Docker版aws-cliをaliasに登録する
[node1] (local) root@192.168.0.18 ~ $ alias awsd='docker run --rm -ti -v ~/.aws:/root/.aws -v $(pwd):/aws amazon/aws-cli'LocalStackは基本的にはGUIで操作できないのでaws-cliを使用する必要があります。
以下の記事を参考に設定しました。
AWS公式さんがDocker Hubで aws-cli のイメージを公開してくれた!
ちなみにawsd
(AWS Dockerの意味) は各自好きなように変更していただいても大丈夫です。2-2-6. Docker版aws-cliを起動し、バージョンを確認する
[node1] (local) root@192.168.0.18 ~ $ awsd --version Unable to find image 'amazon/aws-cli:latest' locally latest: Pulling from amazon/aws-cli 37373184fe69: Pull complete fc9d36ec628d: Pull complete 2ddf91b98617: Pull complete 9504c29fa015: Pull complete 21fd79a0d708: Pull complete Digest: sha256:8f8283ee998f26145569d411f986f1bdf0c56b1f4005077a22d94c7ed4561fb3 Status: Downloaded newer image for amazon/aws-cli:latest aws-cli/2.1.3 Python/3.7.3 Linux/4.4.0-189-generic docker/x86_64.amzn.2初回のDocker版aws-cli実行時にはDockerイメージのプルがまず実行されます。
そして、aws-cliのバージョンが表示されます。
ちなみに、2回目以降は以下のようにDockerイメージのプルが実行されずにDocker版aws-cliを使用できるようになります。[node1] (local) root@192.168.0.18 ~ $ awsd --version aws-cli/2.1.3 Python/3.7.3 Linux/4.4.0-189-generic docker/x86_64.amzn.22-2-7. LocalStack用のaws-cliのconfigureを設定する
[node1] (local) root@192.168.0.18 ~ $ awsd configure --profile=localstack AWS Access Key ID [None]: dummy AWS Secret Access Key [None]: dummy Default region name [None]: ap-northeast-1 Default output format [None]: json上記のように入力してください。
LocalStack用なのでAWS Access Key ID
とAWS Secret Access Key
は適当な値 (dummy
等) で大丈夫です。2-2-8. LocalStack用の情報入力を省略するaliasを設定する
[node1] (local) root@192.168.0.18 ~ $ alias awsdl="awsd --endpoint-url=http://${LOCALHOST_IP_ADDRESS}:4566 --profile=localstack"毎回
awsd --endpoint-url=http://${LOCALHOST_IP_ADDRESS}:4566 --profile=localstack
を入力しなくてもすむように、aliasを設定します。
ちなみにawsdl
(AWS Docker Localstackの意味) は各自好きなように変更していただいても大丈夫です。
なお、この記事ではこれ以降のawsコマンドはawsdl
となっています。2-3. LocalStackの動作確認
Amazon Simple Storage Service (以降、S3) へバケットを登録し、テキストファイルをアップロードできるかを確認します。
2-3-1. S3にバケットを登録する
[node1] (local) root@192.168.0.18 ~ $ awsdl s3 mb s3://test-s3 make_bucket: test-s32-3-2. S3のバケット一覧を取得する
[node1] (local) root@192.168.0.18 ~ $ awsdl s3 ls 2020-11-23 07:04:37 test-s32-3-3. S3へファイルをコピーする
[node1] (local) root@192.168.0.18 ~ $ echo "test text" > s3.txt [node1] (local) root@192.168.0.18 ~ $ awsdl s3 cp ./s3.txt s3://test-s3 upload: ./s3.txt to s3://test-s3/s3.txt2-3-4. 指定したS3のバケットのファイル一覧を取得する
[node1] (local) root@192.168.0.18 ~ $ awsdl s3 ls test-s3 2020-11-23 07:05:43 10 s3.txt2-4. Node.js環境のセットアップ
今回はAWS CDKをTypeScriptを使用して作成するので、Node.js環境が必要となります。
特別な理由はないですが、Node.js環境もDockerで準備していきます。2-4-1. Node.js環境作業ディレクトリを作成する
[node1] (local) root@192.168.0.18 ~ $ mkdir node_workdir && cd node_workdir [node1] (local) root@192.168.0.18 ~/node_workdir $ mkdir app2-4-2. Dockerfileを作成する
[node1] (local) root@192.168.0.18 ~/node_workdir $ vi Dockerfile以下のファイルの中身をコピペしてください。
DockerfileFROM node:14-alpine WORKDIR /app CMD ["sh"]2-4-3. docker-compose.ymlを作成する
[node1] (local) root@192.168.0.18 ~/node_workdir $ vi docker-compose.yml以下のファイルの中身をコピペしてください。
docker-compose.ymlversion: '3' services: app: build: . image: my-node-image volumes: - ./app:/app environment: - LOCALSTACK_HOSTNAME=${LOCALHOST_IP_ADDRESS} tty: trueenvironmentの
LOCALSTACK_HOSTNAME
は後ほど出てくるaws-cdk-localライブラリ内で必要となります。aws-cdk-local/bin/cdklocalから一部抜粋const getLocalEndpoint = () => { const port = process.env.EDGE_PORT || DEFAULT_EDGE_PORT; const host = process.env.LOCALSTACK_HOSTNAME || DEFAULT_HOSTNAME; return `http://${host}:${port}`; };2-4-4. Node.js環境作業ディレクトリの中身を確認する
[node1] (local) root@192.168.0.18 ~/node_workdir $ ls Dockerfile app docker-compose.yml3つの項目が表示されていたら、次の工程へ移りましょう。
2-4-5. Node.js環境コンテナを起動する
[node1] (local) root@192.168.0.18 ~/node_workdir $ LOCALHOST_IP_ADDRESS=$LOCALHOST_IP_ADDRESS docker-compose up -d Creating network "node_workdir_default" with the default driver Building app Step 1/3 : FROM node:14-alpine 14-alpine: Pulling from library/node cbdbe7a5bc2a: Pull complete f2ffd52523c3: Pull complete 48a445fb9d78: Pull complete 7a27e63388b2: Pull complete Digest: sha256:d41417bb7fd04744cd159a40632f918c13bc1af3486a848782e1f68af2c3e6cb Status: Downloaded newer image for node:14-alpine ---> 7f1893c3ede0 Step 2/3 : WORKDIR /app ---> Running in 47b57683cdda Removing intermediate container 47b57683cdda ---> 71423a0bee1b Step 3/3 : CMD ["sh"] ---> Running in e23e65a6f1f7 Removing intermediate container e23e65a6f1f7 ---> c695ce33957e Successfully built c695ce33957e Successfully tagged my-node-image:latest WARNING: Image for service app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating node_workdir_app_1 ... done
docker-compose up -d
コマンドの前にLOCALHOST_IP_ADDRESS=$LOCALHOST_IP_ADDRESS
の指定を忘れないようにお気をつけください。
コンテナの起動に成功するとCreating node_workdir_app_1 ... done
のように生成されたコンテナの名前が出力されます。2-4-6. Node.js環境コンテナの中に入る
[node1] (local) root@192.168.0.18 ~/node_workdir $ docker exec -it node_workdir_app_1 sh /app #先ほど生成されたコンテナの名前を指定して
docker exec
コマンドを実行します。
オプションに-it
を、コマンドにsh
を指定しているので、コンテナの中に入ることができます。
Dockerコンテナに入る方法については以下の記事をご参考ください。
docker exec -itって実際は何をしてるの?【90日目】なお、「2-5. AWS CDKプロジェクトの作成〜デプロイ」は、このコンテナの中に入っている状態で進めていきます。
2-5. AWS CDKプロジェクトの作成〜デプロイ
aws-cdkでプロジェクトを作成し、aws-cdk-localでLocalStackへデプロイしていきます。
2-5-1. aws-cdkとaws-cdk-localをグローバルインストールする
/app # npm install -g aws-cdk /usr/local/bin/cdk -> /usr/local/lib/node_modules/aws-cdk/bin/cdk + aws-cdk@1.74.0 added 188 packages from 186 contributors in 12.617s /app# npm install -g aws-cdk-local /usr/local/bin/cdklocal -> /usr/local/lib/node_modules/aws-cdk-local/bin/cdklocal + aws-cdk-local@1.65.0 added 189 packages from 187 contributors in 7.703s2-5-2. サンプルcdkプロジェクト用ディレクトリを作成し、移動する
/app # mkdir sample && cd sample2-5-3. サンプルcdkプロジェクトを作成する
/app/sample # cdk init sample-app --language=typescript Applying project template sample-app for typescript # Welcome to your CDK TypeScript project! You should explore the contents of this project. It demonstrates a CDK app with an instance of a stack (`SampleStack`) which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic. The `cdk.json` file tells the CDK Toolkit how to execute your app. ## Useful commands * `npm run build` compile typescript to js * `npm run watch` watch for changes and compile * `npm run test` perform the jest unit tests * `cdk deploy` deploy this stack to your default AWS account/region * `cdk diff` compare deployed stack with current state * `cdk synth` emits the synthesized CloudFormation template Initializing a new git repository... /bin/sh: git: not found Unable to initialize git repository for your project. Executing npm install... npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated request-promise-native@1.0.9: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^2.1.2 (node_modules/jest-haste-map/node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.2.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) npm WARN sample@0.1.0 No repository field. npm WARN sample@0.1.0 No license field. ✅ All done!
cdk init
コマンドで--language=typescript
を指定してTypeScriptでファイルが生成されるようにしています。
また、sample-app
と指定すると、簡単なサンプルを含んだプロジェクトが生成されます。出力の中に簡単なサンプルについての説明があります。You should explore the contents of this project. It demonstrates a CDK app with an instance of a stack (`SampleStack`) which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic.(DeepLによる翻訳)
このプロジェクトの内容を探ってみてください。スタック (SampleStack
) のインスタンスを持つ CDK アプリのデモを行います。
これは、Amazon SNSのトピックにサブスクライブされているAmazon SQSキューを含んでいます。生成された簡単なサンプルのソースコードを、ちょっとだけ見てみましょう。
/app/sample # vi ./lib/sample-stack.ts./lib/sample-stack.tsimport * as sns from '@aws-cdk/aws-sns'; import * as subs from '@aws-cdk/aws-sns-subscriptions'; import * as sqs from '@aws-cdk/aws-sqs'; import * as cdk from '@aws-cdk/core'; export class SampleStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const queue = new sqs.Queue(this, 'SampleQueue', { visibilityTimeout: cdk.Duration.seconds(300) }); const topic = new sns.Topic(this, 'SampleTopic'); topic.addSubscription(new subs.SqsSubscription(queue)); } }Amazon Simple Queue Service (以降、SQS) のキューとAmazon Simple Notification Service (以降、SNS)のトピックとサブスクリプションが定義されています。SNSトピックからメッセージを発行すると、サブスクリプションとして登録されているキューに登録されるようになっています。
2-5-4. TypeScriptファイルをJavaScriptファイルにトランスパイルする
/app/sample # npm run build > sample@0.1.0 build /app/sample > tscブラウザやNode.js環境はJavaScriptしか実行できないため、TypeScriptファイルをJavaScriptファイルへ必ず変換しましょう。
2-5-5. 初めてデプロイする場合、デプロイ用のS3バケットを作成する
/app/sample # cdklocal bootstrap ⏳ Bootstrapping environment aws://000000000000/us-east-1... CDKToolkit: creating CloudFormation changeset... [··························································] (0/3) ✅ Environment aws://000000000000/us-east-1 bootstrapped.2-5-6. LocalStackへデプロイする
/app/sample # cdklocal deploy This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening). Please confirm you intend to make the following modifications: IAM Statement Changes ┌───┬─────────────────────────┬────────┬─────────────────┬─────────────────────────┬───────────────────────────┐ │ │ Resource │ Effect │ Action │ Principal │ Condition │ ├───┼─────────────────────────┼────────┼─────────────────┼─────────────────────────┼───────────────────────────┤ │ + │ ${SampleQueue.Arn} │ Allow │ sqs:SendMessage │ Service:sns.amazonaws.c │ "ArnEquals": { │ │ │ │ │ │ om │ "aws:SourceArn": "${Sam │ │ │ │ │ │ │ pleTopic}" │ │ │ │ │ │ │ } │ └───┴─────────────────────────┴────────┴─────────────────┴─────────────────────────┴───────────────────────────┘ (NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299) Do you wish to deploy these changes (y/n)? y SampleStack: deploying... SampleStack: creating CloudFormation changeset... [··························································] (0/6) ✅ SampleStack Stack ARN: arn:aws:cloudformation:us-east-1:000000000000:stack/SampleStack/3b39e2b2-bb7d-42d0-9b36-d53e069c1451途中で
Do you wish to deploy these changes (y/n)?
と入力を求められるので、問題がなければy
を入力しましょう。2-5-7. Node.js環境コンテナから抜け出す
/app/sample # exit [node1] (local) root@192.168.0.18 ~/node_workdir $2-6. AWS CDKからLocalStackへデプロイされたリソースの動作確認
「リソースが生成されているか」と「SNSトピックからメッセージを発行し、サブスクリプションとして登録されているキューに登録されるか」を確認していきます。
2-6-1. SQSキューの一覧を取得する
[node1] (local) root@192.168.0.18 ~/node_workdir $ awsdl sqs list-queues { "QueueUrls": [ "http://localhost:4566/000000000000/queue-7f6ead47" ] }SQSキューがちゃんと生成されていますね。
ちなみに、QueueUrls
に表示されている値は各自の環境で異ります。2-6-2. 指定したSQSキューの詳細を取得する
[node1] (local) root@192.168.0.18 ~/node_workdir $ awsdl sqs get-queue-attributes --queue-url http://localhost:4566/000000000000/queue-7f6ead47 { "Attributes": { "ApproximateNumberOfMessages": "0", "ApproximateNumberOfMessagesDelayed": "0", "ApproximateNumberOfMessagesNotVisible": "0", "CreatedTimestamp": "1606116190.41501", "DelaySeconds": "0", "LastModifiedTimestamp": "1606116190.41501", "MaximumMessageSize": "262144", "MessageRetentionPeriod": "345600", "QueueArn": "arn:aws:sqs:us-east-1:000000000000:queue-7f6ead47", "ReceiveMessageWaitTimeSeconds": "0", "VisibilityTimeout": "300" } }
--queue-url
に指定する値は「2-6-1. SQSキューの一覧を取得する」で取得した各自の値を指定してください。
今回はとりあえず出力結果のうち、次の一項目だけ確認します。ApproximateNumberOfMessages
(キューから取得可能なメッセージのおおよその数) が"0"
になっていることが確認できましたでしょうか。2-6-3. SNSトピックの一覧を取得する
[node1] (local) root@192.168.0.18 ~/node_workdir $ awsdl sns list-topics { "Topics": [ { "TopicArn": "arn:aws:sns:us-east-1:000000000000:topic-cac07a20" } ] }SNSトピックもちゃんと生成されていますね。
TopicArn
も同様に表示されている値は各自の環境で異ります。2-6-4. 指定したSNSトピックへメッセージを発行する
[node1] (local) root@192.168.0.18 ~/node_workdir $ awsdl sns publish --message "test message" --topic-arn "arn:aws:sns:us-east-1:000000000000:topic-cac07a20" { "MessageId": "d06d6c48-fba9-4b8b-ab09-5f96e0784aef" }
--topic-arn
に指定する値は「2-6-3. SNSトピックの一覧を取得する」で取得した各自の値を指定してください。
発行に成功するとMessageId
が入ったJSONが返ってきます。2-6-5. 指定したSQSキューの詳細を取得し、ApproximateNumberOfMessagesを確認する
[node1] (local) root@192.168.0.18 ~/node_workdir $ awsdl sqs get-queue-attributes --queue-url http://localhost:4566/000000000000/queue-7f6ead47 { "Attributes": { "ApproximateNumberOfMessages": "1", "ApproximateNumberOfMessagesDelayed": "0", "ApproximateNumberOfMessagesNotVisible": "0", "CreatedTimestamp": "1606116190.41501", "DelaySeconds": "0", "LastModifiedTimestamp": "1606116190.41501", "MaximumMessageSize": "262144", "MessageRetentionPeriod": "345600", "QueueArn": "arn:aws:sqs:us-east-1:000000000000:queue-7f6ead47", "ReceiveMessageWaitTimeSeconds": "0", "VisibilityTimeout": "300" } }「2-6-2. 指定したSQSキューの詳細を取得する」と同じコマンドを実行しましょう。
ApproximateNumberOfMessages
(キューから取得可能なメッセージのおおよその数) が"1"
になっていたら、SNSトピックから発行されたメッセージがSQSキューに登録される処理がうまくいった証拠です!
- 投稿日:2020-11-24T09:13:12+09:00
【ほぼ無料】FreenomとLet's Encryptを使って0円でドメインとSSL証明書を手に入れて、AWS EC2にdockerを入れてnginxコンテナを起動してドメインで繋がるHTTPS WEBサービスを立ち上げる方法
経緯
何か業務で使う技術や新しい技術を試したいときにAWS上にWebサーバーを立ててAPIとかテストページとか用意して、ローカルのChromeやAndroid端末からhttpで繋いでごにょごにょやるってのを結構やる。
RestAPIの疎通確認ぐらいならそれでいいんだけど、WebRTCやWebSocketの検証で使いたい場合、SSL化されたサイトでないとエラーになって接続できないため動作確認が出来ない問題があった。
どうにかこうにか安価でオレオレ証明書じゃないWebサーバーを立てられないかなーと調べたところ、FreenomとLet's Encryptを使えばほぼ無料で独自ドメインのhttpsサーバーを立てられそうだと判明。Freenomでのドメイン取得方法やLet's EncryptでのSSL証明書取得方法、それらをAWSで設定するやり方等は探せば断片的にはあるけど、全部まとまった記事は無かったので、備忘録もかねてここに残しておく。
やること
- 【無料】Freenomで無料ドメインを取得する
- 【条件付無料】AWS EC2インスタンスを作成してdockerをインストールする
- 【条件付無料】AWS Elastic IPで静的IPアドレスを発行してEC2インスタンスに関連付ける
- 【ほぼ無料】AWS Route53でDNS設定を行いドメイン名でEC2インスタンスに繋がるようにする
- 【無料】dockerでEC2インスタンスにnginxコンテナを立ち上げる
- 【無料】Let's Encryptで無料SSL証明書を取得してhttpsで繋がるようにする
無料の条件とほぼ無料の詳細
- AWS EC2インスタンスは無料利用枠を使用する
- 無料利用枠と記載のあるAmazonマシンイメージ(AMI)は月に750時間無料で使える。今回はそれを使うことで無料とする
- ElasticIPで割り当てたEC2インスタンスは起動したままにしておく
- ElasticIPで発行したIPアドレスがEC2インスタンスに関連付けされていない場合は課金が発生する。いくら課金されるかは調べていないがわずかであるらしい。こういう仕組みになっているのは無駄にIPアドレスを確保されるのを防ぐためだろう。
- AWS Route53では月に0.5$課金される
1. 【無料】Freenomで無料ドメインを取得する
早速やっていきます。ドメインはFreenomというサービスを使って取得します。Freenomとは、ドメインを無料で取得出来る海外のサービスです。ドメイン名は、XXXX.tkやXXXX.ml、XXXX.ga等が無料で取得できます。
https://www.freenom.com/ja/index.htmlドメインが使えることを確認し、チェックアウトする
好きなドメインを取得することが出来ますので、取得したいドメインを入力しましょう。利用可能か調べてくれて利用可能であれば以下のような画面になりますので「今すぐ入手!」を押下した後、「チェックアウト」を押下します。
使用期間を選択する
12ヵ月まで無料で使えるようですので、最大限使用させていただきましょう。Periodで「12 Months @ FREE」を選択して「Continue」を押下します。
ユーザー登録 or ログイン
金額が$0.00USD(無料)なのを確認します。問題なければ購入のためログインします。
私の場合は既に登録済みなので、普通にGoogleでログインします。
初回登録してないと、いろいろ登録しないといけないかもしれません。
規約に同意して購入
再度、金額が$0.00USD(無料)なのを確認してから、規約に同意のチェックを入れ、「Complete Order」を押下します。
これにてドメインの取得は完了しました。
2. 【条件付無料】AWS EC2インスタンスを作成してdockerをインストールする
こちらは私が書いた別の記事がそのまま使用できますので、こちら↓を参照ください。
AWS EC2インスタンスにdockerとdocker-composeをインストールして簡単なWEBサービスを立ち上げる方法
3. AWS Elastic IPで静的IPアドレスを発行してEC2インスタンスに関連付ける
静的IPアドレス(固定IPアドレス)を取得し、上記で起動したEC2インスタンスにそのIPアドレスを割り当てます。こうすることで、EC2を再起動したりしてもIPアドレスが変わることは無くなります。
静的IPアドレスを取得する
まずは画面操作して静的IPアドレスを取得します。
「Elastic IP」を押下し、
次の画面で「Elastic IP アドレスの割り当て」を押下します。
次の画面で「割り当て」を押下します。
静的IPアドレスが取得できました。
EC2インスタンスに静的IPアドレスを関連付ける
割り当てられたIPアドレスを選択状態にして「アクション」内の「Elastic IPアドレスの関連付け」を押下します。
インスタンスには、先ほど作成したEC2のインスタンスIDを入力します。
入力したら「関連付ける」を押下します。
EC2インスタンスと静的IPアドレスの関連付けが完了しました。
4. 【ほぼ無料】AWS Route53でDNS設定を行いドメイン名でEC2インスタンスに繋がるようにする
ドメイン名で繋がるようにDNS設定を行います。
ホストゾーン作成→Aレコード登録→FreenomでNameserver設定という手順になります。ホストゾーンの作成
Route53の画面に行き、
「ホストゾーン」を押下します。
「ホストゾーンの作成」を押下します。
Freenomで取得したドメインを入力して「ホストゾーンの作成」を押下します。
ホストゾーンの作成が完了しました。
Aレコードの作成
「レコードの作成」を押下します。
シンプルルーティングがデフォルト選択されているのを確認して「次へ」を押下します。
「シンプルなレコードを定義」を押下します。
値/トラフィックのルーティング先で「レコードタイプに応じたIPアドレスまたは別の値」を選択した後、先ほど取得した静的IPアドレスを入力して、「シンプルなレコードを定義」を押下します。
レコードの作成を押下します。
レコードの作成が完了しました。
Nameserverの設定
今度はFreenomでNameserverの設定を行います。
「My Domains」を押下し、次の画面で「Manage Domain」を押下します。
「Management Tools」の「Nameservers」を押下します。
「Use custom nameservers(enter below)」を選択、Nameserver欄にはRoute53 ホストゾーンのNSレコードの値をコピペします。
入力したら「Change Nameservers」を押下します。
この時点で数分経過すると、DNSが浸透して行って「http://ドメイン名」でサイトが表示されるようになっているかと思います。
5. 【無料】dockerでEC2インスタンスにnginxコンテナを立ち上げる
6. 【無料】Let's Encryptで無料SSL証明書を取得してhttpsで繋がるようにする
5と6は一気にやっちゃいます。
いろいろやり方はあるかと思いますが、以下構成でdockerを使用してやってみます。
- reverse-ploxyコンテナをインターネットに公開し、https通信を受け付けます。
- reverse-ploxyコンテナからwebコンテナへ通信を転送、webコンテナではreverse-ploxyからhttp通信を受け付けます。
全てのdockerを停止しておく
誤動作防止のため、作業前に一度全てのdockerコンテナを止めて、dockerオブジェクトも全部削除しておくといいでしょう。
docker stop $(docker ps -q) docker system prune -awebコンテナの作成と起動
homeディレクトリ配下にwebディレクトリを作成し、必要な構成ファイルを作成します。
cd mkdir web
ディレクトリ配下とファイルの内容は以下のような構成にしました。
ディレクトリ構成web - html - index.html # hogeとでも書いておく - docker-compose.ymldocker-compose.ymlversion: '3' services: web: image: nginx:latest container_name: web volumes: - ./html:/usr/share/nginx/html作成が終わったらdockerコンテナを起動します。
docker-compose up -d --build起動したことを確認します。
docker-compose ps Name Command State Ports ------------------------------------------------------ web /docker-entrypoint.sh ngin ... Up 80/tcp
reverse-ploxyコンテナの作成と起動
homeディレクトリ配下にreverse-ploxyディレクトリを作成し、必要な構成ファイルを作成します。
cd mkdir reverse-ploxy
ディレクトリ配下とファイルの内容は、悪戦苦闘の結果、以下のような構成にしました。
ディレクトリ構成reverse-proxy - reverse-proxy - default.conf - Dockerfile - entrypoint.sh - docker-compose.ymldefault.confserver{ server_name y-do.tk; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://web/; } }DockerfileFROM nginx COPY default.conf /etc/nginx/conf.d/default.conf RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime RUN apt-get update && apt-get install -y \ wget cron && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* ADD https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /usr/local/bin/wait-for-it.sh RUN chmod +x /usr/local/bin/wait-for-it.sh ADD https://dl.eff.org/certbot-auto /usr/local/bin/certbot-auto RUN chmod a+x /usr/local/bin/certbot-auto RUN certbot-auto --os-packages-only -n COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"]entrypoint.sh#!/bin/bash # hogehoge@example.comはメールアドレス certbot-auto --nginx -d y-do.tk -m hogehoge@example.com --agree-tos -n certbot-auto renew # cron job settings # Let's Encrypt automatic Renew echo '0 8 * * * certbot-auto renew --post-hook "nginx -s reload"' >> /cron-tmpfile crontab /cron-tmpfile rm /cron-tmpfile # cron start /etc/init.d/cron start /bin/bashdocker-compose.ymlversion: '3' services: reverse-proxy: build: ./reverse-proxy tty: true container_name: reverse-proxy logging: driver: "json-file" options: max-size: "10m" max-file: "3" ports: - "80:80" - "443:443" volumes: - '/srv/letsencrypt:/etc/letsencrypt' command: ["wait-for-it.sh", "web:80"] networks: - default - web_default networks: web_default: external: true作成が終わったらdockerコンテナを起動します。
docker-compose up -d --build起動したことを確認します。
docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------- reverse-proxy entrypoint.sh wait-for-it. ... Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
インターネットからhttpsで繋がるようにAWSでセキュリティグループを更新する
FWで弾かれているため、まだインターネットからhttps通信を受け付けることが出来ません。
AWSのセキュリティグループのインバウンドルールを修正します。ルールを追加して、タイプ「HTTPS」、ソースは「0.0.0.0/0」を入力します。
入力したら「ルールを保存」を押下します。動作確認
ここまでやってやっとhttpsで通信が出来るようになっているはずです。アクセスしてみます。
アクセス出来た!!!
結果
月額0.5USDで独自ドメインのSSLサイトが運用できる。
ただし、ドメインは12ヵ月、SSL証明書は3か月で有効期限が切れる(無料だから文句は言えない)ので、今後は自動更新の仕組みを導入したい
- 投稿日:2020-11-24T08:20:20+09:00
S3の画像データを無理やりBlob型に変換する方法
なにこれ
S3の画像データをBlob型にしたい!っていう珍しい状況になった時の解決策です。
Vue(Nuxt)で下記のように'Content-Type': 'multipart/form-data'
で送りたい!って時に遭遇する可能性が高そうです。
test.js
const response = await this.$axios.put(`/hoges/${this.hoge.id}`, req, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
どうやるか
axiosを利用します
axiosでs3のURLをgetして、その時にresponseをblobで受け取ります。
受け取ったresponseを使って、new BlobでBlob型に変換します。test.jsimport axios from 'axios' // 〜省略〜 const req = new FormData() try{ const response = await axios.get(S3のURL, { responseType: 'blob' }) const blobData = new Blob([ response.data ], { type: "image/png" }) req.append(`image`, blobData) } catch (error) { console.error(error.response) }その後は肉なり焼くなり好きに処理してください!
- 投稿日:2020-11-24T03:11:41+09:00
AWSでクソアプリのアーキテクチャを2週間でガチガチに改修した
AWS雰囲気使いを卒業するために、既存アプリのアーキテクチャを
2週間で結構強固なものに改造してみたので改造前と改造後、そして将来的に実装したいFuture workを書き残しておこうと思います。(ほとんど自己満足で行ったので、必要以上のことをしてしまっている部分があったり、説明を省いている部分があります。)
既存アプリの詳細
今回改造することにしたアプリケーションは非同期でチャットができるようなwebアプリで、いわゆるL○NEやカカ○ークのようなチャットアプリのwebブラウザバージョンと思っていただけたらと思います。
改造前は、2つのAZ上のpublic subnetにおいたEC2(t2micro)をロードバランサーに設定したうえ、単一のRDSをprivate subnetに置いただけの設計で、ストレージもそれぞれのEC2インスタンス(Ruby on Rails内)が保持し、DBに画像ファイルのパス名を格納しているというもはや完全に不具合とも捉えられる状態でした。
このままではユーザー数が増えた際のEC2インスタンスのサーバーダウンが容易に考えられ、またDBのフェイルオーバー、スケールアップ等もカバーされていない状態です。
他にも、インフラをdockerを用いて殆ど手動で管理していて、サーバーを起動するのにそれぞれのインスタンス内に接続してdocker-compose upしないといけないような、色々と管理コストの高いアプリケーションでした。
改善したポイント
2週間で実装できる範囲で最低限アプリケーションを強固なものし、また今後のインフラの管理コストをできるだけ下げるべく、ほとんどの管理工程の自動化を試みました。
- ストレージにS3の導入
- EC2スケーリング, 復旧, ストレージ最適化等の自動化
- Auroraの導入、DBスケーリングの自動化, キャッシュメモリの導入
- AWSリソースの管理をコード化(インフラ構築の自動化、CI/CDパイプラインの構築)
- システム状況を可視化
改善後アーキテクチャ
使用AWSリソース
- CloudFront
- S3
- ElastiCache
- Aurora
- Amazon SNS
- Code pipeline
- Code build
- Code deploy
- Cloud watch
- Compute optimizer
- Cloudformation
主な変更点
1.ストレージにS3の導入
2.EC2スケーリング, 復旧, ストレージ最適化等の自動化
3.DBスケーリングの自動化, キャッシュメモリの導入
4.AWSリソースの管理をコード化(インフラ構築の自動化)
5.システム状況を可視化1.ストレージにS3の導入
- 画像ファイルをS3に保管する →現状のコードを少し修正する必要がある
- バックアップのスナップショットもS3に保存
- アクセスはしないが消したくないデータ(ログなど)はS3 glacierに保存
まず、最低限ストレージをS3に統一します。
これをしないと、あるEC2インスタンスでアップロードされた画像が他のインスタンスからは表示されないといった不具合が生じます。また、後で説明するDBのバックアップもスナップショットしてS3に保存します。
さらに、アクセスはしないが消したくないデータ(ログなど)はS3 glacierに保存しておくとより低コストに抑えられるので、導入しました。
2.EC2スケーリング, 復旧, ストレージ最適化等の自動化
- Autoscalingによるスケーリング自動化
- Compute Optimizerでインスタンスタイプ, Autoscalingの最適化
- Cloudwatchアラーム設定でEC2インスタンス の自動復旧
- Amazon SNSによる障害、自動復旧の通知
今後ユーザー数が増えた際に、サーバーに対してリクエスト過多が発生してしまう可能性があります。その際にEC2のスケールアウトを自動化しておくために、Autoscalingを導入します。
また、現在はt2microを採用しているのですがこちらのインスタンスタイプの最適化もCompute Optimizerを導入することによって自動化することができます。
さらに、万が一EC2インスタンスが破損してしまった場合の対策として、Cloudwatchというサービスのアラーム設定をしておくと、EC2インスタンスを自動復旧をしてくれるようになります。
ここで念のため、Amazon SNSでEC2破損時にメールにて通知がくるように設定しておくと、即座に破損のお知らせが届くようになるので、予め設定しておきます。3.DBスケーリングの自動化, キャッシュメモリの導入
- Aurora MySQLの導入 →MySQLの5倍のスループット
- Amazon Aurora Auto Scalingで自動スケーリング
- キャッシュ(ElastiCache)で高速化
- DB故障時はAmazon SNSで即座に通知
- DBの冗長化
まずDBをより高性能なAuroraに変更しました。
現状RDSのMySQLを使用しているということで、モデル変更などの必要はなく、Aurora MySQLに代替することにそれほど作業コストはかかりませんし、 Auroraのデフォルト機能でS3にDBバックアップのスナップショットを保存してくれます。
また、 Aurora Auto Scalingで、自動スケーリングも対応させます。
これにより、DBの移行、管理コストをほぼ0にすることが実現できます。さらに、DBキャッシュであるElastiCacheを導入することで、データの読み込みを最適化します。
最後に、念のため別AZにAuroraをもう一つ設置しておきます。これによって万が一単一のデータセンターで災害がおきてしまった場合もアプリケーションを持続させることが可能になります。
ここまでいくと自己満足です。
4.AWSリソースの管理をコード化(インフラ構築の自動化)
- CloudFormation →コードでAWSリソースの管理
- Former2 →templateの自動生成
- CodeBuild →buildを自動化
- CodeDeploy →deployの自動化
- CodePipeline →パイプライン化しインフラ構築、デプロイを自動化
これまでインフラの構築を手動で行っていたのを自動化し、AWSリソース自体をコードで管理できるようにします。
ここでCloudFormationというサービスを利用するのですが、こちらはAWSのシステム構成をJSONで記述してテンプレート化し、構成の管理、修正、再利用を容易にするサービスのことです。
CloudFormationを導入する際には、システム構成を構築する際のテンプレートの作成に手間が少々かかってしまいがちですが、ここでサードパーティーであるFormer2が大活躍してくれます。これは既存のAWSのリソース情報を取得し、CloudFormation, Terraform, Troposphere のテンプレートを生成してくれるようなOSSで、利用しない手はありませんでした。
また、CodeBuild、CodeDeploy、CodePipelineを用いてCI/CDパイプラインを構築し、リリースプロセスを自動化しました。
5.システム状況を可視化
- Cloudwatchでシステム状況を可視化 →全体のシステムのどの部分に費用がかかっているか可視化
- CloudMapper(サードパーティ)によりアーキテクチャ図を自動で生成 →全体図が把握しやすく, 担当の引き継ぎなどが容易になる
Future work
今回は2週間という期間だったので実現しきれなかったものの、将来的に実現させてみたことを何点か最後に記させていただきます。
- サーバレス化
- NoSQLへの移行
- SPAの実現
- テスト
現段階では、大量同時接続に弱いRDBを用いていますが、将来的にはユーザー数の増加に伴いDynamoDBなどのNoSQLに移行することが望ましいと思っています。
また、現在EC2に保管しているアプリケーションを完全にS3に移すことでSPAも実現させたいです。
おまけとして、これらの移行がかなった際には、Locust等のツールを用いて負荷増大テストとかもやってみるのも夢です。