Skip to content

Commit d2e430b

Browse files
committed
Specify labels/annotations not reflected in VirtualNode API Spec
1 parent af65b10 commit d2e430b

File tree

19 files changed

+139
-98
lines changed

19 files changed

+139
-98
lines changed

apis/virtualkubelet/v1alpha1/virtualnode_types.go

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ type Affinity struct {
3030

3131
// OffloadingPatch contains the information to patch the virtual node.
3232
type OffloadingPatch struct {
33+
// AnnotationsNotReflected is the list of annotations (key) that must not be reflected
34+
AnnotationsNotReflected []string `json:"annotationsNotReflected,omitempty"`
35+
// LabelsNotReflected is the list of labels (key) that must not be reflected
36+
LabelsNotReflected []string `json:"labelsNotReflected,omitempty"`
3337
// NodeSelector contains the node selector to target the remote cluster.
3438
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
3539
// Tolerations contains the tolerations to target the remote cluster.

apis/virtualkubelet/v1alpha1/zz_generated.deepcopy.go

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/liqo-controller-manager/main.go

+17-18
Original file line numberDiff line numberDiff line change
@@ -206,23 +206,21 @@ func main() {
206206

207207
// Options for the virtual kubelet.
208208
virtualKubeletOpts := &forge.VirtualKubeletOpts{
209-
ContainerImage: *kubeletImage,
210-
ExtraAnnotations: kubeletExtraAnnotations.StringMap,
211-
ExtraLabels: kubeletExtraLabels.StringMap,
212-
ExtraArgs: kubeletExtraArgs.StringList,
213-
NodeExtraAnnotations: nodeExtraAnnotations,
214-
NodeExtraLabels: nodeExtraLabels,
215-
RequestsCPU: kubeletCPURequests.Quantity,
216-
RequestsRAM: kubeletRAMRequests.Quantity,
217-
LimitsCPU: kubeletCPULimits.Quantity,
218-
LimitsRAM: kubeletRAMLimits.Quantity,
219-
IpamEndpoint: *kubeletIpamServer,
220-
MetricsAddress: kubeletMetricsAddress,
221-
MetricsEnabled: kubeletMetricsEnabled,
222-
ReflectorsWorkers: reflectorsWorkers,
223-
ReflectorsType: reflectorsType,
224-
LabelsNotReflected: labelsNotReflected.StringList,
225-
AnnotationsNotReflected: annotationsNotReflected.StringList,
209+
ContainerImage: *kubeletImage,
210+
ExtraAnnotations: kubeletExtraAnnotations.StringMap,
211+
ExtraLabels: kubeletExtraLabels.StringMap,
212+
ExtraArgs: kubeletExtraArgs.StringList,
213+
NodeExtraAnnotations: nodeExtraAnnotations,
214+
NodeExtraLabels: nodeExtraLabels,
215+
RequestsCPU: kubeletCPURequests.Quantity,
216+
RequestsRAM: kubeletRAMRequests.Quantity,
217+
LimitsCPU: kubeletCPULimits.Quantity,
218+
LimitsRAM: kubeletRAMLimits.Quantity,
219+
IpamEndpoint: *kubeletIpamServer,
220+
MetricsAddress: kubeletMetricsAddress,
221+
MetricsEnabled: kubeletMetricsEnabled,
222+
ReflectorsWorkers: reflectorsWorkers,
223+
ReflectorsType: reflectorsType,
226224
}
227225

228226
clusterIdentity := clusterIdentityFlags.ReadOrDie()
@@ -435,7 +433,8 @@ func main() {
435433
}
436434

437435
resourceOfferReconciler := resourceoffercontroller.NewResourceOfferController(
438-
mgr, idManager, *resyncPeriod, *offerDisableAutoAccept)
436+
mgr, idManager, *resyncPeriod, *offerDisableAutoAccept,
437+
labelsNotReflected.StringList, annotationsNotReflected.StringList)
439438
if err = resourceOfferReconciler.SetupWithManager(mgr); err != nil {
440439
klog.Fatal(err)
441440
}

cmd/virtual-kubelet/root/flag.go

-3
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,6 @@ func InstallFlags(flags *pflag.FlagSet, o *Opts) {
6363
flags.Var(&o.NodeExtraAnnotations, "node-extra-annotations", "Extra annotations to add to the Virtual Node")
6464
flags.Var(&o.NodeExtraLabels, "node-extra-labels", "Extra labels to add to the Virtual Node")
6565

66-
flags.Var(&o.LabelsNotReflected, "labels-not-reflected", "List of labels (key) that must not be reflected")
67-
flags.Var(&o.AnnotationsNotReflected, "annotations-not-reflected", "List of annotations (key) that must not be reflected")
68-
6966
flags.BoolVar(&o.EnableAPIServerSupport, "enable-apiserver-support", false,
7067
"Enable offloaded pods to interact back with the local Kubernetes API server")
7168
flags.BoolVar(&o.EnableStorage, "enable-storage", false, "Enable the Liqo storage reflection")

cmd/virtual-kubelet/root/opts.go

-6
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ type Opts struct {
101101
// Type of reflection to use for each reflected resource
102102
ReflectorsType map[string]*string
103103

104-
LabelsNotReflected argsutils.StringList
105-
AnnotationsNotReflected argsutils.StringList
106-
107104
NodeLeaseDuration time.Duration
108105
NodePingInterval time.Duration
109106
NodePingTimeout time.Duration
@@ -152,9 +149,6 @@ func NewOpts() *Opts {
152149
ReflectorsWorkers: initReflectionWorkers(),
153150
ReflectorsType: initReflectionType(),
154151

155-
LabelsNotReflected: argsutils.StringList{},
156-
AnnotationsNotReflected: argsutils.StringList{},
157-
158152
NodeLeaseDuration: node.DefaultLeaseDuration * time.Second,
159153
NodePingInterval: node.DefaultPingInterval,
160154
NodePingTimeout: DefaultNodePingTimeout,

cmd/virtual-kubelet/root/root.go

-3
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,6 @@ func runRootCommand(ctx context.Context, c *Opts) error {
162162
HomeAPIServerHost: c.HomeAPIServerHost,
163163
HomeAPIServerPort: c.HomeAPIServerPort,
164164

165-
LabelsNotReflected: c.LabelsNotReflected.StringList,
166-
AnnotationsNotReflected: c.AnnotationsNotReflected.StringList,
167-
168165
OffloadingPatch: vn.Spec.OffloadingPatch,
169166
}
170167

deployments/liqo/crds/virtualkubelet.liqo.io_virtualnodes.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,18 @@ spec:
377377
x-kubernetes-map-type: atomic
378378
type: object
379379
type: object
380+
annotationsNotReflected:
381+
description: AnnotationsNotReflected is the list of annotations
382+
(key) that must not be reflected
383+
items:
384+
type: string
385+
type: array
386+
labelsNotReflected:
387+
description: LabelsNotReflected is the list of labels (key) that
388+
must not be reflected
389+
items:
390+
type: string
391+
type: array
380392
nodeSelector:
381393
additionalProperties:
382394
type: string

docs/usage/reflection.md

+15
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Briefly, the set of supported resources includes (by category):
1010
* [**Configuration**](UsageReflectionConfiguration): *ConfigMaps*, *Secrets*, *ServiceAccounts*
1111
* [**Event**](UsageReflectionEvent): *Events*
1212

13+
(UsageReflectionPolicies)=
14+
1315
## Reflection policies
1416

1517
Liqo implements two different reflection policies:
@@ -40,6 +42,19 @@ liqoctl install ... --set "reflection.secret.workers=0"
4042
```
4143
````
4244

45+
(UsageReflectionLabelsAnnots)=
46+
47+
## Disabling the reflection of specific labels and annotations
48+
49+
In some cases, it could be useful to **not propagate** to the remote clusters some labels/annotations present on reflected resources.
50+
This can be useful to avoid reflecting labels/annotations that lead to conflicts between the local and remote resources (e.g., the ones added by cloud providers and that are tied to the configuration of the hosting cluster), thus **preventing infinite reconciliations** of the reflected resource.
51+
52+
You can disable the reflection of custom labels and annotations by configuring at install-time respectively the Helm values `reflection.skip.labels` and `reflection.skip.annotations` with the list of **keys** that must not be reflected.
53+
To modify the list of not-reflected labels/annotations if Liqo is already installed you can either:
54+
55+
* Patch the individual virtual nodes fields `spec.offloadingPatch.labelsNotReflected` and `spec.offloadingPatch.annotationsNotReflected`.
56+
* Patch the *liqo-controller-manager* args or upgrade Liqo with the new Helm values (but keep in mind that existing virtual nodes will not be updated dynamically, so you should unpeer first and peer again to apply the new changes to existing peers).
57+
4358
(UsageReflectionPods)=
4459

4560
## Pods offloading

pkg/liqo-controller-manager/resourceoffer-controller/controller_config.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ import (
2626
func NewResourceOfferController(
2727
mgr manager.Manager,
2828
identityReader identitymanager.IdentityReader,
29-
resyncPeriod time.Duration, disableAutoAccept bool) *ResourceOfferReconciler {
29+
resyncPeriod time.Duration, disableAutoAccept bool,
30+
labelsNotReflected, annotationsNotReflected []string) *ResourceOfferReconciler {
3031
return &ResourceOfferReconciler{
3132
Client: mgr.GetClient(),
3233
Scheme: mgr.GetScheme(),
3334

34-
identityReader: identityReader,
35-
eventsRecorder: mgr.GetEventRecorderFor("ResourceOffer"),
36-
disableAutoAccept: disableAutoAccept,
37-
resyncPeriod: resyncPeriod,
35+
identityReader: identityReader,
36+
eventsRecorder: mgr.GetEventRecorderFor("ResourceOffer"),
37+
disableAutoAccept: disableAutoAccept,
38+
resyncPeriod: resyncPeriod,
39+
labelsNotReflected: labelsNotReflected,
40+
annotationsNotReflected: annotationsNotReflected,
3841
}
3942
}

pkg/liqo-controller-manager/resourceoffer-controller/resourceoffer_controller.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ type ResourceOfferReconciler struct {
4141
client.Client
4242
Scheme *runtime.Scheme
4343

44-
identityReader identitymanager.IdentityReader
45-
eventsRecorder record.EventRecorder
46-
disableAutoAccept bool
47-
resyncPeriod time.Duration
44+
identityReader identitymanager.IdentityReader
45+
eventsRecorder record.EventRecorder
46+
disableAutoAccept bool
47+
resyncPeriod time.Duration
48+
labelsNotReflected []string
49+
annotationsNotReflected []string
4850
}
4951

5052
//+kubebuilder:rbac:groups=sharing.liqo.io,resources=resourceoffers,verbs=get;list;watch;create;update;patch;delete

pkg/liqo-controller-manager/resourceoffer-controller/resourceoffer_controller_methods.go

+10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/liqotech/liqo/pkg/discovery"
3333
virtualnodectrl "github.com/liqotech/liqo/pkg/liqo-controller-manager/virtualnode-controller"
3434
foreigncluster "github.com/liqotech/liqo/pkg/utils/foreignCluster"
35+
"github.com/liqotech/liqo/pkg/utils/slice"
3536
)
3637

3738
// setControllerReference sets owner reference to the related ForeignCluster.
@@ -126,6 +127,15 @@ func (r *ResourceOfferReconciler) getVirtualNodeMutator(fc *discoveryv1alpha1.Fo
126127
virtualNode.Spec.StorageClasses = resourceOffer.Spec.StorageClasses
127128
virtualNode.Spec.IngressClasses = resourceOffer.Spec.IngressClasses
128129
virtualNode.Spec.LoadBalancerClasses = resourceOffer.Spec.LoadBalancerClasses
130+
131+
if virtualNode.Spec.OffloadingPatch == nil {
132+
virtualNode.Spec.OffloadingPatch = &virtualkubeletv1alpha1.OffloadingPatch{}
133+
}
134+
virtualNode.Spec.OffloadingPatch.AnnotationsNotReflected = slice.Merge(
135+
r.annotationsNotReflected, virtualNode.Spec.OffloadingPatch.AnnotationsNotReflected)
136+
virtualNode.Spec.OffloadingPatch.LabelsNotReflected = slice.Merge(
137+
r.labelsNotReflected, virtualNode.Spec.OffloadingPatch.LabelsNotReflected)
138+
129139
return controllerutil.SetControllerReference(resourceOffer, virtualNode, r.Scheme)
130140
}
131141
}

pkg/liqo-controller-manager/resourceoffer-controller/resourceoffer_controller_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ var _ = Describe("ResourceOffer Controller", func() {
116116
identityReader := fake.NewIdentityReader().Add(remoteClusterIdentity.ClusterID,
117117
testNamespace, kubeconfigSecretName, cluster.GetCfg())
118118

119-
controller = NewResourceOfferController(mgr, identityReader, 10*time.Second, true)
119+
controller = NewResourceOfferController(mgr, identityReader, 10*time.Second, true, []string{}, []string{})
120120
if err := controller.SetupWithManager(mgr); err != nil {
121121
By(err.Error())
122122
os.Exit(1)

pkg/virtualKubelet/forge/forge.go

+19-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"os"
1919
"time"
2020

21+
corev1 "k8s.io/api/core/v1"
2122
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2223

2324
discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1"
@@ -73,14 +74,27 @@ func ApplyOptions() metav1.ApplyOptions {
7374
type ForgingOpts struct {
7475
LabelsNotReflected []string
7576
AnnotationsNotReflected []string
76-
OffloadingPatch *virtualkubeletv1alpha1.OffloadingPatch
77+
NodeSelector map[string]string
78+
Tolerations []corev1.Toleration
79+
Affinity *virtualkubeletv1alpha1.Affinity
7780
}
7881

7982
// NewForgingOpts returns a new ForgingOpts instance.
80-
func NewForgingOpts(labelsNotReflected, annotationsNotReflected []string, offloadingPatch *virtualkubeletv1alpha1.OffloadingPatch) ForgingOpts {
83+
func NewForgingOpts(offloadingPatch *virtualkubeletv1alpha1.OffloadingPatch) ForgingOpts {
84+
if offloadingPatch == nil {
85+
return NewEmptyForgingOpts()
86+
}
87+
8188
return ForgingOpts{
82-
LabelsNotReflected: labelsNotReflected,
83-
AnnotationsNotReflected: annotationsNotReflected,
84-
OffloadingPatch: offloadingPatch,
89+
LabelsNotReflected: offloadingPatch.LabelsNotReflected,
90+
AnnotationsNotReflected: offloadingPatch.AnnotationsNotReflected,
91+
NodeSelector: offloadingPatch.NodeSelector,
92+
Tolerations: offloadingPatch.Tolerations,
93+
Affinity: offloadingPatch.Affinity,
8594
}
8695
}
96+
97+
// NewEmptyForgingOpts returns a new ForgingOpts instance with empty fields.
98+
func NewEmptyForgingOpts() ForgingOpts {
99+
return ForgingOpts{}
100+
}

pkg/virtualKubelet/provider/provider.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ type InitConfig struct {
7979
HomeAPIServerHost string
8080
HomeAPIServerPort string
8181

82-
LabelsNotReflected []string
83-
AnnotationsNotReflected []string
84-
8582
OffloadingPatch *vkalpha1.OffloadingPatch
8683
}
8784

@@ -135,8 +132,10 @@ func NewLiqoProvider(ctx context.Context, cfg *InitConfig, eb record.EventBroadc
135132
}
136133

137134
podreflector := workload.NewPodReflector(cfg.RemoteConfig, remoteMetricsClient, ipamClient, &podReflectorConfig, cfg.ReflectorsConfigs[generic.Pod])
138-
reflectionManager := manager.New(localClient, remoteClient, localLiqoClient, remoteLiqoClient,
139-
cfg.InformerResyncPeriod, eb, cfg.LabelsNotReflected, cfg.AnnotationsNotReflected, cfg.OffloadingPatch).
135+
136+
forgingOpts := forge.NewForgingOpts(cfg.OffloadingPatch)
137+
138+
reflectionManager := manager.New(localClient, remoteClient, localLiqoClient, remoteLiqoClient, cfg.InformerResyncPeriod, eb, &forgingOpts).
140139
With(podreflector).
141140
With(exposition.NewServiceReflector(cfg.ReflectorsConfigs[generic.Service], cfg.EnableLoadBalancer, cfg.RemoteRealLoadBalancerClassName)).
142141
With(exposition.NewIngressReflector(cfg.ReflectorsConfigs[generic.Ingress], cfg.EnableIngress, cfg.RemoteRealIngressClassName)).

pkg/virtualKubelet/reflection/manager/manager.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import (
2626
"k8s.io/client-go/kubernetes"
2727
"k8s.io/client-go/tools/record"
2828
"k8s.io/klog/v2"
29+
"k8s.io/utils/ptr"
2930
"k8s.io/utils/trace"
3031

31-
virtualkubeletv1alpha1 "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1"
3232
liqoclient "github.com/liqotech/liqo/pkg/client/clientset/versioned"
3333
liqoinformers "github.com/liqotech/liqo/pkg/client/informers/externalversions"
3434
traceutils "github.com/liqotech/liqo/pkg/utils/trace"
@@ -62,8 +62,7 @@ type manager struct {
6262

6363
// New returns a new manager to start the reflection towards a remote cluster.
6464
func New(local, remote kubernetes.Interface, localLiqo, remoteLiqo liqoclient.Interface, resync time.Duration,
65-
eb record.EventBroadcaster, labelsNotReflected, annotationsNotReflected []string,
66-
offloadingPatch *virtualkubeletv1alpha1.OffloadingPatch) Manager {
65+
eb record.EventBroadcaster, forgingOpts *forge.ForgingOpts) Manager {
6766
// Configure the field selector to retrieve only the pods scheduled on the current virtual node.
6867
localPodTweakListOptions := func(opts *metav1.ListOptions) {
6968
opts.FieldSelector = fields.OneTermEqualSelector("spec.nodeName", forge.LiqoNodeName).String()
@@ -84,7 +83,7 @@ func New(local, remote kubernetes.Interface, localLiqo, remoteLiqo liqoclient.In
8483
started: false,
8584
stop: make(map[string]context.CancelFunc),
8685

87-
forgingOpts: forge.NewForgingOpts(labelsNotReflected, annotationsNotReflected, offloadingPatch),
86+
forgingOpts: ptr.Deref(forgingOpts, forge.NewEmptyForgingOpts()),
8887
}
8988
}
9089

pkg/virtualKubelet/reflection/manager/manager_test.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
virtualkubeletv1alpha1 "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1"
2828
liqoclient "github.com/liqotech/liqo/pkg/client/clientset/versioned"
2929
liqoclientfake "github.com/liqotech/liqo/pkg/client/clientset/versioned/fake"
30+
"github.com/liqotech/liqo/pkg/virtualKubelet/forge"
3031
reflectionfake "github.com/liqotech/liqo/pkg/virtualKubelet/reflection/generic/fake"
3132
)
3233

@@ -37,15 +38,14 @@ var _ = Describe("Manager tests", func() {
3738
)
3839

3940
var (
40-
mgr Manager
41-
localClient kubernetes.Interface
42-
remoteClient kubernetes.Interface
43-
localLiqoClient liqoclient.Interface
44-
remoteLiqoClient liqoclient.Interface
45-
broadcaster record.EventBroadcaster
46-
labelsNotReflected []string
47-
annotationsNotReflected []string
48-
offloadingPatch *virtualkubeletv1alpha1.OffloadingPatch
41+
mgr Manager
42+
localClient kubernetes.Interface
43+
remoteClient kubernetes.Interface
44+
localLiqoClient liqoclient.Interface
45+
remoteLiqoClient liqoclient.Interface
46+
broadcaster record.EventBroadcaster
47+
offloadingPatch virtualkubeletv1alpha1.OffloadingPatch
48+
forgingOpts forge.ForgingOpts
4949

5050
ctx context.Context
5151
cancel context.CancelFunc
@@ -58,12 +58,12 @@ var _ = Describe("Manager tests", func() {
5858
localLiqoClient = liqoclientfake.NewSimpleClientset()
5959
remoteLiqoClient = liqoclientfake.NewSimpleClientset()
6060
broadcaster = record.NewBroadcaster()
61+
forgingOpts = forge.NewForgingOpts(&offloadingPatch)
6162
})
6263
AfterEach(func() { cancel() })
6364

6465
JustBeforeEach(func() {
65-
mgr = New(localClient, remoteClient, localLiqoClient, remoteLiqoClient, 1*time.Hour, broadcaster,
66-
labelsNotReflected, annotationsNotReflected, offloadingPatch)
66+
mgr = New(localClient, remoteClient, localLiqoClient, remoteLiqoClient, 1*time.Hour, broadcaster, &forgingOpts)
6767
})
6868

6969
Context("a new manager is created", func() {

pkg/virtualKubelet/reflection/workload/podns.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,11 @@ func (npr *NamespacedPodReflector) ForgeShadowPod(ctx context.Context, local *co
331331
saSecretRetriever, ipGetter, npr.config.HomeAPIServerHost, npr.config.HomeAPIServerPort),
332332
forge.ServiceAccountMutator(npr.config.APIServerSupport, local.Annotations))
333333

334-
if forgingOpts.OffloadingPatch != nil {
334+
if forgingOpts != nil {
335335
mutators = append(mutators,
336-
forge.NodeSelectorMutator(forgingOpts.OffloadingPatch.NodeSelector),
337-
forge.TolerationsMutator(forgingOpts.OffloadingPatch.Tolerations),
338-
forge.AffinityMutator(forgingOpts.OffloadingPatch.Affinity))
336+
forge.NodeSelectorMutator(forgingOpts.NodeSelector),
337+
forge.TolerationsMutator(forgingOpts.Tolerations),
338+
forge.AffinityMutator(forgingOpts.Affinity))
339339
}
340340

341341
// Forge the target shadowpod object.

0 commit comments

Comments
 (0)