Spring bootのアプリケーションが入ったコンテナをサーバーにのせる機会があったのですがkubernetesとっても便利ですね。dockerのimageさえ使っておけばpodの設定ファイルで簡単にひょいっとサーバーをたてられちゃいますね。バッチ用のコンテナを入れてjobを作ったりcronを作ったりするのもとっても簡単。
これはどんどんコンテナ増えていきますね。
それはいいけど設定変更をしたい場合どうしたものか、、、
たくさんあるコンテナをうちから対象のコンテナ探してコンテナに入って設定変えて再起動・・・
コンテナを作り直して・・・
いやいやそんなことはさすがにできないか。
ということで、Spring cloud configを使って設定ファイルを集約したいと思います。
Spring cloud configは簡単にいうとapplication.propertiesなどの設定ファイルを
gitから取得してAPIとして提供してくれるサーバーとそれを自動的に受け取ってくれるクライアント側の処理を行ってくれる機能です。
(kubernetesの部分は一旦無視しても大丈夫です)
application.propertiesを各システム内に持たずにSpring cloud configのサーバーから取得するようにします。
こうすることで設定変更はgitにコミットして以下で反映するだけですみます。
http://xxxxxx/refresh
DI済みの場合は
http://xxxxxx/restart
どういう使い方をするか
これについては本来のやり方と違うところもあるかもしれませんが以下のように考えました。
複数システムの設定を別々のリポジトリで管理したくないし、
Spring cloud configのサーバーをいくつもたてたくはない。
そういう場合にどういうやり方があるのか。
以下のように2つのシステムがあるとしてサンプルを作ってみました。
システム |
---|
system abc |
system def |
サンプルソース
Spring cloud configのサーバー(設定ファイルの情報のAPI)
https://github.com/ewai/spring-cloud-config-server
Spring cloud configのクライアント(何かしらのシステム)
https://github.com/ewai/spring-cloud-config-client
設定ファイルが格納されいてるgitリポジトリ
https://github.com/ewai/spring-cloud-config-file
設定ファイルが格納されいてるgitリポジトリ
システムごとのディレクトリ | システムごとの設定ファイル |
---|---|
system-abc | application-abc.properties |
system-def | application-def.properties |
というようにシステムごとのディレクトリをきってその中にシステムごとの設定ファイルを置きます。
application-XXX.properties
の
XXXの部分はdevとかproductionとかで分ける情報が多かったですが、
これでシステム分けてしまおうという考えです。
これらの設定ファイルをどのようにしてSpring cloud configであつかうか。
サーバー
Spring Initializrでテンプレートを作ったら少し修正するだけです。
Clound config > Config server だけで構成できます。
dependencies {
compile('org.springframework.cloud:spring-cloud-config-server')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
アノテーション追加
@SpringBootApplicationの上か下に@EnableConfigServerを追加。
設定追加
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/ewai/spring-cloud-config-file.git
# これらのパスから設定ファイルを探します
spring.cloud.config.server.git.search-paths=system-abc,system-def
# セキュリティ的に問題なければこれをつければいろいろなendpointが使えるようになります。
management.security.enabled=false
もっと考慮することがあるのかもしれませんが、
サーバーは以上で動作します。
パスワードとかも入ってくるので暗号化のあたりはやっておきたいですが、
一旦そのまま進みます。
起動して以下をたたくと
http://localhost:8888/application/abc
{
"name":"application",
"profiles":[
"abc"
],
"label":null,
"version":"a485a58b6fc441fd55c0d87a470d1bbbb89d765c",
"state":null,
"propertySources":[
{
"name":"https://github.com/ewai/spring-cloud-config-file.git/system-abc/application-abc.properties",
"source":{
"demo.data":"demo demo demo...",
"system.name":"system-abc"
}
}
]
}
defにしてみると、
http://localhost:8888/application/def
{
"name":"application",
"profiles":[
"def"
],
"label":null,
"version":"a485a58b6fc441fd55c0d87a470d1bbbb89d765c",
"state":null,
"propertySources":[
{
"name":"https://github.com/ewai/spring-cloud-config-file.git/system-def/application-def.properties",
"source":{
"demo.data":"demo demo demo...",
"system.name":"system-def"
}
}
]
}
動作確認完了。
クライアント側の何かしらのシステム
このサンプルはSpring Initializrでテンプレートから作りました。
Clound config > Config client
Web > Web
だけで構成できます。
既存システムであれば以下の追加でよいと思います。
compile('org.springframework.cloud:spring-cloud-starter-config')
このサンプルでは設定ファイル読み込み用のコンフィグクラスを作りました
@Component
public class ApplicationConfig {
@Value("${demo.deta:not-found}")
private String demo;
@Value("${system.name:not-found}")
private String systemName;
public String getDemo() {
return demo;
}
public void setDemo(String demo) {
this.demo = demo;
}
public String getSystemName() {
return systemName;
}
public void setSystemName(String systemName) {
this.systemName = systemName;
}
}
手抜きですみませんが、
このようにApplicationConfigから簡単に設定を取り出せます。
@SpringBootApplication
@RestController
public class SpringCloudConfigClientApplication {
@Autowired
ApplicationConfig config;
public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigClientApplication.class, args);
}
@RequestMapping("/system")
public String test() {
return config.getSystemName();
}
}
設定は以下です。
# 先ほどのサーバーをローカルでたてておくならこれでよい
spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.name=application
spring.cloud.config.profile=abc
ポイントはここです。
spring.cloud.config.profile=abc
abcとしておくことでsystem-abc/application-abc.propertiesが読み込まれます。
[spring.cloud.config.name]-[spring.cloud.config.profile].properties(yaml)
というフォーマットで形成されるようです。
サーバーからはapplication-abc.propertiesでも、application-def.propertiesでもどちらでも読み込むことができるようになっていますがこの設定をすることでabcの方を使うことができるのです。
サーバーから1回読み込み終わって入ればサーバー側がダウンしていても問題なく動くようです。
が、ある程度の冗長化構成を検討しておいた方がよいかもしれません。
以上になります。
※ propertiesではなくyamlでもできます。
※ ドキュメントの詳細までは読んでいないのでもっと良いやり方があれば教えてください。