diff --git a/README.md b/README.md index 9619241..1136dc3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,12 @@ aasdhajkshd microservices repository + +> INFO +Информация на картинках, как IP адреса, порты или время, может отличаться от приводимой в тексте. + +--- + ## Содержание * [docker-2 Технология контейнеризации. Введение в Docker](#hw16) @@ -11,14 +17,870 @@ aasdhajkshd microservices repository * [monitoring-1 Введение в мониторинг. Системы мониторинга](#hw22) * [kubernetes-1 Введение в kubernetes](#hw27) * [kubernetes-3 Kubernetes. Networks, Storages](#hw30) +* [kubernetes-4 CI/CD в Kubernetes](#hw31) -## Введение в kubernetes +## CI/CD в Kubernetes -> INFO -Информация на картинках, как IP адреса или время, может отличаться от приводимой в тексте! Суть в это не меняется. +Список литературы и статей: + +- [Менеджер пакетов для Kubernetes](https://helm.sh/ru/) +- [Setup a Kubernetes Cluster](https://istio.io/v1.7/docs/examples/microservices-istio/setup-kubernetes-cluster/) +- [Helm 2 vs Helm 3](https://www.hippolab.ru/helm-2-vs-helm-3) +- [helm/helm](https://get.helm.sh/helm-v2.17.1-linux-amd64.tar.gz) +- [The Chart Template](https://helm.sh/docs/chart_template_guide/#the-chart-template-developer-s-guide) +- [Charts](https://helm.sh/docs/topics/charts/) +- [Метки и селекторы](https://kubernetes.io/ru/docs/concepts/overview/working-with-objects/labels/) +- [Аннотации](https://kubernetes.io/ru/docs/concepts/overview/working-with-objects/annotations/) +- [Ingress.yaml template is throwing nil pointer evaluating interface {}.enabled](https://stackoverflow.com/questions/67023533/ingress-yaml-template-is-throwing-nil-pointer-evaluating-interface-enabled) +- [Основы работы с Helm чартами и темплейтами — Часть 2](https://habr.com/ru/articles/548720/) +- [Удаление helm 2](https://stackoverflow.com/questions/47583821/how-to-delete-tiller-from-kubernetes-cluster/47583918) +- [K9s](https://github.com/derailed/k9s) +- [Docker container build driver](https://docs.docker.com/build/drivers/docker-container/) +- [docker buildx build](https://docs.docker.com/engine/reference/commandline/buildx_build/#load) +- [overview of Linux capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) +- [Установка GitLab Runner](https://cloud.yandex.com/en/docs/managed-kubernetes/operations/applications/gitlab-runner) +- [Running privileged containers for the runners](https://docs.gitlab.com/runner/install/kubernetes.html#running-privileged-containers-for-the-runners) +- [skopeo](https://github.com/containers/skopeo) +- [docker buildx imagetools create](https://docs.docker.com/engine/reference/commandline/buildx_imagetools_create/) +- [What kubernetes permissions does GitLab runner kubernetes executor need?](https://stackoverflow.com/questions/60834960/what-kubernetes-permissions-does-gitlab-runner-kubernetes-executor-need) +- [Use tags to control which jobs a runner can run](https://docs.gitlab.com/16.5/ee/ci/runners/configure_runners.html#use-tags-to-control-which-jobs-a-runner-can-run) +- [Непрерывное развертывание контейнеризованных приложений с помощью GitLab](https://cloud.yandex.ru/docs/managed-kubernetes/tutorials/gitlab-containers) +- [Установка GitLab Agent](https://cloud.yandex.ru/docs/managed-kubernetes/operations/applications/gitlab-agent) +- [Environments and deployments](https://docs.gitlab.com/16.5/ee/ci/environments/index.html) + +--- #### Выполненные работы +--- + +### Helm + +1. Установка + +Выполнена установка helm пакета +```bash +helm version +``` + +> Результат: + +```output +version.BuildInfo{Version:"v3.12.0", GitCommit:"c9f554d75773799f72ceef38c51210f1842a1dea", GitTreeState:"clean", GoVersion:"go1.20.4"} +``` + +```bash +yc managed-kubernetes cluster start kube-infra +yc managed-kubernetes cluster get-credentials --name=kube-infra --force --external +kubectl config get-contexts +kubectl config use-context yc-kube-infra +``` + +> WARNING +> Ниже нет необходимости выполнять установку tiller, так как **helm 3 is tiller less**. Tiller окончательно и безвозвратно удален. Helm 3 использует Kubernetes API напрямую. +> Но если версия 2-я, то можно и доустановить, ссылка выше в списке статей. Ниже из методички. + +```bash +kubectl apply -f - << EOF > tiller.yml +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tiller + namespace: kube-system + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tiller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: tiller + namespace: kube-system + +EOF + +helm init --service-account tiller + +kubectl get pods -n kube-system --selector app=helm + +``` + +> INFO +> Пространство имен (namespace) в Kubernetes должно существовать до того, как приступить что-то деплоить helm'ом. + +2. Charts + +```bash +mkdir -p kubernetes/Charts/{comment,post,reddit,ui}/templates + +cat << EOF > kubernetes/Charts/ui/Chart.yaml +name: ui +version: 1.0.0 +description: OTUS reddit application UI +maintainers: + - name: OTUS + email: name.surname@gmail.com +appVersion: 1.0 + +EOF + +``` + +3. Templates + +Подготовлена необходимая шаблонная структура Charts + +![Структура](img/Screenshot_20231024_232101.png) + +Файлы deployment.yaml, service.yaml фактически не различаются и клонировать становится их проще. Далее в CI/CD нужно удалить namespace из yaml файлов. Здесь используются как переменные для изучения. + +```bash +helm lint ui/ comment/ ui/ +``` + +> Результат: + +```output +==> Linting ui/ + +==> Linting comment/ + +==> Linting ui/ + +3 chart(s) linted, 0 chart(s) failed +``` + +4. Управление зависимостями + +При выполнении команды: + +```bash +helm dep update reddit --debug +``` + +> Результат: + +```output +Repository from local path: file://../ui +Repository from local path: file://../post +Repository from local path: file://../comment +Hang tight while we grab the latest from your chart repositories... +...Successfully got an update from the "ingress-nginx" chart repository +Update Complete. ⎈Happy Helming!⎈ +Saving 3 charts +Archiving ui from repo file://../ui +Archiving post from repo file://../post +Archiving comment from repo file://../comment +Deleting outdated charts +``` + +```bash +tree reddit; \ +cat reddit/requirements.lock +``` + +> Появится файл requirements.lock с фиксацией зависимостей: + +```output +reddit/ +├── charts +│   ├── comment-1.0.0.tgz +│   ├── post-1.0.0.tgz +│   └── ui-1.0.0.tgz +├── Chart.yaml +├── requirements.lock +├── requirements.yaml +└── values.yaml + +2 directories, 7 files + +dependencies: +- name: ui + repository: file://../ui + version: 1.0.0 +- name: post + repository: file://../post + version: 1.0.0 +- name: comment + repository: file://../comment + version: 1.0.0 +digest: sha256:c509eeb70b9d2c7cb6aa1ec88f12d6ce386a0abda19490e59ff71dd893e45553 +generated: "2023-10-25T11:41:23.171523839+03:00" +``` + +Поиск репозитория выполняется в [ArtifactHub](https://artifacthub.io/) + +```bash +helm search hub mongo +``` + +> https://artifacthub.io/packages/helm/bitnami/mongodb или +> https://artifacthub.io/packages/helm/microfunctions/mongodb + +В учебной документации предлагается установить https://kubernetes-charts.storage.googleapis.com верию 0.4.18. + +Если же поиск выполнять в `helm search repo`, то нужно добавить репозиторий [charts](https://charts.helm.sh/stable/) +Здесь предлагаются актуальные версии, но для приложения reddit подходит или необходима старая версия - 4.2.4. + +```bash +helm repo list +helm repo add stable https://charts.helm.sh/stable +helm repo update +helm search repo stable/mongodb +``` + +> Результат: + +```output +stable/mongodb 7.8.10 4.2.4 DEPRECATED NoSQL document-oriented database tha... +... +``` + +В конфигурационном файле указываем версию: + +```bash +cat << EOF >> reddit/requirements.yaml + + - name: mongodb + version: 7.8.10 + repository: https://charts.helm.sh/stable + +EOF + +helm dep update reddit --debug +``` + +> Резльтат `reddit/charts/mongodb-7.8.10.tgz`: + +```output +mongodb/Chart.yaml +mongodb/values.yaml +mongodb/templates/NOTES.txt +mongodb/templates/_helpers.tpl +mongodb/templates/configmap.yaml +mongodb/templates/deployment-standalone.yaml +mongodb/templates/ingress.yaml +... +mongodb/.helmignore +mongodb/OWNERS +mongodb/README.md +mongodb/files/docker-entrypoint-initdb.d/README.md +mongodb/values-production.yaml +mongodb/values.schema.json +``` + +В некоторых атрибутах нельзя использовать переменные, как например, а *app*... оставляем аьрибуты без использования переменных. + +```output +Error: INSTALLATION FAILED: YAML parse error on reddit/charts/comment/templates/deployment.yml: error converting YAML to JSON: yaml: line 22: mapping values are not allowed in this context +``` + +Чтобы включить 443 порт, к *ingress.yaml* можно добавить через переменные такие услования: + +```yaml +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + {{- end }} + secretName: {{ .Values.ingress.secretName }} + +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.ingress.secretName }} +... +type: kubernetes.io/tls +{{- end }} +``` + +А в файле переменных *values.yaml* описываем их так: + +```yaml +... +ingress: + enabled: true + secretName: ui-ingress-tls + hosts: + - host: reddit.infranet.dev + paths: + - path: / + backend: + service: + name: ui + tls: + - hosts: + - reddit.infranet.dev +... +``` + +Раскатка в облако Kubernetes: + +```bash +rm -fR reddit/charts/*; \ +helm uninstall reddit-test; \ +helm dep update reddit && \ +helm install reddit --namespace=dev --debug --name-template reddit-test +``` + +> Результат, если выполнилась успешно сборка: + +```yaml +client.go:134: [debug] creating 12 resource(s) +NAME: reddit-test +LAST DEPLOYED: Wed Oct 25 13:31:16 2023 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +TEST SUITE: None +USER-SUPPLIED VALUES: +{} + +COMPUTED VALUES: +... +# Source: post/charts/ui/templates/ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: reddit-test-ui + namespace: dev + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/rewrite-target: / + kubernetes.io/ingress.allow-http: "false" + app.kubernetes.io/instance: reddit-test + app.kubernetes.io/managemt-by: Helm +spec: + ingressClassName: nginx + rules: + - host: "reddit.infranet.dev" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ui + port: + number: 80 + tls: + - hosts: + - "reddit.infranet.dev" + secretName: ui-ingress-tls +``` + +Для добавления дополнительных имен (как обращение по FQDN или другим именам) можно использовать *repository:alias* или externalNames в шаблоне `reddit/templates/externalnames.yaml`: + +```yaml +{{- $values := .Values -}} +{{- $release := .Release -}} +{{- range $key, $value := .Values.service.names }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $value }} + labels: + app: reddit +spec: + type: "ExternalName" + externalName: {{ printf "%s-mongodb.dev.svc.cluster.local" $release.Name }} +{{- end}} +``` + +А в файле переменных: + +```yaml +--- +service: + names: + - post-db + - comment-db +comment: + service: + externalPort: 9292 +post: + service: + externalPort: 5000 +``` + +> Результат команды: `helm install reddit/ -n dev --atomic --replace --debug --name-template reddit-test --set auth.enabled=false`: + +```bash +kubectl get service -A --selector=app=reddit +``` + +> Результат: + +```output +default comment-db ExternalName mongo.dev.svc.cluster.local 104s +default post-db ExternalName mongo.dev.svc.cluster.local 104s +``` + +И видно, что добавлены переменные для указания называний узлов в файл *ui/templates/deployment.yaml*: + +```yaml +spec: +... + env: + - name: POST_SERVICE_HOST + value: {{ .Values.postHost | default (printf "%s-post" .Release.Name) }} + - name: POST_SERVICE_PORT + value: {{ .Values.postPort | default "5000" | quote }} + - name: COMMENT_SERVICE_HOST + value: {{ .Values.commentHost | default (printf "%s-comment" .Release.Name) }} + - name: COMMENT_SERVICE_PORT + value: {{ .Values.commentPort | default "9292" | quote }} + - name: ENV + valueFrom: + fieldRef: + fieldPath: metadata.namespace +``` + +По заданию без указания значений добавляются переменные в *ui/values.yaml*: + +```yaml +... +postHost: +postPort: +commentHost: +commentPort: +``` + +При тестировании выяснилось, что mongodb от bitnami требует аутентификацию. +Добавление этих параметров в *values.yml* для тестирования микросервисов обходит требование авторизоваться. + +```yaml +mongodb: + auth: + enabled: false + usePassword: false + +``` + +> Результат: + +![](img/Screenshot_20231025_192152.png) + +#### GitLab + Kubernetes + +1. Установка и внесение изменений в конфигурационные файлы + +```bash +helm repo add gitlab https://charts.gitlab.io +helm fetch gitlab/gitlab-omnibus --version 0.1.37 --untar +cd gitlab-omnibus +helm install --name-template gitlab . -f values.yaml +``` + +Данная версия устарела для текущей версии Kubernetes: +> Most likely the problem is not related to missing CRDs but to the kubernetes version. + +> WARNING: This chart is deprecated + +```output +Error: INSTALLATION FAILED: unable to build kubernetes objects from release manifest: [resource mapping not found for name: "nginx" namespace: "nginx-ingress" from "": no matches for kind "DaemonSet" in version "extensions/v1beta1" +ensure CRDs are installed first, resource mapping not found for name: "gitlab-gitlab-runner" namespace: "" from "": no matches for kind "Deployment" in version "extensions/v1beta1" +ensure CRDs are installed first, resource mapping not found for name: "gitlab-gitlab" namespace: "" from "": no matches for kind "Deployment" in version "extensions/v1beta1" +ensure CRDs are installed first, resource mapping not found for name: "gitlab-gitlab-postgresql" namespace: "" from "": no matches for kind "Deployment" in version "extensions/v1beta1" +ensure CRDs are installed first, resource mapping not found for name: "gitlab-gitlab-redis" namespace: "" from "": no matches for kind "Deployment" in version "extensions/v1beta1" +ensure CRDs are installed first, resource mapping not found for name: "kube-lego" namespace: "kube-lego" from "": no matches for kind "Deployment" in version "extensions/v1beta1" +ensure CRDs are installed first, resource mapping not found for name: "default-http-backend" namespace: "nginx-ingress" from "": no matches for kind "Deployment" in version "extensions/v1beta1" +ensure CRDs are installed first, resource mapping not found for name: "gitlab-gitlab" namespace: "" from "": no matches for kind "Ingress" in version "extensions/v1beta1" +ensure CRDs are installed first] + +# DEPRECATION NOTICE + +This chart is DEPRECATED. + +### Replacement + +We have built a set of fully cloud native charts in [gitlab/gitlab](https://gitlab.com/charts/gitlab). +``` + +[Установка Gitlab](https://docs.gitlab.com/charts/quickstart/) + +> Пробуем на актуальных версиях ПО... + +```bash +helm install gitlab gitlab/gitlab \ + --set global.hosts.domain=infranet.dev \ + --set certmanager-issuer.email=admin@infranet.dev + +``` +```output +NAME: gitlab +LAST DEPLOYED: Wed Oct 25 21:49:44 2023 +NAMESPACE: default +STATUS: deployed +REVISION: 1 +NOTES: +... + + - Ingress objects must be in group/version `networking.k8s.io/v1`. + +``` + +Получим внешний IP адрес: + +```bash + +kubectl get ingress -lrelease=gitlab +``` + +> Результат: + +```output +NAME CLASS HOSTS ADDRESS PORTS AGE +gitlab-kas gitlab-nginx kas.infranet.dev 158.160.124.2 80, 443 13m +gitlab-minio gitlab-nginx minio.infranet.dev 158.160.124.2 80, 443 13m +gitlab-registry gitlab-nginx registry.infranet.dev 158.160.124.2 80, 443 13m +gitlab-webservice-default gitlab-nginx gitlab.infranet.dev 158.160.124.2 80, 443 13m +``` + +Получить пароль для входа: + +```bash +kubectl get secret gitlab-gitlab-initial-root-password -ojsonpath='{.data.password}' | base64 --decode ; echo + +``` + +Удаление gitlab + +``` +helm uninstall gitlab +``` + +Сброс пароля root'а + +```bash +kubectl get pods -lrelease=gitlab +kubectl exec -it -- bash +/srv/gitlab/bin/rails runner "user = User.first; user.password='#{password}'; user.password_confirmation='#{password}'; user.save!" +``` + +Запущен проект `https://gitlab.infranet.dev/23f03013e37f` + +![Reddit Deploy](img/Screenshot_20231026_172236.png) + +Инициализация проекта в репозиторий Gitlab: + +> Отмечю, что предлагается использовать не master, а main как репозиторий по-умолчанию... + +```bash +cd Gitlab_ci/ui +git init +git remote add origin git@gitlab.infranet.dev:23f03013e37f/$(basename $(pwd)).git +git branch -M main +git add . +git commit -m "init" +git push -uf origin main + +``` + +Аналогичные действия выполнены для других папок: comment, post, reddit-deploy + +Настройка Gitlab Runner'а для запуска Docker-in-Docker (dind). + +Загрузка Chart'а gitlab-runner с сайта: + +```bash +export HELM_EXPERIMENTAL_OCI=1 && \ +helm pull oci://cr.yandex/yc-marketplace/yandex-cloud/gitlab-org/gitlab-runner/chart/gitlab-runner \ + --version 0.54.0-8 \ + --untar && \ +``` + +В файле *values.yaml* в папке gitlab-runner нужно rbac.create либо false или добавить правила rbac.rules, см. [stackoverflow](https://stackoverflow.com/questions/60834960/what-kubernetes-permissions-does-gitlab-runner-kubernetes-executor-need) и runners.privileged установить значение true + +```yaml +... +rbac: + clusterWideAccess: false + create: true + podSecurityPolicy: + enabled: false + resourceNames: + - gitlab-runner + rules: + - apiGroups: [""] + resources: ["pods", "secrets", "configmaps"] + verbs: ["get", "list", "watch", "create", "patch", "delete", "update"] + - apiGroups: [""] + resources: ["pods/exec", "pods/attach"] + verbs: ["create", "patch", "delete"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] +resources: {} +runnerRegistrationToken: "glrt-rCoCNbEHSJPux9PXGemx" +runners: + cache: {} + config: | + [[runners]] + [runners.kubernetes] + namespace = "{{.Release.Namespace}}" + image = "ubuntu:20.04" + {{- if .Values.runners.privileged }} + privileged = true + [[runners.kubernetes.volumes.empty_dir]] + name = "docker-certs" + mount_path = "/certs/client" + medium = "Memory" + {{- end }} + locked: false + privileged: true + tags: "" +secrets: [] +securityContext: + allowPrivilegeEscalation: true + capabilities: + drop: + - ALL + add: + - CAP_NET_ADMIN + - CAP_SYS_ADMIN + privileged: true + readOnlyRootFilesystem: false + runAsNonRoot: true +... +``` + +Установка helm'ом Gitlab Runner'а (не забываем создать в проекте Gitlab - Runner, а Shared можно отключить, так как нет поддержки dind) + +![Gitlab Runner](img/Screenshot_20231029_170717.png) + +![Настройки Runner](img/Screenshot_20231029_170840.png) + +Нужно прописать полученный token и в файле выше *runnerRegistrationToken* и при установке *runnerToken*. + +После получения token'а выполняется установка в свой namespace: + +```bash +helm install --namespace gitlab-runner --create-namespace -f ./gitlab-runner/values.yaml --set gitlabDomain=infranet.dev --set gitlabUrl=https://gitlab.infranet.dev --set runnerToken=glrt-rCoCNbEHSJPux9PXGemx gitlab-runner ./gitlab-runner/ +``` + +Удаление runner'а: + +```bash +helm uninstall -n gitlab-runner gitlab-runner +``` + +```bash +cat < "No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load" + +Далее процесс отправки образа в `docker.io` завершался ошибкой: + +```output +docker push index.docker.io/23f03013e37f/post:test +The push refers to repository [docker.io/23f03013e37f/post] +An image does not exist locally with the tag: 23f03013e37f/post +Cleaning up project directory and file based variables +00:00 +ERROR: Job failed: command terminated with exit code 1 +``` + +Проблему удалось решить путем настройки аутентификации докера раньше сборки, а при сборке использовать ключ --push в *.gitlab-ci.yml*: + +```bash +docker buildx build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --platform=linux/amd64 --push . +``` + +Так как образ уже собран в Registry docker.io, чтобы не "гонять" еще раз после build'а для указания версии, есть возмоджность просто изменить манифест командой: + +```bash +docker buildx imagetools create "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --tag "$CI_APPLICATION_REPOSITORY:$(cat VERSION)" +``` + +> Результат: + +![23f03013e37f/post:0.0.2](img/Screenshot_20231029_171848.png) + +Для заруска задачи (Job) в отдельном Kubernetes POD-е доавлены атрибуты *tags* в CI/CD Runner и в `.gitlab-ci.yml` + +[Пайплайн здорового человека](src/ui/.gitlab-ci.yml) для *ui* можно посмотреть здесь, рабочий вариант... для [reddit-deploy](kubernetes/Charts/.gitlab-ci.yml). + +Чтобы запустить CI/CD в Environment: staging, production нужно подключить кластер Kubernetes к Gitlab, + +Поэтому выполнить настройку аутентификацию Kubernetes в GitLab необходимо. + +По документации нужно создать подключение к кластеру, прямо в строке поиска агента указываем имя и создать: + +![Operate/Kubernetes clusters](img/Screenshot_20231030_163800.png) + +![Operate/Kubernetes clusters](img/Screenshot_20231030_175352.png) + +Установка Gitlab Agent с помощью Helm-чарта (версия должна быть совместима с Gitlab, можно взять с картинки): + +```bash +export HELM_EXPERIMENTAL_OCI=1 && \ +helm pull oci://cr.yandex/yc-marketplace/yandex-cloud/gitlab-org/gitlab-agent/chart/gitlab-agent \ + --version 1.16.0-1 \ + --untar && \ +helm upgrade --install \ + --namespace gitlab-agent-infra \ + --create-namespace \ + --set serviceAccount.create=false \ + --set rbac.create=false \ + --set rbac.useExistingRole=gitlab-runner-role-default \ + --set config.kasAddress='wss://kas.infranet.dev/-/kubernetes-agent/' \ + --set config.token='glagent-JyfC-qffZHonby8YTCykmzFDz8shGXaJxX9g2bpDL3c17QFyLA' \ + gitlab-agent ./gitlab-agent/ +``` + +Если RBAC указывается true, то, возможно, нужно добавить роль (ранее нужно было такое же делать для Runner'а): + +```bash +cat < manager.go:107: warning: a valid Helm v3 hash was not found. Checking against Helm v2 hash... +> Error: the lock file (requirements.lock) is out of sync with the dependencies file (requirements.yaml). Please update the dependencies +> +Возможно, нужно не публиковать requirements.lock в *.gitignore* и еще актуальная версия helm'а, если использовать просто image: alpine - [3.13.1](https://get.helm.sh/helm-v3.13.1-linux-amd64.tar.gz) + +Но переделал способ - это использовать уже **alpine/helm** образ (взято из лекционного материала): + +```yaml +test: + stage: test + image: + name: alpine/helm + entrypoint: ["/bin/sh","-c"] + variables: + KUBE_CONTEXT: 23f03013e37f/reddit-deploy:reddit-deploy + KUBE_NAMESPACE: staging + environment: test + script: + - install_dependencies + - ensure_namespace + - deploy + only: + - branches +``` + +Опытном путём выяснилось, что всё же не нужен KUBE_CONFIG/KUBECONFIG - yaml-файл указывать в переменных в Gitlab-Project-Settings-CI/CD-Variables, KUBECONFIG - файл, будет виден в `set` из преременной `KUBECONFIG=/builds/23f03013e37f/reddit-deploy.tmp/KUBECONFIG` + +Сложно было [разобраться](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html#update-your-gitlab-ciyml-file-to-run-kubectl-commands), какой-же всё же контекст: +/:, где *agent-folder-name*, берется из .gitlab/agents//config.yaml + +```yaml +user_access: + access_as: + agent: {} + projects: + - id: 23f03013e37f/reddit-deploy +ci_access: + projects: + - id: 23f03013e37f/reddit-deploy + groups: + - id: 23f03013e37f +observability: + logging: + level: debug + +``` + +В *gitlab-ci.yml* в ui.image.tag подправлен путь в команде helm'а - добавлен '/-/' в `/ui/-/raw/main/VERSION` + +Далее задать своего агента можно и через переменную: + +![Kube Context Variable](img/Screenshot_20231031_125718.png) + +Все остальные действия уже чисто дело техники, сам процесс уже понятен... :-) + +![](img/Screenshot_20231031_145820.png) + +Альтернатива агенту по схеме pull - [Flux](https://docs.gitlab.com/ee/user/clusters/agent/#gitops-workflow) + +Файлы `.gitlab-ci.yml` скопированы из Gitlab_ci в папку src/{ui,post-py,comment} и для reddit-deploy - в charts. + +--- + +## Введение в kubernetes + Список литературы и статей: - [Минимально жизнеспособный Kubernetes](https://habr.com/ru/companies/otus/articles/513344/) @@ -37,6 +899,7 @@ aasdhajkshd microservices repository - [Динамическая подготовка тома](https://cloud.yandex.ru/docs/managed-kubernetes/operations/volumes/dynamic-create-pv) - [Управление классами хранилищ](https://cloud.yandex.ru/docs/managed-kubernetes/operations/volumes/manage-storage-class#sc-default) - [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) +- [A visual guide on troubleshooting Kubernetes deployments](https://learnk8s.io/troubleshooting-deployments) Абстракции над подами @@ -49,6 +912,12 @@ aasdhajkshd microservices repository Так как на странице **24** домашнего задания представлена картинка управлеяемого кластера, выполнение пунктов выполнялась с установкой Yandex Managed Service для Kubernetes кластере *infra-kube*. +--- + +#### Выполненные работы + +--- + ### Создание управляемого кластера для Kubernetes в YC 1. Настройка групп безопасности @@ -558,7 +1427,7 @@ helm upgrade \ --set folderId=$YC_FOLDER_ID \ --set clusterId=$YC_CLUSTER_ID \ --install ingress-nginx ingress-nginx \ ---set-file saKeySecretKey=../../kubernetes/infra/.secrets/$YC_SVC_ACCT \ +--set-file saKeySecretKey=../../kubernetes/infra/.secrets/$YC_SVC_ACCT.json \ --repo https://kubernetes.github.io/ingress-nginx \ --atomic ``` @@ -933,13 +1802,12 @@ kubectl apply -n dev -f mongo-deployment.yml - `kubectl port-forward` — пробросить порт из Kubernetes на локальный хост - `kubectl exec` — выполнить команду внутри запущенного контейнера +Если что-то не получается, может это поможет? +![Troubleshooting Kubernetes](img/troubleshooting-kubernetes.ru_ru.v2.png) +--- ## Введение в kubernetes -#### Выполненные работы - -1. Выполнены изучение и разбор на практике всех компонентов Kubernetes - Список литературы и статей: - https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ @@ -955,6 +1823,14 @@ kubectl apply -n dev -f mongo-deployment.yml - https://www.linuxtechi.com/install-kubernetes-on-ubuntu-22-04 - https://www.linuxsysadmins.com/install-kubernetes-cluster-with-ansible +--- + +#### Выполненные работы + +--- + +1. Выполнены изучение и разбор на практике всех компонентов Kubernetes + 2. Установка k8s на двух узлах при помощи утилиты kubeadm > Если docker устанавливается для версии ОС Ununtu 16.04, то будет несовместимость с актуальной версией kubernetes 1.28. @@ -1386,9 +2262,9 @@ kubernetes_worker_instance = [ kubernetes_worker_ip_address = "158.160.99.62" ``` -Статус кластера +Статус кластера: + ```output -```bash Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-163-generic x86_64) * Documentation: https://help.ubuntu.com @@ -1460,18 +2336,20 @@ ansible-playbook playbooks/k8s_deploy.yml Ресурсы и статьи по Ansible помимо официального сайта, которые помогли с написанием playbook'ов: -- https://github.com/geerlingguy/ansible-role-kubernetes/tree/master -- https://spec-zone.ru/ansible~2.10/cli/ansible-playbook -- https://opendev.org/starlingx/ansible-playbooks/commit/c52980d44be5841d81e91d3ea0de94ca1bb9f69a -- https://github.com/torgeirl/kubernetes-playbooks/blob/master/playbooks/kube-dependencies.yml -- https://www.linuxsysadmins.com/install-kubernetes-cluster-with-ansible/ -- https://sidmid.ru/%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d1%82%d1%8c-%d1%81-terraform-%d0%b2-yandex-%d0%be%d0%b1%d0%bb%d0%b0%d0%ba%d0%b5/ -- https://www.ipify.org/ -- https://kubernetes.io/docs/reference/config-api/kubeadm-config.v1beta3/ -- https://groups.google.com/g/ansible-project/c/TkDRbw1ques -- https://www.educba.com/ansible-debug/ -- https://www.reddit.com/r/ansible/comments/wqxmoh/print_list_to_separate_lines/ -- https://habr.com/ru/companies/slurm/articles/706920/ +- [ansible-role-kubernetes](https://github.com/geerlingguy/ansible-role-kubernetes/tree/master) +- [ansible - сборник пьес](https://spec-zone.ru/ansible~2.10/cli/ansible-playbook) +- [starlingx/ansible-playbooks](https://opendev.org/starlingx/ansible-playbooks/commit/c52980d44be5841d81e91d3ea0de94ca1bb9f69a) +- [torgeirl/kubernetes-playbooks](https://github.com/torgeirl/kubernetes-playbooks/blob/master/playbooks/kube-dependencies.yml) +- [Install Kubernetes Cluster with Ansible on Ubuntu in 5 minutes](https://www.linuxsysadmins.com/install-kubernetes-cluster-with-ansible/) +- [работать с Terraform в yandex облаке](https://sidmid.ru/%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d1%82%d1%8c-%d1%81-terraform-%d0%b2-yandex-%d0%be%d0%b1%d0%bb%d0%b0%d0%ba%d0%b5/) +- [A Simple Public IP Address API](https://www.ipify.org/) +- [kubeadm Configuration (v1beta3)](https://kubernetes.io/docs/reference/config-api/kubeadm-config.v1beta3/) +- [List of all ansible_ssh_host in group](https://groups.google.com/g/ansible-project/c/TkDRbw1ques +- [Ansible Debug](https://www.educba.com/ansible-debug/) +- [Print list to separate lines](https://www.reddit.com/r/ansible/comments/wqxmoh/print_list_to_separate_lines/) +- [Основы автоматизации в Ansible: роли и сценарии](https://habr.com/ru/companies/slurm/articles/706920/) + +--- ## Введение в мониторинг. Системы мониторинга @@ -1552,12 +2430,19 @@ docker-compose up -d #### Сбор метрик хоста 1. В файлы *docker/docker-compose.yml* и *monitoring/prometheus/prometheus.yml* внсенена информация по новому сервису - node-exporter. Перезапущены сервисы. + 2. В списке Status/Targets'ов новый узел + ![](img/Screenshot_20230927_044159.png) + 3. Ведется сбор данных + ![](img/Screenshot_20230927_044434.png) + 4. Проверка мониторинга + ![](img/Screenshot_20230927_044705.png) + 5. Образы загружены на DockerHub и доступны по ссылкам > @@ -1643,9 +2528,11 @@ modules: ``` 1. В файл docker/docker-compose.yml добавлен сервис blackbox-exporter + 2. В файл *monitoring/prometheus/prometheus.yml* добавлен target для Cloudprober 3. blackbox запустился в Prometheus + ![](img/Screenshot_20230927_113103.png) #### Задания со *star* @@ -1679,6 +2566,8 @@ make push-[ui|post|comment|prometheus|blackbox] make [build|push]-all ``` +--- + ## Устройство Gitlab CI. Построение процесса непрерывной поставки #### Выполненные работы @@ -1721,8 +2610,10 @@ variable "builds" { } ``` -И для раскатки 'gitlab-ci' *docker*'а генерирует из динамического шаблона *inventory.json.tpl* для **ansible** инвентори с внешним IP-адресом, который будет использоваться при установке контейнера 'gitlab-ce:latest', как переменная в шаблоне *docker-compose.yml.j2* и для пункта со \<\*\> в модуле **docker_container**. Так же предусмотрена в **ansible** проверка *gitlab* контейнера и вывод пароля иницализации. Playbook'и организованы с ролями для docker и gitlab. +И для раскатки 'gitlab-ci' *docker*'а генерирует из динамического шаблона *inventory.json.tpl* для **ansible** инвентори с внешним IP-адресом, который будет использоваться при установке контейнера 'gitlab-ce:latest', как переменная в шаблоне *docker-compose.yml.j2* и для пункта со **\<\*\>** в модуле **docker_container**. Так же предусмотрена в **ansible** проверка *gitlab* контейнера и вывод пароля иницализации. Playbook'и организованы с ролями для docker и gitlab. + 3. Чтобы решить ошибку недоступности подключения **ansible** к установленной виртуальной машине сразу. использовался дополнительные модуль 'ansible.builtin.wait_for_connection' и проверкой доступности docker контейнера. + 4. Установка решения выполняется двумя командами: ```bash @@ -1731,13 +2622,14 @@ terraform -chdir=terraform/stage/ apply -auto-approve ``` См. лог gitlab-ci/infra/packer-ansible.md и gitlab-ci/infra/terraform-ansible.md + 5. Можно отдельно запускать сам *ansible-playbook* ```bash ansible-playbook -i ../terraform/stage/inventory.json playbooks/gitlab.yml ``` -8. Проверка работы докера можно выполнить по ssh: +6. Проверка работы докера можно выполнить по ssh: ```bash ssh -l ubuntu -i ~/.ssh/id_rsa-appuser 158.160.60.194 docker inspect -f {{.State.Health.Status}} gitlab @@ -1747,13 +2639,13 @@ ssh -l ubuntu -i ~/.ssh/id_rsa-appuser 158.160.60.194 docker inspect -f {{.State healthy ``` -8. Для получения пароля можно воспользоавться прочтением файла или через **ansible** или *output.tf* из **terraform** +7. Для получения пароля можно воспользоавться прочтением файла или через **ansible** или *output.tf* из **terraform** ```bash ssh -l ubuntu -i ~/.ssh/id_rsa-appuser 158.160.60.194 sudo grep -i 'password:' /srv/gitlab/config/initial_root_password ``` -9. Если пароль забыт, можно сбросить +8. Если пароль забыт, можно сбросить > @@ -1762,9 +2654,11 @@ docker exec -it gitlab bash gitlab-rake 'gitlab:password:reset[root]' ``` -10. После подключения к Gitlab web сайту, выполнено отключение регистрации. -11. Добавлена группа homework, репозиторий example, выполнены пункты задания 4. -12. Зарегистрирован Runner и получен token. +9. После подключения к Gitlab web сайту, выполнено отключение регистрации. + +10. Добавлена группа homework, репозиторий *example*, выполнены пункты задания 4. + +11. Зарегистрирован Runner и получен token. > Проверить, что "Run untagged jobs" установлен. > Indicates whether this runner can pick jobs without tags @@ -1773,7 +2667,7 @@ gitlab-rake 'gitlab:password:reset[root]' gitlab-runner register --url http://158.160.60.194 --token glrt-CXJApPiVyyGssWMxWVVD ``` -1. Добавлен Runner (и как установка в playbook *gitlab.yml*) +12. Добавлен Runner (и как установка в playbook *gitlab.yml*) ```bash docker run -d --name gitlab-runner --restart always -v /srv/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest @@ -1785,7 +2679,7 @@ ea79446f5691 gitlab/gitlab-runner:latest "/usr/bin/dumb-init …" 6 minute 2710b85663fa gitlab/gitlab-ce:latest "/assets/wrapper" 2 hours ago Up 2 hours (healthy) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:2222->22/tcp gitlab ``` -1. Регистрация Runner'а +13. Регистрация Runner'а ```bash docker exec -it gitlab-runner gitlab-runner register \ @@ -1810,7 +2704,7 @@ Runner registered successfully. Feel free to start it, but if it's running alrea Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml" ``` -15. Добавлен Reddit в проект, изменен файл .gitlab-ci.yml и добавлен файл simpletest.rb +14. Добавлен Reddit в проект, изменен файл .gitlab-ci.yml и добавлен файл simpletest.rb ```bash git clone https://github.com/express42/reddit.git && rm -rf ./reddit/.git @@ -1819,12 +2713,18 @@ git commit -m "Add reddit app" git push gitlab gitlab-ci-1 ``` -16. Пройдены тесты в pipeline'е пунктов ДЗ 6.2 -17. Добавлены окружения dev, staging, production и выполнены их проверки пунктов ДЗ 7.X +15. Пройдены тесты в pipeline'е пунктов ДЗ 6.2 + +16. Добавлены окружения dev, staging, production и выполнены их проверки пунктов ДЗ 7.X + ![](img/Screenshot_20230924_174725.png) -18. Проверены условия, ограничения ручной запуск пунктов ДЗ 8.X + +17. Проверены условия, ограничения ручной запуск пунктов ДЗ 8.X + ![](img/Screenshot_20230924_173919.png) -19. Проверено добавление динамических окружений пунктов ДЗ 9.X + +18. Проверено добавление динамических окружений пунктов ДЗ 9.X +19. ![](img/Screenshot_20230924_173702.png) #### Задания со *star* @@ -1900,9 +2800,12 @@ build_job: ``` Прохождение этапа формирования образа docker-in-docker (dind) + ![](img/Screenshot_20230925_142047.png) ![](img/Screenshot_20230925_142118.png) +--- + ## Docker сети, docker-compose #### Выполненные работы @@ -2090,7 +2993,12 @@ b713005ef641 "puma" 7 minutes ago Up 6 minutes 0.0.0.0:9 2. Для изменения настроек приложения, возможно выполнить подключечния тома, как и для БД. ```bash -$ docker-machine ssh docker-host sudo ls -Al /var/lib/docker/volumes/src_ui_app/_data +docker-machine ssh docker-host sudo ls -Al /var/lib/docker/volumes/src_ui_app/_data +``` + +> Результат: + +```output total 48 -rw-r--r-- 1 root root 396 Sep 13 09:01 config.ru ... @@ -2099,12 +3007,23 @@ total 48 3. Для запуска puma приложений в режиме диагностики с двумя процессами *--debug* и *-w 2* можно добавить **command**: puma --debug -w 2 ```bash -$ docker ps +docker ps +``` + +> Результат: + +```output CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f441fae2fbcd 23f03013e37f/ui:1.0 "puma --debug -w 2" 9 seconds ago Up 4 seconds 0.0.0.0:8080->9292/tcp, :::8080->9292/tcp src-ui-1 ... -$ docker logs $(docker ps -a -q --filter "name=src-ui-1") | head -5 +```bash +docker logs $(docker ps -a -q --filter "name=src-ui-1") | head -5 +``` + +> Результат: + +```output [1] Puma starting in cluster mode... [1] * Version 3.10.0 (ruby 2.3.1-p112), codename: Russell's Teapot [1] * Min threads: 0, max threads: 16 @@ -2112,6 +3031,8 @@ $ docker logs $(docker ps -a -q --filter "name=src-ui-1") | head -5 [1] * Process workers: 2 ``` +--- + ## Микросервисы #### Выполненные работы diff --git a/img/Screenshot_20231024_232101.png b/img/Screenshot_20231024_232101.png new file mode 100644 index 0000000..00f402c Binary files /dev/null and b/img/Screenshot_20231024_232101.png differ diff --git a/img/Screenshot_20231025_142253.png b/img/Screenshot_20231025_142253.png new file mode 100644 index 0000000..f69e9d9 Binary files /dev/null and b/img/Screenshot_20231025_142253.png differ diff --git a/img/Screenshot_20231025_192152.png b/img/Screenshot_20231025_192152.png new file mode 100644 index 0000000..c616aa9 Binary files /dev/null and b/img/Screenshot_20231025_192152.png differ diff --git a/img/Screenshot_20231026_172236.png b/img/Screenshot_20231026_172236.png new file mode 100644 index 0000000..dc21b91 Binary files /dev/null and b/img/Screenshot_20231026_172236.png differ diff --git a/img/Screenshot_20231029_154520.png b/img/Screenshot_20231029_154520.png new file mode 100644 index 0000000..b3ce258 Binary files /dev/null and b/img/Screenshot_20231029_154520.png differ diff --git a/img/Screenshot_20231029_155002.png b/img/Screenshot_20231029_155002.png new file mode 100644 index 0000000..d497b87 Binary files /dev/null and b/img/Screenshot_20231029_155002.png differ diff --git a/img/Screenshot_20231029_170607.png b/img/Screenshot_20231029_170607.png new file mode 100644 index 0000000..3535894 Binary files /dev/null and b/img/Screenshot_20231029_170607.png differ diff --git a/img/Screenshot_20231029_170717.png b/img/Screenshot_20231029_170717.png new file mode 100644 index 0000000..c5cff5a Binary files /dev/null and b/img/Screenshot_20231029_170717.png differ diff --git a/img/Screenshot_20231029_170840.png b/img/Screenshot_20231029_170840.png new file mode 100644 index 0000000..cfc3f1b Binary files /dev/null and b/img/Screenshot_20231029_170840.png differ diff --git a/img/Screenshot_20231029_171848.png b/img/Screenshot_20231029_171848.png new file mode 100644 index 0000000..85da623 Binary files /dev/null and b/img/Screenshot_20231029_171848.png differ diff --git a/img/Screenshot_20231030_163800.png b/img/Screenshot_20231030_163800.png new file mode 100644 index 0000000..36c8fbd Binary files /dev/null and b/img/Screenshot_20231030_163800.png differ diff --git a/img/Screenshot_20231030_163925.png b/img/Screenshot_20231030_163925.png new file mode 100644 index 0000000..c8e63d8 Binary files /dev/null and b/img/Screenshot_20231030_163925.png differ diff --git a/img/Screenshot_20231030_164645.png b/img/Screenshot_20231030_164645.png new file mode 100644 index 0000000..9ea732f Binary files /dev/null and b/img/Screenshot_20231030_164645.png differ diff --git a/img/Screenshot_20231030_175352.png b/img/Screenshot_20231030_175352.png new file mode 100644 index 0000000..025f9fd Binary files /dev/null and b/img/Screenshot_20231030_175352.png differ diff --git a/img/Screenshot_20231031_080044.png b/img/Screenshot_20231031_080044.png new file mode 100644 index 0000000..133c40c Binary files /dev/null and b/img/Screenshot_20231031_080044.png differ diff --git a/img/Screenshot_20231031_125718.png b/img/Screenshot_20231031_125718.png new file mode 100644 index 0000000..cd01bd5 Binary files /dev/null and b/img/Screenshot_20231031_125718.png differ diff --git a/img/Screenshot_20231031_145820.png b/img/Screenshot_20231031_145820.png new file mode 100644 index 0000000..dd7cb0e Binary files /dev/null and b/img/Screenshot_20231031_145820.png differ diff --git a/img/troubleshooting-kubernetes.ru_ru.v2.png b/img/troubleshooting-kubernetes.ru_ru.v2.png new file mode 100644 index 0000000..3d819b7 Binary files /dev/null and b/img/troubleshooting-kubernetes.ru_ru.v2.png differ diff --git a/kubernetes/Charts/.gitignore b/kubernetes/Charts/.gitignore new file mode 100644 index 0000000..542128f --- /dev/null +++ b/kubernetes/Charts/.gitignore @@ -0,0 +1,4 @@ +!gitlab-omnibus/templates/gitlab-config.yaml +!gitlab-omnibus/templates/gitlab/gitlab-svc.yaml +!gitlab-omnibus/templates/ingress/gitlab-ingress.yaml +gitlab/ diff --git a/kubernetes/Charts/.gitlab-ci.yml b/kubernetes/Charts/.gitlab-ci.yml new file mode 100644 index 0000000..239506a --- /dev/null +++ b/kubernetes/Charts/.gitlab-ci.yml @@ -0,0 +1,157 @@ +image: alpine/helm:latest + +stages: + - test + - staging + - production + +test: + stage: test + image: + name: alpine/helm + entrypoint: ["/bin/sh","-c"] + variables: + KUBE_CONTEXT: 23f03013e37f/reddit-deploy:reddit-deploy + KUBE_NAMESPACE: test + environment: test + script: + - install_dependencies + - ensure_namespace + - delete + - deploy + only: + - branches + except: + - triggers + +staging: + stage: staging + variables: + KUBE_CONTEXT: 23f03013e37f/reddit-deploy:reddit-deploy + KUBE_NAMESPACE: staging + environment: + name: staging + url: https://staging.infranet.dev + script: + - install_dependencies + - ensure_namespace + - deploy + only: + refs: + - main + except: + - triggers + +production: + stage: production + script: + - install_dependencies + - ensure_namespace + - deploy + variables: + KUBE_CONTEXT: ${KUBE_CONTEXT_PROD} + KUBE_NAMESPACE: production + environment: + name: production + url: https://production.infranet.dev + when: manual + only: + refs: + - main + except: + - triggers + +production_trigers: + stage: production + variables: + KUBE_CONTEXT_PROD: ${KUBE_CONTEXT_PROD} + KUBE_NAMESPACE: production + host: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + name: $CI_ENVIRONMENT_SLUG + environment: + name: production + url: https://production.infranet.dev + script: + - install_dependencies + - ensure_namespace + - deploy + only: + refs: + - triggers + +.auto_devops: &auto_devops | + # Auto DevOps variables and functions + [[ "$TRACE" ]] && set -x + export CI_REGISTRY="index.docker.io" + export CI_APPLICATION_REPOSITORY=$CI_REGISTRY/$CI_PROJECT_PATH + export CI_APPLICATION_TAG=$CI_COMMIT_REF_SLUG + export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID} + export TILLER_NAMESPACE="kube-system" + + function deploy() { + + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + echo -e "\nStarting deployment of the project $name..." + tree ./ + + echo "helm dep build --debug reddit/" + helm dep build --debug reddit/ || true + + helm dep ls reddit/ + + helm template \ + --set ui.ingress.host="$host" \ + --set ui.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/ui/-/raw/main/VERSION)" \ + --set post.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/post/-/raw/main/VERSION)" \ + --set comment.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/comment/-/raw/main/VERSION)" \ + --set auth.enabled=false \ + --namespace="$KUBE_NAMESPACE" --create-namespace \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit/ + + helm upgrade --install --atomic --debug --wait --cleanup-on-fail \ + --set ui.ingress.host="$host" \ + --set ui.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/ui/-/raw/main/VERSION)" \ + --set post.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/post/-/raw/main/VERSION)" \ + --set comment.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/comment/-/raw/main/VERSION)" \ + --set auth.enabled=false \ + --namespace="$KUBE_NAMESPACE" --create-namespace \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit/ + + } + + function install_dependencies() { + echo -e "\nInstalling default depecdencies and setting kube context..." + apk add -U openssl curl tar gzip bash ca-certificates git gpg tree + wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + curl -L -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + chmod +x /usr/bin/kubectl + kubectl version --client + chmod go-rw ${KUBECONFIG} + kubectl config get-contexts + kubectl config use-context $KUBE_CONTEXT + helm version --client + helm repo add gitlab https://charts.gitlab.io + helm repo add stable https://charts.helm.sh/stable + helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx + helm repo update + + } + + function ensure_namespace() { + kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE" + } + + function delete() { + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + echo -e "\nDeleting helm project $name..." + helm delete "$name" || true + } + +before_script: + - *auto_devops diff --git a/kubernetes/Charts/comment/Chart.yaml b/kubernetes/Charts/comment/Chart.yaml new file mode 100644 index 0000000..24cc015 --- /dev/null +++ b/kubernetes/Charts/comment/Chart.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +appVersion: 1.0.0 +name: comment +version: 1.0.0 +description: OTUS reddit application Comment +maintainers: + - name: Someone + email: name.surname@gmail.com +icon: file://reddit_3983906.png diff --git a/kubernetes/Charts/comment/reddit_3983906.png b/kubernetes/Charts/comment/reddit_3983906.png new file mode 100644 index 0000000..ac21ca1 Binary files /dev/null and b/kubernetes/Charts/comment/reddit_3983906.png differ diff --git a/kubernetes/Charts/comment/templates/_helpers.tpl b/kubernetes/Charts/comment/templates/_helpers.tpl new file mode 100644 index 0000000..9b3d4c8 --- /dev/null +++ b/kubernetes/Charts/comment/templates/_helpers.tpl @@ -0,0 +1,3 @@ +{{- define "comment.fullname" -}} +{{- printf "%s-%s" .Release.Name .Chart.Name }} +{{- end -}} diff --git a/kubernetes/Charts/comment/templates/deployment.yaml b/kubernetes/Charts/comment/templates/deployment.yaml new file mode 100644 index 0000000..8ede0c1 --- /dev/null +++ b/kubernetes/Charts/comment/templates/deployment.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} + namespace: {{ .Values.namespace }} + labels: + app: reddit + component: {{ .Values.labels.component }} + release: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: reddit + component: {{ .Values.labels.component }} + release: {{ .Release.Name }} + template: + metadata: + name: comment + labels: + app: reddit + component: {{ .Values.labels.component }} + release: {{ .Release.Name }} + spec: + containers: + - name: comment + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + resources: + limits: + memory: 256Mi + cpu: "1" + env: + - name: COMMENT_DATABASE_HOST + value: {{ .Values.env.databaseHost | default (printf "%s-mongodb" .Release.Name) }} diff --git a/kubernetes/Charts/comment/templates/service.yaml b/kubernetes/Charts/comment/templates/service.yaml new file mode 100644 index 0000000..e70f55d --- /dev/null +++ b/kubernetes/Charts/comment/templates/service.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template "comment.fullname" . }} + namespace: {{ .Values.namespace }} + labels: + app: reddit + component: {{ .Values.labels.component }} + release: {{ .Release.Name }} +spec: + type: ClusterIP + selector: + app: reddit + component: {{ .Values.labels.component }} + ports: + - port: {{ .Values.service.externalPort }} + protocol: TCP + targetPort: {{ .Values.service.internalPort }} diff --git a/kubernetes/Charts/comment/values.yaml b/kubernetes/Charts/comment/values.yaml new file mode 100644 index 0000000..65cf4ed --- /dev/null +++ b/kubernetes/Charts/comment/values.yaml @@ -0,0 +1,13 @@ +--- +service: + internalPort: 9292 + externalPort: 9292 +image: + repository: 23f03013e37f/comment + tag: latest +namespace: dev +env: + databaseHost: +labels: + component: comment +replicaCount: 1 diff --git a/kubernetes/Charts/gitlab-omnibus/.gitlab-ci.yml b/kubernetes/Charts/gitlab-omnibus/.gitlab-ci.yml new file mode 100644 index 0000000..c0e9a6b --- /dev/null +++ b/kubernetes/Charts/gitlab-omnibus/.gitlab-ci.yml @@ -0,0 +1,19 @@ +image: registry.gitlab.com/charts/alpine-helm + +stages: + - test + - release + +lint: + stage: test + script: + - helm lint . + except: + - master + +release-chart: + stage: release + script: + - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master https://gitlab.com/api/v4/projects/2860651/trigger/pipeline + only: + - master diff --git a/kubernetes/Charts/gitlab-omnibus/.helmignore b/kubernetes/Charts/gitlab-omnibus/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/kubernetes/Charts/gitlab-omnibus/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/kubernetes/Charts/gitlab-omnibus/templates/_helpers.tpl b/kubernetes/Charts/gitlab-omnibus/templates/_helpers.tpl new file mode 100644 index 0000000..5dfb005 --- /dev/null +++ b/kubernetes/Charts/gitlab-omnibus/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified postgresql name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "postgresql.fullname" -}} +{{- $appName := (include "fullname" .) | trunc 54 | trimSuffix "-" -}} +{{- printf "%s-%s" $appName "postgresql" -}} +{{- end -}} + +{{/* +Create a default fully qualified redis name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "redis.fullname" -}} +{{- $appName := (include "fullname" .) | trunc 57 | trimSuffix "-" -}} +{{- printf "%s-%s" $appName "redis" -}} +{{- end -}} + +{{/* +Template for outputing the gitlabUrl +*/}} +{{- define "gitlabUrl" -}} +{{- if .Values.gitlabUrl -}} +{{- .Values.gitlabUrl | quote -}} +{{- else -}} +{{- printf "http://%s-gitlab.%s:8005/" .Release.Name .Release.Namespace | quote -}} +{{- end -}} +{{- end -}} diff --git a/kubernetes/Charts/gitlab-omnibus/templates/gitlab-config.yaml b/kubernetes/Charts/gitlab-omnibus/templates/gitlab-config.yaml new file mode 100644 index 0000000..57f5c93 --- /dev/null +++ b/kubernetes/Charts/gitlab-omnibus/templates/gitlab-config.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "fullname" . }}-config + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +data: + external_scheme: http + external_hostname: {{ template "fullname" . }} + registry_external_scheme: https + registry_external_hostname: registry.{{ .Values.baseDomain }} + mattermost_external_scheme: https + mattermost_external_hostname: mattermost.{{ .Values.baseDomain }} + mattermost_app_uid: {{ .Values.mattermostAppUID }} + postgres_user: gitlab + postgres_db: gitlab_production +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "fullname" . }}-secrets + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +data: + postgres_password: {{ .Values.postgresPassword }} + initial_shared_runners_registration_token: {{ default "" .Values.initialSharedRunnersRegistrationToken | b64enc | quote }} + mattermost_app_secret: {{ .Values.mattermostAppSecret | b64enc | quote }} +{{- if .Values.gitlabEELicense }} + gitlab_ee_license: {{ .Values.gitlabEELicense | b64enc | quote }} +{{- end }} diff --git a/kubernetes/Charts/gitlab-omnibus/templates/gitlab/gitlab-svc.yaml b/kubernetes/Charts/gitlab-omnibus/templates/gitlab/gitlab-svc.yaml new file mode 100644 index 0000000..a273157 --- /dev/null +++ b/kubernetes/Charts/gitlab-omnibus/templates/gitlab/gitlab-svc.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +spec: + selector: + name: {{ template "fullname" . }} + ports: + - name: ssh + port: 22 + targetPort: ssh + - name: mattermost + port: 8065 + targetPort: mattermost + - name: registry + port: 8105 + targetPort: registry + - name: workhorse + port: 8005 + targetPort: workhorse + - name: prometheus + port: 9090 + targetPort: prometheus + {{- if and .Values.pagesExternalScheme .Values.pagesExternalDomain}} + - name: pages + port: 8090 + targetPort: pages + {{- end }} + - name: web + port: 80 + targetPort: workhorse diff --git a/kubernetes/Charts/gitlab-omnibus/templates/ingress/gitlab-ingress.yaml b/kubernetes/Charts/gitlab-omnibus/templates/ingress/gitlab-ingress.yaml new file mode 100644 index 0000000..b804f31 --- /dev/null +++ b/kubernetes/Charts/gitlab-omnibus/templates/ingress/gitlab-ingress.yaml @@ -0,0 +1,51 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" + annotations: + kubernetes.io/tls-acme: "true" + kubernetes.io/ingress.class: "nginx" +spec: + tls: + - hosts: + - gitlab.{{ .Values.baseDomain }} + - registry.{{ .Values.baseDomain }} + - mattermost.{{ .Values.baseDomain }} + - prometheus.{{ .Values.baseDomain }} + secretName: gitlab-tls + rules: + - host: {{ template "fullname" . }} +# - host: gitlab.{{ .Values.baseDomain }} + http: + paths: + - path: / + backend: + serviceName: {{ template "fullname" . }} + servicePort: 8005 + - host: registry.{{ .Values.baseDomain }} + http: + paths: + - path: / + backend: + serviceName: {{ template "fullname" . }} + servicePort: 8105 + - host: mattermost.{{ .Values.baseDomain }} + http: + paths: + - path: / + backend: + serviceName: {{ template "fullname" . }} + servicePort: 8065 + - host: prometheus.{{ .Values.baseDomain }} + http: + paths: + - path: / + backend: + serviceName: {{ template "fullname" . }} + servicePort: 9090 +--- diff --git a/kubernetes/Charts/gitlab-omnibus/values.yaml b/kubernetes/Charts/gitlab-omnibus/values.yaml new file mode 100644 index 0000000..1e28065 --- /dev/null +++ b/kubernetes/Charts/gitlab-omnibus/values.yaml @@ -0,0 +1,110 @@ +# Default values for kubernetes-gitlab-demo. +# This is a YAML-formatted file. + +# Required variables + +# baseDomain is the top-most part of the domain. Subdomains will be generated +# for gitlab, mattermost, registry, and prometheus. +# Recommended to set up an A record on the DNS to *.your-domain.com to point to +# the baseIP +# e.g. *.your-domain.com. A 300 baseIP +baseDomain: infranet.dev + +# legoEmail is a valid email address used by Let's Encrypt. It does not have to +# be at the baseDomain. +legoEmail: 23f03013e37f@mail.ru + +# Optional variables +# baseIP is an externally provisioned static IP address to use instead of the provisioned one. +#baseIP: 1.1.1.1 +nameOverride: gitlab +# `ce` or `ee` +gitlab: ce +gitlabCEImage: gitlab/gitlab-ce:10.6.2-ce.0 +gitlabEEImage: gitlab/gitlab-ee:10.6.2-ee.0 +postgresPassword: NDl1ZjNtenMxcWR6NXZnbw== +initialSharedRunnersRegistrationToken: "tQtCbx5UZy_ByS7FyzUH" +mattermostAppSecret: NDl1ZjNtenMxcWR6NXZnbw== +mattermostAppUID: aadas +redisImage: redis:3.2.10 +redisDedicatedStorage: true +#redisStorageSize: 5Gi +redisAccessMode: ReadWriteOnce +postgresImage: postgres:9.6.5 +# If you disable postgresDedicatedStorage, you should consider bumping up gitlabRailsStorageSize +postgresDedicatedStorage: true +postgresAccessMode: ReadWriteOnce +#postgresStorageSize: 30Gi +gitlabDataAccessMode: ReadWriteOnce +#gitlabDataStorageSize: 30Gi +gitlabRegistryAccessMode: ReadWriteOnce +#gitlabRegistryStorageSize: 30Gi +gitlabConfigAccessMode: ReadWriteOnce +#gitlabConfigStorageSize: 1Gi +gitlabRunnerImage: gitlab/gitlab-runner:alpine-v10.6.0 +# Valid values for provider are `gke` for Google Container Engine. Leaving it blank (or any othervalue) will disable fast disk options. +provider: gke + +# Gitlab pages +# The following 3 lines are needed to enable gitlab pages. +# pagesExternalScheme: http +# pagesExternalDomain: your-pages-domain.com +# pagesTlsSecret: gitlab-pages-tls # An optional reference to a tls secret to use in pages + +## Storage Class Options +## If defined, volume.beta.kubernetes.io/storage-class: +## If not defined, but provider is gke, will use SSDs +## Otherwise default: volume.alpha.kubernetes.io/storage-class: default +#gitlabConfigStorageClass: default +#gitlabDataStorageClass: default +#gitlabRegistryStorageClass: default +#postgresStorageClass: default +#redisStorageClass: default + +healthCheckToken: 'SXBAQichEJasbtDSygrD' +# Optional, for GitLab EE images only +#gitlabEELicense: base64-encoded-license + +# Additional omnibus configuration, +# see https://docs.gitlab.com/omnibus/settings/configuration.html +# for possible configuration options +#omnibusConfigRuby: | +# gitlab_rails['smtp_enable'] = true +# gitlab_rails['smtp_address'] = "smtp.example.org" + +gitlab-runner: + checkInterval: 1 + # runnerRegistrationToken must equal initialSharedRunnersRegistrationToken + runnerRegistrationToken: "tQtCbx5UZy_ByS7FyzUH" + # resources: + # limits: + # memory: 500Mi + # cpu: 600m + # requests: + # memory: 500Mi + # cpu: 600m + runners: + privileged: true + ## Build Container specific configuration + ## + # builds: + # cpuLimit: 200m + # memoryLimit: 256Mi + # cpuRequests: 100m + # memoryRequests: 128Mi + + ## Service Container specific configuration + ## + # services: + # cpuLimit: 200m + # memoryLimit: 256Mi + # cpuRequests: 100m + # memoryRequests: 128Mi + + ## Helper Container specific configuration + ## + # helpers: + # cpuLimit: 200m + # memoryLimit: 256Mi + # cpuRequests: 100m + # memoryRequests: 128Mi diff --git a/kubernetes/Charts/gitlab-runner/values.yaml b/kubernetes/Charts/gitlab-runner/values.yaml new file mode 100644 index 0000000..2504539 --- /dev/null +++ b/kubernetes/Charts/gitlab-runner/values.yaml @@ -0,0 +1,82 @@ +affinity: {} +checkInterval: 30 +concurrent: 10 +configMaps: {} +gitlabDomain: "" +hostAliases: [] +image: + image: yandex-cloud/gitlab-org/gitlab-runner/gitlab-runner + registry: cr.yandex/yc-marketplace + tag: alpine-v16.1.0 +imagePullPolicy: IfNotPresent +metrics: + enabled: false + port: 9252 + portName: metrics + serviceMonitor: + enabled: false +nodeSelector: {} +podAnnotations: {} +podLabels: {} +podSecurityContext: + fsGroup: 65533 + runAsUser: 100 +priorityClassName: "" +rbac: + clusterWideAccess: false + create: true + podSecurityPolicy: + enabled: false + resourceNames: + - gitlab-runner + rules: + - apiGroups: [""] + resources: ["pods", "secrets", "configmaps"] + verbs: ["get", "list", "watch", "create", "patch", "delete", "update"] + - apiGroups: [""] + resources: ["pods/exec", "pods/attach"] + verbs: ["create", "patch", "delete"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] +resources: {} +runnerRegistrationToken: "glrt-rCoCNbEHSJPux9PXGemx" +runners: + cache: {} + config: | + [[runners]] + [runners.kubernetes] + namespace = "{{.Release.Namespace}}" + image = "ubuntu:20.04" + {{- if .Values.runners.privileged }} + privileged = true + [[runners.kubernetes.volumes.empty_dir]] + name = "docker-certs" + mount_path = "/certs/client" + medium = "Memory" + {{- end }} + locked: false + privileged: true + tags: "" +secrets: [] +securityContext: + allowPrivilegeEscalation: true + capabilities: + drop: + - ALL + add: + - CAP_NET_ADMIN + - CAP_SYS_ADMIN + privileged: true + readOnlyRootFilesystem: false + runAsNonRoot: true +service: + enabled: false + type: ClusterIP +sessionServer: + enabled: false +terminationGracePeriodSeconds: 3600 +tolerations: [] +useTini: false +volumeMounts: [] +volumes: [] diff --git a/kubernetes/Charts/gitlabci/.gitlab-ci-comment.yml b/kubernetes/Charts/gitlabci/.gitlab-ci-comment.yml new file mode 100644 index 0000000..980101e --- /dev/null +++ b/kubernetes/Charts/gitlabci/.gitlab-ci-comment.yml @@ -0,0 +1,95 @@ +--- +image: alpine:latest + +stages: + - build + - test + - release + - cleanup + +build: + stage: build + image: docker:git + services: + - docker:18.09.7-dind + script: + - setup_docker + - build + variables: + DOCKER_DRIVER: overlay2 + only: + - branches + tags: + - docker + +test: + stage: test + script: + - exit 0 + only: + - branches + tags: + - test + +release: + stage: release + image: docker + services: + - docker:dind + script: + - setup_docker + - release + variables: + DOCKER_TLS_CERTDIR: "" + only: + - main + +.auto_devops: &auto_devops | + [[ "$TRACE" ]] && set -x + export CI_REGISTRY="index.docker.io" + export CI_APPLICATION_REPOSITORY=$CI_REGISTRY/$CI_PROJECT_PATH + export CI_APPLICATION_TAG=$CI_COMMIT_REF_SLUG + export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID} + export TILLER_NAMESPACE="kube-system" + export DOCKER_REGISTRY="$CI_REGISTRY" + export DOCKER_REGISTRY_PASS="$CI_REGISTRY_PASSWORD" + export DOCKER_REGISTRY_USER="$CI_REGISTRY_USER" + + function setup_docker() { + + if ! docker info &>/dev/null; then + if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then + export DOCKER_HOST='tcp://docker:2375' + fi + fi + + if [[ -n "$CI_REGISTRY_USER" ]] && [[ -n "$CI_REGISTRY_PASSWORD" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + echo -e "\n" + else + docker login + echo -e "\n" + fi + } + + function release() { + + echo "Updating docker tag images ..." + docker buildx imagetools create "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --tag "$CI_APPLICATION_REPOSITORY:$(cat VERSION)" + echo -e "\n" + } + + function build() { + + echo "Building Dockerfile-based application..." + echo `git show --format="%h" HEAD | head -1` > build_info.txt + echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt + + echo "Building and pushing to GitLab Container Registry..." + docker buildx build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --platform=linux/amd64 --push . + echo -e "\n" + } + +before_script: + - *auto_devops diff --git a/kubernetes/Charts/gitlabci/.gitlab-ci-post.yml b/kubernetes/Charts/gitlabci/.gitlab-ci-post.yml new file mode 100644 index 0000000..980101e --- /dev/null +++ b/kubernetes/Charts/gitlabci/.gitlab-ci-post.yml @@ -0,0 +1,95 @@ +--- +image: alpine:latest + +stages: + - build + - test + - release + - cleanup + +build: + stage: build + image: docker:git + services: + - docker:18.09.7-dind + script: + - setup_docker + - build + variables: + DOCKER_DRIVER: overlay2 + only: + - branches + tags: + - docker + +test: + stage: test + script: + - exit 0 + only: + - branches + tags: + - test + +release: + stage: release + image: docker + services: + - docker:dind + script: + - setup_docker + - release + variables: + DOCKER_TLS_CERTDIR: "" + only: + - main + +.auto_devops: &auto_devops | + [[ "$TRACE" ]] && set -x + export CI_REGISTRY="index.docker.io" + export CI_APPLICATION_REPOSITORY=$CI_REGISTRY/$CI_PROJECT_PATH + export CI_APPLICATION_TAG=$CI_COMMIT_REF_SLUG + export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID} + export TILLER_NAMESPACE="kube-system" + export DOCKER_REGISTRY="$CI_REGISTRY" + export DOCKER_REGISTRY_PASS="$CI_REGISTRY_PASSWORD" + export DOCKER_REGISTRY_USER="$CI_REGISTRY_USER" + + function setup_docker() { + + if ! docker info &>/dev/null; then + if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then + export DOCKER_HOST='tcp://docker:2375' + fi + fi + + if [[ -n "$CI_REGISTRY_USER" ]] && [[ -n "$CI_REGISTRY_PASSWORD" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + echo -e "\n" + else + docker login + echo -e "\n" + fi + } + + function release() { + + echo "Updating docker tag images ..." + docker buildx imagetools create "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --tag "$CI_APPLICATION_REPOSITORY:$(cat VERSION)" + echo -e "\n" + } + + function build() { + + echo "Building Dockerfile-based application..." + echo `git show --format="%h" HEAD | head -1` > build_info.txt + echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt + + echo "Building and pushing to GitLab Container Registry..." + docker buildx build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --platform=linux/amd64 --push . + echo -e "\n" + } + +before_script: + - *auto_devops diff --git a/kubernetes/Charts/gitlabci/.gitlab-ci-reddit.yml b/kubernetes/Charts/gitlabci/.gitlab-ci-reddit.yml new file mode 100644 index 0000000..239506a --- /dev/null +++ b/kubernetes/Charts/gitlabci/.gitlab-ci-reddit.yml @@ -0,0 +1,157 @@ +image: alpine/helm:latest + +stages: + - test + - staging + - production + +test: + stage: test + image: + name: alpine/helm + entrypoint: ["/bin/sh","-c"] + variables: + KUBE_CONTEXT: 23f03013e37f/reddit-deploy:reddit-deploy + KUBE_NAMESPACE: test + environment: test + script: + - install_dependencies + - ensure_namespace + - delete + - deploy + only: + - branches + except: + - triggers + +staging: + stage: staging + variables: + KUBE_CONTEXT: 23f03013e37f/reddit-deploy:reddit-deploy + KUBE_NAMESPACE: staging + environment: + name: staging + url: https://staging.infranet.dev + script: + - install_dependencies + - ensure_namespace + - deploy + only: + refs: + - main + except: + - triggers + +production: + stage: production + script: + - install_dependencies + - ensure_namespace + - deploy + variables: + KUBE_CONTEXT: ${KUBE_CONTEXT_PROD} + KUBE_NAMESPACE: production + environment: + name: production + url: https://production.infranet.dev + when: manual + only: + refs: + - main + except: + - triggers + +production_trigers: + stage: production + variables: + KUBE_CONTEXT_PROD: ${KUBE_CONTEXT_PROD} + KUBE_NAMESPACE: production + host: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + name: $CI_ENVIRONMENT_SLUG + environment: + name: production + url: https://production.infranet.dev + script: + - install_dependencies + - ensure_namespace + - deploy + only: + refs: + - triggers + +.auto_devops: &auto_devops | + # Auto DevOps variables and functions + [[ "$TRACE" ]] && set -x + export CI_REGISTRY="index.docker.io" + export CI_APPLICATION_REPOSITORY=$CI_REGISTRY/$CI_PROJECT_PATH + export CI_APPLICATION_TAG=$CI_COMMIT_REF_SLUG + export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID} + export TILLER_NAMESPACE="kube-system" + + function deploy() { + + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + echo -e "\nStarting deployment of the project $name..." + tree ./ + + echo "helm dep build --debug reddit/" + helm dep build --debug reddit/ || true + + helm dep ls reddit/ + + helm template \ + --set ui.ingress.host="$host" \ + --set ui.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/ui/-/raw/main/VERSION)" \ + --set post.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/post/-/raw/main/VERSION)" \ + --set comment.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/comment/-/raw/main/VERSION)" \ + --set auth.enabled=false \ + --namespace="$KUBE_NAMESPACE" --create-namespace \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit/ + + helm upgrade --install --atomic --debug --wait --cleanup-on-fail \ + --set ui.ingress.host="$host" \ + --set ui.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/ui/-/raw/main/VERSION)" \ + --set post.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/post/-/raw/main/VERSION)" \ + --set comment.image.tag="$(curl -k https://gitlab.infranet.dev/$CI_PROJECT_NAMESPACE/comment/-/raw/main/VERSION)" \ + --set auth.enabled=false \ + --namespace="$KUBE_NAMESPACE" --create-namespace \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit/ + + } + + function install_dependencies() { + echo -e "\nInstalling default depecdencies and setting kube context..." + apk add -U openssl curl tar gzip bash ca-certificates git gpg tree + wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + curl -L -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + chmod +x /usr/bin/kubectl + kubectl version --client + chmod go-rw ${KUBECONFIG} + kubectl config get-contexts + kubectl config use-context $KUBE_CONTEXT + helm version --client + helm repo add gitlab https://charts.gitlab.io + helm repo add stable https://charts.helm.sh/stable + helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx + helm repo update + + } + + function ensure_namespace() { + kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE" + } + + function delete() { + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + echo -e "\nDeleting helm project $name..." + helm delete "$name" || true + } + +before_script: + - *auto_devops diff --git a/kubernetes/Charts/gitlabci/.gitlab-ci-ui.yml b/kubernetes/Charts/gitlabci/.gitlab-ci-ui.yml new file mode 100644 index 0000000..f5d1bcb --- /dev/null +++ b/kubernetes/Charts/gitlabci/.gitlab-ci-ui.yml @@ -0,0 +1,213 @@ +--- +image: alpine:latest + +stages: + - build + - test + - review + - release + - cleanup + - production + +build: + stage: build + image: docker:git + services: + - docker:18.09.7-dind + script: + - setup_docker + - build + variables: + DOCKER_DRIVER: overlay2 + only: + - branches + tags: + - docker + +test: + stage: test + script: + - exit 0 + only: + - branches + tags: + - test + +review: + stage: review + script: + - install_dependencies + - ensure_namespace + - install_tiller + - deploy + variables: + KUBE_NAMESPACE: review + host: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + environment: + name: review/$CI_PROJECT_PATH/$CI_COMMIT_REF_NAME + url: http://$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + on_stop: stop_review + only: + refs: + - branches + kubernetes: active + except: + - master + - main + +release: + stage: release + image: docker + services: + - docker:dind + script: + - setup_docker + - release + variables: + DOCKER_TLS_CERTDIR: "" + only: + - master + - main + +stop_review: + stage: cleanup + variables: + GIT_STRATEGY: none + script: + - install_dependencies + - delete + environment: + name: review/$CI_PROJECT_PATH/$CI_COMMIT_REF_NAME + action: stop + when: manual + allow_failure: true + only: + refs: + - branches + kubernetes: active + except: + - master + - main + +production: + stage: production + before_script: + - apk add -U curl + script: + - > + export CI_HOSTNAME="gitlab.infranet.dev" + curl -X 'POST' -F token=$token -F ref=main https://$CI_HOSTNAME/api/v4/projects/1/trigger/pipeline + only: + - master + - main + +.auto_devops: &auto_devops | + [[ "$TRACE" ]] && set -x + export CI_REGISTRY="index.docker.io" + export CI_HOSTNAME="gitlab.infranet.dev" + export CI_APPLICATION_REPOSITORY=$CI_REGISTRY/$CI_PROJECT_PATH + export CI_APPLICATION_TAG=$CI_COMMIT_REF_SLUG + export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID} + export TILLER_NAMESPACE="kube-system" + export DOCKER_REGISTRY="$CI_REGISTRY" + export DOCKER_REGISTRY_PASS="$CI_REGISTRY_PASSWORD" + export DOCKER_REGISTRY_USER="$CI_REGISTRY_USER" + + function setup_docker() { + + if ! docker info &>/dev/null; then + if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then + export DOCKER_HOST='tcp://docker:2375' + fi + fi + + if [[ -n "$CI_REGISTRY_USER" ]] && [[ -n "$CI_REGISTRY_PASSWORD" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + echo -e "\n" + else + docker login + echo -e "\n" + fi + } + + function release() { + + echo "Updating docker tag images ..." + docker buildx imagetools create "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --tag "$CI_APPLICATION_REPOSITORY:$(cat VERSION)" + echo -e "\n" + } + + function build() { + + echo "Building Dockerfile-based application..." + echo `git show --format="%h" HEAD | head -1` > build_info.txt + echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt + + echo "Building and pushing to GitLab Container Registry..." + docker buildx build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --platform=linux/amd64 --push . + echo -e "\n" + } + + function deploy() { + + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + + if [[ "$track" != "stable" ]]; then + name="$name-$track" + fi + + echo "Clone deploy repository..." + git clone https://$CI_HOSTNAME/$CI_PROJECT_NAMESPACE/reddit-deploy.git + + echo "Download helm dependencies..." + helm dep update reddit-deploy/reddit + + echo "Deploy helm release $name to $KUBE_NAMESPACE" + helm upgrade --install \ + --wait \ + --set ui.ingress.host="$host" \ + --set $CI_PROJECT_NAME.image.tag=$CI_APPLICATION_TAG \ + --namespace="$KUBE_NAMESPACE" \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit-deploy/reddit/ + } + + function install_dependencies() { + + apk add -U openssl curl tar gzip bash ca-certificates git + wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk + apk add glibc-2.23-r3.apk + rm glibc-2.23-r3.apk + + curl https://storage.googleapis.com/pub/gsutil.tar.gz | tar -xz -C $HOME + export PATH=${PATH}:$HOME/gsutil + + curl https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz | tar zx + + mv linux-amd64/helm /usr/bin/helm + helm version --client + + curl -o /usr/bin/sync-repo.sh https://raw.githubusercontent.com/kubernetes/helm/master/scripts/sync-repo.sh + chmod a+x /usr/bin/sync-repo.sh + + curl -L -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + chmod +x /usr/bin/kubectl + kubectl version --client + } + + function ensure_namespace() { + kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE" + } + + function delete() { + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + helm delete "$name" -n review || true + } + +before_script: + - *auto_devops diff --git a/kubernetes/Charts/post/Chart.yaml b/kubernetes/Charts/post/Chart.yaml new file mode 100644 index 0000000..27b0185 --- /dev/null +++ b/kubernetes/Charts/post/Chart.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +appVersion: 1.0.0 +name: post +version: 1.0.0 +description: OTUS reddit application Post +maintainers: + - name: Someone + email: name.surname@gmail.com +icon: file://reddit_3983906.png diff --git a/kubernetes/Charts/post/reddit_3983906.png b/kubernetes/Charts/post/reddit_3983906.png new file mode 100644 index 0000000..ac21ca1 Binary files /dev/null and b/kubernetes/Charts/post/reddit_3983906.png differ diff --git a/kubernetes/Charts/post/templates/_helpers.tpl b/kubernetes/Charts/post/templates/_helpers.tpl new file mode 100644 index 0000000..9b3d4c8 --- /dev/null +++ b/kubernetes/Charts/post/templates/_helpers.tpl @@ -0,0 +1,3 @@ +{{- define "comment.fullname" -}} +{{- printf "%s-%s" .Release.Name .Chart.Name }} +{{- end -}} diff --git a/kubernetes/Charts/post/templates/deployment.yaml b/kubernetes/Charts/post/templates/deployment.yaml new file mode 100644 index 0000000..560ce0d --- /dev/null +++ b/kubernetes/Charts/post/templates/deployment.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} + namespace: {{ .Values.namespace }} + labels: + app: reddit + component: post + release: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: reddit + component: post + release: {{ .Release.Name }} + template: + metadata: + name: post + labels: + app: reddit + component: post + release: {{ .Release.Name }} + spec: + containers: + - name: post + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + resources: + limits: + memory: 512Mi + cpu: "1" + env: + - name: POST_DATABASE_HOST + value: {{ .Values.env.databaseHost | default (printf "%s-mongodb" .Release.Name) }} diff --git a/kubernetes/Charts/post/templates/service.yaml b/kubernetes/Charts/post/templates/service.yaml new file mode 100644 index 0000000..4ca906c --- /dev/null +++ b/kubernetes/Charts/post/templates/service.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template "comment.fullname" . }} + namespace: {{ .Values.namespace }} + labels: + app: reddit + component: post + release: {{ .Release.Name }} +spec: + type: NodePort + selector: + app: reddit + component: post + ports: + - port: {{ .Values.service.externalPort }} + protocol: TCP + targetPort: {{ .Values.service.internalPort }} diff --git a/kubernetes/Charts/post/values.yaml b/kubernetes/Charts/post/values.yaml new file mode 100644 index 0000000..33f5f42 --- /dev/null +++ b/kubernetes/Charts/post/values.yaml @@ -0,0 +1,12 @@ +--- +service: + internalPort: 5000 + externalPort: 5000 +image: + repository: 23f03013e37f/post + tag: latest +namespace: dev +env: + databaseHost: +labels: + component: post diff --git a/kubernetes/Charts/reddit/Chart.yaml b/kubernetes/Charts/reddit/Chart.yaml new file mode 100644 index 0000000..acd10d6 --- /dev/null +++ b/kubernetes/Charts/reddit/Chart.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +appVersion: 1.0.0 +name: post +version: 1.0.0 +description: OTUS reddit application Post +maintainers: + - name: Someone +icon: file://reddit_3983906.png diff --git a/kubernetes/Charts/reddit/charts/comment-1.0.0.tgz b/kubernetes/Charts/reddit/charts/comment-1.0.0.tgz new file mode 100644 index 0000000..c8c7ae0 Binary files /dev/null and b/kubernetes/Charts/reddit/charts/comment-1.0.0.tgz differ diff --git a/kubernetes/Charts/reddit/charts/mongodb-7.8.10.tgz b/kubernetes/Charts/reddit/charts/mongodb-7.8.10.tgz new file mode 100644 index 0000000..ae35536 Binary files /dev/null and b/kubernetes/Charts/reddit/charts/mongodb-7.8.10.tgz differ diff --git a/kubernetes/Charts/reddit/charts/post-1.0.0.tgz b/kubernetes/Charts/reddit/charts/post-1.0.0.tgz new file mode 100644 index 0000000..ddadcb9 Binary files /dev/null and b/kubernetes/Charts/reddit/charts/post-1.0.0.tgz differ diff --git a/kubernetes/Charts/reddit/charts/ui-1.0.0.tgz b/kubernetes/Charts/reddit/charts/ui-1.0.0.tgz new file mode 100644 index 0000000..3d6f292 Binary files /dev/null and b/kubernetes/Charts/reddit/charts/ui-1.0.0.tgz differ diff --git a/kubernetes/Charts/reddit/configmap.yaml b/kubernetes/Charts/reddit/configmap.yaml new file mode 100644 index 0000000..3c67a70 --- /dev/null +++ b/kubernetes/Charts/reddit/configmap.yaml @@ -0,0 +1,38 @@ +configmap: +# # where and how to store data. +# storage: +# dbPath: /bitnami/mongodb/data/db +# journal: +# enabled: true +# directoryPerDB: false +# # where to write logging data. +# systemLog: +# destination: file +# quiet: false +# logAppend: true +# logRotate: reopen +# path: /opt/bitnami/mongodb/logs/mongodb.log +# verbosity: 0 +# # network interfaces +# net: +# port: 27017 +# unixDomainSocket: +# enabled: true +# pathPrefix: /opt/bitnami/mongodb/tmp +# ipv6: false +# bindIpAll: true +# # replica set options +# #replication: +# #replSetName: replicaset +# #enableMajorityReadConcern: true +# # process management options +# processManagement: +# fork: false +# pidFilePath: /opt/bitnami/mongodb/tmp/mongodb.pid +# # set parameter options +# setParameter: +# enableLocalhostAuthBypass: true +# # security options +# security: +# authorization: disabled +# #keyFile: /opt/bitnami/mongodb/conf/keyfile diff --git a/kubernetes/Charts/reddit/requirements.lock b/kubernetes/Charts/reddit/requirements.lock new file mode 100644 index 0000000..762581d --- /dev/null +++ b/kubernetes/Charts/reddit/requirements.lock @@ -0,0 +1,15 @@ +dependencies: +- name: ui + repository: file://../ui + version: 1.0.0 +- name: post + repository: file://../post + version: 1.0.0 +- name: comment + repository: file://../comment + version: 1.0.0 +- name: mongodb + repository: https://charts.helm.sh/stable + version: 7.8.10 +digest: sha256:584239acc525060347fded59f0e1d5680b494c064dceee80a13cb355f108d49f +generated: "2023-10-25T13:58:59.508751423+03:00" diff --git a/kubernetes/Charts/reddit/requirements.yaml b/kubernetes/Charts/reddit/requirements.yaml new file mode 100644 index 0000000..af8c7e1 --- /dev/null +++ b/kubernetes/Charts/reddit/requirements.yaml @@ -0,0 +1,18 @@ +--- +dependencies: + - name: ui + version: 1.0.0 + repository: "file://../ui" + + - name: post + version: 1.0.0 + repository: "file://../post" + + - name: comment + version: 1.0.0 + repository: "file://../comment" + + - name: mongodb + version: 7.8.10 + repository: https://charts.helm.sh/stable + alias: mongodb diff --git a/kubernetes/Charts/reddit/templates/externalnames.yaml b/kubernetes/Charts/reddit/templates/externalnames.yaml new file mode 100644 index 0000000..6175443 --- /dev/null +++ b/kubernetes/Charts/reddit/templates/externalnames.yaml @@ -0,0 +1,14 @@ +{{- $values := .Values -}} +{{- $release := .Release -}} +{{- range $key, $value := .Values.service.names }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ $value }} + labels: + app: reddit +spec: + type: "ExternalName" + externalName: {{ printf "%s-mongodb.dev.svc.cluster.local" $release.Name }} +{{- end}} diff --git a/kubernetes/Charts/reddit/values.yaml b/kubernetes/Charts/reddit/values.yaml new file mode 100644 index 0000000..9d8b2c7 --- /dev/null +++ b/kubernetes/Charts/reddit/values.yaml @@ -0,0 +1,19 @@ +--- +namespace: dev +service: + names: + - post-db + - comment-db +comment: + service: + externalPort: 9292 +post: + service: + externalPort: 5000 +databaseHost: +mongodb: + auth: + enabled: false + usePassword: false + mongodbSystemLogVerbosity: 2 + enableJournal: false diff --git a/kubernetes/Charts/ui/Chart.yaml b/kubernetes/Charts/ui/Chart.yaml new file mode 100644 index 0000000..661935e --- /dev/null +++ b/kubernetes/Charts/ui/Chart.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +appVersion: 1.0.0 +name: ui +version: 1.0.0 +description: OTUS reddit application UI +maintainers: + - name: Someone +icon: file://reddit_3983906.png diff --git a/kubernetes/Charts/ui/reddit_3983906.png b/kubernetes/Charts/ui/reddit_3983906.png new file mode 100644 index 0000000..ac21ca1 Binary files /dev/null and b/kubernetes/Charts/ui/reddit_3983906.png differ diff --git a/kubernetes/Charts/ui/templates/_helpers.tpl b/kubernetes/Charts/ui/templates/_helpers.tpl new file mode 100644 index 0000000..9b3d4c8 --- /dev/null +++ b/kubernetes/Charts/ui/templates/_helpers.tpl @@ -0,0 +1,3 @@ +{{- define "comment.fullname" -}} +{{- printf "%s-%s" .Release.Name .Chart.Name }} +{{- end -}} diff --git a/kubernetes/Charts/ui/templates/deployment.yaml b/kubernetes/Charts/ui/templates/deployment.yaml new file mode 100644 index 0000000..3acc4cd --- /dev/null +++ b/kubernetes/Charts/ui/templates/deployment.yaml @@ -0,0 +1,48 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} + namespace: {{ .Values.namespace }} + labels: + app: reddit + component: ui + release: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: reddit + component: ui + release: {{ .Release.Name }} + template: + metadata: + name: ui + namespace: {{ .Values.namespace }} + labels: + app: reddit + component: ui + release: {{ .Release.Name }} + spec: + containers: + - name: ui + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + ports: + - containerPort: {{ .Values.service.internalPort }} + resources: + limits: + memory: 256Mi + cpu: "1" + env: + - name: POST_SERVICE_HOST + value: {{ .Values.postHost | default (printf "%s-post" .Release.Name) }} + - name: POST_SERVICE_PORT + value: {{ .Values.postPort | default "5000" | quote }} + - name: COMMENT_SERVICE_HOST + value: {{ .Values.commentHost | default (printf "%s-comment" .Release.Name) }} + - name: COMMENT_SERVICE_PORT + value: {{ .Values.commentPort | default "9292" | quote }} + - name: ENV + valueFrom: + fieldRef: + fieldPath: metadata.namespace diff --git a/kubernetes/Charts/ui/templates/ingress.yaml b/kubernetes/Charts/ui/templates/ingress.yaml new file mode 100644 index 0000000..1e55a52 --- /dev/null +++ b/kubernetes/Charts/ui/templates/ingress.yaml @@ -0,0 +1,50 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-{{ .Chart.Name }} + namespace: {{ .Values.namespace }} + annotations: + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/rewrite-target: / + kubernetes.io/ingress.allow-http: "false" + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managemt-by: {{ .Release.Service }} +spec: + ingressClassName: nginx + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: / + pathType: Prefix + backend: + service: + name: ui + port: + number: 80 + {{- end }} + {{- end }} +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + {{- end }} + secretName: {{ .Values.ingress.secretName }} + +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.ingress.secretName }} + namespace: {{ .Values.namespace }} +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUU2RENDQTlDZ0F3SUJBZ0lTQTF6ZEthZGpoRWVlTktRZDVYWGpJZGNwTUEwR0NTcUdTSWIzRFFFQkN3VUEKTURJeEN6QUpCZ05WQkFZVEFsVlRNUll3RkFZRFZRUUtFdzFNWlhRbmN5QkZibU55ZVhCME1Rc3dDUVlEVlFRRApFd0pTTXpBZUZ3MHlNekV3TVRneE5EVTVOVGhhRncweU5EQXhNVFl4TkRVNU5UZGFNQmt4RnpBVkJnTlZCQU1NCkRpb3VhVzVtY21GdVpYUXVaR1YyTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEKelFkZlZkTXBweURSNUl4QmZFcVFrZW9uV3VRbk40MG9RRDNuTWJsSmxKWDBGYzBGY2tPczNkem11QUlNUmdZNAp1S3pPRE9STSs3ZHBWclJxblJJUjgwOC9ORVg5L01qclFZL29VUUFlay9SckwrMlV6amRiZnFTbGU1ZDJ6VHpkCjhMdnR3NjgweVpJbk5tSnA0cldXZml5c3NvVG01U3dKUExDcmdQWEFKRjk1QUx4dVBVTDNBS1dpZVJPbnFLR1gKK2Z0VlcyUnp5RERURzkwOXVzZ1Vrcmw4M2lVa01QRmI0NzB2SlRBRFBwTThMWEl5dFNEZHV3QklmUUhzUkpoLwplV0ZjQ2xrbWdoQjRlSWxmUWFqTXlMSUFMeGJvVDEzclZuaTI2Rm54amVWcnV1M0lrZmVMS011RW9FNERoaWJvCkxsZUNWMXc2TTZOREVreXVHMzJ3SHdJREFRQUJvNElDRHpDQ0Fnc3dEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CMEcKQTFVZEpRUVdNQlFHQ0NzR0FRVUZCd01CQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjBHQTFVZApEZ1FXQkJSaWdOVFFUQzVyWlRWM1JoRkhYQm9FcURNd0Z6QWZCZ05WSFNNRUdEQVdnQlFVTHJNWHQxaFd5NjVRCkNVRG1INitkaXhUQ3hqQlZCZ2dyQmdFRkJRY0JBUVJKTUVjd0lRWUlLd1lCQlFVSE1BR0dGV2gwZEhBNkx5OXkKTXk1dkxteGxibU55TG05eVp6QWlCZ2dyQmdFRkJRY3dBb1lXYUhSMGNEb3ZMM0l6TG1rdWJHVnVZM0l1YjNKbgpMekFaQmdOVkhSRUVFakFRZ2c0cUxtbHVabkpoYm1WMExtUmxkakFUQmdOVkhTQUVEREFLTUFnR0JtZUJEQUVDCkFUQ0NBUU1HQ2lzR0FRUUIxbmtDQkFJRWdmUUVnZkVBN3dCMUFEdFRkM1UrTGJtQVRvc3dXd2IrUUR0bjJFL0QKOU1lOUFBMHRjbS9oK3RRWEFBQUJpME9ENEpzQUFBUURBRVl3UkFJZ0VQMFdUeGhZMmNjUjRaQ2JTaUc4U21JagorczN1NGxKTUtQeHdoOTRFWElrQ0lDeFFiZmlkYUtmK0x3VGM0TmxSTWltVURQQmFsa0E1d1JQaTczTGFpMUZNCkFIWUFkditJUHdxMis1VlJ3bUhNOVllNk5MU2t6YnNwM0doQ0NwL21aMHhhT25RQUFBR0xRNFBnMUFBQUJBTUEKUnpCRkFpRUFuVmdoeFpkb3RNZjEvYWZXeTJqdWx1UlR3bFJSa0l2aEF6VnBzbHg1QTB3Q0lHYWpZN0FJeXNYeQpGaGdYOFBhU2E0MndQaWJ1c1F0Tks4a3liMkcrUXd0UU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQmZwVUVzCnRHazhxMGd1ZzZvVllZSmdtTk13S2E2MytaRzZNNlFtMWcxN3kwK3NKODB1dGMzaFlJVVo0Q2JTQVJhblFtc1IKdGxkSTJyRUJIVmEyTVpIOTh4WUJ4Z2FOc1FPRXZYNVJPcGRKaHNYWGhlWWp1bW1IT0NJWXBwd2JkRnJQUnFCWgpZbjJQTkFML29HekNrZlR0c2lGZG00Q3l3cTZjV1ViSjJqSFR1WWVOSEpHRlpHQ3VoTzk3eXFydFh0OTRETlNCCkg2VTAwKzRRc0tDbFdGUXNxa1ZYRmE3aXJDWDlrTjBYbnRhQ0ZDU2RsRjE3dXFxV280TkszdjlrWEgvSGpjMWoKbzBTbGZOZytmcVphdkVzYmFxVzZnYXdQTEFqdmduQ3RJQmRRNkNlS1BsUURjRmJ0a2d4cHBtUTQrUkRGMVlLWgpEV29NdEp1Z0dUN2U3QXpQCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KCg== + tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBelFkZlZkTXBweURSNUl4QmZFcVFrZW9uV3VRbk40MG9RRDNuTWJsSmxKWDBGYzBGCmNrT3MzZHptdUFJTVJnWTR1S3pPRE9STSs3ZHBWclJxblJJUjgwOC9ORVg5L01qclFZL29VUUFlay9SckwrMlUKempkYmZxU2xlNWQyelR6ZDhMdnR3NjgweVpJbk5tSnA0cldXZml5c3NvVG01U3dKUExDcmdQWEFKRjk1QUx4dQpQVUwzQUtXaWVST25xS0dYK2Z0VlcyUnp5RERURzkwOXVzZ1Vrcmw4M2lVa01QRmI0NzB2SlRBRFBwTThMWEl5CnRTRGR1d0JJZlFIc1JKaC9lV0ZjQ2xrbWdoQjRlSWxmUWFqTXlMSUFMeGJvVDEzclZuaTI2Rm54amVWcnV1M0kKa2ZlTEtNdUVvRTREaGlib0xsZUNWMXc2TTZOREVreXVHMzJ3SHdJREFRQUJBb0lCQUQvOEI0UU13TWlBQlJEYQp0b3NYNkJNcGJIdkFqUDZZcGxHYUgvOFVFSUwyNHpRMGhma1pacWJjakFJcjNYR3krbHVqempBV3hYR2UxUmh5CmVIMHBTUUhTSHVyczF1MWZOSkFDM2FEOXRRMCtiMzhIR1hQYnNjbU5qM2xKRlJISzU0WjcxNkZFbWVnNEhOV3IKazlqbEM2QzN4M04wNTJ2b3VMOUFjVjF2RkRZbEtFY0hpYStVY2tRRmxiaktwOTlnYjdaenlycWpHRmViNElpUAoydEN1NUhQbGZldG85ZjRCbHFwRUZCSHlIR3R1b3dFR1NiVmZjTVZPK0cyTVlNVHExYWxqaCtZQ2k2OXZuZ3pnCmJZQWhTNUczei9jSjlIcGExRTBBa3RteVl0M2FTSzBkOS9wVlgrVEVwQnNITmFzU3Nxa1U3Wjhhck0xb0JwTUMKbks4RHl4VUNnWUVBNzJ6L1h6aDM4SElYOE95b0s1RmdFWVl5dHZQT09qSTZORndjYmN1b0dybHRtRVJnNnduTApkdm5PWmU4ZmtzRkRUWFdMejZ0bnk4RUU0MlNPbG10UHFiYXplU2NBYXlPeDhMVFZBcVRHTUJRM0dmWmZHS1VXCitEUFpEdnlQbUUzY1plYi9DcitjeElOcktmbGNNblRuSE1kbjdRSmJnR3JGbGFBZDJtMDgxME1DZ1lFQTJ6ak8KWkVtNlRJQk1lTCt3czF2QUZONnlKN1BQWTdQSnhVYkt5aWczdk1ndUw4Y2ZaWnRWa3lmazUvQ013NmdwcnBMdgpKVTJXVWw5U1FqTExhWUpNTTNiNXBaeU5ZQW83MXhWanRoVU9MS1JRN0FHVkhVakVjcFBGV2lhWFo0ajdOMk92CnNYSHU1enpzVm1BaUVRWlVlQ2x0V3gydjlsSTNDcUIvd0hweVQvVUNnWUF4QzZId2JvL2JPSFFCRFdtUnF6RUQKeGZyRGtZUHdWZk9vWUNvT3I4WmEyeHRCTXRpcnJSRDU2VWhIaDBsdmRabUUxNHh4V1FwbEtjQUhtTVRBdVhEVApNakxub1g2cmM5OXlrSWlHQnh6MklsMzdPb1hXZFpNVCt3TCsxK3ZPWmp5OHZ5b0ZtS1RUZUp4T045K1VFbkI1CmE3dTFTR05ZRmdjdGxHUXBKM0ZzSXdLQmdEaDBKNHBpQml6Zk9WSTdJeGo5UHJqaEpJWGU0MEJzczBBdlc5ZTEKaGEwQzdBbjN3RmtkS0d0dDhaL2RMWkxSUW5LbmVoaGtJNXJ3MnpFYS9aRWRNZHhxL2gwczlLZFAyMXNuTWZkWQo4cjZDVGlpSXU4cS95MzhxR0w5L2dxdng5YWVzN3pqRisxem5Mb0dMM2huK1JGQnhjcXp0Tnp3NnJkdjV1d3hwCk8vamxBb0dCQU5icytLaXQ0SEU1WXUzQ0NwT3dpM0FTTGZ4TmpQenNPQ2RJdmhYeGVqV2dvdzRlL2R2aTYwV1cKaHB3eFBTVWNGdDgrRUZ2MUN1bzEvVVUyZEQ1TmI2WUxrcG1ReWRxOXJCam9lQlJpMHZsanNKdklpL3d4RDBIQgpQLy82SGVZaFJNendRdmhib0V5SXFkSUowS2kxS1hIUTk0VEsvT0RXTTFRbWV2RVZILzRyCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCgo= +type: kubernetes.io/tls +{{- end }} diff --git a/kubernetes/Charts/ui/templates/service.yaml b/kubernetes/Charts/ui/templates/service.yaml new file mode 100644 index 0000000..3fd9a94 --- /dev/null +++ b/kubernetes/Charts/ui/templates/service.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template "comment.fullname" . }} + namespace: {{ .Values.namespace }} + labels: + app: reddit + component: ui + release: {{ .Release.Name }} +spec: + type: NodePort + externalTrafficPolicy: Cluster + ports: + - port: {{ .Values.service.externalPort }} + nodePort: {{ .Values.service.nodePort }} + protocol: TCP + targetPort: {{ .Values.service.internalPort }} + selector: + app: reddit + component: ui + release: {{ .Release.Name }} diff --git a/kubernetes/Charts/ui/values.yaml b/kubernetes/Charts/ui/values.yaml new file mode 100644 index 0000000..898337d --- /dev/null +++ b/kubernetes/Charts/ui/values.yaml @@ -0,0 +1,27 @@ +--- +service: + internalPort: 9292 + externalPort: 9292 + nodePort: 30295 +image: + repository: 23f03013e37f/ui + tag: latest +ingress: + enabled: true + secretName: ui-ingress-tls + hosts: + - host: reddit.infranet.dev + paths: + - path: / + backend: + service: + name: ui + tls: + - hosts: + - reddit.infranet.dev +namespace: dev +replicaCount: 1 +postHost: +commentHost: +postPort: 5000 +commentPort: 9292 diff --git a/kubernetes/infra/terraform/managed/.gitignore b/kubernetes/infra/terraform/managed/.gitignore new file mode 100644 index 0000000..f935021 --- /dev/null +++ b/kubernetes/infra/terraform/managed/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/kubernetes/infra/terraform/managed/k8s.tf b/kubernetes/infra/terraform/managed/k8s.tf new file mode 100644 index 0000000..ef5caec --- /dev/null +++ b/kubernetes/infra/terraform/managed/k8s.tf @@ -0,0 +1,123 @@ +# yandex_kubernetes_cluster + +resource "yandex_kubernetes_cluster" "zonal_k8s_cluster" { + name = "my-cluster" + description = "my-cluster description" + network_id = yandex_vpc_network.k8s-mdb-network.id + + master { + version = "1.18" + zonal { + zone = yandex_vpc_subnet.k8s-mdb-subnet.zone + subnet_id = yandex_vpc_subnet.k8s-mdb-subnet.id + } + public_ip = true + } + + service_account_id = yandex_iam_service_account.this.id + node_service_account_id = yandex_iam_service_account.this.id + release_channel = "STABLE" + depends_on = [yandex_resourcemanager_folder_iam_binding.editor] +} + +# yandex_kubernetes_node_group + +resource "yandex_kubernetes_node_group" "k8s_node_group" { + cluster_id = yandex_kubernetes_cluster.zonal_k8s_cluster.id + name = "name" + description = "description" + version = "1.18" + + labels = { + "key" = "value" + } + + instance_template { + platform_id = "standard-v2" + + network_interface { + nat = true + subnet_ids = [yandex_vpc_subnet.k8s-mdb-subnet.id] + } + + resources { + memory = 2 + cores = 2 + } + + boot_disk { + type = "network-hdd" + size = 32 + } + + scheduling_policy { + preemptible = false + } + + metadata = { + ssh-keys = "ubuntu:${file("~/.ssh/id_rsa.pub")}" + } + + } + + scale_policy { + fixed_scale { + size = 1 + } + } + + allocation_policy { + location { + zone = "ru-central1-c" + } + } + + maintenance_policy { + auto_upgrade = true + auto_repair = true + + maintenance_window { + day = "monday" + start_time = "15:00" + duration = "3h" + } + + maintenance_window { + day = "friday" + start_time = "10:00" + duration = "4h30m" + } + } +} + + + +locals { + kubeconfig = < + export CI_HOSTNAME="gitlab.infranet.dev" + curl -X POST \ + -F token=$token \ + -F ref=master \ + http://$CI_HOSTNAME/api/v4/projects/1/trigger/pipeline + only: + - master + - main + +.auto_devops: &auto_devops | + [[ "$TRACE" ]] && set -x + export CI_REGISTRY="index.docker.io" + export CI_HOSTNAME="gitlab.infranet.dev" + export CI_APPLICATION_REPOSITORY=$CI_REGISTRY/$CI_PROJECT_PATH + export CI_APPLICATION_TAG=$CI_COMMIT_REF_SLUG + export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID} + export TILLER_NAMESPACE="kube-system" + export DOCKER_REGISTRY="$CI_REGISTRY" + export DOCKER_REGISTRY_PASS="$CI_REGISTRY_PASSWORD" + export DOCKER_REGISTRY_USER="$CI_REGISTRY_USER" + + function setup_docker() { + + if ! docker info &>/dev/null; then + if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then + export DOCKER_HOST='tcp://docker:2375' + fi + fi + + if [[ -n "$CI_REGISTRY_USER" ]] && [[ -n "$CI_REGISTRY_PASSWORD" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + echo -e "\n" + else + docker login + echo -e "\n" + fi + } + + function release() { + + echo "Updating docker tag images ..." + docker buildx imagetools create "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --tag "$CI_APPLICATION_REPOSITORY:$(cat VERSION)" + echo -e "\n" + } + + function build() { + + echo "Building Dockerfile-based application..." + echo `git show --format="%h" HEAD | head -1` > build_info.txt + echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt + + echo "Building and pushing to GitLab Container Registry..." + docker buildx build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --platform=linux/amd64 --push . + echo -e "\n" + } + + function deploy() { + + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + + if [[ "$track" != "stable" ]]; then + name="$name-$track" + fi + + echo "Clone deploy repository..." + git clone https://$CI_HOSTNAME/$CI_PROJECT_NAMESPACE/reddit-deploy.git + + echo "Download helm dependencies..." + helm dep update reddit-deploy/reddit + + echo "Deploy helm release $name to $KUBE_NAMESPACE" + helm upgrade --install \ + --wait \ + --set ui.ingress.host="$host" \ + --set $CI_PROJECT_NAME.image.tag=$CI_APPLICATION_TAG \ + --namespace="$KUBE_NAMESPACE" \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit-deploy/reddit/ + } + + function install_dependencies() { + + apk add -U openssl curl tar gzip bash ca-certificates git + wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk + apk add glibc-2.23-r3.apk + rm glibc-2.23-r3.apk + + curl https://storage.googleapis.com/pub/gsutil.tar.gz | tar -xz -C $HOME + export PATH=${PATH}:$HOME/gsutil + + curl https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz | tar zx + + mv linux-amd64/helm /usr/bin/helm + helm version --client + + curl -o /usr/bin/sync-repo.sh https://raw.githubusercontent.com/kubernetes/helm/master/scripts/sync-repo.sh + chmod a+x /usr/bin/sync-repo.sh + + curl -L -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + chmod +x /usr/bin/kubectl + kubectl version --client + } + + function ensure_namespace() { + kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE" + } + + function delete() { + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + helm delete "$name" -n review || true + } + +before_script: + - *auto_devops diff --git a/src/comment/VERSION b/src/comment/VERSION index bcab45a..81340c7 100644 --- a/src/comment/VERSION +++ b/src/comment/VERSION @@ -1 +1 @@ -0.0.3 +0.0.4 diff --git a/src/post-py/VERSION b/src/post-py/VERSION deleted file mode 100644 index 4e379d2..0000000 --- a/src/post-py/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.0.2 diff --git a/src/post/.gitlab-ci.yml b/src/post/.gitlab-ci.yml new file mode 100644 index 0000000..a36c0cc --- /dev/null +++ b/src/post/.gitlab-ci.yml @@ -0,0 +1,215 @@ +--- +image: alpine:latest + +stages: + - build + - test + - review + - release + - cleanup + +build: + stage: build + image: docker:git + services: + - docker:18.09.7-dind + script: + - setup_docker + - build + variables: + DOCKER_DRIVER: overlay2 + only: + - branches + tags: + - docker + +test: + stage: test + script: + - exit 0 + only: + - branches + tags: + - test + +review: + stage: review + script: + - install_dependencies + - ensure_namespace + - install_tiller + - deploy + variables: + KUBE_NAMESPACE: review + host: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + environment: + name: review/$CI_PROJECT_PATH/$CI_COMMIT_REF_NAME + url: http://$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + on_stop: stop_review + only: + refs: + - branches + kubernetes: active + except: + - master + - main + +release: + stage: release + image: docker + services: + - docker:dind + script: + - setup_docker + - release + variables: + DOCKER_TLS_CERTDIR: "" + only: + - master + - main + +stop_review: + stage: cleanup + variables: + GIT_STRATEGY: none + script: + - install_dependencies + - delete + environment: + name: review/$CI_PROJECT_PATH/$CI_COMMIT_REF_NAME + action: stop + when: manual + allow_failure: true + only: + refs: + - branches + kubernetes: active + except: + - master + - main + +deploy_production: + stage: deploy_production + before_script: + - apk add -U curl + script: + - > + export CI_HOSTNAME="gitlab.infranet.dev" + curl -X POST \ + -F token=$token \ + -F ref=master \ + http://$CI_HOSTNAME/api/v4/projects/1/trigger/pipeline + only: + - master + - main + +.auto_devops: &auto_devops | + [[ "$TRACE" ]] && set -x + export CI_REGISTRY="index.docker.io" + export CI_HOSTNAME="gitlab.infranet.dev" + export CI_APPLICATION_REPOSITORY=$CI_REGISTRY/$CI_PROJECT_PATH + export CI_APPLICATION_TAG=$CI_COMMIT_REF_SLUG + export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID} + export TILLER_NAMESPACE="kube-system" + export DOCKER_REGISTRY="$CI_REGISTRY" + export DOCKER_REGISTRY_PASS="$CI_REGISTRY_PASSWORD" + export DOCKER_REGISTRY_USER="$CI_REGISTRY_USER" + + function setup_docker() { + + if ! docker info &>/dev/null; then + if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then + export DOCKER_HOST='tcp://docker:2375' + fi + fi + + if [[ -n "$CI_REGISTRY_USER" ]] && [[ -n "$CI_REGISTRY_PASSWORD" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + echo -e "\n" + else + docker login + echo -e "\n" + fi + } + + function release() { + + echo "Updating docker tag images ..." + docker buildx imagetools create "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --tag "$CI_APPLICATION_REPOSITORY:$(cat VERSION)" + echo -e "\n" + } + + function build() { + + echo "Building Dockerfile-based application..." + echo `git show --format="%h" HEAD | head -1` > build_info.txt + echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt + + echo "Building and pushing to GitLab Container Registry..." + docker buildx build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --platform=linux/amd64 --push . + echo -e "\n" + } + + function deploy() { + + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + + if [[ "$track" != "stable" ]]; then + name="$name-$track" + fi + + echo "Clone deploy repository..." + git clone https://$CI_HOSTNAME/$CI_PROJECT_NAMESPACE/reddit-deploy.git + + echo "Download helm dependencies..." + helm dep update reddit-deploy/reddit + + echo "Deploy helm release $name to $KUBE_NAMESPACE" + helm upgrade --install \ + --wait \ + --set ui.ingress.host="$host" \ + --set $CI_PROJECT_NAME.image.tag=$CI_APPLICATION_TAG \ + --namespace="$KUBE_NAMESPACE" \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit-deploy/reddit/ + } + + function install_dependencies() { + + apk add -U openssl curl tar gzip bash ca-certificates git + wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk + apk add glibc-2.23-r3.apk + rm glibc-2.23-r3.apk + + curl https://storage.googleapis.com/pub/gsutil.tar.gz | tar -xz -C $HOME + export PATH=${PATH}:$HOME/gsutil + + curl https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz | tar zx + + mv linux-amd64/helm /usr/bin/helm + helm version --client + + curl -o /usr/bin/sync-repo.sh https://raw.githubusercontent.com/kubernetes/helm/master/scripts/sync-repo.sh + chmod a+x /usr/bin/sync-repo.sh + + curl -L -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + chmod +x /usr/bin/kubectl + kubectl version --client + } + + function ensure_namespace() { + kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE" + } + + function delete() { + track="${1-stable}" + name="$CI_ENVIRONMENT_SLUG" + helm delete "$name" -n review || true + } + +before_script: + - *auto_devops diff --git a/src/post-py/Dockerfile b/src/post/Dockerfile similarity index 100% rename from src/post-py/Dockerfile rename to src/post/Dockerfile diff --git a/src/post/VERSION b/src/post/VERSION new file mode 100644 index 0000000..81340c7 --- /dev/null +++ b/src/post/VERSION @@ -0,0 +1 @@ +0.0.4 diff --git a/src/post-py/docker_build.sh b/src/post/docker_build.sh similarity index 100% rename from src/post-py/docker_build.sh rename to src/post/docker_build.sh diff --git a/src/post-py/helpers.py b/src/post/helpers.py similarity index 100% rename from src/post-py/helpers.py rename to src/post/helpers.py diff --git a/src/post-py/post_app.py b/src/post/post_app.py similarity index 100% rename from src/post-py/post_app.py rename to src/post/post_app.py diff --git a/src/post-py/requirements.txt b/src/post/requirements.txt similarity index 100% rename from src/post-py/requirements.txt rename to src/post/requirements.txt diff --git a/src/ui/.gitlab-ci.yml b/src/ui/.gitlab-ci.yml new file mode 100644 index 0000000..195ca0a --- /dev/null +++ b/src/ui/.gitlab-ci.yml @@ -0,0 +1,200 @@ +--- +image: alpine:latest + +stages: + - build + - test + - review + - release + - cleanup + - deploy_production + +build: + stage: build + only: + - branches + image: docker:git + services: + - docker:18.09.7-dind + variables: + DOCKER_DRIVER: overlay2 + CI_REGISTRY: 'index.docker.io' + CI_APPLICATION_REPOSITORY: $CI_REGISTRY/$CI_PROJECT_PATH + CI_APPLICATION_TAG: $CI_COMMIT_REF_SLUG + CI_CONTAINER_NAME: ci_job_build_${CI_JOB_ID} + before_script: + - > + if [[ -n "$CI_REGISTRY_USER" ]] && [[ -n "$CI_REGISTRY_PASSWORD" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + echo -e "\n" + else + docker login + echo -e "\n" + fi + if ! docker info &>/dev/null; then + if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then + export DOCKER_HOST='tcp://docker:2375' + fi + fi + script: + - echo "Building and pushing to GitLab Container Registry..." + - echo `git show --format="%h" HEAD | head -1` > build_info.txt + - echo `git rev-parse --abbrev-ref HEAD` >> build_info.txt + - docker buildx build -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --platform=linux/amd64 --push . + +test: + stage: test + script: + - exit 0 + only: + - branches + +release: + stage: release + image: docker + services: + - docker:18.09.7-dind + variables: + CI_REGISTRY: 'index.docker.io' + CI_APPLICATION_REPOSITORY: $CI_REGISTRY/$CI_PROJECT_PATH + CI_APPLICATION_TAG: $CI_COMMIT_REF_SLUG + CI_CONTAINER_NAME: ci_job_build_${CI_JOB_ID} + before_script: + - > + if [[ -n "$CI_REGISTRY_USER" ]] && [[ -n "$CI_REGISTRY_PASSWORD" ]]; then + echo "Logging to GitLab Container Registry with CI credentials..." + docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + echo -e "\n" + else + docker login + echo -e "\n" + fi + if ! docker info &>/dev/null; then + if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then + export DOCKER_HOST='tcp://docker:2375' + fi + fi + script: + - echo "Updating docker images ..." + - docker buildx imagetools create "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" --tag "$CI_APPLICATION_REPOSITORY:$(cat VERSION)" + only: + - master + - main + +review: + stage: review + variables: + KUBE_NAMESPACE: review + host: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + TILLER_NAMESPACE: kube-system + CI_APPLICATION_TAG: $CI_COMMIT_REF_SLUG + name: $CI_ENVIRONMENT_SLUG + environment: + name: review/$CI_PROJECT_PATH/$CI_COMMIT_REF_NAME + url: http://$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG + on_stop: stop_review + only: + refs: + - branches + kubernetes: active + except: + - master + - main + before_script: + - apk add -U openssl curl tar gzip bash ca-certificates git + - wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + - wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk + - apk add glibc-2.23-r3.apk + - rm glibc-2.23-r3.apk + + - curl https://kubernetes-helm.storage.googleapis.com/helm-v2.13.1-linux-amd64.tar.gz | tar zx + + - mv linux-amd64/helm /usr/bin/ + - helm version --client + + - curl -L -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + - chmod +x /usr/bin/kubectl + - kubectl version --client + - kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE" + - echo "Checking Tiller..." + - helm init --client-only + - kubectl rollout status -n "$TILLER_NAMESPACE" -w "deployment/tiller-deploy" + - > + if ! helm version --debug; then + echo "Failed to init Tiller." + exit 1 + fi + + script: + - export track="${1-stable}" + - > + if [[ "$track" != "stable" ]]; then + name="$name-$track" + fi + - echo "Clone deploy repository..." + - git clone http://gitlab-gitlab/$CI_PROJECT_NAMESPACE/reddit-deploy.git + - echo "Download helm dependencies..." + - helm dep update reddit-deploy/reddit + - echo "Deploy helm release $name to $KUBE_NAMESPACE" + - echo "Upgrading existing release..." + - echo "helm upgrade --install --wait --set ui.ingress.host="$host" --set $CI_PROJECT_NAME.image.tag="$CI_APPLICATION_TAG" --namespace="$KUBE_NAMESPACE" --version="$CI_PIPELINE_ID-$CI_JOB_ID" "$name" reddit-deploy/reddit/" + - > + helm upgrade \ + --install \ + --wait \ + --set ui.ingress.host="$host" \ + --set $CI_PROJECT_NAME.image.tag="$CI_APPLICATION_TAG" \ + --namespace="$KUBE_NAMESPACE" \ + --version="$CI_PIPELINE_ID-$CI_JOB_ID" \ + "$name" \ + reddit-deploy/reddit/ + +stop_review: + stage: cleanup + variables: + GIT_STRATEGY: none + name: $CI_ENVIRONMENT_SLUG + environment: + name: review/$CI_PROJECT_PATH/$CI_COMMIT_REF_NAME + action: stop + when: manual + allow_failure: true + only: + refs: + - branches + kubernetes: active + except: + - master + - main + before_script: + - apk add -U openssl curl tar gzip bash ca-certificates git + - wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + - wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk + - apk add glibc-2.23-r3.apk + - curl https://storage.googleapis.com/pub/gsutil.tar.gz | tar -xz -C $HOME + - export PATH=${PATH}:$HOME/gsutil + - curl https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz | tar zx + - mv linux-amd64/helm /usr/bin/ + - helm version --client + - curl -o /usr/bin/sync-repo.sh https://raw.githubusercontent.com/kubernetes/helm/master/scripts/sync-repo.sh + - chmod a+x /usr/bin/sync-repo.sh + - curl -L -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + - chmod +x /usr/bin/kubectl + - kubectl version --client + script: + - helm delete "$name" --purge + +deploy_production: + stage: deploy_production + before_script: + - apk add -U curl + script: + - > + curl -X POST \ + -F token=$token \ + -F ref=master \ + http://gitlab-gitlab/api/v4/projects/1/trigger/pipeline + only: + - master + - main diff --git a/src/ui/VERSION b/src/ui/VERSION index 8acdd82..bbdeab6 100644 --- a/src/ui/VERSION +++ b/src/ui/VERSION @@ -1 +1 @@ -0.0.1 +0.0.5