EC2(6)Elastic Load Balancing

ELBとは

ELBとは複数のアベイラビリティゾーンのEC2インスタンスに負荷を分散させるロードバランサである。ELBには、Classic Load BalancerApplication Load Balancerの2種類が存在し、Clasic Load Balancerは、HTTPとHTTPSの他に、TCPSSLにも対応している。一方でApplication Load Balancerは、HTTP/2やWebSocketに対応している。

ロードバランサは、登録されているEC2のうち正常なものだけを選んで負荷を分散する。Clasic Load Balancerは、EC2のインスタンスを直接登録するが、Application Load Balancerは、ターゲットグループをまず生成し、その中にインスタンスを登録する形となる。クロスゾーン負荷分散を無効にしていると、インスタンスがどのようなバランスで配置されていたとしても、アベイラビリティゾーンの数で均等に配分されてしまうので注意が必要である。なお、Application Load Balancerでは、クロスゾーン負荷分散はデフォルトで有効になっている。

ロードバランサに紐付けられているドメイン名に紐づけられたIPアドレスは、負荷に合わせて動的に変化する。DNSエントリは、TTLが60秒に設定されている。また、Application Load Balancerはリクエストタイムアウト値が60秒に設定されている。内側のインスタンスとの通信では、EC2にKeep Aliveを設定しておくことが望ましい。

Application Load Balancer とは

Application Load Balancerは、OSI参照モデルのレイヤー7で動作するロードバランサで、負荷に合わせて自動的にスケールする。ロードバランサには複数のリスナーを紐づけることができ、この下にターゲットグループがぶら下がる。EC2でクライアントの送信先アドレスを取得するためには、x-forwarded-forヘッダフィールドを参照する。またALBが負荷に追従できずスケーリングが間に合わなかった場合は、503を返す。

ELB基本コンポーネント

AWS EC2(5)ユーザデータによる起動時のコマンドの実行

cloud-init

EC2が起動する際に、cloud-initを使って任意のスクリプトを実行させることが可能である。実行する際に渡すことのできるデータ(ユーザデータ)は、プレーンテキスト・ファイル・Base64エンコードされたテキストで、通常は初回起動時のみ実行されるため、再起動時などは実行されない。スクリプトは、シェルスクリプト形式もしくはcloud-initディレクティブ形式で記述することが可能である。なお、スクリプトは、インタラクティブに動作させることはできないことに注意が必要である。また、このスクリプトは、rootユーザとして実行される。

シェルスクリプトによる実行

シェルスクリプトを実行させるためには、通常のシェルスクリプト同様にインタプリタのパスを最初に記述する必要がある。

#!/bin/bash

その他の処理も、通常のシェルスクリプトと同様に記述することができる。

ユーザデータの登録

ユーザデータの登録は、AWSマネージメントコンソール上、もしくはAWS CLIから行うことが可能である。

AWSマネージメントコンソールから登録

AWSマネージドコンソールで行う場合は、インスタンス作成画面の中で、ユーザデータを登録できる。

ユーザデータの登録

また、登録したユーザデータは、「インスタンスの設定」より確認することが可能である。

ユーザデータの確認

実行中のインスタンスから値を取得することも可能である。

curl http://169.254.169.254/latest/user-data

AWS CLIから登録

AWS CLIからEC2を起動する際に、user-dataオプションを付与することで、ユーザデータを指定することができる。指定するファイルは、シェルスクリプトが記述された通常のテキストファイルでよい。

aws ec2 run-instances --cli-input-json file:///tmp/ec2_settings.json --user-data file:///tmp/cloud-init_userdata.txt

AWS EC2(4)AWS CLIからEC2インスタンスを起動する

JSONファイルから起動する

EC2をAWS CLIから起動する際、JSONファイルに設定情報を記述しておくと、複雑なオプションコマンドを書き連ねる必要がなく、設定の管理もラクである。JSON形式の設定ファイルの雛形は、

aws ec2 run-instances --generate-cli-skeleton > /tmp/ec2_settings.json

で取得することが可能であるが、不要な設定も多く含まれているので、どの設定を有効とするかは精査が必要である。AWSマネージメントコンソールで設定可能な項目と同程度の設定であれば、以下の設定で起動することが可能である。

{
    "DryRun": false,
    "ImageId": "ami-XXXXXXXX",
    "KeyName": "XXXXXXXX",
    "SecurityGroups": [
        "XXXXXXXX"
    ],
    "InstanceType": "t2.micro", 
    "BlockDeviceMappings": [
        {
            "DeviceName": "/dev/xvda", 
            "Ebs": {
                "VolumeSize": 8,
                "DeleteOnTermination": true,
                "VolumeType": "gp2"
            }
        }
    ],
    "Monitoring": {
        "Enabled": true
    },
    "DisableApiTermination": true,
    "InstanceInitiatedShutdownBehavior": "stop",
    "IamInstanceProfile": {
        "Name": "XXXXXXXX"
    }
}

それぞれの設定項目と、AWSマネージメントコンソール上の表示との対応は、以下の通り。

JSON項目名 AWSマネージメントコンソール上の名称 内容
DryRun 設定ファイル作成時は、DryRunで確認する
ImageId Amazon マシンイメージ AMIのID
KeyName キーペアの選択 キーペア
SecurityGroups セキュリティグループの設定 セキュリティグループ名
InstanceType インスタンスタイプの選択 インスタンスタイプ
BlockDeviceMappings/DeviceName デバイス AWSマネージメントコンソールは、通常/dev/xvdaが指定される
BlockDeviceMappings/EBS/VolumeSize サイズ(GiB) ボリュームサイズ
BlockDeviceMappings/EBS/DeleteOnTermination 合わせて削除 インスタンス削除時にボリュームも削除するか否か
BlockDeviceMappings/EBS/VolumeType ボリュームタイプ
Monitoring モニタリング CloudWatch 詳細モニタリングを有効化
DisableApiTermination 削除保護の有効化 誤った削除からの保護
InstanceInitiatedShutdownBehavior シャットダウン動作 シャットダウン時にインスタンスを削除するか停止するか
IamInstanceProfile IAM ロール IAM インスタンスプロファイル

なお、Tagはインスタンスを起動しないと指定できない
この設定ファイルを用いてEC2インスタンスを起動する場合は、以下のコマンドを実行する。

aws ec2 run-instances --cli-input-json file:///tmp/ec2_settings.json

この際、設定ファイルに誤りがある場合には、

Parameter validation failed:
Invalid type for parameter SecurityGroups, value: XXXXXXXX, type: <type 'unicode'>, valid types: <type 'list'>, <type 'tuple'>

などのように、エラーメッセージが返される。

AirPods(1)Apple Storeで当日にAirPodsを購入する方法

Apple Storeアプリで購入し店舗で受け取る

12/14に突如発売がアナウンスされたAirPods。当初は最短で12/19お届けだった配送スケジュールも、予約が殺到した結果、あっという間に伸びていき、今や6週間待ち。では、2月中旬まで待てない人は、どうやって入手したら良いのか。一番手っ取り早いのは、Apple Storeまで出向き直接購入する方法だが、これも下の写真のとおり、開店前から長蛇の列で、おまけに入荷されない日の方が多いとのこと。実際にApple Storeに開店前から並んでみたが、開店30分前には、修理や他のApple製品購入の人間も含めて、50人近くが列に並ぶという状況で、列に並んでいる途中にApple Storeの店員から、「在庫が少ないので販売は確約できない」と言われてしまう始末。ではどうしたらよいのか。

Apple Store 心斎橋

列に並んでいる人に対して、開店前にApple Storeの店員からアナウンスがあり、一番早くAirPodsを入手するためには、iOSのApple StoreアプリからAirPodsを購入して、店頭受け取りを指定するという方法が良いとのこと。実際にApple StoreアプリからAirPodsを選択してみると、

Apple Store アプリ

まさかの当日店舗受け取りが可能となっている。Apple Storeアプリからすぐさま購入すると、クレジット決済や在庫の確認等のため、15分程度処理中のステータスとなるが、その後すぐに受け取り待ちのステータスとなり、

Apple Store アプリ

受け取り待ちのステータスになったことを確認した直後に、店舗で購入を申し出ると、すぐに購入手続きへと移ることが可能でした。Apple Storeアプリの店舗受け取りにしている商品の案内は、(AirPodsに限らず)最優先で手続きしてくれるとのこと。というわけで、年内にAirPodsを購入するための最善の方法は、Apple Storeアプリで購入し店舗で受け取る。これだと寒空の下で列に並ぶ必要が無く、購入完了後の好きな時間に店舗に赴けばよい。ただし、店舗に商品が入荷されたタイミングで、当日店舗受け取りが可能なステータスに変更となるようなので、いつ購入しても当日に受け取れるというものでは無いようである。また、店舗受け取りに指定した場合は、3週間以内であればいつ来店しても確実に商品が受け取れる一方で、3週間以内という期限が設けられているので、期限切れには注意が必要だ。

AWS Identity and Access Management(1)IAMとは

AWS Identity and Access Management (IAM)とは

AWS IAMは、AWSをセキュアに使用するための認証認可の仕組み。UserやGroupを作成してパーミッションを付与することができる。AccessKey, SecretKeyの取り扱いは注意が必要で定期的な更新が望ましい。また、Rootアカウント(アカウントを作成したときのID)はIAMの設定するポリシーが適用されない強力なアカウントになるので極力使用しない。

IAMで作成したユーザでマネージメントコンソールにログインすることが可能で、ログインURLはIAM Dashboardより確認編集することが可能である。

安全なアカウント管理のために

安全にアカウントを管理するためには以下の手法を講じることが望ましい。

  • ルートアカウントのアクセスキーを消去する
  • ルートアカウントをMFA認証にする
  • AWSが定期着したポリシーを利用する
  • ユーザにグループを割り当て、グループごとにポリシーを定義する
  • 最小限の権限のみを与える
  • EC2で動作するアプリケーションへは、アクセスキーではなくロールで権限を与える

セキュリティ監査

セキュリティ監査を実施することで高いセキュリティレベルを維持することができる。セキュリティ監査は、定期的もしくはユーザの増減があった際や、サービスの開始/停止時、不正アクセスが疑われる際などに推測を交えずに徹底的に行うと良い。

管理ポリシー

AWSアクセスへの管理権限をJSON形式で指定することが可能である。条件(Condition)は、項目を連ねた場合はAND、項目内で条件を連ねた場合はORとして扱われる。全てのアクセスはデフォルトで拒否、Allowが指定されれば許可、Denyが指定されれば明示的な拒否として扱われる。

分類 項目例 内容
Effect Allow or Deny 許可設定であればAllow, 拒否設定であればDeny
Action s3:createBucket 操作の指定、ワイルドカードも使用可能
Resource arn:aws:s3:::mybucket service:region:account:resouceの順で記述する
Condition “IPAddress”: {“AWS:SourceIP”: “192.168.0.1”} 条件を指定する

IAMロール

AWSサービスに対してAWSアクセスの管理権限を付与する仕組み。UserやGroupには紐付かない。例えばEC2からDynamoDBやS3にアクセスする場合は、EC2上にCredentialを置くのではなくインスタンス作成時に適切なIAMロールを紐付ける。EC2へのIAMロールの紐付けは、インスタンス作成時のみ可能であることに注意が必要である。

AWSCredentialsProvider

AWSの各サービスにアクセスするプログラムをEC2上で動作させる場合に、認証情報をCredentialsから取得するのか、IAMロールから取得するのか選択することができる。Credentialsから取得する場合はProfileCredentialsProviderを、IAMロールから取得する場合はInstanceProfileCredentialsProviderクラスを使用する。

// Credentialsから取得する場合
AWSCredentialsProvider credentialsProvider = new ProfileCredentialsProvider();

// IAMロールから取得する場合
//
// 引数(refreshCredentialsAsync)をtrueにすると認証情報を非同期に更新する新しいスレッドが生成される
// falseにすると認証情報の更新は、インスタンスメタサービスに合わせられる
AWSCredentialsProvider credentialsProvider = new InstanceProfileCredentialsProvider(true);

// 認証情報の取得
credentialsProvider.getCredentials();

Amazon VPC (1)Amazon Virtual Private Cloud とは

VPC

各アベイラビリティゾーンのデフォルトサブネットを持つデフォルトVPCが標準で作成され、インスタンス起動時にサブネットを指定しなかった場合は、このデフォルトVPCが指定される。これに加えて、ユーザ独自にデフォルト外VPCを作成することが可能である。VPCは、ルータを通じて他のVPCと接続(ピアリング接続)したり、S3などの他のAWSサービスのエンドポイントと接続したり、VPN経由で自社のネットワークと接続したりすることが可能である。

VPCは生成する際にサイズを指定することが可能で、/16から/28までを指定できる。生成後にサイズを変更することはできない。指定するCIDR ブロックは、プライベートIPアドレスの範囲から指定することが望ましい。

デフォルトVPC

デフォルトVPCには、ルータインターネットゲートウェイが含まれており、各サブネットは、インスタンスに対してパブリックIPの割り当てが実行される、インターネットに接続可能なパブリックサブネットである。

デフォルトVPC

デフォルト外VPC

デフォルト外VPCには、ルータやインターネットゲートウェイが含まれておらず、自分で設定に加える必要がある。また、サブネットも標準では、パブリックIPの割り当てが行われず、*プライベートサブネット**に設定されている。

デフォルト外VPCでインターネット接続を可能にするためには、インターネットゲートウェイのアタッチや、ルーティングテーブルの追加、各インスタンスへのElastic IPの割り当てが必要である。プライベートサブネットの場合、サブネット内のインスタンスが直接インターネットに接続することができないため、別のパブリックサブネット内にNAT gatewayを生成し、このNAT gateway経由でインターネットと接続を行う。Elastic IPの数には限りがあるので、静的なIPアドレスを多く使用するようなネットワーク構成の場合にも、NAT gatewayは有効である。

サブネット

サブネットは、アベイラビリティゾーン単位で指定できる。サブネットは生成する際にサイズを指定することが可能で、/16から/28までを指定できる。指定したCIDR ブロックの先頭4アドレスと最後の1アドレスは使用することができない。なお、先頭アドレスは、ルータに接続されるIPアドレスとなっている。

ルーティング

各VPCには暗黙的なルータ(implied router)が存在し、標準ではVPC内の各サブネット間の通信のみ許可されている。また、ルートテーブルは、標準で生成されるメインルートテーブルと、各サブネットにそれぞれ割り当てることが可能なカスタムルートテーブルが存在する。明示的にルートテーブルの関連付けを行わない場合は、メインルートテーブルにアタッチされる。インターネットゲートウェイを通じて、インターネットに接続する場合は、ルートテーブルにインターネットゲートウェイへの経路を明示的に追加する必要がある。

ネットワークインタフェース

ネットワークインタフェースは、インスタンスにアタッチ、デタッチしても属性情報は変わらない。1つのインスタンスに複数のネットワークインタフェースをアタッチすることで、管理用ネットワークを別に作成することなどが可能となる。一方で、複数のネットワークインタフェースが存在すると、パブリックIPアドレスの自動割り当ては利用不可となる。

Google Play Developer ConsoleでOpenSSLのバージョンエラーが発生したときの対応法

Cocos2d-xを使ったアプリをGoogle Playで公開しようとするときに、以下のエラーが表示されてAPKの公開を拒否される場合がある。

このAPKは、セキュリティの脆弱性が含まれている点が悪意のある行為に関するポリシーに違反しているため、非承認となりました。

アプリで使用中のOpenSSLのバージョンにセキュリティの脆弱性があります。

Cocos2d-xには、OpenSSLのライブラリが含まれているため、OpenSSLの機能を使っていない場合でも、含まれているOpenSSLのバージョンによっては上記の警告が出る場合がある。その際は、下のリンクにもあるように、内含されているOpenSSLのバージョンを上げる必要がある。

XCodeからiTunes Connectへアップロード後に`has change to Invalid Binary`エラー

XCodeからiTunes Connectへアーカイブファイルをアップロードした後にhas change to Invalid Binaryエラーが発生した場合は、問題の詳細がメールで送信されてくる。

Missing Push Notification Entitlement

Missing Push Notification Entitlementは、Apple Developer > Certificates, Identifiers & Profiles > App IDsでPush Notificationsが有効化されていないか、もしくは、XCode -> TARGET -> Capability -> Push NotificationsでPush Notificationsが有効化されていないかのいずれかの場合が多いため、これらの設定を見直した上で再度アップロードを行う。

Missing Push Notification Entitlement – Your app includes an API for Apple’s Push Notification service, but the aps-environment entitlement is missing from the app’s signature. To resolve this, make sure your App ID is enabled for push notification in the Provisioning Portal. Then, sign your app with a distribution provisioning profile that includes the aps-environment entitlement. This will create the correct signature, and you can resubmit your app. See “Provisioning and Development” in the Local and Push Notification Programming Guide for more information. If your app does not use the Apple Push Notification service, no action is required. You may remove the API from future submissions to stop this warning. If you use a third-party framework, you may need to contact the developer for information on removing the API.

Certificatesの修正が必要な場合

XCode上で修正が必要な場合

privacy-sensitive data without a usage description

iOS10よりユーザデータにアクセスする場合は、使用目的をInfo.plistに記述する必要がある。

We have discovered one or more issues with your recent delivery for “YOUR APP NAME”. To process your delivery, the following issues must be corrected: This app attempts to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.

Info.plistに記述した文言は、データアクセスの許可を求めるポップアップ上に表示される。NAVITIMEアプリの場合はこんな感じ。

Fluentd + Elastichsearch + Kibana(4)Fluentdでホスト名を追加する

Fluentdでログを転送する際、ホスト名も付加したい。そんなときは、標準のfilterプラグインを使って、以下の設定を加える。

sudo vi /etc/td-agent/td-agent.conf

<filter **>
  @type record_transformer
  <record>
    hostname ${hostname}
  </record>
</filter>

このときに、matchタグよりも上位に記述しないと動作しないので注意が必要である。