GitHub Source Code
https://github.com/Gatete-Bruno/email-operator/tree/main
Prerequisites
go version v1.20.0+
docker version 17.03+.
kubectl version v1.11.3+.
Access to a Kubernetes v1.11.3+ cluster.
Installing Docker on your environment
https://docs.docker.com/engine/install/
Installing kubectl on your environment
https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
Installing Go on your environment
Setting a Kubernetes Cluster
In my case I opted to use AWS EKS as it is easier to bootsrap
Requirments :
Make sure you have access to aws cli and you can use aws configure
Have your credentials setup
How to bootsrap your K8s cluster :
eksctl create cluster --name mailersend-cluster --region us-east-1 --nodegroup-name standard-workers --node-type t3.medium --nodes 3
aws eks update-kubeconfig --name mailersend-cluster
We already have our images pushed to docker hub we will need to deploy using that
To Deploy on the cluster
Install the CRDs into the cluster:
make install
Deploy the Manager to the cluster with the image specified byIMG
:
make deploy IMG=bruno74t/email-operator:v13.0
How it will look like
bruno@Batman-2 email-operator % make deploy IMG=bruno74t/email-operator:v13.0
test -s /Users/bruno/Desktop/mailersend-k8s-operator/projects/email-operator/bin/controller-gen && /Users/bruno/Desktop/mailersend-k8s-operator/projects/email-operator/bin/controller-gen --version | grep -q v0.13.0 || \
GOBIN=/Users/bruno/Desktop/mailersend-k8s-operator/projects/email-operator/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.13.0
/Users/bruno/Desktop/mailersend-k8s-operator/projects/email-operator/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
cd config/manager && /Users/bruno/Desktop/mailersend-k8s-operator/projects/email-operator/bin/kustomize edit set image controller=bruno74t/email-operator:v13.0
/Users/bruno/Desktop/mailersend-k8s-operator/projects/email-operator/bin/kustomize build config/default | kubectl apply -f -
namespace/email-operator-system unchanged
customresourcedefinition.apiextensions.k8s.io/emails.email.batman.example.com unchanged
customresourcedefinition.apiextensions.k8s.io/emailsenderconfigs.email.batman.example.com unchanged
serviceaccount/email-operator-email-operator-controller-manager unchanged
role.rbac.authorization.k8s.io/email-operator-leader-election-role unchanged
clusterrole.rbac.authorization.k8s.io/email-operator-manager-role unchanged
clusterrole.rbac.authorization.k8s.io/email-operator-metrics-reader unchanged
clusterrole.rbac.authorization.k8s.io/email-operator-proxy-role unchanged
rolebinding.rbac.authorization.k8s.io/email-operator-leader-election-rolebinding unchanged
clusterrolebinding.rbac.authorization.k8s.io/email-operator-manager-rolebinding unchanged
clusterrolebinding.rbac.authorization.k8s.io/email-operator-proxy-rolebinding unchanged
service/email-operator-controller-manager-metrics-service unchanged
deployment.apps/email-operator-controller-manager unchanged
bruno@Batman-2 email-operator % kubectl get all -n email-operator-system
NAME READY STATUS RESTARTS AGE
pod/email-operator-controller-manager-5dbccbb4cb-ghjf4 2/2 Running 0 24m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/controller-manager-metrics-service ClusterIP 10.100.116.206 <none> 8443/TCP 25m
service/email-operator-controller-manager-metrics-service ClusterIP 10.100.27.240 <none> 8443/TCP 36m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/email-operator-controller-manager 1/1 1 1 36m
NAME DESIRED CURRENT READY AGE
replicaset.apps/email-operator-controller-manager-5dbccbb4cb 1 1 1 24m
replicaset.apps/email-operator-controller-manager-bb9c7cb86 0 0 0 27m
replicaset.apps/email-operator-controller-manager-cfffdf4cf 0 0 0 36m
The most important requirement here will be to setup the mailgun-api-token on your cluster
kubectl create secret generic mailgun-api-token \
--from-literal=api-token=<YOUR-MAILGUN-API-TOKEN> \
-n email-operator-system
You should have something like this on your cluster :
bruno@Batman-2 email-operator % kubectl get secrets -n email-operator-system
NAME TYPE DATA AGE
mailgun-api-token Opaque 1 65m
bruno@Batman-2 email-operator %
Check if all everything is okay on the namespace (email-operator-system)
bruno@Batman-2 email-operator % kubectl get all -n email-operator-system
NAME READY STATUS RESTARTS AGE
pod/email-operator-controller-manager-78c798457d-b9qtw 2/2 Running 0 38m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/controller-manager-metrics-service ClusterIP 10.100.116.206 <none> 8443/TCP 64m
service/email-operator-controller-manager-metrics-service ClusterIP 10.100.27.240 <none> 8443/TCP 75m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/email-operator-controller-manager 1/1 1 1 75m
NAME DESIRED CURRENT READY AGE
replicaset.apps/email-operator-controller-manager-5dbccbb4cb 0 0 0 64m
replicaset.apps/email-operator-controller-manager-78c798457d 1 1 1 38m
replicaset.apps/email-operator-controller-manager-bb9c7cb86 0 0 0 67m
replicaset.apps/email-operator-controller-manager-cfffdf4cf 0 0 0 75m
bruno@Batman-2 email-operator %
Once everything is in place check to see if the operator has been deployed successfully
bruno@Batman-2 email-operator % kubectl logs deployment.apps/email-operator-controller-manager -n email-operator-system
2024-06-13T07:50:13Z INFO setup starting manager
2024-06-13T07:50:13Z INFO starting server {"kind": "health probe", "addr": "[::]:8081"}
2024-06-13T07:50:13Z INFO controller-runtime.metrics Starting metrics server
2024-06-13T07:50:13Z INFO controller-runtime.metrics Serving metrics server {"bindAddress": "127.0.0.1:8080", "secure": false}
I0613 07:50:13.304846 1 leaderelection.go:250] attempting to acquire leader lease email-operator-system/650681eb.batman.example.com...
I0613 07:50:38.613997 1 leaderelection.go:260] successfully acquired lease email-operator-system/650681eb.batman.example.com
2024-06-13T07:50:38Z INFO Starting EventSource {"controller": "emailsenderconfig", "controllerGroup": "email.batman.example.com", "controllerKind": "EmailSenderConfig", "source": "kind source: *v1alpha1.EmailSenderConfig"}
2024-06-13T07:50:38Z INFO Starting Controller {"controller": "emailsenderconfig", "controllerGroup": "email.batman.example.com", "controllerKind": "EmailSenderConfig"}
2024-06-13T07:50:38Z INFO Starting EventSource {"controller": "email", "controllerGroup": "email.batman.example.com", "controllerKind": "Email", "source": "kind source: *v1alpha1.Email"}
2024-06-13T07:50:38Z INFO Starting Controller {"controller": "email", "controllerGroup": "email.batman.example.com", "controllerKind": "Email"}
2024-06-13T07:50:38Z DEBUG events email-operator-controller-manager-78c798457d-b9qtw_e9c498bf-980b-4f47-bf90-29a9ca1dc227 became leader {"type": "Normal", "object": {"kind":"Lease","namespace":"email-operator-system","name":"650681eb.batman.example.com","uid":"4cc830f6-fe99-443e-8556-da98381160b9","apiVersion":"coordination.k8s.io/v1","resourceVersion":"10838"}, "reason": "LeaderElection"}
2024-06-13T07:50:38Z INFO Starting workers {"controller": "emailsenderconfig", "controllerGroup": "email.batman.example.com", "controllerKind": "EmailSenderConfig", "worker count": 1}
2024-06-13T07:50:38Z INFO Starting workers {"controller": "email", "controllerGroup": "email.batman.example.com", "controllerKind": "Email", "worker count": 1}
2024-06-13T07:52:57Z INFO KubeAPIWarningLogger metadata.finalizers: "emailSenderConfig.finalizers.batman.example.com": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers
bruno@Batman-2 email-operator %
Final Step is to Deploy the email testing yaml files
bruno@Batman-2 email-operator % tree config/samples
config/samples
├── email_v1alpha1_email.yaml
├── email_v1alpha1_emailsenderconfig.yaml
└── kustomization.yaml
1 directory, 3 files
bruno@Batman-2 email-operator % cat config/samples/email_v1alpha1_email.yaml
apiVersion: email.batman.example.com/v1alpha1
kind: Email
metadata:
labels:
app.kubernetes.io/name: email
app.kubernetes.io/instance: email-sample
app.kubernetes.io/part-of: email-operator
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: email-operator
name: email-sample
namespace: email-operator-system
spec:
senderConfigRef: emailsenderconfig-sample # Ensure this is correct
recipientEmail: "catobrunoisrael@gmail.com"
subject: "Test Email"
body: "This is the first test email using k8s operator."
bruno@Batman-2 email-operator % cat config/samples/email_v1alpha1_emailsenderconfig.yaml
apiVersion: email.batman.example.com/v1alpha1
kind: EmailSenderConfig
metadata:
labels:
app.kubernetes.io/name: emailsenderconfig
app.kubernetes.io/instance: emailsenderconfig-sample
app.kubernetes.io/part-of: email-operator
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: email-operator
name: emailsenderconfig-sample # Corrected name
namespace: email-operator-system
spec:
apiTokenSecretRef: mailgun-api-token
senderEmail: kato@example.com
mailgunConfig:
domain: "sandbox949259d91ad141fa8fb2518c835ccf49.mailgun.org"
apiKeySecretRef: mailgun-api-token
bruno@Batman-2 email-operator %
Once you have applied the manifest files
kubectl delete -f config/samples/email_v1alpha1_email.yaml
kubectl delete -f config/samples/email_v1alpha1_emailsenderconfig.yaml
kubectl apply -f config/samples/email_v1alpha1_emailsenderconfig.yaml
kubectl apply -f config/samples/email_v1alpha1_email.yaml
Monitor Operator Logs
Monitor the logs of your Kubernetes operator to check for any messages related
bruno@Batman-2 email-operator % kubectl logs deployment.apps/email-operator-controller-manager -n email-operator-system -c manager
2024-06-13T07:50:13Z INFO setup starting manager
2024-06-13T07:50:13Z INFO starting server {"kind": "health probe", "addr": "[::]:8081"}
2024-06-13T07:50:13Z INFO controller-runtime.metrics Starting metrics server
2024-06-13T07:50:13Z INFO controller-runtime.metrics Serving metrics server {"bindAddress": "127.0.0.1:8080", "secure": false}
I0613 07:50:13.304846 1 leaderelection.go:250] attempting to acquire leader lease email-operator-system/650681eb.batman.example.com...
I0613 07:50:38.613997 1 leaderelection.go:260] successfully acquired lease email-operator-system/650681eb.batman.example.com
2024-06-13T07:50:38Z INFO Starting EventSource {"controller": "emailsenderconfig", "controllerGroup": "email.batman.example.com", "controllerKind": "EmailSenderConfig", "source": "kind source: *v1alpha1.EmailSenderConfig"}
2024-06-13T07:50:38Z INFO Starting Controller {"controller": "emailsenderconfig", "controllerGroup": "email.batman.example.com", "controllerKind": "EmailSenderConfig"}
2024-06-13T07:50:38Z INFO Starting EventSource {"controller": "email", "controllerGroup": "email.batman.example.com", "controllerKind": "Email", "source": "kind source: *v1alpha1.Email"}
2024-06-13T07:50:38Z INFO Starting Controller {"controller": "email", "controllerGroup": "email.batman.example.com", "controllerKind": "Email"}
2024-06-13T07:50:38Z DEBUG events email-operator-controller-manager-78c798457d-b9qtw_e9c498bf-980b-4f47-bf90-29a9ca1dc227 became leader {"type": "Normal", "object": {"kind":"Lease","namespace":"email-operator-system","name":"650681eb.batman.example.com","uid":"4cc830f6-fe99-443e-8556-da98381160b9","apiVersion":"coordination.k8s.io/v1","resourceVersion":"10838"}, "reason": "LeaderElection"}
2024-06-13T07:50:38Z INFO Starting workers {"controller": "emailsenderconfig", "controllerGroup": "email.batman.example.com", "controllerKind": "EmailSenderConfig", "worker count": 1}
2024-06-13T07:50:38Z INFO Starting workers {"controller": "email", "controllerGroup": "email.batman.example.com", "controllerKind": "Email", "worker count": 1}
2024-06-13T07:52:57Z INFO KubeAPIWarningLogger metadata.finalizers: "emailSenderConfig.finalizers.batman.example.com": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers
bruno@Batman-2 email-operator %
you should be able to check the status of the emails sent
bruno@Batman-2 email-operator % kubectl describe email email-sample -n email-operator-system
Name: email-sample
Namespace: email-operator-system
Labels: app.kubernetes.io/created-by=email-operator
app.kubernetes.io/instance=email-sample
app.kubernetes.io/managed-by=kustomize
app.kubernetes.io/name=email
app.kubernetes.io/part-of=email-operator
Annotations: <none>
API Version: email.batman.example.com/v1alpha1
Kind: Email
Metadata:
Creation Timestamp: 2024-06-13T07:56:40Z
Generation: 1
Resource Version: 12048
UID: 7327636e-c232-423e-a08b-d2a4c2f7cfc5
Spec:
Body: This is the first test email using k8s operator.
Recipient Email: catobrunoisrael@gmail.com
Sender Config Ref: emailsenderconfig-sample
Subject: Test Email
Status:
Delivery Status: Failed
Error: Unknown error
Events: <none>
bruno@Batman-2 email-operator %
My email Delivery Status is failing without showing any events or anything ..I am still trying to find out why !