MY Scribbling...

AWS Community Hero Masanori YAMAGUCHI の 雑なメモ

The Amazon Builder’s Library "Reliability, constant work, and a good cup of coffee" を読んでみた

The Amazon Builders' Library をご存知でしょうか? re:Invent 2021 においても、新しくリリースされたサービスではありませんが、キーノートで触れられています。

aws.amazon.com

今回は 「Reliability, constant work, and a good cup of coffee」 という記事について取り上げてみたいと思いますが、この記事には、アーキテクチャ図は一切ありません。読み物として書かれています。

Builder’s Library で Architecture タグがついているのに、アーキテクチャ図がないということにとても興味が湧き、読み進めてみたのですが、とても面白かったので感じたことを記録として残しておきます。

aws.amazon.com

ざっくり書くと、エドワードホッパーの「ナイトホークス」という絵画をきっかけに、コーヒーポットがいかにニーズに沿ってシンプルでコスト低でかつ信頼性あるツールなのかというところから、AWSでは信頼性の高いシステムどのように実装しているのか、その設計について解説している話です。

re:Inventをはじめ、日本のカンファレンス、イベントなどの休憩時間に設置されるエンジニアとは馴染み深いコーヒーポット、YAPC::Asiaでは無限コーヒーなど呼ばれていたことを思い出します。やはりエンジニアにコーヒーは必要なのかという点もこの記事を読み始めたきかっけでした。

以下、本題。

Computers: They do exactly as you tell them

システムの信頼性を落とす要因は「不確実性」

信頼性の高いシステムを運用している場合、不確実性が最大の課題。不確実性は障害などによって引き起こされ、結果そしてシステムは高負荷や不安定な状態となり、処理停滞などを発生させる。

コーヒーショップの場合、対応が遅いことによる処理停滞は顧客の待ち行列となるが、システムの場合は物事はシンプルではない。処理停滞はクライアントやバックエンドへの再リクエストによってスパイラル的に影響を拡大する可能性がある。

再リクエスト、過負荷への対応は別の記事がある。(これらの記事も後日で読もうと思う)

Timeouts, retries, and backoff with jitter
https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/

Using load shedding to avoid overload
https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload/

「This is why many of our most reliable systems use very simple, very dumb, very reliable constant work patterns.」

信頼できるシステムはシンプルに一定の処理を提供する。re:Invent 2021のキーノートでWernerが話していたPrimitiveに繋がるのかもしれない。複雑な処理もPrimitiveの組み合わせで実現されるとうことWernerの言葉を思い出す。

信頼性の高いシンプルなシステムは3つの要素で構成される

  • 負荷によってスケールアップや処理遅延しないこと
  • どのような状態でも同じ動作をすること(モードがないと表現されていた)
  • もっとも必要な時にパフォーマンスを向上させること

キャッシュは応答時間を改善するが、キャッシュはキャッシュが存在している時と、存在していない時モードがあると説明されていた。キャッシュが存在していなかったり無効化された場合、システムに対する負荷は存在している時と一定にならないということ。

キャッシュだけを当てにするとキャッシュが効かない状態ではソースとなるシステムに負荷がかかり予期せぬ障害が発生可能性があるかもしれない、これがモードによる影響であることが説明されている。

なお、キャッシュに関する考えはこちらを参照することも記事内で触れられている。

Caching challenges and strategies
https://aws.amazon.com/builders-library/caching-challenges-and-strategies/

Amazon Route 53 health checks and healthiness

ヘルスチェックはとても重要な機能であるということが Route 53 のヘルスチェックをテーマに「モード」「一定の処理を繰り返しおこなうこと」について解説されている。

Route53がヘルチェックのノイズ影響をどのように対応しているか、ヘルスチェッカーによるチェックとその結果をアグリゲーターが条件付けして判定している。ヘルスチェッカーとアグリゲーターはまさに一定の処理を行う「Constant work」に徹している。

ヘルスチェッカーとアグリゲーターはセル設計が採用されていて、新しいヘルスチェック対象が追加されても影響がないように設計されている。各セルで処理できるヘルスチェック数の制限と現在の数を確認していて、制限が近づいたら新しいセルが追加される。

また、アグリゲーターは常に最大サイズのヘルスチェック結果を受け取るようになっている。最大サイズの至らない場合は、ダミーで埋めて常に最大サイズがヘルスチェッカーから送られ、それによって負荷が一定になるように作られている。

ヘルスチェックの対象がAZ障害などで一度に大量のヘルスチェック失敗を返してもヘルスチェックーとアグリゲーターが行う処理は変わらないということが大事な点だと思う。

続いて、ヘルスチェックに失敗した場合の、DNSレコード変更について触れられている。

何万のヘルスチェックが同時に失敗した場合、何万以上のDNSレコード変更が一気に行われる可能性があるが、どのように対応しているのかという点が興味深い。

アグリゲーターは、固定サイズのヘルスチェックステータスを数秒感覚でDNSサーバに送っている。DNSサーバは受信してメモリに保存する。アグリゲーターよりも多いDNSサーバがプッシュを受けれるようにしている。

DNSサーバはクエリに対して、その名前に紐づく全てのレコードを検索して、メモリ内のヘルスチェックステータスと相互参照する。ヘルスチェックのステータスが正常どうかにかかわらず、毎回のヘルスチェックステータスを参照しているので動作が変わらないということがポイント。

モードとは何か、モードが存在しないということの重要性を丁寧に説明されている章だった。

Amazon S3 as a configuration loop

Network Load BalancerはEC2ネットワークに組み込まれているAWS Hyperplaneノード上で実行されている。Network Load Balancerの設定は、Amazon S3上に保存されている構成ファイルによって扱われ、AWS Hyperplaneノード が Amazon S3から設定ファイルをフェッチする。設定変更がされていない場合でも数秒ごとにフェッチして、AWS Hypervisorノードは設定が前回と同じであってもロードする。

これにより、モードは1つで常に最大数の構成変更のロード処理を実行している。設定変更されたロードバランサーの台数による影響は受けない。

構成ファイルも「ダミー」により、最大サイズになっている。

無駄を感じるかもしれないが、とてもにシンプルで複雑な構成を実現するよりも、エンジニアリングコストが最低限に抑えられている。(初期の実装もメンテナンスも) ロードバランサーの機能拡張による影響も受けにくいし、設定変更処理がボトルネックになる可能性が排除されているものだと感じた。

Constant work and self-healing

前述された2つの例は、何かしらの処理失敗があったとしても自己回復を備えている。Constant work Constant work には自己回復が伴う傾向があるということ。

1回目の処理でネットワーク問題などで設定情報が破損した場合、2回目の処理で正常化される。Consitent workはモードを持たないので、常にゼロベースの処理が実行されるため、回復性を備えている。

対照的にワークフローの場合、ワークフローの処理順序、一部の処理でエラーが発生した際の回復処理などをあらかじめ組み込んで置く必要がある。

回復処理がまた動かない時に結果として人が介在しなければいけないし、それはConstant work で継続的なエラーが発生している場合も同じなのだけど、準備にかけるリソースが全く異なるということも伝えているのだと感じた。

Design and manageability

big-O と Constant work の関係性、つまり入力サイズに関係なく、一定数の処理を行うということ。Route 53 、Network Load Balancer においても、ユーザの設定変更量に変わらず、一定数の処理が実行されていることが説明されている。

ただ、懸念する点は、無駄が生じるということ。(コーヒーポットに数百人分のコーヒを入れた結果、飲む人が数人の場合、残りは排水溝行きになると表現されている)

この懸念は構成変更、ヘルスチェックのようなプロパゲーションシステムでは現実にならない。1つのヘルスチェックを伝播することと、多くのヘルスチェックを伝播することによる消費エネルギーのコストはほぼ変わらないため。ピーク時に100台のWebサーバが必要とするシステムに対し、常時100台のWebサーバを用意することは同義ではない。これはサーバ1台あたりのコストと伝播するヘルスチェックとのコスト比較になる。

コスト削減、さらにSutainableであることを考えると、スケーリングを第一に考えてしまうが、スケールアップによる影響が細微な場合は、シンプルな設計を用いた方がコスト低になるということも念頭に置いてアーキテクチャを設計することが必要。

The value of a simple design

シンプルな設計とは、パーツの少なさではない。わかりやすく、使いやすく、オペレーションしやすい設計を指す。(一輪車は自転車よりもパーツが少ないが乗りにくいと例えられている)

そのデザインが、その立ち上げに全く関係ないチームにとっても意味をなすものであれば、それは良いデザインである可能性が高いということも触れられている。

現にAWSでも"ループの中で毎回フルコンフィグレーションを適用する“というコンフィグレーションシステムは意外と多くConstant workは何度も再利用されていると説明されている。

さいごに

今まで考えたことがなかった内容が多く、アーキテクチャを考える上で読んでおいて良かったと思える記事でした。

Builder’s Library は必要になった時に参照することにも使えますが、時間がある時などに読んでみても良いヒントを得られるのでおすすめです。

日本語化されている記事もありますので、AWSがその中で培ってきたアーキテクチャをみなさんもぜひ活用してみてはいかがでしょうか。

aws.amazon.com

【AWS Lambda編】New Relic で サーバーレスアプリケーション をモニタリングする

はじめに

New Relic 初心者の私が AWS Serverless Workshop の1つ AWS Innovator Island にNew Relic を計装することまでの記録を記事として残していきます。

github.com

その初回をCalendar for New Relic | Advent Calendar 2021 - Qiita 21日目として投稿します。

New Relic に対するわたしの知識レベル

  • New Relic のトレーニング受講などの経験なし
  • New Relic のオンラインセミナーに2回ほど参加した(k8sとObservabilityがテーマのもの)
  • New Relic 本と New Relic 公式サイトの情報をもとに進める
  • この記事で New Relic のアカウントをはじめて作成しました!

1. AWS アカウントと New Relic アカウントの接続

New Relic にAWSアカウントのインベントリを作成して、Lambda 関数の CloudWatch メトリクスを収集するため必要な手順

必要なもの

  • AWS CLI v2 がインストールされていて、aws configure などにより profile が登録されていること
  • Python 3.3 以降がインストールされていること
  • newrelic-lambda CLI がインストールされている
    pip3 install newrelic-lambda-cli でインストールできる
  • New Relic アカウントに対して、管理者の役割、またはインフラストラクチャマネージャーのadd-on role が必要(インフラストラクチャマネージャーの add-on role が何かは分からなかった
  • New Relic API ユーザーキー
  • IAM リソース、マネージドシークレット、Lambda関数 を作成するためのアクセス許可を持つIAM ユーザー(プロファイル)
    必要な権限は https://docs.newrelic.com/jp/docs/serverless-function-monitoring/aws-lambda-monitoring/enable-lambda-monitoring/account-linking/ に記載されている
1-1. newrelic-lambdaCLI をインストールする
$ pip3 install newrelic-lambda-cli
1-2. new relic cli を使って AWS アカウントと統合する
newrelic-lambda integrations install --nr-account-id <YOUR_NR_ACCOUNT_ID> \
--nr-api-key <YOUR_NEW_RELIC_USER_KEY>

任意の AWS CLI プロファイルを指定する場合は、--aws-profile オプションをつける

$ newrelic-lambda integrations install --nr-account-id 3XXXXXXX --nr-api-key NRAK-QQQQQQQQQQQQQQQQQQQQQQQQQQQ --aws-profile nr-test

下記のように実行ログが出力される。✨ Install Complete ✨ が出れば AWS アカウントと New Relic アカウントの接続は完了となる

Validating New Relic credentials
Retrieving integration license key
Creating the AWS role for the New Relic AWS Lambda Integration
Waiting for stack creation to complete... ✔️ Done
✔️ Created role [NewRelicLambdaIntegrationRole_3XXXXXXX] in AWS account.
Linking New Relic account to AWS account
✔️ Cloud integrations account [New Relic AWS Integration - 1XXXXXXXXXXXX] was created in New Relic account [3XXXXXXX] with IAM role [arn:aws:iam::1XXXXXXXXXXXX:role/NewRelicLambdaIntegrationRole_3XXXXXXX].
Enabling Lambda integration on the link between New Relic and AWS
✔️ Integration [id=1XXXXXXXX, name=Lambda] has been enabled in Cloud integrations account [New Relic AWS Integration - 1XXXXXXXXXXXX] of New Relic account [3XXXXXXX].
Creating the managed secret for the New Relic License Key
Setting up NewRelicLicenseKeySecret stack in region: ap-northeast-1
Creating change set: NewRelicLicenseKeySecret-CREATE-1XXXXXXXX
Waiting for change set creation to complete, this may take a minute... Waiting for change set to finish execution. This may take a minute... ✔️ Done
Creating newrelic-log-ingestion Lambda function in AWS account
Setting up 'newrelic-log-ingestion' function in region: ap-northeast-1
Fetching new CloudFormation template url
Creating change set: NewRelicLogIngestion-CREATE-1XXXXXXXX
Waiting for change set creation to complete, this may take a minute... Waiting for change set to finish execution. This may take a minute... ✔️ Done
✨ Install Complete ✨

実行結果として、下記の CloudFormation スタックがデプロイされる

  • NewRelicLambdaIntegrationRole
  • NewRelicLicenseKeySecret
  • NewRelicLogIngestion

2. テスト用の Lambda 関数による動作確認

公式手順: https://docs.newrelic.com/jp/docs/serverless-function-monitoring/aws-lambda-monitoring/enable-lambda-monitoring/instrument-example/

独自の Lambda 関数に計装する前にテスト用の Lambda で計装を学べるとのこと。これをスキップすると後でハマりそうなので試してみる。

Node.js、Python、Go、Java、.NET それぞれテスト用の Lambda 関数 があるが、Innovator Islands で使われる Lambda 関数は Node.js なので、今回は Node.js の Lambda 関数 を試してみる。

必要なもの

2.1 デプロイスクリプトの実行

githubリポジトリをクローンする

git clone [https://github.com/newrelic/newrelic-lambda-extension.git](https://github.com/newrelic/newrelic-lambda-extension.git)
cd newrelic-lambda-extension/examples/sam/node

AWS CLI の実行にプロファイル指定が必要な場合は下記のように deploy.sh を修正する

#!/bin/bash

accountId=$1
region=$2
profile=$3

echo "region set to ${region}"

sam build --use-container

bucket="newrelic-example-${region}-${accountId}"

aws s3 mb --region "${region}" "s3://${bucket}" --profile "${profile}"

sam package --region "${region}" --s3-bucket "${bucket}" --output-template-file packaged.yaml --profile "${profile}"

sam deploy \
    --region "${region}" \
    --template-file packaged.yaml \
    --stack-name NewrelicExampleNode \
    --capabilities CAPABILITY_IAM \
    --parameter-overrides "NRAccountId=${accountId}" \
    --profile "${profile}"

AWS CLI の実行にプロファイル指定が必要な場合は下記の引数で deploy.sh を実行する

./deploy.sh <NEWRERICID> <AWS REGION> <AWS CLIのプロファイル>

AWS CLI の実行時にプロファイル指定が必要ない場合は deploy.sh の修正は必要なく、第3引数を除外して deploy.sh を実行する

./deploy.sh <NEWRERICID> <AWS REGION> 

下記のように実行ログが出力され、newrelic-example-nodejs という Lambda 関数がデプロイされる

region set to ap-northeast-1
Starting Build inside a container
Building codeuri: /newrelic-lambda-extension/examples/sam/node/newrelic-example-node runtime: nodejs12.x metadata: {} architecture: x86_64 functions: ['NewRelicExample']

Fetching public.ecr.aws/sam/build-nodejs12.x:latest-x86_64 Docker container image......
Mounting /newrelic-lambda-extension/examples/sam/node/newrelic-example-node as /tmp/samcli/source:ro,delegated inside runtime container

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided

Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
make_bucket: newrelic-example-ap-northeast-1-3XXXXXX
Uploading to 655a6a97cb1410cc550ad7586848d5d1  128736 / 128736  (100.00%)

Successfully packaged artifacts and wrote output template to file packaged.yaml.
Execute the following command to deploy the packaged template
sam deploy --template-file /NR-Lambda/newrelic-lambda-extension/examples/sam/node/packaged.yaml --stack-name <YOUR STACK NAME>

    Deploying with following values
    ===============================
    Stack name                   : NewrelicExampleNode
    Region                       : ap-northeast-1
    Confirm changeset            : False
    Disable rollback             : False
    Deployment s3 bucket         : None
    Capabilities                 : ["CAPABILITY_IAM"]
    Parameter overrides          : {"NRAccountId": "3XXXXXX"}
    Signing Profiles             : {}

Initiating deployment
=====================

Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------
Operation                LogicalResourceId        ResourceType             Replacement
-------------------------------------------------------------------------------------------------
+ Add                    Logs                     AWS::Logs::LogGroup      N/A
+ Add                    NewRelicExampleRole      AWS::IAM::Role           N/A
+ Add                    NewRelicExample          AWS::Lambda::Function    N/A
-------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:7XXXXXXXXXXX:changeSet/samcli-deploy1639833290/7b9bdabd-6dd0-45e8-b377-cc04161b0e44

2021-12-18 22:15:02 - Waiting for stack create/update to complete

CloudFormation events from stack operations
-------------------------------------------------------------------------------------------------
ResourceStatus           ResourceType             LogicalResourceId        ResourceStatusReason
-------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS       AWS::IAM::Role           NewRelicExampleRole      -
CREATE_IN_PROGRESS       AWS::IAM::Role           NewRelicExampleRole      Resource creation
                                                                           Initiated
CREATE_COMPLETE          AWS::IAM::Role           NewRelicExampleRole      -
CREATE_IN_PROGRESS       AWS::Lambda::Function    NewRelicExample          -
CREATE_IN_PROGRESS       AWS::Lambda::Function    NewRelicExample          Resource creation
                                                                           Initiated
CREATE_COMPLETE          AWS::Lambda::Function    NewRelicExample          -
CREATE_IN_PROGRESS       AWS::Logs::LogGroup      Logs                     -
CREATE_IN_PROGRESS       AWS::Logs::LogGroup      Logs                     Resource creation
                                                                           Initiated
CREATE_COMPLETE          AWS::Logs::LogGroup      Logs                     -
CREATE_COMPLETE          AWS::CloudFormation::S   NewrelicExampleNode      -
                         tack
-------------------------------------------------------------------------------------------------

Successfully created/updated stack - NewrelicExampleNode in ap-northeast-1

New Relic One のコンソールから確認すると Instrumental が Yes の Lambda 関数としてデプロイした Lambda 関数が表示されている

f:id:kinunori:20211219193553p:plain

実行時間やエラーレート、コールドスタート、さらにトレースなどの情報がとれた。Insturmental が Yes ではない Lambda 関数の場合、CloudWatch メトリクスとして記録されている情報は確認できたが、コールドスタートやトレースなどの情報は確認できないという違いがあった

手順1で作成された newrelic-log-ingestion という Lambda 関数は実行されていないようで、このLambda 関数の出番は今のところ不明

f:id:kinunori:20211219193608p:plain

次回は Innovator Island の Lambda 関数で New Relic へのテレメトリーデータ送信を計装してみる

AWS公式レポート IPv6 on AWS を読み解いていく

はじめに

re:Invent 前のアップデートにおいても IPv6 に触れる内容が多く、その背景に確かなニーズがあることを考え、2021年10月26日にAWSよりリリースされた IPv6 on AWS レポートを読み解いてみます。

基本的にはIPv6 on AWSの記述に沿うことを前提に記載していますが、IPv6に関する技術を個人的な理解で読み解いている側面もありますので、間違っている内容などあればコメントで教えてもらえると助かります。

本ブログ記事が参照しているオリジナルレポート

IPv6 on AWS(2021年10月26日版)

https://d1.awsstatic.com/whitepapers/IPv6-on-AWS.pdf

IPv6 on AWS

IPv6導入時の注意点

  • ネットワーク制御の再評価: IPv6では、境界線のセキュリティに対するアプローチを再考し、セキュリティ態勢をさらに向上させる設計上の決定を行う機会がある
  • 規模に応じた設計:利用可能なIPv6アドレスが増えたからといって、IPの割り当てや計画を短縮できるわけではない
  • IPv6導入を段階的に進める :ビジネスニーズに焦点を当てて、必要な場所にIPv6を導入し、必要な期間はIPv4IPv6を共存させることができる

IPv6導入の戦略と背景

IPv6導入の背景

  • NATの限界と変換にあたり重複するIPアドレスに対する課題
  • IPv6を採用せざると得ない組織や規制上の義務
  • 政府の政策や業界の規制当局によって義務化されたIPv6エンドポイント
  • モバイルなどIPv6専用ユーザーの増加における利用者損失を回避するためのIPv4/IPv6ネットワークの相互運用
  • パブリックIPv4の枯渇による連続したIPアドレスレンジ割り当ての困難さ
  • 組織内のネットワークが細分化または拡大することによるプライベートIPv4アドレスの枯渇

現時点でIPv6の導入が進んでいるのは、大手インターネットプロバイダ、ネットワーク機器メーカーなど、それ以外の企業における普及率は著しく低い。

理由は、NATやプロキシの普及で多くのグローバルIPv4アドレスを必要としていないこと、プライベートIPv4の組み合わせで組織内のネットワーク構成が実現できていることが挙げられる。

IPv4/IPv6のIPプロトコル間の後方互換性もIPv6採用の障害になっている。

IPv6導入の戦略

IPv6 on AWSドキュメントは、AWSユーザーがIPv6の導入に着手する際、その判断に用いる情報に役立つことも期待している。IPv6導入の戦略は、その導入の背景によって異なる。ここでは主要な4つの背景とそれに対応する採用戦略を記載している。

  • 背景:プライベートIPv4の枯渇
    採用戦略:デュアルスタックネットワークセグメント間でIPv6専用ルーティングを設定し、IPv6スタックを使用した通信を容易にする。デュアルスタックのロードバランサーなど、IPv6IPv4の相互運用層を提供する
  • 背景:パブリックIPv4の枯渇
    採用戦略:デュアルスタックのVPCとサブネットを作成。ロードバランサーやエッジサービスなどのAWSサービスをデュアルスタックモードで構成し、AWSクラウド上に対応するDNSレコードを用意する。オプションとして、IPv4専用またはIPv6専用のデプロイメントでは、IPv4IPv6に別々のエンドポイントを提供する
  • 背景: IPv6のみのネットワークとの相互運用性
    採用戦略:デュアルスタックのVPCを作成し、それを使ってNAT64(IPv4 パケットを IPv6 パケットに変換して転送)の相互運用性レイヤーをホストする。完全なデュアルスタック化は現実的でないことが多いため、相互運用性のあるレイヤーを提供することが望ましい
  • 背景:IPv6が義務付けされたエンドポイント
    採用戦略:デュアルスタックのVPCとサブネットを作成する。ロードバランサーやエッジサービスなどのAWSサービスをデュアルスタックモデルで構成し、AWSクラウド上に対応するDNSレコードを用意する。必要に応じて、IPv4専用およびIPv6専用のスタックで、IPv4IPv6用の別々のエンドポイントを提供する

最終的なIPv4が廃止され、あらゆる場所がIPv6に対応することが目標とされているが、IPv4IPv6は長期で共存することになることが予想される。ビジネス要件に応じて採用の判断を進めることが重要となる。AWSは小規模なステップからIPv6への移行を可能としている。

相互運用性の課題

  • IPv4/IPv6 デュアルスタックモードの運用は、IPv4IPv6の相互運用性に関する多くの問題を快活する反面、管理のオーバーヘッドを生み出す。例えば、各ネットワークスタックごとのセキュリティルールを管理する必要があるため、セキュリティ適用が複雑になる
  • DNSレコードの管理、ルーティングなどの通信に関わるトラブルシューティングなどの管理も発生する

これらはデュアルスタックVPCやロードバランサーなどのAWSサービスが存在する相互運用層の実装・運用に注力することで、相互運用の課題解決の助けになる。

例えば、ロードバランサーを境界としたデュアルスタックを実装することで゙、ネットワーク全体をデュアルスタックにすることを回避できるかもしれない。これにより、既存のネットワークセグメントはほとんどの場合、IPv4で運用を続けることができ、新しいセグメントはIPv6で構築することができる。

AWSクラウドのネットワークにおけるIPv6導入計画

ENI(Elastic Network Interface)は、3つの異なるIPネットワークのモードで動作します。

  • IPv4オンリーモード : リソースはIPv4で通信できますが、IPv6ノードと通信する場合は、相互運用性レイヤーが必要となります
  • IPv6専用モード : リソースはIPv6で通信できますが、IPv4ノードと通信する場合は、相互運用性レイヤーが必要です
  • デュアルスタックモード : リソースは、IPv4IPv6の両方で通信できます。別の相互運用性レイヤーは必要ありません

AWSでのIPv6アドレッシング計画

  • IPv6導入を進める組織にとって最も重要な初期作業の1つとしてIPv6アドレッシング計画の策定がある
  • ほとんどの組織では、IPv4アドレスで構成された既存のAWS環境に並行する形でIPv6が導入されることが予想される
  • IPv4アドレッシング計画は、時間とともにネットワークは成長する傾向がある。計画初期は何ら問題なかったアドレス計画も、その結果として、サブネットとして十分なアドレス空間を確保できていなかったり、連続していないフラグメントなサブネットが構成されることもある
  • IPv4アドレッシング計画をもとにIPv6アドレッシング計画を策定することは、実質的に無限の規模を持つIPv6アドレス空間のメリットを享受できないIPv6アドレッシング計画となってしまう可能性がある

VPCに割り当てられるIPv6アドレス空間

VPCサブネットアドレッシング

  • VPC:/56 IPv6 CIDRブロックを割り当てる。
  • サブネット: /64 のアドレスレンジで固定。

アドレスレンジから見るとVPC内に256のサブネットを作成することが可能なCIDRが割り当てられることとなる

VPCへのIPv6 アドレス 割り当てには2つのオプションがある

  • AWSが割り当てたIPv6 VPCのクラスレスドメイン間ルーティング(CIDR)
  • 独自のIPv6 CIDRブロックの持ち込み(Bring Your Own IPv6 : BYOIPv6)

VPCはユニークローカルアドレス CIDRをサポートしていない

AWSが割り当てたIPv6 VPCのCIDR

  • デフォルトでは、/56 の IPv6 CIDRブロックをVPCアサインする
  • この範囲はVPCによって自動的に割り当てされるため、何かしら組織の定義された基準に基づく形など、カスタムした定義によったIPv6 CIDRブロックの割り当ては行えない
  • 複数のVPCに対して連続したIPv6 CIDRブロックなどの割り当てが必要な場合は、BYOIPv6が必要となる

BYOIPv6 VPC CIDR

  • IPv6アドレス空間を所有している場合は、Bring Your Own IPv6サービスを利用して自身が保有するIPv6アドレス空間AWSアカウントにインポートすることができる
  • 持ってくることができる最小のIPv6アドレス範囲は、AWSがパブリックアドバタイズしているCIDRでは/48、AWSがパブリックアドバタイズしていないCIDRでは/56となる
  • /48のCIDRをインポート後、スペースから/56レンジを同じアカウントの個々のVPCに割り当てることができる。BYOIPに対応していないリージョンもある

IPv6対応のAWSクラウド・ネットワークの設計

Amazon VPCの設計

VPC設計時に考慮される主要なポイントは下記のとおり。

  • 必要なAmazon VPC数と求められる性質
  • Amazon VPCのCIDR範囲とIPアドレスの割り当て
  • パブリック接続用のBYOIP(Bring Your Own IP)
  • サブネットの数と種類
  • 配置するアベイラビリティーゾーン
  • トラフィックパス
  • インターネットからの着信および発信トラフィック
  • ハイブリッド接続
  • VPC間の接続
  • スケーラビリティと拡張性

これらのポイントのほとんどはIPv4IPv6の両方に同じように適用されるが、既存のドキュメントには、ほとんどの場合、IPv4のみの文脈で記載されている。このセクションでは、IPv6に特化した情報を提供することで、これらの既存のドキュメントを補強している。

AWSは、本レポートを最大限に活用するために、まず既存のIPv4中心の資料を読み、その上でこのレポートを活用することを推奨している。

VPCのIPアドレスの割り当て

  • VPCIPv4IPv6 デュアルスタックモードで動作する
  • IPv4IPv6の通信は互いに独立して制御される
  • VPCとサブネットのIPv4サポートは無効化できない(VPCには少なくとも1つのIPv4 CIDRを割り当てる必要がある)
    → 2021年11月23日 にアップデートがあり、IPv6のみのサブネットを作成できるようになった(https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-virtual-private-cloud-ipv6-subnets-ec2-instances/)
  • VPCに複数のIPv4 CIDRを割り当てることは可能だが、IPv6 CIDRは最大1つのみ

f:id:kinunori:20211203105637p:plain
VPCマネージメントコンソール

サブネットアドレスの割り当て

  • 各サブネットに1つの/64 IPv6プレフィックスの割り当てができる
  • 同じVPC内にIPv6を使用するサブネットと使用しないサブネットを混在させることができる

サブネット内のリソースのアドレス割り当ては下記の2つのレベルで行われる。

  • Amazon VPC ENIの構成時
  • リソースのネットワークスタック構成時

Amazon VPC ENIのIPアドレス

VPC内に配置されたENIが必要なリソースの例

ENIには1つ以上のIPv4アドレスとIPv6アドレスを割り当てることができる。IPv6を有効にするために、ENIを追加でリソースにアタッチする必要ない。

  • IPv6が有効なサブネットに配置されたENIは、IPv6アドレスが割り当てられた状態で作成される
  • 割り当てはENIごとに設定することができ、AWSが自動で割り当てるか、サブネットに割り当てたCIDRより未使用のアドレスを指定するか選択できる
  • いずれも割り当てられたアドレスは明示的に変更しない限り、ENIが存在している期間は一定となる

f:id:kinunori:20211203105742p:plain
デュアルスタックVPC構成例

デュアルスタックVPC構成例

リソースのネットワークスタック構成

  • IPv4IPv6の両方について、DHCPによるアドレス設定をサポートしている
  • ドメイン名やDNSサーバーなど設定するDHCPオプションセットも提供(デュアルスタックの場合、オプションセットで利用されるIPアドレスIPv4である必要がる)
  • 既存または移行したワークロードにIPv6を追加しようとしている場合、ホストOSがDHCPv6に対応する必要がある
  • DHCPを使わずに静的にホストOSへIPアドレスを設定することも可能。ただし、ENIに割り当てされているIPアドレスと一致している必要がある(アンチスプーフィングによる強制)

Amazon VPCサービスのサポート

これまでIPv4では 169.254.0.0/16 から公開されていた Amazon VPC サービス。Nitroベースのインスタンスでは IPv6においては IPv6 ULA(ユニークローカルアドレス) を使って提供されている

Instance Metadata Service (IMDS)

Route 53 DNSリゾルバ

  • fd00:ec2::253DNSリゾルバにアクセスできる

NTPサーバ

  • fd00:ec2::123 でNTPサーバにアクセスできる

Amazon VPC IPv6接続オプション

ここでは下記のオプションに触れている

  • VPCピアリング
  • AWS トランジットゲートウェイ
  • AWSプライベートリンク
  • VPCのサブネット共有

VPCピアリング

  • ピアリング自体はIPプロトコルに依存しない。
  • 到達可能なルートテーブル(プレフィックスに関するサブネットのルートテーブル)が必要
  • 同じピアリング内では、IPv4IPv6の両方のプレフィックスがルーティングされる。

f:id:kinunori:20211203105810p:plain
デュアルスタック VPCピアリング

AWSトランジットゲートウェイ

  • トランジットゲートウェイのアタッチメントは、IPプロトコルに依存しない
  • IPv6をサポートするには、アタッチメントが使用するENIにIPv6が割り当てられている必要がある

既存のVPCにトランジットゲートウェイのアタッチメントを使用してを導入する場合は、ENIにIPv6アドレスが自動的に割り当てられないため、明示的に設定する必要がある。

f:id:kinunori:20211203105841p:plain
デュアルスタック トランジットゲートウェイ

デュアルスタック トランジットゲートウェイ

以下のリソースにトランジットゲートウェイにアタッチできる

  • VPC
  • 1つまたは複数のVPN接続
  • 1つまたは複数のAWS Direct Connectゲートウェイ
  • 1つまたは複数のTransit Gateway Connectのアタッチメント
  • 1つまたは複数のトランジットゲートウェイのピアリング接続

AWSトランジットゲートウェイコネクトのIPv6対応アタッチメント

3rdパーティーの仮想アプライアンスとトランジットゲートウェイ間の接続とダイナミックルーティングを確立するトランジットゲートウェイコネクトは IPv6 も対応している。

f:id:kinunori:20211203105922p:plain
トランジットゲートウェイコネクト デュアルスタック IPv6 ルーティング

AWSプライベートリンク

  • AWS PrivateLink は現在、IPv6 をサポートしていない
  • プライベートリンクへの通信はIPv4を利用し、その他の通信はIPv6を利用するデュアルスタックの構成は実現可

f:id:kinunori:20211203105959p:plain
デュアルスタックシナリオにおけるAWSプライベートリンク

VPCシェアリング

  • デュアルスタックサブネットは、IPv4サブネットのみ共有できる
  • IPv6のリソースは共有されていないサブネットと同じ扱いとなる

Amazon VPCのインターネットアクセス

インターネットで到達可能なIPv6リソース

  • VPC内におけるIPv6はグローバルアドレスであるため、Elastic IPアドレスは不要
  • Amazonで割り当てられたIPv6アドレスは自動的にアドバタイズされる(BYOIPv6の場合はオプション)
  • サブネットのルートテーブルにインターネットゲートウェイ(もしくはEgress-Onlyインターネットゲートウェイ)がアタッチされていればインターネットへの到達性を持つ

ハイブリッド接続

ハイブリッド接続は下記の2つの方法がある。

  • AWS Direct Connect
  • AWSマネージド Site-to-Site VPN

AWS Direct Connect

  • 物理接続、アグリゲーション、VLAN、ジャンボフレームなど多くのダイレクトコネクトの設定はIPv4アドレス利用時と変わらない
  • IPv6アドレス利用時においては、ダイレクトコネクトサービスのうちVIFとBGPピアリングのアドレス設定と構成はIPv4アドレス利用時と異なる
  • VIFは、プライベート、トランジット、パブリックの3タイプがあ

既存のVIFにIPv6を導入しても、VIFの再構築や新しいVIFを導入する必要はない

トランジットとプライベートVIFのIPv6ピアリング

  • ポインツーポイントのアドレスをAWSが自動的に割り当てる
  • 各VIFのCIDRは/125であり、カスタムIPv6アドレスを指定することはできない

AWSからのIPv6プレフィックスの広告

  • ダイレクトコネクトゲートウェイを仮想プライベートゲートウェイ(VGW)に接続する場合、「許可されたプレフィックス」で明示的に値を設定する必要がある(::/0は設定できない)
  • 「許可されたプレフィックス」を設定しない場合、全てのアドバタイズがブロックされる

AWSへのIPv6プレフィックスの広告

  • オンプレミスからAWSへのプレフィックスのアドバイスIPv6固有の制限はない(Direct Connectのクォータは除く)
  • アドバタイズされたプレフィックスは自身のAWSネットワーク内でのみ使用される

パブリックVIF IPv6ピアリング

  • BGPピアリング用のアドレスをAWSが自動的に割り当てる
  • CIDRは/125であり、カスタムIPv6アドレスを指定することはできない
  • ただし、ピアリング上で通信するには独自のIPv6プレフィックスを使用する必要がある(自動的に割り当てられるのはBGPピアリング用のIPアドレスのみ)

IPv6では、作成時にIPv6プレフィックスを所有・指定する必要があり、所有を証明可能になっていない場合はVIFのプロビジョニングに失敗する

パブリック、プライベートまたはトランジットVIF上でのIPv6のルーティング

  • パブリックVIFのピアリングでは、VPCのCIDRを含むサマリープレフィックスを受信する
  • パブリックVIFとプライベート/トランジットVIFを併用する場合、どちらのVIFも同じVPCプレフィックスを受信する
  • 異なるVIF上でトラフィックの対称性を確保できるようカスタマーデバイス側でルートフィルタリングを考慮する必要がある

AWSマネージド Site-to-Site VPN

  • Transit Gateway VPNアタッチメントで終端するIPsecトンネルに対してのみ、IPv6をサポートしている

カスタマーゲートウェイ

  • AWSIPsecトンネル内でIPv6をサポートしているが、基本的な接続はIPv4を介して行われるため、AWSとカスタマー側のVPN終端デバイスの両方が、パブリックIPv4アドレスで指定できる必要がある

VPN接続

  • ダウンロード可能なIPsec用の設定は、現時点(2021年10月23日 IPv6 on AWSレポート公開時)でIPv4のみサポートしている
  • ダウンロード可能なIPsec用の設定は、利用者がカスタマーゲートウェイのデバイス固有の設定を考慮し、IPv4特有の設定をIPv6特有の設定に置き換える形であれば利用可能
  • IPsec Phase 2 のスコープに LOCAL, REMOTE IPv6 ネットワークCIDRを使用する場合、P2PのIPをCIDRブロックに含める必要がある
  • VPNの両側でfd00::/8を使用する場合にのみSAスコープを区切ることができ、一意ではないローカルアドレスを使用する場合はSAを ::/0 としてネゴシエートを許容する必要がある
  • BGPピアリングを確立するためには、AWS側のトンネルを指すスタティックルートを定義する必要がある

IPv6のためのDNSの設計

エイリアスレコード

  • エイリアスレコードのターゲットとしてAAAAレコードをサポートしている

パブリックIPv6DNS解決

  • AレコードとAAAAレコードの両方を持つRoute 53パブリックホストゾーンを使用できる
  • IPv6サービスのヘルスチェックをサポートしている

VPC内のDNS解決

  • NitroベースのIPv6ホストではfd00:ec2::253 でDNSゾルバに接続可能
  • VPCに関連付けられたプライベートホストゾーンと任意のリゾルバルールが提供される

プライベートDNS解決

  • プライベートホストゾーンはAAAAレコードをサポートしている

IPv6のセキュリティとモニタリング

ネットワークレベルのアクセスコントロール

  • セキュリティグループ、ネットワークACLともにIPv4/IPv6に対応している

VPCフローログ

  • IPv4と同じようにIPv6トラフィックに関する情報を取得可能
  • ENIが複数のIPアドレスを持っていて、トラフィックセカンダリIPv6アドレスに送信されている場合、VPCフローログのデフォルトフォーマット内の「dstaddr」フィールドにはプライマリのIPv6アドレスが表示される(回避するにはカスタムフォーマットのログで「pkt-dstaddr」を使用する)

VPCトラフィックミラーリング

AWS Web Application Firewall

Web ACL

  • IPv6アドレスやアドレス範囲などの条件でWebリクエストをブロックできる
  • 0.0.0.0/0と ::/0を除くすべてのIPv4IPv6のCIDR範囲をサポートしている

AWSシールド

  • IPv4IPv6で動作し、双方のアドレスでサービスのパフォーマンス、スケーラビリティ、可用性に影響はない

AWSネットワークファイアウォール

AWSシステムマネージャー

  • AWS Systems Managerで管理されるリソースは、Systems ManagerのエンドポイントへのIPv4接続が必要
  • たとえば、Systems Manager Session Managerを使用してEC2インスタンスに接続するには、インスタンスがデュアルスタックを実行している必要がある
  • インターネットまたはVPC エンドポイントへIPv4の接続性がなければ使用できない

拡張性をもつAWSにおけるデュアルスタックネットワークデザイン

Elastic Load Balancing

  • IPv6をサポートするには、アプリケーションロードバランサーまたはネットワークロードバランサーを「デュアルスタック」IPアドレスタイプで構成する
  • デュアルスタック IP アドレスタイプでは、ロードバランサーのDNS 名が IPv4IPv6 の両方のアドレスを提供し、それぞれ A レコードと AAAA レコードが作成される

ELBのIPv6サポート一覧表やターゲットホストへのIPv6アドレス情報の出力など制限事項が記載されているが、IPv6 on AWSレポートがリリースされた後の下記アップデートでサポート状況が更新されている。

2021年11月23日 のアップデートで アプリケーションロードバランサー とネットワークロードバランサーのエンドツーエンドの IPv6 通信がサポートされた (https://aws.amazon.com/jp/about-aws/whats-new/2021/11/application-load-balancer-network-load-balancer-end-to-end-ipv6-support/)

AWS Global Accelerator

  • 現時点(2021年10月23日 IPv6 on AWSレポート公開時)で、AWS Global Accelerator は IPv6 のデュアルスタック実装をサポートしていない。

Amazon CloudFront

  • クライアントからCloudFrontのエッジロケーションまで、IPv4IPv6の両方をサポートしている
  • エッジロケーションは、エンドユーザーにIPv6でネイティブに応答する
  • クライアントは、IPv4IPv6のどちらを使用していても、同じコンテンツと同じセキュリティ、可用性、パフォーマンス、スケーラビリティを受けることができる
  • オリジンサーバーとの通信はIPv4のみとなる

f:id:kinunori:20211203110148p:plain
Amazon CloudFront デュアルスタック

アドバンストなデュアルスタックネットワークデザイン

AWS トランジットゲートウェイ コネクトアタッチメント

  • トランジットゲートウェイ コネクトは、GREトンネル上で MP-BGP(Multi-protocol BGP)をサポートしている(アドレスファミリーと呼ばれる)
  • アドレスファミリーにより、複数のネットワークプロトコルのルーティング情報を伝送できる
  • これにより既存のトンネルに対して後からIPv6をに追加できる
  • SD-WAN仮想アプライアンスをAWS Transit Gatewayにネイティブに統合することで各ブランチの接続を簡素化するソリューションに対して、トランジットゲートウェイ コネクトがMP-BGPをサポートすることでIPv4からIPv6の移行をシンプルにする

参考:Integrate SD-WAN devices with AWS Transit Gateway and AWS Direct Connect(https://aws.amazon.com/jp/blogs/networking-and-content-delivery/integrate-sd-wan-devices-with-aws-transit-gateway-and-aws-direct-connect/)

インターネットのアウトバウンドをIPv6で集中管理

  • IPv4と同じようにアウトバウンドトラフィックを一元化するパターン
  • IPv6-to-IPv6 Network Prefix Translation(NPTv6またはNAT66)と呼ばれる技術を用いたIPv6によるトランスペアレントプロキシを使用するアプローチ
  • OSやアプリケーションで明示的に設定されたフォワードプロキシを使用するアプローチ
  • Transit GatewayでEgressをつかさどるVPCに転送され、NAT66もしくはフォワードプロキシを介してインターネットへトラフィックが送信される

f:id:kinunori:20211203110055p:plain

IPv6でトランジットゲートウェイを使用してIPv4アドレスのオーバーラップを回避する

  • トランジットゲートウェイIPv4アドレスのCIDRが重複しているVPCを接続できる
  • ただし、ルートテーブルは競合するルートを保持することはできない
  • IPv6プレフィックスがグローバルな特性を利用し、IPv4 CIDRが重複しているVPCに存在するホストの接続を提供する

f:id:kinunori:20211203110307p:plain
IPv6のみルーティングするトランジットゲートウェイ

補足

本記事の元となるレポート(IPv6 on AWS: https://d1.awsstatic.com/whitepapers/IPv6-on-AWS.pdf)は、2021年10月26日 に公開されています。

2021年11月にIPv6に関する複数のアップデートがあり、該当のレポートに記載されている制限事項がいくつか解消されている。

今後も、IPv6に関するアップデートが随時提供される可能性があるため、本記事にならびに本記事の元となるレポートを参考とする際は、記載されている制限事項が解消されているかAWSのアップデート情報を確認することを推奨します。