Faveo Helpdesk K8s
Deploying Faveo Helpdesk on managed Kubernetes Cluster
Introduction
In this article, we’ll be deploying Faveo Helpdesk app on top of Kubernetes. But first, you may be wondering why we’re using Kubernetes and Docker for the deployment of our Faveo Helpdesk application. Kubernetes allows us to derive maximum utility from containers and build cloud-native applications that can run anywhere, independent of cloud-specific requirements. With Kubernetes, we can automatically deploy, scale, and manage our application. We will go through the steps one by one required in deploying Faveo Helpdesk app.
Prerequisites
- A Managed Kubernetes 1.19+ cluster with your connection configuration set as the kubectl default on the local machine from which you access the cluster. You can read more about installing kubectl in the official documentation.
- The Helm 3 package manager installed on your local machine. You can follow the official guide here to install Helm 3.
- A Managed Mysql 5.7 or MariaDB 10.3 database in the same region as of the Cluster.
- A Managed Redis database in the same region as of the Cluster.
- Spaces bucket in the same region. (We recommend to have all this requirements in the same region as of the cluster for better performance and good connectivity among them)
- A fully registered domain name with an available A record.You can use the domain registrar of your choice. Don’t worry about associating your domain’s A record with an IP at this time. Once you deploy Nginx ingress controller and your Load balancer is attached to your cluster, you will connect your_domain to the proper IP.
Before beginning the installation take a look at the simplified Architectural Diagram of Faveo Helpdesk on kubernetes. This will help you understand the different components used and how they are inter connected to make Faveo Helpdesk work.
Note: Digital Ocean allows you to install some of the resources or addons via one-click installers. But we recommend to follow the steps in this guide, which uses the Offcial documentaion of that addons to install them, as you will have complete control over there versions.
Step 1: Configuring and Deploying Faveo Helpdesk
In this step, you’ll create a Kubernetes object description file, also known as a manifest, for a deployment. This manifest will contain all of the configuration details needed to deploy your Faveo app to your cluster.
First, you’ll need a directory to store all your YAML configuration files. Create a new directory of your choice and create and open deploy-faveo.yml. Add the below configurations, making sure to replace order-no and license-key with your order number and license in the CURL Api. Leave the commented lines as it is. The reason for commenting certain lines here will be explained later in Step 6.
apiVersion: v1
kind: Service
metadata:
name: faveo-svc
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: faveo-pods
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: faveo-deploy
spec:
replicas: 1
selector:
matchLabels:
app: faveo-pods
template:
metadata:
labels:
app: faveo-pods
spec:
containers:
- name: faveo-apache
image: ladybird/faveo-k8s-apache2-v2
resources:
limits:
memory: 700Mi
cpu: 1
requests:
memory: 600Mi
cpu: 800m
livenessProbe:
httpGet:
path: /probe.php
port: 80
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 1
readinessProbe:
httpGet:
path: /probe.php
port: 80
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 1
volumeMounts:
- name: volume-data
mountPath: /var/www/html
# - name: cm
# mountPath: /var/www/html/.env
# subPath: .env
initContainers:
- name: fetch
image: ladybird/faveo-fetcher
command: ['sh','-c','apt update;apt install git -y; curl https://billing.faveohelpdesk.com/download/faveo\?order_number\=85070569\&serial_key\=5HINJHDGDIBK0000 --output faveo.zip; unzip faveo.zip -d html;chown -R www-data:www-data /html']
volumeMounts:
- name: volume-data
mountPath: /html
volumes:
- name: volume-data
emptyDir: {}
# - name: cm
# configMap:
# name: faveo-env
Save and close the file.
Next, apply your new deployment with the following command:
kubetctl apply -f deploy-faveo.yml
This will create a service and deployment for Faveo helpdesk pods.You can confirm by executing below commands.
kubectl get pods
kubectl get svc
Now that we have the Faveo app running but it is still not accessible externally. For this we need to route the external traffic to faveo-svc service which we created by applying deploy-faveo.yml to the cluster.
You’ve created deployment of the Faveo helpdesk app with accompanying Service.In the next step, you’ll install the Nginx Ingress Controller which will enable external traffic to route to appropriate backed service.
Step 2: Configuring Nginx Ingress Controller
The Nginx Ingress Controller consists of a Pod and a Service. The Pod runs the Controller, which constantly polls the /ingresses endpoint on the API server of your cluster for updates to available Ingress Resources. The Service is of type LoadBalancer, the cluster will automatically create a Load Balancer on your cloud provider, through which all external traffic will flow to the Controller. The Controller will then route the traffic to appropriate Services, as defined in Ingress Resources.
Only the LoadBalancer Service knows the IP address of the automatically created Load Balancer. To install the Nginx Ingress Controller to your cluster, you’ll first need to add its repository to Helm by running:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
Update your local Helm chart repository cache:
helm repo update
Create a namespace for Ingress Nginx:
kubectl create ns ingress-nginx
Finally, run the following command to install the Nginx ingress:
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace=ingress-nginx
The above command installs the Nginx Ingress Controller from the stable charts repository and deploys a LoadBalancer. You can watch the LoadBalancer become availble by running.
kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller
At this point once the External IP is availble copy that and set the A record for your domain in your registrar.
You’ve installed the Nginx Ingress maintained by the Kubernetes community. It will route HTTP and HTTPS traffic from the Load Balancer to appropriate back-end Services, configured in Ingress Resources. In the next step, you’ll expose the Faveo Helpdesk app deployments using an Ingress Resource.
Step 3: Exposing the App Using an Ingress
Now you’re going to create an Ingress Resource and use it to expose the Faveo helpdesk app deployments at your desired domains. You’ll then test it by accessing it from your browser.
You’ll store the Ingress in a file named ingress.yml. Create it using your editor. Add the following lines to your file:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: faveo-ingress
namespace: default
spec:
rules:
- host: "your_domain_name"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: faveo-svc
port:
number: 80
Make sure to replace your_domain_name . Save and close the file.
Create it in Kubernetes by running the following command:
kubectl apply -f ingress.yml
Next, you’ll need to ensure that your domain is pointed to the Load Balancer via A records. This is done in your domain registrar. Once your domain name is fully propagated to the Loadbalancer IP. You can visit your Faveo helpdesk app from browser using http://==your_domain_name== .
You’ve created and configured an Ingress Resource to serve the Faveo Helpdesk app deployments at your domain. In the next step, you’ll set up Cert-Manager, so you’ll be able to secure your Ingress Resources with free TLS certificates from Let’s Encrypt.
Step 4: Securing the Ingress Using Cert-Manager
To secure your Ingress Resources, you’ll install Cert-Manager, create a ClusterIssuer for production, and modify the configuration of your Ingress to take advantage of the TLS certificates. ClusterIssuers are Cert-Manager Resources in Kubernetes that provision TLS certificates for the whole cluster. Once installed and configured, your app will be running behind HTTPS.
Add the Jetstack Helm repository:
helm repo add jetstack https://charts.jetstack.io
Update your local Helm chart repository cache:
helm repo update
Install cert-manager and its Custom Resource Definitions (CRDs) like Issuers and ClusterIssuers
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.8.0 \
--set installCRDs=true
To verify our installation, check the cert-manager Namespace for running pods:
kubectl get pods --namespace cert-manager
You’ll now create one that issues Let’s Encrypt certificates, and you’ll store its configuration in a file named cluster_issuer.yaml. Create it and open it for editing.
Add the following lines:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# Email address used for ACME registration
email: your_email_address
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Name of a secret used to store the ACME account private key
name: letsencrypt-prod
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: nginx
This configuration defines a ClusterIssuer that contacts Let’s Encrypt in order to issue certificates. You’ll need to replace your_email_address with your email address in order to receive possible urgent notices regarding the security and expiration of your certificates.
Save and close the file.
Roll it out with kubectl:
kubectl apply -f cluster_issuer.yml
With Cert-Manager installed, you’re ready to introduce the certificates to the Ingress Resource defined in the previous step. Open ingress.yml for editing. Update it with the below code:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
name: faveo-ingress
namespace: default
spec:
tls:
- hosts:
- your_domain_name
secretName: faveo-tls
rules:
- host: your_domain_name
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: faveo-svc
port:
number: 80
Remember to replace the your_domain_name with your own domain. When you’ve finished editing, save and close the file.
Re-apply this configuration to your cluster by running the following command:
kubectl apply -f ingress.yml
You’ll need to wait a few minutes for the Let’s Encrypt servers to issue a certificate for your domains. In the meantime, you can track its progress by inspecting the output of the following command:
kubectl get certificate
From the output of the above command the READY field must be True. Navigate to your domain in your browser to test. You’ll find the padlock to the left of the address bar in your browser, signifying that your connection is secure.
In this step, you have installed Cert-Manager using Helm and created a Let’s Encrypt ClusterIssuer. After, you updated your Ingress Resource to take advantage of the Issuer for generating TLS certificates. In the end, you have confirmed that HTTPS works correctly by navigating to your domain in your browser.
Step 5: Faveo Helpdesk Web UI installtion
At this point if the domain name is propagated properly with your server’s IP you can open Faveo in browser just by entering your domainname. You can also check the Propagation update by Visiting this site www.whatsmydns.net.
Now you can install Faveo via GUI Wizard
Step 6: Creating and Configuring ConfigMap for .env
After completing Step 4 you have generated .env file under the faveo root directory. Faveo Helpdesk is laravel based Web Application which solely relies on .env file for functionality. The .env file stores all the sensitive information such as Database credentials, Redis, S3 etc which is later used by the code base.
If you take a look at deploy-faveo.yml which you created in Step 1, the replicas and part of volume definitions will be commented out. So creating that deploy-faveo.yml manifest will result in creating only one pod which contains the Faveo code base where we generated the .env file after completing the Step 5.
ConfigMaps allow us to keep configurations separate from application images. Such separation is useful when other alternatives are not a good fit. ConfigMap takes a configuration from a source and mounts it into running containers as a volume. This was we can achieve the configuration of the .env file to be shared across multiple pods and nodes. We are literally achieving persistent volume.
After injecting configmap as volume, we can achieve multiple replicas of pods, auto scalling of pods.
First let’s retrive the content of .env by getting inside the running container. Execute the below command to get the pod name.
kubectl get pod
Copy and replace the pod name from the previous output
kubectl exec -ti your_pod_name -- bash
This is will give you access to the bash shell inside the container. Use cat or nano to get the content of the .env file.
cat .env
or
nano .env
Copy those values and save it somewhere on you machine to be used later.
Now, create a file named configmap.yml. Add the following lines and place all the content of .env you copied previously under “.env: |” section.
apiVersion: v1
kind: ConfigMap
metadata:
name: faveo-env
data:
.env: |
***** Replace you content here *******
.................
DB_ENGINE=MyISAM
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
CACHE_DRIVER=redis
SESSION_DRIVER=file
SESSION_COOKIE_NAME=faveo_8079
QUEUE_DRIVER=sync
FCM_SERVER_KEY=AIzaSyBJNRvyub-_-DnOAiIJfuNOYMnffO2sfw4
FCM_SENDER_ID=505298756081
........................
........................
****************************************
Make sure you replaced all the content of your .env under the “.env |”. Roll it out with kubectl:
kubectl apply -f configmap.yml
Verfify its running:
kubectl get cm
Now, Let’s modify the deployment to mount configmap inside and also lets increase the number of replicas. Open deploy-faveo.yml and uncomment all the commented lines. It should now look like this.
apiVersion: v1
kind: Service
metadata:
name: faveo-svc
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
app: faveo-pods
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: faveo-deploy
spec:
replicas: 3
selector:
matchLabels:
app: faveo-pods
template:
metadata:
labels:
app: faveo-pods
spec:
containers:
- name: faveo-apache
image: ladybird/faveo-k8s-apache2-v2
resources:
limits:
memory: 700Mi
cpu: 1
requests:
memory: 600Mi
cpu: 800m
livenessProbe:
httpGet:
path: /probe.php
port: 80
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 1
readinessProbe:
httpGet:
path: /probe.php
port: 80
initialDelaySeconds: 5
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 1
volumeMounts:
- name: volume-data
mountPath: /var/www/html
- name: cm
mountPath: /var/www/html/.env
subPath: .env
initContainers:
- name: fetch
image: ladybird/faveo-fetcher
command: ['sh','-c','apt update;apt install git -y; curl https://billing.faveohelpdesk.com/download/faveo\?order_number\=85070569\&serial_key\=5HINJHDGDIBK0000 --output faveo.zip; unzip faveo.zip -d html;chown -R www-data:www-data /html']
volumeMounts:
- name: volume-data
mountPath: /html
volumes:
- name: volume-data
emptyDir: {}
- name: cm
configMap:
name: faveo-env
Save and close the file. Lets inject this updated definition to kube api:
kubectl apply -f deploy-faveo.yml
Now the single pod which was running before will be terminating and new 3 pods will be created with updated definition. You can give your desired number of replicas. You can also use Horizontal Pod scaling along with metrics server for autoscaling and descaling. Verify the new pods running by executing the below command:
kubectl get pods
Now that you have created a configmap out of .env and configured it in the deployment which will mount the .env inside all the pods that it creates. The configmap not only will be used by faveo deployment pods but aslo by the supervisor deployment which you will create in next step.
Step 7: Configuring and Deploying Supervisor
Faveo Helpdesk requires certain set of command to be executed to have the Emails sending/receiving, reports generating and recurring. To achieve this we will be spinng a supervisor pod with .env mounted inside it via configmap, which then does the job or us.
Create and open file suprevisor.yml and copy the following lines inside it. Make sure to replace order-no and license-key with your order number and license in the CURL Api.
apiVersion: apps/v1
kind: Deployment
metadata:
name: supervior-deploy
spec:
replicas: 1
selector:
matchLabels:
app: supervisor-pods
template:
metadata:
labels:
app: supervisor-pods
spec:
containers:
- name: faveo-supervisor
image: ladybird/faveo-k8s-supervisor-v2
resources:
limits:
memory: 1024Mi
cpu: 1
requests:
memory: 900Mi
cpu: 900m
volumeMounts:
- name: volume-data
mountPath: /var/www/html
- name: cm
mountPath: /var/www/html/.env
subPath: .env
initContainers:
- name: fetch
image: ladybird/faveo-fetcher
command: ['sh','-c','apt update;apt install git -y; curl https://billing.faveohelpdesk.com/download/faveo\?order_number\=order-no\&serial_key\=license-key --output faveo.zip; unzip faveo.zip -d html;chown -R www-data:www-data /html']
volumeMounts:
- name: volume-data
mountPath: /html
volumes:
- name: volume-data
emptyDir: {}
- name: cm
configMap:
name: faveo-env
Save and close the file.
Next, apply your new deployment with the following command:
kubetctl apply -f deploy-faveo.yml
This will create a supervisor deployment .You can confirm by executing below commands.
kubectl get pods
Now you should see supervisor pod running along with Faveo Helpdesk pods.
The supervisor pod will use the configuration from .env which is mounted via configmap to perform all the operations. Always keep the number of supervisor replicas to 1 increasing this will lead unnecessary overlapping of mails and