From 24fdbf13be085b3c4ef03ffa41fa4ede6e3ae457 Mon Sep 17 00:00:00 2001 From: Pradumna Saraf Date: Tue, 10 Sep 2024 20:02:44 +0530 Subject: [PATCH] feat: Add Kubernetes resources for demo-app namespace, api-node service, api-golang service, client-react-nginx service, and strip-api-prefixes middleware - Added Namespace.yaml for demo-app namespace - Added Service.yaml for api-node service - Added Service.yaml for api-golang service - Added Service.yaml for client-react-nginx service - Added Middleware.yaml for strip-api-prefixes middleware --- docs/docker/introduction.md | 27 ++- .../go-node-react-postgres/Namespace.yaml | 4 + .../go-node-react-postgres/README.md | 165 ++++++++++++++++++ .../api-golang/Deployment.yaml | 45 +++++ .../api-golang/IngressRoute.yaml | 18 ++ .../api-golang/Secret.yml | 9 + .../api-golang/Service.yaml | 12 ++ .../api-node/Deployment.yaml | 45 +++++ .../api-node/IngressRoute.yaml | 18 ++ .../api-node/Secret.yaml | 9 + .../api-node/Service.yaml | 12 ++ .../client-react/ConfigMap.yaml | 24 +++ .../client-react/Deployment.yaml | 48 +++++ .../client-react/IngressRoute.yaml | 16 ++ .../client-react/Service.yaml | 12 ++ .../common/Middleware.yaml | 11 ++ .../common/Namespace.yaml | 4 + .../postgresql/Job.db-migrator.yaml | 19 ++ .../postgresql/Secret.db-password.yaml | 9 + .../postgresql/values.yaml | 9 + docs/kubernetes/introduction.md | 14 ++ 21 files changed, 527 insertions(+), 3 deletions(-) create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/Namespace.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/README.md create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Deployment.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/IngressRoute.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Secret.yml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Service.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Deployment.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-node/IngressRoute.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Secret.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Service.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/client-react/ConfigMap.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Deployment.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/client-react/IngressRoute.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Service.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/common/Middleware.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/common/Namespace.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Job.db-migrator.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Secret.db-password.yaml create mode 100644 docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/values.yaml diff --git a/docs/docker/introduction.md b/docs/docker/introduction.md index ce478e6..8237cb8 100644 --- a/docs/docker/introduction.md +++ b/docs/docker/introduction.md @@ -38,11 +38,20 @@ Docker is an open-source platform designed to simplify the development, deployme - `CMD` (command to run when the container starts) - `WORKDIR` (create a directory where all the files will be copied and used) -To build an image from the **Dockerfile**, use this command: +### Docker Build Architecture + +We can build the image in two ways single architecture or multi-architecture. In the single architecture, we can build the image for a specific architecture, and in multi-architecture, we can build the image for multiple architectures. + +#### Single Architecture + +```bash +docker build -t . +``` + +#### Multi-Architecture ```bash -docker build -// docker build . +docker buildx build --platform linux/amd64,linux/arm64 -t . ``` **Good Practice** @@ -236,6 +245,18 @@ HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost/ || exit 1 ``` +### Container Registry + +A repo - a collection of repositories. Use to store and access container images. + +Some popular registries are: + +- Docker Hub +- GitHub Container Registry (ghcr.io) +- Google Container Registry (gcr.io) +- Amazon Elastic Container Registry (ECR) +- Azure Container Registry (ACR) + ### Private Docker Registry We can create a registry with the official [Registry image](https://hub.docker.com/_/registry). diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/Namespace.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/Namespace.yaml new file mode 100644 index 0000000..679127d --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/Namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: demo-app diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/README.md b/docs/kubernetes/demo-apps/go-node-react-postgres/README.md new file mode 100644 index 0000000..82dccc6 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/README.md @@ -0,0 +1,165 @@ +## Multi Service App + +This is a simple multi-service app that consists of a React Client, a Node API, and a Golang API. The app uses a Postgresql database for data storage. + +### Prerequisites + +- Kubernetes Cluster +- Helm v3 +- kubectl + +## Layout + +The following shows the layout of this directory: + +```markdown +├── api-golang +│ ├── Deployment.yaml +│ ├── IngressRoute.yaml +│ ├── Secret.yml +│ └── Service.yaml +├── api-node +│ ├── Deployment.yaml +│ ├── IngressRoute.yaml +│ ├── Secret.yaml +│ └── Service.yaml +├── client-react +│ ├── ConfigMap.yaml +│ ├── Deployment.yaml +│ ├── IngressRoute.yaml +│ └── Service.yaml +├── common +│ ├── Middleware.yaml +│ ├── Namespace.yaml +└── postgresql + ├── Job.db-migrator.yaml + └── Secret.db-password.yaml +``` + +### Setting up the APP + +Make sure you are in `go-node-react-postgres` directory. + +1. Create a Namespace + +```bash +kubectl apply -f Namespace.yaml +``` + +switch to the namespace: + +```bash +kubectl config set-context --current --namespace=demo-app +``` + +2. Install Postgresql Database using Helm + +Add the bitnami repo: + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +``` + +Install the chart: + +```bash +helm upgrade --install \ + -n postgres \ + postgres bitnami/postgresql \ + --set auth.postgresPassword=foobarbaz \ + --version 15.3.2 \ + --values ./postgresql/values.yaml \ + --create-namespace +``` + +3. Database Migration + +First we need to create a secret for the database password: + +```bash +kubectl apply -f postgresql/Secret.db-password.yaml +``` + +Then we can run the migration job: + +```bash +kubectl apply -f postgresql/Job.db-migrator.yaml +``` + +5. Install traffic Ingress Controller + +Add the traefik repo: + +```bash +helm repo add traefik https://traefik.github.io/charts +``` + +Install the chart: + +```bash +helm upgrade --install \ + -n traefik \ + traefik traefik/traefik \ + --version 20.8.0 \ + --create-namespace +``` + +6. Deploy a Middleware to Strop of the prefix from incoming requests + +```bash +kubectl apply -f common/Middleware.yaml +``` + +7. Deploy the Golang API. + +Before deploying, update the `IngressRoute.yaml` file to match the correct host. + +```yaml +routes: + - kind: Rule + match: Host(`host/domain`) && PathPrefix(`/api/golang`) +``` + +Then deploy the API: + +```bash +kubectl apply -f api-golang +``` + +8. Deploy the Node API. + +Before deploying, update the `IngressRoute.yaml` file to match the correct host. + +```yaml +routes: + - kind: Rule + match: Host(`host/domain`) && PathPrefix(`/api/node`) +``` + +Then deploy the API: + +```bash +kubectl apply -f api-node +``` + +9. Deploy the React Client. + +Before deploying, update the `IngressRoute.yaml` file to match the correct host. + +```yaml +routes: + - kind: Rule + match: Host(`host/domain`) # This will root with no prefix +``` + +Then deploy the client: + +```bash +kubectl apply -f client-react +``` + +Now you should be able to access the app using the host/domain you have set in the IngressRoute files. + +- For Node API, you can access it using `/api/node`. +- For Golang API, you can access it using `/api/golang`. +- For React Client, you can access it using ``. diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Deployment.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Deployment.yaml new file mode 100644 index 0000000..bb62399 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api-golang + namespace: demo-app + labels: + app: api-golang +spec: + replicas: 1 + selector: + matchLabels: + app: api-golang + template: + metadata: + labels: + app: api-golang + spec: + containers: + - name: api-golang + image: sidpalas/devops-directive-docker-course-api-golang:foobarbaz + env: + - name: PORT + value: "8000" + envFrom: + - secretRef: + name: api-golang-database-url + ports: + - containerPort: 8000 + protocol: TCP + readinessProbe: + httpGet: + path: /ping + port: 8000 + resources: + limits: + memory: "100Mi" + requests: + memory: "100Mi" + cpu: "50m" + securityContext: + allowPrivilegeEscalation: false + privileged: false + securityContext: + seccompProfile: + type: RuntimeDefault diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/IngressRoute.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/IngressRoute.yaml new file mode 100644 index 0000000..727cf4f --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/IngressRoute.yaml @@ -0,0 +1,18 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: api-golang + namespace: demo-app +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`d11ae95f-7695-4635-9637-13829bf55c83.lb.civo.com`) && PathPrefix(`/api/golang`) + middlewares: + - name: strip-api-prefixes + services: + - kind: Service + name: api-golang + port: 8000 + scheme: http diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Secret.yml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Secret.yml new file mode 100644 index 0000000..c379450 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Secret.yml @@ -0,0 +1,9 @@ +# ⛔️ DONT PUT SECRET FILES IN VCS +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: api-golang-database-url + namespace: demo-app +stringData: + DATABASE_URL: postgres://postgres:foobarbaz@postgres-postgresql.postgres.svc.cluster.local:5432/postgres diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Service.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Service.yaml new file mode 100644 index 0000000..fa4ae25 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-golang/Service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-golang + namespace: demo-app +spec: + selector: + app: api-golang + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Deployment.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Deployment.yaml new file mode 100644 index 0000000..f61975d --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api-node + namespace: demo-app + labels: + app: api-node +spec: + replicas: 1 + selector: + matchLabels: + app: api-node + template: + metadata: + labels: + app: api-node + spec: + containers: + - name: api-node + image: sidpalas/devops-directive-docker-course-api-node:foobarbaz + env: + - name: PORT + value: "3000" + envFrom: + - secretRef: + name: api-node-database-url + ports: + - containerPort: 3000 + protocol: TCP + readinessProbe: + httpGet: + path: /ping + port: 3000 + resources: + limits: + memory: "100Mi" + requests: + memory: "100Mi" + cpu: "50m" + securityContext: + allowPrivilegeEscalation: false + privileged: false + securityContext: + seccompProfile: + type: RuntimeDefault diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/IngressRoute.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/IngressRoute.yaml new file mode 100644 index 0000000..a41a39c --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/IngressRoute.yaml @@ -0,0 +1,18 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: api-node + namespace: demo-app +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`d11ae95f-7695-4635-9637-13829bf55c83.lb.civo.com`) && PathPrefix(`/api/node`) + middlewares: + - name: strip-api-prefixes + services: + - kind: Service + name: api-node + port: 3000 + scheme: http diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Secret.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Secret.yaml new file mode 100644 index 0000000..46587d2 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Secret.yaml @@ -0,0 +1,9 @@ +# ⛔️ DONT PUT SECRET FILES IN VCS +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: api-node-database-url + namespace: demo-app +stringData: + DATABASE_URL: postgres://postgres:foobarbaz@postgres-postgresql.postgres.svc.cluster.local:5432/postgres diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Service.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Service.yaml new file mode 100644 index 0000000..caa29a0 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/api-node/Service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-node + namespace: demo-app +spec: + selector: + app: api-node + ports: + - protocol: TCP + port: 3000 + targetPort: 3000 diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/ConfigMap.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/ConfigMap.yaml new file mode 100644 index 0000000..c37b9e0 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/ConfigMap.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-conf + namespace: demo-app +data: + default.conf: |- + server { + listen 8080; + + location /ping { + access_log off; + add_header 'Content-Type' 'text/plain'; + return 200 "pong"; + } + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html =404; + } + + include /etc/nginx/extra-conf.d/*.conf; + } diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Deployment.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Deployment.yaml new file mode 100644 index 0000000..777b45f --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Deployment.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: client-react-nginx + namespace: demo-app + labels: + app: client-react-nginx +spec: + replicas: 1 + selector: + matchLabels: + app: client-react-nginx + template: + metadata: + labels: + app: client-react-nginx + spec: + containers: + - image: sidpalas/devops-directive-docker-course-client-react-nginx:foobarbaz + name: client-react-nginx + ports: + - containerPort: 8080 + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /ping + port: 8080 + resources: + limits: + memory: 100Mi + requests: + cpu: 50m + memory: 100Mi + securityContext: + allowPrivilegeEscalation: false + privileged: false + volumeMounts: + - mountPath: /etc/nginx/conf.d + name: nginx-conf + securityContext: + seccompProfile: + type: RuntimeDefault + volumes: + - configMap: + defaultMode: 420 + name: nginx-conf # Name of the ConfigMap + name: nginx-conf # Name of the Volume diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/IngressRoute.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/IngressRoute.yaml new file mode 100644 index 0000000..5462bed --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/IngressRoute.yaml @@ -0,0 +1,16 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: client-react-nginx + namespace: demo-app +spec: + entryPoints: + - web + routes: + - kind: Rule + match: Host(`d11ae95f-7695-4635-9637-13829bf55c83.lb.civo.com`) + services: + - kind: Service + name: client-react-nginx + port: 8080 + scheme: http diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Service.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Service.yaml new file mode 100644 index 0000000..8af989c --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/client-react/Service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: client-react-nginx + namespace: demo-app +spec: + selector: + app: client-react-nginx + ports: + - protocol: TCP + port: 8080 + targetPort: 8080 diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/common/Middleware.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/common/Middleware.yaml new file mode 100644 index 0000000..f11660c --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/common/Middleware.yaml @@ -0,0 +1,11 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: strip-api-prefixes + namespace: demo-app +spec: + stripPrefix: + forceSlash: false + prefixes: + - /api/node + - /api/golang diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/common/Namespace.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/common/Namespace.yaml new file mode 100644 index 0000000..679127d --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/common/Namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: demo-app diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Job.db-migrator.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Job.db-migrator.yaml new file mode 100644 index 0000000..07f2f8c --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Job.db-migrator.yaml @@ -0,0 +1,19 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: db-migrator + namespace: demo-app +spec: + template: + spec: + containers: + - name: migrate + image: sidpalas/devops-directive-kubernetes-course-db-migrator:foobarbaz + args: + - -path=/app/migrations + - -database=$(DATABASE_URL)?sslmode=disable + - up + envFrom: + - secretRef: + name: db-password + restartPolicy: OnFailure diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Secret.db-password.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Secret.db-password.yaml new file mode 100644 index 0000000..fe2fe19 --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/Secret.db-password.yaml @@ -0,0 +1,9 @@ +# ⛔️ DONT PUT SECRET FILES IN VCS +apiVersion: v1 +kind: Secret +metadata: + name: db-password + namespace: demo-app +type: Opaque +stringData: + DATABASE_URL: postgres://postgres:foobarbaz@postgres-postgresql.postgres.svc.cluster.local:5432/postgres # postgres://postgres:foobarbaz@..svc.cluster.local:5432/postgres diff --git a/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/values.yaml b/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/values.yaml new file mode 100644 index 0000000..bc9e8fa --- /dev/null +++ b/docs/kubernetes/demo-apps/go-node-react-postgres/postgresql/values.yaml @@ -0,0 +1,9 @@ +primary: + resources: + limits: + ephemeral-storage: 1Gi + memory: 500Mi + requests: + cpu: 100m + ephemeral-storage: 50Mi + memory: 128Mi diff --git a/docs/kubernetes/introduction.md b/docs/kubernetes/introduction.md index 06f16a1..4573b18 100644 --- a/docs/kubernetes/introduction.md +++ b/docs/kubernetes/introduction.md @@ -585,6 +585,20 @@ type: Opaque # This is the default type stringData: foo: bar baz: qux + +--- +apiVersion: v1 +kind: Pod +metadata: + name: secret-example +spec: + containers: + - name: nginx + image: nginx:1.26.0 + envFrom: + - secretRef: + name: string-data + ``` > Note: the secret value can be `base64` encoded, like `cHJhZHVtbmE`