feat: use architecture-specific image for core k8s components

This is one step towards running Talos on non-amd64 architectures (e.g. arm64).

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
This commit is contained in:
Andrey Smirnov
2020-09-16 00:17:56 +03:00
committed by talos-bot
parent 7f5ffdacb8
commit 15181aeade
11 changed files with 45 additions and 21 deletions

View File

@ -186,6 +186,7 @@ func create(ctx context.Context) (err error) {
generate.WithInstallImage(nodeInstallImage),
generate.WithDebug(configDebug),
generate.WithDNSDomain(dnsDomain),
generate.WithArchitecture(targetArch),
}
for _, registryMirror := range registryMirrors {

View File

@ -10,6 +10,7 @@ import (
"net/url"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/spf13/cobra"
@ -25,6 +26,7 @@ import (
var (
additionalSANs []string
configVersion string
architecture string
dnsDomain string
kubernetesVersion string
installDisk string
@ -101,6 +103,7 @@ func genV1Alpha1Config(args []string) error {
generate.WithAdditionalSubjectAltNames(additionalSANs),
generate.WithDNSDomain(dnsDomain),
generate.WithPersist(persistConfig),
generate.WithArchitecture(architecture),
),
},
),
@ -165,6 +168,7 @@ func init() {
genConfigCmd.Flags().StringVar(&installImage, "install-image", helpers.DefaultImage(constants.DefaultInstallerImageRepository), "the image used to perform an installation")
genConfigCmd.Flags().StringSliceVar(&additionalSANs, "additional-sans", []string{}, "additional Subject-Alt-Names for the APIServer certificate")
genConfigCmd.Flags().StringVar(&dnsDomain, "dns-domain", "cluster.local", "the dns domain to use for cluster")
genConfigCmd.Flags().StringVar(&architecture, "arch", runtime.GOARCH, "the architecture of the cluster")
genConfigCmd.Flags().StringVar(&configVersion, "version", "v1alpha1", "the desired machine config version to generate")
genConfigCmd.Flags().StringVar(&kubernetesVersion, "kubernetes-version", constants.DefaultKubernetesVersion, "desired kubernetes version to run")
genConfigCmd.Flags().StringVarP(&outputDir, "output-dir", "o", "", "destination to output generated files")

View File

@ -6,6 +6,7 @@ package talos
import (
"context"
"runtime"
"github.com/spf13/cobra"
@ -30,11 +31,13 @@ var upgradeK8sCmd = &cobra.Command{
var upgradeK8sCmdFlags struct {
fromVersion string
toVersion string
arch string
}
func init() {
upgradeK8sCmd.Flags().StringVar(&upgradeK8sCmdFlags.fromVersion, "from", "", "the Kubernetes control plane version to upgrade from")
upgradeK8sCmd.Flags().StringVar(&upgradeK8sCmdFlags.toVersion, "to", constants.DefaultKubernetesVersion, "the Kubernetes control plane version to upgrade to")
upgradeK8sCmd.Flags().StringVar(&upgradeK8sCmdFlags.arch, "arch", runtime.GOARCH, "the cluster architecture")
cli.Should(upgradeK8sCmd.MarkFlagRequired("from"))
cli.Should(upgradeK8sCmd.MarkFlagRequired("to"))
addCommand(upgradeK8sCmd)
@ -55,5 +58,5 @@ func upgradeKubernetes(ctx context.Context, c *client.Client) error {
},
}
return k8s.Upgrade(ctx, &state, upgradeK8sCmdFlags.fromVersion, upgradeK8sCmdFlags.toVersion)
return k8s.Upgrade(ctx, &state, upgradeK8sCmdFlags.arch, upgradeK8sCmdFlags.fromVersion, upgradeK8sCmdFlags.toVersion)
}

View File

@ -18,6 +18,7 @@ talosctl gen config <cluster name> <cluster endpoint> [flags]
```
--additional-sans strings additional Subject-Alt-Names for the APIServer certificate
--arch string the architecture of the cluster (default "amd64")
--dns-domain string the dns domain to use for cluster (default "cluster.local")
-h, --help help for config
--install-disk string the disk to install to (default "/dev/sda")

View File

@ -14,6 +14,7 @@ talosctl upgrade-k8s [flags]
### Options
```
--arch string the cluster architecture (default "amd64")
--from string the Kubernetes control plane version to upgrade from
-h, --help help for upgrade-k8s
--to string the Kubernetes control plane version to upgrade to (default "1.19.1")

View File

@ -15,6 +15,7 @@ import (
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"time"
@ -464,7 +465,7 @@ func (suite *UpgradeSuite) upgradeKubernetes(fromVersion, toVersion string) {
suite.T().Logf("upgrading Kubernetes: %q -> %q", fromVersion, toVersion)
suite.Require().NoError(kubernetes.Upgrade(suite.ctx, suite.clusterAccess, fromVersion, toVersion))
suite.Require().NoError(kubernetes.Upgrade(suite.ctx, suite.clusterAccess, runtime.GOARCH, fromVersion, toVersion))
}
// TestRolling performs rolling upgrade starting with master nodes.

View File

@ -34,19 +34,19 @@ const (
)
// Upgrade the Kubernetes control plane.
func Upgrade(ctx context.Context, cluster cluster.K8sProvider, fromVersion, toVersion string) error {
func Upgrade(ctx context.Context, cluster cluster.K8sProvider, arch, fromVersion, toVersion string) error {
switch {
case strings.HasPrefix(fromVersion, "1.18.") && strings.HasPrefix(toVersion, "1.19."):
return hyperkubeUpgrade(ctx, cluster, toVersion)
return hyperkubeUpgrade(ctx, cluster, arch, toVersion)
case strings.HasPrefix(fromVersion, "1.19.") && strings.HasPrefix(toVersion, "1.19."):
return hyperkubeUpgrade(ctx, cluster, toVersion)
return hyperkubeUpgrade(ctx, cluster, arch, toVersion)
default:
return fmt.Errorf("unsupported upgrade from %q to %q", fromVersion, toVersion)
}
}
// hyperkubeUpgrade upgrades from hyperkube-based to distroless images in 1.19.
func hyperkubeUpgrade(ctx context.Context, cluster cluster.K8sProvider, targetVersion string) error {
func hyperkubeUpgrade(ctx context.Context, cluster cluster.K8sProvider, arch, targetVersion string) error {
clientset, err := cluster.K8sClient(ctx)
if err != nil {
return fmt.Errorf("error building K8s client: %w", err)
@ -64,7 +64,7 @@ func hyperkubeUpgrade(ctx context.Context, cluster cluster.K8sProvider, targetVe
daemonsets := []string{kubeAPIServer, kubeControllerManager, kubeScheduler, kubeProxy}
for _, ds := range daemonsets {
if err = hyperkubeUpgradeDs(ctx, clientset, ds, targetVersion); err != nil {
if err = hyperkubeUpgradeDs(ctx, clientset, ds, arch, targetVersion); err != nil {
return fmt.Errorf("failed updating daemonset %q: %w", ds, err)
}
}
@ -158,7 +158,7 @@ func podCheckpointerGracePeriod(ctx context.Context, clientset *kubernetes.Clien
}
//nolint: gocyclo
func hyperkubeUpgradeDs(ctx context.Context, clientset *kubernetes.Clientset, ds, targetVersion string) error {
func hyperkubeUpgradeDs(ctx context.Context, clientset *kubernetes.Clientset, ds, arch, targetVersion string) error {
if ds == kubeAPIServer {
fmt.Printf("temporarily taking %q out of pod-checkpointer control\n", ds)
@ -190,13 +190,13 @@ func hyperkubeUpgradeDs(ctx context.Context, clientset *kubernetes.Clientset, ds
switch ds {
case kubeAPIServer:
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:v%s", constants.KubernetesAPIServerImage, targetVersion)
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s-%s:v%s", constants.KubernetesAPIServerImage, arch, targetVersion)
case kubeControllerManager:
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:v%s", constants.KubernetesControllerManagerImage, targetVersion)
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s-%s:v%s", constants.KubernetesControllerManagerImage, arch, targetVersion)
case kubeScheduler:
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:v%s", constants.KubernetesSchedulerImage, targetVersion)
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s-%s:v%s", constants.KubernetesSchedulerImage, arch, targetVersion)
case kubeProxy:
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:v%s", constants.KubernetesProxyImage, targetVersion)
daemonset.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s-%s:v%s", constants.KubernetesProxyImage, arch, targetVersion)
default:
return fmt.Errorf("failed to build new image spec")
}

View File

@ -66,6 +66,7 @@ type Input struct {
AdditionalMachineCertSANs []string
ClusterName string
Architecture string
ServiceDomain string
PodNet []string
ServiceNet []string
@ -315,6 +316,7 @@ func NewInput(clustername, endpoint, kubernetesVersion string, opts ...GenOption
ServiceNet: []string{serviceNet},
ServiceDomain: options.DNSDomain,
ClusterName: clustername,
Architecture: options.Architecture,
KubernetesVersion: kubernetesVersion,
Secrets: kubeadmTokens,
TrustdInfo: trustdInfo,

View File

@ -53,16 +53,16 @@ func initUd(in *Input) (*v1alpha1.Config, error) {
},
APIServerConfig: &v1alpha1.APIServerConfig{
CertSANs: certSANs,
ContainerImage: emptyIf(fmt.Sprintf("%s:v%s", constants.KubernetesAPIServerImage, in.KubernetesVersion), in.KubernetesVersion),
ContainerImage: emptyIf(fmt.Sprintf("%s-%s:v%s", constants.KubernetesAPIServerImage, in.Architecture, in.KubernetesVersion), in.KubernetesVersion),
},
ControllerManagerConfig: &v1alpha1.ControllerManagerConfig{
ContainerImage: emptyIf(fmt.Sprintf("%s:v%s", constants.KubernetesControllerManagerImage, in.KubernetesVersion), in.KubernetesVersion),
ContainerImage: emptyIf(fmt.Sprintf("%s-%s:v%s", constants.KubernetesControllerManagerImage, in.Architecture, in.KubernetesVersion), in.KubernetesVersion),
},
ProxyConfig: &v1alpha1.ProxyConfig{
ContainerImage: emptyIf(fmt.Sprintf("%s:v%s", constants.KubeProxyImage, in.KubernetesVersion), in.KubernetesVersion),
ContainerImage: emptyIf(fmt.Sprintf("%s-%s:v%s", constants.KubeProxyImage, in.Architecture, in.KubernetesVersion), in.KubernetesVersion),
},
SchedulerConfig: &v1alpha1.SchedulerConfig{
ContainerImage: emptyIf(fmt.Sprintf("%s:v%s", constants.KubernetesSchedulerImage, in.KubernetesVersion), in.KubernetesVersion),
ContainerImage: emptyIf(fmt.Sprintf("%s-%s:v%s", constants.KubernetesSchedulerImage, in.Architecture, in.KubernetesVersion), in.KubernetesVersion),
},
EtcdConfig: &v1alpha1.EtcdConfig{
RootCA: in.Certs.Etcd,

View File

@ -114,6 +114,15 @@ func WithClusterCNIConfig(config *v1alpha1.CNIConfig) GenOption {
}
}
// WithArchitecture specifies architecture of the Talos cluster.
func WithArchitecture(arch string) GenOption {
return func(o *GenOptions) error {
o.Architecture = arch
return nil
}
}
// GenOptions describes generate parameters.
type GenOptions struct {
EndpointList []string
@ -125,6 +134,7 @@ type GenOptions struct {
CNIConfig *v1alpha1.CNIConfig
RegistryMirrors map[string]*v1alpha1.RegistryMirrorConfig
DNSDomain string
Architecture string
Debug bool
Persist bool
}
@ -132,6 +142,7 @@ type GenOptions struct {
// DefaultGenOptions returns default options.
func DefaultGenOptions() GenOptions {
return GenOptions{
Persist: true,
Persist: true,
Architecture: "amd64",
}
}

View File

@ -282,7 +282,7 @@ func (a *APIServerConfig) Image() string {
image := a.ContainerImage
if image == "" {
image = fmt.Sprintf("%s:v%s", constants.KubernetesAPIServerImage, constants.DefaultKubernetesVersion)
image = fmt.Sprintf("%s-%s:v%s", constants.KubernetesAPIServerImage, goruntime.GOARCH, constants.DefaultKubernetesVersion)
}
return image
@ -307,7 +307,7 @@ func (c *ControllerManagerConfig) Image() string {
image := c.ContainerImage
if image == "" {
image = fmt.Sprintf("%s:v%s", constants.KubernetesControllerManagerImage, constants.DefaultKubernetesVersion)
image = fmt.Sprintf("%s-%s:v%s", constants.KubernetesControllerManagerImage, goruntime.GOARCH, constants.DefaultKubernetesVersion)
}
return image
@ -332,7 +332,7 @@ func (p *ProxyConfig) Image() string {
image := p.ContainerImage
if image == "" {
image = fmt.Sprintf("%s:v%s", constants.KubeProxyImage, constants.DefaultKubernetesVersion)
image = fmt.Sprintf("%s-%s:v%s", constants.KubeProxyImage, goruntime.GOARCH, constants.DefaultKubernetesVersion)
}
return image
@ -371,7 +371,7 @@ func (s *SchedulerConfig) Image() string {
image := s.ContainerImage
if image == "" {
image = fmt.Sprintf("%s:v%s", constants.KubernetesSchedulerImage, constants.DefaultKubernetesVersion)
image = fmt.Sprintf("%s-%s:v%s", constants.KubernetesSchedulerImage, goruntime.GOARCH, constants.DefaultKubernetesVersion)
}
return image