Spring Bootのアプリケーション起動時に、AWS Systems Manager パラメータストアからパラメータを取得できるみたいなので試してみました。
AWS Systems Manager パラメータストアとは
設定データ管理と機密管理のための安全な階層型ストレージを提供してくれていて、パスワード、データベース文字列、AMI ID、ライセンスコードなどのデータをパラメータ値として保存できます。値はプレーンテキストまたは暗号化されたデータとして保存できます。詳しい説明は、公式ドキュメントを見てください。
サンプル
環境
Spring Boot等のバージョンは次の通りです。
Java 11
Gradle 6.6.1
Spring Boot 2.3.4.RELEASE
Spring Cloud Hoxton.SR8
パラメータの登録
登録するパラメータのkey
デフォルトだと次のような3階層で設定するようになっています。
[prefix]/[name]_[アプリケーションのprofile(defaultの場合は省略可)]/[key]
設定値の抜粋です。(値はデフォルト値)
- パラメータストアから取得される全プロパティで共有されるプレフィクス。第1階層の値。
- aws.paramstore.prefix=/config
- 全サービスで共有されるコンテキスト名。第2階層の値。
- aws.paramstore.default-context=application
- コンテキスト名とプロファイルの区切り文字.
- aws.paramstore.profile-separator=_
- パラメータストアを利用するかどうか
- aws.paramstore.enabled=true
取得するパラメータを組み立てているロジックは AwsParamStorePropertySourceLocator#PropertySource<?> locate(Environment) にあります。
パラメータストアへの登録
パラメータストアにパラメータを登録します。今回は、DBへのアクセス情報を登録します。
/config/sample/spring.datasource.url=jdbc:mysql://localhost:33306/sample
/config/sample/spring.datasource.username=docker
/config/sample/spring.datasource.password=docker
依存関係
パラメータストアを利用するために追加する依存関係はこれだけです。
build.gradle
dependencies { | |
... | |
implementation 'org.springframework.cloud:spring-cloud-starter-aws-parameter-store-config:2.2.4.RELEASE' | |
... | |
} |
設定ファイル
appliaction.yml(application.properties)には何も書かなくてOKですが、bootstrap.ymlにいくつか設定を書く必要があります。
bootstrap.ymlの全体
spring: | |
datasource: | |
url: | |
username: | |
password: | |
cloud: | |
aws: | |
stack: | |
auto: false | |
region: | |
auto: false | |
static: ap-northeast-1 | |
aws: | |
paramstore: | |
region: ${cloud.aws.region.static} | |
default-context: sample | |
logging: | |
level: | |
com: | |
amazonaws: | |
util: | |
EC2MetadataUtils: error |
パラメータストアから取得するのでkeyのみ書きます。
spring: | |
datasource: | |
url: | |
username: | |
password: |
ローカル環境でSpring Cloud AWSを使うためのおまじないです。アプリケーション起動時にメタデータからリージョン等を取得するのですが、ローカル環境だと取得に失敗してアプリケーションが起動しなくなってしまうために無効にしています。詳しくは、Configuring region と CloudFormation configuration in Spring Boot にあります。
cloud: | |
aws: | |
stack: | |
auto: false | |
region: | |
auto: false | |
static: ap-northeast-1 |
spring-cloud-starter-aws-parameter-store-configの設定です。
aws: | |
paramstore: | |
region: ${cloud.aws.region.static} | |
default-context: sample |
EC2MetadataUtilsがAWS上で動いているか取得しますが、AWS環境以外でのアプリケーション起動時にエラーログを出してしまって気持ち悪いので設定します。(なくても動作には何も問題ないです)
logging: | |
level: | |
com: | |
amazonaws: | |
util: | |
EC2MetadataUtils: error |
アプリケーションの起動
あとはアプリケーションを起動するだけです。
どのパラメータをパラメータストアから取得しているかを確認したい場合は、次の設定をbootstrap.ymlに書いてください。
logging:
level:
org:
springframework:
cloud:
aws:
paramstore:
AwsParamStorePropertySource: debug
設定するとログにこんな感じで出力されます。
2020-10-11 18:35:27.847 DEBUG 55136 --- [ main] o.s.c.a.p.AwsParamStorePropertySource : Populating property retrieved from AWS Parameter Store: spring.datasource.password
2020-10-11 18:35:27.849 DEBUG 55136 --- [ main] o.s.c.a.p.AwsParamStorePropertySource : Populating property retrieved from AWS Parameter Store: spring.datasource.url
2020-10-11 18:35:27.849 DEBUG 55136 --- [ main] o.s.c.a.p.AwsParamStorePropertySource : Populating property retrieved from AWS Parameter Store: spring.datasource.username
プロファイルで設定値を分ける
一般的に、defaultプロファイルしか存在しないことはないかと思います。testプロファイルでは、テスト環境用のDBアクセス情報を取得するみたいなことも可能です。
パラメータストアへの登録
パラメータストアへの登録の仕方については上で説明したので省略します。 これらを登録します。
/config/sample_test/spring.datasource.url=jdbc:mysql://localhost:33307/sample
/config/sample_test/spring.datasource.username=test
/config/sample_test/spring.datasource.password=test
アプリケーションの起動
アクティブプロファイルをtestにして、起動するだけで、 /config/sample_test/*
のパラメータを取得してくれます。
デフォルトプロファイルの/config/sample/
を読み込んでそのあとに/config/sample_test
で上書きするようです。
まとめ
思っていたよりは簡単にできました!AWSのプロファイルはdefault
が使われるので変更したい場合は自前で設定書かないといけないみたいです。
ちなみに設定値の優先順位は パラメータストア > bootstram.yml > application.yml でした。bootstrap.ymlとかapplication.ymlに同じ設定書いてあってもパラメータストアに設定している場合は、パラメータストアの値が優先されます。