mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-20 22:21:13 +02:00
The kubelet fails to start if a machine's hostname is not set. If networkd doesn't set it in time, the kubelet service fails to start. Addionally, this adds retries to container pulls to ensure that any temporary network failures don't cause fatal errors if we can't pull images. Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
129 lines
3.3 KiB
Go
129 lines
3.3 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package install
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/containerd/containerd"
|
|
"github.com/containerd/containerd/cio"
|
|
"github.com/containerd/containerd/namespaces"
|
|
"github.com/containerd/containerd/oci"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
|
|
"github.com/talos-systems/talos/internal/pkg/containers/image"
|
|
"github.com/talos-systems/talos/internal/pkg/kernel"
|
|
"github.com/talos-systems/talos/internal/pkg/runtime"
|
|
"github.com/talos-systems/talos/pkg/constants"
|
|
)
|
|
|
|
// RunInstallerContainer performs an installation via the installer container.
|
|
//nolint: gocyclo
|
|
func RunInstallerContainer(r runtime.Runtime, opts ...Option) error {
|
|
options := DefaultInstallOptions()
|
|
|
|
for _, opt := range opts {
|
|
if err := opt(&options); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
ctx := namespaces.WithNamespace(context.Background(), constants.SystemContainerdNamespace)
|
|
|
|
client, err := containerd.New(constants.SystemContainerdAddress)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var img containerd.Image
|
|
|
|
if options.ImagePull {
|
|
img, err = image.Pull(ctx, client, r.Config().Machine().Install().Image())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
img, err = client.GetImage(ctx, r.Config().Machine().Install().Image())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
mounts := []specs.Mount{
|
|
{Type: "bind", Destination: "/dev", Source: "/dev", Options: []string{"rbind", "rshared", "rw"}},
|
|
}
|
|
|
|
// TODO(andrewrynhard): To handle cases when the newer version changes the
|
|
// platform name, this should be determined in the installer container.
|
|
var config *string
|
|
if config = kernel.ProcCmdline().Get(constants.KernelParamConfig).First(); config == nil {
|
|
return fmt.Errorf("no config option was found")
|
|
}
|
|
|
|
upgrade := "false"
|
|
if r.Sequence() == runtime.Upgrade {
|
|
upgrade = "true"
|
|
}
|
|
|
|
args := []string{
|
|
"/bin/installer",
|
|
"install",
|
|
"--disk=" + r.Config().Machine().Install().Disk(),
|
|
"--platform=" + r.Platform().Name(),
|
|
"--config=" + *config,
|
|
"--upgrade=" + upgrade,
|
|
}
|
|
|
|
for _, arg := range r.Config().Machine().Install().ExtraKernelArgs() {
|
|
args = append(args, []string{"--extra-kernel-arg", arg}...)
|
|
}
|
|
|
|
specOpts := []oci.SpecOpts{
|
|
oci.WithImageConfig(img),
|
|
oci.WithProcessArgs(args...),
|
|
oci.WithHostNamespace(specs.NetworkNamespace),
|
|
oci.WithHostNamespace(specs.PIDNamespace),
|
|
oci.WithMounts(mounts),
|
|
oci.WithHostHostsFile,
|
|
oci.WithHostResolvconf,
|
|
oci.WithParentCgroupDevices,
|
|
oci.WithPrivileged,
|
|
}
|
|
containerOpts := []containerd.NewContainerOpts{
|
|
containerd.WithImage(img),
|
|
containerd.WithNewSnapshot("upgrade", img),
|
|
containerd.WithNewSpec(specOpts...),
|
|
}
|
|
|
|
container, err := client.NewContainer(ctx, "upgrade", containerOpts...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
t, err := container.NewTask(ctx, cio.LogFile("/dev/kmsg"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = t.Start(ctx); err != nil {
|
|
return fmt.Errorf("failed to start %q task: %w", "upgrade", err)
|
|
}
|
|
|
|
statusC, err := t.Wait(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed waiting for %q task: %w", "upgrade", err)
|
|
}
|
|
|
|
status := <-statusC
|
|
|
|
code := status.ExitCode()
|
|
if code != 0 {
|
|
return fmt.Errorf("task %q failed: exit code %d", "upgrade", code)
|
|
}
|
|
|
|
return nil
|
|
}
|