diff --git a/.cspell.json b/.cspell.json index 4023775f..ee99af6a 100644 --- a/.cspell.json +++ b/.cspell.json @@ -17,8 +17,11 @@ "buildplan", "cainjector", "CAROOT", + "certificaterequests", + "certificatesigningrequests", "clsx", "clusterissuer", + "clusterissuers", "clusterrole", "clusterrolebinding", "configmap", @@ -71,6 +74,7 @@ "Kustomizations", "kustomize", "ldflags", + "leaderelection", "libnss", "loadbalancer", "mattn", @@ -117,6 +121,7 @@ "startupapicheck", "stefanprodan", "structpb", + "subjectaccessreviews", "svclb", "systemconnect", "tablewriter", diff --git a/doc/md/guides/expose-a-service.mdx b/doc/md/guides/expose-a-service.mdx index 9377a31a..cf6bf923 100644 --- a/doc/md/guides/expose-a-service.mdx +++ b/doc/md/guides/expose-a-service.mdx @@ -24,8 +24,9 @@ You'll need the following tools installed to complete this guide. 2. [helm](https://helm.sh/docs/intro/install/) - to render Helm Components. 3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to render Kustomize Components. -Optionally, if you'd like to apply the rendered manifests to a real Cluster, -first complete the [localhost Guide](../local-cluster). +As an optional, but recommended step, complete the [Local Cluster] guide if you'd like to apply +the rendered manifests to a cluster. This will smooth out the friction of +managing certificates. ## Create a Git Repository @@ -52,8 +53,8 @@ repository unless stated otherwise. ## Generate the Platform {#Generate-Platform} -Start by generating a platform with one workload Cluster. The `guide` Platform -is intended as a starting point for all of our guides. +Generate a platform with one workload cluster. The `guide` Platform is intended +as a starting point for all of our guides. @@ -63,7 +64,7 @@ holos generate component workload-cluster ``` -```txt showLineNumbers +```txt generated component ``` @@ -87,68 +88,75 @@ git commit -m "holos generate platform guide - $(holos --version)" -## Gateway API +## Namespaces -The Gateway API is an official Kubernetes project focused on L4 and L7 routing . -You'll use the custom resources defined by the Gateway API to expose the httpbin -service outside of the cluster. The Kubernetes Gateway API does not come -installed by default on most Kubernetes clusters, so we need to manage the -custom resource definitions (CRDs). +We often need to manage namespaces prior to workloads being deployed. This is +necessary because a namespace is a security boundary. Holos makes it easier, +safer, and more consistent to manage service accounts, role bindings, and +secrets prior to deploying workloads into a namespace. -Run the following command to generate a Component to manage the Gateway API. +We'll see how this works with the namespaces component, which offers a mechanism +for other components to register their namespaces. The namespaces component +initializes each registered namespace, optionally mixing in resources +consistently. - +Run the following command to generate the namespaces component. + + ```bash -holos generate component gateway-api +holos generate component namespaces ``` -```txt showLineNumbers +```txt generated component ``` -The command generates two main configuration files, one at the leaf, and another -at the root of the tree. At the leaf, the config produces a Kustomize build -plan for Holos to render. At the root, the config adds the Component to all -Clusters in the Platform. - -Notice the `kustomization.yaml` file at the leaf. This is an unmodified -upstream copy of the standard way to install the Gateway API. +The command generates two main configuration files like we've seen with other +components. One file at the leaf, and another at the root. The leaf uses a +Kubernetes build plan to produce resources directly from CUE. - - - `components/gateway-api/gateway-api.cue` + + + `components/namespaces/namespaces.cue` ```cue showLineNumbers package holos -// Produce a kubectl kustomize build plan. -(#Kustomize & {Name: "gateway-api"}).Output -``` - - - `components/gateway-api/kustomization.yaml` -```yaml showLineNumbers -resources: -- standard/gateway.networking.k8s.io_gatewayclasses.yaml -- standard/gateway.networking.k8s.io_gateways.yaml -- standard/gateway.networking.k8s.io_grpcroutes.yaml -- standard/gateway.networking.k8s.io_httproutes.yaml -- standard/gateway.networking.k8s.io_referencegrants.yaml +let Objects = { + Name: "namespaces" + // highlight-next-line + Resources: Namespace: #Namespaces +} + +// Produce a kubernetes objects build plan. +(#Kubernetes & Objects).Output ``` - - `gateway-api.gen.cue` + + `namespaces.gen.cue` ```cue showLineNumbers package holos -// Manage on every Cluster in the Platform +import corev1 "k8s.io/api/core/v1" + +// #Namespaces defines all managed namespaces in the Platform. +// Holos adopts the sig-multicluster position of namespace sameness. +#Namespaces: { + // Validate against v1 of the kubernetes core api + // highlight-next-line + [Name=string]: corev1.#Namespace & { + metadata: name: Name + } +} + +// Manage the Component on every Cluster in the Platform for Fleet in #Fleets { for Cluster in Fleet.clusters { - #Platform: Components: "\(Cluster.name)/gateway-api": { - path: "components/gateway-api" + #Platform: Components: "\(Cluster.name)/namespaces": { + path: "components/namespaces" cluster: Cluster.name } } @@ -157,7 +165,20 @@ for Fleet in #Fleets { -Render the Platform to render the Component for the workload clusters. +Notice the highlighted line in the leaf file. Resources are managed directly in +CUE at the leaf using the Kubernetes component. This is the same mechanism used +to mix-in resources to Helm and Kustomize components. The leaf refers to +`#Namespaces` defined at the root. At the root `#Namespaces` enforces a +constraint: each Namespace must conform to the `k8s.io/api/core/v1` +specification. + +- At the **leaf** Holos tailors the component to your platform, mixing +in resources and customizing the rendered output. +- At the **root** Holos integrates a component with the rest of your platform. + +You'll see this pattern again and again as you build your platform. + +Render the platform to render the component for the workload clusters. @@ -167,131 +188,338 @@ holos render platform ./platform ```txt showLineNumbers -rendered components/gateway-api for cluster workload in 279.312292ms +rendered components/namespaces for cluster workload in 72.675292ms +``` + + + +Add and commit the configuration and rendered manifests. + + + +```bash +git add . +git commit -m "add namespaces component" +``` + + +```txt showLineNumbers +[main 1bf0d61] add namespaces component + 3 files changed, 30 insertions(+) + create mode 100644 components/namespaces/namespaces.cue + create mode 100644 deploy/clusters/workload/components/namespaces/namespaces.gen.yaml + create mode 100644 namespaces.gen.cue ``` +`#Namespaces` is currently empty, so the rendered output of +`namespaces.gen.yaml` is also empty. + :::tip -This example is equivalent to running `kubectl kustomize -./components/gateway-api` and saving the output to a file. Holos simplifies -this task and makes it consistent with Helm and other tools. +Namespaces will be automatically managed as we add more components to the +platform over time. ::: -Add and commit the Component and rendered Platform. +## Cert Manager - +We'll need a valid certificate to browse to httpbin. We'll manage cert-manager +in our cluster to issue valid tls certificates. + +Run the following command to generate the cert-manager component. + + + +```bash +holos generate component cert-manager +``` + + +```txt +generated component +``` + + + +This command generates a configuration file at the leaf and the root. At the +leaf two helm values configure the behavior of the upstream cert-manager chart. +At the root cert-manager is managed on all clusters in the platform. + +1. The leaf references the version and namespace fields defined in +`#CertManager` at the root. +2. The leaf defines two Helm values to manage. Holos makes it easier and safer +to focus on how software is integrated into our platform. +3. The root registers cert-manager for the namespaces component to manage +consistently across all clusters in the platform. +4. The root manages the component on all clusters in the platform. + + + + `components/cert-manager/cert-manager.cue` +```cue showLineNumbers +package holos + +// Produce a helm chart build plan. +(#Helm & Chart).Output + +let Chart = { + Name: "cert-manager" + // highlight-next-line + Version: #CertManager.Version + // highlight-next-line + Namespace: #CertManager.Namespace + + Repo: name: "jetstack" + Repo: url: "https://charts.jetstack.io" + + // highlight-next-line + Values: installCRDs: true + // highlight-next-line + Values: startupapicheck: enabled: false +} +``` + + + `cert-manager.gen.cue` +```cue showLineNumbers +package holos + +// Platform wide configuration +#CertManager: { + Version: "1.15.3" + Namespace: "cert-manager" +} + +// Register the namespace +// highlight-next-line +#Namespaces: (#CertManager.Namespace): _ + +// Manage the component on every cluster in the platform +for Fleet in #Fleets { + for Cluster in Fleet.clusters { + #Platform: Components: "\(Cluster.name)/cert-manager": { + path: "components/cert-manager" + cluster: Cluster.name + } + } +} +``` + + + +Render the platform to render manifests into the deploy directory. + + + +```bash +holos render platform ./platform +``` + + +```txt showLineNumbers +rendered components/namespaces for cluster workload in 65.184791ms +rendered components/cert-manager for cluster workload in 467.379292ms +``` + + + +Add and commit the configuration and rendered manifests. + + ```bash git add . -git commit -m "add gateway-api component" +git commit -m "integrate cert-manager into the platform" ``` ```txt showLineNumbers -[main 88575a5] add gateway-api component - 9 files changed, 26907 insertions(+) - create mode 100644 components/gateway-api/gateway-api.cue - create mode 100644 components/gateway-api/kustomization.yaml - create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_gatewayclasses.yaml - create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_gateways.yaml - create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_grpcroutes.yaml - create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_httproutes.yaml - create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_referencegrants.yaml - create mode 100644 deploy/clusters/workload/components/gateway-api/gateway-api.gen.yaml - create mode 100644 gateway-api.gen.cue +[main c6ab5f4] integrate cert-manager into the platform + 3 files changed, 9434 insertions(+) + create mode 100644 cert-manager.gen.cue + create mode 100644 components/cert-manager/cert-manager.cue + create mode 100644 deploy/clusters/workload/components/cert-manager/cert-manager.gen.yaml ``` -Optionally apply the rendered component to your cluster. +:::tip +We often need to understand how a change affects the platform as a whole. Holos +offers the ability to use your preferred tooling to understand platform wide +changes. +::: - +For example, `git` summarizes all of the components and clusters affected by +adding cert-manager. The output shows both the namespaces and cert-manager +components have changed on the workload cluster. + + ```bash -kubectl apply --server-side=true -f deploy/clusters/workload/components/gateway-api +git show --stat deploy ``` ```txt showLineNumbers -customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io serverside-applied -customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io serverside-applied -customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io serverside-applied -customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io serverside-applied -customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io serverside-applied +deploy/clusters/workload/components/cert-manager/cert-manager.gen.yaml | 9407 +deploy/clusters/workload/components/namespaces/namespaces.gen.yaml | 8 +2 files changed, 9415 insertions(+) ``` -## Namespaces +As an optional step, apply the changes. -We often need to manage namespaces prior to workloads being deployed. This is -necessary because a namespace is a security boundary. Holos makes it easier, -safer, and more consistent to manage service accounts, role bindings, and -secrets prior to deploying workloads into a namespace. + + +```bash +kubectl apply --server-side=true -f deploy/clusters/workload/components/namespaces +``` + + +```txt showLineNumbers +namespace/cert-manager serverside-applied +``` + + -We'll see how this works with the namespaces component, which offers a mechanism -for other components to register their namespaces. The namespaces component -initializes each registered namespace, optionally mixing in resources -consistently. + + +```bash +kubectl apply --server-side=true -f deploy/clusters/workload/components/cert-manager +``` + + +```txt showLineNumbers +serviceaccount/cert-manager-cainjector serverside-applied +serviceaccount/cert-manager serverside-applied +serviceaccount/cert-manager-webhook serverside-applied +customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-cainjector serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-issuers serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificates serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-orders serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-challenges serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-cluster-view serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-view serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-edit serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests serverside-applied +clusterrole.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-cainjector serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-issuers serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificates serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-orders serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-challenges serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests serverside-applied +clusterrolebinding.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews serverside-applied +role.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection serverside-applied +role.rbac.authorization.k8s.io/cert-manager:leaderelection serverside-applied +role.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving serverside-applied +rolebinding.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection serverside-applied +rolebinding.rbac.authorization.k8s.io/cert-manager:leaderelection serverside-applied +rolebinding.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving serverside-applied +service/cert-manager serverside-applied +service/cert-manager-webhook serverside-applied +deployment.apps/cert-manager-cainjector serverside-applied +deployment.apps/cert-manager serverside-applied +deployment.apps/cert-manager-webhook serverside-applied +mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook serverside-applied +validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook serverside-applied +``` + + -Run the following command to generate the namespaces component. +Check the pods become ready - + ```bash -holos generate component namespaces +kubectl get pods -n cert-manager ``` ```txt showLineNumbers +NAME READY STATUS RESTARTS AGE +cert-manager-9647b459d-d5q8f 1/1 Running 0 9s +cert-manager-cainjector-5d8798687c-kv8bs 1/1 Running 0 9s +cert-manager-webhook-c77744d75-j6hv8 1/1 Running 0 9s +``` + + + +## Gateway API + +The Gateway API is an official Kubernetes project focused on L4 and L7 routing . +You'll use the custom resources defined by the Gateway API to expose the httpbin +service outside of the cluster. The Kubernetes Gateway API does not come +installed by default on most Kubernetes clusters, so we need to manage the +custom resource definitions (CRDs). + +Run the following command to generate a Component to manage the Gateway API. + + + +```bash +holos generate component gateway-api +``` + + +```txt generated component ``` -The command generates two main configuration files like we've seen with other -components. One file at the leaf, and another at the root. The leaf uses a -Kubernetes build plan to produce resources directly from CUE. +The command generates two main configuration files, one at the leaf, and another +at the root of the tree. At the leaf, the config produces a Kustomize build +plan for Holos to render. At the root, the config adds the Component to all +Clusters in the Platform. - - - `components/namespaces/namespaces.cue` +Notice the `kustomization.yaml` file at the leaf. This is an unmodified +upstream copy of the standard way to install the Gateway API. + + + + `components/gateway-api/gateway-api.cue` ```cue showLineNumbers package holos -let Objects = { - Name: "namespaces" - // highlight-next-line - Resources: Namespace: #Namespaces -} - -// Produce a kubernetes objects build plan. -(#Kubernetes & Objects).Output +// Produce a kubectl kustomize build plan. +(#Kustomize & {Name: "gateway-api"}).Output ``` - - `namespaces.gen.cue` + + `components/gateway-api/kustomization.yaml` +```yaml showLineNumbers +resources: +- standard/gateway.networking.k8s.io_gatewayclasses.yaml +- standard/gateway.networking.k8s.io_gateways.yaml +- standard/gateway.networking.k8s.io_grpcroutes.yaml +- standard/gateway.networking.k8s.io_httproutes.yaml +- standard/gateway.networking.k8s.io_referencegrants.yaml +``` + + + `gateway-api.gen.cue` ```cue showLineNumbers package holos -import corev1 "k8s.io/api/core/v1" - -// #Namespaces defines all managed namespaces in the Platform. -// Holos adopts the sig-multicluster position of namespace sameness. -#Namespaces: { - // Validate against v1 of the kubernetes core api - // highlight-next-line - [Name=string]: corev1.#Namespace & { - metadata: name: Name - } -} - -// Manage the Component on every Cluster in the Platform +// Manage on every Cluster in the Platform for Fleet in #Fleets { for Cluster in Fleet.clusters { - #Platform: Components: "\(Cluster.name)/namespaces": { - path: "components/namespaces" + #Platform: Components: "\(Cluster.name)/gateway-api": { + path: "components/gateway-api" cluster: Cluster.name } } @@ -300,28 +528,14 @@ for Fleet in #Fleets { -Notice the highlighted line in the leaf file. Resources are managed directly in -CUE at the leaf using the Kubernetes component. This is the same mechanism used -to mix-in resources to Helm and Kustomize components. The leaf refers to -`#Namespaces` defined at the root. At the root `#Namespaces` enforces a -constraint: each Namespace must conform to the `k8s.io/api/core/v1` -specification. - :::important -We've covered three kinds of components so far. The [Quickstart] guide -introduced Helm. We've used Kustomize and Kubernetes in this guide. +We've covered three kinds of components so far: Kubernetes, Helm, and Kustomize. Holos offers a consistent way to manage these different kinds of packaging safely and easily. ::: -- At the **leaf** Holos tailors the component to your platform, mixing -in resources and customizing the rendered output. -- At the **root** Holos integrates a component with the rest of your platform. - -You'll see this pattern again and again as you build your platform. - -Render the platform to render the component for the workload clusters. +Render the Platform to render the Component for the workload clusters. @@ -331,41 +545,63 @@ holos render platform ./platform ```txt showLineNumbers -rendered components/namespaces for cluster workload in 72.675292ms -rendered components/gateway-api for cluster workload in 259.174583ms +rendered components/gateway-api for cluster workload in 279.312292ms ``` -Add and commit the configuration and rendered manifests. +:::tip +This example is equivalent to running `kubectl kustomize +./components/gateway-api` and saving the output to a file. Holos simplifies +this task and makes it consistent with Helm and other tools. +::: + +Add and commit the Component and rendered Platform. ```bash git add . -git commit -m "add namespaces component" +git commit -m "add gateway-api component" ``` ```txt showLineNumbers -[main 1bf0d61] add namespaces component - 3 files changed, 30 insertions(+) - create mode 100644 components/namespaces/namespaces.cue - create mode 100644 deploy/clusters/workload/components/namespaces/namespaces.gen.yaml - create mode 100644 namespaces.gen.cue +[main 88575a5] add gateway-api component + 9 files changed, 26907 insertions(+) + create mode 100644 components/gateway-api/gateway-api.cue + create mode 100644 components/gateway-api/kustomization.yaml + create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_gatewayclasses.yaml + create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_gateways.yaml + create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_grpcroutes.yaml + create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_httproutes.yaml + create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_referencegrants.yaml + create mode 100644 deploy/clusters/workload/components/gateway-api/gateway-api.gen.yaml + create mode 100644 gateway-api.gen.cue ``` -`#Namespaces` is currently empty, so the rendered output of -`namespaces.gen.yaml` is also empty. +As an optional step, apply the rendered component to your cluster. -:::tip -Namespaces will be automatically managed as we add more components to the -platform over time. -::: + + +```bash +kubectl apply --server-side=true -f deploy/clusters/workload/components/gateway-api +``` + + +```txt showLineNumbers +customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io serverside-applied +customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io serverside-applied +``` + + -## Istio +## Istio Service Mesh We'll manage Istio to implement the Gateway API so we can expose the httpbin service outside of the cluster. @@ -379,7 +615,7 @@ holos generate component istio ``` -```txt showLineNumbers +```txt generated component ``` @@ -400,7 +636,7 @@ holos generate component istio-k3d ``` -```txt showLineNumbers +```txt generated component ``` @@ -790,8 +1026,122 @@ kube-system svclb-gateway-5d311af0-fp5mk 3/3 Running 0 -Once all pods are ready, we're ready to manage httpbin so we can route http -traffic to it. +Once all pods are ready, we're ready for the next step toward exposing httpbin. + +## Certificate Issuer + +We need to issue certificates our browser trusts so we can browse httpbin. +We'll do this by configuring a ClusterIssuer using the ca private key we created +in the [Local Cluster] guide. + +Run the following command to generate the local-ca component. + + + +```bash +holos generate component local-ca +``` + + +```txt +generated component +``` + + + +At the leaf, the configuration refers to the `#CertManager.Namespace` value +defined previously at the root by the cert-manager component. + + + +```cue showLineNumbers +package holos + +import ci "cert-manager.io/clusterissuer/v1" + +// Produce a kubernetes objects build plan. +(#Kubernetes & Objects).Output + +let Objects = { + Name: "local-ca" + // highlight-next-line + Namespace: #CertManager.Namespace + + Resources: ClusterIssuer: LocalCA: ci.#ClusterIssuer & { + metadata: name: "local-ca" + // highlight-next-line + metadata: namespace: #CertManager.Namespace + + // The secret name must align with the local cluster guide at + // https://holos.run/docs/guides/local-cluster/ + spec: ca: secretName: "local-ca" + } +} +``` + + + +Render the platform to render manifests into the deploy directory. + + + +```bash +holos render platform ./platform +``` + + +```txt showLineNumbers +TODO +``` + + + +Add and commit the configuration and rendered manifests. + + + +```bash +git add . +git commit -m "integrate local-ca into the platform" +``` + + +```txt showLineNumbers +TODO +``` + + + +As an optional step, apply the configuration to the cluster. + + + +```bash +kubectl apply --server-side=true -f deploy/clusters/workload/components/local-ca +``` + + +```txt showLineNumbers +clusterissuer.cert-manager.io/local-ca serverside-applied +``` + + + +Verify the local-ca ClusterIssuer is ready: + + + +```bash +kubectl get clusterissuers.cert-manager.io +``` + + +```txt showLineNumbers +NAME READY AGE +local-ca True 12s +``` + + ## httpbin diff --git a/doc/md/guides/local-cluster.mdx b/doc/md/guides/local-cluster.mdx index 2897ffa8..5efdae82 100644 --- a/doc/md/guides/local-cluster.mdx +++ b/doc/md/guides/local-cluster.mdx @@ -88,7 +88,7 @@ Finally, add your trusted certificate authority. ```bash kubectl apply --server-side=true -f "$(mkcert -CAROOT)/namespace.yaml" -kubectl apply --server-side=true -f "$(mkcert -CAROOT)/local-ca.yaml" +kubectl apply --server-side=true -n cert-manager -f "$(mkcert -CAROOT)/local-ca.yaml" ``` diff --git a/internal/generate/components/v1alpha3/cert-manager/cert-manager.gen.cue b/internal/generate/components/v1alpha3/cert-manager/cert-manager.gen.cue new file mode 100644 index 00000000..09677b7b --- /dev/null +++ b/internal/generate/components/v1alpha3/cert-manager/cert-manager.gen.cue @@ -0,0 +1,20 @@ +package holos + +// Platform wide configuration +#CertManager: { + Version: "{{ .Version }}" + Namespace: "{{ .Namespace }}" +} + +// Register the namespace +#Namespaces: (#CertManager.Namespace): _ + +// Manage the component on every cluster in the platform +for Fleet in #Fleets { + for Cluster in Fleet.clusters { + #Platform: Components: "\(Cluster.name)/{{ .Name }}": { + path: "components/cert-manager" + cluster: Cluster.name + } + } +} diff --git a/internal/generate/components/v1alpha3/cert-manager/components/cert-manager/cert-manager.cue b/internal/generate/components/v1alpha3/cert-manager/components/cert-manager/cert-manager.cue new file mode 100644 index 00000000..2960b227 --- /dev/null +++ b/internal/generate/components/v1alpha3/cert-manager/components/cert-manager/cert-manager.cue @@ -0,0 +1,16 @@ +package holos + +// Produce a helm chart build plan. +(#Helm & Chart).Output + +let Chart = { + Name: "{{ .Name }}" + Version: #CertManager.Version + Namespace: #CertManager.Namespace + + Repo: name: "{{ .RepoName }}" + Repo: url: "{{ .RepoURL }}" + + Values: installCRDs: true + Values: startupapicheck: enabled: false +} diff --git a/internal/generate/components/v1alpha3/cert-manager/schematic.json b/internal/generate/components/v1alpha3/cert-manager/schematic.json new file mode 100644 index 00000000..58008650 --- /dev/null +++ b/internal/generate/components/v1alpha3/cert-manager/schematic.json @@ -0,0 +1,10 @@ +{ + "name": "cert-manager", + "short": "cloud native X.509 certificate management for kubernetes", + "long": "cert-manager creates tls certificates for workloads in your kubernetes cluster and renews the certificates before they expire.", + "chart": "", + "reponame": "jetstack", + "repourl": "https://charts.jetstack.io", + "version": "1.15.3", + "namespace": "cert-manager" +} diff --git a/internal/generate/components/v1alpha3/local-ca/components/local-ca/local-ca.cue b/internal/generate/components/v1alpha3/local-ca/components/local-ca/local-ca.cue new file mode 100644 index 00000000..a69d3905 --- /dev/null +++ b/internal/generate/components/v1alpha3/local-ca/components/local-ca/local-ca.cue @@ -0,0 +1,20 @@ +package holos + +import ci "cert-manager.io/clusterissuer/v1" + +// Produce a kubernetes objects build plan. +(#Kubernetes & Objects).Output + +let Objects = { + Name: "local-ca" + Namespace: #CertManager.Namespace + + Resources: ClusterIssuer: LocalCA: ci.#ClusterIssuer & { + metadata: name: "local-ca" + metadata: namespace: #CertManager.Namespace + + // The secret name must align with the local cluster guide at + // https://holos.run/docs/guides/local-cluster/ + spec: ca: secretName: "local-ca" + } +} diff --git a/internal/generate/components/v1alpha3/local-ca/local-ca.gen.cue b/internal/generate/components/v1alpha3/local-ca/local-ca.gen.cue new file mode 100644 index 00000000..2528af9f --- /dev/null +++ b/internal/generate/components/v1alpha3/local-ca/local-ca.gen.cue @@ -0,0 +1,11 @@ +package holos + +// Manage the component on every cluster in the platform +for Fleet in #Fleets { + for Cluster in Fleet.clusters { + #Platform: Components: "\(Cluster.name)/{{ .Name }}": { + path: "components/local-ca" + cluster: Cluster.name + } + } +} diff --git a/internal/generate/components/v1alpha3/local-ca/schematic.json b/internal/generate/components/v1alpha3/local-ca/schematic.json new file mode 100644 index 00000000..87c0ed9e --- /dev/null +++ b/internal/generate/components/v1alpha3/local-ca/schematic.json @@ -0,0 +1,6 @@ +{ + "name": "local-ca", + "short": "manages a cluster issuer for use with our guides", + "long": "manages a cluster issuer that uses the mkcert ca private key to issue certs", + "namespace": "cert-manager" +} diff --git a/internal/generate/platforms/cue.mod/pkg/github.com/holos-run/holos/api/schema/v1alpha3/definitions.cue b/internal/generate/platforms/cue.mod/pkg/github.com/holos-run/holos/api/schema/v1alpha3/definitions.cue index fc84db62..9d456981 100644 --- a/internal/generate/platforms/cue.mod/pkg/github.com/holos-run/holos/api/schema/v1alpha3/definitions.cue +++ b/internal/generate/platforms/cue.mod/pkg/github.com/holos-run/holos/api/schema/v1alpha3/definitions.cue @@ -11,6 +11,7 @@ import ( batchv1 "k8s.io/api/batch/v1" app "argoproj.io/application/v1alpha1" + ci "cert-manager.io/clusterissuer/v1" ) #Resources: { @@ -19,6 +20,7 @@ import ( metadata: name: string | *InternalLabel } + ClusterIssuer: [_]: ci.#ClusterIssuer ClusterRole: [_]: rbacv1.#ClusterRole ClusterRoleBinding: [_]: rbacv1.#ClusterRoleBinding ConfigMap: [_]: corev1.#ConfigMap