Пишем CD Pipeline с интеграцией Docker, Kubernetes и Jenkins в Google Cloud (GCE/GKE)

от автора

Автор статьи: Рустем Галиев

Senior DevOps Engineer & Integration Architect at IBM

Привет Хабр! На связи Рустем.

Недавно я был на одном интересном воркшопе от компании iTechArt и хотел бы сегодня поделится тем, что мы там делали, а точнее писали CD Pipeline с интеграцией Docker, Kubernetes и Jenkins в Google Cloud (GCE/GKE).

В этой статье мы узнаем, как развернуть динамическое веб-приложение на GKE (Google Kubernetes Engine) с использованием Jenkins.
Тема достаточно интересная, так что давайте начнем.

Наши реквизиты: Jenkins, Kubernetes(GKE), репозиторий Github и реестр образов Dockerhub.

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

  • GCP: Google Cloud Platform — поставщик общедоступного облака, который предлагает своим пользователям вычислительные услуги через Интернет.

  • Docker: Docker — это программа с открытым исходным кодом, которая позволяет нам создавать, развертывать и управлять виртуализированными приложениями. Это позволяет нам отделить наше приложение от нашей инфраструктуры, поскольку мы можем создавать и запускать наше приложение в контейнерной среде.

  • Jenkins: это сервер автоматизации с открытым исходным кодом, который позволяет разработчикам надежно создавать, тестировать и развертывать свое программное обеспечение. Он организует цепочку действий (сборка, тестирование, развертывание) для достижения процесса непрерывной интеграции и непрерывной доставки автоматизированным способом.

  • Kubernetes: Kubernetes или K8s — это портативная, расширяемая платформа или программное обеспечение с открытым исходным кодом, которое обеспечивает возможности настройки, автоматизации и управления контейнерами, т.е. Решает вопросы оркестрации

    Давайте начнем с подготовки инфраструктуры.

Шаг 1: Создадим и настроим машины

1. Создайте машину разработчика:

Откройте консоль Google Cloud Platform > Compute Engine > Create New Instance

2. Создадим новый экземпляр для сервера Jenkins и Docker Engine:

Установим Docker:

sudo apt-get update sudo apt install docker.io

Установим Jenkins:

1) Сперва установим JDK:

sudo apt-get update sudo apt install openjdk-11-jre-headless

2) Добавим ключ

wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -

 3) Apt repo

sudo sh -c 'echo deb https://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'

4) Обновим пакеты и установим Jenkins

sudo apt-get update sudo apt-get install jenkins

Также не забудьте дать Jenkins’у привелегии администратора

Откроем файл /etc/sudoers и добавим следующую строчку:

jenkins ALL=(ALL) NOPASSWD: ALL

3. Создадим кластер Kubernetes в GKE

Open GCP console > GKE (Kubernetes engine) > Create

Шаг 2. Настроим Jenkins

1. Откройте дэшборд Jenkins через public IP вашего инстанса по порту 8080

http://<server_publicIP>:8080

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

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Теперь выберем Install suggested plugins

После установки Jenkins попросит создать аккаунт для администратора, что мы и сделаем

2. Установим следующие плагины: Git, github, Docker pipeline, Google Kubernetes Engine

Jenkins Dashboard -> Plugin Manager -> Available -> Search bar

3. Добавим реквизиты для аутентификации в GKE и Dockerhub

Загрузите ключ сервисного аккаунта Google:

Open GCP console > IAM and Admin > service account > open default one or create new one > add key > create new key (json format) and save it

Загрузим ключ в Jenkins

Jenkins Dashboard > manage Jenkins > manage credentials > Jenkins > global credentials > add credentials

Для Docker тоже добавим (где Secret — это пароль нашего аккаунта)

3. Создадим Pipeline в Jenkins:

Dashboard -> New item

Дадим любое имя, выбираем pipeline

Definition = Pipeline script from SCM

SCM = git

Repository Url: url вашего репозитория
Script Path: Jenkinsfile

Шаг 3. Настроим наш проект для сборки

Для примера давайте соберем это приложение и форкнем или склоним его: https://github.com/komarserjio/notejam

1. Напишем Dockerfile:

FROM python:2.7 RUN mkdir app COPY django/notejam app/ COPY django/requirements.txt ./ RUN pip install -r requirements.txt RUN pip install psycopg2 WORKDIR app/ EXPOSE 5000

2. Напишем deployment.yaml для Kubernetes
В моем случае он содержит манифест развертывания веб-приложения и его манифест его службы, а также манифест для persistent volume claim, secret, configMap, database deployment и service.

#data-db-persistentvolumeclaim.yam apiVersion: v1 kind: PersistentVolumeClaim metadata:   labels: service: data-db   name: data-db spec:   accessModes: - ReadWriteOnce   resources: requests:   storage: 2Gi    --- #db-configmap.yaml apiVersion: v1 kind: ConfigMap metadata:   labels: service: db   name: db-config data:   db-name: "nj"  #db-secret apiVersion: v1 kind: Secret metadata:   name: notejam-credentials type: Opaque data:   user: YWRtaW4=   password: YWRtaW5AMTIz  #db-deployment apiVersion: apps/v1 kind: Deployment metadata:   labels: service: db   name: db spec:   replicas: 1   selector: matchLabels:   service: db   template: metadata:   labels:     service: db     tier: backend spec:   containers:     - image: postgres       name: database       env:         - name: POSTGRES_USER           valueFrom:             secretKeyRef:               name: notejam-credentials               key: user         - name: POSTGRES_PASSWORD           valueFrom:             secretKeyRef:               name: notejam-credentials               key: password         - name: POSTGRES_DB           valueFrom:             configMapKeyRef:               name: db-config               key: db-name       ports:         - containerPort: 5432       resources:         requests:           cpu: 100m           memory: 128Mi         limits:           cpu: 250m           memory: 256Mi       volumeMounts:         - mountPath: /var/lib/mysql/data           name: data-db   restartPolicy: Always   volumes:     - name: data-db       persistentVolumeClaim:         claimName: data-db  #db-service.yaml apiVersion: v1 kind: Service metadata:   labels: service: db   name: db spec:   ports: - name: "5432"   protocol: TCP   port: 5432   targetPort: 5432   selector: service: db  apiVersion: apps/v1 kind: Deployment metadata:   labels: service: web   name: web spec:   replicas: 1   selector: matchLabels:   service: web   template: metadata:   labels:     service: web spec:   containers:     - args:         - bash         - -c         - python manage.py syncdb --noinput && python manage.py migrate && python manage.py runserver 0.0.0.0:5000       image: arshad1914/pipeline:latest       name: notejam       ports:         - containerPort: 5000       resources:         requests:           cpu: 100m           memory: 128Mi         limits:           cpu: 250m           memory: 250Mi   restartPolicy: Always  apiVersion: v1 kind: Service metadata:   labels: service: web   name: web spec:   type: LoadBalancer   ports: - name: "5000"   port: 5000   targetPort: 5000   selector: service: web

3. Создадим Jenkinsfile, где опишем процесс сборки и доставки

pipeline { agent any     environment {     PROJECT_ID = 'docker'             CLUSTER_NAME = 'jenkins'             LOCATION = 'us-central-1a'             CREDENTIALS_ID = 'kubernetes'     }      stages {     stage('Checkout') {     steps {     checkout scm     }     }     stage('Build image') {     steps {     script {     app = docker.build("zetzo/pipeline:{env.BUILD_ID}")      }           }     }         stage('Deploy to K8s') {     steps{     echo "Deployment started ..."     sh 'ls -ltr'     sh 'pwd'     sh "sed -i 's/pipeline:latest/pipeline:class: 'KubernetesEngineBuilder',        projectId: env.PROJECT_ID,        clusterName: env.CLUSTER_NAME,        location: env.LOCATION,        manifestPattern: 'deployment.yaml',        credentialsId: env.CREDENTIALS_ID,        verifyDeployments: true])     }     }     }     }

Шаг 4. Протестируем наш пайплайн (спойлер: успешно)

Задеплоили, Вы восхитительны!

P.s.

Если хотите чтобы деплой был полностью автоматизированным (т.е. Перейти от Continuous Delivery к Continuous Deployment), то рекомендую настроить вебхук в вашем репозитории

settings > webhooks > add webhooks > url Вашего Jenkins instance

В Вашем Jenkins pipeline, заходим в конфигурацию и ставим галочку в поле здесь

На этом все. Также хочу порекомендовать всем бесплатный урок от OTUS на котором вы сможете изучить предпосылки к возникновению контейнеризации и познакомиться с устройством самого популярного «контейнеризатора» — docker.


ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/699300/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *