Amazon VPC勉強メモ

・ネットマスクは/28(14IP)-/16の範囲で利用可能
サブネットで利用できないIP
1. ネットワークアドレス(.0)
2. VPCルータ(.1)
3. Amazonが提供するDNS(.2)
4. AWSで予約されている(.3)
5. ブロードキャストアドレス(.255)

・VPC作成後はVPCアドレスブロックは変更できない

・同一リージョン内のAZは高速専用線でつながっている。リージョン間はインターネット経由

ネットワークACL(アクセスリスト)でネットワークレベルでのセキュリティソフトを設定

ENI(Elasticネットワークインターフェース)
EC2で利用するネットワークの仮想インターフェース
EC2ごとにENIを複数持つことが可能
下記の情報をENIに紐づけて維持可能
1. プライベートIP(固定の設定可能)
2. Elastic IP
3. MACアドレス
4. セキュリティグループ

Floating IP
サーバに障害が起こった際に、ENIを維持して対応する
※VPCではサブネットを超えてアドレスを付け替えることができない点に注意
参考URL:https://goo.gl/JKphCj

サブネット内のDHCP
サブネット内のENIにIPを自動割り当て
※プライベートIPを固定にした場合はDHCP経由で該当のIPが割り当てられる

・VPCで使えるAmazonが提供するDNS
169.254.169.253
VPCのネットワーク範囲のアドレスに+2をプラスしたIP

プライベートホストゾーン
VPC内のインスタンスのみ参照可能。Route53のプライベートホストゾーンを利用

インターネットゲートウェイ(IGW)
VPC内のリソースにインターネットの接続を提供。VPCにアタッチする
単一障害店や帯域幅のボトルネックはない

メインルートテーブルカスタムルートテーブル
メインルートテーブル:VPCを作成したときに自動的に割り当て
カスタムルートテーブル:任意で作成したルートテーブル。メインに変更することも可能

パブリックサブネットの設定
自動で割り当て:サブネットに自動割り当てを設定
固定で割り当て:Elastic IPをアタッチ

Elastic IP
費用がかかるのは下記の場合
1. 追加でEIPを利用する場合
2. 起動中のEC2インスタンスに割り当てられていないとき
3. アタッチされていないENIに割り当てられている場合
4. 1ヶ月でリマップ(割り当て、取り外し)が100回を超えた場合

NATゲートウェイ
プライベートサブネットのリソースがインターネットに通信するために必要
AZごとに設置するのがベストプラクティス

VPCエンドポイント
プライベートサブネットからS3バケットにアクセス可能
S3アクセスのためにIGWNATインスタンスが不要

バーチャルプライベートゲートウェイ(VGW)
オンプレミスとのVPN接続のためのエンドポイントとなる仮想ルータ。VPC側
単一障害点や帯域幅のボトルネックはなし

カスタマゲートウェイ(CGW)
オンプレミス側。AWSとのVPN接続のため

VPN接続
VGWCGW間でIPsecトンネルが設定

・VPC Peering

2 つの VPC 間でトラフィックをルーティングすることを可能にするネットワーク接続
https://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-peering.html

ネットワーク接続の最大送信単位 (MTU)に注意。VPC Peeringは1500

異なるAWSアカウントでも可能
但し、異なるリージョン間では使用できない

セキュリティグループ
仮想ファイアウォール
1つのEC2で5つのセキュリティグループが設定可能
デフォルトですべての通信は禁止
VPCぴあリング先のセキュリティグループが設定可能

ネットワークACLVSセキュリティグループ
ネットワークACL:サブネットレベルで効果。ステートレスなので戻りのトラフィックも明示的に許可設定
セキュリティグループ:サーバーレベルで効果。ステートフルなので戻りのトラフィックは気にしなくてよい

・オンプレミスとのハイブリッド構成
Direct Connectを使用する
VPCからオンプレミスへの通信をするためには、各サブネットのルートテーブルの設定が必要
宛先:オンプレミスのIP
ターゲット:VGWのID
VPNとDirect Connectで冗長可能。Direct Connectが優先

・VPC設計
アプリケーション/監査/フェーズ(本番/検証/開発)/部署などによる分割

VPC Flow Logs
ネットワークトラフィックをキャプチャ氏、CloudWatchへPublishする機能
ネットワークインターフェースを送信元/送信先とするトラフィックが対象
CloudWatch Logsの標準料金のみ課金
VPC Flow Logsで取得できない通信
1. Amazon DNSサーバへのトラフィック

・VPCのリミット
リージョン当たりのVPCの数:5
VPC当たりのサブネット:200
AWSアカウント当たり1リージョンのEIP:5
ルートテーブルあたりのルートの数:100
VPCあたりのセキュリティグループの数:500

参考URL:
http://kakakakakku.hatenablog.com/entry/2016/08/07/232305
https://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-online-seminar-2016-amazon-vpc

続きを読む

AWS再入門2018 Amazon VPC(Virtual Private Cloud)

AWS再入門2018 Amazon VPC(Virtual Private Cloud)編 | Developers.IO · こんにちは。池田です。某音声操作デバイスの購入招待メールを申し込んでから何日経ったのかは考えないことにしました。 はじめに 今回はAWS再入門2018シリーズとして、Amazon VPC(Virtual Private C…続きを表示loud)について公式サイト … 続きを読む

ZendeskのチケットデータをAmazon Elasticsearch Serviceへ自動的にアップロードする | Developers.IO

Amazon Elasticsearch ServiceはAmazon VPCプライベートサブネットに作成; Amazon API Gateway経由でAWS Lambdaを実行させる; Zendeskの自動化とwebhookでAmazon Elasticsearch Serviceへデータを入れるまでを自動化する; Amazon Elasticsearch Serviceへ入れるデータスキーマ … 続きを読む

matsuu : “読み応えある / https://dev.classmethod.jp/cloud/aws/rei…” – mstdn.jp

IO. 【読んでみた】Amazon VPCを保護するためのベストプラクティス #reinvent #NET309 | Developers.IO. はじめに こんにちは、佐伯です。 私はre:Invent 2017に参加していないので、レポートではなく「読んでみた」という形で以下ワークショップのスライドをGoogle翻訳を駆使して読んでみました。所々にAWSドキュメ […]. 続きを読む

ある程度の規模で運用するAWS CloudFormationの勘所

概要

インフラエンジニアとしてAWS基盤の構築・運用に携わって早1年が経ちました。
今回は自分がCloudFormationを運用する中で培ってきたノウハウや勘所をご紹介したいと思います。

なお、これがCloudFormationのベストプラクティスだとかそんなことを言うつもりはなく、
あくまで自分がこう考えてきたぞというものなので、ご参考程度にお願いします。
いろんな考え方があると思いますので、ぜひマサカリコメントお待ちしてます。

どの程度の規模で運用してきたか?

サービスとしてはビッグデータ分析プラットフォームのようなものを構築しておりますが、
AWSの規模感としては大体こんな感じです。

  • AWSアカウント:2

    • 1つは開発環境・内部結合環境用
    • 1つはステージング環境、本番環境用
  • 環境数:5
    • 開発環境
    • 内部結合環境
    • ステージング環境1
    • ステージング環境2
    • 本番環境
  • 利用しているAWSサービス:約15サービス
    • Amazon VPC
    • Amazon EC2
    • Amazon RDS
    • Amazon ElastiCache
    • Amazon S3
    • Amazon DynamoDB
    • Amazon CloudWatch
    • Amazon SNS
    • Amazon Cognito
    • Amazon Route53
    • AWS Lambda
    • AWS IAM
    • Amazon Kinesis
    • AWS WAF
    • AWS CloudTrail
  • 基盤担当者:2~3名
  • CloudFormation テンプレートステップ数:約80KStep

CloudFormationの適用範囲

さてCloudFormationを利用するにあたって、どのAWSリソースをCloudFormationで管理すべきでしょうか?
個人的には「可能な限り全て」を推奨しています。
「可能な限り全て」というのは、「EC2のキーペア登録などCloudFormationでは管理できないもの、新規サービス等でCloudFormationが対応していないものを除き、CloudFormationで構築可能なAWSリソースの全て」という意味です。

AWSの利用サービスが多いほど全てに対応するのは大変に思えるかもしれません。
しかし管理方法(AWS CLI, CloudFormation, 管理コンソールなど)がバラバラになるよりかは遥かに混乱せずミスも防げます。
特にCloudFormationで作成したリソースをCloudFormation以外で更新・削除してしまうと整合性が取れなくなり、最悪CloudFormationの運用ができなくなってしまうので、そのような事故を避けるという意味でも原則CloudFormationに統一することをお勧めします。

1つの技術要素に統一しておけばキャッチアップコストも低くなるでしょう。

テンプレートフォーマット

テンプレートのフォーマットはJSONとYAMLが選択できますが、これは可読性の観点から「YAML一択」です。
もともとJSONのみのサポートでコメントが書けない等の問題がありましたが、2016年9月のアップデート1でYAMLがサポートされるようになりました。

既にJSONフォーマットのテンプレートを利用している場合でも、CloudFormationデザイナーを利用してコンバート可能なので積極的にYAMLフォーマットを利用しましょう。

ディレクトリ/ファイル構成

ある程度の規模のAWSリソースを管理することが想定される場合、事前にディレクトリ構成やファイル構成をしっかり考えておかないと管理が非常につらくなってきます。

特にファイル構成(1テンプレートファイルに何のAWSリソースを含めるか)は、1度スタックを作成してしまうと後から容易に変更ができないため重要です。

ディレクトリ構成

適切なファイルの構成を考えるためには、適切なディレクトリ構成を考える必要があります。
開発者や運用者がテンプレートファイルを管理しやすい構成が望ましいでしょう。

筆者のチームでは「AWS契約単位」、「環境単位」、「システム or サブシステム単位」にディレクトリを分割することを推奨 2しています。

ディレクトリ構成例
cloudformation
├─ aws-000000000000              # AWSアカウントID[000000000000]のリソースのテンプレートを格納
│  ├─ common                     # 環境共通的なリソースのテンプレートを格納(IAM設定, CloudTrail設定など)
│  │  ├─ iam.template
│  │  ├─ cloudtrail.template
│  │  ├─ …
│  │
│  ├─ production                 # 本番環境のリソースのテンプレートを格納
│  │  ├─ common                  # 本番環境のシステム/サブシステム共通的なリソースのテンプレートを格納  
│  │  │  ├─ network.template
│  │  │  ├─ s3.template
│  │  │  ├─ dns.template
│  │  │  ├─ …
│  │  │
│  │  ├─ systemA                 # 本番環境のAシステム/サブシステムのリソースの/テンプレートを格納
│  │  │  ├─ composite.template
│  │  │  ├─ …
│  │  │
│  │  ├─ systemB                 # 本番環境のBシステム/サブシステムのリソースの/テンプレートを格納
│  │  │  ├─ …
│  │  │
│  │  ├─ …
│  │
│  ├─ staging1                   # ステージング1環境のテンプレートを格納
│  │  ├─ …
│  │
│  └─ staging2                   # ステージング2環境のテンプレートを格納
│     ├─ …
│
└─ aws-111111111111              # AWSアカウントID[111111111111]のリソースのテンプレートを格納
   ├─ …

ファイル構成

ディレクトリ構成が決まるとファイルの構成が概ね見えてきます。
上記のディレクトリ構成に基づくと、1つのテンプレートファイルに複数環境のAWSリソースが存在したり、複数システムのAWSリソースが存在したりするということはあり得ません。

仮に1テンプレートファイルに本番とステージング環境のAWSリソースが混在する場合を考えてみましょう。
ステージング環境のAWSリソースを更新する際は、必然的に本番環境のAWSリソースを含むスタックを更新することになります。仮に本番環境のAWSリソースに変更を加えていないとしても、精神衛生上よろしいものではありませんね。
事故を未然に防ぐという意味でも、最低限「環境単位」、「システム or サブシステム単位」にディレクトリを分割することは有効です。

ではディレクトリ内のファイル単位についてはどう考えるべきでしょうか。
ここで考慮すべきはAWSリソース間の依存度AWS管理者の単位です。

AWSリソース間の依存度

  • 互いに依存度の高いAWSリソースは同一テンプレートで管理すべきです。
    別テンプレートで管理してしまうと、AWSリソース間の依存関係を人が意識してスタックの作成・更新・削除を行わなければなりません。これはAWSに熟練した人ならまだしも、通常は容易なことではありません。
     
  • 互いに依存度の低いAWSリソースはテンプレートで管理すべきです。
    そうすることでスタックの作成・更新・削除時の影響を極小化することができます。(他のリソースをうっかり更新して事故を起こす可能性がなくなります。)

AWS管理者の単位

  • 例えばアカウント(IAM)管理者、データベース(RDS)管理者といったようにAWSのリソースに対して管理者が分かれている場合は、権限制御の観点から1テンプレートファイルに含めるリソースを判断したほうがよいでしょう。

筆者の経験上、上記のディレクトリ構成に基づくのであれば、ディレクトリ配下のAWSリソースは1テンプレートファイルにまとめてしまったほうが運用しやすいです。
実際system系のディレクトリ配下は各種AWSリソース(ALB, EC2, RDS, SecurityGroup, IAMRole, InstanceProfile etc..)をcomposite.templateにひとまとめにしており、分割しているのはcommonディレクトリに含まれるIAM(ユーザ・グループ)、CloudTrailなど明確に他のAWSリソースとの結合度が低いもののみとなっております。

テンプレートの共通化

ここまで読んでいただいた方は「テンプレートの共通化をしないのか?」と思われるかもしれません。

公式ドキュメントのAWS CloudFormationのベストプラクティスでも紹介されていますが、テンプレートファイルはパラメータを利用することによって共通化することが可能です。
同じコンポーネントを宣言する共通パターンを共通テンプレートとして再利用することで、ダブルメンテを防ぐことができます。

しかしながら、筆者はテンプレートの共通化は極力しないほうがむしろメンテナンス性は高いと考えています。

1. 可読性が低い

共通化をしようとすればするほど、各種リソースの設定値をパラメータ化して、外部から値を受け取るようになります。極端な例ですがEC2インスタンスを作成するテンプレートを共通化すると下記のようになります。
パラメータを利用しているため、具体的に何の値が設定されているかは管理コンソールや呼び出し元の親テンプレートを参照しないとわかりません。

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  ImageId:
    Description: EC2 ImageId
    Type: String
    Default: ""
  InstanceType:
    Description: EC2 InstanceType
    Type: String
    Default: ""
  AvailabilityZone:
    Description: EC2 AvailabilityZone
    Type: String
    Default: ""
  InstanceInitiatedShutdownBehavior:
    Description: EC2 InstanceInitiatedShutdownBehavior
    Type: String
    Default: ""
  DeviceName:
    Description: EC2 DeviceName
    Type: String
    Default: ""
  VolumeType:
    Description: EC2 VolumeType
    Type: String
    Default: ""
  VolumeSize:
    Description: EC2 VolumeSize
    Type: String
    Default: ""

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      AvailabilityZone: !Ref AvailabilityZone
      InstanceInitiatedShutdownBehavior: !Ref InstanceInitiatedShutdownBehavior
      BlockDeviceMappings:
        - DeviceName: !Ref DeviceName
          Ebs:
            VolumeType: !Ref VolumeType
            VolumeSize: !Ref VolumeSize
      # 省略

共通化をしない場合、下記のようにパラメータを利用せず設定値をベタ書きする形になります。
似たような記述を繰り返し書くことになりますが、実際のリソースとテンプレートの定義が1対1で定義されており、設定値が一目でわかります。

AWSTemplateFormatVersion: 2010-09-09
Resources:
  EC2Instance001:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-da9e2cbc
      InstanceType: t2.micro
      AvailabilityZone: ap-northeast-1a
      InstanceInitiatedShutdownBehavior: stop
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: 100
            VolumeSize: gp2
      # 省略

  EC2Instance002:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-da9e2cbc
      InstanceType: t2.large
      AvailabilityZone: ap-northeast-1c
      InstanceInitiatedShutdownBehavior: stop
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: 200
            VolumeSize: gp2
      # 省略

2. 修正に伴う影響範囲が大きくなる

共通化できると考えていたとしても後から「この環境だけ、もしくはこのリソースだけ個別に変更を加えたい」というようなことは往々にして発生します。
共通テンプレートを修正する場合は影響を受けるリソースを常に意識しなければなりません。
最悪、共通化したテンプレートの中でConditionによる条件分岐を行うなど、負の遺産を生み出しかねません。

3. 変更プレビューにてネストされたスタックの変更分が参照できない

これは親テンプレートを用意してその中で共通テンプレートを利用する場合に発生する問題となります。
管理コンソールからCloudFormationを実行する場合、実行前に「変更のプレビュー」として、差分を確認できますが、親スタック(テンプレート)の更新を行う場合、子スタック(テンプレート)の詳細な変更分は見ることができません。

Changes.png

仮にテンプレートファイルの差分を事前に別の方法で確認していたとしても、これは精神衛生上非常によくありませんし、思わぬ事故を引き起こすかもしれません。
 
 
以上の理由から、テンプレートファイルはプログラマブルに共通化することによって返って複雑度が増してしまうと考えています。
筆者のチームでは、原則共通化禁止ネストスタック禁止という形で可能な限りテンプレートをわかりやすくシンプルにしてきました。
単純、故に冗長な部分もありますが、裏を返せば簡単であり、知識の少ない運用者でもキャッチアップが容易でミスも最小化できます。

コーディング規約

コーディング規約というほど大それたものではありませんが、テンプレートを作成するにあたっていくつか決めておいたほうがいいことがあります。

  • AWSリソースのキー名
    下記でいうEC2InstanceProductionSystemA0001に相当する部分となります。
    筆者のチームでは「AWSリソース名」+「環境名」+「システム名」+「連番」としています。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  EC2InstanceProductionSystemA0001:
    Type: AWS::EC2::Instance
    # 以下省略
  • AWSリソースに付与するタグ
    筆者のチームでは「環境」、「システム名」、「一意の名称」は最低限必須としています。
     
  • 使用しないプロパティの記載要否
    使用しないプロパティの記載方法については次の3パターンが考えられます。
    筆者のチームでは明示的に使用しない意図が分かるよう「3. 記載した上でAWS::NoValueを参照する」方針としています。

    1. 使用しないプロパティは記載しない
    2. 記載した上でコメントアウトする
    3. 記載した上でAWS::NoValueを参照する

開発フロー/CI

テンプレートファイルはGitなどのバージョン管理システムを利用して管理することが望ましいでしょう。
筆者のチームではGitlabを利用して下記のフローで開発を進めています。

プレゼンテーション1.png

aws-cliのaws cloudformation validate-templateコマンドを実行することでフォーマットの検証を行うことで、実際にスタックを作成する前に、タイポ等の単純なミスを発見することができます。
より細かいチェックを行ってくれるcfn-lintというツールがあるみたいですが、筆者は未検証です。

ある程度の規模までは、このフローで問題なく運用できるはずです。
しかし規模が大きくなればなるほど次のような課題がでてきます。

  • テンプレートファイルが複数に分かれているため、環境横断的に各種リソースの設定値を見たり、横串で修正をしたりするのがつらい。
  • YAMLを書くのがそもそもつらい。
  • コーディング規約違反のチェックなどレビューもつらい。

そこで筆者のチームではCloudFormationの設定値をExcel, RDBで管理し、YAML自動生成するような仕組みを導入しています。
プレゼンテーション2.png

これにより、開発者はExcelだけをメンテナンスすればよくなりました。
同じAWSリソースは1シートに全て定義しているため、環境横断的にリソースの設定値を参照・修正することも容易です。

ただしこのような仕組みを作るのはそれなりに時間がかかりますし、汎用的に作ろうとするとある程度高度な設計も必要になってきます。ご紹介した方法は決して推奨するようなものではなくただの一例になりますが、何かしらのメンテナンスコストを下げるような仕組みがあると幸せになれると思います。

リリース

ここでのCloudFormationのリリースとはスタックを作成・更新・削除することを指します。
AWS CLIを利用してJOB等で実行させるなど色々な方法が考えられますが、スタックの操作については「管理コンソールからの実行」が一番良いと筆者は考えています。
理由としては「変更のプレビュー」により、AWSリソースの変更点が「視覚的」に確認できるためです。

console-changeset-details.png

スタックの更新を行う場合には必ず変更セットの作成から更新を行うようにしましょう。

CloudFormationを腐らせてはいけない

公式ドキュメントにも書かれていますが、AWS CloudFormationで作成したリソースをCloudFormation以外の方法で変更しては絶対にいけません。

スタックを起動した後、AWS CloudFormation コンソール、API、または AWS CLI を使用して、スタック内のリソースを更新します。スタックのリソースを AWS CloudFormation 以外の方法で変更しないでください。 変更するとスタックのテンプレートとスタックリソースの現在の状態の間で不一致が起こり、スタックの更新または削除でエラーが発生する場合があります。詳細については、「ウォークスルー: スタックの更新」を参照してください。

CloudFormationはあくまでCloudFormationの世界でAWSリソースを管理しており、管理コンソールから行った変更をいい感じに取り込んではくれません。最悪の場合、二度とCloudFormationが実行できなくなる可能性があります。

特にこの問題は、CloudFormationに詳しくない運用者に引継ぎを行う場合などに発生します。
本当の緊急事態を除き、原則AWSの管理コンソールはRead Onlyにしておくなど、権限制御を行いましょう。
(人を信じてはいけません。)

おわりに

まとまりなくつらつらと書いてしまいましたが、いかがでしたでしょうか。
CloudFormationを実際の現場でどう運用するのか考える際に、この記事が少しでも参考になれば幸いです。


  1. https://aws.amazon.com/jp/blogs/aws/aws-cloudformation-update-yaml-cross-stack-references-simplified-substitution/ 

  2. マルチリージョンでサービスを提供する場合はAWS契約単位、リージョン単位、環境単位、システム or サブシステム単位に分割したほうがいいでしょう。 

続きを読む

Amazon Elastic Container Service for Kubernetes (EKS)とAWS Fargate

本記事は個人の意見であり、所属する組織の見解とは関係ありません。

AWS re:Invent 2017のKeynoteにおいて、Amazon EKSが発表されました。

Amazon Elastic Container Service for Kubernetes (Amazon EKS) は、Kubernetes クラスターのインストールと運用を自分で行うことなく、Kubernetes を AWS で簡単に実行できるようにするマネージドサービスです。
https://aws.amazon.com/jp/eks/

この記事では、同じくre:Inventで行われたCON215: Intro to Amazon Elastic Container Service for Kubernetesの内容を中心に、Amazon EKSとはどんなものなのか、および2018年での連携が予定されているAWS Fargateとは何なのか、をご紹介したいと思います。

Kubernetes on AWS

少し前になりますが、Amazon Web ServicesはKubernetesを始め多数のプロジェクトをホストしているCloud Native Computing FoundationにPlatinum Memberとして参加をしました1。そして、12月頭に開催されたKubeCon + CloudNativeCon NAでの最新のアンケート調査2によると、69%の方がAWSを現時点で利用されていて、これはオンプレミスも含めた中で最も利用比率が高い環境となっています。

こうした利用者の方々からのフィードバックとして、Kubernetesのマスターおよびその分散データストアであるetcdの管理は非常に大変でありかつ差別化にならない重労働(undifferenciated heavy lifting)である、というものがありました。

Amazon EKSのTenets

そうしたフィードバックを元に、マネージドサービスであるAmazon Elastic Container Service for Kubernetesを開発しました。EKSがどういうものなのか細かい機能を見る前に、そのTenets(日本語にすると教義、信条)を見てみるのが、理解を助けてくれます。

  • Tenet 1: EKSはエンタープライズ企業が本番のワークロードを実行するためのプラットフォームであること

    • 信頼性、可視性、スケーラビリティ、管理の容易さ
  • Tenet 2: EKSはネイティブで最新のKubernetesの体験を提供すること
    • 現状でKubernetesで実現できることと同じことができる
  • Tenet 3: EKSユーザが他のAWSサービスを使うときには、シームレスな連携を実現し不要な作業を取り除くこと
  • Tenet 4: EKSチームは積極的にKubernetesプロジェクトに貢献していくこと

Amazon EKSのアーキテクチャ

EKSはKubernetesのControl planeをフルマネージドで提供するので、そのクラスタにjoinするNodesや操作したいkubectlは割り振られるEndpointを利用するだけで良いです。Control planeはMulti AZ構成になっておりEKSが監視していて、必要に応じて可用性を保ったまま自動でスケールしてくれます。

Worker Nodesは自由なEC2インスタンスを持ち込むことができます。なので、例えばSpot Fleet等既存のEC2で使える機能をフル活用することができますし、利用できるAmazon Machine Image (AMI)にも制約はありません。一方で、Auto Scaling Group等の設定や、OS上でKubernetesに必要な設定を自身で全て行いたくない方も多いのは理解しているので、以下のものが提供される予定です:

  • Amazon LinuxベースのEKS Worker Node用のAMI

    • 更新があれば通知されるAmazon SNS Topicも提供予定
  • 上記AMIをプロビジョンできるPacker3スクリプト
    • 自由なOSをベースにして簡単にカスタムのEKS Worker Node AMIが作成可能
  • Worker Node設定用のAWS CloudFormationテンプレート
    • 必要なパラメータを埋めるだけでWorker Nodesを立ち上げられるテンプレート

EKSのネットワーク

KubernetesのPod(コンテナ)は、専用のPrivate IPアドレスを持っていて互いにフラットなネットワークで接続可能であることを要求されます。これを実現する方法には例えばOverlay Networkの様にNodeのネットワークとは全く異なるアドレス帯を利用することもできますが、パフォーマンスに影響があったり運用やトラブルシューティングも大変になることが多いです。

EKSチームではAmazon VPCのネットワークを最大限活用できる新しいCNI Pluginを開発していて、既にGitHubにて公開されています。CNIとは、Container Network InterfaceというCNCFのプロジェクトの1つで、Kuberenetesに限らずコンテナでのネットワーク設定を標準化したものとなっています。CNI Pluginとして実装を行うことで、ネットワークの設定を柔軟に行うことが可能となります。4

こちらのPluginが払い出すIPアドレスは、EC2インスタンスのElastic Network Interface(ENI)に割当可能なSecondary IPアドレスになっているので、所属するVPCのCIDRの範囲のアドレスとなります。そのため、VPCでルーティング可能な範囲で何も工夫しなくても疎通可能です(Security GroupやNACLも通常通り作用します)。1つのENIに複数のSecondary IPアドレスを割り振れるので、多くのIPアドレスを1つのインスタンス上に集めることも可能です。技術的な詳細についてはCON409 Amazon Elastic Container Service for Kubernetes Deep Diveで説明されているので、興味のある方はご覧になると良いと思います。

上記のCNI PluginはEKSだけでなく、現時点でAWS上に構築しているKubernetesクラスタでも利用可能です。利用方法はPluginの配置と合わせて、L-IPAMというコンポーネントをDaemonSetで各インスタンスに配置する必要があります。Kubernetesクラスタを構築するツールであるkopsでは既にこのPluginで構築するオプションがmergeされているので、近いうちにリリース版にも含まれると思われます。5

また、この設定方法ではVPCのSecurity GroupはENI単位での設定となるので、Pod毎に異なるSecurity Groupを使うことはできません。そうしたより詳細なネットワークポリシーを設定したい場合には、Kubernetesが持っているNetwork Policyという仕組みを利用します。その実装で最もよく利用されているのがProject Calicoです。オープンソースの実装ですが、TIGERA社が有償のサポートも行っています。このCNI PluginでもProject Calicoが利用可能となるようにTIGERAと連携しています。

AWS IAMでの認証

EKSでは、KubernetesのEndpointの認証にAWS IAMを利用します。この実装にはHeptio社が開発しているAuthenticatorを活用しています。これによって、EKSのクラスタにアクセスできるIdentityの認証(それが誰であるかの確認)には既存のIAMを活用できます。一方で、認証したIdentityの認可(何をする権利を持っているか/いないか)については、Kubernetesが持っているRBAC(Role-Based Access Control)を利用します。これは、既にRBACを利用している方が多くそれが必要であるというフィードバックを元にした設計です。kubectlはまだこのIAMでの認証に対応していませんが、この機能にむけた改修をEKSチームで進めているところです。

こちらも、技術的な詳細についてはCON409 Amazon Elastic Container Service for Kubernetes Deep Diveで説明されているので、興味のある方はご覧になると良いと思います。

Kubernetesのバージョン

現時点ではEKSはKubernetes 1.7をサポート予定で、その後バージョンを追加していきます。パッチレベルについてはセキュリティパッチも含まれるので常に最新のものを自動で適応しますが、マイナーバージョンについては最新から過去3つの中から選択できるようにする予定です。マイナーバージョンのアップグレードのポリシーを細かく制御できるようにしたいというのも多くのフィードバックがあったポイントで、EKSでは自動アップグレードや手動でのアップグレードが選択可能になる予定です。

古いバージョンを使い続けていてそのバージョンのサポート(パッチレベルの適応)が終了するときには、事前に通知が行われ期間内にアップグレードするか、自動でアップグレードさせるかという選択をする形になります。

オートスケール

マスターのオートスケールに関しては、EKSが勝手にやってくれるので全く気にする必要はないですが、PodおよびNodeのオートスケールについては既存のKubernetesが持っているオートスケールに機能をそのまま利用することができます。PodレベルのスケーラとNodeレベルのスケーラがあり、前者はCPU利用率といったメトリクスでPodの数を調整するもので、後者はリアクティブにPodのスケジュールに失敗したらNodeの数を増やすというものですが、どちらも利用可能です。

よりAWSとの連携を強めるべき部分ももちろんあり、例えばELBのメトリクスやSQSのキューの長さに応じてスケールさせるといった機能が考えられています。

Private Link

EKSの発表の少し前に発表された新機能としてAWS PrivateLinkというものがあります。これは、各種AWSのサービスエンドポイントとして、VPC内に作成されるENIを利用することができる(もう少し正確に言うとAWSだけでなく誰でもサービスを登録することができる)新機能になります。EKSのマスターのエンドポイントについてもこのPrivateLinkを利用できるようにするオプションを提供予定で、これを使えばインターネットへのアクセスを一切許可することなくEKSを利用することができます。

AWS Fargate

AWS Fargateは、同じくre:Invent Keynoteで発表された新サービスです。これは、インフラ不要なコンテナ実行環境であり、EC2インスタンスのことを一切気にすること無くコンテナだけに集中できる新しいプラットフォームです。コンテナに必要なCPUとメモリ量を設定したら、あとはその割り当てたリソースに対して秒単位で料金が発生する仕組みとなっています。既に、Amazon ECSではLaunch TypeというパラメータをFARGATEとするだけで利用可能な状態でGAしています。FargateについてはAWS Fargate Advent Calendar 2017を開催していて、たくさんの日本語記事が集まっていますのでぜひこちらをご覧下さい。

EKSのroadmapとして、このFargate対応を予定しています。つまり、Kubernetesの機能をそのままにEC2インスタンスを起動することなくコンテナが実行できるようになる予定です。こちらについて興味のある方は、どういった形で実現されると嬉しいのかといったフィードバックをぜひ下さい。フィードバックの方法が分からなければ、AWS Japanの人に相談してみることをおすすめします。

オープンソース

最後に、オープンソースの重要性を話しています。例えば、最近Kubernetes 1.9で取り込まれたType LoadBalancerのNetwork Load Balancer(NLB)対応では、Pull RequestのコードレビューをAWSも実施しています6。CNI Pluginももちろんオープンソースで公開していますが、開発にあたっては外部のコミュニティと協力して行っていて、逆にコードレビューをしてもらっています。

今後もオープンソースのKubernetesのコミュニティへの貢献を続けていくのですが、重要なことはどういった貢献をしてほしいのかを皆さんがフィードバックして欲しいということです。もし何か既に欲しいものや、開始しているプロジェクトなどがあれば、ぜひフィードバックをして下さい。

まとめ

Amazon EKSのプレビューはこちらのサイトからお申込み下さい。そして、継続してフィードバックをお願いします。AWSのサービスのほとんどは皆さんからのフィードバックに基いて作られています。

最後に、AWS上でのKubernetesに興味がある方はまずこちらのWorkshopを試してみることを強くおすすめします。CNCFにAWSから主として参加しているArun Guptaが中心となって作成しており、以下の様な非常に豊富なコンテンツが揃っていて、初級から上級まで様々な体験をすることが簡単にできます。もし日本語でお手伝いしながらの実施をご希望される方がいればぜひお声がけ下さい。

  • Beginner (100 level)

    • Prerequisites
    • Create a Kubernetes cluster using kops
    • First Steps with the Kubernetes CLI
    • Kubernetes Developer Concepts
  • Intermediate (200 – 300 level)
    • Configuration and Secrets Management
    • Service Discovery with Microservices
    • Deploy Applications using Helm Charts
    • Updating Applications & Canary Deployment
    • Logging within a Kubernetes cluster
    • Monitoring within a Kubernetes cluster
    • Upgrading a Kubernetes cluster: In-place Upgrade
    • Cluster Scaling
    • Application Autoscaling
    • Application Tracing
  • Advanced (300 – 400+ level)
    • StatefulSets with EBS
    • Specifying Network Policies
    • Using CoreDNS for Service Discovery
    • Managing IAM roles with kube2iam
    • ALB Ingress Controller
    • Kube AWS Ingress Controller and Skipper
    • Nginx Ingress Controller
    • Service Mesh Integration using Linkerd and Istio

  1. https://medium.com/@adrianco/cloud-native-computing-5f0f41a982bf 

  2. https://www.cncf.io/blog/2017/12/06/cloud-native-technologies-scaling-production-applications/ 

  3. HashiCorpが公開しているイメージ作成ツールです https://www.packer.io/intro/index.html 

  4. AWSではこのPlugin以外にも、Amazon ECSのタスクネットワークを実現するための仕組みもCNI Pluginとして公開しています。GitHubはこちら、その挙動を説明したブログはこちらになります。 

  5. PRはこちら。2017年12月21日現在で利用するには最新revisionを自身でビルドしたkopsを使う必要があります。手順例は[こちら]。(https://gist.github.com/arun-gupta/87f2c9ff533008f149db6b53afa73bd0

  6. https://github.com/kubernetes/kubernetes/pull/53400 

続きを読む

vpc lambdaで外部通信する場合の注意点

問題

AWS lambdaをvpc内に設置して外部通信しようとしたらタイムアウトした

public subnet (Internet GW付き)

原因

http://docs.aws.amazon.com/lambda/latest/dg/vpc.html#vpc-configuring

vpc lambdaにはpublic ipが割り当てられない
(public subnetがauto-assignなpublic IPでも!)

えー。

AWS Lambda は、指定された VPC 情報を使用して、Lambda 関数から VPC リソースにアクセスするための ENI をセットアップします。各 ENI には、指定されたサブネットの IP アドレス範囲からプライベート IP アドレスが割り当てられますが、パブリック IP アドレスは割り当てられません。

対策

private subnetに設置し、nat-gw経由で出て行くようにする

Lambda 関数でインターネットアクセスが必要な場合は、パブリックサブネットまたはインターネットに接続していないプライベートサブネットに添付しないでください。代わりに、NAT インスタンスまたは Amazon VPC NAT ゲートウェイを介して、インターネットにアクセスしているプライベートサブネットにのみ添付してください。

続きを読む