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

Запуск проекта в Kubernetes за 60 минут

Блог компании Mail.ru Group Облачные вычисления *DevOps *Облачные сервисы Kubernetes *


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


Я Павел Селиванов, ведущий DevOps-инженер облачной платформы Mail.ru Cloud Solutions. Я расскажу про альтернативный способ развертывания Kubernetes — использование Managed-варианта от облачного провайдера. Мы запустим реальный API-сервис на примере нашего облака и пройдем основные шаги развертывания приложений в K8s, включая подготовку инфраструктуры, настройку CI/CD-конвейера и всех необходимых объектов Kubernetes: Deployment, Service, Ingress и так далее.


В результате попробуем убедиться, что 60 минут — вполне достаточное время для освоения азов работы с K8s при условии использования его в виде aaS.


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


Практикум в видеоформате можно посмотреть по ссылке.


1. Архитектура проекта


Архитектурно проект будет максимально простым. Мы развернем в кластере Kubernetes небольшое приложение, написанное на Go и представляющее собой простой API-сервис для работы с пользователями — для их добавления, просмотра, изменения и удаления.


Для приложения заранее подготовлен Dockerfile, обеспечивающий сборку Docker-контейнера. Приложение будет развернуто в кластере Kubernetes в двух инстансах. Однако это количество при необходимости можно изменить.


В качестве бэкенда будем использовать базу данных PostgreSQL, которую запустим в виде aaS в облаке MCS. В базе будут храниться пользователи, добавляемые через приложение.


Для организации доступа к приложению через интернет воспользуемся стандартными абстракциями Kubernetes: Ingress и Service.


Код приложения доступен полностью в GitHub.



Архитектура проекта


2. Подготовка инфраструктуры


Для настройки инфраструктуры необходимо зарегистрироваться на платформе Mail.ru Cloud Solutions, зайти в личный кабинет и последовательно настроить кластер Kubernetes и БД PostgreSQL.


Создание кластера Kubernetes


Для добавления нового кластера в панели управления облаком MCS необходимо выбрать пункт меню «Контейнеры» — «Кластеры Kubernetes». В открывшейся форме нажать кнопку «Создать кластер».



Создание нового кластера


На первом шаге требуется выбрать конфигурацию кластера (среду) и необходимые сервисы. Среды отличаются параметрами виртуальных машин и отказоустойчивостью: например, для среды Production предусмотрено 3 Master-узла. Для нашего проекта выберем среду Staging. Среди предустановленных сервисов следует обязательно отметить Ingress Controller Nginx.



Выбор конфигурации и предустановленных сервисов на первом шаге создания кластера


На втором шаге указывается имя кластера, параметры Master-узлов и сети. Все значения параметров можно оставить по умолчанию.



На втором шаге создания кластера оставляем значения по умолчанию


На третьем шаге задаются параметры Node-узлов, а также включается автомасштабирование при необходимости. Укажем количество Node равным 2, остальные параметры можно оставить по умолчанию.



Указание количества Node-узлов на третьем шаге создания кластера


После нажатия на кнопку «Создать кластер» запустится процесс конфигурирования кластера, который может занять 10–20 минут. После его завершения на экране появится информация о созданном кластере, а также можно будет скачать конфигурационный файл kubeconfig. В нем содержатся настройки, необходимые для авторизации в кластере.


Далее необходимо установить клиент kubectl на локальную машину и в переменные окружения экспортировать конфигурационный файл созданного кластера с расширением .yaml следующей командой:


export KUBECONFIG=<путь к файлу kubeconfig>

После этого можно просмотреть узлы, созданные в кластере:


kubectl get no 

В ответе увидим три узла: один Master и две ноды, которые будут использоваться для запуска приложения.



Создание БД PostgreSQL


Для добавления инстанса БД необходимо в панели управления облаком выбрать пункт меню «Базы данных» и нажать на кнопку «Создать БД» на панели «PostgreSQL».



Переход к созданию инстанса БД


На первом шаге можно изменить тип и версию БД — оставляем PostgreSQL версии 12. Из конфигураций выбираем Single — единичный инстанс, подходящий для разработки и тестирования.



Выбор типа БД и конфигурации на первом шаге создания инстанса БД


На втором шаге указывается имя инстанса БД, тип виртуальной машины, размер диска и ряд других параметров. Все значения можно оставить по умолчанию, кроме настроек сети: необходимо выбрать ту же виртуальную сеть, что была выбрана (или создана) для кластера Kubernetes. Это нужно для того, чтобы приложения, запущенные в Kubernetes, могли без каких-либо дополнительных настроек получать доступ к инстансу БД.



Выбор сети кластера Kubernetes на втором шаге создания инстанса БД


На третьем шаге необходимо указать имя базы данных (по умолчанию совпадает с именем инстанса), логин пользователя (по умолчанию user) и пароль пользователя. Для автоматической генерации пароля можно нажать на кнопку «Сгенерировать».


Так как пароль нам в дальнейшем потребуется, можно заранее скопировать его во временный файл (у нас db-password) с помощью команды:


echo -n <сгенерированный пароль> > db-password


Ввод имени БД, логина и пароля пользователя на третьем шаге создания инстанса БД


После нажатия на кнопку «Создать базу данных» запустится процесс инициализации инстанса БД, который займет несколько минут. После его успешного завершения на экране появится информация о созданном инстансе.


3. Добавление проекта на GitLab


Следующий шаг — перенос проекта, который был предварительно создан мной на GitHub, в GitLab для дальнейшей настройки конвейера CI/CD. Для начала клонируем проект с GitHub на локальный компьютер. Далее необходимо зарегистрироваться на официальном сайте GitLab и создать новый проект mcs-kubernetes-project с уровнем доступа Private.



Создание нового проекта в GitLab


Далее клонируем созданный проект на локальную машину командой:


git clone <путь к созданному проекту на GitLab>

При выполнении команды будет показано предупреждение о пустом проекте — это не ошибка.



Переходим в созданную папку mcs-kubernetes-project и копируем в нее содержимое директории app из проекта, предварительного загруженного с GitHub:


cd mcs-kubernetes-project
cp -r <локальный путь к проекту, загруженному с GitHub>/app/* .

Применив после этого команду ls -la, должны получить следующий набор файлов:



Остановимся подробнее на Dockerfile. В нем используется двухэтапная сборка (Multi-stage Build). Сначала собирается Go-приложение в одном образе (golang:1.14), в котором есть компилятор Go, все необходимые библиотеки и зависимости. А затем берется полностью пустой образ (scratch), где будет размещен только бинарник приложения. Содержимое Dockerfile приведено ниже:


FROM golang:1.14 as builder
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server .
FROM scratch
ENV PORT=8080
COPY --from=builder /app/server /
EXPOSE 8080
CMD ["/server"]

Закоммитим изменения и запушим их в GitLab. Для этого выполним следующие команды:


git add .
git commit -m "Initial commit"
git push -u origin master 

В результате должно обновиться содержимое репозитория на GitLab в разделе «Project information»:



Файлы успешно загружены в репозиторий на GitLab


4. Настройка пайплайна CI/CD


Настройка CI/CD необходима для того, чтобы максимально сократить количество ручных операций на проекте. Когда разработчик добавляет изменения в код и пушит их в GitLab, репозиторий должен это обнаружить, протестировать и уведомить об ошибках, а в случае отсутствия ошибок выполнить сборку Docker-образа и разместить его в Docker Registry. В качестве Docker Registry будем использовать тот, что встроен в GitLab. На последнем шаге полностью протестированное приложение будет автоматически развернуто в Kubernetes-кластере.



Упрощенная схема CI/CD


Для реализации описанного пайплайна необходимо:


  • настроить GitLab Runner, который будет брать задачи из yaml-манифеста и выполнять их;
  • настроить непосредственно сам манифест gitlab-ci.yml.

Установка GitLab Runner


Недостаток приватных проектов на GitLab в том, что выделяемые им общедоступные раннеры (Shared Runners) ограничены по количеству CI-часов. Поэтому мы не будем использовать раннеры GitLab — создадим свой собственный. Для этого добавим репозиторий с Helm-чартами GitLab, используя следующую команду:


helm repo add gitlab https://charts.gitlab.io

Далее создадим в Kubernetes отдельный namespace — gitlab:


kubectl create namespace gitlab

И затем в рамках созданного namespace установим GitLab Runner. Но предварительно нам потребуется получить для него регистрационный токен на сайте GitLab. Для этого в меню проекта нужно выбрать пункт «Settings» — «CI/CD» и в секции «Runners» нажать на кнопку «Expand»:



Переход к параметрам «Runners»


В открывшейся форме необходимо отключить использование Shared runners, сбросив флажок «Enable shared runners for this project», и скопировать регистрационный токен из секции «Specific runners».



Копирование токена и отключение Shared runners


Остается установить Runner при помощи следующей команды, предварительно прописав в параметре runnerRegistrationToken скопированное значение токена:


helm install --namespace gitlab gitlab-runner gitlab/gitlab-runner \
  --set rbac.create=true \
  --set runners.privileged=true \
  --set gitlabUrl=https://gitlab.com/ \
  --set runnerRegistrationToken=<скопированный токен из раздела Runners>

Проверить установку Runner можно командой, которая выводит список подов в namespace gitlab:


kubectl get po -n gitlab

Когда в ответе на команду в столбце «READY» появится значение «1/1», раннер будет успешно запущен.



В самом GitLab при этом в разделе «Runners» — «Specific runners» появится информация о добавленном Runner.



Появление Runner в разделе «Runners» — «Specific runners», доступном после выбора пункта меню «Settings» — «CI/CD»


Настройка yaml-манифеста


Манифест с описанием пайплайна gitlab-ci.yml необходимо добавить в репозиторий из проекта, предварительного загруженного с GitHub, следующей командой:


cp -r <локальный путь к проекту, загруженному с GitHub>/.gitlab-ci.yml .

Пайплайн CI/CD будет включать три стадии:


  • test — тестирование,
  • build — сборка Docker-образа,
  • deploy — развертывание в Kubernetes.

Остановимся пока на описании первых двух стадий, к деплою вернемся позднее.


На стадии test будет проводиться простой синтаксический анализ кода с помощью команды gofmt. Когда будут обнаружены изменения в коде и CI/CD запустится, GitLab Runner запустит новый контейнер из образа golang:1.14, в котором есть все необходимые утилиты для работы с Go, склонирует туда репозиторий и выполнит необходимое тестирование.


test:
  stage: test
  image: golang:1.14
  script:
    - gofmt -e . > /dev/null

На стадии build будет выполняться сборка Docker-образа обновленного приложения. Для этого потребуется Docker daemon, который в манифесте описывается в секции services. GitLab Runner будет запускать новый контейнер из образа docker:19.03.12, а в нем — еще один контейнер для запуска демона, и уже там будет происходить сборка образа приложения. В качестве альтернативы такому способу можно использовать «бездокерные» сборки, предлагаемые в ряде Open Source-решений, например Kaniko.


Секция before_script стадии build описывает действия, которые необходимо выполнить перед сборкой — авторизоваться в Docker Registry. Секция script описывает саму сборку — создание Docker-образа и его отправку в Docker Registry. Каждый новый образ будет создаваться с уникальным именем, состоящим из имени Branch или Tag, для которого происходит сборка (CI_COMMIT_REF_SLUG) и уникального идентификатора пайплайна (CI_PIPELINE_ID).


Все переменные, используемые в этих двух секциях, встроены в сам GitLab, то есть значения для них будут подставляться непосредственно при выполнении. Поэтому пайплайн является достаточно универсальным для использования в других проектах.


build:
  image: docker:19.03.12
  stage: build
  services:
    - docker:19.03.12-dind
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID"

После копирования файла gitlab-ci.yml в локальный репозиторий необходимо закоммитить изменения и отправить их в GitLab:


git add .
git commit -m "Add CI"
git push 

При переходе в GitLab увидим запуск первого пайплайна.



Запуск пайплайна в GitLab


Чтобы пояснить суть контейнерных сборок, о которых шла речь выше, можно во время выполнения CI/CD запустить команду для просмотра подов в namespace gitlab с использованием ключа -w (означающего бесконечный проcмотр в режиме реального времени):


kubectl get po -n gitlab -w

В выводе команды будут отображаться поды с префиксом «runner-» — это контейнеры, которые создает Gitlab Runner из образов, указанных в манифесте gitlab-ci.yml. Сначала создается контейнер для выполнения тестирования (test), затем для выполнения сборки (build). Впоследствии они уничтожатся.



Стадии test и build должны выполниться, а deploy завершится с ошибкой, потому что сейчас у нас не хватает дополнительных настроек.



Результат выполнения пайплайна


Созданный на стадии build образ приложения можно посмотреть в GitLab в пункте меню «Packages & Registries» — «Container Registry». Образ можно загрузить на локальный компьютер или развернуть в кластере Kubernetes. Обратите внимание на размер — он будет очень небольшим, всего 4,5 MiB.



Просмотр образа приложения, созданного на стадии «build»


5. Настройка объектов Kubernetes и переменных GitLab, необходимых для деплоя проекта


Deployment


Первое, что нужно сделать для развертывания приложения в кластере Kubernetes, — настроить Deployment. Это абстракция Kubernetes, управляющая жизненным циклом приложения и описывающая особенности его запуска: сколько реплик требуется запустить, из какого образа, на каких портах, сколько ресурсов необходимо выделить (RAM, CPU), какие Healthcheck можно использовать для проверки работоспособности, какие метки и селекторы применять и так далее.



Deployment


Перейдем к настройке Deployment. Для начала скопируем в локальный репозиторий папку .kube из директории с проектом, загруженным с GitHub:


cp -r <локальный путь к проекту, загруженному с GitHub>/.kube .

Содержимое файла deployment.yaml из папки .kube приведено ниже. Несколько слов о важных параметрах Deployment:


  • replicas — количество реплик приложения, в нашем примере равное 2;
  • progressDeadlineSeconds — максимальный тайм-аут (в секундах), допустимый для развертывания. В нашем примере равен 2 минутам. Если по истечении этого времени будут развернуты не все необходимые поды, будет выполнен автоматический откат к предыдущей версии приложения. Kubernetes по умолчанию реализует Rolling Update: откат произойдет максимально незаметно для пользователя с постепенным переводом пользователей на работоспособные реплики;
  • image — ссылка на образ приложения. Плейсхолдер заменять не нужно: он будет заполняться непосредственно при развертывании, при помощи команды sed. Это самый простой вариант, на практике рекомендуется использовать Helm.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: mcs-kubernetes-project
    spec:
    replicas: 2
    progressDeadlineSeconds: 120
    selector:
    matchLabels:
      app: mcs-kubernetes-project
    template:
    metadata:
      labels:
        app: mcs-kubernetes-project
    spec:
      imagePullSecrets:
        - name: mcs-kubernetes-project-image-pull
      containers:
        - name: mcs-kubernetes-project
          image: <IMAGE>
          env:
            - name: DB_HOST
              value: <Адрес БД из интерфейса MCS (в нашем примере 10.0.0.13)>
            - name: DB_PORT
              value: "5432"
            - name: DB_USER
              value: "<Логин пользователя БД из интерфейса MCS (в нашем примере user)>"
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mcs-kubernetes-project
                  key: db-password
            - name: DB_NAME
              value: <Имя БД из интерфейса MCS (в нашем примере PostgreSQL-4463)>
          ports:
            - name: http
              containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: http
            periodSeconds: 10
            initialDelaySeconds: 10

    В файле необходимо вручную прописать ряд параметров.



    Для получения адреса БД, который необходимо прописать в параметре DB_HOST, необходимо вернуться в панель управления облаком MCS и открыть информацию о созданном инстансе БД в пункте меню «Базы данных» — «Инстансы баз данных». Искомый параметр будет отображаться на вкладке «Информация» в поле «Внутренний IP-адрес».



    Получение внутреннего IP-адреса инстанса БД — для параметра DB_HOST


    Имя БД, которое необходимо прописать в параметре DB_NAME, можно взять на второй вкладке формы «Список баз данных».



    Получение имени БД — для параметра DB_NAME


    Логин пользователя, который необходимо прописать в параметре DB_USER, указывался нами на этапе создания БД: мы оставили значение по умолчанию user.


    Пароль пользователя БД также был сгенерирован на этапе создания БД, и мы его скопировали в файл db-password. В deployment.yaml пароль БД будет браться из секрета, который нам необходимо создать. Секреты в Kubernetes предназначены для хранения конфиденциальной информации.


    Создадим новый namespace mcs-kubernetes-project:


    kubectl create ns mcs-kubernetes-project

    И в рамках него добавим секрет с ключом db-password и типом generic на основе созданного ранее файла следующей командой:


    kubectl create secret generic mcs-kubernetes-project \
      -n mcs-kubernetes-project \
      --from-file db-password

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


    kubectl create secret generic mcs-kubernetes-project \
      -n mcs-kubernetes-project \
      --from-literal db-password=<сохраненный ранее пароль от БД>

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


    kubectl get secrets -n mcs-kubernetes-project

    Секрет был успешно добавлен.



    Service


    Это абстракция, необходимая для организации сетевого доступа и балансировки внутри кластера Kubernetes. При этом Service не является Proxy в чистом виде: никакого контейнера, виртуальной машины или иного объекта не создается. Это «виртуальный» балансировщик на основе iptables либо виртуальных IP-адресов Linux. Он конфигурирует кластер Kubernetes таким образом, чтобы могла осуществляться балансировка, и предоставляет следующее:


    • имя, по которому можно обращаться к сервису внутри кластера;
    • IP-адрес, в который будет преобразовываться имя с помощью внутреннего DNS Kubernetes;
    • номер порта.

    Предположим, внутри кластера есть сервис A, которому нужно обратиться к сервису B с несколькими инстансами. Число инстансов и их расположение не имеют значения: достаточно знать имя сервиса B и выполнить запрос по этому имени. Благодаря Service трафик будет автоматически распределен между инстансами.



    Service


    Манифест service.yaml находится в той же папке, что и deployment.yaml — .kube. Содержимое файла ниже.


    apiVersion: v1
    kind: Service
    metadata:
      name: mcs-kubernetes-project
    spec:
      selector:
        app: mcs-kubernetes-project
      ports:
        - name: http
          targetPort: http
          port: 80

    Здесь мы задаем имя сервису mcs-kubernetes-project, по которому можно будет обращаться к подам внутри кластера с нашим API-сервисом. Для сервиса будет открываться 80 порт, который ведет на порт внутри пода с названием http.


    Ingress


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



    Ingress


    Содержимое Ingress.yaml из папки .kube приведено ниже.


    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: mcs-kubernetes-project
    spec:
      rules:
      - http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: mcs-kubernetes-project
                port:
                  name: http

    Объекту Ingress мы присваиваем имя mcs-kubernetes-project. Каких-либо ограничений на хосты нет: все, что придет извне в кластер в корневой url или любой другой, будет направлено на Service с именем mcs-kubernetes-project.


    При этом Ingress Controller, который будет отвечать за обработку внешнего трафика, был создан автоматически при запуске кластера — в рамках namespace ingress-nginx. Чтобы убедиться в этом, можно выполнить команду:


    kubectl get po -n ingress-nginx


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


    RBAC и настройка доступов между GitLab и Kubernetes


    Чтобы GitLab Runner мог деплоить приложение в кластер Kubernetes, необходимо дать ему соответствующие права внутри конкретного namespace. Для этого потребуется создать несколько RBAC-объектов:


    • создать сервисную учетную запись (УЗ) командой:
      kubectl create sa deploy -n mcs-kubernetes-project
    • предоставить ей права на создание объектов внутри namespace mcs-kubernetes-project:
      kubectl create rolebinding deploy \
        -n mcs-kubernetes-project \
        --clusterrole edit \
        --serviceaccount mcs-kubernetes-project:deploy

    Токен созданной УЗ необходимо прописать в GitLab-переменных. С помощью этого токена GitLab Runner сможет получать доступ к кластеру Kubernetes. Для получения токена воспользуйтесь командой:


    kubectl get secret -n mcs-kubernetes-project \
      $(kubectl get sa -n mcs-kubernetes-project deploy \
        -o jsonpath='{.secrets[].name}') \
      -o jsonpath='{.data.token}' 

    Скопируйте токен в буфер обмена и вернитесь в интерфейс GitLab. В пункте меню «Settings» — «CI/CD» нужно нажать на кнопку «Expand» в секции «Variables» и затем на кнопку «Add variable».



    Раскрытие раздела «Variables» в пункте меню «Settings» — «CI/CD»



    Переход к добавлению новой переменной в разделе «Variables»


    В открывшейся форме требуется указать имя переменной, которое будет впоследствии использоваться в секции deploy манифеста gitlab-ci.yml — K8S_CI_TOKEN. В качестве значения переменной нужно использовать скопированный ранее токен сервисной УЗ. Также следует снять флажок «Protect variable», который разрешает доступ к переменным исключительно из ветки master. И нужно установить флажок «Mask variable» — в таком случае переменная будет закрытой, то есть ее значение не будет отображаться внутри логов CI/CD.



    Добавление переменной K8S_CI_TOKEN


    Последнее, что необходимо сделать перед запуском деплоя, — добавить в Kubernetes возможность авторизации в GitLab, чтобы получать из Docker Registry формируемый образ и запускать на его основе приложение. Для этого нужно добавить Deploy token.


    В GitLab необходимо выбрать пункт меню «Repository» и нажать на кнопку «Expand» в секции «Deploy tokens».



    Переход к добавлению Deploy token


    В открывшейся форме необходимо ввести имя токена k8s-pull-token и установить флажок «read_registry», который будет означать доступ к образам только на чтение.



    Добавление Deploy token


    После нажатия на кнопку «Create deploy token» на экране появится информация с именем пользователя и паролем для нового токена.



    Вывод имени пользователя и пароля после добавления Deploy token в GitLab


    Сформированные имя пользователя и пароль нужно скопировать в следующую команду, после чего выполнить ее в консоли. Команда добавит секрет с типом docker-registry и именем mcs-kubernetes-project-image-pull. С помощью секрета Kubernetes сможет получать формируемые образы из GitLab.


    kubectl create secret docker-registry mcs-kubernetes-project-image-pull \
      --docker-server registry.gitlab.com \
      --docker-email 'admin@mycompany.com' \
      --docker-username '<первая строчка (имя пользователя) из окна создания токена в GitLab>' \
      --docker-password '<вторая строчка (пароль) из окна создания токена в GitLab>' \
      --namespace mcs-kubernetes-project

    6. Деплой проекта


    Перед деплоем выполним коммит последних изменений и отправим их в GitLab:


    git add .kube
    git commit -m "Add Kubernetes manifests"
    git push 

    После этого пайплайн повторно запустится в GitLab и на этот раз завершится успешно.



    Успешное завершение пайплайна в GitLab


    Рассмотрим подробнее стадию deploy в файле gitlab-ci.yml. За основу берется образ bitnami/kubectl:1.20, в котором есть предустановленный kubectl.


    В секции before_script происходит подключение GitLab Runner к кластеру Kubernetes при помощи токена сервисной УЗ, который мы прописывали в переменной K8S_CI_TOKEN.


    В секции script описана непосредственно установка приложения. При помощи sed идет замена плейсхолдера в файле deployment.yaml на образ приложения, собранный на стадии build. Далее при помощи команды apply к кластеру Kubernetes применяются все изменения из манифестов папки .kube. И после этого происходит развертывание полученного образа. Команда rollout status позволяет отслеживать его статус. Если за указанный в настройках тайм-аут (2 минуты, про которые мы говорили выше) деплой не будет завершен, будет выполнен автоматический откат к предыдущей версии при помощи команды rollout undo.

    deploy:
      stage: deploy
      image: bitnami/kubectl:1.20
      variables:
        K8S_NAMESPACE: mcs-kubernetes-project
      before_script:
        # Set kubernetes credentials
        - export KUBECONFIG=/tmp/kubeconfig
        - kubectl config set-cluster k8s --insecure-skip-tls-verify=true --server=https://kubernetes.default
        - kubectl config set-credentials ci --token="$(echo $K8S_CI_TOKEN | base64 -d)"
        - kubectl config set-context ci --cluster=k8s --user=ci --namespace $K8S_NAMESPACE
        - kubectl config use-context ci
      script:
        - sed -i -e "s,<IMAGE>,$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID,g" .kube/deployment.yaml
        - kubectl apply -f .kube
        - kubectl rollout status deployment/mcs-kubernetes-project ||
          (kubectl rollout undo deployment/mcs-kubernetes-project && exit 1)

    Чтобы убедиться, что развертывание произошло успешно, достаточно выполнить несколько простых команд в namespace mcs-kubernetes-project:


    • вывод подов, который покажет 2 реплики приложения:


      kubectl get po -n mcs-kubernetes-project


    • вывод Service:


      kubectl get svc -n mcs-kubernetes-project


    • вывод Ingress:


      kubectl get ing -n mcs-kubernetes-project



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


    kubectl get svc -n ingress-nginx

    В результатах команды будут показаны сервисы, автоматически созданные при добавлении Ingress Controller. Среди них сервис с типом LoadBalancer. IP-адрес, указанный для него в столбце «EXTERNAL-IP», и есть искомый адрес для доступа к кластеру, который можно прописать в DNS или использовать напрямую для обращения к нашему приложению.



    Для вывода только внешнего IP-адреса можно воспользоваться расширенным вариантом команды:


    kubectl get svc -n ingress-nginx nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[].ip}'

    Используя этот адрес, проверим работу нашего API-сервиса. Сначала добавим пользователя:


    curl -k https://<INGRESS IP>/users -X POST -H "Content-Type: application/json" --data '{"name":"test","location":"asdf","age":12}'

    В ответе получим сообщение об успешном добавлении.



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


    curl -k https://<INGRESS IP>/users

    В ответе увидим добавленного пользователя.



    Таким образом, приложение работает. Пользователи успешно добавляются и извлекаются из БД PostgreSQL.


    Выводы: чему мы научились за 60 минут


    Мы рассмотрели основные шаги для развертывания Cloud Native-приложения в Kubernetes-кластере. Выбрали архитектуру и последовательно добавили необходимые компоненты: кластер K8s, DBaaS PostgreSQL, репозиторий кода в GitLab. Настроили GitLab Runner, пайплайн CI/CD и все необходимые для деплоя приложения объекты Kubernetes: Deployment, Service и Ingress. Добавили ряд переменных и токенов, чтобы Kubernetes и GitLab могли общаться друг с другом, поработав немного с RBAC и секретами. В результате получили работоспособное отказоустойчивое приложение, сборка и развертывание которого осуществляются автоматически.


    Разумеется, за 60 минут мы не могли охватить все аспекты работы с Kubernetes. Но выяснили, что этого времени достаточно для запуска первого приложения в кластере K8s.


    Тут можно почитать, как устроен Kubernetes aaS на платформе Mail.ru Cloud Solutions: что у него под капотом и что в него еще входит, кроме собственно Kubernetes.

    Если захотите сами повторить то, что описано в этой статье, можете подключить Kubernetes as a Service здесь. Новые пользователи получают 3000 бонусов для тестирования, и этого более чем достаточно, чтобы попробовать всё, что описано в этой статье. В технической поддержке нужно будет дополнительно попросить поднять квоты: 4 инстанса, 5 CPU, 10 ГБ RAM, 5 дисков, два IP-адреса.

    Описанный сценарий не обязательно повторять в облаке: при развертывании On-premise шаги будут примерно те же, но дольше и сложнее. Managed-решения значительно сокращают время конфигурирования кластера, делая работу с ним по-настоящему быстрой и удобной, особенно для новых пользователей.


    Что почитать еще:


    1. Self-Hosted, или Kubernetes для богатых: почему самостоятельное развертывание кластера — не всегда способ сэкономить.
    2. Как работать с Big Data быстрее и эффективнее: Kubernetes для Data Science.
    3. Как запускать в облаке приложения, требовательные к latency? СУБД Arenadata DB на сверхбыстрых облачных дисках.
Теги: mail.ru cloud solutionskubernetesdevopsконтейнеризацияpaasмикросервисная архитектурамикросервисыоблака
Хабы: Блог компании Mail.ru Group Облачные вычисления DevOps Облачные сервисы Kubernetes
Всего голосов 28: ↑27 и ↓1 +26
Комментарии 10
Комментарии Комментарии 10

Похожие публикации

Лучшие публикации за сутки

Информация

Дата основания
Местоположение
Россия
Сайт
team.mail.ru
Численность
5 001–10 000 человек
Дата регистрации
Представитель
Павел Круглов

Блог на Хабре