Kubernetes
Python
API
create_namespaced_secret
Kubernetes Python client

Using create_namespaced_secret API in Kubernetes Python client

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Creating a Kubernetes Secret from Python is straightforward once you understand the shape of the API object and the difference between data and string_data. The create_namespaced_secret call writes a Secret into one namespace, so you need the correct client configuration, namespace, and RBAC permissions. The safest approach is to build a V1Secret explicitly and let the Kubernetes API validate the object.

Load Configuration and Create the API Client

The Kubernetes Python client can run either from your workstation or from inside a cluster.

Local config example:

python
1from kubernetes import client, config
2
3config.load_kube_config()
4api = client.CoreV1Api()

In-cluster example:

python
1from kubernetes import client, config
2
3config.load_incluster_config()
4api = client.CoreV1Api()

Use load_kube_config() for scripts and local tooling, and load_incluster_config() when your Python code runs inside Kubernetes itself.

Build a Secret Object Correctly

The cleanest way to create a Secret is to use client.V1Secret.

You can provide raw strings with string_data and let the API server encode them.

python
1from kubernetes import client
2
3secret = client.V1Secret(
4    api_version="v1",
5    kind="Secret",
6    metadata=client.V1ObjectMeta(name="db-credentials"),
7    type="Opaque",
8    string_data={
9        "username": "app_user",
10        "password": "s3cr3t"
11    }
12)

This is easier and safer than manually base64-encoding the values yourself.

Create the Secret in a Namespace

Once the object is prepared, call create_namespaced_secret.

python
1from kubernetes import client, config
2
3config.load_kube_config()
4api = client.CoreV1Api()
5
6secret = client.V1Secret(
7    api_version="v1",
8    kind="Secret",
9    metadata=client.V1ObjectMeta(name="db-credentials"),
10    type="Opaque",
11    string_data={
12        "username": "app_user",
13        "password": "s3cr3t"
14    }
15)
16
17created = api.create_namespaced_secret(
18    namespace="app-dev",
19    body=secret
20)
21
22print(created.metadata.name)

This creates the secret only in app-dev. Secrets are namespace-scoped, so a pod in another namespace cannot use it unless you create a separate copy there.

data Versus string_data

This distinction causes many first-time mistakes.

Use string_data when:

  • you have normal Python strings
  • you want Kubernetes to handle base64 encoding

Use data when:

  • you already have base64-encoded values
  • you are reproducing an exact manifest format

Manual data example:

python
1import base64
2from kubernetes import client
3
4secret = client.V1Secret(
5    api_version="v1",
6    kind="Secret",
7    metadata=client.V1ObjectMeta(name="api-key"),
8    type="Opaque",
9    data={
10        "token": base64.b64encode(b"my-token").decode("ascii")
11    }
12)

If you use data, the values must already be base64-encoded strings.

Handle Existing Secrets Safely

create_namespaced_secret fails if the secret already exists. If your workflow is idempotent, catch that case and patch or replace instead.

python
1from kubernetes import client, config
2from kubernetes.client.rest import ApiException
3
4config.load_kube_config()
5api = client.CoreV1Api()
6
7try:
8    api.create_namespaced_secret(namespace="app-dev", body=secret)
9except ApiException as e:
10    if e.status == 409:
11        print("Secret already exists")
12    else:
13        raise

For update flows, use replace_namespaced_secret or patch the secret instead of calling create repeatedly.

Verify the Secret

After creation, read it back to confirm metadata and keys.

python
stored = api.read_namespaced_secret(name="db-credentials", namespace="app-dev")
print(stored.metadata.name)
print(list(stored.data.keys()))

Remember that stored.data contains base64-encoded values, because that is how the API represents secret data when reading it back.

RBAC and Operational Concerns

Secret creation is permission-sensitive. Your service account or user must have the right verbs on the secrets resource in the target namespace.

Minimal RBAC concept:

  • 'get'
  • 'create'
  • optionally update or patch

Also remember:

  • secrets are only base64-encoded, not encrypted by default in the client response
  • avoid printing secret values in logs
  • prefer external secret managers when the environment requires stronger secret lifecycle controls

The API call is simple, but secret handling policy is not.

Common Pitfalls

One common mistake is manually base64-encoding values and then putting them into string_data. That causes double-encoding semantics and incorrect stored values.

Another mistake is creating the secret in the wrong namespace and then wondering why the pod cannot mount or reference it.

Developers also log the full secret object while debugging, which can leak credentials into build logs or monitoring systems.

Finally, repeated create calls without conflict handling make automation brittle. If the script may run twice, decide whether the correct behavior is fail, patch, or replace.

Summary

  • Use create_namespaced_secret with a V1Secret object for explicit, readable secret creation.
  • Prefer string_data when you have normal strings and want Kubernetes to encode them.
  • Secrets are namespace-scoped, so choose the target namespace carefully.
  • Handle 409 Conflict if your workflow may attempt to create an existing secret.
  • Treat secret creation as a security-sensitive operation, not just another CRUD call.

Course illustration
Course illustration

All Rights Reserved.