CloudFront に SSL 証明書を導入する際のポイントまとめ

CloudFront に SSL を入れる際に気をつける項目のまとめです。

2017年9月時点では、特に S3 との連携で大きな制約があり、将来的には改善されていくのではと思います。現在の状況を確認してください。

SNI か専用 IP か

まず、ブラウザと CloudFront 間の通信で、SNI (Server Name Indication) が使えるかどうか検討します。

ガラケーやWindowsXP の IE は SNI に対応していません。これらの古い環境でサイトが見えなくても構わないかどうかを確認します。

SNI 非対応のブラウザに対応するには、専用 IP を使う必要があります。専用 IP は $600/月かかります。

専用 IP 独自 SSL の料金体系はシンプルです。SSL 証明書ごとの専用 IP アドレスに伴う追加コストのため、CloudFront ディストリビューションに関連付けられた各独自 SSL 証明書ごとに、毎月 600 USD をお支払いいただきます。

SNI は無料です。

SNI 独自 SSL 証明書管理には、前払い料金や最低月額料金は不要です。お客様にお支払いいただくのは、Amazon CloudFront のデータ転送と HTTPS リクエストに対する通常料金のみです。

証明書の取得について

どのドメインでどんな証明書が必要か、証明書は有料か無料か、を確認します。

証明書の取得方法には、以下の選択肢があります。

  1. 代理店などから購入する (有料)
  2. ACM (AWS Certificate Manager) を使う (無料、ただし EC2 にはインストール不可)
  3. Let’s Encrypt を使う (無料、ただし Amazon Linux 未対応)
  4. etc.

CloudFront – オリジン間を HTTPS にする

通常は、ビューア – CloudFront 間だけでなく、 CloudFront – オリジン間も通信を暗号化します。(表向き暗号化している風を装って、裏を平文で流して良いのかは微妙な問題です…)

CloudFront とオリジンの両方で、証明書が必要になる可能性があります。

オリジンが EC2 の場合、 ELB を入れるか検討する

ACM で取得した証明書を EC2 にインストールすることはできません。

https://aws.amazon.com/jp/certificate-manager/faqs/

Q: ACM により提供された証明書を使用できるのは、AWS のどのサービスですか?

ACM は AWS の以下のサービスと連携できます。
• Elastic Load Balancing – Elastic Load Balancing のドキュメントを参照してください。
• Amazon CloudFront – CloudFront のドキュメントを参照してください。
• Amazon API Gateway – API Gateway のドキュメントを参照してください。
• AWS Elastic Beanstalk – AWS Elastic Beanstalk のドキュメントを参照してください。

https://aws.amazon.com/jp/certificate-manager/faqs/

Q: Amazon EC2 インスタンスや自分のサーバーに証明書を使用できますか?

いいえ。現在のところ、ACM により提供される証明書は、AWS の特定のサービスのみで使用できます。

EC2 で ACM を使いたい場合は、CloudFront – ELB – EC2 の構成にします。証明書が無料になる代わりに、ELB の費用が発生します。

S3 に証明書を入れる必要はない

  • Amazon S3 は SSL/TLS 証明書を提供するため、その必要はありません。

この日本語訳はいまいち何を言っているのかわかりませんが、、

  • Amazon S3 provides the SSL/TLS certificate, so you don’t have to.

「S3 が証明書を提供するので、あなたが(提供する)必要はない」という意味です。

今のところ、S3 に独自の証明書を入れる手段はありません。オリジンに S3 の CNAME を指定することもできません。

http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html

以下の形式を使用してバケットを指定しないでください。

  • Amazon S3 のパススタイル (s3.amazonaws.com/bucket-name)
  • Amazon S3 の CNAME (ある場合)

CloudFront – S3 間の HTTPS には大きな制約がある

S3 をウェブサイトエンドポイントとしてオリジンに設定すると、HTTPS が使えなくなります。

Amazon S3 バケットがウェブサイトエンドポイントとして構成されている場合、オリジンとの通信に HTTPS を使用するように CloudFront を構成することはできません。Amazon S3 はその構成で HTTPS 接続をサポートしていないためです。

ウェブサイトエンドポイントは、

http://example-bucket.s3-website-ap-northeast-1.amazonaws.com/

のような URL での配信方法です。「静的ウェブサイトホスティング」の設定です。この URL をオリジンに設定すると、CloudFront – S3 間で HTTPS が使えません。

ウェブサイトエンドポイントは、以下の機能で必要です。

  • /foo/bar//foo/bar/index.html を返す
  • 独自のエラー画面を表示する
  • リクエストを全てリダイレクトする (例えば、www なしドメインを www ありにリダイレクトする)

ウェブサイトエンドポイントを使わず、S3オリジンで設定すると、サイトのトップ / (Default Root Object) 以外、index.html が見えるようにはなりません。

CloudFrontではDefault Root Objectという設定項目でIndex Documentを指定することができますが、これはRootへのアクセス時(例:http://example.com/) に対してのみ有効であり、サブディレクトリ(例:http://example.com/foo/) に対しては有効になりません。そのため、階層構造のあるWEBサイトをホストする際には不向きだと思われます。

ウェブサイトエンドポイントを使う場合は、裏が暗号化されていなくてもいいのか、バレなければいいのか、を検討しなければならなくなります。。ちなみに、オリジンが S3 であることは Server レスポンスヘッダで判別できます。S3 がウェブサイトエンドポイントかどうかは、/foo/bar/ の挙動で判別できます。

また、ウェブサイトエンドポイントにすると、Origin Access Identity を使うことができなくなります。バケット名を推測して、S3 に直接アクセスされる可能性があります。

ワイルドカード証明書の取得を検討する

CloudFront にもオリジンにも、ワイルドカード証明書が使えます。例えば、以下のような組み合わせが考えられます。

  • CloudFront *.example.com → Origin *.example.com

    • 1つのワイルドカード証明書を使う
  • CloudFront www.example.com → Origin www.example.com
    • 1つの非ワイルドカードの証明書を使う
    • CloudFront から Host ヘッダを転送する場合のみ、オリジンの証明書で Host ヘッダのドメイン名が使える
  • CloudFront www.example.com → Origin *.example.com
    • 表は高い非ワイルドカード証明書を使い、裏は安いワイルドカード証明書で済ませる
  • CloudFront www.example.com → Origin origin.example.com
    • 表と裏と、別々に非ワイルドカード証明書を購入する
    • または、証明書に別名 (SAN) を設定する
  • CloudFront www.example.com → Origin origin.example.jp
    • オリジンは .example.com でなくてもよい。DNS の自由が効かない場合、裏は Route53 で独自のドメインを取得すると便利

詳細は以下のドキュメントを参照してください。

カスタムオリジンを使用する場合、オリジンの SSL/TLS 証明書の共通名フィールドにドメイン名が含まれ、さらにサブジェクト代替名フィールドにもドメイン名がいくつか含まれることがあります。 (CloudFront は証明書ドメイン名にワイルドカード文字を使用できます)。

証明書のドメイン名のうち 1 つは、オリジンドメイン名に指定したドメイン名と一致する必要があります。ドメイン名が一致しない場合、CloudFront は、ビューワーに HTTP ステータスコード 502 (Bad Gateway) を返します。

内部の証明書を安くあげる

エンドユーザの目に触れないオリジン用の証明書にまでコストをかける必要があるかどうかを検討します。安価な証明書でも十分かもしれません。

オリジンが ELB なら ACM が使えます。

DNS を操作する権限があるか確認する

表側の DNS を操作する権限がない場合、オリジンに Route53 で取得した独自ドメインを設定すると、自由度が上がります。

オリジンに独自のドメインを使う場合は、その証明書が必要です。

リリース前の確認方法を検討する

リリース前に CloudFront に別のドメインを割り当てて確認する場合は、ワイルドカード証明書があったほうが便利です。

例えば https://staging.example.com/ のような URL を CloudFront に設定します。

Naked ドメインを使うか確認する

https://example.com/ のような Naked ドメイン (Zone Apex) を使うかどうか確認します。

Route53 を使わずに、Naked ドメインを CloudFront や ELB や S3 に割り当てることはできません。CloudFront を通さず、例えば EC2 で直接リクエストを受ける必要が出てきます。

Naked ドメインへのリクエストを EC2 で受ける場合

Naked ドメインへのリクエストを EC2 で直接受ける場合は、ACM が使えません。ACM で取得した証明書は EC2 にインストールできないからです。

証明書の購入が必要になる可能性があります。

Naked ドメインの DNS に Route53 を使っている場合

Route53 でエイリアスを使うと、CloudFront に Naked ドメイン (Zone Apex) を設定できます。

この場合は、Naked ドメインの証明書取得に ACM が使えます。

ワイルドカード証明書を使う場合、ワイルドカードに Naked ドメインは含まれないので、*.example.com に別名で example.com を設定します。

既存の証明書がある場合は SAN を確認する


既に証明書があって、足りない証明書を購入する場合。

既存の証明書の別名 (SAN) が何になっているのかを確認します。特に Naked ドメインなど、必要なドメインが SAN に設定されているかもしれません。

証明書をインポートするリージョンに注意する

CloudFront の証明書は、バージニア北部リージョンに入れる必要があります。

ACM で証明書を取得する場合にも、バージニア北部リージョンを選ぶ必要があります。

ビューワーと CloudFront との間で HTTPS を必須にするには、証明書をリクエストまたはインポートする前に AWS リージョンを 米国東部(バージニア北部) に変更する必要があります。

CloudFront とオリジンとの間で HTTPS を必須にする場合、オリジンとして ELB ロードバランサーを使用しているなら、任意のリージョンで証明書をリクエストまたはインポートできます。

例えば、オリジンが東京の ELB だとしたら、東京とバージニア北部リージョンの両方の ACM で証明書を取得 (またはインポート) します。

ACM の本人確認について

ACM で証明書を取得する場合は、本人確認 (取得意思の確認) メールが、証明書のドメイン宛てに送信されます。

Whois 情報の更新状態をチェックする

本人確認メールは、公開されている Whois の連絡先アドレスにも送信されます。

Whois に正しいアドレスが公開されている場合は、そのアドレスでメールを受け取るのが簡単です。

SES で ACM の認証を通す

ドキュメントの通りにやれば、ACM の確認メールを SES で受信するのは、さほど難しくありません。

SES の受信設定を行い、DNS に MX レコードを設定、受信したメールを SNS トピックで受け取るようにして、そのトピックに任意のメールアドレスをサブスクライブします。

ルールセットがアクティブになっているかどうかに注意する

SES のメール受信設定には、「ルールセット」というバージョン管理の仕組みがあります。

現行のルールセットをコピーし、編集し、アクティブなルールセットを入れ替える、という手順で設定を変更します。Inactive Rule Sets に新しいルールセットを足しても何も起こりません。

続きを読む

AWSでElastic Stack

はじめに

Elastic Stackについて触る機会があったので、メモを残します。
2017/09月時点の作業です。

Elastic Stackはログの解析・可視化等ができるものなのですが、今回その説明は省かせてもらいますので、公式等をご確認下さい。

作りたい構成

AWSのVPC環境にElasticsearchを仮想マシン3台にインストールしクラスタ化します。
その後、どれか一台にkibanaをインストールしてクラスタの状態をブラウザから確認します。

今回作りたい構成は以下のようなイメージです。
ES01.jpeg

AWS側の設定について

AWS側の設定は以下のようにしました。

VPC:192.100.0.0/24
VPC Subnet:192.100.0.0/27
仮想マシン:Amazon Linux
仮想マシンプラン:m4.large
仮想マシン台数:3台
srv1:192.100.0.4/EIP付き
srv2:192.100.0.5/EIP付き
srv3:192.100.0.6/EIP付き

セキュリティグループ
フルオープンはセキュリティ的に問題があるのである程度絞っています。
・仮想マシン操作用
SSH (22) TCP (6) 22 [sshアクセスするIPアドレス]
・Elasticsearchへのアクセス用
カスタム TCP ルール TCP (6) 9200 [ElasticsearchへアクセスするIPアドレス]
・Elasticsearchの内部通信用
カスタム TCP ルール TCP (6) 9300 192.100.0.0/27
・kibanaへのアクセス用
カスタム TCP ルール TCP (6) 5601 [kibanaへアクセスするIPアドレス]

それでは作ります。

構築作業

1.事前準備

1.1 java8(openJDK)のインストール(仮想マシン3台共通作業)

Amazon Linuxでインストールされているjavaのバージョンは1.7.0がインストールされていますので、1.7.0を削除し、1.8.0をインストールします。
デバッグは使うことは無いと思いますがお作法として入れておきます。

# yum -y remove java-1.7.0-openjdk
# yum -y install java-1.8.0-openjdk-devel
# yum -y install java-1.8.0-openjdk-debuginfo --enablerepo=*debug*

1.2 ElasticsearchをyumでインストールできるようにGPGキーのインポートと、リポジトリの作成(仮想マシン3台共通作業)

# rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
# vi /etc/yum.repos.d/elastic.repo
[elasticsearch-5.x]
name=Elasticsearch repository for 5.x packages
baseurl=https://artifacts.elastic.co/packages/5.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

2.Elasticsearchのインストールと起動

Elasticsearchをクラスターモードで起動します。

2-1.Elasticsearchのインストール(仮想マシン3台共通作業)

インストールはありがたいことにとても簡単です。

# yum install -y elasticsearch

インストール後のElasticsearchのディレクトリ状況は以下のような感じになっていました。

/var/run/elasticsearch
/var/log/elasticsearch
/var/lib/elasticsearch
/var/lib/yum/yumdb/e/e7a7bc22f961d4dd3889c0cac8f668512fe3d2c0-elasticsearch-5.6.2-1-noarch
/var/lib/yum/repos/x86_64/latest/elasticsearch-5.x
/var/cache/yum/x86_64/latest/elasticsearch-5.x
/etc/elasticsearch
/etc/elasticsearch/elasticsearch.yml
/etc/sysconfig/elasticsearch
/etc/rc.d/init.d/elasticsearch
/usr/lib/systemd/system/elasticsearch.service
/usr/lib/sysctl.d/elasticsearch.conf
/usr/lib/tmpfiles.d/elasticsearch.conf
/usr/share/elasticsearch
/usr/share/elasticsearch/lib/elasticsearch-5.6.2.jar
/usr/share/elasticsearch/modules/reindex/elasticsearch-rest-client-5.6.2.jar
/usr/share/elasticsearch/bin/elasticsearch
/usr/share/elasticsearch/bin/elasticsearch.in.sh
/usr/share/elasticsearch/bin/elasticsearch-keystore
/usr/share/elasticsearch/bin/elasticsearch-systemd-pre-exec
/usr/share/elasticsearch/bin/elasticsearch-translog
/usr/share/elasticsearch/bin/elasticsearch-plugin

2.2.elasticsearch.ymlの設定(仮想マシン毎の設定)

elasticsearch.ymlはデフォルトの設定は全てコメント化されていますので、
追加したい内容を追記すればOKでした。
追加する内容は以下です。

cluster.name [cluster-name]:クラスタ名。入力しないとデフォルトの名前になる。
node.name [node-name]:elasticsearchノードの名前。自身の識別に利用する。
discovery.zen.ping.unicast.hosts ["IPADDRESS","IPADDRESS","IPADDRESS"]:クラスタを構成する相手ホスト名をユニキャストで検索する。(3台構成なので3つ書く)
network.host: 0.0.0.0:通信許可設定。通信の制御はAWSのセキュリティグループで行う為、こちらは全許可で記載します。

上記の設定を各サーバのelasticsearch.ymlに記載します。

srv1
# vi /etc/elasticsearch/elasticsearch.yml
cluster.name: my-cluster
node.name: node001
network.host: 0.0.0.0
discovery.zen.ping.unicast.hosts: ["192.100.0.4","192.100.0.5","192.100.0.6"]
srv2
# vi /etc/elasticsearch/elasticsearch.yml
cluster.name: my-cluster
node.name: node002
network.host: 0.0.0.0
discovery.zen.ping.unicast.hosts: ["192.100.0.4","192.100.0.5","192.100.0.6"]
srv3
# vi /etc/elasticsearch/elasticsearch.yml
cluster.name: my-cluster
node.name: node003
network.host: 0.0.0.0
discovery.zen.ping.unicast.hosts: ["192.100.0.4","192.100.0.5","192.100.0.6"]

2.3.Elasticsearchの起動(仮想マシン3台共通作業)

各サーバのElasticsearchサービスを起動します。この時同じタイミングで起動コマンドを打つと、ノードの認識がうまくいかない場合があります。サービスの起動完了を待ちながら1台ずつ起動します。

# /etc/init.d/elasticsearch start

2.4.クラスタ状態の確認

仮想マシン3台の内、どのサーバでも構いませんので以下コマンドを発行し、ノードの状態を確認します。

# curl localhost:9200/_cat/nodes
192.100.0.5 8 43 0 0.00 0.00 0.00 mdi - node002
192.100.0.6 7 43 0 0.00 0.02 0.00 mdi - node003
192.100.0.4 8 44 0 0.00 0.01 0.04 mdi * node001
※クラスタ化ができていない場合は自分のノード名しか表示されません。

クラスタ化がとても簡単に成功しました。
他にもログを確認することでノードが追加されたか確認することができます。
以下のようにログが出力されます。

/var/log/elasticsearch/my-cluster.log
[2017-xx-xxTxx:xx:xx,043][INFO ][o.e.g.GatewayService     ] [node001] recovered [0] indices into cluster_state
[2017-xx-xxTxx:xx:xx,815][INFO ][o.e.c.s.ClusterService   ] [node001] added {{node002}{UTINV4wuTd6UfgLByoG4gQ}{E5ptnPZ0SG-xc629ayXK_Q}{192.100.0.5}{192.100.0.5:9300},}, 
reason: zen-disco-node-join[{node002}{UTINV4wuTd6UfgLByoG4gQ}{E5ptnPZ0SG-xc629ayXK_Q}{192.100.0.5}{192.100.0.5:9300}]

2.5.自動起動設定(仮想マシン3台共通作業)

無事クラスタ化ができましたので、Elasticsearchサービスを自動起動するよう設定しておきます。

# chkconfig --add elasticsearch
# chkconfig --list elasticsearch
elasticsearch   0:off   1:off   2:on    3:on    4:on    5:on    6:off

3.Kibanaのインストールとx-packのインストール

次に可視化ツールのKibanaをインストールします。
また、クラスタの状態をモニタリングする為、x-packを導入します。
作業はsrv1で実施しました。

3.1.kibanaのインストール

Kibanaもインストールはとても簡単です。

# yum -y install kibana

3.2.kibana.ymlの編集

kibanaは5.0.0からリモートホストからのアクセスを受け入れない為、リモートホストからの接続が必要な場合は設定ファイル「/etc/kibana/kibana.yml」の「server.host」の修正が必要です。今回はブラウザから確認したいので、修正を行いました。

# vi /etc/kibana/kibana.yml
server.host: "0.0.0.0"

kibana.ymlもデフォルトの設定は全てコメント化されていますので、
追加したい内容を追記すればOKでした。

3.3.Kibanaの起動

# /etc/init.d/kibana start

3.4.kibanaへのアクセス

ブラウザから1号機のURLにアクセスしてみます。

http://[srv1のEIP]/5601

とりあえずはページが表示されれば問題ありません。本来の目的にはまだ届いていない為、画像は割愛します。

3.5.自動起動設定

kibanaも自動起動するようにしておきます。

# chkconfig --add kibana
# chkconfig --list kibana
kibana          0:off   1:off   2:on    3:on    4:on    5:on    6:off

3.6.x-packのインストール(仮想マシン3台共通作業)

今回の目的である、kibanaでクラスタの状態を確認する為にx-packプラグインをインストールしていきます。まずはelasticsearch用のx-packをインストールします。

kibanaを停止後、x-packインストールします。

# /etc/init.d/kibana stop
# /usr/share/elasticsearch/bin/elasticsearch-plugin install x-pack

途中y(yes)の入力が必要な為、全文を乗せておきます。

-> Downloading x-pack from elastic
[=================================================] 100%??
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@     WARNING: plugin requires additional permissions     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* java.io.FilePermission \.pipe* read,write
* java.lang.RuntimePermission accessClassInPackage.com.sun.activation.registries
* java.lang.RuntimePermission getClassLoader
* java.lang.RuntimePermission setContextClassLoader
* java.lang.RuntimePermission setFactory
* java.security.SecurityPermission createPolicy.JavaPolicy
* java.security.SecurityPermission getPolicy
* java.security.SecurityPermission putProviderProperty.BC
* java.security.SecurityPermission setPolicy
* java.util.PropertyPermission * read,write
* java.util.PropertyPermission sun.nio.ch.bugLevel write
* javax.net.ssl.SSLPermission setHostnameVerifier
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
for descriptions of what these permissions allow and the associated risks.

Continue with installation? [y/N]y
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@        WARNING: plugin forks a native controller        @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This plugin launches a native controller that is not subject to the Java
security manager nor to system call filters.

Continue with installation? [y/N]y
-> Installed x-pack

3.7.elasticsearchのx-packのsecurityを無効化する。(仮想マシン3台共通作業)

x-packには様々な機能が付属しており、securityが有効だとちゃんと設定を行わないとKibanaが起動できません。今回の目的には関係が無い為、securityを無効化することで回避します。

# vi /etc/elasticsearch/elasticsearch.yml
xpack.security.enabled: false
※上記を最下行に追記

追記後Elasticsearchを再起動して反映
# /etc/init.d/elasticsearch restart

3.8.kibanaのx-packのインストール

Kibana用x-packをインストールします。

# /usr/share/kibana/bin/kibana-plugin install x-pack
Attempting to transfer from x-pack
Attempting to transfer from https://artifacts.elastic.co/downloads/kibana-plugins/x-pack/x-pack-5.6.2.zip
Transferring 119528829 bytes....................
Transfer complete
Retrieving metadata from plugin archive
Extracting plugin archive
Extraction complete
Optimizing and caching browser bundles...
Plugin installation complete

途中止まっちゃったかな?と思いたくなるような反応が無い時間がありましたが、気にせず放置しておけば大丈夫です。

3.9.Kibanaの起動

設定が完了しましたのでKibanaを起動します。

# /etc/init.d/kibana start

設定後のプラグインの状態とライセンスの状態がどうなっているかメモしておきます。
コマンドは3台のいずれかのサーバで実行すれば確認できます。

プラグイン状態
# curl -XGET -u elastic:changeme 'http://localhost:9200/_cat/plugins?v'
name    component         version
node003 analysis-kuromoji 5.6.2
node003 x-pack            5.6.2
node002 analysis-kuromoji 5.6.2
node002 x-pack            5.6.2
node001 analysis-kuromoji 5.6.2
node001 x-pack            5.6.2
ライセンス状態
# curl -XGET -u elastic:changeme 'http://localhost:9200/_xpack/license'
{
  "license" : {
    "status" : "active",
    "uid" : "7977deb4-d253-4ef4-8fd1-bf01e1d86315",
    "type" : "trial",
    "issue_date" : "2017-xx-xxTxx:xx:xx.537Z",
    "issue_date_in_millis" : 1506590395537,
    "expiry_date" : "2017-xx-xxTxx:xx:xx.537Z",
    "expiry_date_in_millis" : 1509182395537,
    "max_nodes" : 1000,
    "issued_to" : "my-cluster",
    "issuer" : "elasticsearch",
    "start_date_in_millis" : -1
  }
}

4.kibanaからクラスタ状態を確認

それでは最後にkibanaの画面を確認します。

ブラウザから1号機のURLにアクセスします。
http://[srv1のEIP]:5601

表示された画面の左ペインにある、Monitoringを選択します。
es-monitoring.png

遷移後の画面の真ん中にある、Noedsを選択します。
es-monitoring2.png

Kibanaの画面上からクラスタの状態が確認できました。
es-monitoring3.png

Kibanaの画面上から確認できるようになると、すごくできた感があります。
次回は肝心のログデータの取り込みなんかをメモしたいと思います。

続きを読む

DatadogでJavaのメトリクスを取得する

JavaアプリケーションのパフォーマンスをDatadogで可視化しようとしたときにハマったので、
誰かの役に立てばと思い、残しておきます。

やりたかったこと

  • JVMHeap使用状況などのメトリクスを取得したかった。

公式ドキュメントは以下にあるので、ドキュメントを参考にやってみます。
JMX Checks

JavaのIntegrationを有効にする

DatadogはデフォルトではJavaのメトリクスを取得するようになっていません。
なので明示的に設定をOnにする必要があります。
サイドバーのIntegrationから、Javaを検索し設定をOnにします。
Setup___Datadog.png

availableをクリックし詳細画面からinstall integrationをクリック

Setup___Datadog.png

jmx.yamlを追加

次にdatadog-agentをinstallしたサーバ内に入り、Javaが動いているサーバの情報をdatadog-agentに教えてあげる必要があります。

datadog-agentはデフォルトで様々なintegrationのコンフィグファイル例を用意してくれており、今回はそれをコピーしてそのまま使います。

$ cp /etc/dd-agent/conf.d/jmx.yaml.example  /etc/dd-agent/conf.d/jmx.yaml
$ vim /etc/dd-agent/conf.d/jmx.yaml
/etc/dd-agent/conf.d/jmx.yaml
init_config:
instances:
-   host: localhost
    port: 7199

port: 7199など気になる設定はありますが、そのまま使用します。

datadog-agentをrestartする

設定ファイルを変更した際はagentをrestartすると変更した設定が読み込まれます。

$ sudo /etc/init.d/datadog-agent restart

だが値は取れない

dashboardを作成したときに、jmx.hogehogeが候補として出てくることを期待するが出てこない。
Listenしてないportなどを指定していたので当たり前といえば当たり前です。

結論から言うとJavaアプリケーション起動時にJMXのポートを公開しておかないと値が取れません。
JMXとは何かという方は以下を参照してください。
JMX について

起動時に以下のオプションを追加する。

# jmxをonにする
-Dcom.sun.management.jmxremote
# jmxの情報を取得できるportを指定します。jmx.yamlで指定したportはここでの設定したportになります
-Dcom.sun.management.jmxremote.port=7199
# 通信時にsslをonにするかどうか。今回はlocalhostでの通信なのでOffにします。
-Dcom.sun.management.jmxremote.ssl=false
# password認証をするか
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=true

追加すると

jvmがプレフィックスにつくメトリクスが、Datadogのコンソール上に表示されるようになりました。
biz-prd-elb__created_via_Terraform____Datadog.png

続きを読む

Amazon Aurora のアップグレード

概要

Aurora 1.14 強制アップグレード通知が来たので、AWSドキュメントの隙間をAWSサポート様に聞いたことをまとめる。

Amazon Aurora は定期的に更新をリリースします

更新の案内
https://forums.aws.amazon.com/forum.jspa?forumID=60

過去の更新履歴
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.html

更新(アップグレード)必須のものもあれば、利用者の判断に任せる場合もある。
最近だと、
・Aurora バージョン 1.13 ・・・必須ではありません。
・Aurora バージョン 1.14 ・・・既存の Aurora DB クラスターの必須アップグレードです。

アップグレードします(しなさい)アナウンスは、事前にAWSからメール通知がくる。
利用者の準備や検証期間を考慮しているので期間的にかなり余裕(猶予)がある。

アップグレード開始方法

方法1
 利用者が任意のタイミングで手動でアップグレードを開始する

方法2
 「次のメンテナンスウィンドウ」内でアップグレードを実施する設定をする
 (メンテナンスウィンドウの時間はUTCなので注意)

ZDP (zero-downtime-patching) とは

Aurora バージョン 1.10 から追加された機能
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.20161214.html

通常のアップグレードはインスタンスの再起動が発生するが、ZDPは再起動せずにアップグレードが完了する。
・通常のアップグレード・・・対象インスタンスを再起動するため対象のAuroraインスタンスが
 20〜30秒ダウンする。
・ZDPのアップグレード・・・対象インスタンスを再起動しない。スループットが一時的に (5 秒ほど) 低下
 しますが、アプリケーションセッションは保持されます。

ZDPは Writer インスタンスのみ利用できる。ReaderインスタンスはZDP適用外。

 単一ノード DB クラスター、または、複数ノード DB クラスターの書き込みインスタンスへのパッチに適用されます。 
 ZDP は クラスターのプライマリ DB インスタンスにのみ適用されます。ZDP は Aurora レプリカには適用できません。

 ↓
 単一ノード DB クラスター ⇒ プライマリインスタンスのみ(Writer+Reader)のAuroraクラスター
 複数ノード DB クラスターの書き込みインスタンス ⇒ 複数ノード構成のAuroraクラスターの Writer インスタンス

ZDP は、Writerノードのインスタンスが以下の状態では正常に実行されません。
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.20170515.html

 実行時間が長いクエリが進行中である
 実行時間が長いトランザクションが開いている
 バイナリログ記録が有効になっている
 バイナリログのレプリケーションが実行中である
 パラメータの変更が保留中である
 一時テーブルが使用中である
 テーブルロックが使用中である
 オープン SSL 接続がある

 ※バイナリログ記録が有効になっている
  Auroraは、Writeノードに限りバイナリログを出すことができる。
  Auroraのクラスターパラメータグループに「binlog_format MIXED」というような設定が入っている状態のこと

ZDPが発動するか事前に確認するコマンドや表示項目はないし、AWSサポートに聞いてもわからない。利用者がZDP発動条件に当てはまるのかどうかを確認しないとならず、実際にアップグレードを実施してみないとZDPアップグレードなのか、通常の再起動アップグレードなのかわからない。

ZDP は発動条件を満たしていれば必ずZDPアップグレードが実施される。逆に言うと、ZDP発動条件を満たしていれば、ZDPを無効にして意図的に通常の再起動アップグレードを実施させることはできない。

Aurora アップグレード動作

Aurora バージョン 1.13 から「クラスターパッチ適用モデル」機能が追加された。このモデルでは Aurora DB クラスター内のすべてのノードに同時にパッチが適用されます。このモデルでアップグレードされるのかどうかは、更新の内容次第。
最近だと、
・Aurora バージョン 1.13 ・・・Aurora のバージョン 1.13 では、クラスターパッチ適用モデルを使用しており、
・Aurora バージョン 1.14 ・・・Aurora のバージョン 1.14 では、クラスターパッチ適用モデルが使用されており、

クラスターパッチ適用モデル

アップグレードを処理を開始すると、対象クラスター内の全ノードのアップグレードが開始される。特定のノードだけをアップグレードさせることはできない。

アップグレードが開始されると、最初に Writer からアップグレードされ、その後に Reader がアップデートされる。Readerが複数ある場合、全Readerは同じタイミングでアップグレードが開始される。

ZDP発動条件を満たしている Writer と複数 Reader という Auroraクラスター構成の場合
 (1) Writer インスタンスは ZDP アップグレード
 ・対象の Writer インスタンスのダウンタイムなし。スループットが一時的に (5 秒ほど) 低下するだけ。
 (2) 全Reader インスタンスが同時に再起動アップグレード
 ・全 Reader インスタンスは20〜30秒のダウンタイムが発生する。
 ・全 Reader ノードが同じタイミングでアップグレード開始するので、Readerのノード数に関係なく、
  ダウンタイムはは20〜30秒ほど。
 ※クラスター全体のダウンタイムは Reader のアップグレード時間(バッファーを考慮して数分くらい?)
 ※更新系は助かるけど、参照系は助からない。

ZDP発動条件を満たしていない Writer と複数 Reader という Auroraクラスター構成の場合
 (1) Writer インスタンスは再起動アップグレード
 ・20〜30秒のダウンタイムが発生する。
 (2) 全 Reader インスタンスが同時に再起動アップグレード
 ・全 Reader インスタンスは20〜30秒のダウンタイムが発生する。
 ・全 Reader ノードが同じタイミングでアップグレード開始するので、Readerのノード数に関係なく、
  ダウンタイムはは20〜30秒ほど。
 ※クラスター全体のダウンタイムは Writer のアップグレード時間+Reader のアップグレード時間
  (バッファーを考慮して数分くらい?)
 ※更新系も、参照系も助からない。

アップグレードの際に発生する再起動では、フェイルオーバーは発生しない。当然、ZDPアップグレードでも、
フェイルオーバーは発生しない。

上記のアップグレードの動作は、手動でアップグレードを実施した場合も、メンテナンスウィンドウ内で
アップグレードが実施される場合も同じ

続きを読む