Перевод статьи подготовлен специально для студентов курса Разработчик на Spring Framework.
Давайте создадим простейшее Spring Boot-приложение, которое будет запускаться в кластере Kubernetes.
Структура проекта
Dockerfile build.gradle gradle wrapper gradle-wrapper.jar gradle-wrapper.properties gradlew k8s depl.yaml settings.gradle src main java hello App.java HelloWorldCtrl.java
App.java это точка входа в приложение:
package hello;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class App { public static void main(String[] args) { SpringApplication.run(App.class, args); }}
Приведенный выше код представляет собой минимальное Spring Boot
приложение.
Файл HelloWorldCtrl.java содержит простой контроллер, который мапит
корень (/) на метод index, возвращающий строку приветствия:
package hello;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;@RestControllerpublic class HelloWorldCtrl { @RequestMapping("/") public String index() { return "Greetings from Spring Boot!"; }}
Сборка приложения
Для сборки я использую Gradle. Файл build.gradle также минималистичен:
plugins { id 'org.springframework.boot' version '2.3.3.RELEASE' id 'io.spring.dependency-management' version '1.0.8.RELEASE' id 'java'}group = 'com.test'version = '0.0.1-SNAPSHOT'sourceCompatibility = '1.8'repositories { mavenCentral()}dependencies { implementation 'org.springframework.boot:spring-boot-starter-web'}
Создаем ресурсы K8s
Для развертывания в K8s нам понадобится Docker-образ. Давайте добавим в Dockerfile следующие строки:
FROM gradle:jdk10COPY --chown=gradle:gradle . /appWORKDIR /appRUN gradle buildEXPOSE 8080WORKDIR /appCMD java -jar build/libs/gs-spring-boot-0.1.0.jar
Шаги в нашем Dockerfile:
- копирование проекта в /app
- сборка проекта с помощью Gradle
- запуск приложения, используя результат предыдущего шага
docker build -t marounbassam/hello-spring .docker push marounbassam/hello-spring
Файл манифеста K8s тоже простой. Он состоит из развертывания (Deployment) и сервиса (Service):
apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: hello-worldspec: replicas: 2 template: metadata: labels: app: hello-world visualize: "true" spec: containers: - name: hello-world-pod image: marounbassam/hello-spring ports: - containerPort: 8080---apiVersion: v1kind: Servicemetadata: labels: visualize: "true" name: hello-world-servicespec: selector: app: hello-world ports: - name: http protocol: TCP port: 8080 targetPort: 8080 type: ClusterIP
Deployment определяет две реплики пода, в которых будет выполняться контейнер, созданный из образа, указанного в атрибуте image.
У сервиса (Service) тип ClusterIP (тип сервиса по умолчанию). Он предоставляет внутри кластера возможность подключаться к нам другим приложениям.
Создаем ресурсы в кластере:
kubectl create -f <yaml_file>
Визуально ресурсы можно представить следующим образом:
Внутри кластера
$ kubectl get podsNAME READY STATUS RESTARTS AGEhello-world-5bb87c95-6h4kh 1/1 Running 0 7hhello-world-5bb87c95-bz64v 1/1 Running 0 7h$ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhello-world-service ClusterIP 10.15.242.210 <none> 8080/TCP 5skubernetes ClusterIP 10.15.240.1 <none> 443/TCP 7h$ kubectl exec -it hello-world-5bb87c95-6h4kh bash$ (inside the pod) curl 10.15.242.210:8080$ (inside the pod) Greetings from Spring Boot!
Мы видим, что сервер запустился и работает внутри подов. Вы также можете настроить службу типа LoadBalancer (зависит от вашего облачного провайдера) и получить доступ к приложению из-за пределов кластера.
Заключение
Мы создали простое приложение на Spring Boot, запустили его в Docker-контейнере в поде K8s, который управляется через K8s deployment и доступен через сервис.
У нас получилась простая балансировка нагрузки для двух созданных подов и легкая масштабируемость в соответствии с потребностями приложения.