Is there a way to use a k8s secret for environment...
# prefect-kubernetes
d
Is there a way to use a k8s secret for environment variables in my job variable or prefect deployment? I'd like the pod the prefect-worker spins up to use an environment variable thats loaded from a secret in my namespace. Not sure if this is possible
Could this be done through the baseJobTemplate? Here is what im working with currently
Copy code
apiVersion: v1
kind: ConfigMap
metadata:
  name: prefect-worker-config
data:
  baseJobTemplate.json: |
    {
      "variables": {
        "type": "object",
        "properties": {
          "env": {
            "type": "object",
            "title": "Environment Variables",
            "description": "Environment variables to set when starting a flow run.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Name given to infrastructure created by a worker."
          },
          "image": {
            "type": "string",
            "title": "Image",
            "example": "<http://docker.io/prefecthq/prefect:2-latest|docker.io/prefecthq/prefect:2-latest>",
            "description": "The image reference of a container image to use for created jobs. If not set, the latest Prefect image will be used."
          },
          "labels": {
            "type": "object",
            "title": "Labels",
            "description": "Labels applied to infrastructure created by a worker.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "command": {
            "type": "string",
            "title": "Command",
            "description": "The command to use when starting a flow run. In most cases, this should be left blank and the command will be automatically generated by the worker."
          },
          "cpu_limit": {
            "type": "string",
            "title": "CPU limit",
            "description": "CPU limit for pod"
          },
          "mem_limit": {
            "type": "string",
            "title": "Memory limit",
            "description": "Memory limit for pod"
          },
          "namespace": {
            "type": "string",
            "title": "Namespace",
            "default": "default",
            "description": "The Kubernetes namespace to create jobs within."
          },
          "cpu_request": {
            "type": "string",
            "title": "CPU request",
            "default": "500m",
            "description": "CPU request for pod"
          },
          "mem_request": {
            "type": "string",
            "title": "Memory request",
            "default": "128Mi",
            "description": "Memory request for pod"
          },
          "stream_output": {
            "type": "boolean",
            "title": "Stream Output",
            "default": true,
            "description": "If set, output will be streamed from the job to local standard output."
          },
          "cluster_config": {
            "allOf": [
              {
                "$ref": "#/definitions/KubernetesClusterConfig"
              }
            ],
            "title": "Cluster Config",
            "description": "The Kubernetes cluster config to use for job creation."
          },
          "finished_job_ttl": {
            "type": "integer",
            "title": "Finished Job TTL",
            "description": "The number of seconds to retain jobs after completion. If set, finished jobs will be cleaned up by Kubernetes after the given delay. If not set, jobs will be retained indefinitely."
          },
          "image_pull_policy": {
            "enum": [
              "IfNotPresent",
              "Always",
              "Never"
            ],
            "type": "string",
            "title": "Image Pull Policy",
            "default": "IfNotPresent",
            "description": "The Kubernetes image pull policy to use for job containers."
          },
          "service_account_name": {
            "type": "string",
            "title": "Service Account Name",
            "description": "The Kubernetes service account to use for job creation."
          },
          "job_watch_timeout_seconds": {
            "type": "integer",
            "title": "Job Watch Timeout Seconds",
            "description": "Number of seconds to wait for each event emitted by a job before timing out. If not set, the worker will wait for each event indefinitely."
          },
          "pod_watch_timeout_seconds": {
            "type": "integer",
            "title": "Pod Watch Timeout Seconds",
            "default": 60,
            "description": "Number of seconds to watch for pod creation before timing out."
          }
        },
        "definitions": {
          "KubernetesClusterConfig": {
            "type": "object",
            "title": "KubernetesClusterConfig",
            "required": [
              "config",
              "context_name"
            ],
            "properties": {
              "config": {
                "type": "object",
                "title": "Config",
                "description": "The entire contents of a kubectl config file."
              },
              "context_name": {
                "type": "string",
                "title": "Context Name",
                "description": "The name of the kubectl context to use."
              }
            },
            "description": "Stores configuration for interaction with Kubernetes clusters.\n\nSee `from_file` for creation.",
            "secret_fields": [],
            "block_type_slug": "kubernetes-cluster-config",
            "block_schema_references": {}
          }
        },
        "description": "Default variables for the Kubernetes worker.\n\nThe schema for this class is used to populate the `variables` section of the default\nbase job template."
      },
      "job_configuration": {
        "env": "{{ env }}",
        "name": "{{ name }}",
        "labels": "{{ labels }}",
        "command": "{{ command }}",
        "namespace": "{{ namespace }}",
        "job_manifest": {
          "kind": "Job",
          "spec": {
            "template": {
              "spec": {
                "containers": [
                  {
                    "env": "{{ env }}",
                    "args": "{{ command }}",
                    "name": "prefect-job",
                    "image": "{{ image }}",
                    "resources": {
                      "limits": {
                        "cpu": "{{ cpu_limit }}",
                        "memory": "{{ mem_limit }}"
                      },
                      "requests": {
                        "cpu": "{{ cpu_request }}",
                        "memory": "{{ mem_request }}"
                      }
                    },
                    "imagePullPolicy": "{{ image_pull_policy }}"
                  }
                ],
                "completions": 1,
                "parallelism": 1,
                "restartPolicy": "Never",
                "serviceAccountName": "{{ service_account_name }}"
              }
            },
            "backoffLimit": 0,
            "ttlSecondsAfterFinished": "{{ finished_job_ttl }}"
          },
          "metadata": {
            "labels": "{{ labels }}",
            "namespace": "{{ namespace }}",
            "generateName": "{{ name }}-"
          },
          "apiVersion": "batch/v1"
        },
        "stream_output": "{{ stream_output }}",
        "cluster_config": "{{ cluster_config }}",
        "job_watch_timeout_seconds": "{{ job_watch_timeout_seconds }}",
        "pod_watch_timeout_seconds": "{{ pod_watch_timeout_seconds }}"
      }
    }
It appears to work if you override the template with your envs, I was worried this would break the env overriding in my prefect.yaml job_variables -> env values, however, those values also get set . Heres the change I made to my template from the post above:
Copy code
"env": [
                      {
                        "name": "S3_ACCESS_KEY_ID",
                        "valueFrom": {
                          "secretKeyRef": {
                            "name": "iam-secret",
                            "key": "S3_ACCESS_KEY_ID"
                          }
                        }
                      },
                      {
                        "name": "S3_SECRET_ACCESS_KEY",
                        "valueFrom": {
                          "secretKeyRef": {
                            "name": "iam-secret",
                            "key": "S3_SECRET_ACCESS_KEY"
                          }
                        }
                      }
                    ],
g
@Devin Dennis You can also edit the Base Job Template for a workpool in order to leverage standard K8s features. We use this to both inject secrets as ENVs as well as mount certificates as volumes in our jobs
208 Views