June 9, 2024, 8:34 p.m.
Due to the sheer cost of hosting a personal website on AWS EKS, I have migrated everything into a k3s cluster in the raspberry pi itself. Ah well. Currently a work in progress, and I will have a diagram and write-ups on this when it is worth showing. Thanks for reading!
Nov. 2, 2023, 9:21 p.m.
What you can see above, is the high-level architecture of this website, and how it is hosted. At a glance, it is a django application, hosted as a kubernetes deployment in an AWS Elastic Kubernetes Service (EKS) cluster. It utilises MySQL in an RDS instance for the database. Static images are stored in AWS S3. The infrastructure is all provisioned in terraform, through my Jenkins pipeline. I then have a raspberry pi server which acts as the Jenkins server. To support me being able to access this privately, I utilize bind9(DNS), nginx, wireguard(VPN). This allows me to access the jenkins website from anywhere around the world, privately via a VPN tunnel. This is accessed via johnjenkins.com, a private zone created in my bind9 server.
The cool thing about my infrastructure and the way I deploy it, is that I can delete most of it when I do not want to use it, and be able to re-create everything again, including the data/content in the website. I have 2 jenkins jobs defined in my pipeline, one for deploying the infra, and one for destroying the infra. This infrastructured is maintained through Terraform.
The terraform code can be divided into 2 workspaces/families. One is called john-production and the other is called static-production. john-production contains the resources that can be deleted and deployed whenever the website is needed. This will include the VPCs, subnets, security groups, RDS server, base helm releases (i.e for prometheus-grafana, cluster-autoscaler, metrics-server), ACM certificates, IAM roles etc. static-production then contains the resources that cannot be destroyed no matter what, to keep the main meat and potatoes of this infrastructure fully deployable and destructible at any time. This includes the cloudfront distribution, the S3 buckets containing the static maintenance page, terraform state files, mysqldump files and the static images for the website, and obviously the Route 53 hosted zone for johnmartincada.com
So on "maintenance" mode, only static-production is up. The route 53 record to johnmartincada.com is pointing to the cloudfront distribution, pointing to the static maintenance page bucket. On "production" mode, everything on john-production is deployed and the route 53 record will be pointing to the application load balancer, which points to my EKS cluster hosting the website.
To enter "production" mode, I can run my jenkins job to deploy the infrastructure. I can choose to run this manually, or I can also schedule it to run on a cron schedule (i.e everyday at 9am). The pipeline job will then deploy everything in john-production. Part of the pipeline will also be to perform a helm deployment of my django web application. The pipeline then retrieves the latest mysqldump file in my S3 bucket, to then deploy to the RDS server, ready to be serve data to my website.
To enter "maintenance" mode, I can run my jenkins job to destroy the infrastructure. This will destroy everything in john-production, and ultimately switch the Route 53 record for johnmartincada.com to the cloudfront distribution. It will also perform a mysqldump of the current content in my blog, and store it in an S3 bucket.
II would also like to highlight that if there is any error at any stage of either the deploy-infra or destroy-infra pipeline, I get notified via slack.
My EKS cluster also contains important applications for monitoring, visualization and autoscaling. These are namely applications like grafana, prometheus, metrics-server and cluster autoscaler. In fact, my grafana interface is publicly available. Sadly, I have still yet to set up graphs and charts in it, and make it be fully destructible and re-deployable.
Cluster-autoscaler is course used to scale the nodes in my EKS cluster based on the number of pods deployed. Metrics-server tracks metrics such as CPU/memory utilization of my pods, which can then utilize a Horizontal Pod Autoscaler to scale the number of pods in my Deployments.
The raspberry pi is my all-in-one management server. It mainly acts as the jenkins server, which allows me to automate the deployment and destruction of my infrastructure and applications. But I also have a critical requirement for it, which is to only be accessible by me, from anywhere around the world. This is where the VPN solution, wireguard comes in. Wireguard allows me to configure peering via tunnels between the raspberry pi and the devices I use to access Jenkins, which are devices like my personal PC, laptop and mobile phone. I can access it via johnjenkins.com, which is set up by using bind9 as the DNS server. NGINX then handles rate limiting, serving traffic to my Jenkins server, and also SSL/TLS certificate termination. I create a self-signed certificate, which are then installed to my personal devices.
Configuration management of these services in the raspberry pi are performed through Ansible.