Серия вебинаров: Развертывание и масштабирование микросервисов в Kubernetes

Вступление

Kubernetes - инструмент оркестровки контейнеров с открытым исходным кодом для управления контейнеризованными приложениями. В предыдущем уроке из этой серии A Более пристальный взгляд на Kubernetes вы изучили строительные блоки Kubernetes.

В этом руководстве вы будете применять концепции из предыдущих руководств для создания, развертывания и управления комплексным приложением микросервисов в Kubernetes. Пример веб-приложения, которое вы будете использовать в этом руководстве, представляет собой приложение «список задач», написанное на Node.js, которое использует MongoDB в качестве базы данных. Это то же самое приложение, которое мы использовали в учебном пособии Building Containerized Applications.

Вы создадите образ контейнера для этого приложения из Dockerfile, переместите образ в Docker Hub, а затем разверните его в своем кластере. Затем вы масштабируете приложение, чтобы удовлетворить возросший спрос.

Предпосылки

Для завершения этого урока вам понадобится:

  • Кластер Kubernetes, который вы можете настроить в третьей части этой серии руководств, Getting Started with Kubernetes.

  • Активная учетная запись Docker Hub для хранения изображения.

  • Git установлен на вашем локальном компьютере. Вы можете следовать учебному руководству Contributing для Open Source: Начало работы с Git, чтобы установить и настроить Git на вашем компьютере.

Шаг 1 - Создайте образ с помощью Dockerfile

Мы начнем с контейнера веб-приложения, упаковав его в образ Docker.

Начните с изменения вашего домашнего каталога, затем используйте Git для клонирования примера веб-приложения этого руководства из его официального репозитория на GitHub.

cd ~
git clone https://github.com/janakiramm/todo-app.git

Создайте образ контейнера из Dockerfile. Используйте ключ -t, чтобы пометить изображение именем пользователя реестра, именем изображения и необязательным тегом.

docker build -t sammy/todo .

Вывод подтверждает, что изображение было успешно построено и помечено соответствующим образом.

OutputSending build context to Docker daemon  8.238MB
Step 1/7 : FROM node:slim
 ---> 286b1e0e7d3f
Step 2/7 : LABEL maintainer = "[email protected]"
 ---> Using cache
 ---> ab0e049cf6f8
Step 3/7 : RUN mkdir -p /usr/src/app
 ---> Using cache
 ---> 897176832f4d
Step 4/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 3670f0147bed
Step 5/7 : COPY ./app/ ./
 ---> Using cache
 ---> e28c7c1be1a0
Step 6/7 : RUN npm install
 ---> Using cache
 ---> 7ce5b1d0aa65
Step 7/7 : CMD node app.js
 ---> Using cache
 ---> 2cef2238de24
Successfully built 2cef2238de24
Successfully tagged sammy/todo-app:latest

Убедитесь, что образ создан, запустив команду docker images.

docker images

Вы можете увидеть размер изображения вместе со временем, с момента его создания.

OutputREPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
sammy/todo-app                                   latest              81f5f605d1ca        9 minutes ago       236MB

Затем отправьте изображение в общедоступный реестр на Docker Hub. Для этого войдите в свою учетную запись Docker Hub:

docker login

После того, как вы предоставите свои учетные данные, отметьте свое изображение, используя имя пользователя Docker Hub:

docker tag /todo-app

Затем отправьте изображение в Docker Hub:

docker push

Вы можете убедиться, что новое изображение доступно, выполнив поиск Docker Hub в вашем веб-браузере.

Передав изображение Docker в реестр, давайте запакуем приложение для Kubernetes.

Шаг 2 - Разверните MongoDB Pod в Кубернетесе

Приложение использует MongoDB для хранения списков дел, созданных через веб-приложение. Чтобы запустить MongoDB в Kubernetes, нам нужно упаковать его как Pod. Когда мы запустим этот Pod, он запустит один экземпляр MongoDB.

Создайте новый файл YAML с именем db-pod.yaml:

nano db-pod.yaml

Добавьте следующий код, который определяет Pod с одним контейнером на основе MongoDB. Мы выставляем порт + 27017 +, стандартный порт, используемый MongoDB. Обратите внимание, что определение содержит метки + name и` + app`. Мы будем использовать эти ярлыки для идентификации и настройки конкретных модулей.

дб-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: db
  labels:
    name: mongo
    app: todoapp

spec:
      containers:
      - image: mongo
        name: mongo
        ports:
        - name: mongo
          containerPort: 27017

        volumeMounts:
          - name: mongo-storage
            mountPath: /data/db

      volumes:
          - name: mongo-storage
            hostPath:
              path: /data/db

Данные хранятся в томе, называемом + mongo-storage +, который сопоставлен с местоположением + / data / db + узла. Для получения дополнительной информации о томах см. Официальную документацию по томам Kubernetes.

Выполните следующую команду, чтобы создать Pod.

kubectl create -f db-pod.yml

Вы увидите этот вывод:

Outputpod "db" created

Теперь проверьте создание Pod.

kubectl get pods

Вывод показывает Pod и указывает, что он работает:

OutputNAME      READY     STATUS    RESTARTS   AGE
db   1/1          0          2m

Давайте сделаем этот Pod доступным для внутренних потребителей кластера.

Создайте новый файл с именем + db-service.yaml +, содержащий этот код, который определяет Сервис для MongoDB:

дб-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: db
  labels:
    name: mongo
    app:

spec:
  selector:
    name: mongo

  type: ClusterIP
  ports:
    - name: db
      port: 27017
      targetPort: 27017

Служба обнаруживает все модули в одном и том же пространстве имен, которые соответствуют метке с + name: db +. Раздел + selector + файла YAML явно определяет эту связь.

Мы указываем, что Сервис виден внутри кластера через объявление + type: ClusterIP +.

Сохраните файл и выйдите из редактора. Затем используйте + kubectl +, чтобы отправить его в кластер.

kubectl create -f db-service.yml

Вы увидите этот вывод, указывающий, что Сервис был успешно создан:

Outputservice "db" created

Давайте получим порт, на котором доступен Pod.

kubectl get services

Вы увидите этот вывод:

OutputNAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
db           ClusterIP   10.109.114.243   <none>           14s
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP     47m

Из этого вывода вы можете видеть, что Сервис доступен на порту + 27017 +. Веб-приложение может связаться с MongoDB через этот сервис. Когда он использует имя хоста + db +, служба DNS, работающая в Kubernetes, преобразует адрес в ClusterIP, связанный с Сервисом. Этот механизм позволяет стручкам обнаруживать и общаться друг с другом.

Имея базу данных Pod и Service, давайте создадим Pod для веб-приложения.

Шаг 3. Разверните Node.JS Web App как модуль

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

Создайте новый файл YAML с именем + web-pod.yaml +:

nano web-pod.yaml

Добавьте следующий код, который определяет Pod с одним контейнером на основе образа Docker + sammy / todo-app +. Он выставлен на порт + 3000 + по протоколу TCP.

веб-pod.yaml

apiVersion: v1
kind: Pod

metadata:
  name: web
  labels:
    name: web
    app:

spec:
  containers:
    - image: sammy/todo-app
      name: myweb
      ports:
        - containerPort: 3000

Обратите внимание, что определение содержит метки + name и` + app`. Сервис будет использовать эти метки для маршрутизации входящего трафика на соответствующие порты.

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

kubectl create -f web-pod.yaml
Outputpod "web" created

Давайте проверим создание Pod:

kubectl get pods
OutputNAME      READY     STATUS    RESTARTS   AGE
       1/1       Running   0          8m
      1/1       Running   0          9s

Обратите внимание, что у нас есть и база данных MongoDB, и веб-приложение, работающее как Pod.

Теперь мы сделаем Pod + web + общедоступным Интернетом.

Сервисы предоставляют набор модулей как внутри, так и снаружи. Давайте определим Сервис, который делает «+ web +» Pod общедоступным. Мы представим его через NodePort, схему, которая делает Pod доступным через произвольный порт, открытый на каждом узле кластера.

Создайте новый файл с именем + web-service.yaml +, который содержит этот код, который определяет Сервис для приложения:

apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    name: web
    app:

spec:
  selector:
    name: web
  type: NodePort
  ports:
   - name: http
     port: 3000
     targetPort: 3000
     protocol: TCP

Служба обнаруживает все модули в одном и том же пространстве имен, которые соответствуют метке с именем + web +. Раздел селектора файла YAML явно определяет эту связь.

Мы указываем, что Сервис имеет тип + NodePort + через объявление + type: NodePort +.

Используйте + kubectl + для отправки этого в кластер.

kubectl create -f web-service.yml

Вы увидите этот вывод, указывающий, что Сервис был успешно создан:

Outputservice "web" created

Давайте получим порт, на котором доступен Pod.

kubectl get services
OutputNAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
db           ClusterIP   10.109.114.243   <none>        27017/TCP        12m
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          59m
web          NodePort    10.107.206.92    <none>        3000:   12s

Из этого вывода мы видим, что Сервис доступен через порт + 30770 +. Давайте попробуем подключиться к одному из рабочих узлов.

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

изображение: https: //assets.digitalocean.com/articles/webinar_3_kubernetes_stackpoint/w9acP7y.png [Консоль DigitalOcean, показывающая рабочие узлы]

Получив IP-адрес, используйте команду + curl +, чтобы сделать HTTP-запрос к одному из узлов на порту + 30770 +:

curl http://:30770

Вы увидите вывод, похожий на этот:

Output<!DOCTYPE html>
<html>
  <head>
    <title>Containers Todo Example</title>
    <link rel='stylesheet' href='/stylesheets/screen.css' />
    <!--[if lt IE 9]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
  </head>
  <body>
    <div id="layout">
<h1 id="page-title">Containers Todo Example</h1>
<div id="list">
  <form action="/create" method="post" accept-charset="utf-8">
    <div class="item-new">
      <input class="input" type="text" name="content" />
    </div>
  </form>
</div>
      <div id="layout-footer"></div>
    </div>
    <script src="/javascripts/ga.js"></script>
  </body>
</html>

Вы определили веб-Pod и Сервис. Теперь давайте рассмотрим масштабирование с помощью наборов реплик.

Шаг 5 - Масштабирование веб-приложения

Набор реплик гарантирует, что в кластере постоянно работает минимальное количество модулей. Когда модуль упакован как набор реплик, Kubernetes всегда запускает минимальное количество модулей, указанное в спецификации.

Давайте удалим текущий Pod и воссоздадим два Pod через набор реплик. Если мы оставим модуль запущенным, он не будет частью набора реплик. Таким образом, было бы неплохо запускать Pod через набор реплик, даже если счетчик всего один.

Сначала удалите существующий Pod.

kubectl delete pod web
Outputpod "web" deleted

Теперь создайте новое объявление набора реплик. Определение набора реплик идентично стручку. Основное отличие состоит в том, что он содержит элемент + replica +, который определяет количество модулей, которые необходимо запустить. Как и Pod, он также содержит метки как метаданные, которые помогают в обнаружении служб.

Создайте файл + web-rs.yaml + и добавьте этот код в файл:

apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
  name: web
  labels:
    name: web
    app: todoapp

spec:
  replicas: 2
  template:
    metadata:
      labels:
        name: web
    spec:
      containers:
      - name: web
        image: sammy/todo-app
        ports:
        - containerPort: 3000

Сохраните и закройте файл.

Теперь создайте набор реплик:

kubectl create -f web-rs.yaml
Outputreplicaset "web" created

Затем проверьте количество стручков:

kubectl get pods
OutputNAME        READY     STATUS    RESTARTS   AGE
db          1/1       Running   0          18m
web-n5l5h   1/1       Running   0          25s
web-wh6nf   1/1       Running   0          25s

Когда мы получаем доступ к Сервису через NodePort, запрос будет отправлен одному из модулей, управляемых набором реплик.

Давайте проверим функциональность набора реплик, удалив один из модулей и посмотрев, что произойдет:

kubectl delete pod web-wh6nf
Outputpod "web-wh6nf" deleted

Посмотрите на стручки еще раз:

kubectl get pods
OutputNAME        READY     STATUS              RESTARTS   AGE
db          1/1       Running             0          19m
web-n5l5h   1/1       Running             0          1m
web-wh6nf   1/1       Terminating         0          1m
web-ws59m   0/1       ContainerCreating   0          2s

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

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

Выполните следующую команду, чтобы масштабировать веб-приложение до 10 пакетов.

kubectl scale rs/web --replicas=
Outputreplicaset "web" scaled

Проверьте количество стручков:

kubectl get pods

Вы увидите этот вывод:

OutputNAME        READY     STATUS              RESTARTS   AGE
db          1/1       Running             0          22m
web-4nh4g   1/1       Running             0          21s
web-7vbb5   1/1       Running             0          21s
web-8zd55   1/1       Running             0          21s
web-f8hvq   0/1       ContainerCreating   0          21s
web-ffrt6   1/1       Running             0          21s
web-k6zv7   0/1       ContainerCreating   0          21s
web-n5l5h   1/1       Running             0          3m
web-qmdxn   1/1       Running             0          21s
web-vc45m   1/1       Running             0          21s
web-ws59m   1/1       Running             0          2m

Kubernetes инициировал процесс масштабирования Pod + web +. Когда запрос поступает в Сервис через NodePort, он направляется к одному из модулей в наборе реплик.

Когда трафик и нагрузка уменьшатся, мы можем вернуться к исходной конфигурации двух модулей.

kubectl scale rs/web --replicas=
Outputreplicaset "web" scaled

Эта команда завершает все блоки, кроме двух.

kubectl get pods
OutputNAME        READY     STATUS        RESTARTS   AGE
db          1/1       Running       0          24m
web-4nh4g   1/1       Terminating   0          2m
web-7vbb5   1/1       Terminating   0          2m
web-8zd55   1/1       Terminating   0          2m
web-f8hvq   1/1       Terminating   0          2m
web-ffrt6   1/1       Terminating   0          2m
web-k6zv7   1/1       Terminating   0          2m
web-n5l5h   1/1       Running       0          5m
web-qmdxn   1/1       Terminating   0          2m
web-vc45m   1/1       Terminating   0          2m
web-ws59m   1/1       Running       0          4m

Чтобы проверить доступность набора реплик, попробуйте удалить один из модулей и проверьте количество.

kubectl delete pod web-ws59m
Outputpod "web-ws59m" deleted
kubectl get pods
OutputNAME        READY     STATUS              RESTARTS   AGE
db          1/1       Running             0          25m
web-n5l5h   1/1       Running             0          7m
web-ws59m   1/1       Terminating         0          5m
web-z6r2g   0/1       ContainerCreating   0          5s

Как только счетчик стручков изменяется, Kubernetes настраивает его так, чтобы он соответствовал количеству, определенному в файле YAML. Когда один из веб-модулей в наборе реплик удаляется, немедленно создается другой модуль для поддержания необходимого количества. Это обеспечивает высокую доступность приложения за счет того, что минимальное количество модулей работает постоянно.

Вы можете удалить все объекты, созданные в этом уроке, с помощью следующей команды:

kubectl delete -f db-pod.yaml -f db-service.yaml -f web-rs.yaml -f web-service.yaml
Outputpod "db" deleted
service "db" deleted
replicaset "web" deleted
service "web" deleted

Заключение

В этом руководстве вы применили все концепции, описанные в этой серии, для упаковки, развертывания и масштабирования приложений микросервисов.

В следующей части этой серии вы узнаете, как сделать MongoDB высокодоступным, запустив его как StatefulSet.

Related