- new special internal role `initServer` used only to determine the correct ready-log-message
- ready-log-messages now looked up by role and new `Intent` type (cluster-create/cluster-start/node-create/node-start), as especially for the init server there are different log messages indicating that we can proceed with the next step
- moving types around:
- K3s env vars now under .../types/k3s/env.go
- defaults now under .../types/defaults.go
- ...
- improved waiting for log messages
- not checking the whole log again and again in a loop
- follow log with a single reader (and retry in case we see a fatal error, meaning that the K3s container will restart -> backoff after 10 tries)
- BREAKING: new `*runtimeTypes.NodeLogsOpts` parameter in GetNodeLogs
ReadyLogMessage:"Running kube-apiserver",// initNode means, that we're using etcd -> this will need quorum, so "k3s is up and running" won't happen right now
ReadyLogMessage:types.GetReadyLogMessage(initNode,clusterStartOpts.Intent),// initNode means, that we're using etcd -> this will need quorum, so "k3s is up and running" won't happen right now
EnvironmentInfo:clusterStartOpts.EnvironmentInfo,
EnvironmentInfo:clusterStartOpts.EnvironmentInfo,
});err!=nil{
});err!=nil{
returnfmt.Errorf("Failed to start initializing server node: %+v",err)
returnfmt.Errorf("Failed to start initializing server node: %+v",err)
l.Log().Warnf("Node '%s' is restarting for more than %s now. Possibly it will recover soon (e.g. when it's waiting to join). Consider using a creation timeout to avoid waiting forever in a Restart Loop.",node.Name,k3d.NodeWaitForLogMessageRestartWarnTime)
}
}
returnctx.Err()
time.Sleep(500*time.Millisecond)
default:
}
}
// read the logs
}(ctx,runtime,node,since,donechan)
out,err:=runtime.GetNodeLogs(ctx,node,since)
iferr!=nil{
// Start loop to check log stream for specified log message.
// We're looping here, as sometimes the containers run into a crash loop, but *may* recover from that
// e.g. when a new server is joining an existing cluster and has to wait for another member to finish learning.
// The logstream returned by docker ends everytime the container restarts, so we have to start from the beginning.
fori:=0;i<backOffLimit;i++{
// get the log stream (reader is following the logstream)
l.Log().Warnf("Node '%s' is restarting for more than a minute now. Possibly it will recover soon (e.g. when it's waiting to join). Consider using a creation timeout to avoid waiting forever in a Restart Loop.",node.Name)
}
}
time.Sleep(500*time.Millisecond)// wait for half a second to avoid overloading docker (error `socket: too many open files`)
out.Close()// no more input on scanner, but target log not yet found -> close current logreader (precautionary)
// we got here, because the logstream ended (no more input on scanner), so we check if maybe the container crashed
ifstrings.Contains(previousline,"level=fatal"){
// case 1: last log line we saw contained a fatal error, so probably it crashed and we want to retry on restart
l.Log().Warnf("warning: encountered fatal log from node %s (retrying %d/%d): %s",node.Name,i,backOffLimit,previousline)
out.Close()
time.Sleep(500*time.Millisecond)
continue
}else{
// case 2: last log line we saw did not contain a fatal error, so we break the loop here and return a generic error
break
}
}
l.Log().Debugf("Finished waiting for log message '%s' from node '%s'",message,node.Name)
}
returnnil
returnfmt.Errorf("error waiting for log line `%s` from node '%s': stopped returning log lines",message,node.Name)
}
}
// NodeFilterByRoles filters a list of nodes by their roles
// NodeFilterByRoles filters a list of nodes by their roles
// ... and still stay within the 64 character limit (e.g. of docker)
constDefaultClusterNameMaxLength=32
// DefaultObjectNamePrefix defines the name prefix for every object created by k3d
constDefaultObjectNamePrefix="k3d"
// DefaultRuntimeLabels specifies a set of labels that will be attached to k3d runtime objects by default
varDefaultRuntimeLabels=map[string]string{
"app":"k3d",
}
// DefaultRuntimeLabelsVar specifies a set of labels that will be attached to k3d runtime objects by default but are not static (e.g. across k3d versions)
varDefaultRuntimeLabelsVar=map[string]string{
"k3d.version":version.GetVersion(),
}
// DefaultRoleCmds maps the node roles to their respective default commands
varDefaultRoleCmds=map[Role][]string{
ServerRole:{"server"},
AgentRole:{"agent"},
}
// DefaultTmpfsMounts specifies tmpfs mounts that are required for all k3d nodes
varDefaultTmpfsMounts=[]string{
"/run",
"/var/run",
}
// DefaultNodeEnv defines some default environment variables that should be set on every node
EnvFixCgroupV2K3DFixEnv="K3D_FIX_CGROUPV2"// EnvFixCgroupV2 is the environment variable that k3d will check for to enable/disable the cgroupv2 workaround
EnvFixCgroupV2K3DFixEnv=k3d.K3dEnvFixCgroupV2// EnvFixCgroupV2 is the environment variable that k3d will check for to enable/disable the cgroupv2 workaround
EnvFixDNSK3DFixEnv="K3D_FIX_DNS"// EnvFixDNS is the environment variable that check for to enable/disable the application of network magic related to DNS
EnvFixDNSK3DFixEnv=k3d.K3dEnvFixDNS// EnvFixDNS is the environment variable that check for to enable/disable the application of network magic related to DNS
// NodeStatusRestarting defines the status string that signals the node container is restarting
// NodeStatusRestarting defines the status string that signals the node container is restarting
constNodeStatusRestarting="restarting"
constNodeStatusRestarting="restarting"
@ -72,6 +47,12 @@ const (
RegistryRoleRole="registry"
RegistryRoleRole="registry"
)
)
typeInternalRoleRole
const(
InternalRoleInitServerInternalRole="initServer"
)
// NodeRoles defines the roles available for nodes
// NodeRoles defines the roles available for nodes
varNodeRoles=map[string]Role{
varNodeRoles=map[string]Role{
string(ServerRole):ServerRole,
string(ServerRole):ServerRole,
@ -92,16 +73,6 @@ var ClusterExternalNodeRoles = []Role{
RegistryRole,
RegistryRole,
}
}
// DefaultRuntimeLabels specifies a set of labels that will be attached to k3d runtime objects by default
varDefaultRuntimeLabels=map[string]string{
"app":"k3d",
}
// DefaultRuntimeLabelsVar specifies a set of labels that will be attached to k3d runtime objects by default but are not static (e.g. across k3d versions)
varDefaultRuntimeLabelsVar=map[string]string{
"k3d.version":version.GetVersion(),
}
// List of k3d technical label name
// List of k3d technical label name
const(
const(
LabelClusterNamestring="k3d.cluster"
LabelClusterNamestring="k3d.cluster"
@ -125,48 +96,6 @@ const (
LabelNodeStaticIPstring="k3d.node.staticIP"
LabelNodeStaticIPstring="k3d.node.staticIP"
)
)
// DefaultRoleCmds maps the node roles to their respective default commands
varDefaultRoleCmds=map[Role][]string{
ServerRole:{"server"},
AgentRole:{"agent"},
}
// DefaultTmpfsMounts specifies tmpfs mounts that are required for all k3d nodes
varDefaultTmpfsMounts=[]string{
"/run",
"/var/run",
}
// DefaultNodeEnv defines some default environment variables that should be set on every node