refactor: remove bootstrap sequence
Refactor things to remove the bootstrap sequence, this should help with the task of sequencer concurrency changes and immediate API feedback. Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
parent
89c7da8991
commit
f0b8eea5e5
@ -101,6 +101,8 @@ type Server struct {
|
||||
machine.UnimplementedMachineServiceServer
|
||||
|
||||
Controller runtime.Controller
|
||||
// breaking the import loop cycle between services/ package and v1alpha1_server.go
|
||||
EtcdBootstrapper func(context.Context, runtime.Runtime, *machine.BootstrapRequest) error
|
||||
|
||||
server *grpc.Server
|
||||
}
|
||||
@ -425,17 +427,9 @@ func (s *Server) Bootstrap(ctx context.Context, in *machine.BootstrapRequest) (r
|
||||
return nil, status.Error(codes.AlreadyExists, "etcd data directory is not empty")
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := s.Controller.Run(context.Background(), runtime.SequenceBootstrap, in); err != nil {
|
||||
log.Println("bootstrap failed:", err)
|
||||
|
||||
if err != runtime.ErrLocked {
|
||||
// NB: We stop the gRPC server since a failed sequence triggers a
|
||||
// reboot.
|
||||
s.server.GracefulStop()
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err := s.EtcdBootstrapper(ctx, s.Controller.Runtime(), in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply = &machine.BootstrapResponse{
|
||||
Messages: []*machine.Bootstrap{
|
||||
|
@ -16,8 +16,6 @@ type Sequence int
|
||||
const (
|
||||
// SequenceBoot is the boot sequence.
|
||||
SequenceBoot Sequence = iota
|
||||
// SequenceBootstrap is the boot sequence.
|
||||
SequenceBootstrap
|
||||
// SequenceInitialize is the initialize sequence.
|
||||
SequenceInitialize
|
||||
// SequenceInstall is the install sequence.
|
||||
@ -38,7 +36,6 @@ const (
|
||||
|
||||
const (
|
||||
boot = "boot"
|
||||
bootstrap = "bootstrap"
|
||||
initialize = "initialize"
|
||||
install = "install"
|
||||
shutdown = "shutdown"
|
||||
@ -51,7 +48,7 @@ const (
|
||||
|
||||
// String returns the string representation of a `Sequence`.
|
||||
func (s Sequence) String() string {
|
||||
return [...]string{boot, bootstrap, initialize, install, shutdown, upgrade, stageUpgrade, reset, reboot, noop}[s]
|
||||
return [...]string{boot, initialize, install, shutdown, upgrade, stageUpgrade, reset, reboot, noop}[s]
|
||||
}
|
||||
|
||||
// ParseSequence returns a `Sequence` that matches the specified string.
|
||||
@ -61,8 +58,6 @@ func ParseSequence(s string) (seq Sequence, err error) {
|
||||
switch s {
|
||||
case boot:
|
||||
seq = SequenceBoot
|
||||
case bootstrap:
|
||||
seq = SequenceBootstrap
|
||||
case initialize:
|
||||
seq = SequenceInitialize
|
||||
case install:
|
||||
@ -104,7 +99,6 @@ type PartitionTarget interface {
|
||||
// management of the operating system.
|
||||
type Sequencer interface {
|
||||
Boot(Runtime) []Phase
|
||||
Bootstrap(Runtime) []Phase
|
||||
Initialize(Runtime) []Phase
|
||||
Install(Runtime) []Phase
|
||||
Reboot(Runtime) []Phase
|
||||
|
@ -95,7 +95,7 @@ func (c *Controller) Run(ctx context.Context, seq runtime.Sequence, data interfa
|
||||
// Allow only one sequence to run at a time with the exception of bootstrap
|
||||
// and reset sequences.
|
||||
switch seq { //nolint:exhaustive
|
||||
case runtime.SequenceBootstrap, runtime.SequenceReset:
|
||||
case runtime.SequenceReset:
|
||||
// Do not attempt to lock.
|
||||
default:
|
||||
if opts.Force {
|
||||
@ -384,8 +384,6 @@ func (c *Controller) phases(seq runtime.Sequence, data interface{}) ([]runtime.P
|
||||
switch seq {
|
||||
case runtime.SequenceBoot:
|
||||
phases = c.s.Boot(c.r)
|
||||
case runtime.SequenceBootstrap:
|
||||
phases = c.s.Bootstrap(c.r)
|
||||
case runtime.SequenceInitialize:
|
||||
phases = c.s.Initialize(c.r)
|
||||
case runtime.SequenceInstall:
|
||||
|
@ -248,19 +248,6 @@ func (*Sequencer) Boot(r runtime.Runtime) []runtime.Phase {
|
||||
return phases
|
||||
}
|
||||
|
||||
// Bootstrap is the bootstrap sequence. This primary goal if this sequence is
|
||||
// to bootstrap Etcd and Kubernetes.
|
||||
func (*Sequencer) Bootstrap(r runtime.Runtime) []runtime.Phase {
|
||||
phases := PhaseList{}
|
||||
|
||||
phases = phases.Append(
|
||||
"etcd",
|
||||
BootstrapEtcd,
|
||||
)
|
||||
|
||||
return phases
|
||||
}
|
||||
|
||||
// Reboot is the reboot sequence.
|
||||
func (*Sequencer) Reboot(r runtime.Runtime) []runtime.Phase {
|
||||
phases := PhaseList{}.Append(
|
||||
|
@ -51,7 +51,6 @@ import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform"
|
||||
perrors "github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/errors"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/events"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/services"
|
||||
"github.com/talos-systems/talos/internal/app/maintenance"
|
||||
"github.com/talos-systems/talos/internal/pkg/cri"
|
||||
@ -1858,55 +1857,6 @@ func Install(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc,
|
||||
}, "install"
|
||||
}
|
||||
|
||||
// BootstrapEtcd represents the task for bootstrapping etcd.
|
||||
func BootstrapEtcd(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
|
||||
req, ok := data.(*machineapi.BootstrapRequest)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to typecast boostrap request")
|
||||
}
|
||||
|
||||
if err = system.Services(r).Stop(ctx, "etcd"); err != nil {
|
||||
return fmt.Errorf("failed to stop etcd: %w", err)
|
||||
}
|
||||
|
||||
// This is hack. We need to fake a finished state so that we can get the
|
||||
// wait in the boot sequence to unblock.
|
||||
for _, svc := range system.Services(r).List() {
|
||||
if svc.AsProto().GetId() == "etcd" {
|
||||
svc.UpdateState(events.StateFinished, "Bootstrap requested")
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if entries, _ := os.ReadDir(constants.EtcdDataPath); len(entries) > 0 { //nolint:errcheck
|
||||
return fmt.Errorf("etcd data directory is not empty")
|
||||
}
|
||||
|
||||
svc := &services.Etcd{
|
||||
Bootstrap: true,
|
||||
RecoverFromSnapshot: req.RecoverEtcd,
|
||||
RecoverSkipHashCheck: req.RecoverSkipHashCheck,
|
||||
}
|
||||
|
||||
if err = system.Services(r).Unload(ctx, svc.ID(r)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
system.Services(r).Load(svc)
|
||||
|
||||
if err = system.Services(r).Start(svc.ID(r)); err != nil {
|
||||
return fmt.Errorf("error starting etcd in bootstrap mode: %w", err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
return system.WaitForService(system.StateEventUp, svc.ID(r)).Wait(ctx)
|
||||
}, "bootstrapEtcd"
|
||||
}
|
||||
|
||||
// ActivateLogicalVolumes represents the task for activating logical volumes.
|
||||
func ActivateLogicalVolumes(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
|
||||
|
@ -32,6 +32,7 @@ import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/events"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/health"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner"
|
||||
@ -42,6 +43,7 @@ import (
|
||||
"github.com/talos-systems/talos/pkg/argsbuilder"
|
||||
"github.com/talos-systems/talos/pkg/conditions"
|
||||
"github.com/talos-systems/talos/pkg/logging"
|
||||
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
|
||||
"github.com/talos-systems/talos/pkg/machinery/constants"
|
||||
"github.com/talos-systems/talos/pkg/machinery/resources/k8s"
|
||||
@ -755,3 +757,44 @@ func primaryAndListenAddresses(subnet string) (primary, listen string, err error
|
||||
|
||||
return primary, listen, nil
|
||||
}
|
||||
|
||||
// BootstrapEtcd bootstraps the etcd cluster.
|
||||
//
|
||||
// Current instance of etcd (not joined yet) is stopped, and new instance is started in bootstrap mode.
|
||||
func BootstrapEtcd(ctx context.Context, r runtime.Runtime, req *machineapi.BootstrapRequest) error {
|
||||
if err := system.Services(r).Stop(ctx, "etcd"); err != nil {
|
||||
return fmt.Errorf("failed to stop etcd: %w", err)
|
||||
}
|
||||
|
||||
// This is hack. We need to fake a finished state so that we can get the
|
||||
// wait in the boot sequence to unblock.
|
||||
for _, svc := range system.Services(r).List() {
|
||||
if svc.AsProto().GetId() == "etcd" {
|
||||
svc.UpdateState(events.StateFinished, "Bootstrap requested")
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if entries, _ := os.ReadDir(constants.EtcdDataPath); len(entries) > 0 { //nolint:errcheck
|
||||
return fmt.Errorf("etcd data directory is not empty")
|
||||
}
|
||||
|
||||
svc := &Etcd{
|
||||
Bootstrap: true,
|
||||
RecoverFromSnapshot: req.RecoverEtcd,
|
||||
RecoverSkipHashCheck: req.RecoverSkipHashCheck,
|
||||
}
|
||||
|
||||
if err := system.Services(r).Unload(ctx, svc.ID(r)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
system.Services(r).Load(svc)
|
||||
|
||||
if err := system.Services(r).Start(svc.ID(r)); err != nil {
|
||||
return fmt.Errorf("error starting etcd in bootstrap mode: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -101,6 +101,8 @@ func (s *machinedService) Main(ctx context.Context, r runtime.Runtime, logWriter
|
||||
server := factory.NewServer(
|
||||
&v1alpha1server.Server{
|
||||
Controller: s.c,
|
||||
// breaking the import loop cycle between services/ package and v1alpha1_server.go
|
||||
EtcdBootstrapper: BootstrapEtcd,
|
||||
},
|
||||
factory.WithLog("machined ", logWriter),
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user