The cndi_config.yaml file is the core of your CNDI project. It is a YAML file
that contains all the information about your project, including the the
infrastructure resources you need, the applications you want to deploy, and
the Kubernetes cluster_manifests which configure your cluster.
The entire schema for this config file is defined at ./src/schemas/cndi_config.schema.json and should be up-to-date with the latest version of CNDI.
This one file is the key to understanding CNDI, it's pretty simple, lets step through it.
This first block of config shows CNDI's metadata fields at the top.
-
cndi_versionis the version of CNDI you are using. This is used to determine how we should parse your config, and which schema to validate against. In practicev2is the only version available today. -
project_nameis a human-readable name for your project. It can be used to create infrastructure tags, and is generally expected to be unique per cloud environment. -
provideris the cloud provider you are using. This is used to determine which cloud provider's API to use. -
distributionis the Kubernetes distribution you are using. This is used to determine which Kubernetes distribution's API to use. -
regionis the region to be used in your target provider -
kubernetes_versionis an optional field that lets you pick the Kubernetes version for the control plane and nodes (for managed clusters like EKS/GKE/AKS and for dev distributions when supported). Example:kubernetes_version: "1.33".
Here's an example with those values configured:
cndi_version: v3
project_name: my-cndi-project
provider: aws
distribution: eks
region: us-east-1
kubernetes_version: "1.33"The next block of config shows the infrastructure section of
cndi_config.yaml. This generally includes the cndi key, and also rarely
includes the terraform key if you need to deploy resources from Terraform not
covered by the cndi key.
The terraform key is used to deploy resources using Terraform beyond what
cndi was built to handle. This is generally used for more complex
infrastructure requirements and should be considered an "escape hatch" for when
cndi doesn't cover your use case. For more information on how to use this key
check out the dedicated
infrastructure.terraform documentation.
The cndi key contains a number of in-built modules which can be used to
configure both Kubernetes objects and some cloud resources.
The most common of these is the nodes key, which is used to configure the
Kubernetes nodes in your cluster.
Let's look at a quick basic example:
CNDI will use the provider and distribution to determine which Stack to
deploy, including a group of 3 Kubernetes cluster nodes with a provided
instance_type of
t3.medium
which specifies the hardware spec of the nodes.
project_name: my-postgres-project
cndi_version: v3
provider: aws
distribution: eks
region: us-east-1
infrastructure:
cndi:
nodes:
- name: postgres-nodes
count: 3
instance_type: t3.mediumBy running this configuration, CNDI will deploy a Kubernetes cluster with 3 nodes on EKS including some platform features, but on it's own won't do very much without applications.
But before moving on, let's also list all built-in modules which can be used in
the infrastructure.cndi block:
infrastructure.cndi. |
Description |
|---|---|
nodes |
Configure Cluster Nodes |
cert_manager |
Configure Cert-Manager for your Cluster |
external_dns |
Configure ExternalDNS to create DNS records for your Ingress resources |
argocd |
Configure ArgoCD for your Cluster |
observability |
Configure Observability stack |
network |
Configure Cluster Networking |
functions |
Build and Deploy Custom CNDI Functions |
This document will summarize typical usage for each of these properties, and for more detailed information you can refer to documentation page for each.
The next block of config shows the applications section of cndi_config.yaml.
This section of the config is a thin wrapper over the ArgoCD
Application CRD,
and is used to deploy applications to your cluster. Here's an example of the
applications block in action:
# metadata
project_name: wordpress-project
cndi_version: v2
provider: azure
distribution: aks
# infrastructure
infrastructure: { ... }
# applications
applications:
wordpress:
repoURL: https://charts.bitnami.com/bitnami
chart: wordpress
targetRevision: 23.1.17
destinationNamespace: wordpress
values:
existingSecret: wordpress-pw
wordpressUsername: adminThis block will deploy the wordpress the chart named "wordpress" found in
the https://charts.bitnami.com/bitnami helm repository, with version
23.1.17. The chart will be deployed to the wordpress namespace, and the
values block will be passed to the chart as a values.yaml file.
For more information on how to configure applications, see the applications documentation.
The cluster_manifests section is used to define Kubernetes resources which
should be added to your cluster. This can be used to configure your cluster in
ways that are not covered by the infrastructure or applications sections.
Generally this works by taking the key of the object in the cluster_manifests
block, and writing a Kubernetes manifest in a file with that name in the
cndi/cluster_manifests directory, with a .yaml extension.
Here's a simple example of the cluster_manifests block in action:
cluster_manifests:
valid-simple-ns: # will be written to ./cndi/cluster_manifests/valid-simple-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: simple-nsThe only time the input cluster_manifests entries are transformed is when they
have the Secret kind.
When the manifest contains Secret.data or Secret.stringData defined in
plain-text, they will not be written out to ./cndi/cluster_manifests. Instead,
you can use the cndi_on_ow.seal_secret_from_env_var(MY_VAR) function to
securely encrypt these values from your .env file (or environment).
cluster_manifests:
valid-simple-ns:
apiVersion: v1
kind: Namespace
metadata:
name: simple-ns
bad-secret: # invalid, CNDI will not write this to ./cndi/cluster_manifests
apiVersion: v1
kind: Secret
metadata:
name: my-user-secret
namespace: foo
stringData:
username: admin
password: password123
valid-secret:
# valid! CNDI will write this to ./cndi/cluster_manifests as a SealedSecret
# you can trust the real Secret will be available in your cluster safely
# without putting the plain-text values in git
apiVersion: v1
kind: Secret
metadata:
name: my-user-secret
namespace: foo
stringData:
username: $cndi_on_ow.seal_secret_from_env_var(MY_USERNAME)
password: $cndi_on_ow.seal_secret_from_env_var(MY_PASSWORD)For more information on how to configure cluster_manifests, see the
cluster_manifests documentation.
Now that you've had a high-level overview of the cndi_config.yaml file, you
may be interested in the other parameters you can customize at a deeper level.
Every section of a cndi_config.yaml file is documented more thoroughly in the
./docs/config directory, including:
- applications
- cluster_manifests
- infrastructure.cndi.nodes
- infrastructure.cndi.cert_manager
- infrastructure.cndi.argocd
- infrastructure.cndi.external_dns
- infrastructure.cndi.functions
- infrastructure.cndi.network
- infrastructure.cndi.observability
- infrastructure.terraform
Additionally, here is an example of a typical cndi_config.yaml file:
project_name: wordpress-cluster
cndi_version: v2
provider: azure
distribution: aks
infrastructure:
cndi:
nodes: # ./docs/config/infrastructure/cndi/nodes.md
- name: wordpress-nodes
count: 3
instance_type: Standard_D2_v2
cert_manager: # ./docs/config/infrastructure/cndi/cert_manager.md
email: jane.smith@example.com
external_dns:
provider: azure
argocd: # ./docs/config/infrastructure/cndi/argocd.md
hostname: argocd.my-cluster.example.com
observability: # ./docs/config/infrastructure/cndi/observability.md
grafana:
hostname: observability.my-cluster.example.com
cluster_manifests: # ./docs/config/cluster_manifests.md
wordpress-ingress: # https://kubernetes.io/docs/concepts/services-networking/ingress/
wp-ingress:
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: wordpress-ingress
namespace: wordpress
annotations:
cert-manager.io/cluster-issuer: cluster-issuer
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
external-dns.alpha.kubernetes.io/hostname: wordpress.my-cluster.example.com
spec:
ingressClassName: public
tls:
- hosts:
- wordpress.my-cluster.example.com
secretName: cluster-issuer-private-key
rules:
- host: wordpress.my-cluster.example.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: wordpress
port:
number: 443
wordpress-secret: # https://kubernetes.io/docs/concepts/configuration/secret/
apiVersion: v1
kind: Secret
metadata:
name: wordpress-pw
namespace: wordpress
stringData:
wordpress-password: $cndi_on_ow.seal_secret_from_env_var(WORDPRESS_PASSWORD)
wordpress-ns: # https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
apiVersion: v1
kind: Namespace
metadata:
name: wordpress
external-dns-secret: # https://kubernetes.io/docs/concepts/configuration/secret/
apiVersion: v1
kind: Secret
metadata:
name: external-dns
namespace: external-dns
stringData:
# credentials in JSON string in .env used to modify DNS records
azure.json: $cndi_on_ow.seal_secret_from_env_var(AZURE_CREDENTIALS)
applications: # ./docs/config/applications.md
wordpress:
repoURL: https://charts.bitnami.com/bitnami
chart: wordpress
targetRevision: 23.1.17
destinationNamespace: wordpress
values:
existingSecret: wordpress-pw
wordpressUsername: admin