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

Add experimental volumes and volumeMounts properties to jobs #966

Merged
merged 6 commits into from
Aug 8, 2019

Conversation

radu-matei
Copy link
Contributor

@radu-matei radu-matei commented Aug 4, 2019

depends on brigadecore/brigadier#22

This PR enables experimental support for adding volumes and volume mounts to jobs.

Note that for the simple use case of sharing a volume across all jobs, storage.enabled should still be used.

A pre-built image for the worker: radumatei/brigade-worker:volume-mounts-check.

cc @krancour - this is a very Kubernetes-specific addition - how would this impact non-Kubernetes targets?

Use cases: #955 (comment) and Mounting volumes for ETL jobs

Example:

    const kind = new Job("kind", "radumatei/golang-kind:1.11-0.4")
    kind.privileged = true;
    kind.volumes = [
        {
            name: "modules",
            hostPath: {
                path: "/lib/modules",
                type: "Directory"
            }
        },
        {
            name: "cgroup",
            hostPath: {
                path: "/sys/fs/cgroup",
                type: "Directory"
            }
        },
        {
            name: "docker-graph-storage",
            emptyDir: {}
        }
    ];

    kind.volumeMounts = [
        {
            name: "modules",
            mountPath: "/lib/modules",
            readOnly: true
        },
        {
            name: "cgroup",
            mountPath: "/sys/fs/cgroup"
        },
        {
            name: "docker-graph-storage",
            mountPath: "/var/lib/docker"
        }
    ];

if (cfg.volume.hostPath != undefined && !project.allowHostMounts) {
throw new Error(`allowHostMounts is false in this project, not mounting path ${cfg.volume.hostPath.path}`)
}
this.runner.spec.volumes.push(cfg.volume);
Copy link
Contributor Author

@radu-matei radu-matei Aug 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any scenario where you would need to mount the same volume twice in a single job pod?

The only scenario I can think of is mounting to different paths, although it doesn't seem to be that common - see kubernetes/kubernetes#34453.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have never got to do it myself. But I see some use with subpath, as mentioned in the issue.

Just curious, but does whether to support mounting the same volume multiple times affect our design/implementation? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I got it! You've paired a volume and its corresponding mount in each volumeConfig.

I'd rather suggest exposing volumes and volumeMounts without any abstraction first, so that we can provide a standard library feature like this volumeConfig on top of that, or users can build their own.

IMHO for the standard library, something that solves 80% of the use-cases will be enough, that justifies dropping support for mounting the same volume multiple times.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading radu-matei/brigadier@94f56c2 - If you agree, implementation-wise, I think adding volumeMounts and volumes that are allowed/used only when volumeConfig doesn't exist would suffice.

Copy link
Contributor Author

@radu-matei radu-matei Aug 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That totally makes sense - I initially thought maybe we could simplify and boil things down to a single property, but yeah, you're right, we should keep in line with the Kubernetes abstraction.

Updating.

Copy link
Contributor

@mumoshu mumoshu Aug 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I like the idea of pairing volumes and mounts.

I even think we can happily merge the volume and the mount as in many cases each volume is mounted only once:

job.volumeConfig = [
    {
        name: "modules",
        mountPath: "/lib/modules",
        readOnly: true,
        hostPath: {
            path: "/lib/modules",
            type: "Directory"
        }
    },

    {
        name: "cgroup",
        mountPath: "/sys/fs/cgroup",
        hostPath: {
            path: "/sys/fs/cgroup",
            type: "Directory"
        }
    },
    {
        name: "docker-graph-storage",
        mountPath: "/var/lib/docker",
        emptyDir: {}
    }
]

And I believe names can be usually omitted because they can be generated from mount-path(which are guaranteed to not collide:

job.volumeConfig = [
    {
//        name: "lib-modules",
        mountPath: "/lib/modules",
        readOnly: true,
        hostPath: {
            path: "/lib/modules",
            type: "Directory"
        }
    },

    {
//        name: "sys-fs-cgroup",
        mountPath: "/sys/fs/cgroup",
        hostPath: {
            path: "/sys/fs/cgroup",
            type: "Directory"
        }
    },
    {
//        name: "var-lib-docker",
        mountPath: "/var/lib/docker",
        emptyDir: {}
    }
]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't think we should keep both volume + volumeMounts and volumeConfig, as it just invites confusion - what do you think?

So I'd vote for starting with only volumes + volumeMounts if I need to choose one.

// But I do believe something like volumeConfig has a lot of potential, and worth it, even if it needs an extensive documentation to not confuse users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I initially thought that something like volumeConfig could be an abstraction over how volumes and volume mounts work in Kubernetes and simplify setting them up for a job.

But I agree, let's start with plain volumes and volumeMounts, then decide whether to add a higher level abstraction, how you suggested.

Thanks a lot, this has been really helpful!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brigadier change: brigadecore/brigadier@8c53a1c

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated - could you please give this another look?
Thanks!

@netlify
Copy link

netlify bot commented Aug 4, 2019

Deploy preview for brigade-docs ready!

Built with commit ef8e1a7

https://deploy-preview-966--brigade-docs.netlify.com

@@ -38,7 +38,7 @@
"typescript": "^3.2.2"
},
"dependencies": {
"@brigadecore/brigadier": "^0.5.0",
"@brigadecore/brigadier": "radu-matei/brigadier#job-volume-config-out",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After brigadecore/brigadier#22 is merged and a new version is published, update this.

@radu-matei radu-matei changed the title Add experimental volumeConfig property to jobs Add experimental volumes and volumeMounts properties to jobs Aug 5, 2019
@radu-matei radu-matei marked this pull request as ready for review August 5, 2019 13:02
@radu-matei radu-matei added this to the 1.2 milestone Aug 5, 2019
Copy link
Contributor

@vdice vdice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had one question as well as the request to add an example around a basic configuration somewhere in the docs. Otherwise, looks great!

}

// If the job defines volume mounts, add them to every container's spec.
for (let m of job.volumeMounts) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since volumeMounts and volumes appear to be un-coupled, should we add the same check here to be sure project.allowHostMounts is true?

And/or, in general, should we somehow check for proper API usage? (If, say, configured with a volumeMount setup but no corresponding volume defined, etc. -- or is that allowed?) I suppose as long as we can show the user the k8s library error that should result on mis-configuration, we'd be good.

Copy link
Contributor Author

@radu-matei radu-matei Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you need to declare both volume and volume mount, I think checking is unnecessary - it would end up just taking the volume mount name and iterating through the volumes to check if it's mounting a host path - which already do for all volumes.

As for checking the existence of the volume you reference in the volume mount, that is a good idea, I'll add that.

These two checks should cover both of your questions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a check for the referenced volume, together with a test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed radumatei/brigade-worker:volume-mounts-check if you need to try it on a project.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love the extra validation with volumeExists because that provides us a faster feedback loop 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thanks Radu!

Copy link
Contributor

@mumoshu mumoshu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
I believe we can merge this once brigadecore/brigadier#22 gets merged/published.

@radu-matei
Copy link
Contributor Author

Merged brigadecore/brigadier#22, rebasing, updating, and adding a doc.

@krancour
Copy link
Contributor

krancour commented Aug 7, 2019

cc @krancour - this is a very Kubernetes-specific addition - how would this impact non-Kubernetes targets?

Do we imagine being able to one day orchestrate job containers using something other than Kubernetes? It wasn't on my radar, but even if the answer were yes, I think this could be accommodated with other orchestrators.

@radu-matei
Copy link
Contributor Author

Rebased and added a simple doc.

@krancour - not really, or at least not the JS worker anyway. Just trying to make sure we're not overlooking something that might be affected by this - thanks!

@radu-matei radu-matei merged commit 8525067 into brigadecore:master Aug 8, 2019
@radu-matei
Copy link
Contributor Author

Thanks a lot for the help, everyone!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants