- 投稿日:2020-02-05T18:09:36+09:00
「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ④アクセスキーのローテーションと削除
はじめに
AWSには、アカウントやリソースへの脅威検知に対応した、AWS IAM Access Analyzer, AWS Security Hub, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config などのサービスが用意されています。
また、CIS AWS Foundations Benchmark というセキュリティガイドラインが公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できます。自身のAWSアカウントがこのガイドラインにどの程度準拠しているのかを確認/監査する手段として、AWS Security Hubで、CIS AWS Foundations Standardという機能が提供されています。
本記事では、アカウントやリソースへの脅威検知が可能なAWSサービスを有効化するとともに、
CIS AWS Foundations Benchmark
に限りなく準拠することで、セキュアで堅牢なAWSアカウントを実現します。また、これらをお手軽に実現できるCloudFormationテンプレートを公開しています。このCloudFormationテンプレートの実行はこちらから。
アクセスキーのローテーション
アクセスキー とは、IAM ユーザーまたは ルートユーザー の 長期的な認証情報を指し、AWS SDK や AWS API を実行する際にこのアクセスキーを指定することで、このアクセスキーに許可された権限を実行することができます。したがって、このアクセスキーが外部に流出した場合には、 第三者がアカウントへの永続的アクセスを取得する可能性 があります。そこで、CIS AWS Foundations Benchmark では、
- 1.3 90 日間以上使用されていない認証情報は無効にします
- 1.4 アクセスキーは 90 日ごとに更新します
というガイドラインを規定しており、アクセスキーの定期的なローテーションによって、意図せぬアクセスのリスクを低減するように求めています。
上記ガイドラインに準拠するためには、
AWS Config
を用いて、定期的に現在の状態の確認 を行う必要があります。また、上記基準を満たしていないことが判明した場合は、当該のアクセスキーを無効化、もしくは削除 する必要があります。AWS Config
AWS Config
を設定して、上記ガイドラインに準拠しているかどうかを定期的に確認します。「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ①サービスの有効化も合わせてご覧ください。サービスにリンクされたロールの作成
AWS Config
で使用するService-Linked Role
を作成します。このService-Linked Role
は、 AWSリソースへの読み込み権限 と S3への書き込み権限 をConfig
に、また、IAMとSystemManagerへの書き込み権限 をConfig Remediation
にそれぞれ付与します。Resources: ServiceLinkedRoleForConfig: Type: AWS::IAM::ServiceLinkedRole DeletionPolicy: Retain Properties: AWSServiceName: config.amazonaws.com Description: A service-linked role required for AWS Config to access your resources. ServiceLinkedRoleForConfigRemediation: Type: AWS::IAM::ServiceLinkedRole DeletionPolicy: Retain Properties: AWSServiceName: remediation.config.amazonaws.com Description: A service-linked role required for AWS Config Remediation to access your resources.AWS Configの有効化
AWS Config
のDeliveryChannel
とConfigurationRecorder
を作成します。Resources: ConfigDeliveryChannel: Type: AWS::Config::DeliveryChannel Properties: Name: default S3BucketName: !Ref S3ForConfig SnsTopicARN: !Ref SnsTopicARN ConfigConfigurationRecorder: Type: AWS::Config::ConfigurationRecorder Properties: Name: default RecordingGroup: AllSupported: true IncludeGlobalResourceTypes: true RoleARN: !Sub arn:aws:iam::DefaultSecuritySettings:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfigAmazon S3 バケットを作成
設定情報 (履歴ファイルやスナップショット) を保存するために使用する、
Amazon S3
バケットと、それに紐づくバケットポリシーを作成します。Resources: S3ForConfig: Type: 'AWS::S3::Bucket' DeletionPolicy: Retain Properties: BucketName: !Sub defaultsecuritysettings-config-${AWS::Region}-${AWS::AccountId} LifecycleConfiguration: Rules: - Id: ExpirationInDays ExpirationInDays: 60 Status: Enabled PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true S3BucketPolicyForConfig: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3ForConfig PolicyDocument: Version: 2012-10-17 Id: !Ref S3ForConfig Statement: - Effect: Allow Principal: Service: config.amazonaws.com Action: - 's3:GetBucketAcl' - 's3:ListBucket' Resource: - !GetAtt S3ForConfig.Arn - Effect: Allow Principal: Service: config.amazonaws.com Action: - 's3:PutObject' Resource: - !Join - '' - - !GetAtt S3ForConfig.Arn - /AWSLogs/ - !Sub ${AWS::AccountId} - /Config/* Condition: StringEquals: s3:x-amz-acl: bucket-owner-full-controlAWS Config マネージドルールの追加
AWSによって管理されている
AWS Config マネージドルール
の中に、access-keys-rotated
という名称で、アクティブなアクセスキーが指定された日数内にローテーションされるかどうかを確認できるルール が用意されているので、これを追加します。Resources: ConfigIamAccessKeysRotated: DependsOn: - ConfigConfigurationRecorder Type: 'AWS::Config::ConfigRule' Properties: ConfigRuleName: access-keys-rotated Description: アクティブなアクセスキーが、maxAccessKeyAge で指定された日数内にローテーションされるかどうかを確認します。 InputParameters: maxAccessKeyAge: 90 Source: Owner: AWS SourceIdentifier: ACCESS_KEYS_ROTATED上記で設定した AWS Config ルールは定期的に実行され、アカウントがこのルールに準拠しているかどうかの判定が行われます。しかし、これらの設定は、ルールに準拠しているかどうかを判定するだけであるため、もしルールに非準拠であることが判明した場合には、該当するアクセスキーを手動で削除する必要があります。
アクセスキーの強制削除
そこで、以下の内容も設定に加えることで、ガイドラインの基準に違反するアクセスキーを強制的に削除 することができます。ただし下記の設定は、ユーザに確認を求めることなく問答無用にアクセスキーを削除してしまう ため、下記設定を加えるかどうかについては 慎重な検討が必要 です。またもしこの設定を適用する場合でも、ご自身のアカウントの運用ポリシーに合った内容に処理を書き換えることをオススメします。
Amazon CloudWatch Eventsの追加
AWS Config
が発行するAmazon CloudWatch Events
のうち、AWS Configに非準拠のルールが検知された場合のみを抽出して、後述の アクセスキーを強制削除するLambdaの実行トリガ にします。CloudWatchEventsForConfigIamAccessKeysRotated: Type: 'AWS::Events::Rule' Properties: Description: CloudWatch Events about Config when IAM Access Keys are rotated. EventPattern: source: - aws.config detail-type: - Config Rules Compliance Change detail: messageType: - ComplianceChangeNotification newEvaluationResult: complianceType: - NON_COMPLIANT Name: Config State: ENABLED Targets: - Arn: !GetAtt LambdaDeleteExpiredAccessKeys.Arn Id: lambdaLambda 関数の追加
アクセスキーを強制削除するLambdaを作成します。このLambdaは、AWS Configから通知された内容が、 アクティブなアクセスキーが指定された日数(=90日)内にローテーションされるかどうかを確認できる、
access-keys-rotated
に関連するものであることを確認した上で、作成から90日が経過したアクセスキーのみを削除 します。LambdaDeleteExpiredAccessKeys: Type: 'AWS::Lambda::Function' Properties: Code: ZipFile: | import boto3 import datetime import time import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): logger.info(str(event)) if 'detail' in event: detail = event['detail'] if 'configRuleName' in detail: # access-keys-rotated if detail['configRuleName'] == 'access-keys-rotated': iam = boto3.client('iam') users = iam.list_users() for user in users['Users']: if detail['resourceId'] == user['UserId']: access_keys = iam.list_access_keys( UserName=user['UserName'] ) for access_key in access_keys['AccessKeyMetadata']: create_date = access_key['CreateDate'].timestamp() now = time.time() if now - create_date > 60*60*24*90: response = iam.delete_access_key( UserName=user['UserName'], AccessKeyId=access_key['AccessKeyId'] ) Description: 有効期限が過ぎたアクセスキーを削除します FunctionName: deleteExpiredAccessKeys Handler: index.lambda_handler MemorySize: 128 Role: !GetAtt IAMRoleForLambda.Arn Runtime: python3.7 Tags: - Key: !Ref TagKey Value: !Ref TagValue Timeout: 3 TracingConfig: Mode: Active LambdaDeleteExpiredAccessKeysPermission: Type: 'AWS::Lambda::Permission' Properties: Action: lambda:InvokeFunction FunctionName: !Ref LambdaDeleteExpiredAccessKeys Principal: events.amazonaws.com SourceArn: !GetAtt CloudWatchEventsForConfigIamAccessKeysRotated.Arn LambdaDeleteExpiredAccessKeysLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/lambda/${LambdaDeleteExpiredAccessKeys} RetentionInDays: 60下記のCloudFormationテンプレートを実行することで、上記設定を含む、 AWS IAM Access Analyzer, AWS Security Hub, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config などのサービス全てを有効化することも、今回の設定を含むAWS Configのみを有効化することも可能です。
作成されるAWSサービス CloudFormationテンプレート 全てのセキュリティサービス AWS Configのみ 関連リンク
- サービスの有効化 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- パスワードポリシーの自動修復 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- モニタリングと通知の設定 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- アクセスキーのローテーションと削除 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- 投稿日:2020-02-05T17:04:54+09:00
「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ③CISに準拠するためのモニタリングと通知の設定
はじめに
AWSには、アカウントやリソースへの脅威検知に対応した、AWS IAM Access Analyzer, AWS Security Hub, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config などのサービスが用意されています。
また、CIS AWS Foundations Benchmark というセキュリティガイドラインが公開されており、このガイドラインは、AWSアカウントをセキュアに保つために必要なAWSのセキュリティ設定を集めたベストプラクティス集として活用できます。自身のAWSアカウントがこのガイドラインにどの程度準拠しているのかを確認/監査する手段として、AWS Security Hubで、CIS AWS Foundations Standardという機能が提供されています。
本記事では、アカウントやリソースへの脅威検知が可能なAWSサービスを有効化するとともに、
CIS AWS Foundations Benchmark
に限りなく準拠することで、セキュアで堅牢なAWSアカウントを実現します。また、これらをお手軽に実現できるCloudFormationテンプレートを公開しています。このCloudFormationテンプレートの実行はこちらから。
モニタリングと通知の設定
CIS AWS Foundations Benchmark の第3章には、AWSリソースの モニタリング とその 通知 を定めた、以下のガイドライン項目が存在します。
No. ルール 3.1 不正な API 呼び出し に対してログメトリクスフィルタとアラームが存在することを確認します 3.2 MFA なし の AWS マネジメントコンソール サインイン に対してログメトリクスフィルタとアラームが存在することを確認します 3.3 「ルート」アカウントに対してログメトリクスフィルタとアラームが存在することを確認します 3.4 MFA なし の IAM ポリシーの変更 に対してログメトリクスフィルタとアラームが存在することを確認します 3.5 MFA なし の CloudTrail 設定の変更 に対してログメトリクスフィルタとアラームが存在することを確認します 3.6 AWS マネジメントコンソール 認証の失敗 に対してログメトリクスフィルタとアラームが存在することを確認します 3.7 カスタマー作成の CMK の無効化またはスケジュールされた削除 に対してログメトリクスフィルタとアラームが存在することを確認します 3.8 S3 バケットの変更 に対してログメトリクスフィルタとアラームが存在することを確認します 3.9 AWS Config 設定の変更 に対してログメトリクスフィルタとアラームが存在することを確認します 3.10 セキュリティグループの変更 に対するメトリクスフィルタとアラームが存在することを確認します 3.11 ネットワークアクセスコントロールリスト (NACL) への変更 に対するログメトリクスとアラームが存在することを確認します 3.12 ネットワークゲートウェイへの変更 に対するログメトリクスとアラームが存在することを確認します 3.13 ルートテーブルの変更 に対してログメトリクスフィルタとアラームが存在することを確認します 3.14 VPC の変更 に対してログメトリクスフィルタとアラームが存在することを確認します これらのガイドラインに準拠するためには、 まず CloudTrailを有効化 した上で、このログを CloudWatch Logs上に出力 します。また、
Amazon CloudWatch MetricFilter
を用いてログの中から上記項目に該当するデータのみを抽出して メトリクスを作成 します。 メトリクスのデータがAmazon CloudWatch Alarm
で設定した閾値を超えると、Amazon SNS
を経由してその情報がユーザに通知されます。AWS CloudTrail
CloudTrail
を有効化して、このログをCloudWatch Logs
に出力します。「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート - ①サービスの有効化も合わせてご覧ください。IAMロールの作成
AWS CloudTrail
で使用するIAM Role
を作成します。Resources: IAMRoleForCloudTrail: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: cloudtrail.amazonaws.com Action: 'sts:AssumeRole' Description: A role required for CloudTrail to access CloudWatch Logs. Policies: - PolicyName: !Sub 'DefaultSecuritySettings-AWSCloudTrailCloudWatchLogsPolicy-${AWS::Region}' PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'logs:PutLogEvents' - 'logs:CreateLogStream' Resource: - !GetAtt CloudWatchLogsGroupForCloudTrail.Arn RoleName: !Sub 'DefaultSecuritySettings-CloudTrail-${AWS::Region}'AWS CloudTrail を有効化
AWS CloudTrail
を有効化します。Resources: CloudTrail: DependsOn: - S3BucketPolicyForCloudTrail Condition: CreateCentralizedResources Type: AWS::CloudTrail::Trail Properties: CloudWatchLogsLogGroupArn: !GetAtt CloudWatchLogsGroupForCloudTrail.Arn CloudWatchLogsRoleArn: !GetAtt IAMRoleForCloudTrail.Arn EnableLogFileValidation: true EventSelectors: - DataResources: # All S3 buckets - Type: AWS::S3::Object Values: - arn:aws:s3 # All Lambda functions. - Type: AWS::Lambda::Function Values: - arn:aws:lambda IncludeGlobalServiceEvents: true IsLogging: true IsMultiRegionTrail: true SnsTopicName: !Ref SnsTopicName TrailName: DefaultSecuritySettingsCloudWatch Logs のロググループを作成
イベントログファイルを蓄積するために使用する、ロググループを作成します。
Resources: CloudWatchLogsGroupForCloudTrail: Type: 'AWS::Logs::LogGroup' Properties: LogGroupName: /aws/cloudtrail/DefaultSecuritySettings RetentionInDays: 365Amazon CloudWatch
CloudTrailのログから
Amazon CloudWatch MetricFilter
を用いて該当するデータのみを抽出し、 メトリクスを作成します。 メトリクスのデータがAmazon CloudWatch Alarm
で設定した閾値を超えると、Amazon SNS
を経由してその情報がユーザに通知されます。3.1 不正な API 呼び出しに対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailUnauthorizedAPICalls: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.errorCode="*UnauthorizedOperation") || ($.errorCode="AccessDenied*")}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: UnauthorizedAPICalls MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailUnauthorizedAPICalls: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *不正なAPIコールを検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-Unauthorized-API-Calls' ComparisonOperator: GreaterThanOrEqualToThreshold DatapointsToAlarm: 6 EvaluationPeriods: 60 MetricName: UnauthorizedAPICalls Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.2 MFA なしのAWS マネジメントコンソールサインインに対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailLoginWithoutMFA: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName="ConsoleLogin") && ($.additionalEventData.MFAUsed !="Yes")}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: LoginWithoutMFA MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailLoginWithoutMFA: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *MFAなしのログインを検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-Login-Without-MFA' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: LoginWithoutMFA Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.3 「ルート」アカウントに対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailForRootAcount: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{$.userIdentity.type="Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType !="AwsServiceEvent"}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: ForRootAcount MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailForRootAcount: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *ルートアカウントに対する変更を検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-For-RootAcount' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: ForRootAcount Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.4 IAM ポリシーの変更に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailIamPolicyChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=DeleteGroupPolicy) || ($.eventName=DeleteRolePolicy) || ($.eventName=DeleteUserPolicy) || ($.eventName=PutGroupPolicy) || ($.eventName=PutRolePolicy) || ($.eventName=PutUserPolicy) || ($.eventName=CreatePolicy) || ($.eventName=DeletePolicy) || ($.eventName=CreatePolicyVersion) || ($.eventName=DeletePolicyVersion) || ($.eventName=AttachRolePolicy) || ($.eventName=DetachRolePolicy) || ($.eventName=AttachUserPolicy) || ($.eventName=DetachUserPolicy) || ($.eventName=AttachGroupPolicy) || ($.eventName=DetachGroupPolicy)}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: IamPolicyChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailIamPolicyChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *IAMポリシーの変更を検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-IamPolicy-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: IamPolicyChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.5 CloudTrail設定の変更に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailCloudTrailConfigurationChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=CreateTrail) || ($.eventName=UpdateTrail) || ($.eventName=DeleteTrail) || ($.eventName=StartLogging) || ($.eventName=StopLogging)}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: CloudTrailConfigurationChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailCloudTrailConfigurationChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *CloudTrailの設定変更を検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-CloudTrailConfiguration-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: CloudTrailConfigurationChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.6 AWS マネジメントコンソール 認証の失敗 に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailAuthenticationFailuresDetected: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=ConsoleLogin) && ($.errorMessage="Failed authentication")}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: AuthenticationFailuresDetected MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailAuthenticationFailuresDetected: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *ログイン認証失敗を検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-AuthenticationFailures-Detected' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: AuthenticationFailuresDetected Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.7 カスタマー作成のCMK の無効化またはスケジュールされた削除に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailCustomerCreatedCMKsChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventSource=kms.amazonaws.com) && (($.eventName=DisableKey) || ($.eventName=ScheduleKeyDeletion))}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: CustomerCreatedCMKsChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailCustomerCreatedCMKsChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *カスタマー作成CMKの無効化もしくは削除を検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-CustomerCreatedCMKs-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: CustomerCreatedCMKsChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.8 S3 バケットの変更に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailS3BucketPolicyChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: S3BucketPolicyChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailS3BucketPolicyChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *S3のバケットポリシーの変更を検知* しました。' AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-S3BucketPolicy-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: S3BucketPolicyChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.9 AWS Config 設定の変更に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailConfigConfigurationChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventSource=config.amazonaws.com) && (($.eventName=StopConfigurationRecorder) || ($.eventName=DeleteDeliveryChannel) || ($.eventName=PutDeliveryChannel) || ($.eventName=PutConfigurationRecorder))}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: ConfigConfigurationChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailConfigConfigurationChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *Configの設定変更を検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-ConfigConfiguration-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: ConfigConfigurationChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.10 セキュリティグループの変更に対するメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailSecurityGroupChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=AuthorizeSecurityGroupIngress) || ($.eventName=AuthorizeSecurityGroupEgress) || ($.eventName=RevokeSecurityGroupIngress) || ($.eventName=RevokeSecurityGroupEgress) || ($.eventName=CreateSecurityGroup) || ($.eventName=DeleteSecurityGroup)}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: SecurityGroupChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailSecurityGroupChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *セキュリティグループの変更を検知* しました。' AlarmName: !Sub 'Warning-${AWS::StackName}-CloudTrail-SecurityGroup-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: SecurityGroupChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.11 ネットワークアクセスコントロールリスト (NACL) への変更に対するログメトリクスとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailNACLChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=CreateNetworkAcl) || ($.eventName=CreateNetworkAclEntry) || ($.eventName=DeleteNetworkAcl) || ($.eventName=DeleteNetworkAclEntry) || ($.eventName=ReplaceNetworkAclEntry) || ($.eventName=ReplaceNetworkAclAssociation)}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: NACLChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailNACLChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *NACLの変更を検知* しました。' AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-NACL-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: NACLChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.12 ネットワークゲートウェイへの変更に対するログメトリクスとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailNetworkGatewayChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=CreateCustomerGateway) || ($.eventName=DeleteCustomerGateway) || ($.eventName=AttachInternetGateway) || ($.eventName=CreateInternetGateway) || ($.eventName=DeleteInternetGateway) || ($.eventName=DetachInternetGateway)}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: NetworkGatewayChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailNetworkGatewayChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *ネットワークゲートウェイの変更を検知* しました。' AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-NetworkGateway-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: NetworkGatewayChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.13 ルートテーブルの変更に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailRouteTableChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=CreateRoute) || ($.eventName=CreateRouteTable) || ($.eventName=ReplaceRoute) || ($.eventName=ReplaceRouteTableAssociation) || ($.eventName=DeleteRouteTable) || ($.eventName=DeleteRoute) || ($.eventName=DisassociateRouteTable)}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: RouteTableChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailRouteTableChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *ルートテーブルの変更を検知* しました。' AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-RouteTable-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: RouteTableChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching3.14 VPC の変更に対してログメトリクスフィルタとアラームが存在することを確認します
Resources: CloudWatchLogsMetricFilterCloudTrailVpcChanges: Type: 'AWS::Logs::MetricFilter' Properties: FilterPattern: '{($.eventName=CreateVpc) || ($.eventName=DeleteVpc) || ($.eventName=ModifyVpcAttribute) || ($.eventName=AcceptVpcPeeringConnection) || ($.eventName=CreateVpcPeeringConnection) || ($.eventName=DeleteVpcPeeringConnection) || ($.eventName=RejectVpcPeeringConnection) || ($.eventName=AttachClassicLinkVpc) || ($.eventName=DetachClassicLinkVpc) || ($.eventName=DisableVpcClassicLink) || ($.eventName=EnableVpcClassicLink)}' LogGroupName: !Ref CloudWatchLogsGroupForCloudTrail MetricTransformations: - MetricName: VpcChanges MetricNamespace: LogMetrics MetricValue: '1' CloudWatchAlarmMetricFilterCloudTrailVpcChanges: Type: 'AWS::CloudWatch::Alarm' Properties: ActionsEnabled: true AlarmActions: - !Ref SnsTopicARN AlarmDescription: '*CloudTrail* が *VPCの変更を検知* しました。' AlarmName: !Sub 'Notice-${AWS::StackName}-CloudTrail-Vpc-Changes' ComparisonOperator: GreaterThanOrEqualToThreshold EvaluationPeriods: 1 MetricName: VpcChanges Namespace: LogMetrics OKActions: - !Ref SnsTopicARN Period: 60 Statistic: Maximum Threshold: 1 TreatMissingData: notBreaching
AWS Security Hub
を用いて、CIS AWS Foundations Standard
に対する達成度を確認することができますが、上記の項目をただAmazon SNS
に送信しただけでは、ガイドライン準拠とは見なされません。ガイドラインに準拠するためには、このAmazon SNSに対する サブスクライバーの登録 が必須となりますので、Eメールや(AWS Chatbotから)Slack等を経由して、上記結果を受信できる環境を整えましょう。なお、下記のCloudFormationテンプレートを実行することで、上記設定を含む、 AWS IAM Access Analyzer, AWS Security Hub, Amazon Inspector, Amazon GuardDuty, AWS CloudTrail, AWS Config などのサービス全てを有効化することも、今回の設定内容のみを有効化することも可能です。
作成されるAWSサービス CloudFormationテンプレート 全てのセキュリティサービス 今回の設定のみ 関連リンク
- サービスの有効化 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- パスワードポリシーの自動修復 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- モニタリングと通知の設定 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- アクセスキーのローテーションと削除 - 「セキュアで堅牢なAWSアカウント」を実現する CloudFormationテンプレート
- 投稿日:2020-02-05T16:26:33+09:00
LaravelでAWS認証エラーが起きる?恐らくそれはconfig_cacheの影響です
約6年ぶりくらいにPHP(初Laravel)を触ってるのですがプチハマりしました。残存cacheの影響でハマるとか、物凄く良くありそうなシチュエーションなのに具体的な解決策を見つけられなかったので書いておきます。
LaravelでAWSソリューションを使ってるとこんなエラーレスポンスにめぐりあうかもしれません。
{ "code": "400", "message": "Client error: `GET http://169.254.xxx.xxx/latest/meta-data/iam/security-credentials/` resulted in a `404 Not Found` response:\n<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www. (truncated...)\n", "exception": "GuzzleHttp\\Exception\\ClientException" }このエラーはAWSの認証情報であるCredentialsが何かダメですよ!という内容です。
いやいや.envにちゃんとAWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEY書いてあるYO!という時には、恐らくconfigファイルがキャッシュされているせいで正常にAWSのCredentialsが読み込めておらずエラーレスポンスになってる事があります。
ちなみに稼働環境でphp artisan config:clear
を叩けば最新の.envを読み込み(キャッシュもします)するので解消すると思います。ただし私の環境ではデプロイにDeployerを使っています。なのでデプロイ時に自動実行してもらう為にtaskへ入れておこうと思ったのですが、どうやら標準のタスクには無いようです。なので自分でdeploy.phpにカスタマイズタスクを記載して呼び出します。
task('artisan:config:clear', function () { run('php {{release_path}}/artisan config:clear'); }); /** * Main task */ desc('Deploy your project'); task('deploy:laravel', [ 'deploy:info', 'deploy:prepare', 'deploy:lock', 'deploy:release', 'deploy:update_code', 'deploy:shared', 'deploy:vendors', 'deploy:writable', 'artisan:storage:link', 'artisan:view:clear', 'artisan:cache:clear', 'artisan:config:cache', 'artisan:optimize', // optimizeで何かやってるらしく、ここに書かないとうまく機能しません(面倒なのでちゃんと調べてない) 'artisan:config:clear', 'deploy:symlink', 'deploy:unlock', 'cleanup', ]);ぶっちゃけconfig:clearタスクは省いても良い気がするのですがオーバーヘッドも対してなさそうなので放置しています。
- 投稿日:2020-02-05T14:47:40+09:00
AWS SDKやCLIでS3に対するアカウントレベルの操作を行う場合はS3 Controlを利用する
はじめに
AWS SDKからアカウントレベルでブロックパブリックアクセスの設定を行いたかったのですが
SDKドキュメントのs3の項目にはバケット単位で設定を行う項目はあるものの、
アカウントレベルで設定を行う項目が見当たりません。
アカウントレベルで設定を行うには AWS S3 Control に対してAPIリクエストを行う必要がありました。AWS S3 Control
AWS S3 Controlは、アカウントレベルのブロックパブリックアクセス設定や
バッチオペレーション、アクセスポイントの管理など、
Amazon S3 コントロールプレーンに対するオペレーションのアクセスを提供します。提供されているアクションは以下のドキュメントを参照
Amazon S3 API Reference - AWS S3 Control
https://docs.aws.amazon.com/AmazonS3/latest/API/API_Operations_AWS_S3_Control.html例
アカウントレベルのブロックパブリックアクセスを設定する場合の例です。
Boto3
以下のように実行します。
import boto3 client = boto3.client('s3control') response = client.put_public_access_block( PublicAccessBlockConfiguration={ 'BlockPublicAcls': True, 'IgnorePublicAcls': True, 'BlockPublicPolicy': True, 'RestrictPublicBuckets': True }, AccountId='123456789012' )ドキュメントは以下です。
Boto3 Docs / Available Services / S3Control
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3control.htmlAWS CLI
以下のように実行します。
$ aws s3control put-public-access-block --account-id 123456789012 \ --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"コマンドリファレンスは以下です。
AWS CLI Command Reference - S3 Control
https://docs.aws.amazon.com/cli/latest/reference/s3control/index.htmlその他の言語の例やリンクについては割愛させていただきます。
以上です。
- 投稿日:2020-02-05T13:11:18+09:00
AWS EC2 AmazonLinux2 のdockerホスト用初期設定
やりたいこと
AmazonLinux2に、以下の設定をまとめて実行する。
- タイムゾーンを日本に
- 言語を日本語に
git
docker
docker-compose
最新版インストール- 以下のコマンドのエイリアス(ショートカット)作成
元のコマンド エイリアス docker dcr docker-compose ddc 追記: dockerのエイリアスを dcr に修正しました
コマンド
sudo yum update -y sudo cp /etc/localtime /etc/localtime.org sudo ln -sf /usr/share/zoneinfo/Japan /etc/localtime sudo mv /etc/sysconfig/clock /etc/sysconfig/clock.bk sudo echo -e 'ZONE='Asia/Tokyo'\nUTC=true' > /etc/sysconfig/clock sudo mv /etc/sysconfig/i18n /etc/sysconfig/i18n.bk sudo echo 'LANG=ja_JP.UTF-8' > /etc/sysconfig/i18n export LANG=ja_JP.utf8 export LC_ALL=ja_JP.utf8 sudo yum install -y git jq sudo amazon-linux-extras install -y docker sudo service docker start sudo chkconfig docker on sudo usermod -a -G docker ec2-user #本番環境などでは危険だからやらないでね! compose_version=$(curl https://api.github.com/repos/docker/compose/releases/latest | jq .name -r) output='/usr/local/bin/docker-compose' sudo curl -L https://github.com/docker/compose/releases/download/$compose_version/docker-compose-$(uname -s)-$(uname -m) -o $output sudo chmod +x $output echo "alias dcr='docker'" >> ~/.bashrc echo "alias ddc='docker-compose'" >> ~/.bashrc source ~/.bashrcおまけ: rootでもdocker-composeを使う場合の設定
sudo visudoで
sudoers
編集画面を開き# :/usr/local/binをおしりに追加 Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/binの通りに編集して、保存。
そして以下のコマンドを実行。
sudo sh -c "echo alias dcr='docker' >> /root/.bashrc" sudo sh -c "echo alias ddc='docker-compose' >> /root/.bashrc"
- 投稿日:2020-02-05T13:05:06+09:00
WindowsにCDK環境構築する手順(Python)
CDK環境(python)を整えるための自分用メモです。
※動作未検証です、pythonのバージョンが違うとエラーになった実績もありますので、参考程度でお願いします。・AWS CLI導入
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-windows.html#install-msi-on-windows・AWS IAM アクセスキー設定
コマンドプロンプトで下記コマンド実行
aws configure※事前にアクセスキーとシークレットキーを用意すること
・Node.js8.0以上導入
https://nodejs.org/ja/・CDK導入
コマンドプロンプトで下記コマンド実行
npm install -g aws-cdk・Python3導入
https://www.python.org/downloads/windows/
⇒導入後、「python」コマンドが利用できること(Pathが通っていること)を確認する・エディタ(VisualStudio Code+Python拡張)
https://code.visualstudio.com・git導入
https://git-scm.com/download/win※下記はオプション(とりあえずなくても良い)
・pyyaml導入(設定ファイルをYAMLにして読み込む用途で利用)
pip install pyyaml
- 投稿日:2020-02-05T10:08:13+09:00
AWSCDKでVPCをデプロイする
はじめに
AWSCDKはTypeScriptやPythonといったプログラミング言語でCloudFormationのテンプレートを生成できるフレームワークです。
今回はAWSCDK(TypeScript)でVPCをデプロイする書き方を紹介していきます。必要なパッケージ
VPC関係の定義は
@aws-cdk/aws-ec2
にあります。$ npm i -D @aws-cdk/aws-ec2Stackファイルを書く
import cdk = require("@aws-cdk/core") import { DefaultInstanceTenancy, RouterType, Vpc, Subnet, CfnInternetGateway, CfnVPCGatewayAttachment } from "@aws-cdk/aws-ec2" export class CreateVPCStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props) const vpc = new Vpc(this, "cdk-vpc", { cidr: "10.0.0.0/16", defaultInstanceTenancy: DefaultInstanceTenancy.DEFAULT, enableDnsSupport: true, enableDnsHostnames: true, subnetConfiguration: [] }) const pubSubnet = new Subnet(this, "PublicSubnet1c", { availabilityZone: "us-west-2c", vpcId: vpc.vpcId, cidrBlock: "10.0.0.0/24" }) new Subnet(this, "PrivateSubnet1c", { availabilityZone: "us-west-2c", vpcId: vpc.vpcId, cidrBlock: "10.0.1.0/24" }) new Subnet(this, "PrivateSubnet1d", { availabilityZone: "us-west-2c", vpcId: vpc.vpcId, cidrBlock: "10.0.2.0/24" }) const internetGateway = new CfnInternetGateway(this, "InternetGateway", {}) new CfnVPCGatewayAttachment(this, "gateway", { vpcId: vpc.vpcId, internetGatewayId: internetGateway.ref }) pubSubnet.addRoute("PubSubnetRoute", { routerType: RouterType.GATEWAY, routerId: internetGateway.ref }) } }Stackファイルの説明
VPC
各パラメータを渡してVPCを構築します。
subnetConfiguration
を指定しなければいくつかSubnetが用意されます。
今回はSubnetを自分で構築したいので、subnetConfiguration
に[]
を指定します。const vpc = new Vpc(this, "cdk-vpc", { cidr: "10.0.0.0/16", defaultInstanceTenancy: DefaultInstanceTenancy.DEFAULT, enableDnsSupport: true, enableDnsHostnames: true, subnetConfiguration: [] })Subnets
ここではPublicのSubnetを一つとPrivateのSubnetを2つ作っています。
const pubSubnet = new Subnet(this, "PublicSubnet1c", { availabilityZone: "us-west-2c", vpcId: vpc.vpcId, cidrBlock: "10.0.0.0/24" }) new Subnet(this, "PrivateSubnet1c", { availabilityZone: "us-west-2c", vpcId: vpc.vpcId, cidrBlock: "10.0.1.0/24" }) new Subnet(this, "PrivateSubnet1d", { availabilityZone: "us-west-2c", vpcId: vpc.vpcId, cidrBlock: "10.0.2.0/24" })PublicのSubnetに外からアクセスするためのインターフェースを定義します。
const internetGateway = new CfnInternetGateway(this, "InternetGateway", {}) new CfnVPCGatewayAttachment(this, "gateway", { vpcId: vpc.vpcId, internetGatewayId: internetGateway.ref }) pubSubnet.addRoute("PubSubnetRoute", { routerType: RouterType.GATEWAY, routerId: internetGateway.ref })さいごに
これでVPCをCDKでデプロイすることができるようになりました。
次回はこのVPCを利用してRDSのデプロイをしていこうと思います。
ではまた!!!
- 投稿日:2020-02-05T01:48:45+09:00
AWSの10分間チュートリアルをやってみる 2.Linux 仮想マシンの起動
こんにちは。トリドリといいます。
新卒で入社した会社でJavaを数年やった後、1年ほど前に転職してからはRailsを中心に使用してアプリケーションの開発をしているしがないエンジニアです。今回、AWSの勉強をするために公式の10分間チュートリアルをやってみることにしたので、備忘のために記事に残していこうと思います。
AWSに関しては、1年ほど前転職活動をしていた時期にEC2とRDSを少し触っていた以外ほとんど触ったことが無い初心者です。
(ただし、このときにアカウントを作ったので、12ヶ月の無料枠は切れていました)前回は「AWS コストの管理」を行いました。
今回は「Linux 仮想マシンの起動」をやっていきます。Linux 仮想マシンの起動
https://aws.amazon.com/jp/getting-sdtarted/tutorials/launch-a-virtual-machine/
前述の通り、EC2は少しだけ触ったことがあります。
ただ、独学で少し触っただけでそれから1年近くほぼ触れていないため、かなり記憶の彼方へ行ってしまいました。
ということで、このチュートリアルを通して再度学びなおしていきたいと思います。概要
EC2 = クラウド上に仮想マシンを作成したり、実行したりするためのサービス
インスタンス = AWS上の仮想マシン
という用語の説明がされていますステップ 1:AWS にサインアップする
すでにアカウントは作成済みなので、ただログインするだけのステップです。
このチュートリアルで作成するリソースは無料利用枠の対象です
とありますが、前述の通り12ヶ月の無料枠はすでになくなっているので、有料です…
ステップ 2:Amazon EC2 インスタンスを作成する
a./b.
こちらも、AWSマネジメントコンソールからEC2ダッシュボードを開き、「Launch instance」を押すだけのステップです。
チュートリアルの画像と実際の画面はデザインが変わっています。
私の記憶にある画面はチュートリアルの方なので、1年の間にデザインがリニューアルされたのでしょう。ステップ 3:インスタンスを設定する
a.
Amazon Machine Image (AMI)を選択します。
設定画面上にもAMI は、インスタンスの作成に必要なソフトウェア構成 (OS、アプリケーションサーバー、アプリケーション) を含むテンプレートです。
と説明があるのは親切ですね。
無料枠の期間が過ぎたらその絞り込みも消えると思っていたので、これが残っているのも意外でした。チュートリアルに従って 「Amazon Linux AMI」を選択します。
b.
インスタンスタイプを選択します。
インスタンスタイプはCPU、メモリ、ストレージ、ネットワークキャパシティの組み合わせによって構成されている
ということなのでハード面ですね。
ノートPCを買う時に当てはめてみると、
AMIを決めるのはMacにするのかWindowsにするのかを決めるところで、
インスタンスタイプを決めるのは例えばMacだったらAirにするのかProにするのかを決めるところ、
みたいな感じでしょうか。c.
ここでチュートリアルは確認と作成に進みます。
このあとのステップでサブネットを設定したりセキュリティの設定をしたりできるのは記憶にあるのですが、設定の仕方はうろ覚えなのでチュートリアルに従って私も確認と作成に進みます。
「確認と作成」はPrimaryボタンになっているので、目立つボタンをただ押すだけです。この間のステップについては、今後の10分間チュートリアルで出てくるかは定かではないですが、出てこなければ別途勉強しようと思います。
d.
インスタンスを起動します。
起動ボタンを押すとまずはキーペアを作成するか既存のキーペアを選択するかのダイアログが表示されます。
- キーペアにはパブリックキーというAWSに保存されるキーとプライベートキーというユーザーが保存するキーがあること
- プライベートキーをなくしたらインスタンスにアクセスできないこと
- 第三者がプライベートキーを入手するとその第三者がインスタンスにアクセスできてしまうので、安全な場所に保存する必要があること
がチュートリアルには記載されています。
ここではチュートリアルに従ってキーペアを作成し、
.ssh
ディレクトリに保存します。キーペアの設定後に「インスタンスの起動」ボタンを押すとインスタンスが起動します。
e.
ボタンを押してインスタンス一覧に戻るだけのステップです。
f.
インスタンスの一覧です。
作成したインスタンスは、「インスタンスの状態」がrunnning
になれば起動完了です。
画面の上部には一覧が、下部には選択したインスタンスの詳細が表示されています。チュートリアルに従って、下部の「説明」タブからIPv4パブリックIPをコピーしておきます。
ステップ 4:インスタンスに接続する
作成したインスタンスにSSHを利用して接続します。
とりあえず、SSH = ネットワークで接続された機器同士で安全に通信するための手段ということがわかっていれば先に進めそうです。[SSHについて詳しそうな記事]
https://qiita.com/Pana/items/70cc74cd20c8b5b4fe15
https://qiita.com/angel_p_57/items/2e3f3f8661de32a0d432
https://qiita.com/angel_p_57/items/c441aa469107136aacc5
https://qiita.com/tag1216/items/5d06bad7468f731f590e私の環境がMacなので、Macの手順で進めます。
a.
SSHで接続できるかを確認するため、ターミナルで下記コマンドを実行します。
$ ssh下記のように出てくれば、SSHクライアント(SSHで接続する方のプログラム)が存在するので、OK
usage: sshb.
chmod
コマンドを使用して、プライベートキーのファイルに対し、所有者だけがアクセスできるように権限の設定をします。
コマンドは下記の通り。chmod 400 { プライベートキーのパス }c.
インスタンスに接続します。
コマンドのフォーマットは次の通りです。ssh -i { プライベートキーのフルパス } { ユーザー名 }@{ インスタンスのIPアドレス }Amazon Linux AMIのインスタンスではユーザー名は
ec2-user
なので、ssh -i { プライベートキーのフルパス } ec2-user@{ インスタンスのIPアドレス }となります。
初めての接続時は、
The authenticity of host 'IPアドレス (IPアドレス)' can't be established. Are you sure you want to continue connecting (yes/no)?と聞かれるので、
yes
と打ち込みます。d.
__| __|_ ) _| ( / Amazon Linux AMI ___|\___|___| https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/のようにウェルカム画面が表示されれば接続成功です。
今回の詰まったところ
最初に接続しようとすると何度やってもタイムアウトしてしまいました。
ググって見つけた下記記事を参考にVPCの確認をした結果、時期の通りルートテーブルが正しく設定されていませんでした。
https://qiita.com/yuta-ushijima/items/0c8fbcf315a850c636f4
1年前の自分が触って放置した結果…
とりあえず記事の通りに設定して接続できましたが、VPCとかサブネットとかも記憶の彼方へ行ってしまったので、また勉強し直したいと思います。ステップ 5:インスタンスを削除する
a.
EC2コンソールのインスタンスで画面上部のアクションから「terminate」を選択します。
日本語にしているとstopが停止、terminateが終了でぱっと見分かりづらいので英語のほうが良いと思います。b.
ダイアログで「Yes, Terminate」を押すと、インスタンスが削除されます。
チュートリアルでa.の「terminate」は英語なのに、ここの「Yes, Terminate」は日本語なのが気になる…まとめ
難しいことは考えず、とりあえず起動して接続して削除するだけのチュートリアルでした。
1年前に少し触っていた分、このチュートリアル範囲以上のことはほとんど忘れてしまっていることにも気がつけたので良かったのですが、初めてでこれをやるのはそれ以外の範囲が広がっていることを認識するのが難しそうに思ってしまいました。
本当に10分間でさわりだけ体験できる感じなので、ちゃんと勉強するには本などで体系立ててやる必要がありそうですが、とりあえず「ウェブサイトとウェブアプリ」のチュートリアルについてはこのまま進めて行こうと思っています。次回は、「WordPress ウェブサイトの起動」に進む予定です。
- 投稿日:2020-02-05T00:50:10+09:00
なぜ僕たちはサーバレスでJavaを諦めTypescriptを採用したか
この記事は個人ブログのうち技術に関する箇所のみを抜粋した転載です。
なぜ僕たちはサーバレスでJavaを諦めTypescriptを採用したか -Junks, GC cannot sweep-またブログには書いたのですが、諸事情により先に英語版が存在します。
こちらも書いたのは僕なので、剽窃などではないことはご了承ください。[元記事]: Why we replaced Java with Typescript for Serverless in dev.to
はじめに
サーバレス(serverless)は昨今もっとも注目を集める設計手法の一つで、おそらく多くの開発者が大なり小なり自分のプロダクトに応用し始めているのではないでしょうか?
僕自身、完全にサーバレスに魅せられてしまい、昔ながらの自分でサーバやミドルウェアを管理しながら運用するみたいな世界には戻れる気がしません。
そもそもスケーリングや分散可能性をきちんと考えて設計されたアプリケーションであれば、旧来のサーバーアプリケーションの機能から受けられる恩恵も比較的少なくなりますし、サーバレスに切り替えるデメリットはそこまでありません。
最近は設計に関して相談された時は、必ずサーバレスの話題を出してみることにしています。さて、サーバレスは既存の開発手法とは大きく異なるため、今持っている知識を刷新し、既存の手法や技術スタックを見直しながら開発していく必要があります。
見直しというからには、開発基盤として何の言語を使うかも、当然ながら見直さなくてはいけない技術スタックの対象になります。タイトルにある通り、最終的に僕たちはTypescriptを採用し、およそ一年半開発・メンテナンスを行ってきました。
そして一年半経った今、あくまで個人的な感想ではありますが、Typescriptは僕たちが期待した以上に成果を出してくれました。そこでこの記事では、以前使用していた言語にどんな問題があったのか、そしてなぜTypescriptに切り替えたことでどんな恩恵があったのかをこの記事では解説していきたいと思います。
なぜJavaを諦めなくてはならなかったのか
さて、なぜTypescriptを採用したかについて話す前に、まずなぜ以前使用していた非常に強力な言語であるJavaを諦めなくてはいけなかったかについてお話ししたいと思います。
NOTE
先に述べておきますが、僕は結構なJava好きです。なんなら初めて触った言語もJavaでした。
JVMに関してもそれなりに勉強して、その神がかったランタイムの仕組みにかなり感銘を受けています。(てか多分作ったやつは神)
なので、どこかの大学生のようにJavaがクソだとかレガシーだとか使い物にならんとか、この記事でそういうことを言うつもりは一切ありません。
また、そういったコメントもあまり嬉しくないです。あくまでサーバレスという仕組みにJavaがあまり合わなかっただけなので。
その点だけはご了承いただければ幸いです。
さて、本題に戻りましょう。
僕たちのサービスでは、サーバサイドはサービス設立当時から基本的にJavaだけで書かれていました。
当然ながらすでにJavaには多くの利点があり、特に
- プラットフォームフリー
- よくできたJITコンパイル
- やばいGC
- よく構成された文法
- 静的型付け
- 関数型サポート(最近は特に)
- 多様なライブラリ
- 信頼できるコミュニティ(Oracleではなく、開発者の方)
などなど挙げればきりがありません。
しかし、AWS Lambda上でコードを試していて気づいたのですが、Javaはあまりサーバレスに向かないことがわかりました。
理由としては以下のことが挙げられます。
- JVMの起動オーバーヘッドが大きい
- Springフレームワークを使用してるとさらにエグくなる
- 最終的なパッケージアーカイブがでかすぎる(でかいのは100MB以上)
- 関数が増えてくるとWebフレームワークなしでリクエストを捌くのがきつくなる
- コンテナは30分程度しか走らないため、G1GCやJITなどのJavaの利点が生かせない
- Lambdaは基本的にEC2上に建てられたAmazon Linuxのコンテナで動くため、プラットフォームフリーは関係ない。 (欠点ではないけど)
上述の点は全てなかなかに厄介ですが、今回は特に厄介だった問題についてもう少し書いてみたいと思います。
Cold Startがまじで厄介
一番厄介だったのは、圧倒的にCold Startのオーバーヘッドです。おそらく多くの開発者の方々もこいつに悩まされているのではないかと思います。。。
僕たちはコンピューティング基盤としてAWS Lambdaを使っていたのですが、AWS Lambdaはユーザからのリクエストが来るたびに新しいコンテナを立ち上げます。
一度立ち上がってしまえば、しばらくは同じコンテナインスタンスを再利用してくれるのですが、初回起動時にはJavaのランタイムに加え、フレームワークで利用されるDIコンテナやWebコンテナなども全て初期化する必要があります。
さらに言えば、一つのコンテナで処理できるのはあくまで一つのリクエストのみで、複数のリクエストを処理することはできません。(内部で数百のリクエストスレッドをプーリングしてたとしても同じです。)
つまりどういうことかというと、もし複数のユーザがリクエストを同時に送ってきた場合、Lambdaは起動中のコンテナの他に、別のコンテナを起動しなくてはいけなくなるということです。
通常、僕たちはどの時間に具体的に何軒のリクエストが同時に来るかを事前に予測することはできません。
つまり、何らかの仕組みを作ったとしても、事前に全てのLambdaをhot standbyさせることはできないのです。これは必然的にユーザに数秒から10秒以上の待機時間を強制し、ユーザビリティを著しく下げることにつながります。
こんな感じでCold Startがえげつない事を理解した僕らは、これまでの数年かけて書かれた技術スタックを捨てて、他の言語を選択することを決めました。
なぜTypescriptを選んだのか
めちゃくちゃ恥ずかしい話なのですが、正直Lambdaでサポートされている全ての言語をきちんと精査・比較して決めたわけではないのです。
ただ、正直な話、状況的にTypescript以外の選択肢はなかったのです。まず第一に、動的型付け言語は外しました。長期に渡ってスキルのバラバラな開発者によって保守・メンテ。拡張されるコードなので、動的型付けはあまり使いたくありません。
したがって、PythonとRubyに関してはかなり序盤で選択肢から外れました。
C#とGoに関しても、現在ほとんどのチームがJavaをメインに開発しているサービスなので、既存言語とあまりかけ離れた言語を使うと新規開発者のジョインが難しくなると判断し、今回は見送られました。
もちろん、昨今この二大言語は非常に注目度が高く、特にGolangに関しては徐々にシェアを伸ばしつつあるのは知っています。
しかし、急いでサーバレスに開発を移す必要があったため、僕たち自身のキャッチアップの時間も考慮し、見送らざるを得なかった感じでした。Typescriptの利点
という事で、僕たちはTypescriptを使い始めたわけです。
Typescriptの利点を挙げるとしたらこんな感じでしょうか?
- 静的型付け
- 小さいパッケージアーカイブ
- ほぼ0秒の起動オーバーヘッド
- Javaとjavascriptの知識が再利用できる
- NodeJSのライブラリやコミュニティが使える
- javascriptと比べても関数型プログラミングがしやすい
- ClassとInterfaceにより構造化されたコードが描きやすい
長期に渡って運用・開発が行われるプロジェクトにおいて静的型付け言語がどれだけ大きな恩恵を与えるかは今更語るまでもありませんので、ここには書きません。
ここでは主に、Typescriptのどういった点がサーバレス開発によく馴染んだかについて書いていきたいと思います。
静的型付け以外にもTypescriptを使う利点は非常に大きく、小さいパッケージと小さい起動オーバーヘッド
おそらくサーバレスでTypescriptを使う利点という観点からいうとこれが一番大事だった気がします。(なにせ他のメリットはほぼTypescript自体のメリットなので・・・)
先ほど触れた通り、JavaはJVM本体やフレームワークが利用するDI/Webコンテナなどの起動にかかるオーバヘッドが非常に大きいです。
加えて、Javaの性質上、AWS Lambdaで流すには以下の
Additionally, as the nature of Java, it has the following weak point to be used in the AWS Lambda.マルチスレッドとそれを取り巻くエコシステム
マルチスレッドは非常に強力な機能であり、事実として僕たちはこの機能のおかげで多くのパフォーマンス問題を解決してきました。
JVM自体もガーベージコレクションやJITコンパイルにおいて、デフォルトでにマルチスレッドを活用してあの素晴らしいランタイムを実現してます。
(詳しくはG1GCやJIT Compileを参照)しかし、起動時間単体で見ると、アプリケーションに使用する全てのスレッドを立て終わるまでに、100ミリ秒から数秒かかっていることがわかります。
この機能自体は旧来のいわゆるクラサバモデルでEC2上で動くアプリケーションならほぼ無視できるオーバーヘッドですが、LambdaなどのFaaS上で動くサーバレスアプリケーションでは決して無視できません。Typescriptはnodejsベースであり、基本的にシングルスレッドです。非同期は別スレッドや別プロセスではなくあくまでジョブキュー、イベントループなどで管理されます。
したがって、ほとんどのライブラリやフレームワークは起動時にスレッド展開をする必要はありませんし、ランタイムを起動するためのオーバーヘッドもほとんどかかりません。
巨大なパッケージアーカイブ
サーバレスにおいてソースコードのパッケージアーカイブは、基本的に小さいに越したことはありません。
Lambdaのコンテナは起動時、AWSにより管理されたソースコード用のS3バケットからソースをダウンロードし、コンテナに展開します。
S3からのダウンロード時間は通常非常に短時間ですが、100MBや200MBとなると無視はできません。
NodeJsのパッケージは基本的にJavaに比べて小さくなります。
正直なんでそうなるかに関しては不勉強でわかっていないのですが、以下の理由が関係してるんじゃないかなと思ったりします。(もしこれやでっていうのをご存知の方はコメントで教えてください)
- Javaのフレームワークやライブラリは包括的なものも多く、本来使いたい機能に必要ない依存性を引き込んで来るが、javascriptは目的特化のライブラリが多く、必要最低限に依存を抑えられることが多い。
- Javascript(nodejs)は1ファイルに複数のmoduleを書くことができ、それでいてメンテもしやすいが、Javaにおけるメンテナンス性の重要なポイントはファイル分割とパッケージ管理のためソースが肥大化しやすい。
実際Javaで書いていた時は最大で200MB以上のパッケージができることもあったのですが、nodejsに変えてからは35MB程度で済んでいます。
この巨大なパッケージアーカイブは、僕たちがSpringで書かれた旧来のコードを再利用しようとしたのが大きな原因なのですが、実際これらのいらないフレームワークを除いて最適化したコードでも、どうしても50MBは必要になってしまいました。
Javascriptの知識やエコシステムを利用できる
僕たちもWeb開発者のため、基本的にフロントエンドも書きます。したがって、ある程度のjavascriptやnodejsに関する知識は蓄えていました。
Jquery全盛時代からReact/Vueのようなモダンフレームワークでの開発までを通じて、言語的な特徴はある程度抑えていましたし、どうやって書けばいいコードになるかもある程度理解してるつもりです。
Typescriptはjavascriptの拡張言語であり、最終的にはjavascriptにトランスパイルされます。
多くの文法やイディオムはjavascriptから受け継がれているので、実際それほど準備期間を要さずにサービス開発を始められました。
加えて、ほとんどのメジャなNodeJSのライブラリはTypescriptに必要な型定義を提供しているので、NodeJSのエコシステムのメリットをそのまま享受できたのも非常に嬉しいポイントでした。
関数型の実装が非常にしやすい
昨今の技術トレンドを語る上で、関数型の台頭はなくして語ることはできません。
関数型の実装はその性質上、シンプルでテスト可能で危険性の低い安定したコードを書くのに大きく寄与します。特にAWS Lambdaの場合、常に状態を外部化するコードが求められるため、状態や副作用を隔離する関数型の実装は非常に相性が良く、メンテもしやすくなります。
そもそも、jqueryの生みの親であるJohn ResigがJavaScriptニンジャの極意で語ったように、javascriptはそもそも関数型のプログラミングをある程度サポートしています。
javascriptにおいて関数は関数は第1級オブジェクトであり、jqueryも実は関数型で書かれることを期待して作られています。しかし一方で、動的型付け言語で関数型のコードを書こうとすると、時折非常にめんどくさい事になることがあります。
例えば、プリミティブ型だけで表現できる関数は非常に限られますし、返り値や引数にObjectを取るのは普通に結構危険です。しかしtypescriptでは引数や返り値に型を指定することができます。
加えて、以下のTypescriptの機能は、僕たちの達の書く関数の表現の幅を広げ、より安全でシンプルなコードを書くのに寄与してくれます。
- Type: 共通に使用される型をコンテクストに合わせて型付けできる。(stringとUserIdやPromiseとResponseなど)
- Interface/Class: Objectで表現されるの引数や返り値をコンテクストにあった型で表現できる。
- Enum: よもや語る必要もあるまい
- Readonly: 自分で作成した型をImmutableに出来る
- Generics: 関数のインターフェイスの表現の幅が広がる
Typescriptは他にも関数型で書こうとした時に非常に便利な機能をいろいろ備えていますが、全てをここであげることはしません。(っていうか、結構javascript由来のものが多い)
関数型とTypescriptに関する記事は今後どこかで書いていきたいなと思っています。
Javaで学んだBest Practiceを再利用できる
typescriptの文法を学ぶと、かなりJavaやScalaに似通った記述ができることに驚きます。
僕たちはそもそも、それなりの期間をJavaで開発してくる中で、Javaにおけるいいコードのお作法をある程度蓄積してきました。
ClassやInterfaceをどう設計すべきか、enumはどう使うと効率的か、Stream APIはどう書くと保守性が上がるかなど、蓄積してきたノウハウはそれなりに捨てがたいものがありました。Typescriptはインターフェイスやクラスに加えて、アクセスモディファイアやreadonly(Javaでいうfinalのプロパティ)をサポートしており、僕たちは割とさらっとJavaで育んだノウハウをそのまま導入することができました。
これにはオブジェクト指向的なベストプラクティスやデザインパターンなども含まれます。
(関数指向とオブジェクト指向は二律背反ではないので、プロジェクト内で同時に使用されても問題ないと考えています。個人的には。)もし僕たちがやや文法が独特なPythonやRubyを採用していたとしたら、より品質の高いコードを書くためのプラクティスをどうこの言語に応用すべきかに多くの時間を費やすこになったことかと思います。(それも楽しいんですよ、知ってます、ただ時間がね。。。。)
当然ながら全ての設計やロジックをコピペしたわけではないですし、むしろ大半のコードを書き直ししました。
ただ、おおよその部分をスクラッチで書き直した割に、それなりの品質でそれなりの短期間で書き直しが終わったんだよということは特筆しておくべきかと思います。結論
僕たちもまだまだTypescriptに関しては初心者といっていいレベルでまだまだ勉強が必要ですが、すでにそのメリットは全力で享受しておりいます。
今聞かれれば、Golangもいいなあとか、MicronautとGraalVMとかも面白そうだなあとか、もっと他の選択肢もあったかもなあとか考えたりもするのですが、現状Typescriptには非常に満足しており、最善の選択肢の一つではないかと信じています。
もちろん、処理遅いけどバッチ処理どうすんねんとか、並行処理とか分散処理同すんねんとか、、ワークフロウどう設計すんねんとか、API Gatewayのタイムアウトどうハンドルするねんとか、データの一貫性どう担保すんねんとか、サーバレスやTypescriptに起因する問題にはたくさんぶち当たりました。
ただ、それはそれでギークとして非常に楽しく取り組んできて、すでにいくつかのこれが今の所best practiceじゃね?っていう方法もいくつか見つけました。(これはのちのち記事にしていきたい。)
もし今Javaでサーバレスに取り組んでいて、サーバレスくそやん、きついやん、やっぱ普通にサーバ欲しいわってなっている方がいたら、ぜひTypescriptも試してみてください。想像する以上に生産性出るんじゃないかなぁって期待してます。
長文おつきあいいただきありがとうございました。何かコメントや訂正があればぜひお願いします。
- 投稿日:2020-02-05T00:35:23+09:00
AWS EKSを使用したKubernetes自動構築ツール作った
Kubernetes構築構築ツール作りました!
やっと出来ましたk8s構築ツール(仮)です!長かった。。Ansibleとシェルスクリプト触ったの久々だしTerraformは初めて触るしで時間にして丸々4日くらいかかりました。。
k8s環境構築ツールを作ろうとした理由
- 半年くらい前に少しだけ触ってたが本格的にk8sの知識が必要になりく勉強する必要が出てきたため。
- 一々手動で環境構築するのが手間だと感じたため
AWS EKSを使用した理由
k8s勉強用のVM作るのは難易度が高そう
VMを使用してk8s環境作ろうとするとMaster Node用とWorker Node用にVMを複数作成してそれぞれネットワーク接続できるようにして更にもっと作業して。。と今の自分の保有スキルに対して作業難易度が高めかなぁと思ったからです。(ただ今はネスぺの勉強もしてるので近いうちに挑戦してみたいです!)
AWS触ってみたいから
昨今AWSを使用してるPJが周囲でも増えてきたため、仮に別PJに移ったとして「AWSって聞いたことあるけど分からないマン」となるのは避けなければと思ったからです。
EKSが半額
正直このニュース見て「やらねば(使命感)」となったことが一番の理由かもです 笑
ツールの使い方
前提条件
- AWSアカウントを作成してIAMユーザが作成してあること
- ローカルマシンにvagrantがインストールされてること
k8s環境作成
- mkdir <作業用ディレクトリ> && cd <作業用ディレクトリ>
- vagrant init ubuntu/xenial64
- vagrant up
- vagrant ssh
- ログイン後以下コマンドを実行
git clone https://github.com/arthur-maki/eks_env_tool.git -b feature-add_iam_and_vpc- cd eks_env_tool
- source k8s_env.sh
create
を入力した後以下を入力
aws_secret_access_key
aws_access_key_id
env_name
VpcBlock
(VPC)のCIDERPublicSubnet01Block
、PublicSubnet02Block
のCIDERPrivateSubnet01Block
、PrivateSubnet02Block
のCIDER- うまくいけば構築完了
k8s環境削除
- cd eks_env_tool
- source k8s_env.sh(※)
※ virtualenvが起動してる時((eks_env) ユーザ@ホスト
)は必ずdeactivate
コマンドを実行してユーザ@ホスト
になることを確認してから実行destroy
を入力した後環境構築した時と同じパラメータを入力
- うまくいけば削除成功。念のため、各AWSサービスを見て削除されてるか確認
[捕捉]
構築した時とは異なるvagrant環境でも削除できるように作ってあるため、vagrant init ubuntu/xenial64
で別環境を作ってからk8s環境を削除しても良い確認した動作環境
- vagrantのubuntu/xenial64(latestバージョン)
- vagrantユーザ
本来であれば一般ユーザでも確認するべきだが多分大丈夫だと思う。。今後やりたいこと
ソースコードの見直し
シェルスクリプトとAnsibleコードがありえないくらい汚い。というよりファイル名も適切じゃないかもだし変数名もひどい。全体的に見直す必要あり。というか心が仏の優しいどなたかレビューしてください。。
他ubuntuバージョンだったり他OSに対応
需要があれば対応していきたい
アドバイスやその他意見があればドシドシください!