Kaniko Pipelines¶
Kaniko1 is one of the recommended tools for building Docker images within Kubernetes, especially when you build them as part of a Jenkins Pipeline. I've written about why you should use Kaniko(or similar) tools, the rest assumes you want to use Kaniko within your pipeline.
Quote
Kaniko is a tool to build container images from a Dockerfile, inside a container or Kubernetes cluster.
kaniko doesn't depend on a Docker daemon and executes each command within a Dockerfile completely in userspace. This enables building container images in environments that can't easily or securely run a Docker daemon, such as a standard Kubernetes cluster.
For more examples for leveraging Kaniko when using Jenkins in Kubernetes, you can look at the documentation from CloudBees Core2.
Pipeline Example¶
Note
The Kaniko logger uses ANSI Colors, which can be represented via the Jenkins ANSI Color Plugin.
If you have the plugin installed, you can do something like the snipped below to render the colors.
pipeline {
agent {
kubernetes {
label 'kaniko'
yaml """
kind: Pod
metadata:
name: kaniko
spec:
containers:
- name: golang
image: golang:1.12
command:
- cat
tty: true
- name: kaniko
image: gcr.io/kaniko-project/executor:debug
imagePullPolicy: Always
command:
- /busybox/cat
tty: true
volumeMounts:
- name: jenkins-docker-cfg
mountPath: /kaniko/.docker
volumes:
- name: jenkins-docker-cfg
projected:
sources:
- secret:
name: registry-credentials
items:
- key: .dockerconfigjson
path: config.json
"""
}
}
stages {
stage('Checkout') {
steps {
git 'https://github.com/joostvdg/cat.git'
}
}
stage('Build') {
steps {
container('golang') {
sh './build-go-bin.sh'
}
}
}
stage('Make Image') {
environment {
PATH = "/busybox:$PATH"
REGISTRY = 'index.docker.io' // Configure your own registry
REPOSITORY = 'caladreas'
IMAGE = 'cat'
}
steps {
container(name: 'kaniko', shell: '/busybox/sh') {
sh '''#!/busybox/sh
/kaniko/executor -f `pwd`/Dockerfile.run -c `pwd` --cache=true --destination=${REGISTRY}/${REPOSITORY}/${IMAGE}
'''
}
}
}
}
}
Configuration¶
Kaniko relies on a docker secret for directly communicating to a Docker Registry. This can be supplied in various ways, but the most common is to create a Kubernetes Secret of type docker-registry
.
kubectl create secret docker-registry registry-credentials \
--docker-username=<username> \
--docker-password=<password> \
--docker-email=<email-address>
We can then mount it in the pod via Volumes
(PodSpec level) and volumeMounts
(Container level).
volumes:
- name: jenkins-docker-cfg
projected:
sources:
- secret:
name: docker-credentials
items:
- key: .dockerconfigjson
path: config.json
Azure & ACR¶
Of course, there always have to be difference between the Public Cloud Providers (AWS, Azure, Alibaba, GCP).
In the case of Kaniko, its Azure that does things differently.
Assuming you want to leverage Azure Container Registry (ACR), you're in Azure after all, you will have to do a few things differently.
Create ACR¶
You can use the Azure CLI5 or an Configuration-As-Code Tool such as Terraform6.
Azure CLI¶
First, create a resource group.
And then create the ACR.
Terraform¶
We leverage the azurerm
backend of terraform910.
resource "azurerm_resource_group" "acr" {
name = "${var.resource_group_name}-acr"
location = "${var.location}"
}
resource "azurerm_container_registry" "acr" {
name = "${var.container_registry_name}"
resource_group_name = "${azurerm_resource_group.acr.name}"
location = "${azurerm_resource_group.k8s.location}"
sku = "Premium"
admin_enabled = false
}
Configure Access to ACR¶
Now that we have an ACR, we need to be able to pull and images from and to the registry.
This requires access credentials, which we can create in several ways, we'll explore via ServicePrinciple.
Via ServicePrinciple Credentials¶
The commands below are taken from the Azure Container Registry documentation about authentication7.
First, lets setup some values that are not derived from something.
Second, we fetch the basic information about the registry we have. We need this information for the other commands.
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --query loginServer --output tsv)
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)
Now we can create a ServicePrinciple with just the rights we need8. In the case of Kaniko, we need Push and Pull rights, which are both captured in the role acrpush
.
SP_PASSWD=$(az ad sp create-for-rbac --name http://$SERVICE_PRINCIPAL_NAME --role acrpush --scopes $ACR_REGISTRY_ID --query password --output tsv)
CLIENT_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv)
kubectl create secret docker-registry registry-credentials --docker-server ${ACR_LOGIN_SERVER} --docker-username ${CLIENT_ID} --docker-password ${SP_PASSWD} --docker-email ${EMAIL}