From b718f15b9e559765f8a59fdbe6cf3c1dc7fdf30f Mon Sep 17 00:00:00 2001 From: Anna Nguyen Date: Mon, 5 Jan 2026 22:22:11 +0000 Subject: [PATCH] Add Runtime documentation with about and getting-started pages This commit adds comprehensive documentation for the Plural Runtime chart: - New "Runtime" section under Plural Features in the navigation - About page (index.md) explaining what Runtime is and its core components - Getting started guide with deployment options, configuration reference, and cloud provider setup --- .../runtime/getting-started.md | 320 ++++++++++++++++++ pages/plural-features/runtime/index.md | 77 +++++ src/routing/docs-structure.ts | 7 + 3 files changed, 404 insertions(+) create mode 100644 pages/plural-features/runtime/getting-started.md create mode 100644 pages/plural-features/runtime/index.md diff --git a/pages/plural-features/runtime/getting-started.md b/pages/plural-features/runtime/getting-started.md new file mode 100644 index 00000000..5ab57301 --- /dev/null +++ b/pages/plural-features/runtime/getting-started.md @@ -0,0 +1,320 @@ +--- +title: Getting started with Runtime +description: Learn how to deploy and configure the Plural Runtime chart on your Kubernetes clusters. +--- + +This guide walks you through deploying the Plural Runtime chart to set up a complete network stack on your Kubernetes clusters. + +## Prerequisites + +Before getting started, ensure you have: + +- A Kubernetes cluster managed by Plural +- A Git repository connected to Plural for GitOps +- Access to your cloud provider's DNS service (for external-dns configuration) + +## Deployment Options + +There are two main ways to deploy Runtime: + +1. **Global Service** - Deploy to multiple clusters with shared configuration (recommended) +2. **Single Service** - Deploy to a specific cluster + +## Option 1: Deploy as a Global Service + +Using a Global Service ensures Runtime is consistently deployed across all clusters matching specific tags. This is the recommended approach for fleet-wide deployments. + +Create a file at `bootstrap/components/runtime.yaml`: + +```yaml +apiVersion: deployments.plural.sh/v1alpha1 +kind: GlobalService +metadata: + name: runtime + namespace: infra +spec: + cascade: + delete: true + tags: + role: workload + template: + name: runtime + namespace: plural-runtime + repositoryRef: + kind: GitRepository + name: infra + namespace: infra + git: + ref: main + folder: helm + helm: + version: 0.1.35 + chart: runtime + url: https://pluralsh.github.io/bootstrap + valuesFiles: + - runtime.yaml.liquid +``` + +Then create the values file at `helm/runtime.yaml.liquid`: + +```yaml {% process=false %} +external-dns: + enabled: true + provider: aws + txtOwnerId: plrl-{{ cluster.handle }} + policy: sync + domainFilters: + - {{ cluster.metadata.dns_zone }} + serviceAccount: + annotations: + eks.amazonaws.com/role-arn: {{ cluster.metadata.iam.external_dns }} + +cert-manager: + enabled: true + serviceAccount: + name: cert-manager + annotations: + eks.amazonaws.com/role-arn: {{ cluster.metadata.iam.cert_manager }} + +ingress-nginx: + enabled: true + controller: + service: + annotations: + service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing + service.beta.kubernetes.io/aws-load-balancer-type: external + service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip + +ingress-nginx-private: + enabled: false +``` + +{% callout severity="info" %} +The `.liquid` extension enables dynamic templating using cluster metadata. See {% doclink to="plural_features_service_templating" %}Service Templating{% /doclink %} for more details. +{% /callout %} + +## Option 2: Deploy as a Single Service + +For deploying to a specific cluster, create a ServiceDeployment resource: + +```yaml +apiVersion: deployments.plural.sh/v1alpha1 +kind: ServiceDeployment +metadata: + name: runtime + namespace: infra +spec: + name: runtime + namespace: plural-runtime + clusterRef: + name: my-cluster + namespace: infra + repositoryRef: + kind: GitRepository + name: infra + namespace: infra + git: + ref: main + folder: helm + helm: + version: 0.1.35 + chart: runtime + url: https://pluralsh.github.io/bootstrap + valuesFiles: + - runtime.yaml +``` + +## Configuration Reference + +### Disabling Components + +Each component can be individually disabled. For example, to disable cert-manager if you're managing it separately: + +```yaml +cert-manager: + enabled: false +``` + +### Ingress NGINX Configuration + +The default ingress controller configuration is optimized for production use: + +```yaml +ingress-nginx: + enabled: true + controller: + config: + proxy-body-size: '0' + proxy-read-timeout: '3600' + proxy-send-timeout: '3600' + autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 11 + targetMemoryUtilizationPercentage: 95 + resources: + requests: + cpu: 100m + memory: 250Mi +``` + +### Private Ingress Controller + +Enable the private ingress controller for internal services: + +```yaml +ingress-nginx-private: + enabled: true + controller: + ingressClass: internal-nginx + service: + annotations: + service.beta.kubernetes.io/aws-load-balancer-scheme: internal +``` + +### External DNS Configuration + +Configure external-dns for your DNS provider: + +{% tabs %} +{% tab title="AWS Route53" %} +```yaml +external-dns: + enabled: true + provider: aws + domainFilters: + - example.com + serviceAccount: + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/external-dns +``` +{% /tab %} +{% tab title="Google Cloud DNS" %} +```yaml +external-dns: + enabled: true + provider: google + domainFilters: + - example.com + google: + project: my-gcp-project +``` +{% /tab %} +{% tab title="Azure DNS" %} +```yaml +external-dns: + enabled: true + provider: azure + domainFilters: + - example.com + azure: + resourceGroup: my-resource-group + tenantId: my-tenant-id + subscriptionId: my-subscription-id +``` +{% /tab %} +{% /tabs %} + +{% callout severity="info" %} +External DNS is safe to run multiple times in the same cluster. You can deploy additional instances configured for different domains without conflicts. +{% /callout %} + +### Cert Manager Configuration + +Configure certificate issuance: + +```yaml +cert-manager: + enabled: true + installCRDs: true + +letsencrypt: + enabled: true + email: admin@example.com +``` + +## Cloud Provider Setup + +### AWS (EKS) + +For AWS deployments, ensure you have the necessary IAM roles configured. The `plural up` scaffolding includes these by default in `terraform/modules/clusters/aws/addons.tf`: + +```tf +module "externaldns_irsa_role" { + source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" + version = "~> 5.33" + + role_name = "${module.eks.cluster_name}-externaldns" + attach_external_dns_policy = true + attach_cert_manager_policy = true + + oidc_providers = { + main = { + provider_arn = module.eks.oidc_provider_arn + namespace_service_accounts = [ + "plural-runtime:external-dns", + "cert-manager:cert-manager" + ] + } + } +} +``` + +### GCP (GKE) + +For GKE, use Workload Identity for authentication. See [Google's Workload Identity documentation](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) for setup instructions. + +### Azure (AKS) + +For AKS, configure Azure AD Pod Identity or Workload Identity. See [Azure's documentation](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview) for details. + +## Verifying the Deployment + +After deploying, verify the components are running: + +```sh +kubectl get pods -n plural-runtime +``` + +You should see pods for: +- `ingress-nginx-controller-*` +- `external-dns-*` +- `cert-manager-*` + +Check that the ingress controller has an external IP: + +```sh +kubectl get svc -n plural-runtime +``` + +## Troubleshooting + +### Ingress Controller Not Getting External IP + +If the ingress controller service remains in `Pending` state: + +1. Check cloud provider annotations are correct +2. Verify load balancer controller is running (for AWS) +3. Check service account IAM permissions + +### DNS Records Not Being Created + +If external-dns isn't creating records: + +1. Verify the domain filter matches your zone +2. Check external-dns logs: `kubectl logs -n plural-runtime -l app.kubernetes.io/name=external-dns` +3. Verify IAM/service account permissions for DNS management + +### Certificate Issuance Failing + +If certificates are not being issued: + +1. Check cert-manager logs: `kubectl logs -n plural-runtime -l app.kubernetes.io/name=cert-manager` +2. Verify the ClusterIssuer is ready: `kubectl get clusterissuer` +3. For DNS-01 challenges, ensure cert-manager has DNS permissions + +## Next Steps + +- {% doclink to="plural_features_continuous_deployment_global_service" %}Global Services{% /doclink %} - Learn more about deploying services across your fleet +- {% doclink to="plural_features_service_templating" %}Service Templating{% /doclink %} - Understand how to use Liquid templating for dynamic configuration +- {% doclink to="getting_started_how_to_use_controllers" %}Set up ingress on a cluster{% /doclink %} - Alternative approach using individual components diff --git a/pages/plural-features/runtime/index.md b/pages/plural-features/runtime/index.md new file mode 100644 index 00000000..32d86a23 --- /dev/null +++ b/pages/plural-features/runtime/index.md @@ -0,0 +1,77 @@ +--- +title: Runtime +description: Plural Runtime is an omnibus Helm chart that simplifies setting up essential network infrastructure for Kubernetes clusters. +--- + +Plural Runtime is a consolidated Helm chart that bundles the essential network infrastructure components needed for web-facing Kubernetes applications. Rather than managing multiple Helm releases for ingress, DNS, and TLS certificates separately, Runtime provides a unified, production-ready package with sensible defaults. + +## Why Runtime? + +Setting up a production-ready Kubernetes cluster typically requires configuring several interconnected components: + +- **Ingress controllers** for load balancing HTTP traffic +- **DNS automation** to register hostnames automatically +- **Certificate management** to handle TLS certificates +- **Cloud-specific integrations** like AWS Load Balancer Controller + +Runtime simplifies this by providing a single chart that: + +- Installs and configures all components in one operation +- Uses production-ready defaults optimized for reliability +- Supports modular enable/disable for each component +- Works seamlessly with Plural's fleet management capabilities + +## Core Components + +Runtime includes the following components, each of which can be independently enabled or disabled: + +### Ingress NGINX + +Provides an `nginx` ingress class configured with: + +- AWS NLB support for better websocket handling and cost efficiency +- Extended timeouts for long-running connections (3600s) +- Horizontal pod autoscaling (2-11 replicas) based on memory utilization +- Topology spread constraints for high availability across zones +- Structured JSON logging for observability + +### Private Ingress NGINX + +An additional ingress controller operating on internal networks, providing an `internal-nginx` ingress class. This is useful for services that should only be accessible within your VPC or private network. + +### Cert Manager + +Handles automated TLS certificate issuance with: + +- Default `plural` ClusterIssuer for onplural.sh domains +- Let's Encrypt integration for ACME certificate provisioning +- Support for both HTTP-01 and DNS-01 challenge types + +### External DNS + +A daemon that automatically manages DNS records by: + +- Watching for Ingress and Service resources +- Creating and updating DNS records in supported providers +- Pre-configured for Plural's onplural.sh domain management +- Safe to run multiple instances for different domains + +### Flux Source Controller (Optional) + +Provides GitOps capabilities for sourcing Kubernetes manifests from Git repositories. + +## When to Use Runtime + +Runtime is the recommended approach when you want to: + +- **Quickly bootstrap new clusters** with a complete network stack +- **Maintain consistency** across your cluster fleet with standardized configurations +- **Reduce operational overhead** by managing fewer Helm releases +- **Leverage Plural's defaults** that are battle-tested in production environments + +For organizations with specific requirements or existing tooling, the individual components (ingress-nginx, cert-manager, external-dns) can also be deployed independently using {% doclink to="plural_features_continuous_deployment_global_service" %}Global Services{% /doclink %}. + +## Next Steps + +- {% doclink to="plural_features_runtime_getting_started" %}Getting started with Runtime{% /doclink %} - Learn how to deploy and configure Runtime on your clusters +- {% doclink to="getting_started_how_to_use_controllers" %}Set up ingress on a cluster{% /doclink %} - Alternative approach using individual global services diff --git a/src/routing/docs-structure.ts b/src/routing/docs-structure.ts index 5cb50f63..e811055f 100644 --- a/src/routing/docs-structure.ts +++ b/src/routing/docs-structure.ts @@ -217,6 +217,13 @@ export const docsStructure: DocSection[] = [ title: 'Projects and multi-tenancy', }, { path: 'notifications', title: 'Notification configuration' }, + { + path: 'runtime', + title: 'Runtime', + sections: [ + { path: 'getting-started', title: 'Getting started with Runtime' }, + ], + }, ], }, {