Global services
Replicate services to all or part of your fleet
Plural natively supports a concept of global services, e.g. a service that's replicated across a subset of your fleet. This is particular for low level kubernetes system add-ons like ingress controllers, service meshes, cert manager, etc. To define a global service, you first need to define a service that will serve as a source, then use the GlobalService CRD:
apiVersion: deployments.plural.sh/v1alpha1
kind: Cluster
metadata:
name: k3s-prod
namespace: infra
spec:
handle: k3s-prod
---
apiVersion: deployments.plural.sh/v1alpha1
kind: ServiceDeployment
metadata:
name: system-upgrade
namespace: infra
spec:
namespace: system-upgrade
helm:
version: '0.1.1'
chart: system-upgrade-controller
repository:
namespace: infra
name: console
clusterRef:
kind: Cluster
name: k3s-prod
namespace: infra
---
apiVersion: deployments.plural.sh/v1alpha1
kind: GlobalService
metadata:
name: system-upgrade
namespace: infra
spec:
tags:
fabric: edge
serviceRef:
name: system-upgrade
namespace: infraIn this specific case, we set up the k3s system upgrade controller on a single cluster, then replicate it using the GlobalService CR to all clusters with the edge: fabric tags. You can also target on kubernetes distribution (eg EKS, AKS, GKE, K3s, etc) or cluster api provider, and we're welcome to other targeting/organization mechanisms as well if those are not sufficient.
Templating within Global Services
A very common problem you'll face when redeploying apps across your fleet is there's cluster-specific data you'll need for each instance of it. Plural supports that through its templating capabilities in the deployment agent on a cluster.
Take an example of setting up external-dns fleet wide. You'll likely need to configure a different domain and iam arn for each cluster. You can leverage the cluster resources built-in metadata field alongside templating to accomplish that easily, like so:
apiVersion: deployments.plural.sh/v1alpha1
kind: Cluster
metadata:
name: eks-prod
namespace: infra
spec:
handle: eks-prod
tags:
fabric: eks # add eks tag
metadata:
externaldnsRoleArn: arn:...//externaldns
domain: my.domain.com # can add any nested map structure as metadata
---
apiVersion: deployments.plural.sh/v1alpha1
kind: ServiceDeployment
metadata:
name: externaldns
namespace: infra
spec:
namespace: externaldns
repositoryRef:
kind: GitRepository
name: infra
namespace: infra
git:
ref: main
folder: helm-values # or wherever else you want to store the helm values
helm:
version: 6.31.4
chart: externaldns
valuesFiles:
- externaldns.yaml.liquid # use a liquid extension to enable templating in this file
repository:
namespace: infra
name: externaldns
clusterRef:
kind: Cluster
name: eks-prod
namespace: infra
---
apiVersion: deployments.plural.sh/v1alpha1
kind: GlobalService
metadata:
name: system-upgrade
namespace: infra
spec:
tags:
fabric: eks
serviceRef:
name: externaldns
namespace: infraFrom there, your externaldns.yaml.liquid might look something like:
domainFilters:
- {{ cluster.metadata.domain }}
serviceAccount:
enabled: true
annotations:
eks.amazonaws.com/role-arn: {{ cluster.metadata.externaldnsRoleArm }}If you added secrets, you can access them with something like {{ configuration.YOUR_SECRET_NAME }} and if you want to use service contexts, we recommend checking the docs here.