From 3dbee0781a60042b5d8560776963afd6158c427f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=92=D0=B8?= =?UTF-8?q?=D0=B3=D0=B4=D0=BE=D1=80=D0=BE=D0=B2?= Date: Sat, 28 Jun 2025 21:32:25 +0300 Subject: [PATCH] add drone and k8s configs --- .drone.yml | 81 +++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 1 + k8s/deployment.yaml | 20 +++++++++++ k8s/ingress.yaml | 26 +++++++++++++++ k8s/service.yaml | 11 ++++++ 5 files changed, 139 insertions(+) create mode 100644 .drone.yml create mode 100644 k8s/deployment.yaml create mode 100644 k8s/ingress.yaml create mode 100644 k8s/service.yaml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..337510f --- /dev/null +++ b/.drone.yml @@ -0,0 +1,81 @@ +kind: pipeline +type: kubernetes +name: deploy-frontend + +# Триггеры: запускать на push в ветки main и develop +trigger: + branch: + - master + - develop + event: + - push + +steps: +# --- Шаг 1: Сборка и отправка образа в Harbor --- +# Этот шаг выполняется для любой из веток (main или develop) +- name: build-and-push + image: plugins/docker + settings: + # Укажите ваш домен Harbor + registry: ci.vigdorov.ru + # Имя репозитория в Harbor (например, в проекте library) + repo: ci.vigdorov.ru/library/examples-for-kids-app + # Тег будет равен первым 7 символам хеша коммита (например, a1b2c3d) + tags: + - ${DRONE_COMMIT_SHA:0:7} + # Используем секреты, которые мы создали в Drone + username: + from_secret: HARBOR_USER + password: + from_secret: HARBOR_PASSWORD + +# --- Шаг 2: Развертывание в DEV-окружение --- +- name: deploy-dev + image: alpine/k8s:1.28.2 # Образ с kubectl и другими утилитами + # Запускать этот шаг ТОЛЬКО для ветки 'develop' + trigger: + branch: + - develop + environment: + # Используем секрет с kubeconfig + KUBECONFIG: + from_secret: KUBE_CONFIG + commands: + # Готовим переменные для dev-окружения + - export APP_NAMESPACE="dev-ns" # Будем деплоить в отдельный неймспейс + - export HOSTNAME="dev.examples-for-kids.vigdorov.ru" + - export IMAGE_TAG="${DRONE_COMMIT_SHA:0:7}" + - export IMAGE_NAME="ci.vigdorov.ru/library/examples-for-kids-app" + - export SECRET_NAME="dev-test-tls" + # Создаем неймспейс, если его нет + - kubectl create namespace $APP_NAMESPACE --dry-run=client -o yaml | kubectl apply -f - + # Заменяем метки в шаблонах на реальные значения и применяем + - sed -e "s|__IMAGE__|$IMAGE_NAME:$IMAGE_TAG|g" k8s/deployment.yaml | kubectl apply -n $APP_NAMESPACE -f - + - kubectl apply -n $APP_NAMESPACE -f k8s/service.yaml + - sed -e "s|__HOSTNAME__|$HOSTNAME|g" -e "s|__SECRET_NAME__|$SECRET_NAME|g" k8s/ingress.yaml | kubectl apply -n $APP_NAMESPACE -f - + - echo "Deployed to DEV: https://$HOSTNAME" + +# --- Шаг 3: Развертывание в PROD-окружение --- +- name: deploy-prod + image: alpine/k8s:1.28.2 + # Запускать этот шаг ТОЛЬКО для ветки 'main' + trigger: + branch: + - master + environment: + KUBECONFIG: + from_secret: KUBE_CONFIG + commands: + # Готовим переменные для prod-окружения + - export APP_NAMESPACE="prod-ns" + - export HOSTNAME="examples-for-kids.vigdorov.ru" + - export IMAGE_TAG="${DRONE_COMMIT_SHA:0:7}" + - export IMAGE_NAME="ci.vigdorov.ru/library/examples-for-kids-app" + - export SECRET_NAME="prod-test-tls" + # Создаем неймспейс + - kubectl create namespace $APP_NAMESPACE --dry-run=client -o yaml | kubectl apply -f - + # Разворачиваем приложение + - sed -e "s|__IMAGE__|$IMAGE_NAME:$IMAGE_TAG|g" k8s/deployment.yaml | kubectl apply -n $APP_NAMESPACE -f - + - kubectl apply -n $APP_NAMESPACE -f k8s/service.yaml + - sed -e "s|__HOSTNAME__|$HOSTNAME|g" -e "s|__SECRET_NAME__|$SECRET_NAME|g" k8s/ingress.yaml | kubectl apply -n $APP_NAMESPACE -f - + - echo "Deployed to PROD: https://$HOSTNAME" \ No newline at end of file diff --git a/.gitignore b/.gitignore index f075f3d..6f30d39 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ .dependencies-cache /reports .DS_Store +.cursor diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..e8bd5c7 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: examples-for-kids-app +spec: + replicas: 1 + selector: + matchLabels: + app: examples-for-kids-app + template: + metadata: + labels: + app: examples-for-kids-app + spec: + containers: + - name: examples-for-kids-app + # __IMAGE__ - это метка, которую заменит Drone + image: __IMAGE__ + ports: + - containerPort: 80 \ No newline at end of file diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 0000000..3790015 --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: examples-for-kids-ingress + annotations: + # Запрашиваем сертификат + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + ingressClassName: traefik + tls: + - hosts: + # __HOSTNAME__ - метка для домена + - __HOSTNAME__ + # __SECRET_NAME__ - метка для имени секрета с сертификатом + secretName: __SECRET_NAME__ + rules: + - host: __HOSTNAME__ + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: examples-for-kids-app-service + port: + number: 80 \ No newline at end of file diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..11803b0 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: examples-for-kids-app-service +spec: + selector: + app: examples-for-kids-app + ports: + - protocol: TCP + port: 80 + targetPort: 80 \ No newline at end of file