Merge pull request #4866 from zhsj/doc-fix

Update BUILDING.md after moving to Go modules and various other small docs update
This commit is contained in:
Phil Estes 2020-12-23 08:23:24 -05:00 committed by GitHub
commit 178e9a1012
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 59 additions and 60 deletions

View File

@ -22,12 +22,12 @@ To build the `containerd` daemon, and the `ctr` simple test client, the followin
First you need to setup your Go development environment. You can follow this First you need to setup your Go development environment. You can follow this
guideline [How to write go code](https://golang.org/doc/code.html) and at the guideline [How to write go code](https://golang.org/doc/code.html) and at the
end you need to have `GOPATH` and `GOROOT` set in your environment. end you have `go` command in your `PATH`.
At this point you can use `go` to checkout `containerd` in your `GOPATH`: You need `git` to checkout the source code:
```sh ```sh
go get github.com/containerd/containerd git clone https://github.com/containerd/containerd
``` ```
For proper results, install the `protoc` release into `/usr/local` on your build system. For example, the following commands will download and install the 3.11.4 release for a 64-bit Linux host: For proper results, install the `protoc` release into `/usr/local` on your build system. For example, the following commands will download and install the 3.11.4 release for a 64-bit Linux host:
@ -41,9 +41,8 @@ $ sudo unzip protoc-3.11.4-linux-x86_64.zip -d /usr/local
need to satisfy these dependencies in your system: need to satisfy these dependencies in your system:
* CentOS/Fedora: `yum install btrfs-progs-devel` * CentOS/Fedora: `yum install btrfs-progs-devel`
* Debian/Ubuntu: `apt-get install btrfs-tools` * Debian/Ubuntu: `apt-get install btrfs-progs libbtrfs-dev`
* Debian Buster/Ubuntu 19.10/ Ubuntu 20.04: * Debian(before Buster)/Ubuntu(before 19.10): `apt-get install btrfs-tools`
`apt-get install btrfs-progs libbtrfs-dev`
At this point you are ready to build `containerd` yourself! At this point you are ready to build `containerd` yourself!
@ -63,19 +62,15 @@ correct version of `runc` installed.
For the quick and dirty installation, you can use the following: For the quick and dirty installation, you can use the following:
go get github.com/opencontainers/runc ```
git clone https://github.com/opencontainers/runc
This is not recommended, as the generated binary will not have version cd runc
information. Instead, cd into the source directory and use make to build and
install the binary:
cd $GOPATH/src/github.com/opencontainers/runc
make make
make install sudo make install
```
Make sure to follow the guidelines for versioning in [RUNC.md](RUNC.md) for the Make sure to follow the guidelines for versioning in [RUNC.md](RUNC.md) for the
best results. Some pointers on proper build tag setupVersion mismatches can best results.
result in undefined behavior.
## Build containerd ## Build containerd
@ -83,7 +78,7 @@ result in undefined behavior.
can run: can run:
``` ```
cd $GOPATH/src/github.com/containerd/containerd cd containerd
make make
``` ```
@ -111,7 +106,10 @@ make generate
> For example, adding `BUILDTAGS=no_btrfs` to your environment before calling the **binaries** > For example, adding `BUILDTAGS=no_btrfs` to your environment before calling the **binaries**
> Makefile target will disable the btrfs driver within the containerd Go build. > Makefile target will disable the btrfs driver within the containerd Go build.
Vendoring of external imports uses the [`vndr` tool](https://github.com/LK4D4/vndr) which uses a simple config file, `vendor.conf`, to provide the URL and version or hash details for each vendored import. After modifying `vendor.conf` run the `vndr` tool to update the `vendor/` directory contents. Combining the `vendor.conf` update with the changeset in `vendor/` after running `vndr` should become a single commit for a PR which relies on vendored updates. Vendoring of external imports uses the [Go Modules](https://golang.org/ref/mod#vendoring). You need
to use `go mod` command to modify the dependencies. After modifition, you should run `go mod tidy`
and `go mod vendor` to ensure the `go.mod`, `go.sum` files and `vendor` directory are up to date.
Changes to these files should become a single commit for a PR which relies on vendored updates.
Please refer to [RUNC.md](/RUNC.md) for the currently supported version of `runc` that is used by containerd. Please refer to [RUNC.md](/RUNC.md) for the currently supported version of `runc` that is used by containerd.
@ -131,6 +129,8 @@ make EXTRA_FLAGS="-buildmode pie" \
# Via Docker container # Via Docker container
The following instructions assume you are at the parent directory of containerd source directory.
## Build containerd ## Build containerd
You can build `containerd` via a Linux-based Docker container. You can build `containerd` via a Linux-based Docker container.
@ -148,7 +148,7 @@ containerd source root directory you can run the following command:
```sh ```sh
docker run -it \ docker run -it \
-v ${PWD}:/go/src/github.com/containerd/containerd \ -v ${PWD}/containerd:/go/src/github.com/containerd/containerd \
-e GOPATH=/go \ -e GOPATH=/go \
-w /go/src/github.com/containerd/containerd containerd/build sh -w /go/src/github.com/containerd/containerd containerd/build sh
``` ```
@ -164,10 +164,10 @@ You are now ready to [build](#build-containerd):
## Build containerd and runc ## Build containerd and runc
To have complete core container runtime, you will need both `containerd` and `runc`. It is possible to build both of these via Docker container. To have complete core container runtime, you will need both `containerd` and `runc`. It is possible to build both of these via Docker container.
You can use `go` to checkout `runc` in your `GOPATH`: You can use `git` to checkout `runc`:
```sh ```sh
go get github.com/opencontainers/runc git clone https://github.com/opencontainers/runc
``` ```
We can build an image from this `Dockerfile`: We can build an image from this `Dockerfile`:
@ -187,8 +187,8 @@ Let's suppose you build an image called `containerd/build` from the above Docker
```sh ```sh
docker run -it --privileged \ docker run -it --privileged \
-v /var/lib/containerd \ -v /var/lib/containerd \
-v ${GOPATH}/src/github.com/opencontainers/runc:/go/src/github.com/opencontainers/runc \ -v ${PWD}/runc:/go/src/github.com/opencontainers/runc \
-v ${GOPATH}/src/github.com/containerd/containerd:/go/src/github.com/containerd/containerd \ -v ${PWD}/containerd:/go/src/github.com/containerd/containerd \
-e GOPATH=/go \ -e GOPATH=/go \
-w /go/src/github.com/containerd/containerd containerd/build sh -w /go/src/github.com/containerd/containerd containerd/build sh
``` ```

View File

@ -227,7 +227,7 @@ man: mandir $(addprefix man/,$(MANPAGES))
mandir: mandir:
@mkdir -p man @mkdir -p man
# Kept for backwards compatability # Kept for backwards compatibility
genman: man/containerd.8 man/ctr.8 genman: man/containerd.8 man/ctr.8
man/containerd.8: FORCE man/containerd.8: FORCE

View File

@ -2,7 +2,6 @@
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/containerd)](https://pkg.go.dev/github.com/containerd/containerd) [![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/containerd)](https://pkg.go.dev/github.com/containerd/containerd)
[![Build Status](https://github.com/containerd/containerd/workflows/CI/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ACI) [![Build Status](https://github.com/containerd/containerd/workflows/CI/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ACI)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/containerd/containerd?branch=master&svg=true)](https://ci.appveyor.com/project/mlaventure/containerd-3g73f?branch=master)
[![Nightlies](https://github.com/containerd/containerd/workflows/Nightly/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ANightly) [![Nightlies](https://github.com/containerd/containerd/workflows/Nightly/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ANightly)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd?ref=badge_shield) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd?ref=badge_shield)
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/containerd)](https://goreportcard.com/report/github.com/containerd/containerd) [![Go Report Card](https://goreportcard.com/badge/github.com/containerd/containerd)](https://goreportcard.com/report/github.com/containerd/containerd)
@ -249,6 +248,16 @@ the autocomplete/ctr file in your `.bashrc`, or manually like:
$ source ./contrib/autocomplete/ctr $ source ./contrib/autocomplete/ctr
``` ```
#### Distribution of `ctr` autocomplete for bash and zsh
For bash, copy the `contrib/autocomplete/ctr` script into
`/etc/bash_completion.d/` and rename it to `ctr`. The `zsh_autocomplete`
file is also available and can be used similarly for zsh users.
Provide documentation to users to `source` this file into their shell if
you don't place the autocomplete file in a location where it is automatically
loaded for the user's shell environment.
### CRI ### CRI
`cri` is a [containerd](https://containerd.io/) plugin implementation of the Kubernetes [container runtime interface (CRI)](https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1alpha2/api.proto). With it, you are able to use containerd as the container runtime for a Kubernetes cluster. `cri` is a [containerd](https://containerd.io/) plugin implementation of the Kubernetes [container runtime interface (CRI)](https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1alpha2/api.proto). With it, you are able to use containerd as the container runtime for a Kubernetes cluster.
@ -283,16 +292,6 @@ A Kubernetes incubator project, [cri-tools](https://github.com/kubernetes-sigs/c
* [Configuring `cri` Plugins](./docs/cri/config.md) * [Configuring `cri` Plugins](./docs/cri/config.md)
* [Configuring containerd](https://github.com/containerd/containerd/blob/master/docs/man/containerd-config.8.md) * [Configuring containerd](https://github.com/containerd/containerd/blob/master/docs/man/containerd-config.8.md)
#### Distribution of `ctr` autocomplete for bash and zsh
For bash, copy the `contrib/autocomplete/ctr` script into
`/etc/bash_completion.d/` and rename it to `ctr`. The `zsh_autocomplete`
file is also available and can be used similarly for zsh users.
Provide documentation to users to `source` this file into their shell if
you don't place the autocomplete file in a location where it is automatically
loaded for the user's shell environment.
### Communication ### Communication
For async communication and long running discussions please use issues and pull requests on the github repo. For async communication and long running discussions please use issues and pull requests on the github repo.

View File

@ -124,7 +124,7 @@ func TestRegressionIssue4769(t *testing.T) {
select { select {
case et := <-eventStream: case et := <-eventStream:
if et.Event == nil { if et.Event == nil {
t.Fatal(errors.Errorf("unexpect empty event: %+v", et)) t.Fatal(errors.Errorf("unexpected empty event: %+v", et))
} }
v, err := typeurl.UnmarshalAny(et.Event) v, err := typeurl.UnmarshalAny(et.Event)
@ -133,7 +133,7 @@ func TestRegressionIssue4769(t *testing.T) {
} }
if e, ok := v.(*apievents.TaskExit); !ok { if e, ok := v.(*apievents.TaskExit); !ok {
t.Fatal(errors.Errorf("unexpect event type: %+v", v)) t.Fatal(errors.Errorf("unexpected event type: %+v", v))
} else if e.ExitStatus != 0 { } else if e.ExitStatus != 0 {
t.Fatal(errors.Errorf("expect zero exit status, but got %v", e.ExitStatus)) t.Fatal(errors.Errorf("expect zero exit status, but got %v", e.ExitStatus))
} }

View File

@ -34,7 +34,7 @@ settings.
**imports** **imports**
: Imports is a list of additional configuration files to include. : Imports is a list of additional configuration files to include.
This allows to split the main configuration file and keep some sections This allows one to split the main configuration file and keep some sections
separately (for example vendors may keep a custom runtime configuration in a separately (for example vendors may keep a custom runtime configuration in a
separate file without modifying the main `config.toml`). separate file without modifying the main `config.toml`).
Imported files will overwrite simple fields like `int` or Imported files will overwrite simple fields like `int` or

View File

@ -84,7 +84,7 @@ This is a containerd-defined label which contains ChainID that targets a committ
At this moment, user-defined labels (prefixed by `containerd.io/snapshot/`) will also be merged into the labels option. At this moment, user-defined labels (prefixed by `containerd.io/snapshot/`) will also be merged into the labels option.
```go ```go
// Gets annotations appended to the targetting layer which would contain // Gets annotations appended to the targeting layer which would contain
// snapshotter-specific information passed by the user. // snapshotter-specific information passed by the user.
labels := snapshots.FilterInheritedLabels(desc.Annotations) labels := snapshots.FilterInheritedLabels(desc.Annotations)
if labels == nil { if labels == nil {
@ -98,7 +98,7 @@ labels["containerd.io/snapshot.ref"] = chainID
// snapshotter-specific information passed by the user. // snapshotter-specific information passed by the user.
opts := append(rCtx.SnapshotterOpts, snapshots.WithLabels(labels)) opts := append(rCtx.SnapshotterOpts, snapshots.WithLabels(labels))
// Calls `Prepare` API with target indentifier and snapshotter-specific // Calls `Prepare` API with target identifier and snapshotter-specific
// information. // information.
mounts, err = sn.Prepare(ctx, key, parent.String(), opts...) mounts, err = sn.Prepare(ctx, key, parent.String(), opts...)
``` ```

View File

@ -289,7 +289,7 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des
// If available is true, the caller can assume that required represents the // If available is true, the caller can assume that required represents the
// complete set of content required for the image. // complete set of content required for the image.
// //
// missing will have the components that are part of required but not avaiiable // missing will have the components that are part of required but not available
// in the provider. // in the provider.
// //
// If there is a problem resolving content, an error will be returned. // If there is a problem resolving content, an error will be returned.

View File

@ -42,7 +42,7 @@ func TestCopyTTRPCMetadata(t *testing.T) {
func TestTTRPCNamespaceHeader(t *testing.T) { func TestTTRPCNamespaceHeader(t *testing.T) {
ctx := context.Background() ctx := context.Background()
namespace := "test-namepace" namespace := "test-namespace"
ctx = withTTRPCNamespaceHeader(ctx, namespace) ctx = withTTRPCNamespaceHeader(ctx, namespace)
header, ok := fromTTRPCHeader(ctx) header, ok := fromTTRPCHeader(ctx)

View File

@ -329,7 +329,7 @@ func WithDevices(osi osinterface.OS, config *runtime.ContainerConfig) oci.SpecOp
} }
} }
// WithCapabilities sets the provided capabilties from the security context // WithCapabilities sets the provided capabilities from the security context
func WithCapabilities(sc *runtime.LinuxContainerSecurityContext) oci.SpecOpts { func WithCapabilities(sc *runtime.LinuxContainerSecurityContext) oci.SpecOpts {
capabilities := sc.GetCapabilities() capabilities := sc.GetCapabilities()
if capabilities == nil { if capabilities == nil {

View File

@ -38,7 +38,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
) )
// FakeShaper provides an implementation of the bandwith.Shaper. // FakeShaper provides an implementation of the bandwidth.Shaper.
// Beware this is implementation has no features besides Reset and GetCIDRs. // Beware this is implementation has no features besides Reset and GetCIDRs.
type FakeShaper struct { type FakeShaper struct {
CIDRs []string CIDRs []string

View File

@ -46,7 +46,7 @@ func validateBandwidthIsReasonable(rsrc *resource.Quantity) error {
return fmt.Errorf("resource is unreasonably small (< 1kbit)") return fmt.Errorf("resource is unreasonably small (< 1kbit)")
} }
if rsrc.Value() > maxRsrc.Value() { if rsrc.Value() > maxRsrc.Value() {
return fmt.Errorf("resoruce is unreasonably large (> 1Pbit)") return fmt.Errorf("resource is unreasonably large (> 1Pbit)")
} }
return nil return nil
} }

View File

@ -92,7 +92,7 @@ func (c *criService) containerMetrics(
} }
} }
default: default:
return &cs, errors.Errorf("unxpected metrics type: %v", metrics) return &cs, errors.Errorf("unexpected metrics type: %v", metrics)
} }
} }

View File

@ -56,7 +56,7 @@ func TestGetUserFromImage(t *testing.T) {
"empty user": { "empty user": {
user: "", user: "",
}, },
"multiple spearators": { "multiple separators": {
user: "1:2:3", user: "1:2:3",
uid: newI64(1), uid: newI64(1),
}, },
@ -99,7 +99,7 @@ func TestGetRepoDigestAndTag(t *testing.T) {
expectedRepoDigest: "", expectedRepoDigest: "",
expectedRepoTag: "gcr.io/library/busybox:latest", expectedRepoTag: "gcr.io/library/busybox:latest",
}, },
"repo digest should not be empty if orignal ref is schema1 but has digest": { "repo digest should not be empty if original ref is schema1 but has digest": {
ref: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", ref: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594",
schema1: true, schema1: true,
expectedRepoDigest: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", expectedRepoDigest: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594",

View File

@ -47,7 +47,7 @@ import (
// 2) Containerd containers may be deleted, but SHOULD NOT be added. Or else, recovery logic // 2) Containerd containers may be deleted, but SHOULD NOT be added. Or else, recovery logic
// for the newly added container/sandbox will return error, because there is no corresponding root // for the newly added container/sandbox will return error, because there is no corresponding root
// directory created. // directory created.
// 3) Containerd container tasks may exit or be stoppped, deleted. Even though current logic could // 3) Containerd container tasks may exit or be stopped, deleted. Even though current logic could
// tolerant tasks being created or started, we prefer that not to happen. // tolerant tasks being created or started, we prefer that not to happen.
// recover recovers system state from containerd and status checkpoint. // recover recovers system state from containerd and status checkpoint.
@ -264,7 +264,7 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
return errors.Errorf("unexpected container state for created task: %q", status.State()) return errors.Errorf("unexpected container state for created task: %q", status.State())
} }
case containerd.Running: case containerd.Running:
// Task is running. Container must be in `RUNNING` state, based on our assuption that // Task is running. Container must be in `RUNNING` state, based on our assumption that
// "task should not be started when containerd is down". // "task should not be started when containerd is down".
switch status.State() { switch status.State() {
case runtime.ContainerState_CONTAINER_EXITED: case runtime.ContainerState_CONTAINER_EXITED:

View File

@ -156,7 +156,7 @@ type StatusStorage interface {
// Delete the container status. // Delete the container status.
// Note: // Note:
// * Delete should be idempotent. // * Delete should be idempotent.
// * The status must be deleted in one trasaction. // * The status must be deleted in one transaction.
Delete() error Delete() error
} }

View File

@ -175,7 +175,7 @@ func LoadNetNS(path string) *NetNS {
return &NetNS{path: path} return &NetNS{path: path}
} }
// Remove removes network namepace. Remove is idempotent, meaning it might // Remove removes network namespace. Remove is idempotent, meaning it might
// be invoked multiple times and provides consistent result. // be invoked multiple times and provides consistent result.
func (n *NetNS) Remove() error { func (n *NetNS) Remove() error {
return unmountNS(n.path) return unmountNS(n.path)

View File

@ -39,7 +39,7 @@ func LoadNetNS(path string) *NetNS {
return &NetNS{path: path} return &NetNS{path: path}
} }
// Remove removes network namepace. Remove is idempotent, meaning it might // Remove removes network namespace. Remove is idempotent, meaning it might
// be invoked multiple times and provides consistent result. // be invoked multiple times and provides consistent result.
func (n *NetNS) Remove() error { func (n *NetNS) Remove() error {
return errNotImplementedOnUnix return errNotImplementedOnUnix

View File

@ -41,7 +41,7 @@ func LoadNetNS(path string) *NetNS {
return &NetNS{path: path} return &NetNS{path: path}
} }
// Remove removes network namepace if it exists and not closed. Remove is idempotent, // Remove removes network namespace if it exists and not closed. Remove is idempotent,
// meaning it might be invoked multiple times and provides consistent result. // meaning it might be invoked multiple times and provides consistent result.
func (n *NetNS) Remove() error { func (n *NetNS) Remove() error {
hcnNamespace, err := hcn.GetNamespaceByID(n.path) hcnNamespace, err := hcn.GetNamespaceByID(n.path)

View File

@ -65,7 +65,7 @@ func GenerateTokenOptions(ctx context.Context, host, username, secret string, c
return to, nil return to, nil
} }
// TokenOptions are optios for requesting a token // TokenOptions are options for requesting a token
type TokenOptions struct { type TokenOptions struct {
Realm string Realm string
Service string Service string

View File

@ -163,7 +163,7 @@ type ErrorDescriptor struct {
// keyed value when serializing api errors. // keyed value when serializing api errors.
Value string Value string
// Message is a short, human readable decription of the error condition // Message is a short, human readable description of the error condition
// included in API responses. // included in API responses.
Message string Message string

View File

@ -43,7 +43,7 @@ If are you looking for areas to contribute to containerd just take a pass throug
## containerd Summit Notes ## containerd Summit Notes
Here are the notes from the containerd summit that was held after Dockercon. If there are important to you and you would like to start working on a feature, fix, request, please go ahead and open an issue on github. Just remember, we shouldn't have to have a summit to get things into containerd. Open issues, disscuss with other members of the community and write the code ;) Here are the notes from the containerd summit that was held after Dockercon. If there are important to you and you would like to start working on a feature, fix, request, please go ahead and open an issue on github. Just remember, we shouldn't have to have a summit to get things into containerd. Open issues, discuss with other members of the community and write the code ;)
* “Since containerd is one of the bottom bricks in the stack, how can we setup automated integration tests for consumers of containerd?” * “Since containerd is one of the bottom bricks in the stack, how can we setup automated integration tests for consumers of containerd?”
- Looking for others to provide compute (testing within Docker, K8s, Microsoft) - Looking for others to provide compute (testing within Docker, K8s, Microsoft)

View File

@ -247,7 +247,7 @@ func (s *Snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
} }
// After committed, the snapshot device will not be directly // After committed, the snapshot device will not be directly
// used anymore. We'd better deativate it to make it *invisible* // used anymore. We'd better deactivate it to make it *invisible*
// in userspace, so that tools like LVM2 and fdisk cannot touch it, // in userspace, so that tools like LVM2 and fdisk cannot touch it,
// and avoid useless IOs on it. // and avoid useless IOs on it.
// //

View File

@ -24,7 +24,7 @@ source $(dirname "${BASH_SOURCE[0]}")/utils.sh
DEPLOY_BUCKET=${DEPLOY_BUCKET:-"cri-containerd-staging"} DEPLOY_BUCKET=${DEPLOY_BUCKET:-"cri-containerd-staging"}
# DEPLOY_DIR is the directory in the gcs bucket to store the tarball. # DEPLOY_DIR is the directory in the gcs bucket to store the tarball.
DEPLOY_DIR=${DEPLOY_DIR:-""} DEPLOY_DIR=${DEPLOY_DIR:-""}
# BUILD_DIR is the directory of the bulid out. # BUILD_DIR is the directory of the build out.
BUILD_DIR=${BUILD_DIR:-"_output"} BUILD_DIR=${BUILD_DIR:-"_output"}
# TARBALL is the tarball name. # TARBALL is the tarball name.
TARBALL=${TARBALL:-"cri-containerd.tar.gz"} TARBALL=${TARBALL:-"cri-containerd.tar.gz"}