Skip to content

Commit 9b31e79

Browse files
committed
[ws-manager-mk2] Decide how to apply appamor config based on serverversion to support k8s 1.30+
Tool: gitpod/catfood.gitpod.cloud
1 parent ebd8bc8 commit 9b31e79

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

components/ws-manager-mk2/controllers/create.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
corev1 "k8s.io/api/core/v1"
2222
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2323
"k8s.io/apimachinery/pkg/util/intstr"
24+
"k8s.io/apimachinery/pkg/version"
2425
"k8s.io/utils/pointer"
2526

2627
wsk8s "github.com/gitpod-io/gitpod/common-go/kubernetes"
@@ -62,6 +63,7 @@ type startWorkspaceContext struct {
6263
IDEPort int32 `json:"idePort"`
6364
SupervisorPort int32 `json:"supervisorPort"`
6465
Headless bool `json:"headless"`
66+
ServerVersion *version.Info `json:"serverVersion"`
6567
}
6668

6769
// createWorkspacePod creates the actual workspace pod based on the definite workspace pod and appropriate
@@ -278,12 +280,13 @@ func createDefiniteWorkspacePod(sctx *startWorkspaceContext) (*corev1.Pod, error
278280
"prometheus.io/scrape": "true",
279281
"prometheus.io/path": "/metrics",
280282
"prometheus.io/port": strconv.Itoa(int(sctx.IDEPort)),
281-
"container.apparmor.security.beta.kubernetes.io/workspace": "unconfined",
282283
// prevent cluster-autoscaler from removing a node
283284
// https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-types-of-pods-can-prevent-ca-from-removing-a-node
284285
"cluster-autoscaler.kubernetes.io/safe-to-evict": "false",
285286
}
286287

288+
configureAppamor(sctx, annotations, workspaceContainer)
289+
287290
for k, v := range sctx.Workspace.Annotations {
288291
annotations[k] = v
289292
}
@@ -689,7 +692,7 @@ func createDefaultSecurityContext() (*corev1.SecurityContext, error) {
689692
return res, nil
690693
}
691694

692-
func newStartWorkspaceContext(ctx context.Context, cfg *config.Configuration, ws *workspacev1.Workspace) (res *startWorkspaceContext, err error) {
695+
func newStartWorkspaceContext(ctx context.Context, cfg *config.Configuration, ws *workspacev1.Workspace, serverVersion *version.Info) (res *startWorkspaceContext, err error) {
693696
// we deliberately do not shadow ctx here as we need the original context later to extract the TraceID
694697
span, _ := tracing.FromContext(ctx, "newStartWorkspaceContext")
695698
defer tracing.FinishSpan(span, &err)
@@ -711,9 +714,21 @@ func newStartWorkspaceContext(ctx context.Context, cfg *config.Configuration, ws
711714
IDEPort: 23000,
712715
SupervisorPort: 22999,
713716
Headless: ws.IsHeadless(),
717+
ServerVersion: serverVersion,
714718
}, nil
715719
}
716720

721+
func configureAppamor(sctx *startWorkspaceContext, annotations map[string]string, workspaceContainer *corev1.Container) {
722+
// pre K8s 1.30 we need to set the apparmor profile to unconfined as an annotation
723+
if sctx.ServerVersion.Major <= "1" && sctx.ServerVersion.Minor < "30" {
724+
annotations["container.apparmor.security.beta.kubernetes.io/workspace"] = "unconfined"
725+
} else {
726+
workspaceContainer.SecurityContext.AppArmorProfile = &corev1.AppArmorProfile{
727+
Type: corev1.AppArmorProfileTypeUnconfined,
728+
}
729+
}
730+
}
731+
717732
// validCookieChars contains all characters which may occur in an HTTP Cookie value (unicode \u0021 through \u007E),
718733
// without the characters , ; and / ... I did not find more details about permissible characters in RFC2965, so I took
719734
// this list of permissible chars from Uncyclopedia.

components/ws-manager-mk2/controllers/suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ var _ = BeforeSuite(func() {
107107

108108
conf := newTestConfig()
109109
maintenance := &fakeMaintenance{enabled: false}
110-
wsReconciler, err := NewWorkspaceReconciler(k8sManager.GetClient(), k8sManager.GetScheme(), k8sManager.GetEventRecorderFor("workspace"), &conf, metrics.Registry, maintenance)
110+
wsReconciler, err := NewWorkspaceReconciler(k8sManager.GetClient(), k8sManager.GetConfig(), k8sManager.GetScheme(), k8sManager.GetEventRecorderFor("workspace"), &conf, metrics.Registry, maintenance)
111111
wsMetrics = wsReconciler.metrics
112112
Expect(err).ToNot(HaveOccurred())
113113
Expect(wsReconciler.SetupWithManager(k8sManager)).To(Succeed())

components/ws-manager-mk2/controllers/workspace_controller.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import (
1818
"k8s.io/apimachinery/pkg/runtime"
1919
"k8s.io/apimachinery/pkg/types"
2020
"k8s.io/apimachinery/pkg/util/wait"
21+
"k8s.io/apimachinery/pkg/version"
22+
"k8s.io/client-go/kubernetes"
23+
"k8s.io/client-go/rest"
2124
"k8s.io/client-go/tools/record"
2225
"k8s.io/client-go/util/workqueue"
2326
ctrl "sigs.k8s.io/controller-runtime"
@@ -47,13 +50,20 @@ const (
4750
maintenanceRequeue = 1 * time.Minute
4851
)
4952

50-
func NewWorkspaceReconciler(c client.Client, scheme *runtime.Scheme, recorder record.EventRecorder, cfg *config.Configuration, reg prometheus.Registerer, maintenance maintenance.Maintenance) (*WorkspaceReconciler, error) {
53+
func NewWorkspaceReconciler(c client.Client, restConfig *rest.Config, scheme *runtime.Scheme, recorder record.EventRecorder, cfg *config.Configuration, reg prometheus.Registerer, maintenance maintenance.Maintenance) (*WorkspaceReconciler, error) {
54+
// Create kubernetes clientset
55+
kubeClient, err := kubernetes.NewForConfig(restConfig)
56+
if err != nil {
57+
return nil, fmt.Errorf("failed to create kubernetes client: %w", err)
58+
}
59+
5160
reconciler := &WorkspaceReconciler{
5261
Client: c,
5362
Scheme: scheme,
5463
Config: cfg,
5564
maintenance: maintenance,
5665
Recorder: recorder,
66+
kubeClient: kubeClient,
5767
}
5868

5969
metrics, err := newControllerMetrics(reconciler)
@@ -75,6 +85,8 @@ type WorkspaceReconciler struct {
7585
metrics *controllerMetrics
7686
maintenance maintenance.Maintenance
7787
Recorder record.EventRecorder
88+
89+
kubeClient kubernetes.Interface
7890
}
7991

8092
//+kubebuilder:rbac:groups=workspace.gitpod.io,resources=workspaces,verbs=get;list;watch;create;update;patch;delete
@@ -181,7 +193,8 @@ func (r *WorkspaceReconciler) actOnStatus(ctx context.Context, workspace *worksp
181193
// if there isn't a workspace pod and we're not currently deleting this workspace,// create one.
182194
switch {
183195
case workspace.Status.PodStarts == 0 || workspace.Status.PodStarts-workspace.Status.PodRecreated < 1:
184-
sctx, err := newStartWorkspaceContext(ctx, r.Config, workspace)
196+
serverVersion := r.getServerVersion(ctx)
197+
sctx, err := newStartWorkspaceContext(ctx, r.Config, workspace, serverVersion)
185198
if err != nil {
186199
log.Error(err, "unable to create startWorkspace context")
187200
return ctrl.Result{Requeue: true}, err
@@ -627,6 +640,20 @@ func (r *WorkspaceReconciler) SetupWithManager(mgr ctrl.Manager) error {
627640
Complete(r)
628641
}
629642

643+
func (r *WorkspaceReconciler) getServerVersion(ctx context.Context) *version.Info {
644+
log := log.FromContext(ctx)
645+
646+
serverVersion, err := r.kubeClient.Discovery().ServerVersion()
647+
if err != nil {
648+
log.Error(err, "cannot get server version! Assuming 1.30 going forward")
649+
serverVersion = &version.Info{
650+
Major: "1",
651+
Minor: "30",
652+
}
653+
}
654+
return serverVersion
655+
}
656+
630657
func SetupIndexer(mgr ctrl.Manager) error {
631658
var err error
632659
var once sync.Once

components/ws-manager-mk2/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func main() {
201201
<-mgr.Elected()
202202

203203
workspaceReconciler, err := controllers.NewWorkspaceReconciler(
204-
mgr.GetClient(), mgr.GetScheme(), mgr.GetEventRecorderFor("workspace"), &cfg.Manager, metrics.Registry, maintenanceReconciler)
204+
mgr.GetClient(), mgr.GetConfig(), mgr.GetScheme(), mgr.GetEventRecorderFor("workspace"), &cfg.Manager, metrics.Registry, maintenanceReconciler)
205205
if err != nil {
206206
setupLog.Error(err, "unable to create controller", "controller", "Workspace")
207207
os.Exit(1)

0 commit comments

Comments
 (0)