Abstruct
KubernetesのPod上で動作するSpringBootアプリケーションからConfigMapを変更することができたので、その方法をまとめておきます。
Environment
- minikube
1
2
|
minikube version: v1.16.0
commit: 9f1e482427589ff8451c4723b6ba53bb9742fbb1
|
- docker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
Client: Docker Engine - Community
Cloud integration: 1.0.4
Version: 20.10.0
API version: 1.41
Go version: go1.13.15
Git commit: 7287ab3
Built: Tue Dec 8 18:55:43 2020
OS/Arch: darwin/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.0
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: eeddea2
Built: Tue Dec 8 18:58:04 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.4.3
GitCommit: 269548fa27e0089a8b8278fc4fc781d7f65a939b
runc:
Version: 1.0.0-rc92
GitCommit: ff819c7e9184c13b7c2607fe6c30ae19403a7aff
docker-init:
Version: 0.19.0
GitCommit: de40ad0
|
環境構築は以下のコマンド。
1
2
|
minikube start
eval $(minikube docker-env)
|
eval $(minikube docker-env)
の必要性については、こちらのブログがわかりやすかったです。
What to create
- ServiceAccount
- Pod上からKubernetesのリソースにアクセスするためのアカウント。
- RoleBinding
- DockerImage
- SpringBootApplicationを配置/実行するイメージ
- Pod
- SpringBootApplication
ServiceAccount
service-account.yaml
1
2
3
4
5
|
apiVersion: v1
kind: ServiceAccount
metadata:
name: configmap-access-sa
automountServiceAccountToken: true
|
ServiceAccountの作成方法は以下。
1
|
kubectl apply -f service-account.yaml
|
RoleBinding
role-binding.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: configmap-access-sa-view
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: edit
subjects:
- kind: ServiceAccount
name: configmap-access-sa
namespace: default
|
Roleのデフォルトで用意されているもの(cluster-admin
やedit
など)については、Using RBAC Authorization | Kubernetes を参照するとわかりやすいです。
RoleBindingの作成方法は以下。
1
|
kubectl apply -f ./role-binding.yaml
|
DockerImage
1
2
3
4
|
FROM openjdk:11-jre
ARG JAR_FILE=./build/libs/app.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "./app.jar"]S
|
DockerImageの作成方法は以下。
1
|
docker build . -t game.example/demo-game
|
Pod
configmap-demo-pod.yaml
1
2
3
4
5
6
7
8
9
10
11
|
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo-pod
spec:
serviceAccountName: configmap-access-sa
automountServiceAccountToken: true
containers:
- name: demo
image: game.example/demo-game:latest
imagePullPolicy: IfNotPresent
|
Podの作成方法は以下。
1
|
kubectl apply -f ./configmap-demo-pod.yaml
|
ServiceAccount作成時にできているSecretがマウントされていることを確認すること。
この設定がないと、io.kubernetes.client.ApiException: Forbidden at K8S pod · Issue #542 · kubernetes-client/java のエラーとなり、kubernetesのリソースにアクセスできない。
1
2
3
4
5
6
7
8
9
|
takuto-n@MacBook-Air pod-read-configmap % kubectl get pods/configmap-demo-pod -o yaml
# 省略
serviceAccount: configmap-access-sa
serviceAccountName: configmap-access-sa
# 省略
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: configmap-access-sa-token-2vxlm
readOnly: true
|
SpringBootApplication
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
plugins {
id 'org.springframework.boot' version '2.4.1'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.fabric8:kubernetes-client:4.13.0'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
|
ConfigMapWriter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package com.example.properties.k8s;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ConfigMapWriter {
public boolean update() {
Config config = new ConfigBuilder().build();
KubernetesClient client = new DefaultKubernetesClient(config);
String namespace = client.getNamespace();
if (namespace == null) {
namespace = "default";
}
String name = "config-test";
var configMapResource = client.configMaps().inNamespace(namespace).withName(name);
var configMap = configMapResource.createOrReplace(new ConfigMapBuilder().
withNewMetadata().withNamespace(namespace).withName(name).endMetadata().
addToData("foo", "xxx").
addToData("bar", "beer").
build());
log.info("Upserted ConfigMap at {} data {}", configMap.getMetadata().getSelfLink(), configMap.getData());
return true;
}
}
|
Reference