Kubernetes. Часть 2. Hello World with Minikube

PREREQUISITES

В статье предполагаются базовые знания:

  • Docker
  • Spring Boot

Также предполагается наличие инструментария:

  • Docker
  • Инструменты для Java разработки: Java, Maven

ЦЕЛЬ

  • Установить и настроить Minikube;
  • Создать два простейших Spring Boot приложения;
  • Упаковать их в Docker;
  • Развернуть их в Minikube.

ЧТО ТАКОЕ MINIKUBE

Для локального развёртывания кластера Kubernetes мы будем использовать Minikube - инструмент, позволяющий легко запускать Kubernetes на локальной машине. Кластер, таким образом, будет состоять по факту из одной локальной ноды.

По большому счету, при обучении работе с Kubernetes, не важно сколько именно узлов присутствует в кластере, так как Kubernetes все равно позволяет абстрагироваться от этих деталей.

УСТАНОВКА MINIKUBE И СВЯЗАННОГО ИНСТРУМЕНТАРИЯ

Подготовка

sudo apt-get update -y

sudo apt-get upgrade -y

Устанавка virtualbox

sudo apt install virtualbox virtualbox-ext-pack

install-virtualbox.png

На консоли появится лицензионное соглашение. Нажмем Tab и Enter.

virtualbox-1.png

В следующем окне выберем "Да":

virtualbox-2.png

Установка Minikube

wget https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo cp minikube-linux-amd64 /usr/local/bin/minikube
sudo chmod 755 /usr/local/bin/minikube
minikube version

Установка Kubectl

curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl

chmod +x ./kubectl

sudo mv ./kubectl /usr/local/bin/kubectl

kubectl version -o json

Запуск Minikube

minikube start

start-minikube-service.png

Осталось сконфигурировать Minikube на работу с VirtualBox:

minikube config set vm-driver virtualbox

А также kubectl на работу с Minikube:

kubectl config use-context minikube

Теперь запросим информацию о нашем кластере через kubectl:

kubectl cluster-info

и увидим примерно следующий вывод:

cluster-info.jpg

Поздравляем! Процесс установки и настройки Minikube прошел успешно.

Мы даже можем открыть Kubernetes dashboard в браузере. Для этого надо исполнить:

minikube dashboard

и вы увидите в браузере следующую страничку:

dash.jpg

СОЗДАНИЕ ПРИЛОЖЕНИЙ ДЛЯ РАЗВЕРТЫВАНИЯ

Теперь создадим два простых Spring Boot приложения, которые условно назовем

  • mk-backend
  • mk-frontend

mk-backend будет предоставлять REST-ендпоинт на 8085 порту, возвращающий текст "Hello Kubernetes!".

mk-frontend будет доступен на 8081 порту. Всё, что он будет делать - он будет обращаться к mk-backend и возвращать результат.

(1) Создание mk-backend

С помощью Spring Initializr создадим проект:

mk-b.jpg

Добавим в него контроллер:

package com.example.mkbackend.controller;

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

@RestController
@RequestMapping
public class BackendController {

    @GetMapping(value = "/")
    public String hello() {
        return "Hello Kubernetes!";
    }
}

Отредактируем application.properties:

server.port=8085

Соберем проект maven-ом:

./mvnw clean install

Создадим Dockerfile:

dockfile-mk-back.jpg

FROM openjdk:11
VOLUME /tmp
COPY target/mk-backend-0.0.1-SNAPSHOT.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java -jar /app.jar --debug

(2) Создание mk-frontend

С помощью Spring Initializr создадим проект:

mk-f.jpg

Добавим в него контроллер:

package com.example.mkfrontend.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping
public class FrontendController {

    private static final String BACKEND_URL = "http://mk-backend:8085";

    @GetMapping(value = "/")
    public String hello() {
        RestTemplate restTemplate = new RestTemplate();

        ResponseEntity<String> response = restTemplate.getForEntity(BACKEND_URL, String.class);
        return ":" + response.getBody();
    }
}

Отредактируем application.properties:

server.port=8081

Соберем проект maven-ом:

./mvnw clean install

Создадим Dockerfile:

dockfile-mk-front.jpg

FROM openjdk:11
VOLUME /tmp
COPY target/mk-frontend-0.0.1-SNAPSHOT.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java -jar /app.jar

СОЗДАНИЕ DOCKER-ОБРАЗОВ

Docker-образы мы будем создавать именно в виртуальной машине с Minikube - это важно. Для этого нам нужно перекинуть наши исходники на виртуалку с Minikube.

Воспользуемся для этих целей обычным scp. Однако тут есть нюанс. Сначала нужно узнать логин/пароль этой машины.

# Подключаемся к виртуальной машине с Minikube:
minikube ssh
# Меняем пароль пользователя docker:
sudo passwd docker
# Запоминаем пароль
# Выходим из виртуальной машины:
exit

Далее переходим в папку с проектами и копируем mk-backend на машину с Minikube:

scp -r mk-backend docker@192.168.59.100:/home/docker/mk-backend

Аналогично копируем mk-frontend:

scp -r mk-frontend docker@192.168.59.100:/home/docker/mk-frontend

Теперь снова заходим в Minikube:

minikube ssh

и собираем Docker-образы:

cd mk-backend
docker build --file=Dockerfile --tag=mk-backend:latest --rm=true .
cd ..
cd mk-frontend
docker build --file=Dockerfile --tag=mk-frontend:latest --rm=true .

Убедимся, что образы действительно созданы:

docker images

imagesss.jpg

Итак, мы создали docker-образы наших проектов на виртуальной машине с Minikube.

Теперь выходим из виртуальной машины:

exit

Все дальнейшие шаги будут выполняться через утилиту kubectl и инструменты командной строки Minikube.

СПОСОБЫ РАЗВЕРТЫВАНИЯ В KUBERNETES

Чтобы развернуть контейнеры в инфраструктуре Kubernetes, можно пойти двумя путями:

  1. Разворачивать поды вручную, поочередно вводя команды Kubectl;
  2. Разворачивать поды, используя конфигурационные файлы.

Мы будем разворачивать более стационарным способом - с использованием конфигурационных файлов.

СОЗДАНИЕ КОНФИГУРАЦИЙ KUBERNETES

Создадим конфигурацию kubernetes.yml для развертывания mk-backend:

kuber-8085.jpg

kind: Service
apiVersion: v1
metadata:
  name: mk-backend
spec:
  selector:
    app: mk-backend
  ports:
    - protocol: TCP
      port: 8085
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mk-backend
spec:
  selector:
    matchLabels:
      app: mk-backend
  replicas: 3
  template:
    metadata:
      labels:
        app: mk-backend
    spec:
      containers:
        - name: mk-backend
          image: mk-backend:latest
          imagePullPolicy: Never
          ports:
            - containerPort: 8085

Данным файлом мы описываем две вещи:

  • Сервис
  • Deployment

Рассмотрим каждый элемент отдельно.

Сервис

Сервисы Kubernetes играют роль точек доступа к наборам подов. В случае mk-backend сервис имеет тип ClusterIP. Сервис такого типа предоставляет доступ через внутренний IP кластера. Таким образом – сервис будет доступен только внутри самого класетра.

Мы назвали сервис mk-backend.

С помощью блока spec мы проинструктировали Kubernetes перенаправлять все TCP-запросы к порту 8085 на любой POD, помеченный лейблом mk-backend.

Сервис ClusterIP также осуществляет балансировку нагрузки на POD-ы.

Deployment

Deployment — это абстракция Kubernetes, которая позволяют нам задавать правила развертывания приложений.

Блок template определяет POD:

  • Помечаем создаваемый POD лейблом в блоке labels (в данном случае mk-backend)
  • В блоке containers определяем перечень контейнеров, входящих в POD (в данном случае это будет один контейнер mk-backend)

Блок spec:selector определяет какие POD-ы нужно развернуть. В данном случае мы просто передаем объявленный POD mk-backend.

Наконец, Kubernetes легко позволяет создать несколько реплик одного POD-а с помощью тега replicas.

Аналогичным образом определяем конфигурацию Kubernetes для проекта mk-frontend:

mk-front-kuber.jpg

kind: Service
apiVersion: v1
metadata:
  name: mk-frontend
spec:
  selector:
    app: mk-frontend
  ports:
    - protocol: TCP
      port: 8081
      nodePort: 30001
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mk-frontend
spec:
  selector:
    matchLabels:
      app: mk-frontend
  replicas: 3
  template:
    metadata:
      labels:
        app: mk-frontend
    spec:
      containers:
        - name: mk-frontend
          image: mk-frontend:latest
          imagePullPolicy: Never
          ports:
            - containerPort: 8081

Эта конфигурация очень похожа на предыдущую. Отличия её лишь в номере порта и типе сервиса. Тип сервиса - это в данном случае NodePort, поскольку ClusterIP предоставляет доступ лишь внутри Kubernetes кластера, а NodePort дает доступ извне, что и нужно в случае приложения mk-frontend.

РАЗВЕРТЫВАНИЕ

Итак, приложения созданы, docker-образы уже на виртуальной машине Minikube, конфигурации Kubernetes написаны. Приступаем к развертыванию Kubernetes кластера.

Переходим в директорию mk-backend и запускаем развертывание:

kubectl create -f kubernetes.yml

Перечень существующих развертываний мы теперь можем посмотреть с помощью следующей команды:

kubectl get deployments

Аналогичным образом взглянем на список сервисов:

kubectl get services

Если процесс развертывания прошел правильно, мы увидим на консоли следующее:

depl-8085.jpg

Теперь аналогичным образом разворачиваем mk-frontend. Переходим в директорию mk-frontend и выполняем:

kubectl create -f kubernetes.yml

РЕЗУЛЬТАТ

Поздравления! Мы сконфигурировали и запустили кластер. Следующая команда

minikube service mk-frontend

запустит браузер на нашем хосте, где мы сможем увидеть результат:

res2.jpg

ПОВТОРНЫЙ ВХОД

После перезапуска рабочего PC необходимо запустить Minikube и развернуть все заново:

minikube start --driver=virtualbox

cd Projects/mk-backend

kubectl create -f kubernetes.yml

cd ..

cd mk-frontend

kubectl create -f kubernetes.yml

minikube service mk-frontend

TROUBLESHOOTING

Проверить доступность сервисов можно следующим образом:

# Приконнектиться к Minikube
minikube ssh

# Получить список развернутых Docker-контейнеров:
docker ps -a

# Войти в любой из контейнеров:
docker exec -it 5832775209d3 /bin/bash

# Ипользовать curl, чтобы протестировать endpoint:
curl 127.0.0.1:8081

ОБНОВЛЕНИЕ DOCKER-ОБРАЗОВ

Disclaimer: В данном примере обновление будет выполняться неоптимальным образом. Тем не менее:

1) Удалить сервисы и deployment-ы:

kubectl delete service mk-frontend
kubectl delete deployment mk-frontend
kubectl delete service mk-backend
kubectl delete deployment mk-backend

2) Пересобрать проекты maven-ом

3) Залить заново проекты в Minikube:

scp -r mk-backend docker@192.168.59.100:/home/docker/mk-backend

scp -r mk-frontend docker@192.168.59.100:/home/docker/mk-frontend

4) Собрать новые образы:

minikube ssh

cd mk-backend

docker build --file=Dockerfile --tag=mk-backend:latest --rm=true .

cd.. 

cd mk-frontend

docker build --file=Dockerfile --tag=mk-frontend:latest --rm=true .

exit

cd mk-backend

kubectl create -f kubernetes.yml

cd ..

cd mk-frontend

kubectl create -f kubernetes.yml

minikube service mk-frontend

СПРАВОЧНЫЕ КОМАНДЫ

# Запустить minikube:
minikube start --driver=virtualbox

# Отобразить сервисы:
kubectl get services

# Отобразить список POD-ов:
kubectl get pods --all-namespaces

# Отобразить логи по POD-у "mk-frontend-c8d7bd787-sxr6v":
kubectl logs mk-frontend-c8d7bd787-sxr6v

# Удалить сервисы и deployment-ы:
kubectl delete service mk-frontend
kubectl delete deployment mk-frontend
kubectl delete service mk-backend
kubectl delete deployment mk-backend


# Удалить POD c8d7bd787:
kubectl delete pod c8d7bd787

ССЫЛКИ НА ЛИТЕРАТУРУ

baeldung.com/spring-boot-minikube

habr.com/ru/company/ruvds/blog/438984

rtfm.co.ua/kubernetes-znakomstvo-chast-1-ar..