GitOps repository
Every Solution is backed by a Git repository holding the Kubernetes manifests of its services. That repository is the source of truth: what it contains is what runs in your clusters, and every deployment is a commit you can read, audit and revert.
The platform creates the repository for you and writes the initial manifests. From that point on it is a normal Git repository owned by your organization: you edit it, review it, and push to it like any other.
Folder layout
Section titled “Folder layout”One folder per Solution, one subfolder per service, and a Kustomize base with one overlay per environment:
{solution}/ {service}/ base/ shared manifests deployment.yaml service.yaml kustomization.yaml overlays/ {environment}/ per-environment patches kustomization.yamlThe deployment engine watches overlays/{environment} for each cell of the
Solution matrix. That overlay pulls in base/ through resources: - ../../base,
then applies its own patches: the target namespace, the image tag, and anything
else you declare there.
Two consequences worth remembering:
- A manifest added to
base/applies to every environment of the service. - A manifest added to an overlay applies to that environment only. This is where anything environment-specific belongs, starting with hostnames.
Folder names are not free
Section titled “Folder names are not free”Each folder name must match, character for character, the name of the Solution, the service or the environment it stands for. Those names are lowercase alphanumerics and hyphens, so the folders are too. A mismatch is silent: nothing looks for a folder that was never declared.
Generated files versus your files
Section titled “Generated files versus your files”The platform writes manifests in two situations only: when a service is added to a
Solution (its base/ is created), and when an environment is added (that
overlay is created). Outside of those two events it does not touch the repository,
so the files you add and the edits you make are preserved.
Keep metadata.namespace out of your manifests. The overlay sets it through its
namespace: directive, which is what lets one base serve several environments.
Exposing a service on a domain
Section titled “Exposing a service on a domain”Add the route manifest to the service folder and declare it in the matching
kustomization.yaml, next to the generated resources:
resources: - deployment.yaml - service.yaml - ingress.yaml # your routeExposing a hostname takes two IngressRoutes:
one on the http entry point that redirects to HTTPS, one on the https entry
point that carries the TLS configuration.
apiVersion: traefik.io/v1alpha1kind: IngressRoutemetadata: name: my-servicespec: entryPoints: - http routes: - kind: Rule match: Host(`my-service.my-namespace.h8l.io`) middlewares: # platform middleware, redirects to the https entry point - name: https-redirect namespace: traefik services: - name: my-service port: 8080---apiVersion: traefik.io/v1alpha1kind: IngressRoutemetadata: name: my-service-tlsspec: entryPoints: - https routes: - kind: Rule match: Host(`my-service.my-namespace.h8l.io`) services: - name: my-service port: 8080 tls: secretName: h8lio-tlsReplace my-namespace with your target namespace and 8080 with the port your
Service exposes. Every namespace resolves under *.{namespace}.h8l.io, so no DNS
record is needed for a platform hostname. For your own domain, point it at the
platform first (a CNAME to edge.h8l.io, or an A record to its IP).
TLS certificate
Section titled “TLS certificate”h8lio-tls above is a cert-manager certificate covering
every hostname of your namespace. Declare it once per namespace, alongside your
routes:
apiVersion: cert-manager.io/v1kind: Certificatemetadata: name: h8liospec: dnsNames: - "*.my-namespace.h8l.io" issuerRef: group: cert-manager.io kind: ClusterIssuer name: h8lio-issuer secretName: h8lio-tlsFor a custom domain, use the letsencrypt-http01 cluster issuer instead. The
Certificates guide covers both issuers, the wildcard
case, and the Traefik resolver alternative.
Checking before you push
Section titled “Checking before you push”Kustomize renders locally exactly what the platform applies. Run it on the overlay, not on the base:
kubectl kustomize {solution}/{service}/overlays/{environment}If a resource you added does not appear in that output, it is missing from a
kustomization.yaml and no amount of syncing will deploy it.
Once pushed, the state of each cell is visible on the Solution page of your dashboard: whether it is in sync with the repository, whether the workload is healthy, and the exact error when a manifest is rejected by the cluster.
Adding an environment
Section titled “Adding an environment”Add the environment to the Solution from the dashboard. Its overlay is generated
next to the existing ones, inheriting base/. Anything you had placed in an
overlay, a hostname in particular, is specific to that overlay and has to be
declared again for the new environment.