-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Anish Bista <[email protected]>
- Loading branch information
1 parent
8976d06
commit b281154
Showing
19 changed files
with
1,277 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
package main | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"os" | ||
|
||
"github.com/gin-gonic/gin" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/client_golang/prometheus/promhttp" | ||
_ "github.com/lib/pq" | ||
) | ||
|
||
// Define Prometheus metrics | ||
var ( | ||
addGoalCounter = prometheus.NewCounter(prometheus.CounterOpts{ | ||
Name: "add_goal_requests_total", | ||
Help: "Total number of add goal requests", | ||
}) | ||
removeGoalCounter = prometheus.NewCounter(prometheus.CounterOpts{ | ||
Name: "remove_goal_requests_total", | ||
Help: "Total number of remove goal requests", | ||
}) | ||
httpRequestsCounter = prometheus.NewCounterVec( | ||
prometheus.CounterOpts{ | ||
Name: "http_requests_total", | ||
Help: "Total number of HTTP requests", | ||
}, | ||
[]string{"path"}, | ||
) | ||
) | ||
|
||
func init() { | ||
// Register Prometheus metrics | ||
prometheus.MustRegister(addGoalCounter) | ||
prometheus.MustRegister(removeGoalCounter) | ||
prometheus.MustRegister(httpRequestsCounter) | ||
} | ||
|
||
func createConnection() (*sql.DB, error) { | ||
connStr := fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=disable", | ||
os.Getenv("DB_USERNAME"), | ||
os.Getenv("DB_PASSWORD"), | ||
os.Getenv("DB_HOST"), | ||
os.Getenv("DB_PORT"), | ||
os.Getenv("DB_NAME"), | ||
) | ||
|
||
db, err := sql.Open("postgres", connStr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = db.Ping() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return db, nil | ||
} | ||
|
||
func main() { | ||
router := gin.Default() | ||
|
||
router.LoadHTMLGlob("templates/*") | ||
|
||
router.GET("/", func(c *gin.Context) { | ||
db, err := createConnection() | ||
if err != nil { | ||
log.Println("Error connecting to PostgreSQL", err) | ||
c.String(http.StatusInternalServerError, "Error connecting to the PostgreSQL database") | ||
return | ||
} | ||
defer db.Close() | ||
|
||
rows, err := db.Query("SELECT * FROM goals") | ||
if err != nil { | ||
log.Println("Error querying database", err) | ||
c.String(http.StatusInternalServerError, "Error querying the database") | ||
return | ||
} | ||
defer rows.Close() | ||
|
||
var goals []struct { | ||
ID int | ||
Name string | ||
} | ||
|
||
for rows.Next() { | ||
var goal struct { | ||
ID int | ||
Name string | ||
} | ||
if err := rows.Scan(&goal.ID, &goal.Name); err != nil { | ||
log.Println("Error scanning row", err) | ||
continue | ||
} | ||
goals = append(goals, goal) | ||
} | ||
|
||
httpRequestsCounter.WithLabelValues("/").Inc() | ||
|
||
c.HTML(http.StatusOK, "index.html", gin.H{ | ||
"goals": goals, | ||
}) | ||
}) | ||
|
||
router.POST("/add_goal", func(c *gin.Context) { | ||
goalName := c.PostForm("goal_name") | ||
if goalName != "" { | ||
db, err := createConnection() | ||
if err != nil { | ||
log.Println("Error connecting to PostgreSQL", err) | ||
c.String(http.StatusInternalServerError, "Error connecting to the PostgreSQL database") | ||
return | ||
} | ||
defer db.Close() | ||
|
||
_, err = db.Exec("INSERT INTO goals (goal_name) VALUES ($1)", goalName) | ||
if err != nil { | ||
log.Println("Error inserting goal", err) | ||
c.String(http.StatusInternalServerError, "Error inserting goal into the database") | ||
return | ||
} | ||
|
||
// Increment the add goal counter | ||
addGoalCounter.Inc() | ||
httpRequestsCounter.WithLabelValues("/add_goal").Inc() | ||
} | ||
c.Redirect(http.StatusFound, "/") | ||
}) | ||
|
||
router.POST("/remove_goal", func(c *gin.Context) { | ||
goalID := c.PostForm("goal_id") | ||
if goalID != "" { | ||
db, err := createConnection() | ||
if err != nil { | ||
log.Println("Error connecting to PostgreSQL", err) | ||
c.String(http.StatusInternalServerError, "Error connecting to the PostgreSQL database") | ||
return | ||
} | ||
defer db.Close() | ||
|
||
_, err = db.Exec("DELETE FROM goals WHERE id = $1", goalID) | ||
if err != nil { | ||
log.Println("Error deleting goal", err) | ||
c.String(http.StatusInternalServerError, "Error deleting goal from the database") | ||
return | ||
} | ||
|
||
// Increment the remove goal counter | ||
removeGoalCounter.Inc() | ||
httpRequestsCounter.WithLabelValues("/remove_goal").Inc() | ||
} | ||
c.Redirect(http.StatusFound, "/") | ||
}) | ||
|
||
router.GET("/health", func(c *gin.Context) { | ||
httpRequestsCounter.WithLabelValues("/health").Inc() | ||
c.String(http.StatusOK, "OK") | ||
}) | ||
|
||
// Expose metrics endpoint | ||
router.GET("/metrics", gin.WrapH(promhttp.Handler())) | ||
|
||
router.Run(":8080") | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 kubesimplify | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
This repo is for the video below | ||
|
||
|
||
[![Conplete DevOps Project](https://img.youtube.com/vi/kCWAwXFnYic/0.jpg)](https://www.youtube.com/watch?v=kCWAwXFnYic) | ||
|
||
# Running Locally | ||
## Initialising for base image | ||
``` | ||
bsf init | ||
``` | ||
## Building OCI artifact using bsf and ko | ||
``` | ||
bsf oci pkgs --platform=linux/amd64 --tag=prod-v1 --push --dest-creds {Dockerhub username}:{dockerhub password} | ||
KO_DOCKER_REPO=saiyam911/devops-project KO_DEFAULTBASEIMAGE=saiyam911/devops-proj:base ko build --bare -t v1 . (change your image names here) | ||
``` | ||
## Running using Docker | ||
``` | ||
docker run -d --name grafana -p 3000:3000 grafana/grafana | ||
docker run -d --name prometheus -p 9090:9090 -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus | ||
docker run --name local-postgres -e POSTGRES_USER=myuser -e POSTGRES_PASSWORD=mypassword -e POSTGRES_DB=mydb -p 5432:5432 -d postgres | ||
docker exec -it local-postgres psql -U myuser -d mydb | ||
CREATE TABLE goals ( | ||
id SERIAL PRIMARY KEY, | ||
goal_name TEXT NOT NULL | ||
); | ||
docker run -d \ | ||
--platform=linux/amd64 \ | ||
-p 8080:8080 \ | ||
-e DB_USERNAME=myuser \ | ||
-e DB_PASSWORD=mypassword \ | ||
-e DB_HOST=host.docker.internal \ | ||
-e DB_PORT=5432 \ | ||
-e DB_NAME=mydb \ | ||
-e SSL=disable \ | ||
ttl.sh/devops-project-1a3a3957a5f042748486580be307ed8e@sha256:9ae320cdf05700210dd50ebefa6b3cd4a11ca2feaad1946f6715e0ec725bda62 | ||
``` | ||
|
||
## Cluster creatiom | ||
```ksctl create-cluster azure --name=application --version=1.29``` | ||
|
||
## Switching the KubeConfig file | ||
```ksctl switch-cluster --provider azure --region eastus --name devops-project``` | ||
|
||
## Exporting Kubeconfig | ||
```export KUBECONFIG="/Users/saiyam/.ksctl/kubeconfig"``` | ||
|
||
## Installing basic componenets cert manager, nginx fabric for gateway API, Prometheus. for monitoring and Grafana for visualization. | ||
### Cert manager | ||
``` | ||
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.yaml | ||
``` | ||
Edit cert-manager deployment | ||
``` | ||
- --enable-gateway-api | ||
``` | ||
```kubectl rollout restart deployment cert-manager -n cert-manager``` | ||
|
||
### Install Kube prometheus stack | ||
``` | ||
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts | ||
helm repo update | ||
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --namespace monitoring --create-namespace | ||
``` | ||
### Getting Grafana login secret for admin user | ||
|
||
``` | ||
kubectl get secret --namespace monitoring kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo | ||
kubectl port-forward svc/grafana 3000:80 -n monitoring | ||
``` | ||
|
||
## Install Nginx fabric gateway | ||
``` | ||
kubectl kustomize "https://github.com/nginxinc/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v1.3.0" | kubectl apply -f - | ||
helm install ngf oci://ghcr.io/nginxinc/charts/nginx-gateway-fabric --create-namespace -n nginx-gateway | ||
``` | ||
|
||
|
||
## Install Cloudnative postgress DB | ||
``` | ||
kubectl apply --server-side -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.23/releases/cnpg-1.23.1.yaml | ||
``` | ||
``` | ||
cat << EOF | kubectl apply -f - | ||
apiVersion: postgresql.cnpg.io/v1 | ||
kind: Cluster | ||
metadata: | ||
name: my-postgresql | ||
namespace: default | ||
spec: | ||
instances: 3 | ||
storage: | ||
size: 1Gi | ||
bootstrap: | ||
initdb: | ||
database: goals_database | ||
owner: goals_user | ||
secret: | ||
name: my-postgresql-credentials | ||
EOF | ||
``` | ||
### Creating secret for cluster | ||
``` | ||
kubectl create secret generic my-postgresql-credentials --from-literal=password='new_password' --from-literal=username='goals_user' --dry-run=client -o yaml | kubectl apply -f - | ||
kubectl exec -it my-postgresql-1 -- psql -U postgres -c "ALTER USER goals_user WITH PASSWORD 'new_password';" | ||
``` | ||
|
||
### Creating Table inside the database | ||
``` | ||
kubectl port-forward my-postgresql-1 5432:5432 | ||
PGPASSWORD='new_password' psql -h 127.0.0.1 -U goals_user -d goals_database -c " | ||
CREATE TABLE goals ( | ||
id SERIAL PRIMARY KEY, | ||
goal_name VARCHAR(255) NOT NULL | ||
); | ||
" | ||
``` | ||
|
||
### Create secret to be used by the application | ||
``` | ||
cat << EOF | kubectl apply -f - | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: postgresql-credentials | ||
type: Opaque | ||
data: | ||
password: bmV3X3Bhc3N3b3Jk | ||
username: Z29hbHNfdXNlcg== | ||
EOF | ||
``` | ||
|
||
|
||
### Application deployment(Currently this has the gateway for both Argocd and the application) | ||
``` | ||
kubectl apply -f deploy/deploy,yaml | ||
``` | ||
|
||
## Argocd installation | ||
``` | ||
kubectl create namespace argocd | ||
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml | ||
kubectl patch configmap argocd-cm -n argocd --patch '{"data":{"server.insecure":"true"}}' | ||
kubectl rollout restart deployment argocd-server -n argocd | ||
kubectl get secret --namespace argocd argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 --decode ; echo | ||
``` | ||
|
||
## Create Route for ArgoCD | ||
``` | ||
kubectl apply -f route-argo.yaml | ||
kubectl apply -f referencegrant | ||
``` | ||
## Load testing | ||
``` | ||
k6s run load.js | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
apiVersion: gateway.networking.k8s.io/v1 | ||
kind: Gateway | ||
metadata: | ||
name: app-gateway | ||
namespace: default | ||
annotations: | ||
cert-manager.io/cluster-issuer: letsencrypt-prod | ||
spec: | ||
gatewayClassName: nginx | ||
listeners: | ||
- name: http | ||
port: 80 | ||
protocol: HTTP | ||
hostname: "demo.anishbista.xyz" | ||
- name: https | ||
hostname: "demo.anishbista.xyz" | ||
port: 443 | ||
protocol: HTTPS | ||
allowedRoutes: | ||
namespaces: | ||
from: All | ||
tls: | ||
mode: Terminate | ||
certificateRefs: | ||
- name: demo-com-tls | ||
kind: Secret | ||
group: "" |
Oops, something went wrong.