Build Images in Notebook
In this section, we will build and deploy container images using Kaniko from within a Jupyter notebook. This follows a GCC official implementation of Kaniko. More information on Kaniko can be found here
This functionality can be used to compile Kubernettes KSP IR Dockerfiles, like those for Kubeflow Pipelines.
Notebook¶
from kfp import dsl
from kubernetes import client, config
from kubernetes.client.rest import ApiException
import time
dockerfile_path = "/Dockerfile" # Specify
image_name = "" # Specify
namespace = "default" #Specify
def create_kaniko_pod(dockerfile_path, image_name, context_path=None):
api = client.CoreV1Api()
# Load the in-cluster configuration
config.load_incluster_config()
pod_manifest = {
"apiVersion": "v1",
"kind": "Pod",
"metadata": {"name": "kaniko"},
"spec": {
"restartPolicy": "OnFailure",
"containers": [{
"name": "kaniko",
"image": "gcr.io/kaniko-project/executor:latest",
"args": [
"--dockerfile=/workspace/Dockerfile",
"--context=dir:///workspace",
f"--destination={image_name}",
"--verbosity=trace"
],
"env": [{
"name": "GOOGLE_APPLICATION_CREDENTIALS",
"value": "/secrets/kaniko-secret.json"
}],
"volumeMounts": [
{
"name": "workspace",
"mountPath": "/workspace"
},
{
"name": "kaniko-secret",
"mountPath": "/secrets",
"readOnly": True
}
]
}],
"volumes": [
{
"name": "workspace",
"persistentVolumeClaim": {
"claimName": "kaniko-pvc"
}
},
{
"name": "kaniko-secret",
"secret": {
"secretName": "kaniko-secret",
}
}
]
}
}
try:
api.create_namespaced_pod(namespace=namespace, body=pod_manifest)
print("Kaniko build pod created.")
return api.read_namespaced_pod(name="kaniko", namespace=namespace)
except ApiException as e:
print("ERROR: API Exception: " + str(e))
return
try:
pod = create_kaniko_pod(dockerfile_path, image_name)
if not pod:
raise Exception
while True:
if pod.status.phase == 'Succeeded':
print("Build completed successfully.")
break
elif pod.status.phase in ['Failed', 'Unknown']:
print(f"Build failed with status: {pod.status.phase}")
break
else:
print(f"Current pod phase: {pod.status.phase}, waiting for completion...")
if input("Enter to update status, d to break and delete pod").upper() == 'D':
break
except ApiException as e:
print("ERROR: API Exception: " + str(e))
finally:
try:
api = client.CoreV1Api()
api.delete_namespaced_pod(name="kaniko", namespace=namespace)
print("Kaniko build pod deleted.")
except ApiException as e:
print(f"Exception when calling delete_namespaced_pod: {e}")
print("Done")
Environment¶
Configure Secrets¶
GCC Service Account Key¶
Create a .json GCC Key for your project in a GCC service account in the project that your image is going to be pushed to.
Import Secret¶
Load the .json supplied by the GCC key into the notebook. This can be done by uploading the json, or when not available, pasting the key into a txt file, and renaming it to .json.
Declare Secret¶
Because the kaniko-secret is mounted from a directory '/secrets', we create a subdirectory '/secrets' and add kaniko-secret.json to it.
kubectl create secret generic kaniko-secret --from-file=kaniko-secret.json=secrets/kaniko-secret.json
Test using:
kubectl get secret kaniko-secret
Create Persistent Volume Claim¶
Create a Yaml file called 'kaniko-pvc.yaml'. An example file is provided below
kaniko-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: kaniko-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: standard
Set build image name and location¶
Kaniko requires a place to build a cloud image to. Recommended approach uses a GCR.io bucket image location, but other options can be found of the kaniko github readme: https://github.com/GoogleContainerTools/kaniko
Dockerfile¶
Define the dockerfile to build. The default is a file 'Dockerfile' within the same directory this can be configured in the pod manifest. For other options like tarball, refer to the kaniko github readme.
Run Create Kaniko Pod¶
Run the cell to create the kaniko pod. The cell should run and terminate when the user enters 'd'. The dockerfile will be built and pushed. This enables the user to build using kaniko from within a notebook. This thus allows docker-like runs from a notebook. We should see images built and pushed to the destination.
Demo Video¶
Shown below is a brief video showcasing the steps below. Please follow the steps here if required.