Daniel Soares
08/07/2025, 3:22 PMMarvin
08/07/2025, 3:22 PMMarvin
08/07/2025, 3:24 PMyaml
# base-job-template.yaml
job_configuration:
env:
PREFECT_API_URL: "<http://your-prefect-server:4200/api>"
PREFECT_API_USERNAME: "${PREFECT_API_USERNAME}"
PREFECT_API_PASSWORD: "${PREFECT_API_PASSWORD}"
2. Create/Update the Work Pool
bash
prefect work-pool create "your-pool-name" \
--type kubernetes \
--base-job-template base-job-template.yaml
3. Configure the Worker
When starting your worker, ensure it has the basic auth credentials:
bash
prefect worker start \
--pool "your-pool-name" \
--username your-username \
--password your-password
4. Use Kubernetes Secrets (Recommended)
Instead of passing credentials directly, it's better to use Kubernetes secrets:
yaml
# Create a Kubernetes secret
apiVersion: v1
kind: Secret
metadata:
name: prefect-auth
type: Opaque
data:
username: <base64-encoded-username>
password: <base64-encoded-password>
Then modify your base job template to use these secrets:
yaml
job_configuration:
env:
- name: PREFECT_API_USERNAME
valueFrom:
secretKeyRef:
name: prefect-auth
key: username
- name: PREFECT_API_PASSWORD
valueFrom:
secretKeyRef:
name: prefect-auth
key: password
5. Verify Configuration
- Make sure the PREFECT_API_URL
points to your Prefect server
- Ensure the credentials match those configured in your Prefect server
- Check that the Kubernetes service account used by the worker has access to read the secrets
6. Debug Tips
- You can check the logs of the failed Kubernetes jobs to see the exact authentication error
- Verify the environment variables are correctly set in the pods by running:
bash
kubectl exec -it <pod-name> -- env | grep PREFECT
- Ensure your Kubernetes network policies (if any) allow the pods to reach the Prefect API
If you're still experiencing issues after implementing these changes, could you please share:
1. The exact error message from the Kubernetes job logs
2. The current base job template configuration (with sensitive information redacted)
3. Whether you're using any custom network policies in your GKE cluster
This will help me provide more specific guidance for your setup.Daniel Soares
08/07/2025, 3:33 PMfrom_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 }}",
"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 }}"
}
}Marvin
08/07/2025, 3:33 PMMarvin
08/07/2025, 3:40 PMDaniel Soares
08/07/2025, 3:40 PMMarvin
08/07/2025, 3:40 PMMarvin
08/07/2025, 3:40 PMDaniel Soares
08/07/2025, 3:41 PMMarvin
08/07/2025, 3:41 PMMarvin
08/07/2025, 3:41 PMvariables.env
section, but we need to make sure these are actually being passed to the Kubernetes job pods
2. The PREFECT_API_URL
format seems to have an extra <
and >
- it should be a plain URL without these brackets
3. The credentials are hardcoded in the template - it would be better to use references to Kubernetes secrets
Please share the second part of the template, and I'll provide a complete solution for properly configuring the authentication.Daniel Soares
08/07/2025, 3:41 PMfrom_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 }}",
"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 }}"
}
}Marvin
08/07/2025, 3:42 PMMarvin
08/07/2025, 3:42 PMMarvin
08/07/2025, 3:42 PM"env": "{{ env }}"
will not work properly because Kubernetes expects a specific format for environment variables.
Here's the corrected base job template (I'll focus on the relevant parts that need to change):
json
{
"variables": {
"type": "object",
"properties": {
"env": {
"type": "object",
"title": "Environment Variables",
"default": {
"PREFECT_API_URL": "<http://prefect-url/api>",
"PREFECT_API_PASSWORD": "pass",
"PREFECT_API_USERNAME": "*****"
},
"description": "Environment variables to set when starting a flow run.",
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
// ... other variables remain the same ...
}
},
"job_configuration": {
// ... other configuration remains the same ...
"job_manifest": {
"kind": "Job",
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "prefect-job",
"image": "{{ image }}",
"imagePullPolicy": "{{ image_pull_policy }}",
"args": "{{ command }}",
"env": [
{
"name": "PREFECT_API_URL",
"value": "{{ env.PREFECT_API_URL }}"
},
{
"name": "PREFECT_API_USERNAME",
"value": "{{ env.PREFECT_API_USERNAME }}"
},
{
"name": "PREFECT_API_PASSWORD",
"value": "{{ env.PREFECT_API_PASSWORD }}"
}
]
}
],
"completions": 1,
"parallelism": 1,
"restartPolicy": "Never",
"serviceAccountName": "{{ service_account_name }}"
}
},
// ... rest remains the same ...
}
}
}
}
However, a more secure approach would be to use Kubernetes secrets. Here's how to implement that:
1. First, create a Kubernetes secret:
bash
kubectl create secret generic prefect-auth \
--namespace prefect \
--from-literal=PREFECT_API_USERNAME='your-username' \
--from-literal=PREFECT_API_PASSWORD='your-password'
2. Then modify the template to use the secrets:
```json
{
// ... other configuration remains the same ...
"job_configuration": {
"job_manifest": {
"kind": "Job",
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "prefect-job",
"image": "{{ image }}",
"imagePullPolicy": "{{ image_pull_policy }}",
"args": "{{ command }}",
"env": [
{
"name": "PREFECT_API_URL",
"value": "{{ env.PREFECT_API_URL }}"
},
{
"name": "PREFECT_API_USERNAME",
"valueFrom": {
"secretKeyRef": {
"name": "prefect-auth",
"key": "PREFECT_API_USERNAME"
}
}
},
{
"name": "PREFECT_API_PASSWORD",
"valueFrom": {
"secretKeyRef": {
"name": "prefect-auth",
"key": "PREFECT_API_PASSWORD"
}
}
}
]Marvin
08/07/2025, 3:42 PMTo implement these changes:
1. Save the modified template to a file (e.g., `updated-job-template.json`)
2. Update your work pool with the new template:
```bash
prefect work-pool create "your-pool-name" \
--type kubernetes \
--base-job-template updated-job-template.json \
--overwrite
3. Make sure the service account specified in service_account_name
has access to read the secrets in your namespace.
The key changes made are:
1. Properly formatted the environment variables section in the Kubernetes job spec
2. Removed the angle brackets (<>
) from the API URL
3. Added proper structure for environment variables in the container spec
4. (In the secure version) Added proper secret references
This should resolve the 401 Unauthorized errors you're seeing, as the authentication credentials will now be properly passed to the flow run pods.
Would you like me to explain any part of these changes in more detail?Marvin
08/07/2025, 3:42 PMPREFECT_API_URL
contains extra brackets:
json
"PREFECT_API_URL": "<http://prefect-url/api>"
Should be:
json
"PREFECT_API_URL": "<http://prefect-url/api>"
2. Credentials Security
Instead of hardcoding credentials in the template, let's use Kubernetes secrets. First, create a secret:
yaml
apiVersion: v1
kind: Secret
metadata:
name: prefect-api-credentials
namespace: prefect
type: Opaque
data:
username: <base64-encoded-username>
password: <base64-encoded-password>
3. Updated Base Job Template
Here's how your template should look (this includes the job specification part that would properly inject the environment variables):
json
{
"variables": {
"type": "object",
"properties": {
"env": {
"type": "object",
"title": "Environment Variables",
"default": {}
},
// ... other properties as in your original template ...
}
},
"job_configuration": {
"apiVersion": "batch/v1",
"kind": "Job",
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "prefect-job",
"env": [
{
"name": "PREFECT_API_URL",
"value": "<http://prefect-url/api>"
},
{
"name": "PREFECT_API_USERNAME",
"valueFrom": {
"secretKeyRef": {
"name": "prefect-api-credentials",
"key": "username"
}
}
},
{
"name": "PREFECT_API_PASSWORD",
"valueFrom": {
"secretKeyRef": {
"name": "prefect-api-credentials",
"key": "password"
}
}
}
]
}
]
}
}
}
}
}
4. Implementation Steps
a. First, create the Kubernetes secret:
bash
kubectl create secret generic prefect-api-credentials \
--from-literal=username='your-username' \
--from-literal=password='your-password' \
-n prefect
b. Update your work pool with the new template:
bash
prefect work-pool create --type kubernetes \
--base-job-template updated-template.json \
your-pool-name
Or update existing work pool:
bash
prefect work-pool update --base-job-template updated-template.json your-pool-name
5. Verification Steps
After implementing these changes:
bash
# Check if the secret is properly created
kubectl get secret prefect-api-credentials -n prefect
# When a job is running, check its environment variables
kubectl exec -it <pod-name> -n prefect -- env | grep PREFECT
Could you please:
1. Confirm if you can share the job specification part of your template (the part that defines how the Kubernetes job/pod is created)?
2. Let me know if you're using any custom Kubernetes network policies?
3. Verify that the service account being used (prefect-worker-base
in your template) has permissions to read the secrets?
This will help me provide more specific guidance if needed.Daniel Soares
08/07/2025, 3:47 PMMarvin
08/07/2025, 3:47 PMMarvin
08/07/2025, 3:48 PMPREFECT_API_AUTH_STRING
instead of separate username/password variables.
1. First, create a Kubernetes secret with the auth string:
bash
kubectl create secret generic prefect-api-auth \
--namespace prefect \
--from-literal=auth_string='username:password'
2. Then modify your base job template. Here's the critical part that needs to change:
json
{
"variables": {
"type": "object",
"properties": {
"env": {
"type": "object",
"title": "Environment Variables",
"default": {
"PREFECT_API_URL": "<http://prefect-url/api>"
}
},
// ... rest of your variables ...
}
},
"job_configuration": {
"job_manifest": {
"kind": "Job",
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "prefect-job",
"image": "{{ image }}",
"imagePullPolicy": "{{ image_pull_policy }}",
"args": "{{ command }}",
"env": [
{
"name": "PREFECT_API_URL",
"value": "{{ env.PREFECT_API_URL }}"
},
{
"name": "PREFECT_API_AUTH_STRING",
"valueFrom": {
"secretKeyRef": {
"name": "prefect-api-auth",
"key": "auth_string"
}
}
}
]
}
],
"serviceAccountName": "{{ service_account_name }}"
}
}
}
}
}
}
3. Update your work pool with the new template:
bash
prefect work-pool update --base-job-template updated-template.json your-pool-name
Key points:
- Remove PREFECT_API_USERNAME
and PREFECT_API_PASSWORD
- Add PREFECT_API_AUTH_STRING
in the format "username:password"
- Make sure your PREFECT_API_URL
doesn't have the <>
brackets
To verify the configuration:
1. Check if a pod has the correct environment variables:
bash
kubectl exec -it <pod-name> -n prefect -- env | grep PREFECT
2. You should see:
PREFECT_API_URL=<http://your-prefect-url/api>
PREFECT_API_AUTH_STRING=username:password
This should resolve the 401 Unauthorized error. Let me know if you need any clarification or if you're still experiencing issues!Daniel Soares
08/07/2025, 3:53 PMMarvin
08/07/2025, 3:53 PMMarvin
08/07/2025, 3:53 PMusername:password
(no spaces, no additional characters)
2. Let's check the version of Prefect you're using:
bash
prefect version
3. Can you try to get the exact error message from the Kubernetes job logs? You can use:
bash
kubectl logs <pod-name> -n prefect
4. Also, let's verify the auth configuration on your Prefect server. The server should have:
- PREFECT_SERVER_API_AUTH_STRING
set (not PREFECT_API_AUTH_STRING
)
- The matching credentials as what you're using in the worker
Here's what I suggest trying:
1. First, verify your server configuration:
bash
# On the server
echo $PREFECT_SERVER_API_AUTH_STRING
2. Then, try setting both environment variables in your job template:
json
"env": [
{
"name": "PREFECT_API_URL",
"value": "{{ env.PREFECT_API_URL }}"
},
{
"name": "PREFECT_API_AUTH_STRING",
"valueFrom": {
"secretKeyRef": {
"name": "prefect-api-auth",
"key": "auth_string"
}
}
},
{
"name": "PREFECT_API_KEY",
"valueFrom": {
"secretKeyRef": {
"name": "prefect-api-auth",
"key": "auth_string"
}
}
}
]
3. Also, try setting these environment variables directly on a test pod to verify the authentication works:
bash
kubectl run prefect-test --image=prefecthq/prefect:2-latest -it --rm \
--env="PREFECT_API_URL=your-api-url" \
--env="PREFECT_API_AUTH_STRING=username:password" \
-- python3 -c "from prefect.client import get_client; client = get_client(); print(client.get('/hello'))"
Could you please:
1. Confirm your Prefect version
2. Share the complete error message from the job logs
3. Verify the server's auth string configuration
4. Try the test with both environment variables set as shown above
This will help us narrow down exactly where the authentication is failing.Daniel Soares
08/07/2025, 3:58 PMMarvin
08/07/2025, 3:58 PMDaniel Soares
08/07/2025, 3:58 PMMarvin
08/07/2025, 3:58 PMDaniel Soares
08/07/2025, 3:59 PMMarvin
08/07/2025, 3:59 PMDaniel Soares
08/07/2025, 3:59 PMMarvin
08/07/2025, 4:00 PMMarvin
08/07/2025, 4:00 PMbash
kubectl exec -it <pod-name> -n prefect -- env | grep PREFECT_API_AUTH_STRING
2. Verify there are no extra characters or spaces in the URL:
bash
kubectl exec -it <pod-name> -n prefect -- env | grep PREFECT_API_URL
3. Also, since you're using a custom domain (prefect.qa.gcp.radicant.com), can you confirm:
- Is the API endpoint using HTTP or HTTPS?
- Are there any proxy or ingress configurations in between?
- Can you curl the API endpoint directly from within the pod?
Try this test from within a pod:
bash
kubectl run curl-test --image=curlimages/curl -i --rm --restart=Never -- \
curl -v -H "Authorization: Basic $(echo -n 'your-username:your-password' | base64)" \
<http://prefect.qa.gcp.radicant.com/api/hello>
Please share:
1. The second part of the logs
2. The results of checking the environment variables
3. The result of the curl test
This will help us determine if it's a configuration issue or potentially a networking/proxy issue.Marvin
08/07/2025, 4:00 PM<http://...>
), which shouldn't be there
Let's fix this step by step:
1. First, let's verify the environment variables in the pod:
bash
kubectl exec -it <your-pod-name> -n prefect -- env | grep PREFECT
2. Check your server configuration. On your Prefect server, verify:
bash
echo $PREFECT_SERVER_API_AUTH_STRING
3. Update your base job template with these specific changes:
json
{
"variables": {
"type": "object",
"properties": {
"env": {
"type": "object",
"title": "Environment Variables",
"default": {
"PREFECT_API_URL": "<http://prefect.qa.gcp.radicant.com/api>" // Remove any <> brackets!
}
}
}
},
"job_configuration": {
"job_manifest": {
"kind": "Job",
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "prefect-job",
"env": [
{
"name": "PREFECT_API_URL",
"value": "<http://prefect.qa.gcp.radicant.com/api>"
},
{
"name": "PREFECT_SERVER_API_AUTH_STRING", // Add this
"valueFrom": {
"secretKeyRef": {
"name": "prefect-api-auth",
"key": "auth_string"
}
}
},
{
"name": "PREFECT_API_AUTH_STRING", // Keep this
"valueFrom": {
"secretKeyRef": {
"name": "prefect-api-auth",
"key": "auth_string"
}
}
}
]
}
]
}
}
}
}
}
}
4. Update your Kubernetes secret to ensure the auth string is properly formatted:
bash
kubectl create secret generic prefect-api-auth \
--namespace prefect \
--from-literal=auth_string='username:password' \
--dry-run=client -o yaml | kubectl apply -f -
5. Quick test to verify the authentication:
bash
# Create a test pod
kubectl run prefect-test --image=prefecthq/prefect:3-latest -it --rm \
--env="PREFECT_API_URL=<http://prefect.qa.gcp.radicant.com/api>" \
--env="PREFECT_API_AUTH_STRING=username:password" \
--env="PREFECT_SERVER_API_AUTH_STRING=username:password" \
-- python3 -c "
import asyncio
from prefect.client import get_client
async def test():
client = get_client()
try:
await client.hello()
print('Authentication successful!')
except Exception as e:
print(f'Authentication failed: {e}')
asyncio.run(test())
"
Key changes:
1. Added PREFECT_SERVER_API_AUTH_STRING
alongside PREFECT_API_AUTH_STRING
2. Removed any angle brackets from the API URL
3. Ensured the auth string is in the exact format username:password
Could you please:
1. Confirm if your API URL in the configuration actually has angle brackets (they need to be removed if present)
2. Try adding both auth string environment variables as shown above
3. Run the test pod command to verify authentication works directly
4. Share the output of kubectl exec
showing the environment variables
This will help us identify exactly where the authentication is breaking down.Marvin
08/07/2025, 4:00 PMMarvin
08/07/2025, 4:01 PMjson
{
"variables": {
"type": "object",
"properties": {
"env": {
"type": "object",
"title": "Environment Variables",
"default": {
"PREFECT_API_URL": "<http://my-prefect-url/api>" // No angle brackets!
}
}
}
}
}
2. Double-check your authentication string format. It should be exactly:
username:password
No spaces, no special characters, no angle brackets.
Could you please:
1. Run the environment variable check command I provided above
2. Try the test pod command
3. Confirm if your base job template has any angle brackets in the URL
This will help us identify exactly where the formatting issue is occurring.