Проект состоит из двух репозиториев https://gitlab.com/perhamm/graduation_work и https://gitlab.com/perhamm/graduation_work_iac/
Само приложение запускается тут https://test3.club/
В первом репозитории располагается приложение и в нем содержаться следующие файлы и папки:
- Папки yelb-appserver, yelb-db и yelb-ui - папки с изначальным приложением, форкнутые из репо задания. В код приложения внесены изменения. В бэкенд (yelb-appserver) добавлены переменные для переопределения названий хостов баз данных. В фронт (yelb-ui) внесены многочисленные правки, связанные с версиями node и библиотек, из-за сильно устаревших зависимостей (они буквально deprecated, например https://github.com/vmware-archive/clarity-seed обновлен последний раз 5 лет назад и помечен как архивный - как фронт вообще завелся, я, если честно, не очень понимаю - при сборке количество ошибок просто огромно, портянка из ERROR на несколько листов)
- docker-compose.yml - создан для тестирования корректности запуска приложений после сборки
- Папка test - содержит тест для docker-compose.yml (просто дергает страничку приложения и читает код ответа)
- Папка deployments - не несет никакой роли, форкнута из изначального приложения
- .helm-minikube - позволяет запустить приложение в миникубе
- .helm_redis_and_cloudsql_ha - helm чарт для запуска HA редиса и HA cloudsql - попробовал что работает, но уходит слишком много денег (нужны дополнительные ресурсы для самого кубера - нод 3 штуки + в идеале 3 мастера + 2 ингресса, подов для редиса и sentinel - 3, подов под haproxy - 3, подов под прокси SQL - 3, дополнительная плата за HA Cloud SQL )
- .helm - позволяет запустить приложение с 1 подом редиса с pvc, 1 cloud sql прокси и по паре бэкенд - фронтенд. При смерти редиса или sql прокси - они пересоздаются кубером автоматом, в течении 30 сек. SQL прокси (Cloud SQL Auth proxy) - рекомендованный Google способ взаимодействия с облачной базой данных. Именно его pod поднимается в кубере, и к нему идет обращение от приложения. А он уже идет по шифрованному каналу в Cloud SQL.
Во втором репозитории располагается iac + всё описание проекта и в нем содержаться следующие файлы и папки:
- backend - модуль терраформа для настройки сети
- gke - модуль терраформа для настройки кластера
- vds - модуль терраформа для настройки виртуальной машины под gitlab раннер
- cloudsql - модуль терраформа для настройки cloud sql
В gke - для оптимизации затрат используется только одна нода kubernetes (за каждую дополнительную ноду начисляется значительное количество денег в час + цена самой виртуалки под ноду) - но, если есть необходимость, можно просто увеличить количество нод
cloudsql - запускается без HA (за HA идет доплата) - но, если есть необходимость, включить HA можно, если убрать комментарии со строчек про реплику
vds - просто виртуалка под раннер, раннер ставится и регистрируется автоматически через provision
Итого получается следующая схема работы приложения:
Перед запуском нужно установить раннер в облаке, следовательно, первый запуск необходимо провести с локального компьютера.
Предполагается что gcloud, терраформ и kubectl установлен на локальном компьютере.
Просто заметка для себя - удалить все старые auth для чистого использования консольной gcloud можно так:
gcloud auth revoke --all
В консоли облака - создать новый проект - s015937
У него будет уникальный id - например, s015937-335713
Зайти в iam-admin/serviceaccounts - сделать новый сервис аккаунт, назвать его terrafrom, дать роль owner и создать для него ключ JSON.
Этот ключ кинуть в корень скаченного репо graduation_work_iac под именем terraform.json
Далее включить нужные нам апи:
gcloud config set project s015937-335713
gcloud auth activate-service-account --key-file=terraform.json
gcloud services enable compute.googleapis.com container.googleapis.com sql-component.googleapis.com sqladmin.googleapis.com servicenetworking.googleapis.com cloudresourcemanager.googleapis.com dns.googleapis.com
gcloud config set compute/zone europe-west3-a
gcloud config set compute/region europe-west3
Создать баскет в Cloud Storage с именем s015937-terraform-state
Первое применение терраформа - с локального компа.
Взять токен из раздела настроек раннеров, отключить шаренные раннеры, придумать сложный пароль для постгреса.
terraform init
terraform plan -var="gitlab_runner_registration_token=token" -var="project_id=s015937-335713" -var="sql_pass=password"
terraform apply -var="gitlab_runner_registration_token=token" -var="project_id=s015937-335713" -var="sql_pass=password"
Для доступа по ssh к гитлаб-раннеру, если он нужен по каким-либо причинам, проще всего провалиться в него через
gcloud compute ssh gitlab-runner
Вносим cat terraform.json | base64 -w0
в переменную SERVICEACCOUNT проекта graduation_work_iac в разделе CI/CD настроек.
Туда же вносим PROJECTID, например, s015937-335713, RUNNER_TOKEN и пароль юзера postgres SQL_PASS.
На этом этапе, если появился раннер в настройках - пайплайны должны заработать.
Включаем наш раннер в проекте graduation_work ( enable for this project)
Делаем экспорт kubectl config
gcloud container clusters get-credentials gke-prod-cluster
Узнаем точку входа
kubectl cluster-info
Добавляем её в K8S_API_URL в проекте graduation_work
Ставим в класетр ingress
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
kubectl create ns nginx
helm install nginx ingress-nginx/ingress-nginx --namespace nginx --set rbac.create=true --set controller.publishService.enabled=true
Ставим cert-manager
kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.12/deploy/manifests/00-crds.yaml
kubectl create namespace cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager \
--namespace cert-manager \
--version v0.12.0 \
--set ingressShim.defaultIssuerName=letsencrypt \
--set ingressShim.defaultIssuerKind=ClusterIssuer \
jetstack/cert-manager
После создания ингресс контроллера смотрим ip LoadBalancer - и заносим ip в А запись в днс своего домена.
kubectl get service -A
nginx nginx-ingress-nginx-controller LoadBalancer 10.103.250.72 34.159.44.133
Создаем аккаунт для входа
kubectl create namespace prod
kubectl create serviceaccount --namespace prod ci
cat << EOF | kubectl create --namespace prod -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prod-ci
rules:
- apiGroups: ["", "extensions", "apps", "batch", "events", "certmanager.k8s.io", "cert-manager.io", "monitoring.coreos.com", "networking.k8s.io"]
resources: ["*"]
verbs: ["*"]
EOF
kubectl create clusterrolebinding --namespace prod --serviceaccount prod:ci --clusterrole prod-ci prod-ci-binding
kubectl get secret --namespace prod $( kubectl get serviceaccount --namespace prod ci -o jsonpath='{.secrets[].name}' ) -o jsonpath='{.data.token}' | base64 -d
Добавляем токен в K8S_CI_TOKEN в проекте graduation_work
Проверить токен можно так
kubectl get clusterissuers --as=system:serviceaccount:prod:ci -n prod
Settings > Repository в репо приложения находим Deploy tokens и нажимаем Expand.
В поле Name вводим k8s-pull-token и ставим галочку рядом с read_registry.
Все остальные поля оставляем пустыми.
Нажимаем Create deploy token.
НЕ ЗАКРЫВАЕМ ОКНО БРАУЗЕРА!
Создаем image pull secret - для того, чтобы наш кластер Kubernetes мог получать образы из registry gitlab'а.
kubectl create secret docker-registry gitlab-registry --docker-server registry.gitlab.com --docker-email '[email protected]' --docker-username '<первая строчка из окна создания токена в gitlab>' --docker-password '<вторая строчка из окна создания токена в gitlab>' --namespace prod
Создаем секрет для бд а также секрет с ключом от сервисного ака терраформа для sql proxy
kubectl create secret generic db \
--from-literal=username=postgres \
--from-literal=password=<YOUR-DATABASE-PASSWORD> \
--from-literal=connectionname=<YOUR-INSTANCE_CONNECTION_NAME> \
-n prod
#cd ../graduation_work_iac/
kubectl create secret generic cloudsql-instance-credentials \
--from-file=terraform.json=terraform.json \
-n prod
Также необходимо создать БД для приложения - например, с VM раннера, предварительно поставив psql
gcloud compute ssh gitlab-runner
sudo -i
apt install postgresql-client-common postgresql-client -y
psql -v ON_ERROR_STOP=1 -h <HOST> --username postgres -W <<-EOSQL
CREATE DATABASE yelbdatabase;
\connect yelbdatabase;
CREATE TABLE restaurants (
name char(30),
count integer,
PRIMARY KEY (name)
);
INSERT INTO restaurants (name, count) VALUES ('outback', 0);
INSERT INTO restaurants (name, count) VALUES ('bucadibeppo', 0);
INSERT INTO restaurants (name, count) VALUES ('chipotle', 0);
INSERT INTO restaurants (name, count) VALUES ('ihop', 0);
EOSQL
Итого, должны быть следующие переменные:
graduation_work: K8S_API_URL K8S_CI_TOKEN
graduation_work_iac: PROJECTID RUNNER_TOKEN SERVICEACCOUNT SQL_PASS
Проверяем, сделав пробный запуск (ну или можно сразу запустить пайплайн проекта с приложением)
helm upgrade --install graduationapp .helm -f .helm/values.yaml --namespace prod
Если нужна диагностика - можно запустить под внутри кластера
kubectl run -t -i --rm --image centosadmin/utils test bash -n prod
apk --update add redis
apk --update add postgresql-client
psql -h yelb-db --username postgres -W
Все удалить - terraform destroy и удалить раннер из списка раннеров. Иногда залипает удаление SQL на каком-то модуле - удаляем из консоли, например, вот так
terraform state list
terraform state rm module.cloudsql.google_sql_user.user
terraform destroy
Чтобы совсем окончательно все удалить - удалить баскет, и затем - отключить проект.
Для мониторинга очень удобно использовать встроенные средства GCP
Пара скриншотов с логами и метриками
Вот тут метрики подов - видны CPU Usage
А тут очень удобно смотреть логи контейнеров