[A-00224]簡単なマイクロサービスを作る(1)

Java+Springboot+Docker+Kubernetesで簡単なマイクロサービスを作ります。

・ServiceAを作成する

spring:
  application:
    name: service-a
  main:
    banner-mode: "off"
server:
  port: 8081
package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ServiceAController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello from ServiceA.";
    }
}
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ServiceAApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServiceAApplication.class, args);
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.example</groupId>
	<artifactId>service-a</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>service-a</name>

	<properties>
		<java.version>21</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<version>3.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<version>3.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<version>3.4.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<version>3.4.1</version>
				<configuration>
					<executable>true</executable>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

</project>
FROM openjdk:21

VOLUME /tmp
ADD target/service-a-0.0.1-SNAPSHOT.jar service-a.jar

EXPOSE 8081

ENTRYPOINT ["java","-jar","service-a.jar"]

上記を作成したらmvn buildして、Docker buildします。

mvn clean install
docker build ./ -t service-a:latest

・ServiceBを作成する

spring:
  application:
    name: service-b
  main:
    banner-mode: "off"
server:
  port: 8082
package com.example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class ServiceBController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/call-service-a")
    public String callServiceA() {
        return restTemplate.getForObject("http://service-a:8081/hello", String.class);
    }
}
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ServiceBApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServiceBApplication.class, args);
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.example</groupId>
	<artifactId>service-b</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>service-b</name>

	<properties>
		<java.version>21</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<version>3.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<version>3.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<version>3.4.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<version>3.4.1</version>
				<configuration>
					<executable>true</executable>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

</project>
FROM openjdk:21

VOLUME /tmp
ADD target/service-b-0.0.1-SNAPSHOT.jar service-b.jar

EXPOSE 8082

ENTRYPOINT ["java","-jar","service-b.jar"]

こちらもmvn buildしてDocker buildします。

mvn clean install
docker build ./ -t service-b:latest

・Docker-Composeしてみる

docker-composeで動くか確認します。

services:
  service-a:
    image: service-a:latest
    container_name: service-a
    restart: always
    networks:
      - svc-net
    # ports:
    #   - 8081:8081
  service-b:
    image: service-b:latest
    container_name: service-b
    restart: always
    networks:
      - svc-net
    ports:
      - 8082:8082
networks:
  svc-net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.10.0/24

下記のコマンドでdocker-composeします。動作確認できたらcontainerをダウンさせます。

docker compose up
docker compose down

・Kubernetesで動かしてみる

今回はPod間通信をして疎通確認します。

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kompose.cmd: kompose convert
    kompose.version: 1.35.0 (HEAD)
  labels:
    io.kompose.service: service-a
  name: service-a
spec:
  replicas: 1
  selector:
    matchLabels:
      io.kompose.service: service-a
  template:
    metadata:
      annotations:
        kompose.cmd: kompose convert
        kompose.version: 1.35.0 (HEAD)
      labels:
        io.kompose.service: service-a
    spec:
      containers:
        - image: service-a:latest
          name: service-a
      restartPolicy: Always
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kompose.cmd: kompose convert
    kompose.version: 1.35.0 (HEAD)
  labels:
    io.kompose.service: service-b
  name: service-b
spec:
  replicas: 1
  selector:
    matchLabels:
      io.kompose.service: service-b
  template:
    metadata:
      annotations:
        kompose.cmd: kompose convert
        kompose.version: 1.35.0 (HEAD)
      labels:
        io.kompose.service: service-b
    spec:
      containers:
        - image: service-b:latest
          name: service-b
          ports:
            - containerPort: 8082
              protocol: TCP
      restartPolicy: Always
apiVersion: v1
kind: Service
metadata:
  annotations:
    kompose.cmd: kompose convert
    kompose.version: 1.35.0 (HEAD)
  labels:
    io.kompose.service: service-b
  name: service-b
spec:
  ports:
  - name: "8082"
    port: 8082
    targetPort: 8082
  type: LoadBalancer
  selector:
    io.kompose.service: service-b

下記のコマンドを実行してapplyします。

kubectl apply -f service-a-deployment.yml,service-b-deployment.yml,service-b-service.yml

下記のコマンドでpodとserviceの立ち上がりを確認します。

kubectl get pod
kubectl get svc

下記のコマンドでservice-bに接続します。

curl http://localhost:8082/call-a-service

上記で[Hello from service-a]と返ってきたら完了です。

・Appendix

参考文献はこちら

https://qiita.com/YumaInaura/items/e7155b309e109bc75cf8

https://qiita.com/dingtianhongjie/items/4b90249d1839fe36e973

https://qiita.com/marufeuille/items/b4065c8756e2a92b18aa

https://qiita.com/hrkt/items/0d10ef3e228e6a39c454

https://qiita.com/takuyanin/items/949201e3eb100d4384e1

https://qiita.com/zousan010sanpotyu/items/208dd6b4cb00f88eca67

https://spring.pleiades.io/guides/gs/spring-boot-kubernetes

https://qiita.com/yokawasa/items/bba45ad775bbf8ac25c3

https://spring.pleiades.io/guides/gs/spring-boot-kubernetes

https://github.com/spring-cloud/spring-cloud-kubernetes/tree/main/spring-cloud-kubernetes-examples/kubernetes-leader-election-example

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*