Deploy to k8s with Spinnaker. Часть 1: Установка

Jan 24, 2019 15:31 · 1120 words · 6 minute read spinnaker ci cd kubernetes

Spinnaker - мультиоблачная платформа для непрерывной доставки (continuous delivery) с открытым исходным кодом (open-source) от разработчиков Netflix. Платформа предназначена для управления и деплоя приложений в AWS EC2, Kubernetes, GCE, GKE, GAE, Microsoft Azure и Openstack. Давайте разберемся!

Устанавливать Spinnaker будем в Kubernetes кластер с помощью утилиты Halyard (рекомендуемый способ установки). Для начала установим Halyard на локальный компьютер или VM (с Ubuntu 14.04/16.04, Debian, или macOS).

Примечание. Это также может быть docker-контейнер, но данный вариант установки рассматривать не будем.

В моем случае используется macOS (10.14.2 Mojave). Скачиваем последнюю версию установщика Halyard с помощью команды:

curl -O https://raw.githubusercontent.com/spinnaker/halyard/master/install/macos/InstallHalyard.sh

Устанавливаем утилиту:

sudo bash InstallHalyard.sh

Проверить корректность установки можно так:

hal -v
1.14.0-20190117020510

Примечание. Если команда завершается с ошибкой, убедитесь, что путь к испольняемому файлу hal присутствует в переменной $PATH.

Обновление Halyard можно вызвать командой:

sudo update-halyard

При необходимости удалить Halyard можно так:

sudo ~/.hal/uninstall.sh

Для установки Spinnaker далее следует определиться с облачным провайдером - все доступные варианты можно посмотреть тут, в моем случае будет использоваться вторая версия Kubernetes (Kubernetes Provider V2 (Manifest Based)). Сам Kubernetes кластер запущен на GKE (Google Kubernetes Engine).

Если у вас нет кластера на GKE, его необходимо создать с помощью консольной утилиты gcloud или Cloud Console как описано в официальной документации. Также для этих целей можно использовать сторонние инструменты, например Terraform.

Далее необходимо загрузить учетные данные для доступа к кластеру Kubernetes, например, как написано здесь.

Создаем отдельный сервис-аккаунт для Spinnaker и сгенерируем ему токен для доступа к кластеру Kubernetes:

CONTEXT=$(kubectl config current-context)

# This service account uses the ClusterAdmin role -- this is not necessary, 
# more restrictive roles can by applied.
kubectl apply --context ${CONTEXT} \
    -f https://spinnaker.io/downloads/kubernetes/service-account.yml

TOKEN=$(kubectl get secret --context ${CONTEXT} \
   $(kubectl get serviceaccount spinnaker-service-account \
       --context ${CONTEXT} \
       -n spinnaker \
       -o jsonpath='{.secrets[0].name}') \
   -n spinnaker \
   -o jsonpath='{.data.token}' | base64 --decode)

kubectl config set-credentials ${CONTEXT}-token-user --token ${TOKEN}

kubectl config set-context ${CONTEXT} --user ${CONTEXT}-token-user

По желанию также можно настроить RBAC (Role-Based Access Control) для сервис-аккаунта Spinnaker, например, создав файл spinnaker-role.yaml с таким содержимым:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: spinnaker-role
rules:
- apiGroups: [""]
  resources: ["namespaces", "configmaps", "events", "replicationcontrollers", "serviceaccounts", "pods/log"]
  verbs: ["get", "list"]
- apiGroups: [""]
  resources: ["pods", "services", "secrets"]
  verbs: ["create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"]
- apiGroups: ["autoscaling"]
  resources: ["horizontalpodautoscalers"]
  verbs: ["list", "get"]
- apiGroups: ["apps"]
  resources: ["controllerrevisions", "statefulsets"]
  verbs: ["list"]
- apiGroups: ["extensions", "apps"]
  resources: ["deployments", "replicasets", "ingresses"]
  verbs: ["create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"]
# These permissions are necessary for halyard to operate. We use this role also to deploy Spinnaker itself.
- apiGroups: [""]
  resources: ["services/proxy", "pods/portforward"]
  verbs: ["create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"]
---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
 name: spinnaker-role-binding
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: spinnaker-role
subjects:
- namespace: spinnaker
  kind: ServiceAccount
  name: spinnaker-service-account
---

apiVersion: v1
kind: ServiceAccount
metadata:
 name: spinnaker-service-account
 namespace: spinnaker

и применив его с помощью команды:

kubectl apply -f spinnaker-role.yaml

Теперь можем в настройках Spinnaker’а включить поддержку Kubernetes V2 провайдера и добавить аккаунт(ы):

hal config provider kubernetes enable
CONTEXT=$(kubectl config current-context)

hal config provider kubernetes account add k8s-account \
    --namespaces default \
    --provider-version v2 \
    --context ${CONTEXT}

Примечание. В терминологии Spinnaker аккаунт (account) соответствует контексту (context) Kubernetes кластера; имя аккаунта может отличаться от имени контекста.

В примере выше для взаимодействия с Kubernetes кластерами будет использоваться дефолтный kubeconfig - ~/.kube/config. Можно явно указать путь к kubeconfig с помощью параметра --kubeconfig-file.

Также нужно включить поддержку артефактов:

hal config features edit --artifacts true

Особенно нас интересует возможность использования артефактов с GitHub (в моем примере артефакт - это манифест для k8s в формате .yaml). Для доступа к репозиториям на GitHub Spinnaker’у понадобится токен, который можно сгенерировать здесь. Токену необходимы права доступа repo scope.

hal config artifact github enable
TOKEN=b82c0b5201e5........8d3f1288cb
echo ${TOKEN} | hal config artifact github account add spinnaker-github-token --token

Для хранения персистентных данных (настройки пайплайнов / приложений) Spinnaker’у требуется внешнее хранилище. Доступные варианты хранилищ можно посмотреть здесь, в моем же случае будет использоваться GCS (Google Cloud Storage).

Считаем, что у вас уже создан проект на GCP (Google Cloud Platform) и установлена утилита gcloud.

Для аутентификации Spinnaker’а на GCP создадим сервис-аккаунт с включенной ролью roles/storage.admin с помощью следующих команд:

SERVICE_ACCOUNT_NAME=spinnaker-gcs-account
SERVICE_ACCOUNT_DEST=~/.gcp/gcs-account.json

gcloud iam service-accounts create \
    ${SERVICE_ACCOUNT_NAME} \
    --display-name ${SERVICE_ACCOUNT_NAME}

SA_EMAIL=$(gcloud iam service-accounts list \
    --filter="displayName:${SERVICE_ACCOUNT_NAME}" \
    --format='value(email)')

PROJECT=$(gcloud info --format='value(config.project)')

gcloud projects add-iam-policy-binding ${PROJECT} \
    --role roles/storage.admin --member serviceAccount:${SA_EMAIL}

mkdir -p $(dirname ${SERVICE_ACCOUNT_DEST})

gcloud iam service-accounts keys create ${SERVICE_ACCOUNT_DEST} \
    --iam-account ${SA_EMAIL}

Настраиваем внешнее хранилище для Spinnaker:

BUCKET_LOCATION=europe-west1

hal config storage gcs edit \
    --project ${PROJECT} \
    --bucket-location ${BUCKET_LOCATION} \
    --bucket my-spinnaker-bucket \
    --json-path ${SERVICE_ACCOUNT_DEST}

Включим и настроим поддержку docker-registry (необязательный шаг). В моем случае будут использоваться приватные docker-репозитории организации (Docker Private Organization Repository), и мне необходимо настроить триггер, который бы запускал пайплайн при появлении нового docker-образа в репозитории:

hal config provider docker-registry enable
PASS=Very$tr0ngPaS$
echo ${PASS} | hal config provider docker-registry account add private-dockerhub \
    --provider-version v2 \
    --address index.docker.io \
    --repositories orgname/reponame-1 orgname/reponame-2 orgname/reponame-3 \
    --username admin \
    --password

Примечание. Так как Docker Hub не предоставляет ендпоинта catalog для автоматического получения списка docker репозиториев, их необходимо вручную указать с помощью параметра --repositories.

Больше опций для более тонкой настройки docker registry можно найти здесь.

Стоит отметить, что при большом количестве тэгов в репозиториях docker registry (>1000) можно столкнуться с проблемой - микросервис igor (подробнее о архитектуре Spinnaker можно узнать здесь) не будет видеть новые тэги и не сможет тригеррить пайплайны. В логах это будет выглядеть примерно так:

...
2019-01-22 12:59:55.923  INFO 1 --- [RxIoScheduler-3] c.n.s.i.d.service.ClouddriverService     : ---> HTTP GET http://spin-clouddriver.spinnaker:7002/dockerRegistry/images/find?account=private-dockerhub
2019-01-22 12:59:55.992  INFO 1 --- [RxIoScheduler-3] c.n.s.i.d.service.ClouddriverService     : <--- HTTP 200 http://spin-clouddriver.spinnaker:7002/dockerRegistry/images/find?account=private-dockerhub (68ms)
2019-01-22 12:59:56.034  INFO 1 --- [RxIoScheduler-3] c.n.spinnaker.igor.docker.DockerMonitor  : Found 5546 new images for private-dockerhub
2019-01-22 12:59:56.034 ERROR 1 --- [RxIoScheduler-3] c.n.spinnaker.igor.docker.DockerMonitor  : Number of items (5546) to cache exceeds upper threshold (1000) in monitor=DockerMonitor partition=private-dockerhub
...

Исправить ситуацию можно создав файл ~/.hal/default/profiles/igor-local.yml следующего содержания:

dockerRegistry:
  itemUpperThreshold: 10000

Двигаемся дальше. Указываем тип установки для Spinnaker (в моем примере это будет distributed) и ранее созданный Kubernetes-аккаунт (в какой кластер устанавливать):

hal config deploy edit --type distributed --account-name k8s-account

Далее следует выбрать версию Spinnaker для установки. Список доступных версий можно просмотреть командой:

hal version list

Указываем нужную версию:

hal config version edit --version 1.10.12

Деплой (или обновление настроек) Spinnaker’а выполняется командой:

hal deploy apply

Далее можно выполнить команду (по сути, port-forward):

hal deploy connect

После чего перейти по адресу localhost:9000 для дальнейшей настройки (создания приложений / пайплайнов) Spinnaker - для теста вполне сойдет. Но если вы планируете полноценно использовать Spinnaker для деплоя / управления приложениями, то необходимо настроить субдомены для Spinnaker API и UI серверов (считаем, что домен существует):

DOMAIN=example.org
hal config security ui edit \
    --override-base-url http://spinnaker.${DOMAIN}

hal config security api edit \
    --override-base-url http://spinnaker-api.${DOMAIN}

После чего обновить настройки Spinnaker:

hal deploy apply

Также весьма полезно будет настроить авторизацию/аутентификацию, пример с использованием OAuth2.0 можно увидеть здесь.

tweet Share