はじめに
Spring Cloud Kubernetes は Kubernetes ネイティブ API を使用した Spring Cloud の共通インターフェイスの実装で、次の 4 つの Spring Boot Starter がある。
spring-cloud-starter-kubernetes:
Kubernetes Service からサービス名を解決する Discovery Client の実装。
spring-cloud-starter-kubernetes-config:
Kubernetes ConfigMap と Secret から application properties を読み込む。
ConfigMap または Secret が変更されたときに application properties をリロードすることも可能。
spring-cloud-starter-kubernetes-ribbon:
Kubernetes Endpoint からサーバリストを取得するクライアントサイドロードバランサー(Ribbon)。
spring-cloud-starter-kubernetes-all:
上記すべてを含む Starter
今回は、Playing with Sping Boot on Kubernetes を参考に Kubernetes の世界観に触れつつ、Spring Cloud Kubernetes を使ってみる。
使用するのは上記 4 つの Starter のうち spring-cloud-starter-kubernetes-config のみ。
公式ドキュメントをみて、Kubernetes のアーキテクチャや登場するオブジェクトの名前はおさえておく。
https://kubernetes.io/docs/concepts/
環境
Mac OS X
1. ローカル環境に Minikube を構築する
https://kubernetes.io/docs/tasks/tools/install-minikube
仮想化が Mac OS で有効になっているかをチェック。
sysctl -a | grep -E --color 'machdep.cpu.features|VMX'VMX が赤字で出力されれば VT-x 機能が有効になっているので OK。
kubectl のインストール
https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-on-macos
brew install kubernetes-cli
VirtualBox のインストール
brew cask install virtualbox
Minikube のインストール
brew cask install minikube
Minikube の起動と Cluster の作成
minikube start
ダッシュボードを見る
minikube dashboard
2. アプリケーションを作る
Spring Initializr でひな形を作成する
spring init \ --dependencies=data-jpa,data-rest,actuator,h2,devtools,lombok \ --groupId=sample \ --artifactId=spring-k8s-sample \ --boot-version=2.2.0.BUILD-SNAPSHOT \ --name=Sample \ --package-name=sample \ spring-k8s-sample
NOTE: spring init --list でサービスが一覧できる
IntelliJ IDEA でプロジェクトを開く
idea spring-k8s-sample/
NOTE: コマンドラインから IntelliJ IDEA を開くためには事前に Tools > Create Command-line Launcher を設定しておく。
Entity を作る
src/main/java/sample/Customer.java
@Entity
@Data
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String email;
}Repository を作る
src/main/java/sample/CustomerRepository.java
public interface CustomerRepository extends JpaRepository<Customer, UUID> {
}Spring Boot を起動する
./mvnw spring-boot:run
Customer を登録してみる
curl -X POST http://localhost:8080/customers \
-H 'Content-Type: application/json' \
-d '{
"name": "東方仗助",
"email": "jojo@example.com"
}'Customer を一覧してみる
curl -X GET http://localhost:8080/customers
結果
{
"_embedded" : {
"customers" : [ {
"name" : "東方仗助",
"email" : "jojo@example.com",
"_links" : {
"self" : {
"href" : "http://localhost:8080/users/ed063906-e072-471f-b903-c15dd7ca72d6"
},
"user" : {
"href" : "http://localhost:8080/users/ed063906-e072-471f-b903-c15dd7ca72d6"
}
}
} ]
},
...SKIP...
}3. PostgreSQL の構築
Minikube で作成した Kubernetes Cluster 上に PostgreSQL を構築してみる。
ConfigMap を作成する
kubectl create configmap postgres-config \ --from-literal=postgres.service.name=postgresql \ --from-literal=postgres.db.name=sample
確認する
kubectl get cm postgres-config -o json
Secret を作成する
kubectl create secret generic db-security \ --from-literal=db.user.name=sample \ --from-literal=db.user.password=password
確認する
kubectl get secret db-security -o json
PostgreSQL をデプロイする
PostgreSQL をデプロイするための Kubernetes リソースファイルを作成する。
src/k8s/postgres.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: postgresql
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
app: postgresql
spec:
volumes:
- name: data
emptyDir: {}
containers:
- name: postgres
image: postgres:9.6.5
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: db-security
key: db.user.name
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-security
key: db.user.password
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres.db.name
ports:
- containerPort: 5432
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/
---
apiVersion: v1
kind: Service
metadata:
name: postgresql
namespace: default
spec:
selector:
app: postgresql
ports:
- port: 5432NOTE: 先に作成した ConfigMap と Secret からデータベース名やユーザ名などを取得する。
NOTE: IntelliJ IDEA で Kubernetes のリソースファイルを変数するときには IntelliJ IDEA の Kubernetes プラグインを入れておくと便利。
実行する
kubectl create -f src/k8s/postgres.yml
作成された Deployment を確認する
kubectl get deployment postgresql -o json
作成された Service を確認する
kubectl get service postgresql -o json
4. アプリケーションを修正する
データベースを H2 から構築した PostgreSQL に接続するように修正する。
Spring Cloud Kubernetes を導入する
pom.xml
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.BUILD-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-config</artifactId> </dependency>
PostgreSQL の JDBC ドライバーを導入する
pom.xml
<dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency>
application.properties を修正する
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:postgresql://${${POSTGRES_SERVICE}.service.host}:${${POSTGRES_SERVICE}.service.port}/${POSTGRES_DB_NAME}
spring.datasource.username=${POSTGRES_DB_USER}
spring.datasource.password=${POSTGRES_DB_PASSWORD}ややこしい設定だが、内側のプレースホルダーは ConfigMap から提供される環境変数によって解決され、外側のプレースホルダーは Kubernetes によって解決されることになる。
application.properties を ConfigMap に登録する
kubectl create configmap app-config \ --from-file=src/main/resources/application.properties
bootstrap.properties を作成する
src/main/resources/bootstrap.properties
spring.cloud.kubernetes.config.name=app-config
これでアプリケーションが Kubernetes にデプロイされた時に、app-config として ConfigMap に保存された application.properties が使われるようになる。
5. アプリケーションをデプロイ
fabric8-maven-plugin を導入する
fabric8-maven-plugin (以降 fmp)は次のことを Maven のビルドプロセスで実行する。
- Docker イメージの作成(Dockerfile も自動生成する)
- Kubernetes および OpenShift のリソースファイルの作成
- Kubernetes および OpenShift へのアプリケーションのデプロイ
pom.xml
<plugin> <groupId>io.fabric8</groupId> <artifactId>fabric8-maven-plugin</artifactId> <version>4.2.0</version> <configuration> <enricher> <config> <fmp-service> <type>LoadBalancer</type> </fmp-service> </config> </enricher> </configuration> <executions> <execution> <id>fmp</id> <goals> <goal>resource</goal> <goal>build</goal> </goals> </execution> </executions> </plugin>
Service Account を作成する
Minikube v0.26.0 から RBAC がデフォルトで有効になっているため、アプリケーションから ConfigMap が取得できるように Service Account を作成する。
Service Account の Kubernetes リソースファイルを作成する
src/k8s/sa.yml
apiVersion: v1 kind: ServiceAccount metadata: name: config-reader namespace: default
Role の Kubernetes リソースファイルを作成する
src/k8s/role.yml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-reader rules: - apiGroups: [""] resources: ["pods","configmaps"] verbs: ["get", "watch", "list"]
Role Binding の Kubernetes リソースファイルを作成する
src/k8s/rb.yml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-reader namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pod-reader subjects: - kind: ServiceAccount name: config-reader namespace: default
実行する
kubectl create -f src/k8s/sa.yml kubectl create -f src/k8s/role.yml kubectl create -f src/k8s/rb.yml
アプリケーションのリソースファイルを作成する
ConfigMap からデータベースの接続情報を取得して環境変数にセットする。
src/main/fabric8/app.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${project.artifactId}
namespace: default
spec:
template:
spec:
containers:
- name: ${project.artifactId}
env:
- name: POSTGRES_SERVICE
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres.service.name
- name: POSTGRES_DB_NAME
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres.db.name
- name: POSTGRES_DB_USER
valueFrom:
secretKeyRef:
name: db-security
key: db.user.name
- name: POSTGRES_DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-security
key: db.user.password
serviceAccountName: config-readerビルドする
ビルドした Docker イメージを Minikube から使用できるようにする。
eval $(minikube docker-env)
Maven コマンドの実行
./mvnw clean install
fmp が Maven ビルド時に Dockerfile と Kubernetes のリソースファイルの作成を行う。
target/ ├── classes │ ├── META-INF │ │ └── fabric8 │ │ ├── kubernetes │ │ │ ├── spring-k8s-sample-deployment.yml │ │ │ └── spring-k8s-sample-service.yml │ │ ├── kubernetes.yml ...SKIP... ├── docker │ └── sample │ └── spring-k8s-sample │ └── latest │ ├── build │ │ ├── Dockerfile
NOTE: fmp は Spring Actuator を検出して LivenessProbe と ReadinessProbe を自動設定する。
デプロイする
./mvnw clean install fabric8:apply -DskipTests=true
エンドポイントを確認する
minikube service spring-k8s-sample --url
Customer を登録してみる
curl -X POST http://192.168.99.100:30223/customers \
-H 'Content-Type: application/json' \
-d '{
"name": "東方仗助",
"email": "jojo@example.com"
}'Customer を一覧してみる
curl -X GET http://192.168.99.100:30223/customers
データベースの中身を確認してみる
kubectl exec -it postgresql-5dd8d89d89-p7pdl /bin/bash psql -Usample sample select * from customer; id | email | name --------------------------------------+------------------+---------- 9a34ef06-1027-45f7-88a8-2c09d957a467 | jojo@example.com | 東方仗助 (1 row) \q exit
おわり★
