mirror of https://github.com/k3s-io/k3s
Merge pull request #4681 from manuelbuil/ha-verify-engine
[k3s-engine] Verify new control plane nodes joining the cluster share the same config as cluster memberspull/4699/head
commit
ff9d8db944
|
@ -8,9 +8,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -562,6 +564,10 @@ func (c *Cluster) bootstrap(ctx context.Context) error {
|
||||||
|
|
||||||
// bootstrap managed database via HTTPS
|
// bootstrap managed database via HTTPS
|
||||||
if c.runtime.HTTPBootstrap {
|
if c.runtime.HTTPBootstrap {
|
||||||
|
// Assuming we should just compare on managed databases
|
||||||
|
if err := c.compareConfig(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return c.httpBootstrap(ctx)
|
return c.httpBootstrap(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,3 +583,37 @@ func (c *Cluster) Snapshot(ctx context.Context, config *config.Control) error {
|
||||||
}
|
}
|
||||||
return c.managedDB.Snapshot(ctx, config)
|
return c.managedDB.Snapshot(ctx, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compareConfig verifies that the config of the joining control plane node coincides with the cluster's config
|
||||||
|
func (c *Cluster) compareConfig() error {
|
||||||
|
agentClientAccessInfo, err := clientaccess.ParseAndValidateTokenForUser(c.config.JoinURL, c.config.Token, "node")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
serverConfig, err := agentClientAccessInfo.Get("/v1-" + version.Program + "/config")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clusterControl := &config.Control{}
|
||||||
|
if err := json.Unmarshal(serverConfig, clusterControl); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are saving IPs of ClusterIPRanges and ServiceIPRanges in 4-bytes representation but json decodes in 16-byte
|
||||||
|
ipsTo16Bytes(c.config.CriticalControlArgs.ClusterIPRanges)
|
||||||
|
ipsTo16Bytes(c.config.CriticalControlArgs.ServiceIPRanges)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(clusterControl.CriticalControlArgs, c.config.CriticalControlArgs) {
|
||||||
|
logrus.Debugf("This is the server CriticalControlArgs: %#v", clusterControl.CriticalControlArgs)
|
||||||
|
logrus.Debugf("This is the local CriticalControlArgs: %#v", c.config.CriticalControlArgs)
|
||||||
|
return errors.New("Unable to join cluster due to critical configuration value mismatch")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipsTo16Bytes makes sure the IPs in the []*net.IPNet slice are represented in 16-byte format
|
||||||
|
func ipsTo16Bytes(mySlice []*net.IPNet) {
|
||||||
|
for _, ipNet := range mySlice {
|
||||||
|
ipNet.IP = ipNet.IP.To16()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -101,7 +101,28 @@ type Agent struct {
|
||||||
ProtectKernelDefaults bool
|
ProtectKernelDefaults bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CriticalControlArgs contains parameters that all control plane nodes in HA must share
|
||||||
|
type CriticalControlArgs struct {
|
||||||
|
ClusterDNSs []net.IP
|
||||||
|
ClusterIPRanges []*net.IPNet
|
||||||
|
ClusterDNS net.IP
|
||||||
|
ClusterDomain string
|
||||||
|
ClusterIPRange *net.IPNet
|
||||||
|
DisableCCM bool
|
||||||
|
DisableHelmController bool
|
||||||
|
DisableKubeProxy bool
|
||||||
|
DisableNPC bool
|
||||||
|
Disables map[string]bool
|
||||||
|
DisableServiceLB bool
|
||||||
|
FlannelBackend string
|
||||||
|
NoCoreDNS bool
|
||||||
|
ServiceIPRange *net.IPNet
|
||||||
|
ServiceIPRanges []*net.IPNet
|
||||||
|
Skips map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
type Control struct {
|
type Control struct {
|
||||||
|
CriticalControlArgs
|
||||||
AdvertisePort int
|
AdvertisePort int
|
||||||
AdvertiseIP string
|
AdvertiseIP string
|
||||||
// The port which kubectl clients can access k8s
|
// The port which kubectl clients can access k8s
|
||||||
|
@ -113,21 +134,15 @@ type Control struct {
|
||||||
APIServerBindAddress string
|
APIServerBindAddress string
|
||||||
AgentToken string `json:"-"`
|
AgentToken string `json:"-"`
|
||||||
Token string `json:"-"`
|
Token string `json:"-"`
|
||||||
ClusterIPRange *net.IPNet
|
|
||||||
ClusterIPRanges []*net.IPNet
|
|
||||||
ServiceIPRange *net.IPNet
|
|
||||||
ServiceIPRanges []*net.IPNet
|
|
||||||
ServiceNodePortRange *utilnet.PortRange
|
ServiceNodePortRange *utilnet.PortRange
|
||||||
ClusterDNS net.IP
|
|
||||||
ClusterDNSs []net.IP
|
|
||||||
ClusterDomain string
|
|
||||||
NoCoreDNS bool
|
|
||||||
KubeConfigOutput string
|
KubeConfigOutput string
|
||||||
KubeConfigMode string
|
KubeConfigMode string
|
||||||
DataDir string
|
DataDir string
|
||||||
Skips map[string]bool
|
|
||||||
Disables map[string]bool
|
|
||||||
Datastore endpoint.Config
|
Datastore endpoint.Config
|
||||||
|
DisableAPIServer bool
|
||||||
|
DisableControllerManager bool
|
||||||
|
DisableETCD bool
|
||||||
|
DisableScheduler bool
|
||||||
ExtraAPIArgs []string
|
ExtraAPIArgs []string
|
||||||
ExtraControllerArgs []string
|
ExtraControllerArgs []string
|
||||||
ExtraCloudControllerArgs []string
|
ExtraCloudControllerArgs []string
|
||||||
|
@ -135,18 +150,9 @@ type Control struct {
|
||||||
ExtraSchedulerAPIArgs []string
|
ExtraSchedulerAPIArgs []string
|
||||||
NoLeaderElect bool
|
NoLeaderElect bool
|
||||||
JoinURL string
|
JoinURL string
|
||||||
FlannelBackend string
|
|
||||||
IPSECPSK string
|
IPSECPSK string
|
||||||
DefaultLocalStoragePath string
|
DefaultLocalStoragePath string
|
||||||
SystemDefaultRegistry string
|
SystemDefaultRegistry string
|
||||||
DisableCCM bool
|
|
||||||
DisableNPC bool
|
|
||||||
DisableHelmController bool
|
|
||||||
DisableKubeProxy bool
|
|
||||||
DisableAPIServer bool
|
|
||||||
DisableControllerManager bool
|
|
||||||
DisableScheduler bool
|
|
||||||
DisableETCD bool
|
|
||||||
ClusterInit bool
|
ClusterInit bool
|
||||||
ClusterReset bool
|
ClusterReset bool
|
||||||
ClusterResetRestorePath string
|
ClusterResetRestorePath string
|
||||||
|
|
|
@ -29,23 +29,26 @@ func mustGetAddress() string {
|
||||||
func generateTestConfig() *config.Control {
|
func generateTestConfig() *config.Control {
|
||||||
agentReady := make(chan struct{})
|
agentReady := make(chan struct{})
|
||||||
close(agentReady)
|
close(agentReady)
|
||||||
|
criticalControlArgs := config.CriticalControlArgs{
|
||||||
|
ClusterDomain: "cluster.local",
|
||||||
|
ClusterDNS: net.ParseIP("10.43.0.10"),
|
||||||
|
ClusterIPRange: testutil.ClusterIPNet(),
|
||||||
|
FlannelBackend: "vxlan",
|
||||||
|
ServiceIPRange: testutil.ServiceIPNet(),
|
||||||
|
}
|
||||||
return &config.Control{
|
return &config.Control{
|
||||||
Runtime: &config.ControlRuntime{AgentReady: agentReady},
|
Runtime: &config.ControlRuntime{AgentReady: agentReady},
|
||||||
HTTPSPort: 6443,
|
HTTPSPort: 6443,
|
||||||
SupervisorPort: 6443,
|
SupervisorPort: 6443,
|
||||||
AdvertisePort: 6443,
|
AdvertisePort: 6443,
|
||||||
ClusterDomain: "cluster.local",
|
|
||||||
ClusterDNS: net.ParseIP("10.43.0.10"),
|
|
||||||
ClusterIPRange: testutil.ClusterIPNet(),
|
|
||||||
DataDir: "/tmp/k3s/", // Different than the default value
|
DataDir: "/tmp/k3s/", // Different than the default value
|
||||||
FlannelBackend: "vxlan",
|
|
||||||
EtcdSnapshotName: "etcd-snapshot",
|
EtcdSnapshotName: "etcd-snapshot",
|
||||||
EtcdSnapshotCron: "0 */12 * * *",
|
EtcdSnapshotCron: "0 */12 * * *",
|
||||||
EtcdSnapshotRetention: 5,
|
EtcdSnapshotRetention: 5,
|
||||||
EtcdS3Endpoint: "s3.amazonaws.com",
|
EtcdS3Endpoint: "s3.amazonaws.com",
|
||||||
EtcdS3Region: "us-east-1",
|
EtcdS3Region: "us-east-1",
|
||||||
SANs: []string{"127.0.0.1"},
|
SANs: []string{"127.0.0.1"},
|
||||||
ServiceIPRange: testutil.ServiceIPNet(),
|
CriticalControlArgs: criticalControlArgs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue