Birds Eye View === ## Table of Contents [TOC] # Introduction Let's take a high-level look at the architecture of our infrastucture. ## Overview Our application is a `web application`. As every wep application it needs: * Facade for handling the incoming traffic coming from the users (`CDN`). * Computing middleware for processing the business logics (`GCP in our case`). * Some tools to maintain the development-related activities: * Source Control Manangement * CI/CD Engine * Docker Image Registry (in our case) ## Application ### Stack * Front-End * `HTML`, `CSS`, `JS` * `Angular 1` * Back-end * `PHP 7` * `Magento 2` * DBMS * `MySQL 5.6` * Cache * `Redis` ## Infrastructure ### Environments We consider `3` environments for different purposes: * `production` * `staging` * `develop` ### CloudFlare #### CDN We are using CDN to resolve the following goals: 1) Reduce the response timings of feeding the static content to the end users consistently over the different geo-locations and improve the `UX`. 2) Reduce computation load on our servers on the backend and improve the capacity of our infrastructure. #### DNS We manage all the DNS records over `CloudFlare`. ## Google Cloud Platform ### Production implementation #### Ingress * `Load balancer` So we are using the `L4 load balancer` to `route` and `balance` the `incoming traffic` over the `servers` on the `backend`. #### Processing * `Compute Engine` * `Function` Our backend is hosted on the `Compute Engine` `virtual machines`. `VMs` are joint into `instance groups`: * `general` * `admin` Groups are enabled for `auto-scaling` from min `1` to max `15` virtual machines. `Trigger` is the following: * `Target CPU usage` 90% * `LB capacity fraction` 90% `Machine type` is: * custom (2 vCPUs, 6 GB memory) #### Storage * `Persistent Disk` * `FileStore` * `Bucket` `Persistent Disks` are per `VM`. Single `FileStore` is mounted over all of the VMs, storing media files. `Bucket` is storing the media files as well. #### DBMS * `SQL` We are using `MySQL 5.6` engine. We have `3` instances (by one per environment). ### Kubernetes #### Introduction `Kubernetes` approach is running across all `environments`. #### Engine We use `Google Kubernetes Engine`. #### Clusters We host `2 GKE clusters`: * `dev-staging` * `prod` `dev-staging` cluster is serving and hosting all workloads related to `2` environments: `staging` and `development` `prod` cluster is serving `production` environment #### Ingress Controller We refused using `Google Load Balancer` and replaced it with `Nginx Ingress Controller` to `reduce the running costs` and simplify the `configuration`. #### Node Pools We are using `2` kinds of the `node pools`: * `persistent` * `preemtible` Both pools are enabled for `auto-scaling`: * `persistent`: `1-3` * `preemtible`: `1-15` #### Volumes We are using `2` major `volume classes`: * `NFS` * `Google Persistent Storage` (SSD) We use `NFS` when `multiple nodes read-write` mount type required. *(i.e. when we want to make multiple nodes hosted on different nodes being able to share single filesystem with RW permissions: i.e. media or generated static cache)* In all other cases we use `Google Persistent Storage` Approximate throughput of `NFS` is `~38 Mbytes/second` which is handling the current load well. We create dedicated `NFS` server per `share`. We do that to keep throughput at the highest possible rate for each `shared filesystem` *(i.e. when we need shared `media` for `production` environment we create `nfs-production-media` volume class; for shared `cache` for `production` environment - we create `nfs-production-cache` volume class)*. *(details: that makes sense since each `NFS volume class` is being created based on `NFS server`, so `1 NFS volume class` = `1 NFS server`)* #### Image Registry We are using `Docker Hub` as our `image registry` for `Docker containers`. #### Orchestration We are using both: * `GKE Dashboard` * `Rancher` for orchestrating the `K8s Cluster` ### CI/CD #### Engine We are using `Jenkins`. #### Integrations A couple of other tools are engaged into `CI/CD` process: * `Beanstalk` (SCM) * `Gitea` (SCM) * `Persistent Jenkins workers` `Jenkins workers` are being persistently hosted as `pods` in `k8s cluster`. Each `GKE cluster` has its own `master Jenkins` + `Jenkins worker(s)`: * `dev-staging` cluster has 1 `master Jenkins` and 2 `Jenkins workers`: 1 for `staging` environment and 1 for `develop` environment * `prod` cluster has 1 `master Jenkins` and 1 `Jenkins worker` Several words regarding the `CI/CD flow`. `Jenkins` is pulling codebase from `Beanstalk SCM` and then compiling Angular and Magento `static content` and uploading that to `Gitea SCM`. *(So, `Beanstalk` is storing the `codebase` and `Gitea` is storing the `static content`.)* After that `Jenkins` is triggering `static-content-sync` pod to pull updated `static content` from `Gitea`.