1. Обзор
Jenkins — одно из самых популярных решений для непрерывной интеграции. Оно используется для автоматизации важнейших нечеловеческих аспектов процесса разработки программного обеспечения. Развернув Jenkins в Kubenetes на Google Cloud и используя плагин GKE, мы можем быстро и автоматически масштабировать исполнители сборки по мере необходимости. В сочетании с Cloud Storage мы можем создавать и тестировать приложения с минимальными усилиями.
Что вы будете делать
- Развертывание Jenkins в кластере Kubernetes
- Разверните и настройте плагин Jenkins GKE, чтобы Jenkins мог создавать и уничтожать поды в качестве узлов-исполнителей.
- Создайте и протестируйте пример приложения Spring Boot.
- Создайте и опубликуйте контейнер в Google Container Registry.
- Разверните демонстрационное приложение в тестовой и производственной средах GKE.
Что вам понадобится
- Проект Google Cloud с настроенной системой оплаты. Если у вас его нет, вам придётся его создать .
2. Настройка
Данный практический урок можно полностью выполнить на платформе Google Cloud Platform без какой-либо локальной установки или настройки.
Облачная оболочка
В ходе этого практического занятия мы будем создавать и управлять различными облачными ресурсами и сервисами, используя командную строку через Cloud Shell .
Включить API
Вот API, которые нам нужно будет включить в нашем проекте:
- API Compute Engine — создание и запуск виртуальных машин.
- API Kubernetes Engine — позволяет создавать и управлять приложениями на основе контейнеров.
- Cloud Build API — платформа непрерывной интеграции и непрерывной доставки Google Cloud.
- API управления сервисами — позволяет производителям сервисов публиковать сервисы на платформе Google Cloud Platform.
- API Cloud Resource Manager — создает, считывает и обновляет метаданные для контейнеров ресурсов Google Cloud.
Включите необходимые API с помощью следующей команды gcloud:
gcloud services enable compute.googleapis.com \
container.googleapis.com \
cloudbuild.googleapis.com \
servicemanagement.googleapis.com \
cloudresourcemanager.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}
Создайте корзину GCS.
Нам понадобится хранилище GCS для загрузки наших тестовых работ. Давайте создадим хранилище, используя идентификатор нашего проекта в имени, чтобы обеспечить уникальность:
gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/
3. Создание кластеров Kubernetes
Создайте кластер
Далее мы создадим кластер GKE, который будет размещать нашу систему Jenkins, включая поды, которые будут запущены в качестве рабочих узлов. Дополнительная область действия, указанная флагом --scopes , позволит Jenkins получить доступ к Cloud Source Repositorys и Container Registry. В консоли Cloud выполните следующие действия:
gcloud container clusters create jenkins-cd \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --scopes "https://www.googleapis.com/auth/source.read_write,cloud-platform" \ --cluster-version latest
Давайте также развернем 2 кластера для размещения тестовых и производственных сборок нашего тестового приложения:
gcloud container clusters create staging \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --cluster-version latest
gcloud container clusters create prod \ --machine-type n1-standard-2 --num-nodes 2 \ --zone us-east1-d \ --cluster-version latest
Проверять
После создания кластеров мы можем убедиться в их работоспособности с помощью gcloud container clusters list
В столбце STATUS в выходных данных должно быть RUNNING :
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS jenkins-cd us-east1-d 1.15.9-gke.9 34.74.77.124 n1-standard-2 1.15.9-gke.9 2 RUNNING prod us-east1-d 1.15.9-gke.9 35.229.98.12 n1-standard-2 1.15.9-gke.9 2 RUNNING staging us-east1-d 1.15.9-gke.9 34.73.92.228 n1-standard-2 1.15.9-gke.9 2 RUNNING
4. Развертывание Jenkins с помощью Helm.
Установить Helm
Для установки Jenkins в нашем кластере мы будем использовать Helm, менеджер пакетов приложений для Kubernetes. Для начала загрузите проект, содержащий манифесты Kubernetes, которые мы будем использовать для развертывания Jenkins:
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
Перейдите в текущий рабочий каталог, указав в нем каталог проекта:
cd ~/continuous-deployment-on-kubernetes/
Создайте привязку роли кластера, чтобы предоставить себе права администратора кластера:
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
Подключитесь к кластеру Jenkins, получив его учетные данные:
gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
И загрузите исполняемый файл Helm в свою облачную консоль:
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz
Распакуйте файл и скопируйте входящий в него Helm-файл в текущую рабочую директорию:
tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \ cp linux-amd64/helm .
Tiller — это серверная часть Helm, работающая в кластере Kubernetes. Давайте создадим учетную запись службы с именем tiller :
kubectl create serviceaccount tiller \ --namespace kube-system
И привяжите его к роли кластера cluster-admin , чтобы он мог вносить изменения:
kubectl create clusterrolebinding tiller-admin-binding \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
Теперь мы можем инициализировать Helm и обновить репозиторий:
./helm init --service-account=tiller && \ ./helm repo update
Проверять
Убедитесь, что Helm работает корректно, выполнив команду ./helm version — она должна вернуть номера версий клиента и сервера:
Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Установите Jenkins
Теперь, когда Helm установлен в нашем кластере, мы готовы к установке Jenkins:
./helm install stable/jenkins -n cd \ -f jenkins/values.yaml \ --version 1.2.2 --wait
Проверять
Давайте проверим капсулы:
kubectl get pods
В результате выполнения должен отобразиться статус нашего пода Jenkins: RUNNING:
NAME READY STATUS RESTARTS AGE cd-jenkins-7c786475dd-vbhg4 1/1 Running 0 1m
Убедитесь, что служба Jenkins была создана корректно:
kubectl get svc
Результат должен выглядеть примерно так:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cd-jenkins ClusterIP 10.35.241.170 <none> 8080/TCP 2m27s cd-jenkins-agent ClusterIP 10.35.250.57 <none> 50000/TCP 2m27s kubernetes ClusterIP 10.35.240.1 <none> 443/TCP 75m
В установке Jenkins для создания агентов сборки будет использоваться плагин Kubernetes. Они будут автоматически запускаться главным сервером Jenkins по мере необходимости. После завершения работы они автоматически завершают свою деятельность, а их ресурсы добавляются обратно в пул ресурсов кластера.
Подключитесь к Jenkins
Jenkins запущен в нашем кластере, но для доступа к пользовательскому интерфейсу давайте настроим переадресацию портов из Cloud Shell:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/component=jenkins-master" -l "app.kubernetes.io/instance=cd" -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8080:8080 >> /dev/null &
В процессе установки был сгенерирован пароль администратора. Давайте его получим:
printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
В верхней части окна Cloud Shell нажмите на значок «Предварительный просмотр веб-страницы».
и выберите «Предварительный просмотр на порту 8080».

Мы должны увидеть экран входа в Jenkins, где сможем ввести имя пользователя admin и пароль, полученные на предыдущем шаге:

При нажатии кнопки «Войти» мы должны быть перенаправлены на главную страницу Jenkins.

5. Установите и настройте плагин GKE.
Плагин Google Kubernetes Engine позволяет нам публиковать развертывания, созданные в Jenkins, в наши кластеры Kubernetes, работающие в GKE. Для этого потребуется выполнить некоторую настройку прав доступа IAM для вашего проекта. Мы развернем эту конфигурацию с помощью Terraform.
Сначала загрузите проект плагина GKE:
git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin
Автоматизированная настройка разрешений IAM
Перейдите в текущий рабочий каталог, указав в нем каталог rbac проекта GKE, который мы клонировали ранее:
cd ~/google-kubernetes-engine-plugin/docs/rbac/
gcp-sa-setup.tf — это конфигурационный файл Terraform, который создаст пользовательскую роль GCP IAM с ограниченными правами доступа, а также учетную запись службы GCP для предоставления этой роли. Файл требует значений для переменных проекта, региона и имени учетной записи службы. Мы предоставляем эти значения, сначала объявив следующие переменные среды:
export TF_VAR_project=${GOOGLE_CLOUD_PROJECT}
export TF_VAR_region=us-east1-d
export TF_VAR_sa_name=kaniko-role
Инициализируйте Terraform, сгенерируйте план и примените его:
terraform init terraform plan -out /tmp/tf.plan terraform apply /tmp/tf.plan && rm /tmp/tf.plan
Для сохранения данных в наше облачное хранилище учетной записи службы потребуются права администратора хранилища:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com \
--role 'roles/storage.admin'
Для этапов развертывания нашего конвейера также потребуются разрешения на использование контейнеров:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \
serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'
Теперь мы можем использовать Helm для настройки разрешений кластера для плагина GKE с помощью развертывателя роботов GKE. Перейдите в рабочий каталог проекта GKE, в каталог Helm:
cd ~/google-kubernetes-engine-plugin/docs/helm/
И выполните установку, используя предоставленную Helm-диаграмму:
export TARGET_NAMESPACE=kube-system && \ envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -
6. Настройка Jenkins
Ключи учетных записей служб
Для корректной работы сервисной учетной записи нам потребуется сгенерировать файл закрытого ключа и добавить его в качестве секрета Kubernetes. Сначала сгенерируйте файл с помощью следующей команды gcloud:
gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Мы создадим секретный ключ в хранилище секретов Kubernetes с помощью этого файла:
kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json
Загрузите JSON-файл на свой локальный диск, выбрав пункт «Загрузить файл» в меню Cloud Shell с тремя точками:

Введите путь к файлу /tmp/kaniko-secret.json и нажмите «Скачать».
Вернувшись на страницу Jenkins, в левой боковой панели нажмите «Учетные данные», затем «Система».


В разделе «Система» на странице нажмите «Глобальные учетные данные», затем слева выберите «Добавить учетные данные»:


В раскрывающемся списке «Тип» выберите «Учетная запись службы Google из закрытого ключа ». Введите «kaniko-role» в качестве имени, затем загрузите созданный на предыдущих шагах JSON-ключ и нажмите «ОК».

Переменные окружающей среды
Перед созданием многоветвевого конвейера нам потребуется определить несколько переменных среды в Jenkins. Вот они:
- JENK_INT_IT_ZONE — зона кластера Kubernetes. В нашем случае
us-east1-d - JENK_INT_IT_PROJECT_ID — это идентификатор проекта GCP, в котором размещен данный экземпляр Jenkins.
- JENK_INT_IT_STAGING — это название нашего кластера для "промежуточного хранения", в демонстрационных целях используется
staging - JENK_INT_IT_PROD — это имя нашего кластера 'prod'. Для демонстрационных целей используется название '
prod - JENK_INT_IT_BUCKET — сегмент Google Cloud Storage, созданный на предыдущем шаге.
- JENK_INT_IT_CRED_ID — это учетные данные, созданные с использованием JSON на предыдущем шаге. Значение должно совпадать с именем, которое мы ему присвоили,
kaniko-role
Чтобы добавить их, перейдите в раздел «Управление Jenkins» :

Затем выполните настройку системы:

Там будет раздел «Глобальные свойства» , и когда мы установим флажок напротив «Переменные среды», появится кнопка « Добавить », нажав на которую, мы добавим указанные выше переменные в виде пар ключ-значение:

Чтобы применить изменения, нажмите кнопку « Сохранить» внизу страницы.
7. Настройка конвейера
В Jenkins нажмите «Создать элемент»:

Введите в качестве имени 'jenkins-integration-sample', выберите тип проекта 'Multibranch Pipeline' и нажмите OK:

Мы будем перенаправлены на страницу конфигурации конвейера. В разделе «Источники ветки» введите https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git в качестве репозитория проекта. В разделе «Конфигурация сборки » введите 'gke/Jenkinsfile' в качестве пути к скрипту.

Нажмите «Сохранить» , чтобы применить эти настройки. После сохранения Jenkins запустит сканирование репозитория и последующую сборку для каждой ветки. По мере выполнения сборки вы будете видеть, как создаются, запускаются и уничтожаются поды, на странице «Рабочие нагрузки Kubernetes».
После завершения сборки на странице «Рабочие нагрузки Kubernetes» вы увидите два элемента с именем jenkins-integration-samples-gke, каждый из которых соответствует либо производственному, либо тестовому кластеру. Статус будет отображаться как OK:

С помощью следующей команды gcloud мы увидим, что загрузили образ контейнера в реестр контейнеров Google, соответствующий нашему конвейеру:
gcloud container images list
Чтобы увидеть нагрузку в браузере, получите учетные данные для производственного кластера:
gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
Выполните следующую команду, чтобы настроить переадресацию портов с порта 8081 вашей оболочки на порт 8080 вашей рабочей нагрузки:
export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &
В верхней части окна Cloud Shell щелкните значок «Предварительный просмотр веб-страницы» и выберите «Предварительный просмотр на порту 8081».


8. Уборка
Мы рассмотрели, как развернуть Jenkins и пример многоветвевого конвейера в Kubernetes. Теперь пришло время очистить наш проект от всех созданных нами ресурсов.
Удалить проект
При желании вы можете удалить весь проект. В консоли GCP перейдите на страницу «Менеджер облачных ресурсов» :
В списке проектов выберите проект, над которым мы работали, и нажмите «Удалить» . Вам будет предложено ввести идентификатор проекта. Введите его и нажмите «Завершить».
В качестве альтернативы вы можете удалить весь проект непосредственно из Cloud Shell с помощью gcloud:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Если вы предпочитаете удалять отдельные компоненты, подлежащие оплате, по одному, перейдите к следующему разделу.
Кластер Kubernetes
Удалите весь кластер Kubernetes с помощью gcloud:
gcloud container clusters delete jenkins-cd --zone=us-east1-d
Ведра для хранения
Удалите все загруженные файлы и очистите наше хранилище с помощью gsutil:
gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket
Образы из реестра контейнеров Google
Мы удалим образы из Google Container Registry, используя дайджесты образов. Сначала получите дайджесты с помощью следующей команды:
gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"
Затем для каждого полученного дайджеста возвращалось:
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>
9. Поздравляем!
Ура! Вы это сделали! Вы научились развертывать Jenkins в GKE и отправлять задания в кластеры Kubernetes.
Что мы рассмотрели
- Мы развернули кластер Kubernetes и использовали Helm для установки Jenkins.
- Мы установили и настроили плагин GKE, чтобы Jenkins мог развертывать артефакты сборки в кластерах Kubernetes.
- Мы настроили Jenkins для создания многоветвевого конвейера, который распределяет задачи по кластерам GKE.