In this project, I will walk you through the process of how I set up a local multi-node Kubernetes cluster using MicroK8s for serving the portfolio frontend and backend with a Nginx Ingress controller. This will allow you to experiment with multi-node Kubernetes features and deploy applications in a local environment.
MicroK8s can be installed using snap on Ubuntu. The classic flag is required to install snap packages that require full system access.
1sudo apt-get install snapd
First we need to install microk8s. MicroK8s can be installed using snap on Ubuntu. The classic flag is required to install snap packages that require full system access.
1sudo snap install microk8s --classic
Now that MicroK8s is installed, we can verify the installation by checking the status of the cluster. The --wait-ready flag will wait until all the services are up and running.
1microk8s status --wait-ready
MicroK8s can be used to create a multi-node Kubernetes cluster. We can add other nodes to the cluster using the following command. The command will generate a join command that can be used to add other nodes to the cluster.
1microk8s add-node
MicroK8s comes with a built-in Nginx Ingress controller, DNS, and cert-manager. We will be using these to handle our HTTPS encryption. We can enable those services using the following commands. After enableing the Ingress controller, we can check the status of the pods in the ingress namespace.
1microk8s enable ingress2microk8s enable dns3microk8s enable cert-manager4microk8s kubectl get pods
We need to create a ClusterIssuer for Let's Encrypt to issue certificates for our domain. The following ClusterIssuer will use the Let's Encrypt staging server to issue certificates. This is useful for testing purposes as it has a higher rate limit than the production server.
1apiVersion: cert-manager.io/v12 kind: ClusterIssuer3 metadata:4 name: letsencrypt-staging5 spec:6 acme:7 server: https://acme-staging-v02.api.letsencrypt.org/directory8 email: your-[email protected]9 privateKeySecretRef:10 name: letsencrypt-staging11 solvers:12 - http01:13 ingress:14 podTemplate:15 metadata:16 annotations:17 kubernetes.io/ingress.class: "nginx"
Now we will create a Certificate resource that requests an SSL certificate from Let's Encrypt. This certificate will be used by the Ingress resource.
1apiVersion: cert-manager.io/v12 kind: Certificate3 metadata:4 name: example-com-tls5 namespace: default6 spec:7 secretName: example-com-tls8 issuerRef:9 name: letsencrypt-prod10 kind: ClusterIssuer11 commonName: example.com12 dnsNames:13 - example.com
Now that the Nginx Ingress controller is enabled, our ClusterIssuer is created, and the Certificate resource is ready, we can create an Ingress resource to route traffic to the services running in the cluster. The following Ingress resource will route traffic to the service running on port 80.
1apiVersion: networking.k8s.io/v12kind: Ingress3metadata:4 name: example-ingress5 namespace: default6 annotations:7 cert-manager.io/cluster-issuer: "letsencrypt-prod"8 nginx.ingress.kubernetes.io/ssl-redirect: "false"9 nginx.ingress.kubernetes.io/force-ssl-redirect: "false"10spec:11 ingressClassName: nginx12 tls:13 - hosts:14 - example.com15 secretName: example-com-tls16 rules:17 - host: example.com18 http:19 paths:20 - path: /21 pathType: Prefix22 backend:23 service:24 name: frontend-service25 port:26 number: 80
We will create a Deployment resource for the frontend service. The following Deployment resource will create a pod with the frontend container image and expose it as a service on port 3000. I use gitlab to hold my containers, so I have also included a secret for my gitlab application password.
1apiVersion: apps/v12kind: Deployment3metadata:4 name: frontend-deployment5spec:6 replicas: 17 selector:8 matchLabels:9 app: frontend-deployment10 template:11 metadata:12 labels:13 app: frontend-deployment14 spec:15 containers:16 - name: frontend-deployment17 image: registry.gitlab.com/your_username/frontend_container:latest18 ports:19 - containerPort: 300020 imagePullSecrets:21 - name: gitlab-registry-secret
We will create a Service resource for the frontend service. The following Service resource will pass traffic from the ingress controller on port 80 to port 3000 of the container.
1apiVersion: v12kind: Service3metadata:4 name: frontend-service5spec:6 selector:7 app: frontend-deployment8 ports:9 - protocol: TCP10 port: 8011 targetPort: 300012 type: ClusterIP
Next we will make the Deployment resource for the backend service. The following Deployment resource will create a pod with the backend container image and expose it as a service on port 8000. I use environment variables in my backend to keep the app password for my gmail account that emails the contact information to me so I have included secrets for the environment as well.
1apiVersion: apps/v12kind: Deployment3metadata:4 name: backend-deployment5spec:6 replicas: 17 selector:8 matchLabels:9 app: backend-deployment10 template:11 metadata:12 labels:13 app: backend-deployment14 spec:15 containers:16 - name: backend-deployment17 env:18 - name: SENDER_EMAIL19 valueFrom:20 secretKeyRef:21 name: email-secret22 key: sender-email23 - name: RECIPIENT_EMAIL24 valueFrom:25 secretKeyRef:26 name: email-secret27 key: recipient-email28 - name: SENDER_APP_PASSWORD29 valueFrom:30 secretKeyRef:31 name: email-secret32 key: sender-app-password33 image: registry.gitlab.com/your_username/backend_container:latest34 ports:35 - containerPort: 800036 imagePullSecrets:37 - name: gitlab-registry-secret
We will create a Service resource for the backend service. The following Service resource will pass traffic from the ingress controller on port 8000 to port 8000 of the container. You may have noticed that the ingress controller does not have an entry for the backend service. This is because I am not exposing my backend externally and am only communicating with it server side on the frontend.
1apiVersion: v12kind: Service3metadata:4 name: backend-service5spec:6 selector:7 app: backend-deployment8 ports:9 - protocol: TCP10 port: 800011 targetPort: 800012 type: ClusterIP
The resources are created and ready to be applied to the cluster. We can apply the resources using the following commands. Once the resources are applied, we will verify the certificate.
1microk8s kubectl apply -f cluster-issuer.yaml2microk8s kubectl apply -f certificate.yaml3microk8s kubectl apply -f ingress.yaml4microk8s kubectl apply -f frontend-service.yaml5microk8s kubectl apply -f frontend-deployment.yaml6microk8s kubectl apply -f backend-deployment.yaml7microk8s kubectl apply -f backend-service.yaml8microk8s kubectl describe certificate example-com-tls
You should now have a local Kubernetes cluster set up with a Nginx Ingress controller, DNS, and cert-manager enabled. You should be able to access your frontend over https due to the Let's Encrypt certificate. You can now experiment with deploying other applications and services to your cluster.