20200516のAWSに関する記事は21件です。

EC2のスナップショットを手軽に自動取得する方法

はじめに

EC2のスナップショットを定期的に取得する簡単な方法がないかと探してみたところ、EC2ダッシュボード上にある「データライフサイクルマネージャー」という機能を使うと簡単に実現できることが分かりました。

今回はこのデータライフサイクルマネージャーを使った、スナップショットの作成手順(※GUIベース)を備忘録として記事にしてみました。

手順

1. EC2インスタンスのタグ付け

  • まず最初に、スナップショットを取るEC2インスタンスを識別するためのタグを付与します。
  • 今回はキー「Name」に対する値として、「nkojima-test」を設定しました。

10_EBSスナップショット_00.png

2. データライフサイクルマネージャの設定

  • EC2ダッシュボードの左側のメニューにある、「ライフサイクルマネージャー」をクリックします。
  • データライフサイクルマネージャーの画面に入ったら、[スナップショットのライフサイクルポリシーを作成する]をクリックします。

10_EBSスナップショット_01.png

  • ライフサイクルポリシーの作成画面に入ったら、ポリシーの説明として何らかの文言を設定します。
    • 後で出てくる「スケジュール名」の補足にあたるような文言が良いのかもしれません。
  • リソースタイプの選択については、今回は「インスタンス」を選択しました。
  • ターゲットについては、先程にEC2インスタンスに設定したタグ(Name)を指定します。

10_EBSスナップショット_021.png

  • 次にポリシースケジュールとして、スナップショットを取る時間などを設定します。
  • スナップショットの開始時刻はUTC(協定世界時)のため、画面上で設定する時刻は「日本時間の9時間前」として設定する必要があります。
    • 日本時間で18時からスナップショットを取りたい時は、9:00 UTCと設定します。
  • 今回は保持するタイプはカウント(世代)として、保持する数を1にしました。
    • この設定の場合、保持されるスナップショットは1世代だけで、スナップショットの自動作成が何回繰り返されてもスナップショットは1つだけとなります。

10_EBSスナップショット_022.png

  • タグ付け情報は、[ボリュームからタグをコピーする]という欄にチェックを入れました。
    • これにより、EC2インスタンスに設定されているタグがスナップショットにもコピーされます。

10_EBSスナップショット_023.png

  • スナップショットの高速復元、クロスリージョンコピー、パラメーターについては設定をしませんでした。

10_EBSスナップショット_024.png

  • IAMロールについては、デフォルト値の[デフォルトロール]を選択しました。
    • デフォルト値のままで、動作に特に問題はありませんでした。
  • 最後に[ポリシーを有効にする]にチェックが入っていることを確認して、[ポリシーの作成]をクリックします。
    • スナップショットの自動作成を止めたい時は、ここで[ポリシーを無効にする]にチェックを入れます。

10_EBSスナップショット_025.png

3. 作成されたポリシーの確認

  • ポリシーの作成が完了したら、ライフサイクルマネージャー画面でポリシーの状態が[ENABLED]になっていることを確認します。
    • ポリシーが無効化されていると、ポリシーの状態が[DISABLED]となっているはずです。

10_EBSスナップショット_04.png

4. 作成されたスナップショットの確認

  • スナップショットの作成予定時刻を少し(※1時間程度)過ぎたら、EC2ダッシュボードからスナップショット画面へ入り、スナップショットが作成されていることを確認します。
  • ポリシーの状態が[ENABLED]であるのにスナップショットが作成されていない場合は、スナップショットの取得開始時刻、取得間隔などを確認してください。

10_EBSスナップショット_05.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSアーキテクチャー(疎結合化編)

AWSアーキテクチャーの5つの設計原則と11のベストプラクティス
具体的な説明は以下のリンクをご参考ください。
https://qiita.com/Jenny1025/items/ce55c8724daeef626201

スクリーンショット 2020-05-16 14.14.34.png

コンポーネントの疎結合化

コンポーネントの疎結合化というのは、コンポーネント間の依存関係を減らし、コンポーネントの変更や障害が発生する際に、影響を減少できるようなアーキテクチャーを作り上げることです。

関連するサビース         説明
Lamba サーバーインスタンスではなく、Lambaによるトリガー処理で連結すること。
SQS SQSのキューイングを通信でインスタンス間関連を結ぶこと。
ELB サーバー間のトラフィック量を調整と連結をELBを起点により疎結合化を実現すること。
SNS SNSのアプリケーション間でインスタンス間関連を結ぶこと。

密結合と疎結合設計のバターン比較

スクリーンショット 2020-05-16 15.02.39.png

SQS

SQS: Amazon Simple Queue Service はポーリング型のフルマネーネジ型のキューサービスである。(60秒〜14日間データ保持する、ディフォルトで4日間保持可能)。
*ポーリングとは、複数のプログラム間、一定時間内に問い合わせがあった場合(一旦中継所見たいなところでデータを貯めて)受信側がいいタイミングで通信を行う方式です。

SNS

SNS: Amazon Simple Notification Service
フルマネージド型プッシュ型の非同期通信サービスである。

他のサービスと連携
Amazon CloudWatch: Billing Alertの通知
Amazon SES: Bounce/Complaintのフィードバックの通信
Amazon S3: ファイルがアップロード時の通知
Amazon Elastic Transcoder:動画変更完了/失敗時の通知

SES

Amazon Simple Email Service
フルマネージド型Emailサービスである。

Lambda

インフラに気にする事なくアプリケーションコードを実行できるデータ処理サービスである。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS完全攻略

はじめに

おこている。僕はおこている。
以下の表はAWSに支払った受験料である。
現在までの総利用量は200円程度なのになんだこの金額

試験名 トライ回数 結果 合計
SAP 2 挑戦中 48600
DVA 1 O 16200
SOA 1 O 16200
practice 1 O 10800
security 1 X 32400
125000
模擬試験名 トライ回数 結果 合計
SAP 1 4320
DVA 1 O 2160
SOA 1 O 2160
practice 1 O 2160
security 1 X 4320
12960

そこで自分だけのAWS取説を作ろうと思います。ホワイトペーパーより要点がまとめられていて且つ試験に出てくるレベルの範囲で。

↓から過去の記事一欄へ飛べます。

cloud-practitioner-tag_360x32.png
developer-associate-tag_360x32.png
sysops-administrator-associate-tag_360x32.png
solutions-architect-associate-tag_360x32.png

試験範囲について

SAP

仮説
試験は公式動画の範囲から出題される

根拠

  • 過去二回SAPを受験した体験より

組織の複雑さに対する設計

クロスアカウント戦略とアクセス戦略

一時的なアクセス:委任
  • STSについて
  • AWS IAMについて

    ユーザフェデレーション
  • Cognitoについて

  • SAML2.0/OpenIDについて

    AWS Directory Service
  • AWS Managed Microsoft ADについて

  • AD Connectorについて

  • Simole ADについて

    ネットワーク

    ハイブリッド型VPN戦略
  • AWS Managed VPNについて

  • AWS VPN CloudHubについて

  • Software VPNについて

ハイブリッド型 AWS Direct Connect(DX)
  • DXについて
ハイブリッド型 AWS Storage Gateway
  • File Gatewayについて
  • Tape Gatewayについて
  • Volume Gatewayについて
  • Cash Gatewayについて
VPC EndPoint
  • Interface endpointについて
  • Gateway endpointについて

マルチアカウント戦略

リソースと請求の分離
  • コンソリデーティッドビリングについて
複数アカウントの請求戦略について
  • 通知をグループエイリアスに送るについて
  • 全てのAWSアカウントにAWSタグ付け標準を使用するについて
  • AWS APIとスクリプトを使って企業のベースライン設定を自動化するについて
AWS Organization
  • AWS Organizationについて

新しいソリューションの設計

移行計画

コスト管理

既存のソリューションの継続的な改良

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS怒りの完全攻略

はじめに

おこている。僕はおこている。

ここに現在まででAWSに支払った受験料を戒めとして記す。
合計金額があったら他に何ができるかをよく考えること。
現在までの総利用量は200円程度なのになんなのこの金額

試験名 トライ回数 結果 合計
SAP 2 挑戦中 48600
DVA 1 O 16200
SOA 1 O 16200
practice 1 O 10800
security 1 X 32400
125000
模擬試験名 トライ回数 結果 合計
SAP 1 4320
DVA 1 O 2160
SOA 1 O 2160
practice 1 O 2160
security 1 X 4320
12960

試験範囲について

SAP

仮説
試験は公式動画の範囲から出題される

根拠

  • 今まで受験した体感では全く関係ない範囲の問題は1問のみ出題される
    • 天才達が遊んでる
  • 回答した内容と結果が不透明な試験であるから
    • 謎の強気試験料設定
  • 動画まで作って出題されなかったら意味がない
    • 時間を返して

結論

  • 必ずAWSは試験で遊部ので、その一問を捨てた残りの74問を感覚として八割五分、見直した際に完全に答えが分からなかった問いが10問であれば受かる

組織の複雑さに対する設計

クロスアカウント戦略とアクセス戦略

一時的なアクセス:委任
  • STS
  • AWS IAM ##### ユーザフェデレーション
  • Cognito
  • SAML2.0
  • OpenID ##### AWS Directory Service
  • AWS Managed Microsoft AD
  • AD Connector
  • Simole AD #### ネットワーク #### マルチアカウント戦略

新しいソリューションの設計

移行計画

コスト管理

既存のソリューションの継続的な改良

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CodePipelineで承認ステージ付きのパイプラインを作成する(CloudFormationテンプレート付)

はじめに

CodePipelineは便利。これをCloudFormationで自動構築して、フットワークの軽いデプロイを実現するぜ!
と言っても、商用リソースまで全自動でデプロイするようなクラウドネイティブに振り切ったシステムばかりではないよね。といった望みに、AWSはしっかり答えてくれている。

今回は、リリース直前に「ちょっと待った」をしてくれる承認ステージについての理解を深めてみる。

前提条件

  • さすがにCodePipelineの概要くらいは抑えている

ハードル低め。最低限、以下の記事くらいのことができるのが望ましい。
Windowsのあたりは蛇足なので飛ばしても問題ない。
WindowsのEclipseからCodePipelineを起動してEC2にデプロイ&ECS on Fargateにアプリをデプロイする

ただし、↑の記事で扱っているECS on FargateのパイプラインはCloudFormationで書くと少し面倒なので、今回ベースにするのは、以下の記事のLambdaのパイプラインをベースに考えてみる。

Lambda関数をBlue/GreenデプロイメントするCodePipelineをCloudFormationで自動構築する

ということで、スタート時点では「CodeCommitにPushしたらCodeBuildでビルドしてSAMテンプレートをCloudFormationで実行するパイプライン」があることを前提とする。

承認ステージを作って承認してみる

まず、上のパイプラインに承認ステージを追加してみる。

  • 編集ボタンを押す
    キャプチャ.PNG

  • 今回は、デプロイ直前で寸止めをしてみるとして、Buildステージの後に追加をする
    キャプチャ2.PNG

  • 出てきたダイアログに適当に名前をつける

  • キャプチャ3.PNG

  • つけた名前のステージができるので、アクショングループを追加する
    キャプチャ4.PNG

  • 適当に設定してみる

  • アクション名に適当な名前をつける

  • アクションプロバイダーはMannual approvalを選択

  • コメントを適当に入れる

  • 完了ボタンを押す
    キャプチャ5.PNG

  • パイプラインを走らせると、先ほど作ったApprovalのステージでちゃんとデプロイが「待った」された!

  • ということで、承認をしてみる。
    キャプチャ6.PNG

  • 適当にコメントを入れて「承認します」ボタンを押す
    キャプチャ7.PNG

  • ちゃんとパイプラインが進んだ!
    キャプチャ8.PNG

承認ステージで否認してみる

  • 今度は承認画面で「却下します」ボタンを押す
    キャプチャ9.PNG

  • ちゃんとパイプラインが停まった!(下の方に出ているのは1回前のデプロイ)
    キャプチャ10.PNG

IAMで承認権限のあるIAMユーザのみ承認可能にする

IAMユーザの準備

以下を参考にしながら。

【AWS公式】CodePipeline の IAM ユーザーに承認権限を付与する

以下のIAMポリシーを持ったマネコンログイン可能なIAMユーザを作成する。
テストなので、管理ポリシーでもインラインポリシーでも何でもよい。
ポイントはcodepipeline:PutApprovalResultの権限の有無。これがあると、パイプラインの承認ステージで承認が可能になる。

  • IAMユーザ名: can-approve
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "codepipeline:ListPipelines",
                "codepipeline:GetPipeline",
                "codepipeline:GetPipelineState",
                "codepipeline:GetPipelineExecution",
                "codepipeline:PutApprovalResult"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
  • IAMユーザ名: cannot-approve
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "codepipeline:ListPipelines",
                "codepipeline:GetPipeline",
                "codepipeline:GetPipelineState",
                "codepipeline:GetPipelineExecution"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

なお、今回はおためしのためにResourceを*で指定しているが、当然ながら実運用をする際は最小権限を意識した方が良い。↑のAWS公式のドキュメントにも記載されているように、リソースを

"Resource": "arn:aws:codepipeline:us-east-2:80398EXAMPLE:MyFirstPipeline"

でパイプライン単位に絞ることができるし、パイプラインで複数の承認ステージがある場合(承認者が複数いてそれぞれで承認可能なステージを変えたい場合)は

"Resource": "arn:aws:codepipeline:us-east-2:80398EXAMPLE:MyFirstPipeline/MyApprovalStage/MyApprovalAction"

といった具合に、承認ステージ名や、その中の識別子で絞ることも可能なようだ。

権限のないユーザでの承認行為

上記のcannot-approveユーザで承認しようとすると、当然ながらエラーになる。
直前の「承認します」ボタンまでは押せて、そこで↓このエラーが出るので、設定が失敗したのではないかとちょっと心配になった……。
キャプチャ11.PNG

権限のあるユーザでの承認行為

can-approveユーザで承認すると、パイプラインは継続した。
「承認された でした」って何やねん……って感じだけど…。
キャプチャ12.PNG

承認者に対して通知を送る

CodePipelineは、承認ステージに到達するとAmazon SNSと連携する機能があるので、これで承認者に対して通知を行うことができる。

Amazon SNSの設定

まずはマネコンのAmazon SNSの設定画面に移動し、新規のSNSトピックを作る。
名前や表示名は適当に決めよう。これ以外は、今はひとまずデフォルトのままにしておく。
キャプチャ13.PNG

トピックを作ったら、サブスクリプションを設定する。これ以外もデフォルトのままにしておく。
キャプチャ14.jpg
キャプチャ14.PNG

サブスクリプションの設定ができたら、EメールのConfirmを行っておく(やっておかないとこの後の通知がされない)

CodePipeline実行IAMロールに対するIAMポリシの設定

CodePipeline実行に使うIAMロールに、Amazon SNSに対してPublishする権限がないとエラーになってしまう。しかも、権限がなくて実行失敗したときは却下されたかのように見えてエラー解析が大変になってしまうので、忘れず設定しておく。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "*"
        }
    ]
}

CodePipelineの承認ステージの設定

承認ステージの「SNSトピックのARN」に、↑のSNSトピックを設定すると、承認依頼のメールが配信されるようになる。

キャプチャ15.PNG

承認依頼メール

メールは↓こんな感じで届く。

キャプチャ16.PNG

リンクを踏むと、パイプラインの詳細画面に遷移するので、そこで普通に承認/否認すれば良い。

IaCで書く

前の記事で作ったCloudFormationテンプレートに、以下を追加する。
こちらでは、できる限り最小権限を目指す。
また、CodePipelineのサービスロールと、承認ユーザのIAMユーザはあらかじめ作っておく前提とする(この辺のユーザは、パイプラインが増えても共通であることが多いので、ポリシを付け足していく考え方にする)。承認ユーザには、共通的に使うであろう以下の権限もあらかじめアタッチしておく。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "codepipeline:ListPipelines"
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        }
    ]
}
  • パラメータ
  SNSTopicNameSuffix:
    Description: "SNS Topic Name for Approval stage on CodePipeline"
    Type: "String"
    Default: "-Pipeline-Approval-Request"
  • SNSトピック/サブスクリプション

トピックにインラインでサブスクリプションを記述すると、削除時に消えなかったような気がするので、サブスクリプションも横着せずリソースとして作成するようにする。

  SNSTOPIC:
    Type: AWS::SNS::Topic
    Properties: 
      TopicName: !Sub ${Prefix}${SNSTopicNameSuffix}
      DisplayName: [トピックの表示名(メールのSubject)]

  SNSSUBSCRIPTION:
    Type: AWS::SNS::Subscription
    Properties:
      Protocol: email
      Endpoint: [通知メールの宛先]
      TopicArn: !Ref SNSTOPIC
  • CodePipelineのサービスロールに付与するIAMポリシ
  CODEPIPELINEIAMPOLYCY:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: CodePipeline-SNS-Publish
      Roles:
        - CodePipelineRole
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: !Sub ${Prefix}AmazonSNSPublish
            Effect: Allow
            Action:
              - "sns:Publish"
            Resource: !Ref SNSTOPIC
  • 承認権限を持ったIAMユーザに付与するIAMポリシ
  APPROVALIAMPOLYCY:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: CodePipeline-Approval
      Users:
        - can-approve
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: !Sub ${Prefix}CodePipelineAccess
            Effect: Allow
            Action:
              - "codepipeline:GetPipeline"
              - "codepipeline:GetPipelineState"
              - "codepipeline:GetPipelineExecution"
            Resource: !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Prefix}${PipelineNameSuffix}
          - Sid: !Sub ${Prefix}CodePipelineApproval
            Effect: Allow
            Action:
              - "codepipeline:PutApprovalResult"
            Resource: !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Prefix}${PipelineNameSuffix}/Approval/Approval
  • パイプライン 好きなところに差し込む。後続のアクションのRunOrderをずらすのを忘れないように。
        - Name: Approval
          Actions:
            - RunOrder: 3
              Name: Approval
              ActionTypeId: 
                Category: Approval
                Owner: AWS
                Provider: Manual
                Version: 1
              Configuration:
                NotificationArn: !Ref SNSTOPIC
                CustomData: [コメント]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS SysOps Administrator Associate 出題分野と関連サービス概要

目的

試験の出題範囲と関わるサービス概要をふんわり把握する
そもそも触ったことのないサービスや自身の理解が薄いサービスを発見する
それらを試験対策の目安にする

出題範囲

分野と出題比率

分野 出題の比率
モニタリングとレポート 22%
高可用性 8%
デプロイとプロビジョニング 14%
ストレージとデータ管理 12%
セキュリティとコンプライアンス 18%
ネットワーク 14%
オートメーションと最適化  12%

システム運用に関する分野が出題される
SAAと被っている分野に関しては少しだけ出題比率が減少しているかな?という印象
モニタリングとレポート分野は非常に重要

オンプレで行っていたシステム運用の概念が非常に活きる気がする

各分野で理解しなければならないこと

モニタリングとレポート

主にCloudWatchの理解度が試される分野
次点でCloudTrail

  • メトリクスとアラームの作成と維持
    メトリクスによって何が行われるのか

  • メトリクスを認識し、パフォーマンスと可用性を区別
    メトリクスはどのように記録されるのか
    何によってアラーム状態がトリガーされるのか

  • メトリクスのパフォーマンスと可用性に基づいて是正
    パフォーマンスベースのアラートの場合、そのアラームの種類に基づいて適切な改善を行えるか
    ボトルネックを修正する方法
    可用性、パフォーマンスをモニタリングする方法を理解する

CloudWatch

  • CloudWaychがメトリクスのリポジトリの役割を担っている
  • EC2やCloudFrontなどのほとんどのAWSサービスがCloudWatchにメトリクスをプッシュできる
  • アプリケーション用のカスタムメトリクスをプッシュできる
  • プッシュされたメトリクスに対して統計を利用し、閾値を超えることでアラーム状態になるようにする
  • アラーム状態に対してメールやSNS通知などをアクションすることができる
  • Lambda関数、AutoScalingなどのイベントをトリガーすることができる

CloudWatchアラーム

三つのステータスがあることを理解しておく

  • OK
    正常

  • ALARM
    閾値から外れている状態

  • INSUFFICIENT_DATA
    アラームが存在しないか、データが不足しているまたはデータを頻繁に要求している状態

CloudWatchEvents

  • イベントの確認ができる

CloudWatchLogs

  • ログファイルを解析し、特定の文字列を探索することでアラームを作成できる

CloudTrail

  • AWS APIシステムへの全てのコールを記録する
  • アカウントアクティビティを監視、記録、保持することができる
  • ログはS3バケットに保存される

CloudTrailとCloudWatchLogsを統合し、イベントを自動解析することがベストプラクティスの一つ

AWS Config

  • AWSリソースの設定をモニタリング、記録することができる

高可用性

主にAutoScaling、ELB、CloudWatchの理解度が試される分野
複数リージョンを前提としたグローバルな設計を理解しておく必要がある

  • スケーラビリティと伸縮性を導入する方法は何か
  • 可用性の高い環境とは何か
  • 障害性に優れた環境とは何か

スケーラビリティと伸縮性を実装する方法を理解する
高可用性な環境と耐障害性に優れた環境の違いを理解し、それぞれの環境に対するプラクティスを理解する

Route53

  • ドメイン名を登録できる
  • ドメイン名をIPアドレスに解決することができる
  • リージョン間でトラフィックを分散することができる
    • レイテンシー
    • ヘルスチェック
    • 重み
    • 地理的近接性

CloudFront

  • エンドユーザーに近い場所にシステムのエンドポイントを構成できる
  • 静的コンテンツ、動的コンテンツ、ビデオコンテンツを配信することができる
  • 高パフォーマンス、スケーラビリティ

多くの場合、コストも最適化される

ロードバランサー

  • Application Load Balancer
    HTTP、HTTPSに対して通信の種類に応じてトラフィックをルーティングすることができる

  • Netwoek Load Balancer
    全てのTCPに対してステートレスウェブサーバーにルーティングすることができる
    パフォーマンスに優れている

  • Classic Load Balancer
    HTTP、TCPの両方に対して処理することができる

Auto Scaling

  • 条件トリガーに基づき、EC2インスタンスを起動または終了することができる
    • ヘルスチェック
    • スケジュール
    • カスタム定義

需要を満たすためにスケールアウトし、コスト削減のためにスケールインする

デプロイメントとプロビジョニング

主にElastic Beanstalk、OpsWorks、CloudFromationに関しての理解度が問われる

  • クラウドリソースをプロビジョニングするために必要な手順を理解する
  • デプロイの問題を特定し、修復する

Elastic Beanstalk

- デプロイに関する設定を自動的に処理することができる

  • コードの更新に関する処理も行うことができる インフラの詳細なデプロイを行えるCloudFormationとの差別点となる

OpsWorks

  • 構成管理ツールを利用したデプロイメント、プロビジョニングを行うことができる
  • OpsWorksスタック、Chef、Puppetを使用することができる
  • 問題が発生した場合、スタックが自動的に修復される

オンプレでChefやPuppetを使用している場合は、管理サーバー をAWSに移行すると良い

CloudFormation

IaC(Infrastructure as Code)

  • テンプレートファイルにインフラを定義することができる
  • テンプレートに基づいてスタックを作成、更新、削除することができる
  • スタック作成後、手動で変更していないリソースのみ更新、削除することができる

ストレージとデータ管理

S3、EBS、EFSに関する理解を問われる

・データ保持ポリシー、オペレーションを作成及び管理できる
・データ保護、暗号化、キャパシティ計画のニーズを理解する

運用ストーリーに対して適切なサービス、ストレージの種類を判断できることが必要

S3

  • 高速、高耐久性(イレブンナイン)、高可用性
  • キーベースのオブジェクトにアクセスすることができる

S3 Glacier

  • 低コスト、長期バックアップに向いている
  • データ取り出し時間別にオプションがある
    • 迅速
    • 標準
    • 大容量

EBS

  • EC2インスタンスに接続し、ブロックストレージとして使用できる
  • SSD、HDDで異なるボリュームタイプが存在する
    • SSD
      • 汎用SSD
      • プロビジョンドIOPS SSD
    • HDD
      • スループット最適化HDD
      • Cold HDD

EFS(Elastic File System)

  • 共有ファイルストレージとして使用できる
  • マウントされたファイルボリュームが必要な場合に使用する

セキュリティとコンプライアンス

主に責任共有モデルとIAMの理解度が試される

  • セキュリティポリシーを管理できる
  • アクセスコントロールを管理できる
  • 責任共有モデルの役割と責任を区別できる

IAM

  • アクセスと認証を一元管理できる
  • IAMユーザー、グループ、ロールを作成し、ポリシーを適用する
  • アクセスできるリソース、リソースへのアクセス方法を管理できる

GuardDuty

  • 不審なアクティビティがないかAWS環境をモニタリングし、結果を記録できる

ネットワーク

AWS DirectConnect、AWSマネージドVPN、VPC Peeringなどのネットワーキングサービスの理解度を問われる

  • AWSネットワーキング機能を理解する
  • ハイブリッド方式でAWSに接続する方法を理解する
  • ネットワークのトラブルシューティング情報を収集及び解釈できる

NAT、NACL、セキュリティグループなどSAAと出題範囲が被っている箇所もある

AWS Direct Connect

  • 仮装プライベートゲートウェイを経由してオンプレデータセンターとAWS VPCを接続できる

VPC

  • AWSマネージドVPN
  • VPC Peering
  • VPCエンドポイント
  • NATゲートウェイ

自動化と最適化

  • AWSを使用したリソースの使用率管理、保護を理解する
  • 運用コスト最適化戦略について英回する
  • 手動または繰り返し可能なプロセスを自動化できる

Trusted Advisor

  • 使用されていないインスタンスや未使用のEIPなどを検知することができる

AWS Lambda

  • サーバー のプロビジョニングや管理を行わずにコードを実行できる

Cost Explorer

  • 予算を定義して追跡、モニタリングできる

AWS Systems Manager

  • OSのパッチを自動的に適用することができる
  • システムイメージを保存することができる

Step Functions

  • ワークフローのステートを制御することができる

最後に

詳細や練習問題は公式のデジタルトレーニングでの確認をおすすめします。
出題される概念、問題の解き方など非常に有用なインプットを行えます。
Exam Readiness: AWS Certified SysOps Administrator - Associate (Japanese)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2にデプロイ時、php artisan migrateができないエラーの対処法

LaravelをEC2にデプロイ作業の中でphp artisan migrateを実行しようとするとエラーが出てしまってめっちゃハマってしまったのでメモ兼共有。

php artisan migrateが実行できない

エラー内容
[ec2-user@ip-172-31-36-11 laravel]$ php artisan migrate

   Illuminate\Database\QueryException 

  could not find driver (SQL: select * from information_schema.tables where table_schema = laravel and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671
    667|         // If an exception occurs when attempting to run a query, we'll format the error
    668|         // message to include the bindings with SQL, which will make this exception a
    669|         // lot more helpful to the developer instead of just the database's errors.
    670|         catch (Exception $e) {
  > 671|             throw new QueryException(
    672|                 $query, $this->prepareBindings($bindings), $e
    673|             );
    674|         }
    675|

  • Database name seems incorrect: You're using the default database name `laravel`. This database does not exist.

    Edit the `.env` file and use the correct database name in the `DB_DATABASE` key. 
    https://laravel.com/docs/master/database#configuration

      +36 vendor frames 
  37  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

おそらくDBとLaravel側で連携ができていないと予想。
よくよく考えたら私はMysqlはインストールしたんだけれどもSQLサーバーはインストールしていなかったのが原因なのかなって考えました。
MySQLとSQLサーバーは違うものなのか?正直今でもわかっていないので勉強します。

ただEC2インスタンス内でMySQLを確かにインストールしたはずなのにMySQLコマンドが実行できなかったことから、Qiitaの記事を参考にSQLサーバーであるMariaDBをインストールしました。Mysqlでの派生のものでMysqlを実行できるとのことだったので。
LaravelのローカルでのDB連携でも行ったように.envと同じ名前のDBがないとLaravelとDBの連携ができません。そのため私の場合はMariaDB内にLaravelというDBを用意しました。

[ec2-user@ip-172-31-36-11 laravel]$ mysql -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 247
Server version: 5.5.64-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| laravel            |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

これで準備完了です。いざ

migrate実行
[ec2-user@ip-172-31-36-11 laravel]$ php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table

   Illuminate\Database\QueryException 

  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671
    667|         // If an exception occurs when attempting to run a query, we'll format the error
    668|         // message to include the bindings with SQL, which will make this exception a
    669|         // lot more helpful to the developer instead of just the database's errors.
    670|         catch (Exception $e) {
  > 671|             throw new QueryException(
    672|                 $query, $this->prepareBindings($bindings), $e
    673|             );
    674|         }
    675|

      +11 vendor frames 
  12  database/migrations/2014_10_12_000000_create_users_table.php:24
      Illuminate\Support\Facades\Facade::__callStatic()

      +22 vendor frames 
  35  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

なんとなくエラーでる未来は見えていた。。。
ただ1つだけmigrateできているのでとりあえず実行はできていることは確認。エラー文コピって調べていると下記のサイトを見つけました。
https://helog.jp/laravel/migrate-sql-error/
このサイトの通りに文を追記しました。
再度実行!

[ec2-user@ip-172-31-36-11 laravel]$ php artisan migrate
Migrating: 2014_10_12_000000_create_users_table

   Illuminate\Database\QueryException 

  SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists (SQL: create table `users` (`id` bigint unsigned not null auto_increment primary key, `name` varchar(191) not null, `email` varchar(191) not null, `email_verified_at` timestamp null, `password` varchar(191) not null, `remember_token` varchar(100) null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671
    667|         // If an exception occurs when attempting to run a query, we'll format the error
    668|         // message to include the bindings with SQL, which will make this exception a
    669|         // lot more helpful to the developer instead of just the database's errors.
    670|         catch (Exception $e) {
  > 671|             throw new QueryException(
    672|                 $query, $this->prepareBindings($bindings), $e
    673|             );
    674|         }
    675|

      +11 vendor frames 
  12  database/migrations/2014_10_12_000000_create_users_table.php:24
      Illuminate\Support\Facades\Facade::__callStatic()

      +22 vendor frames 
  35  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

またしてもエラー、、、しかしこれはローカルでのLaravel開発時に嫌という程見てきたエラーなのですぐに対処できました。
なんなのかというとすでにusersテーブルがあるからmigrateできないとのこと。そのためusersテーブルを削除してあげる必要があります。

$ mysql -u root -p
$ use laravel;
$ drop table users;

これで大丈夫なはず。migrateを邪魔しているusersテーブルを削除しました。コード間違っていたらごめんなさい。
migrate実行したら見事いけました!!

しかし、、、、Laravelの画面にはこんなエラーが、、、
スクリーンショット 2020-05-14 13.10.01.png
???もうよくわからん、、、
ただこれはWebサーバーの再起動で消えました。
晴れてローカルのLaravelとEC2にデプロイしたLaravelと見た目が一致しました。本当に大変でした。。。

備考

EC2にMysql実行環境があってもLaravelプロジェクト側にMysql実行環境がないとmigrateはできません。
そのためLaravel側にもMySQL実行できる環境(ドライバ)をインストールしてあげる必要があります。

Mysqlのドライバ入れた
$ sudo yum install php74-php-mysqlnd.x86_64

上記のコマンドを実行していないと下記のphpinfo()PDO driversにはsqliteの記述しかないはずなのでMysqlコマンドが実行されません。気をつけてください。
自分はこれに気づくのに一時間くらいかかりました。

phpinfo()
PDO

PDO support => enabled
PDO drivers => mysql, sqlite
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】Lambda+Amazon SNSでSMSを送信する

やりたいこと

AWS LambdakからAmazon SNSを利用して、任意の電話番号あてにSMSを送信します。

Amazon SNSって?

Amazon Simple Notification Service
任意の通知をいろんなプロトコルで送信できるよ。
事前にトピックっていう通知カテゴリみたいなの作って、そいつに紐づくサブスクリプションを作成しておくと、
トピックが叩かれたときに紐づいているサブスクリプションにメッセージが送信されるよ。
で認識合ってる?

プロトコル/トランスポート
HTTP/HTTPS
Email
Email-JSON
Amazon SQS
AWS Lambda
Platform application endpoint
SMS

公式の概要
Black Beltのスライド

コードとかより注意しておきたいこと

送信制限について

SNSでのSMS送信は送信制限が厳しめに設定されています。
利用料金の上限が1USD/月に設定されていて、東京リージョンにおいては12,3通/月しか送れません。
テスト送信だけで上限に達する可能性もあるので、必要があれば上限緩和申請を出しましょう。

宛先指定について

SNSでSMSを飛ばす分にはトピックを作成しなくても送信が可能です。

SMSじゃなくてE-Mailを送信したいという場合、
SNSでは事前にE-Mailの検証(実際にメールを送って、受信者が認証する)が必要です。
Lambdaでメールアドレスを指定してメール送信したいときにはAmazon SESを使いましょう。

構成

AWS LambdaとAmazon SNSのみです。
tempsnip.png

Lambda関数

事前にLabmda実行ロールにSNS実行ポリシーをアタッチしましょう。
とりあえずテストなのでAmazonSNSFullAccessをアタッチしておきます。

コード

ランタイムはNode.js 12.xです。

TestSendSMS.js
var AWS = require("aws-sdk");
var SNS = new AWS.SNS();

exports.handler = function(event, context, callback){

    // メッセージ情報を設定
    var param = {
        PhoneNumber: 'E.164形式の電話番号',
        Message: 'This is test message.',
        MessageAttributes: {
            'AWS.SNS.SMS.SMSType': {
                DataType: 'String',
                StringValue: 'Transactional' // 信頼性を重視する場合はこちらを
              //StringValue: 'Promotional'   // コストを重視する場合はこちらを
            },
            'AWS.SNS.SMS.SenderID': {
                DataType: 'String',
                StringValue: 'TEST'  // 端末に表示される送信元名
            }
        }
    };

    // メッセージを送信する
    SNS.publish(param, function(err, data){
        if(err){
            context.done(null, err);
        }
        context.done(null, data);
    });
};

多分これでいけます―

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】LaravelファイルをEC2にデプロイの際Composer installができない際の対処法 simplexml

まずLaravelプロジェクトのcomposer installまでの手順はQiitaなどの技術系ブログ記事に多くの手順ブログがありますのでこちらをご覧ください。
私が参考にしたデプロイ記事はこちらになります。
https://qiita.com/nakm/items/0bcc6564538a0604b2ce

PHPのバージョンについては適宜対応してください。

EC2インスタンス内でcomposer installをしようとすると。。。下記のようなエラー

[ec2-user@ip-172-31-36-11 laravel]$ composer install

>
  Problem 1
    - Installation request for aws/aws-sdk-php 3.135.2 -> satisfiable by aws/aws-sdk-php[3.135.2].
    - aws/aws-sdk-php 3.135.2 requires ext-simplexml * -> the requested PHP extension simplexml is missing from your system.
  Problem 2
    - Installation request for doctrine/dbal 2.10.2 -> satisfiable by doctrine/dbal[2.10.2].
    - doctrine/dbal 2.10.2 requires ext-pdo * -> the requested PHP extension pdo is missing from your system.
  Problem 3
    - Installation request for laravel/framework v7.6.2 -> satisfiable by laravel/framework[v7.6.2].
    - laravel/framework v7.6.2 requires ext-mbstring * -> the requested PHP extension mbstring is missing from your system.
  Problem 4
    - Installation request for league/commonmark 1.3.4 -> satisfiable by league/commonmark[1.3.4].
    - league/commonmark 1.3.4 requires ext-mbstring * -> the requested PHP extension mbstring is missing from your system.
  Problem 5
    - Installation request for tijsverkoyen/css-to-inline-styles 2.2.2 -> satisfiable by tijsverkoyen/css-to-inline-styles[2.2.2].
    - tijsverkoyen/css-to-inline-styles 2.2.2 requires ext-dom * -> the requested PHP extension dom is missing from your system.
  Problem 6
    - Installation request for facade/ignition 2.0.2 -> satisfiable by facade/ignition[2.0.2].
    - facade/ignition 2.0.2 requires ext-mbstring * -> the requested PHP extension mbstring is missing from your system.
  Problem 7
    - Installation request for phar-io/manifest 1.0.3 -> satisfiable by phar-io/manifest[1.0.3].
    - phar-io/manifest 1.0.3 requires ext-dom * -> the requested PHP extension dom is missing from your system.
  Problem 8
    - Installation request for phpunit/php-code-coverage 7.0.10 -> satisfiable by phpunit/php-code-coverage[7.0.10].
    - phpunit/php-code-coverage 7.0.10 requires ext-dom * -> the requested PHP extension dom is missing from your system.
  Problem 9
    - Installation request for phpunit/phpunit 8.5.3 -> satisfiable by phpunit/phpunit[8.5.3].
    - phpunit/phpunit 8.5.3 requires ext-dom * -> the requested PHP extension dom is missing from your system.
  Problem 10
    - Installation request for scrivo/highlight.php v9.18.1.1 -> satisfiable by scrivo/highlight.php[v9.18.1.1].
    - scrivo/highlight.php v9.18.1.1 requires ext-mbstring * -> the requested PHP extension mbstring is missing from your system.
  Problem 11
    - Installation request for theseer/tokenizer 1.1.3 -> satisfiable by theseer/tokenizer[1.1.3].
    - theseer/tokenizer 1.1.3 requires ext-dom * -> the requested PHP extension dom is missing from your system.
  Problem 12
    - aws/aws-sdk-php 3.135.2 requires ext-simplexml * -> the requested PHP extension simplexml is missing from your system.
    - league/flysystem-aws-s3-v3 1.0.24 requires aws/aws-sdk-php ^3.0.0 -> satisfiable by aws/aws-sdk-php[3.135.2].
    - Installation request for league/flysystem-aws-s3-v3 1.0.24 -> satisfiable by league/flysystem-aws-s3-v3[1.0.24].
  To enable extensions, verify that they are enabled in your .ini files:
    - /etc/opt/remi/php74/php.ini
    - /etc/opt/remi/php74/php.d/20-bz2.ini
    - /etc/opt/remi/php74/php.d/20-calendar.ini
    - /etc/opt/remi/php74/php.d/20-ctype.ini
    - /etc/opt/remi/php74/php.d/20-curl.ini
    - /etc/opt/remi/php74/php.d/20-exif.ini
    - /etc/opt/remi/php74/php.d/20-fileinfo.ini
    - /etc/opt/remi/php74/php.d/20-ftp.ini
    - /etc/opt/remi/php74/php.d/20-gettext.ini
    - /etc/opt/remi/php74/php.d/20-iconv.ini
    - /etc/opt/remi/php74/php.d/20-json.ini
    - /etc/opt/remi/php74/php.d/20-phar.ini
    - /etc/opt/remi/php74/php.d/20-sockets.ini
    - /etc/opt/remi/php74/php.d/20-sodium.ini
    - /etc/opt/remi/php74/php.d/20-tokenizer.ini
  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

たくさん文字が出てきて驚きました笑
上記のエラーによるとcomposer install時に必要なモジュールがインストールされていなかったようで上記のようなエラーがでております。。。
エラー文のrequiresに続いているものが必要なモジュールの名前になります。そのため、全ての正しいモジュールをインストールしてあげなければなりません。
しかしモジュールをインストールをしているとまたしてもエラー。
ext-simplexmlをインストールしようとするとエラーが発生してしまいます。

[ec2-user@ip-172-31-36-11 laravel]$ sudo yum install --enablerepo=remi  ext-simplexml 
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                                   | 2.4 kB  00:00:00     
251 packages excluded due to repository priority protections
エラー: 何もしません
[ec2-user@ip-172-31-36-11 laravel]$ sudo yum install --enablerepo=remi-php74 php-xml
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                                   | 2.4 kB  00:00:00     
remi-php74                                                                                                   | 3.0 kB  00:00:00     
remi-php74/primary_db                                                                                        | 211 kB  00:00:00     
246 packages excluded due to repository priority protections
パッケージ php-xml-5.4.16-46.amzn2.0.2.x86_64 はインストール済みか最新バージョンです
何もしません
[ec2-user@ip-172-31-36-11 laravel]$ sudo yum install --enablerepo=remi-php74 unzip
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
246 packages excluded due to repository priority protections
パッケージ unzip-6.0-20.amzn2.x86_64 はインストール済みか最新バージョンです
何もしません

上記のような感じで結構頑張ったんですがなぜかext-simplexmlが入りません。
そこで下記を実行してみました。

[ec2-user@ip-172-31-36-11 laravel]$ sudo yum --enablerepo=epel,remi,remi-php74 install php74-php-xml.x86_64
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
301 packages excluded due to repository priority protections
依存性の解決をしています

できたっぽい:joy:
つかさず

$ composer install

いけました。simplexmlだけでこんなにもハマるとは思っていませんでした。もし同じ症状で困っている方がいましたら参考にしてみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSでDNSを設定する

前回はWebサーバーを構築したので、次はドメインを購入して、名前解決できるようにする。

ElasticIPの設定

EC2を起動して、ElasticIPを関連付ける。
EC2に固定IPを付与するを参照。

ドメイン購入

お名前.comで購入する。.workだと一年間は1円で使える。
image.png
料金確認へ進むを選択。
image.png
練習なので、一年登録。AWSのIPと紐付けたいので、レンタルサーバーは利用しない。
メールアドレスとパスワードを入力して次へを選択。
image.png
image.png
その後、個人情報入力、支払い情報の入力で申し込む。申し込みが完了すると以下の画面になる。(途中、サーバー申し込みの画面が出るが、もちろん申し込まない。)
ドメインの自動更新の設定をオフにしたいので、こちらを選択。
image.png
先ほど設定したID、パスワードでログインする。
image.png
ドメインタブを選択して、ドメイン名を選択する。
image.png
自動更新を選択。
image.png
チェックを入れて、確認画面へ進む。
image.png
規約に同意し、上記内容を申し込む。
image.png
解除するを選択。
image.png
手続きを続けるを選択。
image.png
自動更新設定が未設定になったことを確認。
image.png

DNSの設定

AWSのRoute53を使ってDNSを設定していく。

Route53にホストゾーン作成

AWSコンソールにアクセスして、Route53を選択。
image.png
DNS管理の今すぐ始めるを選択。
image.png
ホストゾーン作成を選択。
image.png
ホストゾーン作成を選択して、先ほど購入したドメイン名を入力し、タイプをパブリックホストゾーンにして作成を選択。
image.png
作成すると以下の画面になる。赤枠部分がドメインが登録されたネームサーバー。次に赤枠部分をお名前.comで登録する。
image.png

ネームサーバーの変更

再度お名前.comにログインして、ドメインの詳細画面まで進む。下の方に以下の画面があるので、ネームサーバーの変更を選択。
image.png
ドメインにチェックを入れる。
image.png
その他のネームサーバーを使うにチェックを入れ、先ほどのネームサーバーを入力して、一番下の確認ボタンを選択。
image.png
確認ダイアログが出るので、OKを選択。
image.png
完了。
image.png

ドメイン名とIPアドレスの紐付け

Route53のメニューに行き、ホストゾーンのドメイン名を選択。
image.png
レコードセットの作成を選択して、ElasticIPを値に入力して、作成を選択。
image.png
レコードが追加される。
image.png

DNSの確認

SSHでログインして、以下のコマンドで、設定されたネームサーバー確認する。

お名前.comのネームサーバー情報が未反映の時はお名前.comのDNSのまま
[ec2-user@ip-10-0-10-10 ~]$ dig aws-dns-practice.work NS +short
dns2.onamae.com.
dns1.onamae.com.
反映されるとAWSのRoute53に変更される
[ec2-user@ip-10-0-10-10 ~]$ dig aws-dns-practice.work NS +short
ns-2020.awsdns-60.co.uk.
ns-444.awsdns-55.com.
ns-604.awsdns-11.net.
ns-1525.awsdns-62.org.

ブラウザで繋がるか確認。
image.png

終わりに

次回はWordPressを使えるように構築する!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Lambda+boto3でパラメーターストアにアクセスしたらCloudWatchにエラーも吐かれず異常終了した

まえがき

LambdaからSSMパラメーターストアにアクセスし、鍵情報を取得しようとした際にハマったので共有
※ 今回のケースはパラメーターストアで現象が発生。だけども、KMSとか他機能でも同じことになるかも

結論

boto3のセッションは多重起動してはならない 1

実行環境

やりたいこと

まえがきにも書いているよう、単純にLambdaからパラメーターストアにアクセスし、鍵情報を取得したい
鍵情報はSSMにいくつか格納している

具体的には

Name Value
/Project/secrets/hoge1 huga1
/Project/secrets/hoge2 huga2

と言う感じ

これを踏まえて、サクッと以下のように実装した

handler.py
from boto3.session import Session
import aws_paramstore_py as paramstore

def get_secret1():
    ssm = Session().client('ssm', region_name='ap-northeast-1')
    params = paramstore.get('/Project/secrets', decryption=True, ssm_client=ssm)
    return params['hoge1']

def get_secret2():
    ssm = Session().client('ssm', region_name='ap-northeast-1')
    params = paramstore.get('/Project/secrets', decryption=True, ssm_client=ssm)
    return params['hoge2']

def handler(event, context):
    secret1 = get_secret1()
    secret2 = get_secret2()
    # 以降他の処理...

サクッとしすぎ。まー適当な実装。でも検証だし、と実行
しかし、いざ動かしてみると、なぜかLambdaが途中で実行終了となる
CloudWatchでログを見ても何も出力されていない(見かけ上は正常終了のように見えるが、処理は途中で中断し異常終了している)
ナニコレ?と試行錯誤し、原因を特定

「boto3のセッションは多重起動してはならない」 1

具体的には上記コード内にある

ssm = Session().client('ssm', region_name='ap-northeast-1')

こいつがLambda内で2度呼ばれていることが原因の模様


以下のように修正することで動作しましたとさ

handler.py
from boto3.session import Session
import aws_paramstore_py as paramstore

def get_secrets():
    ssm = Session().client('ssm', region_name='ap-northeast-1')
    secrets = paramstore.get('/Project/secrets', decryption=True, ssm_client=ssm)
    return secrets

def handler(event, context):
    secrets = get_secrets()
    hoge1 = secrets['hoge1']
    hoge2 = secrets['hoge2']
    # 以降他の処理...

そもそも

secrets = paramstore.get('/Project/secrets', decryption=True, ssm_client=ssm)

の実行で、/Project/secrets よりも下の階層に格納されいてるキー(=hoge1, hoge2)が secrets にdictで返却されるので、度々getする必要も無かった
具体的には、 secrets['hoge1']huga1 が取得でき、 secrets['hoge2']huga2 が取得できる

固定になっているリージョンも可変にするよう修正して、ひとまず解決

むすび

これって常識な事例?まあ普通 Session().client を何度も呼ばないよね
今回のケースはパラメーターストアだったけども、KMSとか他機能でも同じことになるかも
適当な実装で痛い目をみた(何度目だ)

# 注釈1にもあるように、類似の事例が見当たらなかったので、何か知っている人いたら教えていただければです


  1. この現象について記述されているドキュメントやら記事が見あたらなく、本当にこの理屈で合っているのかは不明。参考まで 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cognitoを使ってみたい初心者、案件で検討している人向け(大体1.5年くらい使っての所感@2020/5時点

概要

2020/05/16 時点の話。

感想
安易に採用すると後で大変なことに。。。って思うけどやらないとノウハウも溜まらないよねっていう。

案件の条件

推奨する案件の条件

  • 別システムの認証まで含めた統合的な認証システムを作りたい場合
    • 正し、この場合、認証システムを作るっていう別案件を立てるのを激しく推奨。。
  • 別プロバイダでの認証(Googleとか)も許容したい場合
  • MFAで電話番号、メールアドレスを使いたい場合
  • とにかく認証機能を作りたくない場合

推奨しない案件の条件

  • 認証の要件が不確定 or ぐるぐる変わりそうな場合
    • Cognitoにできないことは地力でカバーする必要が出てきて、Cognitoが足かせになる
  • 本当にごく簡単なユーザ登録、認証さえできれば良い場合
    • 例えば、ID/PWで認証できて、登録時にメール飛べばそれだけで良いみたいな軽いヤツ
      後からCognitoの仕様に振り回されるくらいなら自分達作った方が楽
    • まー、簡単だからとりあえず使ってみてノウハウを作るっていう考え方もある

始める前に理解しておくべき技術

  • IDトークンとは何か
  • IDトークンの検証方法

"ホストされた UI"機能を使う場合は↓の各フロー(Implicit Flow 等)の流れ
(使わないなら知らなくても良い(CognitoのAPI叩くだけで完結するので、まー、知ってた方が良いけど。。))

  • Auth2.0
  • OpenIDConnect

※"ホストされた UI" を使う場合、"アプリクライアントの設定" を突き付けられるので嫌でも覚えることになるとは思う

所感(メモに近い感じになったけど。。

■ ユーザープール/IDプールとは何か

  • "ユーザプール" は、ユーザの管理、認証。
  • "IDプール" は、一時クレデンシャル情報の発行。 別プロバイダ用のIDトークン生成。
    ※IDプールはクレデンシャル情報(AWSの一時的なアクセスキー)を発行許可するユーザプール(厳密にいうとIDプロバイダ)を指定する形式

なので、認証情報(IDトークン)が欲しいだけなら、ユーザプールだけでもいいし、
クレデンシャル情報が欲しいだけなら、ユーザプールはいらない(独自認証して、クレデンシャルだけ発行できる。

おまけ

IDトークンって何

Cognitoがこの人認証しましたよっていう情報。

アクセストークンって何

Cognitoのユーザプール用のAPIを叩くときに渡すトークン。

■ クレデンシャル・IDトークンだけ欲しい場合、ユーザ管理・認証にユーザプールを使わないで自前のユーザ管理・認証でも出来る

独自認証については こちら の "開発者が認証した ID の認証フロー" を参照

要は自前で認証処理を作り、

  • 自前の認証を実行する
  • 認証OKだったら、 GetOpenIdTokenForDeveloperIdentity を呼ぶ
    ※レスポンスの Token は独自認証したID用のIDトークン
  • GetOpenIdTokenForDeveloperIdentity のレスポンス値を使って、GetCredentialsForIdentity を呼ぶ
  • 一時クレデンシャルが貰える

という流れ。

■ 一度設定したIDは変更できない

変更できないので、メールアドレス等、時間経過で変更が考えられるモノをIDに使おうとする場合、注意。

■ パスワードポリシーはCognito縛りがある

Cognitoがサポートしているポリシー以外は結局自分たちでカバーする必要がある。

例えば、過去に使用されたパスワードを使ってはいけない、細かいパスワード文字列の条件等、Cognito直接ではなく、専用のAPIを用意し、API内でパスワードのチェック、CognitoのAPIコールをすることになる

■ トークンには必ず期限がある

IDトークン、アクセストークンは更新トークンが生きていれば何度でも好きなタイミングで再生成できる。
が、更新トークンは期限の延長はできない(1~3650日まで)。

ので、ID、アクセストークンが再発行できなくなるタイミングはいつか必ず来る。
(更新トークンを再発行するために、ID/PWの再認証をする必要がある)

■ IDトークンの有効期限は1時間固定である

IDトークンの有効期限は1時間固定。IDトークンの有効期限を使って1時間より短い何かをしようとする時は注意。
(例えばブラウザのセッションタイムアウトの判定に使おうとする等)


ただ、独自認証時、GetOpenIdTokenForDeveloperIdentity でトークン発行する場合は、トークンの期限を1時間以外に指定できる模様。。

■ アクセストークンを使えば認証したユーザへやりたい放題できる

クライアントにIDトークン、アクセストークンが残る場合(Amplifyとか)、アクセストークンを使ってCognitoのAPIを直接叩けば、認証した本人に対してAPIで出来ることは全てできる。(はず、、

例えば、APIを直接叩いて自分自身を削除することもできる。(これは実際にやって確認済み

あくまで、"認証した自分自身に対して"に限定される話ではあるが、良しとするかどうかは判断が必要。

この対策としては "Authorization Code Flow"(ホストされたUI)を使うことになる

これが、嫌な場合、"ホストされた UI"機能を使い、Authorization Code Flow にする必要がある。
(authorization codeを発行するためのAPIはないため。(AWSに問い合わせてないって言われた

この場合、クライアントが直接、CognitoのAPIと直接通信することは無くなる。
発行される authorization code (リダイレクトのパラメータに含まれる)をAPI等に送信し、Cognitoとの通信を代行する形。

アプリクライアントの "アプリケーションのシークレット" を設定し、それが必要になるようにするのを推奨
(APIが内部でシークレットの値を保持し、Cognitoと通信する時に使用する
("client id" と "authorization code" は外から見える情報で、それを使ってトークンが取得できるため、開発側しか知りえない情報(APIの内部値)として "アプリケーションのシークレット" を使って制限をかける

"ホストされた UI"を使う時の参考

Amazon Cognito ユーザープール の Auth API リファレンス

もしくは、Cognitoへの認証はAPIを用意し、APIの中でCognitoの認証をやって、レスポンスとしてIDトークンだけ返すとかそういうのかな。。

って思います。

■ 二要素認証はできる

とりあえず実績があるのは、ID/PW/2要素のコードを画面で同時に入力して、Amplifyで認証、認証前トリガーを使って、2要素のコードを事前にチェックするっていう形式。

詳細は こっち参照 ※2段階にはなってないので注意

カスタムチャレンジを自分で追加する方がオシャレなのかもしれない。。

"ホストされた UI"の方でも出来るかどうかは不明。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS IoT ルール作成

AWS IoTのルールについて作り方のハマりどころ(主に任意のトピックの作成)があったので、手順ごとここにまとめておきます。任意のトピックの有効化については「補足」の項目にまとめてあります。

AWS IoT ルール作成手順

以下のような手順で作成します
(作成方法は2019年12月のものです。アップデートにより作成方法が変わっている場合があることをご了承ください)

1, AWS IoT Coreのページへ移動する

AWSの左上部の「サービス」をクリックし、サービス一覧から「IoT Core」をクリックします。

スクリーンショット 2020-05-16 14.53.43.png

2, 「ACT」をクリックし、その中の「ルール」をクリック

スクリーンショット 2020-05-16 14.57.44.png

3, 作成ボタンをクリック

スクリーンショット 2020-05-16 14.59.18.png

4, ルールの名前・説明を設定

 以下のようなページが表示されるので、必要な項目を設定していきます。まず、ルール名と説明を記入します
 ルールの名前に関しては英文字、「_」のみ使用できます。それ以外は特に制約はないです。

スクリーンショット 2020-05-16 15.01.13.png

5, 受信するデータを設定

「ルールクエリステートメント」の項目を設定する事で、クラウド側で受信するデータのフィルタリングを行います。このルールクエリステートメントに関してはSQLで記述します。下記の画像の赤で囲まれた部分を修正します。

スクリーンショット 2020-05-16 15.04.48.png

上記の画像では「SELECT * FROM 'iot/topic'」となっていますので、「’iot/topic’」というトピック宛てのデータを受信した際に、次の6の手順で設定したアクションが行われます。
 ここでいうトピックというのは、送受信を行うためのアドレスのような役割をしています。詳しい説明はAWSの公式サイトを参考にしてください。
(また、このトピックに関しては任意のもの(例えば'tom/iot/sensor/data'など)を設定して使用可能です。ただし、別途設定を行う必要があるので補足の項目を確認してください)

6, データを受信した際のクラウド側のアクションの設定

「1つ以上のアクションを設定する」の項目を設定する事で、クラウドがデータを受信した際に行うアクションを設定できます。「アクションの追加」ボタンを押すことにより、追加可能なアクションを設定できます。

補足(任意で設定したトピックの有効化)

トピックの名前に関しては、任意の名前を設定できるのですが、「モノ」となるデバイスの扱うことが可能なトピックを設定しないと、任意の名前のトピックで送受信を行うことができません。
 以下の手順で「モノ」でのトピックの設定を行いますので、ご参考ください。
※使用している環境の情報なので、一部の情報を黒く塗りつぶしています。ご了承ください

手順

1, AWS IoT Coreで「管理」→「モノ」を選択

スクリーンショット 2020-05-16 15.11.17.png

2, 登録されている任意のトピックを使用したいデバイスをクリック

スクリーンショット 2020-05-16 15.14.19.png

3, 「セキュリティ」から証明書をクリック

スクリーンショット 2020-05-16 15.15.34.png

4, 「ポリシー」をクリックし、使用しているポリシーをクリック

スクリーンショット 2020-05-16 15.16.28.png

5, 「ポリシードキュメント」にて、記載されている内容を変更

 「ポリシードキュメント」にて、json形式で使用可能なトピックが設定されています。「”Statement”」項目にて、「”Action”」で、「”iot:Publish”, “iot:Receive”」、「”iot:Subscirbe”」に該当する箇所で「”Resource”」のところに送受信可能なトピックが設定されています。

スクリーンショット 2020-05-16 15.17.18.png

「”Resource”」の箇所では
「"arn:aws:iot:ap-northeast-1:XXXXXXXXXXX:topic/sdk/test/java"」や、「"arn:aws:iot:ap-northeast-1:XXXXXXXXXXX:topic/sdk/test/Python"」のようにトピックがデフォルトで設定されていますので(Xの箇所は数字が入ります)、これをコピーし、使用可能にしたいトピックを設定します。

例えば、「iot/testTopic」というトピックを使用したければ、「"arn:aws:iot:ap-northeast-1:XXXXXXXXXXX:topic/iot/testTopic"」を「”Resource”」の項目下に追加してください。

引用

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

クラウド初心者のAWS入門

第4回 ネットワーク構築(2/2)

前回の続きです。作成したパブリックサブネットに、
インターネットへ接続するための設定を行っていきたいと思います。

今回構築する箇所は下図の通りとなります。
システム構成図_第4回目-4.png
項目も多いため、図中の番号順に進めていきたいと思います。

1a. インターネットゲートウェイの作成

まずは、インターネットゲートウェイの作成を行っていきます。

AWSマネジメントコンソールより、「VPC」のサービスを開きます。
その後、「インターネットゲートウェイの作成」を選択します。
1.png
必須入力項目はないので、デフォルトのまま作成を行います。
2.png
※なお、「名前タグ」は、複数ゲートウェイを持たせる際に、
※識別用として用いるようです。今回は使用しません。

1b. インターネットゲートウェイとVPCの関連付け(アタッチ)

作成したインターネットゲートウェイとVPCの関連付け作業を行います。

作成したインターネットゲートウェイを選択し、(チェックボックスにチェック)
「アクション」、「VPCにアタッチ」の順に選択します。
3.png
その後、ドロップダウンリストから、前回作成したVPCを選んで「アタッチ」を選択します。
4.png

まだインターネットには接続できないので、実際にルータに設定を入れていきます。

2a. ルートテーブルへの追加

ルートテーブルは、x.x.x.xからきた通信はy.y.y.yに送信しますよ、
というネットワークの設定です。

今回は、パブリックサブネットから、インターネットゲートウェイへ通信を行いますので、
ルートテーブルの現状を確認し、必要な設定を実施していきます。

ルートテーブルの確認

「ルートテーブル」を選択し、対象のサブネットにチェックを入れます。
その後、「ルート」タブを選択することでルートテーブルを確認します。
6.png

初期状態なので、
送信先「10.0.0.0/16」を「local」に送信する設定しかないかと思います。
そのため、その他の通信はすべて破棄されてしまいます。

例えば、Googleに接続しようとした場合は、通信先「172.217.26.3」となるのですが、
該当のアドレスはルートテーブルに登録されていないため、通信は破棄されてしまいます。

そこで、内部通信以外(10.0.0.0/16)のすべての通信(0.0.0.0/0)を、
インターネットゲートウェイに送信するルートテーブルに追加をしてあげます。


VPCのIDは以下にて確認
6_2.png

ルートテーブルの作成

「ルートテーブルの作成」を選択しルートテーブルを作成していきます。
7.png

「名前タグ」の入力と「VPC」を選択します。(VPCは前回作成したもの)
8.png
また、既存のルートテーブルを削除すると内部通信ができなくなるので、
理由がなければ残置推奨です。

2b.パブリックサブネットとの関連付け

作成したルートテーブルは、サブネットと関連付けをしてあげます。
(このサブネットで使用します、と明示的に指定する必要があります)

設定は、「サブネットの関連付け」タブより設定を行います。
9.png

設定画面からサブネットにチェックを入れ、「保存」を選択します。
10.png

2c.デフォルトゲートウェイの設定

作成したルートテーブルに、デフォルトゲートウェイを設定して完了となります。
すべての通信(0.0.0.0/0)をインターネットゲートウェイに飛ばしてあげる設定です。

「ルートテーブル」より、作成したルートテーブルにチェックを入れ、「ルートの編集」を行います。
11.png

12_2.png

サブネットに対して、ルートテーブルが設定されました。
12.png

長く、複雑になってしまいましたので以下補足です。
(余計ややこしくなるかも知れませんのでお気をつけください)


補足 実機で考える
Untitled Diagram-2.png

誤っている点やわかりづらい点がございましたら、
お気軽にコメントをいただけると幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EBSスナップショットの作成時間の統計方法

AMIの作成時間を測定したいので、色々調べて見た。

  1. AWSにはAMI作成に関してイベントが提供なし
  2. スナップショットを作成イベント (createSnapshots)より時間を測定できれば、それでもOK、SnapshotからAMIを作成の時間を短いですから

アーキテクチャ

file

下記はcreateSnapshotsイベントから着手、1から説明する

SNSトピックとサブスクリプション作成

snapshot-topic トピック作成
file
ARNをメモしておく(arn:aws:sns:ap-northeast-1:123456789012:snapshot-topic)

受信メールアドレスを記入して、サブスクリプション作成
file

サブスクリプションからの確認メールからリンクをクリックして、SNSの配置完成
file

Lambda関数作成

lambda-snapshotのLambda関数作成

file
注意点:
LambdaからSNSを呼び出すので、SNS発行可能なロールを新規作成。

ソースは下記となり。
```python
import boto3

def lambda_handler(event, context):
result = event['detail']['result']
snapshotId = ",".join(event['resources'])
startTime = event['detail']['startTime']
endTime = event['detail']['endTime']

client = boto3.client('sns')

sns_response = client.publish(
    TopicArn="arn:aws:sns:ap-northeast-1:123456789012:snapshot-topic",
    Message=('SNS のスナップショットが作成されました。\n詳細は以下です。\n\n結果:'
    + result
    + '\nスナップショットID:'
    + snapshotId
    + '\n作成開始時間:'
    + startTime
    + '\n作成終了時間:'
    + endTime
    + '\n\n'),
    Subject='demo-SnapshotCreateTime'
)

return sns_response
## CloudWatchEventsを設定

注意:イベントタイプは下記に選択
**EBS Multi-Volume snapshots completion status**

![](https://cloud5.jp/wp-content/uploads/2020/05/キャプチャ.jpg)

JSON
```json
{
  "source": [
    "aws.ec2"
  ],
  "detail-type": [
    "EBS Multi-Volume Snapshots Completion Status"
  ],
  "detail": {
    "event": [
      "createSnapshots"
    ],
    "result": [
      "succeeded",
      "failed"
    ]
  }
}

file

file

試してみる

EC2配下、
ELASTIC BLOCK STORE配下の「スナップショットの作成」をクリック

作成タイプはインスタンスを選択する
file

スナップショット作成成功
file

スナップショット作成時間メールを届けた
file

最後に

この記事が誰かのお役に立てば幸いです

参考資料

AMIの作成時間が知りたかったのでSNS Topicで通知させてみた
https://dev.classmethod.jp/articles/ami-create-time-sns/
説明の方法にはAMIの作成時間を測定できなく、一つEBSのスナップショットのみ測定しかない。

EBS スナップショットイベント
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-cloud-watch-events.html#snapshot-events

create-snapshots CLIヘルパー
https://docs.aws.amazon.com/cli/latest/reference/ec2/create-snapshots.html

スナップショットを作成 (createSnapshots)
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-cloud-watch-events.html#create-snapshots-complete

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Django+PostgreSQLのアプリケーションをAWSのElastic Beanstalkにデプロイする

この記事では EB CLI は使用せずに、コンソールからデプロイします。
また、この記事の内容は一例で、もちろんアプリ内で使用するフレームワークや、ライブラリによって異なりますので、適宜自分のプロジェクトに対応させてください。

目次

  1. Elastic Beanstalkのアプリケーションと環境を作成する
  2. データベースの設定を行う
  3. アプリケーションソースバンドルを準備する
  4. アプリケーションソースバンドルを作成する

1. Elastic Beanstalkのアプリケーションと環境を作成する

AWS マネジメントコンソール にログインしてください。
ただし、AWS Educate のアカウントからの場合はこの記事を参考にしてください。

Elastic Beanstalk を選び、Create Application からアプリケーションを作成します。

  • アプリケーション情報 > アプリケーション名 : 自身のアプリ名
  • アプリケーションタグ : 任意。
  • プラットフォーム : 今回は、プラットフォームPythonプラットフォームのブランチPython 3.6 running on 64bit Amazon Linuxプラットフォームのバージョン2.9.10 を選択しました。
  • アプリケーションコード : とりあえず「サンプルアプリケーション」を選んでおきます。あとから自分のソースをアップロードします。

[アプリケーションの作成] を押します。あとは自動で環境まで作成してくれるので数分待っておきます。
無事終了したら、その環境のダッシュボードのような画面になると思います。左のメニューの、「環境に移動する」をクリックするとサンプルアプリケーションの画面が出てきます。
出てきたURLの http:// などの部分を除く XXX.YYY.ZZZ.elasticbeanstalk.com が自身のアプリのドメインになります。
あとでこれを使うので控えておいてください。

2. データベースの設定を行う

左のメニューから 設定 を選びます。一番下の データベース の右の 編集 ボタンを押します。
データベース設定 の各欄について以下の選択をします。Amazon RDS DB に作成されます。

  • エンジン : postgres
  • エンジンバージョン : 今回は 11.5 を選択
  • インスタンスクラス : とりあえず db.t2.micro を選択
  • ストレージ : 今回は特に変えずに 5 にしておきました。
  • ユーザー名 : 各自作成して(一応)覚えておいてください。
  • パスワード : 各自作成して(一応)覚えておいてください。
  • 保持期間 : スナップショットの作成 にしておきました。
  • アベイラビリティー : 低(1つのAZ) にしておきました。

[適用] を押してください。変更が反映されるまで待っておいてください。

3. アプリケーションソースバンドルを準備する

ここから主にローカルでの作業に移ります。以下、cms というアプリを作成している前提で進めているで、適宜自分のアプリ名に置き換えてください。
最初に、このセクションをすべて終えたときに出来上がるディレクトリ構造の一例を以下に示します。適宜参考にしてください。

├─ .ebextensions         # Added
│  └─ python.config      # Added
├─ requirements.txt
├─ manage.py             # Updated
├─ cms
│  ├─ management         # Added
│  |  ├─ commands        # Added
|  |  |  ├─ createsu.py  # Added
|  |  |  └─ __init__.py  # Added
|  |  └─ __init__.py     # Added
│  ├─ templates
|  ︙
│  └─ views.py
├─ config
│  ├─ __init__.py
│  ├─ settings           # Added (settings.py removed)
|  |  ├─ common.py       # Added
|  |  ├─ local.py        # Added
|  |  └─ production.py   # Added
│  ├─ urls.py
│  └─ wsgi.py            # Updated
├─ docker-compose.yml
└─ Dockerfile

3-1. .ebextensions ディレクトリを作成する

Elastic Beanstalk にデプロイする際に必要となるディレクトリです。
プロジェクトのディレクトリ直下に .ebextensions ディレクトリを作成し、その中に python.config というファイルを作成してください。そのファイルに、以下を書き込んでください。一例なので、適宜書き換えてください。

なお、このファイルのインデントはtabだとエラーが出るので必ずspaceを使用してください。(コピペするとtabになると思うので、spaceに直してください。)

.ebextensions/python.config
packages:
  yum:
    postgresql95-devel: []

container_commands:
  01_migrate:
    command: 'python manage.py migrate'
    leader_only: true
  02_collectstatic:
    command: 'python manage.py collectstatic --noinput'
  03_createsu:
    command: 'python manage.py createsu'
    leader_only: true

option_settings:
  'aws:elasticbeanstalk:application:environment':
    DJANGO_SETTINGS_MODULE: 'config.settings.production'
    PYTHONPATH: '$PYTHONPATH'
  'aws:elasticbeanstalk:container:python':
    StaticFiles: '/static/=www/static/'
    WSGIPath: 'config/wsgi.py'

以下、上記の内容の解説です。

3-1-1. packages

ここで必要なパッケージをインストールします。具体的には、今回は requirements.txt が以下のようになっていて、 psycopg2 をインストールする際に必要となるため、postgresql95-devel を入れています。

requirements.txt
Django>=2.1,<2.2
psycopg2==2.8.5

3-1-2. container_commands

01_migrate ではマイグレーション
02_collectstatic 静的ファイルの処理
03_createsu スーパーユーザーの作成
のコマンドを実行しています。なお、03_createsupython manage.py createsu については後述します。

3-1-3. option_settings

DJANGO_SETTINGS_MODULE の部分で、後ほど作成する、 production.py を読み込むように環境変数を設定しています。
WSGIPathStaticFiles などについては、コンソールの設定のところでも変更可能です。
option_settings について詳しく知りたい方は、以下を参照してください。

3-2. settings.py を分割する

次に、/config/settings.py を、開発用(Local)と本番用(Production)に分割します。
/config/settings.py は、Local 環境と Production 環境で別々のものを読み込む必要があるのですが、毎回書き換えていると大変なので、自動で切り替わるようにします。
具体的には、
1. common.py に Local 環境と Production 環境で共通の設定項目を書き込む
2. local.py は、 common.py の内容に加えて、Local 環境固有の設定項目を書き込む
3. production.py は、 common.py の内容に加えて、Production 環境固有の設定項目を書き込む
4. manage.pywsgi.py を修正する

どちらの環境にも共通している設定項目は、 common.py に書き込みます。

個別に設定すべき内容

Local 環境と Production 環境でそれぞれ固有の設定は例えば以下のようなものです。

  • DEBUG
  • DATABASE
  • ALLOWED_HOSTS
  • MEDIA_ROOT
  • STATIC_ROOT
  • LOGGING

ただし、common.py に書いている設定項目に、local.pyproduction.py で追加したい場合は、例えば以下のようにします。(配列に追加)

INSTALLED_APPS += (
    'django.contrib.admin',
)

3-2-1. common.py, local.py, production.py を作成する

まず、 /config 直下に、 settings というディレクトリを作成し、その中に /config 下の settings.py を移動させ、 common.py にリネームしてください。
また、 /config/settings ディレクトリの中に local.py, production.py の2つのファイルを新規に作成してください。
以下のようなディレクトリ構造になっていることを確認してください。

...
├─ config
│  ├─ settings           # Added
|  |  ├─ common.py       # Added (settings.py をリネームしたもの)
|  |  ├─ local.py        # Added
|  |  └─ production.py   # Added
...

3-2-2. BASE_DIR を修正する

common.py の最初のほうにある BASE_DIR を以下のように変更してください。

/config/settings/common.py
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
...

/config/settings/common.py
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
...

3-2-3. local.py にLocal 環境固有の設定を書き込む

local.py に、 common.py の内容に加えて、Local 環境で固有の設定項目を書き込みます。
common.py の内容を以下のようにimportします。

/config/settings/local.py
from .common import *

あとは、個別に設定すべき内容 を書けばよいだけです。
これを踏まえると、 local.py は例えば以下のようになります。

/config/settings/local.py
from .common import *

DEBUG = True

ALLOWED_HOSTS = [
    '0.0.0.0',
    '127.0.0.1',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
        'PASSWORD': 'somepassword',
    }
}

3-2-3. production.py にProduction 環境固有の設定を書き込む

production.py に、 common.py の内容に加えて、Production 環境で固有の設定項目を書き込みます。
local.py と同様に、 common.py の内容を以下のようにimportします。

/config/settings/production.py
from .common import *

あとは、個別に設定すべき内容 を書けばよいだけです。以下の項目は一例です。自身の環境に合わせて、適宜対応してください。

3-2-3-1. DEBUG

Production 環境では、DEBUGFALSE にします。

/config/settings/production.py
...
DEBUG = False

3-2-3-2. ALLOWED_HOSTS

ALLOWED_HOSTS に自身のアプリのドメインを追加します。ただし、 XXX.YYY.ZZZ.elasticbeanstalk.com の部分は1で確認した自分のアプリのドメインに置き換えてください。

/config/settings/production.py
...
ALLOWED_HOSTS = [
    'XXX.YYY.ZZZ.elasticbeanstalk.com',
]

3-2-3-3. DATABASES

DATABASES を、本番環境の RDS のものに書き換えます。 'RDS_~' という変数を使えば、Elastic Beanstalk のほうで勝手に書き換えてくれます。
'ENGINE'local.py とは変わっていることに注意してください。

/config/settings/production.py
...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': os.environ['RDS_DB_NAME'],
        'USER': os.environ['RDS_USERNAME'],
        'PASSWORD': os.environ['RDS_PASSWORD'],
        'HOST': os.environ['RDS_HOSTNAME'],
        'PORT': os.environ['RDS_PORT'],
    }
}

3-2-3-4. STATIC_ROOT

STATIC_ROOT を追加します。

/config/settings/production.py
...
STATIC_ROOT = os.path.join(BASE_DIR, 'www', 'static')

以上を踏まえると、全体として production.py は例えば以下のようになります。ただし、 XXX.YYY.ZZZ.elasticbeanstalk.com の部分は1で確認した自分のアプリのドメインに置き換えてください。

/config/settings/production.py
from .common import *

DEBUG = False

ALLOWED_HOSTS = [
    'XXX.YYY.ZZZ.elasticbeanstalk.com',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': os.environ['RDS_DB_NAME'],
        'USER': os.environ['RDS_USERNAME'],
        'PASSWORD': os.environ['RDS_PASSWORD'],
        'HOST': os.environ['RDS_HOSTNAME'],
        'PORT': os.environ['RDS_PORT'],
    }
}

STATIC_ROOT = os.path.join(BASE_DIR, 'www', 'static')

3-2-5. common.py を修正する

common.py の、Local 環境とProduction 環境に 個別に設定すべき内容 の項目とその値(中身)をすべて削除してください。
例えば今回であれば、 DEBUGALLOWED_HOSTSDATABASES などが該当します。

3-2-6. common.pySTATIC_URL を追加する

common.py に以下を追記します。すでにある場合は飛ばして構いません。

/config/settings/common.py
...
STATIC_URL = '/static/'
...

なお、Djangoの静的ファイルの扱いについては、この記事がとても分かりやすいので、是非読んでみてください。

3-2-7. manage.pywsgi.py を修正する

ルート直下の manage.py と、/config 直下の wsgi.py の以下の部分を修正します。

...
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
...

manage.py
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
/config/wsgi.py
...
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
...

3-3. スーパーユーザー作成用のコマンドを準備する

最後に、スーパーユーザー作成用のファイルを作成していきます。スーパーユーザーの作成は、Local 環境であれば、

$ python manage.py createsuperuser

などとして、ユーザー名、メールアドレス、パスワードを入力したと思いますが、今回はサーバーに実行してもらうため、それらを手動で入力することができません。なので、事前に入力する値を設定しておいて、それを実行させます。それが前述の 3-1-2 で出てきたものです。

3-3-1. createsu.py を作成する

cms(アプリ名なので置き換えてください。)の下に management フォルダ、その下に commands フォルダを作成し、そこに createsu.py を作成してください。そのファイルに以下を書き込んでください。

8行目の XXX、9行目の XXXYYYZZZ は各自で書き換えて、どこかに控えておいてください。また、8行目の XXX と 9行目の XXX は一致させてください。
これがスーパーユーザーアカウントになります。複数作りたい場合は、 if 文の数を増やせばよいだけです。

cms/management/commands/createsu.py
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth import get_user_model

User = get_user_model()

class Command(BaseCommand):
    def handle(self, *args, **options):
        if not User.objects.filter(username="XXX").exists():
            User.objects.create_superuser(username="XXX", email="YYY", password="ZZZ")
            self.stdout.write(self.style.SUCCESS('Successfully created new super user'))

3-3-2. __init__.py を作成する

次に、作成した management, commands フォルダそれぞれの直下に __init__.py というファイルを作成してください。これらのファイルは作成するだけで、中身は何も書き込みません。

これで「アプリケーションソースバンドルの準備」は完了です。このセクションの最初にお見せした、ディレクトリ構造と同じようになっているかどうかを確認してください!

4. アプリケーションソースバンドルを作成する

あとは、作成したものを zip にして、デプロイするだけです。

4-1. zip ファイルを作成する

何も難しいことはないかと思いますが、 zip にする対象について。
基本的にプロジェクト直下のファイル、フォルダをまとめて zip にします。(プロジェクトのディレクトリそのものzip にするわけではない)
ただし、例えば git を使っているのであれば、 .git フォルダや、 .gitignoreDocker を使っているのであれば、Dockerfile や、 docker-compose.yml などがあると思いますが、それらは含めません。アプリケーションに必要なものだけを対象にしてください。
必要であれば以下を参照してください

Mac, Linux の場合

例えばプロジェクトのルートディレクトリで、以下のようなを実行すれば、プロジェクトの一つ上の階層に myapp.zip が生成されます。( . から始まるものは、 .ebextensions しか含まれないので、ほかに含める必要のあるファイルやフォルダがあれば適宜対応してください。)

$ zip ../myapp.zip -r * .ebextensions

Windowsの場合

コマンドプロンプトやPowershellからもできますが、コマンドが長すぎるのと、含めないファイル(フォルダ)の設定がややこしいのでGUIでやります。以下のように、必要なファイルとフォルダを選択して、
右クリック→送る→圧縮(zip形式)フォルダー
とすれば作成できます。

image.png

4-2. アップロードしてデプロイする

いよいよ、サーバーにアップロードしてデプロイします。
コンソールの実行バージョンの下の、「アップロードとデプロイ」をクリックして、先ほど作成した zip ファイルを選択します。
バージョンラベルは自分でバージョンを区別できるわかりやすいものを付けると良いでしょう。

あとは、「デプロイ」ボタンを押して完了です。
最初のデプロイは完了までに数分かかることがあるので辛抱強く待ってください。

エラーが出ていなければデプロイ完了です。自身のアプリのURLにアクセスして、スーパーユーザーアカウントにログインできるか、などを確認してみましょう。

以上です。お疲れさまでした。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

health checkを除外してCloudWatchのログを眺めたい。

やりたいこと

表題の通りです。

なぜ?

小さなシステムの動作チェックを担当した際に、ログ周りはCloudWatchに書き出されているので、手っ取り早くそちらを眺めました。
でも、health checkのログが多すぎて本来見たいログが埋もれてしまって悲しかった、というのが背景です...。

前提条件

  • AWSの管理コンソールから見るのではなく、awslogsコマンドで手元のターミナルで見たい
  • health checkっぽいのは除外したい
  • health checkを叩いてくるのはロードバランサ (ELB)
  • ヘルスチェックのログ出力自体は、まだ調整中なので抑止せずに書き出しておきたい(わがままで申し訳ないです...)
  • Filter options (--filter-pattern) を使って絞り込む

やってみる

Nginxのログっぽいもので試します。

awslogsのコマンドラインオプションはこの通り。

  • -S オプションは、出力行にロググループ名を添えない(長くなるので)
  • -G オプションは、出力行にログストリーム名を添えない(長くなるので)
  • awslogs get ロググループ名 (ロググループ名まで指定の場合)
  • awslogs get ロググループ名 ログストリーム名 (ログストリーム名まで指定の場合)

お試しデータのスクリーンショット

試しにつっこんだデータ.png

実験: フィルタ無し

  • CloudWatch上に /TestLogGroup というロググループを作成しています
  • さらに、TestStream というログストリームにログを書き出しています
  • -s 1m で直近1分のものを出力します
$ awslogs get /TestLogGroup TestStream -s 1m --aws-region="ap-northeast-1"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:50:54+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 192.0.2.10 - - [2020-05-16T11:50:56+0900] "GET /test/health_check HTTP/1.1" 200 25 "-" "ELB-HealthChecker/2.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:50:58+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 192.0.2.10 - - [2020-05-16T11:51:00+0900] "GET /test/health_check HTTP/1.1" 200 25 "-" "ELB-HealthChecker/2.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:51:03+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 192.0.2.10 - - [2020-05-16T11:51:05+0900] "GET /test/health_check HTTP/1.1" 200 25 "-" "ELB-HealthChecker/2.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:51:07+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 192.0.2.10 - - [2020-05-16T11:51:09+0900] "GET /test/health_check HTTP/1.1" 200 25 "-" "ELB-HealthChecker/2.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:51:11+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 192.0.2.10 - - [2020-05-16T11:51:13+0900] "GET /test/health_check HTTP/1.1" 200 25 "-" "ELB-HealthChecker/2.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:51:15+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
....

実験: フィルタあり

--filter-pattern='-"ELB-HealthChecker/2.0"' を添えて、ELBからのヘルスチェックを除外してみます。

ポイントは、 - (マイナス) で除外パターンを指定している点です。

awslogs get /TestLogGroup TestStream -s 1m --aws-region="ap-northeast-1" --filter-pattern='-"ELB-HealthChecker/2.0"'

# 結果が絞りこまれました!
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:56:46+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:56:50+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:56:55+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:56:59+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:57:04+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:57:08+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:57:13+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:57:18+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:57:22+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
/TestLogGroup TestStream 198.51.100.2 - - [2020-05-16T11:57:28+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"

オプションを調整してスッキリさせてみる

ロググループがわかっている、ログストリームは明示していなくても該当のロググループ内の最新のイベントで確認するだけでいい場合は、

  • -G (グループ名を表示しない)
  • -S (ストリーム名を表示しない)

オプションでもう少しスッキリします。

$ awslogs get /TestLogGroup -s 1m --aws-region="ap-northeast-1" -S -G --filter-pattern='-"ELB-HealthChecker/2.0"'

198.51.100.2 - - [2020-05-16T12:03:49+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
198.51.100.2 - - [2020-05-16T12:03:54+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
198.51.100.2 - - [2020-05-16T12:03:59+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"

あらためて

さて、上記でやりたいこととやったことを書いてしまいましたが、後々のことを考えて、自分のためのメモを添えます。

awslogsについて

AWS CloudWatch logs for Humans™ というキャッチコピーがリポジトリに書かれていますが、まさに大助かりです...。

Issueやプルリクエストも多く、Pythonで書かれているし、基本は更新系でなくapiからの取得と出力なので、OSSの素材としても良さそう!

除外パターンを複数指定したり組み合わせる場合は?

基本はCloudWatchのフィルタパターンに対応した書き方で値を渡します。

/test/health_check, HealthCheck の双方を含むケースを除外

  • - (マイナス) をつけた条件を列挙します
--filter-pattern='-"/test/health_check" -"HealthCheck"'

POSTを含むイベントを抽出したい場合

--filter-pattern='POST'

POSTを含むイベントのうち特定のエンドポイントは不要

  • 条件を列挙しますが、除外の条件は -"条件パターン" を添えます
--filter-pattern='"POST" -"/endpoint_to_ignore"'

どれかのパターンを含むイベントを抽出したい場合

  • キーワードの前に?を添えます
--filter-pattern='?index ?health'

どれかのパターンを含むイベントのうち、あるパターンは除外したい場合

  • ORの条件の後に、-"除外パターン" を添えます
  • 以下だと、index.html か /test/health_check を含む行はヒットしますが、そのうち 12:05台のイベントは除外されます
awslogs get /TestLogGroup -s 10m --aws-region="ap-northeast-1" -S -G -filter-pattern='?index ?health -"T12:05"'

# 出力例 (T12:05は除外)
.....
198.51.100.2 - - [2020-05-16T12:04:52+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
192.0.2.10 - - [2020-05-16T12:04:54+0900] "GET /test/health_check HTTP/1.1" 200 25 "-" "ELB-HealthChecker/2.0" "-"
198.51.100.2 - - [2020-05-16T12:04:58+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
198.51.100.2 - - [2020-05-16T12:06:02+0900] "GET /index.html HTTP/1.1" 200 512 "-" "Dummy-UserAgent/1.0" "-"
192.0.2.10 - - [2020-05-16T12:06:06+0900] "GET /test/health_check HTTP/1.1" 200 25 "-" "ELB-HealthChecker/2.0" "-"
.....

aws cli (aws logs filter-log-events) ではどう?

aws cliでももちろん抽出できますが、除外のパターンはちょっとうまく試せず....
JSONで受けてからjqやgrepでフィルタするといいのかもしれません。

# aws logsだと結果はjsonなので、jqで整形
aws logs filter-log-events --log-group-name /TestLogGroup --filter-pattern "ELB" | jq '.events[] | .message'

.....

"192.0.2.10 - - [2020-05-16T12:06:35+0900] \"GET /test/health_check HTTP/1.1\" 200 25 \"-\" \"ELB-HealthChecker/2.0\" \"-\""
"192.0.2.10 - - [2020-05-16T12:06:41+0900] \"GET /test/health_check HTTP/1.1\" 200 25 \"-\" \"ELB-HealthChecker/2.0\" \"-\""
"192.0.2.10 - - [2020-05-16T12:06:46+0900] \"GET /test/health_check HTTP/1.1\" 200 25 \"-\" \"ELB-HealthChecker/2.0\" \"-\""

そもそも書き出さないようにするには?

エンドポイントとしての機能は利用したいけど、そもそもログは書かなくてもいいのでは?というのもあると思います。
こんなやり方で対応できます。ほかにもいろいろあると思うので、今後試しつつ調整したいと思います。

  • NginxやApacheといったWebサーバ側では、カスタムログの設定で nolog を指定してみる
  • Railsでhealth check用のエンドポイントを持っている場合は、そのhealth checkのアクションに対してはログを出力しないように設定してみる

以上、ちょっとしたログのメモでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『Amazon Web Services 基礎からのネットワーク&サーバー構築』(2)

本記事の目標

・ネットワーク構築

大まかな手順

⓪ 少しIPアドレスの復習をする。
① ネットワークで用いるIPアドレス範囲を定める。
② VPCを作成する
③ VPCをサブネットに分割する。
④ パブリックサブネットをインターネットに接続する。

そもそもIPアドレスとは

一言でいうと「ネットワーク上で互いに重複しない唯一無二の番号

1, インターネットで使われるアドレス
・パブリックIPアドレス
・インターネットで使うので、個人が勝手に設定できない。

2, インターネットで使われないアドレス
・プライベートIPアドレス
・誰にも申請する事なく以下の範囲を自由に使える。
(IPアドレス範囲)
10.0.0.0~ 10.255.255.255
172.16.0.0~ 172.31.255.255
192.168.0.0~ 192.168.255.255

「ネットワーク部」と「ホスト部」

これらは「2のn乗で区切る」というルールがある。
よく使う区切りは「256(8乗)」と「65536(16乗)」。
192.168.0.0~ 192.168.255.255の範囲を例にとると
256   → 192.168.1.0 ~ 192.168.1.255
65536 → 192.168.0.0 ~ 192.168.255.255
みたいな

また上の例を「CIDR」「サブネットマスク」の表記にすると
256個のIPアドレスが欲しい時
192.168.1.0/24(CIDR), 192.168.1.0/255.255.255.0(サブネットマスク)

ネットワーク部のビット長のことを「プレフィックス」と言うらしい。
またAmazon VPCではプレフィックス長は「16以上」を指定する必要があるらしい。
あとIPアドレス範囲をCIDR表記する場合、その範囲を「CIDRブロック」と言うらしい。

①ネットワークで用いるIPアドレス範囲を定める

復習長かったですね。すみません。本題です。

とりあえず範囲を決めるだけなので、プライベートIPアドレス範囲からテキトーに選びます。
今回は
10.0.0.0/16
にします。

②VPCを作成する

「10.0.0.0/16のVPC領域を作る。」

1、AWSマネジメントコンソールでVPCを開く。
2、リージョン(東京)を設定する。
3、VPC領域を作成する。
名前タグ : VPC領域   IPv4 CIDR ブロック:10.0.0.0/16

Screen Shot 2020-05-16 at 10.22.42.png
今のところこんな感じ

③VPCをサブネットに分割する

②で割り当てられたCIDRブロックはそのまま使うことはあまりなく、さらに小さいCIDRブロックに分割します。例をあげると
「10.0.0.0/16の各ブロックに対して、/24の大きさで切って256分割する」
みたいな感じ。(/24はキリがいいからそうしてるだけで、実際なんでもいい)

今回は2つのサブネットに分割する。
1、パブリックサブネット (10.0.1.0/24)
  インターネットからアクセスする事を目的としたサブネット。
  後でWebサーバーを置く領域。

2、プライベートサブネット (10.0.2.0/24)
  インターネットから隔離したサブネット。
  後でDBサーバーを置く領域。

この段階では、パブリックサブネットだけ作成する。
Screen Shot 2020-05-16 at 10.31.23.png
まだインターネットと繋がってない。

④パブリックサブネットをインターネットに接続する

あるサブネットをインターネットに接続するにはどうしたらいいのか

A.インターネットゲートウェイを使う。

(具体的な手順)
1、インターネットゲートウェイを作成する。
2、②で作ったVPC領域にアタッチする。
3、サブネットごとにルートテーブルを設定する。(後ほど詳細を説明)

手順3について
まず、パブリックサブネットのデフォルトのルートテーブルを確認する。
送信先:10.0.0.0/16
ターゲット:local
今のところルートテーブルには、この設定しかない。
つまり自分が所属しているネットワーク(local)にしかパケットを転送できない。

ではどうしたらインターネットの世界(local以外)に出れるのか

A.10.0.0.0/16以外の送信先のパケットをインターネットゲートウェイに転送すればいい。

「0.0.0.0/0」というアドレス(転送先が何も設定されていない場合のデフォルトの転送先)を使う。
このデフォルトの転送先を「デフォルトゲートウェイ」と呼ぶ。
ということで、パブリックサブネットに
新しいルートテーブル
(送信先:0.0.0.0/0  ターゲット:「インターネットゲートウェイ」)
を作成する。
Screen Shot 2020-05-16 at 12.08.54.png

これでネットワークの構築ができました。
次はパブリックサブネット内にサーバー構築します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

composer installで発生したエラーの解決法

AWSを学習中の者です。
以下の記事を参考にAWSを触ってみたところエラーが発生しましたので自分用メモとして残します。
AWSでウェブアプリケーション環境構築:②RDSでDBを作成し、Laravelサンプルアプリを動かす最小構成を構築

【エラー発生箇所1】

PHP拡張モジュールインストール時にトランザクションエラーが発生

【エラー文】

Transaction check error:
file /usr/lib64/php-zts/modules/zip.so from install of php-pecl-zip-1.15.2-3.amzn2.0.1.x86_64 conflicts with file from package php-common-7.2.29-1.amzn2.x86_64

file /usr/lib64/php/modules/zip.so from install of php-pecl-zip-1.15.2-3.amzn2.0.1.x86_64 conflicts with file from package php-common-7.2.29-1.amzn2.x86_64

———————————————
競合が発生しインストールが失敗したようです。
このままでも進められないかと試みたのですが、以下のところでエラーが発生してしまいました。

【エラー発生箇所2】

php7.2をインストール後、composer installしたところでエラーが発生

【エラー文】

Problem 1
- Installation request for laravel/framework v5.2.19 -> satisfiable by laravel/framework[v5.2.19].
- laravel/framework v5.2.19 requires ext-mbstring * -> the requested PHP extension mbstring is missing from your system.
Problem 2
- Installation request for phpunit/phpunit 4.8.23 -> satisfiable by phpunit/phpunit[4.8.23].
- phpunit/phpunit 4.8.23 requires ext-dom * -> the requested PHP extension dom is missing from your system.

To enable extensions, verify that they are enabled in your .ini files:

—————————————
エラー発生箇所1が原因でext-mbstringとext-domがインストールされなかった為インストール失敗したようです。

【試したこと】

ext-mbstringとext-domを別途インストールしました。
具体的な手順を以下に示します。

ext-mbstringのインストール手順

webサーバにSSHログイン後、ターミナル上で以下のように入力します。

cd /var/www/html/laravel-sample
php -v 
yum list | grep "\-mbstring"

実行結果
実行結果.png

php-mbstring.x86_64がインストール可能のようなのでインストールします。

sudo  yum install php-mbstring.x86_64

インストール完了.png

ext-mbstringがインストールできました。

ext-domのインストール手順

ext-domはphp-xmlをインストールすることでext-domを導入できるそうです。
以下のコマンドでphp7.2(自分の環境)でインストール可能なphp-xmlを探します。

 yum list php* | grep amzn2extra-php7.2

実行結果(一部)
一覧一部.png

php-xml.x86_64がインストール可能のようなのでインストールします。

 sudo yum install php-xml.x86_64

実行結果
インストール完了2.png

php-xmlがインストールできました。

もう一度composer installを実行

composer installが失敗した原因となるエラーを解決できたのでもう一度composer installを実行します。

cd /var/www/html/laravel-sample
composer install

実行結果
インストール完了3.png

composer installが実行できました。

参考にしたサイト一覧

Amazon Linuxでphpでmbstringを使う

composerでlaravelを導入しようとして発生したエラー「ext-mbstring」「ext-dom」

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ECRスキャンをCDKから作成したらスキャンの裏側も見れたよ

初めに

ECRのスキャン機能使ったこと無かったので、CDKで作りました

作り方

下記のように、Repositoryの引数にimage_scan_on_pushを追加するだけで自動スキャン機能が使えます
CDK便利ー

from aws_cdk import (
    aws_ecr as ecr,
    core,
)

repository = ecr.Repository(self, "Repo",
    image_scan_on_push=True
)

上記を実行すると、ECRとECRImageScanOnPushが出来ました

$ cdk diff repo
...
Resources
[+] AWS::ECR::Repository Repo Repo02AC86CF 
[+] Custom::ECRImageScanOnPush Repo/ImageScanOnPush/Resource RepoImageScanOnPush94CFD98F 
[+] AWS::IAM::Role AWS679f53fac002430cb0da5b7982bd2287/ServiceRole AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2 
[+] AWS::IAM::Policy AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/DefaultPolicy AWS679f53fac002430cb0da5b7982bd2287ServiceRoleDefaultPolicyD28E1A5E 
[+] AWS::Lambda::Function AWS679f53fac002430cb0da5b7982bd2287 AWS679f53fac002430cb0da5b7982bd22872D164C4C 
...

実際に出来ているかもCLIから確認してみると、確かに出来てることが確認できました
また、image scanの設定も入っていました

$ aws --region us-east-1 ecr describe-repositories | jq .
{
  "repositories": [
    {
      "repositoryArn": "arn:aws:ecr:us-east-1:000000000000:repository/repo-repo0-ny7qkwdk6aru",
      "registryId": "000000000000",
      "repositoryName": "repo-repo0-ny7qkwdk6aru",
      "repositoryUri": "000000000000.dkr.ecr.us-east-1.amazonaws.com/repo-repo0-ny7qkwdk6aru",
      "createdAt": 1589559800,
      "imageTagMutability": "MUTABLE",
      "imageScanningConfiguration": {
        "scanOnPush": true
      }
    }
  ]
}

余談

上記でやりたいことは完了したのですが、リソース作成時に下記のようにECR以外のものが出来ていました
こちらも出来ているか確認してみましょう

[+] AWS::IAM::Role AWS679f53fac002430cb0da5b7982bd2287/ServiceRole AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2 
[+] AWS::IAM::Policy AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/DefaultPolicy AWS679f53fac002430cb0da5b7982bd2287ServiceRoleDefaultPolicyD28E1A5E 
[+] AWS::Lambda::Function AWS679f53fac002430cb0da5b7982bd2287 AWS679f53fac002430cb0da5b7982bd22872D164C4C 

まずはLambdaですが、AWSと書かれたリソースはありませんでした

$ aws --region us-east-1 lambda list-functions | jq .Functions[].FunctionName | grep AWS
$ 

次にIAM Roleですが、こちらもありません
なので、それに紐づくIAM Policyも見つかりませんでした

$ aws --region us-east-1 iam list-roles | jq .Roles[].RoleName | grep AWS679f53fac002430cb0da5b7982bd2287
$ 

つまり、ユーザ側で設定や確認できるリソースではなくAWS側のリソースが出ているのではないかと思います
おそらくECRのスキャンをする時のLambdaとそのIAM Roleになるのかなぁと思います
多分そのうち修正されると思うのですが、ちょっとAWSの内側を知れた気分でした

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

『Amazon Web Services 基礎からのネットワーク&サーバー構築』(1)

はじめに

本記事はインフラ超初心者の方におすすめです。
本書を購入しようと思ったきっかけは、色々なサイトを参考にしてAWSにWordPress環境を構築しようとしたもののうまくいかず、そもそもVPSやLinuxコマンドなど基本的な事に関しても理解できてなかったからです。
本記事では、自分が知らなかったことを中心にメモしていきます。
EK-0824332.jpg
Amazonから購入したい方はこちら
https://www.amazon.co.jp/Amazon-Web-Services-基礎からのネットワーク-サーバー構築/dp/4822237443

本書の目的

インフラにあまり詳しくない人でも、自分でネットワークやサーバーを構築できるようになること。

システム構築をインフラから始めるメリット

ほとんどの開発現場では以下の2つの役割で分かれている。
・「アプリケーションエンジニア
・「インフラエンジニア
多くのアプリケーションエンジニアは、「誰かが作ったインフラ」の上にアプリを作っている。
つまり、システム全体が見えていないため、障害などに対応しにくい。
そのため「システム構築をインフラから始める」のは重要な事である。

サーバーとは

「Webサーバー」「データベースサーバー」「メールサーバー」など用途別に色々ある。
これらは「サーバーに対してそれぞれの機能を提供するソフトウェアをインストールしたもの」である。
そもそもサーバーとは「Linuxなどのサーバー用OSをインストールしたコンピュータ」である。

要するに
①サーバーOSをインストール (Linux, Windows Serverなど)
②ソフトウェアをインストール (Apache, MySQL, Sendmailなど)
これでサーバーは構築できる。

ネットワークとは

以下の3つが重要である。
1、IPアドレスをどのように定めるか。
2、ルータを介したインターネットとのデータの流れをどのように制御するか。
3、DNSとIPの対応。

本書の課題『何もないところからWordPressでブログシステムを作る』

Screen Shot 2020-05-15 at 21.45.06.png

こんな感じで構築するのが目標。

「パブリックサブネット」
インターネットに接続し、公開している。

「プライベートサブネット」
インターネットに接続しない。いたずらされたくないから隠してる。

「NAT」
DBだってソフトウェアをインターネットからダウンロードして、インストールやアップデートしたい時もある。
「インターネット→DB」は不可能で「DB→インターネット」だけ可能にしたい。
これを実現してくれるのが「NAT」です。

ネットワークの分割(サブネット)
①Amazon VPCを作成
②分割したサブネットを作成
③それぞれのサブネットの中にサーバーを配置
みたいな手順。

まとめ

少し読むだけで、全体像が見えた気がする。あとはそれぞれの仕組みの理解と実装かな。
早く終わらせたい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む