Рубрики
Без рубрики

Создайте микросервисную архитектуру с помощью Spring Boot и Kubernetes

В этом руководстве показано, как использовать Kubernetes для развертывания микросервисной архитектуры Spring Boot в Google Cloud и Google Kubernetes Engine (GKE). С тегами java, hibernate, springboot, tutorial.

В этом руководстве вы собираетесь использовать Kubernetes для развертывания архитектуры микросервиса Spring Boot в Google Cloud, в частности Google Kubernetes Engine (GKE). Вы также собираетесь использовать Visio для создания слоя сервисной сетки и создания общедоступного шлюза. Все это будет защищено с помощью аутентификации Okta OAuth JWT.

Это была путаница жаргона. Мы не собираемся подробно описывать здесь микросервисы. Короче говоря, микросервисы – это шаблон проектирования, который разделяет более крупные монолитные сервисы на более мелкие независимые “микро” сервисы. Эти службы слабо связаны по сети. Преимущества этой архитектуры заключаются в том, что каждая служба становится тестируемой, поддерживаемой и независимо развертываемой. В масштабах Интернета и в таких огромных компаниях, как Amazon и Netflix, эта архитектура великолепна, потому что она позволяет компаниям назначать небольшие команды, отвечающие за управляемые, отдельные функциональные единицы; в отличие от огромных монолитных блоков кода, контролируемых тысячами людей. Недостатком является высокая начальная стоимость сложности и инфраструктуры, что может не иметь смысла для небольших проектов, которые не собираются масштабироваться.

Kubernetes – это платформа для развертывания контейнерных сервисов. Вы можете думать об этом как о контейнерном оркестраторе для контейнеров Docker (это упрощение, но оно сработает). Это позволит нам писать сценарии YAML, которые автоматизируют развертывание нашей микросервисной архитектуры на выбранной нами платформе GKE. Это огромный проект, в котором есть над чем покопаться. Взгляните на их документы для получения дополнительной информации.

Edition добавляет еще один уровень функций поверх Kubernetes, добавляя некоторые отличные функции мониторинга, безопасности, контроля доступа и балансировки нагрузки. Проверьте их веб-сайт для получения дополнительной информации.

Последняя часть микросервисной архитектуры – это Google Cloud и GKE . Это платформа, которую вы будете использовать для развертывания микросервиса. Другой вариант, не описанный в этом руководстве, – это Миникуб. Mini cube работает локально на вашем компьютере и может отлично работать для некоторых людей; Я обнаружил, что движок Google Kubernetes проще в использовании и более производителен.

Мы предполагаем, что вы знакомы с Spring Boot и Java. Если нет, взгляните на конец руководства, чтобы найти некоторые ссылки, которые помогут вам начать.

Требования к Spring Boot и Kubernetes

HTTP ie : Установите HTTPie с их веб-сайта , чтобы мы могли легко запускать HTTP-запросы с терминала.

Docker : Пожалуйста, скачайте и установите Docker Desktop с их веб-сайта , если он у вас еще не установлен.

кубектл : Это интерфейс командной строки Kubernetes. Инструкции по его установке находятся на их веб-сайте .

Google Cloud : Вам понадобится учетная запись Google Cloud с включенной выставлением счетов. Доступна бесплатная пробная версия, которая должна включать более чем достаточный кредит и время, чтобы вы прошли этот урок. Перейдите на веб-сайт Google Cloud и зарегистрируйтесь.

Перейдите на веб-сайт Google Cloud и зарегистрируйтесь. : Мы предлагаем бесплатные учетные записи разработчиков на нашем сайте разработчика . Пожалуйста,

облако : Это облачный интерфейс Google Cloud CLI. Установите его, используя инструкции с их веб-сайта. | Как только это будет сделано, вам нужно будет установить компоненты

gcloud components install kubectl

Я упоминал, что микросервисы имеют высокую начальную стоимость сложности?

Создайте проект Google Kubernetes Engine с помощью Istio

Теперь у вас должна быть учетная запись Google Cloud с включенной выставлением счетов. Опять же, вам не нужно на самом деле тратить какие-либо деньги, но без выставления счетов вы не сможете получить доступ к бесплатной пробной версии.

Создайте новый проект. Назовите это spring-boot-gke (или все, что вы хотите, но вам понадобится идентификатор проекта для различных команд). Дождитесь создания проекта.

Название проекта, скорее всего, в конечном итоге будет иметь идентификационный номер, прикрепленный к концу, например spring-boot-gke-232934 . Вам понадобится это имя проекта несколько раз, так что продолжайте и сохраните его в переменной оболочки и примите это к сведению.

PROJECT_NAME=

Как только проект будет готов, откройте панель управления проектом, откройте меню навигации и нажмите на Kubernetes Engine . Нажмите кнопку Включить выставление счетов (если вы еще не включили выставление счетов) и выберите учетную запись для выставления счетов.

Нажмите Создать кластер .

На левой боковой панели выберите Ваш первый кластер .

Назовите кластер “spring-boot-cluster”.

Выберите зону “США-запад1-a”.

Нажмите на ссылку Дополнительные параметры в нижней части панели конфигурации кластера, чтобы отобразить дополнительные параметры. Прокрутите страницу вниз до самого низа и установите флажок Включить выпуск (бета-версия) . Это автоматически установит Istio в кластере.

Внизу нажмите Создать , чтобы создать кластер. Выпейте кофе или сделайте перерыв; на создание кластера уйдет несколько минут.

Тем временем, если вы еще этого не сделали, продолжайте и инициализируйте cloud CLI, выполнив:

gcloud init

В процессе инициализации вы можете установить свой новый проект в качестве проекта по умолчанию, а регион проекта – в качестве региона по умолчанию.

Как только кластер будет развернут, вам необходимо подключить свой локальный cloud и kubectl CLI к нему с помощью следующей команды:

gcloud container clusters get-credentials {yourClusterName} --zone us-west1-a --project {yourProjectId}

Если вы использовали другое название проекта, вам нужно будет изменить команду, чтобы отразить это.

записка: Если вы нажмете на кнопку Подключиться справа от панели управления облачной платформы Google, вы увидите правильную команду для ввода:

В результате вы должны увидеть что-то вроде следующего:

Fetching cluster endpoint and auth data.
kubeconfig entry generated for spring-boot-cluster.

Вам также нужно будет предоставить себе права администратора в кластере:

kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value core/account)

Теперь вам нужно проверить и убедиться, что службы редактора были установлены и запущены. Есть несколько способов проверить это. Сначала на панели инструментов Google Cloud Platform Kubernetes Engine нажмите кнопку Services . Вы должны увидеть список служб Istio в вашем spring-boot-cluster . У всех них должно быть зеленое “Ок” под столбцом статуса.

Пока вы там, обратите внимание на службу с именем istio-входной шлюз типа LoadBalancer . Это общедоступный балансировщик нагрузки для вашего кластера, и в записи указаны общедоступный IP-адрес и открытые порты.

Другой способ проверить – использовать kubectl CLI.

Для проверки служб используйте следующую команду: kubectl get services --all-namespaces . Параметр --all-namespaces требуется для отображения служб истории, которые находятся в пространстве имен istio-system .

$ kubectl get services --all-namespaces
NAMESPACE      NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                                                                                                                   AGE
default        kubernetes               ClusterIP      10.31.240.1                443/TCP                                                                                                                   5m
istio-system   istio-citadel            ClusterIP      10.31.252.214              8060/TCP,9093/TCP                                                                                                         3m
istio-system   istio-egressgateway      ClusterIP      10.31.247.186              80/TCP,443/TCP                                                                                                            3m
istio-system   istio-galley             ClusterIP      10.31.249.131              443/TCP,9093/TCP                                                                                                          3m
istio-system   istio-ingressgateway     LoadBalancer   10.31.244.186   35.185.213.229   80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:30675/TCP,8060:31581/TCP,853:32460/TCP,15030:30998/TCP,15031:31606/TCP   3m
istio-system   istio-pilot              ClusterIP      10.31.251.44               15010/TCP,15011/TCP,8080/TCP,9093/TCP                                                                                     3m
istio-system   istio-policy             ClusterIP      10.31.246.176              9091/TCP,15004/TCP,9093/TCP                                                                                               3m
istio-system   istio-sidecar-injector   ClusterIP      10.31.240.214              443/TCP                                                                                                                   3m
istio-system   istio-telemetry          ClusterIP      10.31.247.23               9091/TCP,15004/TCP,9093/TCP,42422/TCP                                                                                     3m
istio-system   promsd                   ClusterIP      10.31.246.88               9090/TCP                                                                                                                  3m
kube-system    default-http-backend     NodePort       10.31.250.134              80:31955/TCP                                                                                                              4m
kube-system    heapster                 ClusterIP      10.31.250.242              80/TCP                                                                                                                    4m
kube-system    kube-dns                 ClusterIP      10.31.240.10               53/UDP,53/TCP                                                                                                             4m
kube-system    metrics-server           ClusterIP      10.31.245.127              443/TCP

Чтобы проверить модули Kubernetes, используйте: kubectl get pods --all -пространства имен

$ kubectl get pods --all-namespaces
NAMESPACE      NAME                                                      READY     STATUS      RESTARTS   AGE
istio-system   istio-citadel-7c4864c9d5-7xq9x                            1/1       Running     0          10m
istio-system   istio-cleanup-secrets-ghqbl                               0/1       Completed   0          10m
istio-system   istio-egressgateway-c7f44ff8-tz7br                        1/1       Running     0          10m
istio-system   istio-galley-698f5c74d6-hmntq                             1/1       Running     0          10m
istio-system   istio-ingressgateway-774d77cb7c-qvhkb                     1/1       Running     0          10m
istio-system   istio-pilot-6bd6f7cdb-gb2gd                               2/2       Running     0          10m
istio-system   istio-policy-678bd4cf9-r8p6z                              2/2       Running     0          10m
istio-system   istio-sidecar-injector-6555557c7b-99c6k                   1/1       Running     0          10m
istio-system   istio-telemetry-5f4cfc5b6-vj8cf                           2/2       Running     0          10m
istio-system   promsd-ff878d44b-hlkpg                                    2/2       Running     1          10m
kube-system    heapster-v1.6.0-beta.1-8c76f98c7-2b4dm                    2/2       Running     0          9m
kube-system    kube-dns-7549f99fcc-z5trl                                 4/4       Running     0          10m
kube-system    kube-dns-autoscaler-67c97c87fb-m52vb                      1/1       Running     0          10m
kube-system    kube-proxy-gke-spring-boot-cluster-pool-1-b6988227-p09h   1/1       Running     0          10m
kube-system    l7-default-backend-7ff48cffd7-ppvnn                       1/1       Running     0          10m
kube-system    metrics-server-v0.2.1-fd596d746-njws2                     2/2       Running     0          10m

Все модули должны иметь статус Завершено или Работает . Пару раз я сталкивался с проблемой, когда автоматическая настройка не работала, а некоторые модули так и не достигли статуса Running и застряли в Создание контейнера . Мне пришлось удалить кластер и переустановить его, чтобы заставить его работать.

Если это произойдет, вы можете использовать команду describe god's , чтобы посмотреть, что происходит: kubectl describe pods -n istio-system . Это даст вам массу информации обо всех площадках в пространстве имен istio-system , которое задается с помощью параметров -n .

Если вы зашли так далеко без проблем, то теперь у вас есть кластер Kubernetes, развернутый на GLEE с установленным Istio! Довольно мило.

И у Google, и у Isis есть несколько довольно полезных документов, если у вас возникнут проблемы. Ознакомьтесь с документами Google GKE docs и Редактор GKE docs для дальнейшей поддержки.

Создайте проект Spring Boot для ваших микросервисов

Теперь перейдите в Spring Initializer и создайте свой начальный проект.

  • Измените инструмент сборки с Maven на Gradle
  • Использовать Ява и версия Spring Boot/| 2.1.3 Обновите
  • Группу до: Обновите Группу
  • до: Использовать Артефакт
  • : springbootkbe Добавьте три Зависимости : : Творческая сеть

Нажмите Создать проект и загрузите проект. Распакуйте проект где-нибудь на вашем локальном компьютере и откройте его в вашей любимой среде разработки или редакторе.

Инициализатор Spring создал проект barebones reactive Web flux с поддержкой MongoDB, который вы можете расширить.

Как и в некоторых других моих уроках, и поскольку мне нравится кататься на байдарках, вы собираетесь создать простой реактивный сервис REST, который поддерживает базу данных записей о байдарках. На самом деле это просто демонстрация базовой функциональности CRUD (Создание, чтение, обновление и удаление) и может быть обобщено на любой тип ресурса.

В пакете com.okta.spring.springbootkbe в разделе src/main/java создайте класс документа с именем Kayak.java и вставьте в него следующее. Это ваш документ с реактивной моделью данных.

package com.okta.spring.springbootkbe;

import lombok.AllArgsConstructor;  
import lombok.Data;  
import lombok.NoArgsConstructor;  
import org.springframework.data.mongodb.core.mapping.Document;  

@Document  
@Data  
@AllArgsConstructor  
@NoArgsConstructor  
public class Kayak {  

    private String name;  
    private String owner;  
    private Number value;  
    private String makeModel;  
}

Теперь создайте другой файл в том же пакете с именем KayakRepository.java .

package com.okta.spring.springbootkbe;  

import org.springframework.data.mongodb.repository.ReactiveMongoRepository;  

public interface KayakRepository extends ReactiveMongoRepository {  
}

Я не собираюсь вдаваться в подробности в этом руководстве о том, что здесь происходит. Spring Boot выполняет множество автоматических связей между этими двумя файлами для создания полнофункционального документа reactive Mongo.

Далее вам нужно добавить контроллер, чтобы разрешить доступ к модели данных документа Kayak. Создайте файл с именем Kayak Controller в пакете com.okta.spring.springbootkbe .

package com.okta.spring.springbootkbe;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Controller
@RequestMapping(path = "/kayaks")
public class KayakController {

    private final KayakRepository kayakRepository;

    public KayakController(KayakRepository kayakRepository) {
        this.kayakRepository = kayakRepository;
    }

    @PostMapping()
    public @ResponseBody
    Mono addKayak(@RequestBody Kayak kayak) {
        return kayakRepository.save(kayak);
    }

    @GetMapping()
    public @ResponseBody
    Flux getAllKayaks() {
        Flux result = kayakRepository.findAll();
        return result;
    }}

Этот контроллер добавляет два метода к конечной точке /kayaks , конечную точку POST и GET, которые добавляют новую байдарку и перечисляют все байдарки соответственно.

Наконец, добавьте простой корневой контроллер с именем Root Controller .

package com.okta.spring.springbootkbe;  

import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.*;  
import reactor.core.publisher.Flux;  

@Controller  
public class RootController {  

    @GetMapping("/")  
    @ResponseBody  
    public Flux getRoot() {  
      return Flux.just("Alive");  
    }
}

Этот контроллер необходим, потому что Kubernetes выполняет проверку работоспособности корневой конечной точки наших служб и должен возвращать ответ, в противном случае кластер подумает, что ваша служба не работает. Фактическая конечная точка настраивается, но вы можете просто оставить ее в корне на данный момент.

Чтобы загрузить некоторые образцы данных в нашу базу данных, обновите определение класса Springbootapplication , чтобы оно соответствовало следующему.

package com.okta.spring.springbootkbe;  

import org.springframework.boot.ApplicationRunner;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.context.annotation.Bean;  
import reactor.core.publisher.Flux;  

@SpringBootApplication  
public class SpringbootkbeApplication {

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

    @Bean
    ApplicationRunner init(KayakRepository repository) {

        Object[][] data = {
            {"sea", "Andrew", 300.12, "NDK"},
            {"creek", "Andrew", 100.75, "Piranha"},
            {"loaner", "Andrew", 75, "Necky"}
        };

        return args -> {
            repository
                .deleteAll()
                .thenMany(
                    Flux
                        .just(data)
                        .map(array -> {
                            return new Kayak((String) array[0], (String) array[1], (Number) array[2], (String) array[3]);
                        })
                        .flatMap(repository::save)
                )
                .thenMany(repository.findAll())
                .subscribe(kayak -> System.out.println("saving " + kayak.toString()));

        };
    }
}

На данный момент у вас есть полностью функционирующее приложение Spring Boot (за вычетом сервера MongoDB). Чтобы протестировать свое приложение, добавьте следующую зависимость в свой файл build.gradle .

compile 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'

Это добавит встроенную базу данных MongoDB в ваш проект. Вам нужно будет удалить эту зависимость перед развертыванием в кластере, но это позволит вам запустить приложение Spring Boot локально.

Запустите приложение Spring Boot с помощью: gradle bootRun .

Вы должны увидеть кучу выходных данных, заканчивающихся:

2019-02-14 19:29:34.941 INFO 35982 --- [ntLoopGroup-2-4] org.mongodb.driver.connection : Opened connection [connectionId{localValue:5, serverValue:5}] to localhost:61858
2019-02-14 19:29:34.946 INFO 35982 --- [ntLoopGroup-2-3] org.mongodb.driver.connection : Opened connection [connectionId{localValue:4, serverValue:4}] to localhost:61858
saving Kayak(name=sea, owner=Andrew, value=300.12, makeModel=NDK)
saving Kayak(name=loaner, owner=Andrew, value=75, makeModel=Necky)
saving Kayak(name=creek, owner=Andrew, value=100.75, makeModel=Piranha)

Используйте HTTPie для тестирования приложения: http:8080 (при этом выполняется запрос get на порт загрузки Spring по умолчанию).

HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
transfer-encoding: chunked

Alive

И ПОЛУЧИТЕ свою конечную точку /kayaks , используя: http:8080/kayaks .

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
transfer-encoding: chunked
[
  {
    "makeModel": "NDK",
    "name": "sea",
    "owner": "Andrew",
    "value": 300.12
  },
  {
    "makeModel": "Necky",
    "name": "loaner",
    "owner": "Andrew",
    "value": 75
  },
  {
    "makeModel": "Piranha",
    "name": "creek",
    "owner": "Andrew",
    "value": 100.75
  }
]

Предполагая, что все сработало, удалите встроенную зависимость Mongo . Вы собираетесь использовать модуль Mongo Kubernetes, и эта зависимость вызовет проблемы с развертыванием кластера.

compile 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'

Разверните модуль MongoDB Kubernetes Pod для вашего приложения Spring Boot

Kubernetes работает (для грубого обобщения и упрощения) путем развертывания контейнеров Docker с использованием сценариев развертывания YAML.

Создайте файл с именем deployment-mongo.yml в корневом каталоге вашего проекта.

apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: mongodb  
  labels:  
    appdb: mongodb  
spec:  
  replicas: 1  
  selector:  
    matchLabels:  
      appdb: mongodb  
  template:  
    metadata:  
      labels:  
        appdb: mongodb  
    spec:  
      containers:  
        - name: mongodb  
          image: mongo:3.6.6  
          ports:  
            - containerPort: 27017  
---  
apiVersion: v1  
kind: Service  
metadata:  
  name: mongodb  
  labels:  
    app: mongodb  
spec:  
  ports:  
    - port: 27017  
      protocol: TCP  
  selector:  
    appdb: mongodb

Это определяет MongoDB Kubernetes Deployment и Service , необходимые для создания базы данных Mongo в кластере. Я не собираюсь пытаться полностью объяснить, что это за объекты, но вы можете прочитать Kubernetes deployment docs и служебные документы . Грубо говоря, развертывания определяют микроприложения, которые выполняются в развернутых модулях, в то время как службы обеспечивают всеобъемлющую абстракцию, которая определяет точку доступа к приложениям в модулях. Эта абстракция обеспечивает необходимую непрерывность, поскольку модули могут быть отключены и перезапущены, и может быть несколько модулей, выполняющих одну службу.

А теперь немного волнения! Вы собираетесь развернуть развертывание и службу базы данных Mongo в своем кластере GKE.

Используйте следующую команду:

kubectl apply -f deployment-mongo.yml

Вы должны увидеть:

deployment.apps "mongodb" created
service "mongodb" created

Проверьте модуль, запустив:

$ kubectl get pods

Вы должны увидеть:

NAME READY STATUS RESTARTS AGE
mongodb-c5b8bf947-rkw5f 1/1 Running 0 21s

Если статус указан как Контейнер, создающий , подождите немного и снова запустите команду. Если он застрянет на Контейнер создает более нескольких минут, вероятно, что-то пошло не так. Вы можете использовать kubectl для описания модулей и kubectl получает события команды, чтобы получить представление о том, что происходит.

Это настроило базу данных Mongo, работающую на порту 27017, используя стандартный образ docker монго:3.6.6 .

Довольно здорово, да? Следующая остановка – ракетостроение!

Разверните приложение Spring Boot в кластере

Добавьте файл с именем Dockerfile в корневой каталог:

FROM openjdk:8-jdk-alpine  
ENV APP_FILE springbootkbe-0.1.0-SNAPSHOT.jar  
ENV APP_HOME /usr/app  
EXPOSE 8000  
COPY build/libs/*.jar $APP_HOME/  
WORKDIR $APP_HOME  
ENTRYPOINT ["sh", "-c"]  
CMD ["exec java -jar $APP_FILE"]

Обновите src/main/resources/application.properties :

server.port=8000
spring.data.mongodb.host=mongodb
spring.data.mongodb.port=27017

Это настраивает ваш загрузочный порт Spring на порт, который вы предоставляете в Dockerfile , а также настраивает хост и порт MongoDB. Хостом по умолчанию будет имя службы внутри кластера.

Создайте свое приложение снова (вы же удалили зависимость flapdoodle , верно?):

gradle clean build

Создайте другой сценарий развертывания Kubernetes с именем deployment.yml в корневом каталоге проекта:

apiVersion: v1  
kind: Service  
metadata:  
  name: kayak-service  
  labels:  
    app: kayak-service  
spec:  
  ports:  
    - name: http  
      port: 8000  
  selector:  
    app: kayak-service  
---  
apiVersion: extensions/v1beta1  
kind: Deployment  
metadata:  
  name: kayak-service  
spec:  
  replicas: 1  
  template:  
    metadata:  
      labels:  
        app: kayak-service  
        version: v1  
    spec:  
      containers:  
        - name: kayak-app  
          image: gcr.io/spring-boot-gke-/kayak-app:1.0  
          imagePullPolicy: IfNotPresent  
          env:  
            - name: MONGODB_HOST  
              value: mongodb  
          ports:  
            - containerPort: 8000  
          livenessProbe:  
            httpGet:  
              path: /  
              port: 8000  
            initialDelaySeconds: 5  
            periodSeconds: 5

ПРИМЕЧАНИЕ: Внимательно посмотрите на строку с gcr.io/spring-boot-gke/kayak-app:1.0 . Эта средняя часть – название проекта Google Cloud. Это должно соответствовать имени проекта, которое вы использовали, вместе с присвоенным идентификационным номером (что-то вроде spring-boot-gke-43234 ).

gcr.io указывает облачный хост Google для образа docker в Соединенных Штатах. Можно указать другие местоположения. См. Документы реестра контейнеров Google для получения дополнительной информации.

Краткое описание того, что должно произойти, так как здесь много движущихся частей. Приложение Spring Boot будет настроено на docker: встроено в образ docker. Когда вы запустите сценарий развертывания в своем кластере, он попытается извлечь это изображение из реестра контейнеров Google. Поэтому вам нужно поместить изображение в реестр контейнеров и пометить его, чтобы Kubernetes мог найти правильное изображение.

Если вы используете локальный рабочий стол Docker, запустите его и дождитесь его запуска.

Прежде чем вы что-либо сделаете, вам нужно будет настроить Google Cloud и docker так, чтобы они хорошо работали вместе:

gcloud auth configure-docker

Создайте образ docker:

docker build -t kayak-app:1.0 .

Пометьте изображение тегом и поместите его в реестр контейнеров Google (снова обратите внимание на название проекта Google Cloud).:

docker tag kayak-app:1.0 gcr.io/$PROJECT_NAME/kayak-app:1.0;  
docker push gcr.io/$PROJECT_NAME/kayak-app:1.0

Теперь примените файл deployment.yml к кластеру GKE:

kubectl apply -f deployment.yml

Проверьте, правильно ли развернут модуль:

kubectl get pods

NAME                             READY     STATUS    RESTARTS   AGE
kayak-service-7df4fb9c88-srqkr   1/1       Running   0          56s
mongodb-c5b8bf947-dmghb          1/1       Running   0          16m

Однако на данный момент ваш кластер еще не совсем готов. Это не общедоступно.

Создайте файл с именем istio-gateway.yml .

apiVersion: networking.istio.io/v1alpha3  
kind: Gateway  
metadata:  
  name: kayak-gateway  
spec:  
  selector:  
    istio: ingressgateway # use Istio default gateway implementation  
  servers:  
  - port:  
      name: http  
      number: 80  
      protocol: HTTP  
    hosts:  
    - '*'  
---  
apiVersion: networking.istio.io/v1alpha3  
kind: VirtualService  
metadata:  
  name: kayak-service  
spec:  
  hosts:  
  - "*"  
  gateways:  
  - kayak-gateway  
  http:  
  - match:  
    - uri:  
        prefix: /  
    route:  
    - destination:  
        port:  
          number: 8000  
        host: kayak-service

И применяйте его:

 kubectl apply -f istio-gateway.yml

Вы должны получить:

gateway.networking.istio.io "kayak-gateway" created
virtualservice.networking.istio.io "kayak-service" created

Протестируйте развернутое приложение Google Kubernetes Engine + Spring Boot

Теперь, когда вы успешно развернули приложение Spring Boot в кластере Google Kubernetes и создали шлюз, связывающий вашу службу с внешним миром, вы захотите протестировать конечную точку.

На веб-сайте History есть несколько хороших документов о входящем трафике , в которых содержится много полезной информации. Ниже, скопированные с этой страницы, приведены некоторые команды, которые будут определять общедоступный хост/ip-адрес и порты и сохранять их в переменных оболочки.

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}');
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=);

В вашей конфигурации INGRESS_PORT , скорее всего, будет просто 80 по умолчанию для HTTP (без SSL).

Выполните следующую команду, чтобы увидеть хост и порты:

echo "$INGRESS_HOST, HTTP PORT=$INGRESS_PORT";

Общедоступный IP-адрес также можно найти, просмотрев IP-адрес балансировщика нагрузки в Панель инструментов облачной платформы -> Движок Kubernetes -> Сервисы . Найдите istio-входной шлюз сервис типа LoadBalancer .

Протестируйте приложение!

http $INGRESS_HOST:$INGRESS_PORT/

Вы должны увидеть:

HTTP/1.1 200 OK
content-type: text/plain;charset=UTF-8
...

Alive

И попали в /байдарки конечная точка:

http $INGRESS_HOST:$INGRESS_PORT/kayaks

Вы должны увидеть:

HTTP/1.1 200 OK
content-type: application/json;charset=UTF-8
...
[
  {
    "makeModel": "NDK",
    "name": "sea",
    "owner": "Andrew",
    "value": 300.12
  },
  {
    "makeModel": "Piranha",
    "name": "creek",
    "owner": "Andrew",
    "value": 100.75
  },
  {
    "makeModel": "Necky",
    "name": "loaner",
    "owner": "Andrew",
    "value": 75
  }
]

Добро пожаловать в мир микросервисов!

Очевидно, что с GLEE и Istio можно сделать гораздо больше. На практике микросервисы обычно управляют большой сетью служб и развернутых модулей, которые можно масштабировать вверх и вниз по мере необходимости, а сложными архитектурами безопасности можно управлять между различными частями и с внешним миром. В этом руководстве мы не будем вдаваться в подробности, но остался еще один шаг: добавление аутентификации веб-токена JSON с помощью Okta.

Создайте приложение OpenID Connect на Okta

Войдите в ваш developer.okta.com счет (Вы ведь зарегистрировались в одной из их бесплатных учетных записей разработчиков, верно? Если нет, перейдите к developer.okta.com ).

Нажмите на Приложение верхнее меню, затем на кнопку Добавить приложение .

Выберите тип приложения Web .

Нажмите Следующий .

Дайте приложению имя. Я назвал свой “Весенний ботинок GKE”.

В разделе URI перенаправления входа в систему добавить https://oidcdebugger.com/debug .

Внизу, в разделе Разрешенный тип предоставления , установите флажок Неявный (гибридный) .

Нажмите Готово .

Оставьте страницу открытой и обратите внимание на Идентификатор клиента и Секрет клиента . Они понадобятся вам через минуту, когда вы будете использовать отладчик OIDC для создания веб-токена JSON.

Обновите свои микросервисы Spring Boot для OAuth 2.0

Добавьте следующие зависимости в свой build.gradle :

compile 'org.springframework.security:spring-security-oauth2-client'
compile 'org.springframework.security:spring-security-oauth2-resource-server'

Вам также необходимо добавить следующее в свой файл src/main/resources/application.properties (указав свой собственный URL-адрес Oktadeveloper, что-то вроде dev-123456.okta.com ):

spring.security.oauth2.resourceserver.jwt.issuer-uri=https://{yourOktaDomain}/oauth2/default

Это сообщает Spring, куда ему нужно перейти для аутентификации веб-токена JSON (JWT), который вы собираетесь сгенерировать через мгновение.

Наконец, вам нужно добавить новый класс Java с именем SecurityConfiguration.java :

package com.okta.spring.springbootkbe;  

import org.springframework.context.annotation.Bean;  
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;  
import org.springframework.security.config.web.server.ServerHttpSecurity;  
import org.springframework.security.web.server.SecurityWebFilterChain;  

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http
            .authorizeExchange()
            .pathMatchers("/").permitAll()
            .anyExchange().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
        return http.build();
    }
}

Этот файл настраивает проект так, чтобы разрешать все транзакции на корневой конечной точке, но разрешать все остальные транзакции.

Создайте новый образ Docker и переместите его в кластер GKE

Теперь, когда у вас есть новое приложение Spring Boot с поддержкой авторизации, вам нужно создать его, упаковать в контейнер Docker, поместить в реестр Google Cloud Docker и применить новое развертывание к вашему кластеру Kubernetes.

Перейдите в корневой каталог проекта из вашей командной оболочки.

Создайте приложение Spring Boot с обновлениями аутентификации:

gradle clean build

Создайте новый образ Docker. Обратите внимание на новое имя изображения (оно включает в себя -авт. ). Также: убедитесь, что ваш рабочий стол Docker запущен.

docker build -t kayak-app-auth:1.0 .

Пометьте и отправьте свое изображение Docker в реестр облачных контейнеров Google. При необходимости измените имя проекта в пути к репозиторию.

docker tag kayak-app-auth:1.0 gcr.io/$PROJECT_NAME/kayak-app-auth:1.0;  
docker push gcr.io/$PROJECT_NAME/kayak-app-auth:1.0;  

Удалите развернутый модуль в кластере:

kubectl delete -f deployment.yml

Обновите файл deployment.yml , чтобы отразить новое имя образа (строка 28 в файле):

spec:  
  containers:  
    - name: kayak-app  
      image: gcr.io/spring-boot-gke/kayak-app-auth:1.0

Повторно разверните обновленное развертывание Kubernetes:

kubectl apply -f deployment.yml

Используйте kubectl get pods для проверки состояния модуля. Полное обновление займет несколько секунд. Как только он будет готов, протестируйте конечную точку / .

http $INGRESS_HOST:$INGRESS_PORT/
HTTP/1.1 200 OK
...

Alive

И конечная точка /kayaks , которая должна быть защищена:

$ http $INGRESS_HOST:$INGRESS_PORT/kayaks
HTTP/1.1 401 Unauthorized
...

Так близко! Последнее, что вам нужно сделать, это использовать инструмент OIDC Debugger для создания токена и проверки подлинности JWT.

Создайте JWT и протестируйте OAuth 2.0

Перейдите в OIDC Debugger . Вам понадобится ваш Идентификатор клиента из вашего приложения Okta OIDC.

  • Заполните URI авторизации: https://{yourOktaDomain}/oauth2/default/v1/авторизовать .
  • Заполните Идентификатор клиента .
  • Поместите abcdef для состояния .
  • Внизу нажмите Отправить запрос .

Скопируйте сгенерированный токен и сохраните его в переменной оболочки для удобства:

TOKEN=eyJraWQiOiI4UlE5REJGVUJOTnJER0VGaEExekd6bWJqREp...

Снова запустите GET на конечной точке /kayaks , на этот раз с помощью токена:

http $INGRESS_HOST:$INGRESS_PORT/kayaks Authorization:"Bearer $TOKEN"

ОБРАТИТЕ внимание на двойные кавычки! Одинарные кавычки не будут работать, потому что переменная не будет расширена в строке.

Вы должны получить:

HTTP/1.1 200 OK
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-type: application/json;charset=UTF-8
...
[
  {
    "makeModel": "NDK",
    "name": "sea",
    "owner": "Andrew",
    "value": 300.12
  },
  {
    "makeModel": "Piranha",
    "name": "creek",
    "owner": "Andrew",
    "value": 100.75
  },
  {
    "makeModel": "Necky",
    "name": "loaner",
    "owner": "Andrew",
    "value": 75
  }
]

Продвигайтесь вперед с помощью микросервисов Spring Boot и Kubernetes

Вот и все! Вы покрыли здесь тонну земли. Вы создали кластер Kubernetes с историей, используя Google Kubernetes в Google Cloud. Вы настроили свою локальную систему для взаимодействия с кластером с помощью cloud и kubectl . Вы создали приложение Spring Boot, которое использовало серверную часть MongoDB, настроило его, поместило в облачный реестр Google и развернуло в своем кластере. Вы также добавили аутентификацию OIDC в приложение.

Вы можете найти исходный код для этого примера на GitHub по адресу oktadeveloper/okta-spring-boot-microservice-kubernetes .

Если вы увлекаетесь микросервисами и Spring Boot, вам тоже могут понравиться эти посты:

Если у вас есть какие-либо вопросы по поводу этого поста, пожалуйста, добавьте комментарий ниже. Для получения более потрясающего контента подписывайтесь на @oktadev в Twitter, ставьте нам лайки на Facebook или подписывайтесь на наш канал YouTube .

Оригинал: “https://dev.to/oktadev/build-a-microservice-architecture-with-spring-boot-and-kubernetes-3j3k”