Как стать автором
Обновить

Spring Boot приложение в Kubernetes с Postgresql и Loki

Время на прочтение5 мин
Количество просмотров7.4K

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

Более подробно о всех компонентах :

  1. Spring Boot приложение, использующее в качестве БД PostgreSQL

  2. Docker образ сервера базы данных

  3. Docker Grafana (dashboard для отображения логов)

  4. Docker образ Loki(система сбора логов)

  5. Promtail (агент для отсылки логов в Loki).

    Kubernetes cluster будет развернут при помощи microk8s. В качестве балансировщика нагрузки и по совместительству web-сервера будет выступать nginx, а точнее nginx-ingress-controller, который есть в microk8s.


Рассмотрим развертывания каждого компонента по отдельности.

Шаг 1: База данных

Для базы данных используем следующий yaml

apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  ports:
    - port: 5432
  selector:
    app: db
  clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db
spec:
  selector:
    matchLabels:
      app: db
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
        - image: postgres:9.6
          name: db
          env:
            - name: POSTGRES_USER
              value: admin

            - name: POSTGRES_PASSWORD
              value: admin

            - name: POSTGRES_DB
              value: dbname

          ports:
            - containerPort: 5432
              name: db

В файле сразу описан и сервис, и развертывание базы. Как образ ,использован образ Postgres 9.6

Для создания развертывания исполним командуkubectl apply -f db.yaml

Шаг 2: Grafana

Для Grafana используем следующий yaml

apiVersion: v1
kind: Service
metadata:
  name: grafana
spec:
  ports:
    - port: 3000
  selector:
    app: grafana
  clusterIP: None
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
spec:
  selector:
    matchLabels:
      app: grafana
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: grafana
    spec:
      containers:
        - image: grafana/grafana:master
          name: grafana


          ports:
            - containerPort: 3000
              name: grafana

Развертывание похоже на то, что использовано для базы данных. Разница в образе (grafana/grafana:master) и в выставляемом порте.

Аналогично выполним командуkubectl apply -f grafana.yaml

Шаг 3: Loki

Как и выше yaml

apiVersion: v1
kind: Service
metadata:
  name: loki
spec:
  ports:
    - port: 3100
  selector:
    app: loki
  clusterIP: None
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: loki
spec:
  selector:
    matchLabels:
      app: loki
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: loki
    spec:
      containers:
        - image: grafana/loki:latest
          name: loki


          ports:
            - containerPort: 3100
              name: loki

И командаkubectl apply -f grafana.yaml

Шаг 4: Promtail

Для promtail понадобится следующий yaml

apiVersion: v1
kind: List
items:
  - apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: promtail-daemonset
    spec:
      selector:
        matchLabels:
          name: promtail
      template:
        metadata:
          labels:
            name: promtail
        spec:
          serviceAccount: SERVICE_ACCOUNT
          serviceAccountName: SERVICE_ACCOUNT
          volumes:
            - name: logs
              hostPath:
                path: HOST_PATH
            - name: promtail-config
              configMap:
                name: promtail-configmap
          containers:
            - name: promtail-container
              image: grafana/promtail
              args:
                - -config.file=/etc/promtail/promtail.yaml
              volumeMounts:
                - name: logs
                  mountPath: MOUNT_PATH
                - name: promtail-config
                  mountPath: /etc/promtail

  - apiVersion: v1
    kind: ConfigMap
    metadata:
      name: promtail-config
    data:
      promtail.yaml: |
        clients:
            - url: http://loki:3100/loki/api/v1/push

  - apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: promtail-clusterrole
    rules:
      - apiGroups: [ "" ]
        resources:
          - nodes
          - services
          - pods
        verbs:
          - get
          - watch
          - list

  - apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: promtail-serviceaccount

  - apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: promtail-clusterrolebinding
    subjects:
      - kind: ServiceAccount
        name: promtail-serviceaccount
        namespace: default
    roleRef:
      kind: ClusterRole
      name: promtail-clusterrole
      apiGroup: rbac.authorization.k8s.io

И командаkubectl apply -f promtail.yaml

Шаг 5: Ingress

Для nginx используем следующий файл.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: server
spec:
  rules:
     
    - http:
        paths:
          - path: /server
            pathType: Prefix
            backend:
              service:
                name: server
                port:
                  number: 8024
                  
          - path: /grafana
            pathType: Prefix
            backend:
              service:
                name: grafana
                port:
                  number: 3000       

И команду kubectl apply -f ingress.yaml

Шаг 7: Приложение

Этот шаг не похож ни на один предыдущий. Здесь не будет использовано ни одного yaml и ни одного готового Docker образа. Нужное нам развертывание будет создано сразу после процесса сборки. Для этого используется Maven + jkube maven plugin

Рассмотрим процесс сборки . Сначала install собирает jar с приложением, затем k8s:resource генерирует ресурсы, потом k8s:build создаст Docker oбраз и k8s:deploy сделает развертывание.

Ниже пример конфигурации плагина для данного процесса

<profile>
            <id>kube</id>
            <properties>
                <spring.profiles.active>docker</spring.profiles.active>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.eclipse.jkube</groupId>
                        <artifactId>kubernetes-maven-plugin</artifactId>
                        <version>1.1.1</version>
                        <configuration>
                            <verbose>true</verbose>
          
                            <images>
                                <image>
                                    <name>imagename:latest</name>
                                    <alias>some-alias/alias>
                                    <build>
                                        <maintainer>John Smith</maintainer>
                                        <from>fabric8/java-centos-openjdk11-jre</from>
                                        <assembly>
                                            <inline>
                                                <baseDirectory>/deployments</baseDirectory>
                                            </inline>

                                        </assembly>
                                    </build>
                                </image>
                            </images>

                        </configuration>
                        <executions>
                            <execution>
                                <id>run</id>
                                <goals>
                                    <goal>resource</goal>
                                    <goal>build</goal>
                                    <goal>deploy</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>

        </profile>

Образ описан под тегом image. Также можно использовать один из генераторов.

Также необходимо создать сервис. Для этого выполним

kubectl expose deployment server --type=LoadBalancer --name=server --port=<some-port>

Почему был использован данный способ создания сервиса, ведь сервис можно сконфигурировать также в плагине? На данный момент, была обнаружена ошибка в момент старта приложения в поде : вместо ip сервиса, приходит строка tcp://<ip-service>. Это приводит к NumberFormatException.

Шаг 8: Проверка доступа

В браузере или с помощью curl проверить, что localhost возвращает страницу приложения, localhost/grafana покажет страницу входа в Grafana.

Шаг 9: Отобразить логи

Для этого необходимо войти в Grafana с помощью логина/пароля admin . После необходимо указать ,в качестве источника данных Loki(http://loki:3000). Затем в explore ввести {app="название-приложения"} .

P.S.

Сбор логов был основан на данной статье.

Теги:
Хабы:
+1
Комментарии9

Публикации

Истории

Работа

Java разработчик
358 вакансий
DevOps инженер
46 вакансий

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн