Applying Extra Kubernetes Objects¶
Certain deployments require additional Kubernetes objects that are not deployed as a part of this Helm Chart.
The following are some of the use cases:
- Admin credentials are generated and stored in a secret manager such as HashiCorp Vault or AWS Secrets Manager. These credentials must be injected to Pods as a Kubernetes secret.
- Additional Ingresses must be deployed to expose Nautobot on a different hostname.
- Additional Kubernetes Jobs must be executed to perform additional checks or to provision certain aspects of Nautobot deployment.
Let's focus on the use case for admin credentials. Once the credentials are stored in HashiCorp Vault, for example, you can use the ExternalSecrets operator to fetch those credentials and create the Kubernetes Secret object. The following snippet shows an example:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-secret
namespace: nautobot
spec:
data:
- remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: secrets/nautobot/superuser
metadataPolicy: None
property: SUPERUSER_PASSWORD
secretKey: SUPERUSER_PASSWORD
- remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: secrets/nautobot/superuser
metadataPolicy: None
property: API_TOKEN
secretKey: API_TOKEN
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
creationPolicy: Owner
deletionPolicy: Retain
name: my-secret
template:
data:
NAUTOBOT_SUPERUSER_PASSWORD: "{{ `{{ .SUPERUSER_PASSWORD | toString }}` }}"
NAUTOBOT_SUPERUSER_API_TOKEN: "{{ `{{ .API_TOKEN | toString }}` }}"
engineVersion: v2
mergePolicy: Replace
The operator will fetch credentials from Vault and it will create a Kubernetes Secret, after this object is deployed. The Helm Chart values will then specify the existing secret name such as this:
To apply additional Kubernetes objects, such as the one above, you must use an external tool, such as FluxCD, ArgoCD, Ansible, or something else.
To simplify this process, the Nautobot Helm Chart supports an additional
property called extraObjects
. This property is a list of Kubernetes manifests
that must be deployed along to Nautobot objects generated from this Helm Chart.
This allows you to omit using external tools to deploy any extra Kubernetes
objects.
The following snippet shows how the Helm Chart values would look in this case:
---
nautobot:
superUser:
existingSecret: "my-secret"
extraObjects:
- |
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-secret
namespace: nautobot
spec:
data:
- remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: secrets/nautobot/superuser
metadataPolicy: None
property: SUPERUSER_PASSWORD
secretKey: SUPERUSER_PASSWORD
- remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: secrets/nautobot/superuser
metadataPolicy: None
property: API_TOKEN
secretKey: API_TOKEN
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
creationPolicy: Owner
deletionPolicy: Retain
name: my-secret
template:
data:
NAUTOBOT_SUPERUSER_PASSWORD: "{{ `{{ .SUPERUSER_PASSWORD | toString }}` }}"
NAUTOBOT_SUPERUSER_API_TOKEN: "{{ `{{ .API_TOKEN | toString }}` }}"
engineVersion: v2
mergePolicy: Replace
Helm will also deploy the ExternalSecret
object when the release with these
values is deployed. The Nautobot Pods require the my-secret
Secret,
so they will not start until the ExternalSecrets operator creates the Secret.
You must be aware that these manifests are deployed in order defined by Helm. So, there is no guarantee, that certain manifests will be deployed before others. In cases where you need certain manifests (such as a Job for example), you will still need a third-party tool.
The manifests can be defined as a string or as a dictionary, as shown in the following example:
extraObjects:
- apiVersion: v1
kind: ConfigMap
metadata:
name: database-host
namespace: nautobot
data:
DATABASE_HOST: database.example.com
- |
apiVersion: v1
kind: ConfigMap
metadata:
name: database-user
namespace: nautobot
data:
DATABASE_USER: db-admin
You can also use Go templating language to define certain parts of a manifest. All variables from the Helm Chart values file are available. You can also use functions that are available in Go templating language.
The following example shows how you can specify namespace dynamically, and how to define the secret name on a single place.
---
nautobot:
superUser:
existingSecret: "my-secret"
extraObjects:
- |
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ .Values.nautobot.superUser.existingSecret }}
namespace: {{ .Release.Namespace }}
spec:
data:
- remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: secrets/nautobot/superuser
metadataPolicy: None
property: SUPERUSER_PASSWORD
secretKey: SUPERUSER_PASSWORD
- remoteRef:
conversionStrategy: Default
decodingStrategy: None
key: secrets/nautobot/superuser
metadataPolicy: None
property: API_TOKEN
secretKey: API_TOKEN
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
creationPolicy: Owner
deletionPolicy: Retain
name: {{ .Values.nautobot.superUser.existingSecret }}
template:
data:
NAUTOBOT_SUPERUSER_PASSWORD: "{{ `{{ .SUPERUSER_PASSWORD | toString }}` }}"
NAUTOBOT_SUPERUSER_API_TOKEN: "{{ `{{ .API_TOKEN | toString }}` }}"
engineVersion: v2
mergePolicy: Replace
Please note that these objects are processed in a template. So make sure that you don't use the same syntax as used for Go templating. You can use back quotes to "escape" strings in those cases. The following is an example:
The resulting manifest will be: NAUTOBOT_SUPERUSER_PASSWORD: {{ .SUPERUSER_PASSWORD | toString }}