Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to mount HostPath in each Kaniko Pod to be used as cache volume #1690

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/content/en/schemas/v1beta11.json
Expand Up @@ -1306,14 +1306,20 @@
},
"KanikoCache": {
"properties": {
"hostPath": {
"type": "string",
"description": "specifies a path on the host that is mounted to each pod as read only cache volume containing base images. If set, must exist on each node and prepopulated with kaniko-warmer.",
"x-intellij-html-description": "specifies a path on the host that is mounted to each pod as read only cache volume containing base images. If set, must exist on each node and prepopulated with kaniko-warmer."
},
"repo": {
"type": "string",
"description": "a remote repository to store cached layers. If none is specified, one will be inferred from the image name. See [Kaniko Caching](https://github.com/GoogleContainerTools/kaniko#caching).",
"x-intellij-html-description": "a remote repository to store cached layers. If none is specified, one will be inferred from the image name. See <a href=\"https://github.com/GoogleContainerTools/kaniko#caching\">Kaniko Caching</a>."
}
},
"preferredOrder": [
"repo"
"repo",
"hostPath"
],
"additionalProperties": false,
"description": "configures Kaniko caching. If a cache is specified, Kaniko will use a remote cache which will speed up builds.",
Expand Down
2 changes: 1 addition & 1 deletion pkg/skaffold/build/build.go
Expand Up @@ -31,7 +31,7 @@ type Artifact struct {
}

// Builder is an interface to the Build API of Skaffold.
// It must build and make the resulting image accesible to the cluster.
// It must build and make the resulting image accessible to the cluster.
// This could include pushing to a authorized repository or loading the nodes with the image.
// If artifacts is supplied, the builder should only rebuild those artifacts.
type Builder interface {
Expand Down
4 changes: 4 additions & 0 deletions pkg/skaffold/build/cluster/kaniko.go
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/cache"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/cluster/sources"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
Expand Down Expand Up @@ -111,6 +112,9 @@ func appendCacheIfExists(args []string, cache *latest.KanikoCache) []string {
if cache.Repo != "" {
args = append(args, fmt.Sprintf("--cache-repo=%s", cache.Repo))
}
if cache.HostPath != "" {
args = append(args, fmt.Sprintf("--cache-dir=%s", constants.DefaultKanikoDockerConfigPath))
}
return args
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/skaffold/build/cluster/sources/gcs.go
Expand Up @@ -61,7 +61,7 @@ func (g *GCSBucket) Setup(ctx context.Context, out io.Writer, artifact *latest.A

// Pod returns the pod template for this builder
func (g *GCSBucket) Pod(args []string) *v1.Pod {
return podTemplate(g.clusterDetails, g.artifact.Image, args)
return podTemplate(g.clusterDetails, g.artifact, args)
}

// ModifyPod does nothing here, since we just need to let kaniko run to completion
Expand Down
2 changes: 1 addition & 1 deletion pkg/skaffold/build/cluster/sources/localdir.go
Expand Up @@ -85,7 +85,7 @@ func (g *LocalDir) Pod(args []string) *v1.Pod {
VolumeMounts: []v1.VolumeMount{vm},
}

p := podTemplate(g.clusterDetails, g.artifact.Image, args)
p := podTemplate(g.clusterDetails, g.artifact, args)
p.Spec.InitContainers = []v1.Container{ic}
p.Spec.Containers[0].VolumeMounts = append(p.Spec.Containers[0].VolumeMounts, vm)
p.Spec.Volumes = append(p.Spec.Volumes, v)
Expand Down
23 changes: 21 additions & 2 deletions pkg/skaffold/build/cluster/sources/sources.go
Expand Up @@ -51,7 +51,7 @@ func Retrieve(clusterDetails *latest.ClusterDetails, artifact *latest.KanikoArti
}
}

func podTemplate(clusterDetails *latest.ClusterDetails, image string, args []string) *v1.Pod {
func podTemplate(clusterDetails *latest.ClusterDetails, artifact *latest.KanikoArtifact, args []string) *v1.Pod {
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "kaniko-",
Expand All @@ -62,7 +62,7 @@ func podTemplate(clusterDetails *latest.ClusterDetails, image string, args []str
Containers: []v1.Container{
{
Name: constants.DefaultKanikoContainerName,
Image: image,
Image: artifact.Image,
Args: args,
ImagePullPolicy: v1.PullIfNotPresent,
Env: []v1.EnvVar{{
Expand Down Expand Up @@ -91,6 +91,25 @@ func podTemplate(clusterDetails *latest.ClusterDetails, image string, args []str
},
}

if artifact.Cache != nil && artifact.Cache.HostPath != "" {
volumeMount := v1.VolumeMount{
Name: constants.DefaultKanikoCacheDirName,
MountPath: constants.DefaultKanikoCacheDirMountPath,
}

pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, volumeMount)

volume := v1.Volume{
Name: constants.DefaultKanikoCacheDirName,
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{
Path: artifact.Cache.HostPath,
},
},
}
pod.Spec.Volumes = append(pod.Spec.Volumes, volume)
}

if clusterDetails.DockerConfig == nil {
return pod
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/skaffold/build/cluster/sources/sources_test.go
Expand Up @@ -196,7 +196,7 @@ func TestPodTemplate(t *testing.T) {

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
actual := podTemplate(test.initial, test.image, test.args)
actual := podTemplate(test.initial, &latest.KanikoArtifact{Image: test.image, Cache: &latest.KanikoCache{}}, test.args)
testutil.CheckDeepEqual(t, test.expected, actual, opt)
})
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/skaffold/constants/constants.go
Expand Up @@ -46,6 +46,8 @@ const (
DefaultKanikoContainerName = "kaniko"
DefaultKanikoEmptyDirName = "kaniko-emptydir"
DefaultKanikoEmptyDirMountPath = "/kaniko/buildcontext"
DefaultKanikoCacheDirName = "kaniko-cache"
DefaultKanikoCacheDirMountPath = "/cache"
DefaultKanikoDockerConfigSecretName = "docker-cfg"
DefaultKanikoDockerConfigPath = "/kaniko/.docker"

Expand Down
3 changes: 3 additions & 0 deletions pkg/skaffold/schema/latest/config.go
Expand Up @@ -219,6 +219,9 @@ type KanikoCache struct {
// Repo is a remote repository to store cached layers. If none is specified, one will be
// inferred from the image name. See [Kaniko Caching](https://github.com/GoogleContainerTools/kaniko#caching).
Repo string `yaml:"repo,omitempty"`
// HostPath specifies a path on the host that is mounted to each pod as read only cache volume containing base images.
// If set, must exist on each node and prepopulated with kaniko-warmer.
HostPath string `yaml:"hostPath,omitempty"`
}

// ClusterDetails *beta* describes how to do an on-cluster build.
Expand Down