2019-01-01 08:23:01 +00:00
package config
import (
2019-03-26 22:15:16 +00:00
"bufio"
2019-01-09 16:54:15 +00:00
"context"
2019-04-23 17:53:06 +00:00
cryptorand "crypto/rand"
2019-01-01 08:23:01 +00:00
"crypto/tls"
2019-04-23 17:53:06 +00:00
"encoding/hex"
2019-11-15 23:48:03 +00:00
"encoding/pem"
2019-01-01 08:23:01 +00:00
"fmt"
2022-10-08 00:36:57 +00:00
"io"
2021-09-01 06:50:23 +00:00
"net"
2019-04-19 18:20:34 +00:00
"net/http"
2019-01-01 08:23:01 +00:00
"net/url"
"os"
2019-01-09 16:54:15 +00:00
"os/exec"
2019-01-01 08:23:01 +00:00
"path/filepath"
2019-03-26 22:15:16 +00:00
"regexp"
2023-12-06 00:25:49 +00:00
"strconv"
2019-03-05 18:28:26 +00:00
"strings"
2019-01-01 08:23:01 +00:00
"time"
2022-12-09 23:42:15 +00:00
"github.com/k3s-io/k3s/pkg/agent/containerd"
2022-03-02 23:47:27 +00:00
"github.com/k3s-io/k3s/pkg/agent/proxy"
2022-05-03 16:59:51 +00:00
agentutil "github.com/k3s-io/k3s/pkg/agent/util"
2022-03-02 23:47:27 +00:00
"github.com/k3s-io/k3s/pkg/cli/cmds"
"github.com/k3s-io/k3s/pkg/clientaccess"
"github.com/k3s-io/k3s/pkg/daemons/config"
"github.com/k3s-io/k3s/pkg/daemons/control/deps"
2023-12-06 00:25:49 +00:00
"github.com/k3s-io/k3s/pkg/spegel"
2022-03-02 23:47:27 +00:00
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/version"
2022-09-01 17:20:32 +00:00
"github.com/k3s-io/k3s/pkg/vpn"
2019-01-01 08:23:01 +00:00
"github.com/pkg/errors"
2023-12-05 18:16:22 +00:00
"github.com/rancher/wharfie/pkg/registries"
2021-05-10 22:58:41 +00:00
"github.com/rancher/wrangler/pkg/slice"
2019-01-01 08:23:01 +00:00
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/json"
2023-11-15 01:24:58 +00:00
"k8s.io/apimachinery/pkg/util/wait"
2023-07-21 08:55:14 +00:00
utilsnet "k8s.io/utils/net"
2019-01-01 08:23:01 +00:00
)
2020-04-27 16:41:57 +00:00
const (
DefaultPodManifestPath = "pod-manifests"
)
2021-07-27 21:56:05 +00:00
// Get returns a pointer to a completed Node configuration struct,
// containing a merging of the local CLI configuration with settings from the server.
2023-11-15 01:24:58 +00:00
// Node configuration includes client certificates, which requires node password verification,
// so this is somewhat computationally expensive on the server side, and is retried with jitter
// to avoid having clients hammer on the server at fixed periods.
2021-07-27 21:56:05 +00:00
// A call to this will bock until agent configuration is successfully returned by the
2023-12-08 00:13:53 +00:00
// server, or the context is cancelled.
func Get ( ctx context . Context , agent cmds . Agent , proxy proxy . Proxy ) ( * config . Node , error ) {
2023-11-15 01:24:58 +00:00
var agentConfig * config . Node
var err error
// This would be more clear as wait.PollImmediateUntilWithContext, but that function
// does not support jittering, so we instead use wait.JitterUntilWithContext, and cancel
// the context on success.
ctx , cancel := context . WithCancel ( ctx )
wait . JitterUntilWithContext ( ctx , func ( ctx context . Context ) {
agentConfig , err = get ( ctx , & agent , proxy )
2019-01-01 08:23:01 +00:00
if err != nil {
2021-07-29 00:02:01 +00:00
logrus . Infof ( "Waiting to retrieve agent configuration; server is not ready: %v" , err )
2023-11-15 01:24:58 +00:00
} else {
cancel ( )
2019-01-01 08:23:01 +00:00
}
2023-11-15 01:24:58 +00:00
} , 5 * time . Second , 1.0 , true )
2023-12-08 00:13:53 +00:00
return agentConfig , err
2019-01-01 08:23:01 +00:00
}
2021-07-27 21:56:05 +00:00
// KubeProxyDisabled returns a bool indicating whether or not kube-proxy has been disabled in the
// server configuration. The server may not have a complete view of cluster configuration until
// after all startup hooks have completed, so a call to this will block until after the server's
// readyz endpoint returns OK.
func KubeProxyDisabled ( ctx context . Context , node * config . Node , proxy proxy . Proxy ) bool {
2023-11-15 01:24:58 +00:00
var disabled bool
var err error
wait . PollImmediateUntilWithContext ( ctx , 5 * time . Second , func ( ctx context . Context ) ( bool , error ) {
disabled , err = getKubeProxyDisabled ( ctx , node , proxy )
2021-07-27 21:56:05 +00:00
if err != nil {
2021-07-29 00:02:01 +00:00
logrus . Infof ( "Waiting to retrieve kube-proxy configuration; server is not ready: %v" , err )
2023-11-15 01:24:58 +00:00
return false , nil
2021-07-27 21:56:05 +00:00
}
2023-11-15 01:24:58 +00:00
return true , nil
} )
return disabled
2021-07-27 21:56:05 +00:00
}
2022-03-29 18:36:48 +00:00
// APIServers returns a list of apiserver endpoints, suitable for seeding client loadbalancer configurations.
// This function will block until it can return a populated list of apiservers, or if the remote server returns
// an error (indicating that it does not support this functionality).
func APIServers ( ctx context . Context , node * config . Node , proxy proxy . Proxy ) [ ] string {
2023-11-15 01:24:58 +00:00
var addresses [ ] string
var err error
wait . PollImmediateUntilWithContext ( ctx , 5 * time . Second , func ( ctx context . Context ) ( bool , error ) {
addresses , err = getAPIServers ( ctx , node , proxy )
2022-03-29 18:36:48 +00:00
if err != nil {
logrus . Infof ( "Failed to retrieve list of apiservers from server: %v" , err )
2023-11-15 01:24:58 +00:00
return false , err
2022-03-29 18:36:48 +00:00
}
if len ( addresses ) == 0 {
logrus . Infof ( "Waiting for apiserver addresses" )
2023-11-15 01:24:58 +00:00
return false , nil
2022-03-29 18:36:48 +00:00
}
2023-11-15 01:24:58 +00:00
return true , nil
} )
return addresses
2022-03-29 18:36:48 +00:00
}
2022-12-08 23:59:21 +00:00
type HTTPRequester func ( u string , client * http . Client , username , password , token string ) ( [ ] byte , error )
2019-04-19 18:20:34 +00:00
func Request ( path string , info * clientaccess . Info , requester HTTPRequester ) ( [ ] byte , error ) {
2020-09-24 06:47:17 +00:00
u , err := url . Parse ( info . BaseURL )
2019-01-01 08:23:01 +00:00
if err != nil {
return nil , err
}
2019-04-19 18:20:34 +00:00
u . Path = path
2022-12-08 23:59:21 +00:00
return requester ( u . String ( ) , clientaccess . GetHTTPClient ( info . CACerts , info . CertFile , info . KeyFile ) , info . Username , info . Password , info . Token ( ) )
2019-04-19 18:20:34 +00:00
}
2021-09-01 06:50:23 +00:00
func getNodeNamedCrt ( nodeName string , nodeIPs [ ] net . IP , nodePasswordFile string ) HTTPRequester {
2022-12-08 23:59:21 +00:00
return func ( u string , client * http . Client , username , password , token string ) ( [ ] byte , error ) {
2019-04-19 18:20:34 +00:00
req , err := http . NewRequest ( http . MethodGet , u , nil )
if err != nil {
return nil , err
}
2022-12-08 23:59:21 +00:00
if token != "" {
req . Header . Add ( "Authorization" , "Bearer " + token )
} else if username != "" {
2019-04-19 18:20:34 +00:00
req . SetBasicAuth ( username , password )
}
2020-05-05 22:09:04 +00:00
req . Header . Set ( version . Program + "-Node-Name" , nodeName )
2019-04-23 17:53:06 +00:00
nodePassword , err := ensureNodePassword ( nodePasswordFile )
if err != nil {
return nil , err
}
2020-05-05 22:09:04 +00:00
req . Header . Set ( version . Program + "-Node-Password" , nodePassword )
2021-04-21 22:56:20 +00:00
req . Header . Set ( version . Program + "-Node-IP" , util . JoinIPs ( nodeIPs ) )
2019-04-23 17:53:06 +00:00
2019-04-19 18:20:34 +00:00
resp , err := client . Do ( req )
if err != nil {
return nil , err
}
defer resp . Body . Close ( )
2023-06-28 19:53:04 +00:00
// If we got a 401 Unauthorized response when using client certs, try again without client cert auth.
// This allows us to fall back from node identity to token when the node resource is deleted.
if resp . StatusCode == http . StatusUnauthorized {
if transport , ok := client . Transport . ( * http . Transport ) ; ok && transport . TLSClientConfig != nil && len ( transport . TLSClientConfig . Certificates ) != 0 {
logrus . Infof ( "Node authorization rejected, retrying without client certificate authentication" )
transport . TLSClientConfig . Certificates = [ ] tls . Certificate { }
resp , err = client . Do ( req )
if err != nil {
return nil , err
}
defer resp . Body . Close ( )
}
}
2019-05-29 18:53:51 +00:00
if resp . StatusCode == http . StatusForbidden {
2019-11-05 09:45:07 +00:00
return nil , fmt . Errorf ( "Node password rejected, duplicate hostname or contents of '%s' may not match server node-passwd entry, try enabling a unique node name with the --with-node-id flag" , nodePasswordFile )
2019-05-29 18:53:51 +00:00
}
2019-04-19 18:20:34 +00:00
if resp . StatusCode != http . StatusOK {
return nil , fmt . Errorf ( "%s: %s" , u , resp . Status )
}
2022-10-08 00:36:57 +00:00
return io . ReadAll ( resp . Body )
2019-04-19 18:20:34 +00:00
}
}
2019-11-05 09:45:07 +00:00
func ensureNodeID ( nodeIDFile string ) ( string , error ) {
if _ , err := os . Stat ( nodeIDFile ) ; err == nil {
2022-10-08 00:36:57 +00:00
id , err := os . ReadFile ( nodeIDFile )
2019-11-05 09:45:07 +00:00
return strings . TrimSpace ( string ( id ) ) , err
}
id := make ( [ ] byte , 4 , 4 )
_ , err := cryptorand . Read ( id )
if err != nil {
return "" , err
}
nodeID := hex . EncodeToString ( id )
2022-10-08 00:36:57 +00:00
return nodeID , os . WriteFile ( nodeIDFile , [ ] byte ( nodeID + "\n" ) , 0644 )
2019-11-05 09:45:07 +00:00
}
2019-04-25 17:53:21 +00:00
func ensureNodePassword ( nodePasswordFile string ) ( string , error ) {
2019-04-23 17:53:06 +00:00
if _ , err := os . Stat ( nodePasswordFile ) ; err == nil {
2022-10-08 00:36:57 +00:00
password , err := os . ReadFile ( nodePasswordFile )
2019-04-25 17:53:21 +00:00
return strings . TrimSpace ( string ( password ) ) , err
2019-04-23 17:53:06 +00:00
}
password := make ( [ ] byte , 16 , 16 )
_ , err := cryptorand . Read ( password )
if err != nil {
2019-04-25 17:53:21 +00:00
return "" , err
2019-04-23 17:53:06 +00:00
}
2019-04-25 17:53:21 +00:00
nodePassword := hex . EncodeToString ( password )
2022-10-08 00:36:57 +00:00
return nodePassword , os . WriteFile ( nodePasswordFile , [ ] byte ( nodePassword + "\n" ) , 0600 )
2019-04-23 17:53:06 +00:00
}
2019-11-05 09:45:07 +00:00
func upgradeOldNodePasswordPath ( oldNodePasswordFile , newNodePasswordFile string ) {
2022-10-08 00:36:57 +00:00
password , err := os . ReadFile ( oldNodePasswordFile )
2019-11-05 09:45:07 +00:00
if err != nil {
return
}
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( newNodePasswordFile , password , 0600 ) ; err != nil {
2019-11-05 09:45:07 +00:00
logrus . Warnf ( "Unable to write password file: %v" , err )
return
}
if err := os . Remove ( oldNodePasswordFile ) ; err != nil {
logrus . Warnf ( "Unable to remove old password file: %v" , err )
return
}
}
2021-09-01 06:50:23 +00:00
func getServingCert ( nodeName string , nodeIPs [ ] net . IP , servingCertFile , servingKeyFile , nodePasswordFile string , info * clientaccess . Info ) ( * tls . Certificate , error ) {
2021-04-21 22:56:20 +00:00
servingCert , err := Request ( "/v1-" + version . Program + "/serving-kubelet.crt" , info , getNodeNamedCrt ( nodeName , nodeIPs , nodePasswordFile ) )
2019-01-01 08:23:01 +00:00
if err != nil {
return nil , err
}
2019-11-15 23:48:03 +00:00
servingCert , servingKey := splitCertKeyPEM ( servingCert )
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( servingCertFile , servingCert , 0600 ) ; err != nil {
2019-04-19 18:20:34 +00:00
return nil , errors . Wrapf ( err , "failed to write node cert" )
}
2019-01-01 08:23:01 +00:00
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( servingKeyFile , servingKey , 0600 ) ; err != nil {
2019-04-19 18:20:34 +00:00
return nil , errors . Wrapf ( err , "failed to write node key" )
}
2019-01-01 08:23:01 +00:00
2019-05-29 18:53:51 +00:00
cert , err := tls . X509KeyPair ( servingCert , servingKey )
2019-01-01 08:23:01 +00:00
if err != nil {
return nil , err
}
return & cert , nil
}
2019-11-15 23:48:03 +00:00
func getHostFile ( filename , keyFile string , info * clientaccess . Info ) error {
2019-05-29 18:53:51 +00:00
basename := filepath . Base ( filename )
2021-03-06 10:29:57 +00:00
fileBytes , err := info . Get ( "/v1-" + version . Program + "/" + basename )
2019-05-29 18:53:51 +00:00
if err != nil {
return err
}
2019-11-15 23:48:03 +00:00
if keyFile == "" {
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( filename , fileBytes , 0600 ) ; err != nil {
2019-11-15 23:48:03 +00:00
return errors . Wrapf ( err , "failed to write cert %s" , filename )
}
} else {
fileBytes , keyBytes := splitCertKeyPEM ( fileBytes )
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( filename , fileBytes , 0600 ) ; err != nil {
2019-11-15 23:48:03 +00:00
return errors . Wrapf ( err , "failed to write cert %s" , filename )
}
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( keyFile , keyBytes , 0600 ) ; err != nil {
2019-11-15 23:48:03 +00:00
return errors . Wrapf ( err , "failed to write key %s" , filename )
}
2019-01-01 08:23:01 +00:00
}
2019-05-29 18:53:51 +00:00
return nil
}
2019-01-01 08:23:01 +00:00
2019-11-15 23:48:03 +00:00
func splitCertKeyPEM ( bytes [ ] byte ) ( certPem [ ] byte , keyPem [ ] byte ) {
for {
b , rest := pem . Decode ( bytes )
if b == nil {
break
}
bytes = rest
if strings . Contains ( b . Type , "PRIVATE KEY" ) {
keyPem = append ( keyPem , pem . EncodeToMemory ( b ) ... )
} else {
certPem = append ( certPem , pem . EncodeToMemory ( b ) ... )
}
}
return
}
2021-09-01 06:50:23 +00:00
func getNodeNamedHostFile ( filename , keyFile , nodeName string , nodeIPs [ ] net . IP , nodePasswordFile string , info * clientaccess . Info ) error {
2019-05-29 18:53:51 +00:00
basename := filepath . Base ( filename )
2021-04-21 22:56:20 +00:00
fileBytes , err := Request ( "/v1-" + version . Program + "/" + basename , info , getNodeNamedCrt ( nodeName , nodeIPs , nodePasswordFile ) )
2019-05-29 18:53:51 +00:00
if err != nil {
return err
}
2019-11-15 23:48:03 +00:00
fileBytes , keyBytes := splitCertKeyPEM ( fileBytes )
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( filename , fileBytes , 0600 ) ; err != nil {
2019-05-29 18:53:51 +00:00
return errors . Wrapf ( err , "failed to write cert %s" , filename )
}
2022-10-08 00:36:57 +00:00
if err := os . WriteFile ( keyFile , keyBytes , 0600 ) ; err != nil {
2019-11-15 23:48:03 +00:00
return errors . Wrapf ( err , "failed to write key %s" , filename )
}
2019-05-29 18:53:51 +00:00
return nil
2019-01-01 08:23:01 +00:00
}
2019-03-26 22:15:16 +00:00
func isValidResolvConf ( resolvConfFile string ) bool {
file , err := os . Open ( resolvConfFile )
if err != nil {
return false
}
defer file . Close ( )
nameserver := regexp . MustCompile ( ` ^nameserver\s+([^\s]*) ` )
scanner := bufio . NewScanner ( file )
for scanner . Scan ( ) {
ipMatch := nameserver . FindStringSubmatch ( scanner . Text ( ) )
if len ( ipMatch ) == 2 {
2021-09-01 06:50:23 +00:00
ip := net . ParseIP ( ipMatch [ 1 ] )
2019-03-26 22:15:16 +00:00
if ip == nil || ! ip . IsGlobalUnicast ( ) {
return false
}
}
}
if err := scanner . Err ( ) ; err != nil {
return false
}
return true
}
func locateOrGenerateResolvConf ( envInfo * cmds . Agent ) string {
if envInfo . ResolvConf != "" {
return envInfo . ResolvConf
}
resolvConfs := [ ] string { "/etc/resolv.conf" , "/run/systemd/resolve/resolv.conf" }
for _ , conf := range resolvConfs {
if isValidResolvConf ( conf ) {
return conf
}
}
2022-05-03 16:59:51 +00:00
resolvConf := filepath . Join ( envInfo . DataDir , "agent" , "etc" , "resolv.conf" )
if err := agentutil . WriteFile ( resolvConf , "nameserver 8.8.8.8\n" ) ; err != nil {
logrus . Errorf ( "Failed to write %s: %v" , resolvConf , err )
2019-03-26 22:15:16 +00:00
return ""
}
2022-05-03 16:59:51 +00:00
logrus . Warnf ( "Host resolv.conf includes loopback or multicast nameservers - kubelet will use autogenerated resolv.conf with nameserver 8.8.8.8" )
return resolvConf
2019-03-26 22:15:16 +00:00
}
2021-03-08 22:10:00 +00:00
func get ( ctx context . Context , envInfo * cmds . Agent , proxy proxy . Proxy ) ( * config . Node , error ) {
2019-01-09 16:54:15 +00:00
if envInfo . Debug {
logrus . SetLevel ( logrus . DebugLevel )
2019-01-01 08:23:01 +00:00
}
2022-12-08 23:59:21 +00:00
clientKubeletCert := filepath . Join ( envInfo . DataDir , "agent" , "client-kubelet.crt" )
clientKubeletKey := filepath . Join ( envInfo . DataDir , "agent" , "client-kubelet.key" )
withCert := clientaccess . WithClientCertificate ( clientKubeletCert , clientKubeletKey )
info , err := clientaccess . ParseAndValidateToken ( proxy . SupervisorURL ( ) , envInfo . Token , withCert )
2019-01-01 08:23:01 +00:00
if err != nil {
return nil , err
}
2020-04-28 22:00:30 +00:00
controlConfig , err := getConfig ( info )
2019-01-01 08:23:01 +00:00
if err != nil {
2021-04-21 22:56:20 +00:00
return nil , errors . Wrap ( err , "failed to retrieve configuration from server" )
2019-01-01 08:23:01 +00:00
}
2021-03-06 10:29:57 +00:00
// If the supervisor and externally-facing apiserver are not on the same port, tell the proxy where to find the apiserver.
2020-04-28 22:00:30 +00:00
if controlConfig . SupervisorPort != controlConfig . HTTPSPort {
2023-10-10 10:34:54 +00:00
isIPv6 := utilsnet . IsIPv6 ( net . ParseIP ( [ ] string { envInfo . NodeIP . String ( ) } [ 0 ] ) )
2022-03-31 09:49:30 +00:00
if err := proxy . SetAPIServerPort ( ctx , controlConfig . HTTPSPort , isIPv6 ) ; err != nil {
2020-04-28 22:00:30 +00:00
return nil , errors . Wrapf ( err , "failed to setup access to API Server port %d on at %s" , controlConfig . HTTPSPort , proxy . SupervisorURL ( ) )
}
2019-01-01 08:23:01 +00:00
}
2021-09-01 06:50:23 +00:00
var flannelIface * net . Interface
2022-12-05 22:01:01 +00:00
if controlConfig . FlannelBackend != config . FlannelBackendNone && len ( envInfo . FlannelIface ) > 0 {
2021-09-01 06:50:23 +00:00
flannelIface , err = net . InterfaceByName ( envInfo . FlannelIface )
2019-05-29 18:53:51 +00:00
if err != nil {
2023-09-13 13:55:43 +00:00
return nil , errors . Wrapf ( err , "unable to find interface %s" , envInfo . FlannelIface )
2019-05-29 18:53:51 +00:00
}
}
2020-11-10 06:15:56 +00:00
clientCAFile := filepath . Join ( envInfo . DataDir , "agent" , "client-ca.crt" )
2019-11-15 23:48:03 +00:00
if err := getHostFile ( clientCAFile , "" , info ) ; err != nil {
2019-01-01 08:23:01 +00:00
return nil , err
}
2020-11-10 06:15:56 +00:00
serverCAFile := filepath . Join ( envInfo . DataDir , "agent" , "server-ca.crt" )
2019-11-15 23:48:03 +00:00
if err := getHostFile ( serverCAFile , "" , info ) ; err != nil {
2019-01-01 08:23:01 +00:00
return nil , err
}
2020-11-10 06:15:56 +00:00
servingKubeletCert := filepath . Join ( envInfo . DataDir , "agent" , "serving-kubelet.crt" )
servingKubeletKey := filepath . Join ( envInfo . DataDir , "agent" , "serving-kubelet.key" )
2019-11-05 09:45:07 +00:00
nodePasswordRoot := "/"
if envInfo . Rootless {
2020-11-10 06:15:56 +00:00
nodePasswordRoot = filepath . Join ( envInfo . DataDir , "agent" )
2019-11-05 09:45:07 +00:00
}
nodeConfigPath := filepath . Join ( nodePasswordRoot , "etc" , "rancher" , "node" )
if err := os . MkdirAll ( nodeConfigPath , 0755 ) ; err != nil {
return nil , err
}
2020-11-10 06:15:56 +00:00
oldNodePasswordFile := filepath . Join ( envInfo . DataDir , "agent" , "node-password.txt" )
2019-11-05 09:45:07 +00:00
newNodePasswordFile := filepath . Join ( nodeConfigPath , "password" )
upgradeOldNodePasswordPath ( oldNodePasswordFile , newNodePasswordFile )
2021-09-01 06:50:23 +00:00
nodeName , nodeIPs , err := util . GetHostnameAndIPs ( envInfo . NodeName , envInfo . NodeIP )
2019-11-05 09:45:07 +00:00
if err != nil {
return nil , err
}
2022-09-01 17:20:32 +00:00
// If there is a VPN, we must overwrite NodeIP and flannel interface
var vpnInfo vpn . VPNInfo
if envInfo . VPNAuth != "" {
vpnInfo , err = vpn . GetVPNInfo ( envInfo . VPNAuth )
if err != nil {
return nil , err
}
2023-06-29 14:23:14 +00:00
2023-07-21 08:55:14 +00:00
// Pass ipv4, ipv6 or both depending on nodeIPs mode
2023-06-29 14:23:14 +00:00
var vpnIPs [ ] net . IP
2023-10-03 10:28:13 +00:00
if utilsnet . IsIPv4 ( nodeIPs [ 0 ] ) && vpnInfo . IPv4Address != nil {
vpnIPs = append ( vpnIPs , vpnInfo . IPv4Address )
if vpnInfo . IPv6Address != nil {
2023-07-21 08:55:14 +00:00
vpnIPs = append ( vpnIPs , vpnInfo . IPv6Address )
}
2023-10-03 10:28:13 +00:00
} else if utilsnet . IsIPv6 ( nodeIPs [ 0 ] ) && vpnInfo . IPv6Address != nil {
vpnIPs = append ( vpnIPs , vpnInfo . IPv6Address )
if vpnInfo . IPv4Address != nil {
vpnIPs = append ( vpnIPs , vpnInfo . IPv4Address )
}
} else {
return nil , errors . Errorf ( "address family mismatch when assigning VPN addresses to node: node=%v, VPN ipv4=%v ipv6=%v" , nodeIPs , vpnInfo . IPv4Address , vpnInfo . IPv6Address )
2023-06-29 14:23:14 +00:00
}
2023-07-21 08:55:14 +00:00
// Overwrite nodeip and flannel interface and throw a warning if user explicitly set those parameters
2023-06-29 14:23:14 +00:00
if len ( vpnIPs ) != 0 {
logrus . Infof ( "Node-ip changed to %v due to VPN" , vpnIPs )
2022-09-01 17:20:32 +00:00
if len ( envInfo . NodeIP ) != 0 {
logrus . Warn ( "VPN provider overrides configured node-ip parameter" )
}
if len ( envInfo . NodeExternalIP ) != 0 {
logrus . Warn ( "VPN provider overrides node-external-ip parameter" )
}
2023-06-29 14:23:14 +00:00
nodeIPs = vpnIPs
2022-09-01 17:20:32 +00:00
flannelIface , err = net . InterfaceByName ( vpnInfo . VPNInterface )
if err != nil {
return nil , errors . Wrapf ( err , "unable to find vpn interface: %s" , vpnInfo . VPNInterface )
}
}
}
2021-12-07 23:42:40 +00:00
nodeExternalIPs , err := util . ParseStringSliceToIPs ( envInfo . NodeExternalIP )
if err != nil {
return nil , fmt . Errorf ( "invalid node-external-ip: %w" , err )
}
2019-11-05 09:45:07 +00:00
if envInfo . WithNodeID {
nodeID , err := ensureNodeID ( filepath . Join ( nodeConfigPath , "id" ) )
if err != nil {
return nil , err
}
nodeName += "-" + nodeID
}
2020-12-22 22:17:00 +00:00
os . Setenv ( "NODE_NAME" , nodeName )
2021-12-07 23:42:40 +00:00
nodeExternalAndInternalIPs := append ( nodeIPs , nodeExternalIPs ... )
servingCert , err := getServingCert ( nodeName , nodeExternalAndInternalIPs , servingKubeletCert , servingKubeletKey , newNodePasswordFile , info )
2019-01-01 08:23:01 +00:00
if err != nil {
return nil , err
}
2021-04-21 22:56:20 +00:00
if err := getNodeNamedHostFile ( clientKubeletCert , clientKubeletKey , nodeName , nodeIPs , newNodePasswordFile , info ) ; err != nil {
2019-05-29 18:53:51 +00:00
return nil , err
}
2020-11-10 06:15:56 +00:00
kubeconfigKubelet := filepath . Join ( envInfo . DataDir , "agent" , "kubelet.kubeconfig" )
2021-03-03 18:14:12 +00:00
if err := deps . KubeConfig ( kubeconfigKubelet , proxy . APIServerURL ( ) , serverCAFile , clientKubeletCert , clientKubeletKey ) ; err != nil {
2019-05-29 18:53:51 +00:00
return nil , err
}
2020-11-10 06:15:56 +00:00
clientKubeProxyCert := filepath . Join ( envInfo . DataDir , "agent" , "client-kube-proxy.crt" )
clientKubeProxyKey := filepath . Join ( envInfo . DataDir , "agent" , "client-kube-proxy.key" )
2019-11-15 23:48:03 +00:00
if err := getHostFile ( clientKubeProxyCert , clientKubeProxyKey , info ) ; err != nil {
2019-05-29 18:53:51 +00:00
return nil , err
}
2020-11-10 06:15:56 +00:00
kubeconfigKubeproxy := filepath . Join ( envInfo . DataDir , "agent" , "kubeproxy.kubeconfig" )
2021-03-03 18:14:12 +00:00
if err := deps . KubeConfig ( kubeconfigKubeproxy , proxy . APIServerURL ( ) , serverCAFile , clientKubeProxyCert , clientKubeProxyKey ) ; err != nil {
2019-05-29 18:53:51 +00:00
return nil , err
2019-03-19 23:28:43 +00:00
}
2020-11-10 06:15:56 +00:00
clientK3sControllerCert := filepath . Join ( envInfo . DataDir , "agent" , "client-" + version . Program + "-controller.crt" )
clientK3sControllerKey := filepath . Join ( envInfo . DataDir , "agent" , "client-" + version . Program + "-controller.key" )
2019-11-15 23:48:03 +00:00
if err := getHostFile ( clientK3sControllerCert , clientK3sControllerKey , info ) ; err != nil {
2019-10-27 05:53:25 +00:00
return nil , err
}
2020-11-10 06:15:56 +00:00
kubeconfigK3sController := filepath . Join ( envInfo . DataDir , "agent" , version . Program + "controller.kubeconfig" )
2021-03-03 18:14:12 +00:00
if err := deps . KubeConfig ( kubeconfigK3sController , proxy . APIServerURL ( ) , serverCAFile , clientK3sControllerCert , clientK3sControllerKey ) ; err != nil {
2019-10-27 05:53:25 +00:00
return nil , err
}
2019-01-09 16:54:15 +00:00
nodeConfig := & config . Node {
2022-07-28 19:32:15 +00:00
Docker : envInfo . Docker ,
2020-08-11 23:17:32 +00:00
SELinux : envInfo . EnableSELinux ,
2019-03-04 06:29:06 +00:00
ContainerRuntimeEndpoint : envInfo . ContainerRuntimeEndpoint ,
2023-09-27 20:20:50 +00:00
ImageServiceEndpoint : envInfo . ImageServiceEndpoint ,
2023-12-05 18:30:38 +00:00
EmbeddedRegistry : controlConfig . EmbeddedRegistry ,
2019-09-03 23:41:54 +00:00
FlannelBackend : controlConfig . FlannelBackend ,
2022-01-14 15:54:55 +00:00
FlannelIPv6Masq : controlConfig . FlannelIPv6Masq ,
2022-10-22 00:22:01 +00:00
FlannelExternalIP : controlConfig . FlannelExternalIP ,
2022-05-17 19:25:43 +00:00
EgressSelectorMode : controlConfig . EgressSelectorMode ,
2021-02-12 15:35:57 +00:00
ServerHTTPSPort : controlConfig . HTTPSPort ,
2021-07-27 21:56:05 +00:00
Token : info . String ( ) ,
2019-01-09 16:54:15 +00:00
}
2019-03-19 23:28:43 +00:00
nodeConfig . FlannelIface = flannelIface
2020-11-10 06:15:56 +00:00
nodeConfig . Images = filepath . Join ( envInfo . DataDir , "agent" , "images" )
2019-01-09 16:54:15 +00:00
nodeConfig . AgentConfig . NodeName = nodeName
2019-11-05 09:45:07 +00:00
nodeConfig . AgentConfig . NodeConfigPath = nodeConfigPath
2022-12-08 23:59:21 +00:00
nodeConfig . AgentConfig . ClientKubeletCert = clientKubeletCert
nodeConfig . AgentConfig . ClientKubeletKey = clientKubeletKey
2019-05-29 18:53:51 +00:00
nodeConfig . AgentConfig . ServingKubeletCert = servingKubeletCert
nodeConfig . AgentConfig . ServingKubeletKey = servingKubeletKey
2019-01-09 16:54:15 +00:00
nodeConfig . AgentConfig . ClusterDNS = controlConfig . ClusterDNS
2019-04-12 06:06:35 +00:00
nodeConfig . AgentConfig . ClusterDomain = controlConfig . ClusterDomain
2019-03-26 22:15:16 +00:00
nodeConfig . AgentConfig . ResolvConf = locateOrGenerateResolvConf ( envInfo )
2019-05-29 18:53:51 +00:00
nodeConfig . AgentConfig . ClientCA = clientCAFile
nodeConfig . AgentConfig . KubeConfigKubelet = kubeconfigKubelet
nodeConfig . AgentConfig . KubeConfigKubeProxy = kubeconfigKubeproxy
2019-10-27 05:53:25 +00:00
nodeConfig . AgentConfig . KubeConfigK3sController = kubeconfigK3sController
2019-10-19 10:18:51 +00:00
if envInfo . Rootless {
2020-11-10 06:15:56 +00:00
nodeConfig . AgentConfig . RootDir = filepath . Join ( envInfo . DataDir , "agent" , "kubelet" )
2019-10-19 10:18:51 +00:00
}
2020-07-17 23:16:23 +00:00
nodeConfig . AgentConfig . Snapshotter = envInfo . Snapshotter
2019-09-03 23:41:54 +00:00
nodeConfig . AgentConfig . IPSECPSK = controlConfig . IPSECPSK
2020-11-10 06:15:56 +00:00
nodeConfig . Containerd . Config = filepath . Join ( envInfo . DataDir , "agent" , "etc" , "containerd" , "config.toml" )
nodeConfig . Containerd . Root = filepath . Join ( envInfo . DataDir , "agent" , "containerd" )
2021-12-16 20:00:40 +00:00
nodeConfig . CRIDockerd . Root = filepath . Join ( envInfo . DataDir , "agent" , "cri-dockerd" )
2023-09-27 20:20:50 +00:00
if ! nodeConfig . Docker {
if nodeConfig . ImageServiceEndpoint != "" {
nodeConfig . AgentConfig . ImageServiceSocket = nodeConfig . ImageServiceEndpoint
} else if nodeConfig . ContainerRuntimeEndpoint == "" {
switch nodeConfig . AgentConfig . Snapshotter {
case "overlayfs" :
if err := containerd . OverlaySupported ( nodeConfig . Containerd . Root ) ; err != nil {
return nil , errors . Wrapf ( err , "\"overlayfs\" snapshotter cannot be enabled for %q, try using \"fuse-overlayfs\" or \"native\"" ,
nodeConfig . Containerd . Root )
}
case "fuse-overlayfs" :
if err := containerd . FuseoverlayfsSupported ( nodeConfig . Containerd . Root ) ; err != nil {
return nil , errors . Wrapf ( err , "\"fuse-overlayfs\" snapshotter cannot be enabled for %q, try using \"native\"" ,
nodeConfig . Containerd . Root )
}
case "stargz" :
if err := containerd . StargzSupported ( nodeConfig . Containerd . Root ) ; err != nil {
return nil , errors . Wrapf ( err , "\"stargz\" snapshotter cannot be enabled for %q, try using \"overlayfs\" or \"native\"" ,
nodeConfig . Containerd . Root )
}
nodeConfig . AgentConfig . ImageServiceSocket = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
2021-09-01 23:27:42 +00:00
}
2023-09-27 20:20:50 +00:00
} else {
nodeConfig . AgentConfig . ImageServiceSocket = nodeConfig . ContainerRuntimeEndpoint
2020-11-25 02:50:24 +00:00
}
}
2020-11-10 06:15:56 +00:00
nodeConfig . Containerd . Opt = filepath . Join ( envInfo . DataDir , "agent" , "containerd" )
2023-01-13 18:30:50 +00:00
nodeConfig . Containerd . Log = filepath . Join ( envInfo . DataDir , "agent" , "containerd" , "containerd.log" )
2023-11-30 02:14:01 +00:00
nodeConfig . Containerd . Registry = filepath . Join ( envInfo . DataDir , "agent" , "etc" , "containerd" , "certs.d" )
nodeConfig . Containerd . NoDefault = envInfo . ContainerdNoDefault
2023-01-13 18:30:50 +00:00
nodeConfig . Containerd . Debug = envInfo . Debug
2021-06-10 19:27:00 +00:00
applyContainerdStateAndAddress ( nodeConfig )
2021-12-16 20:00:40 +00:00
applyCRIDockerdAddress ( nodeConfig )
2024-02-09 19:28:06 +00:00
applyContainerdQoSClassConfigFileIfPresent ( envInfo , & nodeConfig . Containerd )
2020-11-10 06:15:56 +00:00
nodeConfig . Containerd . Template = filepath . Join ( envInfo . DataDir , "agent" , "etc" , "containerd" , "config.toml.tmpl" )
2019-05-29 18:53:51 +00:00
nodeConfig . Certificate = servingCert
2019-09-03 23:41:54 +00:00
2021-04-21 22:56:20 +00:00
nodeConfig . AgentConfig . NodeIPs = nodeIPs
2023-09-21 13:39:05 +00:00
listenAddress , _ , _ , err := util . GetDefaultAddresses ( nodeIPs [ 0 ] )
2021-04-21 22:56:20 +00:00
if err != nil {
2021-11-10 19:23:05 +00:00
return nil , errors . Wrap ( err , "cannot configure IPv4/IPv6 node-ip" )
2021-04-21 22:56:20 +00:00
}
2023-09-21 13:39:05 +00:00
nodeConfig . AgentConfig . NodeIP = nodeIPs [ 0 ] . String ( )
2021-11-10 19:23:05 +00:00
nodeConfig . AgentConfig . ListenAddress = listenAddress
2021-12-07 23:42:40 +00:00
nodeConfig . AgentConfig . NodeExternalIPs = nodeExternalIPs
2021-04-21 22:56:20 +00:00
// if configured, set NodeExternalIP to the first IPv4 address, for legacy clients
2021-11-10 19:23:05 +00:00
// unless only IPv6 address given
2021-04-21 22:56:20 +00:00
if len ( nodeConfig . AgentConfig . NodeExternalIPs ) > 0 {
2023-09-21 13:39:05 +00:00
nodeConfig . AgentConfig . NodeExternalIP = nodeConfig . AgentConfig . NodeExternalIPs [ 0 ] . String ( )
2021-04-21 22:56:20 +00:00
}
2022-12-05 22:01:01 +00:00
nodeConfig . NoFlannel = nodeConfig . FlannelBackend == config . FlannelBackendNone
2019-01-09 16:54:15 +00:00
if ! nodeConfig . NoFlannel {
2020-04-27 16:01:47 +00:00
hostLocal , err := exec . LookPath ( "host-local" )
if err != nil {
return nil , errors . Wrapf ( err , "failed to find host-local" )
}
2019-08-08 05:56:09 +00:00
if envInfo . FlannelConf == "" {
2021-11-20 19:12:03 +00:00
nodeConfig . FlannelConfFile = filepath . Join ( envInfo . DataDir , "agent" , "etc" , "flannel" , "net-conf.json" )
2019-08-08 05:56:09 +00:00
} else {
2021-11-20 19:12:03 +00:00
nodeConfig . FlannelConfFile = envInfo . FlannelConf
2019-08-08 05:56:09 +00:00
nodeConfig . FlannelConfOverride = true
}
2019-01-09 16:54:15 +00:00
nodeConfig . AgentConfig . CNIBinDir = filepath . Dir ( hostLocal )
2020-11-10 06:15:56 +00:00
nodeConfig . AgentConfig . CNIConfDir = filepath . Join ( envInfo . DataDir , "agent" , "etc" , "cni" , "net.d" )
2022-06-08 08:38:07 +00:00
nodeConfig . AgentConfig . FlannelCniConfFile = envInfo . FlannelCniConfFile
2022-09-01 17:20:32 +00:00
// It does not make sense to use VPN without its flannel backend
if envInfo . VPNAuth != "" {
nodeConfig . FlannelBackend = vpnInfo . ProviderName
}
2019-01-09 16:54:15 +00:00
}
2019-12-10 23:16:26 +00:00
2021-12-16 20:00:40 +00:00
if nodeConfig . Docker {
nodeConfig . AgentConfig . CNIPlugin = true
nodeConfig . AgentConfig . RuntimeSocket = nodeConfig . CRIDockerd . Address
} else if nodeConfig . ContainerRuntimeEndpoint == "" {
2021-01-21 01:03:22 +00:00
nodeConfig . AgentConfig . RuntimeSocket = nodeConfig . Containerd . Address
2019-03-04 06:29:06 +00:00
} else {
2019-12-10 23:16:26 +00:00
nodeConfig . AgentConfig . RuntimeSocket = nodeConfig . ContainerRuntimeEndpoint
2019-01-09 16:54:15 +00:00
}
2019-12-10 23:16:26 +00:00
2019-01-09 16:54:15 +00:00
if controlConfig . ClusterIPRange != nil {
2021-04-21 22:56:20 +00:00
nodeConfig . AgentConfig . ClusterCIDR = controlConfig . ClusterIPRange
2021-09-01 06:50:23 +00:00
nodeConfig . AgentConfig . ClusterCIDRs = [ ] * net . IPNet { controlConfig . ClusterIPRange }
2021-04-21 22:56:20 +00:00
}
if len ( controlConfig . ClusterIPRanges ) > 0 {
nodeConfig . AgentConfig . ClusterCIDRs = controlConfig . ClusterIPRanges
2019-01-01 08:23:01 +00:00
}
2021-02-01 19:11:17 +00:00
if controlConfig . ServiceIPRange != nil {
2021-04-21 22:56:20 +00:00
nodeConfig . AgentConfig . ServiceCIDR = controlConfig . ServiceIPRange
2021-09-01 06:50:23 +00:00
nodeConfig . AgentConfig . ServiceCIDRs = [ ] * net . IPNet { controlConfig . ServiceIPRange }
2021-04-21 22:56:20 +00:00
}
if len ( controlConfig . ServiceIPRanges ) > 0 {
nodeConfig . AgentConfig . ServiceCIDRs = controlConfig . ServiceIPRanges
2021-02-01 19:11:17 +00:00
}
if controlConfig . ServiceNodePortRange != nil {
nodeConfig . AgentConfig . ServiceNodePortRange = * controlConfig . ServiceNodePortRange
}
2021-04-21 22:56:20 +00:00
if len ( controlConfig . ClusterDNSs ) == 0 {
2021-09-01 06:50:23 +00:00
nodeConfig . AgentConfig . ClusterDNSs = [ ] net . IP { controlConfig . ClusterDNS }
2021-04-21 22:56:20 +00:00
} else {
nodeConfig . AgentConfig . ClusterDNSs = controlConfig . ClusterDNSs
2021-03-01 12:12:25 +00:00
}
2021-05-10 22:58:41 +00:00
nodeConfig . AgentConfig . PauseImage = envInfo . PauseImage
nodeConfig . AgentConfig . AirgapExtraRegistry = envInfo . AirgapExtraRegistry
2021-05-12 23:50:08 +00:00
nodeConfig . AgentConfig . SystemDefaultRegistry = controlConfig . SystemDefaultRegistry
2021-05-10 22:58:41 +00:00
// Apply SystemDefaultRegistry to PauseImage and AirgapExtraRegistry
if controlConfig . SystemDefaultRegistry != "" {
2021-05-12 23:50:08 +00:00
if nodeConfig . AgentConfig . PauseImage != "" && ! strings . HasPrefix ( nodeConfig . AgentConfig . PauseImage , controlConfig . SystemDefaultRegistry ) {
2021-05-10 22:58:41 +00:00
nodeConfig . AgentConfig . PauseImage = controlConfig . SystemDefaultRegistry + "/" + nodeConfig . AgentConfig . PauseImage
}
if ! slice . ContainsString ( nodeConfig . AgentConfig . AirgapExtraRegistry , controlConfig . SystemDefaultRegistry ) {
nodeConfig . AgentConfig . AirgapExtraRegistry = append ( nodeConfig . AgentConfig . AirgapExtraRegistry , controlConfig . SystemDefaultRegistry )
}
}
2019-04-05 00:43:00 +00:00
nodeConfig . AgentConfig . ExtraKubeletArgs = envInfo . ExtraKubeletArgs
nodeConfig . AgentConfig . ExtraKubeProxyArgs = envInfo . ExtraKubeProxyArgs
2019-05-07 23:47:07 +00:00
nodeConfig . AgentConfig . NodeTaints = envInfo . Taints
nodeConfig . AgentConfig . NodeLabels = envInfo . Labels
2021-05-10 22:58:41 +00:00
nodeConfig . AgentConfig . ImageCredProvBinDir = envInfo . ImageCredProvBinDir
nodeConfig . AgentConfig . ImageCredProvConfig = envInfo . ImageCredProvConfig
2019-10-15 21:17:26 +00:00
nodeConfig . AgentConfig . DisableCCM = controlConfig . DisableCCM
2019-10-17 21:46:15 +00:00
nodeConfig . AgentConfig . DisableNPC = controlConfig . DisableNPC
2019-10-19 10:18:51 +00:00
nodeConfig . AgentConfig . Rootless = envInfo . Rootless
2020-11-10 06:15:56 +00:00
nodeConfig . AgentConfig . PodManifests = filepath . Join ( envInfo . DataDir , "agent" , DefaultPodManifestPath )
2020-07-20 23:31:56 +00:00
nodeConfig . AgentConfig . ProtectKernelDefaults = envInfo . ProtectKernelDefaults
2021-11-09 15:44:34 +00:00
nodeConfig . AgentConfig . DisableServiceLB = envInfo . DisableServiceLB
2023-12-19 03:14:02 +00:00
nodeConfig . AgentConfig . VLevel = cmds . LogConfig . VLevel
nodeConfig . AgentConfig . VModule = cmds . LogConfig . VModule
nodeConfig . AgentConfig . LogFile = cmds . LogConfig . LogFile
nodeConfig . AgentConfig . AlsoLogToStderr = cmds . LogConfig . AlsoLogToStderr
2019-05-07 23:47:07 +00:00
2023-12-05 18:16:22 +00:00
privRegistries , err := registries . GetPrivateRegistries ( envInfo . PrivateRegistry )
if err != nil {
return nil , err
}
nodeConfig . AgentConfig . Registry = privRegistries . Registry
2023-12-06 00:25:49 +00:00
if nodeConfig . EmbeddedRegistry {
psk , err := hex . DecodeString ( controlConfig . IPSECPSK )
if err != nil {
return nil , err
}
if len ( psk ) < 32 {
return nil , errors . New ( "insufficient PSK bytes" )
}
conf := spegel . DefaultRegistry
conf . ExternalAddress = nodeConfig . AgentConfig . NodeIP
conf . InternalAddress = controlConfig . Loopback ( false )
conf . RegistryPort = strconv . Itoa ( controlConfig . SupervisorPort )
conf . ClientCAFile = clientCAFile
conf . ClientCertFile = clientK3sControllerCert
conf . ClientKeyFile = clientK3sControllerKey
conf . ServerCAFile = serverCAFile
conf . ServerCertFile = servingKubeletCert
conf . ServerKeyFile = servingKubeletKey
conf . PSK = psk [ : 32 ]
conf . InjectMirror ( nodeConfig )
}
2021-04-21 22:56:20 +00:00
if err := validateNetworkConfig ( nodeConfig ) ; err != nil {
return nil , err
}
2019-01-01 08:23:01 +00:00
return nodeConfig , nil
}
2022-03-29 18:36:48 +00:00
// getAPIServers attempts to return a list of apiservers from the server.
func getAPIServers ( ctx context . Context , node * config . Node , proxy proxy . Proxy ) ( [ ] string , error ) {
2022-12-08 23:59:21 +00:00
withCert := clientaccess . WithClientCertificate ( node . AgentConfig . ClientKubeletCert , node . AgentConfig . ClientKubeletKey )
info , err := clientaccess . ParseAndValidateToken ( proxy . SupervisorURL ( ) , node . Token , withCert )
2022-03-29 18:36:48 +00:00
if err != nil {
return nil , err
}
data , err := info . Get ( "/v1-" + version . Program + "/apiservers" )
if err != nil {
return nil , err
}
endpoints := [ ] string { }
return endpoints , json . Unmarshal ( data , & endpoints )
}
2021-07-27 21:56:05 +00:00
// getKubeProxyDisabled attempts to return the DisableKubeProxy setting from the server configuration data.
// It first checks the server readyz endpoint, to ensure that the configuration has stabilized before use.
func getKubeProxyDisabled ( ctx context . Context , node * config . Node , proxy proxy . Proxy ) ( bool , error ) {
2022-12-08 23:59:21 +00:00
withCert := clientaccess . WithClientCertificate ( node . AgentConfig . ClientKubeletCert , node . AgentConfig . ClientKubeletKey )
info , err := clientaccess . ParseAndValidateToken ( proxy . SupervisorURL ( ) , node . Token , withCert )
2021-07-27 21:56:05 +00:00
if err != nil {
return false , err
}
// 500 error indicates that the health check has failed; other errors (for example 401 Unauthorized)
// indicate that the server is down-level and doesn't support readyz, so we should just use whatever
// the server has for us.
if err := getReadyz ( info ) ; err != nil && strings . HasSuffix ( err . Error ( ) , "500 Internal Server Error" ) {
return false , err
}
controlConfig , err := getConfig ( info )
if err != nil {
return false , errors . Wrap ( err , "failed to retrieve configuration from server" )
}
return controlConfig . DisableKubeProxy , nil
}
// getConfig returns server configuration data. Note that this may be mutated during system startup; anything that needs
// to ensure stable system state should check the readyz endpoint first. This is required because RKE2 starts up the
// kubelet early, before the apiserver is available.
2019-01-01 08:23:01 +00:00
func getConfig ( info * clientaccess . Info ) ( * config . Control , error ) {
2021-03-06 10:29:57 +00:00
data , err := info . Get ( "/v1-" + version . Program + "/config" )
2019-01-01 08:23:01 +00:00
if err != nil {
return nil , err
}
controlControl := & config . Control { }
return controlControl , json . Unmarshal ( data , controlControl )
}
2021-04-21 22:56:20 +00:00
2021-07-27 21:56:05 +00:00
// getReadyz returns nil if the server is ready, or an error if not.
func getReadyz ( info * clientaccess . Info ) error {
_ , err := info . Get ( "/v1-" + version . Program + "/readyz" )
return err
}
2021-04-21 22:56:20 +00:00
// validateNetworkConfig ensures that the network configuration values provided by the server make sense.
func validateNetworkConfig ( nodeConfig * config . Node ) error {
// Old versions of the server do not send enough information to correctly start the NPC. Users
// need to upgrade the server to at least the same version as the agent, or disable the NPC
// cluster-wide.
if nodeConfig . AgentConfig . DisableNPC == false && ( nodeConfig . AgentConfig . ServiceCIDR == nil || nodeConfig . AgentConfig . ServiceNodePortRange . Size == 0 ) {
return fmt . Errorf ( "incompatible down-level server detected; servers must be upgraded to at least %s, or restarted with --disable-network-policy" , version . Version )
}
return nil
}