docs/integrations/platforms/kubernetes/infisical-static-secret-crd.mdx
import KubernetesOperatorTemplating from "/snippets/kubernetes-operator-v1beta1-templating.mdx";
The InfisicalStaticSecret CRD syncs secrets from Infisical into your Kubernetes cluster as native Kubernetes Secrets or ConfigMaps.
It replaces the v1alpha1 InfisicalSecret CRD with a cleaner design: authentication and connection details are defined as separate reusable resources (InfisicalAuth and InfisicalConnection) instead of inline blocks.
Before creating an InfisicalStaticSecret, you need:
apiVersion: secrets.infisical.com/v1beta1
kind: InfisicalStaticSecret
metadata:
name: my-static-secret
labels:
label-to-be-passed-to-managed-secret: sample-value
annotations:
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
spec:
infisicalAuthRef:
name: my-infisical-auth
namespace: default
syncOptions:
refreshInterval: 60s
instantUpdates: false
sources:
- projectId: <your-project-id>
environmentSlug: dev
secretPath: /
targets:
- name: managed-secret
namespace: default
kind: Secret
creationPolicy: Owner
| Field | Required | Description |
|---|---|---|
name | Yes | The name of the InfisicalAuth resource. |
namespace | Yes | The namespace of the InfisicalAuth resource. |
See the InfisicalAuth CRD documentation for details. </Accordion>
<Accordion title="syncOptions"> Controls the synchronization behavior.| Field | Required | Description |
|---|---|---|
refreshInterval | Yes | How often to resync (e.g. 60s, 5m, 1h). |
instantUpdates | No | When true, the operator receives real-time push updates from Infisical. Please note that this is an Enterprise feature. |
When multiple sources produce a secret with the same key, the first occurrence wins — sources listed earlier in the array take precedence over later ones. Direct secrets always take precedence over imported secrets, regardless of source order.
| Field | Required | Description |
|---|---|---|
projectId | Yes | The Infisical project ID. |
environmentSlug | Yes | The environment slug (e.g. dev, staging, prod). |
secretPath | Yes | The path to the secrets. Root is /. |
tagSlugs | No | Filter secrets by tag slugs. |
recursive | No | Whether to recursively fetch secrets from sub-folders. Defaults to false. |
sources:
- projectId: <your-project-id>
environmentSlug: dev
secretPath: /app
- projectId: <your-project-id>
environmentSlug: dev
secretPath: /shared
recursive: true
tagSlugs:
- backend
| Field | Required | Description |
|---|---|---|
name | Yes | Name of the managed Kubernetes Secret or ConfigMap. |
namespace | Yes | Namespace of the managed Kubernetes Secret or ConfigMap. |
kind | Yes | The type of resource to create. Must be Secret or ConfigMap. |
secretType | No | Override the default Opaque secret type. Only applies when kind: Secret. When using a typed secret (e.g. kubernetes.io/tls, kubernetes.io/dockerconfigjson), you must use a template to produce the keys that Kubernetes requires for that type, otherwise the API server will reject the resource. |
creationPolicy | Yes | Owner sets a Kubernetes owner reference so the managed resource is automatically deleted by the garbage collector when the InfisicalStaticSecret is removed. Orphan leaves the managed resource in place. |
template | No | Optional templating configuration (see Templating below). |
metadata | No | Custom labels and annotations to set on the managed resource. When set, these values are used as-is and not merged with the InfisicalStaticSecret CRD metadata. |
targets:
- name: app-secrets
namespace: default
kind: Secret
creationPolicy: Owner
- name: app-config
namespace: default
kind: ConfigMap
creationPolicy: Orphan
metadata:
labels:
app: my-app
annotations:
description: "Synced from Infisical"
The operator provides flexible options for managing labels and annotations on managed Kubernetes Secrets and ConfigMaps.
<AccordionGroup> <Accordion title="Default behavior"> By default, the operator merges labels and annotations from the `InfisicalStaticSecret` resource into each managed Secret or ConfigMap that does not define target-level `metadata`.Conflict behavior:
- Existing labels and annotations that were not previously managed by the operator are preserved.
- Labels and annotations from the `InfisicalStaticSecret` resource take precedence when the same key already exists on the managed resource.
- Labels and annotations previously propagated by the operator are removed if they are removed from the `InfisicalStaticSecret` resource.
- Kubernetes system annotations and Infisical operator tracking annotations are preserved.
```yaml
apiVersion: secrets.infisical.com/v1beta1
kind: InfisicalStaticSecret
metadata:
name: my-static-secret
labels:
label-to-be-passed-to-managed-secret: sample-value
annotations:
example.com/annotation-to-be-passed-to-managed-secret: "sample-value"
spec:
infisicalAuthRef:
name: my-infisical-auth
namespace: default
sources:
- projectId: <your-project-id>
environmentSlug: dev
secretPath: /
targets:
- name: managed-secret
namespace: default
kind: Secret
creationPolicy: Owner
```
This creates a managed Secret with the inherited metadata:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: managed-secret
namespace: default
labels:
label-to-be-passed-to-managed-secret: sample-value
annotations:
example.com/annotation-to-be-passed-to-managed-secret: sample-value
secrets.infisical.com/version: W/"3f1-ZyOSsrCLGSkAhhCkY2USPu2ivRw"
type: Opaque
data: ...
```
- Target `metadata.labels` replaces the managed resource's labels.
- Target `metadata.annotations` replaces user-defined annotations on the managed resource.
- Kubernetes system annotations and the Infisical version annotation are preserved.
- Labels and annotations from the `InfisicalStaticSecret` resource are not propagated to that target.
- This lets you keep CRD-specific metadata separate from managed resource metadata.
<Tip>
To prevent any propagation while using target `metadata`, pass empty objects for labels and/or annotations:
```yaml
targets:
- name: managed-secret
namespace: default
kind: Secret
creationPolicy: Owner
metadata:
labels: {}
annotations: {}
```
</Tip>
```yaml
apiVersion: secrets.infisical.com/v1beta1
kind: InfisicalStaticSecret
metadata:
name: my-static-secret
labels:
managed-by: infisical-operator
annotations:
example.com/cr-specific: "metadata"
spec:
infisicalAuthRef:
name: my-infisical-auth
namespace: default
sources:
- projectId: <your-project-id>
environmentSlug: prod
secretPath: /
targets:
- name: managed-secret-with-custom-metadata
namespace: default
kind: Secret
creationPolicy: Owner
metadata:
labels:
app: my-application
environment: production
tier: backend
annotations:
secret.example.com/description: "Production database credentials"
secret.example.com/owner: "platform-team"
```
This creates a managed Secret with only the target metadata:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: managed-secret-with-custom-metadata
namespace: default
labels:
app: my-application
environment: production
tier: backend
annotations:
secret.example.com/description: "Production database credentials"
secret.example.com/owner: "platform-team"
type: Opaque
data: ...
```
kubectl apply -f infisical-static-secret.yaml
Verify the managed secret was created:
kubectl get secrets -n <namespace>
The managed Kubernetes Secret or ConfigMap works like any other native resource. You can reference it via envFrom, env, or volumes:
<Accordion title="env">
```yaml
env:
- name: SECRET_NAME
valueFrom:
secretKeyRef:
name: managed-secret
key: SOME_SECRET_KEY
```
</Accordion>
<Accordion title="volumes">
```yaml
volumes:
- name: secrets-volume
secret:
secretName: managed-secret
```
</Accordion>
</AccordionGroup>
<Accordion title="env">
```yaml
env:
- name: CONFIG_VALUE
valueFrom:
configMapKeyRef:
name: managed-configmap
key: SOME_CONFIG_KEY
```
</Accordion>
<Accordion title="volumes">
```yaml
volumes:
- name: config-volume
configMap:
name: managed-configmap
```
</Accordion>
</AccordionGroup>
Pods that consume a managed Secret or ConfigMap don't reload automatically when the underlying data changes. Without a restart, the workload may continue using stale values, especially when secrets are injected as environment variables.
To trigger a rolling restart when the managed resource updates, add the following annotation to the Deployment, StatefulSet, or DaemonSet that consumes it:
secrets.infisical.com/auto-reload: "true"
You can check the status of your InfisicalStaticSecret resource by inspecting its conditions:
kubectl get infisicalstaticsecret my-static-secret -o jsonpath='{.status.conditions}' | jq
When reconciliation is successful, the secrets.infisical.com/LastReconcileStatus condition will have Status: "True", Reason: "OK", and Message: "Reconciliation successful".
If reconciliation fails, Status will be "False", Reason will be set to Error, and Message will contain details about what went wrong.
The ObservedGeneration field indicates which generation of the resource spec the operator has last processed. If ObservedGeneration is less than metadata.generation, the operator has not yet reconciled the latest changes to the resource.