Skip to content

Commit

Permalink
[ws-manager-mk2] update to support k8s 0.30 API
Browse files Browse the repository at this point in the history
Without which, we cannot remove the gitpod finalizer, pods do not terminate, and as such, we do not scale down nodes

Tool: gitpod/catfood.gitpod.cloud
  • Loading branch information
kylos101 committed Feb 5, 2025
1 parent d25d928 commit c82bc46
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
49 changes: 46 additions & 3 deletions components/ws-manager-mk2/controllers/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/version"
"k8s.io/utils/pointer"

wsk8s "github.com/gitpod-io/gitpod/common-go/kubernetes"
Expand Down Expand Up @@ -95,7 +96,11 @@ func (r *WorkspaceReconciler) createWorkspacePod(sctx *startWorkspaceContext) (*
}
}

pod, err := createDefiniteWorkspacePod(sctx)
serverVersion, err := r.kubeClient.Discovery().ServerVersion()
if err != nil {
return nil, xerrors.Errorf("cannot get server version: %w", err)
}
pod, err := createDefiniteWorkspacePod(sctx, serverVersion)
if err != nil {
return nil, xerrors.Errorf("cannot create definite workspace pod: %w", err)
}
Expand Down Expand Up @@ -243,7 +248,7 @@ func mergeProbe(dst, src reflect.Value) (err error) {

// createDefiniteWorkspacePod creates a workspace pod without regard for any template.
// The result of this function can be deployed and it would work.
func createDefiniteWorkspacePod(sctx *startWorkspaceContext) (*corev1.Pod, error) {
func createDefiniteWorkspacePod(sctx *startWorkspaceContext, serverVersion *version.Info) (*corev1.Pod, error) {
workspaceContainer, err := createWorkspaceContainer(sctx)
if err != nil {
return nil, xerrors.Errorf("cannot create workspace container: %w", err)
Expand Down Expand Up @@ -278,12 +283,20 @@ func createDefiniteWorkspacePod(sctx *startWorkspaceContext) (*corev1.Pod, error
"prometheus.io/scrape": "true",
"prometheus.io/path": "/metrics",
"prometheus.io/port": strconv.Itoa(int(sctx.IDEPort)),
"container.apparmor.security.beta.kubernetes.io/workspace": "unconfined",
// prevent cluster-autoscaler from removing a node
// https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-types-of-pods-can-prevent-ca-from-removing-a-node
"cluster-autoscaler.kubernetes.io/safe-to-evict": "false",
}

// pre K8s 1.30 we need to set the apparmor profile to unconfined as an annotation
minorVersion, err := strconv.Atoi(serverVersion.Minor)
if err != nil {
return nil, xerrors.Errorf("Failed to convert minor version to integer: %w", err)
}
if minorVersion <= 30 {
annotations["container.apparmor.security.beta.kubernetes.io/workspace"] = "unconfined"
}

for k, v := range sctx.Workspace.Annotations {
annotations[k] = v
}
Expand Down Expand Up @@ -684,6 +697,12 @@ func createDefaultSecurityContext() (*corev1.SecurityContext, error) {
RunAsGroup: &gitpodGUID,
RunAsNonRoot: pointer.Bool(true),
RunAsUser: &gitpodGUID,
// TODO: set AppArmorProfile field here, if the K8s minor version is >= 30
// Ref: https://pkg.go.dev/k8s.io/[email protected]/core/v1#SecurityContext
// and https://pkg.go.dev/k8s.io/[email protected]/core/v1#AppArmorProfile
// and https://pkg.go.dev/k8s.io/[email protected]/core/v1#AppArmorProfileType
//
// requires we update k8s libraries to 0.30.8
}

return res, nil
Expand Down Expand Up @@ -738,3 +757,27 @@ func getRandomString(length int) (string, error) {
}
return string(b), nil
}

// Helper function to compare K8s versions
func isK8sVersionGreaterOrEqual(serverVersion *version.Info, targetVersion string) bool {
serverVersionParts := strings.Split(serverVersion.GitVersion, ".")
targetVersionParts := strings.Split(targetVersion, ".")

// Compare major version
serverMajor := strings.TrimPrefix(serverVersionParts[0], "v")
if serverMajor > targetVersionParts[0] {
return true
}
if serverMajor < targetVersionParts[0] {
return false
}

// Compare minor version
if len(serverVersionParts) > 1 && len(targetVersionParts) > 1 {
if serverVersionParts[1] >= targetVersionParts[1] {
return true
}
}

return false
}
3 changes: 3 additions & 0 deletions components/ws-manager-mk2/controllers/workspace_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -75,6 +76,8 @@ type WorkspaceReconciler struct {
metrics *controllerMetrics
maintenance maintenance.Maintenance
Recorder record.EventRecorder

kubeClient kubernetes.Interface
}

//+kubebuilder:rbac:groups=workspace.gitpod.io,resources=workspaces,verbs=get;list;watch;create;update;patch;delete
Expand Down

0 comments on commit c82bc46

Please sign in to comment.