Technical Documentation: antonputra/tutorials
âđïļ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
New Video - https://youtu.be/gwtoJTevxSA
Consulting
ðĻâðž Mentorship/On-the-Job Support/Consulting - Calendar or [email protected]
ð Check out recommendations from my previous clients.
Playlists
ð - Terraform Tutorial on AWS [Full Course]
ð - AWS EKS Kubernetes Tutorial [Full Course]
ð - Argo CD Tutorials
ð - Kubernetes Tutorials
ð - Benchmarks
Contents
ð - Lessons
Social
ðĨ - YouTube
ðž - LinkedIn
ð ïļ - Twitter/X
ðââïļ - Instagram
ðĻ - [email protected]
Overview (`lessons/006/README.md`)
Instructions to create VPC
- Create VPC
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=main}]'- Create public subnet
aws ec2 create-subnet \
--vpc-id <your-vpc-id> \
--availability-zone us-east-1a \
--cidr-block 10.0.0.0/24 \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public}]'- Create private subnet
aws ec2 create-subnet \
--vpc-id <your-vpc-id> \
--availability-zone us-east-1b \
--cidr-block 10.0.1.0/24 \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private}]'- Allocate IP for NAT Gateway
aws ec2 allocate-address- Create NAT Gateway
aws ec2 create-nat-gateway \
--subnet-id <your-subnet-id> \
--allocation-id <your-eipalloc-id> \
--tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=my-nat-gateway}]'- Create internet gateway
aws ec2 create-internet-gateway- Cretae public route table
aws ec2 create-route-table \
--vpc-id <your-vpc-id> \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=public-route}]'- Attach internet gateway
aws ec2 attach-internet-gateway \
--internet-gateway-id <your-igw-id> \
--vpc-id vpc-0724881ef1256d0ee- Create default route to Internet
aws ec2 create-route \
--route-table-id <your-rtb-id> \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id <your-igw-id>- Cretae private route table
aws ec2 create-route-table \
--vpc-id <your-vpc-id> \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=private-route}]'- Create default route to NAT gateway
aws ec2 create-route \
--route-table-id <your-rtb-id> \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id <your-nat-id>- Change routing table for public subnet
aws ec2 associate-route-table \
--route-table-id <your-rtb-id> \
--subnet-id <your-subnet->- Change routing table for private subnet
aws ec2 associate-route-table \
--route-table-id <your-rtb-id> \
--subnet-id <your-subnet-id>- Updaye public subnet to assign public IPs
aws ec2 modify-subnet-attribute \
--subnet-id <your-subnet-id> \
--map-public-ip-on-launchOverview (`lessons/014/README.md`)
Terraform Ansible Integration | Terraform Ansible AWS Example?
Overview (`lessons/020/README.md`)
Terraform Import Existing Resources AWS
Initialize Terraform
$ terraform initAdd VPC Resource and Run Terraform Plan
$ terraform planImport AWS VPC using vpc id
$ terraform import aws_vpc.main vpc-<id>Add Subnets to Terraform
Import Subnets using ids
$ terraform import aws_subnet.public subnet-<id>
$ terraform import aws_subnet.private subnet-<id>Add IGW to Terraform
Import IGW using id
$ terraform import aws_internet_gateway.igw igw-<id>Add EIP to Terraform
Import EIP using Public IP
$ terraform import aws_eip.nat_eip <ip-address>Add NAT Gateway to Terraform
Import NAT Gateway using id
$ terraform import aws_nat_gateway.nat nat-<id>Add Routes and Route Associating to Terraform
Import to Terraform State
$ terraform import aws_route_table.public rtb-<id>
$ terraform import aws_route_table.private rtb-<id>
$ terraform import aws_route_table_association.public subnet-<id>/rtb-<id>
$ terraform import aws_route_table_association.private subnet-<id>/rtb-<id>Add Security Group and EC2 to Terraform
Import to Terraform State
$ terraform import aws_security_group.nginx sg-<id>
$ terraform import aws_instance.nginx i-<id>Add Route53 Hosted Zone and A Record to Terraform
Import to Terraform State
$ terraform import aws_route53_zone.devops <id>
$ terraform import aws_route53_record.nginx <id>_api.devopsbyexample.io_AOverview (`lessons/021/README.md`)
Helm 3 Tutorial (Create Helm 3 Hello World Example)
Create Kubernetes Cluster (Optional)
$ eksctl create cluster -f lessons/021/eksctl-cluster.yaml
$ kubectl get svc -n defaultInitialize a Helm Chart Repository
$ helm repo add stable https://charts.helm.sh/stableList Available Charts
$ helm search repo stableCreate Hello-world Example
$ helm create hello-wolrdInstall Hello-worls Helm Chart
$ kubectl create namespace dev
$ helm install -f hello-wolrd/values.yaml -n dev hello-wolrd ./hello-wolrdLearn About hello-world Release
$ helm ls -n devGet Pods, Services
$ kubectl get pods -n dev
$ kubectl get services -n devClean Up
# Uninstall a Release
$ helm uninstall -n dev hello-wolrd
# remove stable repo
$ helm repo remove stableOverview (`lessons/022/README.md`)
Helm 3 Dependencies Condition (3 Ways to Add Dependency)
Option one
$ helm create app
$ helm create databaseAdd Dependency to your app chart
# app/Chart.yaml
dependencies:
- name: database
version: 0.1.0
condition: database.enabled
repository: file://../databaseAdd YAML key/value to enable Helm chart
# app/values.yaml
database:
enabled: trueBuild Helm dependencies and install chart
$ helm dependency update
$ helm install -f values.yaml web .Option two
$ helm create app
$ helm create databaseAdd Dependency to your app chart
# app/Chart.yaml
dependencies:
- name: database
version: 0.1.0
enabled: true
repository: file://../databaseBuild Helm dependencies and install chart
$ helm dependency update
$ helm install -f values.yaml web .Option Three
$ helm create app
$ helm create databaseAdd Dependency to your app chart
# app/Chart.yaml
dependencies:
- name: database
version: 0.1.0
repository: file://../database
tags:
- databaseAdd YAML key/value to enable Helm chart
# app/values.yaml
tags:
database: trueBuild Helm dependencies and install chart
$ helm dependency update
$ helm install -f values.yaml web .Overview (`lessons/038/README.md`)
Terraform EKS Cluster Creation
YouTube Playlist
Overview (`lessons/041/README.md`)
Kubernetes Persistent Volumes NFS (AWS | EKS | EFS Storage Class | EFS Provisioner | ReadWriteMany)
Create EKS Cluster
$ eksctl create cluster -f cluster.yamlDelete EKS Cluster
$ eksctl delete cluster -f cluster.yamlOverview (`lessons/042/README.md`)
How to Create Kubernetes Secrets?
Create EKS Cluster
$ eksctl create cluster -f cluster.yamlDelete EKS Cluster
$ eksctl delete cluster -f cluster.yamlOverview (`lessons/043/README.md`)
How to Create Kubernetes Secrets?
Create EKS Cluster
$ eksctl create cluster -f cluster.yamlDelete EKS Cluster
$ eksctl delete cluster -f cluster.yamlOverview (`lessons/044/README.md`)
How to Create Kubernetes Secrets?
Create EKS Cluster
$ eksctl create cluster -f eks.yamlDelete EKS Cluster
$ eksctl delete cluster -f eks.yamlOverview (`lessons/045/README.md`)
How Do I Get All the Pods on a NODE? (Filter Kubernetes Pods by Node NAME | Node LABEL)
Create EKS Cluster
$ eksctl create cluster -f eks.yamlDelete EKS Cluster
$ eksctl delete cluster -f eks.yamlDeploy All Kuberentes Objects
kubectl apply -f k8sOverview (`lessons/046/README.md`)
How to Deploy NodeJS App to Kubernetes?
Create EKS Cluster
$ eksctl create cluster -f eks.yamlDelete EKS Cluster
$ eksctl delete cluster -f eks.yamlOverview (`lessons/047/README.md`)
How to Create Lambda Container Images?
Overview (`lessons/048/README.md`)
How to Test Lambda Container Images?
Overview (`lessons/049/README.md`)
How to Install Prometheus on Kubernetes Cluster?
Overview (`lessons/050/README.md`)
How to Install MongoDB on Kubernetes?
Overview (`lessons/051/README.md`)
How to Deploy React App to GitHub Pages?
Overview (`lessons/052/README.md`)
How to Configure GitHub Pages Custom Domain?
Overview (`lessons/053/README.md`)
How to Run Terraform from CircleCI?
Overview (`lessons/054/README.md`)
How to Generate Self-Signed Certificate?
Overview (`lessons/055/README.md`)
How to Run Nginx Docker Container?
Overview (`lessons/056/README.md`)
AWS Session Manager Step by Step Tutorial: SSH | Port-Forward | Audit | Logs
Overview (`lessons/057/README.md`)
How to Get Letsencrypt WILDCARD Certificate?
Overview (`lessons/058/README.md`)
Introduction to Amazon S3 Object Lambda
Overview (`lessons/060/README.md`)
Flux v2 Kubernetes Tutorial: Building CI/CD Pipeline for Kubernetes
Overview (`lessons/061/README.md`)
Kubernetes Continuous Delivery with Flux v2: AWS | EKS | ECR | CD Pipeline | Fluxcd | GitOps
Overview (`lessons/062/README.md`)
HashiCorp Packer AWS Tutorial: AMI Example | Builder | Provisioner | EC2 | Tags | SSH | Debug
Overview (`lessons/063/README.md`)
Terraform Blue Green Deployment & Terraform Canary Deployment ðĩðĢðĒ AWS | ALB | EC2
Overview (`lessons/064/README.md`)
How to Create GKE Cluster from SCRATCH? ðĪŦ (Shared VPC | Host and Service Projects | Best Practices)
Overview (`lessons/065/README.md`)
IAM Roles for Service Accounts & Pods: (IRSA EKS | IAM OIDC Provider | AWS EKS | Kubernetes)
Overview (`lessons/066/README.md`)
Kubernetes Network Policy Examples & Tutorial (Calico Isolate Namespaces, Pods & IP Blocks)
Create EKS cluster
eksctl create cluster -f eks.yamlInstalling Calico on Amazon EKS
Apply the Calico manifests
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-operator.yaml
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/calico-crs.yamlWatch the calico-system DaemonSets
kubectl get daemonset calico-node -n calico-systemCreate Services
Check Connection
kubectl exec service-a-<id> -n staging -- nc -vz service-b 8080
kubectl get pods --show-labels
kubectl exec service-a-<id> -n staging -- nc -vz service-c.production 8080Overview (`lessons/067/README.md`)
How To Install and Use PyTorch
Create a virtual environment (Optionally)
$ python3 -m venv .venvActivate virtual environment
$ source .venv/bin/activateInstall PyTorch pip package (macOS)
$ pip install torch torchvisionOn Linux and Windows, use the following commands for a CPU-only build
$ pip install torch==1.7.1+cpu torchvision==0.8.2+cpu -f https://download.pytorch.org/whl/torch_stable.htmlCreate a JSON file to convert neural network output to a human-readable class name
Create Python script to classify an image
Run classifier
# python classify.py dog.jpgOverview (`lessons/068/README.md`)
Git Submodules Explained: Tutorial | Example | Guide | GitHub | Add | Update
Create Two Repos
# create module-a with README
# create module-b with README
git clone [email protected]:antonputra/module-a.git
cd module-a
git submodule add [email protected]:antonputra/module-b.git
git status
git diff --cached --submodule
git commit -am 'Add module-b'
git push origin mainCloning a Project with Submodules
cd ..
rm -rf module-a
git clone [email protected]:antonputra/module-a.git
cd module-a
code .
git submodule update --init --recursive
cd ..
rm -rf module-a
Optionally: git clone --recurse-submodules [email protected]:antonputra/module-a.git
cd module-a
code .Pulling in Upstream Changes from the Submodule Remote
# Add "update v2" to README.md in module-b and commit "Update README.md v2"
cd module-b
git fetch
git merge origin/main
cd ..
git diff
git diff --submodule
git config --global diff.submodule log
git diff
# Optionally: easier way
# Make another change in module-b "Update README.md v3"
git submodule update --remote
git status
git config status.submodulesummary 1
git status
git commit -am 'Update Submodule'
git push origin mainWorking on a Submodule
code .
cd module-b
git checkout main
git pull
# add main.py print('Hello')
git add main.py
git commit -m 'Add main.py'
cd ..
git submodule update --remote --merge
# (make change in module-b "Update README.md v4")
git submodule update --remote --rebase
git commit -am 'Update Submodule'Publishing Submodule Changes
git diff
git push --recurse-submodules=check
git config push.recurseSubmodules check
git push
git push --recurse-submodules=on-demandOverview (`lessons/069/README.md`)
How to Create GKE Cluster Using TERRAFORM from Scratch?
Set Up Default Credentials
gcloud auth application-default loginOverview (`lessons/070/README.md`)
EKS Cluster Auto Scaling (Kubernetes Autoscaler | EKS Cluster Autoscaler | EKS Autoscale Nodes)
Overview (`lessons/071/README.md`)
Kubernetes Horizontal Pod Autoscaler
Overview (`lessons/072/README.md`)
How to Install Prometheus on Kubernetes Cluster?
Steps
0. Create EKS Cluster (Optional)
eksctl create cluster -f eks.yaml1. Deploy Prometheus Stack Helm Chart
- Download
prometheus-values.yamlfile for Prometheus from here - Update following variables
etcd: false # line 37
kubeScheduler: false # line 53
adminPassword: test123 # line 628
kubeControllerManager: # line 910
enabled: false
kubeEtcd: # line 1057
enabled: false
kubeScheduler: # line 1122
enabled: false
serviceMonitorSelector: # line 2050
matchLabels:
prometheus: devops
commonLabels: # line 27
prometheus: devopshelm repo add prometheus-community \
https://prometheus-community.github.io/helm-chartshelm repo updatehelm search repo kube-prometheus-stack --max-col-width 23helm install monitoring \
prometheus-community/kube-prometheus-stack \
--values prometheus-values.yaml \
--version 16.10.0 \
--namespace monitoring \
--create-namespacekubectl get pods -n monitoringkubectl get svc -n monitoringkubectl port-forward \
svc/monitoring-kube-prometheus-prometheus 9090 \
-n monitoring- Go to
http://localhost:9090and selecttargets
kubectl get cm kube-proxy-config -n kube-system -o yamlkubectl -n kube-system get cm kube-proxy-config -o yaml |sed 's/metricsBindAddress: 127.0.0.1:10249/metricsBindAddress: 0.0.0.0:10249/' | kubectl apply -f -watch -n 1 -t kubectl get pods -n kube-systemkubectl -n kube-system patch ds kube-proxy -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"updateTime\":\"`date +'%s'`\"}}}}}"Go back to
http://localhost:9090undertargetsandalertsWait 20-30 min to get more data in Prometheus
kubectl port-forward \
svc/monitoring-grafana 3000:80 \
-n monitoring- Open following dashboards
- Kubernetes / Compute Resources / Cluster
- Kubernetes / Kubelet
- USE Method / Cluster
2. Deploy Postgres Helm Chart
helm repo add bitnami https://charts.bitnami.com/bitnamihelm repo updatehelm search repo postgresql --max-col-width 23Download
postgres-values.yamlfile for Postgres from hereUpdate following variables
postgresqlDatabase: test # line 155
metrics: # line 734
enabled: true
serviceMonitor: # line 744
enabled: false
additionalLabels:
prometheus: devopshelm install postgres \
bitnami/postgresql \
--values postgres-values.yaml \
--version 10.5.0 \
--namespace db \
--create-namespacekubectl get pods -n db3. Create Service Monitor for Postgres
- Create
service-monitor.yaml
---
# https://github.com/prometheus-operator/prometheus-operator
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: postgres-postgresql
namespace: db
labels:
<labels>
spec:
endpoints:
- port: <port>
interval: 60s
scrapeTimeout: 30s
namespaceSelector:
matchNames:
- <namespace>
selector:
matchLabels:
<labels>kubectl get prometheus \
monitoring-kube-prometheus-prometheus \
-o yaml \
-n monitoringkubectl get endpoints -n dbkubectl get services -n dbkubectl describe endpoints postgres-postgresql-metrics -n dbkubectl apply -f service-monitor.yaml- Import Grafana dashboard
9628
Clean Up
helm repo remove prometheus-community bitnami
helm uninstall monitoring -n monitoring
helm uninstall postgres -n db
kubectl delete crd alertmanagerconfigs.monitoring.coreos.com
kubectl delete crd alertmanagers.monitoring.coreos.com
kubectl delete crd podmonitors.monitoring.coreos.com
kubectl delete crd probes.monitoring.coreos.com
kubectl delete crd prometheuses.monitoring.coreos.com
kubectl delete crd prometheusrules.monitoring.coreos.com
kubectl delete crd servicemonitors.monitoring.coreos.com
kubectl delete crd thanosrulers.monitoring.coreos.comeksctl delete cluster -f eks.yamlOverview (`lessons/073/README.md`)
Horizontal Pod Autoscaler CUSTOM METRICS & PROMETHEUS
Steps
1. Run Sample App Locally
- Go over express app
0-express - Open 2 tabs and run it locally
node 0-express/server.jsServer listening at http://0.0.0.0:8081
curl localhost:8081/fibonacci \
-H "Content-Type: application/json" \
-d '{"number": 10}'Fibonacci number is 89!
curl localhost:8081/fibonacci \
-H "Content-Type: application/json" \
-d '{"number": 20}'Fibonacci number is 10946!
curl localhost:8081/metrics# HELP http_requests_total Total number of http requests
# TYPE http_requests_total counter
# http_requests_total{method="POST"} 2
2. Create EKS Cluster Using eksctl
- Open
eks.yamlfile and create EKS cluster
eksctl create cluster -f eks.yaml2021-06-26 18:22:20 [âđ] nodegroup "general" has 1 node(s)
2021-06-26 18:22:20 [âđ] node "ip-192-168-11-151.ec2.internal" is ready
2021-06-26 18:24:23 [âđ] kubectl command should work with "/Users/antonputra/.kube/config", try 'kubectl get nodes'
2021-06-26 18:24:23 [â] EKS cluster "my-cluster-v4" in "us-east-1" region is ready
3. Create Namespaces in Kubernetes
- Create
demoandmonitoringnamespaces
kubectl apply -f 1-namespacesnamespace/demo created
namespace/monitoring created
4. Create Prometheus Operator CRDs
- Create Prometheus CRDs and RBAC
kubectl apply -f 2-prometheus-operator-crdclusterrole.rbac.authorization.k8s.io/prometheus-crd-view created
clusterrole.rbac.authorization.k8s.io/prometheus-crd-edit created
customresourcedefinition.apiextensions.k8s.io/alertmanagerconfigs.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/alertmanagers.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/podmonitors.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/probes.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheuses.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheusrules.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/servicemonitors.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/thanosrulers.monitoring.coreos.com created
5. Deploy Prometheus Operator on Kubernetes
kubectl apply -f 3-prometheus-operatorserviceaccount/prometheus-operator created
clusterrole.rbac.authorization.k8s.io/prometheus-operator created
clusterrolebinding.rbac.authorization.k8s.io/prometheus-operator created
deployment.apps/prometheus-operator created
service/prometheus-operator created
kubectl get pods -n monitoringNAME READY STATUS RESTARTS AGE
prometheus-operator-585f487768-745xp 1/1 Running 0 11m
kubectl logs -l app.kubernetes.io/name=prometheus-operator -f -n monitoringlevel=info ts=2021-06-27T01:44:00.696399754Z caller=operator.go:355 component=prometheusoperator msg="successfully synced all caches"
level=info ts=2021-06-27T01:44:00.702534377Z caller=operator.go:267 component=thanosoperator msg="successfully synced all caches"
level=info ts=2021-06-27T01:44:00.79632208Z caller=operator.go:287 component=alertmanageroperator msg="successfully synced all caches"
6. Deploy Prometheus on Kubernetes
kubectl apply -f 4-prometheusserviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
prometheus.monitoring.coreos.com/prometheus created
kubectl get pods -n monitoringNAME READY STATUS RESTARTS AGE
prometheus-operator-585f487768-745xp 1/1 Running 0 11m
prometheus-prometheus-0 2/2 Running 1 5m17s
kubectl logs -l app.kubernetes.io/instance=prometheus -f -n monitoringlevel=info ts=2021-06-27T01:50:04.190Z caller=main.go:995 msg="Completed loading of configuration file" filename=/etc/prometheus/config_out/prometheus.env.yaml totalDuration=507.082Âĩs remote_storage=3.213Âĩs web_handler=388ns query_engine=1.274Âĩs scrape=74.372Âĩs scrape_sd=3.853Âĩs notify=996ns notify_sd=1.554Âĩs rules=34.528Âĩs
7. Deploy Sample Express App
- Open Prometheus Target page
kubectl port-forward svc/prometheus-operated 9090 -n monitoringForwarding from 127.0.0.1:9090 -> 9090
Forwarding from [::1]:9090 -> 9090
Go to http://localhost:9090
Use
httpto query Prometheus (empty)Create following files
5-demo/0-deployment.yaml5-demo/1-service.yaml5-demo/2-service-monitor.yaml5-demo/3-hpa-http-requests.yaml
kubectl apply -f 5-demodeployment.apps/express created
service/express created
servicemonitor.monitoring.coreos.com/express created
horizontalpodautoscaler.autoscaling/http created
- Go back to
http://localhost:9090target page - Port forward express app
kubectl port-forward svc/express 8081 -n demo- Use curl to hit fibonacci enpont twice
curl localhost:8081/fibonacci \
-H "Content-Type: application/json" \
-d '{"number": 10}'Fibonacci number is 89!
- Use
httpto query Prometheus - Get hpa
kubectl get hpa -n demo/500m
kubectl describe hpa http -n demokubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jqError from server (NotFound): the server could not find the requested resource
Deploy Prometheus Adapter
- Create following files
6-prometheus-adapter/0-rbac.yaml6-prometheus-adapter/1-deployment.yaml6-prometheus-adapter/2-service.yaml6-prometheus-adapter/3-apiservice.yaml6-prometheus-adapter/4-configmap.yaml(only 1 rule)
- Run PromQL
http_requests_total{namespace!="",pod!=""}query - Deploy Prometheus Adapter
kubectl apply -f 6-prometheus-adapter- Open 3 tabs
watch -n 1 -t kubectl get hpa -n demowatch -n 1 -t kubectl get pods -n demokubectl describe hpa http -n demoWarning FailedGetPodsMetric 26s (x13 over 3m30s) horizontal-pod-autoscaler unable to get metric http_requests_per_second: unable to fetch metrics from custom metrics API: no custom metrics API (custom.metrics.k8s.io) registered
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jqError from server (NotFound): the server could not find the requested resource
- Deploy Prometheus adapter
configmap last one
kubectl apply -f 6-prometheus-adapterkubectl get apiservicekubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jqhelm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm search repo prometheus-adapter --max-col-width 23helm install custom-metrics prometheus-community/prometheus-adapter \
--namespace monitoring \
--version 2.14.2 \
--values 8-prometheus-adapter-helm/1-values.yamlClean Up
helm repo remove prometheus-community
eksctl delete cluster -f eks.yamlOverview (`lessons/074/README.md`)
Vertical Pod Autoscaling
1. Create EKS Cluster Using eksctl
- Create EKS cluster
eksctl create cluster -f eks.yaml- Verify that you can connect to the cluster
kubectl get svc2. Deploy Metrics server (YAML)
- List api services
kubectl get apiservice- Use grep and filter by
metrics
kubectl get apiservice | grep metrics- Use kubectl to get metrics
kubectl top pods -n kube-system- Access metrics API
kubectl get --raw /apis/metrics.k8s.io/v1beta1 | jqCreate deployemnt files under
0-metrics-serverdirectory0-service-account.yaml1-cluster-roles.yaml2-role-binding.yaml3-cluster-role-bindings.yaml4-service.yaml5-deployment.yaml6-api-service.yaml
Apply created filies
kubectl apply -f 0-metrics-server- Verify deployment
kubectl get pods -n kube-system- List api services
kubectl get apiservice- List services in
kube-systemnamespace
kubectl get svc -n kube-system- Access metrics API
kubectl get --raw /apis/metrics.k8s.io/v1beta1 | jq- Get metrics for pods using raw command\
kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods | jq- Use kubectl to get metrics
kubectl top pods -n kube-system3. Deploy Metrics server (HELM)
- Find default values for metrics-server chart
- Create
values.yamlfile - Add
bitnamihelm repo
helm repo add bitnami https://charts.bitnami.com/bitnami- Search for
metrics-server
helm search repo metrics-server --max-col-width 23- Install
metrics-serverHelm Chart
helm install metrics bitnami/metrics-server \
--namespace kube-system \
--version 5.8.13 \
--values values.yaml3. Install Vertical Pod Autoscaler
Open Autoscaler GitHub page
Clone VPA repo
git clone https://github.com/kubernetes/autoscaler.git- Change directory
cd autoscaler/vertical-pod-autoscaler- Preview installation
./hack/vpa-process-yamls.sh print- Install VPA
./hack/vpa-up.sh- Tear down VPA
./hack/vpa-down.sh4. Upgrade LibreSSL on Mac/OS X
- Get OpenSSL version
openssl version- Upgrade LibreSSL with Homebew
brew install libressl- Get OpenSSL version
openssl version- Check instalation path of OpenSSL
which openssl- Check version of the LibreSSL installed with Homebew
/opt/homebrew/opt/libressl/bin/openssl version- Try to create a soft link
sudo ln -s /opt/homebrew/opt/libressl/bin/openssl /usr/bin/openssl- Try to rename openssl
sudo mv /usr/bin/openssl /usr/bin/openssl-old- Create soft link to /usr/local/bin/ which should take precedence on your path over /usr/bin.
sudo ln -s /opt/homebrew/opt/libressl/bin/openssl /usr/local/bin/openssl- Open new tab and run version command
openssl version5. Install Vertical Pod Autoscaler (Continue)
- Open new tab and change directory
cd Developer/autoscaler/vertical-pod-autoscaler- Install VPA
./hack/vpa-up.sh6. Demo
Create deployment files under
1-demodirectory0-deployment.yaml1-vpa.yamlOpen two tabs
watch -n 1 -t kubectl top pods- Deploy sample app
kubectl apply -f 1-demo- Let's run 5-10 min and in a new tab get VPA
kubectl get vpa- Describe VPA
kubectl describe vpa hamster-vpa- Update deployment and reapply
kubectl apply -f 1-demo/0-deployment.yamlClean Up
- Delete EKS cluster
eksctl delete cluster -f eks.yaml
sudo rm /usr/local/bin/openssl
brew remove libressl
helm repo remove bitnami
rm -rf Developer/autoscalerOverview (`lessons/075/README.md`)
AWS SAM
1. Install AWS SAM CLI
macOS
brew tap aws/tapbrew install aws-sam-clisam --version2. Setting up AWS credentials
- Create
adminuser for AWS SAM - Download Credentials
- Configure AWS Cli
aws configure3. Create AWS Lambda API Gateway Node JS
- Initialize SAM project
sam init- Go over project structure
- Remove generated project
rm -rf sam- Created
samdirectory - Create
apidirectory - Change directory to
api
cd sam/api- Run
npm init
npm init- Create a
function.jsfile - Create
template.yamlfile
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS SAM Tutorial
Globals:
Function:
MemorySize: 128
Resources:
APIFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs14.x
Handler: function.lambdaHandler
CodeUri: api/
Timeout: 3
Events:
Hello:
Type: Api
Properties:
Path: /hello
Method: POST
RestApiId:
Ref: HelloAPI
HelloAPI:
Type: AWS::Serverless::Api
Properties:
StageName: staging
OpenApiVersion: 3.0.3
Outputs:
APIFunction:
Description: "Api Lambda Function ARN"
Value: !GetAtt APIFunction.Arn
Tutorials:
Description: "YouTube Channel"
Value: https://www.youtube.com/antonputra4. Test Lambda Locally SAM
- Change directory to
sam - Run
sam build - Create
api/event.json sam local invoke APIFunction -e api/event.json- Run
sam deploy --guided - Go to S3
- Get URL from console
curl -d '{"name": "Anton"}' https://jh7n04hpaj.execute-api.us-east-1.amazonaws.com/staging/hello5. Test Lambda from Console
- Create new
TestNameevent
{
"body": "{\"name\": \"Anton\"}"
}Create AWS Lambda S3 File Upload NodeJS
- Create
s3folder - Run
npm initfroms3folder - Create
function.jsfile - Install aws-sdk
npm i aws-sdk - Add S3Function, ExampleBucket and Outputs
- Run
sam build - Run
sam deploy - Go to S3
- Fo to lambda
- Upload README to S3
- Go to CloudWatch
Create AWS Lambda SNS Python Example
- Create
snsfolder - Create
function.py,requirements.txt, andDockerfile - Add
SNSFunctionandOutputs - Create SNS topic
sns-topic-for-lambda - Run
sam build - Run
sam deploy --guided - Create ECR repo
sns - Publish message
- Check CloudWatch logs
Clen Up
- Delete SNS topic
sns-topic-for-lambda - Delete ECR repository
sns - Delete all cloud watch log groups
- Delete IAM User
admin - Delete AWS CLI
sam
brew remove aws-sam-cli- Delete all S3 buckets
- Delete all CloudFormation Templates
Overview (`lessons/076/README.md`)
How to Build Slack Bot? (Node JS | AWS Lambda & DynamoDB - AWS Serverless | New Slack Apps)
1. Create Slack Bot App
- Go to https://api.slack.com/apps
- Select create an app
From scratch - Give it a name
WALL-Eand select your namespace - Scroll down to
App CredentialsaDisplay Information - Give it a short description
Compactor robot - Upload app icon and change color
- Go to
Event Subscriptions
2. Create IAM User with Full Access
- Create
adminuser and place it inAdmingroup - Download credentials
- Configure AWS profile with
aws configure - Test profile with
aws sts get-caller-identity
3. Create IAM Role for AWS Lambda
- Create IAM Policy
AWSLambdaSlackAccess
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:us-east-1:424432388155:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:424432388155:log-group:/aws/lambda/wall-e:*"
},
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:us-east-1:424432388155:table/todos"
}
]
}- Create
wall-e-rolefor Lambda and attachAWSLambdaSlackAccessIAM Policy - Optionally:
aws iam get-role --role-name wall-e-role
4. Create AWS Lambda Function
- Create
wall-edirectory - Run
npm initfromwall-edirectory - Create
app.js
exports.handler = (event, context, callback) => {
const response = { 'message': `Hello World!` };
callback(null, response);
};- Create
Dockerfile
FROM public.ecr.aws/lambda/nodejs:14
COPY *.js package*.json /var/task/
RUN npm install
CMD [ "app.handler" ]- Create ECR Repository
wall-e
aws ecr get-login-password --region us-east-1 \
| docker login \
--username AWS \
--password-stdin 424432388155.dkr.ecr.us-east-1.amazonaws.comdocker build \
-t 424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.0 .docker push \
424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.05. Deploy Lambda Using Container Image
- Select
Containerimagefrom the console - Call function
wall-e - Use an existing role
wall-e-role - Select
wall-eECR image
6. Create API Gateway for Lambda Function
- Create HTTP API
slack - Test Lambda with curl
curl -X POST https://uss0o5l3h3.execute-api.us-east-1.amazonaws.com/production/wall-e- Check logs
- Use this URL for Slack
7. Use AWS Lambda for Slack Event Subscriptions
- Create
tests/event.jsonfile
{
"version": "2.0",
"routeKey": "ANY /bot",
"rawPath": "/default/bot",
"rawQueryString": "",
"headers": {
"accept": "*/*",
"accept-encoding": "gzip,deflate",
"content-length": "129",
"content-type": "application/json",
"host": "4o68t2fwke.execute-api.us-east-1.amazonaws.com",
"user-agent": "Slackbot 1.0 (+https://api.slack.com/robots)",
"x-amzn-trace-id": "Root=1-60f9f121-0e6b301236f5d57d46fbd0e1",
"x-forwarded-for": "3.94.92.68",
"x-forwarded-port": "443",
"x-forwarded-proto": "https",
"x-slack-request-timestamp": "1626992929",
"x-slack-signature": "v0=d12f7cb55add77074248241c2ec2d3c9fe4611e7879a965c92315edd8f0ec0cf"
},
"requestContext": {
"accountId": "424432388155",
"apiId": "4o68t2fwke",
"domainName": "4o68t2fwke.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "4o68t2fwke",
"http": {
"method": "POST",
"path": "/default/bot",
"protocol": "HTTP/1.1",
"sourceIp": "3.94.92.68",
"userAgent": "Slackbot 1.0 (+https://api.slack.com/robots)"
},
"requestId": "C5KdVjAlIAMEPzg=",
"routeKey": "ANY /bot",
"stage": "default",
"time": "22/Jul/2021:22:28:49 +0000",
"timeEpoch": 1626992929961
},
"body": "{\"token\":\"UdG3UFNsPGoobvRzK5F2oIqe\",\"challenge\":\"6KaNtlamllYYaLZ7qhHxZbzyYut62TlDKu2wAZXp4rZlInRbcDTH\",\"type\":\"url_verification\"}",
"isBase64Encoded": false
}- Update body of the function
exports.handler = (event, context, callback) => {
const body = JSON.parse(event.body);
switch (body.type) {
case "url_verification": callback(null, body.challenge); break;
default: callback(null);
}
};- Package and upload docker image
docker build \
-t 424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.1 .docker push \
424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.1- Redeploy AWS Lambda using v0.1.1 image tag
- Go back to Slack and click
Retry
8. Verify Slack Requests Using Signing Secret
- Optionally: Create verify.js
- Run with
node verify.js - Compare string with event.json
- Create
security.js
const crypto = require("crypto");
exports.validateSlackRequest = (event, signingSecret) => {
const requestBody = event["body"];
const headers = makeLower(event.headers);
const timestamp = headers["x-slack-request-timestamp"];
const slackSignature = headers["x-slack-signature"];
const baseString = 'v0:' + timestamp + ':' + requestBody;
const hmac = crypto.createHmac("sha256", signingSecret)
.update(baseString)
.digest("hex");
const computedSlackSignature = "v0=" + hmac;
const isValid = computedSlackSignature === slackSignature;
return isValid;
};
const makeLower = (headers) => {
let lowerCaseHeaders = {}
for (const key in headers) {
if (headers.hasOwnProperty(key)) {
lowerCaseHeaders[key.toLowerCase()] = headers[key].toLowerCase()
}
}
return lowerCaseHeaders
}- Update
app.js
const security = require('./security');
const signingSecret = process.env.SLACK_SIGNING_SECRET;
exports.handler = (event, context, callback) => {
if (security.validateSlackRequest(event, signingSecret)) {
const body = JSON.parse(event.body);
switch (body.type) {
case "url_verification": callback(null, body.challenge); break;
default: callback(null);
}
}
else callback("verification failed");
};- Add Environment variable to Lambda
SLACK_SIGNING_SECRET(next video aws lambda secrets manager integration) - Create unit test
security.test.js - Install Jest
npm i --save-dev jest - Update test command to
jest - Run tests
npm test
9. Process Slack Messages
- Create private Slack channel
earth - Subscribe to following events
- message.groups
- message.channels
- Install app to workspace
- Optionally: set
Always Show My Bot as OnlinefromApp Home - Go to
OAuth & Permissionsto check automatically added permissions - Add
event_callbackevent
case "event_callback": processRequest(body, callback); break;- Create
processRequestmethod
const processRequest = (body, callback) => {
switch (body.event.type) {
case "message": processMessages(body, callback); break;
default: callback(null);
}
};- Create
processMessagesmethod inapp.js
const processMessages = (body, callback) => {
console.debug("message:", body.event.text);
callback(null);
};- Update
Dockerfileto usenpm ci --production - Package and upload docker image
docker build \
-t 424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.2 .docker push \
424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.2- Update AWS Lambda to use
v0.1.2tag - Optionally: Delete all log streams
- Inviite
WALL-Etoearthchannel - Post
hellomessage - Open CloudWatch logs
10. Save Messages Using AWS Lambda to DynamoDB
- Create
todosDynamoDB table withuuidprimary key - Replace
message.groupsandmessage.channelswithapp_mentionevent - Add
chat:writeinstead ofmessage.* - Reinstall app
- Install
aws-sdk,uuid, andaxios
npm i aws-sdk uuid axios- Create
db.js
const AWS = require('aws-sdk');
const { v4: uuidv4 } = require('uuid');
AWS.config.update({ region: 'us-east-1' });
const ddb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });
exports.saveItem = (item, callback) => {
const params = {
TableName: 'todos',
Item: {
'uuid': { S: uuidv4() },
'item': { S: item }
}
};
ddb.putItem(params, (error, data) => {
if (error) {
callback(new Error(error));
} else {
callback(null);
}
});
};- Add
app_mentioncase
case "app_mention": processAppMention(body, callback); break;- Import
axiosanddb
const axios = require('axios');
const db = require('./db');- Create
tokenvariable and add it to Lambda
const token = process.env.SLACK_BOT_TOKEN;- Create
processAppMentionmethod
const processAppMention = (body, callback) => {
const item = body.event.text.split(":").pop().trim();
db.saveItem(item, (error, result) => {
if (error !== null) {
callback(error)
} else {
const message = {
channel: body.event.channel,
text: `Item: \`${item}\` is saved to *Amazon DynamoDB*!`
};
axios({
method: 'post',
url: 'https://slack.com/api/chat.postMessage',
headers: { 'Content-Type': 'application/json; charset=utf-8', 'Authorization': `Bearer ${token}` },
data: message
})
.then((response) => {
callback(null);
})
.catch((error) => {
callback("failed to process app_mention");
});
}
});
};- Package and upload docker image
docker build \
-t 424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.3 .docker push \
424432388155.dkr.ecr.us-east-1.amazonaws.com/wall-e:v0.1.3- Redeploy Lambda using
v0.1.3tag - Post
@WALL-E todo: Save the Planet!message - Open DynamoDB
todostable
Clean Up
- Delete ECR
wall-e - Delete IAM User
admin - Delete IAM Role
wall-e-role - Delete IAM Policy
AWSLambdaSlackAccess - Delete DynamoDB table
todos - Delete Lambda
wall-e - Delete CloudWatch log groups
/aws/lambda/wall-e - Delete API Gateway
slack - Delete docker images
docker rmi -f $(docker images -a -q) - Delete slack bot
wall-e - Delete
earthSlack channel
Links
- Basic app setup
- Signing secrets
- Features - Choosing between HTTP APIs and REST APIs
- HTTP API Price
- Validating Library for Node JS
- Verify Requst from Slack
- chat.postMessage
Overview (`lessons/077/README.md`)
AWS Lambda Secrets Manager Example: 2 Ways to Grant Access | Resource Permissions
1. Create Secret in AWS Secrets Manager
- Create
SLACK_BOT_TOKENsecret with random value - Give it a name
prod/slack-bot/token-v3
2. Create IAM User with Full Access
- Create
adminuser and place it inAdminIAM group - Configure aws cli
aws configure
3. Create IAM Role for AWS Lambda
- Create IAM Policy
AWSLambdaSecretsAccess
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:us-east-1:424432388155:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:424432388155:log-group:/aws/lambda/secret-access:*"
}
]
}- Create
secret-access-roleIAM Role
4. Create AWS Lambda Function
- Create
secret-accessfolder - Run
npm init - Install aws-sdk
npm i aws-sdk - Create
app.js - Create
Dockerfile
5. Deploy Lambda Using Container Image
- Create ECR
secret-access - Build and push image
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS \
--password-stdin 424432388155.dkr.ecr.us-east-1.amazonaws.comdocker build -t 424432388155.dkr.ecr.us-east-1.amazonaws.com/secret-access:v0.1.0 .docker push 424432388155.dkr.ecr.us-east-1.amazonaws.com/secret-access:v0.1.0- Deploy lambda
- Test with curl (fail)
6. Grant Access for IAM Role
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-east-1:424432388155:secret:prod/slack-bot/token-v3-<id>"
}- Remove access
7. Create Resource-based Policy for Secret
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:sts::424432388155:assumed-role/secret-access-role/secret-access"
},
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-east-1:424432388155:secret:prod/slack-bot/token-v3-<id>"
}
]
}Clean UP
- Delete
adminIAM user - Delete ECR
secret-access - Delete
secret-access-roleIAM Role - Delete
AWSLambdaSecretsAccessIAM Policy - Delete
secret-accesslambda - Delete
secret-access-APIAPI gateway - Delete CloudWatch logs
- Delete secrets
Links
Resource-based policies
AWS JSON policy elements: Principal
Overview (`lessons/078/README.md`)
How to Secure Nginx with Lets Encrypt on Ubuntu 20.04 with Certbot?
1. Create EC2 Instance in AWS Ubuntu 20.04 LTS
- Create EC2 instance
Ubuntu 20.04t3.micro(cpu cores > 1)public subnetenable public ip
- Create Security Group
nginx- open port
80, and443
- open port
- Create
devopskep pair - Update permissions on
devopskey pair- Keys need to be only readable by you
chmod 400 devops.pem
- Keys need to be only readable by you
2. Install Nginx Ubuntu 20.04 LTS
- SSH to the Ubuntu server
ssh -i devops.pem [email protected]- Update Ubuntu packages
sudo apt update- Check version of
nginxto be installed
apt policy nginx- Check current versions of
nginxhere - Add
nginxdeb repository
sudo vi /etc/apt/sources.list.d/nginx.listdeb https://nginx.org/packages/ubuntu/ focal nginx
deb-src https://nginx.org/packages/ubuntu/ focal nginxdeb lines are relative to binary packages, that you can install with apt.
deb-src lines are relative to source packages (as downloaded by apt-get source $package) and next compiled.
Source packages are needed only if you want to compile some package yourself, or inspect the source code for a bug. Ordinary users don't need to include such repositories.
- Update Ubuntu packages
sudo apt update- Add GPG key
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ABF5BD827BD9BF62- Update Ubuntu packages
sudo apt update- Check version of
nginxto be installed
apt policy nginx- Install
nginx
sudo apt install nginx=1.20.1-1~focal- Start
nginx
sudo systemctl start nginx- Enable
nginx
sudo systemctl enable nginx- Check
nginxstatus
sudo systemctl status nginx(Can't open PID file /run/nginx.pid (yet?) after start: Operation not permitted)
- Go to browser
3. Nginx Setup Server Block
- Check the main
nginxconfig
cat /etc/nginx/nginx.conf- Check default
nginxconfig
cat /etc/nginx/conf.d/default.conf- Create folder for our website
sudo mkdir -p /var/www/devopsbyexample.io/html- Update ownership
sudo chown -R $USER:$USER /var/www/devopsbyexample.io/html- Update permissions
sudo chmod -R 755 /var/www/devopsbyexample.io- Create a web page
vi /var/www/devopsbyexample.io/html/index.html
<html>
<head>
<title>Welcome to devopsbyexample.io!</title>
</head>
<body>
<h1>Success! The devopsbyexample.io server block is working!</h1>
</body>
</html>- Create
sites-availabledirectory
sudo mkdir /etc/nginx/sites-available/- Create
sites-enableddirectory
sudo mkdir /etc/nginx/sites-enabled- Create
nginxserver block
sudo vi /etc/nginx/sites-available/devopsbyexample.ioserver {
listen 80;
root /var/www/devopsbyexample.io/html;
index index.html;
server_name devopsbyexample.io www.devopsbyexample.io;
location / {
try_files $uri $uri/ =404;
}
}- Add include statement
sudo vi /etc/nginx/nginx.confinclude /etc/nginx/sites-enabled/*;- Create a symlink
sudo ln -s /etc/nginx/sites-available/devopsbyexample.io /etc/nginx/sites-enabled/- Test
nginxconfig
sudo nginx -t- Reload
nginxconfig
sudo nginx -s reload- Create A records
- Check DNS (if you are using cloudflare enable full strict by ssl/tsl>overview>full_strict)
dig devopsbyexample.io
dig www.devopsbyexample.io4. Install Certbot on Ubuntu 20.04 LTS
snap version- If you don't have it
apt policy snapdandapt install snapd - Ensure that your version of snapd is up to date
sudo snap install core; sudo snap refresh core- Remove certbot-auto and any Certbot OS packages
sudo apt-get remove certbot- Install Certbot
sudo snap install --classic certbot- Prepare the Certbot command
sudo ln -s /snap/bin/certbot /usr/bin/certbot- Check certbot version
sudo certbot --version5. Secure Nginx with Lets Encrypt on Ubuntu 20.04 LTS
- Test certbot
sudo certbot --nginx --test-cert- Open nginx block
cat /etc/nginx/sites-available/devopsbyexample.io- Go to browser https://devopsbyexample.io
- Issue real certificate
sudo certbot --nginx- Go to browser https://devopsbyexample.io
- Go to browser https://www.devopsbyexample.io
- Test renewal
sudo certbot renew --dry-run- Check systemctl times
systemctl list-timersClean Up
- Delete EC2 instance
- Delete security group
nginx - Delete key pair
devops - Remove A records
Links
- Ubuntu Releases
- Nginx Download
- Nginx Installation
- Failed to read PID from file /run/nginx.pid
- Sites-Available/Sites-Enabled Not Here?
- Certbot
- Installing snap on Ubuntu
Overview (`lessons/079/README.md`)
AWS EKS & Secrets Manager (File & Env | Kubernetes | Secrets Store CSI Driver | K8s)
1. Create IAM User with Full Access
- Create
adminuser and place it inAdminIAM group - Configure aws cli
aws configure
2. Create Secret in AWS Secrets Manager
- Select
Other type of secrets - Create key:
MY_API_TOKENand random value:7623fd72g3d - Give it a name
prod/service/token - Open created secret to check ARN
3. Create EKS Cluster Using eksctl
- Create
eks.yamlconfig file - Create EKS cluster
eksctl create cluster -f eks.yaml- Check connection to EKS cluster
kubectl get svc4. Create IAM OIDC Provider for EKS
- Copy
OpenID Connect provider URL - Create Identety Provider - select
OpenID Connect - Enter
sts.amazonaws.comfor Audience
5. Create IAM Policy to Read Secrets
- Create
APITokenReadAccessIAM policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "<secret-arn>"
}
]
}6. Create IAM Role for a Kubernetes Service Account
- Click
Web identityand select Identity provider that we created - Select
APITokenReadAccessIAM Policy - Give it a name
api-token-access - Update trust relationships on the role
- Update
aud->sub - Update
sts.amazonaws.com->system:serviceaccount:production:nginx
7. Associate an IAM Role with Kubernetes Service Account
- Create
nginx/namespace.yaml - Create
nginx/service-account.yaml - Apply kubernetes objects
kubectl apply -f nginx- Get Kubernetes namespaces
kubectl get ns- Describe service account
kubectl get sa -n production8. Install the Kubernetes Secrets Store CSI Driver
- Create
secrets-store-csi-driver/0-secretproviderclasses-crd.yaml - Create
secrets-store-csi-driver/1-secretproviderclasspodstatuses-crd.yaml - Apply CRDs
kubectl apply -f secrets-store-csi-driver- Create
secrets-store-csi-driver/2-service-account.yaml - Create
secrets-store-csi-driver/3-cluster-role.yaml - Create
secrets-store-csi-driver/4-cluster-role-binding.yaml - Create
secrets-store-csi-driver/5-daemonset.yaml - Create
secrets-store-csi-driver/6-csi-driver.yaml - Apply Kubernetes objects
kubectl apply -f secrets-store-csi-driver- Check the logs
kubectl logs -n kube-system -f -l app=secrets-store-csi-driver- (Optionally) use helm chart
helm repo add secrets-store-csi-driver https://raw.githubusercontent.com/kubernetes-sigs/secrets-store-csi-driver/master/charts- (Optionally) install helm chart
helm -n kube-system install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver9. Install AWS Secrets & Configuration Provider (ASCP)
- Create
aws-provider-installer/0-service-account.yaml - Create
aws-provider-installer/1-cluster-role.yaml - Create
aws-provider-installer/2-cluster-role-binding.yaml - Create
aws-provider-installer/3-daemonset.yaml - Apply aws-provider-installer
kubectl apply -f aws-provider-installer- Check logs
kubectl logs -n kube-system -f -l app=csi-secrets-store-provider-aws10. Create Secret Provider Class
- Create
nginx/2-secret-provider-class.yaml
kubectl apply -f nginx11. Demo
- Create nginx
3-deployment.yaml - Open 2 tabs
kubectl logs -n kube-system -f -l app=secrets-store-csi-driverkubectl apply -f nginxkubectl -n production exec -it nginx-<id> -- bash- Print mounted file
cat /mnt/api-token/secret-token- Print environment variables with a secret
echo $API_TOKENBonus
Clean Up
- Delete EKS Cluster
eksctl delete cluster -f eks.yaml- Delete IAM Policy
APITokenReadAccess - Delete IAM Role
api-token-access - Delete IAM User
admin
Links
- secrets-store-csi-driver
- AWS Secrets & Configuration Provider (ASCP)
- Using Secrets Manager secrets in Amazon Elastic Kubernetes Service
- How to use AWS Secrets & Configuration Provider with your Kubernetes Secrets Store CSI driver
- IAM role configuration
- kubectx
Overview (`lessons/080/README.md`)
How to Get Letsencrypt Wildcard Certificate (Using Letsencrypt Nginx DNS Challenge)
Prerequisites
- Ubuntu 20.04
- Nginx
- Certbot
- Watch this before: How to Secure Nginx with Lets Encrypt on Ubuntu 20.04 with Certbot? - https://youtu.be/R5d-hN9UtpU
1. Get Letsencrypt Wildcard Certificate
- Request wildcard certificate
sudo certbot certonly --manual --preferred-challenges dns --test-cert- Enter
*.devopsbyexample.io - Create
TXTrecord with following value:_acme-challenge.devopsbyexample.io.-<generated value> - Anycast
- Verify with dig -t txt
dig -t txt +short _acme-challenge.devopsbyexample.io- Press enter
Certificate is saved at: /etc/letsencrypt/live/devopsbyexample.io/fullchain.pem
Key is saved at: /etc/letsencrypt/live/devopsbyexample.io/privkey.pem
- Decode certificate
sudo openssl x509 -in /etc/letsencrypt/live/devopsbyexample.io/fullchain.pem -text -noout2. Set Up Nginx SSL Wildcard Server Block
- Create folder for website
sudo mkdir -p /usr/share/devopsbyexample.io/html- Update ownership
sudo chown -R $USER:$USER /usr/share/devopsbyexample.io/html- Update permissions
sudo chmod -R 755 /usr/share/devopsbyexample.io- Create
index.htmlpage
vi /usr/share/devopsbyexample.io/html/index.html<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Wildcard server block is working!</h1>
</body>
</html>- Create nginx server block
sudo vi /etc/nginx/conf.d/devopsbyexample.io.confserver {
listen 80;
root /usr/share/devopsbyexample.io/html;
index index.html;
server_name *.devopsbyexample.io;
location / {
try_files $uri $uri/ =404;
}
}- Test nginx config
sudo nginx -t- Reload nginx config
sudo nginx -s reload- Create
api.devopsbyexample.ioandhello.devopsbyexample.ioA records - Try
https://api.devopsbyexample.io/ - Verify with dig
dig +short api.devopsbyexample.iodig +short hello.devopsbyexample.io- Check in the browser http://api.devopsbyexample.io
3. Secure Nginx with Lets Encrypt Certificate
- Update nginx config
sudo vi /etc/nginx/conf.d/devopsbyexample.io.confserver {
listen 80;
server_name *devopsbyexample.io;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/devopsbyexample.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/devopsbyexample.io/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}- Test nginx config
sudo nginx -t- Fix
server_name - Reload nginx config
sudo nginx -s reload- Go to
https://api.devopsbyexample.io/andhttps://hello.devopsbyexample.io/
Links
Overview (`lessons/081/README.md`)
How to Setup Auto-Renew for Letsencrypt WILDCARD Certificate with DNS challenge?
Allocate Elastic IP to EC2 Instance
- Add tag
Name=server
Create Ubuntu EC2 Instance
- Launch
Ubuntu 20.04EC2 instance - Create
serverSG - Create
devopskey pair - Associate Elastic IP address with EC2
- Update
devopskey pair permissions
chmod 400 devops.pem- SSH to the EC2 instance
ssh -i devops.pem ubuntu@<public-ip>Install acme-dns Server
- Create folder for
acme-dnsand change directory
sudo mkdir /opt/acme-dns
cd !$- Download and extract tar with
acme-dnsfrom GitHub
sudo curl -L -o acme-dns.tar.gz \
https://github.com/joohoi/acme-dns/releases/download/v0.8/acme-dns_0.8_linux_amd64.tar.gz
sudo tar -zxf acme-dns.tar.gz- List files
ls- Clean Up
sudo rm acme-dns.tar.gz- Create soft link
sudo ln -s \
/opt/acme-dns/acme-dns /usr/local/bin/acme-dns- Create a minimal
acme-dnsuser
sudo adduser \
--system \
--gecos "acme-dns Service" \
--disabled-password \
--group \
--home /var/lib/acme-dns \
acme-dns- Update default acme-dns config compare with IP from the AWS console. CAn't bind to the public address need to use private one.
ip addrsudo mkdir -p /etc/acme-dns
sudo mv /opt/acme-dns/config.cfg /etc/acme-dns/
sudo vim /etc/acme-dns/config.cfg- Move the systemd service and reload
cat acme-dns.service
sudo mv \
acme-dns.service /etc/systemd/system/acme-dns.service
sudo systemctl daemon-reload- Start and enable acme-dns server
sudo systemctl enable acme-dns.service
sudo systemctl start acme-dns.service- Check acme-dns for posible errors
sudo systemctl status acme-dns.service- Use journalctl to debug in case of errors
journalctl --unit acme-dns --no-pager --follow- Create A record for your domain
auth.devopsbyexample.io IN A <public-ip>- Create NS record for auth.devopsbyexample.io pointing to auth.devopsbyexample.io. This means, that auth.devopsbyexample.io is responsible for any *.auth.devopsbyexample.io records
auth.devopsbyexample.io IN NS auth.devopsbyexample.io- Test acme-dns server (Split the screen)
journalctl -u acme-dns --no-pager --follow- From local host try to resolve random DNS record
dig api.devopsbyexample.io
dig api.auth.devopsbyexample.io
dig 7gvhsbvf.auth.devopsbyexample.ioInstall acme-dns-client
sudo mkdir /opt/acme-dns-client
cd !$
sudo curl -L \
-o acme-dns-client.tar.gz \
https://github.com/acme-dns/acme-dns-client/releases/download/v0.2/acme-dns-client_0.2_linux_amd64.tar.gz
sudo tar -zxf acme-dns-client.tar.gz
ls
sudo rm acme-dns-client.tar.gz
sudo ln -s \
/opt/acme-dns-client/acme-dns-client /usr/local/bin/acme-dns-clientInstall Certbot
cd
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotGet Letsencrypt Wildcard Certificate
- Create a new acme-dns account for your domain and set it up
sudo acme-dns-client register \
-d devopsbyexample.io -s http://localhost:8080dig _acme-challenge.devopsbyexample.io- Get wildcard certificate
sudo certbot certonly \
--manual \
--test-cert \
--preferred-challenges dns \
--manual-auth-hook 'acme-dns-client' \
-d *.devopsbyexample.iosudo openssl x509 -text -noout \
-in /etc/letsencrypt/live/devopsbyexample.io/fullchain.pem- Renew certificate (test)
sudo certbot renew \
--manual \
--test-cert \
--dry-run \
--preferred-challenges dns \
--manual-auth-hook 'acme-dns-client'dig -t txt _acme-challenge.devopsbyexample.ioSetup Auto-Renew for Letsencrypt WILDCARD Certificate
- Setup cronjob
sudo crontab -e
0 */12 * * * certbot renew --manual --test-cert --preferred-challenges dns --manual-auth-hook 'acme-dns-client'Clen Up
- Terminate EC2 Instance
- Delete
devopskey pair - Delete
serverSG - Release
serverElastic IP - Delete DNS records from google domains
Links
Overview (`lessons/082/README.md`)
NGINX Ingress Controller for Kubernetes Tutorial
You can find tutorial here.
Overview (`lessons/083/README.md`)
Cert Manager Kubernetes Tutorial (Let's Encrypt & Nginx Ingress & ACME | 5 Examples | YAML & HELM)
Prerequisites
Deploy Prometheus on Kubernetes
kubectl apply -f prometheus/0-crd
kubectl apply -f prometheus/1-prometheus-operator
kubectl apply -f prometheus/2-prometheus
kubectl get pods -n monitoringDeploy Cert Manager Helm & YAML
Review default helm values
Add the Jetstack Helm repository
helm repo add jetstack \
https://charts.jetstack.io- Update your local Helm chart repository cache
helm repo updateCreate
cert-manager-values.yamlfile to override default variablesSearch for cert-manager
helm search repo cert-manager- Generate YAML files
helm template cert-083 jetstack/cert-manager \
--namespace cert-manager \
--version v1.5.3 \
--values cert-manager-values.yaml \
--output-dir helm-generated-yaml- Create
cert-managernamespace
kubectl apply -f cert-manager-ns.yaml- Install cert-manager with Helm
helm install cert-083 jetstack/cert-manager \
--namespace cert-manager \
--version v1.5.3 \
--values cert-manager-values.yaml- Get Helm releases
helm list -n cert-manager- Get pods
kubectl get pods -n cert-managerPort forward Prometheus
kubectl port-forward svc/prometheus-operated 9090 -n monitoring- Go to Prometheus targets
http://localhost:9090
Generate Self Signed Certificate (Example 1)
Create SelfSigned ClusterIssuer
example-1/0-self-signed-issuer.yamlGenerate Self Signed Certificate
example-1/1-ca-certificate.yaml
kubectl apply -f example-1- Get certificate
kubectl get certificate -n cert-manager- Get secrets
kubectl get secrets -n cert-manager- Get x509 certificate
kubectl get secrets devopsbyexample-io-key-pair \
-o yaml \
-n cert-manager- Decode base64 certificte
echo "base64" | base64 -d -o ca.crt- Decode CA certificate
openssl x509 -in ca.crt -text -nooutGenerate TLS Certificate using CA (Example 2)
Create CA ClusterIssuer
example-2/0-ca-issuer.yamlCreate
stagingnamespaceexample-2/1-staging-ns.yamlCreate certificate for blog.devopsbyexample.io
example-2/example-2/2-blog-certificate.yaml
kubectl apply -f example-2- Get certificate
kubectl get certificate -n staging- Get secrets
kubectl get secrets -n staging- Get x509 certificate
kubectl get secrets blog-devopsbyexample-io-key-pair \
-o yaml \
-n staging- Decode base64 certificte
echo "base64" | base64 -d -o blog-devopsbyexample-io.crt- Decode CA certificate
openssl x509 -in blog-devopsbyexample-io.crt -text -nooutDeploy Nginx Ingress Controller
- Add ingress-nginx Helm repo
helm repo add ingress-nginx \
https://kubernetes.github.io/ingress-nginx- Update Helm repos
helm repo update- Search for Nginx Helm Chart
helm search repo ingress-nginxCreate
nginx-ingress-values.yamlwithout ACME sectionInstall Nginx Ingress
helm install ing-083 ingress-nginx/ingress-nginx \
--namespace ingress \
--version 4.0.1 \
--values nginx-ingress-values.yaml \
--create-namespace- Get pods
kubectl get pods -n ingress- Get Ingress Class
kubectl get ingressclassDeploy Grafana on Kubernetes
- Deploy Grafana using YAML
grafana/0-secret.yamlgrafana/1-datasources.yamlgrafana/2-dashboard-providers.yamlgrafana/3-cert-manager.yamlgrafana/4-deployment.yamlgrafana/5-service.yaml
kubectl apply -f grafana- Get services in monitoring namespaces
kubectl get svc -n monitoring- Create
HTTPingress without TLS sectionexample-3/grafana.yaml
kubectl apply -f example-3- Get ingresses
kubectl get ing -n monitoringCreate
CNAMErecord forgrafana.devopsbyexample.ioGo to data sources and dashboards
http://grafana.devopsbyexample.ioLogout
Install wireshark
brew install wireshark- Get public ip address of Grafana
dig +short grafana.devopsbyexample.io- Get network interfaces
ifconfig- Get POST TCP packets
sudo tshark -i en1 -x -f "host grafana.devopsbyexample.io and port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354" > post.pcapcat post.pcap- Add TLS section to grafana ingress
example-3/grafana.yaml
kubectl apply -f example-3- Get certificates in monitoring namespace
kubectl get certificates -n monitoring- Get ingresses in monitoring ns
kubectl get ing -n monitoringGo to
https://grafana.devopsbyexample.ioto check TLS certsAdd CA to the keychain
Login to Grafana
Listen on port 443
sudo tshark -i en1 -x -f "port 443"Secure NGINX ingress with Let's Encrypt & ACME (Example 4)
Create
letsencrypt-stagingIssuer inmonitoringnamespaceexample-4/letsencrypt-staging-issuer.yaml
Create
letsencrypt-stagingIssuer inmonitoringnamespaceexample-4/letsencrypt-prod-issuer.yaml
kubectl apply -f example-4- Get issuers in
monitoringnamespace
kubectl get issuers -n monitoring- If it's not ready describe to get error message
kubectl describe issuer letsencrypt-http01-prod -n monitoringCreate Prometheus ingress with
letsencrypt-prodissuerexample-4/2-prometheus-ing.yaml
Apply Prometheus ingress
kubectl apply -f example-4/2-prometheus-ing.yaml- Get CRDs
kubectl get Certificates -n monitoring
kubectl describe Certificates \
prometheus-v4-devopsbyexample-io-key-pair -n monitoring
kubectl get CertificateRequests -n monitoring
kubectl describe CertificateRequests \
prometheus-v4-devopsbyexample-io-key-pair-ss2h8 -n monitoring
kubectl get Orders -n monitoring
kubectl describe Orders \
prometheus-v4-devopsbyexample-io-key-pair-ss2h8-98152280 -n monitoring
kubectl get Challenges -n monitoring
kubectl describe Challenges \
prometheus-v4-devopsbyexample-io-key-pair-2zjpw-9815-4236669664 -n monitoring- Make sure that all pods are up in monitoring namespace including
cm-acme-http-solver-
kubectl get pods -n monitoring- To complete we need to create CNAME record for prometheus
kubectl get ing -n monitoring- Print out acme ing
kubectl get ing cm-acme-http-solver-lxtws -o yaml -n monitoring- Watch Certificates and Challenges
watch -n 1 -t kubectl get certificates -n monitoring
watch -n 1 -t kubectl get Challenges -n monitoringCreate CNAME for
prometheus-v4.devopsbyexample.ioGo to
https://prometheus-v4.devopsbyexample.io
Delegate a Subdomain to Route53
Create
monitoring.devopsbyexample.ioRoute53 hosted zoneGet Name Servers from
Hosted zone detailsAdd NS records for the subdomain
monitoringCreate A record to test route53 zone
test.monitoring.devopsbyexample.io-> 10.10.10.10Wait up to 1 minute and test with dig
dig +short test.monitoring.devopsbyexample.ioCreate IAM Role for Kubernetes Service Account
Create OpenID Connect provider, use
sts.amazonaws.comfor AudienceCreate IAM policy with Route53 access
CertManagerRoute53Access
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "route53:GetChange",
"Resource": "arn:aws:route53:::change/*"
},
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/<id>"
}
]
}Create IAM role for
cert-manager-acmecert-managerGet service account name for cert-manager
kubectl get sa -n cert-manager- Update trust for IAM role to allow only
cert-083-cert-managerservice account to assume it
aud -> sub
sts.amazonaws.com -> system:serviceaccount:cert-manager:cert-083-cert-manager- Update service account manually, add following line to annotations
kubectl edit sa -n cert-managereks.amazonaws.com/role-arn: arn:aws:iam::424432388155:role/cert-manager-acme- Modify the cert-manager Deployment with the correct file system permissions, so the ServiceAccount token can be read.
kubectl get deployment -n cert-manager
kubectl edit deployment cert-083-cert-manager -n cert-manager- --issuer-ambient-credentials- Make sure pod restarted
kubectl get pods -n cert-manager- This change can be inclused to Helm Chart (include to
cert-manager-values.yamlbefore installing or upgrade Helm release)
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::424432388155:role/cert-manager-acme
extraArgs:
- --issuer-ambient-credentialsResolve DNS-01 challenge with cert-manager (Example 5)
Create Issuer to use dns-01 challenge
example-5/0-letsencrypt-staging-dns01-issuer.yamlexample-5/1-letsencrypt-prod-dns01-issuer.yamlexample-5/2-grafana-ing.yaml
Watch Certificates and Challenges
watch -n 1 -t kubectl get certificates -n monitoring
watch -n 1 -t kubectl get challenges -n monitoringkubectl apply -f example-5Go to Route53 to get TXT record
Create CNAME for grafana-v4.monitoring.devopsbyexample.io
Go to
https://grafana-v4.monitoring.devopsbyexample.ioCheck logs
kubectl get pods -n cert-manager
kubectl logs -f <pod> -n cert-managerhttps://cert-manager.io/docs/configuration/acme/dns01/route53/
Monitor Cert Manager with Prometheus and Grafana
Clean Up
- Remove Helm repo
helm repo remove jetstack
helm repo remove ingress-nginx- Remove wireshark
brew remove wiresharkRemove
devopsbyexample.ioCADelete Route53 hosted zone
monitoring.devopsbyexample.ioDelete all DNS records in google domains
Delete IAM Role
cert-manager-acmeDelete IAM Policy
CertManagerRoute53Access
Overview (`lessons/084/README.md`)
AWS Point to Site VPN Setup (Free OpenVPN AWS Setup | EC2 | Route53 Private DNS | Ubuntu 20.04)
Create AWS VPC
- Create AWS VPC (Virtual Private Cloud)
- give it a name
main - define IPv4 CIDR block
10.0.0.0/16
- give it a name
Create AWS Internet Gateway
Create AWS Internet Gateway
- call it
igw
- call it
Attach Internet Gateway to AWS VPC
Create AWS Public Subnet
Create public subnet
- call it
public - define IPv4 CIDR block
10.0.0.0/22, it will give you1,024IP addresses, witht the last IP -10.0.3.255
- call it
Create
publicroute table with default route to the internet gatewayAttach
publicroute table to the public subnet
Create AWS NAT Gateway
Allocate Elastic IP address for nat
- tag
Name: nat
- tag
Create NAT gateway
- call it
nat
- call it
Place it to public subnet
Create AWS Private Subnets
Create
private-largesubnet10.0.16.0/20Create
private-smallsubnet10.0.32.0/24Create
privateroute table with default route to nat gatewayUpdate route tables for private subnets
Create Ubuntu EC2 Instance
Allocate static public IP address
openvpnCreate Ubuntu 20.04
- tag
Name: openvpn - Instance type:
t3.small - SG:
OpenVPN, add1194custom udp fromAnywhere
- tag
Associate Elastic IP with EC2
Install OpenVPN on Ubuntu 20.04
- Update permissions on the key
chmod 400 devops.pem- SSH to the Ubuntu server
ssh -i devops.pem ubuntu@<ip>- Update Ubuntu repositories
sudo apt update- Check OpenVPN candidate
apt policy openvpnCompate verion with the latest release of OpenVPN on GitHub
We would need to run commands as a root, let's temporary use
sudo -s
sudo -s- Then import the public GPG key that is used to sign the packages:
wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg|apt-key add -- Add OpenVPN repo
echo "deb http://build.openvpn.net/debian/openvpn/stable focal main" > /etc/apt/sources.list.d/openvpn-aptrepo.list- Update repositories again with the new openvpn source list
apt update- Exit root
exit- Check version of candidate again
apt policy openvpn- Install the latest one
sudo apt install openvpn=2.5.3-focal0Install easy-rsa on Ubuntu 20.04
- Check the candidate verion
apt policy easy-rsaCheck available verions on GitHub
Download
easy-esatarball
wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz- Untar it
tar -zxf EasyRSA-3.0.8.tgz- Clean UP
ls
rm EasyRSA-3.0.8.tgz- Move
easy-rsato OpenVPN
sudo mv EasyRSA-3.0.8/ /etc/openvpn/easy-rsa- (Optionally) create soft link
sudo ln -s /etc/openvpn/easy-rsa/easyrsa /usr/local/bin/- Change directory to home and test cli
easyrsa --versionCreating PKI for OpenVPN with easy-rsa
- Change directory to openvpn
cd /etc/openvpn/easy-rsa- Initialize a PKI CA
easyrsa init-pki- List directories
ls
ls pki- Create vars file
vim vars- Create CA (security or convenience)
easyrsa build-ca nopass- List files
ls pki
ls pki/privateGenerate Certificate for OpenVPN Server
- Generate signing request
easyrsa gen-req openvpn-server nopass- Sign cert
easyrsa sign-req server openvpn-serverConfigure OpenVPN Cryptographic Material
- Generate the tls-crypt pre-shared key
openvpn --genkey secret ta.key
cat ta.keyConfigure OpenVPN server
- Enable IP forwarding
sudo vim /etc/sysctl.conf- Read the file and load the new values for the current session
sudo sysctl -p- Configure IP Tables
sudo iptables -t nat -S- Find out network public network interface
ip route list default- Configure nat routing
sudo iptables \
-t nat -I POSTROUTING -s 10.8.0.0/24 -o ens5 -j MASQUERADE- Save iptables
sudo apt-get install iptables-persistent- Create config file, leave routes out for now
sudo vim /etc/openvpn/server/server.conf- Check if you have
nobodyuser
cat /etc/passwd | grep nobody- Check if you have
nogroup
cat /etc/group | grep nogroupCheck subnet masks for CIDR here
Start OpenVPN
sudo systemctl start openvpn-server@server- Check status OpenVPN
sudo systemctl status openvpn-server@server- Enable openvpn-server
sudo systemctl enable openvpn-server@server- Check logs
journalctl \
--no-pager --full -u openvpn-server@server -fCreate Client Profile .ovpn Manually
- Generate key pair
easyrsa gen-req example-1 nopass- Sign certificate request
easyrsa sign-req client example-1- Create
example-1.ovpnprofile
cat /etc/openvpn/easy-rsa/pki/ca.crt
cat \
/etc/openvpn/easy-rsa/pki/issued/example-1.crt
cat \
/etc/openvpn/easy-rsa/pki/private/example-1.key
cat /etc/openvpn/easy-rsa/ta.key- Install tunnelblick
brew install --cask tunnelblickInstall
example-1.ovpnprofileRun journalctl on OpenVPN server
journalctl \
--no-pager --full -u openvpn-server@server -fConnect to the VPN
Check routes on mac
netstat -rCreate Ubuntu server in
private-smallsubnet- Use openvpn security group as a source
SSH to Ubuntu using private IP address
ssh -i devops.pem ubuntu@<private ip>Create Route53 Private Hosted Zone
Create
devops.pvtprivate hosted zoneCreate
test.devops.pvtA record with random IP addressTry to resolve it from development host
dig test.devops.pvt- Enable VPC DNS resolution
- To use private hosted zones, you must set the following Amazon VPC settings to true:
- enableDnsHostnames
- enableDnsSupport
- To use private hosted zones, you must set the following Amazon VPC settings to true:
Revoke OpenVPN Client Certificate
- Revoke
example-1certificate
cd /etc/openvpn/easy-rsa/
easyrsa revoke example-1- Generate CRL (Certificate Revocation List)
easyrsa gen-crl- Add CRL to OpenVPN server config
sudo vim /etc/openvpn/server/server.conf
crl-verify /etc/openvpn/easy-rsa/pki/crl.pem
sudo systemctl restart openvpn-server@server
journalctl \
--no-pager --full -u openvpn-server@server -fGenerate profiles
cd /etc/openvpn/
sudo mkdir client-configs
cd client-configs
sudo vim base.ovpn
cd /etc/openvpn/easy-rsa/
easyrsa gen-req example-2 nopass
easyrsa sign-req client example-2
vim gen_client_profile.sh
sudo chmod +x gen_client_profile.sh
sudo ./gen_client_profile.sh example-2
cat \
/etc/openvpn/client-configs/example-2.ovpnCreate
example-2.ovpnInstall
example-2.ovpnprofileCheck DNS again
dig test.devops.pvtInstall docker on Ubuntu 20.04
- Set up the repository
sudo apt install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release- Add Dockerâs official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg- Set up the stable repository
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null- Install Docker Engine
sudo apt update
sudo apt install \
docker-ce docker-ce-cli containerd.io- Install docker compose
sudo apt install docker-compose- Create
docker-compose.yamlto run MySQL 5.7
vim docker-compose.yaml- Run docker compose up
sudo docker-compose up -d- Check running containers
sudo docker psConfigure MySQL 5.7 Server for gate-sso
- Install MySQL client
sudo apt install mysql-client- Connect to mysql
mysql -u root -p -h 127.0.0.1 -P 3306- Create user for gate-sso
CREATE USER 'gate' IDENTIFIED BY 'devops123';- Grant access to
gate_developmentandgate_testdatabases
GRANT ALL PRIVILEGES ON gate_development.* TO 'gate';
GRANT ALL PRIVILEGES ON gate_test.* TO 'gate';
FLUSH PRIVILEGES;- Log out
exitInstall Ruby on Rails on Ubuntu 20.04
- Check ruby version (must be >= 2.4)
ruby -v- Install rvm
curl -L https://get.rvm.io | bash -s stable- Import GPG keys
curl -sSL https://rvm.io/mpapis.asc | gpg --import -
curl -sSL https://rvm.io/pkuczynski.asc | gpg --import -- Run script again
curl -L https://get.rvm.io | bash -s stable- To start using RVM, load the script environment variables using the source command:
source ~/.rvm/scripts/rvm- Install ruby
2.4.3with rvm
rvm install 2.4.3- Install
bundlergem
gem install bundlerInstall gate-sso
- Clone gate-sso GitHub repository
cd /opt
sudo git clone https://github.com/gate-sso/gate.git- Update ownership of the repository
sudo chown -R ubuntu:ubuntu gate- Install gate-sso dependencies
cd gate
bundle install- Fix deps
sudo apt-get install libmysqlclient-dev- Run bundle install again
bundle install- Install nodejs
sudo apt install nodejs- Run again
rake app:initCreate SSO in gcp
- Go to APIs & Services
- Create OAuth Client ID credentials
- http://gate.devopsbyexample.io/users/auth/google_oauth2/callback
Update env
vim .envGATE_SERVER_URL=http://gate.devopsbyexample.io
GATE_OAUTH_CLIENT_ID=771040318735-7anf9ct0fo5a23s6gqsnmc2vo3ifbo28.apps.googleusercontent.com
GATE_OAUTH_CLIENT_SECRET=8SNXY_H7RE2-nffqDGIKGZ9i
GATE_HOSTED_DOMAIN=devopsbyexample.io
GATE_HOSTED_DOMAINS=antonputra.com
GATE_DB_HOST=127.0.0.1
GATE_DB_PASSWORD=devops123Create A record for gate.devopsbyexample.io
Run setup
rake app:setupOpen port 80 on SG
Create
sudo vim /etc/openvpn/easy-rsa/gen-client-conf(Update remote ip)Create
sudo vim /etc/openvpn/easy-rsa/gen-client-keys(Update remote ip)Start rails
rvmsudo rails server \
--port 80 \
--binding 0.0.0.0 \
--daemon- Go to http://gate.devopsbyexample.io and download profile
Links
Certificate Authority (CA)
Starting from OpenVPN 2.4, one can also use elliptic curves for TLS connections (e.g. tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384). Elliptic curve cryptography provides more security and eliminates the need for a Diffie-Hellman parameters file. See [2] and [3].
Clean UP
- VPC
main - Key pair
devops - Release public IPs
- Delete tunnelblick
brew remove tunnelblick- Delete Route53 hosted zone
devops.pvt - Remove GCP credentials
- Remove
gate.devopsbyexample.ioA record
Overview (`lessons/085/README.md`)
How to Deploy React App on Firebase Hosting? (CI/CD with GitHub Actions | Preview | Custom Domain)
Prerequisites
- Firebase Account
- npm 5.2+
Create React App from Scratch 2021
- Check
npmversion
npm --version- Create a new single-page application in React
npx create-react-app react-demo-085- Change directory to the app
cd react-demo-085- Inspect the folder content
code .- Run react locally
npm startCreate Firebase Project
Go to Firebase
Click
Go to consoleClick
Create a projectCreate
react-demo-085Firebase project
Deploy React App on Firebase Hosting
- Install the Firebase CLI
npm install firebase-tools- Log in and test the Firebase CLI
firebase login- Test that the CLI is properly installed and accessing your account by listing your Firebase projects.
firebase projects:list- Build for React application
npm run build- Initialize your project
firebase init hosting- Deploy to your site
firebase deploy --only hostingOpen hosting URL
Check TLS certificate
Firebase Hosting Add Custom Domain
Go to Firebase console
Navigate to
HostingClick
Add custom domainEnter your domain, in my case
devopsbyexample.ioCreate A record for your domain
Optionally add
wwwsubdomain
Set up automatic builds and deploys with GitHub
Create GitHub repo
react-demo-085, let's make it privateAdd existing repository
git remote add origin [email protected]:antonputra/react-demo-085.git
git add .
git commit - 'init commit'
git push origin main- Reinitialize Firebase hosting
firebase init hosting- Create new branch for new feature
git checkout -b feature-xModify
src/App.jsCommit, push and create PR
git add .
git commit -m 'Add new feature X'
git push origin feature-x- Go to
Actionsin GitHub repo
Links
Clean Up
Remove
react-demo-085firebase projectRemove
firebase-tools
npm uninstall -g firebase-toolsRemove
react-demo-085GitHub repoRemove DNS records
Log out from Firebase
firebase logoutOverview (`lessons/086/README.md`)
Build a Docker Image and Publish It to AWS ECR using Github Actions
Content
This guide contains instructions on how to:
- Create GitHub Repository
- Create Golang App
- Create Dockerfile for Golang
- Create GitHub Actions Workflow
- Create AWS ECR Repository
- Create AWS IAM User, Policy, and Group
- Test GitHub Actions
- Add Automatic Tagging of Releases
Create GitHub Repository
- Create GitHub repo
lesson-086 - Clone repository
git clone [email protected]:antonputra/lesson-086.git- Initialize the Go module
go mod init github.com/antonputra/lesson-086Create
main.gofileFormat the code and run it
# go install golang.org/x/tools/cmd/goimports@latest
go mod tidy
goimports -w .
go run main.goCreate Dockerfile for Golang
- Create
Dockerfile
Create GitHub Actions Workflow
- Create
.github/workflows/main.ymlfile, uselatestforIMAGE_TAG
Create AWS ECR Repository
- Go to AWS console, search for
ecr - Create private ECR repository
lesson-086
Create AWS IAM User, Policy, and Group
- Create IAM Policy
AllowPushPullPolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetAuthorizationToken",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
],
"Resource": [
"arn:aws:ecr:us-east-1:424432388155:repository/lesson-086"
]
}
]
}Create
push-pull-imagesIAM Group and attachAllowPushPullPolicyIAM PolicyCreate user
github-actionsand place it topush-pull-imagesIAM Group
Test GitHub Actions
- Create initial commit
git add .
git commit -m 'init commit'
git push origin main- Check ECR repository
Add Automatic Tagging of Releases
Create
build/git_update.shscriptMake a change and push to remote branch from
mainCreate a new branch
aputra, make a change, updatepatch->majorand push
Links
Clean Up
- Delete
github-actionsAWS IAM User - Delete
AllowPushPullPolicyAWS IAM Policy - Delete
push-pull-imagesAWS IAM Group
Overview (`lessons/087/README.md`)
Build a Docker Image and Publish It to GCP GCR & Artifact Registry using Github Actions
Content
- Create GitHub Repository
- Create Flask App
- Create Docker Image for Flask App
- Create Service Account in GCP
- Create GitHub Actions Docker Build and Push Workflow
- Use GitHub Actions to Push Docker to Artifact Registry
- Increment Git Tag for Each Commit and Use It for Docker Image
Create GitHub Repository
- Go to GitHub
- Create empty repository
lesson-087, keep it public - Clone repository
git clone [email protected]:antonputra/lesson-087.gitCreate Flask App
- Create
app.py - Create
requirements.txt - Optionally, create
.gitignore
Create Docker Image for Flask App
- Create
Dockerfile - Build docker image
docker build -t lesson-087:latest .- Run docker locally
docker run -p 5000:5000 lesson-087:latest- Use curl to test
curl localhost:5000/helloCreate Service Account in GCP
- Create
github-actionsservice account - Create and download key for service account
- Add
Storage Adminrole to the service account, project wide permissions (fix later)
Create GitHub Actions Docker Build and Push Workflow
- Create
.github/workflows/gcp.yml - Create GitHub secret
SERVICE_ACCOUNT_KEY - Commit and push
git add .
git commit -m 'init commit'
git push origin main- Check docker image in GCR
- Fix permissions, remove wide project permissions and add to GS bucket
- Create empty commit to test CI
git commit --allow-empty -m "Trigger CI"
git push origin mainUse GitHub Actions to Push Docker to Artifact Registry
- Create
imagesArtifact Registry repository - Add
github-actionsservice account toimagesrepo withArtifact Registry Writerrole - Add
gcloud auth configure-docker us-west2-docker.pkg.dev --quiettoConfigure Docker Clientstep - Add
Push Docker Image to Artifact Registrystep - Commit and push
git add .
git commit -m 'add step to push docker to artifact registry'
git push origin mainIncrement Git Tag for Each Commit and Use It for Docker Image
- Create
scripts/git_update.sh - Add
Automatic Tagging of Releasesstep - Update
GIT_TAGvariable to${{ steps.increment-git-tag.outputs.git-tag }} - Commit and test
git add .
git commit -m 'add step to increment git tag'
git push origin main- Check GitHub Tag, GCR and Artifact registry
Links
- Push to GCR GitHub Action
- Uploading a Docker image to GCR using Github Actions
- Using Github Actions to Build and Push Images to Google Container Registry
- Creating a CI/CD environment for serverless containers on Cloud Run with GitHub Actions
- Granting permissions
Clean Up
- Delete
github-actionsservice account - Delete
lesson-087GCR repository - Delete
artifacts.devopsbyexample-325402.appspot.comGS bucket - Delete
imagesartifact repository
Overview (`lessons/088/README.md`)
How to Create Your Own GitHub Actions?
Content
- Demo
- Build JavaScript GitHub Action
- Test JavaScript GitHub Action
Build JavaScript GitHub Action
Create GitHub repository
increment-git-tagfor JavaScript GitHub Action. Keep it public to allow other repositories to use this action. Also, add a README.md file, gitignore, and select MIT Licence.Clone repository
git clone [email protected]:antonputra/increment-git-tag.git- Initialize the project and install dependencies
cd increment-git-tag
npm init -y
npm i @actions/core
npm i @actions/exec- Open Project
code .Create
action.ymlCreate
index.jsInstall vercel/ncc
npm i @vercel/ncc- Compile JavaScript code into single file
ncc build index.js -o action- Create
git_update.sh - Make
git_update.shexecutable
chmod +x chmod +x action/git_update.sh- Commit and push
git add .
git commit -m 'init commit'
git tag -a -m "increment git tag" v1
git push --follow-tagsTest JavaScript GitHub Action
Create GitHub repository
lesson-088(private)Clone repo
git clone [email protected]:antonputra/lesson-088.gitCreate
.github/workflows/main.yaml(patch)Commit and push
Increment major version, commit and push
Links
Overview (`lessons/089/README.md`)
GitHub Actions Self Hosted Runner (Autoscaling with Kubernetes)
Content
- Create GitHub Repository
- Create EKS Cluster with Terraform
- Install Cert-Manager on Kubernetes
- Install actions-runner-controller
- Create Single GitHub Actions Self Hosted Runner
- Create Multiple GitHub Actions Self Hosted Runners
- Autoscaling with Kubernetes
Create GitHub Repository
- Create private GitHub repository
lesson-089
Create EKS Cluster with Terraform
Go over each file under
terraformfolderCreate EKS with terraform
terraform init
terraform apply- Configure kubectl
aws eks --region us-east-1 update-kubeconfig --name demoif you get an error 'NoneType' object is not iterable, run rm ~/.kube/config
- Check connection with Kubernetes
kubectl get svcInstall Cert-Manager on Kubernetes
- Add Helm repo
helm repo add jetstack https://charts.jetstack.io- Update Helm
helm repo update- Search for latest verion
helm search repo cert-manager- Split the screen and install Helm chart
watch kubectl get pods -A- Install Helm chart
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.6.0 \
--set prometheus.enabled=false \
--set installCRDs=trueInstall actions-runner-controller
Create GitHub App, call it
k8s-actions-89Create namespace
kubectl create ns actions- Create secret to authenticate with GitHub
kubectl create secret generic controller-manager \
-n actions \
--from-literal=github_app_id=<> \
--from-literal=github_app_installation_id=<> \
--from-file=github_app_private_key=<>- Add actions helm repo
helm repo add actions-runner-controller https://actions-runner-controller.github.io/actions-runner-controller
helm repo update
helm search repo actions- Install Helm chart
helm install actions \
actions-runner-controller/actions-runner-controller \
--namespace actions \
--version 0.14.0 \
--set syncPeriod=1mCreate Single GitHub Actions Self Hosted Runner
- Create
k8s/runner.yaml
kubectl apply -f k8s/runner.yaml
kubectl get pods -n actions
kubectl logs -f k8s-single-runner -c runner -n actionsGo to GitHub to check self hosted runners
Clone
lesson-089repository
git clone [email protected]:antonputra/lesson-089.git- Create
.github/workflows/main.yaml - Commit & push
- Check pods
kubectl get pods -n actionsCreate Multiple GitHub Actions Self Hosted Runners
- Create
k8s/runner-deployment.yaml
kubectl apply -f k8s/runner-deployment.yaml
kubectl get pods -n actionsCheck in GitHub repo self-hosted runners
Create 2 build jobs with docker
Create
DockerfileCeate
.github/workflows/example-2.yaml
Autoscaling with Kubernetes
- Deploy
k8s/horizontal-runner-autoscaler.yaml
kubectl apply -f k8s/horizontal-runner-autoscaler.yaml- Ceate
.github/workflows/example-3.yaml
Links
- Hosting your own runners
- GitHub Actions Runner
- actions-runner-controller
- actions-runner-controller values.yaml
Overview (`lessons/090/README.md`)
Kubernetes Terminal: 6 Must-Have Tools to Install & Examples
Overview (`lessons/091/README.md`)
Kubernetes NodePort vs LoadBalancer vs Ingress?
Overview (`lessons/092/README.md`)
Kubernetes Namespaces vs. Virtual Clusters
Install vcluster
vcluster create vcluster-1 -n host-namespace-1
vcluster connect vcluster-1 --namespace host-namespace-1
kubectl get namespace
kubectl create namespace demo-nginx
kubectl create deployment nginx-deployment -n demo-nginx --image=nginx
kubectl get pods -n demo-nginx
kubectl get deployment -n host-namespace-1
kubectl get pods -n host-namespace-1Links
Overview (`lessons/093/README.md`)
Kubernetes Basics: Pods, Nodes, Containers, Deployments and Clusters
Overview (`lessons/094/README.md`)
Kubernetes Quality of Service (QoS) Classes for Pods (Guaranteed, Burstable, BestEffort)
Links
Overview (`lessons/095/README.md`)
Kubernetes Pod Priority
kubectl get pods -A
kubectl get pods -A \
-o jsonpath='{range .items[*]}{.metadata.name}{" - "}{.spec.priorityClassName}{"\n"}{end}'Overview (`lessons/096/README.md`)
Kubernetes Affinity and Anti Affinity vs NodeSelector (Examples)
Overview (`lessons/097/README.md`)
Kubernetes Taints and Tolerations
kubectl get nodes
kubectl taint nodes node1 role=spot:NoSchedule
kubectl get podsOverview (`lessons/098/README.md`)
Kubernetes Pod Disruption Budget
Overview (`lessons/099/README.md`)
Kubernetes Local Persistent Volume: DON'T use hostPath!
Postgress
kubectl port-forward database-postgresql-0 5432
psql --host localhost \
--port 5432 \
--username postgres \
--password
CREATE DATABASE test_hostpath;
\lDrain Nodes
kubectl get nodes
kubectl drain <node-name> \
--delete-emptydir-data \
--ignore-daemonsetsPrepare Disks
ssh -i ~/Downloads/devops.pem [email protected]
lsblk
sudo mkfs -t xfs /dev/nvme1n1
sudo lsblk -o +UUID
sudo mkdir \
-p /mnt/ssd-disks/<UUID>
sudo mount \
/dev/nvme1n1 \
/mnt/ssd-disks/<UUID>
sudo vi /etc/fstab
UUID=<UUID> /mnt/ssd-disks/<UUID> xfs defaults,nofail 0 2Overview (`lessons/100/README.md`)
How to Deploy Create React App to GitHub Pages?
Create React App & GitHub Repo
Create
react-pages-demoempty GitHub repositoryCreate react app using
create-react-apptool
npx create-react-app react-pages-demo- Test react app locally
cd react-pages-demo
npm startDeploy React App to GitHub Pages
- Add
homepageattribute to thepackage.jsonfile
{
...
"homepage": "https://antonputra.github.io/react-pages-demo",
...
}- Install
gh-pagesnpm module to publishing files to a gh-pages branch on GitHub
npm install gh-pages- Add couple of tasks to
package.jsonfile
{
...
"scripts":
{
...
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
}
}- Connect local repository to the remote
git remote add origin [email protected]:antonputra/react-pages-demo.git
git branch -M main
git push -u origin main- Deploy react app to GitHub pahes
npm run deploySetup Custom Domain for GitHub Pages
Set your custom DNS name from the GitHub settings Pages (devopsbyexample.io)
Go to your DNS provider (in my case Google Domains)
Create
Arecord for your Apex domain (devopsbyexample.io)
185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153Create
CNAMErecord forwwwsubdomain- www -> antonputra.github.io
Add
CNAMEfile underpublicdirectory
devopsbyexample.io- Update homepage attribute
{
...
"homepage": "https://devopsbyexample.io",
...
}- Commit the changes and deploy to github pages
git add .
git commit -m 'Add custom domain'
git push origin main
npm run deployAutomate Deployment with GitHub Actions
- Create
.github/workflows/github-pages.ymlGitHub actions workflow
---
name: Build and Deploy React App to GitHub Pages
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
name: Build and Deploy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build
run: npm install
- name: Test
run: npm run test
- name: Deploy
run: |
git config --global user.name 'Anton Putra'
git config --global user.email '[email protected]'
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
npm run deployUpdate
src/App.jswith random textCommit and push
git add .
git commit -m 'Add GitHub Actions'
git push origin mainLinks
Overview (`lessons/101/README.md`)
Terraform Ansible Integration: GCP Example & Multiple VMs
Prerequisites
- Ansible
- Terraform
Generate SSH Key Pair
- Run the following command to generate elliptic curve ssh key pair
ssh-keygen -t ed25519 -f ~/.ssh/ansbile_ed25519 -C ansible- Optionally, you can generate RSA key pair
ssh-keygen -t rsa -f ~/.ssh/ansbile -C ansible -b 2048Add SSH Key to GCP Project
- Go to compute engine section
- Click Metadata
- Select
SSH KEYStab and clickADD SSH KEY - Upload public
ansbile_ed25519.pubkeycat ~/.ssh/ansbile_ed25519.pub
Create Ansible Playbook for Nginx Installation
- Create
roles/nginx/tasks/main.yamltask - Create
nginx.yamlplaybook - Create Ansible config
ansible.cfgto skip host key verification
Create Terraform Ansible Integration Example
- Create terraform file
1-example.tf - Open default firewall rules
- Verify that you have Terraform and Ansible installed
command -v terraform
command -v ansible-playbook- Run
terraform initto download provider and plugins - Run
terraform applyto create Nginx instance in GCP
Provision Multiple VMs
- Destroy previous example
terraform destroy - Copy
1-example.tf->2-example.tf - Rename
1-example.tf->1-example.tf.bac - Add local variable
web_servers = {
nginx-000-staging = {
machine_type = "e2-micro"
zone = "us-central1-a"
}
nginx-001-staging = {
machine_type = "e2-micro"
zone = "us-central1-b"
}
}for_each = local.web_servers
name = each.key
machine_type = each.value.machine_type
zone = each.value.zonehost = self.network_interface.0.access_config.0.nat_ipcommand = "ansible-playbook -i ${self.network_interface.0.access_config.0.nat_ip}, --private-key ${local.private_key_path} nginx.yaml"output "nginx_ips" {
value = {
for k, v in google_compute_instance.nginx : k => "http://${v.network_interface.0.access_config.0.nat_ip}"
}
}- Run
terraform apply
Clean Up
terraform destroy- rm ~/.ssh/ansbile*
- Delete SSH public key from GCP project
Overview (`lessons/102/README.md`)
How to Create EKS Cluster Using Terraform
You can find tutorial here.
Overview (`lessons/103/README.md`)
How to Add IAM User and IAM Role to AWS EKS Cluster?
You can find tutorial here.
Overview (`lessons/104/README.md`)
How to Install Prometheus and Grafana on Ubuntu?
You can find tutorial here.
Overview (`lessons/105/README.md`)
How to Install MongoDB on Kubernetes?
You can find tutorial here.
Overview (`lessons/106/README.md`)
Google Cloud Functions Tutorial
You can find tutorial here.
Overview (`lessons/107/README.md`)
How to Hack a Password in Python?
You can find tutorial here.
Overview (`lessons/108/README.md`)
How to Create GKE Cluster Using TERRAFORM?
You can find tutorial here.
Overview (`lessons/109/README.md`)
How to Create EKS Cluster Using eksctl?
You can find tutorial here.
Overview (`lessons/110/README.md`)
How to Deploy React App (any static website) to S3 and CloudFront?
You can find tutorial here.
Overview (`lessons/111/README.md`)
Kubernetes Kustomize Tutorial: 10 examples
You can find tutorial here.
Overview (`lessons/112/README.md`)
Native EKS Ingress: AWS Load Balancer Controller & 5 Examples (Terraform, TLS, IngressGroup, IP)
You can find tutorial here.
Overview (`lessons/113/README.md`)
Create AWS EKS Fargate Using Terraform (EFS, HPA, Ingress, ALB, IRSA, Kubernetes, Helm, Tutorial)
You can find tutorial here.
Overview (`lessons/114/README.md`)
Kubernetes Node Autoscaling with Karpenter (AWS EKS & Terraform)
You can find tutorial here.
Overview (`lessons/115/README.md`)
How to Create AWS Lambda with Terraform? (API Gateway & GET/POST & IAM S3 Access & Dependencies)
You can find tutorial here.
Overview (`lessons/116/README.md`)
How to Integrate Amazon API Gateway with Amazon EKS? (Terraform & AWS Lambda & Serverless & NLB)
You can find tutorial here.
Overview (`lessons/117/README.md`)
AWS API Gateway - Custom Domain (Console + Terraform | Route53 + Without Route53)
You can find tutorial here.
Overview (`lessons/118/README.md`)
AWS API Gateway - EC2 Integration (Console + Terraform | Backend | Endpoint | HTTP | Node JS)
You can find tutorial here.
Overview (`lessons/119/README.md`)
AWS API Gateway - WebSocket API + EC2 (HTTP & VPC Link & Auth & API Keys & Lambda Authorizer)
You can find tutorial here.
Overview (`lessons/120/README.md`)
How To SSH into your VM? - Google Cloud Platform (GCP | IAP tunnel | OS Login | Audit | Google IAM)
You can find tutorial here.
Overview (`lessons/121/README.md`)
I've LOST my private key. How to connect to EC2 instance?? (Amazon Web Services | AWS | SSH | SSM)
You can find tutorial here.
Overview (`lessons/122/README.md`)
how to send AWS CloudWatch Alarms to Slack? (Terraform Included)
You can find tutorial here.
Overview (`lessons/123/README.md`)
Creating a Linux service with systemd
You can find tutorial here.
Overview (`lessons/124/README.md`)
AWS Lambda Go vs. Node.js performance benchmark
- Compile go code for Lambda
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main main.go- Run load test
loadtest \
--concurrency 5 \
--maxRequests 1000 \
--rps 10 \
--keepalive \
https://<your-id>.lambda-url.us-east-1.on.aws/Overview (`lessons/125/README.md`)
How to create EKS Cluster using Terraform MODULES (AWS Load Balancer Controller + Autoscaler + IRSA)
Architecture Diagram
You can find tutorial here.
Overview (`lessons/126/README.md`)
AWS Lambda Python vs. Node.js performance benchmark
You can find tutorial here.
Overview (`lessons/127/README.md`)
How to create Application Load Balancer using Terraform? (AWS ALB | HTTPS)
You can find tutorial here.
Overview (`lessons/128/README.md`)
AWS Lambda Go vs. Rust performance benchmark
You can find tutorial here.
Overview (`lessons/129/README.md`)
AWS Lambda vs Cloud Functions (2nd gen) performance benchmark
You can find tutorial here.
Overview (`lessons/130/README.md`)
Monitoring EKS & EC2 instances with MANAGED Prometheus & Grafana
You can find tutorial here.
Overview (`lessons/131/README.md`)
Send Alerts to Slack, Email, PagerDuty - AWS Managed Prometheus (AMP)
You can find tutorial here.
Overview (`lessons/132/README.md`)
GCP Managed Prometheus Tutorial: Managed Collection + Grafana + Workload Identity + Terraform
You can find tutorial here.
Overview (`lessons/133/README.md`)
EKS Storage | Install Amazon EBS CSI driver & KMS
You can find tutorial here.
Overview (`lessons/134/README.md`)
How to monitor Persistent Volume usage in Kubernetes using Prometheus?
You can find tutorial here.
Overview (`lessons/135/README.md`)
How to monitor Containers in Kubernetes using Prometheus & cAdvisor & Grafana? CPU, Memory, Network
You can find tutorial here.
Overview (`lessons/136/README.md`)
Monitor HTTP/REST API in Kubernetes using Prometheus & Nginx Ingress Controller
You can find tutorial here.
Overview (`lessons/137/README.md`)
How to Monitor Golang with Prometheus (Counter - Gauge - Histogram - Summary)
You can find tutorial here.
Overview (`lessons/138/README.md`)
Go (Golang) vs. Rust: (HTTP/REST API in Kubernetes) Performance Benchmark
You can find tutorial here.
Overview (`lessons/139/README.md`)
Use Kubernetes Gateway API instead of Ingress! (TLS - Cert Manager - Istio - Prometheus)
You can find tutorial here.
Overview (`lessons/140/README.md`)
How to Monitor Nginx with Prometheus and Grafana? (Ste-by-Step - Install - Monitor - Fluentd)
You can find tutorial here.
Overview (`lessons/141/README.md`)
How to Build Custom Prometheus Exporter? (Step-by-Step - Real-world Example - Parse Log + HTTP)
You can find tutorial here.
Overview (`lessons/142/README.md`)
Use Kubernetes Gateway API for Mesh (Service-to-Service Communication - Istio - Kiali - Prometheus)
You can find tutorial here.
Overview (`lessons/143/README.md`)
Go (Golang) vs Node JS (Microservices) performance benchmark (Istio - Prometheus - Grafana)
You can find tutorial here.
Overview (`lessons/144/README.md`)
Nginx vs Traefik performance benchmark (HTTP - HTTPS - gRPC | Latency - CPU - Memory | Prometheus)
You can find tutorial here.
Overview (`lessons/145/README.md`)
Go (Golang) vs Java performance benchmark (Fiber vs Spring Boot | Prometheus | Minio | MongoDB)
You can find tutorial here.
Overview (`lessons/146/README.md`)
Nginx vs Apache HTTP Server performance benchmark (Prometheus | HTTP | HTTPS | Grafana | Ansible)
You can find tutorial here.
Overview (`lessons/147/README.md`)
Go (Golang) vs Rust performance benchmark (gRPC | Tonic | Prometheus | Kubernetes | Grafana)
You can find tutorial here.
Overview (`lessons/148/README.md`)
HTTP/2 vs HTTP/3 performance benchmark (Nginx - Prometheus - Grafana - GCP - Terraform - Ansible)
You can find tutorial here.
Overview (`lessons/149/README.md`)
gRPC vs REST performance benchmark (Protobuf - JSON - GKE - Terraform - Golang - Kubernetes - k6)
You can find tutorial here.
Overview (`lessons/150/README.md`)
ARM vs x86 performance benchmark (amd64 vs arm64 - AWS Graviton - AWS EKS - Kubernetes - Golang)
You can find tutorial here.
Overview (`lessons/151/README.md`)
Nginx vs Envoy performance benchmark (HTTP - HTTPS - gRPC - Golang - OpenTelemetry - Prometheus)
You can find tutorial here.
Overview (`lessons/152/README.md`)
gRPC vs Kafka: Which one should you choose?
You can find tutorial here.
Overview (`lessons/153/README.md`)
Traefik vs Caddy 2 performance benchmark
You can find tutorial here.
Overview (`lessons/154/README.md`)
Prometheus Operator Kubernetes Tutorial
You can find tutorial here.
Overview (`lessons/155/README.md`)
Istio Service Mesh Tutorial
You can find tutorial here.
Overview (`lessons/156/README.md`)
How to Use EKS Blueprints Terraform Modules?
You can find tutorial here.
Overview (`lessons/157/README.md`)
DevOps Interview Questions: (Step-by-Step) #1
You can find tutorial here.
Overview (`lessons/158/README.md`)
ArgoCD Tutorial for Beginners: GitOps CD for Kubernetes
You can find tutorial here.
Overview (`lessons/159/README.md`)
ArgoCD Image Updater: Decouple CI from CD! #2
You can find tutorial here.
Overview (`lessons/160/README.md`)
Terragrunt Tutorial: Create VPC, EKS from Scratch! (Step-by-Step)
You can find tutorial here.
Overview (`lessons/161/README.md`)
Terraform Tips & Tricks: loops, if-statements, and more
You can find tutorial here.
Overview (`lessons/162/README.md`)
How to Manage Secrets in Terraform
You can find tutorial here.
Overview (`lessons/163/README.md`)
Thanos (Prometheus) Tutorial: Remote Read/Write - mTLS - Step-by-Step!
You can find tutorial here.
Overview (`lessons/164/README.md`)
An Introduction to Terraform
You can find tutorial here.
Overview (`lessons/165/README.md`)
How to manage Terraform State?
You can find tutorial here.
Overview (`lessons/166/README.md`)
HardenEKS: Best Practices For Amazon EKS (Programmatically)
You can find tutorial here.
Overview (`lessons/167/README.md`)
9 Ways to Expose an App on Amazon EKS to the Internet
You can find tutorial here.
Overview (`lessons/168/README.md`)
How to build multi-arch Docker Images? (Docker Hub - ECR - EKS Demo)
You can find tutorial here.
Overview (`lessons/169/README.md`)
How do I run a PostgreSQL image?
First of all, you need to run the PostgreSQL Docker container in the background.
docker run --detach --name my-postgres --env POSTGRES_PASSWORD=devops123 aputra/postgres-169:15.3You don't need to install the PostgreSQL client locally on your laptop. Instead, SSH into the PostgreSQL container by running the following command.
docker exec -it my-postgres psql -U postgresVerify that you have all the necessary tables.
\dList of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | action | table | postgres
public | customer | table | postgres
public | event | table | postgres
public | event_v2 | table | postgres
public | student | table | postgres
public | teacher | table | postgresInner JOIN
SELECT *
FROM customer
JOIN event
ON customer.customer_id = event.customer_id;Left JOIN
SELECT *
FROM customer
LEFT JOIN event
ON customer.customer_id = event.customer_id;Left Outer JOIN with Exclusion
SELECT *
FROM customer
LEFT JOIN event
ON customer.customer_id = event.customer_id
WHERE event.customer_id IS NULL;Right JOIN
SELECT *
FROM event_v2
RIGHT JOIN action
ON event_v2.action_id = action.action_id;Rewrite as Left JOIN
SELECT *
FROM action
LEFT JOIN event_v2
ON action.action_id = event_v2.action_id;Join 3 tables
SELECT *
FROM action
LEFT JOIN event_v2
ON event_v2.action_id = action.action_id
LEFT JOIN customer
ON customer.customer_id = event_v2.customer_id;Select only customer and action names
SELECT action.name, customer.name
FROM action
LEFT JOIN event_v2
ON event_v2.action_id = action.action_id
LEFT JOIN customer
ON customer.customer_id = event_v2.customer_id;Full JOIN
SELECT *
FROM teacher
FULL OUTER JOIN student
ON teacher.age = student.age;UNION
SELECT age
FROM teacher
UNION
SELECT age
FROM student;UNION ALL
SELECT age
FROM teacher
UNION ALL
SELECT age
FROM student;CROSS JOIN
SELECT *
FROM teacher
CROSS JOIN student;How can I build a multi-architecture Docker image?
docker build -t aputra/postgres-169-arm64:15.3 --platform linux/arm64 .
docker build -t aputra/postgres-169-amd64:15.3 --platform linux/amd64 .
docker push aputra/postgres-169-arm64:15.3
docker push aputra/postgres-169-amd64:15.3
docker manifest create aputra/postgres-169:15.3 \
aputra/postgres-169-arm64:15.3 \
aputra/postgres-169-amd64:15.3
docker manifest push aputra/postgres-169:15.3How can I manually create tables and insert data?
CREATE TABLE customer (
customer_id integer PRIMARY KEY,
name varchar(256),
address varchar(256)
);
INSERT INTO customer
VALUES
(1, 'Casey', '2295 Spring Avenue'),
(2, 'Peter', '924 Emma Street'),
(3, 'Erika', '397 Terry Lane');
CREATE TABLE event (
event_id integer PRIMARY KEY,
customer_id integer REFERENCES customer(customer_id),
action varchar(256)
);
INSERT INTO event
VALUES
(101, '3', 'LOGIN'),
(102, '3', 'VIEW PAGE'),
(103, '1', 'LOGIN'),
(104, '1', 'SEARCH');
CREATE TABLE action (
action_id integer PRIMARY KEY,
name varchar(256)
);
INSERT INTO action
VALUES
(201, 'LOGIN'),
(202, 'VIEW PAGE'),
(203, 'SEARCH'),
(204, 'LOGOUT');
CREATE TABLE event_v2 (
event_id integer PRIMARY KEY,
customer_id integer REFERENCES customer(customer_id),
action_id integer REFERENCES action(action_id)
);
INSERT INTO event_v2
VALUES
(101, 2, 201),
(102, 2, 204);
CREATE TABLE teacher (
teacher_id integer PRIMARY KEY,
name varchar(256),
age integer
);
INSERT INTO teacher
VALUES
(1, 'Tiffany', 28),
(2, 'Mathew', 35);
CREATE TABLE student (
student_id integer PRIMARY KEY,
name varchar(256),
age integer
);
INSERT INTO student
VALUES
(1, 'Ben', 28),
(2, 'Jenny', 21);Select all the data
SELECT * FROM customer;
SELECT * FROM event;
SELECT * FROM action;
SELECT * FROM event_v2;
SELECT * FROM teacher;
SELECT * FROM student;Overview (`lessons/170/README.md`)
Kubernetes Node Selector vs Node Affinity vs Pod Affinity vs Tains & Tolerations
You can find tutorial here.
Start minikube with 3 nodes
minikube start --nodes 3 --driver=dockerGet Kubernetes node labels
kubectl get node --show-labelsSet the node label
# kubectl label nodes <node> <label-key>=<label-value>
kubectl label nodes minikube-m03 disktype=ssdSet the node taint
# kubectl taint nodes <node> <taint-key>=<taint-value>:<taint-effect>
kubectl taint nodes minikube-m03 price=spot:NoScheduleLinks
Overview (`lessons/171/README.md`)
Most Common Kubernetes Deployment Strategies (Examples & Code)
You can find tutorial here.
Start Minikube
minikube start --driver=dockerDeploy Prometheus (apply 2 times)
kubectl apply --server-side -R -f monitoring/Install Istio & Flagger
cd terraform
terraform applyTest application
kubectl run curl --image=alpine/curl:8.2.1 -n kube-system -i --tty --rm -- sh
for i in `seq 1 1000`; do curl myapp.default:8181/version; echo ""; sleep 1; doneOverview (`lessons/172/README.md`)
Linkerd vs. Istio (Rust vs. C++) performance benchmark
You can find tutorial here.
Overview (`lessons/173/README.md`)
Kubernetes Canary Deployment (Manual vs Automated)
You can find tutorial here.
Start Minikube
minikube start --driver=dockerDeploy All Dependencies
cd terraform
terraform applyGrafana
# username: admin, password: devops123
kubectl port-forward svc/grafana 3000 -n monitoringTest application (Example 1)
kubectl run curl --image=alpine/curl:8.2.1 -n default -i --tty --rm -- sh
for i in `seq 1 1000`; do curl myapp:8080/version; echo ""; sleep 1; doneTest application (Example 2)
kubectl run curl --image=alpine/curl:8.2.1 -n staging -i --tty --rm -- sh
for i in `seq 1 1000`; do curl myapp:8080/version; echo ""; sleep 1; doneOverview (`lessons/174/README.md`)
Kubernetes Ingress Explained (2 Types)
You can find tutorial here.
Overview (`lessons/175/README.md`)
AWS App Mesh Tutorial (EKS | Ingress | Terraform)
You can find tutorial here.
Overview (`lessons/176/README.md`)
Crossplane Tutorial (vs Terraform): Create AWS VPC - EKS - IRSA - Cluster Autoscaler - CSI Driver
You can find tutorial here.
Install Crossplane on Kubernetes
minikube start --driver=docker
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm search repo crossplane
helm install crossplane \
--namespace crossplane-system \
--create-namespace \
--version 1.13.2 \
crossplane-stable/crossplane
kubectl get pods -n crossplane-system
kubectl get crds | grep crossplane.ioCreate S3 Bucket using Crossplane
kubectl apply -f 0-crossplane/1-provider-aws-s3.yaml
kubectl get providers
kubectl get pods -n crossplane-system
kubectl get crds | grep aws.upbound.io
kubectl create secret generic aws-secret \
-n crossplane-system \
--from-file=creds=./aws-credentials.txt
kubectl apply -f 0-crossplane/0-provider-aws-config.yaml
kubectl apply -f 1-s3/0-my-bucket.yaml
kubectl get bucket
kubectl describe bucket
kubectl get bucket
kubectl apply -f 1-s3/1-my-bucket-versioning.yaml
kubectl get bucketversioningCreate AWS VPC using Crossplane
kubectl apply -f 0-crossplane/2-provider-aws-ec2.yaml
kubectl get providers
kubectl apply -f 2-vpc
kubectl get VPC
kubectl get InternetGateway
kubectl get RouteTableAssociationCreate EKS Cluster using Crossplane
kubectl apply -f 0-crossplane
kubectl get providers
kubectl apply -f 3-eks
kubectl get Cluster
kubectl get NodeGroup
aws configure --profile crossplane
aws eks update-kubeconfig --name dev-demo --region us-east-2 --profile crossplane
kubectl get nodesCreate OpenID Connect Provider (OIDC)
kubectl apply -f 4-irsa
kubectl get OpenIDConnectProvider
kubectl get AddonDeploy EBS CSI driver
kubectl apply -f 5-storageclassDeploy Cluster Autoscaler
helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm search repo cluster-autoscaler
helm install autoscaler \
--namespace kube-system \
--version 9.29.3 \
--values 6-cluster-autoscaler/1-helm-values.yaml \
autoscaler/cluster-autoscalerOverview (`lessons/177/README.md`)
Azure Kubernetes Service (AKS) Tutorial: (Terraform - Nginx Ingress & TLS - OIDC Workload Identity)
You can find tutorial here.
Create AKS cluster using Terraform
az login
az account list
az account set --subscription <id>
terraform init
terraform apply
az aks get-credentials --resource-group tutorial --name dev-demoCreate Public and Private load balancers
kubectl apply -f k8s/1-example
kubectl get svc
curl http://<ip>/Auto-Scaling
kubectl get nodes
kubectl apply -f k8s/2-example
kubectl get pods
kubectl describe pods nginx-v2-788b5579fd-dmbg8
kubectl get pods
kubectl get nodesCreate an Ingress using Nginx Ingress
kubectl get svc -n ingress
kubectl apply -f k8s/3-example
kubectl get pods
kubectl get ing
curl --resolve "echo.antonputra.pvt:80:20.96.71.30" http://echo.antonputra.pvt/Secure the Ingress with TLS & Cert-manager
kubectl apply -f k8s/4-example
kubectl get pods
kubectl get ing
kubectl get Certificate
kubectl describe Certificate
kubectl describe CertificateRequest
kubectl describe Order
kubectl describe Challenge
kubectl get ing
kubectl get Certificate
dig echo.devopsbyexample.com
kubectl get ingTest Workload Identity
kubectl apply -f k8s/5-example
kubectl get pods -n dev
kubectl exec -it azure-cli-c97fd4f7c-rp2mc -n dev -- sh
az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID
az storage blob list -c test --account-name devtest2392919
kubectl delete -f k8s/5-exampleOverview (`lessons/178/README.md`)
OpenTelemetry Golang Tutorial (Tracing in Grafana & Kubernetes & Tempo)
You can find tutorial here.
Commands from the Tutorial
git clone [email protected]:antonputra/tutorials.git
cd tutorials/lessons/178
cd terraform
terraform init
terraform apply
cd ..
cd myapp
go mod tidy
kubectl get pods -n monitoring
kubectl port-forward svc/tempo 4318 -n monitoring
export OTLP_ENDPOINT=localhost:4318
curl http://0.0.0.0:8080/devices
kubectl port-forward svc/grafana 3000:80 -n monitoring
# Datasource URL: http://tempo.monitoring:3100
kubectl apply -f k8s
kubectl get pods -n default
kubectl get svc -n default
kubectl port-forward svc/myapp 8080:8080 -n defaultOverview (`lessons/179/README.md`)
ArgoCD Notifications (Successful/Failed Deployments)
You can find tutorial here.
Commands from the Tutorial
minikube start
cd terraform
terraform init
terraform apply
kubectl get pods -n argocd
kubectl get svc -n argocd
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
kubectl port-forward svc/argocd-server 8080:80 -n argocd
git add .
git commit -m 'deploy nginx to staging'
git push origin main
kubectl apply -f k8s/
git add .
git commit -m 'fix the bug'
git push origin main
kubectl get application nginx -o yaml -n argocd
git add .
git commit -m 'update spec for nginx deployment'
git push origin main# nginx/deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25.0
ports:
- containerPort: 80Overview (`lessons/180/README.md`)
Go (Golang) vs Python Performance Benchmark (Kubernetes - OpenTelemetry - Prometheus - Grafana)
You can find tutorial here.
Commands from the Tutorial
kubectl port-forward svc/tempo 4317 -n monitoring
kubectl port-forward svc/prometheus-operated 9090 -n monitoring
kubectl apply -R -f lessons/180/deployment
kubectl apply -f 1-test
kubectl apply -f 2-testOverview (`lessons/181/README.md`)
Kubernetes Autoscaling: HPA vs. VPA vs. Keda vs. CA vs. Karpenter vs. Fargate
You can find tutorial here.
Overview (`lessons/182/README.md`)
Kubernetes Workload Resources: App vs. Container vs. Pod vs. Deployment vs. StatefulSets & More
You can find tutorial here.
Overview (`lessons/184/README.md`)
Kubernetes Health Checks: Liveness vs. Readiness vs. Startup Probe
You can find tutorial here.
Overview (`lessons/185/README.md`)
Kubernetes Architecture
You can find tutorial here.
Overview (`lessons/186/README.md`)
Apache Kafka Architecture
You can find tutorial here.
Overview (`lessons/187/README.md`)
Docker vs Kubernetes vs Containerd
You can find tutorial here.
Overview (`lessons/188/README.md`)
Docker Networking Tutorial (Bridge - None - Host - IPvlan - Macvlan - Overlay)
You can find tutorial here.
Commands from the Tutorial
Bridge
docker network ls
docker network inspect bridge
docker run -d --name myapp -p 8081:8080 aputra/myapp-188:v3
docker ps
docker inspect myapp
curl localhost:8081/api/info
docker run -d --name myapp-v2 -p 8082:8080 aputra/myapp-188:v3
docker ps
curl localhost:8081/api/info
curl localhost:8082/api/info
docker exec -it myapp sh
curl 172.17.0.2:8080/api/info
curl 172.17.0.3:8080/api/info
curl myapp-v2:8080/api/info
docker rm -f myapp myapp-v2
docker network create my-bridge-net --subnet 10.0.0.0/19 --gateway 10.0.0.1
docker network ls
docker network inspect my-bridge-net
docker run -d --name myapp -p 8081:8080 --network my-bridge-net aputra/myapp-188:v3
docker run -d --name myapp-v2 -p 8082:8080 --network my-bridge-net aputra/myapp-188:v3
curl localhost:8081/api/info
curl localhost:8082/api/info
docker exec -it myapp sh
curl myapp-v2:8080/api/info
docker rm -f myapp myapp-v2
docker network rm my-bridge-net
docker compose -f 1-compose.yaml up -dHost
docker run -d --name myapp --network host aputra/myapp-188:v3
docker ps
curl 192.168.50.55:8080/api/info
docker rm -f myappNone
docker run -d --name myapp --network none aputra/myapp-188:v3
docker exec myapp ip addr
docker run -d --name myapp -p 8081:8080 --network none aputra/myapp-188:v3
docker run -d --name myapp -p 8081:8080 aputra/myapp-188:v3
curl localhost:8081/api/infoIPvlan
ip addr
docker network create -d ipvlan \
--subnet=192.168.50.0/24 \
--gateway=192.168.50.1 \
-o ipvlan_mode=l2 \
-o parent=ens33 my-ipvlan-net
docker network ls
docker run -d --name myapp --network my-ipvlan-net aputra/myapp-188:v3
docker inspect myapp
curl 192.168.50.2:8080/api/infoMacvlan
docker network create -d macvlan \
--subnet=192.168.50.0/24 \
--gateway=192.168.50.1 \
-o parent=ens33 my-macvlan-net
docker network ls
docker run -d --name myapp --network my-macvlan-net aputra/myapp-188:v3
docker inspect myapp
docker exec -it myapp shOverlay
(host 1) ip addr
(host 1) sudo ethtool -K ens33 tx-checksum-ip-generic off
(host 2) ip addr
(host 2) sudo ethtool -K ens33 tx-checksum-ip-generic off
(host 1) docker swarm init
(host 2) docker swarm join ...
(host 1) docker network create -d overlay --attachable my-overlay-net
(host 1) docker network ls
(host 1) docker run -d --name myapp --network my-overlay-net aputra/myapp-188:v3
(host 2) docker network ls
(host 2) docker run -dit --name myapp-v2 --network my-overlay-net aputra/myapp-188:v3
(host 2) docker network ls
(host 2) docker exec -it myapp-v2 sh
curl myapp:8080/api/infoOverview (`lessons/189/README.md`)
What Is a Graph Database?
You can find tutorial here.
Commands from the Tutorial
docker run \
--publish=7474:7474 \
--publish=7687:7687 \
--env=NEO4J_PLUGINS='["graph-data-science"]' \
--env=NEO4J_AUTH=none \
neo4j:5.17.0open http://localhost:7474/Create a node
MERGE (a:Location {name: 'A'})
RETURN aGet a node
MATCH (a:Location {name: 'A'})
RETURN aCreate another node
MERGE (a:Location {name: 'B'})Select all nodes and relationships
MATCH (n)
RETURN nCreate a relationship between A and B
MATCH (a:Location {name: 'A'})
MATCH (b:Location {name: 'B'})
MERGE (a)-[:ROAD {cost: 50}]->(b)Search these nodes
MATCH (a:Location {name: 'A'})-[:ROAD]-(b:Location {name: 'B'})
RETURN a,bCreate the rest of the nodes
CREATE (c:Location {name: 'C'}),
(d:Location {name: 'D'}),
(e:Location {name: 'E'}),
(f:Location {name: 'F'});Select all nodes and relationships
MATCH (n)
RETURN nCreate the remaining nodes and relationships
MATCH (a:Location {name: 'A'})
MATCH (b:Location {name: 'B'})
MATCH (c:Location {name: 'C'})
MATCH (d:Location {name: 'D'})
MATCH (e:Location {name: 'E'})
MATCH (f:Location {name: 'F'})
MERGE (a)-[:ROAD {cost: 50}]->(c)
MERGE (a)-[:ROAD {cost: 100}]->(d)
MERGE (b)-[:ROAD {cost: 40}]->(d)
MERGE (c)-[:ROAD {cost: 40}]->(d)
MERGE (c)-[:ROAD {cost: 80}]->(e)
MERGE (d)-[:ROAD {cost: 30}]->(e)
MERGE (d)-[:ROAD {cost: 80}]->(f)
MERGE (e)-[:ROAD {cost: 40}]->(f)Select all nodes and relationships
MATCH (n)
RETURN n[Optional] Create nodes and relationships in one statement
CREATE (a:Location {name: 'A'}),
(b:Location {name: 'B'}),
(c:Location {name: 'C'}),
(d:Location {name: 'D'}),
(e:Location {name: 'E'}),
(f:Location {name: 'F'}),
(a)-[:ROAD {cost: 50}]->(b),
(a)-[:ROAD {cost: 50}]->(c),
(a)-[:ROAD {cost: 100}]->(d),
(b)-[:ROAD {cost: 40}]->(d),
(c)-[:ROAD {cost: 40}]->(d),
(c)-[:ROAD {cost: 80}]->(e),
(d)-[:ROAD {cost: 30}]->(e),
(d)-[:ROAD {cost: 80}]->(f),
(e)-[:ROAD {cost: 40}]->(f);Create index
CALL gds.graph.project(
'myGraph',
'Location',
'ROAD',
{
relationshipProperties: 'cost'
}
)Calculate the shortest route
MATCH (source:Location {name: 'A'}), (target:Location {name: 'F'})
CALL gds.shortestPath.dijkstra.stream('myGraph', {
sourceNode: source,
targetNode: target,
relationshipWeightProperty: 'cost'
})
YIELD index, sourceNode, targetNode, totalCost, nodeIds, costs, path
RETURN
index,
gds.util.asNode(sourceNode).name AS sourceNodeName,
gds.util.asNode(targetNode).name AS targetNodeName,
totalCost,
[nodeId IN nodeIds | gds.util.asNode(nodeId).name] AS nodeNames,
costs,
nodes(path) as path
ORDER BY indexOverview (`lessons/190/README.md`)
What is a Reverse Proxy? (vs. Forward Proxy) | Proxy servers explained
You can find tutorial here.
Overview (`lessons/191/README.md`)
Types of Load Balancing Algorithms
You can find tutorial here.
Overview (`lessons/192/README.md`)
Kubernetes RBAC Explained
You can find tutorial here.
Overview (`lessons/193/README.md`)
How to debug Kubernetes? (Deployments, Services & Ingress)
You can find tutorial here.
Overview (`lessons/194/README.md`)
How to debug Kubernetes Ingress? (TLS - Cert-Manager - HTTP-01 & DNS-01 Challenges)
You can find tutorial here.
Overview (`lessons/195/README.md`)
AWS EKS Kubernetes Tutorial
You can find tutorial here.
Overview (`lessons/196/README.md`)
AWS EKS Kubernetes Tutorial
You can find tutorial here.
Changes from EKS 1.29 to 1.30
- AWS Load Balancer controller now requires
vpcId. - There is no longer a default storage class in EKS, so you need to explicitly set
storageClassName: gp2. - Updated all EKS add-ons and Helm chart versions used in this tutorial.
Clean Up
- Manually delete IAM user secret keys from the AWS Console.
terraform destroy --target helm_release.external_nginxterraform destroy
Overview (`lessons/197/README.md`)
Kubernetes Tutorial for Beginners
You can find tutorial here.
Overview (`lessons/199/README.md`)
Docker Compose Tutorial for Beginners (Networks - Volumes - Secrets - Postgres - Letsencrypt)
You can find tutorial here.
Commands
python3 -m venv .venv
source .venv/bin/activate
pip install Flask
pip freeze > requirements.txt
flask --app app run
curl 127.0.0.1:5000/about
export APP_VERSION=0.1.0
env | grep APP_VERSION
pip install gunicorn
docker build -t aputra/flask:0.1.0 .
docker run -p 7070:8080 aputra/flask:0.1.0
curl localhost:7070/about
docker run -p 7070:8080 -e APP_VERSION=0.1.0 aputra/flask:0.1.0
deactivate
docker compose up
docker build -t aputra/flask:latest .
docker compose up --build
APP_TOKEN=secret123 docker compose up
curl -X POST localhost:7070/volumes
curl -X GET localhost:7070/volumes
docker ps
docker exec -it 199-postgres-1 psql -h localhost -p 5432 -U myuser -d mydb
CREATE TABLE item (
item_id serial PRIMARY KEY,
priority varchar(256),
task varchar(256)
);
CREATE USER myapp WITH PASSWORD 'devops123';
GRANT ALL PRIVILEGES ON DATABASE mydb to myapp;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO myapp;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO myapp;
pip install "psycopg[binary,pool]"
curl -H "Content-Type: application/json" -d '{"priority":"high","task":"doctor appointment"}' localhost:7070/items
curl -H "Content-Type: application/json" -d '{"priority":"low","task":"buy dinner"}' localhost:7070/items
SELECT * FROM item;
curl localhost:7070/itemsOverview (`lessons/200/README.md`)
How to Set Up ArgoCD for Production? (EKS - ECR - Helm - App of Apps - Image Updater - GitOps)
You can find tutorial here.
Overview (`lessons/201/README.md`)
Java (Quarkus) vs. Go (Golang): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/202/README.md`)
C# (.NET) vs. Go (Golang): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/203/README.md`)
Rust (Actix) vs. Go (Golang): Performance Benchmark in Kubernetes (EKS)
You can find tutorial here.
Overview (`lessons/204/README.md`)
Go (fiber) vs. Go (stdlib) vs. Go (gin): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/205/README.md`)
Rust (Actix) vs. Go (Stdlib): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/206/README.md`)
Rust (Actix) vs Rust (Axum) vs Rust (Rocket): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/207/README.md`)
Zap (Zig) vs Actix (Rust) vs http.zig (Zig): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/208/README.md`)
Actix (Rust) vs Zap (Zig) vs Stdlib (Zig): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/209/README.md`)
Django (Python) vs Stdlib (Go): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/210/README.md`)
Node.js vs Golang: Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/211/README.md`)
Node.js vs Golang (Round 2): Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/212/README.md`)
Bun vs Node.js: Performance Benchmark in Kubernetes
You can find tutorial here.
Overview (`lessons/213/README.md`)
Go (Golang) vs. Bun: Performance (Latency - Throughput - Saturation - Availability)
You can find tutorial here.
Overview (`lessons/214/README.md`)
MySQL vs PostgreSQL Performance Benchmark (Latency - Throughput - Saturation)
You can find tutorial here.
Overview (`lessons/215/README.md`)
Rust vs Zig vs Go: Performance (Latency - Throughput - Saturation - Availability)
You can find tutorial here.
Overview (`lessons/216/README.md`)
MySQL vs PostgreSQL (Round 2) Performance Benchmark (Latency - Throughput - Saturation)
You can find tutorial here.
Hardware Details
| EC2 type | i3en.large |
|---|---|
| vCPU | 2 |
| Memory (GiB) | 16 |
| Storage (GB) | 1 x 1250 NVMe SSD |
| Network (Gbps) | Up to 25 |
I'll use an i3en.large in the following test and may scale it up to an i3en.xlarge or i3en.2xlarge in future tests.
Database Configuration
Credit to @melroy89 and @nscuro for the initial database configuration settings.
To tune PostgreSQL, I used Pgtune, and for MySQL, I used MySQLTuner-perl.
Database Schema
/* Detailed source-code truncated for AI context efficiency. */Test Design
The goal is to test CRUD operations, not to implement actual shopping cart functionality. Also, I'm not using transactions to be able to measure the performance of each query from the client side.
-- Create shopping cart
INSERT INTO cart(customer_id, total) VALUES (4, 0);
-- Add body wash to the cart
INSERT INTO cart_item(cart_id, product_id, quantity) VALUES (1, 7, 1);
-- Update value of the cart
UPDATE cart SET total = 10.10 WHERE customer_id = 4;
-- Add 2 shampoos the cart
INSERT INTO cart_item(cart_id, product_id, quantity) VALUES (1, 1, 2);
-- Update value of the cart
UPDATE cart SET total = 25.90 WHERE customer_id = 4;
-- Create an order
INSERT INTO "order"(customer_id, total) VALUES (4, 25.90);
-- Add body wash to the order
INSERT INTO order_item(order_id, product_id, quantity) VALUES (1, 7, 1);
-- Reduce the stock quantity of the body wash
UPDATE product SET stock_quantity = 99 WHERE id = 7;
-- Add 2 shampoos the order
INSERT INTO order_item(order_id, product_id, quantity) VALUES (1, 1, 2);
-- Reduce the stock quantity of the shampoo
UPDATE product SET stock_quantity = 98 WHERE id = 1;
-- Delete shopping cart and items
DELETE FROM cart_item WHERE cart_id = 1;
DELETE FROM cart WHERE id = 1;2nd Test
SELECT
customer.username, customer.first_name, customer.last_name, customer.address, product.name, order_item.quantity, `order`.total
FROM
`order`
LEFT JOIN customer ON customer.id = `order`.customer_id
LEFT JOIN order_item ON order_item.order_id = `order`.id
LEFT JOIN product ON product.id = order_item.product_id
WHERE `order`.id = 431;
SELECT customer.username, customer.first_name, customer.last_name, customer.address, product.name, order_item.quantity, `order`.total FROM `order` LEFT JOIN customer ON customer.id = `order`.customer_id LEFT JOIN order_item ON order_item.order_id = `order`.id LEFT JOIN product ON product.id = order_item.product_id WHERE `order`.id = $1;Overview (`lessons/217/README.md`)
Deno vs. Node.js vs Bun: Performance (Latency - Throughput - Saturation - Availability)
You can find tutorial here.
Overview (`lessons/218/README.md`)
Apache Kafka vs RabbitMQ Performance (Latency - Throughput - Saturation)
You can find tutorial here.
Overview (`lessons/219/README.md`)
Nginx vs Apache Performance (Latency - Throughput - Saturation - Availability | HTTP/2 - TLS - Gzip)
You can find tutorial here.
Apache
/* Detailed source-code truncated for AI context efficiency. */Overview (`lessons/220/README.md`)
Ruby on Rails vs Node.js Performance (Latency - Throughput - Saturation - Availability)
You can find tutorial here.
Overview (`lessons/221/README.md`)
Nginx vs Caddy Performance (Latency - Throughput - Saturation - Availability | HTTP/2 - TLS - Gzip)
You can find tutorial here.
Overview (`lessons/222/README.md`)
Ruby vs Node.js: Performance Benchmark
You can find tutorial here.
Overview (`lessons/223/README.md`)
SQLite vs PostgreSQL
You can find tutorial here.
Database Schema
/* Detailed source-code truncated for AI context efficiency. */Test Design
The goal is to test CRUD operations, not to implement actual shopping cart functionality. Also, I'm not using transactions to be able to measure the performance of each query from the client side.
-- Create shopping cart
INSERT INTO cart(customer_id, total) VALUES (4, 0);
-- Add body wash to the cart
INSERT INTO cart_item(cart_id, product_id, quantity) VALUES (1, 7, 1);
-- Update value of the cart
UPDATE cart SET total = 10.10 WHERE customer_id = 4;
-- Add 2 shampoos the cart
INSERT INTO cart_item(cart_id, product_id, quantity) VALUES (1, 1, 2);
-- Update value of the cart
UPDATE cart SET total = 25.90 WHERE customer_id = 4;
-- Create an order
INSERT INTO "order"(customer_id, total) VALUES (4, 25.90);
-- Add body wash to the order
INSERT INTO order_item(order_id, product_id, quantity) VALUES (1, 7, 1);
-- Reduce the stock quantity of the body wash
UPDATE product SET stock_quantity = 99 WHERE id = 7;
-- Add 2 shampoos the order
INSERT INTO order_item(order_id, product_id, quantity) VALUES (1, 1, 2);
-- Reduce the stock quantity of the shampoo
UPDATE product SET stock_quantity = 98 WHERE id = 1;
-- Delete shopping cart and items
DELETE FROM cart_item WHERE cart_id = 1;
DELETE FROM cart WHERE id = 1;2nd Test
SELECT
customer.username, customer.first_name, customer.last_name, customer.address, product.name, order_item.quantity, `order`.total
FROM
`order`
LEFT JOIN customer ON customer.id = `order`.customer_id
LEFT JOIN order_item ON order_item.order_id = `order`.id
LEFT JOIN product ON product.id = order_item.product_id
WHERE `order`.id = 431;Overview (`lessons/224/README.md`)
Nginx vs Traefik: What Is the BEST Reverse Proxy?
You can find tutorial here.
Overview (`lessons/225/README.md`)
Redis vs Memcached Performance Benchmark
You can find tutorial here.
Overview (`lessons/226/README.md`)
Pingora vs Nginx Performance Benchmark
You can find tutorial here.
Overview (`lessons/227/README.md`)
MongoDB vs. PostgreSQL: Performance & Functionality
You can find tutorial here.
SQL
CREATE TABLE product (
id SERIAL PRIMARY KEY,
jdoc jsonb
);
CREATE INDEX idx__product__price ON product using BTREE(((jdoc -> 'price')::NUMERIC));
INSERT INTO product(jdoc) VALUES ('{"name": "Shampoo", "price": 7.90, "stock": 100}');
INSERT INTO product(jdoc) VALUES ('{"name": "Hairspray", "price": 11.50, "stock": 100}');
UPDATE product SET jdoc = jsonb_set(jdoc, '{stock}', '98') WHERE id = 2;
SELECT id, jdoc->'price' as price, jdoc->'stock' as stock FROM product WHERE (jdoc -> 'price')::numeric < 10;
DELETE FROM product WHERE id = 1;
CREATE VIEW sales AS
SELECT "order".product_id, "order".quantity, inventory.price
FROM "order"
LEFT OUTER JOIN inventory ON "order".product_id = inventory.product_id;
SELECT product_id, SUM(quantity * price) AS amount_sold FROM sales GROUP BY product_id;db.product.insertOne({name: "Shampoo", price: 7.90, stock: 100})
db.product.insertOne({name: "Hairspray", price: 11.50, stock: 100})
db.product.updateOne({ _id: ObjectId("674705957b0ee5f68236d2b1") }, { $set: { 'stock': 98 } })
db.product.find({ price: { $lt: 10 } })
db.product.deleteOne( {"_id": ObjectId("674705957b0ee5f68236d2b1")})
db.createView( "sales", "order", [
{
$lookup:
{
from: "inventory",
localField: "product_id",
foreignField: "product_id",
as: "inventory_docs"
}
},
{
$project:
{
_id: 0,
product_id: 1,
quantity: 1,
price: "$inventory_docs.price"
}
},
{ $unwind: "$price" }
] );
db.sales.aggregate( [
{
$group:
{
_id: "$product_id",
amount_sold: { $sum: { $multiply: [ "$price", "$quantity" ] } }
}
}
] );Overview (`lessons/228/README.md`)
Redis vs Dragonfly Performance (Latency - Throughput - Saturation)
You can find tutorial here.
Install Dragonfly
export VERSION="1.25.4"
wget https://github.com/dragonflydb/dragonfly/releases/download/v${VERSION}/dragonfly_amd64.deb
sudo dpkg -i dragonfly_amd64.deb
sudo tee /etc/dragonfly/dragonfly.conf <<EOF
--pidfile=/var/run/dragonfly/dragonfly.pid
--log_dir=/var/log/dragonfly
--dir=/var/lib/dragonfly
--max_log_size=20
--cache_mode=true
--df_snapshot_format=false
EOF
sudo chown dfly:dfly /etc/dragonfly/dragonfly.conf
sudo systemctl enable dragonfly
sudo systemctl restart dragonfly
sudo systemctl status dragonflyInstall Redis
sudo apt -y install build-essential pkg-config
export REDIS_VER="7.4.1"
wget https://github.com/redis/redis/archive/refs/tags/${REDIS_VER}.tar.gz
tar -xzf ${REDIS_VER}.tar.gz
sudo mv redis-${REDIS_VER}/ /opt/redis
cd /opt/redis/
make
sudo make install
cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF
sudo sysctl vm.overcommit_memory=1
sudo tee /etc/redis.conf <<EOF
maxclients 10000
protected-mode no
appendonly no
save ""
EOF
sudo useradd --system --no-create-home --shell /bin/false redis
sudo chown redis:redis /etc/redis.conf
sudo tee /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=500
StartLimitBurst=5
[Service]
User=redis
Group=redis
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/redis-server /etc/redis.conf
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redisCreate Redis Cluster
export REDIS_VER="7.4.1"
wget https://github.com/redis/redis/archive/refs/tags/${REDIS_VER}.tar.gz
tar -xzf ${REDIS_VER}.tar.gz
sudo mv redis-${REDIS_VER}/ /opt/redis
cd /opt/redis/
make
sudo make install
cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF
sudo sysctl vm.overcommit_memory=1
sudo tee /etc/redis.conf <<EOF
cluster-enabled yes
cluster-config-file /etc/redis/nodes.conf
cluster-node-timeout 5000
dir /etc/redis/
maxclients 10000
protected-mode no
appendonly no
save ""
EOF
sudo useradd --system --no-create-home --shell /bin/false redis
sudo mkdir /etc/redis
sudo chown -R redis:redis /etc/redis
sudo chown redis:redis /etc/redis.conf
sudo tee /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=500
StartLimitBurst=5
[Service]
User=redis
Group=redis
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/redis-server /etc/redis.conf
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redis
redis-cli --cluster create redis-0.antonputra.pvt:6379 redis-1.antonputra.pvt:6379 redis-2.antonputra.pvt:6379 redis-3.antonputra.pvt:6379 --cluster-replicas 0Overview (`lessons/229/README.md`)
FASTEST Go Web Framework: gnet vs fiber vs fasthttp vs net/http?
You can find tutorial here.
Overview (`lessons/230/README.md`)
Elixir vs Go (Golang) Performance (Latency - Throughput - Saturation - Availability)
You can find tutorial here.
Overview (`lessons/231/README.md`)
Python (FastAPI) vs Go (Golang) Performance Benchmark
You can find tutorial here.
Overview (`lessons/232/README.md`)
Python (FastAPI) vs Go (Golang) Performance Benchmark
You can find tutorial here.
Overview (`lessons/233/README.md`)
Elixir vs Go Performance Benchmark (Round 2)
You can find tutorial here.
Overview (`lessons/234/README.md`)
PostgreSQL vs Amazon RDS: Performance & Price
You can find tutorial here.
Overview (`lessons/235/README.md`)
Terraform GCP Tutorial (Getting Started with Google Cloud Platform)
You can find tutorial here.
Overview (`lessons/236/README.md`)
FastAPI vs Node.js Performance
You can find tutorial here.
Overview (`lessons/237/README.md`)
VM vs Kubernetes: Performance ð
You can find tutorial here.
Overview (`lessons/238/README.md`)
Create GKE Cluster using Terraform
You can find tutorial here.
Overview (`lessons/239/README.md`)
FastAPI vs Go (Golang) vs Node.js: Performance & Price
You can find tutorial here.
Overview (`lessons/240/README.md`)
gRPC vs REST vs GraphQL: Comparison & Performance
You can find tutorial here.
Overview (`lessons/241/README.md`)
Deno vs. Node.js vs. Bun: Performance Comparison
You can find tutorial here.
Overview (`lessons/242/README.md`)
Rust vs. Go (Golang): Performance (Only Standard Library)
You can find tutorial here.
Overview (`lessons/243/README.md`)
Rust vs. Go (Golang): Performance 2025
You can find tutorial here.
Overview (`lessons/244/README.md`)
Rust vs. Go (Golang): Performance (Fastest Frameworks + PostgreSQL)
You can find tutorial here.
Overview (`lessons/245/README.md`)
Rust vs C++ Performance
You can find tutorial here.
Commands
# C++
git clone --depth 1 --branch v1.9.9 https://github.com/drogonframework/drogon
cd drogon
git submodule update --init
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make && sudo make install
cd /tmp/drogon-app/build
cmake -DCMAKE_BUILD_TYPE=Release ..
make
## Rust
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh -s -- -y
cd /tmp/rust-app
source $HOME/.cargo/env && cargo build --releaseOverview (`lessons/246/README.md`)
TCP vs UDP Performance (Latency & Throughput)
You can find tutorial here.
Overview (`lessons/247/README.md`)
Actix vs Axum vs May vs Ntex
Actix vs Axum vs Rocket vs Warp
Overview (`lessons/249/README.md`)
TCP vs UDP Performance: HUGE Improvement!
You can find tutorial here.
Overview (`lessons/250/README.md`)
Nginx vs. HAProxy vs. Traefik: Performance
You can find tutorial here.
Overview (`lessons/251/README.md`)
TCP vs UDP performance (Round 3)
You can find tutorial here.
Overview (`lessons/252/README.md`)
Nginx vs. HAProxy: Performance
You can find tutorial here.
Overview (`lessons/253/README.md`)
Redis Streams vs Pub/Sub: Performance
You can find tutorial here.
Overview (`lessons/254/README.md`)
Redis Streams vs Pub/Sub: Performance
You can find tutorial here.
Overview (`lessons/255/README.md`)
Terraform Tutorial on AWS
You can find tutorial here.
Overview (`lessons/256/README.md`)
Terraform AWS VPC Tutorial - Public, Private, and Isolated Subnets
You can find tutorial here.
Overview (`lessons/257/README.md`)
Fastest Rust Framework in 2025? ð Benchmarking the Best!
You can find tutorial here.
Overview (`lessons/258/README.md`)
Redis vs Valkey performance
You can find tutorial here.
Redis
export REDIS_VER="8.0-rc1"
wget https://github.com/redis/redis/archive/refs/tags/${REDIS_VER}.tar.gz
tar -xzf ${REDIS_VER}.tar.gz
sudo mv redis-${REDIS_VER}/ /opt/redis
cd /opt/redis/
make
sudo make install
cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF
sudo sysctl vm.overcommit_memory=1
sudo tee /etc/redis.conf <<EOF
maxclients 10000
protected-mode no
appendonly no
save ""
EOF
sudo useradd --system --no-create-home --shell /bin/false redis
sudo chown redis:redis /etc/redis.conf
sudo tee /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=500
StartLimitBurst=5
[Service]
LimitNOFILE=100000
User=redis
Group=redis
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/redis-server /etc/redis.conf --port 6379
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redisValkey
export VALKEY_VER="8.1.1"
wget https://github.com/valkey-io/valkey/archive/refs/tags/${VALKEY_VER}.tar.gz
tar -xzf ${VALKEY_VER}.tar.gz
sudo mv valkey-${VALKEY_VER}/ /opt/valkey
cd /opt/valkey/
make
sudo make install
cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF
sudo sysctl vm.overcommit_memory=1
sudo tee /etc/valkey.conf <<EOF
maxclients 10000
protected-mode no
appendonly no
save ""
EOF
sudo useradd --system --no-create-home --shell /bin/false valkey
sudo chown valkey:valkey /etc/valkey.conf
sudo tee /etc/systemd/system/valkey.service <<EOF
[Unit]
Description=Valkey
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=500
StartLimitBurst=5
[Service]
LimitNOFILE=100000
User=valkey
Group=valkey
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/valkey-server /etc/valkey.conf --port 6379
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable valkey
sudo systemctl start valkey
sudo systemctl status valkeyOverview (`lessons/263/README.md`)
Rust vs C++ Performance: Can Rust Actually Be Faster?
You can find tutorial here.
Commands
## C++
cmake --preset default -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE="-O3 -ffast-math"
cmake --build build && ./build/app
## Rust
cargo build --releaseOverview (`lessons/264/README.md`)
ZeroMQ vs Aeron: Best for Market Data? Performance (Latency & Throughput)
You can find tutorial here.
Commands
/usr/local/bin/aeronmd \\
-Daeron.threading.mode=DEDICATED \\
-Daeron.conductor.buffer.size=16m \\
-Daeron.driver.event.log=disabled \\
-Daeron.driver.idle.strategy=busy_spin \\
-Daeron.print.configuration=true
## 1st Test
CHANNEL="aeron:udp?endpoint=10.0.89.94:40123" SLEEP_INTERVAL_US="2000" STAGE_INTERVAL_US="2000000" DECREMENT_INTERVAL_US="1" /usr/local/bin/aeron-publisher
CHANNEL="aeron:udp?endpoint=10.0.89.94:40123" /usr/local/bin/aeron-subscriber
CHANNEL="tcp://*:5555" SLEEP_INTERVAL_US="2000" STAGE_INTERVAL_US="2000000" DECREMENT_INTERVAL_US="1" /usr/local/bin/zeromq-publisher
CHANNEL="tcp://10.0.65.17:5555" /usr/local/bin/zeromq-subscriber
# 2nd Test
CHANNEL="aeron:ipc" SLEEP_INTERVAL_US="2000" STAGE_INTERVAL_US="2000000" DECREMENT_INTERVAL_US="1" /usr/local/bin/aeron-publisher
CHANNEL="aeron:ipc" /usr/local/bin/aeron-subscriber
CHANNEL="ipc:///tmp/zmq_bbo" SLEEP_INTERVAL_US="2000" STAGE_INTERVAL_US="2000000" DECREMENT_INTERVAL_US="1" /usr/local/bin/zeromq-publisher
CHANNEL="ipc:///tmp/zmq_bbo" /usr/local/bin/zeromq-subscriberOverview (`lessons/265/README.md`)
Rust vs C++ Performance: Can Rust Actually Be Faster? (Pt. 2)
You can find tutorial here.
Commands
## C++
cmake --preset default -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE="-O3 -ffast-math"
cmake --build build && ./build/app
## Rust
cargo build --releaseOverview (`lessons/268/README.md`)
Build a Secure AWS EKS CI/CD Pipeline: Step-by-Step Tutorial (ArgoCD + GitHub Actions)
You can find tutorial here.
Commands
/* Detailed source-code truncated for AI context efficiency. */Overview (`lessons/269/README.md`)
Reduce AWS Latency by 200x: Drop from 7ms to 35Ξs
You can find tutorial here.
Overview (`lessons/270/README.md`)
How to Create a Fully Private AWS EKS Cluster? (Client VPN & Resolve Private Route 53 DNS Locally)
You can find tutorial here.
Commands
/* Detailed source-code truncated for AI context efficiency. */Overview (`lessons/271/README.md`)
HTTP vs WebSockets: Performance (Latency - CPU - Memory - Network)
You can find tutorial here.
Overview (`lessons/272/README.md`)
Redis vs Valkey: Performance & Comparison
You can find tutorial here.
# ec2: c8g.4xlarg
/usr/local/bin/redis-server --io-threads 9 --save --protected-mode no
/usr/local/bin/valkey-server --io-threads 9 --save --protected-mode noOverview (`lessons/273/README.md`)
Deno vs. Node.js vs. Bun: Performance Comparison
You can find tutorial here.
Overview (`lessons/274/README.md`)
Protobuf vs JSON: Performance Benchmark & Size
You can find tutorial here.
Overview (`lessons/275/README.md`)
Go (Golang) vs TypeScript: Performance Benchmark
You can find tutorial here.
Overview (`lessons/276/README.md`)
Python vs JavaScript Performance: Best Backend Language 2026 (FastAPI vs Bun)
You can find tutorial here.
Overview (`lessons/277/README.md`)
Python vs JavaScript Performance: Best Backend Language 2026 (FastAPI vs Bun)
You can find tutorial here.
Schema
/* Detailed source-code truncated for AI context efficiency. */Test
-- Create shopping cart
INSERT INTO cart(customer_id, total) VALUES (4, 0);
-- Add body wash to the cart
INSERT INTO cart_item(cart_id, product_id, quantity) VALUES (1, 7, 1);
-- Update value of the cart
UPDATE cart SET total = 10.10 WHERE customer_id = 4;
-- Create an order
INSERT INTO "order"(customer_id, total) VALUES (4, 25.90);
-- Add body wash to the order
INSERT INTO order_item(order_id, product_id, quantity) VALUES (1, 7, 1);
-- Reduce the stock quantity of the body wash
UPDATE product SET stock_quantity = 99 WHERE id = 7;
-- Delete shopping cart and items
DELETE FROM cart_item WHERE cart_id = 1;
DELETE FROM cart WHERE id = 1;
-- Select the order
SELECT
oi.id AS order_item_id,
p.name AS product_name,
oi.quantity,
p.price,
(oi.quantity * p.price) AS total_item_price
FROM order_item oi
JOIN product p ON oi.product_id = p.id
WHERE oi.order_id = 1;Overview (`lessons/278/README.md`)
Zig vs Rust Performance Benchmark
You can find tutorial here.
zig build -Doptimize=ReleaseFast
cargo build --releaseOverview (`lessons/279/README.md`)
6 SQL Joins you MUST know! (Animated + Practice)
You can find tutorial here.
To practice SQL, run the following commands:
docker run --detach --name my-postgres --env POSTGRES_PASSWORD=devops123 aputra/postgres-279:v2
docker exec -it my-postgres psql -U postgresInner Join
SELECT *
FROM facebook
INNER JOIN linkedin
ON facebook.name = linkedin.name;Left Join
SELECT *
FROM facebook
LEFT JOIN linkedin
ON facebook.name = linkedin.name;Right Join
SELECT *
FROM facebook
RIGHT JOIN linkedin
ON facebook.name = linkedin.name;Full Outer Join
SELECT *
FROM facebook
FULL OUTER JOIN linkedin
ON facebook.name = linkedin.name;Union
SELECT name, friends
FROM facebook
UNION ALL
SELECT name, connections
FROM linkedin;Cross
SELECT sizes.size, colors.color
FROM sizes
CROSS JOIN colors;Overview (`lessons/280/README.md`)
Kubernetes Networking: NodePort, LoadBalancer, Ingress, or Gateway API?
You can find tutorial here.
Commands:
helm upgrade --install ingress ingress-nginx/ingress-nginx --values values/nginx-ingress.yaml --namespace ingress --create-namespace
kubectl get ingressclass
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml
helm upgrade --install istiod istio/istiod --namespace istio-system --create-namespace
kubectl get gatewayclassOverview (`lessons/281/README.md`)
Redis vs Valkey: Performance & Comparison
You can find tutorial here.
# ec2: c8g.4xlarge -> 16/32
/usr/local/bin/redis-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode no
/usr/local/bin/valkey-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode noRedis
sudo apt -y install build-essential pkg-config
export REDIS_VER="8.6.0"
wget https://github.com/redis/redis/archive/refs/tags/${REDIS_VER}.tar.gz
tar -xzf ${REDIS_VER}.tar.gz
sudo mv redis-${REDIS_VER}/ /opt/redis
cd /opt/redis/
make
sudo make install
cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF
sudo sysctl vm.overcommit_memory=1
sudo useradd --system --no-create-home --shell /bin/false redis
sudo tee /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
LimitNOFILE=100000
User=redis
Group=redis
Type=simple
Restart=on-failure
RestartSec=30s
ExecStart=/usr/local/bin/redis-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode no
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redisValkey
sudo apt -y install build-essential pkg-config
export VALKEY_VER="9.0.2"
wget https://github.com/valkey-io/valkey/archive/refs/tags/${VALKEY_VER}.tar.gz
tar -xzf ${VALKEY_VER}.tar.gz
sudo mv valkey-${VALKEY_VER}/ /opt/valkey
cd /opt/valkey/
make
sudo make install
cat <<EOF | sudo tee -a /etc/sysctl.conf
vm.overcommit_memory = 1
EOF
sudo sysctl vm.overcommit_memory=1
sudo useradd --system --no-create-home --shell /bin/false valkey
sudo tee /etc/systemd/system/valkey.service <<EOF
[Unit]
Description=Valkey
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
LimitNOFILE=100000
User=valkey
Group=valkey
Type=simple
Restart=on-failure
RestartSec=30s
ExecStart=/usr/local/bin/valkey-server --io-threads 9 --io-threads-do-reads yes --save --protected-mode no
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable valkey
sudo systemctl start valkey
sudo systemctl status valkeyOverview (`lessons/050/drage/README.md`)
Description
Nest framework TypeScript starter repository.
Installation
$ npm installRunning the app
# development
$ npm run start
# watch mode
$ npm run start:dev
# production mode
$ npm run start:prodTest
# unit tests
$ npm run test
# e2e tests
$ npm run test:e2e
# test coverage
$ npm run test:covSupport
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.
Stay in touch
- Author - Kamil MyÅliwiec
- Website - https://nestjs.com
- Twitter - @nestframework
License
Nest is MIT licensed.
Overview (`lessons/051/app123/README.md`)
Getting Started with Create React App
This project was bootstrapped with Create React App.
Available Scripts
In the project directory, you can run:
`npm start`
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
`npm test`
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
`npm run build`
Builds the app for production to the build folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
`npm run eject`
Note: this is a one-way operation. Once you eject, you canât go back!
If you arenât satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point youâre on your own.
You donât have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldnât feel obligated to use this feature. However we understand that this tool wouldnât be useful if you couldnât customize it when you are ready for it.
Learn More
You can learn more in the Create React App documentation.
To learn React, check out the React documentation.
Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
`npm run build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
Overview (`lessons/052/app123/README.md`)
Getting Started with Create React App
This project was bootstrapped with Create React App.
Available Scripts
In the project directory, you can run:
`npm start`
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
`npm test`
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
`npm run build`
Builds the app for production to the build folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
`npm run eject`
Note: this is a one-way operation. Once you eject, you canât go back!
If you arenât satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point youâre on your own.
You donât have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldnât feel obligated to use this feature. However we understand that this tool wouldnât be useful if you couldnât customize it when you are ready for it.
Learn More
You can learn more in the Create React App documentation.
To learn React, check out the React documentation.
Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
`npm run build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
Overview (`lessons/110/www.devopsbyexample.io/README.md`)
Getting Started with Create React App
This project was bootstrapped with Create React App.
Available Scripts
In the project directory, you can run:
`npm start`
Runs the app in the development mode.
Open http://localhost:3000 to view it in your browser.
The page will reload when you make changes.
You may also see any lint errors in the console.
`npm test`
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
`npm run build`
Builds the app for production to the build folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
`npm run eject`
Note: this is a one-way operation. Once you eject, you can't go back!
If you aren't satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
Learn More
You can learn more in the Create React App documentation.
To learn React, check out the React documentation.
Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
`npm run build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
Overview (`lessons/146/demo-certs/README.md`)
Generate Certificate Authority
cfssl gencert -initca ca-csr.json | cfssljson -bare caGenerate Certificate for the client
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo api-nginx-antonputra-pvt-csr.json | cfssljson -bare api-nginx-antonputra-pvtOverview (`lessons/147/demo-certs/README.md`)
Generate Certificate Authority
cfssl gencert -initca ca-csr.json | cfssljson -bare caGenerate Certificate for the client
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo api-rust-antonputra-pvt-csr.json | cfssljson -bare api-rust-antonputra-pvtOverview (`lessons/149/demo-certs/README.md`)
Generate Certificate Authority
cfssl gencert -initca ca-csr.json | cfssljson -bare caGenerate Certificate for the client
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo rest-antonputra-pvt-csr.json | cfssljson -bare rest-antonputra-pvt
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo grpc-antonputra-pvt-csr.json | cfssljson -bare grpc-antonputra-pvtOverview (`lessons/151/demo-certs/README.md`)
Generate Certificate Authority
cfssl gencert -initca ca-csr.json | cfssljson -bare caGenerate Certificate for the client
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo api-envoy-antonputra-pvt-csr.json | cfssljson -bare api-envoy-antonputra-pvt
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo api-nginx-antonputra-pvt-csr.json | cfssljson -bare api-nginx-antonputra-pvtOverview (`lessons/153/demo-certs/README.md`)
Generate Certificate Authority
cfssl gencert -initca ca-csr.json | cfssljson -bare caGenerate Certificate for the client
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo caddy-antonputra-pvt-csr.json | cfssljson -bare caddy-antonputra-pvt
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=demo traefik-antonputra-pvt-csr.json | cfssljson -bare traefik-antonputra-pvtOverview (`lessons/182/0-app/README.md`)
How to run the application locally?
Navigate to the '0-app' directory
cd tutorials/lessons/182/0-appDownload the application's dependencies
go mod tidyRun the application
go run .Access the application from a separate terminal window
curl -i localhost:8080/api/devicesGet the current status of the application.
curl -i localhost:8080/statusOverview (`lessons/182/1-container/README.md`)
How to build container image?
Navigate to the '1-container' directory
cd tutorials/lessons/182/1-containerBuild container image
docker build -t <your-username>/myapp:0.1.0 .Log in to Docker Hub to upload the image
docker login --username <your-username>Push the container image to the remote repository
docker push <your-username>/myapp:0.1.0Overview (`lessons/182/2-pod/README.md`)
How to create a pod in Kubernetes?
Set up a local Kubernetes cluster using Minikube
minikube startDeploy a standalone pod in Kubernetes
kubectl apply -f 2-pod/0-pod.yamlGet the list of pods in the default namespace
kubectl get podsTail the logs from the pod
kubectl logs -f myappOverview (`lessons/191/3-dns-round-robin/README.md`)
Instructions
Create DNS A record
host: api
type: A
ttl: as small as posible
values:
- 10.0.0.1
- 10.0.0.2
- 10.0.0.3
dig api.devopsbyexample.com
Overview (`lessons/193/myapp/README.md`)
myapp
This project uses Quarkus, the Supersonic Subatomic Java Framework.
If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ .
Running the application in dev mode
You can run your application in dev mode that enables live coding using:
./mvnw compile quarkus:devNOTE: Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/.
Packaging and running the application
The application can be packaged using:
./mvnw packageIt produces the quarkus-run.jar file in the target/quarkus-app/ directory.
Be aware that itâs not an Þber-jar as the dependencies are copied into the target/quarkus-app/lib/ directory.
The application is now runnable using java -jar target/quarkus-app/quarkus-run.jar.
If you want to build an Þber-jar, execute the following command:
./mvnw package -Dquarkus.package.type=uber-jarThe application, packaged as an Þber-jar, is now runnable using java -jar target/*-runner.jar.
Creating a native executable
You can create a native executable using:
./mvnw package -DnativeOr, if you don't have GraalVM installed, you can run the native executable build in a container using:
./mvnw package -Dnative -Dquarkus.native.container-build=trueYou can then execute your native executable with: ./target/myapp-0.1.0-runner
If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.
Provided Code
REST
Easily start your REST Web Services
Overview (`lessons/200/java-app/README.md`)
java-app
This project uses Quarkus, the Supersonic Subatomic Java Framework.
If you want to learn more about Quarkus, please visit its website: https://quarkus.io/.
Running the application in dev mode
You can run your application in dev mode that enables live coding using:
./mvnw compile quarkus:devNOTE: Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/.
Packaging and running the application
The application can be packaged using:
./mvnw packageIt produces the quarkus-run.jar file in the target/quarkus-app/ directory.
Be aware that itâs not an Þber-jar as the dependencies are copied into the target/quarkus-app/lib/ directory.
The application is now runnable using java -jar target/quarkus-app/quarkus-run.jar.
If you want to build an Þber-jar, execute the following command:
./mvnw package -Dquarkus.package.jar.type=uber-jarThe application, packaged as an Þber-jar, is now runnable using java -jar target/*-runner.jar.
Creating a native executable
You can create a native executable using:
./mvnw package -DnativeOr, if you don't have GraalVM installed, you can run the native executable build in a container using:
./mvnw package -Dnative -Dquarkus.native.container-build=trueYou can then execute your native executable with: ./target/java-app-0.1.0-runner
If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.
Provided Code
REST
Easily start your REST Web Services
Overview (`lessons/201/java-app-reactive/README.md`)
java-app
This project uses Quarkus, the Supersonic Subatomic Java Framework.
If you want to learn more about Quarkus, please visit its website: https://quarkus.io/.
Running the application in dev mode
You can run your application in dev mode that enables live coding using:
./mvnw compile quarkus:devNOTE: Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/.
Packaging and running the application
The application can be packaged using:
./mvnw packageIt produces the quarkus-run.jar file in the target/quarkus-app/ directory.
Be aware that itâs not an Þber-jar as the dependencies are copied into the target/quarkus-app/lib/ directory.
The application is now runnable using java -jar target/quarkus-app/quarkus-run.jar.
If you want to build an Þber-jar, execute the following command:
./mvnw package -Dquarkus.package.jar.type=uber-jarThe application, packaged as an Þber-jar, is now runnable using java -jar target/*-runner.jar.
Creating a native executable
You can create a native executable using:
./mvnw package -DnativeOr, if you don't have GraalVM installed, you can run the native executable build in a container using:
./mvnw package -Dnative -Dquarkus.native.container-build=trueYou can then execute your native executable with: ./target/java-app-0.1.0-runner
If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.
Provided Code
REST
Easily start your REST Web Services
Overview (`lessons/201/java-app/README.md`)
java-app
This project uses Quarkus, the Supersonic Subatomic Java Framework.
If you want to learn more about Quarkus, please visit its website: https://quarkus.io/.
Running the application in dev mode
You can run your application in dev mode that enables live coding using:
./mvnw compile quarkus:devNOTE: Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/.
Packaging and running the application
The application can be packaged using:
./mvnw packageIt produces the quarkus-run.jar file in the target/quarkus-app/ directory.
Be aware that itâs not an Þber-jar as the dependencies are copied into the target/quarkus-app/lib/ directory.
The application is now runnable using java -jar target/quarkus-app/quarkus-run.jar.
If you want to build an Þber-jar, execute the following command:
./mvnw package -Dquarkus.package.jar.type=uber-jarThe application, packaged as an Þber-jar, is now runnable using java -jar target/*-runner.jar.
Creating a native executable
You can create a native executable using:
./mvnw package -DnativeOr, if you don't have GraalVM installed, you can run the native executable build in a container using:
./mvnw package -Dnative -Dquarkus.native.container-build=trueYou can then execute your native executable with: ./target/java-app-0.1.0-runner
If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.
Provided Code
REST
Easily start your REST Web Services
Overview (`lessons/207/http.zig/README.md`)
Pure Zig port, using http.zig
Note that there are some very app specific tweaks in the server config here, to tailor this server to the intended environment.
This doesnt do much for performance, but its mainly to get the memory usage down
Comparison with Rust
On a Mac M2, im seeing these figures on local
testing with
wrk -c 100 -d 30 -t 4 http://localhost:8080/healthzwrk -c 100 -d 30 -t 4 http://localhost:8080/api/devices
There is really no difference between the healthz endpoint and the api/devices endpoint that needs to JSONify a struct ... so really all the time is being spent doing IO
Rust in --release mode
2.5 MB Binary
6 MB Memory
4 Threads
Running 30s test @ http://localhost:8086/api/devices
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 440.79us 167.31us 4.09ms 83.65%
Req/Sec 46.01k 2.53k 51.07k 79.40%
5511737 requests in 30.10s, 856.79MB read
Requests/sec: 183100.15
Transfer/sec: 28.46MBHTTP.zig in ReleaseSmall mode
141kb Binary
2 MB Memory
4 Threads
Running 30s test @ http://localhost:8086/api/devices
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 507.73us 184.11us 4.19ms 85.25%
Req/Sec 48.57k 10.33k 57.82k 80.48%
5819106 requests in 30.10s, 688.14MB read
Requests/sec: 193313.51
Transfer/sec: 22.86MBHTTP.zig in ReleaseFast mode
Running 30s test @ http://localhost:8086/api/devices
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 492.28us 185.23us 6.05ms 83.81%
Req/Sec 50.01k 11.59k 60.59k 79.05%
5985889 requests in 30.10s, 707.86MB read
Requests/sec: 198855.02
Transfer/sec: 23.52MBRunning both with Debug compiles, similar story
Actix compiled in Debug mode
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.50ms 230.25us 5.05ms 86.76%
Req/Sec 16.73k 2.05k 67.69k 83.85%
1999217 requests in 30.10s, 310.78MB read
Requests/sec: 66409.49
Transfer/sec: 10.32MBZig compiled in Debug mode
Thread Stats Avg Stdev Max +/- Stdev
Latency 0.88ms 281.05us 20.30ms 91.38%
Req/Sec 28.58k 2.83k 59.14k 87.60%
3418569 requests in 30.10s, 404.26MB read
Requests/sec: 113569.44
Transfer/sec: 13.43MBTL;DR - much of a muchness for runtime performance ! There really isnt anything between them
Actix generally has better latency, and less scatter (std deviation)
Zig has a better peak throughput, and uses 1 third the memory (at least with these config tweaks)
The main difference (to me) is that the Actix build is pulling in a huge number of dependencies :(
The zig code is only pulling in 1 dependency
Overview (`lessons/208/http.zig/README.md`)
Pure Zig port, using http.zig
Note that there are some very app specific tweaks in the server config here, to tailor this server to the intended environment.
This doesnt do much for performance, but its mainly to get the memory usage down
Comparison with Rust
On a Mac M2, im seeing these figures on local
testing with
wrk -c 100 -d 30 -t 4 http://localhost:8080/healthzwrk -c 100 -d 30 -t 4 http://localhost:8080/api/devices
There is really no difference between the healthz endpoint and the api/devices endpoint that needs to JSONify a struct ... so really all the time is being spent doing IO
Rust in --release mode
2.5 MB Binary
6 MB Memory
4 Threads
Running 30s test @ http://localhost:8086/api/devices
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 440.79us 167.31us 4.09ms 83.65%
Req/Sec 46.01k 2.53k 51.07k 79.40%
5511737 requests in 30.10s, 856.79MB read
Requests/sec: 183100.15
Transfer/sec: 28.46MBHTTP.zig in ReleaseSmall mode
141kb Binary
2 MB Memory
4 Threads
Running 30s test @ http://localhost:8086/api/devices
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 507.73us 184.11us 4.19ms 85.25%
Req/Sec 48.57k 10.33k 57.82k 80.48%
5819106 requests in 30.10s, 688.14MB read
Requests/sec: 193313.51
Transfer/sec: 22.86MBHTTP.zig in ReleaseFast mode
Running 30s test @ http://localhost:8086/api/devices
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 492.28us 185.23us 6.05ms 83.81%
Req/Sec 50.01k 11.59k 60.59k 79.05%
5985889 requests in 30.10s, 707.86MB read
Requests/sec: 198855.02
Transfer/sec: 23.52MBRunning both with Debug compiles, similar story
Actix compiled in Debug mode
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.50ms 230.25us 5.05ms 86.76%
Req/Sec 16.73k 2.05k 67.69k 83.85%
1999217 requests in 30.10s, 310.78MB read
Requests/sec: 66409.49
Transfer/sec: 10.32MBZig compiled in Debug mode
Thread Stats Avg Stdev Max +/- Stdev
Latency 0.88ms 281.05us 20.30ms 91.38%
Req/Sec 28.58k 2.83k 59.14k 87.60%
3418569 requests in 30.10s, 404.26MB read
Requests/sec: 113569.44
Transfer/sec: 13.43MBTL;DR - much of a muchness for runtime performance ! There really isnt anything between them
Actix generally has better latency, and less scatter (std deviation)
Zig has a better peak throughput, and uses 1 third the memory (at least with these config tweaks)
The main difference (to me) is that the Actix build is pulling in a huge number of dependencies :(
The zig code is only pulling in 1 dependency
Overview (`lessons/212/bun-app-static/README.md`)
bun-app-static
To install dependencies:
bun installTo run:
bun run app.jsThis project was created using bun init in bun v1.1.29. Bun is a fast all-in-one JavaScript runtime.
Overview (`lessons/212/bun-app/README.md`)
bun-app
To install dependencies:
bun installTo run:
bun run app.jsThis project was created using bun init in bun v1.1.29. Bun is a fast all-in-one JavaScript runtime.
Overview (`lessons/213/bun-app/README.md`)
bun-app
To install dependencies:
bun installTo run:
bun run app.jsThis project was created using bun init in bun v1.1.29. Bun is a fast all-in-one JavaScript runtime.
Overview (`lessons/217/bun-app/README.md`)
bun-app
To install dependencies:
bun installTo run:
bun run app.jsThis project was created using bun init in bun v1.1.29. Bun is a fast all-in-one JavaScript runtime.
Overview (`lessons/219/my-website/README.md`)
This is a Next.js project bootstrapped with create-next-app.
Getting Started
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.js. The page auto-updates as you edit the file.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.
Learn More
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
Deploy on Vercel
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
Overview (`lessons/220/rails-app/README.md`)
README
This README would normally document whatever steps are necessary to get the
application up and running.
Things you may want to cover:
Ruby version
System dependencies
Configuration
Database creation
Database initialization
How to run the test suite
Services (job queues, cache servers, search engines, etc.)
Deployment instructions
...
Overview (`lessons/220/ruby-app/README.md`)
README
Basic Ruby application. 25x faster than Rails on my Mac M1.
To setup database run the following commands:
bin/rake db:create
bin/rake db:migrateTo run the server:
bin/iodine -p 8080Defaults
WORKERS_NUM=2Local benchmark
`rails-app`
WORKERS_NUM=2 RAILS_ENV=production rs
wrk -c 10 -t 2 -d 10 --latency http://localhost:8080/api/devices
Running 10s test @ http://localhost:8080/api/devices
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.12ms 846.12us 31.20ms 94.80%
Req/Sec 2.42k 239.12 2.66k 88.12%
Latency Distribution
50% 1.94ms
75% 2.17ms
90% 2.63ms
99% 5.35ms
48603 requests in 10.10s, 46.07MB read
Requests/sec: 4811.04
Transfer/sec: 4.56MB`ruby-app`
WORKERS_NUM=2 bin/iodine -p 8080 config.ru
wrk -c 10 -t 2 -d 10 --latency http://localhost:8080/api/devices
Running 10s test @ http://localhost:8080/api/devices
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 142.99us 660.05us 21.06ms 99.01%
Req/Sec 48.48k 9.07k 60.82k 63.00%
Latency Distribution
50% 83.00us
75% 112.00us
90% 160.00us
99% 798.00us
965345 requests in 10.01s, 613.14MB read
Requests/sec: 96422.17
Transfer/sec: 61.24MB`ruby-app` with docker
docker build -t ruby-app .
docker run --rm -p 8080:8080 --name ruby-app ruby-app
wrk -c 10 -t 2 -d 10 --latency http://localhost:8080/api/devices
Running 10s test @ http://localhost:8080/api/devices
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 785.27us 3.26ms 62.81ms 97.92%
Req/Sec 12.66k 3.14k 15.44k 84.50%
Latency Distribution
50% 351.00us
75% 430.00us
90% 614.00us
99% 12.92ms
251840 requests in 10.00s, 159.96MB read
Requests/sec: 25176.72
Transfer/sec: 15.99MBOverview (`lessons/221/my-website/README.md`)
This is a Next.js project bootstrapped with create-next-app.
Getting Started
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.js. The page auto-updates as you edit the file.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.
Learn More
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
Deploy on Vercel
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
Overview (`lessons/222/elixir-app/README.md`)
App
To start your Bandit server:
- Run
mix setupto install and setup dependencies - Run
iex -S mixto start the server
Now you can visit localhost:4000 from your browser.
Overview (`lessons/222/ruby-app-node-equivalent/README.md`)
Ruby Device Management API
A Ruby-based HTTP server application for managing IoT devices with PostgreSQL database integration and Prometheus metrics. This is a Ruby equivalent of the Node.js application in the node-app folder.
Overview
This application provides a RESTful API for managing device records, including:
- Device listing and creation
- PostgreSQL database integration
- Prometheus metrics for monitoring
- Health check endpoint
Features
- HTTP Server: Built with Rack and WEBrick
- Database: PostgreSQL integration using the
pggem - Metrics: Prometheus histogram metrics for tracking database operation duration
- RESTful API: Endpoints for device management
- Docker Support: Multi-stage Dockerfile for containerized deployment
Prerequisites
- Ruby 3.3 or higher
- PostgreSQL database
- Bundler gem (usually comes with Ruby)
Installation
- Install dependencies:
bundle installConfiguration
The application uses a config.yaml file for configuration. Create or modify config.yaml:
---
appPort: 8080
db:
user: node
password: devops123
host: postgresql.antonputra.pvt
database: mydb
maxConnections: 75Note: Update the database connection details to match your PostgreSQL setup.
Running the Application
Local Development
- Ensure PostgreSQL is running and accessible
- Make sure the database and
node_devicetable exist (see migration notes below) - Start the server:
ruby app.rbThe server will start on http://0.0.0.0:8080 (or the port specified in config.yaml).
Using Docker
- Build the Docker image:
docker build -t ruby-app-node-equivalent .- Run the container:
docker run -p 8080:8080 ruby-app-node-equivalentAPI Endpoints
GET /api/devices
Returns a list of sample devices.
Response:
[
{
"id": 1,
"uuid": "9add349c-c35c-4d32-ab0f-53da1ba40a2a",
"mac": "5F-33-CC-1F-43-82",
"firmware": "2.1.6",
"created_at": "2024-05-28T15:21:51.137Z",
"updated_at": "2024-05-28T15:21:51.137Z"
},
...
]POST /api/devices
Creates a new device in the database.
Request Body:
{
"mac": "AA-BB-CC-DD-EE-FF",
"firmware": "1.0.0"
}Response (201 Created):
{
"id": 4,
"uuid": "generated-uuid",
"mac": "AA-BB-CC-DD-EE-FF",
"firmware": "1.0.0",
"created_at": "2024-11-08T12:34:56.789Z",
"updated_at": "2024-11-08T12:34:56.789Z"
}Error Response (400 Bad Request):
{
"message": "Error message"
}GET /metrics
Returns Prometheus metrics in text format. This endpoint exposes the myapp_request_duration_seconds histogram metric that tracks database operation durations.
GET /healthz
Health check endpoint. Returns OK if the server is running.
Response:
OKDatabase Schema
The application expects a PostgreSQL table named node_device with the following structure:
CREATE TABLE node_device (
id SERIAL PRIMARY KEY,
uuid VARCHAR(255) NOT NULL,
mac VARCHAR(255) NOT NULL,
firmware VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NOT NULL
);Project Structure
ruby-app-node-equivalent/
âââ app.rb # Main HTTP server application
âââ config.rb # Configuration loader
âââ config.yaml # Configuration file
âââ db.rb # PostgreSQL database connection
âââ devices.rb # Device database operations
âââ metrics.rb # Prometheus metrics setup
âââ Gemfile # Ruby dependencies
âââ Dockerfile # Docker build configuration
âââ .dockerignore # Docker ignore patterns
âââ README.md # This fileDependencies
- pg: PostgreSQL database adapter
- prometheus-client: Prometheus metrics client library
- rack: Web server interface
- yaml: YAML configuration parsing (built-in)
Metrics
The application tracks database operation duration using a Prometheus histogram metric:
- Metric Name:
myapp_request_duration_seconds - Type: Histogram
- Labels:
op(operation type, e.g., "db") - Buckets: Custom buckets optimized for low-latency operations (0.00001 to 17.5 seconds)
Error Handling
- Database errors are caught and returned as 400 Bad Request with an error message
- Invalid JSON in POST requests will result in a 400 error
- All errors are logged to stdout
Notes
- The server uses a 60-second keep-alive timeout
- UUIDs are automatically generated using Ruby's
SecureRandom.uuid - Timestamps are generated in ISO 8601 format with millisecond precision
- The application uses a single PostgreSQL connection (connection pooling can be added if needed)
Overview (`lessons/222/ruby-app/README.md`)
README
Basic Ruby application. 25x faster than Rails on my Mac M1.
To setup database run the following commands:
bin/rake db:create
bin/rake db:migrateTo run the server:
bin/iodine -p 8080Defaults
WORKERS_NUM=2
RAILS_MAX_THREADS=2Local benchmark
`rails-app`
WORKERS_NUM=2 RAILS_MAX_THREADS=2 RAILS_ENV=production rs
wrk -c 10 -t 2 -d 10 --latency http://localhost:8080/api/devices
Running 10s test @ http://localhost:8080/api/devices
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.12ms 846.12us 31.20ms 94.80%
Req/Sec 2.42k 239.12 2.66k 88.12%
Latency Distribution
50% 1.94ms
75% 2.17ms
90% 2.63ms
99% 5.35ms
48603 requests in 10.10s, 46.07MB read
Requests/sec: 4811.04
Transfer/sec: 4.56MB`ruby-app`
WORKERS_NUM=2 RAILS_MAX_THREADS=2 bin/iodine -p 8080 config.ru
wrk -c 10 -t 2 -d 10 --latency http://localhost:8080/api/devices
Running 10s test @ http://localhost:8080/api/devices
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 142.99us 660.05us 21.06ms 99.01%
Req/Sec 48.48k 9.07k 60.82k 63.00%
Latency Distribution
50% 83.00us
75% 112.00us
90% 160.00us
99% 798.00us
965345 requests in 10.01s, 613.14MB read
Requests/sec: 96422.17
Transfer/sec: 61.24MB`ruby-app` with docker
docker build -t ruby-app .
docker run --rm -p 8080:8080 --name ruby-app ruby-app
wrk -c 10 -t 2 -d 10 --latency http://localhost:8080/api/devices
Running 10s test @ http://localhost:8080/api/devices
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 785.27us 3.26ms 62.81ms 97.92%
Req/Sec 12.66k 3.14k 15.44k 84.50%
Latency Distribution
50% 351.00us
75% 430.00us
90% 614.00us
99% 12.92ms
251840 requests in 10.00s, 159.96MB read
Requests/sec: 25176.72
Transfer/sec: 15.99MBOverview (`lessons/226/actix-app/README.md`)
Logging
RUST_LOG=debug RUST_PORT=8080 cargo runOverview (`lessons/230/elixir-app/README.md`)
App
To start your Bandit server:
- Run
mix setupto install and setup dependencies - Run
iex -S mixto start the server
Now you can visit localhost:4000 from your browser.
Overview (`lessons/233/elixir-app/README.md`)
App
To start your Bandit server:
- Run
mix setupto install and setup dependencies - Run
iex -S mixto start the server
Now you can visit localhost:4000 from your browser.
Overview (`lessons/241/bun-app/README.md`)
bun-app
To install dependencies:
bun installTo run:
bun run app.jsThis project was created using bun init in bun v1.2.1. Bun is a fast all-in-one JavaScript runtime.
Overview (`lessons/274/app/README.md`)
App
protoc -I proto --cpp_out=./src/market ./proto/*Contents (`docs/contents.md`)
Contents
- 069 - How to Create GKE Cluster Using TERRAFORM from Scratch?
- 070 - EKS Cluster Auto Scaling
- 071 - Kubernetes Horizontal Pod Autoscaler
- 072 - How to Install Prometheus on Kubernetes Cluster?
- 073 - Horizontal Pod Autoscaler CUSTOM METRICS & PROMETHEUS
- 074 - Vertical Pod Autoscaling
- 075 - AWS Serverless Application Model
- 076 - How to Build Slack Bot?
- 077 - AWS Lambda Secrets Manager Example
- 078 - How to Secure Nginx with Lets Encrypt on Ubuntu 20.04 with Certbot?
- 079 - AWS EKS & Secrets Manager
- 080 - How to Get Letsencrypt Wildcard Certificate
- 081 - How to Setup Auto-Renew for Letsencrypt WILDCARD Certificate with DNS challenge?
- 082 - NGINX Ingress Controller for Kubernetes Tutorial
- 083 - Cert Manager Kubernetes Tutorial
- 084 - AWS Point to Site VPN Setup
- 085 - How to Deploy React App on Firebase Hosting?
- 086 - Build a Docker Image and Publish It to AWS ECR using Github Actions
- 087 - Build a Docker Image and Publish It to GCP GCR & Artifact Registry using Github Actions
- 088 - How to Create Your Own GitHub Actions?
- 089 - GitHub Actions Self Hosted Runner (Autoscaling with Kubernetes)
- 090 - Kubernetes Terminal: 6 Must-Have Tools to Install & Examples
- 091 - Kubernetes NodePort vs LoadBalancer vs Ingress?
- 092 - Kubernetes Namespaces vs. Virtual Clusters
- 093 - Kubernetes Basics: Pods, Nodes, Containers, Deployments and Clusters
- 094 - Kubernetes Quality of Service (QoS) Classes for Pods
- 095 - Kubernetes Pod Priority
- 096 - Kubernetes Affinity and Anti Affinity vs NodeSelector
- 097 - Kubernetes Taints and Tolerations (Examples)
- 098 - Kubernetes Pod Disruption Budget
- 099 - Kubernetes Local Persistent Volume: DON'T use hostPath!
- 100 - How to Deploy Create React App to GitHub Pages?
- 101 - Terraform Ansible Integration: GCP Example & Multiple VMs
- 102 - How to Create EKS Cluster Using Terraform?
- 103 - How to Add IAM User and IAM Role to AWS EKS Cluster?
- 104 - How to Install Prometheus and Grafana on Ubuntu?
- 105 - How to Install MongoDB on Kubernetes?
- 106 - Google Cloud Functions Tutorial
- 107 - How to Hack a Password in Python?
- 108 - How to Create GKE Cluster Using TERRAFORM?
- 109 - How to Create EKS Cluster Using eksctl?
- 110 - How to Deploy React App (any static website) to S3 and CloudFront?
- 111 - Kubernetes Kustomize Tutorial: 10 examples
- 112 - Native EKS Ingress: AWS Load Balancer Controller
- 113 - Create AWS EKS Fargate Using Terraform
- 114 - Kubernetes Node Autoscaling with Karpenter
- 115 - How to Create AWS Lambda with Terraform?
- 116 - AWS API Gateway - with EKS
- 117 - AWS API Gateway - Custom Domain
- 118 - AWS API Gateway - EC2 Integration
- 119 - AWS API Gateway - WebSocket API + EC2
- 120 - How To SSH into your VM? - Google Cloud Platform
- 121 - How to connect to EC2 instance?
- 122 - How to send AWS CloudWatch Alarms to Slack?
- 123 - Creating a Linux service with systemd
- 124 - AWS Lambda Go vs. Node.js performance benchmark
- 125 - How to create EKS Cluster using Terraform MODULES?
- 126 - AWS Lambda Python vs. Node.js performance benchmark
- 127 - How to create Application Load Balancer using Terraform?
- 128 - AWS Lambda Go vs. Rust performance benchmark
- 129 - AWS Lambda vs Cloud Functions (2nd gen) performance benchmark
- 130 - Monitoring EKS & EC2 instances with MANAGED Prometheus & Grafana
- 131 - Send Alerts to Slack, Email, PagerDuty - AWS Managed Prometheus
- 132 - GCP Managed Prometheus Tutorial (Managed Collection)
- 133 - EKS Storage | Install Amazon EBS CSI driver & KMS
- 134 - How to monitor Persistent Volume usage in Kubernetes using Prometheus?
- 135 - How to monitor Containers in Kubernetes using Prometheus & cAdvisor?
- 136 - Monitor HTTP/REST API in Kubernetes using Prometheus & Nginx Ingress Controller
- 137 - How to Monitor Golang with Prometheus (Counter - Gauge - Histogram - Summary)
- 138 - Go (Golang) vs. Rust: (HTTP/REST API in Kubernetes) Performance Benchmark
- 139 - Use Kubernetes Gateway API instead of Ingress! (Cert Manager - Istio - Prometheus)
- 140 - How to Monitor Nginx with Prometheus and Grafana? (Install - Monitor - Fluentd)
- 141 - How to Build Custom Prometheus Exporter?
- 142 - Use Kubernetes Gateway API for Mesh (Service-to-Service - Istio - Kiali - Prometheus)
- 143 - Go (Golang) vs Node JS (Microservices) performance benchmark
- 144 - Nginx vs Traefik performance benchmark (HTTP - HTTPS - gRPC | Prometheus)
- 145 - Go (Golang) vs Java performance benchmark (Fiber vs Spring Boot)
- 146 - Nginx vs Apache HTTP Server performance benchmark
- 147 - Go (Golang) vs Rust performance benchmark (gRPC)
- 148 - HTTP/2 vs HTTP/3 performance benchmark
- 149 - gRPC vs REST performance benchmark
- 150 - ARM vs x86 performance benchmark
- 151 - Nginx vs Envoy performance benchmark
- 152 - gRPC vs Kafka: Which one should you choose?
- 153 - Traefik vs Caddy 2
- 154 - Prometheus Operator Kubernetes Tutorial
- 155 - Istio Service Mesh Tutorial
- 156 - How to Use EKS Blueprints Terraform Modules? (EFS - Karpenter - Add User - Fargate - ALB Controller)
- 157 - DevOps Interview Questions: (Step-by-Step) #1
- 158 - ArgoCD Tutorial for Beginners: GitOps CD for Kubernetes #1
- 159 - ArgoCD Image Updater: Decouple CI from CD! #2
- 160 - Terragrunt Tutorial: Create VPC, EKS from Scratch! (Step-by-Step)
- 161 - Terraform Tips & Tricks: loops, if-statements, and more
- 162 - How to Manage Secrets in Terraform
- 163 - Thanos (Prometheus) Tutorial: Remote Read/Write - mTLS - Step-by-Step!
- 164 - An Introduction to Terraform #1
- 165 - How to manage Terraform State? #2
- 166 - HardenEKS: Best Practices For Amazon EKS (Programmatically)
- 167 - 9 Ways to Expose an App on Amazon EKS to the Internet
- 168 - How to build multi-arch Docker Images? (Docker Hub - ECR - EKS Demo)
- 171 - Most Common Kubernetes Deployment Strategies
- 172 - Linkerd vs. Istio (Rust vs. C++) performance benchmark
- 173 - Kubernetes Canary Deployment (Manual vs Automated)
- 174 - Kubernetes Ingress Explained (2 Types)
- 175 - AWS App Mesh Tutorial (EKS | Ingress | Terraform)
- 176 - Crossplane Tutorial (vs Terraform): Create AWS VPC - EKS - IRSA - Cluster Autoscaler
- 177 - Azure Kubernetes Service (AKS) Tutorial: (Terraform - Nginx Ingress & TLS - OIDC Workload Identity)
- 178 - OpenTelemetry Golang Tutorial (Tracing in Grafana & Kubernetes & Tempo)
- 179 - ArgoCD Notifications (Successful/Failed Deployments)
- 180 - Go (Golang) vs Python Performance Benchmark (Kubernetes - OpenTelemetry - Prometheus - Grafana)
- 181 - Kubernetes Autoscaling: HPA vs. VPA vs. Keda vs. CA vs. Karpenter vs. Fargate
- 182 - Kubernetes Workload Resources: App vs. Container vs. Pod vs. Deployment vs. StatefulSets & More
- 184 - Kubernetes Health Checks: Liveness vs. Readiness vs. Startup Probe
- 185 - Kubernetes Architecture?
- 186 - Apache Kafka Architecture?
- 187 - Docker vs Kubernetes vs Containerd
- 188 - Docker Networking Tutorial (Bridge - None - Host - IPvlan - Macvlan - Overlay)
- 189 - What Is a Graph Database?
- 190 - What is a Reverse Proxy? (vs. Forward Proxy)
- 191 - Types of Load Balancing Algorithms
- 192 - Kubernetes RBAC Explained
- 193 - How to debug Kubernetes? (Deployments, Services & Ingress)
- 194 - How to debug Kubernetes Ingress? (TLS - Cert-Manager - HTTP-01 & DNS-01 Challenges)
- 195 - AWS EKS Kubernetes Tutorial
- 196 - AWS EKS Kubernetes Tutorial - Full Course
- 197 - Kubernetes Tutorial for Beginners - Full Course
- 198 - How To Structure Terraform Project (3 Levels)
- 199 - Docker Compose Tutorial for Beginners
- 200 - How to Set Up ArgoCD for Production?
- 201 - Java (Quarkus) vs. Go (Golang): Performance Benchmark in Kubernetes
- 202 - C# (.NET) vs. Go (Golang): Performance Benchmark in Kubernetes
- 203 - Rust (Actix) vs. Go (Golang): Performance Benchmark in Kubernetes (EKS)
- 204 - Go (fiber) vs. Go (stdlib) vs. Go (gin): Performance Benchmark in Kubernetes
- 205 - Rust (Actix) vs. Go (Stdlib): Performance Benchmark in Kubernetes
- 206 - Rust (Actix) vs Rust (Axum) vs Rust (Rocket): Performance Benchmark in Kubernetes
- 207 - Zap (Zig) vs Actix (Rust): Performance Benchmark in Kubernetes
- 208 - Actix (Rust) vs Zap (Zig) vs Stdlib (Zig): Performance Benchmark in Kubernetes
- 209 - Django (Python) vs Stdlib (Go): Performance Benchmark in Kubernetes
- 210 - Node.js vs Golang: Performance Benchmark in Kubernetes
- 211 - Node.js vs Golang (Round 2): Performance Benchmark in Kubernetes
- 212 - Bun vs Node.js: Performance Benchmark in Kubernetes #212
- 213 - Go (Golang) vs. Bun: Performance (Latency - Throughput - Saturation - Availability)
- 214 - MySQL vs PostgreSQL Performance Benchmark (Latency - Throughput - Saturation)
- 215 - Rust vs Zig vs Go: Performance (Latency - Throughput - Saturation - Availability)
- 216 - MySQL vs PostgreSQL (Round 2) Performance Benchmark (Latency - Throughput - Saturation)
- 217 - Deno vs. Node.js vs Bun: Performance (Latency - Throughput - Saturation - Availability)
- 218 - Apache Kafka vs RabbitMQ Performance (Latency - Throughput - Saturation)
- 219 - Nginx vs Apache Performance (Latency - Throughput - Saturation - Availability | HTTP/2 - TLS - Gzip)
- 220 - Ruby on Rails vs Node.js Performance (Latency - Throughput - Saturation - Availability)
- 221 - Nginx vs Caddy Performance (Latency - Throughput - Saturation - Availability | HTTP/2 - TLS - Gzip)
- 222 - Ruby vs Node.js: Performance Benchmark
- 223 - SQLite vs PostgreSQL
- 224 - Nginx vs Traefik: What Is the BEST Reverse Proxy?
- 225 - Redis vs Memcached Performance Benchmark
- 226 - Pingora vs Nginx Performance Benchmark
- 227 - MongoDB vs. PostgreSQL: Performance & Functionality
- 228 - Redis vs Dragonfly Performance (Latency - Throughput - Saturation)
- 229 - FASTEST Go Web Framework: gnet vs fiber vs fasthttp vs net/http?
- 230 - Elixir vs Go (Golang) Performance (Latency - Throughput - Saturation - Availability)
- 231 - Python (FastAPI) vs Go (Golang) Performance Benchmark
- 232 - Python (FastAPI) vs Go (Golang) Performance Benchmark (Round 2)
- 233 - Elixir vs Go Performance Benchmark (Round 2)
- 234 - PostgreSQL vs Amazon RDS: Performance & Price
- 235 - Terraform GCP Tutorial (Getting Started with Google Cloud Platform)
- 236 - FastAPI vs Node.js Performance
- 237 - VM vs Kubernetes: Performance ð
- 238 - Create GKE Cluster using Terraform
- 239 - FastAPI vs Go (Golang) vs Node.js: Performance & Price
- 240 - gRPC vs REST vs GraphQL: Comparison & Performance
- 241 - Deno vs. Node.js vs. Bun: Performance Comparison
- 242 - Rust vs. Go (Golang): Performance (Only Standard Library)
- 243 - Rust vs. Go (Golang): Performance 2025
- 244 - Rust vs. Go (Golang): Performance (Fastest Frameworks + PostgreSQL)
- 245 - Rust vs C++ Performance
- 246 - TCP vs UDP Performance (Latency & Throughput)
- 249 - TCP vs UDP Performance: HUGE Improvement!
- 250 - Nginx vs. HAProxy vs. Traefik: Performance
- 251 - TCP vs UDP performance (Round 3)
- 252 - Nginx vs HAProxy Performance (HTTP/1 - HTTP/2 - HTTPS - Compression)
- 253 - Redis Streams vs Pub/Sub: Performance
- 254 - Intel vs AMD vs Graviton: Performance & Price
- 255 - Terraform Tutorial on AWS
- 256 - Terraform AWS VPC Tutorial - Public, Private, and Isolated Subnets
- 258 - Redis vs Valkey performance
- 259 - Rust vs C++ Performance: Can Rust Actually Be Faster?
- 260 - ZeroMQ vs Aeron: Best for Market Data? Performance (Latency & Throughput)
- 265 - Rust vs C++ Performance: Can Rust Actually Be Faster? (Pt. 2)
- 268 - Build a Secure AWS EKS CI/CD Pipeline: Step-by-Step Tutorial (ArgoCD + GitHub Actions)
- 269 - Reduce AWS Latency by 200x: Drop from 7ms to 35Ξs
- 270 - How to Create a Fully Private AWS EKS Cluster? (Client VPN & Resolve Private Route 53 DNS Locally)
- 271 - HTTP vs WebSockets: Performance (Latency - CPU - Memory - Network)
- 272 - Redis vs Valkey: Performance & Comparison
- 273 - Deno vs. Node.js vs. Bun: Performance Comparison
- 274 - Protobuf vs JSON: Performance Benchmark & Size
- 275 - Go (Golang) vs TypeScript: Performance Benchmark
- 276 - Python vs JavaScript Performance: Best Backend Language 2026 (FastAPI vs Bun)
- 277 - SQLite vs PostgreSQL Performance & Comparison (2026)
- 278 - Zig vs Rust Performance Benchmark 2026
- 279 - 6 SQL Joins you MUST know! (Animated + Practice)
--- METRICS ---
- Files Extracted: 274
- Estimated Token Budget: ~60418 tokens
- Canonical Reference: https://codewiki.google/github.com/antonputra/tutorials