In the guidance below, you will see my example and my process of deploying this application. All Kubernetes yaml files can be found in the folder "kubernetes-yamls".
Clone the backend and frontend repositories locally:
$ git clone https://github.com/AntTechLabs/awesome_cats_backend.git
$ git clone https://github.com/AntTechLabs/awesome_cats_frontend.git
-
Create a Cloud SQL Instance
- Navigate to the Google Cloud Console, search for Cloud SQL, and create a PostgreSQL instance.
- Save the instance ID, password, and IP address.
- Create or select a database named
awesome_cats_db
. - Configure network settings to allow connections from your Kubernetes cluster. Add the Network in the Connection section.
-
Install PostgreSQL Locally
- Download and install the PostgreSQL version matching your Cloud SQL instance from here.
-
Connect to Cloud SQL via CLI
$ gcloud sql connect sql-instance-bekaiym --user=postgres postgres=> \c awesome_cats_db
-
Create Tables
CREATE TABLE login ( id serial PRIMARY KEY, email text UNIQUE NOT NULL, hash VARCHAR(100) NOT NULL ); CREATE TABLE users ( id serial PRIMARY KEY, name VARCHAR(100), email text UNIQUE NOT NULL, score BIGINT DEFAULT 0, joined TIMESTAMP NOT NULL );
Create a secret for your database credentials:
kubectl create secret generic db-secret \
--from-literal=PGHOST='YOUR_INSTANCE_IP' \
--from-literal=PGUSER='postgres' \
--from-literal=PGDATABASE='awesome_cats_db' \
--from-literal=PGPASSWORD='YOUR_PASSWORD'
-
Create Dockerfile for Backend
FROM node:14 WORKDIR /app COPY package*.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["node", "server.js"]
-
Build and Push Docker Image
$ docker build -t gcr.io/YOUR_PROJECT_ID/awesome-cats-backend:v1 . $ docker push gcr.io/YOUR_PROJECT_ID/awesome-cats-backend:v1
-
Create Dockerfile for Frontend
# Build FROM node:14 AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Prod FROM nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
-
Build and Push Docker Image
$ docker build -t gcr.io/YOUR_PROJECT_ID/awesome-cats-frontend:v1 . $ docker push gcr.io/YOUR_PROJECT_ID/awesome-cats-frontend:v1
-
Create Backend Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: awesome-cats-backend spec: replicas: 2 selector: matchLabels: app: awesome-cats-backend template: metadata: labels: app: awesome-cats-backend spec: containers: - name: backend image: gcr.io/YOUR_PROJECT_ID/awesome-cats-backend:v1 ports: - containerPort: 3000 env: - name: PGHOST valueFrom: secretKeyRef: name: db-secret key: PGHOST - name: PGUSER valueFrom: secretKeyRef: name: db-secret key: PGUSER - name: PGPASSWORD valueFrom: secretKeyRef: name: db-secret key: PGPASSWORD - name: PGDATABASE valueFrom: secretKeyRef: name: db-secret key: PGDATABASE
-
Create Backend Service
apiVersion: v1 kind: Service metadata: name: backend-service spec: selector: app: awesome-cats-backend ports: - protocol: TCP port: 3000 targetPort: 3000 type: ClusterIP
-
Apply Backend Deployment and Service
$ kubectl apply -f backend-deployment.yaml $ kubectl apply -f backend-service.yaml
-
Create Frontend Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: awesome-cats-frontend spec: replicas: 2 selector: matchLabels: app: awesome-cats-frontend template: metadata: labels: app: awesome-cats-frontend spec: containers: - name: frontend image: gcr.io/YOUR_PROJECT_ID/awesome-cats-frontend:v1 ports: - containerPort: 80
-
Create Frontend Service
apiVersion: v1 kind: Service metadata: name: frontend-service spec: selector: app: awesome-cats-frontend ports: - protocol: TCP port: 80 targetPort: 80 type: ClusterIP
-
Apply Frontend Deployment and Service
$ kubectl apply -f frontend-deployment.yaml $ kubectl apply -f frontend-service.yaml
-
Install NGINX Ingress Controller
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx $ helm repo update $ kubectl create namespace ingress-nginx $ helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx
-
Create Ingress Resource
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: nginx-ingress annotations: cert-manager.io/issuer: letsencrypt-prod nginx.ingress.kubernetes.io/ssl-redirect: "true" kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: tls: - hosts: - app.bekaiym.biz secretName: bekaiym-biz-secret rules: - host: app.bekaiym.biz http: paths: - path: /?(.*) pathType: Prefix backend: service: name: frontend-service port: number: 80 - path: /api/?(.*) pathType: Prefix backend: service: name: backend-service port: number: 3000
-
Apply Ingress Resource
$ kubectl apply -f ingress.yaml
-
Check Ingress Resource
$ kubectl get ingress
-
Configure Domain with Cloud DNS
- Set up DNS records to point to your NGINX Ingress Load Balancer IP.
-
Install Cert-Manager
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.6.1/cert-manager.yaml
-
Create ClusterIssuer and Certificate
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: email: YOUR_EMAIL server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: bekaiym-biz-cert spec: secretName: bekaiym-biz-secret dnsNames: - app.bekaiym.biz issuerRef: name: letsencrypt-prod kind: ClusterIssuer
-
Apply ClusterIssuer and Certificate
$ kubectl apply -f cluster-issuer.yaml $ kubectl apply -f certificate.yaml
-
Check Resources
$ kubectl get pods $ kubectl get svc $ kubectl get ingress
-
Access Application
- Navigate to your domain, (in my case, it is
http://app.bekaiym.biz
) and verify your application is accessible. - Confirm SSL is working correctly by accessing
https://app.bekaiym.biz
.
- Navigate to your domain, (in my case, it is
-
Check Logs
$ kubectl logs <POD_NAME>
-
Describe Resources
$ kubectl describe pod <POD_NAME> $ kubectl describe service <SERVICE_NAME> $ kubectl describe ingress <INGRESS_NAME>
Now, you have successfully deployed the Awesome Cats application on GKE with an NGINX Ingress Controller, secure SSL certificates via Cert-Manager, and PostgreSQL as your database.