Tutorial - Clean up MicroK8s Cluster and Redeploy with Helm
In this tutorial, you will learn how to clean up the MicroK8s cluster removing all the containers, deployments, configmaps, secrets, etc from the previous tutorials. MariaDB and EJBCA are deployed using a Helm chart on the cleaned-up cluster. The database is backed up and restored that way all the configuration that has been done from the previous tutorials is not lost.
Over the last year, all the EJBCA tutorials have been demonstrated on a MicroK8s virtual machine. EJBCA was deployed with YAML files and it would be nice to redeploy EJBCA using Helm. It’s time to clean up and clear out the cluster starting with a fresh deployment of EJBCA using a backup of the MariaDB database.
If you want to clean house, start fresh, and use Helm then this tutorial is for you.
The tutorial covers these steps:
Review what is deployed in the MicroK8s cluster
Backup the MariaDB database
Reset the MicroK8s cluster
Install required services on the MicroK8s cluster
Deploy MariaDB using Helm and restore the MariaDB backup
Deploy EJBCA using Helm
Prerequisites
For this tutorial, EJBCA Community Docker container version 8.2.0.1 was used.
Before you begin, you need:
A virtual machine running MicroK8s.
To have completed the tutorial deploy EJBCA and MariaDB containers in MicroK8s.
Step 1 - Review what is deployed in the cluster
If you have been trying out the previous tutorials, there are a lot of pieces and parts deployed and configured in MicroK8s from following the tutorials. Follow the steps below to review what is currently deployed in the cluster:
Review all of the deployments and items deployed:
$ kubectl get all,ingress,secret,pv,pvc,svc,no --all-namespacesThe output is similar to the following:
NAMESPACE NAME READY STATUS RESTARTS AGEcert-manager pod/cert-manager-55cf8685cb-tztzk1/1Running 15 (2d21h ago) 151dcert-manager pod/cert-manager-cainjector-fbd548cb8-nrr7l1/1Running 20 (2d21h ago) 151dcert-manager pod/cert-manager-webhook-655b4d58fb-46zzh1/1Running 12 (2d21h ago) 151dejbca-cert-manager pod/ejbca-cert-manager-issuer-6c5549d575-qd52x1/1Running 30 (2d21h ago) 137dejbca-k8s pod/ejbca-deployment-78fdbbb5c4-n5v2p1/1Running 12 (2d21h ago) 167dejbca-k8s pod/ejbca-httpd-7d646c85f9-2n68j1/1Running 3 (2d21h ago) 48dejbca-k8s pod/mariadb-deployment-5665d96759-sdg241/1Running 3 (2d21h ago) 48dingress pod/nginx-ingress-microk8s-controller-sqk8c1/1Running 2 (2d21h ago) 24distio-system pod/istio-egressgateway-66fc798fb8-6cmc40/1Running 22 (2d21h ago) 442distio-system pod/istio-ingressgateway-668c8c965b-s77250/1Running 22 (2d21h ago) 442distio-system pod/istiod-7fc54f9bd-qhwxg1/1Running 27 (2d21h ago) 442dkube-system pod/calico-kube-controllers-7c8c9d85c9-htp241/1Running 3 (2d21h ago) 48dkube-system pod/calico-node-c4ffk1/1Running 0 2d21hkube-system pod/coredns-6f5f9b5d74-wxbmz1/1Running 28 (2d21h ago) 449dkube-system pod/hostpath-provisioner-69cd9ff5b8-fx8ps1/1Running 45 (2d21h ago) 449dmetallb-system pod/controller-9556c586f-gzbm61/1Running 28 (2d21h ago) 449dmetallb-system pod/speaker-58lm51/1Running 39 (2d21h ago) 449dpkirules pod/ejbca-cm-issuer-helloworld-one-6c886556f9-xth781/1Terminating 8 (2d21h ago) 136dNAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEcert-manager service/cert-managerClusterIP 10.152.183.223 <none> 9402/TCP151dcert-manager service/cert-manager-webhookClusterIP 10.152.183.154 <none> 443/TCP151ddefault service/kubernetesClusterIP 10.152.183.1 <none> 443/TCP449dejbca-k8s service/ejbca-database-serviceClusterIP 10.152.183.44 <none> 3306/TCP449dejbca-k8s service/ejbca-internalClusterIP 10.152.183.133 <none> 443/TCP,80/TCP449dejbca-k8s service/ejbca-serviceClusterIP 10.152.183.46 <none> 8009/TCP449dingress service/ejbca-node1LoadBalancer 10.152.183.171 172.16.170.240 80:31205/TCP,443:30622/TCP449distio-system service/istio-egressgatewayClusterIP 10.152.183.125 <none> 80/TCP,443/TCP442distio-system service/istio-ingressgatewayLoadBalancer 10.152.183.92 172.16.170.241 15021:30350/TCP,80:31533/TCP,443:30430/TCP,31400:32547/TCP,15443:31322/TCP442distio-system service/istiodClusterIP 10.152.183.76 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP442dkube-system service/kube-dnsClusterIP 10.152.183.10 <none> 53/UDP,53/TCP,9153/TCP449dmetallb-system service/webhook-serviceClusterIP 10.152.183.52 <none> 443/TCP449dNAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGEingress daemonset.apps/nginx-ingress-microk8s-controller1 1 1 1 1 <none> 449dkube-system daemonset.apps/calico-node1 1 1 1 1 kubernetes.io/os=linux 449dmetallb-system daemonset.apps/speaker1 1 1 1 1 kubernetes.io/os=linux 449dNAMESPACE NAME READY UP-TO-DATE AVAILABLE AGEcert-manager deployment.apps/cert-manager1/11 1 151dcert-manager deployment.apps/cert-manager-cainjector1/11 1 151dcert-manager deployment.apps/cert-manager-webhook1/11 1 151dejbca-cert-manager deployment.apps/ejbca-cert-manager-issuer1/11 1 137dejbca-k8s deployment.apps/ejbca-deployment1/11 1 167dejbca-k8s deployment.apps/ejbca-httpd1/11 1 449dejbca-k8s deployment.apps/mariadb-deployment1/11 1 449distio-system deployment.apps/istio-egressgateway0/11 0 442distio-system deployment.apps/istio-ingressgateway0/11 0 442distio-system deployment.apps/istiod1/11 1 442dkube-system deployment.apps/calico-kube-controllers1/11 1 449dkube-system deployment.apps/coredns1/11 1 449dkube-system deployment.apps/hostpath-provisioner1/11 1 449dmetallb-system deployment.apps/controller1/11 1 449dNAMESPACE NAME DESIRED CURRENT READY AGEcert-manager replicaset.apps/cert-manager-55cf8685cb1 1 1 151dcert-manager replicaset.apps/cert-manager-cainjector-fbd548cb81 1 1 151dcert-manager replicaset.apps/cert-manager-webhook-655b4d58fb1 1 1 151dejbca-cert-manager replicaset.apps/ejbca-cert-manager-issuer-6c5549d5751 1 1 137dejbca-k8s replicaset.apps/ejbca-deployment-78fdbbb5c41 1 1 167dejbca-k8s replicaset.apps/ejbca-httpd-7d646c85f91 1 1 449dejbca-k8s replicaset.apps/mariadb-deployment-5665d967591 1 1 449distio-system replicaset.apps/istio-egressgateway-66fc798fb81 1 0 442distio-system replicaset.apps/istio-egressgateway-7bf64578670 0 0 442distio-system replicaset.apps/istio-ingressgateway-668c8c965b1 1 0 442distio-system replicaset.apps/istio-ingressgateway-8576d6c55f0 0 0 442distio-system replicaset.apps/istiod-77f9c8bf680 0 0 442distio-system replicaset.apps/istiod-7fc54f9bd1 1 1 442dkube-system replicaset.apps/calico-kube-controllers-5cdbddfc90 0 0 449dkube-system replicaset.apps/calico-kube-controllers-75b6ddb7b80 0 0 408dkube-system replicaset.apps/calico-kube-controllers-79568db7f80 0 0 449dkube-system replicaset.apps/calico-kube-controllers-7c8c9d85c91 1 1 48dkube-system replicaset.apps/calico-kube-controllers-7c9cdf4bfc0 0 0 396dkube-system replicaset.apps/calico-kube-controllers-7fcc7d84960 0 0 167dkube-system replicaset.apps/calico-kube-controllers-b5fcf779f0 0 0 60dkube-system replicaset.apps/calico-kube-controllers-df49bb540 0 0 364dkube-system replicaset.apps/coredns-6f5f9b5d741 1 1 449dkube-system replicaset.apps/hostpath-provisioner-69cd9ff5b81 1 1 449dmetallb-system replicaset.apps/controller-9556c586f1 1 1 449dNAMESPACE NAME CLASS HOSTS ADDRESS PORTS AGEejbca-k8s ingress.networking.k8s.io/ejbca-node1public ejbca-node1.ejbca-k8s 127.0.0.1 80, 443 24dNAMESPACE NAME TYPE DATA AGEcert-manager secret/cert-manager-webhook-caOpaque 3 151dcert-manager secret/sh.helm.release.v1.cert-manager.v1 helm.sh/release.v1 1 151dejbca-cert-manager secret/ejbca-ca-secretOpaque 1 151dejbca-cert-manager secret/ejbca-secretkubernetes.io/tls2 151dejbca-cert-manager secret/sh.helm.release.v1.ejbca-cert-manager-issuer.v1 helm.sh/release.v1 1 137dejbca-csr-signer secret/ejbca-client-certkubernetes.io/tls2 442dejbca-csr-signer secret/ejbca-credentialsOpaque 1 442dejbca-k8s secret/ejbca-mariadb-secretOpaque 1 449dejbca-k8s secret/mariadb-secretOpaque 1 449dejbca-k8s secret/mtls-trust-chainOpaque 1 47dejbca-k8s secret/tls-ejbca-node1kubernetes.io/tls2 60distio-system secret/external-ca-certOpaque 1 442distio-system secret/istio-ca-secretistio.io/ca-root5 442dmetallb-system secret/memberlistOpaque 1 449dmetallb-system secret/webhook-server-certOpaque 4 449dvault secret/tls-api-vaultkubernetes.io/tls2 160dvault secret/vault-ha-tlsOpaque 3 160dNAMESPACE NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGEpersistentvolume/pvc-031c7c9d-63dd-42b7-8c20-83e9e57782d7100M RWO Delete Bound ejbca-k8s/mariadb-pvcmicrok8s-hostpath <unset> 449dpersistentvolume/pvc-230714e3-ed56-498f-8386-c84b941e9b001Gi RWO Delete Bound vault/data-vault-1microk8s-hostpath <unset> 160dpersistentvolume/pvc-3d0cc22e-3c9a-4e8a-a867-9f99b9f974241Gi RWO Delete Bound vault/audit-vault-2microk8s-hostpath <unset> 160dpersistentvolume/pvc-4cacc08e-2802-4b54-9af5-b386750fa7151Gi RWO Delete Bound vault/audit-vault-0microk8s-hostpath <unset> 160dpersistentvolume/pvc-5be3658f-abda-4512-873a-38b4e9e465561Gi RWO Delete Bound vault/audit-vault-1microk8s-hostpath <unset> 160dpersistentvolume/pvc-6d665f7a-c89e-4536-8b3a-f8f5a79a4b001Gi RWO Delete Bound vault/data-vault-0microk8s-hostpath <unset> 160dpersistentvolume/pvc-903289f8-db05-44c2-8ded-fdb93a34fb211Gi RWO Delete Bound vault/data-vault-2microk8s-hostpath <unset> 160dpersistentvolume/pvc-b1d34ec9-10db-4b8d-ab3d-d8ba7810be1430M RWO Delete Bound ejbca-k8s/ejbca-pvcmicrok8s-hostpath <unset> 449dNAMESPACE NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGEejbca-k8s persistentvolumeclaim/ejbca-pvcBound pvc-b1d34ec9-10db-4b8d-ab3d-d8ba7810be14 30M RWO microk8s-hostpath <unset> 449dejbca-k8s persistentvolumeclaim/mariadb-pvcBound pvc-031c7c9d-63dd-42b7-8c20-83e9e57782d7 100M RWO microk8s-hostpath <unset> 449dvault persistentvolumeclaim/audit-vault-0Bound pvc-4cacc08e-2802-4b54-9af5-b386750fa715 1Gi RWO microk8s-hostpath <unset> 160dvault persistentvolumeclaim/audit-vault-1Bound pvc-5be3658f-abda-4512-873a-38b4e9e46556 1Gi RWO microk8s-hostpath <unset> 160dvault persistentvolumeclaim/audit-vault-2Bound pvc-3d0cc22e-3c9a-4e8a-a867-9f99b9f97424 1Gi RWO microk8s-hostpath <unset> 160dvault persistentvolumeclaim/data-vault-0Bound pvc-6d665f7a-c89e-4536-8b3a-f8f5a79a4b00 1Gi RWO microk8s-hostpath <unset> 160dvault persistentvolumeclaim/data-vault-1Bound pvc-230714e3-ed56-498f-8386-c84b941e9b00 1Gi RWO microk8s-hostpath <unset> 160dvault persistentvolumeclaim/data-vault-2Bound pvc-903289f8-db05-44c2-8ded-fdb93a34fb21 1Gi RWO microk8s-hostpath <unset> 160dNAMESPACE NAME STATUS ROLES AGE VERSIONnode/microk8-01Ready <none> 449d v1.29.4 microk8s-hostpath <unset> 159d
You have now reviewed what has been deployed in MicroK8s, continue to the next step to backup the EJBCA database.
Step 2 - Backup the EJBCA database
Time was invested to configure EJBCA following the tutorials and it would be great to not lose the EJBCA configuration. Follow these steps to backup the EJBCA database before the MicroK8s cluster is reset:
Review what directories are present in the VM host:
$ls-lThe output is similar to the following:
total 20-rw-rw-r--. 1 user user 3612 Apr 24 07:56 ca.crtdrwxrwxr-x. 3 user user 4096 Jan 26 06:30 cert-managerdrwxrwxr-x. 3 user user 88 Mar 25 2023 csr-apidrwxrwxr-x. 2 user user 4096 May 17 11:58 k81drwx------. 3 user microk8s 22 Mar 18 2023 snapdrwxrwxr-x. 2 user user 4096 Jun 9 15:34 sqldrwxrwxr-x. 2 user user 4096 Jan 2 12:01 vault
Install the MariaDB client using the DNF package manager:
$sudodnfinstall-y <https://dlm.mariadb.com/2690116/MariaDB/mariadb-10.10.2/yum/rhel8-amd64/rpms/MariaDB-client-10.10.2-1.el8.x86_64.rpm> \<https://dlm.mariadb.com/2690045/MariaDB/mariadb-10.10.2/yum/rhel8-amd64/rpms/MariaDB-backup-10.10.2-1.el8.x86_64.rpm> \<https://dlm.mariadb.com/2690100/MariaDB/mariadb-10.10.2/yum/rhel8-amd64/rpms/MariaDB-common-10.10.2-1.el8.x86_64.rpm> \<https://dlm.mariadb.com/2690079/MariaDB/mariadb-10.10.2/yum/rhel8-amd64/rpms/MariaDB-shared-10.10.2-1.el8.x86_64.rpm>Backup the database to the SQL directory:
$ mariadb-dump -h 10.152.183.44 -u root -p --all-databases --quick --lock-tables=false--system=users--insert-ignore --force > sql/20240610_BackupToMigrate.sqlThe output is similar to the following:
# mariadb-dump: Couldn't execute 'SELECT CONCAT(QUOTE(u.user), '@', QUOTE(u.Host)) AS u FROM mysql.user u /*!80001 LEFT JOIN mysql.role_edges e ON u.user=e.from_user AND u.host=e.from_host WHERE e.from_user IS NULL */ /*M!100005 WHERE is_role='N' */': Illegal mix of collations (utf8mb4_general_ci,COERCIBLE) and (utf8mb4_uca1400_ai_ci,COERCIBLE) for operation '=' (1267)
You have now backed up the EJBCA MariaDB database using the mariadb-dump utility. Continue to the next step to reset the MicroK8s cluster.
Step 3 - Reset the MicroK8s cluster
When MicroK8s is reset, the cluster is cleaned up by removing the entire configuration and restoring the cluster to the default install from when MicroK8s was first installed. To reset the cluster follow these steps:
Uninstall the ejbca cert-manager Issuer Helm deployment:
$ helm uninstall -n ejbca-cert-manager ejbca-cert-manager-issuerThe output is similar to the following:
release"ejbca-cert-manager-issuer"uninstalled
Uninstall the cert-manager Helm deployment:
$ helm uninstall -n cert-manager cert-managerThe output is similar to the following:
release"cert-manager"uninstalled
Uninstall istio using istioctl:
$ csr-api/ejbca-csr-signer/istio-1.16.3/bin/istioctluninstall --purge --forceThe output is similar to the following:
failed to get proxy infos: failure running port forward process: failure running port forward process: error upgrading connection: error dialing backend: dial tcp 172.16.170.187:10250: connect: connection refusedAll Istio resources will be pruned from the clusterProceed? (y/N)
Enter y to continue.
The output is similar to the following:
Removed IstioOperator:istio-system:installed-state.Removed Deployment:istio-system:istio-egressgateway.Removed Deployment:istio-system:istio-ingressgateway.Removed Deployment:istio-system:istiod.Removed Service:istio-system:istio-egressgateway.Removed Service:istio-system:istio-ingressgateway.Removed Service:istio-system:istiod.Removed ConfigMap:istio-system:istio.Removed ConfigMap:istio-system:istio-sidecar-injector.Removed Pod:istio-system:istio-egressgateway-66fc798fb8-6cmc4.Removed Pod:istio-system:istio-ingressgateway-668c8c965b-s7725.Removed Pod:istio-system:istiod-7fc54f9bd-qhwxg.Removed ServiceAccount:istio-system:istio-egressgateway-service-account.Removed ServiceAccount:istio-system:istio-ingressgateway-service-account.Removed ServiceAccount:istio-system:istio-reader-service-account.Removed ServiceAccount:istio-system:istiod.Removed ServiceAccount:istio-system:istiod-service-account.Removed RoleBinding:istio-system:istio-egressgateway-sds.Removed RoleBinding:istio-system:istio-ingressgateway-sds.Removed RoleBinding:istio-system:istiod.Removed RoleBinding:istio-system:istiod-istio-system.Removed Role:istio-system:istio-egressgateway-sds.Removed Role:istio-system:istio-ingressgateway-sds.Removed Role:istio-system:istiod.Removed Role:istio-system:istiod-istio-system.Removed EnvoyFilter:istio-system:stats-filter-1.13.Removed EnvoyFilter:istio-system:stats-filter-1.14.Removed EnvoyFilter:istio-system:stats-filter-1.15.Removed EnvoyFilter:istio-system:stats-filter-1.16.Removed EnvoyFilter:istio-system:tcp-stats-filter-1.13.Removed EnvoyFilter:istio-system:tcp-stats-filter-1.14.Removed EnvoyFilter:istio-system:tcp-stats-filter-1.15.Removed EnvoyFilter:istio-system:tcp-stats-filter-1.16.Removed PodDisruptionBudget:istio-system:istio-egressgateway.Removed PodDisruptionBudget:istio-system:istio-ingressgateway.Removed PodDisruptionBudget:istio-system:istiod.Removed MutatingWebhookConfiguration::istio-revision-tag-default.Removed MutatingWebhookConfiguration::istio-sidecar-injector.Removed ValidatingWebhookConfiguration::istio-validator-istio-system.Removed ValidatingWebhookConfiguration::istiod-default-validator.Removed ClusterRole::istio-reader-clusterrole-istio-system.Removed ClusterRole::istio-reader-istio-system.Removed ClusterRole::istiod-clusterrole-istio-system.Removed ClusterRole::istiod-gateway-controller-istio-system.Removed ClusterRole::istiod-istio-system.Removed ClusterRoleBinding::istio-reader-clusterrole-istio-system.Removed ClusterRoleBinding::istio-reader-istio-system.Removed ClusterRoleBinding::istiod-clusterrole-istio-system.Removed ClusterRoleBinding::istiod-gateway-controller-istio-system.Removed ClusterRoleBinding::istiod-istio-system.Removed CustomResourceDefinition::authorizationpolicies.security.istio.io.Removed CustomResourceDefinition::destinationrules.networking.istio.io.Removed CustomResourceDefinition::envoyfilters.networking.istio.io.Removed CustomResourceDefinition::gateways.networking.istio.io.Removed CustomResourceDefinition::istiooperators.install.istio.io.Removed CustomResourceDefinition::peerauthentications.security.istio.io.Removed CustomResourceDefinition::proxyconfigs.networking.istio.io.Removed CustomResourceDefinition::requestauthentications.security.istio.io.Removed CustomResourceDefinition::serviceentries.networking.istio.io.Removed CustomResourceDefinition::sidecars.networking.istio.io.Removed CustomResourceDefinition::telemetries.telemetry.istio.io.
Reset microk8s to restore MicroK8s to the default install:
$sudo/var/lib/snapd/snap/bin/microk8sresetThe output is similar to the following:
Disabling all addonsDisabling addon : core/cert-managerDisabling addon : core/dashboardDisabling addon : core/dnsDisabling addon : core/gpuDisabling addon : core/helmDisabling addon : core/helm3Disabling addon : core/host-accessDisabling addon : core/hostpath-storageDisabling addon : core/ingressDisabling addon : core/kube-ovnDisabling addon : core/mayastorDisabling addon : core/metallbDisabling addon : core/metrics-serverDisabling addon : core/minioDisabling addon : core/observabilityDisabling addon : core/prometheusDisabling addon : core/rbacDisabling addon : core/registryDisabling addon : core/storageAll addons are disabled.Deleting the CNICleaning resourcesinnamespace bookinfoCleaning resourcesinnamespace cert-managerCleaning resourcesinnamespace defaultCleaning resourcesinnamespace ejbca-cert-managerCleaning resourcesinnamespace ejbca-csr-signerCleaning resourcesinnamespace ejbca-k8sCleaning resourcesinnamespace ingressCleaning resourcesinnamespace istio-systemCleaning resourcesinnamespace kube-node-leaseCleaning resourcesinnamespace kube-publicCleaning resourcesinnamespace kube-systemCleaning resourcesinnamespace metallb-systemCleaning resourcesinnamespace pkirulesCleaning resourcesinnamespace vaultRemoving CRDsRemoving PriorityClassesRemoving StorageClassesRemoving namespace/bookinfoRemoving namespace/cert-managerRemoving namespace/ejbca-cert-managerRemoving namespace/ejbca-csr-signerRemoving namespace/ejbca-k8sRemoving namespace/ingressRemoving namespace/istio-systemRemoving namespace/metallb-systemRemoving namespace/pkirulesRemoving namespace/vaultRestarting clusterStopped.Setting up the CNI
You have now reset MicroK8s back to the default. Continue to the next step to enable the required services in MicroK8s for deploying MariaDB and EJBCA.
Step 4 - Enable required services on MicroK8s
Enable DNS, Helm, and hostpath storage on the MicroK8s cluster which are used to deploy EJBCA and MariaDB and provide persistent storage for MariaDB. Follow the steps below to prepare the cluster:
Enable the DNS, Helm, and hostpath-storage addons on the cluster:
$ microk8senabledns hostpath-storage helmThe output is similar to the following:
Infer repository coreforaddon dnsInfer repository coreforaddon hostpath-storageInfer repository coreforaddon helmWARNING: Do notenableor disable multiple addonsinonecommand.This form of chained operations on addons will be DEPRECATEDinthe future.Please,enableone addon at atime:'microk8s enable <addon>'Addon core/dnsis already enabledEnabling default storage class.WARNING: Hostpath storage is not suitableforproduction environments.A hostpath volume can grow beyond the size limitsetinthe volume claim manifest.deployment.apps/hostpath-provisionercreatedstorageclass.storage.k8s.io/microk8s-hostpathcreatedserviceaccount/microk8s-hostpathcreatedclusterrole.rbac.authorization.k8s.io/microk8s-hostpathcreatedclusterrolebinding.rbac.authorization.k8s.io/microk8s-hostpathcreatedStorage will be available soon.Addon core/helmis already enabled
Enable the Metal LB addon on the cluster using the IP range of the VM network the VM is on:
$ microk8senablemetallb:172.16.170.240-172.16.170.245The output is similar to the following:
Infer repository coreforaddon metallbEnabling MetalLBApplying Metallb manifestcustomresourcedefinition.apiextensions.k8s.io/addresspools.metallb.io createdcustomresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io createdcustomresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io createdcustomresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io createdcustomresourcedefinition.apiextensions.k8s.io/communities.metallb.io createdcustomresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io createdcustomresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io creatednamespace/metallb-systemcreatedserviceaccount/controllercreatedserviceaccount/speakercreatedclusterrole.rbac.authorization.k8s.io/metallb-system:controller createdclusterrole.rbac.authorization.k8s.io/metallb-system:speaker createdrole.rbac.authorization.k8s.io/controllercreatedrole.rbac.authorization.k8s.io/pod-listercreatedclusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller createdclusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker createdrolebinding.rbac.authorization.k8s.io/controllercreatedsecret/webhook-server-certcreatedservice/webhook-servicecreatedrolebinding.rbac.authorization.k8s.io/pod-listercreateddaemonset.apps/speakercreateddeployment.apps/controllercreatedvalidatingwebhookconfiguration.admissionregistration.k8s.io/validating-webhook-configurationcreatedWaitingforMetallb controller to be ready.deployment.apps/controllercondition metipaddresspool.metallb.io/default-addresspoolcreatedl2advertisement.metallb.io/default-advertise-all-poolscreatedMetalLB is enabled
Create an alias for helm command:
$sudosnapaliasmicrok8s.helm helmThe output is similar to the following:
#Added:# - microk8s.helm as helm
Review what is deployed in the cluster after the microk8s reset:
$ kubectl get all,secret,pv,pvc,svc,no --all-namespacesThe output is similar to the following:
NAMESPACE NAME READY STATUS RESTARTS AGEkube-system pod/calico-kube-controllers-7cb4fd5784-xs4db1/1Running 0 3m39skube-system pod/calico-node-s42fj1/1Running 0 3m39skube-system pod/coredns-85db789d58-2pfxz1/1Running 0 2m3skube-system pod/hostpath-provisioner-7df77bc496-xcdbm1/1Running 0 50smetallb-system pod/controller-5f7bb57799-wxcvx1/1Running 0 50smetallb-system pod/speaker-rdn591/1Running 0 50sNAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEdefault service/kubernetesClusterIP 10.152.183.1 <none> 443/TCP6m31skube-system service/kube-dnsClusterIP 10.152.183.10 <none> 53/UDP,53/TCP,9153/TCP2m3smetallb-system service/webhook-serviceClusterIP 10.152.183.225 <none> 443/TCP102sNAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGEkube-system daemonset.apps/calico-node1 1 1 1 1 kubernetes.io/os=linux 4m44smetallb-system daemonset.apps/speaker1 1 1 1 1 kubernetes.io/os=linux 102sNAMESPACE NAME READY UP-TO-DATE AVAILABLE AGEkube-system deployment.apps/calico-kube-controllers1/11 1 4m44skube-system deployment.apps/coredns1/11 1 2m3skube-system deployment.apps/hostpath-provisioner1/11 1 114smetallb-system deployment.apps/controller1/11 1 102sNAMESPACE NAME DESIRED CURRENT READY AGEkube-system replicaset.apps/calico-kube-controllers-7cb4fd57841 1 1 3m39skube-system replicaset.apps/coredns-85db789d581 1 1 2m3skube-system replicaset.apps/hostpath-provisioner-7df77bc4961 1 1 50smetallb-system replicaset.apps/controller-5f7bb577991 1 1 50sNAMESPACE NAME TYPE DATA AGEmetallb-system secret/memberlistOpaque 1 49smetallb-system secret/webhook-server-certOpaque 4 102sNAMESPACE NAME STATUS ROLES AGE VERSIONnode/microk8-01Ready <none> 449d v1.29.4
You have now enabled the required services to deploy EJBCA and MariaDB using Helm. Continue to the next step to deploy MariaDB using Helm.
Step 5 - Deploy MariaDB with Helm & restore the EJBCA SQL backup
Before EJBCA is deployed you need to have the database (MariaDB) deployed and the SQL backup restored. That way when EJBCA is deployed you begin right where you left off from the last backup taken. Follow these steps to deploy MariaDB with Helm and restore the EJBCA database backup:
Install Helm repository for MariaDB:
$ helm repo add groundhog2k https://groundhog2k.github.io/helm-chartsThe output is similar to the following:
"groundhog2k"has been added to your repositories
Create namespace for the EJBCA MariaDB deployment:
$ kubectl create namespace ejbca-k8sThe output is similar to the following:
namespace/ejbca-k8screated
Create the MariaDB root password secret:
$ kubectl -n ejbca-k8s create secret generic mariadb-secret --from-literal=MARIADB_ROOT_PASSWORD=ejbcaThe output is similar to the following:
secret/mariadb-secretcreated
Change to the k81 directory:
$cdk81Create the
mariadb-override.yamlfile with settings to deploy MariaDB:$cat> mariadb-override.yaml << EOF## Default values for MariaDB deployment## MariaDB docker imageimage:registry:"docker.io"repository:"mariadb"pullPolicy: IfNotPresent# Overrides the image tag whose default is the chart appVersion.tag:"latest"## Optional service accountserviceAccount:# Specifies whether a service account should be createdcreate:true# Annotations to add to the service accountannotations: {}# The name of the service account to use.# If not set and create is true, a name is generated using the fullname templatename:""# Resource limits and requestsresources:limits:cpu: 2memory: 2048Mirequests:cpu: 1000mmemory: 1024Mi## Use Kubernetes Deployment instead of StatefulSetuseDeployment:false## Database configurationsettings:## Arguments for the container entrypoint processarguments:- --character-set-server=utf8mb4- --collation-server=utf8mb4_unicode_ci## Optional existing secret for the MariaDB root passwordexistingSecret: mariadb-secret## Set true to skip loading timezone data during initskipTZInfo:false## Storage parametersstorage:## Alternative set requestedSize to define a size for a dynamically created PVCrequestedSize: 1GiEOFDeploy MariaDB using helm chart with override:
$ helminstall-n ejbca-k8s ejbca-mariadb groundhog2k/mariadb-f mariadb-override.yamlThe output is similar to the following:
NAME: ejbca-mariadbLAST DEPLOYED: Sun Jun 9 13:31:31 2024NAMESPACE: ejbca-k8sSTATUS: deployedREVISION: 1TEST SUITE: None
Check on the deployment after waiting for 1 min:
$ kubectl -n ejbca-k8s get allThe output is similar to the following:
NAME READY STATUS RESTARTS AGEpod/ejbca-mariadb-01/1Running 0 85sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/ejbca-mariadbClusterIP 10.152.183.95 <none> 3306/TCP85sNAME READY AGEstatefulset.apps/ejbca-mariadb1/185s
Connect to the database using the
service/ejbca-mariadbto make sure the DB is accessible, enter the password for therootaccount when prompted:$ mariadb -h 10.152.183.234 -u root -pEnter the password for the
rootaccount.The output is similar to the following:
Enter password:Welcome to the MariaDB monitor. Commands end with ; or \g.Your MariaDB connectionidis 51Server version: 11.4.2-MariaDB-ubu2404 mariadb.org binary distributionCopyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.Type'help;'or'\h'forhelp. Type'\c'toclearthe current input statement.MariaDB [(none)]>
Enter
exitto exit the database shell:MariaDB [(none)]>exitThe output is similar to the following:
MariaDB [(none)]>exitBye
Import the EJBCA SQL backup into MariaDB, enter the password for the root account when prompted:
$ mariadb -h 10.152.183.234 -u root -p < ../sql/20240610_BackupToMigrate.sqlEnter the password for the
rootaccount.Connect to the
ejbcadatabase as theejbcauser:$ mariadb -h 10.152.183.234 -u ejbca -p ejbcaEnter the password for the
ejbcaaccount.The output is similar to the following:
Enter password:Reading table informationforcompletion of table and column namesYou can turn off this feature to get a quicker startup with -AWelcome to the MariaDB monitor. Commands end with ; or \g.Your MariaDB connectionidis 185Server version: 11.4.2-MariaDB-ubu2404 mariadb.org binary distributionCopyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.Type'help;'or'\h'forhelp. Type'\c'toclearthe current input statement.MariaDB [ejbca]>
Verify the tables are present:
MariaDB [ejbca]> show tables;The output is similar to the following:
MariaDB [ejbca]> show tables;# Output similar to the following:+-------------------------------+| Tables_in_ejbca |+-------------------------------+| AccessRulesData || AcmeAccountData || AcmeAuthorizationData || AcmeChallengeData || AcmeNonceData || AcmeOrderData || AdminEntityData || AdminGroupData || AdminPreferencesData || ApprovalData || AuditRecordData || AuthorizationTreeUpdateData || Base64CertData || BlacklistData || CAData || CRLData || CertReqHistoryData || CertificateData || CertificateProfileData || CryptoTokenData || EndEntityProfileData || GlobalConfigurationData || IncompleteIssuanceJournalData || InternalKeyBindingData || KeyRecoveryData || NoConflictCertificateData || OcspResponseData || PeerData || ProfileData || PublisherData || PublisherQueueData || RoleData || RoleMemberData || SctData || ServiceData || UserData || UserDataSourceData |+-------------------------------+37 rowsinset(0.001 sec)
Enter
exitto exit the database:MariaDB [ejbca]>exitThe output is similar to the following:
MariaDB [ejbca]>exitBye
You have now deployed MariaDB using Helm and restored the EJBCA database backup. You then verified the tables created from restoring the backup. Continue to the next step to deploy EJBCA using Helm.
Step 6 - Deploy EJBCA with Helm
EJBCA is deployed after MariaDB is deployed and the database backup is restored. Follow the steps below to deploy EJBCA:
Install the Helm repository for EJBCA:
$ helm repo add ejbca-ce https://keyfactor.github.io/ejbca-community-helmThe output is similar to the following:
"ejbca-ce"has been added to your repositories
Create the
ejbca-override.yamlfile:$cat> ejbca-overrides.yaml << EOFejbca:useEphemeralH2Database:falseuseH2Persistence:falseimportExternalCas:falseimportAppserverKeystore:falseimportAppserverTruststore:falseimportEjbcaConfFiles:falseenv:TLS_SETUP_ENABLED:"simple"DATABASE_JDBC_URL:"jdbc:mariadb://ejbca-mariadb.ejbca-k8s:3306/ejbca?characterEncoding=utf8"LOG_AUDIT_TO_DB:trueLOG_LEVEL_APP:"INFO"LOG_LEVEL_SERVER:"INFO"OBSERVABLE_BIND:"127.0.0.1"METRICS_ENABLED:falseOCSP_CHECK_SIGN_CERT_VALIDITY:falseOCSP_NON_EXISTING_IS_GOOD:trueenvRaw:- name: DATABASE_USERvalueFrom:secretKeyRef:name: ejbcadbcredentialskey: database_user- name: DATABASE_PASSWORDvalueFrom:secretKeyRef:name: ejbcadbcredentialskey: database_password# - name: PASSWORD_ENCRYPTION_KEY# valueFrom:# secretKeyRef:# name: ejbca-confidentiality-secrets# key: password_encrpytion_keyenvFrom: []initContainers: []sidecarContainers: []volumes: []volumeMounts: []services:directHttp:enabled:falseproxyAJP:enabled:falseproxyHttp:enabled:truetype: LoadBalancerbindIP: 0.0.0.0httpPort: 80httpsPort: 443sidecarPorts: []nginx:enabled:truehost:"ejbca-node1.ejbca-k8s"proxy_url_host: localhostmountInternalNginxCert:truesecretInternalNginxCert:"internal-nginx-credential-secret-ca"service:enabled:falsetype: NodePorthttpPort: 30080httpsPort: 30443ingress:enabled:falsereplicaCount: 1updateStrategy: {}image:repository: keyfactor/ejbca-cepullPolicy: IfNotPresenttag: latestimagePullSecrets: []nameOverride:"ejbca-ca"fullnameOverride:"ejbca-ca"serviceAccount:create:trueannotations: {}name:""podLabels: {}podAnnotations: {}podSecurityContext: {}securityContext: {}resources:limits:cpu: 4memory: 4096Mirequests:cpu: 1000mmemory: 2048Miautoscaling:enabled:falseminReplicas: 1maxReplicas: 5targetCPUUtilizationPercentage: 80behavior: {}podDisruptionBudget:create:falseminAvailable: 1maxUnavailable:""nodeSelector: {}affinity: {}tolerations: []topologySpreadConstraints: []priorityClassName:""schedulerName:""terminationGracePeriodSeconds:""EOFCreate the secret for the EJBCA Database username and password:
$ kubectl -n ejbca-k8s create secret generic ejbcadbcredentials --from-literal=database_user=ejbca --from-literal=database_password=ejbcaThe output is similar to the following:
secret/ejbcadbcredentialscreated
Create the TLS secret for the certificate, key, and CA cert used by NGINX that is deployed in the EJBCA pod:
$ kubectl -n ejbca-k8s create secret generic internal-nginx-credential-secret-ca \--from-file=ejbca-node1.ejbca-k8s.pem=ejbca-node1.ejbca-k8s.crt \--from-file=ejbca-node1.ejbca-k8s-Key.pem=ejbca-node1.ejbca-k8s.key \--from-file=ejbca-node1.ejbca-k8s-CA.pem=../ca.crtThe output is similar to the following:
secret/internal-nginx-credential-secret-cacreated
Deploy EJBCA using the Helm chart and the override values:
$ helminstall-n ejbca-k8s ejbca-ca ejbca-ce/ejbca-community-helm-f ejbca-overrides.yamlThe output is similar to the following:
NAME: ejbca-caLAST DEPLOYED: Sun Jun 9 15:29:16 2024NAMESPACE: ejbca-k8sSTATUS: deployedREVISION: 1TEST SUITE: NoneNOTES:Thank youforinstalling EJBCA CE!Now that you have deployed EJBCA, you shouldlookover the docs on usingEJBCA available here:<https://doc.primekey.com/>Your release is named ejbca-ca. To learnmoreabout the release, try:$ helm status ejbca-ca$ helm get manifest ejbca-ca
Review what has been deployed:
kubectl -n ejbca-k8s get allThe output is similar to the following:
NAME READY STATUS RESTARTS AGEpod/ejbca-ca-84649f7f7b-ck5bn1/2Running 0 15spod/ejbca-mariadb-01/1Running 0 83mNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/ejbca-caLoadBalancer 10.152.183.78 172.16.170.240 80:31313/TCP,443:30725/TCP15sservice/ejbca-mariadbClusterIP 10.152.183.95 <none> 3306/TCP83mNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/ejbca-ca0/11 0 15sNAME DESIRED CURRENT READY AGEreplicaset.apps/ejbca-ca-84649f7f7b1 1 0 15sNAME READY AGEstatefulset.apps/ejbca-mariadb1/183m
Check the EJBCA container logs and verify the container has properly started:
$ kubectl -n ejbca-k8s logs pod/ejbca-ca-84649f7f7b-spwh7-c ejbca-caThe output is similar to the following:
2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)#######################################################################################################2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# Whenever you are ready for production: #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# Try out the commercially supported EJBCA Enterprise Cloud on AWS or Azure, fully featured with: #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# - Additional enrollment APIs such as a complete REST API, EST, ACME and more. #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# - Support for external Registration Authority and OCSP responders #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# - Hardware Security Module support #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# - Application updates #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# - ...and more! #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# Feel free to contact us directly for a cloud, on-prem, SaaS, embedded or hybrid solution that fits #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# your specific needs. #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# <https://aws.amazon.com/marketplace/seller-profile?id=7edf9048-58e6-4086-9d98-b8e0c1d78fce> #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# <https://azuremarketplace.microsoft.com/en-us/marketplace/apps/primekey.ejbca_enterprise_cloud_2> #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# <https://www.keyfactor.com> #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# sales@keyfactor.com #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)# #2024-06-09 19:29:50,009+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1)#######################################################################################################2024-06-09 19:29:50,015+0000 INFO [/opt/keyfactor/bin/start.sh] (process:1) Health check now reports application status at/ejbca/publicweb/healthcheck/ejbcahealth
Open a web browser and access EJBCA Administration.
You have now deployed EJBCA using Helm and logged into the AdminWeb to verify that all your configuration is present from the database restore. At this point, you can continue using EJBCA and try out some of the the other EJBCA integrations.
Next steps
In this tutorial, you learned how to clean up/reset the MicroK8s cluster and deploy MariaDB along with EJBCA using Helm.
Here are some next steps we recommend:
If you are interested in EJBCA Enterprise, read more on Keyfactor EJBCA Enterprise.
If you are interested in EJBCA Community, check out EJBCA Community vs Enterprise or read more on ejbca.org.
If you are an EJBCA Enterprise customer and need support, visit the Keyfactor Support Portal.
Discuss with the EJBCA Community on GitHub Discussions.