- 投稿日:2022-02-01T23:43:21+09:00
Amazon Kinesis Video Streams から動画を受信して画像処理をおこなう (Python)
GetMediaForFragmentList または GetClip API を使って動画を取得し、画像を抜き出して処理する方法です。 関連 Amazon Kinesis Video Streams から動画をリアルタイム受信して画像処理をおこなう (Java) HLS から受信して処理 (OpenCV+ffmpeg) Amazon Kinesis Video Streams から HLS URL を取得し、VideoCapture に指定することで、HLS から受信することができます。 LIVE(最新映像)/LIVE_REPLAY(指定日時以降の過去映像)/ON_DEMAND(指定区間の過去映像)のいずれかを指定して再生可能。 HLS の仕組み上、セグメント長(1s~10s)ごとに映像が更新されるため、元映像のセグメント長に応じて遅延が発生する。 フレームごとの日時などのメタデータが取得できない。(と思われる) import os import boto3 import cv2 OUTPUT_DIR = "output" def get_data_endpoint(stream_name: str, api_name: str) -> str: """ call GetDataEndpoint API https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_GetDataEndpoint.html """ kinesis_video = boto3.client("kinesisvideo") res = kinesis_video.get_data_endpoint(StreamName=stream_name, APIName=api_name) return res["DataEndpoint"] def get_hls_streaming_session_url(stream_name: str) -> str: """ call GetHLSStreamingSessionURL API https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_reader_GetHLSStreamingSessionURL.html """ res = boto3.client( "kinesis-video-archived-media", endpoint_url=get_data_endpoint(stream_name, "GET_HLS_STREAMING_SESSION_URL") ).get_hls_streaming_session_url( StreamName=stream_name, PlaybackMode="LIVE" ) return res["HLSStreamingSessionURL"] def process(stream_name: str): hls_url = get_hls_streaming_session_url(stream_name) cap = cv2.VideoCapture(hls_url) for i in range(300): ret, frame = cap.read() if frame is None: break file_path = os.path.join(OUTPUT_DIR, f"{i:04d}.png") cv2.imwrite(file_path, frame) print(f"Saved: {file_path}") cap.release() 指定期間のセグメントデータを取得して処理 ListFragments + GetMediaFromFragmentList API でセグメント単位で受信し、一旦ファイルに保存してから各フレームを取得して処理します。 指定区間の過去映像のみ取得可能 OpenCV+ffmpeg の場合 import operator import os from datetime import datetime from tempfile import NamedTemporaryFile import boto3 import cv2 from botocore.response import StreamingBody OUTPUT_DIR = "output" READ_FRAGMENTS = 1 # いちどに読み込むフラグメントの数 def get_data_endpoint(stream_name: str, api_name: str) -> str: """ call GetDataEndpoint API https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_GetDataEndpoint.html """ kinesis_video = boto3.client("kinesisvideo") res = kinesis_video.get_data_endpoint(StreamName=stream_name, APIName=api_name) return res["DataEndpoint"] def list_fragments(stream_name: str, start_time: datetime, end_time: datetime) -> list[dict]: """ call ListFragments API https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_reader_ListFragments.html """ res = boto3.client( "kinesis-video-archived-media", endpoint_url=get_data_endpoint(stream_name, "LIST_FRAGMENTS") ).list_fragments( StreamName=stream_name, FragmentSelector={ "FragmentSelectorType": "PRODUCER_TIMESTAMP", "TimestampRange": { "StartTimestamp": start_time, "EndTimestamp": end_time } } ) return res["Fragments"] def get_media_for_fragment_list(stream_name, fragment_numbers: list[str]) -> StreamingBody: """ call GetMediaForFragmentList API https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_reader_GetMediaForFragmentList.html """ res = boto3.client( "kinesis-video-archived-media", endpoint_url=get_data_endpoint(stream_name, "GET_MEDIA_FOR_FRAGMENT_LIST") ).get_media_for_fragment_list( StreamName=stream_name, Fragments=fragment_numbers ) return res["Payload"] def process_media(start_dt: datetime, media: StreamingBody): print(f"--> {start_dt}") with NamedTemporaryFile(suffix=".mkv") as f: f.write(media.read()) cap = cv2.VideoCapture(f.name) i = 0 while True: ret, frame = cap.read() if frame is None: break frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) file_path = os.path.join(OUTPUT_DIR, f"{start_dt}.{i:02d}.png") cv2.imwrite(file_path, frame) print(f"Saved: {file_path}") i += 1 cap.release() def chunks(lst: list, n: int) -> list: for i in range(0, len(lst), n): yield lst[i:i + n] def process(stream_name: str, start_dt: datetime, end_dt: datetime): all_fragments = list_fragments(stream_name, start_dt, end_dt) sorted_fragments = sorted(all_fragments, key=operator.itemgetter("ProducerTimestamp")) for fragments in chunks(sorted_fragments, READ_FRAGMENTS): fragment_numbers = list(map(lambda x: x["FragmentNumber"], fragments)) media = get_media_for_fragment_list(stream_name, fragment_numbers) process_media(fragments[0]["ProducerTimestamp"], media) imageio+ffmpeg の場合 def process_media(start_dt: datetime, media: StreamingBody): print(f"--> {start_dt}") with NamedTemporaryFile(suffix=".mkv") as f: f.write(media.read()) reader = imageio.get_reader(f.name, "ffmpeg") # class imageio.plugins.ffmpeg.FfmpegFormat.Reader metadata = reader.get_meta_data() print(json.dumps(metadata)) for i, frame in enumerate(reader): frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) file_path = os.path.join(OUTPUT_DIR, f"{start_dt}.{i:04d}.png") cv2.imwrite(file_path, frame) print(f"Saved: {file_path}") reader.close()
- 投稿日:2022-02-01T23:41:44+09:00
Amazon Kinesis Video Streams から動画画像をリアルタイム受信して画像処理をおこなう (Java)
Kinesis Video Streams の API 呼び出しは AWS SDK for Java を、ストリームから MKV を解析するためのライブラリとして別途 Amazon Kinesis Video Streams Parser Library が提供されているので、これらを使って処理する方法です。 参考) Amazon Kinesis Video Stream Parser Library 関連 Amazon Kinesis Video Streams から動画を受信して画像処理をおこなう (Python) AWS クライアントクラス (AWS SDK) Kineis Video Streams は 3 つのカテゴリに分かれており、API によって異なる以下の Client クラスを使用します。ストリームに対する操作は API によって異なるデータエンドポイントを指定する必要があります。 AmazonKinesisVideoClient AmazonKinesisVideoMediaClient AmazonKinesisVideoArchivedMediaClient 例) GetMedia API の呼び出し Regions region = Regions.AP_NORTHEAST_1; String streamName = "stream-test"; // AWS 認証情報 AWSCredentialsProvider credentialsProvider = new ProfileCredentialsProvider(); // AmazonKinesisVideoClient を生成 AmazonKinesisVideoClient amazonKinesisVideo = AmazonKinesisVideoClientBuilder.standard() .withRegion(region) .withCredentials(credentialsProvider) .build(); // AmazonKinesisVideoMediaClient を生成 : GetDataEndpoint API でデータエンドポイントを取得して指定する String endPoint = amazonKinesisVideo.getDataEndpoint(new GetDataEndpointRequest().withAPIName(APIName.GET_MEDIA).withStreamName(streamName)).getDataEndpoint(); AmazonKinesisVideoMediaClient amazonKinesisVideoMedia = AmazonKinesisVideoMediaClientBuilder.standard() .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, region.getName())) .withCredentials(credentialsProvider) .build(); // GetMedia API 呼び出し StartSelector startSelector = new StartSelector().withStartSelectorType(StartSelectorType.NOW); GetMediaResult result = amazonKinesisVideoMedia.getMedia(new GetMediaRequest().withStreamName(streamName).withStartSelector(startSelector)); // ストリーム生成 InputStream inputStream = new InputStreamParserByteSource(result.getPayload()); StreamingMkvReader ストリームから MKV エレメントを読み出すクラスです。Visitor クラス(後述)を指定することで読み出した MKV エレメントを処理します。 StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(inputStream); mkvStreamReader.apply(visitor); MkvElementVisitor ストリームから読み出したセグメント、フレームを処理するクラスです。 MkvElementVisitor CompositeMkvElementVisitor FrameRendererVisitor FrameVisitor : フレーム+メタデータを処理する (フレーム単位) FragmentMetadataVisitor : メタデータを処理する (フラグメント単位) FragmentProgressTracker OutputSegmentMerger : セグメントをマージして出力する SimpleFrameVisitor : フレームを処理する(簡易版) (フレーム単位) CopyVisitor CountVisitor ElementSizeAndOffsetVisitor MkvChildElementCollector CompositeMkvElementVisitor 複数の Visitor を束ねます。 CompositeMkvElementVisitor visitors = new CompositeMkvElementVisitor(visitor1, visitor2, ...); OutputSegmentMerger 指定したストリームに出力します。 OutputSegmentMerger outputSegmentMerger = OutputSegmentMerger.createDefault(outputStream); FrameVisitor FrameVisitor.FrameProcessor を継承して処理を記述します。 class MyFrameProcessor implements FrameVisitor.FrameProcessor { @Override public void process(final Frame frame, final MkvTrackMetadata trackMetadata, final Optional<FragmentMetadata> fragmentMetadata) throws FrameProcessException { // TODO } } FrameVisitor frameVisitor = FrameVisitor.create(new MyFrameProcessor()); 以下のデータが処理できます。 Frame : フレームデータ trackNumber : トラック番号 (1~) timeCode : タイムコード (セグメント先頭からの時間 (ms)) keyFrame : キーフレームかどうか invisible discardable lacing frameData : フレームデータ MkvTrackMetadata : トラックに対するメタデータ trackNumber : トラック番号 (1~) trackUID [OPTIONAL] trackName : kinesis_video codecId : コーデック (例: "V_MPEG4/ISO/AVC") codecName : コーデック名 pixelWidth [OPTIONAL] : 横ピクセル数 pixelHeight [OPTIONAL] : 縦ピクセル数 samplingFrequency [OPTIONAL] channels [OPTIONAL] bitDepth [OPTIONAL] FragmentMetadata : フラグメントに対するメタデータ fragmentNumberString : フラグメント番号 (String) serverSideTimestampMillis : サーバータイムスタンプ (UNIX EPOCH (ms)) producerSideTimestampMillis : プロデューサータイムスタンプ (UNIX EPOCH (ms)) fragmentNumber : フラグメント番号 (BigInteger) success : 成否 (boolean) errorId : エラー番号 (long) errorCode : エラーコード (String) millisBehindNow [OPTIONAL] continuationToken [OPTIONAL] FrameProcessor には以下のものが用意されています。 H264FrameDecoder : H.264 デコード H264FrameRenderer H264BoundingBoxFrameRenderer H264FrameRenderer 映像をウインドウに表示する Visitor KinesisVideoFrameViewer frameViewer = new KinesisVideoFrameViewer(1280, 720); frameViewer.setVisible(true); H264FrameRenderer frameRenderer = H264FrameRenderer.create(frameViewer); FrameVisitor frameRenderVisitor = FrameVisitor.create(frameRenderer); H264FrameDecoder H.264 デコードして処理したい場合はこちらを継承します。 class MyFrameDecodeProcessor extends H264FrameDecoder { @Override public void process(final Frame frame, final MkvTrackMetadata trackMetadata, final Optional<FragmentMetadata> fragmentMetadata) throws FrameProcessException { BufferedImage image = decodeH264Frame(frame, trackMetadata); // TODO } } FrameVisitor frameVisitor = FrameVisitor.create(new MyFrameDecodeProcessor()); 以下のようにすれば JPEG で保存できます。 Date d = new Date(fragmentMetadata.get().getProducerSideTimestampMillis() + frame.getTimeCode()); String dt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").format(d); File outputFile = new File(String.format("output/%s.jpg", dt)); ImageIO.write(image, "jpg", outputfile);
- 投稿日:2022-02-01T23:36:09+09:00
カスタムドメイン+S3+静的ウェブサイトホスティング+SSL化(Terraform)
前書き 間違った情報もあると思うので、話半分で聞いてね☆ 前提 独自ドメインを取得済み ながーれ route53に静的ウェブサイトを公開したいレコードを登録 acmにてssl証明書を取得 S3に静的ファイルを配置 Cloud Frontディストリビューションを作成 レッツTerraform まずはゾーンの登録とレコードの追加です。 取得済みドメインは heigineer.jpの体にします。 余談ですが、ゾーンはレコードを管理するためのコンテナです。 同じvpc内であればひとつのゾーン下で色々なサブドメインを切り、さまざまなトラフィックを制御することもできます。 route53.tf // zoneの登録 resource "aws_route53_zone" "main" { name = "heigineer.jp" } resource "aws_route53_record" "info" { zone_id = aws_route53_zone.main.zone_id name = "www.heigineer.jp" type = "A" alias { name = aws_cloudfront_distribution.info.domain_name zone_id = aws_cloudfront_distribution.info.hosted_zone_id evaluate_target_health = false } } ipv4でipとドメインを紐づけるAレコードとして登録します。 aliasについてはのちほど作成するCloud Frontディストリビューションを指定しています。 次にssl通信を実現するためにacmのサービスを利用し、ssl証明書を発行します。 acm.tf resource "aws_acm_certificate" "info" { domain_name = "www.heigineer.jp" validation_method = "DNS" provider = aws.virginia } resource "aws_route53_record" "info_validation" { for_each = { for dvo in aws_acm_certificate.info.domain_validation_options : dvo.domain_name => { name = dvo.resource_record_name record = dvo.resource_record_value type = dvo.resource_record_type } } allow_overwrite = true name = each.value.name records = [each.value.record] ttl = 60 type = each.value.type zone_id = aws_route53_zone.main.zone_id } resource "aws_acm_certificate_validation" "example" { certificate_arn = aws_acm_certificate.info.arn validation_record_fqdns = [for record in aws_route53_record.info_validation : record.fqdn] } ポイントとして、Cloud Frontでacmの証明書を利用する場合はバージニア北部のリージョンを指定する必要があるので、providerをそれに対応させます。 あらかじめ以下のようにproviderのaliasを使って構成を用意しておくと良いかと思います。 config.tf provider "aws" { region = "us-east-1" alias = "virginia" } その他証明書周りの詳細な挙動については深く把握できていないので、割愛させてください。 基本的にterraformの公式からコピッたコードになってます。 上記の手順で、ゾーン、レコード、ssl証明書を手配するリソースができたので、続いて静的ページ用のコンテンツをS3に準備します。 s3.tf resource "aws_s3_bucket" "info" { bucket = "www.heigineer.jp" acl = "public-read" website { index_document = "index.html" } } resource "aws_s3_bucket" "cloudfront_logs" { bucket = "logs" acl = "private" } data "aws_iam_policy_document" "info" { statement { actions = [ "s3:GetObject" ] resources = [ "${aws_s3_bucket.info.arn}/*" ] condition { test = "StringLike" variable = "aws:referer" values = ["https://www.heigineer.jp"] } principals { identifiers = ["*"] type = "*" } } } resource "aws_s3_bucket_policy" "info" { bucket = aws_s3_bucket.info.id policy = data.aws_iam_policy_document.info.json } resource "aws_s3_bucket_object" "object" { bucket = aws_s3_bucket.info.id key = "index.html" source = "./index.html" etag = filemd5("./index.html") } index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>My test page</title> </head> <body> <p>This is my page</p> </body> </html> いくつかポイントを補足していきます。 公開用ファイルのバケット名ですが、これはroute53に登録したレコードと一致している必要があるっぽいです。 websiteブロックで静的ウェブサイトオブジェクトとして取り扱う定義をし、 index_documentでルートドメインアクセス時に返すファイルを指定しています。 ポリシードキュメントなのですが、conditionブロックで、ポリシーのキーバリューとリクエストコンテキストの一致を検証し、Cloud Frontからのアクセスのみを許容するための記述を施しています。aws:refererでアクセス元のURLがvaluesの値と部分一致しているかを見ています。 またCloud Frontログ用バケットも作成しました。 そして次にCloud Frontディストリビューションの作成です。 cloudfront.tf resource "aws_cloudfront_distribution" "info" { // コンテンツの保存場所 origin { // ウェブサイトオブジェクトとして取り扱うのでwebsite_endpoint domain_name = aws_s3_bucket.info.website_endpoint origin_id = aws_s3_bucket.info.id // s3で指定したポリシーに合わせ、nameとvalueのheaderを指定 custom_header { name = "referer" value = "https://www.heigineer.jp" } // customオリジンとして取り扱うための定義 custom_origin_config { http_port = "80" https_port = "443" origin_protocol_policy = "http-only" origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"] } } // Cloud Frontディストリビューションの有効化の可否 enabled = true // ipv6の対応可否 is_ipv6_enabled = true // ロギング設定 logging_config { include_cookies = false bucket = aws_s3_bucket.cloudfront_logs.bucket_domain_name prefix = "info_pages/" } // Cloud Frontの代替ドメイン(CNAME) aliases = ["www.heigineer.jp"] default_cache_behavior { allowed_methods = ["GET", "HEAD"] cached_methods = ["GET", "HEAD"] target_origin_id = aws_s3_bucket.info.id // クエリ文字列やcookieのoriginへの転送設定 forwarded_values { query_string = false cookies { forward = "none" } } // originへのアクセスプロトコルの指定 viewer_protocol_policy = "redirect-to-https" min_ttl = 0 default_ttl = 3600 max_ttl = 86400 } // コンテンツ配信の地理別制限 restrictions { geo_restriction { restriction_type = "none" } } // ssl構成設定 viewer_certificate { cloudfront_default_certificate = false acm_certificate_arn = aws_acm_certificate.info.arn ssl_support_method = "sni-only" minimum_protocol_version = "TLSv1.2_2021" } } originブロックでコンテンツの保存場所を指定しています。 今回、静的ウェブサイトホスティングを使用するので、domain_nameはwebsite_endpointを指定します。 custom_headerブロックなのですが、バケットポリシーに指定したconditionの条件を満たすためにcustom_headerとして、refererとurlのname、valueを指定しています。もしかするとこれはこなくても良いのかもしれませんが、外すと403でアクセスできなかったので、定義しています。 このあたりちょっとよくわかりません。。。 静的ウェブサイトホスティングを利用する場合は、カスタムオリジンとして取り扱いわなければならないそうなので、custom_origin_configを定義しています。ちなみにカスタムオリジンとはS3などで配置する単純な静的ファイル等ではなく、一般的なWebサーバーとしてコンテンツを取り扱うオリジンのことみたいです。 aliasesはCloud Frontの代替ドメインを指定しています、これは作成したレコードとリンクさせておく必要があるみたいです。 cacheの挙動は以下の記事がわかりやすかった気がします。 viewer_protocol_policyはredirect-to-httpsを選んでおくのが無難な気がします。 viewer_certificateはあらかじめ取得したacmの証明書リソースを指定しています。 あとは色々とよしなに手を入れてもらってapplyしてもらえればアクセスできるんじゃないかなーと。 (できなかったらごめんなさい、誤りや不足等があったのだと。。。) 疑問に思ったこと Cloud Frontディストリビューションにて、custom_headerでrefererを指定しなければバケットポリシーで定義したIAM条件演算子をパスできなかったこと。(Cloud Frontからのアクセスのみ許容するという要件が満たせなかったこと) aws_route53_recordリソースを作った際のaliasでCloud Frontディストリビューションを指定しているのに、なぜCloud Front側のリソースで再度aliasesを定義してあげないとダメなのか? 静的ウェブサイトホスティングの場合オリジンをカスタムオリジンとして取り扱わなければならない性質上、OAIによるアクセス制限ができない。公式にはカスタムヘッダーの利用が推奨されていたので、X-なんちゃらのようなnameとランダム文字列のvalueでヘッダーを送り、バケットポリシー側で指定した文字列がリクエストとして送られてきているかというようなconditionで制限をかけようと思ったのですが、うまくいかず。。。refererを使用することにしました。カスタムオリジンにおいて、「Cloud Frontからのアクセスのみ許可」という要件を満たすのには何がベスプラなのだろうか。。。 https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-overview.html#forward-custom-headers-restrict-access おわりに Cloud Front難しい。
- 投稿日:2022-02-01T23:31:09+09:00
Terraformを使ってEC2インスタンスの自動起動/自動停止環境を構築する
はじめに もう何番煎じかわかりませんが、EC2インスタンスの自動起動・停止を実現する環境が欲しくなったので構築します。 会社で検証に使っているAWS環境が1週間ごとに消えてしまう仕様なので、毎回手動で設定しなくてもいいようにTerraformを使って環境構築の自動化を行いました。 実現したかったこと AWS EC2インスタンスの自動起動・停止を行い、利用料を削減する 平日の9:00〜21:00の間だけ稼働させる。ただし休日に作業したい際や、夜通し動かしたいといった要件に備えて柔軟にスケジュール設定できるようにしておく 検証環境のため、対象サーバは基本全部。インスタンスが増えてもコードや設定をいじらずに対応できるようにする。また一応特定のインスタンスをターゲットにできるようにしておく できる限り最小限の稼働で環境構築を行う 成果物と使い方 以下のGitLab.comに今回作成したコードをあげています。 「とにかく使えればいい」場合はこちらからcloneなりforkしてREADMEを参照の上お使いください。 突貫工事のため、コードが汚いですがご了承ください。 Gitリポジトリ:https://gitlab.com/skitamur/aws-terraform 使い方:https://gitlab.com/skitamur/aws-terraform/-/blob/main/autostartstop_function/README.md 参考手順 基本は以下の公式ページのプロセスを参考にTerraformを作成しています。 https://aws.amazon.com/jp/premiumsupport/knowledge-center/start-stop-lambda-eventbridge/ 前提条件 AWS IAMユーザー(AdministratorAccess) Terrafrom v1.1.2 aws provider : v3.74.0 archive : v2.2.0 概要 各tfファイルの簡単な概要と解説になります。 フォルダ・ファイル構成 $ tree autostartstop_function autostartstop_function . ├── README.md ├── cloudwatch_event.tf ├── data_lambda_src.tf ├── iam_lambda.tf ├── lambda_function.tf ├── lambda_permission.tf ├── local.tf ├── provider.tf └── src ├── autostart │ └── autostart.py └── autostop └── autostop.py Provider Gitにあげる関係上、access_keyとsecret_keyは環境変数にて設定する記載にしています(設定方法はGitのREADMEを参照) Lambdaにコードをアップする際に該当のフォルダをzip圧縮する必要があるため、archive providerを使用します。 provider.tf provider "aws" { #Set the access key to the environment variable "AWS_ACCESS_KEY_ID". #Set the secret key to the environment variable "AWS_SECRET_ACCESS_KEY". region = local.region } provider "archive" {} local.tf(抜粋) locals { region = "ap-northeast-1" IAM Lambda用のIAMロール、IAMポリシーを作成してaws_iam_policy_attachmentで関連づけます。 参考ページとほぼ同じポリシーですが、実環境からインスタンスIDを取得するため、ポリシーにec2:Describe*actionを追記しています。 iam_lambda.tf resource "aws_iam_role" "lambda_role" { name = local.iam_role.name assume_role_policy = local.iam_role.assume_role_policy } resource "aws_iam_policy" "lambda_policy" { name = local.iam_policy.name policy = local.iam_policy.policy } resource "aws_iam_policy_attachment" "lambda-iam-attach" { name = "lambda-iam-attachment" roles = [ aws_iam_role.lambda_role.name ] policy_arn = aws_iam_policy.lambda_policy.arn } local.tf(抜粋) iam_role = { name = "AutoStartStopRoleForLambda" assume_role_policy = <<EOT { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOT } iam_policy = { name = "AutoStartStopPolicy" policy = <<EOT { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": [ "ec2:Start*", "ec2:Stop*", "ec2:Describe*" ], "Resource": "*" } ] } EOT } Lambda用Python 参考ページのコードをベースとしていますが、以下2点の修正を行なっています。 ReginをLambdaの環境変数から取得する。もし環境変数REGIONの指定がない場合はデフォルト値ap-northeast-1を使う 指定のRegion上にあるインスタンスIDを取得し、配列に格納。もし環境変数INSTANCESの指定がない場合は取得したインスタンスID全てを対象とする(詳細は後述) autostart.py import boto3 import os region = os.environ.get('REGION','ap-northeast-1') ec2 = boto3.client('ec2', region_name=region) ec2_data = ec2.describe_instances() ec2_instance_id = list() for ec2_reservation in ec2_data['Reservations']: for ec2_instance in ec2_reservation['Instances']: ec2_instance_id.append(ec2_instance['InstanceId']) instances = os.environ.get('INSTNACES',ec2_instance_id) def lambda_handler(event, context): ec2.start_instances(InstanceIds=instances) print('started your instances: ' + str(instances)) autostop.py import boto3 import os region = os.environ.get('REGION','ap-northeast-1') ec2 = boto3.client('ec2', region_name=region) ec2_data = ec2.describe_instances() ec2_instance_id = list() for ec2_reservation in ec2_data['Reservations']: for ec2_instance in ec2_reservation['Instances']: ec2_instance_id.append(ec2_instance['InstanceId']) instances = os.environ.get('INSTNACES',ec2_instance_id) def lambda_handler(event, context): ec2.stop_instances(InstanceIds=instances) print('stopped your instances: ' + str(instances)) Pythonスクリプトを圧縮 Lambdaに作成したPythonスクリプトをアップする際はzipに圧縮する必要があるため、archive providerのdata.archive_fileを使って圧縮します。 data_lambda_src.tf # Lambda File archive to Zip data "archive_file" "autostart_lambda_file" { type = local.autostart_lambda_file.archive_file_type source_dir = local.autostart_lambda_file.lambda_source_dir output_path = local.autostart_lambda_file.deploy_upload_filename } # Lambda File archive to Zip data "archive_file" "autostop_lambda_file" { type = local.autostop_lambda_file.archive_file_type source_dir = local.autostop_lambda_file.lambda_source_dir output_path = local.autostop_lambda_file.deploy_upload_filename } local.tf(抜粋) autostart_lambda_file = { archive_file_type = "zip" lambda_source_dir = "./src/autostart" deploy_upload_filename = "./src/autostart_lambda_src.zip" } autostop_lambda_file = { archive_file_type = "zip" lambda_source_dir = "./src/autostop" deploy_upload_filename = "./src/autostop_lambda_src.zip" } Lambda Function いくつかパラメータがあるので、特徴的なものを説明します。 filename:Lambdaスクリプトを指定。今回はarchive_fileで作成したzipファイルを参照 role:前述のIAMロールを指定 handler:実行するLambdaのハンドラーを指定。今回は上記のスクリプトの通りautostart.lambda_handlerとなる source_code_hash:ソースコードのハッシュ値を参照して、もし異なる場合はソースコードの更新を実施する local.tfのvariablesでLambdaの環境変数を指定しています。ここでINSTANCESをコメントアウトしているので、デフォルトでは全インスタンスを対象としています。 もしインスタンスを指定する場合はコメントアウトを解除し、記載方法を参考に修正してください。 lambda_function.tf resource "aws_lambda_function" "autostart_lambda" { filename = data.archive_file.autostart_lambda_file.output_path function_name = local.autostart_lambda_function.function_name role = aws_iam_role.lambda_role.arn handler = local.autostart_lambda_function.handler source_code_hash = data.archive_file.autostart_lambda_file.output_base64sha256 runtime = local.autostart_lambda_function.runtime timeout = local.autostart_lambda_function.timeout environment { variables = local.autostart_lambda_function.variables } } resource "aws_lambda_function" "autostop_lambda" { filename = data.archive_file.autostop_lambda_file.output_path function_name = local.autostop_lambda_function.function_name role = aws_iam_role.lambda_role.arn handler = local.autostop_lambda_function.handler source_code_hash = data.archive_file.autostop_lambda_file.output_base64sha256 runtime = local.autostop_lambda_function.runtime timeout = local.autostop_lambda_function.timeout environment { variables = local.autostop_lambda_function.variables } } local.tf(抜粋) autostart_lambda_function = { filename = "autostart.py" function_name = "StartEC2Instances" runtime = "python3.9" timeout = 10 handler = "autostart.lambda_handler" variables = { REGION = local.region # If INSTANCES is not set, then all instances will be targeted. #INSTANCES = "[i-XXXXXXXXXXX,i-XXXXXXXXXXX]" } } autostop_lambda_function = { filename = "autostop.py" function_name = "StopEC2Instances" runtime = "python3.9" timeout = 10 handler = "autostop.lambda_handler" variables = { REGION = local.region # If INSTANCES is not set, then all instances will be targeted. #INSTANCES = "[i-XXXXXXXXXXX,i-XXXXXXXXXXX]" } } EventBridge CloudWatch EventはEventBridgeに包含されましたが、使うresourceはaws_cloudwatch_event_ruleやaws_cloudwatch_event_targetになります。 schedule_expressionにcronを記述することで柔軟なスケジュール実行を実現できます。 cronはUTC(日本時間-9時間)なので、時間の記載には気をつけてください。 is_enabledにtrueやfalseを設定することで、自動実行のON/OFFを切り替えられます。「停止は自動化したいけど起動は自分でやる」といった使い方にも対応可能です。 cloudwatch_event.tf # Auto Start Rule resource "aws_cloudwatch_event_rule" "autostart_rule" { name = local.autostart_event_rule.name description = local.autostart_event_rule.description schedule_expression = local.autostart_event_rule.schedule_expression is_enabled = local.autostart_event_rule.is_enabled } # Auto Start Target resource "aws_cloudwatch_event_target" "autostart_target" { arn = aws_lambda_function.autostart_lambda.arn rule = aws_cloudwatch_event_rule.autostart_rule.id } # Auto Stop Rule resource "aws_cloudwatch_event_rule" "autostop_rule" { name = local.autostop_event_rule.name description = local.autostop_event_rule.description schedule_expression = local.autostop_event_rule.schedule_expression is_enabled = local.autostop_event_rule.is_enabled } # Auto Stop Target resource "aws_cloudwatch_event_target" "autostop_target" { arn = aws_lambda_function.autostop_lambda.arn rule = aws_cloudwatch_event_rule.autostop_rule.id } local.tf(抜粋) autostart_event_rule = { name = "StartEC2Instances" description = "Start EC2 Instances" # Run at 0:00 (UTC) every Monday through Friday schedule_expression = "cron(0 0 ? * MON-FRI *)" is_enabled = true } autostop_event_rule = { name = "StopEC2Instances" description = "Stop EC2 Instances" # Run at 12:00 (UTC) every Monday through Friday schedule_expression = "cron(0 12 ? * MON-FRI *)" is_enabled = true } Lambdaのパーミッション設定 参考ページの手順では気にすることのない設定ですが、Terraformで実行する際は明示的に設定が必要な箇所になります。 詳細は以下のページに記載されています。 https://aws.amazon.com/jp/premiumsupport/knowledge-center/eventbridge-lambda-not-triggered/ ここはlocal.tfで設定する必要のない箇所ですので、「ふーんこんなのが必要なんだ」くらいの認識でOKです。 lambda_permission.tf resource "aws_lambda_permission" "start_allow_cloudwatch" { statement_id = "AllowExecutionFromCloudWatch" action = "lambda:InvokeFunction" function_name = aws_lambda_function.autostart_lambda.function_name principal = "events.amazonaws.com" source_arn = aws_cloudwatch_event_rule.autostart_rule.arn } resource "aws_lambda_permission" "stop_allow_cloudwatch" { statement_id = "AllowExecutionFromCloudWatch" action = "lambda:InvokeFunction" function_name = aws_lambda_function.autostop_lambda.function_name principal = "events.amazonaws.com" source_arn = aws_cloudwatch_event_rule.autostop_rule.arn } local.tf(全体) local.tf locals { region = "ap-northeast-1" iam_role = { name = "AutoStartStopRoleForLambda" assume_role_policy = <<EOT { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOT } iam_policy = { name = "AutoStartStopPolicy" policy = <<EOT { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": [ "ec2:Start*", "ec2:Stop*", "ec2:Describe*" ], "Resource": "*" } ] } EOT } autostart_lambda_function = { filename = "autostart.py" function_name = "StartEC2Instances" runtime = "python3.9" timeout = 10 handler = "autostart.lambda_handler" variables = { REGION = local.region # If INSTANCES is not set, then all instances will be targeted. #INSTANCES = "[i-XXXXXXXXXXX,i-XXXXXXXXXXX]" } } autostop_lambda_function = { filename = "autostop.py" function_name = "StopEC2Instances" runtime = "python3.9" timeout = 10 handler = "autostop.lambda_handler" variables = { REGION = local.region # If INSTANCES is not set, then all instances will be targeted. #INSTANCES = "[i-XXXXXXXXXXX,i-XXXXXXXXXXX]" } } autostart_lambda_file = { archive_file_type = "zip" lambda_source_dir = "./src/autostart" deploy_upload_filename = "./src/autostart_lambda_src.zip" } autostop_lambda_file = { archive_file_type = "zip" lambda_source_dir = "./src/autostop" deploy_upload_filename = "./src/autostop_lambda_src.zip" } autostart_event_rule = { name = "StartEC2Instances" description = "Start EC2 Instances" # Run at 0:00 (UTC) every Monday through Friday schedule_expression = "cron(0 0 ? * MON-FRI *)" is_enabled = true } autostop_event_rule = { name = "StopEC2Instances" description = "Stop EC2 Instances" # Run at 12:00 (UTC) every Monday through Friday schedule_expression = "cron(0 12 ? * MON-FRI *)" is_enabled = true } } おわりに 当初実現したいことはこのコードで概ね実現できました。 Tagで判別して云々すればもっと柔軟な設定を実現できますが、あくまで検証用ですので、これくらいでいいかなと思います。
- 投稿日:2022-02-01T22:31:15+09:00
【備忘】プライベートサブネット内のEC2にPostgreSQLをインストールする。
はじめに 最近AWSについて勉強中で、EC2環境にDjangoアプリをデプロイしようと思っているので、備忘で記載します。 今回はPostgresインストール。 PostgreSQLのインストール 1. 環境について ・プライベートサブネット内のEC2インスタンス ・AmazonLinux2 ・PostgreSQL13(今回入れるやつ) すごい端折ってるけど、大体こんな感じ。なんでS3書いたんだろう笑 2. PostgreSQL のインストール PostgreSQLの公式っぽい団体のサイトを参考に いつも通りyumでインストール。 あ〜楽勝。と思いつつ、まずは目的のパッケージを調べる。 $ yum search postgresql 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd Could not retrieve mirrorlist https://amazonlinux-2-repos-us-east-2.s3.dualstack.us-east-2.amazonaws.com/2/core/latest/x86_64/mirror.list error was 12: Timeout on https://amazonlinux-2-repos-us-east-2.s3.dualstack.us-east-2.amazonaws.com/2/core/latest/x86_64/mirror.list: (28, 'Failed to connect to amazonlinux-2-repos-us-east-2.s3.dualstack.us-east-2.amazonaws.com port 443 after 2701 ms: Connection timed out') One of the configured repositories failed (不明), and yum doesn't have enough cached data to continue. At this point the only safe thing yum can do is fail. There are a few ways to work "fix" this: 1. Contact the upstream for the repository and get them to fix the problem. 2. Reconfigure the baseurl/etc. for the repository, to point to a working upstream. This is most often useful if you are using a newer distribution release than is supported by the repository (and the packages for the previous distribution release still work). 3. Run the command with the repository temporarily disabled yum --disablerepo=<repoid> ... 4. Disable the repository permanently, so yum won't use it by default. Yum will then just ignore the repository until you permanently enable it again or use --enablerepo for temporary usage: yum-config-manager --disable <repoid> or subscription-manager repos --disable=<repoid> 5. Configure the failing repository to be skipped, if it is unavailable. Note that yum will try to contact the repo. when it runs most commands, so will have to try and fail each time (and thus. yum will be be much slower). If it is a very temporary problem though, this is often a nice compromise: yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true Cannot find a valid baseurl for repo: amzn2-core/2/x86_64 エラー起きとるやないかい! てか、プライベートサブネットだから外に出れないのか。 パブリックサブネット内のサーバーをプロキシサーバにして、プロキシ経由でyumすれば行けそうだなあ。 そう思いつつ、ググってみるともっと良い方法があった。 ・プライベートサブネット内でyum 下記のAWSの記事の通り、AmazonLinuxのyumリポジトリはS3にあって、VPCエンドポイントの設定でプライベートサブネット内から直接通信できるらしい。 上の記事に沿って、設定完了後、yumコマンドでうまくいきました。 ・デフォルトのPostgreSQLのバージョンが9.x? やっとインストールできる!そう思いつつインストールするPostgreSQLのバージョンを確認すると、 9.2.24だった。 $ yum info postgresql-server 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd 利用可能なパッケージ 名前 : postgresql-server アーキテクチャー : x86_64 バージョン : 9.2.24 リリース : 6.amzn2 容量 : 3.8 M リポジトリー : amzn2-core/2/x86_64 要約 : The programs needed to create and run a PostgreSQL server URL : http://www.postgresql.org/ ライセンス : PostgreSQL 説明 : PostgreSQL is an advanced Object-Relational database : management system (DBMS). The postgresql-server package : contains the programs needed to create and run a : PostgreSQL server, which will in turn allow you to create : and maintain PostgreSQL databases. ん〜PostgreSQL13がいいな!なんとなく! 調べると、amazon-linux-extrasに13があった。 $ sudo amazon-linux-extras ~省略~ 41 postgresql11 available [ =11 =stable ] ~省略~ 58 postgresql12 available [ =stable ] 59 postgresql13 available [ =stable ] なので、こんな感じで準備して $ sudo amazon-linux-extras install postgresql13 $ yum info postgresql-server 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd 利用可能なパッケージ 名前 : postgresql-server アーキテクチャー : x86_64 バージョン : 13.3 リリース : 2.amzn2.0.1 容量 : 5.4 M リポジトリー : amzn2extra-postgresql13/2/x86_64 要約 : The programs needed to create and run a PostgreSQL server URL : http://www.postgresql.org/ ライセンス : PostgreSQL 説明 : PostgreSQL is an advanced Object-Relational database : management system (DBMS). The postgresql-server package : contains the programs needed to create and run a : PostgreSQL server, which will in turn allow you to create : and maintain PostgreSQL databases. 満を持して、postgreSQLインストール。 $ sudo yum install postgresql-server 完了? 結構手こずった。
- 投稿日:2022-02-01T20:33:20+09:00
AWSパラメータストアのSecureStringを取得して、起動テンプレートのユーザデータに入れる方法
AWSパラメータストアのSecureStringを取得するには下記のコマンドを実施する。パラメータの意味は次の通り。--name "MyParameterName"でパラメータ名を指定。--query 'Parameter.Value'でパラメータの値を指定。--with-decryptionで暗号化された文字列を復号。 $ aws ssm get-parameter --name "MyParameterName" --query 'Parameter.Value' --with-decryption --output text EC2起動テンプレートのユーザデータにパラメータストアの値を入れるには下記のようにすればいい。これで${PARAMETER}に値がセットされる。 $ set $(aws ssm get-parameter --name "MyParameterName" --query 'Parameter.Value' --with-decryption --output text) $ PARAMETER=${1} $ echo ${PARAMETER} <パラメータの値が表示される>
- 投稿日:2022-02-01T20:21:31+09:00
40 代おっさん EC2にmariadbをダウンロードをしてlaravelで使用してみる
本記事について 本記事は AWS 初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。 もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。 構築環境 ・EC2:Amazon Linux2 ・PHP7.3 ・Laravel 5.8 ・mariadb mariadb以外の構築環境は https://qiita.com/kou1121/items/638c7052f44b8d1b1766 参照してください mariadb mariadbのダウンロード sudo yum install -y mariadb-server mariadbの起動 sudo systemctl start mariadb mariadbのパスワードを設定 sudo mysql_secure_installation Enter current password for root (enter for none): このように聞いてくるがEnterでおk! ついぎに Set root password? と聞いてくるので y を 自分のパスワードを入れてください。 再度パスワード入れてと来るので再度入れる。 次は色々聞かれますがすべて y で対応!! Thanks for using MariaDB! とでたら大丈夫です。 mariadbの自動起動を有効化 sudo systemctl enable mariadb Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service. と出ました。 起動してるか確かめる sudo systemctl is-enabled mariadb enabled となっていれば大丈夫です。 laravelの.eneでデータベースの設定をする。 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=自分のUSERNAME DB_PASSWORD=自分のPASSWORD mariadbに入ってデータベースを作る。 mysql -u root -p Enter password: と聞かれますので自分のパスワードを mariadbに入りましたら create database laravel; 出来たか確認 show databases; +--------------------+ | Database | +--------------------+ | information_schema | | laravel | | mysql | | performance_schema | +--------------------+ laravelのデータベースが出来ています。 exit 出てください。 phpMyAdminをブラウザ上で見れるように設定する。 laravel の public に必要なファイルを入れる publicに移動 cd public 移動したら wget https://files.phpmyadmin.net/phpMyAdmin/4.8.3/phpMyAdmin-4.8.3-all-languages.zip ファイルをダウンロードしたら解凍 unzip phpMyAdmin-4.8.3-all-languages.zip ファルダ名が長いのでphpMyAdminにする。 出来ましたら phpMyAdmin/index.php をURLの後ろにつけるとphpMyAdminの画面が出てくる。 できました~~ 久しぶりに頑張って見ました。 ゆっくりながらも勉強頑張ります。 参考資料
- 投稿日:2022-02-01T20:02:30+09:00
AWSとオンプレミスの技術要素の比較(超簡易版)
はじめに 私は、AWSクラウドプラクティショナーの資格を取るために1月から勉強を始めた者です。 AWSのサービスとオンプレミスのサービスについて、その違いを簡単にまとめていきます。 参考 AWSエンジニア入門講座――学習ロードマップで体系的に学ぶ Amazon EC2 EC2はAWSサーバーを提供するサービスです。 オンプレミスの場合、物理サーバーを準備し、物理サーバーの環境構築を行い、それを自社で運用・管理していきます。 独自カスタマイズできたりはできるものの、手間暇がかかります。 EC2ならば、クラウド上に仮想サーバーを立ち上げることができるため、準備や環境構築の手間がかかりさほどかかりません。 性能面の拡張や縮小、必要に応じたスケールアウトやスケールインも行ってくれるので、運用や保守といった手間からも解放されます。 Amazon S3 S3は、データを保存するためのストレージを提供するサービスです。 「オブジェクトのファイル単位」で出し入れが可能なので、その場に応じて自由な使い道が想定され、より柔軟なデータ保存が実行できるのが特徴となっています。 オンプレミスでは、自社でネットワーク接続ストレージを調達して設定し、ファイルのアップロード元とネットワーク接続するといったことを行います。 S3ならば、すでにストレージが用意されているので、いくつかの設定さえ行えばすぐに使い始めることができます。 容量無制限かつイレブンナインの耐久性を誇り、さらにはユーザーファーストな価格で提供されている素晴らしいサービス内容となっています。 Amazon VPC VPCは、AWS上で仮想ネットワークを提供するサービスです。 AWSアカウント内に専用のネットワークを作成でき、このネットワーク内に「EC2」(Amazon EC2)などのAWSリソースを配置できます。 いくつかの操作を行えば数分でネットワークを構築できます。ルータ機能、DNS、NTPなどネットワークで必要な基本機能はAWS側で提供されます。 オンプレミスの場合だと、ルーターやスイッチなど、ネットワークを構成する機器の準備や設定を全て行うことになります(それらを一括して制御するSDN(Software Defined Network)を使う)。 データセンター、ハードウェア、回線など用意すべきものが多く、準備期間と初期コストがかかることとなります。 Amazon Route53 Route53は、AWS上でDNS(Domain Name System)を提供するサービスです。 オンプレミスでは、BIND(Berkeley Internet Name Domain)などのDNSソフトウェアをインストールしたサーバーに相当します。 Route53には、DNSサービスはもちろん、ヘルスチェック、フェイルオーバールーティング、DDNSの機能を利用できるほか、ドメインの購入まで可能となっています。 Amazon CloudFront CloudFrontは、AWS上でコンテンツ配信の効率化を提供するCDN(content Delivery Network)サービスです。 オンプレミスでは、自力で世界中にキャッシュサーバーを用意することは難しいため、その場合、AkamaiやCloudFlareなどを利用することとなります。 ELB ELB(Elastic Load Balancing)は、AWS上で負荷分散を提供するサービスです。 オンプレミスでは、ロードバランサーと呼ばれる負荷分散装置を導入します。 ELBでは、用途に応じで、ALB(Application Load Balancer)、NLB(Network Load Balancer)を使い分けることができます。 IAM IAMは、AWS上のリソースに対するアクセス権限の管理を提供するサービスです。 オンプレミスの場合、LinuxではLDAP(エルダップ / Lightweight Directory Access Protocol)、WindowsではAD(アクティブディレクトリ / Active Directory)などのドメイン管理サービスを利用してアカウントや機器を管理します。 IAMでは、LDAPやADのように高度な管理権限を設定することが可能です。 Amazon CloudWatch CloudWatchは、AWS上のリソースやアプリケーションを監視できるモニタリングサービスです。 オンプレミスでは、監視ソフトウェアを利用して実現できます。 ZabbixやNagiosといった代表的なオープンソースがあります。 CloudWatchでは、他のサービスと連携させることが容易なため、柔軟で広範囲にわたりモニタリングを行うことができます。 AWS lambda Lambdaは、AWS上にサーバーレスのプログラム実行環境を提供するサービスです。 オンプレミスでは、プライベーとクラウドなどの自社システムを利用してプログラムの実行環境を用意できますが、必ずOSやコンテナの管理・保守が必要となります。 Lambdaはサーバレスな環境で利用できるサービスなので、管理や保守といった点ではメリットがあると言えます。 Amazon RDS RDSは、 AWS上にデータベースを提供するサービスです。 オンプレミスでは、サーバー上にデータベースソフトウェアをインストールすることになります。 インストールした後は、データベースの可用性を向上させるために複雑な設計や構築をしなければいけません。 RDSでは、マルチAZへのプロビジョニングによって可用性が担保されています。 また、MySQLやPostgreSQLなどのメジャーなデータベースとの互換性もあるところが特徴です。 参考 AWSエンジニア入門講座――学習ロードマップで体系的に学ぶ
- 投稿日:2022-02-01T18:58:07+09:00
AWS SAA合格体験記
【2022年1月】AWS SAA合格体験記 先日、AWS SAAを取得しましたので、合格までの学習方法について記載します。 これから学習する方にとって、少しでもお役に立てれば幸いです。 ※2021年8月にAWS CLF 合格済 学習教材&学習時間 ・AWS認定資格試験テキスト(12時間) ・Web問題集(28時間) ・社内勉強会(3時間) 勉強方法 1. AWS認定資格試験テキストを一周する(7時間) 2. 復習しながらNotionに纏める(5時間) ※試験後も定期的に確認できるように纏めました↓ 中身↓ 3.AWS Web問題集(28時間) 80~150を3周解きました。 こちらのサイトでは、本番と似た形式の問題や同難易度の問題を解くことができます。 問題数がとても多いので、初回で正答率80%を超えた回は2回目を解かない、などルールを決めてどんどん先に進みました。 4.社内勉強会(3時間) 社内研修でAWSのSAA対策を受講しました。 VPC、セキュリティ周辺の知識をハンズオン形式で学びました。 試験結果 試験本番は初めて見る問題や語句もありましたが、可能な限り選択肢を二択に絞りました。 それでも結構ギリギリでしたが、なんとか合格することができました!
- 投稿日:2022-02-01T17:56:56+09:00
[2022年] AWS ソリューションアーキテクト - アソシエイトに本2冊で合格した話
はじめに 10年以上セキュリティエンジニアとして働いていましたが、訳あって最近インフラのリーダーになりました。会社では主にAWSを利用しているため、勉強がてらAWSの資格を取得したという話です。 ちなみにセキュリティエンジニアの時はAWSを使うことはなくGCPで色々なことをやっていました。AWSを使わなかった理由は、数年前にAmazonアソシエイトを意味不明な理由で垢バンされたからです。。 前提知識 クラウドプラクティショナーの資格を取得したくらいで、AWSはほぼ触ったことがないです。 勉強方法 以下2冊の本を読み込みました。どちらも1年以上前の本ですが特に問題なかったです。 Amazonアソシエイトを垢バンされているためアフィリエイトリンクにはなっておりません。安心してクリックしてください。 以下の本は項目ごとに必要な情報がまとまっていたので暗記するのに使いやすかったです。 3日くらいかけて内容を暗記しました。 上の本1冊だけでは不安だったので以下の本も買いました。 上の本に記載していない内容が多々ありましたので買ってよかったです。 こちらも3日くらいかけて内容を暗記しました。 受験 ピアソンVUEで自宅から受験しました。 楽勝だと思って受験しましたが、見たことない単語がでてきたりいまいち内容が理解できない問題が出てきたりしてもしかして落ちたかも・・と思いながら解いていました。 結果は無事合格できたのですが、運が良かった気もします。 感想 AWS全体を広く浅く把握するためにはちょうどよい勉強ができたと思います。
- 投稿日:2022-02-01T16:52:02+09:00
Amazon Virtual Private Cloud (VPC) が、意図しないネットワークアクセスを簡単に特定できる Network Access Analyzer を発表
はじめに Amazon VPC Network Access Analyzerは、AWS上のリソースへの意図しないネットワークアクセスの特定に有効な新しい特徴があります。Network Access Analyzer を使用すると、 Virtual Private Cloud (VPC) リソースのネットワークアクセスが、セキュリティやコンプライアンスのガイドラインを満たしているかどうかを検証することができます。Network Access Analyzer を使用すると、クラウドのセキュリティ体制を評価し、改善点を特定することができます。さらに、Network Access Analyzer を使用することで、ネットワークが特定の規制要件を満たしていることを簡単に実証することができます。 AWS の責任共有モデルの一環として、ユーザーは、AWS 上のネットワークが、意図しないネットワークアクセスをブロックするための適切なコントロールで構築されていることを確認する必要があります。例えば、「データベースはインターネットからアクセスしてはならない」、「アプリケーションサーバは信頼できるオンプレミスのIPレンジにのみポート443でTCPトラフィックを送信できる」、「本番用VPCは開発用VPCからアクセスしてはならない 」などです。 Network Access Analyzerでは、そのような要件をシンプルかつ正確な仕様でキャプチャすることを許可しています。自動推論により、Network Access Analyzer は、定義した要件を満たしていない AWS 環境のネットワークパスを特定します。IPアドレス範囲、ポート範囲、トラフィックプロトコル、AWSリソースID、AWSリソースグループ、およびインターネットゲートウェイや NAT ゲートウェイなどのリソースタイプの条件から、ネットワークアクセス要件の送信元と宛先を特定できます。このようにして、ネットワークの構成方法に関係なく、AWS 環境全体のネットワークアクセスを簡単に管理することができます。 開始するには、AWS マネジメントコンソールにアクセスし、Network Access Analyzer で Amazon が作成したネットワークアクセススコープの1つを使用してネットワークを評価します。AWS CLI、AWS SDK、または AWS マネジメントコンソールを使用して、独自の Network Access Scopes を定義し、ネットワークを分析することもできます。 Amazon VPC Network Access Analyzer は、通常、米国東部 (バージニア北部)、米国東部 (オハイオ)、米国西部 (北カリフォルニア)、米国西部 (オレゴン)、アフリカ (ケープタウン)、アジアパシフィック (香港)、アジアパシフィック (ムンバイ)、アジアパシフィック (ソウル)、アジアパシフィック (シンガポール)、アジアパシフィック (シドニー)、アジアパシフィック (東京)、カナダ (中部)、欧州 (フランクフルト)、欧州 (アイルランド)、欧州 (ロンドン)、欧州 (ミラノ)、欧州 (パリ)、欧州 (ストックホルム)、南米 (サンパウロ)、および 中東 (バーレーン) の各 AWS リージョンでご利用いただけます。 詳細はこちら、Network Access Analyzer の Amazon VPC ドキュメント とブログ記事をご覧ください。Network Access Analyzer の料金を表示するには、Amazon VPC 料金をご覧ください。 の記事確認です。 要するに Network Access Analyzer を使用することで、意図しないネットワーク経路を抽出できるそうです。 例) - 「データベースはインターネットからアクセスしてはならない」 - 「アプリケーションサーバは信頼できるオンプレミスのIPレンジにのみポート443でTCPトラフィックを送信できる」 - 「本番用VPCは開発用VPCからアクセスしてはならない 」など 料金は 評価1回 ENI 1つあたり 0.002 USD とのことです。 やってみる VPCのところにあります。 開始すると...... AWS が事前に用意してくれた経路抽出設定が4つ確認できます。 インターネットゲートウェイ、ピアリング接続、VPCサービスエンドポイント、VPN、トランジットゲートウェイからVPCへの入力パスを特定 インターネットゲートウェイからすべてのネットワークインターフェイスへの入力パスを特定 すべてのVPCからインターネットゲートウェイ、ピアリング接続、VPCエンドポイント、VPN、トランジットゲートウェイへの出力パスを特定 すべてのネットワークインターフェイスからインターネットゲートウェイへの出力パスを特定 インターネットゲートウェイからすべてのネットワークインターフェイスへの入力パスを特定 をやってみましょう。 分析を押すと...... 分析が開始し... リージョン内に存在するインターネットゲートウェイからネットワークインターフェイスへの経路がリストされます 結果の経路を選択すると... 経由されているリソース含めて確認できます。 自分で経路抽出設定1を作成することもできます。 作成を押して...... 空のテンプレートを選択して...... 抽出条件と除外条件を設定します。 仮に、インターネットゲートウェイからでEC2インスタンスまで80ポート以外の経路を条件として抽出してみましょう。 確認して、作成します。 分析すると......リストされました。 経路確認します。セキュリティグループのIDからリンク飛ぶと...... 確かに80ポート以外が抽出されていそうです 意図しない経路を抽出することが出来ました。 まとめ Network Access Analyzer は意図しない経路抽出に役立ちそう。 (ただし、最初に違反していると考えられるパスを洗い出すのが結構手間かも。) 参考 Network Access Scopeと呼びます ↩
- 投稿日:2022-02-01T16:17:09+09:00
[AWS] EventBus で別アカウントにイベントを送信する/受信する
メモ代わりの殴り書きです。 あとで書き直すかもしれないし、書き直さないかもしれない。 EventBus の概要 EventBus は、他のアカウントやリージョンにイベントを連動できる機能。 以前は CloudWatch Events の一部であったが、今は EventBridge というサービスに統合されている。 CloudWatch Events の EventBus が無くなったわけでは無い。 リソース実物は同じなのにインタフェースが違うという、少しややこしい状況。 EventBridge のほうができることが多い。 この記事では EventBridge のほうから使う前提で。 設定 必要なリソース [受信側] EventBus EventBus Policy [送信側] EventRule Target IAM Role 各リソースの動作・設定の要約 これは最低限。受信側にTargetがないので、イベントを受け取るだけで何もしない。 動作確認したいなら SNS Topic や Lambda に繋げるよろし。 EventBus でイベントを受け取る。 受信側のイベントバスには、送信側からの events:PutEvents を受け入れるリソースポリシーが必要。 送信側は、受信側イベントバスを宛先としたターゲットを設定する。 そのターゲット設定には、 Action: "events:PutEvents" と Resource: "受信側EventBusのARN" の権限を持つ Role が必要。 補足 送信側の EventTarget を作成するとき、送信先(受信側)の EventBus が存在していなくても登録できる。 送信側は AWS CLI/SDK で put_evnets が実行できそう。 なので、厳密にいえば送信側にはリソースは何もいらないのかもしれない。権限さえれば。 検証はしていないので間違ってるかも。 設定詳細(大事なところだけ抜粋) 受信側イベントバスのポリシー { "Version" : "2012-10-17", "Statement" : [{ "Sid" : "allow_account_to_put_events", "Effect" : "Allow", "Principal" : { "AWS" : "arn:aws:iam::<送信元アカウントID>:root" }, "Action" : "events:PutEvents", "Resource" : "<受信側EventBusのARN>" }] } 送信側イベントルールのイベントパターン例 飛ばしたいイベントのパターンを書く。 送信側のイベント検知の設定であるので、特別なことは何もない。通常のイベントパターン通り。 下記イベントパターンは、指定されたS3オブジェクトがPutされたときに発火する。 ※CloudTrailのデータイベント設定で当該S3を監視する設定が必要。 { "detail": { "eventName": ["PutObject", "CompleteMultipartUpload", "CopyObject"], "eventSource": ["s3.amazonaws.com"], "requestParameters": { "bucketName": ["<S3-BucketName>"], "key": ["<S3-Key>"] } }, "detail-type": ["AWS API Call via CloudTrail"], "source": ["aws.s3"] } 送信側ターゲット用ロールのポリシー { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": "events:PutEvents", "Resource": "<受信側EventBusのARN>" } ] } 受信側イベントルールのイベントパターン例 上記のリソースでは受信側にルール・ターゲットを設定していないが、設定するとしたらこうなる。 イベントバスで受け取ったイベントであるが、こちらも特別な書き方は不要。 通常のイベントパターンと同様の記述内容になる。 ただし、アカウントは制限しておいたほうがよい。(後述) { "detail": { "eventName": ["PutObject", "CompleteMultipartUpload", "CopyObject"], "eventSource": ["s3.amazonaws.com"], "requestParameters": { "bucketName": ["<S3-BucketName>"], "key": ["<S3-Key>"] } }, "detail-type": ["AWS API Call via CloudTrail"], "source": ["aws.s3"], + "account" : ["<送信元アカウントID>"] } 必須ではないが考慮しておくべきこと。 受信側のトリガー(イベントパターン)は、アカウントやサービス・アクションを絞っておくべき。特にアカウント。 全く想定していないアカウントのイベントを送り付けられると非常に困る。 送信側も適切に絞っておかないと、CloudTrail荒らしになる。 補足事項:イベント情報の構成 マネコンからイベントルールを書くと、いくつか選択肢があって選んでいくとある程度は自動的にイベントパターンを設定してくれるが、細かい条件を追加しようと思うとどう書いたらよいのかが分からない。分かりづらい。 なので、イベント情報の構成を知っておきたい。 Events がキャッチするイベントは下記jsonの構成になっている。例外はあるかもしれないが未確認。 CloudTrail のイベント情報をラッピングする形。 イベントパターンを書くときは、この構成に合わせて各要素のマッチ条件を書いていく。 { "version": "0", "id": "********-****-****-****-*************", "detail-type": "AWS API Call via CloudTrail", "source": "aws.s3", "account": "***********", "time": "2022-02-01T04:31:54Z", "region": "ap-northeast-1", "resources": [], "detail": { "eventVersion": "1.08", "userIdentity": { ... ... }, ... <CloudTrailのイベントレコードと同一> } }
- 投稿日:2022-02-01T13:30:11+09:00
AWS SAA(SAA-C02)受験レポート
はじめに AWS SAAを取得したので私と同じような環境・経歴の方の参考になればと思い投稿します。 資格取得を思い立った時の自分の状態 とあるプロダクト専任チームに異動するもなかなかアサインされず、このままだと評価に響くなと悩んでいた 上記プロダクトは専門性も今のところの需要も高いものの、この先ずっとこれ1本で食べていける想像は出来なかった 尖ったスキルに加えて、汎用性の高いスキルを身に着けたい インセンティブで数万円貰えるし、価値も高められるので今後のキャリアも見据えSAA取得を決意 経歴 エンジニア歴約8年のNW嫌いなサーバ寄りインフラエンジニア。ほんのちょびっとコンサルティングも経験。 資格は研修時代に取得したLPIC1(現Linuc1)のみ AWS含むクラウドの実務経験なし。検証環境でEC2,VPCを触った程度 ターゲット なるべくお金をかけない(受験料も会社負担なのでUdemy1,500円のみ) 1~2か月程度での合格を目標 勉強は1日3時間程度。週末や年末年始はお休み。 試験対策 AWS:ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得 兎にも角にもサービス名と概要を覚えなければいけない。なのでまずは動画での解説を眺める。この動画はハンズオンの時間帯もあるので初心者にはありがたい。 メリット:NWやDNS、Load Balanceなどクラウド関係なくインフラの知識も身に着けられる デメリット:特になし。強いて言えば、講師の話し方が独特 CloudTech 無料で最大200問の問題を受けられるのでまずはこれをひたすら解く。講師からのアドバイスとして、1~10問目を2週してから11~20問目を解く。なぜなら人は何かを思い出すときに記憶が定着するからだと。 メリット:10問単位で結果が分かり解説も丁寧なので、なぜ間違ったのかがすぐわかる デメリット:出題が優しすぎて本番試験に則していない。そのため無料範囲のCloudTechのみで受験するのはやめておいたほうが良い。余談だが、Snowballは現在は非推奨なので選択肢をSnowball Edgeに修正してほしい 【2022年版】これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座 これは購入必須だと思う。Udemyは頻繁にセールをやっており1,500円程度で買えることも。65問×6種類の模擬問題があり、出題内容も本番試験に近い内容となっている。 メリット:本番試験相当の問題に触れることができる。出題のされ方に慣れるという意味でも非常によい デメリット:65問解き終わらないと回答が見れない 以下の注意書きがあるが、本試験を受けた人間から言わせてもらうと、この模擬問題をスラスラと回答できないと合格は厳しいだろう。 試験レベルで難易度の高めの問題などを中心に構成しており、今一歩合格が出来ていない方向けの最終仕上げとしての問題集です。 本模擬試験は多様で難易度が高い問題になれてもらうことで、合格する可能性を高めることを目的としています。したがって、正答率が70%未満であっても、本試験に合格することができる方も多いです。 AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(SAA-C02試験対応版) SAA-C02に特化して解説している動画。上3つの合間に見直すことで理解を深められることだろう。最初は理解できなくとも問題を解いていく中で、動画で言っていた意味が理解できた瞬間が何度もあったのでこれもおススメ。 「ゼロから~」でまずはサービスや挙動を確認し、「CloudTech」で記憶を定着させ、「【2022年版】これだけでOK!~」で出題傾向に慣れ、「AWS 認定ソリューションアーキテクト~」を適宜見直す。これで私はSAAを合格できた。あとは自分なりの資料をエクセルにまとめてみるとよいと思う。余力がある方は、実際にサービスを動かしてみるとより理解が深まると思うが、私の場合は合格することに重きを置いていたのでひたすら問題を解いていった。 スケジュール 2021/11/29 勉強開始 まずはUdemyで動画を購入しCloudTechに会員登録する。なお、AWSはアップデートが頻繁に行われるため書籍は購入していない。 2021/12/27 オンライン試験(トラブル発生) オンライン試験の登録方法は他の方が紹介しているので割愛する。 (8年前に買ったMacでは)スペックが足らずファンが唸りを上げマウスが動かなくなりチャットでの問い合わせも出来なくなる。監督員から非通知での電話にてカメラから試験の様子を確認できないのでPC再起動するよう指示される。 再起動するもまたすぐにPCが固まってしまう。今度はPCにインストールしたアプリ越しで監督員から試験の様子を確認できないので、今回の試験は中断することに。バウチャーを発行するので再度受験してほしいと言われる。 5問ほどしか進めなかったが問題が難しすぎて合格できる気がしなかった。なので無料で再受験できたのは不幸中の幸いだった。 2022/1/5 勉強再開 「【2022年版】これだけでOK!~」をひたすら解いていく。最終的にどの模擬試験も10周ほど受け、おおむね90%まで行った。 2022/1/29 再受験 今回はテストセンターにて受験。130分の中で80分ほどかけて解き、見直しで40分ほど費やしたので結構疲れた。絶対受かりたかったからね!試験提出後アンケートも答えたらその場で合否が表示される。まったく心の準備していなかったがめでたく合格の文字が!ちなみに730点だったのでギリギリ。 出題問題における前提条件で最適なサービス・組み合わせ・区別の把握に苦労した データベース(RDS, ElastiCache, Aurora, DynamoDB) ストレージ(S3, EBS, EFS, Glacier)。特にS3はデータの保持期間と取り出し速度に応じて5段階に分かれる 頭文字で出題されてもわからないので正式名称を覚えてサービス概要と紐づけておく(SMS, ADS, DMS, KMS, SWF…) SESとSNSのEメール利用の使い分け CloudFormationとElasticBeanstalkは被ってる機能が多い。因みにOpsWorksだけはChef/Puppetが条件なので覚えられた 位置情報ルーティングポリシーと地理的近接性ポリシーの使い分け これからSAAを受験する方へ ※理解するよりも合格することを目的とする人向け 同じ問題をひたすら解け。答えを覚えてしまうほどに繰り返し解け。 最後に Twitter, Qiita等で「○日間の勉強で合格」や「〜に合格して○冠達成」みたいな投稿がありますが、そんなの無視してください。何の参考にもなりません。なぜなら資格取得は他人と競うものではないからです。自分のペースで進めていきましょう。
- 投稿日:2022-02-01T13:26:48+09:00
細かいつまずいたことをメモしておく(1月編)
はじめに 先月は特にメモするような話題がなかったので2か月ぶりのメモ記事です。 案外自分でみることが多く、役立っているこのシリーズですが、他の人に見られることはほぼないと思ってはいます(調べればわかることをメモしてるだけです) 今月から案件のサポートとして参加することになりすこしずつわからないこともでてくるようになりました。 問題 1. VPN接続している際に(在宅)WSL2でgit cloneができない 以下の記事の通りに対処することで解決 https://zenn.dev/mallowlabs/articles/ssh-on-wsl2-with-vpn 前も同じようなところで詰まっていました。.bashrcなどに書いて毎度実行するほうが良いかもしれないです。 2. SageMakerのドメインが削除できない ユーザープロファイルを削除したのにドメイン削除ボタンが押せない。 コンテナイメージをアタッチしたエラーがずっと表示されておりそれが原因かもしれない。 以下のコマンドでCLIから削除したところ削除できた $ aws sagemaker delete-domain --domain-id [ドメインID] --region [リージョン(ap-northeast-1など)] 3. Access denied for user 'root'がでてしまう MySQLで接続できないエラーが発生 まさかのwebpackerコンテナからrails db:createしていた。 また、database.ymlのusernameをrootにしていなかったのもあった 4. Railsで複数選択可能なチェックボックスの作成 以下の記事を参考に作成した 【Rails入門説明書】checkboxについて解説 Railsで複数check_boxを配列で送って、カラムに登録、viewで表示して、checkedもつける方法 checkboxでmultipleをつけると配列で値を受け取れるが、params.requireで値を取るとnilになってしまうところで苦戦した。 結果以下の箇所を修正することでできるようにした。 test.html.erb <div class='d-inline text-nowrap ml-1'> <label class='fw-normal'> <%= f.check_box :color, {multiple: true}, '青色', nil %> 青色 </label> </div> <div class='d-inline text-nowrap ml-1'> <label class='fw-normal'> <%= f.check_box :color, {multiple: true}, '黄色', nil %> 黄色 </label> </div> test.controller def notebook_params notebook_params = params.require(:notebook).require(:size, :width) notebook_params[:color] = params.require(:notebook).permit({:color => []})[:color] notebook.rb(model) serialize :color, Array before_save do self.color.split(',').map{ |m| m.delete('[]"\\')} if attribute_present?("color") end これで配列にして保存ができる。パラメータの取り方が特殊になるらしい 5. ./bin/webpack-dev-server: Permission deniedが時々起きる (chmod・chownが効かない) なぜかファイルが権限で読み込めなくなる現象が時々おきる。一回治ると以降起きないが、Gitからダウンロードしたときにコンテナをあげると起きたり、起きなかったり。 Dockerfileでchmod +x ./bin/webpacker-dev-serverをしても同じエラーがでてしまいchown, chmodが効いていない これはローカルにある./bin/webpacker-dev-serverで上書きされてしまうために起きていて、そのファイルはなぜか読み込める権限がなかった。 これはWSL2のフォルダをデスクトップにダウンロードしてからWSL2に再度戻したことにより権限が変わっていたことが原因でした。Gitに上げる前に権限を変更してあげないとCloneした人も同じ現象が起きてしまうので注意が必要 おわりに 本当は来月から1年出張しにくはずでしたが、コロナで完全リモートになりました。 来月も引き続きAWSとWeb技術頑張ります。 参考 WSL2 内の Ubuntu 20.04 で VPN をつないだときだけ ssh できない 【保存版】Docker上に構築したRails6でVue.jsを表示する方法(エラー対処法&Vuetifyの使い方) 【Rails入門説明書】checkboxについて解説 Railsで複数check_boxを配列で送って、カラムに登録、viewで表示して、checkedもつける方法
- 投稿日:2022-02-01T12:59:08+09:00
Amplify CLIでLambda関数を定期実行させる方法
Amplify CLIでLambda関数を定期実行させる方法 注意点 先に注意点を書いておきます。 amplify add functionの時点で、定期実行の設定をする必要があります。 「え、更新すればいけるやろ?」と思いますが、私はできませんでした。 また、調べてもamplify add functionの時点で設定している記事しか見つかりませんでした。 もし後からでも設定できる場合は、教えてください。 Amplify CLIでLambda関数を定期実行させる方法 amplifyの環境が設定済みという前提で書いています。 もしamplifyがわからない場合は、こちらを参考にしてください。 Amplify SNS Workshop 最初にamplify add functionを実行します。 そうすると、以下の基本的な設定の質問が出てきます。 基本的な設定 ? Provide a friendly name for your resource to be used as a label for this category in the project: lambdafunction ? Provide the AWS Lambda function name: lambdafunction(関数名) ? Choose the runtime that you want to use: NodeJs(好きなものを選んでください) ? Choose the function template that you want to use: Hellow World(好きなものを選んでください) 高度な設定(直訳) 基本的な設定の質問が終わると、以下の質問が出てきます。 ? Do you want to configure advanced settings? この質問をYesにすると、定期実行の設定、レイヤーの追加、アクセス権限の設定などができます。 上記の質問をYesにした後は、いくつか質問されます。 そのなかでも、定期実行の質問は、? Do you want to invoke this function on a recurring schedule?です。 必ずこの質問はYesにしてください。 そうすると、単位(時、分、秒)と、数値の設定をする質問が出てきます。 以下では、例として30分間隔で定期実行するように設定します。 ? At which interval should the function be invoked: Minutes ? Enter the rate in minutes: 30 上記の設定が終われば、設定を反映させるために、amplify pushをすれば終わりです。 もし追加情報や間違いがあれば、教えてください。
- 投稿日:2022-02-01T12:29:54+09:00
AWS Lambda Layer(レイヤー)を作成する方法
Lambda Layerとは 複数のLambda関数に、共通の外部ライブラリやビジネスロジックを追加できる仕組みです。 1つのLambda関数に、5つまでLayerを追加できます。 しかし、Layerのサイズには、制限があります。 Lambda Layerを作成する方法 nodejsディレクトリを作成する ディレクトリ名は必ずnodejsにする必要があります。 (それ以外の名前では、ダメだと思います。) 必要なライブラリをインストールする npm init npm install (必要なライブラリ) npm initとnpm install (必要なライブラリ)を行い、node_modulesディレクトリが作成され、中にインストールしたものが入っていれば大丈夫です。 zipにしてアップロードする 上記で作成したnodejsディレクトリをzip形式にして、アップロードします。 アップロードする場所は、AWSのコンソール→Lambda→レイヤー→レイヤーの作成の順に進むと、アップロードするところがあります。 既存のレイヤーのバージョンを更新する方法 新しいレイヤーを作成せずに、既存のレイヤーを更新する場合は、既存レイヤーのnodejsディレクトリをインストールできます。 AWSのコンソール→Lambda→レイヤー→(更新したいレイヤーを選ぶ)の順に進み、ダウンロードすると、既存レイヤーのnodejsディレクトリがダウンロードできます。 そのディレクトリのなかに、必要なライブラリをインストールしてください。 その後、AWSのコンソール→Lambda→レイヤー→(更新したいレイヤーを選ぶ)の順に進み、新しいバーションを作成すると、既存レイヤーを更新できます。 既存のレイヤーを更新した場合でも、新しいバージョンのレイヤーを付け直す必要があります。 何か間違いや追加情報があれば、訂正してください!
- 投稿日:2022-02-01T12:20:42+09:00
AWS学習まとめ(AWS Cloud Practitioner Essentials)
AWSの認定資格一覧 基礎コースの AWS Cloud Practitioner ワードの意味、役割、特徴をまとめた。 1.AWSサービスの紹介 AWSのサービス製品 人工知能 ロボット開発 ストレージ ネットワークセキュリティ 機械学習 ブロックチェーン 映像制作 軌道衛星 コンピューティング 現在全てのコンピューティングはクライアントサーバ型。 コンピューティングにおいてクライアントはwebブラウザやアプリのこと。 クライアントがリクエストし、サーバが応える。 AWSでは仮想サーバの一種であるAmazon Elastic Cloud Compute(EC2)を指す。 オンプレでは容量を3倍にするにはその後のコストが気になる。 AWSは容量の増減はボタンひとつ。従量課金制で使った分だけ払う。 ※アーキテクチャ:ソフトウェアの基本的な設計概念 ※トランザクション:一連のやりとり ※オンプレミス:自社内やデータセンターでユーザ自身で管理運用↔️クラウド:ネットワーク経由 クラウドコンピューティング クラウドコンピューティング:従量課金制によるインターネット経由でのITリソースのオンデマンド配信 使った分だけ払う ネット経由で 容量を 自由に使える ※オンデマンド:要求に応じて提供する形態 クラウドコンピューティングの3つのデプロイモデル クラウドベースのデプロイ 完全クラウドベースでアプリケーションを作れる。 アプリケーションの全てをクラウド上で実行する 既存のアプリケーションをクラウドに移行する 新しいアプリケーションをクラウド上で設計及び構築する オンプレミスデプロイ(プライベートクラウドデプロイ) オンプレのアプリに技術やツールを組み込む。 仮想化ツールとリソース管理ツールを使用して、リソースをデプロイする アプリケーション管理と仮想化技術を使用して、リソースの使用率を上げる ハイブリッドデプロイ レガシーアプリをオンプレ運用のままクラウド上のサービスを使う。 クラウドベースのリソースをオンプレミスのインフラストラクチャに接続する クラウドベースのリソースを従来の IT アプリケーション と統合する クラウドコンピューティングの利点 先行支出を変動支出に切り替える(初期費用負担がない) データセンターの維持管理費が不要(インフラ/サーバ管理に多大な費用/時間が必要だったがクラウドは管理タスク負担底で他に集中できる) キャパシティーの予測が不要(需要に合わせスケールイン/アウトできる) 圧倒的なスケールメリット(大多数のユーザーのリソース使用がクラウドに集約されるためAWSでは高いスケールメリットを享受できる、よって課金額を安く抑えることができる) スピードを俊敏性を向上(開発/デプロイが簡単になり、実験とイノベーションに費やせる) 数分でグローバルに展開(AWSはグローバル規模のサービスで、低レイテンシーで各国に提供し、最小限の遅延で利用できる) ※インフラストラクテャ:インフラ ※スケールメリット:規模のメリット ※イノベーション:革新。変革。新しい捉え方や切り口など幅広い意味あい。 ※レイテンシー:遅延 2.クラウドでのコンピューティング(EC2) オンプレのサーバ準備 ・ハードウェア購入の先行投資 ・サーバが届くのを待つ ・サーバを物理センターに設置する ・サイト公開の設定 上記に対し Amazon Elastic Compute Cloud (Amazon EC2) 通称EC2はEC2インスタンスとしてAWSクラウドで提供するサーバ。 EC2インスタンスは数分以内にプロビジョニング、作成できる。 ワークロードの実行が完了したら、使用停止できる。 インスタンスは起動時のみ料金が発生する(停止/終了は料金発生しない) ※プロビジョニング:設定。提供(ITではインフラをセットアップするプロセスを意味する) ※ワークロード:仕事量 Amazon EC2 インスタンスタイプ 一つの店舗でも様々専門職に特化した従業員がいるように、 インスタンスもタスクに合わせた物をチョイスできる。 インスタンスファミリーには以下のタイプがある。 汎用インスタンス 一般的なアプリ メモリ/ネットワークのリソースをバランスよく提供。 コンピューティング最適化 負荷の高いサーバーに最適。 メモリ最適化インスタンス 大規模DB、高パフォーマンスDBに最適。 高速コンピューティングインスタンス ハードウェアアクセラレーターやコアプロセッサーでデータ処理を高速化。 グラフィックやストリーミングアプリに最適。 ストレージ最適化インスタンス 大規模なデータに対する読み取りや書き込みする、高頻度のアンライントランザクション処理システム、分散ファイルシステム、データウェアハウジングアプリに最適。 ※ハードウェアアクセラレーター:データ処理を高速化するコンポーネント ※コンポーネント:部品、構成要素。 ※コアプロセッサー:CPUコア ※データウェアハウス:データ分析向けに設計されており、大量のデータを読み取り、データ全体で関係や傾向を把握できる。データサイエンティスト等が分析アプリを通してアクセスしたりする。 EC2の料金 料金プラン オンデマンド 初期費用なし。 使用時間秒単位で料金発生。 中断できない不規則・短期なワークに最適。 1年以上のワークには非推奨。 Savings Plans 1・3年契約で1時間単位で料金発生。 オンデマンドの最大72%オフ節約可能。 リザーブドインスタンス 使用量が予測可能・一定のワーク向け。 全額や一部前払いで1・3年契約でンデマンドの最大75%オフ節約可能 Savings Plansと違い使用量を決める必要がある。 スポットインスタンス オンデマンドの最大90%オフで利用できる。 中断できる、一時的に利用するワーク向け。 Dedicated Hosts 物理サーバー 他のユーザに利用されない。 最も高価 EC2のスケーリング オンプレミスでは利用平均値に合わせハードウェアを購入した場合、繁忙期に耐えられない。 逆に繁忙期に合わせたら、利用率が下がってコストが嵩む。 オンプレでこの問題を解決するのは難しいが、EC2なら対応ができる。 スケーラビリティ スケーラビリティによって需要に応じて自動的にスケールイン/アウトするアーキテクチャを設計できる。そのサービスがAmazon EC2 Auto Scaling ※アーキテクチャ:構造 Amazon EC2 Auto Scaling ウェブにアクセスしてタイムアウトが発生するのはインスタンスが足りていない可能性がある。 Amazon EC2 Auto Scalingを利用すると自動でEC2インスタンスを作成削除する。 その中で2種類のスケーリング方法が用意されている。 動的スケーリング(変化する需要に対応) 予測スケーリング(予測された数を用意) Auto Scaling グループを設定する際、インスタンスの最小数は1になり、 最大値を設定しておくことも可能。 レジ担当は最大5人、厨房は最大10人のようにグループごとに設定できる。 Elastic Load Balancing を使用してトラフィックを転送する Elastic Load Balancing(ELB)は、アプリへのトラフィックをEC2インスタンスなどに自動的に分散する。 ELBはリージョンごとに1つ設定できる。 ELBでインスタンスのスケーリングによるトラフィックの偏りを分散できる。 アクセス(トラフィック)→ELB(分散)→インスタンス(サーバ) ※ロードバランサー:負荷分散 ※リージョン:地域。日本なら東京リージョンしかなかったような気がする。 メッセージングとキューイング レジで受けた注文を紙ベースでバリスタに毎回渡していた場合、 バリスタが忙しいと注文が停止してしまう。 紙ベースではなく注文受付中のモニターを介すようなバッファを設けることで、 お互いの作業が停止しない。 このように保留を行うことをメッセージング/キューイングという。 アプリ→アプリ:この構成を密結合アーキテクチャ(カスケード障害が起きる) アプリ→中継(キュー)→アプリ:疎結合アーキテクチャ(後者アプリが死んでも前者は動ける) ※バッファ:余裕(ITでは空きメモリとか) ※カスケード障害:1つの部品の障害がシステム全体に影響を及ぼすこと モノリシックアプリケーションとマイクロサービス アプリケーションは複数のコンポーネントで構成されている。 DB・サーバ・UI・ビジネスロジックなどが蜜結合したものを モノリシックアプリケーションという。 逆にマイクロサービスにアプローチすることで疎結合し、互いの障害の影響を防げる。 AWSではAmazon Simple Notification Service (Amazon SNS) と Amazon Simple Queue Service (Amazon SQS) の 2 つのサービスによって、疎結合を用意に実現できる。 レジ注文→メッセージ→キュー→バリスタ(→メッセージで完了通知) ※マイクロサービス:開発技法の1つでアプリを小分けし独立させる。 Amazon Simple Notification Service (Amazon SNS) メッセージを発行するサービス。 メッセージに保存されたデータはペイロードと呼ばれ、配信されるまで保持する。 メッセージをユーザに送信することで注文受付/完了といった通知をすることもできる。 サブスクで異なるトピックのニュースを配信することにも使える。 Amazon SNSにおいてサブスクライバーは人ではなく、Webやメール、AWS Lambda関数となる。(システム観点での配信先のこと?) Amazon Simple Queue Service (Amazon SQS) AWSが提供するキューサービス。 SQSキューは処理されるまでメッセージを保存する場所 その他のコンピューティングサービス AWSは複数のサーバーレスコンピュティングを提供している。 サーバーレスとは基盤となるインフラを意識しないこと。 サーバーレスコンピューティング EC2の場合 ・インスタンス(仮想サーバ)をプロビジョニングする ・コードをアップする ・アプリ実行中、インスタンスを管理し続ける サーバーレスはプロビジョニング/管理が必要なくコードをアップするだけ。 もう1つの利点は自動的にスケールもされる。 EC2インスタンスを管理したくない場合はAWS Lambdaを使う。 AWS Lambda AWS LambdaとはAWSが提供すサーバーレスサービスの1つ。 使用時間に対してのみ課金される。 ラムダは15分以内で完了する処理である必要があるため、ディープラーニングには向かない。 コードUP→ラムダ関数(=UP内容)にトリガーするようコード設定→トリガー実行(15分以内) ラムダを使わないサーバーレス サーバーレスの導入で移植や効率性が気になる場合は、ECSとEKSが使える。 プロジェクトをコンテナ化すれば、この2でコンテナ管理を行うことができ、 AWS Fargateでサーバーレスにできる。 コンテナ コンテナは、アプリのコードや依存関係を1つのオブジェクトにパッケージ化する技術。 Docker は、アプリケーションをすばやく構築、テスト、デプロイできるソフトウェアプラットフォーム。 Amazon Elastic Container Service (Amazon ECS) Amazon Elastic Container Service (Amazon ECS) は、スケーラビリティとパフォーマンスに優れたコンテナ管理システム。 コンテナ化されたアプリを AWS で実行およびスケールできる。 Docker コンテナをサポートしている。 ECS では、API コールを使用して Docker コンテナを起動および停止できる。 Amazon Elastic Kubernetes Service (Amazon EKS) コンテナ管理システム。 AWS で Kubernetes を実行できるフルマネージドサービス。 AWS Fargate AWS Fargate は、コンテナ向けのサーバーレスエンジン。 Amazon ECS と Amazon EKS の両方で利用できる。 3.グローバルインフラストラクチャと信頼性 グローバルインフラストラクチャ データセンターに災害が起こった場合、 バックアップを取る対応しかしていないので災害が発生しないことを祈るしかない。 AWSは世界中の各リージョンで動かすことができる。一部で災害が発生してもサービスを停止させる必要はないし、ハードウェア故障コストもない。 リージョン間でデータは受け付けないため、事前に承認するリージョンを選択しておく必要がある。 選択には以下4つの要素を考慮する。 データガバナンスとコンプライアンス 特定に国で実行する/保管しないといけない。 近接性 レイテンシーを考慮するとユーザと近いリージョンを選択する。 リージョン内で利用可能なサービス 新サービスだと未対応の場合がある。 料金 ある米国リージョンとブラジルをを比較した時50%高くなる可能性がある. アベイラビリティーゾーン(AZ) リージョン内では1つのデータセンター、またはデータセンターグループで構成されている。 リージョン内は互いに数十キロ離れている。 このリージョンのグループをアベイラビリティーゾーンという。 つまり、リージョンは2つ以上のアベイラビリティーゾーンで構成されている。 AWS グローバルインフラストラクチャの完全に分離された部分でもある。 -リージョン l-リージョンa(アベイラビリティーゾーン) l-データセンター l-リージョンb(アベイラビリティーゾーン) l-データセンターグループ l-リージョンc(アベイラビリティーゾーン) l-データセンター 同じリージョン内のため低レイテンシーを実現できる。リージョンの一部で災害が発生してもゾーン内の他のデータセンターが保険になる。AWSはゾーンで2つ以上での利用を推奨。 障害に備えて、アプリを複数のアベイラビリティーゾーンにデプロイすることは、耐障害性と可用性に優れたアーキテクチャを構築するうえで重要な要素。 AWSの基本はマルチAZ構成(複数AZ構成)でこれにより高い可用性を実現している。 ※可用性:システム障害で停止しないこと。稼働率。 エッジロケーション(Point Of Presents) お客様の近くにリージョンがない場合 各地のエッジロケーションにリージョンからプッシュできる。 エッジロケーションは、Amazon CloudFront(CDNの一種) で、コンテンツのキャッシュされたコピーをお客様の近くに保存するために使用する場所。これにより、リージョンと離れてても低レンテンシーが実現できる。 リージョン→キャッシュ→エッジロケーション(でAmazon CloudFrontを使用)→ユーザ ※Amazon CloudFront:コンテンツ配信サービス Amazon Route 53 Amazon Route 53はDNSの一種でエッジロケーションで実行される。 ユーザ↔️エッジロケーションの安定した低レンテンシーを実現する。 AWS Outpost AWS Outpostはミニリージョンとして十分に機能があり、自社の建物内で使いたい、エッジロケーションを使わない人向けのサービス。(ハイブリッドクラウド(オンプレ)アプローチのインフラ運用サービス) ※DNS:ドメインネームサービス ※CDN:コンテンツデリバリーネットワーク AWSリソースをプロビジョニングする方法 AWSのサービスはAPIで操作できる 方法①手動ツール AWS のサービスを操作する方法 APIへ送信したりリソースを操作できる準備された主なツール 操作が簡単順 AWSマネジメントコンソール(ブラウザ、UIで操作) ヒューマンエラーのリスクがある 学習用に丁度良い AWSコマンドラインインターフェース(CLI) コマンドでAPIをコールする AWSマネジメントコンソール内容をスクリプト化できる AWSソフトウェア開発キット(SDK) プログラム言語でAWSを操作できる 方法②自動化サービス AWS Elastic Beanstalk EC2のプロビジョニングに便利なサービス。 コードと設定情報を提供することで必要なリソースが自動デプロイされる。 よって全ての要素をプロビジョニングする必要はなくなる。 環境は保存されるため、簡単に再度デプロイできる。 以下のようなタスクに必要なリソースが自動デプロイされる。 ・キャパシティーの調整 ・負荷分散 ・自動スケーリング ・アプリケーションの状態モニタリング AWS CloudFormation インフラをコードとして扱えるサービス。EC2以外でも使える。 AWS マネジメントコンソールを使用する代わりにコード記述で環境構築できる。 以下のようなリソースをサポートしている。 ・ストレージ ・データベース ・分析 ・機械学習 リソース定義をテンプレート化(CloudFormationテンプレート)し異なるリージョンにデプロイできる。完全自動化なのでヒューマンエラーリスクが低い。 エラーが出たら自動でロールバックされる。 4.ネットワーク AWSへの接続 Amazon Virtual Private Cloud (Amazon VPC) 何百万ものお客様がいるとする。EC2インスタンスなどの数百万のリソースが作成されたとする。こうしたすべてのリソースに対する境界がなければ、リソース間でネットワークを流れるトラフィックが制限なく発生してしまう。 この境界を確立するためのサービスが、Amazon Virtual Private Cloud (Amazon VPC) 。 VPCではパブリックな一般向けの入口と社内向けのプライベートな入口を設置できる。 インターネットゲートウェイ インターネットからパブリックトラフィックをVPCに渡すには インターネットゲートウェイをVPCにアタッチする。 つまり、入口を作らないと誰も入れない(アクセスできない)。 ※アタッチ:取り付ける。 ※サブネット:VPC内のIPアドレスの集合、VPCの一部かつEC2を配置できる場所。 ・店に置き換える例(EC2を従業員とする) サブネット:レジカウンター VPC:店の外壁。 インターネットゲートウェイ:店の玄関口。 仮想プライベートゲートウェイ(VGW) VPC 内のプライベートリソースにアクセスするには、仮想プライベートゲートウェイを使用する。 インターネットトラフィックを暗号化するVPN接続で承認された接続を受け付ける。 ※VPN:仮想プライベートネットワーク AWS Direct Connect インターネットゲートウェイも仮想プライベートゲートウェイも同じ回線(帯域幅)のため、渋滞が生じるリスクがある。AWS Direct Connectでは専用の完全プライベート接続で低レンテンシーを実現できる。近くの提供されたルーターを利用し物理接続を行う。 サブネットとネットワークアクセスコントロールリスト AWSには様々なセキュリティ対策がある。 ・ネットワーク強化 ・アプリケーションセキュリティ ・ユーザーアンデンティティ ・認証と認可 ・分散型サービス妨害(DDoS)攻撃の防御 ・データの生合成 ・暗号化 以下よりVPCにおけるネットワーク強化の側面を解説する。 サブネット VPCでパブリックとプライベートを設定できたように、サブネットでも設定できる。 パブリックサブネットではレジ受付のように誰でも一般に利用できるリソースが含まれる。 プライベートサブネットは注文履歴や個人情報を扱うリソース(DB)等が含まれる。 ⭕️インターネットゲートウェイ(IGW)→パブリサブ→プラベサブ ❌インターネットゲートウェイ(IGW)→プラベサブ ネットワークアクセスコントロールリスト (ACL) サブネット自身にもネットワークアクセスコントロールリスト (ACL)というアクセスチェックがあり、リクエストで飛んできたパケットがアクセス許可リストにあるかチェックしている。 VPCを設定する際、デフォルトACLのデフォ設定は全アクセス許可、 カスタムACLを作成した場合のデフォ設定は全アクセス拒否になっている。 ※パケット:ネットまたはネットワークを介して送信されるデータの単位。 セキュリティグループ ACLはサブネットの出入りしか管理しておらず、サブネット内のEC2インスタンスは管理していない。 個々のEC2インスタンスにはセキュリティグループを設けてパケットをチェックする必要がある。 デフォルトではEC2インスタンスのセキュリティグループは全てのポートをブロックする。(確か8080とかアクセスできるように設定した記憶ある・・) ステート(フル/レス)パケットフィルタリング セキュリティグループは通過(許可)したパケットを記録するステートフルなので2度目以降は確認しないだが、ACLはステートレスで、記録せず毎回チェックを行う。 インスタンスのパケット移動 EC2インスタンスA→セキュリティグループ→サブネットA→(Aの)ACL →(Bの)ACL→サブネットB→セキュリティグループ→インスタンスB パケットがインスタンスBからAへ戻るときはセキュリティグループのチェックはない。 グローバルネットワーク ドメインネームシステム (DNS) DNS は、インターネットで電話帳と同じ役割を果たす。DNS 解決は、ドメイン名を IP アドレスに変換するプロセス。文字列のアドレスする→DNSサーバーがウェブサーバーにアドレスを問い合わせし数値(IPアドレス)に変換→本来のサーバーに送信している。 Amazon Route 53 Amazon Route 53 は DNSウェブサービス。 リクエストをインフラストラクチャ (EC2インスタンスやロードバランサーなど) に接続する。 また、AWS外のインフラストラクチャにルーティングすることもできる。 もう一つの機能として、ドメイン名のDNSレコードを管理できる。ユーザーは、新しいドメイン名をRoute53に直接登録できる。また、他のドメインレジストラで管理されている既存のドメイン名のDNSレコードを転送することもでき、よって、すべてのドメイン名を1か所で管理できるようになる。 エッジロケーションの説明で安定した低レンテンシーを実現する為に Amazon Route 53を実装していると上で話したが以下はその図 Amazon Route 53でIPを割り出しクライアントに返してから送信される。 5.ストレージとデータベース インスタンスストアと Amazon Elastic Block Store (Amazon EBS) インスタンスストア EC2インスタンスを作成するとインスタンスストレージボリュームというローカルストレージが作成作れる。AWSホストに物理的にアタッチされている。その上でEC2インスタンスが作成され、通常のハードディスクのように書き込みできる。注意点は直接アタッチされているため、EC2インスタンスを削除すると同じく書き込みデータも削除される。ホストが変わることがある状況に対応するための仕様。主に一時データの保存に使う。 Amazon Elastic Block Store (Amazon EBS) EBSサービスを利用するとEBSストレージボリュームが提供される。 これはAWSホストにはアタッチされないため、EC2インスタンスが停止削除されてもデータの使用が可能。 EBSボリュームはサイズ・タイプ・設定を選択できる。 ボリュームのプロビショニングが完了したらEC2インスタンスにアタッチできる。 EBSではバックアップの役割もあり、増分バックアップをEBSスナップショットとして保存できる。 全てを毎回バックアップしているのではなく、変更分のみをスナップショットとしてバックアップデータに追加つしている。 まとめると、長期保有したいデータがあればEBSを利用する。 いずれもブロックレベルのストレージなのでブロック上の変更データのみが上書きされ円滑に動作する。 ※スナップショット:バックアップ Amazon Simple Storage Service (Amazon S3) オブジェクトストレージ オブジェクトストレージの各オブジェクトは、データ、メタデータ、キーで構成される。 データ:画像、動画、テキスト等のファイル。 メタデー:データの種類、使用方法、オブジェクトサイズなどの情報。 キー:一意の識別子 ブロックストレージ内のファイルを変更すると、変更した部分のみが更新される。オブジェクトストレージ内のファイルを変更すると、オブジェクト全体が更新される。 ###Amazon S3 S3のサービスはテキストや動画の保存に適している。 ・データはオブジェクとして保存される。 ・ディレクトリではなくバケットに保存される。 ・ストレージは無制限でオブジェクトの最大サイズは5TB ・オブジェクトをバージョン管理できる。 ・99.999999999%(イレブンナイン)の耐久性を誇る。 S3 にアップ時、そのファイルの可視性とアクセス許可を設定できる。 S3 のバージョニング機能を使用して、オブジェクトの経時的な変更を追跡することもできる。 ※経時的:時間の経過に伴うこと。 Amazon S3 ストレージクラス S3では実際に使用した分だけ料金発生。 様々なストレージクラスから選択できる。 以下の2つを考慮して選択する。 ・データの取得頻度 ・データの可用性の要件 ストレージクラス S3標準 高頻度アクセス向け。 最低3つのアベイラビリティゾーンにデータ保存。 S3標準-低頻度アクセス(S3標準-IA) 低頻度アクセス向け。 S3標準より、ストレージが低料金、取り出しが高料金。 S3 1ゾーン-低頻度アクセス(S3 1ゾーン-IA) 1つのアベイラビリティゾーンにデータを保存。 S3標準-IAよりもストレージ低料金。 ※1ゾーンの為、コスト節約/データ復元が簡単な場合に最適。 S3 Intelligent-Tierring アクセスパターンが不明、変化するデータに最適 オブジェクトごとに月単位のモニタリングとオートメーション料が必要。 S3 Glacier データアーカイブ用の低コストストレージ 数分〜数時間以内にオブジェクトを取得可能。 S3 Glacier Deep Archive 最も低コストのオブジェクトストレージで、アーカイブに最適。 12時間以内にオブジェクトを取得可能。 EBSとE3の比較 EBS E3 コスト ○EBSより低コスト データ更新 ブロックレベル。大容量ファイルでも一部更新で済む オブジェクトレベル。全体更新の為、低頻度アクセス向け サーバーレス EC2必要 ○EC2必要無し リスク ○ゾーン共有で安心 ※EBSの利点が少なく見えるが、複雑や小規模大量の更新は最適。 Amazon Elastic File System (Amazon EFS) EFSは共有ファイルシステム 共有ファイルサーバーは従来オンプレで管理されており、 容量が決まっている。 EFSは、 スケーリングとレプリケーションをAWSに任せられる。 必要に応じてスケールアップ/ダウンができる(自動)。 複数のインスタンスから同時にアクセスできる。 リージョンレベルのLinuxファイルシステム クラウドとオンプレ両方で利用できる。 ※レプリケーション:レプリカ(複製)すること。 ファイルストレージ ファイルストレージは、ファイルパスを使って複数クライアントが同時にアクセス可能。 Amazon EBS と Amazon EFS の比較 1 EBS EFS アクセスレベル アタッチしたインスタンス ○複数インスタンス リソースレベル アベイラビリティーゾーン ○リージョン スケーリング 手動 ○自動 ・EFSはリージョナルサービス(リージョンレベル)なので複数ゾーンに保存される。 ・リソースレベル内に保存するので、レベル内からじゃないとアクセスできない。 ・よって、EBSは同一ゾーン内にEC2とEBSが存在しないとアタッチできない。 ※ボリューム:リソースの一種。ハードウェア容量。 Amazon Relational Database Service (Amazon RDS) リレーショナルデータベース(RDBMS) リレーショナルデータベースはデータ同士を関連付けて保存操作できる。 SQLを利用してテーブルを結合して確認できる。 Amazon Relational Database Service RDSはAWSのRDBMS。 Lift&Shiftという移行方法でオンプレDBも扱える。 サポートDBエンジン ・Amazon Aurora ・PostgreSQL ・MySQL ・MariaDB ・Oracle データベース ・Microsoft SQL Server RDSに備わっている機能 自動パッチ適用 バックアップ 冗長性 フェイルオーバー 災害対策 Amazon Aurora Amazon Aurora(オーロラ)にデプロイ/移行するとさらに簡単に構築できる。 Auroraは、エンタープライズ規模のリレーショナルデータベース。以下2つのRDBMSと互換性があり、標準より機能が高い。不必要な入出力 (I/O) オペレーションを減らすことでコストを減らしつつ可用性を確保。 Auroraの特徴 PostgreSQL 標準の最大3倍の速度 MySQL 標準の最大5倍の速度 コストは商用の1/10 データレプリケーション ゾーン間でデータを6つレプリケートする データをS3に継続的にバックアップする リードレプリカを最大15個作成し読み取り負荷低減 ポイントインタイムリカバリ 特定の機関からデータ復旧可能 Amazon DynamoDB 非リレーショナルデータベース 非リレーショナルデータベースは、行と列以外の構造を使用してデータを整理する。 NoSQL DBとも呼ばれる。 構造的の 1 つとして、キーバリューペアがある。(FirebaseのJsonで保存するRealtimeDBと同じ感じ。) キー バリュー 1 名前:あ 住所:A 2 名前:い 住所:B Amazon DynamoDB Amazon DynamoDBは非リレーショナルデータベース。 サーバーレスDBなのでDB管理が必要ない。 いつでも項目内の属性追加削除できる。 複雑なsqlクエリは使えない。 Amazon DynamoDBの特徴 NoSQL 数ミリ秒台の応答時間 フルマネージド型 高いスケーラビリティ(自動スケーリング) Amazon Redshift Amazon Redshiftはビッグデータ分析に使用するデータウェアハウンジングサービス。 運用分析ではなく履歴分析に特化している。 高いスケーラビリティ。 ビッグデータに対して単一のSQLクエリを処理できる。 AWS Database Migration Service AWS Database Migration Service (AWS DMS) DMSはDB移行システム。 オンプレやクラウドからAWSに簡単に移行できる。 移行中も通常通り運用できる。 例: オンプレミス、またはEC2インスタンス、RDSに保存されている MySQL DBがある。そのDBをソースデータベースとし、DMSを使用して、Auroraなどのターゲットデータベースにデータを移行できる。 その他のデータベース Amazon DocumentDB MongoDBをサポートするドキュメントサービス Amazon Neptune グラフデータベースサービス レコメンデーションエンジン、不正検出、ナレッジグラフ等を使うアプリを構築して実行できる Amazon Quantum Leger Database(QLDB) 台帳データベースサービス 如何なるデータも削除できないイミュータブルな記録 Amazon Managed Blockchain ブロックチェーンで中央機関を介さずトランザクションを実行しデータ共有する分散台帳システム Amazon ElastiCashe キャッシュレイヤーを追加しリクエストの読み込み時間を高速化する Amazon DynamoDB Accelerator(DAX) DynamoDBのインメモリキャッシュ 非リレーショナルDBの応答を飛躍的に向上 ※イミュータブル:オブジェクト作成後、変更できないこと ※ミュータブル:オブジェクト作成後も変更できること ※インメモリキャッシュ:DBの手前でキャッシュを保存するメモリ。例:ROMストレージへアクセスせず、より高速であるRAMを使うように処理速度が向上する。 6.セキュリティ 責任共有モデル セキュリティの最終責任はお客様とAWS両方にある。 AWS環境は単一のオブジェクトではない。 クラウドはAWS、クラウド内はお客様の責任となる。この概念を共有責任モデルという。 AWSは土地や家(物理的なセキュリティとインフラ) お客様は家具や鍵(セキュリティ設定と暗号化) ユーザーのアクセス許可とアクセス権 AWS Identity and Access Management (IAM) IAMはAWSサービスのリソース/サービスのアクセス管理を行う。 デフォルトでは全くアクセス権限がない。 最小権限の原則に従い、特定のタスクを実行するために必要なアクセス許可のみを付与することを推奨。 AWS アカウントのルートユーザー AWS アカウントを初めて作成するときに、ルートユーザーと呼ばれるアイデンティティが設定される。 ルートユーザーは、アカウントにおけるすべての AWS のサービスとリソースにアクセスできる。 日常タスクではルートユーザーを使用せず、IAMユーザーを作成して使う。 IAMユーザー IAM(アイアム)ユーザーは、AWS内に作成するIDで、AWSのサービス/リソースを操作するユーザーやアプリを表す。これは、名前と認証情報で構成される。 デフォルトではアクセス許可が何もない。S3やEC2を扱うにはアクセス許可を付与する。 一人に対し1IAMユーザーの割り当てを推奨。 IAMポリシー IAMユーザーに許可/拒否アクションを記述したjsonをIAMポリシーとしてアタッチできる。 IAMグループにもアタッチできる。 IAMグループ IAMユーザーの集まり。 IAMポリシーを複数に割り当てたいときに作成する。 IAM ロール 一時的なアクセスや複数回役割が変わる場合、IAMロールを使用する。 役割毎にロールを作成し、アタッチするロールを切り替えられる。 多要素認証(MFA) ルートユーザーとIAMユーザーに多要素認証を設定できる AWS Orgnizitions AWS Orgnizitionsで、全てのAWSアカウントを一元的に管理できる。 OUと個別垢にアタッチできる。 一括請求(コンソリデーディットビリング) 使用量が多いほど割引があるサービスなどが適用されやすくなる。 アカウントのグループ化が可能になる 開発者垢を開発者OUへグループ化とか OU配下はOUにアタッチしたポリシーを継承する AWSサービス/APIアクションのアクセス管理 サービスコントロールポリシー(SCP)で各垢のアクセス許可を制限できる。 ※OU(Organizational Unit):組織単位 コンプライアンス AWS Artifact AWS Artifactは、AWSのセキュリティ/コンプライアンスレポート、契約を提供するサービス。 主要なセクション AWS Artifact Agreements 個別のアカウントと AWS Organizations のすべてのアカウントにおいて契約の確認、受諾、管理を行うことができる。 AWS Artifact Reports AWSのセキュリティ制御の証拠として提示することができる。 カスタマーコンプライアンスセンター AWS コンプライアンスの詳細を確認することに役立つ。 コンプライアンスに関する重要な質問に対する AWS の回答 AWS リスクとコンプライアンスの概要 セキュリティ監査チェックリスト サービス妨害攻撃 AWS Shield DDoS攻撃から保護するサービスを2つ提供している。 AWS Shield Standardは、一般的なDDoS攻撃から無料/自動的に保護する AWS Shield Advancedは、高度なDDoS攻撃を有料で検出/緩和する その他セキュリティサービス AWS Key Management Service (AWS KMS) 暗号化キーの作成、管理、使用を行える 様々なサービス/アプリでのキーの使用を制御できる。 AWS WAF リクエストをモニタリングするウェブアプリケーションファイアウォール ACLを使用してAWSリソースを保護する Amazon Inspector 自動化セキュリティ評価で、アプリのセキュリティとコンプライアンスを改善する 脆弱性のあるバージョン検出等も行う Amazon GuardDuty AWSインフラ/リソースの脅威を機械学習等を利用し検出する。 AWS環境内のネットワークとアカウントアクティビティの継続的モニタリングで脅威を特定する 7.モニタリングと分析 Amazon CloudWatch Amazon CloudWatch は、様々なメトリクスをモニタリングおよび管理し、それらのデータに基づいてアラームを設定できるウェブサービス。 利点 取得メトリクスの可視化 メトリクスベースのアラーム 2種類のメトリクス 標準メトリクス(EC2の場合) CPU平均使用率等の取得 カスタムメトリクス OS内でないと取得できないときに使用 例:メモリ使用率 ※モニタリング:監視。メトリクスの収集 ※メトリクス:数値データ。リソースに関連づけられた変数。 CloudWatch アラーム CloudWatchで定義したメトリクス値を超えた場合、自動実行するアラームを作成できる。 例えば、CPU使用率を設定し、EC2の停止漏れアラームを作成できる。 CloudWatch ダッシュボード EC2インスタンスのCPU 使用率、S3 バケットに対して行われたリクエストの合計数などをモニタリングできる。 AWS CloudTrail AWS CloudTrailは、API コールを記録する。 リクエストや行の追加アクション、誰が操作したか全て記録される。 CloudTrailで、ログを残すことで運用等に活用できる。 CloudTrail Insights CloudTrail では、CloudTrail Insights を有効にすることもで、異常なユーザーアクティビティ/APIを自動的に検出できる。 例えば、通常よりもEC2インスタンスが最近作成された場合など。 AWS Trusted Advisor Trusted Advisor は、AWS環境を検査し、AWSのベストプラクティスに基づいてリアルタイムの推奨を提供するウェブサービス。まさにアドバイザー。 S3バケット等セキュリティーも確認する。 5つのカテゴリチェックを提供する コスト 削除して、コストを削減できる可能性がある未使用のまたはアイドル状態のリソースを見つける パフォーマンス 使用状況や設定を分析する セキュリティ アクセス許可を確認したり、有効にする AWS セキュリティ機能を特定 耐障害性 アプリの可用性と冗長性を向上 サービス制限 意図しない支出から保護、80%を超過すると通知 緑の四角は問題なし 黄色の三角は調査の推奨 赤い丸は推奨アクション 8.料金とサポート AWS無料利用枠 次の3種類のオファーが用意されている。 無期限無料 12ヶ月間無料 トライアル AWSの料金の概念 使用分のみ課金される 予約して支払いを削減する 使用量が増えるほど、ボリュームディスカウントにより支払い料金が少なくなる AWS料金計算ツール 見積もり作成ができ共有できる。 請求ダッシュボード AWS の請求書の支払いを行ったり、使用量をモニタリングしたり、コストを分析、管理したりできる。 当月の今日現在の残高と前月を比較したり、現在の使用量に基づいて翌月の予測を入手したりする 今月の初めから現在までのサービス別利用料を確認する サービス別の無料利用枠の使用状況を確認する Cost Explorer にアクセスして予算を作成する Savings Plans の購入や管理を行う AWS のコストと使用状況レポートを発行する 一括請求(コンソリデーティッドビリング) AWS Organizations では、一括請求 (コンソリデーティッドビリング) ができる。 請求書をまとめられる 複数の垢をまとめた使用量にすると割引を受けれたりする AWS Budgets AWS Budgets では、予算を作成してサービスの使用量、サービスのコスト、インスタンスの予約を計画できる。定義使用量を超えた場合アラームを受け取れる。 AWS Cost Exploer 時間の経過に伴う AWS のコストと使用量を可視化して把握し、管理できるツール。 AWSサポートプラン 以下4つのサポートプランが用意されている。 AWSの全ての人へ無料提供されるベーシックプランに加え、 デベロッパー、ビジネス、エンタープライズの3つ有料プランを追加できる。 3つとも月間利用料がかかる。 ベーシック 無料 デベロッパー 24時間対応メール 12時間以内の障害対応 4時間以内の本番障害対応 1時間以内の本番システムダウン対応 ビジネス 上記全てのサポート AWS Trusted Advisorの全チェック機能 電話の問い合わせ 30分以内にビジネスクリティカルなシステムダウン対応 エンタープライズ 上記全てのサポート 15分以内にビジネスクリティカルなシステムダウン対応 専属テクニカルアカウントマネージャー テクニカルアカウントマネージャー (TAM) エンタープライズサポートプランでは、テクニカルアカウントマネージャー (TAM) によるサポートを受けることができる。 TAM が AWS の主要な窓口になり、アプリケーションの計画、デプロイ、最適化に関するガイダンスやアーキテクチャのレビューを提供し、お客様と継続的に連絡をとる。 AWS Marketplace デジタルカタログ。AWS Marketplace を使用すると、AWS で実行するソフトを見つけて試したり、購入したりできる。色々入ったパッケージを売り買いできる 9.移行とイノベーション AWS Cloud Adoption Framework(AWS CAF) Cloud Adoption Frameworkは移行する為の6つの主要なパースペクティブをまとめたガイダンス。 各パースペクティブは、個別の責任に対応する。 計画プロセスは、組織の適切な担当者が事前に変更に備えるのに役立つ。 ビジネスパースペクティブ ビジネス戦略と IT 戦略が別々になるモデルから、IT 戦略を組み込むビジネスモデルに移行する 人員パースペクティブ クラウドベースのコンピテンシーを追加して組織のプロセスとスタッフのスキルを新しくすることで、チームでクラウド導入の準備を整える ガバナンスパースペクティブ 必要なスタッフのスキルと組織のプロセスを新しくする方法を理解する プラットフォームパースペクティブ セキュリティの側面 オペレーションパースペクティブ アジャイルベストプラクティスを使用してクラウド内で運用する ※ガイダンス:案内。指導。手引き。 移行戦略 移行時に導入できる最も一般的な 6 つの戦略 リホスト "Lift & Shift" とも呼ばれる。 変更せずにアプリケーションを移行する。 リプラットフォーム 「リフト、ティンカー(手直し)、シフト」とも呼ばれる リホストに手直しを加える リファクタリング/アーキテクチャの再設計 クラウドネイティブの機能を使用してアプリのアーキテクチャの設計開発方法を作り直すなど 再購入(Repurchase) 古いライセンスを切って、新しいライセンスを取得や、他への乗り換えなど 保持(Retain) 必要なアプリを移行せず保持や、移行の延期 リタイア 不要になったアプリケーションを削除するプロセス AWS Snowファミリー AWS Snow ファミリーは、エクサバイト規模までのデータをAWSとの間で物理的に転送できる物理デバイス。 シンプルかつ低コスト、セキュア。 Snowファミリーの3つのデバイス(容量の少ない順) AWS Snowcone 8TBのストレージ AWS Snowball 以下2種類のデバイスがある Snowball Edge Storage Optimized 大規模なデータ移行と定期的な転送向け 80TBのストレージ Snowball Edge Compute Optimized 機械学習/フルモーション動画分析/ローカルコンピューティングスタックなどのユースケース向け 42TBのストレージ AWS Snowmobile 大容量データ、エクサバイト規模を転送できる 100PBのストレージ AWSでのイノベーション クラウドジャーニーを続ける上で将来予測される経路 サーバーレスアプリケーション AWS Lambda等 人工知能 Amazon Transcribe で音声をテキストに変換 Amazon Comprehend でテキストのパターンを検出 Amazon Fraud Detector で不正の可能性があるオンラインアクティビティを特定 Amazon Lex で音声およびテキストチャットボットを構築 機械学習(ML) Amazon SageMaker で従来のMLより簡単に構築/トレーニング/デプロイできる ※クラウドジャーニー:クラウド化への継続的な取り組み。 10.クラウドジャーニー AWS Well-Architectedフレームワーク AWS Well-Architected フレームワークは、信頼性、安全性、効率が高く、コスト効率に優れたシステムを設計し、AWS クラウドで運用する方法を理解するのに役立ちます。また、このフレームワークは、ベストプラクティスに照らしてアーキテクチャを評価し、原則を設計し、改善すべき分野を特定する一貫した方法を提供する。 Well-Architected フレームワークは以下の5つの柱に基づく。 運用上の優秀性 ワークロードを効果的に実行し、運用の知見を得る セキュリティ 信頼性 正確で一貫したワークロード パフォーマンス効率 リソースの効率や需要/技術の変化に応じた効率性の維持 コスト最適化 安価にシステム実行し、ビジネス価値を実現 (持続性) AWSクラウドの利点 クラウドコンピューティングの利点6つ 先行支出を変動支出に切り替える 圧倒的なスケールメリットを享受できる キャパシティーの予測が不要になる スピードと俊敏性が向上する データセンターの維持管理にかかる費用が不要になる 数分で世界中にデプロイできる
- 投稿日:2022-02-01T11:05:07+09:00
VMware Cloud on AWSの利用料金について (利用料金計算ツール利用方法)
1. はじめに 「VMware Cloud on AWS」の簡易サイジング方法について前回ご紹介しましたので、今回は定価ベースでの利用料金の算出方法についてご紹介します。 2. VMware Cloud on AWSの利用料金を把握したい オンデマンド、1年サブスクリプション、3年サブスクリプションそれぞれの定価ベースの利用料金について、次のVMware社提供のWebツールから簡単に算出できます。 試してみる 本番環境での最小構成であるi3.metalを2台をTokyo Regionで利用する場合は次のようにインプットすると、オンデマンド/1年サブスクリプション/3年サブスクリプションの3パターンで算出します。 1年/3年サブスクリプションの考え方は「Amazon EC2」などで利用できる「Dedicated Host」と同様の概念です。複数年の利用をコミットすることにより大幅なディスカウントを受けられます。VMware Cloud on AWSの場合では3年サブスクリプションでオンデマンド利用と比べて最大50%のディスカウントを受けられます! 3. 参考記事
- 投稿日:2022-02-01T11:05:07+09:00
VMware Cloud on AWSの利用料金について (利用料金計算ツール利用方法ほか)
1. はじめに 「VMware Cloud on AWS」の簡易サイジング方法について前回ご紹介しましたので、今回は定価ベースでの利用料金の算出方法についてご紹介します。 2. VMware Cloud on AWSの利用料金を把握したい オンデマンド、1年サブスクリプション、3年サブスクリプションそれぞれの定価ベースの利用料金について、次のVMware社提供のWebツールから簡単に算出できます。 試してみる 本番環境での最小構成であるi3.metalを2台をTokyo Regionで利用する場合は次のようにインプットすると、オンデマンド/1年サブスクリプション/3年サブスクリプションの3パターンで算出します。 1年/3年サブスクリプションの考え方は「Amazon EC2」などで利用できる「Dedicated Host」と同様の概念です。複数年の利用をコミットすることにより大幅なディスカウントを受けられます。VMware Cloud on AWSの場合では3年サブスクリプションでオンデマンド利用と比べて最大50%のディスカウントを受けられます! 3. 参考記事
- 投稿日:2022-02-01T09:38:54+09:00
AWS コンテナ運用設計に関するアプローチ
ECSメインにAWSサービスを利用してコンテナの運用設計を考えてみます。 コンテナの運用設計 ECS 上で稼働するWebアプリケーションを前提に運用の要件を考えてみます。 コンテナを使用したマイクロサービスの運用は、モノシリックなシステム運用とは少し異なります、以下の項目を運用項目としてピックアップします。 可用性/スケーリング CI/CD ロギング トレース モニタリング ECS/ECR のアーキテクチャ まずはECS/ECR のアーキテクチャについて触れます。 Amazon ECSはコンテナの作成、実行、停止といった管理をメインとしたサービスであり、Amazon ECRは Dockerのレジストリサービスとなります。リポジトリにあるイメージをプッシュしたり、イメージの保管等を行います。 全体的なイメージを以下のように理解をしています。 ECSの機能 まずECSです。 ECSは複数のエンティティから機能を果たすため、各々どのような役割を担うかを理解する必要があるかと思います。以下は包含関係と関係性を図解として描いています。 Task definition(タスク定義) task definitionとは起動するtaskの情報が定義されたもので、 docker-compose.ymlのようなイメージです。 起動するタイプ(EC2 or Farate)をタスク定義から定義し、1つのタスク定義上に複数のコンテナを定義する事が可能です。 task definitionのimageパラメーター上で、後述のECR imageに対してアクセスし、ECR image をそのままTaskとして実行する事も出来ます。 また、後述するServiceはtask definitionを指定する必要があります。 サンプルとしてtask definitionが保持するデータを表示させてみます。 イメージ情報やコンピューティングリソース、通信プロトコルなどが定義されている事が判ります。 sample1-describe-task-definition.json { "taskDefinition": { "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:xxxxxx:task-definition/php-sample-fargate:4", "containerDefinitions": [ { "name": "php-sample-fargate", "image": "xxxx.dkr.ecr.ap-northeast-1.amazonaws.com/test:latest", "cpu": 256, "memoryReservation": 128, "portMappings": [ { "containerPort": 80, "hostPort": 80, "protocol": "tcp" } ], "essential": true, "environment": [], "mountPoints": [], "volumesFrom": [], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/php-sample-fargate", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } } } ], "family": "php-sample-fargate", "taskRoleArn": "arn:aws:iam::xxxxxxx:role/ecsTaskExecutionRole", "executionRoleArn": "arn:aws:iam::xxxxxxxx:role/ecsTaskExecutionRole", "networkMode": "awsvpc", "revision": 4, "volumes": [], "status": "ACTIVE", "requiresAttributes": [ { "name": "com.amazonaws.ecs.capability.logging-driver.awslogs" }, { "name": "ecs.capability.execution-role-awslogs" }, { "name": "ecs.capability.execution-role-ecr-pull" }, { "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18" }, { "name": "ecs.capability.task-eni" } ], "placementConstraints": [], "compatibilities": [ "EC2", "FARGATE" ], "requiresCompatibilities": [ "FARGATE" ], "cpu": "256", "memory": "512", "registeredAt": "2021-07-16T10:21:54.039000+09:00", "registeredBy": "arn:aws:sts::xxxxxxxxxx:assumed-role/xxxxxxx } } Task definitionはJSONにて定義出来ます。 なお、AWS CLI を使用してタスク定義のテンプレートを生成する事が可能で、 空のタスク定義のテンプレートがAWSドキュメントに記載されています。 generate-template.awscli aws ecs register-task-definition --generate-cli-skeleton タスク定義テンプレート 以下に示しているのは、空のタスク定義テンプレートです。このテンプレートを使用してタスク定義を作成します。これにより、コンソールの JSON 入力領域に貼り付けるか、ファイルに保存して AWS CLI の --cli-input-json オプションで使用できるようになります。詳細については、「タスク定義パラメータ」を参照してください。 ECS Cluster クラスター自体は、後述するACTIVEなService、Taskが実行される論理的なグループという理解で良いかと思います。 また、クラスターを作成する際に、VPC/サブネットなどのネットワーク情報を定義します。 サンプルとしてECSクラスターが保持するデータを表示させてみます。 sample2-describe-ecs-cluster.json { "clusters": [ { "clusterArn": "arn:aws:ecs:ap-northeast-1:xxxxxx:cluster/fargate-cluster", "clusterName": "fargate-cluster", "status": "ACTIVE", "registeredContainerInstancesCount": 0, "runningTasksCount": 2, "pendingTasksCount": 0, "activeServicesCount": 2, "statistics": [], "tags": [], "settings": [], "capacityProviders": [ "FARGATE_SPOT", "FARGATE" ], "defaultCapacityProviderStrategy": [] } ], "failures": [] } Service Service は、Task definitionで指定されたTaskに紐づき、ECSクラスター上でACTIVEとなります。 主幹はロードバランサーやAutoScalingをECSクラスター上で機能させる要素です。 また、後述のTaskとは機能が分離しており、ECSを立ち上げる必須機能ではありません。 サンプルとしてServiceが保持するデータを表示させてみます。 ロードバランサーの情報や、スケーリングポリシー、後述のTaskのリビジョンを管理、制御するタスクセット(tasksets)と呼ばれる情報を返しています。 なお、aws ecs create-service --cli-input-json により定義されたJSONファイルからサービスの作成も可能です。 sample3-describe-ecs-service.json { "services": [ { "serviceArn": "arn:aws:ecs:ap-northeast-1:xxxxxxxx:service/fargate-cluster/php-samplefargate", "serviceName": "php-samplefargate", "clusterArn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxx:cluster/fargate-cluster", "loadBalancers": [ { "targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxxxx:targetgroup/tg-fargat-php-samplefargate-2/xxxxxx", "containerName": "test", "containerPort": 80 } ], "serviceRegistries": [], "status": "ACTIVE", "desiredCount": 1, "runningCount": 1, "pendingCount": 0, "launchType": "FARGATE", "platformVersion": "1.4.0", "taskDefinition": "arn:aws:ecs:ap-northeast-1:xxxxxxxx:task-definition/test-task:1", "deploymentConfiguration": { "maximumPercent": 200, "minimumHealthyPercent": 100 }, "taskSets": [ { "id": "ecs-svc/xxxxxxxxx", "taskSetArn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxx:task-set/fargate-cluster/php-samplefargate/ecs-svc/xxxxxxxxx","clusterArn": "arn:aws:ecs:ap-northeast-1:386755752236:cluster/fargate-cluster", "startedBy": "CodeDeploy", "externalId": "xxxxxxxxx", "status": "PRIMARY", "taskDefinition": "arn:aws:ecs:ap-northeast-1:xxxxxxxxx:task-definition/test-task:1", "computedDesiredCount": 1, "pendingCount": 0, "runningCount": 1, "createdAt": "2021-07-16T11:04:41.383000+09:00", "updatedAt": "2022-01-21T08:54:17.942000+09:00", "launchType": "FARGATE", "platformVersion": "1.4.0", "networkConfiguration": { "awsvpcConfiguration": { "subnets": [ "subnet-xxxxxxxxx", "subnet-xxxxxxxxx" ], "securityGroups": [ "xxxxxxxxx" ], "assignPublicIp": "DISABLED" } }, "loadBalancers": [ { "targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxxxxx:targetgroup/tg-fargat-php-xxxxxxxxx", "containerName": "test", "containerPort": 80 } ], "serviceRegistries": [], "scale": { "value": 100.0, "unit": "PERCENT" }, "stabilityStatus": "STABILIZING", "stabilityStatusAt": "2022-01-21T08:54:17.942000+09:00", "tags": [] } ], "deployments": [] ... Task タスク定義 からECSクラスター上に起動したコンテナの集合体であり、アプリケーションの処理をメインに行います。 また、ECSクラスター上で稼働しているTaskは、起動/停止が可能です。 ECRの機能 ECR の主要コンポーネントである レジストリ / リポジトリ / イメージについてです。 Registry レジストリ内にイメージリポジトリを作成し、イメージを保存します。 レジストリ自体は認証(Dockerクライアントとの認証許可を行う事で、レジストリ内のリポジトリとの間でイメージをプッシュ、プルできるようにする)、レプリケーション(AWSのクロスリージョン、クロスアカウントに対するイメージのレプリケーション)等によるものなので、設定情報という理解で良いかと思います。 Repository 後述のコンテナイメージは Amazon ECRリポジトリに保存されます。 また、2020年12月以降、ECRはパブリック領域としての利用が可能となり、コンテナイメージをパブリックに公開する事も、ダウンロードすることが可能になりました。 image docker imageのようなもので、イメージをリポジトリ内へpush(docker push)して、登録を行います。イメージはURI形式で連携が可能で、ECSのタスク定義として使用出来ます。実態はS3へ配置されます。 稼動システムの全体像 コンテナの運用をするために複数のAWSサービスを使用します。 今回は、一般的なWebアプリケーションを想定し、以下の構成図から運用を考えていきます。 Monitoring ECSに対して監視を行う場合、Cloudwatch メトリクスとCloudwatch Container Insightsの二種類の機能を使用する状況を把握する事が出来ます。 いずれもメトリクスと呼ばれる指標となるデータポイントを一定期間で集計したもので、対象のメトリクスが閾値を超えた場合、アラームを送信するなどの対策も可能です。 Cloudwatch メトリクス Cloudwatch メトリクスは、ECSのサービス単位で MemoryUtilization / CPUUtilization の2つの指標をモニターします。 メトリクス 説明 MemoryUtilization クラスター、サービス単位で使用されているメモリーの割合(%) CPUUtilization クラスター、サービスで使用されている CPU の割合(%) MemoryUtilization / CPUUtilizationでは、クラスター・サービスいずれもタスクの総数から除算する方式で算出されるため、タスク全てが均衡化された数値としてカウントされるようです。これは、特定のタスクへ負荷をモニタリングする要件にはマッチしない事を意味します。 Cloudwatch Container Insights Cloudwatch Container Insightsは、Cloudwatchメトリクスより詳細なメトリクスを取得出来ます。また、メトリクス情報を返すリソースの粒度(クラスター、サービス、タスク)も拡張されるためモニタリング機能としてはCloudwatch Container Insightsの方が情報量に優れています。 Amazon ECS クラスターで Container Insights を有効にし、以下のいずれか、または両方を使用する事で多くのメトリクス情報を返します。 クラスターレベル、タスクレベル、およびサービスレベルのメトリクスの収集を開始するには、AWS Management Console または AWS CLI を使用します。 CloudWatch エージェントを DaemonSet としてデプロイし、インスタンスでホストされているクラスターで Amazon EC2 インスタンスレベルのメトリクスの収集を開始します。 メトリクス 対象 説明 ContainerInstanceCount ClusterName クラスターに登録されている Amazon ECS エージェントを実行している EC2 インスタンス数 CpuUtilized TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースのタスクにより使用されている CPU ユニット数 CpuReserved TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースのタスクにより予約されている CPU ユニット数 DeploymentCount ServiceName、ClusterName ECS サービスでのデプロイの数 DesiredTaskCount ServiceName、ClusterName ECS サービスに必要なタスクの数 MemoryUtilized TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースのタスクにより使用されているメモリ MemoryReserved TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースのタスクにより予約されているメモリ NetworkRxBytes TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースにより受信されるバイト/秒 ※ネットワークモードがawsvpc、bridgeが対象 NetworkTxBytes TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースにより送信されるバイト/秒 ※ネットワークモードがawsvpc、bridgeが対象 PendingTaskCount ServiceName、ClusterName PENDING 状態にあるタスクの数 RunningTaskCount ServiceName、ClusterName RUNNING 状態にあるタスクの数 ServiceCount ClusterName クラスター内のサービスの数 StorageReadBytes TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースのストレージから読み込まれたバイト数 StorageWriteBytes TaskDefinitionFamily、ClusterName、ServiceName 指定した対象のリソースのストレージヘ書き込まれたバイト数 TaskCount ClusterName クラスターで実行されているタスクの数 TaskSetCount ServiceName、ClusterName サービス内のタスクセットの数 CloudWatch エージェントからEC2インスタンスレベルのメトリクスの収集 メトリクス 対象 説明 instance_cpu_limit ClusterName クラスター内の単一の EC2 インスタンスに割り当てることができる CPU ユニットの最大数 instance_cpu_reserved_capacity ClusterName、InstanceId、ContainerInstanceId クラスター内の単一の EC2 インスタンスで現在予約されている CPU ユニットの最大数 instance_cpu_usage_total ClusterName クラスター内の単一 EC2 インスタンスで使用されている CPU ユニットの数 instance_cpu_utilization ClusterName、InstanceId、ContainerInstanceId クラスター内の単一の EC2 インスタンスで使用されている CPU ユニットの合計割合 instance_filesystem_utilization ClusterName、InstanceId、ContainerInstanceId クラスター内の単一の EC2 インスタンスで使用されているファイルシステム容量の合計割合 instance_memory_limit ClusterName このクラスター内の単一の EC2 インスタンスに割り当てることができるメモリの最大量(バイト単位) instance_memory_reserved_capacity ClusterName、InstanceId、ContainerInstanceId クラスター内の単一の EC2 インスタンスで現在予約されているメモリの割合 instance_memory_utilization ClusterName、InstanceId、ContainerInstanceId クラスター内の単一の EC2 インスタンスで使用されているメモリの合計割合 instance_memory_working_set ClusterName クラスター内の単一の EC2 インスタンスで使用されているメモリの量(バイト単位) instance_network_total_bytes ClusterName クラスター内の単一の EC2 インスタンスでネットワーク上で送受信された 1 秒あたりの合計バイト数 instance_number_of_running_tasks ClusterName クラスター内の単一の EC2 インスタンスで実行中のタスクの数 CWエージェントは、ECR経由でのエージェントが入ったイメージの導入も可能です。 ネットワークモードについて メトリクス NetworkRxBytes/NetworkTxBytes で出てきたネットワークモードについて少し触れます。 ECSのネットワークモードとは、タスクのネットワーク動作を定義するものです。 ネットワークモードは、主に以下3点となりますが、Fargateでのタスクネットワーキングはawsvpcのみとなります。 awsvpc タスクには、独自の Elastic Network Interface (ENI) とプライマリプライベート IPv4 アドレスが割り当てられます。これにより、タスクに Amazon EC2 インスタンスと同じネットワークプロパティが与えられます。 bridge タスクは、タスクをホストする各 Amazon EC2 インスタンス内で実行される Docker の組み込み仮想ネットワークを利用します。 host タスクは Docker の組み込み仮想ネットワークをバイパスし、タスクをホストしている Amazon EC2 インスタンスの ENI にコンテナポートを直接マッピングします。その結果、ポートマッピングが使用されている場合、1 つの Amazon EC2 インスタンスで同じタスクのインスタンスを複数実行することはできません。 可用性とScaling ECSの可用性とScalingはServiceの機能がカバーします。 それぞれの観点から見ていきます。 可用性 ECSのService にはサービススケジューラ(schedulingStrategy)というパラメーターが存在します。 schedulingStrategy では、以下の2つを指定出来ます。 REPLICA クラスター全体で必要な数のタスク(DesiredCount)を配置して維持します。デフォルトでは、サービススケジューラによってタスクはアベイラビリティーゾーン間で分散する構成を自動で行います。 DAEMON クラスター内のアクティブなコンテナインスタンスごとに、1 つのタスクのみをデプロイします。サービススケジューラは、実行中のタスクのタスク配置制約(後述の参考URL)を評価し、配置制約を満たさないタスクを停止します。 つまりインスタンス数とタスク数が 1対1で実行するように維持します。 DAEMONタイプの設定は、Fargate 起動タイプでは利⽤が出来ません。 Scaling ECS上で機能するスケーリングについて考えていきます。 スケーリングには、スケールアップ(タスクサイズと呼ばれるtaskのCPU/memoryの増強)とスケールアウト/インが考えられますが、今回はTaskの停止を伴わないスケールアウト/インについて触れていきます。 AutoScaling ECSでは、ServiceへAuto Scalingを設定する事が出来ます。(Service Auto Scaling) これはサービスの必要タスク数(DesiredCount)を⾃動的に増減させるというものです。 タスクの必要数 Service Auto Scaling で使用するタスクの数 タスクの最小数 Service Auto Scaling で使用するタスクの下限数 タスクの最大数 Service Auto Scaling で使用するタスクの上限数 なお、タスクの必要数は、最小タスク数と最大タスク数の範囲内である必要があります。 Service Auto Scalingでは、オプション機能により、ユーザー定義の条件に従ってスケーラブルする仕組みとなっており、ECSの CloudWatch メトリクスを使用して、ピーク時に対処するためにサービスをスケールアウトし (実行するタスクを増やし)、使用率の低い期間にコストを削減するためにサービスをスケールインする (実行するタスクを減らす) ことができます。 以下の2タイプが Service Auto Scalingとしてサポートしています。 ステップスケーリング アラーム違反の大きさに応じて異なる一連のスケーリング調整値に基づいてリソースをスケールします。 以下2つのメトリクスから選択し、任意のパーセンテージに応じたスケールアウト/インが動作する仕組みです。 ECSServiceAverageCPUUtilization サービスの平均 CPU 使用率 ECSServiceAveregemorutilization サービスのメモリ平均使用率 例として、メトリクス ECSServiceAverageCPUUtilizationを使用し、30 - 70%を通常時のtaskカウントとし、30%未満でtask 1つへスケールイン、70 - 89% でtaskを3つへスケールアウト、90%以上はtaskを4つへスケールアウトなどという設定が可能です。 また、クールダウンと呼ばれるスケールアウト/インアクティビティが完了してから別のアクティビティが開始されるまでの時間を指定する事が可能です。 なお、スケールインのクールダウンの場合、クールダウン期間中に別のアラームによってスケールアウトがトリガーされると、Service Auto Scaling によって即座にスケールアウトされます。 スケーリングイベントが発生している最中に、別のスケーリングイベント(80%から更に90%以上になった場合)が発生し得る場合、クールダウン時間を減らす事で突如発生するスパイクにも対応が可能となります。 ターゲット追跡スケーリング 特定の CloudWatch メトリクスのターゲット値に基づいてリソースをスケールします。 ステップスケーリング同様に以下3つのメトリクスを選択し、ターゲット値を指定します。 ECSServiceAverageCPUUtilization サービスの平均 CPU 使用率 ECSServiceAveregemorutilization サービスのメモリ平均使用率 ALBRequestCountPerTarget Application Load Balancer ターゲットグループ内のターゲットごとに完了したリクエスト数 ターゲット追跡スケーリング では、選択したメトリクスのターゲット値を標準としたアラームの自動生成が行われます。 例えばECSServiceAverageCPUUtilizationのターゲット値を60%とした場合、スケールアウト/インの閾値(%)が、自動で作成され、60%を保とうとする仕組みです。 サービス可用性の影響を軽減させるため、スケールインポリシーは長期間にわたって実行されるようです。(X分間のXデータポイントのX値がスケールアウトポリシーの評価対象より長く設定される) Capacity Provider ECSクラスターでは、Capacity Providerと、Capacity Provider strategyと呼ばれる実行されたタスクをスケーリングする際に、リソースを指定する機能が備わっています。 AutoScaling の戦略に合わせて、Capacity Providerを使用して、コストを削減する事も可能です。 Capacity Provider ECSクラスターに関連付けられ、後述の Capacity Provider strategyに使用されます。 タスクが実行されるインフラストラクチャがFargateであれば FargateあるいはFargate spot を選択します。EC2であれば既存の Auto Scaling group をラップする形で使用します。 起動タイプ キャパシティプロバイダー EC2 Auto Scaling Group Fargate FARGATE, FARGATE SPOT ECS on EC2におけるCapacity Providerは、指定したAutoScaling Groupをラップします。起動タイプがEC2に特化した、Capacity Providerのパラメーターは主に2つです。 Managed Scaling 有効な場合、Auto Scalingのスケーリングプランを使用して Auto Scaling Groupのスケールアウト/インのアクションを管理します。無効になっている場合、Auto Scaling Groupを自分で管理します。 Target Capacity Managed Scalingが有効になっている場合に指定可能で、1~100%をターゲット値として指定する事で、先述したターゲット追跡スケーリングポリシーを使用する事が出来ます。 一方、Fargateの場合、FARGATE SPOTが存在します。 FARGATE SPOTは通常のFARGATEよりもコストが安く、通常の FARGATEに比較して最大70%割引されます。但し、Spot の在庫が少なくなってくるとタスクの停止されることがありますので、ある程度仕組み化が必要なようです。 Capacity Provider strategy Capacity Provider strategyを指定する事でCapacity Provider が有効となります。Capacity Provider strategyは、2つのパラメーターを指定する事で起動する割合を指定する事が出来ます。これらに FARGATEと FARGATE SPOT を指定する事で有効となります。 パラメーター 説明 Base 最小起動数 Weight 比率 例として、FARGATEおよびFARGATE SPOT を使用するCapacity Providerを指定します。 最低タスク数を2とした場合、以下のような割合で定義すると、Scaleoutしたタスクは、FARGATE SPOTにて起動します。 CapacityProvider/Service Auto Scaling FARGATE FARGATE SPOT Base 2 - Weight 1 1 Service Auto Scaling 2 (Scaleout policy on) CI/CD コンテナを使用するシステムの開発、運用工程では、再現性のあるコンテナの継続的にデプロイをする、あるいはテスト・ビルド・デプロイの自動化をするためなどの目的により、CI/CDの考え方を用いた事例が多いかと思います。 AWSでは、Codeサービスと呼ばれるCI/CDパイプラインを構築する事で、CI/CDをAWS内で完結させることが出来ます。 今回はECSを使用したシステムのため、ECSへ特記した事項として2点あります。 1. CodeBuildでビルドしたイメージはbuildspec.ymlで定義した情報からECRへイメージをpushが出来ます。(ECRのサービスロールからCodeBuildからのアクセスを許可する必要があります) 2. ECR に格納されているイメージへの変更を検出し、CodeDeployを使用して、ECS クラスターとロードバランサーにルーティングしてデプロイする事が出来ます。 これらを踏まえて、運用観点からどのような設計を行うかを考えていきます。 パイプライン設計とイメージのメンテナンス CI/CD パイプラインからイメージの更新がある場合、ECRへイメージを自動プッシュする流れとなります。プロダクションを意識したCI/CD パイプラインでは、本番・検証・開発環境が共存するサービス、分離すべきサービスが混雑する可能性が高いため、環境単位、タスク単位などの細かなパイプライン設計が事前に必要となってくると思います。 その一つとして、ECRリポジトリをどのように分けるなども考慮が必要です。 ECRのリポジトリにプッシュされたイメージの実態はS3へ保存されますが、このリポジトリに対して、ライフサイクルポリシーを設定する事が可能です。 ライフサイクルはルールに沿って解釈され、イメージのタグに基づいたポリシーを設定する事も可能です。開発規模が大きければ大きいほど、イメージの更新頻度は上がりますので、ライフサイクルも同時に踏まえた上で全体のリポジトリの設計を行い、不要なファイルをメンテナンスする仕組みを設けた方がよさそうです。 sample4-template-ecr-lifecycle-rule.json { "rules": [ { "rulePriority": 1, "description": "Expire images older than 10 days", "selection": { "tagStatus": "untagged", "countType": "sinceImagePushed", "countUnit": "days", "countNumber": 10 }, "action": { "type": "expire" } } ] } sample5-template-ecr-lifecycle-rule.json { "rules": [ { "rulePriority": 1, "description": "prod Expire images older than 100 days", "selection": { "tagStatus": "tagged", "tagPrefixList": ["prod"], "countType": "sinceImagePushed", "countUnit": "days", "countNumber": 100 }, "action": { "type": "expire" } }, { "rulePriority": 2, "description": "stageanddev Expire images older than 10 days", "selection": { "tagStatus": "tagged", "tagPrefixList": ["stage","dev"], "countType": "sinceImagePushed", "countUnit": "days", "countNumber": 10 }, "action": { "type": "expire" } } ] } 承認プロセスの利用 CodePipeline には承認プロセスを追加する機能が存在します。 CI/CD パイプライン経由でプロダクション環境を新しいリジョンで適用する際に、承認プロセスを設けてリリース可否を判断させる仕組みを設ける事で、開発者/運用者と承認者の間でリリースの影響下をお互いに共有する事ができ、予期せぬアクシデント未然に防ぐ、あるいは自動化に意思決定の判断を設ける、ガバナンスの強化といった様々な観点を保護します。 Code Pipeline のGUIとApproval アクションを追加する際の設定項目です。 設定項目 説明 アクション名 承認アクションの任意の名前 アクションプロバイダー 承認プロセスでは手動承認を選択 SNS トピックの ARN 承認アクションの通知を送るために使用するトピック レビュー用 URL レビュー担当者に提供する URL コメント メールやコンソールでレビュアーに向けて表示出来るコメント内容 変数の名前空間 パイプラインアクションで使用できる変数 AWS CI/CDの各サービスの概要はこちらに少しまとめています。 Logging コンテナのログ出力は、ドライバーにより異なります。 Fargate 起動タイプを使用するタスクの場合、サポートされるログドライバーは awslogs、splunk、awsfirelens です。 EC2 起動タイプを使用するタスクの場合、サポートされるログドライバーは awslogs、fluentd、gelf、json-file、journald、logentries、syslog、splunk、awsfirelens です。 今回は AWSに標準で使用される awslogsとawsfirelensについて記載していきます。 Cloudwatch Logs によるログ運用 awslogsは、コンテナのログをCloudwatch Logsへ転送します。 Cloudwatch Logs に転送されたログをエラーハンドリングする事も、ログストレージとして使用する事も可能です。 使用方法は、Task Definition のコンテナ定義に定義された logConfiguration パラメーターから logDriver:awslogs を指定し、有効化します。タスク定義から作成された各コンテナのログはCloudWatch Logs へ転送されます。 sample6-task-Definition.json { "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "awslogs-wordpress", "awslogs-region": "us-west-2", "awslogs-stream-prefix": "awslogs-example" } }, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "awslogs-mysql", "awslogs-region": "us-west-2", "awslogs-stream-prefix": "awslogs-example" } } } ], "family": "awslogs-example" } Cloudwatch Container Insightsを有効化した場合にも CloudWatch Logsロググループが生成され、転送を行います。サンプルを以下に表示します。 sample7-Cloudwatch-Container-Insights.json { "Version": "0", "Type": "Task", "TaskId": "xxxxxxxxxxxx", "TaskDefinitionFamily": "xxxxxx", "TaskDefinitionRevision": "4", "ClusterName": "fargate-cluster", "AccountID": "xxxxxxxx", "Region": "ap-northeast-1", "AvailabilityZone": "ap-northeast-1d", "KnownStatus": "RUNNING", "LaunchType": "FARGATE", "PullStartedAt": 1643191009843, "PullStoppedAt": 1643191018055, "CreatedAt": 1643190996073, "StartedAt": 1643191019944, "Timestamp": 1643659440000, "CpuUtilized": 0.032220646540323895, "CpuReserved": 256, "MemoryUtilized": 15, "MemoryReserved": 512, "StorageReadBytes": 0, "StorageWriteBytes": 0, "NetworkRxBytes": 0, "NetworkRxDropped": 0, "NetworkRxErrors": 0, "NetworkRxPackets": 129716, "NetworkTxBytes": 4, "NetworkTxDropped": 0, "NetworkTxErrors": 0, "NetworkTxPackets": 30343, "EphemeralStorageReserved": 21.47, "CloudWatchMetrics": [ { "Namespace": "ECS/ContainerInsights", "Metrics": [ { "Name": "CpuUtilized", "Unit": "None" }, { "Name": "CpuReserved", "Unit": "None" }, { "Name": "MemoryUtilized", "Unit": "Megabytes" }, { "Name": "MemoryReserved", "Unit": "Megabytes" }, { "Name": "StorageReadBytes", "Unit": "Bytes/Second" }, { "Name": "StorageWriteBytes", "Unit": "Bytes/Second" }, { "Name": "NetworkRxBytes", "Unit": "Bytes/Second" }, { "Name": "NetworkTxBytes", "Unit": "Bytes/Second" }, { "Name": "EphemeralStorageReserved", "Unit": "Gigabytes" } ], "Dimensions": [ [ "ClusterName" ], [ "ClusterName", "TaskDefinitionFamily" ] ] } ] } ログの転送は、ECS Task Role、ECS Task execution Role上に CloudwatchLogsのアクセス権限を付与する必要があります。 AWS FireLens によるログ運用 FireLensは、コンテナから直接Cloudwatch Logsへ転送せず、FireLensコンテナをTaskへ追加する事でFireLensコンテナを経由したログ送信を行います。FireLensは、CloudWatch Logs への転送経路だけではなく、S3やRedshiftなどにも転送が可能です。 FireLensを使用する場合、ログルーティングとしての機能を果たすため、 Fluentd または Fluent Bitのコンテナイメージを使用する必要がありますが、ECR Public Gallery上にfluent bitのイメージが公開されているため、タスク定義に他のアプリケーション用のコンテナと同梱する事が可能です。 なお、Fluent Bit は、リソース使用率が Fluentd よりも低いとされています。 タスク定義で FireLensの設定を指定する場合、logDriver:awsfirelens を指定して、Name:cloudwatch_logs/kinesis_firehose/kinesis_streamsを指定します。 sample8-task-definition.json "logConfiguration": { "logDriver":"awsfirelens", "options": { "Name": "kinesis_firehose", "region": "us-west-2", "delivery_stream": "my-stream" } } なお、FireLensを使用して出力先を分岐する場合、fluent Bit conf を変更する必要があります。 sample9-firelens.conf [INPUT] Name xxxxx Listen xxxx Port xxxxx [FILTER] Name xxxxxxxx Match xxxx Record xxxxx [OUTPUT] Name firehose Match xxx-firelens* delivery_stream xxx region ap-northeast-1 ECS Task Role、ECS Task execution Role上に各サービスのアクセス権限を付与する必要があります。 Trace コンテナサービスでは、サービス間の通信や、アプリケーションへのリクエストを処理する情報が煩雑します。 X-Rayは、アプリケーションへのリクエストとレスポンスの情報、呼び出しの詳細な情報などを収集し、問題の特定や可視化を行うサービスとなります。 ECS上でX-Rayを使用する場合、FireLens同様にサイドカー構成として、X-rayコンテナをタスク定義にコンポーネントします。 X-ray デーモンからX-rayに対してデータを送信するためには以下の点をクリアにする事で実装が可能です。 デーモンからX-Rayにアクセス許可を与えるには、SDK でAWS認証情報(credentials)を許可します。 ECS Task Roleから、X-rayの書き込み権限を許可する必要があります。 X-ray への到達経路にはVPC エンドポイントが必要となります。 なお、X-ray にはインサイトと呼ばれる機能があります。 インサイトでは、アプリケーションパフォーマンスの異常を自動的に検出します。 これにより、Amazon EventBridge イベントを経由して特定の閾値に対して発生した問題をメッセージレベルで確認する事が出来ます。 今回は、Service Discovery や Appmesh について触れられていませんでしたが、別の機会の記事を作成しようと思います。 参考文献 本記事は、以下の文献を参考とさせていただきました。 AWSコンテナ設計・構築[本格]入門 Amazon Elastic Container Service ドキュメント
- 投稿日:2022-02-01T07:57:32+09:00
AWS認定試験に初めて合格しました。(DVA)
Introduction 本記事は2022年1月現在の情報となります。 最新の情報は、ご自身でAWS認定試験のWebページを参照ください。 きっかけ 学生時代からずっと興味を持っていたAWSの資格試験。その名もAWS認定試験。 試験方法がよく分からず、カタカナもいまいちピンとこず、試験内容にも不安しかなかったため、ずるずると受験を先延ばししてきました。 しかし業務での必然性を感じて、断片的なAWSの知識獲得をやめ、網羅的に学び始めることにしました。ついに重い腰を上げて受験したので、受験体験記という名目で記録を残しておきます。 本記事は、誰かの参考になるかもしれないと思い、筆を取りました。 褒めてください AWS歴:2~3年(ギュッとしたら6ヶ月くらい) 学習期間:1ヶ月(ギュッとしたら1週間くらい) 受験回数:1回 結論 受験した認定試験: AWS Certified Developer – Associate(DVA) 受験方式:ピアソン VUE 点数: 749 / 1000点 合格最低点:720点以上 合格ぎりぎりといった感じでした。 ちなみに、色々と調べてみるとアソシエイト試験の中では、ソリューションアーキテクト試験のアソシエイト(SAA)から受験するのが王道らしいです。 難しいことは分かりません 受験の感想としては、140分で65問も解くのは大変でした。ピアソン VUE 試験方式を選択したため、業務終わりに使い慣れないPCで2時間奮闘するのが、大変でした。1 まずはAWS Certified Developer – Associate(DVA)を合格出来て、よかったです。2 本日のお品書き ・模試が無料になりました。 ・チュートリアルを活用しましょう。 ・[驚愕]AWS試験は日程を変更できる。 対象者 ・AWS認定試験に興味を持っている方 ・1を聞いて10を理解できるエンジニア 非対象者 ・AWS認定試験を受けたことがある方 ・説明下手な筆者を攻撃しようとするエンジニア 自己紹介 自己紹介ページ Let's Start 本記事は2022年1月現在の情報となります。 最新の情報は、ご自身でAWS認定試験のWebページを参照ください。 模試が無料になりました。 今回は試験対策として、主にこちらの記事の模擬試験を利用しました。 自分は数年前に購入した書籍も購入してありましたが、基本的には上記の模擬試験を繰り返し解きました。さらに模擬試験を解いていくなかで、回答時に表示されるドキュメントもたくさん目を通しました。 しかしどうしても選択の根拠がわからない問題に関しては、チュートリアル的なものを通じてきちんと知識として定着させるようにしました。 他には、AWSの動画学習も活用しました。 Exam Readiness: AWS Certified Developer – Associate (Digital) (Japanese) AWS Skill Builder というサイトで上記タイトルを探していただくとAWSのスタッフによるDVA試験相当の解説動画を視聴できます。 こちらの動画コンテンツは合計で2時間程度です。 大まかな説明 -> トピックごとの問題 -> 解説 となっていて、良質なコンテンツでした。 結局手を動かすことが大切。 実際の試験を受けたいま、上記の学習量を振り返ってみると、広く浅く学んだように感じます。 もう少しハンズオンを活用すべきかもしれません。 書籍は今回あまり参照しませんでしたし、今後も参照しないと思います。 理由としては、二点あります。 1. 購入したのが2~3年前と古いこともあって、現在のAWSの実情と異なる点があるかもしれないからです。3 2. ここまでオンライン学習環境が整備されている現状、書籍(オフライン)と公式ドキュメント(オンライン)を行き来するのが億劫だからです。 書籍自体に問題があるわけではありません。あくまで個人の勉強スタイルの問題です。4 様々なチュートリアルを活用しましょう。 様々なチュートリアルがあります。自分が利用したいくつかのチュートリアルを下記に示します。 S3のチュートリアル SQSのチュートリアル SNSのチュートリアル AWSには上記のチュートリアルとは異なり、ユースケースごとにまとまっているドキュメントもあります。 各種ハンズオン:https://aws.amazon.com/jp/getting-started/hands-on AWSに馴染みのない方でも、実際の運用を想定した開発を疑似体験することもできます。 さらに普段使っているようなサービスであっても、全然違う使い方をしている場合もあります。 受験の有無に関わらず、調べてみると面白いと思います。 [驚愕] AWS試験は日程を変更できる。 実は元々二週間ほど前の受験を予定していましたが、直前で不安になり試験日を延期しました。 その際、試験から24時間前だったら、試験日を変更することが出来ます!(2回まで) なんて斬新なシステムなんでしょう! はい。試験の 24 時間前までに試験をキャンセルするか、再度予約することができます。追加料金は発生しません。試験を再度予約またはキャンセルするには、AWS 認定アカウントにアクセスして [PSI 試験の管理] または [Pearson VUE 試験の管理] ボタンをクリックしてください。PSI で予約した場合は、管理したい予約済み試験の [詳細の表示] ボタンをクリックします。Pearson VUE で予約した場合は、[今後の予定] メニューから管理したい予約済み試験を選択できます。予定された試験までの残り時間が 24 時間より短い場合は、試験のキャンセルや再予約を行うことができません。予約した試験当日に出席しなかった場合、受験料は返金対象になりません。欠席した試験時間から 24 時間経過すると、再度申し込みができます。試験を欠席した場合でも、ステータスは「不合格」になりません。 元の予定を立てた後で予定を変更できるのは、2 回のみです。3 回目に予定を変更したい場合は、予定を取り消して、新しい予定を立てる必要があります。予定の制限が新しい予定に適用されます。試験の予約は予約時間の 24 時間前を切るとキャンセルできません。 https://aws.amazon.com/jp/certification/faqs/ To be Continued 終わりに 今後もTwitterでこのような情報を発信しています。興味があったらご覧ください。 大抵はくだらないことです。 Sempleのツイッター タッチパッドでなくマウスを使う。椅子の高さ調整(普段はスタンディングデスク)。試験会場独特の物音。長時間続く緊張感。などなど ↩ どこをどうとればDVAになるのかよく分かってません。略称って難しい。 ↩ 情報が既に古い可能性があるため、わざわざ学ぶ気になりません。 ↩ 資格試験は合格点を超えれば良いと思っている人間なので、点数の多寡には触れないでください。負け惜しみです ↩
- 投稿日:2022-02-01T01:41:43+09:00
ARNって何だ? URIとURNと比較してみる
はじめに ARNってご存知でしょうか? AWSを利用している人なら、何度も目にしていると思いますが、 arn:aws:iam::123456789012:user/Development/product_1234/* こんなものですね。 詳細は、AWSのドキュメントにもあるので、そちらを参照してもらうとして、 「ああ、URIのAWS独自スキームでURNっぽいなぁ」と思いました。 ではURIなのか、URNとどう違うのか?など気になったので、URIとURNと比較して見てみましょう。 その前に少し小話を一つ。Webで検索するとURIとURNと同列にURLが並べられて説明されていますが、URL(Uniform Resource Locators)は技術文書(RFC)では、正式には定義されていません。正確には、RFC1738で規定されていましたが、URIの規定がなされた2005年のRFC3986で更新され、さらにRFC4248とRFC4266の策定によって廃止とされています。ということがRFCを読むと読み取れるので、URLとURIでどっちの言葉使うの?とかモヤモヤしたことがある人は、技術的な正しい定義が必要なところはURIで、それ以外ではコミュニケーションが成り立つならどちらでもいいんじゃないかなというのでよさそうですね。 URIとURNと比較して 以下、RFCの引用とその日本語訳を RFC原文は引用 RFC原文の日本語訳は斜体 という形式で記載していきます。 URIと比較 URIとは、RFC3986のIntroductionに、 A Uniform Resource Identifier (URI) provides a simple and extensible means for identifying a resource. Uniform Resource Identifier (URI) は、リソースを識別するためのシンプルで拡張可能な手段を提供します。 また、同Abstractで、 The URI syntax defines a grammar that is a superset of all valid URIs, allowing an implementation to parse the common components of a URI reference without knowing the scheme-specific requirements of every possible identifier. This specification does not define a generative grammar for URIs; that task is performed by the individual specifications of each URI scheme. URI構文は、すべての有効なURIのスーパーセットである文法を定義し、可能なすべての識別子のスキーム固有の要件を知らなくても、実装がURI参照の共通コンポーネントを解析できるようにします。この仕様ではURIの生成文法は定義されていません。このタスクは、各URIスキームの個々の指定によって実行されます。 とあります。つまり、URIは一般的文法を定義しているだけで、 文法上で表せない詳細な定義や意味は各URIスキーム個別に定義してねと言っています。 スキームって?という話になるかと思いますが、Section 3でURIの構文があります。 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] URIはschemeから始まりコロン: まで、ARNでいうと arn になります。 ちなみに、 hier-part とは?と思う方も居るかもしれません。何の略かの説明がないのですが、文意的に階層を表す Hierarchy(ヒエラルキー) Partではないかと私は想像しています。 さて、スキームについて、RFCのSection 3.1 Scheme にて以下の様に説明しています。 Each URI begins with a scheme name that refers to a specification for assigning identifiers within that scheme. As such, the URI syntax is a federated and extensible naming system wherein each scheme's specification may further restrict the syntax and semantics of identifiers using that scheme. 各URIは、そのスキーム内で識別子を割り当てるための仕様を参照するスキーム名で始まります。このように、URI構文は統合された拡張可能な命名システムであり、各スキームの仕様は、そのスキームを使用する識別子の構文およびセマンティクスをさらに制限することができる。 つまり、URIとしての構文定義の範囲内で、 arn 以下の定義がなされれば、URIのサブセットとして、中身に関わらず解析できたり、URIを知っている人から理解しやすくなります。Parserでも作ろうかと考えることがある場合は気になる話でですね(世の中にいるかどうかは分かりませんが)。 URIの構文定義を少し見てみます。2.2 Reserved Characters を見てみましょう。 URIs include components and subcomponents that are delimited by characters in the "reserved" set. URIには、 「予約済」 セット内の文字で区切られたコンポーネントおよびサブコンポーネントが含まれます。 If data for a URI component would conflict with a reserved character's purpose as a delimiter, then the conflicting data must be percent-encoded before the URI is formed. URIコンポーネントのデータが、デリミタとしての予約文字の目的と競合する場合は、競合するデータをパーセント・エンコードしてからURIを作成する必要があります。 予約語を見てみると、 reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" デリミタ(区切り文字)以外でこれらを用いる場合は、パーセントエンコードしなさいと言っています。ARNでは :(コロン)を resource-specific information の区切り文字に使っていますので、URIの目的と競合しません。また、 resource-type/resource-id と利用している /(スラッシュ)もサブコンポーネントの区切り文字という解釈ができるでしょう。ここまではARNはURIに準拠していそうです。 ただし、最初に示した例のARNだと、 arn:aws:iam::123456789012:user/Development/product_1234/* として、 * (アスタリスク)が書かれていました。これは、URIではsub-delimisとして予約されています。ARNの * は階層化されたこの直下のリソース全ての表現ですので、区切り文字という解釈は難しそうです。URIに従うなら、パーセントエンコードが必要になります。なので、ARNはURI準拠でなく、URI風と考えるべきですね。(だれも準拠なんて言っていないので余計なお世話ですね) ちなみにRFC3986には、 * を含むいくつかの文字が予約語に移動した説明があります。 Section 2, on characters, has been rewritten to explain what characters are reserved, when they are reserved, and why they are reserved, even when they are not used as delimiters by the generic syntax. The mark characters that are typically unsafe to decode, including the exclamation mark ("!"), asterisk ("*"), single-quote ("'"), and open and close parentheses ("(" and ")"), have been moved to the reserved set in order to clarify the distinction between reserved and unreserved and, hopefully, to answer the most common question of scheme designers. 文字に関するセクション2は、総称構文で区切り文字として使用されていない場合でも、どのような文字が予約されているのか、いつ予約されているのか、なぜ予約されているのかを説明するために書き直されました。感嘆符 ("!") 、アスタリスク ("") 、単一引用符 ("'") 、および開き括弧と閉じ括弧 (" ("および") ") は、予約セットに移動されました。これは、予約と未予約の区別を明確にするためであり、スキーム設計者に最もよくある質問に答えるためです。* この説明だけでは私の知識では合点がいく訳ではないのですが、そのような質問があって混乱を生んでいたのかと想像で済ませて置きます。 内容とは関係ないですが、後半の英語の文章はピリオドがなく長い一文ですが、英語力の低い私としては、英文を一回読んで理解することができない類いのもですが、最近の機械翻訳に通した文章は、分割されており読みやすく翻訳されているのがありがたい話ですね。最近の機械学習の翻訳の質の向上は目を見張るものがありますね。(ちなみにRFCの日本語訳のサイトで公開されている翻訳文も意味としては理解できない文章になっていますので、自身で翻訳をかけ直すことをおすすめします) 次はURIのPathについて見てみたいと思います。Section 3 Syntax Componentsには、 The scheme and path components are required, though the path may be empty (no characters). When authority is present, the path must either be empty or begin with a slash ("/") character. When authority is not present, the path cannot begin with two slash characters ("//"). These restrictions result in five different ABNF rules for a path (Section 3.3), only one of which will match any given URI reference. スキームとパスコンポーネントが必要ですが、パスは空 (文字なし) でもかまいません。authorityが存在する場合、パスは空であるか、スラッシュ ("/") 文字で始まる必要があります。権限がない場合、パスを2つのスラッシュ文字 ("//") で始めることはできません。これらの制限により、パス(第3.3章)に対して5つの異なるABNF規則が生成され、そのうちの1つだけが特定のURI参照に一致します。 URIのAuthorityは、パスコンポーネント以下を規定する権限の委任先を表しているので、ARNではAuthorityは定義されていないと考えていいでしょうし、URIの仕様としてもAuthorityがない場合、2つの // で初めてはならないと規定しています。パスコンポーネントとして見た場合、URIのパスの定義としては、説明のように5つ(path-abempty, path-absolute, path-noscheme, path-rootless, empty-path)ありますが、ARNや path-rootless, URNはpath-noschemeだと解釈できそうです。ARNは arn:: という表現が許されているし arn:aws: として2つめの要素で必ずアルファベット始まりで、 URNはurn:NID のNIDがアルファベットはじまりであると定義されています。 ちなみに5つのABNF規則は(厳密ではないですが)簡単に書き下すと以下のようになります。 path-abempty: / 始まりか 空か path-absolute: / は始まりで、 // でない path-noscheme: : でない文字始まり path-rootless: : で始まってもよい empty-path: 文字列なし URNと比較 URNはARNと一文字違いで構文もコロンを区切り文字にしているところがよく似ています。 urn:example:a123,z456 一方ARNのドキュメントでは、 Amazon Resource Names (ARNs) uniquely identify AWS resources. Amazonリソースネーム (ARN) は、AWSリソースを一意に識別します。 と言っています。 一方、URNは、RFC8141のAbstractにおいて、 A Uniform Resource Name (URN) is a Uniform Resource Identifier (URI) that is assigned under the "urn" URI scheme and a particular URN namespace, with the intent that the URN will be a persistent, location-independent resource identifier. Uniform Resource Name (URN) はUniform Resource Identifier (URI) であり、 「urn」 URIスキームと特定のURN名前空間の下で割り当てられます。URNが場所に依存しない永続的なリソース識別子になることを目的としています。 と記載されているように場所に依存しない永続的なリソース識別子を掲げています。 ここで場所って何かを考えると、URLはリソースの置き場所としてホスト名やディレクトリ構造を表していました。しかしリソース(いわゆるWebコンテンツとしてHTMLファイル)などは移動がたやすく、リソースとしては同じなのに、アクセするための場所が変わることを想定せざるをえない仕様となっていました。HTTPレスポンスステータスコード 307 Temprary Redirect や 410 Gone などはまさに移動するリソースのためのレスポンスコードですよね。この場所を表すのではなく、識別子として永続的な名前の定義というのがポイントかと思います。永続的であることが期待できるなら、識別子として広くシステム内で参照しても変更は入らないことが期待できます。ARNのドキュメントに永続的なという表現はないですが、ARNが変わったという話は聞かないので、多分期待はしてもよさそうです。 ARNとURNの構文面で見てみましょう。URNでは、スキーム(先頭のurnという文字列)とNID(コロン区切りの2番目の文字列)は、大文字小文字を区別しません。なので、 urn:examle:a123,z456 URN:EXAMPLE:a123,z456 も同じ識別子ですが、ARNは大文字小文字を区別します。 URNを参考にしつつ、面倒な処理は抑えたいのでこのような仕様になっているのかなとも思いました。ただ、URNが想起されるので、「ARNとスキームを表す arn と partitionをあらわす文字列は大文字小文字を区別します」という説明があった方が親切かなとは思います。 ARN独自 ARNはURIやURNに似た構文を持ちつつも、AWSでリソース表現するために都合よい構文としていると思います。基本的にARNはAWSの都合でシステムから与えられるもので、ユーザーが自身で組み立てる必要はないですが、ユーザーが読んでその階層構造と、表現された文字列で伝えようとしている意味が理解しやすい仕様であると感じます。(URIのheir-partという階層構造という前提が所見でもすっと入って来ているのでしょうね。) 例えば、S3のバケットとその直下にあるリソースを表すARNは、 arn:aws:s3:::my_corporate_bucket/* となりますが、URNに通じるARNが一意にリソースを識別するという理解で見ると、 my_corporate_bucket がawsの partition (ほぼ全てのユーザーにおいてグローバル)のs3に置いてユニーク(な文字列)であると読めます。 account-id が記載されていれば、アカウント内で閉じた識別子なので、衝突よりも外に出ないようにセキュリティを意識する必要があるかもと気を配ったりするのにも役に立ちますね。 最後に ARNは特にURIに準拠と謳っている訳ではないので、URIやURNと比較すること自体意味はないのかもしれませんが、構文がこれらを想起させるので、何がどう違うのかなと見て来ました。似ているところ、違うところなどありましたが、ベースの知識としてURIやURNがあるとより早く理解が進むのではと思います。 RFCなどの文章に慣れていないと、読むのが辛いところもあるとは思いますが、このような文章には仕様の定義の曖昧性をなくすような記述にもなっているので、仕様定義などしようとする人はこのような表現に慣れて置いてもいいのではと思います。また、RFCの更新と統合と再定義の過程を追うことで、複数の仕様を分解したり、共通項を再定義を包含するための定義のあり方を学ぶよい教材だとも思います。 最近では多くのRFCが日本語化されていますが、日本語訳がおかしいこともあるので、常に原文も参照するのがおすすめです。 なお、この文章の英文の翻訳はすべて株式会社みらい翻訳の Mirai Translator® もしくは みらい翻訳社提供の無料翻訳サイト「お試し翻訳」で翻訳された文章を無加工で載せています。
- 投稿日:2022-02-01T00:59:15+09:00
【AWS】VPC同士を接続してみた(VPC ピアリング接続 編)
概要 2つのVPC同士をピアリング接続し、それぞれに起動したEC2からICMP、sshで疎通できることを確認した際の備忘録です。 TransitGatewayを試してみる前段として比較のために作成したため、本記事は2部構成の第1部となります。 VPC ピアリング ってなんぞ?という方はまず以下をどうぞ。 ■VPC ピアリング接続 https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-peering.html スタートとゴール スタート:VPCを2つ作成するところから(今回は同一リージョン内に作成) ゴール:各VPCに起動したEC2間でICMP、sshの疎通を確認するところまで デフォルトの1リージョンに作成できるVPCの数は5つまでです。 既にVPCが存在するアカウント・リージョンで検証する場合は以下を参考に制限緩和のリクエストをしておくとよいでしょう。 ■AWS サービスクォータ https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws_service_limits.html 完成予想図 ざっくり以下のような構成を想定 やってみた 事前準備 まず、お好きなリージョンに以下のように2つのVPCを作成します。 VPC Name IPv4 CIDR my-vpc-01 172.16.0.0/16 my-vpc-02 172.17.0.0/16 このタイミングで各VPCにサブネットも作成しておきましょう。 ※各VPCに最低1つずつあれば十分です。 my-vpc-01 Subnet Name IPv4 CIDR my-vpc-01-public 172.16.10.0/24 my-vpc-01-private 172.16.20.0/24 my-vpc-02 Subnet Name IPv4 CIDR my-vpc-02-public 172.17.10.0/24 my-vpc-02-private 172.17.20.0/24 ピアリング接続の作成 VPCメニューから「ピアリング接続」を選択し、「ピアリング接続を作成」をクリック。 必要項目を入力後、「ピアリング接続を作成」をクリック。 作成後画面に遷移するので、アクションから「リクエストを承諾」をクリック。 確認画面で、内容確認の上「リクエストを承諾」をクリック。 これでピアリング接続は完了。 引き続き各VPCでルートテーブルの設定およびセキュリティグループの作成をしていきます。 ルートテーブルの設定 それぞれのVPCのルートテーブルへ設定を追加します。 送信先は相手のVPCのCIDR、ターゲットは先程作成したピアリング接続を指定します。 セキュリティグループの作成 my-vpc-01 からのICMP及びsshを許可するよう、my-vpc-02 用のセキュリティグループを作成します。 完成! それぞれのVPCにEC2インスタンスを起動し、疎通を確認してみましょう。 my-vpc-01 側のインスタンスにssh接続し、そこから my-vpc-02 側のインスタンスへping、sshが可能になっているはずです。 my-vpc-01 [ec2-user@ip-172-16-10-230 ~]$ ping -c 3 172.17.20.59 PING 172.17.20.59 (172.17.20.59) 56(84) bytes of data. 64 bytes from 172.17.20.59: icmp_seq=1 ttl=64 time=1.88 ms 64 bytes from 172.17.20.59: icmp_seq=2 ttl=64 time=1.88 ms 64 bytes from 172.17.20.59: icmp_seq=3 ttl=64 time=1.86 ms --- 172.17.20.59 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 1.860/1.877/1.886/0.012 ms [ec2-user@ip-172-16-10-230 ~]$ [ec2-user@ip-172-16-10-230 ~]$ ssh -i 〓鍵ファイル〓 172.17.20.59 Last login: Sat Jan 29 15:52:52 2022 from 172.16.10.230 __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| https://aws.amazon.com/amazon-linux-2/ [ec2-user@ip-172-17-20-59 ~]$ 以上、とても簡単にVPC同士を接続することが出来ました。 次回は同様の接続をTransitGatewayを利用して作成してみたいと思います。