Actually it's pretty easy to do using official Kubernetes Python Client. You need to do two steps:
- create a secret of type
dockerconfigjson (could be done by command line or using Python client) - you are putting here your credentials
- add this secret into your deployment / pod definition using
imagePullSecrets so Kubernetes client can pull images from private repositories
Create secret of type dockerconfigjson:
Replace <something> with your data.
Command line:
kubectl create secret docker-registry private-registry \
--docker-server=<your-registry-server> --docker-username=<your-name> \
--docker-password=<your-pword> --docker-email=<your-email>
Equivalent in Kubernetes Python Client (remember to pass in secure way variable password, for example check this):
import base64
import json
from kubernetes import client, config
config.load_kube_config()
v1 = client.CoreV1Api()
# Credentials
username = <your-name>
password = <your-pword>
mail = <your-email>
secret_name = "private-registry"
namespace = "default"
# Address of Docker repository - in case of Docker Hub just use https://index.docker.io/v1/
docker_server = <your-registry-server>
# Create auth token
auth_decoded = username + ":" + password
auth_decoded_bytes = auth_decoded.encode('ascii')
base64_auth_message_bytes = base64.b64encode(auth_decoded_bytes)
base64_auth_message = base64_auth_message_bytes.decode('ascii')
cred_payload = {
"auths": {
docker_server: {
"username": username,
"password": password,
"email": mail,
"auth": base64_auth_message
}
}
}
data = {
".dockerconfigjson": base64.b64encode(
json.dumps(cred_payload).encode()
).decode()
}
secret = client.V1Secret(
api_version="v1",
data=data,
kind="Secret",
metadata=dict(name=secret_name, namespace=namespace),
type="kubernetes.io/dockerconfigjson",
)
v1.create_namespaced_secret(namespace, body=secret)
Add this secret into your deployment / pod definition using imagePullSecrets: option
Now, let's move to using newly created secret - depends how you want to deploy pod / deployment in Python code there are two ways: apply yaml file or create pod / deployment manifest directly in the code. I will show both ways. As before, replace <something> with your data.
Example yaml file:
apiVersion: v1
kind: Pod
metadata:
name: private-registry-pod
spec:
containers:
- name: private-registry-container
image: <your-private-image>
imagePullSecrets:
- name: private-registry
In last line we are referring to secret docker-registry created in previous step.
Let's apply this yaml file using Kubernetes Python client:
from os import path
import yaml
from kubernetes import client, config
config.load_kube_config()
v1 = client.CoreV1Api()
config_yaml = "pod.yaml"
with open(path.join(path.dirname(__file__), config_yaml)) as f:
dep = yaml.safe_load(f)
resp = v1.create_namespaced_pod(body=dep, namespace="default")
print("Deployment created. status='%s'" % str(resp.status))
All in Python code - both pod definition and applying process:
from kubernetes import client, config
import time
config.load_kube_config()
v1 = client.CoreV1Api()
pod_name = "private-registry-pod"
secret_name = "private-registry"
namespace = "default"
container_name = "private-registry-container"
image = <your-private-image>
# Create a pod
print("Creating pod...")
pod_manifest= {
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": pod_name
},
"spec": {
"containers": [
{
"name": container_name,
"image": image
}
],
"imagePullSecrets": [
{
"name": secret_name
}
]
}
}
resp = v1.create_namespaced_pod(body=pod_manifest, namespace=namespace)
# Wait for a pod
while True:
resp = v1.read_namespaced_pod(name=pod_name, namespace=namespace)
if resp.status.phase != 'Pending':
break
time.sleep(1)
print("Done.")
Sources: