agola-io / agola

Agola: CI/CD Redefined

Home Page:https://agola.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use 2 and more containers for commands (steps)

kvaster opened this issue · comments

Currrently Agola uses only one container to run commands (steps) - the first one.

This container is also used for 'clone' step. This is uncomfortable, cause images you need usually are without 'git' command and you need to create separate pod and save cloned repository to workspace - wasting resources.

My proposition is to use separate container for 'clone' step - this will make guarantees that clone will not fail.

And we can go further - we may allow N containers for running commands. My proposition is to

  • Add names to containers in order to be able to reference them. Container is treated to be runnable if either it is first or it have name. Such approach will not break current functionality.
  • Add container reference to 'run' and 'clone' steps.
  • Use first container for 'run' step if it has no container reference.
  • Use 'clone' container by default for 'clone' step.
  • Use 'alpine-git' as default 'clone' container if there is no explicitly defined 'clone' container.

I've made PR for this: #355

@sgotti, I would appreciate if you will have time to take a look. Thanks!

@kvaster Thanks.

you need to create separate pod and save cloned repository to workspace - wasting resources.

This is true only if you have a single task. If you have multiple tasks (like a build matrix) it'll be better to clone one time only, save to workspace and restore in the other tasks.

So to summarize and to split it in multiple parts:

  • Add ability to have multiple "steps" container and reference them in the step definition. If no container is referenced in the step then the primary one is used.

There're multiple issues to face:

  • It'll require having a shared volume between "step containers". Where will this shared volume should be mounted? There're some things to consider:
    • Currently we can define a working dir (defaulting to ~/project if not defined) in different places (task, run step). The working dir is then expanded by the executor at the step execution time to resolve possible ~ (using toolbox expanddir) . So the working dir full path depends on the current step user. We cannot assume it'll be root since it could be defined in different places (container, task)
    • The working dir is created by the executor using the task user and the task working dir (using toolbox mkdir)
    • So we cannot by default choose a "shared dir" related to the working dir also if it's the current default (~/project) since it's not fixed but depends by multiple variables.
    • For the same reason, since we have to mount volume at the container creation time we cannot know the working_dir at that time.
  • We cannot assume the step executing user will be root.
  • Now the executor determines the step user by looking at the task user (username or uid), then the container user (username or uid) or it'll be passed as empty to the executor that will use the image default user. If we have multiple "step" container we should explicitly document that we are using the primary step container user and that it must exist on all step containers and have the same uid

Possible solution:

  • For single "step" container configs do nothing (to not impact existing configs).

  • For multiple "step" container configs:

    • Change the default working_dir to a fixed full path (like /opt/project).
    • Add an option to define the task shared volume mount path with a default as the default working_dir (like /opt/project).
    • The executor will create a volume and tell the executor driver to mount it to the shared volume path in all the "step" containers.
    • One thing to check is which permission the volume will have (may depend on executor type) and make possible that it'll be accessible by the task user (we could probably need to find a way to chown the mounted dir to the task user of the primary container)
  • Add a lot of tests to check all the possible cases.

  • Use 'clone' container by default for 'clone' step.
  • Use 'alpine-git' as default 'clone' container if there is no explicitly defined 'clone' container.

I'll avoid adding a default definition of a "clone" container and making it the default for the clone step since it'll break current configs (a user can have its custom image with its binaries and this will change it)

Thanks. I'll try to prepare changes.