20210512のAWSに関する記事は22件です。

AWS CloudFormationでLambda Layerを使用したSlack通知定期実行Lambdaを構築しよう

はじめに AWS CloudFormationを利用してLambda Layerを使用したSlack通知定期実行Lambdaの構築のテンプレートのサンプルです。 CloudWatchにて、Lambdaを定期実行します。また、Lambdaは、S3アーティファクトを使用します。 通知内容は起動しているEC2インスタンスを停止する際の情報になります。 テンプレートの概要が分からない場合は、はじめてのAWS CloudFormationテンプレートを理解するを参考にしてください。 コードはGitHubにもあります。 今回は、akane というシステムの dev 環境を想定しています。 同じ構成で違う環境を作成する場合は、{環境名}-parameters.jsonを別途作成します。 ディレクトリ構成 akane (システム) ├── lambda (スタック) │ ├── code │ │ └── getEC2InfoToSlack.py (S3アーティファクトソース) │ ├── code-lambda-getEC2InfoToSlack.zip (S3アーティファクト) │ ├── delete_artifact.dev.sh (S3アーティファクト削除シェル) │ ├── dev-parameters.json (dev 環境のパラメータ) │ ├── lambda.yml (CFnテンプレート) │ ├── mkzip.sh (S3アーティファクト作成シェル) │ └── upload_artifact.dev.sh (S3アーティファクトアップロードシェル) ├── lambda-layer │ ├── all-parameters.json (all 環境のパラメータ) │ ├── code │ │ └── python │ │ ├── requirements.txt │ │ └── setSlackWebHook.py (S3アーティファクトソース) │ ├── code-lambda-setSlackWebHook.zip (S3アーティファクト) │ ├── delete_artifact.all.sh (S3アーティファクト削除シェル) │ ├── lambda-layer.yml (CFnテンプレート) │ ├── mkzip.sh (S3アーティファクト作成シェル) │ └── upload_artifact.all.sh (S3アーティファクトアップロードシェル) └─ s3 (スタック) ├─ s3.yml (CFnテンプレート) └─ all-parameters.json (all 環境のパラメータ) AWS リソース構築内容 lambdaスタック Lambdaロール Lambda lambda-layerスタック Lambda-layer s3スタック s3バケット (akane-all-s3-artifacts) バケットポリシー (s3:GetObject) 実行環境の準備 AWS CloudFormationを動かすためのAWS CLIの設定を参考にしてください。 AWS リソース構築準備 akane/lambda/dev-parameters.json の SlackWebHookUrlにSlack Incoming WebhookのURLを記述する。 ※ incoming-webhookにて作成する akane/lambda/dev-parameters.json の SlackChannelにSlack通知のチェンネル名を記述する。 #test_slack AWS リソース構築手順 下記を実行してスタックを作成 ./create_stacks.sh ※ 実行後、AWS Certificate Manager にて、対象ドメインを選択し、Route 53 でのレコード作成を押下する。 下記を実行してLambdaの動作を確認 ./test_lambda.sh 下記を実行してスタックを削除 ./delete_stacks.sh 構築テンプレート 1. s3スタック s3.yml AWSTemplateFormatVersion: 2010-09-09 Description: S3 For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. # Mappings # Conditions # Transform Resources: # S3 Bucket作成 akaneS3Bucket: Type: AWS::S3::Bucket Properties: AccessControl: Private BucketName: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType # S3 BucketPolicy作成 akaneS3BucketPolicy: Type: AWS::S3::BucketPolicy DependsOn: akaneS3Bucket Properties: Bucket: !Ref akaneS3Bucket PolicyDocument: Statement: - Action: - s3:GetObject Effect: Allow Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref akaneS3Bucket - /* Principal: AWS: '*' Outputs: akaneS3Bucket: Value: !Ref akaneS3Bucket Export: Name: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} all-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "all" } ] } 2. lambda-layerスタック lambda-layer.yml AWSTemplateFormatVersion: 2010-09-09 Description: Lambda Layer For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. ArtifactS3Bucket: Type: String LambdaLayerName: Type: String CompatibleRuntime1: Type: String # Mappings # Conditions # Transform Resources: # LambdaLayer 作成 akaneLambdaLayerSetSlackWebHook: Type: AWS::Lambda::LayerVersion Properties: CompatibleRuntimes: - !Ref CompatibleRuntime1 Content: S3Bucket: !Ref ArtifactS3Bucket S3Key: !Sub - code-lambda-${LambdaLayerName}.zip - {LambdaLayerName: !Ref LambdaLayerName} Description: !Sub - ${SystemName}-${EnvType}-lambda-layer-${LambdaLayerName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaLayerName: !Ref LambdaLayerName} LayerName: !Ref LambdaLayerName LicenseInfo: MIT Outputs: akaneLambdaLayerSetSlackWebHook: Value: !Ref akaneLambdaLayerSetSlackWebHook Export: Name: !Sub - ${SystemName}-${EnvType}-lambda-layer-arn-${LambdaLayerName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaLayerName: !Ref LambdaLayerName} all-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "all" }, { "ParameterKey": "ArtifactS3Bucket", "ParameterValue": "akane-all-s3-artifacts" }, { "ParameterKey": "LambdaLayerName", "ParameterValue": "setSlackWebHook" }, { "ParameterKey": "CompatibleRuntime1", "ParameterValue": "python3.8" } ] } 3. lambdaスタック lambda.yml AWSTemplateFormatVersion: 2010-09-09 Description: Lambda For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. EnvTypeCommon: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. ArtifactS3Bucket: Type: String LambdaName: Type: String LambdaMemorySize: Type: Number LambdaRuntime: Type: String SlackWebHookUrl: Type: String SlackChannel: Type: String LambdaLayerName: Type: String # Mappings # Conditions # Transform Resources: # ロール 作成 akaneRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Description: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess Path: / Policies: - PolicyName: ec2 PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - ec2:Start* - ec2:Stop* Resource: '*' RoleName: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType # Lambda 作成 akaneLambdaGetEC2InfoToSlack: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Ref ArtifactS3Bucket S3Key: !Sub - code-lambda-${LambdaName}.zip - {LambdaName: !Ref LambdaName} Description: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Environment: Variables: SLACK_WEB_HOOK_URL: !Ref SlackWebHookUrl SLACK_CHANNEL: !Ref SlackChannel FunctionName: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Handler: !Sub - ${LambdaName}.handler - {LambdaName: !Ref LambdaName} Layers: - Fn::ImportValue: !Sub - ${SystemName}-${EnvTypeCommon}-lambda-layer-arn-${LambdaLayerName} - {SystemName: !Ref SystemName, EnvTypeCommon: !Ref EnvTypeCommon, LambdaLayerName: !Ref LambdaLayerName} MemorySize: !Ref LambdaMemorySize Role: !GetAtt akaneRole.Arn Runtime: !Ref LambdaRuntime Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType Timeout: 900 TracingConfig: Mode: PassThrough # スケジュール 作成 akaneEventsRule: Type: AWS::Events::Rule Properties: Description: !Sub - ${SystemName}-${EnvType}-rule-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Name: !Sub - ${SystemName}-${EnvType}-rule-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} ScheduleExpression: "rate(24 hours)" State: ENABLED Targets: - Arn: !GetAtt akaneLambdaGetEC2InfoToSlack.Arn Id: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} # LambdaPermission 作成 akaneLambdaPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt akaneLambdaGetEC2InfoToSlack.Arn Principal: events.amazonaws.com SourceArn: !GetAtt akaneEventsRule.Arn Outputs: akaneLambdaGetEC2InfoToSlackArn: Value: !GetAtt akaneLambdaGetEC2InfoToSlack.Arn Export: Name: !Sub - ${SystemName}-${EnvType}-lambda-arn - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} dev-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "dev" }, { "ParameterKey": "EnvTypeCommon", "ParameterValue": "all" }, { "ParameterKey": "ArtifactS3Bucket", "ParameterValue": "akane-all-s3-artifacts" }, { "ParameterKey": "LambdaName", "ParameterValue": "getEC2InfoToSlack" }, { "ParameterKey": "LambdaMemorySize", "ParameterValue": "128" }, { "ParameterKey": "LambdaRuntime", "ParameterValue": "python3.8" }, { "ParameterKey": "SlackWebHookUrl", "ParameterValue": "https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX" }, { "ParameterKey": "SlackChannel", "ParameterValue": "#test_slack" }, { "ParameterKey": "LambdaLayerName", "ParameterValue": "setSlackWebHook" } ], "Capabilities": [ "CAPABILITY_NAMED_IAM" ] } 4. 実行ファイル create_stacks.sh #!/bin/sh cd `dirname $0` SYSTEM_NAME=akane create_stack () { ENV_TYPE=$1 STACK_NAME=$2 aws cloudformation create-stack \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} \ --template-body file://./${SYSTEM_NAME}/${STACK_NAME}/${STACK_NAME}.yml \ --cli-input-json file://./${SYSTEM_NAME}/${STACK_NAME}/${ENV_TYPE}-parameters.json aws cloudformation wait stack-create-complete \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} } create_stack all s3 ./akane/lambda-layer/mkzip.sh ./akane/lambda-layer/upload_artifact.all.sh create_stack all lambda-layer ./akane/lambda/mkzip.sh ./akane/lambda/upload_artifact.dev.sh create_stack dev lambda exit 0 test_lambda.sh #!/bin/sh cd `dirname $0` LAMBDA_NAME=akane-dev-lambda-getEC2InfoToSlack OUTPUT_FILE=response.json aws lambda invoke --function-name ${LAMBDA_NAME} --log-type Tail ${OUTPUT_FILE} --query 'LogResult' --output text | base64 -D cat ${OUTPUT_FILE} exit 0 delete_stacks.sh #!/bin/sh cd `dirname $0` SYSTEM_NAME=akane delete_stack () { ENV_TYPE=$1 STACK_NAME=$2 aws cloudformation delete-stack \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} aws cloudformation wait stack-delete-complete \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} } delete_stack dev lambda ./akane/lambda/delete_artifact.dev.sh delete_stack all lambda-layer ./akane/lambda-layer/delete_artifact.all.sh delete_stack all s3 exit 0 4. アーティファクト関連ファイル mkzip.sh #!/bin/sh cd `dirname $0` ENV_TYPE=dev LAMBDA_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') FILE=../code-lambda-${LAMBDA_NAME}.zip cd ./code ls . | grep -v -E ".gitignore|${LAMBDA_NAME}.py" | xargs rm -rf rm -f ${FILE} zip -r ${FILE} ./* exit 0 upload_artifact.dev.sh #!/bin/sh cd `dirname $0` BASENAME=$(basename $0) FILENAME=${BASENAME%.*} ENV_TYPE=${FILENAME##*.} BUCKET_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "ArtifactS3Bucket").ParameterValue') ARTIFACT_NAME=code-lambda-$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') aws s3 cp ${ARTIFACT_NAME}.zip s3://${BUCKET_NAME}/${ARTIFACT_NAME}.zip exit 0 delete_artifact.dev.sh #!/bin/sh cd `dirname $0` BASENAME=$(basename $0) FILENAME=${BASENAME%.*} ENV_TYPE=${FILENAME##*.} BUCKET_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "ArtifactS3Bucket").ParameterValue') ARTIFACT_NAME=code-lambda-$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') aws s3 rm s3://${BUCKET_NAME}/${ARTIFACT_NAME}.zip exit 0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CloudFormationでLambda Layerを使用したSlack通知を構築しよう

はじめに AWS CloudFormationを利用してLambda Layerを使用したSlack通知構築のテンプレートのサンプルです。 CloudWatchにて、Lambdaを定期実行します。また、Lambdaは、S3アーティファクトを使用します。 通知内容は起動しているEC2インスタンスを停止する際の情報になります。 テンプレートの概要が分からない場合は、はじめてのAWS CloudFormationテンプレートを理解するを参考にしてください。 コードはGitHubにもあります。 今回は、akane というシステムの dev 環境を想定しています。 同じ構成で違う環境を作成する場合は、{環境名}-parameters.jsonを別途作成します。 ディレクトリ構成 akane (システム) ├── lambda (スタック) │ ├── code │ │ └── getEC2InfoToSlack.py (S3アーティファクトソース) │ ├── code-lambda-getEC2InfoToSlack.zip (S3アーティファクト) │ ├── delete_artifact.dev.sh (S3アーティファクト削除シェル) │ ├── dev-parameters.json (dev 環境のパラメータ) │ ├── lambda.yml (CFnテンプレート) │ ├── mkzip.sh (S3アーティファクト作成シェル) │ └── upload_artifact.dev.sh (S3アーティファクトアップロードシェル) ├── lambda-layer │ ├── all-parameters.json (all 環境のパラメータ) │ ├── code │ │ └── python │ │ ├── requirements.txt │ │ └── setSlackWebHook.py (S3アーティファクトソース) │ ├── code-lambda-setSlackWebHook.zip (S3アーティファクト) │ ├── delete_artifact.all.sh (S3アーティファクト削除シェル) │ ├── lambda-layer.yml (CFnテンプレート) │ ├── mkzip.sh (S3アーティファクト作成シェル) │ └── upload_artifact.all.sh (S3アーティファクトアップロードシェル) └─ s3 (スタック) ├─ s3.yml (CFnテンプレート) └─ all-parameters.json (all 環境のパラメータ) AWS リソース構築内容 lambdaスタック Lambdaロール Lambda lambda-layerスタック Lambda-layer s3スタック s3バケット (akane-all-s3-artifacts) バケットポリシー (s3:GetObject) 実行環境の準備 AWS CloudFormationを動かすためのAWS CLIの設定を参考にしてください。 AWS リソース構築準備 akane/lambda/dev-parameters.json の SlackWebHookUrlにSlack Incoming WebhookのURLを記述する。 ※ incoming-webhookにて作成する AWS リソース構築手順 下記を実行してスタックを作成 ./create_stacks.sh ※ 実行後、AWS Certificate Manager にて、対象ドメインを選択し、Route 53 でのレコード作成を押下する。 下記を実行してLambdaの動作を確認 ./test_lambda.sh 下記を実行してスタックを削除 ./delete_stacks.sh 構築テンプレート 1. s3スタック s3.yml AWSTemplateFormatVersion: 2010-09-09 Description: S3 For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. # Mappings # Conditions # Transform Resources: # S3 Bucket作成 akaneS3Bucket: Type: AWS::S3::Bucket Properties: AccessControl: Private BucketName: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType # S3 BucketPolicy作成 akaneS3BucketPolicy: Type: AWS::S3::BucketPolicy DependsOn: akaneS3Bucket Properties: Bucket: !Ref akaneS3Bucket PolicyDocument: Statement: - Action: - s3:GetObject Effect: Allow Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref akaneS3Bucket - /* Principal: AWS: '*' Outputs: akaneS3Bucket: Value: !Ref akaneS3Bucket Export: Name: !Sub - ${SystemName}-${EnvType}-s3-artifacts - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} all-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "all" } ] } 2. lambda-layerスタック lambda-layer.yml AWSTemplateFormatVersion: 2010-09-09 Description: Lambda Layer For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. ArtifactS3Bucket: Type: String LambdaLayerName: Type: String CompatibleRuntime1: Type: String # Mappings # Conditions # Transform Resources: # LambdaLayer 作成 akaneLambdaLayerSetSlackWebHook: Type: AWS::Lambda::LayerVersion Properties: CompatibleRuntimes: - !Ref CompatibleRuntime1 Content: S3Bucket: !Ref ArtifactS3Bucket S3Key: !Sub - code-lambda-${LambdaLayerName}.zip - {LambdaLayerName: !Ref LambdaLayerName} Description: !Sub - ${SystemName}-${EnvType}-lambda-layer-${LambdaLayerName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaLayerName: !Ref LambdaLayerName} LayerName: !Ref LambdaLayerName LicenseInfo: MIT Outputs: akaneLambdaLayerSetSlackWebHook: Value: !Ref akaneLambdaLayerSetSlackWebHook Export: Name: !Sub - ${SystemName}-${EnvType}-lambda-layer-arn-${LambdaLayerName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaLayerName: !Ref LambdaLayerName} all-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "all" }, { "ParameterKey": "ArtifactS3Bucket", "ParameterValue": "akane-all-s3-artifacts" }, { "ParameterKey": "LambdaLayerName", "ParameterValue": "setSlackWebHook" }, { "ParameterKey": "CompatibleRuntime1", "ParameterValue": "python3.8" } ] } 3. lambdaスタック lambda.yml AWSTemplateFormatVersion: 2010-09-09 Description: Lambda For Akane # Metadata: Parameters: SystemName: Type: String AllowedPattern: '[a-zA-Z0-9-]*' EnvType: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. EnvTypeCommon: Description: Environment type. Type: String AllowedValues: [all, dev, stg, prod] ConstraintDescription: must specify all, dev, stg, or prod. ArtifactS3Bucket: Type: String LambdaName: Type: String LambdaMemorySize: Type: Number LambdaRuntime: Type: String SlackWebHookUrl: Type: String SlackChannel: Type: String LambdaLayerName: Type: String # Mappings # Conditions # Transform Resources: # ロール 作成 akaneRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Description: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess Path: / Policies: - PolicyName: ec2 PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - ec2:Start* - ec2:Stop* Resource: '*' RoleName: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-role-lambda-${AWS::Region} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType # Lambda 作成 akaneLambdaGetEC2InfoToSlack: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Ref ArtifactS3Bucket S3Key: !Sub - code-lambda-${LambdaName}.zip - {LambdaName: !Ref LambdaName} Description: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Environment: Variables: SLACK_WEB_HOOK_URL: !Ref SlackWebHookUrl SLACK_CHANNEL: !Ref SlackChannel FunctionName: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Handler: !Sub - ${LambdaName}.handler - {LambdaName: !Ref LambdaName} Layers: - Fn::ImportValue: !Sub - ${SystemName}-${EnvTypeCommon}-lambda-layer-arn-${LambdaLayerName} - {SystemName: !Ref SystemName, EnvTypeCommon: !Ref EnvTypeCommon, LambdaLayerName: !Ref LambdaLayerName} MemorySize: !Ref LambdaMemorySize Role: !GetAtt akaneRole.Arn Runtime: !Ref LambdaRuntime Tags: - Key: Name Value: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} - Key: SystemName Value: !Ref SystemName - Key: EnvType Value: !Ref EnvType Timeout: 900 TracingConfig: Mode: PassThrough # スケジュール 作成 akaneEventsRule: Type: AWS::Events::Rule Properties: Description: !Sub - ${SystemName}-${EnvType}-rule-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} Name: !Sub - ${SystemName}-${EnvType}-rule-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} ScheduleExpression: "rate(24 hours)" State: ENABLED Targets: - Arn: !GetAtt akaneLambdaGetEC2InfoToSlack.Arn Id: !Sub - ${SystemName}-${EnvType}-lambda-${LambdaName} - {SystemName: !Ref SystemName, EnvType: !Ref EnvType, LambdaName: !Ref LambdaName} # LambdaPermission 作成 akaneLambdaPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt akaneLambdaGetEC2InfoToSlack.Arn Principal: events.amazonaws.com SourceArn: !GetAtt akaneEventsRule.Arn Outputs: akaneLambdaGetEC2InfoToSlackArn: Value: !GetAtt akaneLambdaGetEC2InfoToSlack.Arn Export: Name: !Sub - ${SystemName}-${EnvType}-lambda-arn - {SystemName: !Ref SystemName, EnvType: !Ref EnvType} dev-parameters.json { "Parameters": [ { "ParameterKey": "SystemName", "ParameterValue": "akane" }, { "ParameterKey": "EnvType", "ParameterValue": "dev" }, { "ParameterKey": "EnvTypeCommon", "ParameterValue": "all" }, { "ParameterKey": "ArtifactS3Bucket", "ParameterValue": "akane-all-s3-artifacts" }, { "ParameterKey": "LambdaName", "ParameterValue": "getEC2InfoToSlack" }, { "ParameterKey": "LambdaMemorySize", "ParameterValue": "128" }, { "ParameterKey": "LambdaRuntime", "ParameterValue": "python3.8" }, { "ParameterKey": "SlackWebHookUrl", "ParameterValue": "https://hooks.slack.com/services/XXXXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX" }, { "ParameterKey": "SlackChannel", "ParameterValue": "#test_slack" }, { "ParameterKey": "LambdaLayerName", "ParameterValue": "setSlackWebHook" } ], "Capabilities": [ "CAPABILITY_NAMED_IAM" ] } 4. 実行ファイル create_stacks.sh #!/bin/sh cd `dirname $0` SYSTEM_NAME=akane create_stack () { ENV_TYPE=$1 STACK_NAME=$2 aws cloudformation create-stack \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} \ --template-body file://./${SYSTEM_NAME}/${STACK_NAME}/${STACK_NAME}.yml \ --cli-input-json file://./${SYSTEM_NAME}/${STACK_NAME}/${ENV_TYPE}-parameters.json aws cloudformation wait stack-create-complete \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} } create_stack all s3 ./akane/lambda-layer/mkzip.sh ./akane/lambda-layer/upload_artifact.all.sh create_stack all lambda-layer ./akane/lambda/mkzip.sh ./akane/lambda/upload_artifact.dev.sh create_stack dev lambda exit 0 test_lambda.sh #!/bin/sh cd `dirname $0` LAMBDA_NAME=akane-dev-lambda-getEC2InfoToSlack OUTPUT_FILE=response.json aws lambda invoke --function-name ${LAMBDA_NAME} --log-type Tail ${OUTPUT_FILE} --query 'LogResult' --output text | base64 -D cat ${OUTPUT_FILE} exit 0 delete_stacks.sh #!/bin/sh cd `dirname $0` SYSTEM_NAME=akane delete_stack () { ENV_TYPE=$1 STACK_NAME=$2 aws cloudformation delete-stack \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} aws cloudformation wait stack-delete-complete \ --stack-name ${SYSTEM_NAME}-${ENV_TYPE}-${STACK_NAME} } delete_stack dev lambda ./akane/lambda/delete_artifact.dev.sh delete_stack all lambda-layer ./akane/lambda-layer/delete_artifact.all.sh delete_stack all s3 exit 0 4. アーティファクト関連ファイル mkzip.sh #!/bin/sh cd `dirname $0` ENV_TYPE=dev LAMBDA_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') FILE=../code-lambda-${LAMBDA_NAME}.zip cd ./code ls . | grep -v -E ".gitignore|${LAMBDA_NAME}.py" | xargs rm -rf rm -f ${FILE} zip -r ${FILE} ./* exit 0 upload_artifact.dev.sh #!/bin/sh cd `dirname $0` BASENAME=$(basename $0) FILENAME=${BASENAME%.*} ENV_TYPE=${FILENAME##*.} BUCKET_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "ArtifactS3Bucket").ParameterValue') ARTIFACT_NAME=code-lambda-$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') aws s3 cp ${ARTIFACT_NAME}.zip s3://${BUCKET_NAME}/${ARTIFACT_NAME}.zip exit 0 delete_artifact.dev.sh #!/bin/sh cd `dirname $0` BASENAME=$(basename $0) FILENAME=${BASENAME%.*} ENV_TYPE=${FILENAME##*.} BUCKET_NAME=$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "ArtifactS3Bucket").ParameterValue') ARTIFACT_NAME=code-lambda-$(cat ${ENV_TYPE}-parameters.json | jq -r '.Parameters[] | select(.ParameterKey == "LambdaName").ParameterValue') aws s3 rm s3://${BUCKET_NAME}/${ARTIFACT_NAME}.zip exit 0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudFormationで空のスタックを作成する

Conditions: HasNot: !Equals [ 'true', 'false' ] # dummy (null) resource, never created Resources: NullResource: Type: 'Custom::NullResource' Condition: HasNot ダミーとして空のスタックを一旦作ってからにすると、スタックが削除されるロールバックがなくなって開発が楽になる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS_13.1]php -vで「No such file or directory」のエラー

環境 MacBook Pro (13-inch, 2016, Four Thunderbolt 3 Ports) macOS 11.3.1(20E241) AWS EC2 t2.micro エラー # php -v -bash: /usr/bin/php: No such file or directory # which php /usr/bin/which: no php in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin) どうやら[AWS_13]でPHP既存の削除して、新しいバージョンのPHPを有効化したものの、新しいバージョンそのものはダウンロードできていなかったらしい。 PHPをダウンロードして、確認 # amazon-linux-extras install php7.4 (省略) # php -v PHP 7.4.15 (cli) (built: Feb 11 2021 17:53:39) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies # which php /usr/bin/php
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VMware SD-WAN on Equinix Network Edge と AWS との接続 ~専用線いらずのマルチクラウド接続〜

SD-WAN を用いたマルチクラウド接続(AWS編) 最近では自社のオンプレミス環境(Data Center)以外にも複数のクラウドを活用しているユーザーがどんどん増えて来ているかと思います。 クラウドも AWS, Azure, GCP や VMware の仮想化技術(NSX, vSAN, vSphere)を用いてサービス提供をしているVMware Cloud on AWS、Azure VMware Solution、Google Cloud VMware Engine、Oracle Cloud VMware Solution、と様々なクラウドが提供されています。 大規模な環境においては、今までは上記のクラウドとの接続には専用線を用いることが多いかと思いますが、SD-WAN を用いることによって、専用線や専用ハードウェアを使わずに即座にクラウドに接続することが出来ます。 今回は下記のようなトポロジーで Equinix の Network Edge というプラットフォーム上に VMware SD-WAN Edge をデプロイし、AWS と接続する設定、手順について記載します。 Virtual VeloCloud Edge を Equinix Network Edge 上に作成 # 基本的にはこちらのマニュアル通りに設定いただければ問題ないはずです。 https://docs.equinix.com/ja/Content/Interconnection/NE/user-guide/NE-create-VMware-Edge-Instance.htm VMware SD-WAN Orchestrator から Virtual Edge を作成 VMware SD-WAN Orchestrator(以下VCO)にログインし、New Edge から作成します。 GE1 の WAN Overlay と NAT Direct Traffic のチェックを外します。 ※ GE1 は Equinix との Management 用で、特に WAN Overlay のチェックを外しておかないと、Equinix Portal からデプロイが正常に認識されません。 GE2 でも NAT Direct Traffic のチェックを外しておきます。(必須ではないです。) アクティベーションキーの情報を控えておきます。(Equinix Portal からのデプロイ時に必要になります。) VMware SD-WAN 側はこれだけで最低限の準備は完了となります。 Equinix Fabric で VMware SD-WAN Edge を作成 Equinix Fabric Portalへログインし、Network Edge タブから 仮想デバイスの作成 を選択します。 今回は Single Virtual Device を選択し、 VMware SD-WAN Edge Instance を選択します。 内容をザラッと確認し、 Virtual VeloCloud Edge をデプロイしたいリージョンを選びます。(Tokyo が2021年5月にローンチされています) サイズやバージョンなどを選択し、Device Name(任意)、先に控えておいた Activation Key を貼り付け、VCOのFQDNを入力します。 (Equinix Portal には VCOとバージョンが同じでないといけない、という記載がありますが、ずれていても問題ありません。デプロイ時にバージョンを上げてくれます) Interface数は現時点では8個で固定です。(クラウド向けInterface数は5個となります。数も増やせないので注意が必要です。) VeloCloud Edge に対しての Inbound Rule を設定する必要がありますが、VeloCloud自身のセキュリティが強固なので、permit anyで問題ないですが、設定が必要な場合には、UDP2426 だけ空けておけばOKです。 Internet側向けの Bandwidthを設定します。15Mbpsまでは無料。(リージョンによって選択できる数値は変わるようです。) 最後に Create Device を押せば、自動でプロビジョニングが完了します。 以下は VMware SD-WAN Orchestrator の画面です。 AWS との接続準備 まず、AWS の Account ID を確認しておく必要があります。(Equinix Portal で Virtual Circuit を作成する際に必要となります) Equinix Fabric Portal から先程作成した Virtual VeloCloud Edge を選択し、接続の作成(Create Connection)を選択します 今回は AWS との接続なので、AWS を選択します。 ※ VMware Cloud on AWS の場合も同様です。 AWS Direct Connect を選択し、利用可能な拠点に Tokyo があることを確認しておきます。 接続元に先程作成した Virtual VeloCloud Edge を選択し、接続先はAWSのAPAC内のTokyoを選択します。(レイテンシーが参考として載っていますが、Tokyoは1msと超低レイテンシーです) ここで AWS Account ID を入力し、VeloCloud Edge と AWS 間の Virtual Circuit の帯域を選択します。 内容に問題がなければ オーダーを送信 を押せば、Virtual Circuit が AWS Tokyo リージョンまで接続されに行きます。(この時点では AWS Direct Connect とはまだつながっていません。) AWS 側の設定作業 次にAWS側と接続するために、AWS Portal にログインし、Virtual Private Gateway を作成します。 Virtual Private Gateway を VPC にアタッチします。(VPCが作成されていない場合は、VPCの作成も必要になります) Direct Connect Gateway も作成し、ここでAWS側のプライベートAS番号を設定します。 Gateway の関連付け(Associate gateway)を行います。 Equinixから Virtual Circuit のオーダーが送出されていると、State が ordering となっています。Accept を選択すると、L2接続が完了します。 Direct Connect に Virtual Interface を作成します。 Type は Private を選択し、必要事項を入力します。ここで VeloCloud Edge 側の BGP番号を入力します。 Vlan番号も入力を求められますが、この値は意識する必要はありません(後述のVeloCloud の設定でもこの Vlan は設定しません。) Additional Settings を選択すると、デバイス間のIPや、BGP MD5などがマニュアルで設定できます。 このような形で AWS 側のBGP設定が行われるので、IPアドレスや BGP authentication key を控えておきます。 この時点では BGP Peer は張られていないので、 BGP status は down となっています。 最後に Route Table の Route Propagate を有効にしておきます。 VMware SD-WAN Edge のInterface, BGP設定 VMware SD-WAN にログインし、Virtual VeloCloud Edge の Interface の設定をを行います。 どの Interaface が AWS Direct Connect 接続に使われているかは、Equinix Portal から 仮想デバイスの詳細→インタフェース から確認できます。 対象のGE4の設定を行い BGPの設定を行えば接続完了です 確認 AWS側でもVirtual InterfaceのBGP statusがupし、 VMware SD-WAN Orchestrator 側でも BGPが上がっていることを確認できました。 私の自宅にも VeloCloud Edge が置かれており、このような構成になっているのですが、 ちゃんと Pingも飛び、iperfで負荷をかけることもできましたw # 帯域が少ないのは、instanceサイズが小さいためとなります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon EC2(Windows OS)でSSLサイト(IIS利用)を構築する

以前にAmazon EC2(CentOS)でSSLサイトをApacheを使って構築する記事を書きましたが、Windows(IIS)版の記事を書いてなかったので、お試しがてら記事にします。GUIで操作できる分、コマンド操作に慣れていない方はこっちの方がしっくりくるかもです。 前提条件 利用するEC2 AMI はWindows Server2019とします。 SSL証明書はwin-acme(旧Let'sEncrypt)で無料のものを発行します。 利用するドメインはFreenomなどで取得済みとします。 VPCのセキュリティグループおよびEC2側のFWでHTTPおよびHTTPS通信を許可します。 今回のゴール https://xxxx.xxx でアクセスしてWebサイトが表示されること。 構築手順 ① EC2(WinsowsOS)をパブリックサブネットにデプロイする ② EC2にログインして、IISをインストールする ③ FreenomにEC2のグローバルIPをAレコードで登録する ④ IISでHTTP(ポート80通信)を設定する ⑤ Let's Encrypt でSSL証明書を発行し、HTTPS(ポート443通信)を設定する ⑥ Webアクセス時に表示させるHTMLファイルを作成する ⑦ ブラウザーからhttps://xxx.xxx でアクセス試験 実際にやってみた ①については割愛します。②から初めていきます。EC2にRDPしてサーバマネージャから「役割と機能の追加」からIISをインストールしていきます。 基本的にはWebサーバ(IIS)の役割追加を選択したら、あとはデフォルトのままの「次へ」を押していくだけです。 対象サーバ(操作しているサーバ)を選択して、「サーバの役割」でWebサーバ(IIS)にチェックを入れてください。あとはインストールまで「次へ」を押していくだけです。 10分程度でインストールが完了します。IISはインストールしてもサーバを再起動する必要はないです。 インストール完了後、IISの設定は「サーバマネージャ」-「ツール」-「IISマネージャ」からできます。 次に③のFreenomにEC2へのグローバルIPのAレコードの登録をやっていきます。Freenomにログインして、「Manage Freenom DNS」をクリックし、以下のようにDNSにAレコードを登録します。 しばらくするとDNSレコードが伝播していき、http://"取得したドメイン" でアクセスするとEC2にルーティングされるようになります。 レコードが伝播しているかはコマンドプロンプトでnslookupコマンドで確認できます。 nslookup "取得したドメイン" 名前: "取得したドメイン" Address: EC2のグローバルIP 上記のように表示されればOKです。 次に④のIISの設定をしていきます。EC2にhttpアクセス(ポート80宛通信)があったときにWebサイトを表示させる(Webサイトをバインド)ようにします。 IISマネージャにアクセスして、「Default Web Site」で右クリックし、「バインドの編集」を選択します。サイトバインド編集画面で「追加」を選択し、ホスト名のところに取得したドメインを記載します。その他のIPアドレス、ポート番号は編集しなくてもOKです。あとはAWS セキュリティグループでHTTPアクセスが許可されていれば、http://"取得したドメイン" でアクセス出来るようになっています。 エラーになる場合はIISを再起動させましょう。 続いて本記事のメインである⑤のSSLサイト化(SSL証明書発行および証明書の適用)を行います。 まずSSL証明書を発行するwin-acme(旧Let's Encrypt)をインストールするために、Windows Server のインターネットセキュリティ設定を変更します。 ※デフォルト設定のままだとexeファイルやデータのDLができない仕様のため サーバマネージャの「IE セキュリティ強化構成」が有効になっているので、これをAdministratorグループはオフにします。これでexeファイルなどのDLができるようになります。 続いてhttps://www.win-acme.com/ からツール一式をDLします。 DLして、解凍すると中に「wacs」という名前のファイルがあるので、管理者権限で実行します。 実行するとコマンドプロンプトの画面になります。 表示される内容に従い、以下のように入力していきます。 A simple Windows ACMEv2 client (WACS) Software version 2.1.17.1065 (release, pluggable, standalone, 64-bit) Connecting to https://acme-v02.api.letsencrypt.org/... Scheduled task not configured yet Please report issues at https://github.com/win-acme/win-acme N: Create certificate (default settings) M: Create certificate (full options) R: Run renewals (0 currently due) A: Manage renewals (0 total) O: More options... Q: Quit Please choose from the menu: n Running in mode: Interactive, Simple Please select which website(s) should be scanned for host names. You may input one or more site identifiers (comma-separated) to filter by those sites, or alternatively leave the input empty to scan *all* websites. 1: Default Web Site (1 binding) Site identifier(s) or <Enter> to choose all: 1 1: "④でWebサイトバインドしたドメイン" (Site 1) Listed above are the bindings found on the selected site(s). By default all of them will be included, but you may either pick specific ones by typing the host names or identifiers (comma-separated) or filter them using one of the options from the menu. P: Pick bindings based on a search pattern A: Pick *all* bindings Binding identifiers(s) or menu option: a 1: "④でWebサイトバインドしたドメイン" (Site 1) Continue with this selection? (y*/n) - yes Target generated using plugin IIS: "④でWebサイトバインドしたドメイン" ["④でWebサイトバインドしたドメイン"] Authorizing... ["④でWebサイトバインドしたドメイン"] Authorizing using http-01 validation (SelfHosting) ["④でWebサイトバインドしたドメイン"] Authorization result: valid Requesting certificate [IIS] Default Web Site, (any host) Store with CertificateStore... Installing certificate in the certificate store Adding certificate [IIS] Default Web Site, (any host) @ 2021/5/11 23:34:24 to store WebHosting Installing with IIS... Adding new https binding *:443:"④でWebサイトバインドしたドメイン" Committing 1 https binding changes to IIS Adding Task Scheduler entry with the following settings - Name win-acme renew (acme-v02.api.letsencrypt.org) - Path C:\Users\Administrator\Documents\win-acme.v2.1.17.1065.x64.pluggable - Command wacs.exe --renew --baseuri "https://acme-v02.api.letsencrypt.org/" - Start at 09:00:00 - Random delay 02:00:00 - Time limit 02:00:00 Adding renewal for [IIS] Default Web Site, (any host) Next renewal scheduled at 2021/7/5 23:34:16 Certificate [IIS] Default Web Site, (any host) created これで⑤のSSL証明書を発行し、HTTPS(ポート443通信)の設定が完了です。 上記完了後に再度サイトバインドの設定画面を見ると以下のようにhttpsが自動的にバインドされています。 あとは⑥のhttpsアクセスがあったときに表示させるWebサイト(htmlファイル)を作成して、ウェブルートのフォルダに格納しておきましょう。 htmlファイルの内容は下記参照してください。 <html lang="ja"> <head> <meta charset="utf-8"> <title>test-page</title> </head> <body> <h1>Hellow world! <br>This is Test!<?br> </h1> </body> </html> ウェブルートのフォルダはデフォルトでは「C:\inetpub\wwwroot」なので、ここに上記のhtmlファイルをいれておきます。 https://"取得したドメイン"/index.html でアクセスすると以下のようにSSL化してWebサイトが表示されます。  ※今回はxxx.tk というドメインで取得しています おまけ ついでに以下も設定してみました。 ① Basic認証  どういう機能かというとWebページを閲覧するのにIDとPWを入力して、ユーザ認証をする機能です。   htmlファイルを格納しているフォルダのアクセス権を付与されているユーザのID/PWで認証します。    設定方法はIISをインストールした「サーバの役割と機能の追加」でWebサーバの役割の中から基本認証をインストールし、  IISマネージャの「認証」を選択し、匿名認証を「無効」にして、基本認証を「有効」にすればOKです。 ② HTTPリダイレクト  どういう機能かというとhttpでアクセスした場合に別サイトへリダイレクトする機能です。リダイレクトするサイトはサイトバインドされていないものでもOKですが一般的な使い方としてはhttp://abcd-xxx.com にアクセスしてきたら https://abcd-xxx.com/index.hmtl にリダイレクトさせるという方法かなと思います。 設定方法はIISをインストールした「サーバの役割と機能の追加」でWebサーバの役割の中からHTTPリダイレクトをインストールし、 以下のようにリダイレクト先を記述する形になります。 おわりに ApacheでSSLサイトを作るよりWindows(IIS)の方が作業自体は簡単な気がします。 またLinuxでは自身でCron設定しないといけなかったSSL証明書の更新ですがWindows(IIS)ではwin-acmeが自動的にタスクスケジューラに登録して更新してくれるみたいです。 ちょっとしたHP運用や試験環境を作るときに簡単にSSL化サイトが作れます。ありがたやぁ~ありがたやぁ~...d('ω') 参考にしたWebページ https://www.ipentec.com/document/software-iis-ssl-certificate-using-win-acme https://www.ipentec.com/document/software-iis-ssl-certificate-using-lets-encrypt https://extan.jp/?p=2076 https://webbibouroku.com/Blog/Article/iis-basic
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon EC2(Windows OS)で構築したWebサーバ(IIS)のSSL設定

以前にAmazon EC2(CentOS)でSSLサイトをApacheを使って構築する記事を書きましたが、Windows(IIS)版の記事を書いてなかったので、お試しがてら記事にします。GUIで操作できる分、コマンド操作に慣れていない方はこっちの方がしっくりくるかもです。 前提条件 利用するEC2 AMI はWindows Server2019とします。 SSL証明書はwin-acme(旧Let'sEncrypt)で無料のものを発行します。 利用するドメインはFreenomなどで取得済みとします。 VPCのセキュリティグループおよびEC2側のFWでHTTPおよびHTTPS通信を許可します。 今回のゴール https://xxxx.xxx でアクセスしてWebサイトが表示されること。 構築手順 ① EC2(WinsowsOS)をパブリックサブネットにデプロイする ② EC2にログインして、IISをインストールする ③ FreenomにEC2のグローバルIPをAレコードで登録する ④ IISでHTTP(ポート80通信)を設定する ⑤ Let's Encrypt でSSL証明書を発行し、HTTPS(ポート443通信)を設定する ⑥ Webアクセス時に表示させるHTMLファイルを作成する ⑦ ブラウザーからhttps://xxx.xxx でアクセス試験 実際にやってみた ①については割愛します。②から初めていきます。EC2にRDPしてサーバマネージャから「役割と機能の追加」からIISをインストールしていきます。 基本的にはWebサーバ(IIS)の役割追加を選択したら、あとはデフォルトのままの「次へ」を押していくだけです。 対象サーバ(操作しているサーバ)を選択して、「サーバの役割」でWebサーバ(IIS)にチェックを入れてください。あとはインストールまで「次へ」を押していくだけです。 10分程度でインストールが完了します。IISはインストールしてもサーバを再起動する必要はないです。 インストール完了後、IISの設定は「サーバマネージャ」-「ツール」-「IISマネージャ」からできます。 次に③のFreenomにEC2へのグローバルIPのAレコードの登録をやっていきます。Freenomにログインして、「Manage Freenom DNS」をクリックし、以下のようにDNSにAレコードを登録します。 しばらくするとDNSレコードが伝播していき、http://"取得したドメイン" でアクセスするとEC2にルーティングされるようになります。 レコードが伝播しているかはコマンドプロンプトでnslookupコマンドで確認できます。 nslookup "取得したドメイン" 名前: "取得したドメイン" Address: EC2のグローバルIP 上記のように表示されればOKです。 次に④のIISの設定をしていきます。EC2にhttpアクセス(ポート80宛通信)があったときにWebサイトを表示させる(Webサイトをバインド)ようにします。 IISマネージャにアクセスして、「Default Web Site」で右クリックし、「バインドの編集」を選択します。サイトバインド編集画面で「追加」を選択し、ホスト名のところに取得したドメインを記載します。その他のIPアドレス、ポート番号は編集しなくてもOKです。あとはAWS セキュリティグループでHTTPアクセスが許可されていれば、http://"取得したドメイン" でアクセス出来るようになっています。 エラーになる場合はIISを再起動させましょう。 続いて本記事のメインである⑤のSSLサイト化(SSL証明書発行および証明書の適用)を行います。 まずSSL証明書を発行するwin-acme(旧Let's Encrypt)をインストールするために、Windows Server のインターネットセキュリティ設定を変更します。 ※デフォルト設定のままだとexeファイルやデータのDLができない仕様のため サーバマネージャの「IE セキュリティ強化構成」が有効になっているので、これをAdministratorグループはオフにします。これでexeファイルなどのDLができるようになります。 続いてhttps://www.win-acme.com/ からツール一式をDLします。 DLして、解凍すると中に「wacs」という名前のファイルがあるので、管理者権限で実行します。 実行するとコマンドプロンプトの画面になります。 表示される内容に従い、以下のように入力していきます。 A simple Windows ACMEv2 client (WACS) Software version 2.1.17.1065 (release, pluggable, standalone, 64-bit) Connecting to https://acme-v02.api.letsencrypt.org/... Scheduled task not configured yet Please report issues at https://github.com/win-acme/win-acme N: Create certificate (default settings) M: Create certificate (full options) R: Run renewals (0 currently due) A: Manage renewals (0 total) O: More options... Q: Quit Please choose from the menu: n Running in mode: Interactive, Simple Please select which website(s) should be scanned for host names. You may input one or more site identifiers (comma-separated) to filter by those sites, or alternatively leave the input empty to scan *all* websites. 1: Default Web Site (1 binding) Site identifier(s) or <Enter> to choose all: 1 1: "④でWebサイトバインドしたドメイン" (Site 1) Listed above are the bindings found on the selected site(s). By default all of them will be included, but you may either pick specific ones by typing the host names or identifiers (comma-separated) or filter them using one of the options from the menu. P: Pick bindings based on a search pattern A: Pick *all* bindings Binding identifiers(s) or menu option: a 1: "④でWebサイトバインドしたドメイン" (Site 1) Continue with this selection? (y*/n) - yes Target generated using plugin IIS: "④でWebサイトバインドしたドメイン" ["④でWebサイトバインドしたドメイン"] Authorizing... ["④でWebサイトバインドしたドメイン"] Authorizing using http-01 validation (SelfHosting) ["④でWebサイトバインドしたドメイン"] Authorization result: valid Requesting certificate [IIS] Default Web Site, (any host) Store with CertificateStore... Installing certificate in the certificate store Adding certificate [IIS] Default Web Site, (any host) @ 2021/5/11 23:34:24 to store WebHosting Installing with IIS... Adding new https binding *:443:"④でWebサイトバインドしたドメイン" Committing 1 https binding changes to IIS Adding Task Scheduler entry with the following settings - Name win-acme renew (acme-v02.api.letsencrypt.org) - Path C:\Users\Administrator\Documents\win-acme.v2.1.17.1065.x64.pluggable - Command wacs.exe --renew --baseuri "https://acme-v02.api.letsencrypt.org/" - Start at 09:00:00 - Random delay 02:00:00 - Time limit 02:00:00 Adding renewal for [IIS] Default Web Site, (any host) Next renewal scheduled at 2021/7/5 23:34:16 Certificate [IIS] Default Web Site, (any host) created これで⑤のSSL証明書を発行し、HTTPS(ポート443通信)の設定が完了です。 上記完了後に再度サイトバインドの設定画面を見ると以下のようにhttpsが自動的にバインドされています。 あとは⑥のhttpsアクセスがあったときに表示させるWebサイト(htmlファイル)を作成して、ウェブルートのフォルダに格納しておきましょう。 htmlファイルの内容は下記参照してください。 <html lang="ja"> <head> <meta charset="utf-8"> <title>test-page</title> </head> <body> <h1>Hellow world! <br>This is Test!<?br> </h1> </body> </html> ウェブルートのフォルダはデフォルトでは「C:\inetpub\wwwroot」なので、ここに上記のhtmlファイルをいれておきます。 https://"取得したドメイン"/index.html でアクセスすると以下のようにSSL化してWebサイトが表示されます。  ※今回はxxx.tk というドメインで取得しています おまけ ついでに以下も設定してみました。 ① Basic認証  どういう機能かというとWebページを閲覧するのにIDとPWを入力して、ユーザ認証をする機能です。   htmlファイルを格納しているフォルダのアクセス権を付与されているユーザのID/PWで認証します。    設定方法はIISをインストールした「サーバの役割と機能の追加」でWebサーバの役割の中から基本認証をインストールし、  IISマネージャの「認証」を選択し、匿名認証を「無効」にして、基本認証を「有効」にすればOKです。 ② HTTPリダイレクト  どういう機能かというとhttpでアクセスした場合に別サイトへリダイレクトする機能です。リダイレクトするサイトはサイトバインドされていないものでもOKですが一般的な使い方としてはhttp://abcd-xxx.com にアクセスしてきたら https://abcd-xxx.com/index.hmtl にリダイレクトさせるという方法かなと思います。 設定方法はIISをインストールした「サーバの役割と機能の追加」でWebサーバの役割の中からHTTPリダイレクトをインストールし、 以下のようにリダイレクト先を記述する形になります。 おわりに ApacheでSSLサイトを作るよりWindows(IIS)の方が作業自体は簡単な気がします。 またLinuxでは自身でCron設定しないといけなかったSSL証明書の更新ですがWindows(IIS)ではwin-acmeが自動的にタスクスケジューラに登録して更新してくれるみたいです。 ちょっとしたHP運用や試験環境を作るときに簡単にSSL化サイトが作れます。ありがたやぁ~ありがたやぁ~...d('ω') 参考にしたWebページ https://www.ipentec.com/document/software-iis-ssl-certificate-using-win-acme https://www.ipentec.com/document/software-iis-ssl-certificate-using-lets-encrypt https://extan.jp/?p=2076 https://webbibouroku.com/Blog/Article/iis-basic
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ECSから rails db:migrate:reset するときに発生するエラー(〇〇 is being accessed by other users)を解消する

注意 ポートフォリオ用に作成したサイトの本番環境を直接操作しています。 適切な対処法でないかもしれないので、とりあえずエラーを直したいという方はどうぞ。 背景 railsコンテナで rails db:migrate:reset ができない あるときseedファイルを変更したので、一度RDSの中をリセットしようと思いrailsコンテナから上記のコマンドを打つと、タイトルのエラーが発生しました。他のユーザー(というかコンテナ)が接続しており、実行できないとのことです。 使用技術 ・ECS:EC2タイプ ・RDS:PostgresQL(11.11) 上記のインスタンスの作成は割愛します。 やったこと EC2にpsqlコマンドをインストールしてRDSに接続 railsコンテナからRDSにアクセスしようとしたのですが、肝心のpsqlコマンドをインストールしていませんでした。 そこで応急処置として、EC2にpsqlコマンドを入れて接続しました。 以下、その手順です。 (現在、amazon-linux-extrasはpostgresql11までしかインストールできません。12,13をインストールする場合はこちらの記事が参考になります。) # ご使用のバージョンに合わせてインストールしてください $ sudo amazon-linux-extras postgresql11 # バージョンの確認 $ psql --version psql (PostgreSQL) 11.5 # DBアクセス用のuserがいない場合は作成してください $ sudo adduser <ユーザー名> $ su - <ユーザー名> # postgresサーバーに接続 $ psql \ > --host=<RDSのエンドポイント> \ > --username=<ユーザー名> > --password \ > --port=5432 \ > --dbname=<RDSのインスタンス名> これで接続は完了です。 (接続できないときは、RDSのセキュリティグループのインバウンドを確認してみてください) RDSにアクセスしているプロセスを削除 接続できれば、あとは接続中のプロセスをみつけて削除するだけです。 # すべてのプロセスを表示 SELECT pid FROM pg_stat_activity where pid <> pg_backend_pid(); # 表示例 1234 1235 # プロセスを削除 SELECT pg_terminate_backend(1234); SELECT pg_terminate_backend(1235); # psqlの終了 \q # コンテナに入ったのち、下記のコマンドを実行 $ bundle exec rake db:migrate:reset DISABLE_DATABASE_ENVIRONMENT_CHECK=1 以上になります。 まとめ 私は開発環境でPostgresQLをコンテナ化していたので、エラーが出た時はDBコンテナを壊して再構築していました。そのため、本番環境の対処がわからず戸惑いました。何も考えずに作業すると良くないですね勉強します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS認定 SysOpsアドミニストレイターに合格した

受験動機 一昨年にSAAを取得していたので、アソシエイトの三冠をとりあえず目指す 使用した機材について AWS認定アソシエイト3資格対策(対策本) 内容はソリューションアーキテクト寄りで、SOA/DVA用としては深度が足りない 奥付みると初版が2019/6なので、対策本も今ならもっと良いのがあるかも AWS WEB問題集で学習しよう(オンラインサービス) 結局こればっかりやってた SAA取得の時に比べると「本試験モード」みたいなメニューが増えている(本番と同じく2時間で65問回答する) 出題の範囲、問題の深度は本試験に近く、とても実用的 日本語の言い回しが微妙で解釈しづらい問題(問われている技術については理解出来ているけど、選択でどちらを選ぶべきか?が分かりづらい)があるが、これも本番に近い仕様なのであえてそう書いている…と思い、イライラせずに進めるべき 出題文を読んで回答を導き出す思考パターンに慣れておくこと(試験慣れ) 40番以降は難易度が上がる感じがあるので、後半だけ繰り返しておくのもイイかも 本試験モードで満点が取れるぐらいまでやり込めば確実に合格できる 受験まで 2020/02~ ホントは昨年(2020)にSOA資格取りたくて対策本を買ったのだけど、業務形態の変化や諸々で取り掛かれなかった 2月中旬に「そろそろやるか」と思い立って「AWS WEB問題集」のサービスを申し込んだ 2020/03~ 以前SAAの勉強した時は通勤時間を勉強に充てていたけど、リモートワークの現状況だと自宅で「勉強モード」に入るのが結構難しい 自宅だと中々スイッチを切り替えるのができない、すぐに誘惑に負ける これは自分でも認識してたので、以前はあえて外出して(長時間OKな喫茶店とか)自主的にモードを切り替えてたけど、このご時世だと外出もリスクがある 仕事を終えたあとそのまま勉強モードに入るパターンだとわりとやりやすいので「業務後1時間は勉強」のルーチンを作る 2020/04~ 業務後の勉強も慣れてきたので、勉強時間を1日約2時間に増やす 問題集をとりあえず一周したところで模擬試験を受ける 95点とか思わぬ好成績だったので「もう本試験受けようかな」とか一瞬考えるが、やっぱり思い直す 問題集を二周したところで出題範囲と傾向はそれなりに把握できたので、本試験の日程を決める 試験前日は問題集を全通しでやっておく 受験当日 SAAと同じCBTS歌舞伎座テストセンターで受験、コロナ対策で窓が開いていたせいでちょっと騒音が気になった 受験時間よりすこし前に来ても自由に始められるのはよい SAAと同じでとにかくイージーミスは絶対に避けるべきなので、問題の二度読みと選択肢の全項目読みを徹底した フラグ立てつつ65問回答までで約1時間、その後フラグ問題の検討で20分、見直し2回で20分ぐらいの時間消費 受験結果 無事合格(スコア918) 本試験では特に「日本語の言い回しによる解釈を悩む」ような問題はなかった(たまたまかも) 要点 CloudFormationは出来れば実際にテストコードを書いた方が理解が早い(自分はこれまでノータッチだったのでわりと苦労した) SAAよりも出題範囲は狭いが、その分サービスへの理解度はやや深いレベルが要求される 自分の印象ではSAAよりもスコープを絞れるのは良いが、その分覚えるサービス項目も細かくなるので難易度はそんなに変わらない?と思う 実際に触ってた経験があっても試験の時正確なパラメータを思い出せるとは限らないので、アーキテクチャの仕様をきちんと頭に入れておくことは重要(現場なら公式から情報を引き出してそこで判断ができれば問題ないけど、試験ではそうはいかない) 試験テクニック(消去法での正解抽出)は変わらず必須 今後 次はDVAを目指します アプリケーション系はこれまで関わってこなかったので、苦戦しそうな予感…
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ターミナルでcd .ssh/戻ってから

ターミナルでcd .ssh/戻ってから出ないとEC2へターミナルからアクセスできない
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSでWebサイトを構築してみた【第一回】全?回(VPC編)

AWS を実際に触りながら、実際にやったことを残しておこうと思いました。 これから何回かに分けて書いていきます。 今回は VPC 編ということで、VPC を作成していきます。 今回作成する構成 ※ 構成図はdraw.ioにて作成  https://app.diagrams.net/ 利用するサービス ・ VPC (Virtual Private Cloud) ・ ELB (Elastic Load Balancing) ・ AMI (Amazon Machine Images) ・ EC2 (Elastic Compute Cloud)     EC2 : t2.micro インスタンス × 2 ・ RDS (Relational Database Service)     RDS for MySQL : db.t2.micro マルチ AZ 配置 注意すること RDSリソースのみ無料利用対象外ですが、構築後にすぐ削除すれば発生する料金は数十円程度です。  無料利用枠についてはこちらで確認できます。  https://aws.amazon.com/jp/free/ リソースの削除 ・ 作成したリソースは必ず削除しましょう。削除し忘れた場合、想定以上の料金が発生する場合があります。 全体の流れ 全体の流れはこのような感じで進めていきます。 VPC の作成 EC2 の作成 RDS の作成 ELB の作成 WordPress の初期設定 AMI の作成 2つ目の EC2 インスタンスの作成 2つ目の EC2 インスタンスを ELB に登録 RDS インスタンスのマルチ AZ 配置 EC2 インスタンスを1つ停止させ、全体の可用性の確認 RDS インスタンスのフェイルオーバーを行い、全体の可用性を確認 作成したリソースの削除 VPC の作成 最初に1つのVPCとその中に4つのサブネットを作成していきます。 名称やIP CIDRは図のような感じで作成しますが、自分の構成図に合わせて変更しても構いません。 1. AWSマネジメントコンソールにログイン AWSマネジメントコンソールにログインしたら、リージョンを確認します。 「東京」が表示されていない場合は、▼マークをクリックして 「アジアパシフィック(東京)ap-northeast-1」を選択します。 2.VPCの作成 2-1.検索ボックスにVPCと入力  入力すると同時に検索結果にVPCのサービスが表示されますのでクリックします。 2-2.VPCウィザードの起動  今回は VPC ウィザードを利用し、必要なコンポーネント を自動的に作成後、  足りないコンポーネントを手動で作成・設定していきます。  「VPC ウィザードを起動」をクリックします。 2-3.VPC作成 ステップ1 : 1個のパブリックサブネットを持つ VPC が選ばれていることを確認し、選択ボタンをクリック。 ステップ2 : 構成図を元に図のように入力し、VPC の作成ボタンをクリック。  他の項目はデフォルトのままでOKです。 VPC が正常に作成されると下記画面が表示されるので、OKをクリックします。 3.VPCの確認 1.作成した VPC が存在するか確認します。  ※ 無い場合はブラウザを再表示してみてください。 2.IPv4 CIDR が 設定した 10.0.0.0/16 であることを確認します。 4.パブリックサブネットの確認 1.左側のペインからサブネットをクリック 2.サブネット表示欄にある「Name」から public-subnet-a1 を探し、左横のチェックボックスをクリック  (レ点が入っていることを確認) 3.アベイラビリティゾーンが ap-northeast-1a であることを確認 4.IPc4 CIDR が 10.0.0.0/24 であることを確認 5.サブネットのルートテーブルの確認 1.先ほどの4でサブネットにチェックが入っていると、画面中段以降に「詳細」、「フローログ」、「ルートテーブル」、「ネットワークACL」、「共有」、「タグ」というタブが表示されていると思います。その中から「ルートテーブル」を選択。 2.送信先に表示されている 0.0.0.0/0 のターゲットが、 igw-xxxxx (xは人により異なります)に設定されていることを確認 3.igw- から始まるターゲットに表示されているリンクをクリック 6.インターネットゲートウェイの確認 インターネットゲートウェイが、作成したVPCにアタッチされていることを確認 ここまで VPC 作成ウィザードにより、VPC、1つのパブリックサブネット、ルートテーブル、インターネットゲートウェイを作成してきました。 ここからさらに3つのサブネットを作成していきます。 7.サブネットの作成 7-1.作成するサブネット 名前 VPC アベイラビリティゾーン CIDRブロック 備考 1 public-subnet-1a 自分のVPC ap-northeast-1a 10.0.0.0/24 作成済み 2 public-subnet-1c 自分のVPC ap-northeast-1c 10.0.1.0/24 3 private-subnet-1a 自分のVPC ap-northeast-1a 10.0.2.0/24 4 private-subnet-1c 自分のVPC ap-northeast-1c 10.0.3.0/24 7-2.public-subnet-1cの作成 1.左側のペインからサブネットをクリックするとサブネットの画面が表示されます。 2.サブネットの作成をクリックします。 1.VPC ID のプルダウンメニューから作成した VPC を選択します。(デフォルトは選択しないでください) 2.サブネット名に public-subnet-1c を入力 3.アベイラビリティゾーンのプルダウンメニューから ap-northeast-1c を選択 4.IPv4 CIDR ブロックで設定する値を入力(値がいろいろ表示されますが、手入力可能です) 5.タグ-オプションは変更せずデフォルトのままでOKです 6.サブネット作成をクリックします 成功すると下記画面が表示されますので、続けて3つ目のサブネットを作成していきます。 1.サブネット作成画面でない場合は、左側のペインからサブネットをクリックします。 2.サブネットの作成をクリックします。 7-3.private-subnet-1a の作成 1.左側のペインからサブネットをクリック 2.サブネットの作成をクリック  ※ 思ったこと:この画面でのこの「サブネット作成」ボタンは、「サブネットの追加」もしくは「新しいサブネットの追加」などの方が良いような気がします・・・。  サブネットの設定画面にある「サブネットの作成」ボタンと被っているので混乱する人がいるかもです。  イメージとしては「作成→実際に追加反映される」、「追加→設定のみを行い即時反映されないためキャンセルも可」ですかね。  サブネット画面での「サブネット作成」ボタンは設定するための画面が表示されるだけなので。 1.VPC ID のプルダウンメニューから作成した VPC を選択します。(デフォルトは選択しないでください) 2.サブネット名に private-subnet-1a を入力 3.アベイラビリティゾーンのプルダウンメニューから ap-northeast-1c を選択 4.IPv4 CIDR ブロックで設定する値を入力(値がいろいろ表示されますが、手入力可能です) 5.タグ-オプションは変更せずデフォルトのままでOKです 6.サブネット作成をクリックします 7-4.private-subnet-1c の作成 1.左側のペインからサブネットをクリック 2.サブネットの作成をクリック 1.VPC ID のプルダウンメニューから作成した VPC を選択します。(デフォルトは選択しないでください) 2.サブネット名に private-subnet-1c を入力 3.アベイラビリティゾーンのプルダウンメニューから ap-northeast-1c を選択 4.IPv4 CIDR ブロックで設定する値を入力(値がいろいろ表示されますが、手入力可能です) 5.タグ-オプションは変更せずデフォルトのままでOKです 6.サブネット作成をクリックします 7-5作成した全てのサブネットを確認 左側のペインからサブネットをクリックし、4つのサブネットが全て正しく作成されていることを確認します。 スクロールバーで隠れている項目を見ることができます。 右上の歯車をクリックすると、画面に表示させる項目を選択することができます。 自分の環境に合わせて見やすいように変更しても良いかもしれません。 8.public-subnet-1c のルートテーブルを変更する ここで public-subnet-1a と public-subnet-1c のルートテーブルを確認します。 public-subnet-1a こちらはターゲットにインターネットゲートウェイへのルートが設定されています。 この場合のサブネットは「パブリックサブネット」になります。 逆にインターネットゲートウェイへのルートがないサブネットは、「プライベートサブネット」になるためインターネットと接続されていないことになります。 では、public-subnet-1c を見てみましょう。 public-subnet-1c public-subnet-1c のターゲットに igw- が見当たりません。この場合は「プライベートサブネット」です。 ですので、インターネットと通信できるようにルートテーブルを変更していきます。 1.public-subnet-1c を選択します。 2.ルートテーブルをクリックします。 3.ルートテーブルの関連付けの編集をクリックします。 1.ルートテーブルIDから、既に選択されているルートテーブル(メインテーブル)とは異なるルートテーブルを選択する。 2.デフォルトルート 0.0.0.0/0 のターゲットが "igw-xxxxx" と表示されていることを確認。 3.保存をクリックする。 最後に public-subnet-1c のルートテーブルを確認します。 ちゃんと作成されていることが確認できました。 今回は VPC を作成しました。 次回は EC2 の作成をしていきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSでWebサイトを構築してみる【第一回】全?回(VPC編)

AWS を実際に触りながら、実際にやったことを残しておこうと思いました。 これから何回かに分けて書いていきます。 今回は VPC 編ということで、VPC を作成していきます。 今回作成する構成 ※ 構成図はdraw.ioにて作成  https://app.diagrams.net/ 利用するサービス ・ VPC (Virtual Private Cloud) ・ ELB (Elastic Load Balancing) ・ AMI (Amazon Machine Images) ・ EC2 (Elastic Compute Cloud)     EC2 : t2.micro インスタンス × 2 ・ RDS (Relational Database Service)     RDS for MySQL : db.t2.micro マルチ AZ 配置 注意すること RDSリソースのみ無料利用対象外ですが、構築後にすぐ削除すれば発生する料金は数十円程度です。  無料利用枠についてはこちらで確認できます。  https://aws.amazon.com/jp/free/ リソースの削除 ・ 作成したリソースは必ず削除しましょう。削除し忘れた場合、想定以上の料金が発生する場合があります。 全体の流れ 全体の流れはこのような感じで進めていきます。 VPC の作成 EC2 の作成 RDS の作成 ELB の作成 WordPress の初期設定 AMI の作成 2つ目の EC2 インスタンスの作成 2つ目の EC2 インスタンスを ELB に登録 RDS インスタンスのマルチ AZ 配置 EC2 インスタンスを1つ停止させ、全体の可用性の確認 RDS インスタンスのフェイルオーバーを行い、全体の可用性を確認 作成したリソースの削除 VPC の作成 最初に1つのVPCとその中に4つのサブネットを作成していきます。 名称やIP CIDRは図のような感じで作成しますが、自分の構成図に合わせて変更しても構いません。 1. AWSマネジメントコンソールにログイン AWSマネジメントコンソールにログインしたら、リージョンを確認します。 「東京」が表示されていない場合は、▼マークをクリックして 「アジアパシフィック(東京)ap-northeast-1」を選択します。 2.VPCの作成 2-1.検索ボックスにVPCと入力  入力すると同時に検索結果にVPCのサービスが表示されますのでクリックします。 2-2.VPCウィザードの起動  今回は VPC ウィザードを利用し、必要なコンポーネント を自動的に作成後、  足りないコンポーネントを手動で作成・設定していきます。  「VPC ウィザードを起動」をクリックします。 2-3.VPC作成 ステップ1 : 1個のパブリックサブネットを持つ VPC が選ばれていることを確認し、選択ボタンをクリック。 ステップ2 : 構成図を元に図のように入力し、VPC の作成ボタンをクリック。  他の項目はデフォルトのままでOKです。 VPC が正常に作成されると下記画面が表示されるので、OKをクリックします。 3.VPCの確認 1.作成した VPC が存在するか確認します。  ※ 無い場合はブラウザを再表示してみてください。 2.IPv4 CIDR が 設定した 10.0.0.0/16 であることを確認します。 4.パブリックサブネットの確認 1.左側のペインからサブネットをクリック 2.サブネット表示欄にある「Name」から public-subnet-a1 を探し、左横のチェックボックスをクリック  (レ点が入っていることを確認) 3.アベイラビリティゾーンが ap-northeast-1a であることを確認 4.IPc4 CIDR が 10.0.0.0/24 であることを確認 5.サブネットのルートテーブルの確認 1.先ほどの4でサブネットにチェックが入っていると、画面中段以降に「詳細」、「フローログ」、「ルートテーブル」、「ネットワークACL」、「共有」、「タグ」というタブが表示されていると思います。その中から「ルートテーブル」を選択。 2.送信先に表示されている 0.0.0.0/0 のターゲットが、 igw-xxxxx (xは人により異なります)に設定されていることを確認 3.igw- から始まるターゲットに表示されているリンクをクリック 6.インターネットゲートウェイの確認 インターネットゲートウェイが、作成したVPCにアタッチされていることを確認 ここまで VPC 作成ウィザードにより、VPC、1つのパブリックサブネット、ルートテーブル、インターネットゲートウェイを作成してきました。 ここからさらに3つのサブネットを作成していきます。 7.サブネットの作成 7-1.作成するサブネット 名前 VPC アベイラビリティゾーン CIDRブロック 備考 1 public-subnet-1a 自分のVPC ap-northeast-1a 10.0.0.0/24 作成済み 2 public-subnet-1c 自分のVPC ap-northeast-1c 10.0.1.0/24 3 private-subnet-1a 自分のVPC ap-northeast-1a 10.0.2.0/24 4 private-subnet-1c 自分のVPC ap-northeast-1c 10.0.3.0/24 7-2.public-subnet-1cの作成 1.左側のペインからサブネットをクリックするとサブネットの画面が表示されます。 2.サブネットの作成をクリックします。 1.VPC ID のプルダウンメニューから作成した VPC を選択します。(デフォルトは選択しないでください) 2.サブネット名に public-subnet-1c を入力 3.アベイラビリティゾーンのプルダウンメニューから ap-northeast-1c を選択 4.IPv4 CIDR ブロックで設定する値を入力(値がいろいろ表示されますが、手入力可能です) 5.タグ-オプションは変更せずデフォルトのままでOKです 6.サブネット作成をクリックします 成功すると下記画面が表示されますので、続けて3つ目のサブネットを作成していきます。 1.サブネット作成画面でない場合は、左側のペインからサブネットをクリックします。 2.サブネットの作成をクリックします。 7-3.private-subnet-1a の作成 1.左側のペインからサブネットをクリック 2.サブネットの作成をクリック  ※ 思ったこと:この画面でのこの「サブネット作成」ボタンは、「サブネットの追加」もしくは「新しいサブネットの追加」などの方が良いような気がします・・・。  サブネットの設定画面にある「サブネットの作成」ボタンと被っているので混乱する人がいるかもです。  イメージとしては「作成→実際に追加反映される」、「追加→設定のみを行い即時反映されないためキャンセルも可」ですかね。  サブネット画面での「サブネット作成」ボタンは設定するための画面が表示されるだけなので。 1.VPC ID のプルダウンメニューから作成した VPC を選択します。(デフォルトは選択しないでください) 2.サブネット名に private-subnet-1a を入力 3.アベイラビリティゾーンのプルダウンメニューから ap-northeast-1c を選択 4.IPv4 CIDR ブロックで設定する値を入力(値がいろいろ表示されますが、手入力可能です) 5.タグ-オプションは変更せずデフォルトのままでOKです 6.サブネット作成をクリックします 7-4.private-subnet-1c の作成 1.左側のペインからサブネットをクリック 2.サブネットの作成をクリック 1.VPC ID のプルダウンメニューから作成した VPC を選択します。(デフォルトは選択しないでください) 2.サブネット名に private-subnet-1c を入力 3.アベイラビリティゾーンのプルダウンメニューから ap-northeast-1c を選択 4.IPv4 CIDR ブロックで設定する値を入力(値がいろいろ表示されますが、手入力可能です) 5.タグ-オプションは変更せずデフォルトのままでOKです 6.サブネット作成をクリックします 7-5作成した全てのサブネットを確認 左側のペインからサブネットをクリックし、4つのサブネットが全て正しく作成されていることを確認します。 スクロールバーで隠れている項目を見ることができます。 右上の歯車をクリックすると、画面に表示させる項目を選択することができます。 自分の環境に合わせて見やすいように変更しても良いかもしれません。 8.public-subnet-1c のルートテーブルを変更する ここで public-subnet-1a と public-subnet-1c のルートテーブルを確認します。 public-subnet-1a こちらはターゲットにインターネットゲートウェイへのルートが設定されています。 この場合のサブネットは「パブリックサブネット」になります。 逆にインターネットゲートウェイへのルートがないサブネットは、「プライベートサブネット」になるためインターネットと接続されていないことになります。 では、public-subnet-1c を見てみましょう。 public-subnet-1c public-subnet-1c のターゲットに igw- が見当たりません。この場合は「プライベートサブネット」です。 ですので、インターネットと通信できるようにルートテーブルを変更していきます。 1.public-subnet-1c を選択します。 2.ルートテーブルをクリックします。 3.ルートテーブルの関連付けの編集をクリックします。 1.ルートテーブルIDから、既に選択されているルートテーブル(メインテーブル)とは異なるルートテーブルを選択する。 2.デフォルトルート 0.0.0.0/0 のターゲットが "igw-xxxxx" と表示されていることを確認。 3.保存をクリックする。 最後に public-subnet-1c のルートテーブルを確認します。 ちゃんと作成されていることが確認できました。 今回は VPC を作成しました。 次回は EC2 の作成をしていきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS ec2 デプロイ laravel8 php8 mysql8

ほぼ受け売りです。 参考: 公式 LaravelをAWSのEC2へデプロイする手順 laravelをAWS EC2にデプロイする インバウンド HTTP (ポート 80) 接続をインスタンスに許可するセキュリティルールを追加していない場合には、ルールを追加する。 公式の最初のほうに書かれてあるのを参考に。 php8.0をインストール sudo amazon-linux-extras install -y php8.0 sudo yum install php-mbstring php-openssl php-xml unzip Apacheのインストール sudo yum install -y httpd 設定 wabサーバの起動 sudo service httpd start システムがブートするたびにapacheが起動するよう設定 sudo chkconfig httpd on 有効か確認 chkconfig --list httpd ウェブサーバーをテストします。ウェブブラウザで、インスタンスのパブリック DNS アドレス (またはパブリック IP アドレス) を入力します。 Apacheの初期画面が表示されれば成功です。 ec2-user アカウントがこのディレクトリで複数のファイルを操作することを許可するには、ディレクトリの所有権とアクセス許可を変更する必要があります。 ec2-userをapacheグループに追加 sudo usermod -a -G apache ec2-user いったんログアウトして、再度ログイン exit /var/www とそのコンテンツのグループ所有権を apache グループに変更 sudo chown -R ec2-user:apache /var/www グループに、/var/wwwの書き込み許可追加 sudo chmod 2775 /var/www /var/www とサブディレクトのディレクトリ許可を変更 find /var/www -type d -exec sudo chmod 2775 {} \; /var/www とサブディレクトリのファイル許可を変更 find /var/www -type f -exec sudo chmod 0664 {} \; MYSQL8インストール 既存でインストールされている邪魔者を削除 sudo yum remove mariadb-libs sudo rm -rf /var/lib/mysql リポジトリのインストール sudo rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm MYSQLのインストール cd /usr/lib64 sudo ln libsasl2.so.3 libsasl2.so.2 sudo yum clean all sudo yum -y install mysql-community-server mysql-devel MYSQLの起動 sudo systemctl start mysqld.service sudo systemctl enable mysqld.service 初期パスワードに確認 sudo cat /var/log/mysqld.log | grep 'temporary password' パスワード変更 sudo mysql_secure_installation 再起動 sudo systemctl restart mysqld.service gitをインストール インストール sudo curl -sS https://getcomposer.org/installer | php パスを通す sudo mv composer.phar /usr/local/bin/composer composer自身のインストール curl -sS https://getcomposer.org/installer | php composerコマンドのパスを通す sudo mv composer.phar /usr/local/bin/composer パス確認(/usr/local/bin/composerと表示されればOK) which composer Laravelプロジェクトをgit clone sudo yum install git cd /var/www git clone [URL] Apacheの設定変更 http.confファイルのDocumentRootの変更 Laravelでは、プロジェクト内のpublicディレクトリをドキュメントルートに指定する必要がある sudo vi /etc/httpd/conf/httpd.conf キーボードで「i」を押して入力状態にする DocumentRoot "/var/www/html"の箇所をDocumentRoot "/var/www/プロジェクト名/public"に変更 http.confファイルに以下のDirectoryを追加(.htaccessの有効化) <Directory /var/www/プロジェクト名/public> AllowOverride All </Directory> Escキーを押して次のコマンドを入力(画面左下に入力中のコマンドが表示される) :wq Apacheの設定変更後は、再起動。 sudo service httpd restart パッケージのインストール cd /var/www/[プロジェクトのフォルダ名] composer.jsonファイルがない場合 composer init vendorディレクトリが生成される composer install Laravelプロジェクトの設定 sudo chmod -R 777 /var/www/[プロジェクト名]/storage sudo chmod -R 775 /var/www/[プロジェクト名]/bootstrap/cache config, routeのキャッシュクリア だいたいなんかエラー出たら、これ打っときゃ直る。 php artisan config:cache php artisan route:cache .envの設定 git cloneしたLaravelプロジェクトには.envファイルがないので、 composer insatallで作成された、.env.exampleを使用する cp .env.example .env vi .env APP_URL=http://IPアドレス ←サーバーのIPにする DB_CONNECTION=mysql DB_HOST=←RDSのエンドポイント DB_DATABASE=データベース名 DB_USERNAME=RDS作成時のユーザ名 DB_PASSWORD=設定したパスワード キーを作成し、キャッシュをクリアする php artisan key:generate php artisan config:clear 後は煮るなり焼くなり
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Lambdaで I/O Errorが発生した場合の対応

はじめに 個人的な備忘録が目的です。 言語は Python のみですが、考え方は他の言語にも流用できるかなと思います。 問題点 Lambdaでファイル作成系のコマンドを実行すると、たまに I/O Error 発生したりします。 例えば、 poppler にある pdftohtml を実行すると、 pdftohtml test.pdf output I/O Error: Couldn't open html file 'outputs.html 原因は、Lambdaではカレントディレクトリにファイルを作成することができないからです。 対応策 上記のStackOverflowの記事にも書かれている通り、 /tmp に作成するようにしたら良いです。 subprocess を使う場合は、以下のような感じですね。 command_list = ["pdftohtml", "-s", "-i", "test.pdf", "output"] process = subprocess.Popen(command_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd="/tmp", universal_newlines=True) さいごに 何かありましたら、コメント頂けると助かります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS S3に写真をアップロード設定を行なっていた時のエラー

storage.yml local: service: Disk root: <%= Rails.root.join("storage") %> amazon: service: S3 region: ap-northeast-1 bucket: tast123456 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> インデントを揃えないとエラーが出る設定になっています。 上記だとservice: Diskと同じ並びになるのでlocal:の続きと読まれてしまう。 storage.yml local: service: Disk root: <%= Rails.root.join("storage") %> amazon: service: S3 region: ap-northeast-1 bucket: tast123456 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】AWS SDK for Rubyにおけるリソースの認証情報の優先順位ランキング

AWSリソースに設定しているIAMユーザーのクレデンシャル情報を削除し、リソースにアタッチされたIAMロールの権限に切り替えることで、セキュリティが強化されます。 今回、Railsアプリで利用している AWS SDK for Ruby の認証情報の優先順位を調査しました。 【参考】 https://docs.aws.amazon.com/ja_jp/sdk-for-ruby/v3/developer-guide/setup-config.html 【結論】 優先1: 環境変数でクレデンシャルが設定してあると、その権限が優先されます。 優先2: 設定されていない場合、.aws/credentials ファイルでセットアップされたプロファイルを優先します。 優先3: どちらも設定されていない場合、アタッチされたロールの認証情報を利用されます。 ジョーカー: ソース内で設定することで、上記の設定を上書きすることができます。 1位 環境変数に設定されたクレデンシャル export AWS_ACCESS_KEY_ID=your_access_key_id export AWS_SECRET_ACCESS_KEY=your_secret_access_key 2位 .aws/credentials でセットアップされたプロファイル [default] aws_access_key_id = your_access_key_id aws_secret_access_key = your_secret_access_key 3位 上記どちらも設定されていない場合、リソースにロールをアタッチされたロールの権限が取得されます。 つまり、ロール権限に切り替えるためには、環境変数とプロファイルにIAMユーザーのクレデンシャルを設定しない必要があるということです。 ジョーカー ソースコードで設定することで、上記の設定を上書きすることができます。 クライアントオブジェクト内で認証情報を設定する ec2 = Aws::EC2::Resource.new( access_key_id: your_access_key_id, secret_access_key: your_secret_access_key, region: "ap-northeast-1" ) Aws.config を使用して認証情報を設定する Aws.config.update({ credentials: Aws::Credentials.new('your_access_key_id', 'your_secret_access_key') }) 認証情報の確認 EC2などのリソースにアクセスして、$ aws sts get-caller-identityを叩くと、認証情報が取得できます。 ロールの権限の場合 { "Account": "xxx", "UserId": "xxx:xxx", "Arn": "arn:aws:sts::xxx:assumed-role/<role-name>/xxx" }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】VPCエンドポイントについて

プログラミング勉強日記 2021年5月12日 VPCエンドポイント  VPCエンドポイントはグローバルIPを持つAWSサービスに対してVPCの中から直接アクセスするための出口。S3はグローバルアドレスを持っていて特有の名前をつけないといけない。特にVPCやAZを指定しなくても作ることができる。そのため、VPCの外にあるS3にアクセスしたいときにエンドポイントを使って設定できる。  VPCエンドポイントはGateway型とPrivateLink型の2種類の接続形式がある。 Gateway型  Gateway型はサブネットに特殊なルーティングを設定して、VPC内部から直接外のサービスと通信する。ルートテーブルからVPCエンドポイントでエンドポイントポリシーを作ってそこで制御する。基本的には無料で冗長性はAWS側が対応しているマネーシド型サービス。 PrivateLink型  PrivateLink型はサブネットにエンドポイント用のプライベートIPアドレスを作って、そのアドレスをDNSが名前ルーティングする。通常のIPアドレスがVPCエンドポイントにも付与されるというやり方。アクセス制御はセキュリティグループを設定する。料金は有料で冗長性はマルチAZ設計になっている。 VPCの設定上限  VPCにはそれぞれの設定において上限数がある。そのため、大規模運用する場合は考慮しなくてはいけない。 リソース 上限数 リージョン当たりのVPC 5 VPC当たりのサブネット 200 VPC当たりのセキュリティグループ 500 AWSアカウント当たりの1リージョン内のElasticIPの数 5 ルートテーブル当たりのルート 100 セキュリティグループ当たりのルール 50
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

S3導入時に発生したSSHKit::Command::Failed: bundle exit status: 1の解決策

はじめに S3を導入した際にエラーが発生したため,その経緯と解決策を備忘録として残します. 作業環境 Ruby 2.6.5 Ruby on Rails 6.0.0 本番環境(EC2) NGINX Unicorn MySQL 経緯 S3を導入し,本番環境に反映させようとしたときに下記のエラーが発生した. SSHKit::Command::Failed: bundle exit status: 1 エラー発生の原因 本番環境にAWSのアクセスキーとシークレットキーを追加していなかった. 解決策 本番環境で環境変数を保存しているファイル(アプリ名/etc/environment)にAWSのアクセスキーとシークレットキーを追加する. こうすると無事本番環境にデプロイすることができた. おわりに 環境変数の設定は忘れやすいので注意したい.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Athenaの奇妙な仕様(ADDとDROPで構文が違う?)

ADD PARTITIONとDROP PARTITIONの構文違いに注意 AWS Athenaの奇妙な仕様(?)を発見しました。 ALTER TABLE 構文の ADD PARTITIONとDROP PARTITIONで構文が違う(ADDはスペース区切り、DROPはカンマ区切り)じゃないと通らないようでした。 *2021/5/12時点 ADDは通るのに、DROPが落ちていることがわかり、行き着いた結果。 'ADD PARTITIONはスペース区切り' ALTER TABLE ADD PARTITION(pt=1) PARTITION(pt=2) 'DROPはカンマ区切り' ALTER TABLE DROP PARTITION(pt=1),PARTITION(pt=2) AWS公式ドキュメント ▼ALTER TABLE ADD https://docs.aws.amazon.com/ja_jp/athena/latest/ug/alter-table-add-partition.html ALTER TABLE orders ADD PARTITION (dt = '2016-05-14', country = 'IN') LOCATION 's3://mystorage/path/to/INDIA_14_May_2016/' PARTITION (dt = '2016-05-15', country = 'IN') LOCATION 's3://mystorage/path/to/INDIA_15_May_2016/'; ▼ALTER TABLE DROP https://docs.aws.amazon.com/ja_jp/athena/latest/ug/alter-table-drop-partition.html ALTER TABLE orders DROP PARTITION (dt = '2014-05-14', country = 'IN'), PARTITION (dt = '2014-05-15', country = 'IN'); ご注意ください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

組織管理されているAWS環境下のアクセスアクティビティからIAMポリシーを自動生成する

IAMユーザーやIAMロールの CloudTrailログ から実際に利用されたIAMポリシーを生成する機能。 CloudTrail の設定によってはうまく動作しないので調査メモと回避策を書いておきます。 IAM Access Analyzer makes it easier to implement least privilege permissions by generating IAM policies based on access activity | AWS Security Blog IAM Access Analyzer まず前提知識として。 よく理解できていないが、IAM Access Analyzer は最低でも2種類の機能を持っていて、それぞれで求められる権限が違う。今回はポリシー生成のほうの話。 アナライザーがリソースをモニタリングしてポリシーを分析する機能 AWS IAM Access Analyzer を使用する - AWS Identity and Access Management CloudTrailログを確認してポリシーを生成する機能 アクセスアクティビティに基づくポリシーの生成 - AWS Identity and Access Management Control Tower 管理下 CloudFormation StackSet AWSControlTowerBP-BASELINE-CLOUDTRAIL によって CloudTrail の有効化が行われています。 CloudTrail ログの保存先は Log archiveアカウント の S3バケット が指定されています。 そのため IAM Access Analyzer はクロスアカウントで CloudTrailログ を読み取る必要がでてきます。 権限がない状態でポリシーを生成しようとするとエラーとなります。 Log archiveアカウント の S3バケットポリシー を変更してクロスアカウントアクセスを許可すればいけそうですが、さらに問題が。 必須のガードレール である ログアーカイブで AWS Control Tower が作成した S3 バケットのバケットポリシーの変更を許可しない があり、 SCP によりバケットポリシーの変更ができません。 つまりSCPを一時的に解除してバケットポリシーを編集、クロスアカウントアクセスを可能にして、ようやくポリシーが生成できます。 どうにもAWSの推奨設定から外れまくっている感じしますね。 Organization 管理下 AWS CloudTrail と AWS Organizations - AWS Organizations アクセスアクティビティに基づくポリシーの生成 - AWS Identity and Access Management AWS Organizations – Organizations CloudTrail 証跡を使用してポリシーを生成することはできません。 なんと、Organizations CloudTrail 証跡を使っているとポリシー生成できません! たまにある推奨構成で組むと新機能が使えないジレンマ。 回避策 AWSの推奨事項を抑えつつポリシー生成を行うには、別途 CloudTrail証跡 を作るしかないかと思います。 2つ目なので費用がかかってしまいますが、常時チェックし続けるものでもないので、短期間だけ証跡作ってポリシー生成したら削除するのがよさそうです。 思うところ 各アカウントの CloudTrail が90日間のログを持っているはずなので(GuardDutyなどが見ているやつ)、S3 の CloudTrailログ へアクセスしなくてもポリシー生成できそうなものなんですが、それができない仕組みなんですかね。 まだ出て日が浅い機能なので今後のアップデートに期待しましょうか。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS EC2でwordpressをユーザーデータで立ち上げる

この記事でできること 後半に記載の前準備後に、ユーザーデータを利用して、wordpress AWS EC2でコピペだけでを立ち上げられる 先に結論 これをユーザーデータにコピペするだけ ECインスタンスのユーザーデータにコピペするbash(バッシュ) #!/bin/bash echo "===sudu su -===" #以下、管理者権限 sudu su - echo "===yum -y update===" # インストールされている すべてのソフトの アップデート yum -y update echo “===amazon-linux-extras install php7.2 -y===” # レポジトリからphp7.2 install yes amazon-linux-extras install php7.2 -y # wordpress(PHP)に必要なソフトをインストールする echo “===yum -y install mysql httpd php-mbstring php-xml gd php-gd===” yum -y install mysql httpd php-mbstring php-xml gd php-gd echo "===systemctl start httpd.service===" #アパッチを起動 systemctl start httpd.service echo "===systemctl enable httpd.service===" #アパッチ再起動後も実行を有効 systemctl enable httpd.service # wget(HTTP/(S)でダウンロード) 最新のwordpress tar.gz形式 # オプション-O がないと保存先がひとつ前になる、なぜ(?) echo “===wget http://ja.wordpress.org/latest-ja.tar.gz -O /usr/local/src/latest-ja.tar.gz===” wget http://ja.wordpress.org/latest-ja.tar.gz -O /usr/local/src/latest-ja.tar.gz echo "===cd /usr/local/src/===" #ディレクトリ移動 ダウンロードは一般にここに入れるらしい cd /usr/local/src/ #tar.gz形式の最新ワードプレスjpを展開。 z(gzipファイル)をx(展開)v(詳細を表示する)f(ファイルの指定) echo”===tar zxvf latest-ja.tar.gz===” tar zxvf latest-ja.tar.gz #カレントディレクトリにあるwordpressとサブディレクトリすべてを /var/www/html/のしたにコピーする -r(コピー元にディレクトリを指定した場合、再帰的に(サブディレクトリも含めて)コピーする echo”===cp -r wordpress/* /var/www/html/===” cp -r wordpress/* /var/www/html/ #/var/www/htmlの権限をapacheの所有者apacheのユーザーにする -R(再帰的に変更) echo”===chown apache:apach -R /var/www/html===” chown apache:apache -R /var/www/html インスタンス起動後数分すると・・・ 上記を実行する前には、下記の準備を行っておく必要があります。 前準備 あくまで例です VPC 10.0.0.0/21 subnet (サブネット把握しやすいように第3オクテットをNameの末尾の数字とした) RDSでマルチAZ構成のため異なるAZにpublic,privateサブネットをそれぞれ用意する ap-northeast-1a Name:PublicSubnet0 10.0.0.0/24 ap-northeast-1a Name:PrivateSubnet2 10.0.2.0/24 ap-northeast-1c Name:PublicSubnet1 10.0.1.0/24 ap-northeast-1c Name:PrivateSubnet3 10.0.3.0/24 インターネットゲートウェイ VPCにアタッチ ルートテーブル サブネット PublicSubnet0 のルートテーブルで 0.0.0.0/0 でインターネットゲートウェイを指定 RDS サブネットグループを作成 RDSを作成 WordPressにはMySQLが必須。WordPressではMySQLまたはMariaDBが推奨されています。 多くのレンタルサーバーはデータベースにMySQLを採用しています。 ということなので、MySQLを選択 VPCセキュリティグループは、新しく RDS-SG の名称で作成する  (マスターユーザー名:wordpress、インスタンス安いのに変更、vpc指定、サブネットグループ指定、Azは1a、あとは大体デフォルト) セキュリティグループ テストなので今回はHTTPのみ。本番はHTTPS+AWS HTTPS 証明書 ACM+(ELB or Route53)ご利用ください。 Name:Web-SG で以下で作成 インバウンドルールを編集 HTTP TCP 80 0.0.0.0/0 – HTTP TCP 80 ::/0 – SSH TCP 22 0.0.0.0/0 – RDSで作成したセキュリティグループ RDS-SG を以下に変更 インバウンドルールを編集 既存IPアドレス削除し、Web-SGを指定する。 EC2 (やっと出番です) 最初に示したバッシュをユーザーデータにコピペして、セキュリティグループWeb-SG でインスタンスを起動!!!! はまったこと sudo su - がないと権限が足りない wget http://ja.wordpress.org/latest-ja.tar.gz -O /usr/local/src/latest-ja.tar.gz のオプションOがないとcloud-init-output.log でScheme missing.表示で失敗する。 まとめ sudo su cat /var/log/cloud-init-output.log がめっちゃ役立つのよくわかった 【ハンズオン1】基本的なブログサービスを構築する(シングル構成) AWSCloudTech
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【本番環境】【エラー解決】【備忘録】Failed to start The nginx HTTP and reverse proxy server.Unit nginx.service entered failed state.nginx.service failed.

ローカルで作成したRailsのアプリをデプロイするために、 AWSのサービスである「EC2」と「VPC」を利用しています。 ▼(デプロイ編②)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで https://qiita.com/naoki_mochizuki/items/5a1757d222806cbe0cd1#nginx%E3%81%AE%E8%B5%B7%E5%8B%95 上記記事に沿ってデプロイを進めていきましたが、 エラーがなかなか解決できずに息詰まりました・・・。 まだ、ブラウザの画面でアプリを表示させることは実現できていませんが、 一つエラー解決できたので、コマンドなど忘れないためにも記録として残しておきます。 また、この記事がどなたかのお役に立てたなら幸いです。 $ sudo service nginx startを実行した結果 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful 特に問題なさそうです。 $ systemctl status firewalldを実行した結果 Unit firewalld.service could not be found. $ ps -ef | grep unicorn | grep -v grepを実行した結果 asami 4290 1 0 5月08 ? 00:00:01 unicorn_rails master -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production asami 4293 4290 0 5月08 ? 00:00:00 unicorn_rails worker[0] -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production asami 4294 4290 0 5月08 ? 00:00:00 unicorn_rails worker[1] -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production 特に問題なさそうです。 $ curl http://127.0.0.1/の結果 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Welcome to Amazon Linux 2</title> <style rel="stylesheet" type="text/css"> html { background-color: white; font-family: "DejaVu Sans", "Liberation Sans", sans-serif; margin: 10% 20%; } body { margin:0; padding:0; background: white; } a { color: #007eb9; } </style> </head> <body> <p>Thank you for using <a href="https://aws.amazon.com/amazon-linux-2/">Amazon Linux 2</a>.<p> <p>Now that you have it installed, find announcements and discussion in <a href="https://forums.aws.amazon.com/forum.jspa?forumID=228">the AWS Discussion Forums</a>. Also try <a href="https://aws.amazon.com/documentation/">AWS documentation</a>.</p> </body> </html> 特に問題なさそうです。 http://xx.xxx.xx.xx/(Elastic IP アドレス) を実行した結果 CONNECTION REFUSED というエラー。。。 AWSの状況 ①EC2/インスタンス ②インスタンスに使われているセキュリティグループ ③所属するサブネットのルートテーブル /etc/nginx/conf.d/アプリ名.confの中身 # log directory error_log /var/www/rails/アプリ名/log/nginx.error.log; access_log /var/www/rails/アプリ名/log/nginx.access.log; # max body size client_max_body_size 2G; upstream app_server { # for UNIX domain socket setups server unix:/var/www/rails/アプリ名/tmp/sockets/unicorn.sock fail_timeout=0; } upstream unicorn { server unix:/var/www/rails/アプリ名/tmp/sockets/unicorn.sock; } server { listen 80; server_name 18.180.71.74; # nginx so increasing this is generally safe... keepalive_timeout 5; # path for static files root /var/www/rails/アプリ名/public; # page cache loading try_files $uri/index.html $uri.html $uri @app; location @app { # HTTP headers proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://app_server; } location @unicorn { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://unicorn; } # Rails error pages error_page 500 502 503 504 /500.html; nginxのログの状況 ①$ sudo nano /var/log/nginx/access.logを実行した結果 111.239.181.40 - - [09/May/2021:11:17:42 +0000] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36$ 188.166.70.83 - - [09/May/2021:11:20:20 +0000] "GET / HTTP/1.0" 500 1635 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/2010010$ 127.0.0.1 - - [09/May/2021:11:32:28 +0000] "GET / HTTP/1.1" 200 732 "-" "curl/7.61.1" "-" 188.166.70.83 - - [09/May/2021:11:48:07 +0000] "GET /_ignition/execute-solution HTTP/1.1" 301 5 "-" "python-requests/2.18.4" "-" 132.145.196.125 - - [09/May/2021:12:15:13 +0000] "POST / HTTP/1.1" 307 5 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like $ 132.145.196.125 - - [09/May/2021:12:15:15 +0000] "GET /.env HTTP/1.1" 301 5 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, li$ 124.219.132.185 - - [09/May/2021:12:35:52 +0000] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHT$ 170.254.75.31 - - [09/May/2021:12:44:03 +0000] "GET / HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like$ 47.241.125.249 - - [09/May/2021:13:00:54 +0000] "\x05\x01\x00" 400 157 "-" "-" "-" 47.241.125.249 - - [09/May/2021:13:01:20 +0000] "GET http://passport.baidu.com/ HTTP/1.1" 200 732 "-" "-" "-" 47.241.125.249 - - [09/May/2021:13:02:16 +0000] "\x04\x01\x00Pg)\xA7\xEA\x00" 400 157 "-" "-" "-" ②sudo service nginx statusを実行した結果 Redirecting to /bin/systemctl status nginx.service ● nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) Active: inactive (dead) 5月 10 14:23:27 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: Failed to start The nginx HTTP and reverse proxy server. 5月 10 14:23:27 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: Unit nginx.service entered failed state. 5月 10 14:23:27 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: nginx.service failed. 5月 10 14:26:24 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: Starting The nginx HTTP and reverse proxy server... 5月 10 14:26:24 ip-10-0-0-248.ap-northeast-1.compute.internal nginx[20542]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 5月 10 14:26:24 ip-10-0-0-248.ap-northeast-1.compute.internal nginx[20542]: nginx: configuration file /etc/nginx/nginx.conf test is su...sful 5月 10 14:26:24 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: Failed to read PID from file /run/nginx.pid: Invalid argument 5月 10 14:26:24 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: Started The nginx HTTP and reverse proxy server. 5月 10 15:29:29 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: Stopping The nginx HTTP and reverse proxy server... 5月 10 15:29:29 ip-10-0-0-248.ap-northeast-1.compute.internal systemd[1]: Stopped The nginx HTTP and reverse proxy server. Hint: Some lines were ellipsized, use -l to show in full. 上記のメッセージの中に、下記エラーメッセージ発見! 解決方法は後半で説明します。 Failed to start The nginx HTTP and reverse proxy server. Unit nginx.service entered failed state. nginx.service failed. Failed to read PID from file /run/nginx.pid: Invalid argument unicornのログの状況 /var/www/rails/アプリ名/log に移動し、 $ sudo tail unicorn.log(最新10行のログ確認コマンド)を実行した結果 I, [2021-05-08T17:43:30.984050 #4428] INFO -- : worker=0 ready I, [2021-05-08T17:43:30.985252 #4429] INFO -- : worker=1 ready I, [2021-05-08T18:20:29.354874 #4425] INFO -- : reaped #<Process::Status: pid 4428 exit 0> worker=0 I, [2021-05-08T18:20:29.354950 #4425] INFO -- : reaped #<Process::Status: pid 4429 exit 0> worker=1 I, [2021-05-08T18:20:29.355014 #4425] INFO -- : master complete I, [2021-05-08T19:24:42.486318 #4290] INFO -- : Refreshing Gem list I, [2021-05-08T19:24:44.942332 #4290] INFO -- : listening on addr=/var/www/rails/アプリ名/tmp/sockets/unicorn.sock fd=9 I, [2021-05-08T19:24:44.957852 #4290] INFO -- : master process ready I, [2021-05-08T19:24:44.962589 #4293] INFO -- : worker=0 ready I, [2021-05-08T19:24:44.964148 #4294] INFO -- : worker=1 ready $ netstat -tlntを実行した結果 Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp6 0 0 :::3306 :::* LISTEN tcp6 0 0 :::111 :::* LISTEN tcp6 0 0 :::22 :::* LISTEN 【補足】ツールのバージョン macOs Catalina 10.15.7 Nginx 1.16.1 Unicorn 6.0.0 Rails 6.0.3 Ruby 2.7.2p137 【結論】SELinuxを「Permissive モード」に変更すれば、下記エラーに関しては解消される 先程のエラーメッセージ4列のうち、下記3列に関してはSELinuxのモード変更で簡単に解消できます。 Permissiveモードに変更してください。 Failed to start The nginx HTTP and reverse proxy server. Unit nginx.service entered failed state. nginx.service failed. 手順は下記参考記事の【手順4.2 Permissive モードへの変更】のとおりです。 ▼参考記事 https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-security-enhanced_linux-working_with_selinux-changing_selinux_modes 以上です。 ただし、先程のエラーメッセージ4列のうち、下記1列に関してはまだ解決できていません。 Failed to read PID from file /run/nginx.pid: Invalid argument 解決できたらまた記事にしたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む