20210510のAWSに関する記事は28件です。

【ポートフォリオをECSで!】Rails×NginxアプリをFargateにデプロイするまでを丁寧に説明してみた(VPC作成〜CircleCIによる自動デプロイまで) 後編

概要 ↓前編 後編では、独自ドメインの取得〜CircleCIの自動デプロイの設定まで行いたいと思います。 【前編】 1.VPCの設定 2.RDSの設定 3.ECRの設定 4.ECSの設定 【後編】 5.独自ドメインの設定(お名前ドットコム) 6.ACMの設定 7.ALBの設定 8.CircleCIの設定 5.独自ドメインの取得(お名前ドットコム) 前編でパブリックIPでFargateにデプロイしたアプリにアクセスできましたが、ここから独自ドメインを使ってアクセスできるように設定していきます。 以下のお名前ドットコムにアクセスして独自ドメインの設定をしていきましょう。 5.1 独自ドメインの設定 お名前ドットコムにアクセスしたら検索バーに取得したいドメインを入力し検索ボタンを押します。 筆者はmodern-tech.workを選択しました。 次に希望のドメインにチェックを入れてください。2のサーバーは利用しないを選択してください。 お申し込む内容確認画面に飛ぶので、ログインして購入画面に進みます。Whoisメールとドメインプロテクションは好みに合わせてチェックしてください。はじめの利用する場合は初めてご利用する方を選択して、登録を行ってください。 支払い方法を登録して申し込むをクリックすることで申し込みが完了します。 ※ ドメインを取得して一定時間後、ドメインの取得認証のメールアドレスが登録したメールアドレス宛に送信されます。 こちらの認証がメールが届いてから2週間以内に行われない場合、ドメインが使用不可になってしまいますので注意してください。 (筆者はこちらが原因でサーバーが止まり原因特定にかなりの時間を要しました汗) この後、以下のお名前ドットコム.naviにアクセスして操作をしていきますのでリンクを他のタブで開いておいてください。 5.2 Route53のホストゾーンの設定 Route53のホストゾーンの設定を行います。 AWSに戻り、サービスからRoute53を選び、Route53→ホストゾーン→ホストゾーンの作成で選択します。 そして以下のように設定をし、ホストゾーンの作成をクリックします。 タグ 値 ドメイン名 お名前ドットコムで取得したドメイン名 説明 適当 タイプ パブリックホストゾーン 5.3 ネームサーバーの設定 5.2で作成したホストゾーンを選択して詳細画面に飛んでください。 タイプがNSのルーティング先4つを最後の.を省いてコピーしてください。 例えば、xxx-00.org.であればxxx-00.orgという感じです。 コピーが終わったら他のタブで開いておいたお名前ドットコム.naviに移動します。 ドメイン→利用ドメイン一覧→取得したドメイン→ネームサーバー情報→ネームサーバーの変更で選択し、その他→その他ネームサーバーを使うより先程Route53でコピーした4つのネームサーバーを入力します。入力が完了したら確認をクリックしてください。 ネームサーバーの登録完了したら以下のコマンドをローカルターミナルで叩きRoute53のネームサーバーがドメイン名と紐付いているか確認してください。こちらは . が最後に入っています terminal dig 取得したドメイン名 NS +short 6.ACMの設定 AWS Certificate Manager(ACM)はSSL証明書発行サービスです。AWS内のサービスにSSLを適用させなければいけない制約はあるもののACM自体は無料で利用することができます。 6.1 ACMのリクエスト サービスからACMを検索し、ACM→証明書のリクエストを選択します。 パブリック証明書を選択して証明書のリクエストをクリックします。 ドメインの追加画面になったら以下のように設定を行います。 *.取得したドメイン名をドメイン名に追加することで、www.modern-tech.workのようなサブドメインを設定することが可能になります。これにより、サブドメインを設定することで無限にドメインを追加する事ができるようになります。 ドメイン名 取得したドメイン名 *.取得したドメイン名 検証の選択はDNSの検証を選択し次へをクリックします。 タグの追加で以下のようにタグを設定し確認をクリックします。 タグ 値 タグ名 sample-acm 確認画面に行くので、確定とリクエストをクリックしてSSL証明書の発行を行います。 検証保留中の画面になるので続行を押して検証が完了するまで待ちます。 6.2のRoute53のレコードの追加に使いますのでDNS設定をファイルにエクスポートを押してCNAMEレコードの設定ファイルをダウンロードしてください。 そして、取得したDNS設定ファイルのレコード名・レコードタイプ・レコードバリューの3つをコピーしてください。(取得したドメイン名と*.取得したドメイン名で同じになってるはずです) 6.2 ACMにCNAMEレコードを追加 Route53→ホストゾーン→取得したドメイン名を選択し、レコードを作成をクリックします。 タグ 値 レコード名 コピーしたレコード名のドメイン名より前の部分 レコードタイプ CNAME 値 コピーしたレコードバリュー(最後の.も含めます) 7.ALBの設定 ECSのクラスターを形成する際にロードバランサーが必要になります。 ロードバランサーとはサーバーに掛かる負荷を分散することで、1つあたりのサーバーに掛かる負荷を抑えるものです。 これにより、サーバー一つにかかる負荷が小さくなりサーバーダウンが防げます。 7.1 ALBのセキュリティグループの作成 VPC→セキュリティグループ→セキュリティグループの作成を選択します。 タグ 値 名前 sample-alb-security 説明 適当 VPC sample_vpc インバウンドルールは以下のようにhttp通信とhttps通信ができるように2つ設定します。 タグ 値 タイプ HTTP リソースタイプ 任意の場所 タグ 値 タイプ HTTPS リソースタイプ 任意の場所 アウトバウンドルールは以下のようにECSのセキュリティグループへのみ通信を制御するようにデフォルトの設定を削除して以下の設定を追加します。 設定が完了したらセキュリティグループを作成をクリックします。 タグ 値 タイプ HTTP 送信先タイプ カスタム 送信先 sample_ecs_security 7.2 ALBの作成 ※この作業はSSL証明書の発行が完了しないとできないためACMからリクエストした証明書が発行されていることを確認してから実行してください。 EC2→ロードバランサー→ロードバランサーの作成を選択します。 最終的に独自のドメインを取得し、HTTPS通信することを目標とするのでApplication Load Balancer(ALB)を選択します。 ロードバランサーの設定は以下のようにします。 アドオンサービスの設定はチェックせずに次の手順へ進みます。 タグ 値 名前 sample-alb リスナー HTTP, HTTPS(ポートは勝手に選択されます) VPC sample_vpc アベイラビリティゾーン ap-northeast-1a(sample_public_subnet1), ap-northeast-1c(sample_public_subnet2) ログ設定 ON セキュリティ設定の構成は以下のように設定します。 セキュリティポリシーはAWSで推奨されているデフォルトのELBSecurityPolicy-2016-08で次の手順に進みます。 タグ 値 証明書タイプ ACMから証明書を選択します 証明書の名前 発行した証明書 セキュリティグループの設定は7.1で作成したsample-alb-securityを選択して次の手順に進みます。 ルーティングの設定は以下のようにします。ヘルスチェックはルートパスで行われるように設定しています。設定が完了したら次の手順へ進みます。 タグ 値 ターゲットグループ 新しいターゲットグループ 名前 sample-target ターゲットの種類 IP プロトコル HTTP ポート 80 プロトコルバージョン HTTP1 ターゲットは登録せずに確認をして作成を行ってください。 7.3 ALBを含めたECSのサービスの作成 ECS→クラスター→sample-clusterを選択してくだい。 そして、前編の4章で作成したsample-serviceを削除して新しいサービスを作成します。sample-serviceを削除した後、サービス→作成を選択します。 サービス設定は以下のように行い次のステップに進みます。 タグ 値 起動タイプ FARGATE タスク定義 ファミリー sample タスク定義 リビジョン latest クラスター sample-cluster サービス名 sample-alb-service タスクの数 1 ネットワーク構成は以下のように行います。 タグ 値 クラスターVPC sample_vpc サブネット sample_public_subnet1 セキュリティグループ sample_ecs_security パブリック IP の自動割り当て ENABLED 今回はロードバランサーの設定も加えます。 タグ 値 ロードバランシング Application Load Balancer ロードバランサー名 sample-alb ロードバランス用コンテナにnginxが選択されていると思うのでロードバランサーに追加をクリックします。 その後、ターゲットグループ名をsample-targetとして次のステップに行きます。 Auto Scalingの設定は今回はしないでサービスを作成します。 サービスが起動するまで待ちましょう。 7.4 ドメインとロードバランサーの結びつけ 最後に独自ドメインからサービスにアクセスできるようにロードバランサーと結びつけをします。 Route53→ホストゾーン→取得したドメイン名→レコードの作成を選択します。 以下のように設定します。 タグ 値 レコード名 空 レコードタイプ A トラフィックのルーティング先 エイリアスON→Application Loadbalancer→ap-northeast-1→sample-alb また、サブドメインからもアクセスできることを確認するため以下のレコードもついでに追加します。 タグ 値 レコード名 www レコードタイプ A トラフィックのルーティング先 エイリアスON→Application Loadbalancer→ap-northeast-1→sample-alb ここまでの設定が完了したらhttp(s)://ドメイン名で検索してみてください。以下のようにアプリが開ければ成功です。 また、http(s)://www.ドメイン名でも同様にアプリが開けることを確認してください。 ※もし開けない場合、route53の設定が誤っていないか確認してみてください。また、ドメインがお名前ドットコムから発行されてからインターネットで使用できるようになるためタイムラグ(最大1日)が発生するのでしばらく待ってからアクセスを試みてください。 ルーティングの整備 httpsでの通信が確認できたらhttp通信があると暗号化されない通信に間違ってアクセスしてしまう可能性があるので、http通信を遮断します。 ALBのセキュリティグループのsample-alb-securityにアクセスしインバウンドルールの編集を選択します。 インバウンドルールが編集語に以下のようになっているのを確認してください。 再び、https://ドメイン名にアクセスしてアプリが表示されることを確認してください。また、http://ドメイン名にアクセスしてアクセスできなくなっていることを確認してください。 8.CircleCIの設定 最後にCircleCIの設定です。 こちらを設定することによりECSの自動てプロイが可能になります。 8.1 CircleCIのファイルを作成する 以下のようにCircleCIのファイルを作成してください。 今回はcircleciの自動デプロイをmasterブランチに限定しました。 .circleci/config.yml version: 2.1 orbs: aws-ecr: circleci/aws-ecr@6.15 aws-ecs: circleci/aws-ecs@2.0.0 workflows: # Nginxのデプロイ nginx-deploy: jobs: - aws-ecr/build-and-push-image: #AWS_ECR_ACCOUNT_URL => ${アカウントID}.dkr.ecr.${リージョン}.amazonaws.com account-url: AWS_ECR_ACCOUNT_URL # リージョン region: AWS_REGION aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY # ECRにリポジトリがなかったら創るか? create-repo: true # Dockerfleのパス(デフォルトはカレントディレクトリのパス) dockerfile: ./nginx/Dockerfile # ECRのリポジトリ repo: nginx-sample tag: "${CIRCLE_SHA1}" filters: branches: only: master - aws-ecs/deploy-service-update: requires: - aws-ecr/build-and-push-image # ECSのタスク定義名 family: 'sample' # ECSのクラスター名かARNのフルパス cluster-name: 'sample-cluster' # サービス名 service-name: 'sample-alb-service' # containerはタスク定義で設定したコンテナ名にする container-image-name-updates: "container=nginx,tag=${CIRCLE_SHA1}" # Railsのデプロイ rails-deploy: jobs: - aws-ecr/build-and-push-image: account-url: AWS_ECR_ACCOUNT_URL region: AWS_REGION aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY # ECRにリポジトリがなかったら創るか? create-repo: true dockerfile: ./Dockerfile.prod # ECRのリポジトリ repo: rails-sample tag: "${CIRCLE_SHA1}" filters: branches: only: master - aws-ecs/deploy-service-update: requires: - aws-ecr/build-and-push-image # ECSのタスク定義名 family: 'sample' # ECSのクラスター名かARNのフルパス cluster-name: 'sample-cluster' # サービス名 service-name: 'sample-alb-service' # containerはタスク定義で設定したコンテナ名にする container-image-name-updates: "container=rails,tag=${CIRCLE_SHA1}" 8.2 CircleCIの環境変数を設定 まずは以下のURLからCircleCIのプロジェクトにいき、Set Up Projectをクリックして対象のリポジトリをCircleCIが適用できるように設定します。 そして、環境変数に以下を設定します。 環境変数 値 AWS_ACCESS_KEY_ID IAMのアクセスキーID AWS_SECRET_ACCESS_KEY IAMのシークレットアクセスキー AWS_REGION ECR・ECSを作成したリージョン(ap-northeast-1) AWS_DEFAULT_REGION ECR・ECSを作成したリージョン(ap-northeast-1) AWS_ECR_ACCOUNT_URL {IAMのアカウントID(数字だけのやつ)}.dkr.ecr.{IAMのリージョン}.amazonaws.com 8.3 CircleCIの自動デプロイテスト 試しにヘッダーの色を黄色に変更してgithubにプッシュしてみます。 みなさんも自分のアプリの一部を変更して自動デプロイができるか確かめてみましょう。 変更が済んだら以下のようにコマンドを叩きgithubへプッシュします。 terminal git checkout master git add . git commit -m "ciecleci sample test" git push origin master CircleCIのダッシュボードに行き自動てプロイがsuccessになっているのを確認してください。 以下のようになっていれば成功です。 CircleCIの自動てプロイが完了しているのを確認したらhttp://ドメイン名にアクセスして変更が適用されているか確認しましょう。 これで全ての工程は終了です。お疲れさまでした。 もし、使わなくなった場合は結構お金を持っていかれるので作成した構成を削除してください。 おわり ここまで長かったですがECSの自動デプロイまで説明してきました。 AWSの構成の仕方で途中でエラーが出たり、不具合があった場合はコメントを残してくださると幸いです。 よかったらLGTMをお願いします!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ポートフォリオをECSで!】Rails×NginxアプリをFargateにデプロイするまでを丁寧に説明してみた(VPC作成〜CircleCIによる自動デプロイまで) 前編

概要 現在、運営しているサークルの公式サイトを作成しているのですがデプロイ環境をEC2からECSに引っ越しました。その際に、色々ハマりながらデプロイしたので、方法を忘れないために書きます。 この方法を真似ればFargateへのデプロイが再現できてるので、ぜひ活用してください。 以下のようなインフラ構成を想定しております。 【前編】 1.VPCの設定 2.RDSの設定 3.ECRの設定 4.ECSの設定 【後編】 5.独自ドメインの設定(お名前ドットコム) 6.ACMの設定 7.ALBの設定 8.CircleCIの設定 追記 sample_public_subnetがtypoで写真内でsample_pubnet_subnetとなっていました。sample_public_subnetだと思って進めてください。 前提 Dockerの環境とAWSでIAMを管理者権限で作成していること前提で話を進めます。また、筆者は以下のような技術を使っています。 名前 バージョン リージョン 東京 Docker 20.10.5 Ruby 2.6.5 Rails 6.1.3 (バージョン5でも可) PostgreSQL 9.6.2 注意点 今回のECSの構成をするに当たり、料金が発生します。 お金をかけたくない場合は、すぐに作ったネットワーク構成を削除してください。 1.VPCの設定 Amazon Virtual Private Cloud(VPC)は、AWSの提供する機能の1つで、プライベートな可塑のネットワークを構成できます。このネットワークの中で、仮想サーバ「EC2」など多くのAWSのサービスが起動します。このネットワーク内にEC2やRDSなどを起動させることでアプリケーションを構築することができます。そして、サブネットとはVPCによって作成されるcidrブロックを分割したネットワーク群のことです。サブネット内にEC2やRDSなどを設置します。 以下のような設計で構成します。 1.1 VPCを作成 AWSのサービスよりVPCを選択して、VPCの作成をクリックします。 その後、以下のように設定していきます。 タグ 値 名前 sample_vpc CIDRブロック 10.0.0.0/16 ※テナンシーとは物理的にハードウェアを占領したいかで、必要がないためデフォルトを選択しています。 1.2 サブネットの作成 VPC内にサブネットを構成します。 サービスからサブネットを選択して、サブネットの作成を押します。 そして、以下のようにプライベートサブネット2つとパブリックサブネット2つの4つのサブネットを構成してください。(プライベートサブネットはVPC内部でのみ通信可能なサブネット(送信先が10.0.0.0/16)のことで、パブリックサブネットは外部のインターネットから通信可能なサブネットのことです。1.3のインターネットゲートウェイの作成と1.4のルートテーブルの作成の時にプライベートとパブリックの作成方法の違いを説明します。) サブネットのCIDRブロックはVPCのCIDRブロックの16bit目(10.0)までは等しい必要があります。 それ以降は自由で構いません。 ECS用パブリックサブネット タグ 値 名前 sample_public_subnet1 AZ ap-northeast-1a CIDRブロック 10.0.0.0/24 タグ 値 名前 sample_public_subnet2 AZ ap-northeast-1c CIDRブロック 10.0.1.0/24 RDS用サプネット タグ 値 名前 sample_private_subnet1 AZ ap-northeast-1a CIDRブロック 10.0.10.0/24 タグ 値 名前 sample_private_subnet2 AZ ap-northeast-1c CIDRブロック 10.0.11.0/24 以下はsample_public_subnet1を作成しているときの画面です。 ※VPC IDには作成したVPC(sample_vpc)を選択してください。 1.3 インターネットゲートウェイの作成 インターネットゲートウェイとはVPCとインターネットの通信を可能にするもので、これを設定することによって誰のパソコンからも自分のVPC内のアプリにアクセスできるようになります。 以下の公式リファレンスに詳しい内容が記述されています。 インターネットゲートウェイのサービスを選択して、インターネットゲートウェイの作成を選択します。 タグ 値 名前 sample_igw 作成が終わったら、作成したインターネットゲートウェイにチェックを入れてアクションからVPCにアタッチするを選択します。 以下でsample_vpcが表示されるので選択します。 1.4 ルートテーブルの作成 ルートテーブルとはサブネットのインスタンスがどこと通信するのかを明示的に定めるものです。ルートテーブルの作成により、サブネットがVPC内のどこと通信できるのか、また外部と通信できるのかを選択できます。ここで、インターネットゲートウェイの通信ルールを入れるか否かで先ほど作成したサブネットをプライベートサブネットにするかパブリックサブネットにするかを決められます。 ルートテーブルの作成を選択し、以下のように設定を行います。 タグ 値 名前 sample_route VPC sample_vpc ルートテーブルの作成が完了したら、作成したルートテーブルを選択してアクション→ルートの編集を選択します。 VPCをインターネットから通信できるようにルールを編集するために全てのIPアドレスを選択する0.0.0.0を送信先に設定し、ターゲットにはInternet Gateway→先程作成したターゲットを選択します。 次に、サブネットとの関連付けを行います。 この操作をすることにより1.2で作成したECS用のサブネットをインターネットゲートウェイを介して外部と通信できるようにします。 作成したルートテーブルを選択してアクション→サブネットの関連付けの編集を選択します。 そうしたらsample_public_subnet1とsample_public_subnet2の2つを選択して保存を押します。 1.5 セキュリティグループの作成 セキュリティグループとはファイアウォール機能であり、インスタンスへのアクセスを許可したり、トラフィックを制御することができます。 以下ではECSとRDSのセキュリティグループを設計していきます。 ECSのセキュリティグループ 基本的な詳細 タグ 値 名前 sample_ecs_security 説明 適当 VPC sample_vpc インバウンドルール インバウンドルールはセキュリティグループに関連付けられたインスタンスへのアクセスを制限するルールです。 ※Fargateだとsshアクセスできないのでポート22番を解放する必要がありません。 タグ 値 タイプ HTTP リソースタイプ 任意の場所 アウトバウンドルール アウトバウンドルールはセキュリティグループに関連付けられたインスタンスからどの送信先にトラフィックを送信できるか決めるルールです。 変更なし RDSのセキュリティグループの作成 基本的な詳細 タグ 値 名前 sample_rds_security 説明 適当 VPC sample_vpc インバウンドルール こちらはECSのセキュリティグループからのみアクセスできるように設定します。 ※MySQLや他のデータベースを使用する人は、自分のデータベースにあったタイプを選択してください。 タグ 値 タイプ PostgreSQL リソースタイプ カスタム ソース sample_ecs_security アウトバウンドルール 変更なし 2.RDSの設定 ここからRDS周りの設定に移ります。 Amazon Relational Database Service (RDS)は、AWSのデータベース機能です。こちらを使用することにより、Amazon Aurora、PostgreSQL、MySQL、MariaDB、Oracle データベース、SQL Serveといったデータベースを簡単にセットアップできます。 AWSのアカウントを作成してはじめの1年間は無料枠を使用することによりお金をかけず使用することができます。 2.1 RDS用サブネットグループの作成 RDSの作成には2つ以上のサブネットを束ねたサブネットグループを作成する必要があります。 1.2のサブネットの作成の際に、RDS用のサブネットのAZにap-northeast-1aとap-northeast-1cの2つを選択しているため、マルチAZにできます。(マルチAZとは複数のAZを使用する構成のことで、1つのAZでしょうが板起きても他のAZで稼働を続けることができるため可用性が向上します。) サービス検索よりRDSを検索し、サブネットグループのを選択します。すると、DBサブネットグループを作成をクリックし以下のように設定します。 サブネットグループの詳細 タグ 値 名前 sample_rds_subnet_group 説明 適当 VPC sample_vpc サブネットを追加 タグ 値 アベイラビリティゾーン ap-northeast-1a, ap-northeast-1c サブネット 1.2で作成したRDSのサブネットをそれぞれのAZで選択 2.2 RDSの作成 次にRDSを作成します。 RDSを検索後、データベースを選択します。すると、データベースの作成という項目があるのでクリックして以下のように設定を行います。 タグ 値 エンジンのオプション PostgreSQL(自分の使っているDB) サブネット バージョン(自分の使っているDBのバージョン(異なると動作しない可能性があるのでバージョンによる差異があるのか調べたほうがいいかも)) タグ 値 DBインスタンス識別子 sample-db マスターユーザー名 postgres マスターパスワード 自分で決める DBインスタンスサイズ db.t2.micro(無料枠) タグ 値 ストレージタイプ 汎用(SSD) ストレージ割り当て 20 ストレージの自動スケーリング 有効 最大ストレージしきい値 1000 タグ 値 VPC sample_vpc サブネットグループ sample_rds_subnet_group パブリックアクセス可能 なし VPCセキュリティグループ 既存の選択 既存のVPCセキュリティグループ sample_rds_security アベイラビリティゾーン 指定なし エンドポイントはメモしておいてください。 3.ECRへイメージのプッシュ Amazon Elastic Container Registry (ECR)はDockerイメージのレジストリサービスです。 ここからECRへ自分のDockerイメージのプッシュを行っていきます。 3.1 ECRのリポジトリの作成 まずはDockerイメージをプッシュするためのリポジトリを作成します。 このリポジトリでDockerイメージのバージョン管理を行います。少しGithubに似てますね笑 まずは、Rails用のリポジトリを作成します。 以下のように設定します。 タグ 値 可視性設定 プライベート リポジトリ名 rails-sample 同様にして、nginxのリポジトリを作成してください。 タグ 値 可視性設定 プライベート リポジトリ名 nginx-sample 3.2 Dockerfileの確認 (1) Rails Dockerfileの中身 筆者のDockerfileの中身は以下のようになっています。 Dockerfile(Rails) FROM ruby:2.6.5 # 以下の記述を追加 ENV RAILS_ENV=production RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - && apt-get update && \ apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/* RUN apt-get update -qq && apt-get install -y build-essential libpq-dev sudo vim RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn && apt-get install imagemagick RUN yarn add node-sass WORKDIR /app RUN mkdir -p tmp/pids RUN mkdir -p tmp/sockets COPY Gemfile /app/Gemfile COPY Gemfile.lock /app/Gemfile.lock COPY yarn.lock /app COPY package.json /app RUN bundle install # ここでyarn installをしないとwebpackerを実行できない RUN yarn install COPY . /app # RUN yarn add jquery popper.js bootstrap # WARNING:webpack:installをするとwebpackの設定ファイルが初期化されてjqueryなどが使えなくなってしまう # RUN rails webpacker:install RUN NODE_ENV=production ./bin/webpack COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] # 以下の記述があることでnginxから見ることができる VOLUME /app/public VOLUME /app/tmp CMD bash -c "rm -f tmp/pids/server.pid && bundle exec puma -C config/puma.rb" ※webpackerを使っていますが、sprocketsを使っている場合はrake assets:precompileで置き換えてください。 ポイントとしては、Dockerfile内でVOLUMEを設定することで、nginxコンテナからrailsコンテナのsockファイルが見えるようにしてください。 VOLUME /app/public VOLUME /app/tmp またentrypoint.shにdbのマイグレーションなどを行う設定をしてください。 ※ 2回目以降のタスク実行時にはdb:createとdb:seedを行うとエラーになるのでコメントアウトしてください。 entrypoint.sh #!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /app/tmp/pids/server.pid # WARNING:createとseedはfargateの初回のみ実行 # WARNING:タスクを個々に作って実行の方がいいかも bundle exec rails db:create bundle exec rails db:migrate bundle exec rails db:seed # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@" (2) nginx Dockerfile(nginx) FROM nginx:1.16 RUN apt-get update && \ apt-get install -y apt-utils \ locales && \ echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \ locale-gen ja_JP.UTF-8 ENV LC_ALL ja_JP.UTF-8 # 初期状態の設定ファイル ADD ./nginx/nginx.conf /etc/nginx/nginx.conf ADD ./nginx/default.conf /etc/nginx/conf.d/default.conf 3.3 ECRの設定 まずはRailsのイメージをプッシュします。 先程作成したsample-railsというリポジトリを選択するとプッシュコマンドの表示からプッシュコマンドを確認します。 こういう感じでコマンドが出てくると思います。 terminal # awsのログイン aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${IAM_ID}.dkr.ecr.ap-northeast-1.amazonaws.com # dockerイメージのビルド docker build -t rails-sample . --no-cache # dockerイメージのタグ付け docker tag rails-sample:latest ${IAM_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/rails-sample:latest # dockerイメージをECRのリポジトリへプッシュ docker push ${IAM_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/rails-sample:latest ※ aws-cliが入っていない場合は以下のリンクよりaws-cliのインストールを行ってください。 ※ dockerファイルがカレントディレクトリでDockerfileでない場合は、以下のように-fのオプションを付けることでDockerファイル名とパスを選択してください。 (例) nginxディレクトリにあるDockerfile.nginxというdockerファイルを選択したい場合 terminal docker build -f ./nginx/Dockerfile.nginx -t sample-rails . --no-cache 同様にnginxのイメージについても同様の手順でECRのリポジトリへプッシュをしてください。 さらに、リポジトリへプッシュできたことが確認できたら、URIをそれぞれコピーして控えておいてください。(ECSのタスク定義で使います。) 4.ECSの作成 遂にECSの作成に入ります。 Amazon Elastic Container Service (ECS) はクラスターでコンテナをスケーラブルに実行、停止、管理できるサービスです。 簡単に言うと、クラスターと呼ばれる複数のコンテナを束ねることができる基盤の上でコンテナを実行し、サービスを構成するサービスと考えるとわかりやすいかも知れません。 4.1 タスクの作成 ECSのタスクとはコンテナを組み合わせやボリュームの設定などサービスを動作させるための設定を行う部分です。 docker-compose.ymlの役割に似ているかも知れません。 ECS→タスク定義→新しいタスク定義の作成を選択し、タスクの作成を行いましょう。 起動タイプはFARGATEを選択してください。 タグ 値 タスク定義名 sample タスクロール なし タスク実行ロール ecsTaskExecutionRole タスクロールとはECS上のコンテナ中のアプリケーションのIAMロールのようなものでコンテナ中のアプリケーションが他のサービス(S3やElastic Searchなど)にアクセスする権限を設定することができます。 対してタスク実行ロールとはタスク定義がAWSのサービスを利用するためのルールで、タスクのログをCloud Watchに出力したり、ECRのコンテナイメージを使用するために用いられます。 ↓参考 タグ 値 タスクメモリ 0.5GB タスクCPU 0.25vCPU タスクメモリとタスクCPUについては料金を最小限にするために上の設定にしていますが、自分のサービスの規模に合わせて変更してください。 次にコンテナの追加を行います。 railsコンテナとnginxコンテナの2つを追加します。 (1) Railsコンテナ タグ 値 名前 rails イメージ ECRの作成の際メモしたsample-railsのリポジトリURI ポートマッピング 3000 環境変数 docker-compose.ymlや.envに設定している環境変数(RAILS_MASTER_KEYがCircleCIデプロイをする際に必要になるのでmaster.keyの値を入れておいてください) ログ設定 ON (2) Nginxコンテナ ポイントはボリュームソースにRailsコンテナのコンテナ名(今回の場合はRailsコンテナに付けた名前のrails)を設定しています。 これにより、railsコンテナのsockファイルをnginxコンテナから見ることができるようになります。 タグ 値 名前 nginx イメージ ECRの作成の際メモしたsample-nginxのリポジトリURI ポートマッピング 80 ボリュームソース rails ログ設定 ON 残りはデフォルトで作成を押します。 以下のようにsample-taskのステータスがActiveになっていればタスク定義成功です。 4.2 クラスターの作成 次にクラスターの作成を行います。 ECS→クラスター→クラスターの作成を選択する。 Fargateを使ってデプロイするのでネットワーキングのみを選択します。 選択したら次のステップへをクリックします。 クラスターの設定は以下のように行います。 そして作成をクリックします。 タグ 値 名前 sample-cluster CloudWatch Container Insights OFF 4.3 サービスの作成 クラスターが作成できたらサービスを選択し、作成をクリックします。 サービス設定は以下のように行います。今回は料金を最小にするためにタスクの数を1にして行いたいと思います。 設定が終わったら次のステップをクリックします。 タグ 値 起動タイプ FARGATE タスク定義 ファミリー sample タスク定義 リビジョン latest クラスター sample-cluster サービス名 sample-service タスクの数 1 (概要で説明した編成のようにALBによって負荷分散するためには2以上にする必要があります) ネットワーク構成は以下のように行います。 まだ独自ドメインを取っていないためALBを設定していないので今回はロードバランサー無しで次のステップへ進みます。 タグ 値 クラスターVPC sample_vpc サブネット sample_public_subnet1 セキュリティグループ sample_ecs_security パブリック IP の自動割り当て ENABLED Auto Scalingは今回は調整しない設定にします。 選択したら次のステップへ進みます。 最後に確認画面になりますので、内容を確認したらサービスの作成をクリックしてサービスを起動します。 タスクがRUNNINGになっているのを確認したら、railsのLogsを確認して以下の一番下のログのようにdatabaseが作成されているのを確認してください。 ※ データベースとの連携ができない場合、以下のような原因が考えられます。 ① ユーザー名かパスワードが誤っている ② RDSのエンドポイントが間違ってる ③ RDSのインバウンドルールにECSのセキュリティグループが設定されていない ①②の対処法はRDSサービスに一度アクセスしてユーザー名とエンドポイントがあっているか確認してください。パスワードは確認ができないため変更からパスワードの変更を行ってください。 ③の場合はRDSのセキュリティグループのインバウンドルールにECSのセキュリティグループが設定されているか確認してください。また、インバウンドルールのタイプがPostgreSQLになっているか確認してください どちらかわからない場合は、一度RDSのセキュリティグループのソースを任意の場所(0.0.0.0)に変更してタスクを再度実行してください。(確認が終わったらセキュリティ上の問題からすぐにソースをもとに戻してください) ↓のようになっていれば③はOK 4.4 サービスの再作成 4.3でデータベースの作成が終わったので以下のようにentrypoint.shをdb:createとdb:seedをコメントアウトします。 entrypoint.sh #!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /app/tmp/pids/server.pid # WARNING:createとseedはfargateの初回のみ実行 # WARNING:タスクを個々に作って実行の方がいいかも # bundle exec rails db:create bundle exec rails db:migrate # bundle exec rails db:seed # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@" その後、ECRのリポジトリに移動しrails-sampleを選択します。 イメージタグがlatestのものを削除します。 削除が終わったら再度ECRにentrypoint.shを変更したコンテナをプッシュします。 キャッシュが残っているとコンテナの内容が変更されていない可能性があるので --no-cacheは必ず付けてbuildを行ってください。 次にタスク定義の変更を行います。 タスクsampleに移動して最新のリビジョンを選択して新しいリビジョンの作成をクリックします。(筆者は一度データベースの生成に失敗しているためリビジョンが2になっていますが皆さんの場合は最新が1になっているはずです) タスク内部に移動したら一度railsコンテナを削除して再度コンテナの追加より設定を行ってください。設定内容は変わらず以下のように行います。 タグ 値 名前 rails イメージ ECRの作成の際メモしたsample-railsのリポジトリURI ポートマッピング 3000 環境変数 docker-compose.ymlや.envに設定している環境変数(RAILS_MASTER_KEYがCircleCIデプロイをする際に必要になるのでmaster.keyの値を入れておいてください) ログ設定 ON 次にクラスターに移動します。 クラスターsample-clusterを選択し、サービス名sample-serviceを選択してください。 そうしたらリビジョンを最新に変更してあとは同じままサービスを更新します。 サービスの更新が完了したらしばらく待って以下のようにタスクからタスク定義が最新になっているのとステータスがRUNNINGになっているのを確認します。 確認が終わったらタスク定義をクリックします。 パブリックIPを確認できるのでアクセスします。 以下のように自分のサービスがパブリックIPからアクセスできることが確認できるはずです。 仮にアクセスできない場合以下の可能性があります。 ①タスク定義のLogsからnginxとrailsのコンテナでエラーが起きている ②タスク定義のサブネットIDをコピーしてVPC→サブネット→ルートテーブルより送信先にインターネットゲートウェイが追加されているか確認する ↓②の確認例 次回、独自ドメインの設定〜CircleCIの自動デプロイの設定まで行います。 ↓後編
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2インスタンスを使用して簡単にDokuWikiを起動してみる

はじめに DokuWiki(ドクウィキ)はPHPを使用したWiki作成のためのソフトウェアです。 詳しいことはWikipediaからどうぞ。 会社で社内Wikiの作成を検討しており、 DokuWikiの使用感を確かめてみたかったためEC2を使用して起動してみました。 AWS MarketplaceにあるAMIを使用して簡単に起動できたので、自分用備忘録として残します。 下記の方には役に立つかもしれません。 DokuWikiの使用感を確認してみたい DokuWikiを起動するまでの環境構築を簡単にしたい EC2インスタンスを使用して何かを作ってみたい EC2インスタンスの起動 AWSマネジメントコンソールから「EC2」に移動し、「インスタンスの起動」をクリック 「AMIの選択」にて「AWS Marketplace」を選択し、"dokuwiki"で検索 検索結果トップの「DokuWiki Certified by Bitnami」を選択 内容を確認して一番下までスクロールし、「Continue」をクリック 無料枠のインスタンスタイプを選択 そのまま次のステップ そのまま次のステップ 任意でタグを追加し次のステップ セキュリティグループはそのまま、確認と作成 今回はすぐに終了する予定なので、気にせずそのまま起動します。 キーペアがある場合はそのまま使用、ない場合は作成します。 (ブラウザからちょっと遊ぶだけの場合はキーペア使いませんので気にしなくてOKです) DokuWikiにアクセス インスタンスが作成されたら、ステータスチェックが緑色になるまで待ちます(数分) 緑色になったら、インスタンスをチェックし、表示されるパブリックIPv4アドレスをそのままブラウザのURLに入力します。 もう起動できました。簡単! 右上の「Log In」をクリックします。 ログイン画面ですが、管理者の初回Usernameは「user」です。 パスワードの確認方法は下記に続けます。 パスワードを確認するために、EC2の画面に戻り、今回のインスタンスにチェックします。 右上の「アクション」 > 「モニタリングとトラブルシューティング」 > 「システムログを取得」をクリックします。 表示されたシステムログを上にスクロールすると下記のようにパスワードが記載されている場所があります。 入手したパスワードを入力してログインすると管理や編集、投稿などができるようになります! 少し遊んで、今回はすぐに終了しました(お金かけたくないので。。) インスタンスを選択し「インスタンスの状態」 > 「インスタンスの終了」をクリックします。 DokuWikiをカスタマイズする 使い方やカスタマイズに関しては下記の記事が参考になりました。 社内WikiにDokuWikiを利用する場合のおすすめの使い方 DokuWikiマニュアル DokuWikiで情報発信 おわりに 最後まで読んでいただきありがとうございます。 どなたかの役に立てれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Amazon RDS】マルチAZとリードレプリカの違い

はじめに RDSはマルチAZに配置することが出来、また、リードレプリカを作成することが出来るが、それぞれの違いがよく分かっていないため、まとめたいと思う。 通常、「マルチAZ」は、「複数のAZ(データセンター群)」を意味する。 RDSのマルチAZとは、RDSが複数のAZにて配置されていることを意味する。 「リードレプリカ」は、1つのAZ、または複数のAZにて、「読込専用」のRDSを複製することを意味する。 RDSをマルチAZに配置する場合、リードレプリカを作成する場合の違いについて、以下に記載する。 RDSをマルチAZに配置する場合 「高可用性」を実現したい時にRDSをマルチAZに配置する。 可用性は、「システムを利用したい時に利用できる状態」を意味する。 以下の図では、可用性を高めるため、複数(マルチ)のデータセンター群(AZ)に、「プライマリDBインスタンス」、「スタンバイレプリカ」をそれぞれ配置し、「同期レプリケーション」によって、DBを冗長化するイメージを表す。 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html AWS管理コンソール上のダッシュボードからは、「データベースの作成」ボタン押下後、以下にて設定することが可能。 選択するDBによって表示内容が異なる。 Amazon Auroraの場合 MySQL、MariaDB、PostgreSQL、Oracleの場合 Microsoft SQL Severの場合 リードレプリカを作成する場合 RDSのスケーラビリティを実現したい時にリードレプリカを作成する。 リージョンを跨いでクロスリージョンレプリケーションを行うことも可能。 公式ページには、「Amazon RDS リードレプリカは、マルチ AZ 配置を補完します。」と記載されている。 上記「RDSをマルチAZに配置する場合」にて、RDSをマルチAZに配置するのは、「高可用性」を実現するのが目的と記載したが、リードレプリカを使用しても高可用性は実現可能。但し、データを同期するかどうかがマルチAZとの主な違い。 詳細な違いについては、公式ページに記載されている。 https://aws.amazon.com/jp/rds/features/read-replicas/ AWS管理コンソール上からは以下の手順で操作することが出来る。 DB作成後のみ利用することが可能。DB作成時には、リードレプリカ作成の操作が存在しない。 これは、リードレプリカがスケーラビリティを実現する目的のため。 DBの容量が不足した際に、自動的に容量を追加すること(オートスケール)も可能。 具体的には、以下の条件全てに合致する場合に自動的に容量が追加される。 使用可能な空き領域が、割り当てられたストレージの10%未満になった場合 低ストレージ状態が5分以上の場合 最後のストレージ変更から 6時間以上経過している場合 追加されるDBのサイズは、次のうちいずれか大きい方の増分となる。 5 GiB 現在割り当てられているストレージの10% ※60 GiB割り当てられているなら、6 GiB。 直近 1 時間の FreeStorageSpace(使用可能なストレージ領域の容量) メトリクスの変動に基づいて予測される 7 時間のストレージの増分。 ※RDS DB インスタンスのストレージサイズが 100 GiB で 10.1 GiB の空き容量があり、ストレージの消費量が通常 1 時間あたり 100 MB の場合、100 MB × 7 時間 = 700 MB オートスケールの詳細については、公式ページに記載されている。 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_PIOPS.StorageTypes.html#USER_PIOPS.Autoscaling https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/monitoring-cloudwatch.html AWS管理コンソール上からは以下の手順で操作することが出来る。 ちなみに、データロードの増加が予想される場合は (RDS DB インスタンスの現在のストレージサイズの 20% を超えるロードなど)、データロードの前に RDS DB ストレージのサイズを手動で増加させることがベストプラクティスであると公式ページに記載されている。 https://aws.amazon.com/jp/premiumsupport/knowledge-center/rds-autoscaling-low-free-storage/ Auroraはオートスケールでリードレプリカを追加することが可能。 AWS管理コンソール上からは以下の手順で操作することが出来る。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

S3ファイルの大量コピーは、AthenaのINSERT INTOでやると高速(1案として)

s3で、大量のファイル(10万とか)をコピーしたい時、どうされていますか? *ディレクトリ名をちょっと変えたいとかで、大量のディレクトリとファイルがある場合 boto3でプログラム組んで、コピーしようとしたら、ゾッとする遅さでした。 管理コンソール上で数秒で終わるコピーが、何分もかかるとは、思わなかった・・・ 今回の方法は、やや制約(gzipになる、HIVE形式でディレクトリ出力される)は発生しますが、同じ溝にはまった人はご参考までに。 s3で大量コピー:boto3(python)の場合 boto3 pythonで実行したところ、100ファイルごとに30秒前後かかっていて、震えました。。。 目の前の25万ファイルを目にして。 30秒×25万ファイル=2083時間 = 87日 もかかる・・・ Athenaでやってみた どうしようか、、、と考えて、思いついた方法 「AthenaのINSERT INTOを使おう!」 という話です。 [手順] (1) COPY元のテーブルを作成   (ディレクトリをパーティションに指定) * コツ: テーブルカラムはstringに統一した方が面倒がないかも (2) COPY元のパーティションを追加してください。 MSCK REPAIR TABLEは超遅いから、 ALTER TABLEでやりましょう。 例えば、日付("dt", YYYYMMDD形式)をパーティションキーにする場合のコードを載せておきます。 from datetime import datetime , timedelta start_day = datetime.strptime('2020-10-15','%Y-%m-%d') #例えば2020/10/15 ~ last_day = datetime.strptime('2021-05-10','%Y-%m-%d') # 2021/5/10までのデータをコピーする時 q = 'ALTER TABLE old_table ADD IF NOT EXISTS' # q に ALTER TABLEが入る part = " PARTITION (dt='{dt}') LOCATION 's3://bucket/path/to/{dt}/'" dts = [] # ここには、100パーティションの "dt in ({parttion})" に指定するリストが入る key = [] ctr = 0 while start_day.timestamp() <= last_day.timestamp(): ctr +=1 d = start_day.strftime('%Y%m%d') q += part.format(dt=d) key.append("'{}'".format(d)) start_day += timedelta(days=1) if ctr >=100: dts.append(",".join(key)) key = [] ctr = 0 if ctr >0: dts.append(",".join(key)) (3) COPY先のテーブルを作成   (ディレクトリをパーティションに指定)  * [制約]HIVE形式( /dt=xxxx/ になる)  * [制約]出力はgzip形式になる    (4) パーティション数が100以上になる場合は、100単位で分割 Athenaは一気に100パーティション以上扱えないらしい。  だから、パーティション100個分ずつ、実行する必要がある。 (5) INSERT INTOを実行 ・一応重複がないように、ファイル名が一致したら取り込まないようにする [追記/訂正] こちら、new."$path"としてますが、ファイル名変わるのでカラムとして取り込まないとダメでした。すいません。 INSERT INTO new_table (select old.* from old_table as old left join new_table as new on egexp_extract(old."\$path", '[^/]+$') = regexp_extract(new."\$path", '[^/]+$') where new."$path" is null and dt in ('20201015','20201016' ) [結果] -> ざっくりですが、250ディレクトリ、 25万件ほどのファイルコピーが実行3回(合計、15分くらい)で終わった。 よかった。。。 Athenaって便利ですね。 他にも方法があるのかもしれませんが。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Data Pipelineへの入口といくつかのTips

はじめに 仕事でデータレイクを構築する際に AWS Data Pipeline を初めて使用しましたが、インターネット上にあまり情報が見つからずかなり手探りで進めることになりました。 (触り始めはほんとうにどこをどう触ってよいかわからなかった…) わずかばかりの知見ですが、これから取り組む方の役に少しでも立てばと思い、いくつかのTipsを記事にしてみました。 AWS Data Pipelineはどんなサービス? 公式ドキュメントにある下図1がイメージをつかみやすいです。 RDS、DynamoDB、S3等AWSの各種サービス上にあるデータのクレンジングや移動を定期タスクで処理させることができます。単にEC2を立ててシェルを実行させるだけのタスクを組むこともできるので、タスクスケジューラ的な使い方もできる様子。 タスクはAWSコンソールからブロック(AWSから提供される機能の箱)を繋いで組み立てるか、AWS CLIからJSON形式の定義ファイルをアップロードして作成します。公式にチュートリアルやテンプレートはいくつかあるので、やりたいことに合致しそうであればそのまま流用できると思います。 実際に触ってみるとわかりますが、ブロックの編集の仕方には少し癖があります…。 ブロックを追加する際は下図左上の「Add」からブロックの種類を選択するのですが、フォーカス中のブロックの下に追加されるわけではなくルートにぶら下がるような形になります。 そこで、下図のように右側メニュー内の「Runs On」や「Depends On」で各ブロックごとに親を設定する必要があります。 ブロックを削除したい場合は右側メニュー内から消したいブロックを探して名前横の×印を押す必要があります。 ちなみに右側メニューの「Activities」の横にある▼ですが、クリックしても閉じません。他の閉じている項目の▶をクリックすることで今開いている項目が閉じて新たにクリックした項目が開きます? このあたりの操作があまり直感的ではなくて、最初とても戸惑いました。が、設定できるパラメータを眺めることで大体すべきことが見えてくるのでそこは理解しやすくてよいなーと思いました。 Tips スケジュール実行/オンデマンド実行 Pipelineのタスクはスケジュールで動かしたいけれど、開発中は任意のタイミングで処理を動かしたい!という場合はルートにあるConfigurationブロックの「Schedule Type」を ONDEMAND にすることでアクティベーションごとに都度実行させることができるようになります。 シェル異常終了時のリトライ回数指定 デフォルト設定では、シェルの異常終了が3回繰り返された後にタスクがFAILEDで終了するようになっています。シェルブロックの「Maximum Retries」を1にしておくと、1回の異常終了ですぐにタスクを終了させることができるため異常ケースのテスト時など設定しておくと便利です。 設定のエクスポートとインポート 別の環境に構築済みのPipelineをコピーしたい場合は、コンソールの「Export」ボタンを押下してJSON定義を表示し、コピーしてJSONファイルとして保存することでエクスポートができます。 エクスポートしたJSON定義は、新たなPipeline構築時にインポートすることができます。 ※ブロック名が日本語だと文字化けしたので、基本英数使用がよさそうです 実行権限 Configurationブロックのパラメータには「Resource Role」と「Role」があります。 それぞれ Resource Role:DataPipelineから作成されたEC2に付与されるIAMロール Role:DataPipelineがEC2を作成する際に使用するIAMロール となっているので、データ処理の際にEC2からアクセスするリソース(S3のシェルなど)の権限はResource Roleの方に付与する必要があります。 パラメータの説明確認 「Add an optional field...」のセレクトボックス項目からこのパラメータ何を設定すればいいんだろう?と思った時は、一度追加してパラメータ名をクリックすると説明とドキュメントへのリンクを表示することができるのでスムーズに調べられます。 おわりに DXでデータの需要が高まってゆく昨今、インフラとして採用率の高いAWSの各種データリソースを手軽に扱えるため、使えるようになっておいて損はないように感じました。(癖は強めですが) 記事では細かい内容は紹介していませんが、EMRのクラスタを作成してそれなりに重い処理ができたり、Pipelineで実行するシェルの上でAWS CLIを動かせばPipelineのブロックでできないことにも対応できたりと、かなり応用が利きそうです。 参考 画像引用元:https://docs.aws.amazon.com/ja_jp/datapipeline/latest/DeveloperGuide/what-is-datapipeline.html ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

クラウドエンジニア(AWS)ロードマップ2021

はじめに インフラ初学者がAWSを用いた設計・構築レベルに到達するため、学習の全体像をロードマップ図にまとめました。 背景 パブリッククラウド全盛期においてAWSは全エンジニアにとって「常識」となりました。 しかしながら、情報過多によってAWS学習に必要な情報がネット上のノイズに埋もれてしまい、初学者の直感による判断が誤った学習に行き着くこともあります。 このロードマップはAWS学習の全体像を俯瞰でき、パブリッククラウドを用いた設計・構築レベルに到達するまで導く体系的なスキルセット、および前提となるオンプレ知識や各種ツールの学習順序を提示します。 今自分がどこにいるのか?次は何を学習すべきか? インフラ・クラウド領域の大海原を渡り歩くための海図としてお役立てください。 ■初学者の方へ - AWS学習の全体像が把握できます - 学習順序に迷わず、安心して独学を進められます ■育成者の方へ - エンジニアの育成指導に役立ちます 制作メンバーについて 当ロードマップ制作にあたり、協力いただいた皆様には深く感謝いたします。 ■ルビコン (AWSクラウドエンジニア / フリーランス&起業 / AWS CloudTech公認メンター / AWSの個別相談・個別指導が強み / Twitter=駆け出しエンジニアの頼れるお兄さん) ■小澤 聡(富士山が育んだおじさんエンジニア / 立命館大学ラグビー愛好会出身/ 田舎が好き・釣りが好き / 一瞬でもいいから同級生の渡部陽一くんよりバズりたい) ■Kento.Yamada (自分をフルスタックエンジニアと信じて止まない一般男性 / 株式会社KDDIエボルバ ITスペシャリスト / 雑食系オンラインサロンAWS部部長 / AWS CloudTech 道場チャンネル主催 / Twitter / 発言は個人の見解) ■久保玉井純(AWS認定講師 / 沖縄県最大の専門学校の先生 / ラーメン戦士 / 学生は無料のAWS教材を提供中 / Twitter) ■yusuke.aoki(株式会社Olive) ■井上嵩章(某SIerのフロントエンジニア/Twitter) ■たかくにしんのすけ (株式会社ギブ・アンド・テイク / 未経験からクラウドエンジニア2年生 ) ■tokku(某SIerのインフラエンジニア/プロフィール/Flutter Guild Japan/Twitter) ■mikawaya (夢に向かい日々奮闘する40代おっさんエンジニア/マインドマップの使い手) ■くろかわ こうへい (エンジニア系YouTuber / 株式会社KWS代表取締役 / 会員数600名超のAWS学習サービス運営 / Twitter) Special Thanks! (masakiさん、フランさん、コムチュア株式会社 和田担当部長) ロードマップ YouTube動画でも解説しました! YouTubeはコチラ 補足 上から下に学習を進めるのを推奨しますが、途中の興味があるサービスから始めたり下から上に進んでもOKです。 進め方に正解はありません。あなたの目的や実務環境に合わせてアレンジして下さい。そもそも学習に正解を求め過ぎるのは良くないです。 目的を「いち早くロードマップ通りに学習を完了すること」としないでください。 学習は他人とスピードを競うものではありません。 皆同じような行動を求める学校教育の弊害により、早く正確にできる人が賞賛され、ゆっくりと自分の考えを深める研究的な学習は「マイペース」と揶揄されがちですが、あなたなりの学習方法が必ずあります。ぜひとも挑戦する心を失わずに自分の学習スタイルを研究し続けてください。 AWS Basic 基礎知識 What's AWS and Cloud? Amazon Web Services (AWS) は世界シェア第1位の クラウドコンピューティングサービスおよび、サービスを展開している企業です。  AWS(クラウド)はインターネットを介してコンピューティングリソース(サーバー、ストレージ、ネットワーク機能など)をユーザー(我々)に提供してくれます。その対価としてサービスの利用した量に応じての金額を支払います。これにより従来型のITでは「所有」の概念であったコンピューティングリソースが、クラウドの登場により「利用」の概念にシフトされつつあります。 従来型のITの考え方 所有: 自分自身でサーバーを購入し、運用・保守点検を自身で行う。運用の柔軟性が高いものの、予め想定したピーク量の推定が必要であり、また購入までの時間的なコストが高い。 たとえるなら:自分で選択したグレードの車を購入し、自分で運転し目的地へ向かう。 クラウド型のIT の考え方 利用:クラウドサービス上に展開されたリソース、およびサービスを利用し、利用した量に応じて金額を支払う。柔軟なスケール変更が即座に可能である一方で、クラウドベンダーの計画に合わせたメンテナンス・アップグレードに追従する必要がある。 たとえるなら:状況に合わせた公共交通機関を選択した後料金を払って利用し、目的地へ向かう。 リージョン(Region)、アベイラビリティゾーン (Availability Zones、AZ )  AWSは超巨大な分散型システムです。そのため世界中で稼働しています。世界地域での地理的な拠点単位は「リージョン(Region)」と呼びます。全てのリージョン間は地理的に離れていますが、常に高速なネットワークで繋がっています。  リージョンを構成するデータセンター群を「アベイラビリティゾーン(Availability Zones、AZ)」と呼びます。リージョンを構成するAZは最低2つ以上となっており、地理的に分散され、常に高速なネットワークで相互に繋がっています。  各リージョン、各AZに自由にリソースを配置させることができます。これによりリージョンやAZ規模の障害、地理的な要件・制約に対応をすることが可能です。「障害が発生しても動き続ける仕組み」、「直ちに復旧できる仕組み」を構築するうえで非常に重要な要素となります。 https://aws.amazon.com/jp/about-aws/global-infrastructure/regions_az/ 責任共有モデル  ユーザー(我々)とクラウドベンダー (AWS)でセキュリティおよび運用・保守における責任を持つ分界点の定義となります。  例えばEC2 (Infrastructure as a Service 、IaaS)における責任分界点は以下の通りとなります。 これは一例でありサービス内容で変化するため使用するサービス毎の定義を確認しておきましょう。 ユーザー:ミドルウェア、アプリケーション、データ AWS: OS 、ハードウェア、ネットワーク https://aws.amazon.com/jp/compliance/shared-responsibility-model/ AWS Well-Architected フレームワーク (W-A)  AWSが長年の運用によって導き出したクラウドでのITアーキテクチャを考える際のベストプラクティス集となります。「運⽤上の優秀性 」、「セキュリティ」 、「信頼性」、「パフォーマンス効率」、「コスト最適化」、の5つの原則があり、クラウドをより活用するための設計原則と、システム構築に関するベストプラクティスに沿っているかを確認するための質問と回答で構成されています。  なお5つの原則を全て盛り込む必要はありません。一番重要なことはベストプラクティスとリスクを理解した上でビジネス判断でW-Aの5つの原則を取捨選択すること、そしてW-Aによって顕在化したリスクや改善方法を企業・チームで認識することです。 https://d1.awsstatic.com/International/ja_JP/Whitepapers/AWS_Well-Architected_Framework_2018_JA_final.pdf EC2 EC2とはElastic Compute Cloudの略でAWSの仮想サーバーサービスです。 EC2を理解するためにはサーバーの構成要素を分解すると学びやすいでしょう。 各構成要素とAWSサービスを対応付けると以下の通り CPU,メモリなどのスペック = インスタンスタイプ HDD,SSD = EBS OS,その他設定情報 = AMI EC2は自由度が高いですが、その反面コストが高くなりがちです。 時間単位の利用料金に加えてウィルスソフトなどのセキュリティコストや運用管理コストも必要となるケースがあるので注意しましょう。 デフォルトのオンデマンド以外の購入方法の特徴(リザーブド・スポット)や使いどころを理解すればコスト削減に繋がります。 基本的なLinuxコマンド、および後続のネットワークの知識も必須です。 一説によるとAWSで稼働しているEC2インスタンスのOSタイプはLinuxとWindowsが半々のシェアと言われており、Windows Serverの構築・運用スキルがあると強みになるでしょう。 Windows Server独自のトピックを次にまとめました。 Windows Server EC2上でもWindows Serverを動作させることが出来ます。.NET Frameworkを利用して作られたアプリケーションを動作させる場合や、エンタープライズ向けのOA基盤(企業内のアカウント、メール、ファイルサーバー、Microsoft Office製品などを配布・管理する基盤)はまだまだWindowsが主流であることから、ある程度規模の大きいプロジェクトに参画する際にはWindowsの基礎的な知識習得は必須と言えます。 GUIでの操作が主になるので、初学者にとってLinuxよりもとっつきやすいと思いますが、WEB/APサーバーであるIIS(Internet Information Service)、タスクスケジューラによる定期実行、WSFC(Windows Server Failover Cluster)によるクラスタリングなど、出来ることは多岐に渡るので必要な機能を一つずつ覚えていけば良いかと思います。 また、LinuxやMacのターミナルとコマンド体系が根本的に異なるので、コマンドプロンプト(cmd)での基本コマンドの習得や、PowerShellの習得をやっておくと尚良いです。 OA基盤(企業のPC、Officeソフト、メール、プリンターなど、一般的な業務で扱う機器を使えるようにするITインフラ)の構築や運用に携わったら必ずActive Directoryというサーバーを扱うことになります。企業内のコンピューターやユーザーの管理を一挙に担うことから重要度が高いサーバーですが、習得するにはLDAP(ユーザーやコンピューターの集中管理を行うためのプロトコル)とDNSの基礎を身に着け、その上でActive Directory特有の考え方を身に着ける必要がある、難易度の高い技術要素となっています。Microsoft365(旧Office365)やMicrosoft Azureとの連携でもフェデレーションサービスとして扱うことになる技術ですので、Windowsを極めたい方は勉強してみるのもいいかと思います。 VPC VPCはAWSの仮想ネットワークサービスであり、地域(リージョン)毎にアカウントと紐づいた仮想的なネットワーク空間です。 1つのアカウントで複数のVPCを作成することができます。 たとえば勉強用、本番稼働用、検証用とネットワークの環境を分けて運用することが可能です。 VPCの主な機能 外部インターネットとの接続を行う「InternetGateway」 VPC内のネットワークを細分化する「Subnet」 ネットワークの通信経路を設定する「Route Table」 セキュリティ機能である「Security Group」や「NetworkACL」 他にもVPC同士を接続する「VPC Peering」や「Endpoint」「ENI」や「EIP」などの機能もあります。 AWS上で作成したサービスをインターネット上で公開したり、AWSとオンプレミスをVPNや専用線で接続するなどVPCの知識はAWSを利用する上で必須となりますので、AWS学習の各種サービスの中でも特に優先度を高く設定した方が良いでしょう。 TCP/IPを始めとしたネットワークの基礎知識があれば容易に設定できると思います。 AWSに限りませんが、Webサーバやデータベースサーバーなどのシステム運用においてもネットワークの知識は重要な要素となるため、VPCと並行してネットワークの基礎知識も学習することをお勧めします。 参考:Amazon VPCとは? https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html IAM IAMとはIdentity and Access Managementの略で、AWSの認証管理サービスです。 従来のパスワード認証の制御と違ったロールベースアクセス制御 (RBAC)の概念がポイントとなります。 ユーザー(またはAWSリソース)に対して直接操作権限を与えずロールを通して操作権限を与える方法です。 ロールは操作許可ポリシーを複数アタッチして権限をひとまとめにした単位であり、「何ができるか?」という側面と「誰がこのロールを使用できるか?」を決める「信頼関係」の側面があります。 これにより、各人のアクセス権の管理は「このロールは誰が使用可能か」を適切に割り当てることが中心となるため単純化できます。 権限関連のエラーが発生した際にIAMの知識がなければ原因究明は非常に難しいものとなります。 そのため、最低限IAM独自のポシリーの要素(Effect, Principal, Action, Resource, Condition)は読み解けるようにしましょう。 権限エラーを回避するために「とりあえずルート権限を付与する」考えは改めるべきです。 IAMのベストプラクティスに「最小権限の原則」があります。 ユーザーやロール作成時はデフォルトで何の権限も持っておらず、必要に応じてアクセス権限を追加する原則です。最初に強力な権限を与えておいて徐々に絞るのはセキュリティ的に推奨されるものではありません。 AWSのベストプラクティスを定期的に見直し、システム運用がそれに沿っているかどうか振り返るのが重要です。 参考:IAM でのセキュリティのベストプラクティス AWS CLI AWS CLIはAWSリソースをCLIベースで操作するためのオープンソースのツールです。 Linux, Windows, MacOSなど様々なOSに対応しており、ローカルPCにインストールしてAWSリソースを操作することが可能です。 Amazon Linux2を使用したEC2インスタンスではデフォルトでAWS CLIがインストールされているため環境構築不要で学習する事が可能です。 AWS CLIを使用してAWSリソースを操作する際は、IAMユーザから生成される認証情報の文字列(アクセスキーとシークレットアクセスキー)を用いて認証する方法があります。 万が一アクセスキーとシークレットアクセスキーが漏洩すると、第三者からリソース操作(設定した権限に応じた操作。例えばリソースの作成、情報取得、削除など)が可能となるため取り扱いには注意しましょう。 AWS CLIはバージョンが1系・2系の2種類存在しますが、基本的には最新のバージョン2系を学習しましょう。 学習方法としてはマネジメントコンソール(GUIベース)で学習したチュートリアルをAWS CLIで再現するなどの方法がお勧めです。 なお、コマンドの量が膨大なため、全コマンドを覚えようとするのは現実的ではありません。 実現したいコマンドやオプションを公式ドキュメントから素早く引けるようにしましょう。 また、マネジメントコンソールで設定出来ないことがAWS CLIで可能になるケースもたまにあります。例:AWS Config Delivery 配信チャネルを再作成するケース 参考: 公式リファレンス(英語表記ですが諦めずにファイトです!) ローカルPCでのAWS CLI環境構築 RDS RDSはAWSでデータベース(DB)をフルマネージドで使用するためのサービスです。 データを取り扱う手段として、ほぼ全てのシステムが何かしらのDBを使用しています。 このため、システム開発する上でDBの学習は必須といえます。 特にMySQLに関しては、以下の理由により今後も重要なRDBであり続ける可能性が高いと思います。 まずはMySQLを題材に学習を始めるのが良いと思われます。 スケーラブルなWebアプリケーションに最適な選択肢 LAMPスタックに標準で含まれている 一般的なコンテンツ管理システム(Drupal、Joomla、WordPress)は MySQL に依存している 直近で使用するDBがわかっているのであれば、それを選択して学習することも良いかと思います。 Oracle Database:有償のDBであり、他のDBと比較するとコストがかかる為、主に日本では構築予算に余裕があるSIer系の企業で使われるケースが多い PostgreSQL:無償のDBであり、おおきな特徴としてはBSDライセンスという非常に緩やかなライセンスを採用している為、非常に扱いやすく商用環境で利用される場合もある。 また、Heroku標準で利用されるデータベースでもある。 PostgreSQL派生のDWH向けエンジンとしてAmazon Redshift、Netezza等がある。このため基礎として学習しておくのもあり。 フルマネージドであるRDSを使用することを考えますとDBの非常に詳細な部分まで理解しておく必要はないと思いますが、基本的な部分は理解し、最低でも独自で構築・運用できるレベルにはなりたいものです。 また、可能であればアプリ開発での利用に対応するための知識習得ができると尚良いかと思います。 CloudWatch CloudWatchはリソース監視(モニタリング)サービスです。 AWSリソースによっては作成直後に自動で監視メトリクス(監視データ)がCloudWatchに送信され、CloudWatch管理画面から状態をグラフで確認できます。 CloudWatch監視エージェントをオンプレのサーバーにインストールすることでオンプレとクラウドの監視を一元化できます。 CPU,メモリなど負荷状況の推移をグラフで可視化できる アラーム発砲の閾値を設定できる(CPU使用率が70%を超えたら発砲 など) 閾値超過に応じたアクションを設定できる(アラームメール送信、オートスケーリング発動など) CloudWatch Logs CloudWatchサービスの機能のひとつで、ログ監視に特化したサービスです。 EC2インスタンスのログやアプリケーションログを収集し、リアルタイムでモニタリングします。 特定の文字列の出現を監視して条件にヒットすればアクションを実行するといった基本的な監視機能を備えています。 データは蓄積するだけではなく、積極的に活用すべきです。CloudWatch Logsは収集したログをS3やKinesisなど他のAWSサービスへ連携できるので、ログ分析のための入り口の役割も担うことができます。 CloudWatch Events (Amazon EventBridge) CloudWatchサービスの機能のひとつで、AWSリソースの状態変化(イベント)を監視するサービスです。 イベントとは、例えば「EC2が停止した」「EC2 Auto Scalingが発動した」などです。 発生したイベントがCloudWatch Eventsで予め設定したルールに一致した場合にアクション(Lambda発動、SNS発動など)を設定できます。 cron式を用いて定期的にアクションを発生することも可能です。この場合、タイムゾーンはUTCで判定されるため日本時間と9時間ズレがあるので注意しましょう。 CloudWatch Eventsは拡張サービスであるAmazon EventsBridgeに統合されています。将来的な機能追加はすべてAmazon EventsBridgeの方で行われます。CloudWatch Eventsは廃止されるわけではなく、名称がAmazon EventsBridgeに置き換えられる予定です。 https://aws.amazon.com/jp/eventbridge/faqs/ ELB (Elastic Load Balancing) ELBはクライアントからのリクエストをLoad Balancing(負荷分散)してくれるサービスです。 オンプレの時代は高価な装置で、年間100万円以上するので勉強することも貴重でした。AWSでは安価に1ヶ月1,900円程度で使えます(それでも他サービスよりは高いかもしれませんが...)EC2やRDSと違い、停止して課金を避けることができないのでご注意ください。 ELBは4種類ありますが、良く使うのはHTTP/HTTPSに特化したALB (Application Load Balancer)、それ以外のTCP/UDPにも対応できるNLB (Network Load Balancer)です。ちなみにELBの"B"は「Balancing(分散サービス)」、ALBやNLBの"B"は「Balancer(分散装置)」で違うので、知っているとドヤ顔できるかもしれません。4種類の違いについては公式の https://aws.amazon.com/jp/elasticloadbalancing/features/ をご覧ください。 その他の特徴や機能についてまとめておきます。 インターネットに向けて公開するELBと、VPC内部でしか使えない内部ELBの2通りある 後述するACMの証明書を使えば独自ドメインを使ったHTTPS通信が簡単に実装できる。セキュリティポリシーはデフォルトから変更してTLS1.0と1.1を無効にするのがオススメ 負荷分散先(=ターゲット)は当初EC2インスタンスだけだったが、ALBではLambdaやECSコンテナなどにも分散できるようになった ALBではターゲットが正常でない場合に振り分けないよう、ヘルスチェックの設定が必要 ALBではHTTPリクエストの中身(HTTPヘッダーやURLのパス)によって振り分け先を変えたり、HTTPからHTTPSへリダイレクトしたり、固定で403 Forbiddenや404 Not Foundの応答を返すこともできる S3 S3とはAWSのサービスに含まれる機能のひとつで、「Amazon Simple Storage Service」の略称です。オブジェクトストレージサービスの一種であり、拡張性・安さ・耐久性を兼ね備えたクラウドストレージです。 データ容量を気にすることなく保存することができる 1GBあたり0.025ドル(東京リージョン、スタンダードストレージ記事執筆時点の価格) 99.999999999% (9 x 11) の耐久性を実現するように設計されている オブジェクトのファイル単位での出し入れが可能なので、その場に応じて自由な使い道が想定され、より柔軟なデータ保存が実行できるのも特徴です。 データ加工や分析系の他AWSサービスとの連携も容易なため、データを一元的に集約保管するデータレイク(Data Lake)としてS3を利用することがあります。 また静的ウェブサイトホスティングの機能も備えており、様々なケースで利用可能です。 まずは、ストレージとしての利用(ストレージクラス/ライフサイクル管理/バージョニング機能/バケットポリシー etc.)、静的ウェブサイトホスティングとしての利用をメインに学習を開始すると良いでしょう。 データ転送料金について、S3へのアップロード(受信)、同一リージョン内の(AZ非依存な)AWSサービスとの転送料金は無料です。つまり同一リージョン内のS3間のデータ同期にともなうトラフィック料金はかかりません。 Route53 Route 53とは、AWSが提供するフルマネージド型のDNSサービスです。DNSとはドメイン名からIPアドレスを特定するためのプロトコルで、DNSがなければ現代のWEBアプリケーションは正しく動作できません。 単にEC2にパブリックIPアドレスを割り当てただけでも自動でドメイン名が割り当てられますが、AWSから自動で割り当てられるドメイン名ではなく、独自ドメイン名で運用を行いたい場合にRoute 53が必要となります。 Route 53ではドメイン自体を購入することも、別サービスで取得したドメインを指定することも出来、さらにルーティングポリシーを活用してLBの障害時にsorryページを表示させるような機能を実装することもできます。 一般的なDNSの知識(ドメイン、名前解決の仕組み)を理解し、その上でRoute53で提供されているルーティングポリシーの知識を身に着けると効率よく学習できるかと思います。 ルーティングポリシーの選択 - Amazon Route 53 DNSとは - JPNIC CloudFront Amazon CloudFront は、高い安全性と高性能な実現するプログラム可能なコンテンツデリバリーネットワーク(CDN)です。 エッジサーバでコンテンツのキャッシングを⾏い、オリジンの負荷をオフロード Distributionで証明書を設定することにより、独自ドメインでのHTTPS通信を実現 HTTPからHTTPSへのリダイレクト、IPv6、HTTPレスポンス圧縮もチェック一つで対応 さらに踏み込んで学習する際は、エッジロケーション、トランジットセンター、AWS Global Acceleratorなど他ネットワーク要素と組みあわせて理解するとより良いでしょう。 参考となるドキュメント:AWS のネットワークで知っておくべき10のこと ACM (AWS Certificate Manager) ACMはSSL/TLSサーバー証明書を無料で発行できるサービスです。他で有料で購入したSSL/TLSサーバー証明書をインポートして使うことも可能です。発行時に[ドメイン名]だけでなく、*.[ドメイン名]の別名も一緒に付けると1つの証明書でサブドメインにも使い回せます。 前述のELBやCloudFrontでHTTPS通信を提供するために使えます。ただしEC2を直接公開する場合には使えないのでご注意ください。 証明書発行時にDNS検証を使うと有効期限が近づいた際に自動で更新してくれるので、期限切れを心配する必要がなくなります。無料なので使わない手はないですね。 東京リージョンのELBで使うならACMも東京リージョンで発行しますが、CloudFrontは全リージョン共通なのでACMはバージニア北部リージョンで発行してください。 CloudFormation AWSリソースをコードで管理できるサービスです。 CloudFormation独自の記述ルールに沿ってAWSリソースをテキストファイル(JSON or YAML形式)で表します。(このテキストファイルをテンプレートと呼びます。) AWSリソースの作成・更新・削除を効率化できます。 インフラをコード化する概念はIaC(Infrastructure as Code)と呼ばれます。 IaC化を行うことで以下のメリットがあります。 構築の効率化(GUIで手動構築する手間が省ける) 拡張がしやすい(環境の複製が容易。環境に合わせて一部パラメーターを変数化することも可能) 属人性の排除(誰でも同じ構成をデプロイする事ができる。環境が可視化できる) バージョン管理(Githubのフローを利用できる。バックアップ手段としても有効) 他、代表的なIaCツールはTerraformがあります。 CloudFormation学習の1歩目はテンプレートのステートメント(宣言)を理解する事です。 各ステートメントで何のAWSリソースをどのようなオプションで設定しているか読み解けるようになりましょう。 JSONとYAML形式どちらでもリソース定義が可能ですが、初学者にはコメントアウトが可能なYAMLをお勧めします。 AWS CLIと同様、全てのリソースのパラメーターを網羅して覚えようとするのは現実的ではありません。 上達への近道は「対象リソースの記述方法や詳細パラメーターを公式リファレンスから素早く読み解く力」がポイントとなります。 注意点は、「全てCloudFormationでコード化するのが正解ではない」ということです。 例えば、ほとんど変更が入らず使い回しが発生しにくい箇所(専用線接続部分など)のテンプレート作成に時間を使うのは効率的ではありません。 環境構築を自動化するサービスは他にもElastic Beanstalk、OpsWorksがあります。 目的に合わせてサービスを使い分けましょう。 参考: 公式リファレンス Zenn:CloudFormationまとめ AWS初心者によるAWS初心者のためのAWS環境自動化入門 Lambda 通常、Webサービスをインターネットに公開するためにはプログラムだけでなくサーバなども構築する必要があります。 サーバーの構築や保守や負荷対策など管理をすることなくプログラムコードを実行できるサービスがAWS Lambda(ラムダ)です。 サーバーの管理が一切不要になるので「サーバーレスコンピューティング」とも呼ばれます。 Lambdaは、AWSに関するなにかしらのイベントによって処理を実行できます。 たとえば S3にファイルをアップしたときにプログラムを実行 APIサーバとして、クライアントから通信を受けたらプログラムを実行 といったような特定イベント時に自作プログラムを実行させることができます。 主にアプリケーション開発で使用されるケースが多いのですが、インフラ構築でも簡単な処理(S3に関する処理など)を書くのに便利です。 また、利用するアプリ側で何ができるか把握しておくこともインフラエンジニアとしては望ましいことです。 まずは、Lambdaが どのようなもので/何ができるのか の概略をつかめればよいかと思います。 Git基本操作 CloudFormationのテンプレートを社内共有・管理する為にもGitの基本操作は必須です。 リポジトリホスティングサービスはセキュリティの関係で会社指定があるかと思いますが、基本的にはGitHubを学習しておけば他サービスでも十分対応できます。 エディタはユーザー数が多く拡張プラグインも豊富なVSCodeを選択するのが無難です。 構成図作成ツールはdraw.io、もしくはVSCodeと連携するdraw.ioのプラグインを推奨します。 業務に役立つテンプレートも豊富で、AWSアイコンもインポートできます。 3Dで立体的に構成図を作成できるCloudcraftもユニークでお勧めです。 参考 VSCodeでDraw.ioが使えるようになったらしい! おわりに このロードマップ作成はAWS学習サービス AWS CloudTechのコミュニティの有志によるプロジェクトメンバーで制作しました。 ロードマップ作成にあたりご協力いただいた皆様には改めて感謝いたします。 インフラエンジニアの教育、新人指導などで役立てていただけますと幸いです。 この記事に対するご意見などはQiitaのコメントか、もしくは専用のフォームを用意しましたので何なりとお寄せください。 建設的なご意見お待ちしております。 更新履歴 2021/5/10 初回投稿
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

社内AWS研修の振り返り

取り組みを実施した背景 社内の新人Webエンジニアがインフラにあまり慣れていなかった為、インフラスキルの向上を目的にAWS研修を実施していただきました?‍♂️ 実施にあたり自分のAWSに関するスキル感 EC2上でWordPressを立てたことがある プライベートサブネットにWordPressのEC2サーバを、プライベートサブネットにMySQLのEC2サーバを立てた ELBやAWS Auto Scalingは使用したことがない 今回作ったインフラの構成図と使用したもの 開発環境 本番環境 使用したもの OS: Amazon Linux release 2 (Karoo) リバースプロキシサーバ: nginx 1.18.0 WEBサーバ: PHPビルトインウェブサーバ PHP 8.0.1 DBサーバ: MySQL 8.0.20 研修の流れと「やったこと、わかったこと、わからなかったこと」 座学 ? IPアドレスやサブネットマスク IPアドレスの基礎知識 - Qiita OSの種類 yumやapt-getについて リージョンやアベイラビリティーゾーン 可用性の高め方 VPCやサブネット パブリックサブネットとプライベートサブネットの使い分け VPCやサブネットってなんなの?AWSをオフィスビルでわかりやすく表現してみた:穂苅智哉の Webビジネス!日進月歩:オルタナティブ・ブログ EC2、RDS、ELBについて 0から始めるAWS入門:概要 - Qiita 分からなかったこと ロードバランサーの設定方法イメージ出来なかった WEBサーバの前段でアクセス負荷を分散させてくれるということは知っていた しかし、スキーム、証明書の設定、ターゲットグループといった概念や設定方法をなんとなくでしか理解していなかった 後ほど行ったハンズオンで理解することが出来ました?‍♂️ 開発環境構築(ハンズオン)? やったこと パブリックサブネットでグローバルIPのあるEC2を作成 yumでnginxを入れて初期ページを表示する yumでPHP8系をインストール その後PHPのビルトインサーバでHelloWorld PHP-FPMとビルトインサーバの2つがWEBサーバの候補で、他の参加者がPHP-FPMを選んでいたため物は試しと思いあえてビルトインサーバの方を選んだ(結果的に良くない実装だった? ) yumでMySQL8系をインストール その後ビルトインサーバでHelloWorld PHPでMySQLに入れたダミーデータを取得し表示 WordPressをインストール nginx.confにルーティングを記述し、nginx再起動 ビルトインサーバを起動 IPアドレス経由でWordpressが開くかどうかをデバッグしながら確認 分かったこと EC2インスタンスの構築方法 MySQL5.7系以降のパスワードの初期値について 参考サイト: MySQLにrootでログインできない!初期設定やファイル変更が必要です! PHPにおけるMySQLとの連携方法 分からなかったこと WordPressコンテンツが読み込まない状態になってしまった DB内の「WordPressの設定データ」が間違っていた可能性がある 原因調査しきれず?‍♂️ WordPress再インストールとconfigの再設定、DBの再生成で直った?‍♂️ 本番環境構築(ハンズオン)? やったこと 開発環境からのコピー 開発環境のEC2からamiを作成し、本番環境のEC2を生成&起動 開発環境のDBからdump取って、本番環境のRDSに入れる 分かったこと amiのとり方 amiから複製する方法 開発環境のDBからdumpをエクスポートする方法 本番環境のDBにdumpをインポートする方法 分からなかったこと 特になし 本番環境構築(ハンズオン)続き? やったこと ALBの作成 AWSの3種類のLBの比較と使い分け (ALB, NLB, CLB) - Qiita ACMを利用してSSL証明書の作成とALBへの設定 AutoScalingさせる ターゲットグループの設定 オートスケーリンググループの設定 わかったこと AutoScalingの設定方法 ApacheBenchコマンドを用いた負荷テストで、Scalingするかを確認する方法 Apache Benchでサクッと性能テスト - Qiita 分からなかったこと AutoScalingで新規起動したサーバでビルトインサーバを起動する方法? 個人アプリ検討、選定、実装まで 検討 MoonGift等でOSSを調べて以下のアプリに興味を持った OWASP ZAP Webアプリケーションセキュリティスキャナー Redmine プロジェクト管理ソフトウェア Lottery 懇親会等で使えそうなルーレットアプリ 選定 Dockerで立ち上げ可能なアプリを選定 第1候補: OwaspZap 理由: 今後業務でアプリを作った際に試しに自己診断してみたいと考えたため 第2候補: Redmine 理由: チケット管理ツールを立ち上げて実際に使ってみることで、今後の開発時に活きる「実装アイディア」を得られればなと考えた ただ、現状業務ではプロジェクト管理はGitHub内の機能を使用しているため、Redmineが業務に直接活きないと考えたため第2候補にした 実装 OwaspZap DockerでCUIが起動出来た しかし、GUIを起動するにはマシンリソース不足だったため断念? Redmine Dockerを用いて起動出来た GUIで起動出来た? 振り返り? うまくいったこと ? EC2インスタンスで開発環境と本番環境を作ること LBを経由してWordPressを公開すること うまくいかなかったこと? nginxのルーティングをベストな設定で記述したかった 十分な理解が無いままに記述して序盤上手く行ってしまったため、終盤にルーティングがぐちゃぐちゃになって困った WordPressを稼働させる上で最適な構成にしたかった ビルトインサーバで稼働させる方向で進めてしまった その影響もありAutoScalingの設定時に他の参加者では不要な作業が発生した もし次やるならPHP-FPMで作りたい 今後トライしたいこと? コンテナ周りのマネージドサービスを適切に使用して、運用負荷の少ないシステム構築すること nginxのルーティングを、きちんと理解した上で記述出来るようにすること AutoScalingで新規起動したサーバ上で、アプリケーションもちゃんと起動するようにすること まとめ 一度プライベートでEC2でWordPressを立てたことはあったのですが、ざっくりとしか着手していなかった為今回の研修では「わかっていなかった所」が数多く見つかり、かつその理解を深めることが出来たのでとても良かったです。ありがとうございました?‍♂️ 「ビルトインサーバでWordPress環境構築」という、「PHP-FPMを使った構築」より比較的情報が少ないかつ本番環境では非推奨な実装方法で進めてしまったため、問題が起こったときの原因究明が難しかったことが印象に残っています。(とはいえ、インフラの根本的な仕組みについて理解していれば解決は難しくないはず。主に自身の実力不足。) 今後技術選定を行うときは、「信頼できる情報源が豊富かどうか」も頭に入れた方が良いと学びました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【BacklogAPIレート制限対応】ユーザーごとのAPIレートの監視をする仕組みを作った

背景 2021年7月末からBacklog APIに対するレート制限が実装される。 レート制限に関するブログ : https://backlog.com/ja/blog/backlog-api-rate-limit-announcement/ このレート制限は、APIの種類ごと・ユーザー単位・分単位での制限となる。 この対応のために、まずBacklog APIを利用している各サービスでのAPI利用状況を把握し影響箇所を調査する必要がある。 方法 「レート制限情報の取得」APIが用意されている。このAPIを利用することで、その時点のAPI利用状況が把握できる。 https://developer.nulab.com/ja/docs/backlog/api/2/get-rate-limit/# ただし、得られる情報はAPIのリクエストを送った時点の情報のみであり、特定期間内における利用状況を把握するためには、その期間中に定期的にこのAPIを実行し情報を取得する必要がある。 そのために、以下の簡易な監視システムを構築した。 監視システム リポジトリ 作成したものは以下のリポジトリに格納。 ソースコード等はこのリポジトリを参照 仕様・注意事項 調査したいBacklogユーザーのAPIキーを使い、レート制限情報の取得APIを定期実行して利用状況を把握する https://developer.nulab.com/ja/docs/backlog/api/2/get-rate-limit/# 取得した情報はCloudWatchメトリクスにカスタムメトリクスとして値を格納し、ダッシュボードでグラフを参照できるようにする。 上記構成図の通り、バッチ処理はLambda + Eventbridgeで構成。 取得頻度は 約5秒 Lambdaは1分毎に実行される。コード内で5秒置きに取得するように実装。 値の精度 Lambdaの重複実行に対する冪等な実装はしていない。 レート制限情報を取得する時間とメトリクスを作成する時間同じになるよう実装していないため、ms単位での誤差がある。 以上のように 完全に正確な値であるとは保証されないが、利用状況の傾向や大幅なリクエスト増加を見る前提で、この精度で十分であると判断する。 このレート情報取得自体にreadが使われるため、readの値にはその分が上乗せされたで状態で集計される メトリクス仕様 Namespace : BacklogApiRate メトリクス名 説明 Limit 制限数 Remaining 制限残数 (残り利用可能なリクエスト数) Usage 利用数。Limit - Remaining ディメンション 説明 ApiKey 対象のAPIキーの先頭5文字 ApiType 対象のAPI種別。read = 読み込み , update = 更新 , search = 検索 , icon = アイコン。 詳細 ダッシュボードを別途作成 収集したメトリクスをダッシュボード化して可視化。ダッシュボードは上記デプロイ後、別途作成。 作成例 まとめ 簡易ではあるが、傾向を把握するのには十分な精度で利用状況を可視化することができた。これを元に影響箇所を調査し対応することとした。 ただし、複数のワークロードにまたがって1つのユーザーをAPIに利用されていることもあるため、できればAPIキー単位でレート情報を取得できれば嬉しかった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

troccoの導入で何が改善されたか

はじめに 当社ではデータ分析基盤改善の一環としてtroccoを導入しました。 この記事ではtrocco導入により何がどのように改善されたのかをまとめて記載します。 0. troccoとは troccoはEmbulkをSaaS版にしたようなサービスです。各種ストレージ、SaaS、DBなどのデータ転送をWEBのGUI上で設定、管理することができます。それ以外にもRedshift/BigQueryへのクエリ発行やtrocco上のジョブの管理等の便利機能もあり非常に使い勝手が良いのが特徴です。 1. trocco導入を検討した理由 当社ではプロダクション用DBのコピーをBigQueryに転送し分析に用いているのですが、この転送部分に対処しにくい2点の問題があった為troccoへの乗り換えを検討しました。詳細は以下の通りです。 1.1 Embulk+digdag on EC2の運用問題 当時の構成では、転送はEmbulkで行い、転送ジョブや転送テーブルの制御などをdigdagで作り込み、それらをEC2上でホスティングしていました。転送自体はdigdagのスケジューリングで毎日実行されるものの、転送エラーが発生したり、Embulkやdigdagのバージョンアップに追随できていないなど問題がありました。一方で、各種設定を行った方は既に退職されており詳細が不明瞭なことと、BigQueryでの分析が重要な役割を持つ為、現状動いているインスタンスを下手にいじることができず、手詰まりになっていました。 1.2 作り込み部分の問題 Embulk+digdagの作り込み部分にも改良したい点がありました。当社では弁護士ドットコムの他に税理士ドットコムやBUSINESS LAWYERSといった各種サービスを提供しています。サービス別にDBインスタンスは分けられているのですが、当社でのdigdagのジョブ管理の仕様上、ひとつのサービスのDBしか転送できないように作り込まれていました。ジョブ管理部分を一から書き直すには労力がかかり、仮にこれを解決しても1.1で記載したセルフホストの問題があるため躊躇していました。 2. trocco導入後の改善点 troccoを導入することにより問題点がどのように改善されたのかを記載します。 2.1 運用面 冒頭でも記載した通りtroccoはSaaS版Embulkと言えるサービスです。ユーザーがやることといえばEmbulk等の設定のみあり、それらが稼働するリソース管理を全てお任せできてしまうのは非常に嬉しいです。特に当社の場合は1.1で記載した通りEmbulkを稼働させる為のリソース管理で悩みがあったため、その恩恵は非常に大きなものでした。 2.2 機能面 各種DBへの接続設定は独立して作成することができるため、troccoに乗り換えたことで1.2の問題は解決されました。ここでは転送機能以外に当社が活用している便利機能をいくつか紹介します。 DWH管理機能 BigQueryやRedShiftの任意のテーブルに対してクエリを発行する機能です。データ転送後に集計処理を噛ませた中間テーブルを作成したり、あるカラムの型変換をかけたりと何かと融通が利く使い方ができます。当社の場合は、元々digdagで実行させていた中間テーブル生成処理をこの機能に載せ替えました。 ワークフロー機能 GUIを用い、転送・DWH管理などのジョブ単位でワークフローを作成できる機能です。ジョブA~Cが完了次第Dを実行する、といった依存関係も作成することができます。当社ではデータ転送後に中間テーブル生成ジョブを実行するよう設定しています。また、終了時にSlack通知することもできます。 これら以外にも便利機能はありますが、いずれも分析基盤の運用をtroccoに寄せていけるようなものになっていました。 3. まとめ troccoの導入により当初抱えていた問題を解決することができました。 今後はtroccoを使い倒していきたいと思います。 導入を検討されている方の参考になれば幸いです。 参考 trocco
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

社内AWS研修振り返り

取り組みを実施した背景 この記事は、新人社員のインフラ知識向上を目的に、AWSを使用した簡単なWEBアプリケーション環境の構築を行った研修のブログ記事です。 最終目標 今回はこのような構成のインフラ環境の構築を目標に進めました。 開発環境 本番環境 実施にあたり自分のAWSに関するスキル感 EC2やALBという単語を聞いたことはあるけど、実際どんな動きをしているかは答えられないレベル? (学生の時、Linucという資格を取るために勉強したことがあるので、インフラについての知識が0だったわけではないですが、苦手意識が強く、実際にAWSを使用した環境構築をしたことはありませんでした) 研修の流れ・所感 1. 座学 IPアドレス、サブネット、OSの種類等について、インフラの基礎知識 region, availability zone, EC2, ALBなど、AWSの基礎知識 わかったこと 前述の通り、IPアドレスやOSについては軽く勉強したことがあったので、教えていただきながら理解することができました。 わからなかったこと インターネットゲートウェイ、セキュリティグループ、ロードバランサーの設定は、どこをどこに繋げれば良いかわからず混乱しました。 特にセキュリティグループのインバウンドルールはどこを開ければ良いか迷いましたが、調べたり質問しながらハンズオンで実際に環境構築することで慣れていき、最終的にはうまく繋げることができました? 2. 開発環境構築(ハンズオン) EC2を使用し開発用サーバ構築 構築した開発用サーバへSSH接続し、必要なものをyumインストール Nginxのconfファイルを編集し、PHP, MySQL, Wordpressをそれぞれ使ったファイルの表示 今回用意した環境 - Amazon Linux release 2 (Karoo) - NGINX(1.18.0) - PHP(8.0.1) - MySQL(8.0.2) - PHP-FPM - Wordpress ↓こんな感じで表示できました PHPからこんにちは! DBからこんにちは! Wordpressからこんにちは! わかったこと 教えてもらいながらということもあり、開発用サーバ構築や各ソフトウェアのインストールまでは結構すんなり進めたので、それまで苦手意識しかなかったAWSですが、少し楽しくなってきました。 わからなかったこと PHP-FPMについては正直まだよくわかっていません? 調べると、PHP-FPMってなに? → FastCGIってなに? → … ってなって沼にはまりそうだったので、一旦今回は記事に従ってPHPを動かすことだけを目標に進めました… Nginxも初めて触ったのですが、403や404エラーが出て、ファイル権限あるしパスもあってるはずなのに何で??? となったり、WordpressのHTMLは正常に表示されているのにJSとCSSだけ読み込まれていなかったりとたくさんはまり、小さなエラーの解決に何時間もかかったので、まだ勉強が必要だと感じました。(今回の研修で一番Nginxが一番難しかった…?) 3. 本番環境構築(ハンズオン) 開発用サーバからAMIの取得、そのAMIから本番用のEC2を起動 SSL証明書の取得、HTTPS化 ドメインの用意 開発環境で使用したDBを別サーバ(RDS)へ移行し、ウェブサーバとDBサーバを分離 ロードバランサ(ALB)の作成、起動したEC2の紐付け Auto Scalingの設定 Apache Benchを使用し負荷テスト、スケールイン/アウトしているか確認 わかったこと ロードバランサ設定→セキュリティグループ設定→ターゲットグループ設定というALB作成の流れを掴むことができた。 また、Auto Scaling設定後の負荷テスト実施時、CloudWatchでスケールイン/アウトしている動きが目に見えて理解しやすかった。 わからなかったこと(はまったところ) Nginxの設定ファイル編集中、急にSSH接続できなくなりAWSコンソールを確認すると、接続先のインスタンスが停止されており、それまで作業していたインスタンスの中身が全部吹っ飛びました? 何事かと思い相談すると、Nginxの設定に間違いがあり、Auto Scalingに設定しているインスタンスのヘルスチェックが通らず、インスタンスが自動停止されたようでした… 練習用で良かった…? この事件のおかげでAuto Scalingの設定時に気を付けるべきことやAMIを取得しておくべきだということを学びました? 4. 個人アプリ検討、選定、実装 今回の研修の成果発表として、社内で使えるようなアプリを選定、実装することにし、私はRoulette.jsを使わせていただくことにしました。 (環境は上記で3. 本番環境構築で構築したものをそのまま使用) 振り返り Keep AWSを使用した簡単なWEBアプリケーション環境を構築し、作成手順や構造を把握することができた。 「ロードバランサー」や「Auto Scaling」など、聞いたことはあるけど漠然と「便利なんだな」としか認識していなかった言葉が、実際どういう風に使われ、どう便利なのかわかってきた。 Problem Nginxの設定がまだあまり理解できておらず、404エラーが発生したり、その404エラーを修正すると今度はWordpress内のJSとCSSだけが反映されなくなったりと、Wordpressを表示するだけでも手間取った。 (そもそもNginxにエラーログがあることを知らず、ブラウザに表示されるエラー(404とか)のみを見て戦っていたので、エラー修正にとても時間がかかった) Try エラー発生時、表示されるエラーだけを見て対処するのではなく、他にも見えないところでエラーが発生していないか、デバッグの方法も調べるようにする。 まとめ ハンズオンしてみると、ドキュメントを読むだけではわからなかったエラーがたくさん発生するので、やっぱり実際に体験してみることが一番ですね! 苦手意識しかなかったインフラ構築ですが、今回の研修で苦手克服への第一歩を踏み出しました? 私が今関わっているプロジェクトでもAWSを使用しているので、今後はその業務に生かせるよう引き続き勉強します?? 参考記事集 AWSを理解するにあたりお世話になった記事 0から始めるAWS入門:概要 PHP8系のインストールで詰まった時一番参考にした記事 Installer PHP 8 & NGINX sur AWS EC2 一瞬でABテストできるようになる記事 Apache Benchでサクッと性能テスト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CodeDeployでEC2をデプロイするための設定作業

CodeDeployでEC2をデプロイできるように、事前の設定作業が必要なので、大まかな流れだけをまとめてみた。 EC2側の設定 アタッチするIAMロールの設定 (参考: Step 4: Create an IAM instance profile for your Amazon EC2 instances) ポリシーの作成 ロールの作成 タグの設定 CodeDeployエージェントをインストールする CodeDeployエージェント CodeDeploy agentを起動しているか sudo systemctl status codedeploy-agent CodeDeployログの確認 sudo tail -f /var/log/aws/codedeploy-agent/codedeploy-agent.log sudo tail -f /opt/codedeploy-agent/deployment-root/deployment-logs/codedeploy-agent-deployments.log CodeDeploy側の設定 アプリケーションの作成 デプロイグループの作成 EC2に設定したタグでデプロイ対象を指定する 参考 Configure an Amazon EC2 instance to work with CodeDeploy Step 4: Create an IAM instance profile for your Amazon EC2 instances
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudWatchLogsの特定の文字列を含むログをSlackに転送する -後編-

slackへのbotの導入やlambdaのアップロードまで サブスクリプションフィルターの設定 対象となるロググループのコンソール画面よりサブスクリプションフィルターを設定します lambdaのトリガーとなる文字列を指定 今回はERRORもしくはerrorという文字列を含む場合に指定のlambdaを実行するように設定します。 結果
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windows版Bitnami Redmineの移行覚書(3.4.2-4 > 3.4.6-5)

ローカルサーバのBitnami Redmine(Windows版)をAWSに移行したので、その移行方法覚え書き。 移行先のバージョン 現在のBitnami Redmine最新バージョンは4.2.1(2021/05/10現在)。公式ページからダウンロード可能。 最初は最新版に更新しようと思っていたけれど、ひとつハマりどころが。 現サーバのRedmineに管理ユーザでログインして 管理 > プラグイン を見ると現在使っているプラグインが分かるのだけど、使っているプラグインが4.1系に対応していない! というわけで3.4系の最終版である3.4.6を入れることになったのでした。 サーバ構築 普通にAWSのEC2で構築。ちゃんとやるならLinuxで作ったほうがメンテナンスは楽だと思うけれど、移行自体に手間を掛けたくなかったのでWindows Server 2019にした。 インスタンスサイズは小さいものでいいのだが、Windowsにt3.microでも大丈夫か……? ま、t3.smallでいいか。公式のAMIからサクッと作って日本語化、PC名とかその他諸々必要な設定を実施。 インストール 3.4.6のインストーラが公式にない! ってことで、URLを直に打ってダウンロードする。これ。 あとは管理者で実行して普通にインストール。途中でユーザIDとパスワードを入れるところがあるが、パスワードに注意。MySQLのrootユーザのパスワードもこのユーザのパスワードと同一になるのだ。また、メール設定については後でやればいいやと思ってチェックを外した。 インストール後、忘れてはいけないのが環境変数の設定。これしないと後でコマンド叩くときにすごく面倒くさい。 環境変数 PATH に、いまインストールされたRubyのフォルダを追加する。これ↓。 <インストールフォルダ>\ruby\bin\ DBのmigration 念の為DBのドロップをしてからデータ移行するので、Pluginのインストールとかより先に実施。 旧サーバからバックアップ まずは旧サーバからデータを回収。コマンドプロンプトでコマンドを実行。 旧サーバ cd <インストールフォルダ>\mysql\bin mysqldump -u bitnami -p bitnami_redmine --default-character-set=binary > %TEMP%/redmine-sqlbackup.dmp Enter Password: とか言われるので、bitnamiユーザのパスワードを入れる。このパスワードはRedmineインストール時に自動生成されるもので、<インストールフォルダ>\apps\redmine\htdocs\config\database.yml に書いてある。サーバ毎に異なるので、旧サーバで上記ファイルを確認すること。 少し待つと %TEMP% (C:\Users<ユーザ名>\AppData\Local\Temp)にダンプファイルが出力される。これを新サーバへコピーする。 新サーバでレストア まずは初期DBをDROPする。コマンドプロンプトを起動。 新サーバ mysql -u root -p mysql> DROP DATABASE bitnami_redmine; mysql> CREATE DATABASE bitnami_redmine; mysql> GRANT all privileges on bitnami_redmine.* to bitnami@localhost; mysql> flush privileges; mysql> exit; mysql -u bitnami -p bitnami_redmine < <旧サーバからコピーしたダンプファイルのフルパス> 最初のコマンドでまたパスワードの入力を求められる。これは、Redmineインストール時に初期ユーザで設定したパスワードを入力する。 成功すると mysql にログインできるので、DBのDROPとCREATE、bitnamiユーザへの権限付与を実施する。 最後は、bitnamiユーザでDBデータをレストア。パスワードは先程バックアップしたときと同じく、新サーバのdatabase.yml を見て確認する。 Redmineの新旧のバージョンが大きく違う場合はmysqlのバージョン変更などにより、もう少し諸々の設定変更などが必要になったりすることもあるが、今回はそのあたりは不要だった。 よって、データの移行についてはこれでOK。 添付ファイルの移行 ファイルを旧サーバから新サーバにコピーする。場所はここ。 <インストールフォルダ>\apps\redmine\htdocs\files Pluginのインストール Pluginのファイルを <インストールフォルダ>\apps\redmine\htdocs\plugins にコピーする。ファイルは、旧サーバのRedmine > 管理 > プラグイン に公式ページがあるのでそこからダウンロード。いちいち Git コマンド叩いたりしなくてもブラウザから行ける便利さがWindowsの強み。更新がないなら、旧サーバの同じフォルダからフォルダごとコピーしてきてもOK。 それから、コマンドプロンプトを開いてRubyのコマンドを叩く。インストール後に環境変数を設定していないと見つからないとか言われるので気をつけよう。 cd <インストールフォルダ>\apps\redmine\htdocs bundle install bundle exec rake redmine:plugins:migrate RAILS_ENV=production Rubyはよく知らないが、後ろの「RAILS_ENV=production」は本番環境のDBをいじるための決まり文句のようなものらしい。productionの他にはdevelopmentとかtestとかがあるようだ。 今回はうまくいっていたが、bundle install時にdevelopmentが云々とかのエラーが出ることがあるらしい。その場合は末尾に --without オプションを追加する。その場合、インストールコマンドは以下のようになる。 bundle install --without development これでプラグインのインストールも完了。Redmineを再起動させる。 再起動は、<インストールフォルダ>\manager-windows.exe からやるのが便利でよい。exeを叩いて Manage Servers のタブを開き、下部の Restart All で再起動する。 このツールのショートカットでも作っておくと後が楽。 メール設定 このままでも動作には問題ないが、メールを飛ばしたいならメールサーバの設定を入れる必要がある。なぜか管理画面からはできないようなので、ファイルを直接編集。 ファイルはここにある。なければメモ帳で空のファイルを作る。 <インストールフォルダ>\apps\redmine\htdocs\config\configuration.yml ファイルの一番上の方にメール設定があるので、とりあえずコメントアウトしてしまう。 configuration.yml # email_delivery: # delivery_method: :smtp # smtp_settings: # # address: smtp.gmail.com # port: 587 # domain: example.net # authentication: :login # user_name: # password: 該当箇所の先頭に # を付けてコメントアウトした。 コメントアウトした場所の直下に自分のメール環境を追記する。 設定方法はどのメールサービスを利用するかによって変わるので注意。以下はAWSのSES(東京リージョン)を利用している場合。 configuration.yml production: email_delivery: delivery_method: :smtp smtp_settings: enable_starttls_auto: true address: "email-smtp.ap-northeast-1.amazonaws.com" port: 587 domain: "<mydomain.com>" authentication: :login user_name: "<user>" password: "<password>" それ以外のメールサービスは、Redmineガイドに詳しい。 ファイルを上書き保存(管理者権限でないと保存できないので、一旦別のところに保存して上書きする等してみる)したら、先程と同様にmanager-windows.exeで再起動して、管理ページからテストメールが送信できるか試してみる。 問題なく送信できれば設定完了。 なお、当環境では、メールサーバにM365(Exchange)を設定するとテスト送信時にInternal Errorが出るという状況に陥った。ログファイル(<インストールフォルダ>\apps\redmine\htdocs\log\production.log)を確認したところ、ActionDispatch::Cookies::CookieOverflowというエラーが発生していた。Rubyに依存する問題で、Cookieが4kbを越えると出るらしい。ちゃんと対応するのであれば、activerecord-session_storeなんかを入れて、MySQL上でセッションを管理するとよいようだ。 こちらではメールサーバをAWS SESに変更したらエラーが解消されたので、M365のせいということにしてスルー。 終わり 以上でRedmineの移行が完了した。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】セキュリティグループとネットワークACL

プログラミング勉強日記 2021年5月10日 セキュリティグループ  インスタンスへのトラフィックのアクセス可否を設定する。なので、EC2のアクセス制御はセキュリティグループによって行う。EC2に対する権限の設定はIAMで行うが、どこのPCが・どのユーザがサーバーにアクセスできるのかということはセキュリティグループが通信の制御をしている。  例えば、EC2インスタンスをWebサーバーにしてホームページを作った場合、HTTPのトラフィックのアクセスが許可されていないとみることができない。以下のような設定だと、セキュリティグループはポート22のSSHのみを許可している。つまり、ホームページを作ってもホームページにアクセスできない設定状況になっている。EC2インスタンスの内部の操作をするためにはSSHプロトコルを使ってアクセスをする。    それぞれのEC2インスタンスに対して1つずつセキュリティグループを設定する。同じ設定であれば1つのセキュリティグループで複数のEC2インスタンスに共有して使うこともできる。 ネットワークACL  トラフィック制御の1つでサブネットに対するトラフィック制御を実施する。要するに、仮想ネットワーク自体に制御するためにはネットワークACLを使う。 セキュリティグループとネットワークACLの違い  トラフィック設定はセキュリティグループかネットワークACLを使う。 セキュリティグループ設定 ネットワークACLs設定 サーバー単位で適用する VPC/サブネット単位で適用する ステートフル(インバウンド※1 のみの設定でアウトバウンド※2 も許可される) ステートレス(インバウンド設定のみではアウトバウンドは許可されない) 許可のみをin/outで指定 許可と拒否をin/outで指定 デフォルトではセキュリティグループ内通信のみ許可 デフォルトではすべての通信を許可 すべてのルールを適用 番号の順序通りに適用(複数の通信制御を設定した場合、上のだけ適用されて後ろは適用されないこともある) ※1 インバウンド:トラフィック制御の入り口(外からEC2インスタンスにくるトラフィック) ※2 アウトバウンド:外部に通信を出すこと(EC2インスタンスから外に通信を出す)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】Amazon SESの署名バージョン4に対応させる

はじめに RailsでAmazon SESの署名バージョンを3から4に対応させたときの備忘録です。 SESのライブラリはgem 'aws-ses'を使っていました。 人によってファイルの設定やリージョンなどは異なるので、あくまで参考程度にしてください。 環境 Rails 6.0.3.7 ruby 2.6.5 MacOS gem 'aws-ses', '~> 0.6' エラー内容 FATAL -- : AWS::SES::ResponseError (InvalidClientTokenId - Signature Version 3 requests are deprecated from March 1, 2021. From that date on, we are progressively rejecting such requests. To resolve the issue you must migrate to Signature Version 4. If you are self-signing your requests, refer to the documentation for Authenticating requests to the Amazon SES API [1] with Signature Version 4 [2]. If you are not self-signing your requests, simply update your SDK/CLI to the latest version. [1] https://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-ses-api-authentication.html [2] https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html): google翻訳 致命的-: AWS :: SES :: ResponseError(InvalidClientTokenId-署名バージョン3のリクエストは2021年3月1日から非推奨になりました。その日以降、このようなリクエストは段階的に拒否されます。問題を解決するには、署名バージョン4に移行する必要があります。 -リクエストに署名するには、署名バージョン4 [2]を使用したAmazonSES API [1]へのリクエストの認証に関するドキュメントを参照してください。リクエストに自己署名しない場合は、SDK / CLIを最新バージョンに更新してください。[ 1] https://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-ses-api-authentication.html [2] https://docs.aws.amazon.com/general/latest/gr/ sigv4-create-canonical-request.html): エラーの内容通り、署名バージョンを4に移行させる必要があるそうです。 やったこと gem 'aws-ses', '~> 0.6'を gem aws-ses-v4に変えた。 aws-sesのissuesをみると、バージョン4に移行することについて結構多くの人が話していました。 gem aws-ses-v4はgem 'aws-ses'を署名バージョン4に対応させたgemです。 他にもAWSが推奨しているaws-sdk-railsというGemがあるそうですが、そちらに移行させる時間はなさそうだったので今回はaws-ses-v4を使うことにしました。 できれば公式が推奨している方を使うべきだと思います。 Gemを変更 Gemfile - gem 'aws-ses', '~> 0.6' + gem "aws-ses-v4", require: "aws/ses" $ bundle install aws.rbの変更 ここら辺は人によって違うかもしれません。 各々のメールの設定に合わせてください。 ちなみに私は最終的に以下のようになりました。 config/initializers/aws.rb ActionMailer::Base.add_delivery_method :ses, AWS::SES::Base, access_key_id: Rails.application.credentials.aws_ses_access_key_id, secret_access_key: Rails.application.credentials.aws_ses_secret_access_key, server: 'email.リージョン名.amazonaws.com', #人によって違います region: 'リージョン名' #SESのリージョンを指定。 例:us-east-2 以下のエラーが出た時はSESのリージョンが間違っている可能性があります。 SignatureDoesNotMatch - Credential should be scoped to a valid region, not 'ap-northeast-1' また、awsのアクセスキーなどを記載するcredentials.yml.encには、以下のコマンドで確認・編集できます。 EDITOR=vim rails credentials:edit 以上です。 参考 aws-ses GitHub aws-ses-v4 GitHub 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudWatchLogsの特定の文字列を含むログをSlackに転送する①

完成例 slack apiにアクセスしてアプリを作成 botの作成の仕方やslackへのメッセージ投稿の仕方は以下の記事を参考にしてください。 Pythonのコードのディレクトリ構造 ディレクトリ構造は以下のようになっています ディレクトリ構造 sendLogToSlack ├── lambda_function.py ├── postslack.py └── slack_sdk slack_sdkのインストール slack_sdkはlambdaの標準モジュールではないので、 pipでインストールしてからzipでパッケージ化する必要があります。 ディレクトリ構造 mkdir sendLogToSlack cd sendLogToSlack pip install slack_sdk -t ./ lambda_function.py lambda_function.py import zlib import base64 import postslack import json def lambda_handler(event, context): data = zlib.decompress(base64.b64decode(event['awslogs']['data']), 16+zlib.MAX_WBITS) data_json = json.loads(data) log_json = json.loads(json.dumps(data_json["logEvents"][0], ensure_ascii=False)) postslack.SendSlackMessage(str(log_json)) こちらの記事を参考に作成させて頂きました。 postslack.py postslack.py from slack_sdk import WebClient from slack_sdk.errors import SlackApiError def SendSlackMessage(message): client = WebClient(token='your_token') response=client.chat_postMessage(channel='your_channel', text=message) slack_sdkの使い方に関してはこちらの記事で紹介しています。 パッケージ化 lambdaにアップロードする為にzipコマンドでパッケージ化します。 sendLogToSlack zip -r sendslack * lambdaにアップロード 続き ここまで出来れば残りの作業はもう少しです。 CloudWatchLogsの特定の文字列を含むログをSlackに転送する②に続きます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudWatchLogsの特定の文字列を含むログをSlackに転送する -前編-

完成例 slack apiにアクセスしてアプリを作成 botの作成の仕方やslackへのメッセージ投稿の仕方は以下の記事で紹介しています。 Pythonのコードのディレクトリ構造 ディレクトリ構造は以下のようになっています ディレクトリ構造 sendLogToSlack ├── lambda_function.py ├── postslack.py └── slack_sdk slack_sdkのインストール slack_sdkはlambdaの標準モジュールではないので、 pipでインストールしてからzipでパッケージ化する必要があります。 ディレクトリ構造 mkdir sendLogToSlack cd sendLogToSlack pip install slack_sdk -t ./ lambda_function.py lambda_function.py import zlib import base64 import postslack import json def lambda_handler(event, context): data = zlib.decompress(base64.b64decode(event['awslogs']['data']), 16+zlib.MAX_WBITS) data_json = json.loads(data) log_json = json.loads(json.dumps(data_json["logEvents"][0], ensure_ascii=False)) postslack.SendSlackMessage(str(log_json)) こちらの記事を参考に作成させて頂きました。 postslack.py postslack.py from slack_sdk import WebClient from slack_sdk.errors import SlackApiError def SendSlackMessage(message): client = WebClient(token='your_token') response=client.chat_postMessage(channel='your_channel', text=message) slack_sdkの使い方に関してはこちらの記事で紹介しています。 パッケージ化 lambdaにアップロードする為にzipコマンドでパッケージ化します。 sendLogToSlack zip -r sendslack * lambdaにアップロード 続き ここまで出来れば残りの作業はもう少しです。 CloudWatchLogsの特定の文字列を含むログをSlackに転送する-後編-に続きます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CloudWatch Logs Insight】サンプルクエリ

2xx 系のメッセージログを抽出する fields @message | filter (status < 300) | display @message | limit 10 特定の送信元 IP アドレス以外の 送信元 IP アドレスごとのリクエスト数をカウントする fields @message | filter ip not in ["<除外したい IP アドレス1>", "<除外したい IP アドレス2>", ...] | stats count(*) as count by ip | sort count desc | limit 10 送信元 IP アドレス, リクエストメソッド, リクエストURI ごとのリクエスト数をカウントする fields @message | stats count(*) as count by ip, httpMethod, resourcePath, status | sort count desc | limit 10 上記のサンプルの参考サイト 送信元 IP ごとにカウント fields @message | filter @logStream =~ /<ログストリーム名>/ | parse @message '* * * [*] "* * *" * "*" "*"' as srcIpAddress, srcUser, remoteUser, timestamp, httpMethod, requestUri, protocol, statusCode, transferredData, referer, userAgent | filter requestUri = "/" | filter statusCode =~ /2\d\d/ | stats count(*) as count by srcIpAddress | sort count desc | limit 10 parseコマンドの参考サイト
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WEBアプリ『ひとこと日記』概要

アプリの概要 アプリ名:ひとこと日記ver2 日々の記録をテキスト形式で保存する、シンプルな日記アプリです。 コードはGithubにてご覧いただけます。(フロントエンドのコード・バックエンドのコード) 作成環境 ・インフラ:AWS ・バックエンド:node.js + Express ・フロントエンド:Vue.js ・データベース:MySQL ●各バージョン node.js v12.18.2, Express 4.17.1, Vue.js 2.6.12, Veu-CLI 4.4.6, MySQL 8.0 アプリで行う主な処理 ユーザー登録・認証処理 日記のCRUD処理 アプリの構成 ・インフラは、AWSのEC2上にExpressサーバーを立て、RDS上にMySQLデータベースを立てています。 ・フロントエンドは、Veu-CLIを使って構築し、SPAにしています。(Nuxt.jsは使っていません) ・Expressサーバーにて、SPAのホスティングと、データベース処理用のエンドポイントの提供を行っています。 ・Vue.js-Express間の通信は、axiosでデータをやり取りしています。 サーバーとクライアントの構成図 ユーザー登録・認証機能の動作 ・UIからユーザー登録、ログインを行います。 ・Vue.jsからaxiosで通信し、Expressサーバーのエンドポイントへアクセスすることで、ユーザー登録、ログインの処理を実現します。 ・ログインするとトークンが発行され、以降の処理はトークンによってユーザーを一意に特定します。 日記機能の動作 ・UIから日記の表示・作成・更新・削除を行います。 ・Vue.jsからaxiosで通信し、Expressサーバーのエンドポイントへアクセスすることで、日記のCRUD処理を実現します。 ・axios通信時にサーバーにトークンを送信することで、ユーザーを一意に特定して、日記データを処理します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】 ロードバランサーとAutoScaling について no.11

こんにちは、まゆみです。 AWSについての記事をシリーズで書いています 今回は第11回目になります。 今回の記事では AWSのロードバランサー Auto Scaling について書いていこうと思います ではさっそく始めていきますね。 ELBとは? ELBとはElastic Load Balancer のことです。 以前に第1回目の記事で、クラウドサービスとオンプレミスを比べた時の特長について書かせていただきましたが、ELBを活用する事によって、 障害に強く スケーラブルな(拡張性の高い) システムを構築する事ができます ELBの役割 あなたが、一つのサーバーだけでサイト運営をしているとします 平均的に1時間に1000人の人がアクセスするから、それに耐えられるサーバーをと。。。 それは最善の策でしょうか? ある時間によっては、一時的にでもアクセスが爆増する事もあるかも知れません。 また、サーバーがクラッシュしてしまったらどうでしょうか? ELBであらかじめリスクヘッジをしておけば、そのような事に対処できます。 ①ELBに関連付けられたEC2インスタンスにトラフィックを均等に配分して、負荷を軽減させることができます ②何かの理由で、サーバーがクラッシュした時に、(ヘルスチェックという)切り離しをしてくれる では、さらに既存のサーバーに均等に振り分けるのでも足りないくらいアクセスが増えた時はどうでしょうか? その時の対処法を下記に書いていきます Auto Scalingとは? Auto Scaling とは必要に応じて、インスタンス数を増減させてくれるサービスです 引用元:AWSドキュメント Auto Scaling に実際触ってみる では、実際にAWSのコンソールからAuto Scaling を使ってみましょう まずは、テンプレートを作ります 下のような画面になりますので、例にならって記入してみてください。 そのままスクロールしていくと『高度な詳細』と書いてあるところがあるので、そこを開いて一番下のユーザーデータに下のコードをコピペしてみてください。 ユーザーデータとは以前にこちらの記事でも説明させていただきましたが、 インスタンスが最初に起動させられた時に実行されるコードになります。 下記のコードの詳しい解説は割愛させていただきますが、下記のコードをユーザーデータにコピペしておくことで、このインスタンスを起動させた時に、『当該インスタンスが、どこのサブネットに存在しているか』を示させることができます #!/bin/bash yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd EC2AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone) echo '<center><h1>This Amazon EC2 instance is located in Availability Zone: AZID </h1></center>' > /var/www/html/index.txt sed "s/AZID/$EC2AZ/" /var/www/html/index.txt > /var/www/html/index.html EC2のダッシュボードに戻り、一番下の『Auto Scaling グループ』を開きます 下のスクショの例にならって選択します。 サブネットは全て選択します。(Auto Scale によってインスタンスが作られる時、どのサブネット内に作られるかを決めることができます) 『次へ』をクリックします 下のようなページになるので、そのまま何も変えずに『次へ』をクリック 最小キャパシティと最大キャパシティを2にして、次へ進みます あとは最後まで何も変えずに『次へ』をクリックし続けて、Auto Scalingグループを作ってください。 正常に作られた後、Auto Scaling グループの詳細を見てみます アクティビティのタブをクリックして開くと、EC2が2つ作られているのが表示されています また、インスタンスも、各サブネットに2つづつ作られました。 先ほどユーザーデータにコピペしたコードが上手く実行されるか見てみますね。 うまく行っています では、次にロードバランサーに触れていきましょう ロードバランサーを作る ロードバランサーから均等にインスタンスにトラフィックが配分され負荷を減らすわけですが、どのインスタンスでトラフィックを分けるか決めます それが、ターゲットグループになります グループ詳細の指定については、特に変更なしでそのまま次に進みます 使用可能なインスタンスは全て選択します 少しスクロールすると、『保留中として以下を含める』と書いてあるところがあるのでそちらもクリックして選択します ロードバランサーを作ります ウェブアプリケーションを作っているので、『Application Load Balancer』を選択します 下のようなページに行きます。少しスクロールするとアベイラビリティゾーンを選択するところがあるので、全て選択しましょう 先ほど作ったターゲットグループを選択します 後は、そのまま何も変えずに次へ進んで、ロードバランサーを作ります ロードバランサーがどのように働くか見る前に、一応、ターゲットグループのヘルス状態が正常が見てみますね。 では、ロードバランサーがちゃんと、既存のEC2インスタンスに均等にトラフィックを割り当てているか見てみます ロードバランサーのDNS名をコピーして、新しいブラウザーに貼り付けてみます リロードするたびに、アベイラビリティゾーン名が変わっているのが分かると思います まとめ 今回の記事はこれで締めくくらせていただきます お役に立てれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Google Mediapipe Holisticを使って人の行動判定を試作しました

Google Mediapipe Holisticを使って人の行動を判定する技術を紹介します。 なお、本内容は、TECH PLAY 2021/4/21のイベントの「映像分析の楽しいモノづくり~手軽な映像分析AIやクラウドの活用~」で紹介した試作と同じものになります。 (本ブログでは、上記のイベントで細かいところまで紹介できなかった内容やプログラムの一部を共有させていただきます) 前提として、以下がありますので、ご注意ください。 * 動作確認のブラウザは、Google Chromeを使いました。 * 2021年3月頃に調べたり動作確認した内容です。 目次 1.はじめに 1.1.私の裏話 2.構成 2.1.Google Mediapipe Holistic 2.2.AWSの活用サービス 2.3.Webアプリ 3.技術解説 3.1.Google Mediapipe Holisticのデータ活用と姿勢判定用のデータ化 3.2.姿勢判定のカスタマイズ 4.おわりに a.参考リンク 1. はじめに 今回試作したプロトタイプの概要は、以下のイメージ図となります。 ここで実現しているものは、カメラ画像からクラウド(AWS)で姿勢を推定し、例えば、挙手をしたら、Zoomの挙手ボタンを自動的に押したり、ビデオをONにするといった、ジェスチャーによるリモートコミュニケーション支援です。 他にも、複数の人をVRで表示したり、色々なことに活用できると思っています。 1.1. 私の裏話 私の業務は、新技術をみつけて検証し、使える・使えない・使うなら!を明らかにして、開発に役立ててもらうといったことです。 しかし、まだ経験が浅いこともあり、思っていたよりも難しさを感じております。 (本当は、社会課題等の課題を持つお客さんとPoC検証をすることが目標です。以前、色々教えてくれた先生に、現場に入りこむことの大切さを教えてもらったこともありまして) そんな中、2020年6月にGoogle Mediapipeを知りました。 Google MediapipeのWebサイトを見たとき、なんかすごそう。いろいろできそう。と思ったのを覚えています。 その時プロトタイプ検証の候補を選定していたので、Google Mediapipeを検証するチャンスがありましたが、別の検証に決まり、触ることはできませんでした。 でも、1月にまた候補を選ぶチャンスがあり、そこで、検証することができるように持っていけました。 2. 構成 今回試作したプロトタイプの構成は、以下のイメージ図となります。 AWSをインフラにして、Google Mediapipe Holisticで人の姿勢推定を動かし、Webアプリでユーザが活用する感じです。 個人的にですが、2020年度からWebアプリにはまっています。色々なデバイスで稼働でき、改造も色々できるので、ちょっとしたプロトタイプ作成によさそうです。 ただ、どうしてもできない領域があるので、そこは別の何かと連携させて何とか回避するしかないのが難点ですかね。 あと、今回の構成で、Webブラウザ上で稼働するGoogle Mediapipe Holisticを使っているのにクラウド(AWS)連携させていることを疑問に思われるかもしれません。 Webブラウザ上で快適に稼働する設備が手元になく、またクラウド活用の要望もあり、このような構成にしました。 Google Mediapipe Holisticは軽量で高速なので、7年前のCore i5のノートPCでも、最近のミドルレンジのAndroid端末でも十分に動作しましたので、次は、Webアプリ単体での構成にトライしたいところです。 では、以下で、構成内のそれぞれのパーツについて、補足させてもらいます。 2.1. Google Mediapipe Holistic この画像認識AIは、色々な方のブログでも登場しており、ご存じの方も多いと思いますが、百聞は一見に如かず、ということで、こちらの公式Webサイトをご覧になると、すごそうなことがわかると思います。 Webデモもあり、自分のカメラで動かして、手軽に試すこともできます。(残念ながら、手持ちのiPhone 7等のiOS系ではWebデモは動作しませんでした) Google Mediapipeは、クロスプラットフォームで軽量で高速で、色々なソリューション(顔検出から物体検出等も)を提供しています。 ライセンスもApache-2.0なので商用向けにも扱いやすいです。 Google Mediapipe Holisticは、以下の図の通り、一人の人の全身と両手と顔のランドマークというポイントの座標データ(x,y,z座標等)が得られます。(内部を改造するともっといろいろできるのかもしれません) 2.2. AWSの活用サービス 今回は、S3にWebアプリのソースを配置して、署名付き一時URLで共有しつつ、コンテナインフラECSのFargateでGoogle Mediapipe HolisticのPython版を載せたDockerイメージを稼働させました。 そして、Kinesis Data Streamsを使って、Webアプリとコンテナ間で、データ(画像と姿勢データ)を送受信しました。 Fargateは、コンテナイメージに個別の設定(使用するKinesis Data Streamsの名前等)を入れて動作させてしまいました。 このやり方だと、個別ユーザ対応できないので、環境変数の機能を使う等の改善が必要だとは考えております。 2.3. Webアプリ AWS SDK for JavaScriptを使って、カメラ映像から画像データをKinesis Data Streamsに順次送信し、 AWSで分析された姿勢データをKinesis Data Streamsから順次受信させました。 受信した姿勢データを使って、グラフへ描画したり、簡単な行動の判定を行ったりしました。 ユーザがグラフや行動の判定をWebアプリ上でカスタマイズできるように、JavaScriptのFunction機能を活用しました。(最初eval()を使おうとしたら、使わずにFunctionを使うこと、と記載がありましたので切り替えました) Webアプリ上に、TextAreaを用意して、そこに記述されたプログラムを、姿勢データ受信後に実行させることで、プログラムでカスタマイズが可能となりました。 作成したWebアプリは、こんな感じの見ばえです。デザイン性はないですが、機能は盛り込みました。 3. 技術解説 姿勢を汎用的に判定できるようにするために、姿勢データを行動の判定がしやすいように、データを拡張したことや、 あと、色々な判定ができるようにするためのカスタマイズ部分について、以下で紹介させてもらいます。 3.1. Google Mediapipe Holisticのデータ活用と姿勢判定用のデータ化 Google Mediapipe Holisticから得られたデータはカメラからの相対的なx,y,z座標データ等です。 このデータだと、プログラムや機械学習による姿勢判定で使うには、汎用性がなかったり難しいように思えました。 例えば、人の向きとかが変わると、結果が大きく変わったりするのでは、と推測しました。 なので、以下の図のように、体の軸のデータを追加しつつ、関節どうしをベクトル化し、関節の角度を追加しました。 また、体の軸に対する各ベクトルの角度も出し、色々とデータを追加しました。 そして、手も同様に、手の軸のデータを追加しました。以下の図のような感じです。 また、体と手の関係により、手のジェスチャーも変わってくるので、体の軸に対する手の軸の角度も追加しました。以下の図のような感じです。 上記で追加したデータすべて使っているわけではありませんが、現在は試作段階なので、今後最適化して不要なのは削除したいとは思います。 上記の作業の中、苦労したのが、体の軸で前向きのベクトルを算出する計算です。 座標変換のサイトを参考にさせてもらいつつ、頭で考えていたのですが、難しくうまく進みませんでした。 割り箸で、x,y,zの3軸を形作ったものを回しながら考えるとよい、という情報があったので、爪楊枝で以下の写真のものを作って考えると、だいぶましになりました。(でもまだまだ自信はありません。大学時代に勉強していたはずなのですが、もう記憶になく頭もなかなかついてきません) 以下が、自作した座標変換(回転、移動)をイメージするツールです。 こんな状況の中、作成した座標変換のライブラリのコードを共有させてもらいます。(間違っているところがありましたら、ご指摘いただけると幸いです。) Python実装です。 座標変換サンプルコード(coordinateTransformatinLib.py)(ここをクリックするとコードが表示されます) import numpy import math x_line = numpy.array([1.0, 0.0, 0.0]) y_line = numpy.array([0.0, 1.0, 0.0]) z_line = numpy.array([0.0, 0.0, 1.0]) def x_turn(angle): angle_radians = math.radians(angle) return numpy.array([[1.0, 0.0, 0.0], [0.0, numpy.cos(angle_radians), numpy.sin(angle_radians)], [0.0, -numpy.sin(angle_radians), numpy.cos(angle_radians)]]) def y_turn(angle): angle_radians = math.radians(angle) return numpy.array([[numpy.cos(angle_radians), 0.0, -numpy.sin(angle_radians)], [0.0, 1.0, 0.0], [numpy.sin(angle_radians), 0.0, numpy.cos(angle_radians)]]) def z_turn(angle): angle_radians = math.radians(angle) return numpy.array([[numpy.cos(angle_radians), numpy.sin(angle_radians), 0.0], [-numpy.sin(angle_radians), numpy.cos(angle_radians), 0.0], [0.0, 0.0, 1.0]]) def get_subtended_angle(p1, p2): inner = numpy.inner(p1, p2) length1 = numpy.linalg.norm(p1) length2 = numpy.linalg.norm(p2) radian = numpy.arccos(inner / (length1 * length2)) angle = numpy.rad2deg(radian) if numpy.isnan(angle) == True: angle = -360.0 # to no nan TODO return angle LINE_ID_X = 0 LINE_ID_Y = 1 LINE_ID_Z = 2 def get_line_consider(consider_vec, target_line, turn_line): target_angle_vec = numpy.array([0.0, 0.0, 0.0]) if target_line == LINE_ID_X: ajust_line = x_line target_angle_vec[0] = consider_vec[0] if turn_line == LINE_ID_X: pass # TODO invalid ? elif turn_line == LINE_ID_Y: target_angle_vec[2] = consider_vec[2] turn_api = y_turn elif turn_line == LINE_ID_Z: target_angle_vec[1] = consider_vec[1] turn_api = z_turn elif target_line == LINE_ID_Y: ajust_line = y_line target_angle_vec[1] = consider_vec[1] if turn_line == LINE_ID_X: target_angle_vec[2] = consider_vec[2] turn_api = x_turn elif turn_line == LINE_ID_Y: pass # TODO invalid ? elif turn_line == LINE_ID_Z: target_angle_vec[0] = consider_vec[0] turn_api = z_turn elif target_line == LINE_ID_Z: ajust_line = z_line target_angle_vec[2] = consider_vec[2] if turn_line == LINE_ID_X: target_angle_vec[1] = consider_vec[1] turn_api = x_turn elif turn_line == LINE_ID_Y: target_angle_vec[0] = consider_vec[0] turn_api = y_turn elif turn_line == LINE_ID_Z: pass # TODO invalid ? ajust_angle = get_subtended_angle(target_angle_vec, ajust_line) return ajust_angle, turn_api def line_turn_ajust(input_vec, consider_vec, target_line, turn_line, is_reverse=False): ajust_angle, turn_api = get_line_consider(consider_vec, target_line, turn_line) if is_reverse == True: ajust_angle *= -1 ajust_array = turn_api(ajust_angle) result_vec = numpy.dot(input_vec, ajust_array) return result_vec def line_turn_ajust_x(input_vec): #print("input_vec: ", input_vec) y_line_ajust = line_turn_ajust(input_vec, input_vec, LINE_ID_X, LINE_ID_Z, False) #print("y_line_ajust: ", y_line_ajust) zy_line_ajust = line_turn_ajust(y_line_ajust, y_line_ajust, LINE_ID_X, LINE_ID_Y, True) #print("zy_line_ajust: ", zy_line_ajust) return zy_line_ajust # TODO test def line_turn_ajust_y(input_vec): x_line_ajust = line_turn_ajust(input_vec, input_vec, LINE_ID_Y, LINE_ID_Z, True) zx_line_ajust = line_turn_ajust(x_line_ajust, x_line_ajust, LINE_ID_Y, LINE_ID_X, True) return zx_line_ajust # TODO test def line_turn_ajust_z(input_vec): y_line_ajust = line_turn_ajust(input_vec, input_vec, LINE_ID_Z, LINE_ID_X, True) xy_line_ajust = line_turn_ajust(y_line_ajust, y_line_ajust, LINE_ID_Z, LINE_ID_Y, True) return xy_line_ajust def turn_vec_x(input_vec, consider_vec): y_ajust_angle, y_turn_api = get_line_consider(consider_vec, LINE_ID_X, LINE_ID_Z) y_ajust_array = y_turn_api(-y_ajust_angle) y_ajust_vec = numpy.dot(input_vec, y_ajust_array) #print("y_ajust_vec: ", y_ajust_vec) zy_ajust_angle, zy_turn_api = get_line_consider(consider_vec, LINE_ID_X, LINE_ID_Y) zy_ajust_array = zy_turn_api(zy_ajust_angle) zy_ajust_vec = numpy.dot(y_ajust_vec, zy_ajust_array) #print("zy_ajust_vec: ", zy_ajust_vec) return zy_ajust_vec def turn_vec_y(input_vec, consider_vec): x_ajust_angle, x_turn_api = get_line_consider(consider_vec, LINE_ID_Y, LINE_ID_Z) x_ajust_array = x_turn_api(x_ajust_angle) x_ajust_vec = numpy.dot(input_vec, x_ajust_array) #print("x_ajust_vec: ", x_ajust_vec) zx_ajust_angle, zx_turn_api = get_line_consider(consider_vec, LINE_ID_Y, LINE_ID_X) zx_ajust_array = zx_turn_api(zx_ajust_angle) zx_ajust_vec = numpy.dot(x_ajust_vec, zx_ajust_array) #print("zx_ajust_vec: ", zx_ajust_vec) return zx_ajust_vec def turn_vec_z(input_vec, consider_vec): x_ajust_angle, x_turn_api = get_line_consider(consider_vec, LINE_ID_Z, LINE_ID_Y) x_ajust_array = x_turn_api(x_ajust_angle) x_ajust_vec = numpy.dot(input_vec, x_ajust_array) #print("x_ajust_vec: ", x_ajust_vec) yx_ajust_angle, yx_turn_api = get_line_consider(consider_vec, LINE_ID_Z, LINE_ID_X) yx_ajust_array = yx_turn_api(yx_ajust_angle) yx_ajust_vec = numpy.dot(x_ajust_vec, yx_ajust_array) #print("yx_ajust_vec: ", yx_ajust_vec) return yx_ajust_vec 上記サンプルコードを活用したコード例(ここをクリックするとコードが表示されます) # front # body center_body_list = get_vector_list(pose['landmarks'][POSE_NO.CENTER_BODY]) center_body_vector = calc_vector_from_index(pose, pose_vector_map, POSE_NO.CENTER_BODY) center_body_vector_list = get_vector_list(center_body_vector) left_body_vector = calc_vector_from_index(pose, pose_vector_map, POSE_NO.LEFT_BODY) left_body_vector_list = get_vector_list(left_body_vector) ajust_vec = coordinateTransformatinLib.line_turn_ajust_x(left_body_vector_list) front_ajust_array = coordinateTransformatinLib.y_turn(90) front_ajust_vector = numpy.dot(ajust_vec, front_ajust_array) front_body_vector = coordinateTransformatinLib.turn_vec_x(front_ajust_vector, left_body_vector_list) front_body_list = front_body_vector + center_body_list front_body = {"x": front_body_list[0], "y": front_body_list[1], "z": front_body_list[2]} pose['landmarks'].append(front_body) # FRONT_BODY 上記を活用して、体の中心とHIPとSHOULDERの3点について、前方向のランドマークやベクトルを計算しました。 A-FRAMEで可視化すると以下のようになります。ただ、前方向が微妙に斜めになっているような気がするので、今後気を付けて確認していきたいと思います。(表示がうまくいっていないのか、計算が間違っているのか。。単体テストで簡単に確認した範囲では問題なさそうだったのですが。。。) 3.2. 姿勢判定のカスタマイズ 最初は、以下の図のように控えめな挙手を、判定していました。 上向きの角度は45°まで許容するようにしたので、結構ゆるめな判定となってしまい、挙手でない場合も挙手と判定するケースがありました。 今思えば、手の平を前に向けている、といった判定も追加すればよかったかもしれません。 上記の挙手の判定を、手のGood Jobジェスチャーの判定に変更できるように、Webアプリを作成しました。 2.3.Webアプリに記載したように、HTMLのTextAreaの入力をJavaScriptのFunction()で実行するようにしました。 ちなみにですが、Good Jobジェスチャーの判定は、以下のようなイメージで判定させました。 ただ、上記のような方法だと、JavaScriptで姿勢データを理解してプログラミングできる人しか、カスタマイズできません。 将来的には、Webアプリ上で、姿勢データの各数値と画像にラベル付けして、機械学習でラベルを判定できるようにしたいと思っています。 これができれば、プログラミングせずに姿勢判定ができるようになるかと思うので、カスタマイズのハードルが下がり、多くの人が活用できそうです。 4. おわりに OSSのGoogle Mediapipe Holisticを使って人の行動判定の試作や技術を紹介させてもらいましたが、いかがでしたでしょうか? まだまだ課題は色々あるのですが、 個人的には、Google Mediapipe Holisticを活用することで、人の姿勢推定ができ、姿勢データ拡張で汎用的になり、様々な方面で応用ができるのでは、と考えております。 特に、デフォルトでは一人向けなこともあり、在宅ワークや、リモート会議等で活用することが身近で活用シーンも多そうでよさそうに思えています。 イベントで本件を紹介させてもらった際は、「マウスの操作ができる?」といった質問もいただきました。 実際に検証してみると課題は色々と出てきそうですが、ある程度はできるのではと思えています。 みなさんもこういったツールを活用して、いろんなシーンに利用することを試してみてはいかがでしょうか。 では、最後まで参照いただきありがとうございました。 a. 参考リンク Google Mediapipe Google Mediapipe Holistic Google Mediapipe Pose Google Mediapipe Hands AWS Kinesis Data Sample Code AWS Kinesis Data Streams JavaScript PutRecord AWS ECS 環境変数の指定 3次元における回転座標変換行列
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「転生したらスライムだった件」の大賢者チャットボットを作ってみた件

チャットボットを制作していたのですが、ボットとの会話が味気ないなと感じ、思案した結果、転スラの大賢者風に話せてみようと作ってみました。 「転スラ」をご存じないという方はこちらを見てください。 https://www.ten-sura.com/ 完成イメージ動画 前回書いた記事 環境 Windows10 Virtualbox v6 Docker AWS CLI Nginx Botpress v12 PHP 参考リンク Botpressインストール 今回はWindows10上にVirtualboxをセットアップしてCentos7をインストール、そのCentos7にDockerを入れてBotpressのコンテナを起動させています。 かなり複雑になってしまった。。。(;^ω^) Botpress設定 全体フロー図 段々とノードが増えていくにつれ、見にくくなっていくので対象のノードを探すのに困っています。このあたり何んとかならないものかな。。。 システムフロー ユーザ→Bopress→API→コマンド実行 FAQ Emulatorをしばらく置いておくとセッションが切れてしまうので面倒でしたが↓で設定できることが分かりました。 最後に Botpressはチャットボットを自分で一からスクラッチ開発出来るので気に入っています。 今回はチャットボットの制作で力尽き、詳細をお伝えできませんがまたその内、更新したいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

njsでAPIGatewayっぽいものを作ってローカルでLambdaを動かしてみる

そもそもnjsとはなんぞや?という感じですが、簡単に言うとNginxをJavaScriptで制御できるようにするためのモジュールです。 njsだけでなくメジャーなものでLuaというスクリプト言語があり、そちらの方が歴史も古く、nginxに対する制御も色々できるようですが、新しい構文を覚えるのが面倒だったので選択しませんでした。 njs自体の初出がここ最近ということもあり、ほとんどネット上に情報がなかったので筆を取りました。 経緯とか 個人でNext.jsで開発をしていたのですが、ローカルでLambda関数の実行ができてそのコードをそのままAWSに上げて実行することができた方が楽なのでまずバックエンド側の開発環境を作ろうというところが始まりでした。 まぁ既にDockerイメージにそういう感じのがあるだろうと思って探すと、amazon/aws-lambda-ruby:2.7というイメージがありました。 早速使ってみると curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}' といった感じで実行するとのことでした。 おや・・・?これだとパスとか指定できなくない? という感じで少し困りましたが、Lambda関数毎にDockerコンテナ作ってURLとコンテナを紐付けるミドルウェア的なルーター的なコンテナがあればいいんじゃね?という解決策を思いつきました。(後から調べるとAWS SAM Localを使うのが一般的という感じがしたので当時の自分に誰か教えてくれ。) 最初は脳死でRailsとかLaravelでルーティングしようとか思っていたのですが、ルーティングだけ使うのにフレームワークを入れるのは明らかにオーバースペックだったので、じゃあphp-fpmとかRackだけ入れてルーティング用のスクリプトを噛ませようと思いましたが、ブラウザ→Nginx→hoge.rb→Lambdaというリクエストのリレーは効率が悪いのと、結局hoge.rbからHttpClientを実行する必要があるので管理が面倒と感じて、nginxだけでリクエストとレスポンスを整形してプロキシできないか?という感じで調べてnjsに辿り着いたというわけです。 なので最初からnjsを使おうと思って使ったわけではありませんでした。 とりあえず作ってみる えみゅれーたーって言ってみたいのでapi_gateway_emulatorとしています。 あくまで「っぽいもの」なので、自分がローカルで開発するための最低限の部分しか作っていないのでご注意ください。 Dockerfile(api_gateway_emulator) # 1.19なら最初からnjsのモジュールが使える FROM nginx:1.19-alpine RUN apk --update add \ bash \ && rm -rf /var/cache/apk/* WORKDIR /api_gateway_emulator/js # njsのモジュールを読み込むconf COPY ./docker/settings/api_gateway_emulator/nginx.conf /etc/nginx/ # ルーティング等を行うconf COPY ./docker/settings/api_gateway_emulator/default.conf /etc/nginx/conf.d/ COPY ./docker/settings/api_gateway_emulator/js/* /api_gateway_emulator/js/ Dockerfile(Lambda) FROM amazon/aws-lambda-ruby:2.7 # ローカルにfunctionsディレクトリを作り、Lambda用のファイルを入れておく COPY ./functions/* /var/task/ nginx.conf ... # モジュール読み込み load_module modules/ngx_http_js_module.so; load_module modules/ngx_stream_js_module.so; ... http { ... } default.conf # jsファイルをインポート js_import /api_gateway_emulator/js/main.js; # jsの関数をインポートしてconf上で使用できるようにする js_set $createUrl main.createUrl; server { # subrequest(後述)を利用した場合、 # デフォルトのDNSサーバーで名前解決できなくなるので # DockerNetworkで名前解決をする resolver 127.0.0.11 ipv6=off; ... # バッファを設定する # 値は適当ですがファイルアップロードをしたい場合等に調整する必要があります subrequest_output_buffer_size 600k; # Originは開発環境に合わせて変更する add_header Access-Control-Allow-Origin 'http://localhost:22281'; add_header Access-Control-Allow-Methods 'GET,POST,PUT,DELETE,OPTIONS'; add_header Access-Control-Allow-Headers 'Accept,Authorization,Cache-Control,Content-Type,Keep-Alive,Origin,User-Agent,Cookie'; add_header Access-Control-Allow-Credentials true; # preflight対応 if ($request_method = 'OPTIONS') { return 200; } # ここを通してLambdaのコンテナにプロキシする location /container/proxy { proxy_pass $url; } # まずここにマッチする location / { # subrequest後に元のURIが保持されないようなのであらかじめ変数に入れておく # ここでlocalhost:9000/2015-03-31/...からコンテナ名への変換を行う # (http://container_name:9000/2015-03-31/...といった形) set $url $createUrl; # このjs内でLambdaが受け取れる形にRequestの整形をする # その後、/container/proxyへsubrequestを行う js_content main.requestLambda; } ... } default.confは結構ハマりポイントが多かったです。 subrequestはNginxの内部向けのリクエストと解釈していますが解釈として正しいかはわかりません。 /container/proxyはsubrequestを送るパスですが、別に名前はなんでもいいです。 js_setもNode.jsのimportっぽいようなそうでもない感じで、set $url $createUrl;も分かりにくいと思いました。 実際は$urlという変数に$createUrlという変数の中に入った関数(第一引数にリクエスト情報が入ったオブジェクトが暗黙的に入る)の結果をセットするという挙動になります。 続いてnjsの中身ですが、情報がないのでひたすらリファレンスを見るしかないです。 なのでnjsの記事を他の人も書いてくれという気持ちを込めてこの記事を書いています。 Lambda用のマッピングはこちらを参考にしました。 main.js // 必ず引数rをとる // rはリクエストに関する全ての値が入っている function requestLambda(r) { // Lambda用にリクエストを整形 r.subrequest("/container/proxy", { method: r.method, body: JSON.stringify({ "httpMethod": r.method, "headers": getHeaders(r), "body": r.requestBody, "queryStringParameters": r.args }) }) .then((result) => { // レスポンスの整形 var body = JSON.parse(result.responseBody); var responseBody = {}; if ("body" in body) { responseBody = body.body; } // ヘッダを読み取ったり整形したり if ("headers" in body) { ... if ("Location" in body.headers) { // リダイレクトの場合 r.return(301, body.headers["Location"]); return; } } // r.returnでブラウザにレスポンスを返して終了 r.return(body.statusCode, responseBody); }) .catch((result) => { // エラーの場合 // r.errorはコンソールにログ出すのに便利 r.error(result.message); r.return(result.status, result.message); }); } ... // 実際にコンテナ用のアドレスに変換している箇所 function createUrl(r) { var domain = convertSlash(r.uri); return "http:/" + domain + ":9000/2015-03-31/functions/function/invocations"; } // conf上で使う関数をエクスポートする export default { createUrl, requestLambda }; 流れをまとめると、 ブラウザから/hogehogeにリクエスト→location /でキャッチ→njsでリクエスト整形->/container/proxyにsubrequestを送る→Lambdaコンテナへproxyされる→njsでレスポンス整形→ブラウザにレスポンスを返すという感じになります。 実装は以上で、あとはdocker-compose.ymlを見ていきましょう。 docker-compose.yml version: '3' services: api_gateway_emulator: build: context: . dockerfile: ./docker/images/api_gateway_emulator/Dockerfile networks: - api_gateway_emulator ports: - 22280:80 command: bash -c "/usr/sbin/nginx -g 'daemon off;'" base: &lambda container_name: base build: context: . dockerfile: ./docker/images/lambda/Dockerfile volumes: - ./functions:/var/task:cached command: base.handler networks: - api_gateway_emulator tty: true # 関数が増えた場合はbaseを継承して追加していくだけ google_redirect: <<: *lambda container_name: google_redirect command: google_redirect.handler networks: api_gateway_emulator: external: true 関数が増えてもcontainer_nameとcommandを追加していくだけなので簡単です。 この状態でdocker-compose upをすればcurl http://localhost:22280/baseのようにすれば結果が返ってきます。 あとはdocker networkで他のコンテナから繋いだりして開発していくことができます。 解説用にコード改変や省略をしているので、全コードはgitに置いてあります。 誰かの参考になれば幸いです。 あとがき 今回njsでAPI Gatewayっぽいものを作ってみましたが、かなり色々応用が効く技術だと思います。 開発環境で外部APIを利用箇所用のMockサーバーを作ったりできますし、LuaだとできるようですがNginxから直接MySQLを実行できるようになればマイクロサービスであればバックエンドのフレームワークが不要になるかもしれません。 そうなるとnjs部分をTypeScriptで記述したりすることにもなると思います。 Luaすごい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[合格した]AWSクラウドプラクティショナー(PSI)学習[無料で模試受ける方法]書くから受かれ。

この記事読んで得られること 2021年AWSクラウドプラクティショナー(以下「CLF」)合格した人の勉強方法 2,000円ちょい払わずに無料で,(実質)模試受ける方法 公式やで!!※ぼくは払った後に知りました..? CLF学習で何を得たのか、メリットは?(ぼくの感想) さて、まず結果を見せろ Score:788/1000 微妙..。 まぁ、まぁ。落ち着いてください。 勉強法概要 (⭐️は推奨) ※実は書籍使ってないです。 ⓪[前提]ぼくのAWS知識・経験、取得目的 AWS:ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得 これはやってた。 ①Udemyちょっとだけやった(結論:今回は不要) これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(SAA-C02試験対応版) ②⭐️AWS公式e-learning(最高)やろうや AWS Cloud Practitioner Essentials (Japanese) (日本語字幕版) ある程度経験者なら6hとかで終わる AWS初心者なら20hくらいかけてよい。 これの最後に実質模試がある ③模試(有料)受けた 30問なの知らんかった。 本番は65問 (うち5問は採点と無関係) ④⭐️YouTubeで試験問題的なの見てた AWSチャンネル くろかわこうへいさんの試験特化サブチャンネル。 ゆーて30問くらい見ただけ。 は?結局何やればええんや? CLF受かるだけなら⭐️AWS公式e-learningだけで多分いける。 追加でUdemyかYouTubeかでEC2、VPC、サブネット、Route53、IAMくらい手を動かしてみれば十分。 ではまず前提から ⓪[前提]ぼくのAWS知識・経験、取得目的 ▽知識・経験 業務での利用経験なし(使いたい)。 個人学習でちょいやった程度 関連記事 NGINX+WordPress+AWS Aurora Serverless(MySQL5.6)でなんとか立ち上げてみる 基本的なサービスは実際使ったことあるので大体イメージはつく。 UdemyのAWS:ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得 これはやってた。 いろんな教材見たわけじゃないけど最初にやるにはすごくいい教材だと思います 今ならYouTubeにもありそうなのでまぁ手を動かせばなんでもいい気がする ▽CLF取得目的 AWS学習のモチベーションのため! シンプルにAWS面白くて。 本当はSAA(ソリューションアーキテクト)最初にやろうと思ってたけど、まぁCLF受かったら半額で受けられるしええかという気持ちで申し込み。 ①Udemyやった(今回は不要だった) 最初SAAやろうと思って購入したので15%まで進めました(全然進めてない?) これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座 (SAA-C02試験対応版) いや、教材はいいんです。途中で公式e-learningに出会っただけなので。 あと、15%ってまでVPCの話入ってないレベルなので今回のCLF無関係です。 やらなくても多分大丈夫だよということも伝えたい。 ②⭐️AWS公式e-learning(最高)やろうや はい。お待たせしました。 なぜか他の合格体験記に全然登場しないのに最高の教材。 はい。ぼくは100%で1周しかしてませんが、2、3周見てもいいと思います。 AWS Cloud Practitioner Essentials (Japanese) (日本語字幕版) ある程度経験者なら6hとかで終わる AWS初心者なら20hくらいかけてよい。 これの最後に実質模試がある 利用にはAmazonアカウントが必要 普通のショッピングで利用するアカウントでOK これは試験申し込みでも使うし、持ってると思いますが.. ちなみに下記でも辿れますが旧版があるので注意❗️。 AWS 認定 クラウドプラクティショナーの試験の準備というリンクが下の方にあるんですが、クリックすると次の案内に飛びます↓ ほんで、基礎レベルのところを開くと↓ いかにもな「AWS クラウドプラクティショナーの基礎知識|デジタル」をクリック  →デジタルコースを受講を選択 すでに新しいバージョンがリリースされています との表示。 案内通りリンクをクリックすると最新の教材に飛べます。 はい。これです。 AWS公式e-learningが最高な理由3つ 無料で(実質)模試が受けられる 簡潔なモジュールで分けられ、動画のスクリプトが見れるのでさくさく進められる AWSサービスをコーヒーショップに例えていて、ストーリーがあり、グラフィカルな動画のクオリティが半端ない。 無料で(実質)模試が受けられる 先に気になってると思うので書きます。 モジュールの一番下に「小テスト」と題して、実質的な模試があります。 (いや、本物の模試が小テストなんかもしれない) 有料の模試と同じく30問。 有料模試(2,000円)購入した後知ったので、どっちもやりましたが正直クオリティに差はないです。 ちなみに各モジュール内にも小テストがある(最高)が、それと同じというわけではない。 無料模試の特徴 学習したモジュールを復習できるような内容 スコアを表示してくれる 解説も表示 何度も使える(ただし内容は同じ) →いや有料模試よりええやんけ!!!!!!! 有料模試(2,000円ちょい)の特徴 試験は1回きり(だと思う) 何回も受けれる方法あったら教えて... 解説なし メールで合計・各分野のスコア(割合)教えてくれる サクサク進むし、サービスの例えが超一流でわかりやすい。そしてグラフィカルでクオリティが頂点 小見出しに詰め込んでしまいました。 これは、ストレージのモジュールの一コマです。 サイドバーでモジュールを開くとレッスンが並ぶ。 基本はコーヒーショップを基にし、AWSサービスを例えてくれるストーリーで教えてくれます コーヒーショップでAWSを使うんではなく、AWSをコーヒーショップで例えてくれる。まじでわかりやすかった。 ただし、ITガチ初心者でファイアウォール、SQLって何みたいな人はちょっと時間かかるかも それでもおすすめです。OSI参照モデルとか扱いません。かなり別の単元「クラウド」としてAWSを学べます。 「動画のトランスクリプト」を開くと、動画を見なくても全文表示してくれる。 動画は0.5~2.0まで倍速可能 画像の動画はコーヒーショップとは若干テイスト違いますが、何が伝えたいかと言うと"面白いんです"。 ③模試(有料)受けた はい。有料模試の特徴で上述した通り、個人的には別にやらなくていいと思ってます。 ④⭐️YouTubeで試験問題的なの見てた AWSチャンネル くろかわこうへいさんの試験特化サブチャンネル。 ゆーてご飯食べたりしながら30問くらい見ただけ。 解説もあるのでよいかんじです。 公式e-learning、模試の補足的な役割。 結局どんくらい時間、費用かかるんです?? ちょっと分けて書きます。 時間 CLF試験準備として実際にかかった時間:14h それが試験に必要だった時間:6h ほぼ公式e-learning。 AWS初心者(アカウントなし)が始めるならかかるだろう目安時間:40h ぼくの個人的な感覚です。もちろん実践あり。 費用 実際にかけた費用:約5,000円 受験費用除く Udemyと模試 必要な学習費用:0円 多分いらんす。あえてかくなら0円でもいける。 PSIでオンライン受験ってどんな感じ? 感想としては「なるほ、こんなもんね、へ〜」とオンライン試験運営の勉強になってしまいました。 流れ AWS training and certificationへ行く Trainingページ(e-learning)の「認定」メニューからも飛べます Amazonアカウントでログイン必要 PSI試験の管理をクリック Ready for Scheduleから試験を選択し、受験日程を選択 クレジットカード等で精算 メールが届く。 正直後の流れ全部書いてあるのでみてください笑? PSI試験の管理ページでDetailからも確認できます。 PSI Secure Browser Installして動作確認 カメラ使えるか、マイク使えるか 試験当日は他アプリ立ち上がっている場合切るよう表示あるけど、動作確認段階だと出てこなかったと思う 事前準備(全部PSIのDetailに書いてあるので要点だけ) 上記の追加 パスポートや運転免許証、マイナンバーカードなどID証明できるもの 上下左右にカンニングが疑われるようなものがない状態の部屋 周りに手を伸ばしても何も届かないような試験環境の整備 当日飲食禁止なのでトイレ行っといたらいいんじゃないか(知らん) PSI試験当日 ぼくはベッドの上に棚置いてPC置いて受験しました? デスクの横に本棚があってどかすの面倒だった。 一人暮らしの小さい部屋なので物とかはシーツとか毛布とかで無理やり8割隠した Amazonの試験管理ページの予約した試験から、LaunchすればOK これわからずに、Secure Browser立ち上げてたら、「始められません、問い合わせてください」みたいなのが出てマジで焦った。 ブラウザ立ち上げて受験番号入力じゃないのかも まずは、ID証明確認 パスポートを枠に収めて写真撮影した スマホとかで撮って送るのかと思ったら、Secure Browserに撮影機能があったのでMacのインカメラに向けて、ボタン押して撮影。 次に顔を枠に収めて撮影した ここから10~15分くらい照合で待機。 待機するよう表示される。 この時間何していいかわからんかった...怖かったので特に何もせず待ってました。 照合が終わると、チャットがくる(試験監督みたいな役割の人をプロクターというらしい) IDを持ってカメラに見せて欲しいと。 見せた。ほんで遠くに置いた 今の場所から部屋全体を見せて欲しいと。 とりあえずMacをカメラ角度変えながら3回転くらいしたらOKだった PC置いてるデスクの上、下見せて 見せた。 スマホどこにあるか聞かれた 見せた。そして投げた(遠くに置いた) 手首と耳を見せた。 確かこんくらいで始めることができた。 試験中・試験後 試験中もカメラは起動したまま、枠が表示されて、顔をトラッキングし続ける うーん、と考えるような格好で口の前に手を置いていたら「試験中すみません、口の前に手を置くのは控えてもらえますか」とチャットあり。 その後大人しく受けてたら何もなかった。 試験終わったらボタン教して終了なんだが、一応一回チャットで「終わってもいいですか?」と聞いた。 「ちょっとまって」と言われた1秒後に「OKやで」と言われたので終わった。 ちなみに回答時のUIは、 選択肢選んで次へを押したり 設問番号押して戻ることができたり 設問ごとにコメント残せたり 設問ごとにフラグをつけられたり 日本語(選択言語?)と英語切り替えられたり する。普通でいい感じ。 ピアソンとの違いは? 試験実施提携会社が違うってだけだと思う。 いや調べた上でPSI選んだけど。公式にも載ってるので見てみてください。 ピアソンは日本語対応可能 PSIに比べて選べる日時が少ないらしい 試験中別のアプリが立ち上がると試験中止になるらしい クラウドプラクティショナー合格したメリットは? 学習の過程でのメリット AWSの基本サービス同士の違いをより理解できた 基本サービスだけど知らなかった使い方も理解できた AWSで個人だと使う機会がないようなサービスも知ることができた CLF合格したメリット モチベーションup!達成感を感じた?素直に嬉しい。 これだけ。 いや、他にも資格としてかける・話が広がるとかあるけど、正直うすいかな? CLF学習して何を得たの?実際意味あんの? 得たのは上記メリット。 これは資格全般に言えるけど、CLF合格したからAWS使えるとか全然別の話です。 求人とかでAWS資格歓迎(CLFは除く)みたいなのたまにみますが、受かってみて、そうだと思います笑 そもそも資格と業務できるかは相関なだけで、勝手に期待して勝手に失望してるんですよね(知らんけど) 仕事できるかはAWSの知識とは全く別にある(と思う) これも資格全般に言えるけど、CLFをマイルストーンとしてモチベーション維持しながら学習するという意味では良いと思います。楽しいです。 あえて一般論的なメリットを書くなら CLF試験合格しました!記事をかける 個人でも企業にも使える AWSの試験を受けるほど自己学習意欲があると見せられる AWSの基本サービスを抑えることでAzureでも理解の応用がきく AWSサービス使っているベンダー,クライアントと話が(少し)できる 履歴書等資格に書けるので、口頭アピールまで辿り着かなくても認識してくれる もちろん、職務経歴書に書けるならその方がい 最後に。 ここまで読んでいただいてありがとうございます。 試験概要色々調べましたが、AWSのe-learningの魅力を伝えた記事があまりなかったので伝わると嬉しいです。 そして、クラウドプラクティショナーバッジゲットして自分がレベルアップしている感覚楽しんでください! 偉そうに書きましたががんばっていきます。 ほんで、受かれ?。 ※リスペクト込みのタメ口 関連/参考 NGINX+WordPress+AWS Aurora Serverless(MySQL5.6)でなんとか立ち上げてみる(これは自分の記事) AWS認定試験 PSIでのオンライン試験を受けてみました Serverworks:AWS認定試験をオンラインで受けてみた Serverworks:AWSの認定試験に合格すると貰える特典を有効活用しよう AWSソリューションアーキテクトアソシエイト(SAA-C02)合格体験記【オマケ:半額で受験する方法】 AWS Cloud Practitioner Essentials (Japanese) (日本語字幕版)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudWatchEvents+lambda+boto3でサーバー代を節約する

目的→サーバー代の節約 http://myhero2.s3-website-us-west-2.amazonaws.com Angularのチュートリアルを参考に作成したポートフォリオです。 バックエンドでSpringBoot(EC2)とKeyCloak(FARGATE)とMySQLが動いています。 特にFARGATEは個人で運用する分にはサーバ代が高い為、 CloudWatchEvents+lambdaで決まった時間にタスクをストップさせる構成を実装します。 lambdaの作成と設定 AWS Lambdaのコンソール画面より関数の作成をクリックします。 1.lambda関数名を設定します。 2.今回はpythonのAWSSDK(boto3)を使用する為、「Python 3.8」を選択します。 3.関数の作成をクリックします。 これで関数は作成できましたが、デフォルトの実行ロールではECSのサービスの設定をアップデートさせることができません。以下の手順を参考にデフォルトのロールに権限を付与します。 FullAccessのポリシーをアタッチしてしまうのはセキリティ上、ベストプラクティスではない場合がありますが、今回は個人のアカウントなのでFullAccessのポリシーをアタッチします。 lambdaのソースコード example.py def lambda_handler(event, context): #desiredcountを0にする client = boto3.client('ecs') response = client.update_service( cluster='myk', service='ecs-kck-myk', desiredCount=0, ) #停止するために必要なtaskArnを取得 response = client.list_tasks( cluster='myk', launchType='FARGATE' ) taskArns=response["taskArns"] #タスクを停止 for task in taskArns: response = client.stop_task( cluster='myk', task=task, ) desiredCountを0にすることでECSのサービス内のタスクをストップさせた時、自動でタスクが開始されるのを防ぎます。今回は特にサービスなどを指定せずにクラスター内のtaskArnを全て取得して、クラスター内の全てのタスクを停止させています。 CloudWatchEventsでルールを作成する AWSコンソールよりCloudWatchEventsの画面を開き、ルールの作成をクリックします。 CloudWatchEventsの設定 1.スケジュールをクリック 2.Cron式をクリックしてlambdaを実行したい時間を入力 今回は平日の18:00にlambdaを実行させたい為、 0 3 ? * TUE-SAT * と入力します。GMTとJSTの9時間の時差を考慮することに注意します。 Cron式についてはこちらに詳しく書いてあります。 https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html 3.ターゲットの選択より実行したいlambda関数を選択します。 4.設定の詳細をクリックします。後はルールの名前を決めてルールを作成します。 CloudWatchEvents側での設定は以上です。 これで、指定された時間にlambda関数が実行されます。 今回は決まった時間にタスクを停止させる構成を実装をしましたが、同様にしてタスクを開始させる構成を実装することで、決まった時間のみにポートフォリオを公開することができ、サーバー代を節約できます!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

さくらインターネットのサーバーでAWSのSESの設定方法

本文について 自分でやっているサイトにSESを導入して新規登録ユーザーにメールが届くシステムの導入をするため、やったAWSのSESの設定方法を記載しておきます。(備忘録程度に) 難しくはないので、未経験でポートフォリオを作成している方にも導入をおすすめします。 AWSの設定 まずは、AWSのサービス一覧から「Amazon Simple Email Service(以下、SES)」を選択し、SESのホームへ そして、サイドメニューから「Domains」をクリック Domainsの画面から「Verify a New Domain」を選択 ドメインの登録をするため、表示されるモーダルの「Domain」に使用するドメインの入力と、「Generate KDIM Settings」にチェックをして「Verify This Domain」」をクリック そしたら、ドメインのゾーン設定に必要な内容が表示される さくらインターネットの設定 ゾーンの設定をするため、会員メニューのドメインから「管理ドメインとネームサーバの一覧」を選択し、登録したドメインの「ゾーン編集」のボタンをクリック 黒色のところが登録された内容 先ほど表示された内容を全て登録を行う AWSでの確認 設定が完了してから数時間は下記のような状態です。 数時間後には、ドメインの検証が完了して下記のようになっていれば設定の完了になります。 次回は、メールアドレスの設定とCakephp4でメール送信までの方法を投稿しようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CloudFormationでカスタムドメインを使用したAPI Gatewayを構築しよう

はじめに AWS CloudFormationを利用してカスタムドメインを使用したAPI Gateway構築のテンプレートのサンプルです。 API GatewayはLambdaを使用する。また、Lambdaは、S3アーティファクトを使用します。 テンプレートの概要が分からない場合は、はじめてのAWS CloudFormationテンプレートを理解するを参考にしてください。 コードはGitHubにもあります。 今回は、akane というシステムの dev 環境を想定しています。 同じ構成で違う環境を作成する場合は、{環境名}-parameters.jsonを別途作成します。 ディレクトリ構成 akane (システム) ├── acm (スタック) │ ├── acm.yml (CFnテンプレート) │ └── dev-parameters.json (dev 環境のパラメータ) ├── apigw (スタック) │ ├── apigw.yml (CFnテンプレート) │ └── dev-parameters.json (dev 環境のパラメータ) ├── lambda (スタック) │ ├── code │ │ └── getTiAmo.py (S3アーティファクトソース) │ ├── code-lambda-getTiAmo.zip (S3アーティファクト) │ ├── delete_artifact.dev.sh (S3アーティファクト削除シェル) │ ├── dev-parameters.json (dev 環境のパラメータ) │ ├── lambda.yml (CFnテンプレート) │ ├── mkzip.sh (S3アーティファクト作成シェル) │ └── upload_artifact.dev.sh (S3アーティファクト削除シェル) └─ s3 (スタック) ├─ s3.yml (CFnテンプレート) └─ all-parameters.json (all 環境のパラメータ) AWS リソース構築内容 acmスタック 証明書 apigwスタック CloudWatch ログのロール API Gateway 使用量プラン API キー lambdaスタック Lambdaロール Lambda s3スタック s3バケット (akane-all-s3-artifacts) バケットポリシー (s3:GetObject) 実行環境の準備 AWS CloudFormationを動かすためのAWS CLIの設定を参考にしてください。 AWS リソース構築準備 Route 53にてドメインを作成する。 miyabiz.com akane/acm/parameters.json の DomainNameにドメインを記述する。 api.dev.miyabiz.com AWS リソース構築手順 下記を実行してスタックを作成 ./create_stacks.sh ※ 実行後、AWS Certificate Manager にて、対象ドメインを選択し、Route 53 でのレコード作成を押下する。 カスタムドメインをRoute 53 の ホストゾーン の レコード に登録 ※ Route 53 の ホストゾーン の レコードを作成 を押下する。 レコード名に api.dev.miyabiz.com を入力 トラフィックのルーティング先のエイリアスを選択 API Gateway API へのエイリアス を選択 リージョンとして、アジアパシフィック (東京) [ap-northeast-1] を選択 エンドポイントを選択 下記を実行してLambdaの動作を確認 ./test_lambda.sh 下記を実行してAPI Gatewayの動作を確認 ./test_apigw.sh <URL> <API_KEY> 下記を実行してスタックを削除 ./delete_stacks.sh 構築テンプレート 1. s3スタック s3.yml AWSTemplateFormatVersion: 2010-09-09 Description: S3 For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. # Mappings # Conditions # Transform Resources: # S3 Bucket作成 akaneS3Bucket: Type: AWS::S3::Bucket Properties: AccessControl: Private BucketName: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType # S3 BucketPolicy作成 akaneS3BucketPolicy: Type: AWS::S3::BucketPolicy DependsOn: akaneS3Bucket Properties: Bucket: !Ref akaneS3Bucket PolicyDocument: Statement: - Action: - s3:GetObject Effect: Allow Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref akaneS3Bucket - /* Principal: AWS: '*' Outputs: akaneS3Bucket: Value: !Ref akaneS3Bucket Export: Name: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} all-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "all" } ] } 2. acmスタック acm.yml AWSTemplateFormatVersion: 2010-09-09 Description: S3 For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. DomainName: Type: String MinLength: 1 MaxLength: 253 AllowedPattern: '^(\*\.)?(((?!-)[A-Za-z0-9-]{0,62}[A-Za-z0-9])\.)+((?!-)[A-Za-z0-9-]{1,62}[A-Za-z0-9])$' # Mappings # Conditions # Transform Resources: # 証明書 作成 akaneCertificate: Type: AWS::CertificateManager::Certificate Properties: # CertificateAuthorityArn: String # CertificateTransparencyLoggingPreference: String DomainName: !Ref DomainName # DomainValidationOptions: # - DomainValidationOption # SubjectAlternativeNames: # - String Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-acm - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType ValidationMethod: DNS Outputs: akaneCertificate: Value: !Ref akaneCertificate Export: Name: !Sub - ${SystemName}-${EnvType}-acm - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} akaneDomainName: Value: !Ref DomainName Export: Name: !Sub - ${SystemName}-${EnvType}-acm-domain - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} dev-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "dev" }, { "ParameterKey": "DomainName", "ParameterValue": "api.dev.miyabiz.com" } ] } 3. lambdaスタック lambda.yml AWSTemplateFormatVersion: 2010-09-09 Description: Lambda For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. ArtifactS3Bucket: Type: String LambdaName: Type: String LambdaMemorySize: Type: Number LambdaRuntime: Type: String GirlName: Type: String # Mappings # Conditions # Transform Resources: # ロール作成 akaneRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Description: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Path: / RoleName: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType # Lambda作成 akaneLambdaGetTiAmo: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Ref ArtifactS3Bucket S3Key: !Sub - code-lambda-${LambdaName}.zip - {LambdaName: !Ref LambdaName} Description: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Environment: Variables: GIRL_NAME: !Ref GirlName FunctionName: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Handler: !Sub - ${LambdaName}.handler - {LambdaName: !Ref LambdaName} MemorySize: !Ref LambdaMemorySize Role: !GetAtt akaneRole.Arn Runtime: !Ref LambdaRuntime Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType Timeout: 900 TracingConfig: Mode: PassThrough Outputs: akaneLambdaGetTiAmoArn: Value: !GetAtt akaneLambdaGetTiAmo.Arn Export: Name: !Sub - ${SystemName}-${EnvType}-lambda-arn - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} dev-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "dev" }, { "ParameterKey": "ArtifactS3Bucket", "ParameterValue": "akane-all-s3-artifacts" }, { "ParameterKey": "LambdaName", "ParameterValue": "getTiAmo" }, { "ParameterKey": "LambdaMemorySize", "ParameterValue": "128" }, { "ParameterKey": "LambdaRuntime", "ParameterValue": "python3.8" }, { "ParameterKey": "GirlName", "ParameterValue": "akane" } ], "Capabilities": [ "CAPABILITY_NAMED_IAM" ] } 3. apigwスタック apigw.yml AWSTemplateFormatVersion: 2010-09-09 Description: API Gateway For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. EnvTypeCommon: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. APIPathPart: Type: String APIGatewayStage: Type: String # Mappings # Conditions # Transform Resources: # ApiGateway CloudWatchRole 作成 akaneCloudWatchRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - apigateway.amazonaws.com Action: sts:AssumeRole Description: !Sub - ${SystemName}-${EnvTypeCommon}-role-apigw-cloudwatch-${AWS::Region} - {SystemName: !Ref SystemName, EnvTypeCommon: !Ref EnvTypeCommon} ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs Path: / RoleName: !Sub - ${SystemName}-${EnvTypeCommon}-role-apigw-cloudwatch-${AWS::Region} - {SystemName: !Ref SystemName, EnvTypeCommon: !Ref EnvTypeCommon} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvTypeCommon}-role-apigw-cloudwatch-${AWS::Region} - {SystemName: !Ref SystemName, EnvTypeCommon: !Ref EnvTypeCommon} - Key: SystemName Value: !Ref SystemName - Key: EnvTypeCommon Value: !Ref EnvTypeCommon akaneApiGatewayAccount: Type: AWS::ApiGateway::Account Properties: CloudWatchRoleArn: !GetAtt akaneCloudWatchRole.Arn # ApiGateway 作成 akaneApiGateway: Type: AWS::ApiGateway::RestApi DependsOn: akaneApiGatewayAccount Properties: Name: !Sub - ${SystemName}-${EnvType}-apigw - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Description: !Sub - ${SystemName}-${EnvType}-apigw - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} EndpointConfiguration: Types: - REGIONAL Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-apigw - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType akaneApiGatewayResource: Type: AWS::ApiGateway::Resource Properties: RestApiId: !Ref akaneApiGateway ParentId: !GetAtt akaneApiGateway.RootResourceId PathPart: !Ref APIPathPart akaneApiGatewayLambdaPermission: Type: AWS::Lambda::Permission Properties: FunctionName: Fn::ImportValue: !Sub - ${SystemName}-${EnvType}-lambda - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Action: lambda:InvokeFunction Principal: apigateway.amazonaws.com akaneApiGatewayResourceMethod: Type: AWS::ApiGateway::Method DependsOn: akaneApiGatewayLambdaPermission Properties: RestApiId: !Ref akaneApiGateway ResourceId: !Ref akaneApiGatewayResource ApiKeyRequired: true AuthorizationType: NONE HttpMethod: GET Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Join - '' - - 'arn:aws:apigateway:' - !Ref AWS::Region - ':lambda:path/2015-03-31/functions/' - Fn::ImportValue: !Sub - ${SystemName}-${EnvType}-lambda-arn - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - '/invocations' akaneApiGatewayDeployment: Type: AWS::ApiGateway::Deployment DependsOn: akaneApiGatewayResourceMethod Properties: Description: !Sub - ${SystemName}-${EnvType}-apigw-deployment - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} RestApiId: !Ref akaneApiGateway akaneApiGatewayStage: Type: AWS::ApiGateway::Stage DependsOn: akaneApiGatewayDeployment Properties: DeploymentId: !Ref akaneApiGatewayDeployment Description: !Sub - ${SystemName}-${EnvType}-apigw-stage - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} MethodSettings: - CacheDataEncrypted: false CachingEnabled: false DataTraceEnabled: true # CloudWatch ログを有効化 HttpMethod: '*' LoggingLevel: ERROR MetricsEnabled: false # 詳細 CloudWatch メトリクスを有効化 ResourcePath: '/*' RestApiId: !Ref akaneApiGateway StageName: !Ref APIGatewayStage Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-apigw-stage - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType TracingEnabled: false # X-Ray トレースの有効化 # ApiGateway APIキー 作成 akaneApiGatewayKey: Type: AWS::ApiGateway::ApiKey Properties: Description: !Sub - ${SystemName}-${EnvType}-apigw-key - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Enabled: true akaneApiGatewayUsagePlan: Type: AWS::ApiGateway::UsagePlan DependsOn: akaneApiGatewayStage Properties: ApiStages: - ApiId: !Ref akaneApiGateway Stage: !Ref APIGatewayStage Description: !Sub - ${SystemName}-${EnvType}-apigw-usage-plan - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} UsagePlanName: !Sub - ${SystemName}-${EnvType}-apigw-usage-plan - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-apigw-usage-plan - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType akaneApiGatewayUsagePlanKey: Type: AWS::ApiGateway::UsagePlanKey Properties: KeyId: !Ref akaneApiGatewayKey KeyType: API_KEY UsagePlanId: !Ref akaneApiGatewayUsagePlan # ApiGateway カスタムドメイン 作成 akaneApiGatewayDomainName: Type: AWS::ApiGateway::DomainName DependsOn: akaneApiGatewayUsagePlan Properties: DomainName: Fn::ImportValue: !Sub - ${SystemName}-${EnvType}-acm-domain - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} EndpointConfiguration: Types: - REGIONAL RegionalCertificateArn: Fn::ImportValue: !Sub - ${SystemName}-${EnvType}-acm - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} SecurityPolicy: TLS_1_2 Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-apigw-domain - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType akaneApiGatewayApiMapping: Type: AWS::ApiGatewayV2::ApiMapping DependsOn: akaneApiGatewayDomainName Properties: ApiId: !Ref akaneApiGateway ApiMappingKey: !Ref APIGatewayStage DomainName: !Ref akaneApiGatewayDomainName Stage: !Ref APIGatewayStage Outputs: akaneApiGatewayEndpoint: Value: !Join - '' - - 'https://' - !Ref akaneApiGatewayDomainName - '/v1/whisper' Export: Name: !Sub - ${SystemName}-${EnvType}-apigw-endpoint - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} dev-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "dev" }, { "ParameterKey": "EnvTypeCommon", "ParameterValue": "all" }, { "ParameterKey": "APIPathPart", "ParameterValue": "whisper" }, { "ParameterKey": "APIGatewayStage", "ParameterValue": "v1" } ], "Capabilities": [ "CAPABILITY_NAMED_IAM" ] } 4. 実行ファイル create_stacks.sh #!/bin/sh cd `dirname $0` SYSTEM_NAME=akane create_stack () { ENV_TYPE=$1 STACK_NAME=$2 aws cloudformation create-stack \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} \ --template-body file://./${SYSTEM_NAME}/${STACK_NAME}/${STACK_NAME}.yml \ --cli-input-json file://./${SYSTEM_NAME}/${STACK_NAME}/${ENV_TYPE}-parameters.json aws cloudformation wait stack-create-complete \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} } create_stack all s3 create_stack dev acm ./akane/lambda/mkzip.sh ./akane/lambda/upload_artifact.dev.sh create_stack dev lambda create_stack dev apigw exit 0 test_lambda.sh #!/bin/sh cd `dirname $0` echo " --- \033[0;33m TEST LAMBDA \033[0;39m --- " LAMBDA_NAME=akane-dev-lambda-getTiAmo OUTPUT_FILE=response.json aws lambda invoke --function-name ${LAMBDA_NAME} --log-type Tail ${OUTPUT_FILE} --query 'LogResult' --output text | base64 -D cat ${OUTPUT_FILE} exit 0 test_apigw.sh #!/bin/sh set -e if [ $# -ne 2 ]; then echo " --- \033[0;31m [ERROR]: The following arguments are required \033[0;39m --- " echo " \033[0;33m$0 <URL> <API_KEY>\033[0;39m" echo " \033[0;33m<URL> Example: https://{custom_daomin}/v1/whisper\033[0;39m" exit 1 fi cd `dirname $0` echo " --- \033[0;33m TEST APIGW \033[0;39m --- " URL=$1 API_KEY=$2 curl -X GET -H 'Content-Type: application/json' \ -H "x-api-key: ${API_KEY}" \ "${URL}" exit 0 delete_stacks.sh #!/bin/sh cd `dirname $0` SYSTEM_NAME=akane delete_stack () { ENV_TYPE=$1 STACK_NAME=$2 aws cloudformation delete-stack \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} aws cloudformation wait stack-delete-complete \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} } delete_stack dev apigw delete_stack dev lambda ./akane/lambda/delete_artifact.dev.sh delete_stack dev acm delete_stack all s3 exit 0 4. アーティファクト関連ファイル mkzip.sh #!/bin/sh cd `dirname $0` ENV_TYPE=dev LAMBDA_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') FILE=../code-lambda-${LAMBDA_NAME}.zip cd ./code ls . | grep -v -E ".gitignore|${LAMBDA_NAME}.py" | xargs rm -rf rm -f ${FILE} zip -r ${FILE} ./* exit 0 upload_artifact.dev.sh #!/bin/sh cd `dirname $0` BASENAME=$(basename $0) FILENAME=${BASENAME%.*} ENV_TYPE=${FILENAME##*.} BUCKET_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "ArtifactS3Bucket").ParameterValue') ARTIFACT_NAME=code-lambda-$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') aws s3 cp ${ARTIFACT_NAME}.zip s3://${BUCKET_NAME}/${ARTIFACT_NAME}.zip exit 0 delete_artifact.dev.sh #!/bin/sh cd `dirname $0` BASENAME=$(basename $0) FILENAME=${BASENAME%.*} ENV_TYPE=${FILENAME##*.} BUCKET_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "ArtifactS3Bucket").ParameterValue') ARTIFACT_NAME=code-lambda-$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') aws s3 rm s3://${BUCKET_NAME}/${ARTIFACT_NAME}.zip exit 0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む