-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3429 from estesp/add-nerdctl
Initial provider implementation for nerdctl (+finch)
- Loading branch information
Showing
12 changed files
with
1,498 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
name: Nerdctl | ||
|
||
on: | ||
workflow_dispatch: | ||
pull_request: | ||
branches: | ||
- main | ||
paths-ignore: | ||
- 'site/**' | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
nerdctl: | ||
name: Nerdctl | ||
runs-on: ubuntu-22.04 | ||
timeout-minutes: 30 | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
ipFamily: [ipv4, ipv6] | ||
deployment: [singleNode, multiNode] | ||
exclude: | ||
- ipFamily: ipv6 | ||
env: | ||
JOB_NAME: "nerdctl-${{ matrix.deployment }}-${{ matrix.ipFamily }}" | ||
IP_FAMILY: ${{ matrix.ipFamily }} | ||
NERDCTL_VERSION: "1.7.3" | ||
CONTAINERD_VERSION: "1.7.13" | ||
CNI_PLUGINS_VERSION: "1.3.0" | ||
KIND_EXPERIMENTAL_PROVIDER: "nerdctl" | ||
steps: | ||
- name: Check out code into the Go module directory | ||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: Install kind | ||
run: sudo make install INSTALL_DIR=/usr/local/bin | ||
|
||
- name: Install kubectl | ||
run: | | ||
curl -LO https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl | ||
chmod +x ./kubectl | ||
sudo mv ./kubectl /usr/local/bin/kubectl | ||
- name: Enable ipv4 and ipv6 forwarding | ||
run: | | ||
sudo sysctl -w net.ipv6.conf.all.forwarding=1 | ||
sudo sysctl -w net.ipv4.ip_forward=1 | ||
- name: Install nerdctl | ||
run: | | ||
sudo systemctl is-active --quiet docker.service || systemctl stop docker.service | ||
sudo apt-get remove -y docker-ce docker-ce-cli docker-buildx-plugin podman | ||
# Install Containerd | ||
sudo curl -sSL https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz|sudo tar -xvz -C /usr | ||
sudo systemctl restart containerd.service | ||
sudo ctr version | ||
# Install CNI | ||
sudo mkdir -p /opt/cni/bin | ||
sudo curl -sSL https://github.com/containernetworking/plugins/releases/download/v${CNI_PLUGINS_VERSION}/cni-plugins-linux-amd64-v${CNI_PLUGINS_VERSION}.tgz |sudo tar -xvz -C /opt/cni/bin | ||
# Install nerdctl | ||
sudo curl -sSL https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz|sudo tar -xvz -C /usr/local/bin | ||
- name: Create single node cluster | ||
if: ${{ matrix.deployment == 'singleNode' }} | ||
run: | | ||
cat <<EOF | sudo /usr/local/bin/kind create cluster -v7 --wait 1m --retain --config=- | ||
kind: Cluster | ||
apiVersion: kind.x-k8s.io/v1alpha4 | ||
networking: | ||
ipFamily: ${IP_FAMILY} | ||
EOF | ||
- name: Create multi node cluster | ||
if: ${{ matrix.deployment == 'multiNode' }} | ||
run: | | ||
cat <<EOF | sudo /usr/local/bin/kind create cluster -v7 --wait 1m --retain --config=- | ||
kind: Cluster | ||
apiVersion: kind.x-k8s.io/v1alpha4 | ||
networking: | ||
ipFamily: ${IP_FAMILY} | ||
nodes: | ||
- role: control-plane | ||
- role: worker | ||
- role: worker | ||
EOF | ||
- name: Get Cluster status | ||
run: | | ||
# wait network is ready | ||
sudo kubectl wait --for=condition=ready pods --namespace=kube-system -l k8s-app=kube-dns | ||
sudo kubectl get nodes -o wide | ||
sudo kubectl get pods -A | ||
# TODO: similar to podman, this fails because the imageID() code in KinD is hardcoded to run a docker command | ||
# need to solve this code before this test will work properly | ||
- name: Load nerdctl image | ||
run: | | ||
sudo nerdctl pull busybox | ||
sudo /usr/local/bin/kind load docker-image busybox | ||
continue-on-error: true | ||
|
||
- name: Export logs | ||
if: always() | ||
run: | | ||
sudo cat /etc/cni/net.d/* | ||
sudo mkdir -p /tmp/kind/logs | ||
sudo /usr/local/bin/kind export logs /tmp/kind/logs | ||
sudo chown -R $USER:$USER /tmp/kind/logs | ||
- name: Upload logs | ||
if: always() | ||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 | ||
with: | ||
name: kind-logs-${{ env.JOB_NAME }}-${{ github.run_id }} | ||
path: /tmp/kind/logs | ||
|
||
- name: Delete cluster | ||
run: sudo /usr/local/bin/kind delete cluster |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
labels: | ||
- area/provider/nerdctl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
Copyright 2019 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliep. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package nerdctl | ||
|
||
// clusterLabelKey is applied to each "node" container for identification | ||
const clusterLabelKey = "io.x-k8s.kind.cluster" | ||
|
||
// nodeRoleLabelKey is applied to each "node" container for categorization | ||
// of nodes by role | ||
const nodeRoleLabelKey = "io.x-k8s.kind.role" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
Copyright 2019 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package nerdctl | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"time" | ||
|
||
"sigs.k8s.io/kind/pkg/errors" | ||
"sigs.k8s.io/kind/pkg/exec" | ||
"sigs.k8s.io/kind/pkg/log" | ||
|
||
"sigs.k8s.io/kind/pkg/cluster/internal/providers/common" | ||
"sigs.k8s.io/kind/pkg/internal/apis/config" | ||
"sigs.k8s.io/kind/pkg/internal/cli" | ||
) | ||
|
||
// ensureNodeImages ensures that the node images used by the create | ||
// configuration are present | ||
func ensureNodeImages(logger log.Logger, status *cli.Status, cfg *config.Cluster, binaryName string) error { | ||
// pull each required image | ||
for _, image := range common.RequiredNodeImages(cfg).List() { | ||
// prints user friendly message | ||
friendlyImageName, image := sanitizeImage(image) | ||
status.Start(fmt.Sprintf("Ensuring node image (%s) 🖼", friendlyImageName)) | ||
if _, err := pullIfNotPresent(logger, image, 4, binaryName); err != nil { | ||
status.End(false) | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// pullIfNotPresent will pull an image if it is not present locally | ||
// retrying up to retries times | ||
// it returns true if it attempted to pull, and any errors from pulling | ||
func pullIfNotPresent(logger log.Logger, image string, retries int, binaryName string) (pulled bool, err error) { | ||
// TODO(bentheelder): switch most (all) of the logging here to debug level | ||
// once we have configurable log levels | ||
// if this did not return an error, then the image exists locally | ||
cmd := exec.Command(binaryName, "inspect", "--type=image", image) | ||
if err := cmd.Run(); err == nil { | ||
logger.V(1).Infof("Image: %s present locally", image) | ||
return false, nil | ||
} | ||
// otherwise try to pull it | ||
return true, pull(logger, image, retries, binaryName) | ||
} | ||
|
||
// pull pulls an image, retrying up to retries times | ||
func pull(logger log.Logger, image string, retries int, binaryName string) error { | ||
logger.V(1).Infof("Pulling image: %s ...", image) | ||
err := exec.Command(binaryName, "pull", image).Run() | ||
// retry pulling up to retries times if necessary | ||
if err != nil { | ||
for i := 0; i < retries; i++ { | ||
time.Sleep(time.Second * time.Duration(i+1)) | ||
logger.V(1).Infof("Trying again to pull image: %q ... %v", image, err) | ||
// TODO(bentheelder): add some backoff / sleep? | ||
err = exec.Command(binaryName, "pull", image).Run() | ||
if err == nil { | ||
break | ||
} | ||
} | ||
} | ||
return errors.Wrapf(err, "failed to pull image %q", image) | ||
} | ||
|
||
// sanitizeImage is a helper to return human readable image name and | ||
// the docker pullable image name from the provided image | ||
func sanitizeImage(image string) (string, string) { | ||
if strings.Contains(image, "@sha256:") { | ||
return strings.Split(image, "@sha256:")[0], image | ||
} | ||
return image, image | ||
} |
Oops, something went wrong.