Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion cmd/kubesolo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type kubesolo struct {
loadBalancer bool
localStorage bool
localStorageSharedPath string
disableIPv6 bool
embedded types.Embedded
}

Expand All @@ -74,6 +75,7 @@ func service() (*kubesolo, error) {
loadBalancer: *flags.LoadBalancer,
localStorage: *flags.LocalStorage,
localStorageSharedPath: *flags.LocalStorageSharedPath,
disableIPv6: *flags.DisableIPv6,
}, nil
}

Expand Down Expand Up @@ -207,7 +209,7 @@ func (s *kubesolo) run() {
}

log.Info().Str("component", "kubesolo").Msg("deploying coredns...")
if err := coredns.Deploy(s.embedded.AdminKubeconfigFile); err != nil {
if err := coredns.Deploy(s.embedded.AdminKubeconfigFile, s.embedded.DisableIPv6); err != nil {
log.Fatal().Err(err).Msg("failed to deploy coredns")
}

Expand Down Expand Up @@ -453,5 +455,8 @@ func (s *kubesolo) bootstrap() {

// Portainer Edge
IsPortainerEdge: s.portainerEdgeID != "" && s.portainerEdgeKey != "",

// IPv6
DisableIPv6: s.disableIPv6,
}
}
1 change: 1 addition & 0 deletions internal/config/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ var (
LocalStorageSharedPath = Application.Flag("local-storage-shared-path", "Path to the shared file system for the local storage. Defaults to empty string.").Envar("KUBESOLO_LOCAL_STORAGE_SHARED_PATH").Default("").String()
Debug = Application.Flag("debug", "Enable debug logging. Defaults to false.").Envar("KUBESOLO_DEBUG").Default("false").Bool()
PprofServer = Application.Flag("pprof-server", "Enable pprof server. Defaults to false.").Envar("KUBESOLO_PPROF_SERVER").Default("false").Bool()
DisableIPv6 = Application.Flag("disable-ipv6", "Disable IPv6 support. When set, CoreDNS will not serve ip6.arpa reverse zones and kubelet will register with an explicit IPv4 node address. Defaults to false.").Envar("KUBESOLO_DISABLE_IPV6").Default("false").Bool()
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flag help text says kubelet will only register with an explicit IPv4 node address when this flag is set, but the current kubelet args unconditionally set --node-ip. Either make kubelet’s --node-ip conditional on DisableIPv6, or adjust this description to match the actual behavior.

Copilot uses AI. Check for mistakes.
)
32 changes: 28 additions & 4 deletions pkg/components/coredns/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,25 @@ import (
"k8s.io/client-go/kubernetes"
)

// CoreDNSConfig contains minimal CoreDNS Corefile configuration
const CoreDNSConfig = `.:53 {
const coreDNSConfigIPv4Only = `.:53 {
errors
loop
cache 30 {
disable denial cluster.local
}
kubernetes cluster.local in-addr.arpa {
pods insecure
fallthrough in-addr.arpa
ttl 30
}
forward . /etc/resolv.conf
minimal
reload
health :8080
ready :8181
}`

const coreDNSConfigDualStack = `.:53 {
errors
loop
cache 30 {
Expand All @@ -28,18 +45,25 @@ const CoreDNSConfig = `.:53 {
ready :8181
}`

func coreDNSConfig(disableIPv6 bool) string {
if disableIPv6 {
return coreDNSConfigIPv4Only
}
return coreDNSConfigDualStack
}

// createConfigMap creates a configMap with the bare minimum CoreDNS configuration
// it creates a new configmap if it does not exist
// it updates the configmap if it already exists
// it returns an error if it fails
func createConfigMap(ctx context.Context, clientset *kubernetes.Clientset) error {
func createConfigMap(ctx context.Context, clientset *kubernetes.Clientset, disableIPv6 bool) error {
configMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: coreDNSConfigMapName,
Namespace: coreDNSNamespace,
},
Data: map[string]string{
"Corefile": CoreDNSConfig,
"Corefile": coreDNSConfig(disableIPv6),
},
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/components/coredns/coredns.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const (
)

// Deploy deploys all the necessary Kubernetes resources for CoreDNS
func Deploy(adminKubeconfig string) error {
func Deploy(adminKubeconfig string, disableIPv6 bool) error {
time.Sleep(types.DefaultComponentSleep)

ctx, cancel := context.WithTimeout(context.Background(), types.DefaultContextTimeout)
Expand All @@ -33,7 +33,7 @@ func Deploy(adminKubeconfig string) error {
return fmt.Errorf("failed to create kubernetes client: %v", err)
}

if err := createConfigMap(ctx, clientset); err != nil {
if err := createConfigMap(ctx, clientset, disableIPv6); err != nil {
Comment on lines 24 to +36
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the exported coredns.Deploy signature to add a positional bool parameter is a breaking API change and the call site doesn’t self-document what true/false means. Consider using an options struct (e.g., Deploy(adminKubeconfig string, opts DeployOptions)) or a separate helper like DeployIPv4Only(...) to keep the API clearer and easier to extend without adding more boolean parameters.

Copilot uses AI. Check for mistakes.
return fmt.Errorf("failed to create CoreDNS ConfigMap: %v", err)
}

Expand Down
1 change: 1 addition & 0 deletions pkg/kubernetes/kubelet/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ func (s *service) configureKubeletArgs(command *cobra.Command) {
command.SetArgs([]string{
"--config", s.kubeletConfigFile,
"--hostname-override", s.nodeName,
"--node-ip", s.nodeIP,
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--node-ip is now always set. This changes kubelet behavior even when --disable-ipv6 is not enabled and will break IPv6-only hosts (it will force 127.0.0.1 from GetNodeIP() when no IPv4 exists). Consider only adding --node-ip when the new disable-IPv6 mode is enabled (e.g., plumb DisableIPv6 into the kubelet service) or otherwise allow kubelet to auto-select the appropriate node IP in dual-stack/IPv6 setups.

Suggested change
"--node-ip", s.nodeIP,

Copilot uses AI. Check for mistakes.
"--root-dir", s.kubeletDir,
"--kubeconfig", s.kubeletKubeConfigFile,
})
Expand Down
3 changes: 3 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ type Embedded struct {

// Portainer Edge
IsPortainerEdge bool

// IPv6
DisableIPv6 bool
}

// EdgeAgentConfig contains configuration for Portainer Edge Agent
Expand Down