Correctly handle platforms that include CPU variants (#1929)
* Correctly handle platforms that include CPU variants Prior to this change, Kaniko would only select the platform-specific image from a multi-platform image using the OS and architecture to select the image. This leads to problems when there are two platforms that are indistinguishable using only this information (e.g., linux/arm/v5 and linux/arm/v7). This change more explicitly selects the right image from a multi-platform image, taking CPU variant into account (v5 vs v7), using containerd's CPU variant detection logic. This also moves platform defaulting up as early as possible in execution as it can go, so that malformed platform values are detected as soon as possible. * set platform in unit test
This commit is contained in:
parent
ef97636546
commit
3589382378
|
|
@ -32,7 +32,9 @@ import (
|
|||
"github.com/GoogleContainerTools/kaniko/pkg/logging"
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/timing"
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/genuinetools/bpfd/proc"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -223,6 +225,14 @@ func addKanikoOptionsFlags() {
|
|||
if val, ok := os.LookupEnv("KANIKO_REGISTRY_MIRROR"); ok {
|
||||
opts.RegistryMirrors.Set(val)
|
||||
}
|
||||
|
||||
// Default the custom platform flag to our current platform, and validate it.
|
||||
if opts.CustomPlatform == "" {
|
||||
opts.CustomPlatform = platforms.DefaultString()
|
||||
}
|
||||
if _, err := v1.ParsePlatform(opts.CustomPlatform); err != nil {
|
||||
logrus.Fatalf("Invalid platform %q: %v", opts.CustomPlatform, err)
|
||||
}
|
||||
}
|
||||
|
||||
// addHiddenFlags marks certain flags as hidden from the executor help text
|
||||
|
|
|
|||
|
|
@ -24,7 +24,10 @@ import (
|
|||
"github.com/GoogleContainerTools/kaniko/pkg/cache"
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/config"
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/logging"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -84,6 +87,14 @@ func addKanikoOptionsFlags() {
|
|||
RootCmd.PersistentFlags().VarP(&opts.RegistriesCertificates, "registry-certificate", "", "Use the provided certificate for TLS communication with the given registry. Expected format is 'my.registry.url=/path/to/the/server/certificate'.")
|
||||
RootCmd.PersistentFlags().VarP(&opts.RegistryMirrors, "registry-mirror", "", "Registry mirror to use as pull-through cache instead of docker.io. Set it repeatedly for multiple mirrors.")
|
||||
RootCmd.PersistentFlags().StringVarP(&opts.CustomPlatform, "customPlatform", "", "", "Specify the build platform if different from the current host")
|
||||
|
||||
// Default the custom platform flag to our current platform, and validate it.
|
||||
if opts.CustomPlatform == "" {
|
||||
opts.CustomPlatform = platforms.DefaultString()
|
||||
}
|
||||
if _, err := v1.ParsePlatform(opts.CustomPlatform); err != nil {
|
||||
logrus.Fatalf("Invalid platform %q: %v", opts.CustomPlatform, err)
|
||||
}
|
||||
}
|
||||
|
||||
// addHiddenFlags marks certain flags as hidden from the executor help text
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||
"github.com/GoogleContainerTools/kaniko/testutil"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/empty"
|
||||
|
|
@ -371,6 +372,7 @@ COPY --from=second /bar /bat
|
|||
ioutil.WriteFile(f.Name(), []byte(tt.args.dockerfile), 0755)
|
||||
opts := &config.KanikoOptions{
|
||||
DockerfilePath: f.Name(),
|
||||
CustomPlatform: platforms.DefaultString(),
|
||||
}
|
||||
testStages, metaArgs, err := dockerfile.ParseStages(opts)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package remote
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/config"
|
||||
|
|
@ -129,28 +128,11 @@ func setNewRegistry(ref name.Reference, newReg name.Registry) name.Reference {
|
|||
func remoteOptions(registryName string, opts config.RegistryOptions, customPlatform string) []remote.Option {
|
||||
tr := util.MakeTransport(opts, registryName)
|
||||
|
||||
// on which v1.Platform is this currently running?
|
||||
platform := currentPlatform(customPlatform)
|
||||
|
||||
return []remote.Option{remote.WithTransport(tr), remote.WithAuthFromKeychain(creds.GetKeychain()), remote.WithPlatform(platform)}
|
||||
}
|
||||
|
||||
// CurrentPlatform returns the v1.Platform on which the code runs
|
||||
func currentPlatform(customPlatform string) v1.Platform {
|
||||
if customPlatform != "" {
|
||||
customPlatformArray := strings.Split(customPlatform, "/")
|
||||
imagePlatform := v1.Platform{}
|
||||
imagePlatform.OS = customPlatformArray[0]
|
||||
if len(customPlatformArray) > 1 {
|
||||
imagePlatform.Architecture = customPlatformArray[1]
|
||||
if len(customPlatformArray) > 2 {
|
||||
imagePlatform.Variant = customPlatformArray[2]
|
||||
}
|
||||
}
|
||||
return imagePlatform
|
||||
}
|
||||
return v1.Platform{
|
||||
OS: runtime.GOOS,
|
||||
Architecture: runtime.GOARCH,
|
||||
// The platform value has previously been validated.
|
||||
platform, err := v1.ParsePlatform(customPlatform)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Invalid platform %q: %v", customPlatform, err)
|
||||
}
|
||||
|
||||
return []remote.Option{remote.WithTransport(tr), remote.WithAuthFromKeychain(creds.GetKeychain()), remote.WithPlatform(*platform)}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue