AWS SDKでAuthFailure【cloudpack 大阪 BLOG】

発生した障害

boto(python)で定期的にS3にファイルをアップロードしているスクリプトが突然エラーとなり実行できなくなる問題に遭遇しました。
エラーログを確認すると「403 Forbidden」が発生していました。

調査したこと

何らかの原因で使用しているアクセスキーが有効でなくなった可能性をがあると想定しましたが問題なし。
ポリシーも確認しましたが権限は問題なし。
ざっと見たところ原因分からず。

問題の切り分け

同じ権限を持ったユーザーを再作成して試したところ上記と同様のエラーとなる
ここでS3にエラーが発生してないか気になりヘルスチェックを確認しましたがこちらも問題なし
一応、再作成したユーザーが本当に正しい権限が付与されているか確認するためにaws cliを手動で実行したところ下記エラーが発生しました。

An error occurred (AuthFailure) when calling the DescribeInstances operation: AWS was not able to validate the provided access credentials

認証失敗とありますが、あまり見慣れていないエラーが発生していたため即ググったところ、OSの時間がずれていることが原因らしいことが判明。OSの時刻を確認すると確かに20分ほどずれており、ntpで正常に同期できていませんでした。手動で時刻同期して再度aws cliを実行すると正常に実行できました。
その後定期スクリプトを再度実行したところ正常に終了しました。

参考ページ
awscliはOS内の時間が狂ってるとAuthFailureが出る | hacknote
これをやると http://qiita.com/sonots/private/4d5dbec2b12621ef27e9 こうなる · GitHub

上記のページを確認するとOSの時刻がずれているとAPIの認証が通らないようです。
AWSのドキュメントにも以下の記載がありました。

AWS CLI、または AWS SDK を使用してインスタンスからリクエストを行う場合、これらのツールによって
自動的にリクエストに署名されます。
インスタンスの日時が正しく設定されていない場合、署名の日付がリクエストの日付と一致しないことがあり、
その場合は AWS によってリクエストが却下されます。

Linux インスタンスの時刻の設定 - Amazon Elastic Compute Cloud

AWS CLISDKを使用する場合は気をつける必要がありますね。

AutoScalingでEC2のDetach/StandByができない場合の対処法【cloudpack 大阪 BLOG】

はじめに

AutoScalingを設定していて手動で設定を変更していると、たまに台数がずれるなどして最低台数の制限に引っかかりAutoScalingGroupからEC2をDetachやStandByにできない場合があります。スケーリングポリシーに基づいてインスタンスの増減が実施されていればほぼ発生しないと思いますが、メンテナンスやインスタンスの入れ替えなどを手動で実施すると発生する場合があります。今回はこうしたケースの対処法を紹介しようと思います。

Detachできない状態

AutoScalingGroupには3台紐付いていますが、DesiredとMinがそれぞれ2台となっています。
f:id:cloudfish:20170303154435p:plain

1台をDetachしてAutoScalingGroupを2台にしたいのですが、この状態でDetachを実施すると、
Desiredが2から1に変わりMinを下回ることからエラーとなります。
f:id:cloudfish:20170307100751p:plain

対応方法

Desiredを2から3に変更した後にDetachできればいいのですが、普通に変更するとインスタンスが新規に追加されてしまいます。
対応としては以下のように「Suspended Processes」でLaunchを設定します。こうすることでAutoScalignGroupの設定を変更しても新規にインスタンスの追加が実行されません。この状態にしてからDesiredを3に変更します。
f:id:cloudfish:20170307101316p:plain

正しく設定が完了すれば以下のようにAutoScalignGroupのインスタンス数が変わらずDesiredが3になります。
この状態で再度、対象インスタンスをDetachすると問題なく実行できるはずです。
f:id:cloudfish:20170307101420p:plain

Detach完了後です。正常にDetachが完了しました。
f:id:cloudfish:20170303154600p:plain

AutoScalingは便利な機能ですが、手動でインスタンスを制御しようとすると思わぬ動作をしてインスタンスの削除や追加が実行されます。追加はともかく削除は困ることが多いと思いますので手動で何かをする際は事前にしっかりと検証したほうがいいと思います。

起動後のEC2にIAM Roleを付与する【cloudpack 大阪 BLOG】

待望の機能追加があったので実際にやってみました。
これまで起動後のec2インスタンスにはiam-roleが付与できなくて不便な思いをしてきましたがやっと開放されそうです

現時点ではawscliからのみしかできません。
またawscliの更新が必要になりますので気をつけてください。

以下に手順を記載します。ec2にアタッチするroleについては作成されているものとします

①roleアタッチ

aws ec2 associate-iam-instance-profile --instance-id ${InstancdId} --iam-instance-profile Name=${profile_name}

②アタッチ確認

aws ec2 describe-iam-instance-profile-associations

③roleデタッチ

aws ec2 disassociate-iam-instance-profile  --association-id ${associationId} 

※${associationId}については②で確認できます

また、stop中のインスタンスについては、画面のEC2のrole項目は更新されませんでしたが、起動後に正しく表示されました。

rsyslogで中継サーバ経由してログ送信を行う【cloudpack 大阪 BLOG】

以下のような構成でrsyslogを使用してログをログ収集サーバへ集約させる要件がありました。
検証で動作確認を実施してみたので、備忘録としてやり方を残しておきたいと思います。

f:id:cloudfish:20170126190943p:plain,w400,h250

やりたいこと

webサーバの/var/log/messagesをログ中継サーバを経由させてログ収集サーバへ送信する
ユースケースとしてはログ収集サーバが別のVPCや外部DCにあるケースを想定しています。

構成

サーバ IP
webサーバ 172.31.0.1
中継サーバ 172.31.0.2
ログ収集サーバ 172.31.0.3

webサーバの設定

■/etc/rsyslog.config

*.info;mail.none;authpriv.none;cron.none                /var/log/messages
*.info;mail.none;authpriv.none;cron.none                @@172.31.02      ←追加

# 以下コメントを解除(73-78行目)
$WorkDirectory /var/lib/rsyslog # where to place spool files
$ActionQueueFileName fwdRule1 # unique name prefix for spool files
$ActionQueueMaxDiskSpace 1g   # 1gb space limit (use as much as possible)
$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
$ActionQueueType LinkedList   # run asynchronously
$ActionResumeRetryCount -1    # infinite retries if host is down

中継サーバの設定

■/etc/rsyslog.config

# 以下コメントを解除
$ModLoad imtcp
$InputTCPServerRun 514

$AllowedSender TCP, 127.0.0.1, 172.31.0.0/24   ←送信元を指定

*.info;mail.none;authpriv.none;cron.none                /var/log/messages
*.info;mail.none;authpriv.none;cron.none                @@172.31.03       ←追加

#コメントを解除(73-78行目)
$WorkDirectory /var/lib/rsyslog # where to place spool files
$ActionQueueFileName fwdRule1 # unique name prefix for spool files
$ActionQueueMaxDiskSpace 1g   # 1gb space limit (use as much as possible)
$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
$ActionQueueType LinkedList   # run asynchronously
$ActionResumeRetryCount -1    # infinite retries if host is down

ログ収集サーバの設定

■/etc/rsyslog.config

# 以下コメントを解除
$ModLoad imtcp
$InputTCPServerRun 514

$AllowedSender TCP, 127.0.0.1, 172.31.0.0/24   ←送信元を指定

#フォーマット指定
$template message_log,"/var/log/message.d/%fromhost%_%$year%%$month%%$day%.log"   ←追加
*.info;mail.none;authpriv.none;cron.none     -?message_log             ←追加

上記設定後にwebサーバでmessagesにログを出力し、ログ収集サーバに転送されていれば正常に設定されています。

logger logtest

Terraformで[Error reading config for xxxx : Invalid dot index found:]エラー【cloudpack 大阪 BLOG】

最近Terraformを触っていて少し躓いたので備忘録として残しておこうと思います。
現象としては、mapping定義にドットで参照しようとしてエラーが発生しました

variable "vpc_subnet_cidr" {
     default = {
       public-a  = "10.1.10.0/24"
       public-c  = "10.1.20.0/24"
       private-a = "10.1.100.0/24"
       private-c = "10.1.200.0/24"
     }
}

上記のようなmapping定義に対して以下のように変数を参照したとことタイトルのエラーが発生しました。

output "cidr" {
  value = "${var.vpc_subnet_cidr.public-a}"
}


発生したエラーの全文です。

Error loading config: Error loading terraform_test/main.tf: Error reading config for output cidr: Invalid dot index found: 'var.vpc_subnet_cidr.public-a'. Values in maps and lists can be referenced using square bracket indexing, like: 'var.mymap["key"]' or 'var.mylist[1]'. in:

エラーメッセージ内容から下記のように書き直せばいいのは分かるのですが、別案件で稼働実績のあるソースを持ってきたので何故動かないのか気になりました。

output "cidr" {
  value = "${var.vpc_subnet_cidr["public-a"]}"
}

調べてみるとCHANGELOGに記載がありました。
terraform/CHANGELOG.md at master · hashicorp/terraform · GitHub

原因はterraformのバージョン違いによるものでした。別案件で使用していたterraformは0.6系でしたが自分が利用している
terraformは0.7でした。後方互換のない変更がはいったようです。

f:id:cloudfish:20161222025343p:plain

基本的な参照方法を変更するとはなかなか思い切った変更ですね。
0.6系で作ったterraformソースを0.7以降で利用する場合は気をつける必要がありそうです。

Json形式からYaml形式に変換するWebサービスを作った【cloudpack 大阪 BLOG】

タイトルのとおりなんですが、json形式をyaml形式に変換するWebサービスを作りました。
きっかけは、CloudFormationがyaml対応したのでyaml形式で書き初めたのですが、AWSのユーザーガイドにjson形式しか記載されていなかったので、手軽に変換できるようにWebサービスを作りました。

作ったサービス

j2y.link

使い方

JSONのテキストエリアに変換したいデータを貼るとYAMLのテキストエリアに変換されて表示されます。ちなみにjavascriptで変換しているためサーバーへデータはアップしていません。
f:id:cloudfish:20161024144300p:plain

YAMLのすぐ横にあるアイコンをクリックすると結果をコピーできます。
f:id:cloudfish:20161024144423p:plain:w400

このサービスを公開した直後に、CloudFormationのユーザーガイドを確認したところ、YAMLのサンプルも表示されているという切ない結果になりましたが、jsonyamlに変換するという需要はあると思いますのでぜひ使ってみていただけたらと思います。

AWS Certificate Managerでサブドメインを発行する時に承認メール送信先を変更する【cloudpack 大阪 BLOG】

AWS Certificate Managerで証明書を発行する際のドメイン認証については、現在、メール承認のみとなっています。
例えばexample.comサブドメインSSL証明書を発行した場合で、ドメイン管理者が管理者のメールアドレスを公開していないと、デフォルトで以下のようにサブドメインがメールドメインの宛先に承認確認メールが送信されてしまいます。この場合メールを受信できないことが多いため、これをメインドメインへ承認メールを送信する方法を紹介します。

サブドメイン
 stg.example.com
◆メール送信先
 admin@stg.example.com
 postmaster@stg.example.com
 administrator@stg.example.com
 webmaster@stg.example.com
 proxy@whoisprotectservice.com
 hostmaster@stg.example.com

現在、AWSコンソールからは制御ができませんので、aws cliを使用してACMを発行します。

発行対象ドメイン:stg.example.com
メール送信先対象ドメイン:example.com

とした場合、以下のようなコマンドで発行が可能です。

aws acm request-certificate \
 --domain-name stg.example.com \
 --domain-validation-options DomainName=stg.example.com,ValidationDomain=example.com

エラーがでなければ、AWSコンソールから発行したACMについて、承認メール送信先が意図したものとなっているか確認してください


よくある質問 - AWS Certificate Manager(簡単に SSL/TLS 証明書を作成、管理、配置) | AWS
request-certificate — AWS CLI 1.10.67 Command Reference