Skip to content
Merged
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
25 changes: 18 additions & 7 deletions 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
fullMode bool
embedded types.Embedded
}

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

Expand Down Expand Up @@ -114,10 +116,16 @@ func (s *kubesolo) run() {
cancel()
}()

profile := "edge"
if s.fullMode {
profile = "full"
}

log.Info().
Str("version", Version).
Str("build-date", BuildDate).
Str("commit", Commit).
Str("profile", profile).
Msg("starting kubesolo...")

log.Info().Str("component", "kubesolo").Msg("ensuring all embedded dependencies are available...")
Expand Down Expand Up @@ -196,7 +204,7 @@ func (s *kubesolo) run() {
{
name: "kubeproxy",
start: func() {
kubeproxyService := kubeproxy.NewService(ctx, cancel, kubeproxyReadyCh, s.embedded.AdminKubeconfigFile)
kubeproxyService := kubeproxy.NewService(ctx, cancel, kubeproxyReadyCh, s.embedded.AdminKubeconfigFile, s.embedded.FullMode)
s.wg.Go(func() {
kubeproxyService.Run(kubeletReadyCh)
})
Expand Down Expand Up @@ -420,12 +428,12 @@ func (s *kubesolo) bootstrap() {
},

// Containerd paths
ContainerdDir: filepath.Join(basePath, types.DefaultContainerdDir),
ContainerdSocketFile: filepath.Join(basePath, types.DefaultContainerdDir, types.DefaultContainerdSocket),
ContainerdBinaryFile: filepath.Join(basePath, types.DefaultContainerdDir, "containerd"),
ContainerdImagesDir: filepath.Join(basePath, types.DefaultContainerdDir, "images"),
ContainerdShimBinaryFile: filepath.Join(basePath, types.DefaultContainerdDir, "containerd-shim-runc-v2"),
ContainerdConfigFile: filepath.Join(basePath, types.DefaultContainerdDir, "config.toml"),
ContainerdDir: filepath.Join(basePath, types.DefaultContainerdDir),
ContainerdSocketFile: filepath.Join(basePath, types.DefaultContainerdDir, types.DefaultContainerdSocket),
ContainerdBinaryFile: filepath.Join(basePath, types.DefaultContainerdDir, "containerd"),
ContainerdImagesDir: filepath.Join(basePath, types.DefaultContainerdDir, "images"),
ContainerdShimBinaryFile: filepath.Join(basePath, types.DefaultContainerdDir, "containerd-shim-runc-v2"),
ContainerdConfigFile: filepath.Join(basePath, types.DefaultContainerdDir, "config.toml"),
ContainerdRootDir: filepath.Join(basePath, types.DefaultContainerdDir, "root"),
ContainerdStateDir: filepath.Join(basePath, types.DefaultContainerdDir, "state"),
ContainerdRegistryConfigDir: filepath.Join(basePath, types.DefaultContainerdDir, "registry"),
Expand Down Expand Up @@ -476,5 +484,8 @@ func (s *kubesolo) bootstrap() {

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

// Full mode
FullMode: s.fullMode,
}
}
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()
Full = Application.Flag("full", "Disable memory-saving overrides and use upstream Kubernetes defaults. Kubesolo still uses NodeSetter in favour of the scheduler. Recommended for CI and developer environments where memory is not constrained. Leave unset for edge deployments.").Envar("KUBESOLO_FULL").Default("false").Bool()
Comment thread
stevensbkang marked this conversation as resolved.
)
56 changes: 29 additions & 27 deletions pkg/kubernetes/apiserver/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,11 @@ func (s *service) configureAPIServerFlags(command *cobra.Command) error {

// networking settings
_ = flags.Set("insecure-port", "0")
_ = flags.Set("secure-port", "6443")
_ = flags.Set("bind-address", "0.0.0.0")
_ = flags.Set("advertise-address", s.nodeIP)
_ = flags.Set("service-cluster-ip-range", types.DefaultServiceClusterIPRange)

// etcd configuration
_ = flags.Set("etcd-servers", types.DefaultKineEndpoint)
_ = flags.Set("etcd-compaction-interval", "5m")
_ = flags.Set("etcd-count-metric-poll-period", "0")
_ = flags.Set("etcd-db-metric-poll-interval", "0")

// security and certificates
_ = flags.Set("cert-dir", s.pkiAPIServerDir)
Expand All @@ -40,33 +35,40 @@ func (s *service) configureAPIServerFlags(command *cobra.Command) error {
_ = flags.Set("proxy-client-cert-file", s.requestHeaderClientCert)
_ = flags.Set("proxy-client-key-file", s.requestHeaderClientKey)

// authorization and admission
// authorization
_ = flags.Set("allow-privileged", "true")
_ = flags.Set("authorization-mode", "Node,RBAC")
_ = flags.Set("enable-admission-plugins", "NodeRestriction,ServiceAccount,ValidatingAdmissionWebhook,MutatingAdmissionWebhook,DefaultStorageClass,CertificateApproval,CertificateSigning,CertificateSubjectRestriction,ValidatingAdmissionPolicy,MutatingAdmissionPolicy")
_ = flags.Set("disable-admission-plugins", "RuntimeClass,PodSecurity,ClusterTrustBundleAttest,DefaultIngressClass,TaintNodesByCondition,DefaultTolerationSeconds,StorageObjectInUseProtection,PersistentVolumeClaimResize,ResourceQuota,LimitRanger,Priority")
_ = flags.Set("enable-bootstrap-token-auth", "false")

// performance and resource limits
_ = flags.Set("max-requests-inflight", "2000")
_ = flags.Set("max-mutating-requests-inflight", "1000")
_ = flags.Set("min-request-timeout", "180")
_ = flags.Set("request-timeout", "900s")
_ = flags.Set("kubelet-timeout", "30s")
_ = flags.Set("watch-cache", "true")
_ = flags.Set("event-ttl", "1h")

// features and garbage collection
_ = flags.Set("enable-garbage-collector", "true")
_ = flags.Set("profiling", "false")

// feature gates - disable SizeBasedListCostEstimate to suppress "Error getting keys" messages
_ = flags.Set("feature-gates", "SizeBasedListCostEstimate=false")

// audit logging
_ = flags.Set("audit-log-path", "-")
_ = flags.Set("audit-log-maxage", "0")
_ = flags.Set("audit-log-maxbackup", "0")
_ = flags.Set("audit-log-maxsize", "0")
// Edge-optimised overrides — only applied when not in full mode.
// When full mode is enabled, upstream Kubernetes defaults are used instead.
if !s.fullMode {
// etcd metric collection
_ = flags.Set("etcd-count-metric-poll-period", "0")
_ = flags.Set("etcd-db-metric-poll-interval", "0")

// request throttling and timeouts
_ = flags.Set("max-requests-inflight", "2000")
_ = flags.Set("max-mutating-requests-inflight", "1000")
_ = flags.Set("min-request-timeout", "180")
_ = flags.Set("request-timeout", "900s")
_ = flags.Set("kubelet-timeout", "30s")

// diagnostics
_ = flags.Set("profiling", "false")

// admission control
_ = flags.Set("enable-admission-plugins", "NodeRestriction,ServiceAccount,ValidatingAdmissionWebhook,MutatingAdmissionWebhook,DefaultStorageClass,CertificateApproval,CertificateSigning,CertificateSubjectRestriction,ValidatingAdmissionPolicy,MutatingAdmissionPolicy")
_ = flags.Set("disable-admission-plugins", "RuntimeClass,PodSecurity,ClusterTrustBundleAttest,DefaultIngressClass,TaintNodesByCondition,DefaultTolerationSeconds,StorageObjectInUseProtection,PersistentVolumeClaimResize,ResourceQuota,LimitRanger,Priority")

// audit logging
_ = flags.Set("audit-log-path", "-")
_ = flags.Set("audit-log-maxage", "0")
_ = flags.Set("audit-log-maxbackup", "0")
_ = flags.Set("audit-log-maxsize", "0")
}

return nil
}
2 changes: 2 additions & 0 deletions pkg/kubernetes/apiserver/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type service struct {
requestHeaderCAFile string
requestHeaderClientCert string
requestHeaderClientKey string
fullMode bool
kubeSoloWebhook *webhook.Service
}

Expand All @@ -51,6 +52,7 @@ func NewService(ctx context.Context, cancel context.CancelFunc, apiServerReady c
requestHeaderCAFile: embedded.RequestHeaderCerts.CACert,
requestHeaderClientCert: embedded.RequestHeaderCerts.ClientCert,
requestHeaderClientKey: embedded.RequestHeaderCerts.ClientKey,
fullMode: embedded.FullMode,
kubeSoloWebhook: webhook.NewService(nodeName, embedded.NodeIP, embedded.PKIDir, embedded.AdminKubeconfigFile, embedded.LoadBalancer),
}
}
84 changes: 41 additions & 43 deletions pkg/kubernetes/controller/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ func (s *service) configureControllerManagerFlags(command *cobra.Command) {
flags := command.Flags()

// controller manager settings
_ = flags.Set("bind-address", "0.0.0.0")
_ = flags.Set("secure-port", "10257")
_ = flags.Set("allocate-node-cidrs", "true")
_ = flags.Set("cluster-cidr", types.DefaultPodCIDR)
_ = flags.Set("v", "0")
_ = flags.Set("service-account-private-key-file", s.serviceAccountKeyFile)
_ = flags.Set("kubeconfig", s.adminKubeconfigFile)
_ = flags.Set("authentication-kubeconfig", s.adminKubeconfigFile)
Expand All @@ -23,50 +20,51 @@ func (s *service) configureControllerManagerFlags(command *cobra.Command) {
_ = flags.Set("tls-cert-file", s.controllerManagerCertFile)
_ = flags.Set("tls-private-key-file", s.controllerManagerKeyFile)
_ = flags.Set("leader-elect", "false")
_ = flags.Set("profiling", "false")
_ = flags.Set("use-service-account-credentials", "true")

// controllers
_ = flags.Set("controllers", "deployment,replicaset,service,serviceaccount,namespace,attachdetach,endpoint,daemonset,statefulset,root-ca-certificate-publisher-controller,serviceaccount-token-controller,node-ipam-controller,endpointslice-controller,persistentvolume-binder-controller,job-controller,cronjob-controller,garbage-collector-controller,disruption,csrsigning,clusterrole-aggregation")
// Edge-optimised overrides — only applied when not in full mode.
// When full mode is enabled, upstream Kubernetes defaults are used instead.
if !s.fullMode {
// controllers
_ = flags.Set("controllers", "deployment,replicaset,service,serviceaccount,namespace,attachdetach,endpoint,daemonset,statefulset,root-ca-certificate-publisher-controller,serviceaccount-token-controller,node-ipam-controller,endpointslice-controller,persistentvolume-binder-controller,job-controller,cronjob-controller,garbage-collector-controller,disruption,csrsigning,clusterrole-aggregation")

// thresholds
_ = flags.Set("terminated-pod-gc-threshold", "20")
_ = flags.Set("large-cluster-size-threshold", "10")
_ = flags.Set("unhealthy-zone-threshold", "0.7")
_ = flags.Set("profiling", "false")
_ = flags.Set("terminated-pod-gc-threshold", "20")
_ = flags.Set("large-cluster-size-threshold", "10")
_ = flags.Set("unhealthy-zone-threshold", "0.7")

// sync settings
_ = flags.Set("concurrent-deployment-syncs", "2")
_ = flags.Set("concurrent-replicaset-syncs", "2")
_ = flags.Set("concurrent-daemonset-syncs", "2")
_ = flags.Set("concurrent-job-syncs", "2")
_ = flags.Set("concurrent-endpoint-syncs", "2")
_ = flags.Set("concurrent-service-endpoint-syncs", "2")
_ = flags.Set("concurrent-gc-syncs", "2")
_ = flags.Set("concurrent-namespace-syncs", "2")
_ = flags.Set("concurrent-cron-job-syncs", "2")
_ = flags.Set("concurrent-horizontal-pod-autoscaler-syncs", "2")
_ = flags.Set("concurrent-rc-syncs", "2")
_ = flags.Set("concurrent-resource-quota-syncs", "2")
_ = flags.Set("concurrent-service-syncs", "2")
_ = flags.Set("concurrent-serviceaccount-token-syncs", "2")
_ = flags.Set("concurrent-statefulset-syncs", "2")
_ = flags.Set("concurrent-ttl-after-finished-syncs", "2")
_ = flags.Set("concurrent-ephemeralvolume-syncs", "2")
_ = flags.Set("concurrent-validating-admission-policy-status-syncs", "2")
_ = flags.Set("mirroring-concurrent-service-endpoint-syncs", "2")
// sync settings
_ = flags.Set("concurrent-deployment-syncs", "2")
_ = flags.Set("concurrent-replicaset-syncs", "2")
_ = flags.Set("concurrent-job-syncs", "2")
_ = flags.Set("concurrent-endpoint-syncs", "2")
_ = flags.Set("concurrent-service-endpoint-syncs", "2")
_ = flags.Set("concurrent-gc-syncs", "2")
_ = flags.Set("concurrent-namespace-syncs", "2")
_ = flags.Set("concurrent-cron-job-syncs", "2")
_ = flags.Set("concurrent-horizontal-pod-autoscaler-syncs", "2")
_ = flags.Set("concurrent-rc-syncs", "2")
_ = flags.Set("concurrent-resource-quota-syncs", "2")
_ = flags.Set("concurrent-service-syncs", "2")
_ = flags.Set("concurrent-serviceaccount-token-syncs", "2")
_ = flags.Set("concurrent-statefulset-syncs", "2")
_ = flags.Set("concurrent-ttl-after-finished-syncs", "2")
_ = flags.Set("concurrent-ephemeralvolume-syncs", "2")
_ = flags.Set("concurrent-validating-admission-policy-status-syncs", "2")
_ = flags.Set("mirroring-concurrent-service-endpoint-syncs", "2")

// sync period
_ = flags.Set("horizontal-pod-autoscaler-sync-period", "60s")
_ = flags.Set("node-monitor-period", "60s")
_ = flags.Set("pvclaimbinder-sync-period", "120s")
_ = flags.Set("resource-quota-sync-period", "15m")
_ = flags.Set("namespace-sync-period", "15m")
_ = flags.Set("route-reconciliation-period", "60s")
_ = flags.Set("attach-detach-reconcile-sync-period", "10m")
_ = flags.Set("node-monitor-grace-period", "300s")
_ = flags.Set("min-resync-period", "12h")
// sync period
_ = flags.Set("horizontal-pod-autoscaler-sync-period", "60s")
_ = flags.Set("node-monitor-period", "60s")
_ = flags.Set("pvclaimbinder-sync-period", "120s")
_ = flags.Set("resource-quota-sync-period", "15m")
_ = flags.Set("namespace-sync-period", "15m")
_ = flags.Set("route-reconciliation-period", "60s")
_ = flags.Set("attach-detach-reconcile-sync-period", "10m")
_ = flags.Set("node-monitor-grace-period", "300s")

// api server interactions
_ = flags.Set("kube-api-qps", "50")
_ = flags.Set("kube-api-burst", "100")
// api server interactions
_ = flags.Set("kube-api-qps", "50")
_ = flags.Set("kube-api-burst", "100")
}
}
2 changes: 2 additions & 0 deletions pkg/kubernetes/controller/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type service struct {
caFile string
adminKubeconfigFile string
serviceAccountKeyFile string
fullMode bool
}

// NewService creates a new controller service
Expand All @@ -33,5 +34,6 @@ func NewService(ctx context.Context, cancel context.CancelFunc, controllerReady
caFile: embedded.CACerts.Cert,
adminKubeconfigFile: embedded.AdminKubeconfigFile,
serviceAccountKeyFile: embedded.ServiceAccountKeyFile,
fullMode: embedded.FullMode,
}
}
88 changes: 38 additions & 50 deletions pkg/kubernetes/kubelet/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,11 @@ func (s *service) writeKubeletConfigFile() error {
}

func (s *service) generateKubeletConfig() map[string]any {
return map[string]any{
"kind": "KubeletConfiguration",
"apiVersion": "kubelet.config.k8s.io/v1beta1",
"enableServer": true,
config := map[string]any{
"kind": "KubeletConfiguration",
"apiVersion": "kubelet.config.k8s.io/v1beta1",

"containerRuntimeEndpoint": "unix://" + s.containerdSockFile,
"imageServiceEndpoint": "unix://" + s.containerdSockFile,

"authentication": map[string]any{
"anonymous": map[string]any{
Expand Down Expand Up @@ -88,52 +86,42 @@ func (s *service) generateKubeletConfig() map[string]any {

"cgroupDriver": cgroupDriver(),

"registerNode": true,
"readOnlyPort": 0,
"port": 10250,
"syncFrequency": "5m0s",
"fileCheckFrequency": "2m0s",
"httpCheckFrequency": "2m0s",
"nodeStatusUpdateFrequency": "60s",
"nodeStatusReportFrequency": "15m0s",
"volumeStatsAggPeriod": "5m0s",
"imageMinimumGCAge": "10m0s",
"imageMaximumGCAge": "0s",
"imageGCHighThresholdPercent": 95,
"imageGCLowThresholdPercent": 80,
"runtimeRequestTimeout": "60s",
"cpuManagerReconcilePeriod": "60s",
"streamingConnectionIdleTimeout": "1h0m0s",
"rotateCertificates": true,

"registerWithTaints": []map[string]any{},

"evictionHard": map[string]string{
"memory.available": "75Mi",
"nodefs.available": "50Mi",
},
"systemReserved": map[string]string{"memory": "25Mi"},
"kubeReserved": map[string]string{"memory": "25Mi"},
"failSwapOn": false,

"kubeAPIQPS": 10,
"kubeAPIBurst": 20,
"serializeImagePulls": true,
"imagePullProgressDeadline": "1m",

"registryPullQPS": 5,
"registryBurst": 10,

"eventRecordQPS": 5,
"eventBurst": 10,
"readOnlyPort": 0,
"rotateCertificates": true,

"containerLogMaxSize": "512Ki",
"enableProfilingHandler": false,
"enableDebugFlagsHandler": false,
"maxPods": 20,
"failSwapOn": false,
}

"featureGates": map[string]bool{
"RotateKubeletServerCertificate": true,
},
// Edge-optimised overrides — only applied when not in full mode.
// When full mode is enabled, upstream Kubernetes defaults are used instead.
if !s.fullMode {
config["enableProfilingHandler"] = false
config["enableDebugFlagsHandler"] = false
config["streamingConnectionIdleTimeout"] = "1h0s"
Comment thread
stevensbkang marked this conversation as resolved.
config["syncFrequency"] = "5m0s"
config["fileCheckFrequency"] = "2m0s"
config["httpCheckFrequency"] = "2m0s"
config["nodeStatusUpdateFrequency"] = "60s"
config["nodeStatusReportFrequency"] = "15m0s"
config["volumeStatsAggPeriod"] = "5m0s"
config["imageMinimumGCAge"] = "10m0s"
config["imageMaximumGCAge"] = "0s"
config["imageGCHighThresholdPercent"] = 95
config["runtimeRequestTimeout"] = "60s"
config["cpuManagerReconcilePeriod"] = "60s"
config["kubeAPIQPS"] = 10
config["kubeAPIBurst"] = 20
config["eventRecordQPS"] = 5
config["eventBurst"] = 10
config["containerLogMaxSize"] = "512Ki"
config["maxPods"] = 20
config["evictionHard"] = map[string]string{
"memory.available": "75Mi",
"nodefs.available": "50Mi",
}
config["systemReserved"] = map[string]string{"memory": "25Mi"}
config["kubeReserved"] = map[string]string{"memory": "25Mi"}
}

return config
}
Loading