Move all klipper-lb daemonset to common namespace for PodSecurity

The baseline PodSecurity profile will reject klipper-lb pods from running.
Since klipper-lb pods are put in the same namespace as the Service this
means users can not use PodSecurity baseline profile in combination with
the k3s servicelb.

The solution is to move all klipper-lb pods to a klipper-lb-system where
the security policy of the klipper-lb pods can be different an uniformly
managed.

Signed-off-by: Darren Shepherd <darren@acorn.io>
This commit is contained in:
Darren Shepherd 2022-06-08 21:39:03 -07:00 committed by Brad Davidson
parent 12695cea15
commit f4cc1b8788

View File

@ -34,6 +34,7 @@ import (
var (
svcNameLabel = "svccontroller." + version.Program + ".cattle.io/svcname"
svcNamespaceLabel = "svccontroller." + version.Program + ".cattle.io/svcnamespace"
daemonsetNodeLabel = "svccontroller." + version.Program + ".cattle.io/enablelb"
daemonsetNodePoolLabel = "svccontroller." + version.Program + ".cattle.io/lbpool"
nodeSelectorLabel = "svccontroller." + version.Program + ".cattle.io/nodeselector"
@ -41,8 +42,9 @@ var (
)
const (
Ready = condition.Cond("Ready")
ControllerName = "svccontroller"
Ready = condition.Cond("Ready")
ControllerName = "svccontroller"
KlipperNamespace = "klipper-lb-system"
)
var (
@ -81,7 +83,7 @@ func Register(ctx context.Context,
pods,
endpoints)
return nil
return createOrDeleteKlipperNamespace(ctx, enabled, kubernetes)
}
type handler struct {
@ -98,6 +100,24 @@ type handler struct {
recorder record.EventRecorder
}
func createOrDeleteKlipperNamespace(ctx context.Context, enabled bool, k8s kubernetes.Interface) error {
_, err := k8s.CoreV1().Namespaces().Get(ctx, KlipperNamespace, meta.GetOptions{})
if !apierrors.IsNotFound(err) {
return err
}
if enabled {
_, err := k8s.CoreV1().Namespaces().Create(ctx, &core.Namespace{
ObjectMeta: meta.ObjectMeta{
Name: KlipperNamespace,
},
}, meta.CreateOptions{})
return err
}
return k8s.CoreV1().Namespaces().Delete(ctx, KlipperNamespace, meta.DeleteOptions{})
}
func (h *handler) onResourceChange(name, namespace string, obj runtime.Object) ([]relatedresource.Key, error) {
if ep, ok := obj.(*core.Endpoints); ok {
return []relatedresource.Key{
@ -118,6 +138,11 @@ func (h *handler) onResourceChange(name, namespace string, obj runtime.Object) (
return nil, nil
}
serviceNamespace := pod.Labels[svcNamespaceLabel]
if serviceNamespace == "" {
return nil, nil
}
if pod.Status.PodIP == "" {
return nil, nil
}
@ -125,7 +150,7 @@ func (h *handler) onResourceChange(name, namespace string, obj runtime.Object) (
return []relatedresource.Key{
{
Name: serviceName,
Namespace: pod.Namespace,
Namespace: serviceNamespace,
},
}, nil
}
@ -136,12 +161,6 @@ func (h *handler) onChangeService(key string, svc *core.Service) (*core.Service,
return nil, nil
}
if svc.Spec.Type != core.ServiceTypeLoadBalancer || svc.Spec.ClusterIP == "" || svc.Spec.ClusterIP == "None" {
// If the Service type changes from LoadBalancer to something else, make sure we remove the DaemonSet
err := h.deletePod(svc)
return svc, err
}
if err := h.deployPod(svc); err != nil {
return svc, err
}
@ -175,8 +194,9 @@ func (h *handler) updateService(svc *core.Service) (runtime.Object, error) {
return svc, nil
}
pods, err := h.podCache.List(svc.Namespace, labels.SelectorFromSet(map[string]string{
svcNameLabel: svc.Name,
pods, err := h.podCache.List(KlipperNamespace, labels.SelectorFromSet(map[string]string{
svcNameLabel: svc.Name,
svcNamespaceLabel: svc.Namespace,
}))
if err != nil {
@ -329,21 +349,6 @@ func filterByIPFamily(ips []string, svc *core.Service) ([]string, error) {
return nil, errors.New("unhandled ipFamilyPolicy")
}
// deletePod ensures that there is not a DaemonSet for the service.
func (h *handler) deletePod(svc *core.Service) error {
name := fmt.Sprintf("svclb-%s", svc.Name)
ds, err := h.daemonsets.DaemonSets(svc.Namespace).Get(context.TODO(), name, meta.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return nil
}
return err
}
h.recorder.Eventf(svc, core.EventTypeNormal, "DeletedDaemonSet", "Deleted LoadBalancer DaemonSet %s/%s", ds.Namespace, ds.Name)
objs := objectset.NewObjectSet()
return h.processor.WithOwner(svc).Apply(objs)
}
// deployPod ensures that there is a DaemonSet for the service.
// It also ensures that any legacy Deployments from older versions of ServiceLB are deleted.
func (h *handler) deployPod(svc *core.Service) error {
@ -351,7 +356,7 @@ func (h *handler) deployPod(svc *core.Service) error {
return err
}
objs := objectset.NewObjectSet()
if !h.enabled {
if !h.enabled || svc.Spec.Type != core.ServiceTypeLoadBalancer || svc.Spec.ClusterIP == "" || svc.Spec.ClusterIP == "None" {
return h.processor.WithOwner(svc).Apply(objs)
}
@ -369,7 +374,7 @@ func (h *handler) deployPod(svc *core.Service) error {
// newDaemonSet creates a DaemonSet to ensure that ServiceLB pods are run on
// each eligible node.
func (h *handler) newDaemonSet(svc *core.Service) (*apps.DaemonSet, error) {
name := fmt.Sprintf("svclb-%s", svc.Name)
name := fmt.Sprintf("svclb-%s-%s", svc.Name, svc.UID[:8])
oneInt := intstr.FromInt(1)
// If ipv6 is present, we must enable ipv6 forwarding in the manifest
@ -383,16 +388,7 @@ func (h *handler) newDaemonSet(svc *core.Service) (*apps.DaemonSet, error) {
ds := &apps.DaemonSet{
ObjectMeta: meta.ObjectMeta{
Name: name,
Namespace: svc.Namespace,
OwnerReferences: []meta.OwnerReference{
{
Name: svc.Name,
APIVersion: "v1",
Kind: "Service",
UID: svc.UID,
Controller: &trueVal,
},
},
Namespace: KlipperNamespace,
Labels: map[string]string{
nodeSelectorLabel: "false",
},
@ -410,8 +406,9 @@ func (h *handler) newDaemonSet(svc *core.Service) (*apps.DaemonSet, error) {
Template: core.PodTemplateSpec{
ObjectMeta: meta.ObjectMeta{
Labels: map[string]string{
"app": name,
svcNameLabel: svc.Name,
"app": name,
svcNameLabel: svc.Name,
svcNamespaceLabel: svc.Namespace,
},
},
Spec: core.PodSpec{