Setup e2e_node to support testing on ARM64
* Enable dockerized build with --use-dockerized-build=true * Build and create test artifacts for ARM64 with --target-build-arch=arm64 * Prepull multi-arch ready container image * Download ARM64 binaries/packages if running on ARM64 machine
This commit is contained in:
parent
6d09ab86c2
commit
e21cf9a54e
@ -29,6 +29,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var k8sBinDir = flag.String("k8s-bin-dir", "", "Directory containing k8s kubelet binaries.")
|
var k8sBinDir = flag.String("k8s-bin-dir", "", "Directory containing k8s kubelet binaries.")
|
||||||
|
var useDockerizedBuild = flag.Bool("use-dockerized-build", false, "Use dockerized build for test artifacts")
|
||||||
|
var targetBuildArch = flag.String("target-build-arch", "linux/amd64", "Target architecture for the test artifacts for dockerized build")
|
||||||
|
|
||||||
var buildTargets = []string{
|
var buildTargets = []string{
|
||||||
"cmd/kubelet",
|
"cmd/kubelet",
|
||||||
@ -47,6 +49,11 @@ func BuildGo() error {
|
|||||||
}
|
}
|
||||||
targets := strings.Join(buildTargets, " ")
|
targets := strings.Join(buildTargets, " ")
|
||||||
cmd := exec.Command("make", "-C", k8sRoot, fmt.Sprintf("WHAT=%s", targets))
|
cmd := exec.Command("make", "-C", k8sRoot, fmt.Sprintf("WHAT=%s", targets))
|
||||||
|
if IsDockerizedBuild() {
|
||||||
|
klog.Infof("Building dockerized k8s binaries targets %s for architecture %s", targets, GetTargetBuildArch())
|
||||||
|
// Multi-architecture build is only supported in dockerized build
|
||||||
|
cmd = exec.Command(filepath.Join(k8sRoot, "build/run.sh"), "make", fmt.Sprintf("WHAT=%s", targets), fmt.Sprintf("KUBE_BUILD_PLATFORMS=%s", GetTargetBuildArch()))
|
||||||
|
}
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
@ -56,6 +63,21 @@ func BuildGo() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDockerizedBuild returns if test needs to use dockerized build
|
||||||
|
func IsDockerizedBuild() bool {
|
||||||
|
return *useDockerizedBuild
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTargetBuildArch returns the target build architecture for dockerized build
|
||||||
|
func GetTargetBuildArch() string {
|
||||||
|
return *targetBuildArch
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTargetArchArm64 returns if the target is for linux/arm64 platform
|
||||||
|
func IsTargetArchArm64() bool {
|
||||||
|
return GetTargetBuildArch() == "linux/arm64"
|
||||||
|
}
|
||||||
|
|
||||||
func getK8sBin(bin string) (string, error) {
|
func getK8sBin(bin string) (string, error) {
|
||||||
// Use commandline specified path
|
// Use commandline specified path
|
||||||
if *k8sBinDir != "" {
|
if *k8sBinDir != "" {
|
||||||
@ -77,7 +99,7 @@ func getK8sBin(bin string) (string, error) {
|
|||||||
return filepath.Join(path, bin), nil
|
return filepath.Join(path, bin), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buildOutputDir, err := utils.GetK8sBuildOutputDir()
|
buildOutputDir, err := utils.GetK8sBuildOutputDir(IsDockerizedBuild(), GetTargetBuildArch())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -61,7 +62,6 @@ var NodePrePullImageList = sets.NewString(
|
|||||||
imageutils.GetPauseImageName(),
|
imageutils.GetPauseImageName(),
|
||||||
imageutils.GetE2EImage(imageutils.NodePerfNpbEp),
|
imageutils.GetE2EImage(imageutils.NodePerfNpbEp),
|
||||||
imageutils.GetE2EImage(imageutils.NodePerfNpbIs),
|
imageutils.GetE2EImage(imageutils.NodePerfNpbIs),
|
||||||
imageutils.GetE2EImage(imageutils.NodePerfTfWideDeep),
|
|
||||||
imageutils.GetE2EImage(imageutils.Etcd),
|
imageutils.GetE2EImage(imageutils.Etcd),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,6 +70,11 @@ var NodePrePullImageList = sets.NewString(
|
|||||||
// 2. the ones passed in from framework.TestContext.ExtraEnvs
|
// 2. the ones passed in from framework.TestContext.ExtraEnvs
|
||||||
// So this function needs to be called after the extra envs are applied.
|
// So this function needs to be called after the extra envs are applied.
|
||||||
func updateImageAllowList(ctx context.Context) {
|
func updateImageAllowList(ctx context.Context) {
|
||||||
|
// Architecture-specific image
|
||||||
|
if !isRunningOnArm64() {
|
||||||
|
// NodePerfTfWideDeep is only supported on x86_64, pulling in arm64 will fail
|
||||||
|
NodePrePullImageList = NodePrePullImageList.Insert(imageutils.GetE2EImage(imageutils.NodePerfTfWideDeep))
|
||||||
|
}
|
||||||
// Union NodePrePullImageList and PrePulledImages into the framework image pre-pull list.
|
// Union NodePrePullImageList and PrePulledImages into the framework image pre-pull list.
|
||||||
e2epod.ImagePrePullList = NodePrePullImageList.Union(commontest.PrePulledImages)
|
e2epod.ImagePrePullList = NodePrePullImageList.Union(commontest.PrePulledImages)
|
||||||
// Images from extra envs
|
// Images from extra envs
|
||||||
@ -96,6 +101,10 @@ func updateImageAllowList(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRunningOnArm64() bool {
|
||||||
|
return runtime.GOARCH == "arm64"
|
||||||
|
}
|
||||||
|
|
||||||
func getNodeProblemDetectorImage() string {
|
func getNodeProblemDetectorImage() string {
|
||||||
const defaultImage string = "registry.k8s.io/node-problem-detector/node-problem-detector:v0.8.7"
|
const defaultImage string = "registry.k8s.io/node-problem-detector/node-problem-detector:v0.8.7"
|
||||||
image := os.Getenv("NODE_PROBLEM_DETECTOR_IMAGE")
|
image := os.Getenv("NODE_PROBLEM_DETECTOR_IMAGE")
|
||||||
|
@ -107,7 +107,7 @@ func (c *ConformanceRemote) SetupTestPackage(tardir, systemSpecName string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can find the newly built binaries
|
// Make sure we can find the newly built binaries
|
||||||
buildOutputDir, err := utils.GetK8sBuildOutputDir()
|
buildOutputDir, err := utils.GetK8sBuildOutputDir(builder.IsDockerizedBuild(), builder.GetTargetBuildArch())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to locate kubernetes build output directory %v", err)
|
return fmt.Errorf("failed to locate kubernetes build output directory %v", err)
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ func (n *NodeE2ERemote) SetupTestPackage(tardir, systemSpecName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can find the newly built binaries
|
// Make sure we can find the newly built binaries
|
||||||
buildOutputDir, err := utils.GetK8sBuildOutputDir()
|
buildOutputDir, err := utils.GetK8sBuildOutputDir(builder.IsDockerizedBuild(), builder.GetTargetBuildArch())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to locate kubernetes build output directory: %w", err)
|
return fmt.Errorf("failed to locate kubernetes build output directory: %w", err)
|
||||||
}
|
}
|
||||||
@ -62,6 +62,7 @@ func (n *NodeE2ERemote) SetupTestPackage(tardir, systemSpecName string) error {
|
|||||||
requiredBins := []string{"kubelet", "e2e_node.test", "ginkgo", "mounter", "gcp-credential-provider"}
|
requiredBins := []string{"kubelet", "e2e_node.test", "ginkgo", "mounter", "gcp-credential-provider"}
|
||||||
for _, bin := range requiredBins {
|
for _, bin := range requiredBins {
|
||||||
source := filepath.Join(buildOutputDir, bin)
|
source := filepath.Join(buildOutputDir, bin)
|
||||||
|
klog.V(2).Infof("Copying binaries from %s", source)
|
||||||
if _, err := os.Stat(source); err != nil {
|
if _, err := os.Stat(source); err != nil {
|
||||||
return fmt.Errorf("failed to locate test binary %s: %w", bin, err)
|
return fmt.Errorf("failed to locate test binary %s: %w", bin, err)
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,16 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/test/e2e_node/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// utils.go contains functions used across test suites.
|
// utils.go contains functions used across test suites.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cniVersion = "v1.2.0"
|
cniVersion = "v1.2.0"
|
||||||
cniArch = "amd64"
|
|
||||||
cniDirectory = "cni/bin" // The CNI tarball places binaries under directory under "cni/bin".
|
cniDirectory = "cni/bin" // The CNI tarball places binaries under directory under "cni/bin".
|
||||||
cniConfDirectory = "cni/net.d"
|
cniConfDirectory = "cni/net.d"
|
||||||
cniURL = "https://storage.googleapis.com/k8s-artifacts-cni/release/" + cniVersion + "/" + "cni-plugins-linux-" + cniArch + "-" + cniVersion + ".tgz"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const cniConfig = `{
|
const cniConfig = `{
|
||||||
@ -60,14 +60,25 @@ providers:
|
|||||||
- "*.pkg.dev"
|
- "*.pkg.dev"
|
||||||
defaultCacheDuration: 1m`
|
defaultCacheDuration: 1m`
|
||||||
|
|
||||||
|
func getCNIURL() string {
|
||||||
|
cniArch := "amd64"
|
||||||
|
if builder.IsTargetArchArm64() {
|
||||||
|
cniArch = "arm64"
|
||||||
|
}
|
||||||
|
cniURL := fmt.Sprintf("https://storage.googleapis.com/k8s-artifacts-cni/release/%s/cni-plugins-linux-%s-%s.tgz", cniVersion, cniArch, cniVersion)
|
||||||
|
return cniURL
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Install the cni plugin and add basic bridge configuration to the
|
// Install the cni plugin and add basic bridge configuration to the
|
||||||
// configuration directory.
|
// configuration directory.
|
||||||
func setupCNI(host, workspace string) error {
|
func setupCNI(host, workspace string) error {
|
||||||
klog.V(2).Infof("Install CNI on %q", host)
|
klog.V(2).Infof("Install CNI on %q", host)
|
||||||
cniPath := filepath.Join(workspace, cniDirectory)
|
cniPath := filepath.Join(workspace, cniDirectory)
|
||||||
|
klog.V(2).Infof("Install CNI on path %q", cniPath)
|
||||||
cmd := getSSHCommand(" ; ",
|
cmd := getSSHCommand(" ; ",
|
||||||
fmt.Sprintf("mkdir -p %s", cniPath),
|
fmt.Sprintf("mkdir -p %s", cniPath),
|
||||||
fmt.Sprintf("curl -s -L %s | tar -xz -C %s", cniURL, cniPath),
|
fmt.Sprintf("curl -s -L %s | tar -xz -C %s", getCNIURL(), cniPath),
|
||||||
)
|
)
|
||||||
if output, err := SSH(host, "sh", "-c", cmd); err != nil {
|
if output, err := SSH(host, "sh", "-c", cmd); err != nil {
|
||||||
return fmt.Errorf("failed to install cni plugin on %q: %v output: %q", host, err, output)
|
return fmt.Errorf("failed to install cni plugin on %q: %v output: %q", host, err, output)
|
||||||
|
@ -51,7 +51,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run node e2e test
|
// Run node e2e test
|
||||||
outputDir, err := utils.GetK8sBuildOutputDir()
|
outputDir, err := utils.GetK8sBuildOutputDir(builder.IsDockerizedBuild(), builder.GetTargetBuildArch())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Fatalf("Failed to get build output directory: %v", err)
|
klog.Fatalf("Failed to get build output directory: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -64,12 +64,17 @@ func RootDir() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetK8sBuildOutputDir returns the build output directory for k8s
|
// GetK8sBuildOutputDir returns the build output directory for k8s
|
||||||
func GetK8sBuildOutputDir() (string, error) {
|
// For dockerized build, targetArch (eg: 'linux/arm64', 'linux/amd64') must be explicitly specified
|
||||||
|
// For non dockerized build, targetArch is ignored
|
||||||
|
func GetK8sBuildOutputDir(isDockerizedBuild bool, targetArch string) (string, error) {
|
||||||
k8sRoot, err := GetK8sRootDir()
|
k8sRoot, err := GetK8sRootDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
buildOutputDir := filepath.Join(k8sRoot, "_output/local/go/bin")
|
buildOutputDir := filepath.Join(k8sRoot, "_output/local/go/bin")
|
||||||
|
if isDockerizedBuild {
|
||||||
|
buildOutputDir = filepath.Join(k8sRoot, "_output/dockerized/bin/", targetArch)
|
||||||
|
}
|
||||||
if _, err := os.Stat(buildOutputDir); err != nil {
|
if _, err := os.Stat(buildOutputDir); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user