golangでSQSのqueueの一覧を取得しようとしたときこんなふうに書くことができる.

package main

import (
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/sqs"
)

func main() {
	c := &aws.Config{
		Region: aws.String("ap-northeast-1"),
	}

	svc := sqs.New(session.Must(session.NewSession(c)))

	list, err := svc.ListQueues(&sqs.ListQueuesInput{})
	if err != nil {
		panic(err)
	}

	fmt.Println(list.String())
}

このように書いた場合 github.com/aws/aws-sdk-go/aws/credentials とか github.com/aws/aws-sdk-go/aws/stscredes とかを利用していない.
つまり利用されるawsのアクセス権限の元になる情報は ~/.aws 以下に設定された情報だったり ECSの場合はtaskRoleARNに設定された情報となる.

私が上記の実装をした上でdocker containerをビルドして実行したときハマったことを書こうと思う.

ECSは標準出力の内容をcloud watch logsに出力することができる.
上記の実装を実行したと気次のようなエラーが出力された.

For verbose messaging see aws.Config.CredentialsChainVerboseErrors
panic: NoCredentialProviders: no valid providers in chain. Deprecated.

はじめはtask roleにsqsのアクセス権限を忘れたことによって発生していた問題かと思ったが違った.

ECS上でコンテナを動かしたとき特に何もしない場合はtask roleで設定した情報を元に権限が設定される.
実際のところ裏側ではAWS SDK側で 169.254.170.2 にアクセスしてメタ情報からクレデンシャル情報を引っ張ってくる.
httpでrest apiを叩いて情報を取得しているのでネットワークに問題があると情報を取得できない.

今回問題が発生していたと気task definitionのnetowork modeを None に設定してしまっていた.
なのでメタ情報にアクセスができずにエラーになってしまった.

対処方法としてはnetwork modeを bridge にした.

これで晴れてSQSのAPIを叩くことができた.

今回はgolangでハマったがおそらく違う言語のときも気をつけないと同じようにハマると思う.

細かい仕様に関しては公式の情報によってまとめられている.
Amazon ECS タスクメタデータエンドポイント