20210728のAWSに関する記事は23件です。

【AWS】EC2を起動&停止&性能変更するdiscord bot

はじめに EC2は起動している時間単位で課金されるため、使う・使わないに応じてコマメに起動・停止するのが理想。 AWSコンソールで操作するのは手軽さに欠けるため、誰でも自由に操作できる環境を整備したい。 本ページではdiscordのメンバーが自由にEC2を起動・停止できるようにする他、 インスタンスタイプ(サーバー性能)を変更できるようにするbotを設定する。 サンプルコード↓ 構成図 Herokuで動いているdiscord botから、APIGWを介してLambdaをキックして、EC2を起動・停止する。 やること EC2を起動・停止するLambdaを設置 EC2起動時に、インスタンスタイプを変更する処理を追加 discordのメンバーが送信した特定のemojiを検知してLambdaを起動するbotを設置 前提 初期設定済のEC2 discord botを実行する環境(本ページではHeroku) もくじ Lambdaを設定する discord botを設定する 動作を確認する 1. Lambdaを設定する 1-1. APIGWとLambdaの設定方法 下記ページを参照。 1-2. Lambdaの中身(ec2_up) EC2のインスタンスタイプを上書きした後、起動する。 INSTANCE_IDとALLOWED_INSTANCE_TYPESは各自の環境に合わせて書き換える必要がある。 index.py import boto3 # YOUR OWN INSTANCE ID INSTANCE_ID = 'i-00000000000000000' ALLOWED_INSTANCE_TYPES = ['t3a.large', 'm5n.large'] def lambda_handler(event, context): new_instance_type = event['instance_type'] if not new_instance_type in ALLOWED_INSTANCE_TYPES: return response_maker(400, "[ERROR!] invalid instance_type") ec2 = boto3.client("ec2") # only running instance will return description = ec2.describe_instance_status( InstanceIds=[INSTANCE_ID], IncludeAllInstances=True ) instance_state = description['InstanceStatuses'][0]['InstanceState']['Name'] if instance_state != 'stopped': return response_maker(400, "[ERROR!] ec2 instance is not in 'stopped' state") ec2.modify_instance_attribute( InstanceId=INSTANCE_ID, Attribute='instanceType', Value=new_instance_type ) ec2.start_instances(InstanceIds=[INSTANCE_ID]) return response_maker(200, "minecraft up up up ...") def response_maker(status, message): return { "isBase64Encoded": True, "statusCode": status, "headers": { "Content-Type": "application/json", }, "body": { "message": message } } 1-3. Lambdaの中身(ec2_down) EC2を停止する。 instancesは各自の環境に合わせて書き換える必要がある。 index.py import boto3 # YOUR OWN INSTANCE ID instances = ['i-00000000000000000'] def lambda_handler(event, context): ec2 = boto3.client("ec2") ec2.stop_instances(InstanceIds=instances) return { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": { "message": "minecraft down down down ..." } } 1-4. APIGWの設定 /upと/downで異なるLambdaをinvokeするように紐付けておく。 2. discord botを設定する 2-1. discord botの運用環境 GCPでは最小インスタンスを1つまで無料で運用できる。 また、1ヶ月あたりの起動時間に制限こそあるが、用途によってはHerokuでも十分に無料運用できる。 Herokuにdiscord botをディプロイする方法は既にすばらしい記事が存在するため、深堀りしない↓ 2-2. botの中身 discordサーバーの特定チャンネル内で、特定のemoji:ec2_down:, :ec2_up_common:, :ec2_up_boost:が送信されたとき、Lambdaをキックする。 emojiはメッセージ本文に含んだとき、リアクションとして押したとき、両方とも反応する。 押すスタンプの種類によって、インスタンスタイプの種類をt3a.largeとm5n.largeで切り替えている。 (高負荷の休日と、低負荷の平日でサーバー性能を使い分けるような想定。) TOKEN, ID_CHANNEL_BOT, LAMBDA_INVOKE_PATHは各自の環境に合わせて書き換える必要がある。 EC2ManagerBot.py import discord import requests # YOUR OWN DISCORD BOT TOKEN TOKEN = 'AAAAAAAAAAAAAAAAAAAAAAAA.AAAAAA.AAAA_AAAAAAAAAAAAAAAAAAAAA' # YOUR OWN DISCORD CHANNEL ID ID_CHANNEL_BOT = 000000000000000000 EMOJI_EC2_DOWN = 'ec2_down' EMOJI_EC2_UP_COMMON = 'ec2_up_common' EMOJI_EC2_UP_BOOST = 'ec2_up_boost' EC2_INSTANCE_TYPE_POOR = 't3a.large' EC2_INSTANCE_TYPE_GOOD = 'm5n.large' LAMBDA_INVOKE_PATH = 'https://${YOUR_OWN_APIGW_PATH}/dev/ec2' STATUS_OK = 200 client = discord.Client() async def down_ec2(user_name): channel = client.get_channel(ID_CHANNEL_BOT) r = requests.get(f'{LAMBDA_INVOKE_PATH}/down').json() status = r["statusCode"] if status == STATUS_OK: await channel.send(f'ec2 down down down ... by `{user_name}`') else: await channel.send(f'[ERROR!] lambda invocation error --> `{r["body"]}`') async def up_ec2(user_name, ec2_instance_type): channel = client.get_channel(ID_CHANNEL_BOT) r = requests.get( f'{LAMBDA_INVOKE_PATH}/up?instance_type={ec2_instance_type}' ).json() status = r["statusCode"] if status == STATUS_OK: await channel.send(f'ec2 up up up ... by `{user_name}`\ninstance type is `{ec2_instance_type}`') else: await channel.send(f'[ERROR!] lambda invocation error --> `{r["body"]}`') async def validate_message(message): if message.author.bot: return channel_id = message.channel.id if channel_id != ID_CHANNEL_BOT: return content = message.content author = message.author.name if EMOJI_EC2_DOWN in content: await down_ec2(author) return if EMOJI_EC2_UP_COMMON in content: await up_ec2(author, EC2_INSTANCE_TYPE_POOR) return if EMOJI_EC2_UP_BOOST in content: await up_ec2(author, EC2_INSTANCE_TYPE_GOOD) return async def validate_reaction(payload): channel_id = payload.channel_id if channel_id != ID_CHANNEL_BOT: return emoji = payload.emoji.name author = payload.member if emoji == EMOJI_EC2_DOWN: await down_ec2(author) return if emoji == EMOJI_EC2_UP_COMMON: await up_ec2(author, EC2_INSTANCE_TYPE_POOR) return if emoji == EMOJI_EC2_UP_BOOST: await up_ec2(author, EC2_INSTANCE_TYPE_GOOD) return @client.event async def on_ready(): channel = client.get_channel(ID_CHANNEL_BOT) await channel.send('hello!') @client.event async def on_message(message): await validate_message(message) @client.event async def on_raw_reaction_add(payload): await validate_reaction(payload) client.run(TOKEN) 2-3. discordサーバーにemojiを追加 わかりやすい画像を用意して、よしなに追加する。 3. 動作を確認する 使うemojiによってインスタンスの性能を変更しつつ、EC2を起動・停止できた。 discordに参加しているメンバーなら、ワンボタンでEC2を操作できるようになった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Pricing Calculator とは

勉強前イメージ そのまま訳したら価格の計算?見積もりツール? こちら の計算ツールと何が違うんだろう 調査 AWS Pricing Calculator とは AWSのサービスについての費用見積もりツールになります。 簡単に直感的な見積もりが可能になります。 SIMPLE MONTHLY CALCULATOR は? SIMPLE MONTHLY CALCULATORは従来の見積もりツールで、 そろそろ廃止になるようです。 見積もりをしてみる こちらのURL からアクセスしてみてください β版ではEC2のみでしたが、現在は100サービス以上あります。 今回は、EC2を見積もりしてみます。 説明と、EC2を見積もりするリージョンを変更します。 EC2の数量やインスタンスタイプなど設定します。 価格はオンデマンドインスタンスにしてみます。 EBSのストレージを設定してみます。 設定を記載したら見積もりを追加。 出力された見積もりが以下になります。 見積もりを共有することもできます。 勉強後イメージ SIMPLE MONTHLY CALCULATORで見積もり出してたこともあるけど、 AWS Pricing Calculatorのがわかりやすいかも? ファイルに出力できるのも残せるので良いなぁと思います。 参考 AWS Simple Monthly Calculator がついに勇退するようです! AWS Pricing Calculator に新しいサービスが追加されています!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS SAA試験前まとめ

はじめに 模擬試験を繰り返してきてまとめておいたほうがいいかなというところをBlack Beltを見たりしてまとめたものです。 AWSの基本的なアーキテクチャを作成するためのサービス EC2 VPC S3 Route53 AutoScaling ELB CloudWatch CloudFront(コンテンツ配信を行うようなサービスの場合) 特にサーバレスなアプリケーションを構成する場合のサービス Lambda SQS SNS APIGateway ElastiCache DynamoDB(非ステートレスであれば) Step function (分散アーキテクチャの疎結合を助ける、特にオンプレミスのワークロードとの連携もできる) データ分析ワークロード Lambda SQS S3 Redshift Athena Glue EMR Kinesis LakeFormation アプリケーションやワークロードの自動化、テンプレート OpsWorks Cloud Formation Step function(分散アーキテクチャやマイクロサービスでの疎結合化を図るが、本質はワークロードの設定や管理の自動化。タスクで構成されるワークフローを簡単に作成できる) SWF(Step FunctionのEC2インスタンスを使う版。) コンテナサービスによるマイクロアーキテクチャ Elastic Beanstalk(ECS、EKS、ECRと連携して自動化) ECS EKS リポジトリ管理からデプロイまでのワークロード CodeCommit(リポジトリの管理、つまりソースコード管理) CodeBuild(コードのビルド及びテスト担当) CodeDeploy(ビルドに成功したモジュールのデプロイ担当) CodePipeline(上記の3工程をCI/CD化するサービス) EC2 インスタンスファミリー 汎用 コンピューティング最適化(HPC、バッチ処理、動画エンコーディングを行うワークロード) ストレージ最適化(ビッグデータ処理や分散型ファイルシステム用途のワークロード) メモリ最適化(ハイパフォーマンスDBのインスタンスを作りたい、インメモリDBを使いたいといったワークロード) 高速コンピューティング(AI、3D、画像レンダリング、機械学習・ディープランニング・ゲノム処理、リアルタイムビデオ処理……等々超高性能やGPUが必要になるワークロード) 以上に分類される。 インスタンスファミリーの個別については正直覚えきれないので箇条書きにして試験ではお祈りする。 汎用…… A、T、Mシリーズ コンピューティング最適化…… Cシリーズ ストレージ最適化…… Hシリーズ(分散型ファイルシステム及びビッグデータ処理向け)、Iシリーズ(NoSQL、DWH向け) メモリ最適化…… Rシリーズ、Xシリーズ(インメモリDB向け)、Zシリーズ(電子設計(EDA)、RDB向け) 高速コンピューティング(アクセラレーテッド)…… Gシリーズ(レンダリングなど)、Pシリーズ(機械学習、ディープラーニング)、Fシリーズ(ゲノム分析、リアルタイムビデオ処理、リスク計算) ちなみにT2・T3はバースト性能あり(ベースラインを下回る負荷のときクレジットを貯め。ベースラインを超えるとクレジットを消費して一時的に性能を上げる仕組み) Bare MetalとDedicatedとハードウェア専有の違い 以下の通りとなる。 頻出なので整理しておく。 Bare Metalは仮想環境を経由しないでAWSが提供するハードウェアへアクセスができるインスタンス。 ハードウェアのOSからカーネルを利用するコンテナ式の仮想環境化とは違い、EC2のような仮想環境は以下のように構築されていて、EC2インスタンス(つまり仮想マシン)でOSが動く形式になる。 出典:【AWS Black Belt Online Seminar】Amazon EC2 Bare Metalはこの仮想マシンのOSが下層にあるHyperVisorを経由せずに直接HostServer(ハードウェア)へアクセスができるというインスタンスの形式になる。 なので、AWSのホストサーバーのハードウェアレベルまで自分達で管理したい、あるいは管理する必要がある場合や仮想環境下で実行できないワークロード等のユースケースで使う。 ただし、HyperVisor等仮想化ソフトウェアはプリインストールされていないことに注意。 Dedicated Hostは通常のEC2インスタンスの利用のように仮想環境下のワークロードではあるが、コンプライアンス上他のユーザーどころか自社所有の他アカウントであっても同一ハードウェア内に混在してリソースを作ってはいけないような行けない場合、ハードウェアを専有して任意のアカウントのリソースのみ展開させるという場合に使う。 ハードウェア専有インスタンスは他のユーザーのリソースはダメだが、自社が所有するアカウントのリソースであれば展開して良いといったDedicatedよりも緩い条件で専有したい場合に選択する。 まとめると BareMetal…… 仮想環境下で行えないワークロードやハードウェアまで自己管理する必要があるので物理サーバーごと専有する Dedicated…… 仮想環境下でのワークロードだが、任意のアカウントのリソースのみ展開する必要があるので物理サーバーごと専有する ハードウェア専有インスタンス…… 物理サーバーごと専有するけれども、自社内アカウントのリソースのみ展開したいなど、Dedicatedよりは緩い条件で専有している ということになる。 プレイスメントグループ 複数EC2インスタンス間の通信に関してより最適化するための設定方法のようなもの。 クラスタープレイスメント インスタンスを密に配置することでネットワークパフォーマンスの最適化を図る。 結果低レイテンシーと高スループットを期待できる。 AZを跨いで設定することはできず、このグループに入っているインスタンスは他のグループには属せない。 スプレッドプレイスメント EC2インスタンスを別々の物理サーバー(ハードウェア)に分散して配置することで、AZ障害等物理的な障害に対し被害を軽減させるためのグループ。 同一AZでクラスターレベルでEC2を展開していてかつ、クラスタープレイスメントを使っていない場合有効。 特性上AZを跨いで設定できて、1AZにつき7インスタンスまで設定可能。 パーティションプレイスメント インスタンスをパーティションして配置するグループ。 パーティションが異なるEC2インスタンスはスプレッドプレイスメントのように分散して物理サーバーに配置されるので、ハードウェア障害が起きた場合単独パーティションのみに被害を抑えることができる。 EBS 忘れやすいところ ブロックストレージであり、一時記憶領域であるインスタンスストアとEBSボリュームとに分かれる EBSはAZごとに独立しているので同一AZのインスタンスのみアタッチ可能 1インスタンスに複数EBSをアタッチすることは可能(RAIDを組むことも可)だが、1つのEBSを複数のインスタンスで共有するEFSのような使い方はできない どのボリューム使えばいいの? 個人的にわかりやすいフローチャートは 高スループットが必要であるか? → (必要なら)500Mib以上のスループットまたは高いIOPSが必要か だと思う。 なぜならAWSリソースは基本的にコスト最適化に則って利用するように作られているので、スループット能力が必要なら必然的にプロビジョンドIOPSかスループット最適に絞れるからだ。 まとめると判断基準は以下の通り。 高スループットが必要 → スループット性能またはIOPSがどこまで必要かで判断 具体的には高いIOPSが必要か、IOPSは必要ないが500Mib以上のスループットが必要ならプロビジョンドIOPS。 それ以外ならスループット最適化を選択。 高スループットはいらない → 汎用SSDを選択。ただし、ログ・バックアップ・コピーのコピー等重要度やアクセス頻度が低いものの保管用とであればコールドを選ぶ。 ちなみに、プロビジョンド以外はバースト機能あり。 プロビジョンドはある程度処理負荷を予測して自分でIOPSを設定して使うボリュームなのでない。 EBSパフォーマンスの改善ポイント 詳しくは【AWS Black Belt Online Seminar】Amazon EBSを確認。 ボトルネックとなるポイントは以下の3点らしい。 EC2インスタンス側のスループット性能が低い → インスタンスタイプを上げて改善する EBSボリュームのIOPS性能が低い → EBSボリュームの変更で改善する EBSボリュームのスループット性能が低い → EBSボリュームの変更で改善する いずれもCloudWatchでメトリクスを確認し、性能上限に達しているかで判断する。 Snapshotについて Snapshotは整合性を保つために静止点を設けた上で作成することが推奨されているが、実は静止点を設けてSnapshotの作成を指示したあとレスポンスが返ってきたら動作を再開してもいい。 たまに、Snapshot作ってる間EBSボリュームは動作していいのか?ということを聞かれることがあるので覚えておくと助かるかも。 暗号化について KMS(AES-256)またはCMKで実行可能。 ちなみにボリューム作成後に行いたい場合はSnapshotを暗号化してそこから新しいボリュームを作ってアタッチし直す形でできる。 新規作成したEBSを利用するには? A. EC2インスタンスにアタッチし、ファイルシステムを作成してフォーマットする 外付けドライブを使う時と同じ感覚。 VPC セキュリティグループとネットワークACL 問題文の書き方がややこしいとどっちで制限かけるか間違えるポイント。 基本的に セキュリティグループはサーバー単位(つまりEC2インスタンス)に対して効果を発揮する ネットワークACLはサブネットレベルで効果を発揮する この2点に注目する。 なので、インスタンス同士で接続がうまく行かないとかの場合はセキュリティグループ。 特定のIPアドレスを拒否したい場合や異なるサブネット間に跨がるインスタンス同士の通信がうまく行かないなどのケースはネットワークACLを疑う。 他にも SGはステートレスだが。、ネットワークACLはステートレス(常に同じレスポンスを返す必要がある)なのでアウトバウンドのルールも明示的に設定する必要がある SGはすべてのルールを適用するが、ネットワークACLはルールは番号順で(つまり先に設定したルールから)評価されて適用される SGはインスタンスに対して個別にSGを適用するが、ネットワークACLはサブネットに対して設定するので、サブネット内すべてのインスタンスがルールの管理下になる という違いがある。 CIDRについて 基本的に/16(VPCに設定)~/28(/18から+2した数値で設定、サブネットに設定できる)。 サブネットマスクが2ずつ上がるごとに使用できるIPアドレス数が約1/4ずつ少なくなる。 /18…… 16379 /20…… 4091 /22…… 1019 /24…… 251 /26…… 59 /28…… 11 AZについて AZは互いに地理的にも電源的にもネットワーク的にも分離されたデーターサーバー群。 VPCエンドポイントについて グローバルIPをもつAWSのサービスに対して、VPC内部から直接アクセスするための出口となる。 ちなみにオンプレミスなど外部との接続に関してはVPN(Site-to-Site、Client VPN)や専用線を用いたDirect Connectがある。 VPCエンドポイントはGateway型(S3、DynamoDBに対して利用)、PrivateLink型とがある。 ちなみにGateway型は同一リージョン内の接続のみ。 詳しくは下記引用スライドより。 出典:【AWS Black Belt Online Seminar】Amazon VPC VPCフローログ ネットワークトラフィックをキャプチャしてCloudWatch LogsやS3に反映させることができる仕組み。 もっというとインスタンスの通信(セキュリティグループ及びネットワークACLのルール内でのaccepted/reject)のログを取得する。 これを設定しておかないとインスタンスの通信をロギングしたり詳細にモニタリングできなかったりする。 無料では10分間隔、有料だと短くできる。 ちなみにミラーリングするなら Traffic Mirroringという機能を使う。 AutoScaling 基本的には 静観(希望容量=現実の起動台数) スケールアウト スケールイン の3つの状況をメトリクスして現実の起動リソースが希望容量(リソースが理想的に動作するキャパシティやその状態)に合致するように推移させるためのサービス。 EC2に付随するサービスであったが、現在はECS・DynamoDB・Aurora・EMR……と他のサービスでも利用できるようになってきていて、それらを統合して独立したサービスとして成立させようとする傾向が見られる。 基本的には動的なスケーリングを行いたいという場合がほとんどなので Min Capacity(最低これだけは起動していないといけない台数) Max Capacity(最大スケール台数) Desired Capacity(希望容量、なおこれは動的スケーリングの場合Min~Max間で推移することになる) を設定して使うことになる。 速やかなスケーリングを行いたい場合はCloudWatchのモニタリングを詳細(有料)に設定する。 またELBを利用している場合はEC2ヘルスチェックと合わせてELBEヘルスチェックもスケーリングの際適用するように設定しておく。 スケーリングの種類 たまに聞かれるのでざっと押さえておく。 簡易スケーリング(1つのメトリクスに対し、1種類だけのスケーリング条件を設定してスケーリング。なお現在は非推奨) ステップスケーリング(1つのメトリクスに対し、複数のスケーリング条件を設定して細かくスケーリングできる。現在の主流) ターゲットスケーリング(1つのメトリクスに対し、CPU使用率を40%に維持するといった目標値を指定してそれを遵守するようにスケーリングさせる) 予測スケーリング(2週間分のメトリクスから機械学習で需要予測を行いそれに合わせてスケーリングする。仕様上24時間分のメトリクスが必須なのでAuto Scaling Groupを作成した直後には利用できない) スケジュールスケーリング(ある決まったタイミングで1度限りor定期的なスケーリングを実施するように設定できる) 以上からわかるように利用にはCloudWatchによるメトリクスが必須となる。 ステップスケーリング補足 ステップスケーリングで気をつける話。 複数のスケーリング条件を指定できるということは CPU使用率50%を超えたら1台追加 CPU使用率60%を超えたら2台追加 CPU使用率70%を超えたら3台追加 というようにスケーリング条件を指定できることになる。 しかし、インスタンスの起動には時間がかかるので例えば50%を超えると1台追加マシンが起動を始めるわけだがそうこうしているうちに70%になってしまった……なんてこともある。 そうなると4台もマシンが追加されてしまい余計なスケーリングを行ってしまうことになる。 これを避けるためにウォームアップ期間を設定し、追加マシンが起動するまでの時間を予め設定しておくことでAutoScalingに今、マシン起動中だからそれを考えてスケーリングしてねと伝えることができるようにする。 すると、AutoScalingはこのケースの場合、1台追加で起動中に70%だから……じゃあ2台追加で大丈夫かと判断してスケーリングを行ってくれる。 詳しくは引用スライドを。 出典: 【AWS Black Belt Online Seminar】Amazon EC2 Auto Scaling and AWS Auto Scaling スケールアウト、インで通信やデータベースへのアクセスができなくなる この手のトラブルはスケールアウト、インの度にIPアドレスが変更されていることが原因である。 スケールアウトしたインスタンスで通信やアクセスが不可となっている場合はElastic IPを付与するように設定することで起動のたびにIPアドレスが変わること問題に対処する。 スケールインしたあとでも通信やアクセスが不可となっている場合は、ターミネーションポリシーでOldestInstanceから削除するように設定されている可能性があるのでそこを見直す。 ELB 割と危なさそうだなというところを簡潔に。 多分SAA試験レベルではこのサービスの30%くらいしか理解できないだろうなというくらい内容が厚い。 Route53と同じくネットワークに関する知見が求められるな……とひしひしと感じる。 特徴としては 同一インスタンスで複数ポートに負荷分散可能 IPアドレスをターゲットに設定可能 ELB自体も自動でスケーリングする(ロードバランサーノードの仕組み) というものがある。 ただし、AutoScaling等々との兼ね合いもあり、スケーリングするとIPアドレスが変わってしまうこともあるので基本的はAZ、リソース、DNS名をターゲットにすることが推奨されている。 IPアドレスをターゲットにするケースはオンプレミスサーバーに対してもバランスを行いたい時。 クロスゾーン分散 基本的にELBは複数AZに負荷分散するためのサービス。 仕組みとしてはVPC内にELBがあり、さらにそこからAZごとあるいはインスタンスごとにさらにELBを置く(これをロードバランサーノードという)2段階での分散を行っている。 1段階目はELBからELBノードへ処理を分散、2段階目はノードからインスタンスへ負荷分散。 出典: 【AWS Black Belt Online Seminar】Elastic Load Balancing (ELB) これとは別にさらにクロスゾーン分散を行うことで、リージョン内の複数AZに対して負荷分散を行うことができる。 利用する目的としてはAZ間でリソース(例えばインスタンスの数)が不均等である場合にAZの負荷を元に分散することで均等化したいというところにある。 ちなみにRoute53と合わせて使うらしい。 コネクション トラブルシューティング等で聞かれるのでまとめておく。 コネクションタイムアウト…… 設定した秒数無通信状態が続くとそのコネクションを自動で切断する Connection Draining …… バックエンドのEC2インスタンスをELBから登録解除したり、ヘルスチェックが失敗するなどリクエストのタイミングで空白が生まれてしまった場合、指定した秒数新規リクエストの割り振りを中止し、処理中のリクエストが終わるまで一定期間待機させる スティッキー・セッション…… 同じユーザーから来たリクエストを全て同じインスタンスに送信する セキュリティ SSL/TLS Terminationを利用すればバックエンド(EC2インスタンスなど)でSSL処理せずにELBで解決できる。 また、ACMを利用することでHTTPS/SSL証明書を利用することもできる。 ちなみに、ELBを使用しない場合ACM発行の証明書は使えないのでサードパーティ制の証明書をインポートして利用する。 例えばALBにおいてクライアントとの通信中のデータ保護を行う場合は、ACMを利用してSSL証明書を発行し、その証明書を使ってHTTPS通信を利用できるようにすることで実現できる。 ALB アプリケーション層、つまりL7でのロードバランサー。 なので、HTTP、HTTPS、HTTP/2プロトコルでの通信をバランシングする。 急激な負荷が見込まれる場合は暖気申請をする。 ちなみにスケーリングするときはIPアドレスが変わる。 WAFを適用してALBを保護することもできる。 NLB TCP/UDP……つまりトランスポート層でロードバランシングしてくれるL4ロードバランサー。 高可用性、高スループット、低レイテンシーである。 暖気申請は必要なく、IPアドレスもAZ毎に1つ固定で付与される。 CloudFront アクセス制限周りについて間違えるところをまとめる。 SSL証明書 ELBと同じようにACMと合わせて利用できる。 ELBと合わせて使わない場合はサードパーティ製の証明書をインポートして使うケースがある。 署名付きURL/Cookie 発行されたURL/Cookie以外からのリクエストを拒否する仕組み。 これを利用して特定のユーザーのみアクセスできるコンテンツ配信ができる。 フローの例としては以下の通り。 ユーザーが認証リクエストを行う 認証成功なら署名付きURLやCookieを発行して、そこへリダイレクトしコンテンツへアクセス 認証失敗なら403 ちなみにCookieの場合はワイルドカードでパス指定できるので、単一コンテンツの場合は署名付きURL、複数の場合は署名付きCookieを使う。 特定のユーザーやIPアドレスのみアクセスを許可したい 特にS3のコンテンツへのアクセスに対して行うケース。 OAI(Origin Access Identify)をホワイトリスト形式で設定し、対象のS3バケットを用いるディストリビューションに紐つけることでこれを設定したユーザーのみが対象のバケットへアクセスできるようにバケットポリシーを作る。 そうすると、そのバケットはCloudFront経由でのみしかそのバケットにはアクセスができなくなりかつOAIで設定したユーザーのみが対象のバケットへアクセスできるようになる。 ちなみにIPアドレス制限をかけるならWAFも使う。 またオンプレミスで展開していたアプリケーションをAWSへ移行する際にホワイトリストで管理していたIPアドレスも移行させたい場合はROA(Route Origin Authorization)を使う。 Referer制限やサイト保護かけたい WAF、AWS Shieldを使う。 特にReferer制限はWAFと連携しないと使えないことに注意。 ロードエラーに対してフェイルオーバーを実行したい Route53でフェイルオーバールーティングを設定し、CloudFrontディストリビューションを作成する際にフェイルオーバーオプションを設定する。 サイト単位ではなく、オブジェクト単位のフェイルオーバーになる。 Route53 このサービスが1番苦手分野なのでちょっとまとめておく。 まず基本的な考え方としてRoute53は広義的にはDNSに関するマネージドサービスであり、主要な役割の1つとしてName Serverのマネージドサービスがあることを押さえておく。 ではDNSとかName Serverって何? となるので確認していく。 DNSって? FQDN(ドメインを一意に特定できるような形式で書いたもの、例えばwww1.sub.example.com.など。必ず「.」で終わる)をキーに対応するIPアドレスなどの情報を取得する仕組みのこと。 詳しくはBlack Belt資料の以下の図を見てほしい。 出典:【AWS Black Belt Online Seminar】Amazon Route 53 Resolver そして、このDNSを構成する要素の1つにName Serverという仕組みがある。 Name Serverとは 先程のFQDNを「.」を起点にしてすべて探索できるように構成された分散データベース、およびそれを成す一つ一つのNameSeverのことを指す。 権威DNSサーバーやAuthoritative Serverなんて呼ばれることもある。 詳しくはBlack Belt資料の以下の図を見てほしい。 出典:【AWS Black Belt Online Seminar】Amazon Route 53 Resolver 親ゾーンから子ゾーンへと権限移譲をするという形式で成り立っている。 レコードについてはあとで纏めるが、そのレコードで権限移譲を表すと以下の通り。 NSレコードはゾーンを管理するネームサーバーのFQDNを指し示すレコード。 ゾーンについてはName Serveが管理する名前空間(例えば.comのName Serverであれば.comとつくFQDNに関しての情報を返してくれる(名前解決)ような空間)のこと。 example.com. 3600 IN NS ns1.example.com. example.com. 3600 IN NS ns2.example.com. この場合はexample.com.が親ゾーン、ns1.example.com.やns2.example.com.が子ゾーンとなり、これをNSレコードにおいて結びつけている。 そして最終的に欲しいIPアドレスを返してもらうために移譲先で以下のようにAレコードを定義する。 ns1.example.com. 3600 IN A 192.0.2.1 ns2.example.com. 3600 IN A 192.0.2.2 ではRoute53って? 上記のような仕組みをAWSがマネージドで提供してくれる。 Name Server以外にもDNSを構成する要素である Full Service Resolver Stub Resolver Forwarder 以上の機能も提供してくれる(Route53 Resolver、Route53 Resolver for Hybrid Cloudsなど)があるが今回は割愛する。 Route53、正確にはRoute53 Hosted ZoneはNameServerの役割を担うと先程書いたが正確には以下の2種類に分類できる。 Public Hosted Zone(インターネットに公開されているDNSドメインのゾーンに対応する) Private Hosted Zone(VPC内のPrivateなネットワークでのDNSドメインゾーンに対応する) レコードについて これもよくわからなくなるので主要なところを簡単にまとめておく。 SOAレコード ゾーンの管理主体(ゾーンの起点や権威)であることを宣言するためのレコード。 ゾーンの管理、応答するRRSetに関わる情報や設定が含まれる。 NSレコード 前述の通りゾーンを管理するNameServerのFQDNを示すレコード。 ゾーンからゾーンへ権限移譲する場合はこれを使う。 AまたはAAAAレコード そのFQDNに対応するIPアドレスを定義する。 AレコードであればIPv4、AAAAレコードであればIPv6が紐付けられる。 www.example.com. 3600 IN A 192.0.2.3 www.example.com. 3600 IN AAAA 2001:0DB8::1 CNAMEレコード あるドメイン(ホスト名)に別名をつけたいときに使う。 役割としては名前解決する場合、CNAMEで指定した名前に置き換えて継続できるようにするレコード。 ちなみにSOAやNSで定義しているドメイン名(ホスト名)は通常CNAMEレコードで新たに定義することはできないが、後述のALIASレコードを用いることでそれを回避できる。 例えば下記のようなRRsetだと最終的に192.0.2.3が返ってくる。 info.example.com. 3600 IN CNAME www.example.com. www.example.com. 3600 IN A 192.0.2.3 MXレコード IPアドレスをメールサーバーのFQDNと紐つける。 ALIASレコード CNAMEでやっていたようなことをCNAMEを利用することによるZone Apexの制約を受けずに行えるRoute53固有の機能。 ただし、AWSリソースに対しての利用に限る。 S3バケット CloudFront ディストリビューション Route53ホストゾーンの他のレコード 以上のリソースに対して利用できる。 例としては以下の通り www.example.com. 60 IN CNAME www-a.example.com. www-a.example.com. 60 IN CNAME xxxx.cloudfront.net. xxxx.cloudfront.net.60 IN CNAME 192.0.2.3 以上のRRsetで行っていることをALIASレコードとして定義した以下のレコードで同じように実行できる。 www.example.con. 60 IN A 192.0.2.3 トラフィックルーティング Route53でよく出てくる機能なので改めて。 シンプルルーティング レコードで設定したIPアドレスへとルーティングする。 例は以下の通り。 以下のようなRRsetの場合、3つのIPアドレスから都度ランダムで1つ応答がある。 www.example.con. 60 IN A 192.0.2.4 www.example.con. 60 IN A 192.0.2.3 www.example.con. 60 IN A 192.0.2.1 加重ルーティング トラフィックを指定した比率でリソースに振り分けるためのルーティング。 A/BテストやBlue/Greenデプロイによる段階的な環境、バージョン移行に使ったり単純にサーバーごとの負担を平準化するために利用する。 フェイルーオーバールーティング ヘルスチェックの結果に基づいて利用可能なリソースにルーティングする。 アクティブ/アクティブ(常にどちらの環境も動いている)構成かアクティブ/パッシブ(フェイルオーバー先はコールド状態)構成を選択できる。 ヘルスチェックは複数結果を結合でき、それをフェイルオーバー条件とすることもできる。 主に複数リージョンにまたがる冗長構成、災害時のクロスリージョンフェイルオーバー、S3静的WebホスティングのError Pageの表示に利用できる。 ちなみにこのルーティングを利用するにはCNAMEレコードをして移行先のリソースのホスト名と移行元のホスト名を紐つけておく。 複数値回答(マルチバリュー)ルーティング 最大8つのランダムに選択された正常なレコードから応答するようにするルーティング。 シンプルルーティングでRRsetを構成したような状態と似ているが、こちらはヘルスチェックを行い、各リソースが正常かを確認して正常なリソースからのみ応答させる。 ちなみに応答をキャッシュした後であるなら、当該リソースが利用できなくなった場合は他のIPアドレスを利用できる。 レイテンシールーティング ネットワークレイテンシーが最も低いAWSリージョンのリソースへとルーティングする。 - 位置情報ルーティング クライアントの位置情報に基づいて、ルーティングする。 具体的には特定の地域・国からのDNSクエリに対して、特定のアドレスを応答させるようにする。 これはクライアントの地域によって適切な言語でコンテンツを提供したり、CloudFrontにおいて地域制限をかけたいといったときに利用する。 物理的近接性ルーティング ユーザーとリソースの緯度経度情報に基づいて、地理的場所的にルーティングする。 トラフィックフローを使わないと作成できない。 RDS RDSでマルチAZを有効化すると? A. 自動的に別AZに同期レプリケーション及び自動フェイルオーバーを実現するスタンバイ状態のDBインスタンス(スレーブ)が構成される ただし、スタンバイ状態ではアクセスはできないので負荷分散はリードレプリカを作成して行う。 この機能によって単純にAZやインスタンス障害発生時のフェイルオーバーに限らず パッチ適用等のメンテナンス 手動でマスター側をリブートする といったような通常はサービスの停止が必要な場合においてもそれを回避したり、その影響を軽減できる。 リードレプリカの昇格について リードレプリカはRDS採用しているDBエンジンによって実は仕様が異なる。 主な違いは以下の通り。 レプリケーションの仕様の違い…… MySQLとMariaDBは論理レプリケーション、Oracle・Postgre・SQLは物理レプリケーション。 トランザクションログの削除 リードレプリカにWriteできるか…… MySQLとMariaDBは可能。OracleとSQLは不可(DBインスタンスに昇格させれば可)、Postgreは不可 リードレプリカのバックアップ…… MySQLとMariaDBは可能、Postgreは可能(自動バックアップ機能は使えない)、OracleとSQLは不可 並列レプリケーション(レプリケーション処理のマルチスレッド化)…… Postgre以外は可能 リードレプリカのマウント状態の維持…… Oracle以外不可 そしてRDSのリードレプリカは以下の状況に応じてスタンドアロンDBインスタンスに昇格することができる。 DDL操作(MySQLとMariaDBのみ) シャーディング(データベース……というよりテーブルの分散配置) DR対策としてプライマリDBの障害に対してリードレプリカを昇格させフェイルオーバーする ただしリードレプリカはクロスリージョンに配置することもできるがここが少しややこしいので次項で解説。 クロスリージョンリードレプリカとフェイルオーバー マルチAZの場合、構成を有効化すると自動でスタンバイDBが出来上がりプライマリDBと同期レプリケーションを行い自動フェイルオーバーの体制が整う。 しかし、マルチAZの場合でもそうだがリードレプリカを昇格させるのは基本的には手動で行わないといけないのでクロスリージョンリードレプリカを使ったフェイルオーバーは自動ではできない。 ただし、RDSのDBエンジンでAuroraを使用していてかつGlobal Databaseを有効にしてクロスリージョンレプリケーションを作成している場合は設定要件に従って自動でフェイルオーバーすることもできる。 クロスリージョンレプリケーションの基本的な構成は以下の通り。 出典: Amazon RDS Online Seminar 「マルチリージョンを利用した高可用性構成と Amazon Aurora のチューニング」よりマルチリージョンを利用した高可用性構成のPDF資料 Auroraのクロスリージョンフェイルオーバーに関してはこちらの記事が参考になります。 Amazon Aurora Global Databaseをリージョン間でフェイルオーバーさせてみた ちなみにマルチAZにしろクロスリージョンにしろフェイルオーバーはレプリケーションを伴うので単純にDBインスタンスのリソースを2倍用意しないといけないのでコストはかなりかかることに注意。 特にクロスリージョンはデータ転送料もかかるので余計にかかる、ホットスタンバイ構成の場合は目も当てられない。 バックアップってどうなってるの? DB自体は自動バックアップ機能あり(リードレプリカのそれはDBエンジンによって異なる)。 バックアップはSnapshot形式で行われて、リストアもそれで行う。 Snapshotはリージョン、またはアカウント間、両方を経由しての別リーションの別アカウントへのコピーも可能。 ただし、リストアしたDBはエンドポイントの名前が変わるのでアプリケーション側でエンドポイントの接続名の修正を行うか、エンドポイントのリネームを忘れないようにする。 モニタリングどうなってるの? A. 基本的にはCloudWatchと連携。ただし、OSメトリクスやプロセスのモニタリングやCloudWatch Logsへの出力、特定メトリクスへのアラート、メトリクスの60秒以下単位での取得をしたい場合は拡張モニタリングを有効にする。 その他 カスタムサインインコードや独自のユーザーIDを管理したくない A. Web ID フェデレーションの設定を行いSTSを利用する。 これで、OpenID Connect互換の外部IDプロパイダ(早い話がGoogle等)からサインインし、そのユーザーにSTSで認証トークンを付与しそれと引き換えにIAMロールをマッピングするという処理ができる。 OpenID Connectを利用しない場合は、SAML フェデレーションの設定を行う。 フルマネージドに依存せず、自社基盤のオペレーティングシステムにアクセス可能なAWSサービスを利用したい A. EC2インスタンスを利用したAWSサービスを利用する。 基本的にフルマネージドサービスではなく、アンマネージドなサービスを利用すればいい。 代表的なものがEC2になる。 ただし、EMRのようにマネージド型ではあるが、EC2を利用してリソースが構築されるため要件に合致するというケースもある。(マネージドではあるが、フルではないというケース) アクセスがほとんど発生しないデータの保存先としてGlacierってコスト最適じゃないの? A.90日は必ずデータを保持するため、特に30日以内に削除するデータの場合についてはIAなストレージの方がコスト最適。 これはかなり罠かつ問題文でもアクセスや更新は保存後殆ど発生しないデータに対してのS3の保存先をコスト最適を考えてを選択してくださいみたいな書かれ方しかしないので判断しづらかったりする。 こういうのはちょっと卑怯だと思った。 S3で403エラーが出る A. バケットポリシーで読み取り権限が設定されていない or パブリックアクセスブロックの無効化がなされていない。 よく間違えるところですが、パブリックアクセスの許可設定の有効化という設定は存在しない。 あくまでバケットはデフォルトではパブリックアクセスブロック状態であり、静的Webホスティング等でパブリックなアクセスを許可する必要がある場合にこれを無効化する設定を行うということを覚えておく。 S3でバケットの暗号化を有効にしているのになぜか失敗する A. バケットポリシーやACLで暗号化なしのPUTリクエストを拒否している可能性があるので見直す データ登録は バケットポリシーで評価 → バケットに追加 のフローで行われる。 つまり、登録前データが暗号化されていないものの場合はバケットポリシー等で暗号化なしのPUTリクエストを拒否していると評価のフェーズで当然拒否されてしまうので。バケットの暗号化設定を行ってたところで意味がない。 なので、ポリシーを見直す。 S3のバージョンニングを有効にしているバケットにおいてHTTP503エラーが発生している A. ライフサイクル管理でバージョンに有効期限をつけて削除する オブジェクトをバージョニングで管理している場合、例えばあるオブジェクトでバージョンが数百万もできている……という状態になるとS3が過剰なリクエストトラフィックから保護するためにバケットへのリクエストを調整してしまい、結果としてサーバーエラーが起きてしまう。 なので、ライフサイクル管理においてNonCurrentVersionとExpiredObjectDeleteMarkerのポリシーを有効にして、バージョンに有効期限を設けて期限切れのものを削除するようにする。 AとBのVPCでVPC Peeringを行っているが、オンプレミスと接続しているAのVPCをの接続を冗長化させたい 参考 気をつけることは以下のポイント VPC Peeringはあくまで1対1のVPC間接続であってA-B、B-CでピアリングしてもA-Cの関係にはならない 同様にエッジ間ルーティングもサポートしていないので、今回のケースのようにA-オンプレミスで接続関係にあってもBからオンプレミスへ接続することはできない なので、A-オンプレミスの接続を冗長化、フォールトトレランスを実現したい場合は Direct Connectを利用している場合は、仮想インターフェース(オンプレ側のルーターやファイアウォール)を増設して接続先を増やして動的ルーティングを行う VPNを利用している場合は同じ理屈でカスタマーゲートウェイを増設する Direct ConnectとVPNを併用する といったように接続パターンを複数用意することで、実現できる。 オンプレミスでActive Directoryを使っているのでAWSでも利用したい A .AWS Directory Service AD Connectorを利用する 具体的には次の2ステップ。 AD Connectorを利用してオンプレ側のMicrosoft Active DirectoryとIAMユーザーを連携させる 次に連携させたユーザーやグループに対してIAMロールを付与して権限管理を行う オンプレミスのストレージとEFSでデータ移行を行いたい A. AWS DataSyncを使う EFSではなく、S3や同じファイルシステムでもWindowsファイルシステムならFSx、あるいはテープボリュームを利用したい場合やボリュームゲートウェイを利用してプライマリーは自社データセンターに残すが、S3にバックアップを保存したい、またはS3をプライマリーにして自社データセンターにはキャッシュを残す……等々の利用方法の場合はStorage Gatewayを使う。 ACMがサポートされていないリージョンでSSL証明書を使いたい A. IAMで外部プロパイダーから取得したSSL証明書をデプロイする オンプレミスのデータセンターのサーバーの使用率等のデータ、依存関係のマッピングを収集したい A. AWS Application Discovery Serviceを利用する オンプレミスのワークロードをAWSに移行したい A. AWS Server Migration Service利用する ちなみにデータベースの移行だとDatabase Migration Serviceを利用する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS(ECS)上でデータベースが作成されない!? Dockerで環境構築したRails6をRDSと連携できない問題を解決!

開発環境をDockerで開発していたRails6アプリケーションをAWS(ECS)にデプロイしている実装で、AWS上にデータベースが作成できない問題が発生したので解決までの手順を残しておこうと思います。 開発環境 RubyMine Ruby 3.0.1 Ruby on Rails 6.1.3 Docker 20.10.7 AWS (ECS fargate/ECR/VPC/RDS/ACM/ALB/S3/Route53) 発生していた問題 オリジナルアプリをDockerで開発していたので、デプロイ先をAWS(ECS fargate)にしたいと思い実装を進めているなかで、本番環境でデータベースが作成されないエラーが起きました。 エラー内容(ECSタスク上のログ) 2021-07-26 19:26:48Tasks: TOP => db:create 2021-07-26 19:26:48(See full trace by running task with --trace) 2021-07-26 19:26:48rails aborted! 2021-07-26 19:26:48ActiveRecord::ConnectionNotEstablished: Unknown MySQL server host 'db' (-2) 2021-07-26 19:26:48Caused by: 2021-07-26 19:26:48Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2) 2021-07-26 19:26:48Unknown MySQL server host 'db' (-2) 2021-07-26 19:26:48Couldn't create 'locat' database. Please check your configuration. エラー文を調べたところ、サーバーホスト名dbが本番環境で見つからないというエラー内容だとわかりました。 修正前のdatabase.yml # MySQL. Versions 5.5.8 and up are supported. # # Install the MySQL driver # gem install mysql2 # # Ensure the MySQL gem is defined in your Gemfile # gem 'mysql2' # # And be sure to use new-style password hashing: # https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html # default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password socket: /tmp/mysql.sock host: db development: <<: *default database: locat_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: locat_test production: <<: *default database: <%= Rails.application.credentials.db[:database] %> username: <%= Rails.application.credentials.db[:username] %> password: <%= Rails.application.credentials.db[:password] %> socket: <%= Rails.application.credentials.db[:socket] %> # As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # # Instead, provide the password or a full connection URL as an environment # variable when you boot the app. For example: # # DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase" # # If the connection URL is provided in the special DATABASE_URL environment # variable, Rails will automatically merge its configuration values on top of # the values provided in this file. Alternatively, you can specify a connection # URL environment variable explicitly: # # production: # url: <%= ENV['MY_APP_DATABASE_URL'] %> # # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database # for a full overview on how database connection configuration can be specified. # エラー原因 エラー原因は、ローカルのmysqlサーバーホスト名'db'でECS上で設定しているRDSとの連携をしようとしていたことが原因でした。 つまり、ローカルの接続先ホストをRDSのエンドポイントにして連携させてあげる必要がある。 ローカルのホスト名と本番環境のRDSを同じにしてあげないと、RDS上にはない'db'で接続しようとしてしまいデータベースが作成できないエラーが発生してしまうということでした。 解決方法 ローカルの接続先ホストをRDSのエンドポイントに指定してあげることでデータベースの作成ができました。 修正方法 % EDITOR=vim bin/rails credentials:edit でhostを作成してRDSのエンドポイントを指定する #aws: # access_key_id: AKIAU2S6QQYAB4JOXSO6 # secret_access_key: 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 # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies. secret_key_base: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx db: database: RDSのデータベース名 username: RDSのユーザー名 password: RDSのパスワード socket: xxxxxxxxxxxxxxxxxxxxxxxxx host: ここにRDSのエンドポイントを指定してあげる credential.ymlにエンドポイントを指定すると、ECSで作成するコンテナの環境変数にエンドポイントを設定する必要はなくなる(設定しても可) credential.ymlに必要なエンドポイントを指定したあとは、database.ymlを下記のように編集する database.yml production: <<: *default database: <%= Rails.application.credentials.db[:database] %> username: <%= Rails.application.credentials.db[:username] %> password: <%= Rails.application.credentials.db[:password] %> socket: <%= Rails.application.credentials.db[:socket] %> host: <%= Rails.application.credentials.db[:host] %> host: <%= Rails.application.credentials.db[:host] %>を設定する ここまで修正したらECRに設定したリポジトリのlatestを削除後にプッシュを行う。 (Rails側のDockerfileをプッシュ) CircleCIを導入している方は自動デプロイで可能。 タスク定義のリビジョンでコンテナの再定義を行う。再定義後にクラスターのサービス名の設定内のリビジョンを変更した最新のlatestに変更。 ここまで修正したらタスクのログでデータベースが作成できているか確認をしてみる。(おそらくデータベースの作成ができているでしょう。) まとめ 初めてECSに触れたので、デプロイまでの実装でかなりつまずきました。ひとまずデータベースの作成ができたので一安心。 インフラ周りが自分の中で最も難しい分野だと感じているので、知識を増やして正しく構築できるように勉強していこうと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アラサー未経験フリーターがITインフラ業界に放り込まれてawsの資格をプロフェッショナルまで取った話 ③プロフェッショナル2種

アラサーIT未経験の私がawsプロフェッショナル系を取得した時の勉強法まとめです。私と同じくIT経験の浅い方の参考になればと思います。 取得した資格は以下 ソリューションアーキテクト・プロフェッショナル DevOpsエンジニア・プロフェッショナル 今回2つの試験は自宅でのオンライン受験でした。 クラウドプラクティショナー編はこちら アソシエイト編はこちら ソリューションアーキテクト・プロフェッショナル 勤続約2年程で受験しました。 この時の技術レベルはLDAPサーバー構築、CF-S3を使って静的webサイトを構築したり Terraformでインフラをコード化する等結構いろんな技術を触っている段階でした。 受験しようとしたきっかけは、費用が会社持ちということと、合格すれば資格手当が出るからという金銭的な面からでした。 たまたまこの時期は業務的に余裕があり、時間が取れるタイミングだった事もあって受験してみようという流れでした。 今回もアソシエイト系と同じく下記サイトをメインに進めました。 ココの問題集を解く 問題に出てきたawsサービスの公式ドキュメントを総ざらい 改めて問題集を解く 間違えた問題に出てきたサービスの公式ドキュメント以下略 進め方はもう全く一緒ですね。 学習としては、ひたすら広範囲を深く掘り下げていくという何とも気の遠くなりそうな内容でした。。。 ハイブリッドクラウドや、オンプレからAWSに移行するときのベストプラクティス、オンプレのLDAPからSSO等々、普段業務で触らない範囲の出題がとても多い印象でした。 兎にも角にもAWSの公式ドキュメントを隅から隅まで網羅しましょう。ひたすら根気勝負です。 学習期間は2ヶ月ほどで受験しました。 前日に友人と泥酔してしまい、当日は試験時間前まで自宅のトイレで過ごしました。 モニターにピントが合わず苦戦しました。 ここまでの試験全てで前日泥酔からの合格だったので、 もうここまで来たら受験前日に泥酔した方が受かるんじゃないかと泥酔しながら考えていました。 結果は合格。 受験者スコアは798点でした。 やはり普段触らないコスト管理が厳しい結果となりました。 とにかく問題文が長い!長ーい!! 問題を一周した時点で120分ほど消化してしまっており、見直しにあまり時間をかけることだ出来ませんでした。 長文読解が非常に多いので、違う選択肢を素早く見つけて2択位に絞ってから長考に入った方が効率的に進められるかと思います。 DevOpsエンジニア・プロフェッショナル SOPに合格してから1ヶ月の期間で受験しました。 SAPよりも範囲は絞られます。 SAPで学習した内容と集中力が途切れないうちに受けることをお勧めします。 基本的にはSAP+SysOps+Developerの範囲を総ざらいしました。 正直SAPに合格していれば何とかなると思います。 前日に友人と泥酔してしまい、当日は試験時間前まで自宅のトイレで過ごしました。 モニターにピントが合わず苦戦しました。 結果は合格。 受験者スコアは835点でした。 感想はSAPより遥かにスムーズに進行出来ました。SAPの長文問題を突破できるなら何とかなる範囲かと。 ここまでで5つの資格を取得できました。 全3回に渡って更新しましたが、少しでも誰かの参考になれば幸いです。 ......試験前に酒飲むと合格できるらしい 最後まで閲覧いただきありがとうございました。 ではまた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Client VPNからのPrivate Subnetアクセス

1.目的 オンプレミスからPrivate Subnetへのアクセスは、以下の接続方式などがあります。 閉域網アクセス(Direct Connect) VPNアクセス(サイト間VPN) VPNアクセス(Client VPN) 本記事では、Client VPNの設定方法について解説します。サイト間VPNと比較して専用のルータ等を必要とせずに、作業用PCさえあれば実現可能という観点では、個人利用では最も設定が容易な接続方式だと思います。 2.手順(AWS側) VPN接続の認証は 3種類(AD認証, サーバ証明書・クライアント証明書による相互認証、これら組み合わせによる認証)から選択することが可能です。今回は、サーバ証明書・クライアント証明書による相互認証を採用します。まず、認証に必要な証明書を作成します。Githubにアクセス可能な任意のサーバから実行します。 証明書の作成 git clone https://github.com/OpenVPN/easy-rsa.git cd easy-rsa/easyrsa3 ./easyrsa init-pki ./easyrsa build-ca nopass ./easyrsa build-server-full server nopass ./easyrsa build-client-full client1.domain.tld nopass mkdir ~/cert_folder/ cp pki/ca.crt ~/cert_folder/ cp pki/issued/server.crt ~/cert_folder/ cp pki/private/server.key ~/cert_folder/ cp pki/issued/client1.domain.tld.crt ~/cert_folder cp pki/private/client1.domain.tld.key ~/cert_folder/ cd ~/cert_folder/ 作成した証明書をACMへインポートします。AWS Management Consolでも登録可能ですが、 以下ではAWS CLIで実行します。 ACMへのインポート aws acm import-certificate --certificate fileb://server.crt --private-key fileb://server.key --certificate-chain fileb://ca.crt --region ap-northeast-1 aws acm import-certificate --certificate fileb://client1.domain.tld.crt --private-key fileb://client1.domain.tld.key --certificate-chain fileb://ca.crt --region ap-northeast-1 VPCサービスより、Client VPNエンドポイントを作成します。Client VPN経由でアクセスするPCのネットワークレンジをクライアントIPv4 CIDRに記載します。接続先のVPCとは別のネットワークレンジを指定します。ACMに登録済のサーバ証明書、クライアント証明書も以下キャプチャの通り設定します。 Client VPNエンドポイントの作成が完了したら、接続先のVPCのサブネットに関連付けを行います。 続いて、受信の承認を設定します。接続先のVPCのCIDRブロックを許可するように設定します。 クライアント設定のダウンロードを行いACMに登録したサーバ証明書と秘密鍵を、設定ファイルの末尾に追加します。 設定ファイルの編集その1 <cert> ※client1.domain.tld.crt(-----BEGIN CERTIFICATE-----~-----END CERTIFICATE-----)の内容※ </cert> <key> ※client1.domain.tld.key(-----BEGIN PRIVATE KEY-----~-----END PRIVATE KEY-----)の内容※ </key> そして、その設定ファイルのVPCエンドポイントの値のプレフィックスに任意の文字列を追加します。 設定ファイルの編集その2(設定例です) aiueo.cvpn-endpoint-XXXXXXXXXXXXXXXX.prod.clientvpn.us-west-2.amazonaws.com 3.手順(オンプレミス側) サポートのことも考えて、AWS公式のOpen-VPNクライアントツールを使用します。ここからダウンロードすることができます。上記手順でダウンロード&編集した設定ファイルをVPN設定ファイルに取り込みます。 設定ファイルを取り込み後、VPN接続することが可能です。紐づけたSubnet内のPrivate IPに対してSSHやPINGなどでアクセスすることができます。 その他 Client VPNの設定情報はCloudwatchの統計情報で確認することができます。例えば、ActiveConnectionsCountで0になったらアラートが上がるといったような仕掛けを設けるとよいかもしれません。 以上 参考情報 Client VPNの設定を非常にわかりやすく纏まっている技術ブログ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コロナで不健康になった人の為に、健康に特化したレシピサイト作ってみた。AWS/Rails/Puma/Nginx

はじめに 現在、高校3年生でプログラミング歴は約1年半です。 プログラミング歴 2020/2~ HTML/CSS/JavaScript(jQuery) 2020/10~ Python/Django・Flask 2021/5~ Ruby/Rails 60日程度でレシピサイトをリリースしました。 現在も作成段階ですが、ある程度形になったのでこの記事を書いています。 ※随時更新中です。 筋肉食堂(Muscle meal) 筋肉食堂(Muscle meal) はダイエットやトレーニングをしている方に向けた、健康に特化したレシピサイトです。 URL https://muscle-meal-recipes.com/ https://github.com/holasoynaoki/muscle_meal 作成に至った経緯 コロナウイルスが流行している今日では、健康に関して2つの問題が発生すると考えました。 外出自粛の影響で運動不足になり、不健康な人が増える 人と会う回数が減り、精神的な苦痛を受ける人が増える これらの問題を解決するために、健康を支える重要な要素である「食事」にフォーカスしました。 外食があまりできない影響で自炊をする方が増えたため、健康に特化したレシピサイトを作ることで、少しでも多くの人の健康状況を助けることが出来ると考えています。 また、食事を通して趣味・趣向が合う方と繋がることで、精神的にも豊かにすることが出来るのではないかと考えました。 以上の理由により、作成に至りました。 ER図 インフラ構成図 機能一覧 基本機能 会員登録・ログイン機能(devise) ユーザーフォロー機能 (Ajax) プロフィールページ機能 プロフィール登録情報変更(ユーザー名、ニックネーム、自己紹介文、プロフィール画像) 通知機能 投稿に関する機能 新規登録機能 画像投稿機能 カロリー自動計算機能(Ajax) 投稿いいね機能(Ajax) 投稿キーワード・タグ検索機能 投稿ソート機能(いいね順・新着順・古い順) ページネーション(Kaminari) その他 ヘッダーハンバーガーメニュー 今後の改善点 テストを充実させる 開発環境にDockerを使用する Circle CIの使用によるテスト・ビルド・デプロイの自動化 どのように学習(開発)したか? 学習(開発)のポイントとして、仮説→実行→反省を回すことを意識しました。 まず、最低限のスキルを「ある程度動くサービスをリリースする」と仮説を立て、Railsを中心に学習をしました。 最初はインフラにHerokuを使用し、まずはネット上に公開することを目指しました。 RailsとHerokuは約1ヶ月でできるようになりました。 Python/Djangoの知識があったのである程度理解は早かったと思います。 次に、他の未経験者のポートフォリオを拝見し、自分にはインフラの知識(主にAWS)が足りないと仮説を立てました。 なので、「作ったサービスをAWSでデプロイする」という目標を立てました。 AWSに関しては、デプロイするだけでなくRoute53でのドメイン設定やSSL化など様々な工程を踏むことで、インフラの基礎知識をつけていきました。 デプロイに関しては約2週間でできました。 今後の学習予定としては テストを充実させる 開発環境にDockerを使用する Circle CIを使用し、継続的なサービスにする これらを学習/開発していきたいと思っています。 開発を経ての反省 開発する順序に反省があったと感じました。 実際に行った順序 ローカル環境である程度動くサービス herokuにデプロイ インフラをAWSに変更 サービス向上 理想の順序 企画 AWSにデプロイ(インフラを整える) サービスを開発 テスト 実際に行った順序では、余計なエラーなどが発生してなかなか厄介でした。 1ヶ月以上かけて作ったサービスが504 Gateway Time-outや502 Bad Gatewayなどで見られなくなったときは非常に焦りました。 なので今後開発していく方には、インフラなどを整えるところから始めることを勧めます。 最後に Python/Djangoでの開発経験があったおかげでMVCモデルなどの概念があったため、スムーズに開発を進めることができました。 しかし、サービスをリリースすることは容易ではありませんでした。 開発中には、何度も難しいところが出てきました。 Trelloなどを使用し、課題を明確にする 順序を付け、1個づつタスクをこなす このやり方で着実に進めることができました。 今後は、よりサービスを向上させていくと同時に、たくさんの知識をつけていきたいと思っています。 今後のサービス向上のため、誤っている箇所やおかしいと思う箇所がございましたら、コメントの方でご指導願います。 質問に関しては、コメントの方にいただければ出来る限り返答したいと思っておりますので、ご気軽にコメントしていただければと思います。 最後まで読んでくださりありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

独学・未経験者がレシピサイト作ってみた。AWS/Rails/Puma/Nginx

はじめに 現在、高校3年生でプログラミング歴は約1年半です。 プログラミング歴 2020/2~ HTML/CSS/JavaScript(jQuery) 2020/10~ Python/Django・Flask 2021/5~ Ruby/Rails 60日程度でレシピサイトをリリースしました。 現在も作成段階ですが、ある程度形になったのでこの記事を書いています。 ※随時更新中です。 筋肉食堂(Muscle meal) 筋肉食堂(Muscle meal) はダイエットやトレーニングをしている方に向けた、健康に特化したレシピサイトです。 URL https://muscle-meal-recipes.com/ https://github.com/holasoynaoki/muscle_meal 作成に至った経緯 コロナウイルスが流行している今日では、健康に関して2つの問題が発生すると考えました。 外出自粛の影響で運動不足になり、不健康な人が増える 人と会う回数が減り、精神的な苦痛を受ける人が増える これらの問題を解決するために、健康を支える重要な要素である「食事」にフォーカスしました。 外食があまりできない影響で自炊をする方が増えたため、健康に特化したレシピサイトを作ることで、少しでも多くの人の健康状況を助けることが出来ると考えています。 また、食事を通して趣味・趣向が合う方と繋がることで、精神的にも豊かにすることが出来るのではないかと考えました。 以上の理由により、作成に至りました。 ER図 インフラ構成図 機能一覧 基本機能 会員登録・ログイン機能(devise) ユーザーフォロー機能 (Ajax) プロフィールページ機能 プロフィール登録情報変更(ユーザー名、ニックネーム、自己紹介文、プロフィール画像) 通知機能 投稿に関する機能 新規登録機能 画像投稿機能 カロリー自動計算機能(Ajax) 投稿いいね機能(Ajax) 投稿キーワード・タグ検索機能 投稿ソート機能(いいね順・新着順・古い順) ページネーション(Kaminari) その他 ヘッダーハンバーガーメニュー 今後の改善点 テストを充実させる 開発環境にDockerを使用する Circle CIの使用によるテスト・ビルド・デプロイの自動化 どのように学習(開発)したか? 学習(開発)のポイントとして、仮説→実行→反省を回すことを意識しました。 まず、最低限のスキルを「ある程度動くサービスをリリースする」と仮説を立て、Railsを中心に学習をしました。 最初はインフラにHerokuを使用し、まずはネット上に公開することを目指しました。 RailsとHerokuは約1ヶ月でできるようになりました。 Python/Djangoの知識があったのである程度理解は早かったと思います。 次に、他の未経験者のポートフォリオを拝見し、自分にはインフラの知識(主にAWS)が足りないと仮説を立てました。 なので、「作ったサービスをAWSでデプロイする」という目標を立てました。 AWSに関しては、デプロイするだけでなくRoute53でのドメイン設定やSSL化など様々な工程を踏むことで、インフラの基礎知識をつけていきました。 デプロイに関しては約2週間でできました。 今後の学習予定としては テストを充実させる 開発環境にDockerを使用する Circle CIを使用し、継続的なサービスにする これらを学習/開発していきたいと思っています。 開発を経ての反省 開発する順序に反省があったと感じました。 実際に行った順序 ローカル環境である程度動くサービス herokuにデプロイ インフラをAWSに変更 サービス向上 理想の順序 企画 AWSにデプロイ(インフラを整える) サービスを開発 テスト 実際に行った順序では、余計なエラーなどが発生してなかなか厄介でした。 1ヶ月以上かけて作ったサービスが504 Gateway Time-outや502 Bad Gatewayなどで見られなくなったときは非常に焦りました。 なので今後開発していく方には、インフラなどを整えるところから始めることを勧めます。 最後に Python/Djangoでの開発経験があったおかげでMVCモデルなどの概念があったため、スムーズに開発を進めることができました。 しかし、サービスをリリースすることは容易ではありませんでした。 開発中には、何度も難しいところが出てきました。 Trelloなどを使用し、課題を明確にする 順序を付け、1個づつタスクをこなす このやり方で着実に進めることができました。 今後は、よりサービスを向上させていくと同時に、たくさんの知識をつけていきたいと思っています。 今後のサービス向上のため、誤っている箇所やおかしいと思う箇所がございましたら、コメントの方でご指導願います。 質問に関しては、コメントの方にいただければ出来る限り返答したいと思っておりますので、ご気軽にコメントしていただければと思います。 最後まで読んでくださりありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ポートフォリオ】独学・未経験者がレシピサイト作ってみた。AWS/Rails/Puma/Nginx

はじめに 現在、高校3年生でプログラミング歴は約1年半です。 プログラミング歴 2020/2~ HTML/CSS/JavaScript(jQuery) 2020/10~ Python/Django・Flask 2021/5~ Ruby/Rails 60日程度でレシピサイトをリリースしました。 現在も作成段階ですが、ある程度形になったのでこの記事を書いています。 ※随時更新中です。 筋肉食堂(Muscle meal) 筋肉食堂(Muscle meal) はダイエットやトレーニングをしている方に向けた、健康に特化したレシピサイトです。 URL https://muscle-meal-recipes.com/ https://github.com/holasoynaoki/muscle_meal 作成に至った経緯 コロナウイルスが流行している今日では、健康に関して2つの問題が発生すると考えました。 外出自粛の影響で運動不足になり、不健康な人が増える 人と会う回数が減り、精神的な苦痛を受ける人が増える これらの問題を解決するために、健康を支える重要な要素である「食事」にフォーカスしました。 外食があまりできない影響で自炊をする方が増えたため、健康に特化したレシピサイトを作ることで、少しでも多くの人の健康状況を助けることが出来ると考えています。 また、食事を通して趣味・趣向が合う方と繋がることで、精神的にも豊かにすることが出来るのではないかと考えました。 以上の理由により、作成に至りました。 ER図 インフラ構成図 機能一覧 基本機能 会員登録・ログイン機能(devise) ユーザーフォロー機能 (Ajax) プロフィールページ機能 プロフィール登録情報変更(ユーザー名、ニックネーム、自己紹介文、プロフィール画像) 通知機能 投稿に関する機能 新規登録機能 画像投稿機能 カロリー自動計算機能(Ajax) 投稿いいね機能(Ajax) 投稿キーワード・タグ検索機能 投稿ソート機能(いいね順・新着順・古い順) ページネーション(Kaminari) その他 ヘッダーハンバーガーメニュー 今後の改善点 テストを充実させる 開発環境にDockerを使用する Circle CIの使用によるテスト・ビルド・デプロイの自動化 どのように学習(開発)したか? 学習(開発)のポイントとして、仮説→実行→反省を回すことを意識しました。 まず、最低限のスキルを「ある程度動くサービスをリリースする」と仮説を立て、Railsを中心に学習をしました。 最初はインフラにHerokuを使用し、まずはネット上に公開することを目指しました。 RailsとHerokuは約1ヶ月でできるようになりました。 Python/Djangoの知識があったのである程度理解は早かったと思います。 次に、他の未経験者のポートフォリオを拝見し、自分にはインフラの知識(主にAWS)が足りないと仮説を立てました。 なので、「作ったサービスをAWSでデプロイする」という目標を立てました。 AWSに関しては、デプロイするだけでなくRoute53でのドメイン設定やSSL化など様々な工程を踏むことで、インフラの基礎知識をつけていきました。 デプロイに関しては約2週間でできました。 今後の学習予定としては テストを充実させる 開発環境にDockerを使用する Circle CIを使用し、継続的なサービスにする これらを学習/開発していきたいと思っています。 開発を経ての反省 開発する順序に反省があったと感じました。 実際に行った順序 ローカル環境である程度動くサービス herokuにデプロイ インフラをAWSに変更 サービス向上 理想の順序 企画 AWSにデプロイ(インフラを整える) サービスを開発 テスト 実際に行った順序では、余計なエラーなどが発生してなかなか厄介でした。 1ヶ月以上かけて作ったサービスが504 Gateway Time-outや502 Bad Gatewayなどで見られなくなったときは非常に焦りました。 なので今後開発していく方には、インフラなどを整えるところから始めることを勧めます。 最後に Python/Djangoでの開発経験があったおかげでMVCモデルなどの概念があったため、スムーズに開発を進めることができました。 しかし、サービスをリリースすることは容易ではありませんでした。 開発中には、何度も難しいところが出てきました。 Trelloなどを使用し、課題を明確にする 順序を付け、1個づつタスクをこなす このやり方で着実に進めることができました。 今後は、よりサービスを向上させていくと同時に、たくさんの知識をつけていきたいと思っています。 今後のサービス向上のため、誤っている箇所やおかしいと思う箇所がございましたら、コメントの方でご指導願います。 質問に関しては、コメントの方にいただければ出来る限り返答したいと思っておりますので、ご気軽にコメントしていただければと思います。 最後まで読んでくださりありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon VPCを利用したネットワークの構築方法

AWSの学習にこれから取り組む者です。 「Amazon Web Services 基礎からのネットワーク&サーバー構築」 という書籍を参考に、「Amazon VPC」というサービスを使ってネットワークを構築する方法を学びましたので、アウトプットしたいと思います。 (AWSのサインアップ手順については省略します) また、実際にネットワークを構築した後の様子を撮って解説しているため、少し紛らわしいかもしれません。ご了承ください  VPC(仮想ネットワーク)領域の作成 [手順1] AWSにサインインし、VPCを開く。 一番上の検索バーから「VPC」と入力すると出てきます。 VPCを開くと以下の画像のような画面が表示されます。 [手順2] リージョンを設定する。 画面右上のメニューから、VPCの操作対象とするリージョンを選択します(今回は東京リージョンを選択)。 ここで用語を少し解説↓ ・リージョンとは? → 全世界に22箇所存在するデータセンター群のこと。「東京リージョン」「オレゴンリージョン」「バージニアリージョン」などがある。 ・データセンターとは? → サーバーを安全に保管するための施設のこと。 ・アベイラビリティゾーンとは? → AWSの各リージョン内に存在するデータセンターのこと。 Amazon VPCやAmazon EC2で仮想的なサーバーやネットワークを構築する際は、「どのリージョンのどのアベイラビリティゾーンにするか」を設定する必要があります。 [手順3] 左メニューの「VIRTUAL PRIVATE CLOUD」下の「VPC」をクリックし、次の画面で「VPCの作成」をクリック。 [手順4] 名前タグとCIDRブロックを入力する (今回は「VPC領域」、「10.0.0.0/16」というCIDRブロックを入力) ここまでがVPC(仮想ネットワーク)領域の作成方法です。 VPCをサブネットに分割(パブリックサブネットの作成) 先ほど作成した「VPC領域」内には、2種類のサブネット(ネットワークの中にあるネットワークのこと)を作ることができます。 パブリックサブネット: インターネットからアクセスすることを目的としたサブネット。 プライベートサブネット: インターネットから乖離したサブネット。社内ネットワークで「経理部のネットワークだけ分けて、他部署からアクセスできないようにしたい!」といった場合に利用されるそう。 今回はパブリックサブネットを作成します。 [手順1] 左のメニューから「サブネット」をクリックし、右上の「サブネットの作成ボタン」をクリックします。 [手順2] VPC ID、サブネット名、CIDRブロックを入力し、「サブネットを作成」をクリックします。 今回は 「VPC ID: 先ほど作成したVPC領域を選択」 「サブネット名: パブリックサブネット」 「CIDRブロック: 10.0.1.0/24」 を入力。 以上により、VPC領域内に「パブリックサブネットを作成しました。 しかし、まだこのパブリックサブネットはインターネットと接続できていません。したがって、インターネットの接続設定を行います。 インターネットに接続する設定 サブネットをインターネットに接続するために、「インターネットゲートウェイ」を用います。 [手順1] 左のメニューからインターネットゲートウェイを作成し、「インターネットゲートウェイの作成」をクリックします。 [手順2] そのまま「作成」をクリックします。 (名前タグに名前を入力すれば、インターネットゲートウェイに名前をつけることもできます。複数のインターネットゲートウェイを作成する際には名前をつけると区別しやすい) [手順2] 作成したインターネットゲートウェイにチェックをつけ、「アクション」をクリック、「VPCにアタッチ」をクリックします。 すると、結びつける先のVPC領域を選択する画面が表示されますので、最初に作成した「VPC領域」を選択し、「アタッチ」をクリックします。 次に、ネットワークにデータを流すための「ルーティング情報(ルートテーブル)」を設定します。 Amazon VPCでルートテーブルを設定 [手順1]ルートテーブルの作成をするために、左メニューから「ルートテーブル」をクリックし、「ルートテーブルの作成」をクリック。 [手順2] 「名前タグ」と「VPC(選択式)」を入力し、「作成」をクリック。 今回は以下を入力します。 「名前: パブリックルートテーブル」 「VPC: 最初に作成したVPC領域」 パブリックサブネットをインターネットに接続する [手順1]作成した「パブリックルートテーブル」にチェックを入れ、「サブネット関連づけ」タブをクリック。 「サブネットの関連づけの編集」をクリックした後、割り当てたいサブネットにチェックを入れて「関連付けを保存」をクリックする。 [手順2] 左メニューから「サブネット」をクリックし、「ルート」タブをクリック。「ルートの編集」をクリックした後、「ルートの追加」をクリック。 「送信先」と「作成したインターネットゲートウェイ」を入力し、「ルートの保存」をクリックする。 今回は 「送信先: 0.0.0.0/0」 「ターゲット: 作成したインターネットゲートウェイを選択(igw-〇〇〇〇)」 を入力。 これで、仮想ネットワークの作成は完了です。 これを下地に、次回は「Amazon EC2を利用した仮想サーバーの作成方法」もアウトプットしていきたいと思います。 ここまで読んでいただき、ありがとうございました。 次回→ Amazon EC2を利用した仮想サーバーの構築方法①(EC2インスタンス作成編)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon S3 Interface型エンドポイント(PrivateLink)のアクセス

1.目的 本記事では、Interface型エンドポイントを用いて、Amazon S3にアクセスする方法を整理する。Interface型エンドポイントを作成するとエンドポイント固有のDNSが作成される。このエンドポイント固有のDNS名はパブリック DNS ドメインから解決できます。 2.作成手順 S3エンドポイントをVPCサービスから作成。タイプをInterface型のものを選択する。セキュリティグループは、要件に合わせて設定する。送信元を絞り、プロトコルHTTPS:443を許可するイメージ。 3.エンドポイントに割り当てられるDNS名の確認 ・Interface型エンドポイントには「リージョン固有のDNSホスト名」と「ゾーンごとのDNSホスト名」が発行される。 ・リージョンDNSホスト名は紐づいている全てのENIのプライベートIPアドレスを返す。ゾーンDNSホスト名は各AZ毎に生成され、そのゾーンにあるENIのプライベートIPアドレスを返す。 試しに、リージョンDNSをVPC内部のサーバから名前解決を試みると、、、 digコマンドの結果 dig vpce-XXXXXXXXXXXXXXXXXXX.s3.ap-northeast-1.vpce.amazonaws.com ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.87.amzn1 <<>> vpce-04fc227a85d14d7d7-8slelhjt.s3.ap-northeast-1.vpce.amazonaws.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2612 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;vpce-04fc227a85d14d7d7-8slelhjt.s3.ap-northeast-1.vpce.amazonaws.com. IN A ;; ANSWER SECTION: vpce-04fc227a85d14d7d7-8slelhjt.s3.ap-northeast-1.vpce.amazonaws.com. 60 IN A 172.31.48.202 vpce-04fc227a85d14d7d7-8slelhjt.s3.ap-northeast-1.vpce.amazonaws.com. 60 IN A 172.31.49.113 vpce-04fc227a85d14d7d7-8slelhjt.s3.ap-northeast-1.vpce.amazonaws.com. 60 IN A 172.31.50.240 たしかに、Private IPを返している。VPC外部(というかAWS外部)からnslookupを実施しても同様の結果が得られた。具体的には、ここのサイトを利用した。 nslookupの名前解決の結果 Server: (当社Dnsサーバ) Address: 157.65.26.10#53 Non-authoritative answer: Name: vpce-XXXXXXXXXXXXXX.s3.ap-northeast-1.vpce.amazonaws.com Address: 172.31.50.240 Name: vpce-XXXXXXXXXXXXXX.s3.ap-northeast-1.vpce.amazonaws.com Address: 172.31.48.202 Name: vpce-XXXXXXXXXXXXXX.s3.ap-northeast-1.vpce.amazonaws.com Address: 172.31.49.113 ちなみに、VPC内部からの名前解決は、VPCを構築した際に払い出されるAmazonProvidedDNS(VPC のネットワークアドレス +2 の IPアドレスを持つ。)によって実行される。VPC内部のEC2インスタンスから、以下コマンドを叩くことで確認できる。 providedDNSの確認 cat /etc/resolv.conf options timeout:2 attempts:5 ; generated by /sbin/dhclient-script search ap-northeast-1.compute.internal nameserver 172.31.0.2 4.Interface型エンドポイントを経由したアクセス endpoint-urlオプションでDNS名をつけることでアクセスすることができる。ここではBucket一覧を取得している。 Interface型エンドポイントを用いたアクセス aws s3 --endpoint-url https://bucket.XXXXXXXXXXXX.s3.ap-northeast-1.vpce.amazonaws.com ls 2021-02-17 01:48:26 XXXXXXXXXXXX 2021-02-17 00:24:53 XXXXXXXXXXXX 以上 参考URL 公式ドキュメント クラスメソッドの記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QuickSight on S3 でCURを可視化

QuickSightでCURを可視化する CURは、Cost & Usage Reportsの略で、AWSのコストと使用状況レポートを表します 今回は、AWSのBIサービスQuickSightを使って、CURを可視化します。 事前準備 S3バケット作成 CURのデータを入れるS3バケットを作成します バケット名:demo-report-ue CURの設定 CURのデータをS3に出力するレポート作成を行います。 AWSの管理画面の画面右上のユーザー名をクリックし、"マイ請求書ダッシュボード"をクリックし、左側メニューの"Cost & Usage Reports"をクリックします。 その後、真ん中上部の[レポート作成]をクリックします。 ※この画面ではテスト実行後に画面キャプチャ取得したため、レポートが作成された状態になっていますがご了承ください 1つ目の画面でレポート名に任意の名前を入れ[次へ]をクリックします。 2つ目の画面で、S3バケットを設定します。[設定]をクリックします。 作成したバケット(demo-report-ue)を選択し、[次へ]をクリックします 適用されるバケットポリシーが出力されます。問題なければ"このポリシーが正しいことを確認しました"にチェックを入れ、[保存]をクリックします その他は以下の設定を入れ、[次へ]をクリックします。 ポイントとしては"レポート統合の有効化"でQuickSightを選んでいます。これによって後述するQuickSightのマニフェストファイルが自動作成されます。 レポートパスのプレフィックス:demo 使用量の時間詳細度:時間別 レポートバージョニング:新しいレポートバージョンを作成(画面キャプチャ間違ってますmm) レポートデータ統合の有効化:Amazon QuickSight 次の画面はサマリが出ますので[確認して完了]をクリックします。 S3の操作 作成したバケットに、レポート配信確認用オブジェクト"aws-programmatic-access-test-object"ができてることを確認します。 また、プレフィックスで設定した"demo"のディレクトリが出来ていることを確認します。このdemoのディレクトリはレポートデータが出力されるため、データが出力されるまで作成されません。数時間か一日くらい時間がかかります。 CURが出力されると"demo"ディレクトリが作成され、demo-reportの下にCURデータが入るフォルダと、"QuickSight"という名前のフォルダが出来ます。 "QuickSight"ディレクトリをクリックすると、json形式のマニフェストファイルがあります。これはQuickSightでS3のデータを可視化する際に使うファイルで、可視化するS3上のファイルの位置や形式を記述しています。 このマニフェストファイルの"オブジェクトURLを"コピーしておきます。 QuickSightの操作 QuickSightの初期設定は割愛します。必要なら別途公式ドキュメントを確認ください。 QuickSightが使える状態になったら、データセットを作成します。画面右側メニューの"データセット"をクリックし、画面右上の[新しいデータセット]をクリックします。 "S3"をクリックします。 以下を入力し[接続]をクリックします。 データソース名:Demo-CUR マニフェストファイルのアップロード:先程コピーしたURL 次の画面で[視覚化する]をクリックします。 画面操作でダッシュボードを作っていきます。 QuickSightでダッシュボード作成 このハンズオン資料を参考にダッシュボードを作ります。若干カラム名が違いますが分かると思います。ハンズオン資料はQuickSight+Athenaの想定ですが、今回のQuickSight+S3でもQuickSight上のダッシュボード作成にはさほど違いはありません。 カラム名は以下のように違いがあります line_item_unblendedcost => lineitem/unblendedcost のような"/"を使った形になってる ハンズオンで出てくる計算フィールドはこんな感じ↓ ifelse(split({lineItem/UsageType},':',1) = 'SpotUsage','Spot',ifelse(right(split({product/usagetype},':',1), 8) = 'BoxUsage',{pricing/term},'other')) このようなダッシュボードが出来ます 運用 ※(TODO)後日確認します。 多分、マニフェストファイルは日時なりCURの更新タイミングで更新されます。そのため、QuickSight側もSPICEを定期的に更新する設定をすることで、更新されたマニフェストファイルやデータを取り込み、最新のCURデータの反映が行われます。 参照リンク こちらが公式のナレッジです。 https://aws.amazon.com/jp/premiumsupport/knowledge-center/quicksight-cost-usage-report/ 公式ハンズオン https://www.wellarchitectedlabs.com/cost/200_labs/200_5_cost_visualization/2_create_visualizations/ CTCの方のJAWSの資料「Cost Exploreでは満足できない!」 https://jawsdays2020.jaws-ug.jp/wp-content/uploads/2020/03/CostExplorer%E3%81%A7%E3%81%AF%E6%BA%80%E8%B6%B3%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84.pdf Amazon S3 でのコストおよび使用状況レポートへのアクセス https://docs.aws.amazon.com/ja_jp/cur/latest/userguide/access-cur-s3.html#manifest-cur-files
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

API Gateway でコンソールからAuthorizationヘッダーを付与してリクエスト送る方法

書き方 API Gatewy のコンソール、ヘッダーの入力欄から{}なしでヘッダーに下記のようにコロン区切りで記載する Authorization:Bearer eyJhbGciOiJSU....aAWDvT6g ヘッダーを付与するとこんな感じになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DynatraceのLog Monitoring v2を使ってAWSのログを監視してみる

はじめに Dynatraceで新しく導入されたLog Monitoring v2を利用することで様々なテクノロジーからログを取り込むことができるようになります。 本記事では、このLog Monitoring v2を利用してAWS Cloudwatch Logsの取得を試してみます。 通常のホストのログやAWS以外にも以下のアーキテクチャに対応しています。 オープンソースのフレームワーク(FluentDやLogstash) Kubernetesのログやイベント クラウドプロバイダ(AWS、GCP、Microsoft Azure、Red Hat OpenShift) その他 様々なデバイスやクラウドプロバイダ自身がログを生成しますが、個別にログ監視するのは非常に手間がかかります。Dynatraceのような監視ツールを使うことで以下のようなメリットが生まれます データを一元管理できる。わざわざ個別のデバイスにログインすることなくログの確認が可能 問題発生時に障害が発生したホストだけでなく周辺装置のログ情報も同時に確認可能 Dynatraceでは15日間の無料トライアルを利用することができるので、自分の環境でも簡単に試してみることができます。 Dynatraceフリートライアル 参考URL Dynatraceの公式サイトに必要な情報がまとまっています。 Set up AWS log forwarding | Dynatrace Documentation Log Monitoring v2 | Dynatrace Documentation dynatrace-oss/dynatrace-aws-log-forwarder: AWS log forwarding allows you to stream logs from AWS CloudWatch into Dynatrace logs 前提条件 ログを転送するのに、ActiveGateを経由する必要があります。本手順ではActiveGateはすでに構築済みとして進めますが、インストールスクリプトを実行する際にActiveGateを自動で構築することも可能です。 また、LambdaからActiveGateへアクセスできる必要があるため、ActiveGateの/var/lib/dynatrace/gateway/config/custom.propertiesに以下の設定を追加し、プロセスの再起動を実施します。また、セキュリティグループでTCP: 9999をフルオープンにする必要がございます。 /var/lib/dynatrace/gateway/config/custom.properties [connectivity] dnsEntryPoint = https://パブリックDNS名:9999 プロセス再起動 sudo systemctl restart dynatracegateway.service 設定手順 API Token の発行 ログをアップロードするために必要なAPIの発行を行います。 Dynatrace GUI上のSettings > Integration > Dynatrace APIを選びます。 Type a token nameフィールドにトークン名を入力し、Ingest logsを有効にします。 Generateボタンをクリックすると、トークンが発行されるので、忘れずにパスワードマネージャなどに保存します。 再表示はできないため、保存を忘れた場合は、再度トークンを発行する必要があります。 デプロイ 必要なポリシーの確認 CloudFormationにより、ログ取得に必要な設定は自動で実行されますが、AWS CLIを実行する端末に以下のポリシーが割り当てられている必要があります。 CloudFormation実行に必要なポリシー { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "cloudformation:CreateChangeSet", "cloudformation:ExecuteChangeSet", "cloudformation:DescribeChangeSet", "cloudformation:DescribeStacks", "s3:CreateBucket", "s3:PutLifecycleConfiguration", "iam:GetRole", "iam:CreateRole", "iam:AttachRolePolicy", "iam:PutRolePolicy", "iam:GetRolePolicy", "iam:PassRole", "lambda:CreateFunction", "lambda:UpdateFunctionCode", "lambda:GetFunction", "lambda:GetFunctionCodeSigningConfig", "cloudwatch:PutDashboard", "cloudwatch:GetDashboard", "firehose:DescribeDeliveryStream", "firehose:CreateDeliveryStream", "firehose:ListTagsForDeliveryStream", "logs:DeleteSubscriptionFilter", "logs:DescribeLogGroups", "logs:PutSubscriptionFilter" ], "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "kms:Decrypt", "kms:Encrypt", "kms:DescribeKey", "kms:CreateGrant" ], "Resource": "*", "Condition": { "ForAnyValue:StringEquals": { "kms:ResourceAliases": "aws/lambda" } } } ] } 環境変数の設定 TARGET_URL=https://<ActiveGate のパブリックDNS名>:9999/e/<DynatraceのテナントID> TARGET_API_TOKEN=<先ほど発行した_API_token> REQUIRE_VALID_CERTIFICATE=false インストールスクリプトの実行 wget -O dynatrace-aws-log-forwarder.zip https://github.com/dynatrace-oss/dynatrace-aws-log-forwarder/releases/latest/download/dynatrace-aws-log-forwarder.zip \ && unzip -qo dynatrace-aws-log-forwarder.zip \ && ./dynatrace-aws-logs.sh deploy --target-url $TARGET_URL --target-api-token $TARGET_API_TOKEN --use-existing-active-gate true --require-valid-certificate $REQUIRE_VALID_CERTIFICATE dynatrace-aws-logsというスタック名でCloudFormationが実行されます。 ロググループの購読 CloudWatchのロググールプからDynatraceへ送りたいロググループを登録します。 ここではテスト試しに/aws/lambda/testFuncのログを登録してみます。 以下のコマンドを実行することで、ロググループの購読が開始されます。 ./dynatrace-aws-logs.sh subscribe --log-groups /aws/lambda/testFunc ログの確認 CloudWatchに新しいログが出力されるとDynatrace側にも該当ログが送られます。 DynatracenのLog Viewer AWS CloudWatchログのログイベント まとめ 本記事ではDynatraceで新しく導入されたLog Monitoring v2を使用してAWSのCloudWatchのログをDynatrace側で取得できる方法についてまとめました。 コンテナ環境のログなども含めてログの管理を一元化できるのは大きなメリットがありますので、ぜひ試してみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】rsync(lsyncd)によるサーバー間同期での冗長化はベストプラクティスではない?

はじめに Webサーバー2台をrsyncで同期して冗長化 ALBでWebサーバーへのアクセスは振り分け Webサーバー1にデプロイするとWebサーバー2にも同期される という設計を見たことがあり、自分もこの設計でインフラを構築したことがあるのですが、色々勉強して、この設計は悪いとまではいかないもののベストプラクティスではないのではないか? という考えに変わりました。 共有です。 この構築の問題点 rsync(lsyncd)の設定や動作状況確認が面倒、トラブルのもと デプロイ時にダウンタイムが生じる 同期の目的がgit管理されたソースコードと、ユーザーによって作られたgit管理されていないファイルの複製であるとするならば、前者はともかく後者の存在がかなり厄介 片方向の同期(Webサーバー1→Webサーバー2へ同期される設定)だった場合、Webサーバー2にユーザーによって重要なファイルが作られてしまったら大変。ユーザーが次にアクセスした際にWebサーバー1を参照してしまうと……? スティッキーセッション(ユーザーの参照先サーバーを一定期間固定する機能)で対応するのも限度がある。 双方向同期設定はもっと厄介。 じゃあどうするの Webサーバー1とWebサーバー2は同期しない アプリケーションは要するに「同じソースコードがWebサーバー1でもWebサーバー2でも動けば良い」という設計にする。ユーザーが生成するファイルがサーバー内で永続化するような設計はよろしくない。永続化するならDBやS3へ。 デプロイは2台に順次デプロイするような設定にする。CodeDeployでローリングデプロイ等の設定をすれば良い。 ダウンタイムも避けられます まとめ AWSの場合は「冗長化のためにrsyncを使う」という機会はかなり限られそう。少なくとも今の自分には思いつかないです。 何かご意見あればコメントください。 ではまた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LWCでAWS側S3と連携する方法

1.目的 今回LWC中にAWSのSDKでS3と連携する方法を共有します。 2.前提 ➀AWS側S3バケットCross-Origin Resource Sharing (CORS)の設定 [ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "HEAD", "GET", "PUT", "POST", "DELETE" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [ "ETag" ] } ] ➁Salesforce側静的リソースにAWSのSDKをアップロード ➂Salesforce側CSP 信頼済みサイトの設定 3.ソース構成図 lwc ├─fileuploadMock ├─fileuploadModal ├─progressbar └─utils fileuploadMock fileuploadMock.css .container { background-color: #fff; min-height:100%; } .wrapper { background-color: #cecece; overflow: scroll; width: 100%; } fileuploadMock.html <template> <template if:true={loading}> <lightning-spinner alternative-text="Loading" size="medium"></lightning-spinner> </template> <c-progressbar upload-file-name={uploadFileName} progress={progress} onabort={Abort}> </c-progressbar> <c-fileupload-modal title="ファイル追加" onselect={uploadHandler} onfolderchange={folderchangeHandler}></c-fileupload-modal> <lightning-card> <div class="slds-p-horizontal_small"> <div class="slds-form"> <div class="slds-form__row"> <div class="slds-form__item"> <button class="slds-button slds-button_brand" onclick={fileSelectorHandler}>ファイル追加</button> </div> </div> </div> </div> <div slot="footer"> <lightning-datatable hide-checkbox-column key-field="key" columns={columns} data={objectlist} onrowaction={handleRowAction}> </lightning-datatable> </div> </lightning-card> </template> fileuploadMock.js import { LightningElement, track } from 'lwc'; import { NavigationMixin } from 'lightning/navigation'; import { loadScript } from 'lightning/platformResourceLoader'; import AWS_SDK from '@salesforce/resourceUrl/aws_sdk'; import { showToast, dateFormat, fileSizeUnit } from 'c/utils'; const bucketName = "bucket-name";//バケット名 const region = "ap-northeast-1";//地域 const accessKeyId = "accessKeyId ";//アクセスID const secretAccessKey = "secretAccessKey";//アクセスキー export default class FileuploadMock extends NavigationMixin(LightningElement) { //ファイル非活性 @track fileDisable; @track datas; @track objectlist = []; @track folder; @track loading; @track uploadFileName; @track progress; /** * 初期化AWS */ async initAWS() { AWS.config.update({ region: region, accessKeyId: accessKeyId, secretAccessKey: secretAccessKey }); this.s3 = new AWS.S3({ apiVersion: "2006-03-01", params: { Bucket: bucketName } }); await this.listObjects(); } /** * ファイルアップロード * @param {*} event */ async uploadHandler(event) { let input = event.detail; let files = input.files; if (files.length > 0) { try { // let result = await this.upload(files[0]); let result = await this.managedUpload(files[0], (progress) => { this.uploadFileName = files[0].name; this.progress = Math.floor(progress.loaded / progress.total * 100); this.template.querySelector('c-progressbar').open(); }); // console.log(result); this.template.querySelector('c-progressbar').close(); await this.listObjects(); showToast(this, '', '成功にアップロードしました', 'success'); } catch (err) { showToast(this, '', err.message, 'error'); console.error("Error:", err); } } } /** * ファイルアップロードキャンセル */ async Abort() { await this.request.abort(); } /** * ファイルダウンロード * @param {*} event */ async fileDownload(fileKey) { try { this.loading = true; await this.downloadFile(fileKey); } catch (err) { showToast(this, '', err.message, 'error'); console.error("Error:", err); } finally { this.loading = false; } } /** * ファイル削除 * @param {string} fileKey */ async deleteFile(fileKey) { try { this.loading = true; await this.deleteObject(fileKey); await this.listObjects(); showToast(this, '', '成功に削除しました', 'success'); } catch (err) { showToast(this, '', err.message, 'error'); console.error("Error:", err); } finally { this.loading = false; } } /** * ファイルリスト取得 */ async listObjects() { let data = await this.s3.listObjects().promise(); console.log(data); this.objectlist = []; data.Contents.forEach(e => { let key = e.Key; let folder; let fileName; if (e.Size === 0) return; if (key.lastIndexOf('/') > -1) { fileName = key.substring(key.lastIndexOf('/') + 1, key.length); folder = './' + key.replace(fileName, ''); } else { folder = './'; fileName = key; } let fileType = fileName.split('.')[1]; this.objectlist.push({ key: key, folder: folder, fileName: fileName, fileType: fileType, LastModified: dateFormat(e.LastModified, 'YYYY/mm/dd HH:MM:SS'), Owner: e.Owner.DisplayName, Size: fileSizeUnit(e.Size), StorageClass: e.StorageClass }) }); } /** * ファイル取得処理 * @param {string} fileKey キー * @param {string} fileName ファイル名 */ async downloadFile(fileKey) { let url = await this.getSignedUrlPromise('getObject', { Bucket: bucketName, Key: fileKey, Expires: 1 }); console.log(url); window.location.href = url; } /** * オブジェクト取得 * @param {*} fileKey キー */ getObject(fileKey) { return this.s3.getObject({ Key: fileKey }).promise(); } /** * ファイル保存処理 * @param {File(blob)} file ファイル */ putObject(file) { const { folder } = this; let fileName = file.name; let fileKey; if (folder || folder === 0) fileKey = `${folder}/${fileName}`; else fileKey = fileName; return this.s3.putObject({ Key: fileKey, Body: file }).promise(); } /** * ファイル削除処理 * @param {string} fileKey ファイルキー */ deleteObject(fileKey) { return this.s3.deleteObject({ Key: fileKey }).promise(); } /** * ファイル保存処理(ビッグサイズ用) * @param {File(blob)} file ファイル */ upload(file) { const { folder } = this; let fileName = file.name; let fileKey; if (folder || folder === 0) fileKey = `${folder}/${fileName}`; else fileKey = fileName; return this.s3.upload({ Key: fileKey, Body: file }).promise(); } /** * URL発行 * @param {*} action アクション:getObject,putObject,deleteObject * @param {*} fileKey ファイルキー */ getSignedUrlPromise(action, params) { return this.s3.getSignedUrlPromise(action, params); } /** * マルチファイルアップロード管理 * @param {*} file */ managedUpload(file, progressCallBack) { const { folder } = this; let fileName = file.name; let fileKey; if (folder || folder === 0) fileKey = `${folder}/${fileName}`; else fileKey = fileName; this.request = new AWS.S3.ManagedUpload({ partSize: 100 * 1024 * 1024, queueSize: 1, params: { Bucket: bucketName, Key: fileKey, Body: file } }); this.request.on('httpUploadProgress', (progress) => { if (progressCallBack) progressCallBack(progress); else console.log('progress:', Math.floor(progress.loaded / progress.total * 100)); }); this.request.send((err, data) => { if (err) console.error(err); console.info(data); }); return this.request.promise(); } /** * ファイル選択 * @param {*} event */ fileSelectorHandler(event) { event.preventDefault(); this.template.querySelector('c-fileupload-modal').open(); } /** * フォルダ選択 * @param {*} event */ folderchangeHandler(event) { this.folder = event.detail; } /** * RowAction * @param {*} event */ async handleRowAction(event) { const action = event.detail.action; const row = event.detail.row; switch (action.name) { case 'download': await this.fileDownload(row.key); break; case 'delete': await this.deleteFile(row.key); break; } } /** * 初期化 */ connectedCallback() { this.columns = [ { label: 'フォルダー名', fieldName: 'folder' }, { label: 'ファイル名', fieldName: 'fileName', }, { label: 'タイプ', fieldName: 'fileType' }, { label: '最新更新日', fieldName: 'LastModified', }, { label: '所有者', fieldName: 'Owner', }, { label: 'サイズ', fieldName: 'Size', }, { label: 'ストレージクラス', fieldName: 'StorageClass', }, { type: 'action', typeAttributes: { rowActions: [ { label: 'ダウンロード', name: 'download' }, { label: '削除', name: 'delete' } ], menuAlignment: 'auto' } } ]; } /** * aws-sdkロード */ renderedCallback() { if (this.jsinit) return; this.jsinit = true; Promise.all([ loadScript(this, AWS_SDK), ]) .then(async() => { await this.initAWS(); }) .catch(error => { showToast(this, 'JSライブラリロードに失敗しました', error.message, 'error') }); } } fileuploadMock.js-meta.xml <?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>52.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__Tab</target> </targets> </LightningComponentBundle> fileuploadModal fileuploadModal.html <template> <!--Use template if:true to display/hide popup based on isModalOpen value--> <template if:true={_isModalOpen}> <!-- Modal/Popup Box LWC starts here --> <section role="dialog" tabindex="-1" aria-modal="true" class="slds-modal slds-fade-in-open" style="z-index:9001"> <div class="slds-modal__container" style="width: auto;max-width: fit-content;"> <!-- Modal/Popup Box LWC header here --> <header class="slds-modal__header"> <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={close}> <lightning-icon icon-name="utility:close" alternative-text="close" variant="inverse" size="small"> </lightning-icon> <span class="slds-assistive-text">Close</span> </button> <h2 class="slds-text-heading_medium slds-hyphenate">{title}</h2> </header> <!-- Modal/Popup Box LWC body starts here --> <div class="slds-modal__content slds-p-around_medium" style="height:50%"> <lightning-input label="パス" name="path" onchange={commonChange}></lightning-input> <lightning-input type="file" label="ファイルアップロード" onchange={uploadHandler}> </lightning-input> </div> <!-- Modal/Popup Box LWC footer starts here --> <footer class="slds-modal__footer"> <button class="slds-button slds-button_neutral" onclick={close}>キャンセル</button> <!-- <button class="slds-button slds-button_brand" onclick={confirmHandle}>ファイル追加</button> --> </footer> </div> </section> <div class="slds-backdrop slds-backdrop_open"></div> </template> </template> fileuploadModal.js import { LightningElement, track, api } from 'lwc'; export default class FileUploadModal extends LightningElement { @api name; @track path; //表示フラグ @track _isModalOpen; /** * 共通Change処理 * @param {*} event */ commonChange(event) { let name = event.target.name; let value = event.target.value; this[name] = value; this.dispatchEvent(new CustomEvent("folderchange", { detail: value, composed: true, bubbles: true, cancelable: true, })); } /** * ファイルアップロード * @param {*} event */ uploadHandler(event) { let changenEvent = new CustomEvent("select", { detail: event.target, composed: true, bubbles: true, cancelable: true, }); this.dispatchEvent(changenEvent); } /** * モーダル開く */ @api open() { this._isModalOpen = true; } /** * モーダル閉じる */ close(e) { e.preventDefault(); this._isModalOpen = false; } } fileuploadModal.js-meta.xml <?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>52.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle> progressbar progressbar.html <template> <template if:true={isShow}> <section role="dialog" tabindex="-1" class="slds-modal slds-fade-in-open" aria-modal="true" style="z-index:9002"> <div class="slds-modal__container" style="width: auto;max-width: 50rem;"> <header class="slds-modal__header"> <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={cancel}> <lightning-icon icon-name="utility:close" alternative-text="close" variant="inverse" size="small"> </lightning-icon> <span class="slds-assistive-text">Close</span> </button> <h2 class="slds-modal__title slds-hyphenate">ファイルをアップロード</h2> </header> <div class="slds-modal__content slds-p-around_medium" style="display: grid;grid-template-columns: 0.5fr 3fr 3fr 0.5fr; height: 5rem;overflow-y: hidden;"> <div style="align-self: center;"> <span class="slds-icon_container slds-icon-doctype-xml"> </span> </div> <div style="align-self: center;"> <span>{uploadFileName} <br /><b>{progress}%</b></span> </div> <div class="slds-progress-bar slds-progress-bar_circular" style="align-self: center;height: 0.6rem;width: 20rem;"> <span class="slds-progress-bar__value" style={barStyle}></span> </div> <div style="align-self: center;margin-left: 0.2rem;"> <span class={barClass}> </span> </div> </div> <footer class="slds-modal__footer"> <span style="float: left;"></span> <button class="slds-button slds-button_brand" onclick={cancel}>キャンセル</button> </footer> </div> </section> <div class="slds-backdrop slds-backdrop_open"></div> </template> </template> progressbar.js import { LightningElement, track, api } from 'lwc'; const bar_cancel_class = 'slds-icon_container slds-icon_container_circle slds-icon-action-description slds-icon-standard-password'; const bar_success_class = 'slds-icon_container slds-icon_container_circle slds-icon-action-description slds-icon-text-success'; // const approval_flag = myResource + 'action-sprite/svg/symbols.svg#approval'; // const remove_flag = myResource + 'action-sprite/svg/symbols.svg#remove'; export default class Fileupload extends LightningElement { @api uploadFileName; @api progress = 0; @track isShow; /** * ProgressBar */ get barStyle() { return `width:${this.progress}%`; } get barClass() { return this.progress >= 100 ? bar_success_class : bar_cancel_class; } /** * キャンセル */ cancel(e) { e.preventDefault(); this.dispatchEvent(new CustomEvent('abort', { detail: true })); this.close(); } @api close() { this.isShow = false; } @api open() { this.isShow = true; } } progressbar.js-meta.xml <?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>52.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle> utils utils.js import { ShowToastEvent } from 'lightning/platformShowToastEvent'; /** * メッセージ表示 * @param {window} that * @param {string} title タイトール * @param {string} message メッセージ * @param {string} variant タイプ info、success、warning、error */ export const showToast = (that, title, message, variant) => { const event = new ShowToastEvent({ title: title, message: message, variant: variant, }); that.dispatchEvent(event); } /** * デートフォマート * @param {Date} date date * @param {string} fmt format * @returns {string} StringDate */ export const dateFormat = (date, fmt = 'YYYY/mm/dd') => { let ret; const opt = { 'Y+': date.getFullYear().toString(), // 年 'm+': (date.getMonth() + 1).toString(), // 月 'd+': date.getDate().toString(), // 日 'H+': date.getHours().toString(), // 時 'M+': date.getMinutes().toString(), // 分 'S+': date.getSeconds().toString() // 秒 }; for (let k in opt) { ret = new RegExp('(' + k + ')').exec(fmt); if (ret) { fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, '0'))) }; }; return fmt; } /** * YYYY/MM/DD⇒Mon Nov 27 2017 20:30:00 GMT+0900 (JST)に変換 * @param {string} dataStr stringDate * @returns {Date} Date */ export const datePrase = (dataStr) => { return new Date(dataStr); } /** * デートフォマート * @param {string} date strData * @param {string} fmt format * @returns {string} StringDate */ export const strDateFormat = (strData, fmt = 'YYYY/mm/dd HH:MM:SS') => { return dateFormat(datePrase(strData), fmt); } /** * ファイルサイズ変換 * @param {*} size バイト * @returns 変換後のサイズ */ export const fileSizeUnit = (size) => { // 1 KB = 1024 Byte const kb = 1024 const mb = Math.pow(kb, 2) const gb = Math.pow(kb, 3) const tb = Math.pow(kb, 4) const pb = Math.pow(kb, 5) const round = (size, unit) => { return Math.round(size / unit * 100.0) / 100.0 } if (size >= pb) { return round(size, pb) + 'PB' } else if (size >= tb) { return round(size, tb) + 'TB' } else if (size >= gb) { return round(size, gb) + 'GB' } else if (size >= mb) { return round(size, mb) + 'MB' } else if (size >= kb) { return round(size, kb) + 'KB' } return size + 'バイト' } utils.js-meta.xml <?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>52.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle> 4.Salesforce側動作確認 ➀Salesforce側Lightning コンポーネントタブを作成 ➁タブを開く ➂ファイル追加 ➃ファイルダウンロード ➄ファイル削除 5.参考 ➀AWS-SDK: https://github.com/aws/aws-sdk-js ➁S3のCORSの設定:https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/ManageCorsUsing.html ➂LWC Platform Resource Loader:https://developer.salesforce.com/docs/component-library/bundle/lightning-platform-resource-loader/documentation ➃AWS-SDK使い方:https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IPv4

172.12.1.0/25 172.12.1.0 -172.12.1.127 172.12.1.128/25 172.12.1.128 - 172.12.1.255 /24 : 0 - 255 /25 : 0 - 127 /26 : 0 - 63 /27 : 0 - 31 /28 : 0 - 15 /29 : 0 - 7 /30 : 0 - 3 /31 : 0 - 1 /32 : 0 - 0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Elastic Load Balancing のまとめ

概要 Elastic Load Balancing (ELB) はトラフィックの負荷分散のサービス。例えば、Webサーバーとして機能するEC2インスタンスが複数台あり、それらへアクセスを分散させて安定稼働を図りたい場合等に用いられる。アクセスが割り当てられる先をターゲットという。リスナーにはListenするプロトコルとポート番号、ターゲットへの接続用のプロトコルとポート番号等を設定する。 また、ELBは自動的にスケールするため、ロードバランサ自体の冗長構成はユーザーは気にしなくて良い。ただしAZ内での冗長化のため、マルチAZ構成にするにはAZ毎にELBを設定する必要がある。ALB, CLBに関してはスケール時にIPアドレスが変化するので、基本的にDNS名を用いたアクセスを行うことが推奨されている。 現在、AWSではNLBかALBの選択が推奨されている。 機能 Health Check 設定値(プロトコル、ポート、パス、タイムアウト時間、正常の閾値、非正常の閾値、間隔、成功コード)に基づいてターゲットに対してヘルスチェックを行う。正常なターゲットに対してトラフィックをルーティングする。 ※ 正常/非正常の閾値・・・正常/非正常を判定するまでに必要なヘルスチェックの連続成功/失敗回数 Sticky Sessions 同じユーザーから来たリクエストを同じインスタンスに送信する。アプリケーション内でセッション管理する場合等に用いる。デフォルトでは無効になっている。HTTP, HTTPSでのみ利用可能。 Connection Draining バックエンドのインスタンスをELBから登録解除、またはヘルスチェックが失敗した際に機能する。そのような事象が起きた際には、新規のリクエストの割り振りは中止し、処理中のリクエストはリクエストが終了するまで一定時間待機する。デフォルトで300秒、最大3600秒の設定ができる。 SSL/TLS Termination ELB側でSSL/TLS認証を行う機能。クライアント、ELB、バックエンドインスタンス間で通信を分割することができる。例えば、ELBにはHTTPSでアクセスし、ELB-バックエンドインスタンス間はHTTPでアクセスする等。 モニタリング CloudWatchによりELBメトリクス(HealthyHostCount, RequestCount, Latency, HTTPCode_ELB_XXX, HTTPCode_Backend_XXX, BackendConnectionErrors, SurgeQueueLength, SpilloverCount...)を60秒間隔で監視できる。 ポートへの負荷分散 単一インスタンス内の複数ポートに対して負荷分散する機能。コンテナへの負荷分散等に適する。 クロスゾーン負荷分散 AZ毎にインスタンス数が不均一であったとしても、それぞれのインスタンスの負荷が均一化されるように分散される機能。 コンテンツベースルーティング ALBで利用可能な機能。HTTPヘッダ内の情報、クエリ文字列等に基づいてトラフィックを割り振ることができる。 3種のロードバランサーの比較 NLB ALB CLB どのレイヤで機能するか 4 7 4/7 IPアドレス 静的(EIPの使用も可) 動的 動的  セキュリティグループ なし (※1) あり あり コネクションタイムアウト値 360秒 1-4000秒(デフォルト60秒) 1-4000秒(デフォルト60秒) リスナーのプロトコル TCP, TLS, UDP, TCP_UDP HTTP, HTTPS HTTP, HTTPS, TCP, SSL ルーティングアルゴリズム フローハッシュアルゴリズム ラウンドロビン ラウンドロビン(TCP), The least outstanding requests routing algorithm (HTTP/HTTPS) クロスゾーン負荷分散のデフォルト設定 無効 有効 有効 暖気運転 (※2) 不必要 必要 必要 ポートに対する負荷分散 ○ ○ × バックエンドインスタンスのIPアドレス指定 ○ ○ × スティッキーセッション × ○ ○ コンテンツベースルーティング × ○ × (※1) NLB自体にはセキュリティグループの設定がない。そのためNLBのセキュリティグループIDをターゲット側のセキュリティグループで設定することができない。したがって、ターゲットインスタンスのセキュリティグループでクライアントからのインバウンドを許可する必要がある。 (※2) 暖気申請はBussiness/Enterpriseのサポートが必要。 その他留意事項 ALB, CLBにおいてHTTP/HTTPSリスナーを用いた場合は、設定しない限りクライアントIPを取得しない。アプリケーション内でクライアントIPが必要となる場合には、X-Forwarder-Forヘッダを使用して、ヘッダ内でクライアントIP情報をバックエンドインスタンスへ渡す。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS IoT] 証明書の作成・登録方法 Part3 JITR (Just In Time Regstration)

はじめに 前回の記事ではJITPによる証明書の作成・登録方法を試してみました。 上の表の分類で、JITPと同じく、Amazon以外のCAで発行した証明書を用いて、デバイスからの初回アクセス時に証明書の発行と事前登録を行うJust In Time Registration(JITR)について今回は試してみました。JITRとJITPの主な違いは、JITPは事前に作成したテンプレートをもとにしてプロビジョニングを行うのに対して、JITRはLambda関数を用意してプロビジョニングを行う、という違いになります。そのため、JITRの手順の前半はJITPと共通になります。 Just In Time Registration それでは試してみたいと思います。 CA証明書と検証証明書の作成 (ここはJITPの手順と同じです) まず、CA証明書と検証証明書をを作成する必要があります。CA証明書はOpenSSLのコマンドで作成することができます。 CA証明書を作成 $ openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem # 適宜入力 ----- Country Name (2 letter code) []:JP State or Province Name (full name) []:Tokyo Locality Name (eg, city) []:Tokyo Organization Name (eg, company) []:MyOrg Organizational Unit Name (eg, section) []:MyUnit Common Name (eg, fully qualified host name) []:RootCA Email Address []:hogehoge AWS IoT registration code を取得 $ aws iot get-registration-code { "registrationCode": "017102e221eb356519.....(中略)" } 検証証明書のキーペアを作成 $ openssl genrsa -out verificationCert.key 2048 検証証明書のCSRを作成 (Common Nameに registration codeを入力) $ openssl req -new -key verificationCert.key -out verificationCert.csr Country Name (2 letter code) []:JP State or Province Name (full name) []:JP Locality Name (eg, city) []:Tokyo Organization Name (eg, company) []:MyOrg Organizational Unit Name (eg, section) []:MyOU Common Name (eg, fully qualified host name) []:017102e221eb356519 ......(中略) Email Address []: CSRから検証証明書を作成 $ openssl x509 -req -in verificationCert.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out verificationCert.crt -days 500 -sha256 AWS IoT CoreにCA証明書を登録 aws iot register-ca-certificate --ca-certificate rootCA.pem --verification-cert verificationCert.crt 登録すると、CA証明書のCertificateIDが表示されるので、登録したCA証明書をACTIVEに設定します。 aws iot update-ca-certificate --certificate-id <CertificateID> --new-status ACTIVE デバイス証明書の自動登録を有効化します。 aws iot update-ca-certificate --certificate-id <CertificateID> --new-auto-registration-status ENABLE IoT Ruleの設定とLambda関数の設定 JITRでは以下の図のように、IoT RuleとLambda関数を使用して証明書をACTIVEに設定し、Policyの作成、モノの作成と証明書のアタッチ等を行います。 IoTCoreではデバイス証明書の自動登録が有効化されると、新しいデバイスが初回接続された場合に、AWSの予約Topic $aws/events/certificates/registered/<caCertificateID> に対してMQTTメッセージがPublishされます。 このメッセージのフォーマットは { "certificateId": "certificateID", "caCertificateId": "caCertificateId", "timestamp": timestamp, "certificateStatus": "PENDING_ACTIVATION", "awsAccountId": "awsAccountId", "certificateRegistrationTimestamp": "certificateRegistrationTimestamp" } のようなフォーマットとなっています。このメッセージをルールエンジン経由でLambda関数に渡し、Lambda関数の中で証明書の有効化やPolicyの作成を行います。 まずはLambda関数を作成します。Lambdaのマネジメントコンソールから関数の作成をクリックし、Lambda関数を作成します。ここではPythonにて作成しました。 import json import boto3 import sys IOT = boto3.client('iot') POLICY_NAME = 'My_IoT_Policy' REGION = 'ap-northeast-1' THINGNAME = 'MyTestThing0002' def attach_Policy(awsID, CertID): CertificateARN = 'arn:aws:iot:'+ REGION + ':' + awsID + ':cert/' + CertID try: IOT.attach_principal_policy( policyName = POLICY_NAME, principal = CertificateARN ) except Exception as e: print(e.message) raise def activate_Cert(ID): try: IOT.update_certificate( certificateId = ID, newStatus = 'ACTIVE' ) except Exception as e: print(e.message) raise def create_Thing(): try: IOT.create_thing( thingName = THINGNAME ) except Exception as e: print(e) raise def attach_Thing( awsID, CertID): CertificateARN = 'arn:aws:iot:'+ REGION + ':' + awsID + ':cert/' + CertID try: IOT.attach_thing_principal( thingName=THINGNAME, principal=CertificateARN ) except Exception as e: print(e.message) raise def lambda_handler(event, context): # just in time event structure #{ # "certificateId": "<certificateID>", # "caCertificateId": "<caCertificateId>", # "timestamp": "<timestamp>", # "certificateStatus": "PENDING_ACTIVATION", # "awsAccountId": "<awsAccountId>", # "certificateRegistrationTimestamp": "<certificateRegistrationTimestamp>" #} awsID = event['awsAccountId'] certID = event['certificateId'] caCert = event['caCertificateId'] print("awsID:"+ awsID) print("certID:"+ certID) print("caCert:"+ caCert) try: print('attach_poclicy') attach_Policy(awsID, certID) print ('activate_Cert') activate_Cert(certID) print ('create_Thing') create_Thing() print ('attach_Thing') attach_Thing(awsID, certID) except Exception as e: print('Error on Lambda') raise return すでに作成済みのデバイス用のPolicyがあったので、Policyを証明書にアタッチし、証明書をアクティベートし、モノを作成し、証明書をモノにアタッチしています。モノの名前やPolicyの名前は簡単のため決め打ちで行いました。本当であれば、デバイスから送られてくる情報からモノの名前がつけられるとよいのですが(JITPの場合にはCommon Nameにつけられましたよね)MQTTで上がってくる情報にそのような情報が含まれていなかったので、そのようなことをやりたい場合には別途デバイスから取得する必要がありそうです。Lambda関数の実行のPermissionを管理するロールをIAMにて作成します。以下のようなPolicyを作成してロールにアタッチしました。 { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "iot:*", "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:CreateLogGroup", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" } ] } 次に、MQTTメッセージをLambdaに渡すIoT Ruleを作成します。IoT CoreのACT>ルールから作成を選択し、以下のルールクエリでルールを作成します。 SELECT * FROM '$aws/events/certificates/registered/<caCertificateID>' アクションはLambda関数を呼び出し、を選択し先程作成したLambda関数を指定します。 これにて準備は完了です。 デバイスからの接続 まずは、先程作成したCAを使ってデバイス証明書を作成します。 まず、キーを作成。 openssl genrsa -out deviceCert.key 2048 CSRを作成 openssl req -new -key deviceCert.key -out deviceCert.csr プロンプトで以下のように適宜入力 ----- Country Name (2 letter code) []:JP State or Province Name (full name) []:State Locality Name (eg, city) []:Tokyo Organization Name (eg, company) []:Org Organizational Unit Name (eg, section) []:OU Common Name (eg, fully qualified host name) []:CN Email Address []: CSRからCAを使って証明書を作成 openssl x509 -req -in deviceCert.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out deviceCert.crt -days 365 -sha256 証明書とCAを連結します。 cat deviceCert.crt rootCA.pem > deviceCertAndCACert.crt 次に作成された証明書(deviceCertAndCACert.crt)、デバイスキー(deviceCert.key)を使ってアクセスしてみます。Amazonのサーバー認証用のCA証明書が必要となるのでこちらから事前にダウンロードしておきます。クライアントとしてmosquittoを使って接続しました。 初回の接続。 $ ./mosquitto_pub --cafile jitr_cert/root.cert --cert jitr_cert/deviceCertAndCACert.crt --key jitr_cert/deviceCert.key -h "<host name>-ats.iot.ap-northeast-1.amazonaws.com" -p 8883 -q 1 -d -t topic/test -m "Hello World" -i id01 --tls-version tlsv1.2 接続エラーとなります。 Client id01 sending CONNECT Error: The connection was lost. 2回目の接続 ./mosquitto_pub --cafile jitr_cert/root.cert --cert jitr_cert/deviceCertAndCACert.crt --key jitr_cert/deviceCert.key -h "<host name>-ats.iot.ap-northeast-1.amazonaws.com" -p 8883 -q 1 -d -t topic/test -m "Hello World" -i id01 --tls-version tlsv1.2 1回目の失敗時にデバイス証明書が登録されているため正しく接続されます。 Client id01 sending CONNECT Client id01 received CONNACK (0) Client id01 sending PUBLISH (d0, q1, r0, m1, 'topic/test', ... (11 bytes)) Client id01 received PUBACK (Mid: 1, RC:0) Client id01 sending DISCONNECT IoTのコンソールを確認すると、Lambdaで指定した名前でモノが作成され、証明書がアタッチさせていることが確認できます。 CloudWatchにてLambda関数のLogを確認すると、正しく実行されたことが確認できます。 まとめ Just In Time Registration(JITR)による証明書の作成・登録について試してみました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DynamoDBのローカル開発環境構築(マイグレーション編)

概要 前回の記事でローカル開発環境にDynamoDBのインストール方法を記載しました。 今回はTBL作成やデータのロードに関する記事となります。 TBL確認 TBL一覧の確認 ~/develop/aws/dynamodb/dynamodb_local_latest $ aws dynamodb list-tables --endpoint-url http://localhost:8000 { "TableNames": [] } TBL作成 Musicテーブル作成 aws dynamodb create-table \ --table-name Music \ --attribute-definitions \ AttributeName=Artist,AttributeType=S \ AttributeName=SongTitle,AttributeType=S \ --key-schema \ AttributeName=Artist,KeyType=HASH \ AttributeName=SongTitle,KeyType=RANGE \ --provisioned-throughput \ ReadCapacityUnits=10,WriteCapacityUnits=5 \ --endpoint-url http://localhost:8000 MusicTBLへのデータ挿入 aws dynamodb put-item \ --table-name Music \ --item \ '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "1"}}' \ --endpoint-url http://localhost:8000 MusicTBLへのデータ取得 aws dynamodb get-item --consistent-read \ --table-name Music \ --key '{ "Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}}' \ --endpoint-url http://localhost:8000 MusicTBLへのデータ更新 aws dynamodb update-item \ --table-name Music \ --key '{ "Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}}' \ --update-expression "SET AlbumTitle = :newval" \ --expression-attribute-values '{":newval":{"S":"Updated Album Title"}}' \ --return-values ALL_NEW \ --endpoint-url http://localhost:8000 MusicTBLへのクエリ実行 aws dynamodb query \ --table-name Music \ --key-condition-expression "Artist = :name" \ --expression-attribute-values '{":name":{"S":"Acme Band"}}' \ --endpoint-url http://localhost:8000
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【7日目】AWS認定ソリューションアーキテクト合格までの道

ネットワークサービス VPC内で利用できるネットワークサービス Elastic Load Balancer(ELB) EC2や特定のIPアドレスへのトラフィックを分散するロードバランシングサービス EC2インスタンス(バックエンドインスタンス)を登録するだけで利用できる Classic Load Balancer(CLB) 標準的なロードバランシング 複数のEC2インスタンス間で基本的な負荷分散を提供し、リクエストレベルと接続レベルの両方で動作する Application Load Balancer(ALB) リクエストレベル(レイヤー7)で動作し、トラフィックをリクエストの内容に基づいて、ターゲット(EC2インスタンス/コンテナ/IPアドレス/Lambda関数)にルーティングする HTTPトラフィックおよびHTTPSトラフィックの負荷分散に最適 Network Load Balancer(NLB) リクエストレベル(レイヤー4)で動作し、IPプロトコルデータに基づいてVPC内のターゲット(EC2インスタンス/マイクロサービス/コンテナー)に接続をルーティングする TCPトラフィックとUDPトラフィックの両方の負荷分散に最適 超低遅延(低レイテンシー)を維持しながら、1秒あたり数百万の要求を処理 アベイラビリティーゾーンごとに単一の静的IPアドレスを使用しながら、突然の不安定なトラフィックパターンを処理するように最適化されている レイヤーとはデータ通信を実現するためのネットワーク構造の設計方針 レイヤー4(トランスポート層) ・ネットワークの端から端までの通信管理(エラー訂正、再送制御等) レイヤー7(アプリケーション層) ・具体的な通信サービス(ファイル・メールの転送、遠隔データベースアクセスなど)を提供 ・HTTPやHTTPS等の通信サービス ELBの特徴 特徴 詳細 高可用性 トラフィックを複数のAZに分散できる/EC2インスタンスやAZに障害が発生しても正常なインスタンスとの通信が続けられる 自動スケーリング トラフィックの負荷に応じて自動でスケーリングする/ELB自体にも冗長性がある セキュリティ機能 SSL復号の機能がある/バックエンドインスタンスの負荷軽減や証明書の一元管理が可能/ELB自体にもセキュリティグループを設定できるため、ELBのみでアクセス制御も可能 ヘルスチェック/モニタリング 正常に作動していないインスタンスへのトラフィックの振り分けを停止して正常なインスタンスとのみ通信する/スティッキーセッション機能セッションが確立したインスタンスにユーザーリクエストを送信できる/Connecting Draining機能によりELBから切り離してもリクエスト中のインスタンスへ指定秒数の間は通信は切れない クロスゾーン負荷分散 複数のAZに登録された全てのインスタンスに対して、リクエストを均等に分散/無効になっている場合、AZごとにリクエストを均等に分散するため、AZによってインスタンス数が異なると全てのインスタンスに均等に分散できない 外部ELB(Internet-Facing)/内部ELB(Internal) 外部ELBはパブリックサブネットに配置し、バックエンドインスタンスをプライベートサブネットに配置する/内部ELBは外部アクセスできないプライベートサブネットでのみ利用できる  Auto Scaling リソースの使用状況をモニタリングし、状況に応じてEC2インスタンスを自動でスケールアウト/スケールインするサービス あらかじめ設定したAmazon Machine Image(AMI)からインスタンスを起動するため最新化しておく必要がある スケーリングプラン いつ/どのような条件でAuto Scalingを実行するか定義したもの 正常なインスタンスを維持するように実行 手動でスケーリングを実行 スケジュールを指定して実行 CloudWatchのメトリクス(リソースの使用状況)に応じて自動実行 自動実行のポリシータイプ ポリシータイプ 説明 シンプルスケーリング ひとつのポリシーに基づいて実行 ステップスケーリング CloudWatchのアラーム設定に応じた一連のスケーリングポリシーに基づいて実行 ターゲットトラッキングスケーリング 特定のメトリクスのターゲット値を維持するように実行 Auto Scalingの種類 種類 対象サービス 機能 EC2 Auto Scaling EC2 スケーリングポリシーに基づいてEC2インスタンスをスケーリング Application Auto Scaling EC2以外の対象サービス EC2以外のリソースの使用状況に応じて自動スケーリングする AWS Auto Scaling EC2/EC2以外の対象サービス 自動スケーリングと予測スケーリング機能を持つ/予測スケーリングで過去の使用状況を分析し、今後の利用量を予測して適切な利用状況になるように管理する 起動設定 Auto Scaling実行時に起動するEC2インスタンスの情報を定義 EC2を構築する際に必要なパラメーター →AMI/インスタンスタイプ/セキュリティグループなど Auto Scalingグループ EC2インスタンスの管理を行う範囲のこと インスタンスの最小数/最大数/希望数を定義することでその範囲内でEC2インスタンス数が増減する 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CodeCommitにSSH接続しようとしたら"Permission denied (publickey)"になった件

課題 AWS CodeCommitにRepositoryを立てて、サクッとSourceを共有しようとしたら、予想外にハマった件。 接続元は、Fedora34 Workstation. [root@ip-***-***-***-*** ~]# ssh -T A******************D@git-codecommit.us-east-1.amazonaws.com sign_and_send_pubkey: no mutual signature supported A******************D@git-codecommit.us-east-1.amazonaws.com: Permission denied (publickey). 原因 詳細はよく分からないが、最近のOpenSSHは古い暗号化形式を拒否するらしい。 これ、昔から使ってるSSH Private Keyを使って最新のAmazon LinuxのEC2に接続しようとするときにもたまに起こる。 対応方法 /etc/ssh/ssh_configに以下を追記する。 Include /etc/ssh/ssh_config.d/*.conf PubkeyAcceptedKeyTypes +ssh-dss # <= 追記 ~/.ssh/configに個別に記述する方法もあるけど、意外とハマりがちなので特別な理由がないなら ssh_configに記述した方がSmartっぽい。 結果 SSH接続できるようになる。 # ssh -T A******************D@git-codecommit.us-east-1.amazonaws.com You have successfully authenticated over SSH. You can use Git to interact with AWS CodeCommit. Interactive shells are not supported.Connection to git-codecommit.us-east-1.amazonaws.com closed by remote host. もちろん、Git cloneも上手く行く。 # git clone ssh://A******************D@git-codecommit.us-east-1.amazonaws.com/v1/repos/*** Cloning into '***'... warning: You appear to have cloned an empty repository. その他 CodeCommitを利用するIAM UserにはMFAを有効にしない方が良いっぽい。 どうしても有効にする必要がある場合には、こことかここを参考にすると良さそう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Could not initialize Amplify: PluginError: Unable to decode configuration

ある日突然、以下のようなエラーが出て、時間を溶かしたのでメモを残します。 Could not initialize Amplify: PluginError: Unable to decode configuration Recovery suggestion: Make sure the plugin configuration is JSONValue 同じようなエラーが発生した人によってissueが立てられていたのですが、Amplifyでpushを忘れているからという理由でした。 amplify statusでのリソースの状態は正しかったため、まさかと思っていたのですが、、 というのも、 こちらの記事を参考にBackend.swiftを作成し、使うリソース(AuthとApi、Storage)をまとめて初期化しています。 Backend.swift import UIKit import Amplify import AmplifyPlugins class Backend { static let shared = Backend() static func initialize() -> Backend { return .shared } private init() { // initialize amplify do { try Amplify.add(plugin: AWSCognitoAuthPlugin()) try Amplify.add(plugin: AWSAPIPlugin(modelRegistration: AmplifyModels())) try Amplify.add(plugin: AWSS3StoragePlugin()) try Amplify.configure() print("Initialized Amplify") } catch { print("Could not initialize Amplify: \(error)") } } } しかし、Amplifyを新しく作り直した際に、Storageはとりあえず使わないから、とaddしていなかった。 にもかかわらず、Backend.swiftでStorageの初期化も行おうとしているためエラーが出ていたようです。 あっちゃあ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む