Skip to content

compose app images dumping and preloading#71

Merged
mike-sul merged 1 commit intomasterfrom
image-preloading
Jul 23, 2020
Merged

compose app images dumping and preloading#71
mike-sul merged 1 commit intomasterfrom
image-preloading

Conversation

@mike-sul
Copy link
Copy Markdown
Contributor

  • dump all container images of each app into a tar file, format
    dockerd:overlay2;
  • load the dumped images into var/lib/docker during LmP build.

Signed-off-by: Mike Sul [email protected]

Copy link
Copy Markdown
Member

@doanac doanac left a comment

Choose a reason for hiding this comment

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

pretty clever way of doing this. nothing major i see.

archs.append(platform.split('/')[1])

with tempfile.TemporaryDirectory() as tmp_dst_dir:
dump_app_images(os.path.abspath(os.getcwd()), archs, tmp_dst_dir)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i think you can replace os.path.abspath(os.getcwd()) with the cur_work_dir you've added on line 146

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

line #148 can change a cur dir, so we have to get it once more here. cur_work_dir is needed here to make sure that execution environment comes back to the original cur work dir. But, all that stuff can be removed, I basically need it for unit & manual testing, it allows me running this script from ci-scripts directory and points it to my factory's containers dir.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this all kind of makes sense. the code might be a little less complex if this test-env specific logic was moved into the the main section, but I'm not sure. this is tested, so i'd say leave it.

Comment thread factory-containers/publish-compose-apps
Comment thread lmp/preload-app-images
target_name = list(target_json.keys())[0]
logging.info('Preloading app images for ' + target_name)
sha = target_json[target_name]['custom']['containers-sha']
image_data_dir = os.path.join('/var/cache/bitbake/app-images/', sha)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess this directory will grow over time. I've added a note in Jira about this so we remember to attempt to prune old data eventually: https://foundriesio.atlassian.net/jira/software/projects/FF/boards/13?selectedIssue=FF-11

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we might be able to reason about what to delete by looking at targets.json and understanding that no new LMP builds would use an existing tarball, so it could be safe to delete. then we'd basically always keep the minimal amout of tarballs around. but that can be added further down the road

Copy link
Copy Markdown
Contributor Author

@mike-sul mike-sul Jul 17, 2020

Choose a reason for hiding this comment

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

I consider it as a temporal solution, putting image data is simple and straightforward and good for a start, but it has many drawbacks.

  • First of all, it requires the container and lmp builds to have access to the same NFS volume;
  • secondary, this storage has size limits and is not redundant and so reliable as GCS or S3;
  • Once we move towards using ostree as a storage for container images we will have to store images somewhere on the cloud (most likely Treehub backed by S3 for the beginning) so devices have access to it.

shutil.rmtree(self._container_dir)


class DockerDaemon:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we already have dockerd running when this code gets hit. Do you need your own instance to make sure you have a pristine environment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, there are a few reasons for that (the one you mentioned is valid too):

  1. a host environment executing the given may have or may not have dockerd running. The given approach makes the implementation less vulnerable/sensitive to a host env, so it can work on a local host, VM or any other container as long as dockerd is installed;

  2. The host dockerd's data root (/var/lib/docker/) can be polluted by data of some other images while we need data/files that belongs solely to the target app images;

  3. Using --platform option requires running dockerd in the experimental mode. "--platform" is only supported on a Docker daemon with experimental features enabled. This option is required because we want to dump images of other than a host architecture (dumping arm64's images on amd64 host).

  4. It allows dumpling images of all target architectures concurrently, multiple instances of DockerDaemon can be running concurrently without interfering each other what can speed up an overall process. Not implemented yet though :)

def pull(self, platform, url):
cmd = self._get_cmd(platform, url)
logger.info('Fetching image: {}'.format(cmd))
subprocess.run(cmd.split(), check=True, stdout=None, stderr=None, env=self._env)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

think you need to check the return value of subprocess.run or do a subprocess.check_call which will raise an error if it fails

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think check=True param makes it raise an exception if the command/process fails. Anyway, I see that I need to improve the implementation in terms of exception handling, I think I should catch exception within the given module. Thanks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added (forced push) exception handling in the main.

logger.info('Copying image {} to {}'.format(service_cfg['image'], dst_dir))
downloader.pull(arch, service_cfg['image'])

yield download_app
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

slick use of chaining together some context managers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@doanac foundriesio/meta-lmp#195 has been merged, so I suppose we should merge this PR too.

@ricardosalveti
Copy link
Copy Markdown
Member

Please add a license/copyright to the new files (not every file got one, something we should fix, but we can get the new ones right).

e.g.:

# Copyright (c) 2020 Foundries.io
# SPDX-License-Identifier: Apache-2.0

def __init__(self, dst_dir: str, containerd_addr: str):
self.data_root = dst_dir
self._containerd_addr = containerd_addr
#self.cmd = '/home/mike/bin/dockerd-rootless.sh'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please remove this line if not really required.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just some minor comments, but LGTM, will let @doanac do the final +1 here.

Updated (forced push) according to the comments.

@ricardosalveti
Copy link
Copy Markdown
Member

Just some minor comments, but LGTM, will let @doanac do the final +1 here.

@mike-sul mike-sul force-pushed the image-preloading branch 2 times, most recently from 7423eb4 to 28b4f3d Compare July 22, 2020 18:44
Comment thread lmp/preload-app-images Outdated
image_data_dir = os.path.join('/var/cache/bitbake/app-images/', sha)

arch_map = {'aarch64': 'arm64', 'x86_64': 'amd64', 'arm': 'arm'}
image_data_tar = os.path.join(image_data_dir, '{}-{}.tar'.format(sha[:7], arch_map[arch]))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just noticed this - sha[:7] isn't actually always the case:
8edbdad

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Are you implying to use a full hash/sha value? BTW, we use it in other places, e.g.

svc['image'] = img + ':' + tag
(tag is 7 symbol hash).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not the full hash but tag needs to be computed correctly. In the example you shared its actually getting that from the TAG environment variable set in docker-app-publish.sh which uses git log -1 --format=%h. Basically what I'm saying is 99% of the time the short-hash (TAG) is 7 characters. However, we occasionally have exceptions, so you have to use git log -1 --format=%h to ensure you get the correct tag.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

understood. In this case, I should think of something else as the given script is called during lmp build while 'sha' is a sha of corresponding containers repo commit so running git log -1 --format=%h will yield an abbreviated hash of the current lmp commit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

updated

- dump all container images of each app into a tar file, format
dockerd:overlay2;
- load the dumped images into var/lib/docker during LmP build.

Signed-off-by: Mike Sul <[email protected]>
@mike-sul mike-sul merged commit bdcd973 into master Jul 23, 2020
@mike-sul mike-sul deleted the image-preloading branch July 23, 2020 15:11
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.

3 participants