Skip to content

Commit 1ab0dce

Browse files
Add port and hostNetwork overrides for calico-webhooks (tigera#4468)
1 parent 17de3c2 commit 1ab0dce

6 files changed

Lines changed: 339 additions & 46 deletions

File tree

api/v1/calico_webhooks_types.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ type CalicoWebhooksDeploymentContainer struct {
3232
// If omitted, the calico-webhooks Deployment will use its default value for this container's resources.
3333
// +optional
3434
Resources *v1.ResourceRequirements `json:"resources,omitempty"`
35+
36+
// Ports allows customization of the calico-webhooks container's ports.
37+
// If specified, this overrides the default container port configuration.
38+
// If omitted, the calico-webhooks Deployment will use its default port (6443).
39+
// +optional
40+
Ports []CalicoWebhooksDeploymentContainerPort `json:"ports,omitempty"`
41+
}
42+
43+
// CalicoWebhooksDeploymentContainerPort defines a port override for a calico-webhooks container.
44+
type CalicoWebhooksDeploymentContainerPort struct {
45+
// Name is an enum which identifies the calico-webhooks Deployment container port by name.
46+
// Supported values are: calico-webhooks
47+
// +kubebuilder:validation:Enum=calico-webhooks
48+
Name string `json:"name"`
49+
50+
// Number of port to expose on the pod's IP address.
51+
// This must be a valid port number, 0 < x < 65536.
52+
// +kubebuilder:validation:Minimum=1
53+
// +kubebuilder:validation:Maximum=65535
54+
ContainerPort int32 `json:"containerPort"`
3555
}
3656

3757
// CalicoWebhooksDeploymentPodSpec is the calico-webhooks Deployment's PodSpec.
@@ -65,6 +85,13 @@ type CalicoWebhooksDeploymentPodSpec struct {
6585
// WARNING: Please note that this field will override the default calico-webhooks Deployment tolerations.
6686
// +optional
6787
Tolerations []v1.Toleration `json:"tolerations"`
88+
89+
// HostNetwork forces the webhook pod to use the host's network namespace.
90+
// When true, the webhook pod will run with hostNetwork=true and DNSPolicy=ClusterFirstWithHostNet.
91+
// When nil or omitted, the operator auto-detects whether host networking is required
92+
// (e.g., for EKS/TKG with Calico CNI).
93+
// +optional
94+
HostNetwork *bool `json:"hostNetwork,omitempty"`
6895
}
6996

7097
// CalicoWebhooksDeploymentPodTemplateSpec is the calico-webhooks Deployment's PodTemplateSpec

api/v1/zz_generated.deepcopy.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/imports/crds/operator/operator.tigera.io_apiservers.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,6 +2592,37 @@ spec:
25922592
enum:
25932593
- calico-webhooks
25942594
type: string
2595+
ports:
2596+
description: |-
2597+
Ports allows customization of the calico-webhooks container's ports.
2598+
If specified, this overrides the default container port configuration.
2599+
If omitted, the calico-webhooks Deployment will use its default port (6443).
2600+
items:
2601+
description:
2602+
CalicoWebhooksDeploymentContainerPort
2603+
defines a port override for a calico-webhooks
2604+
container.
2605+
properties:
2606+
containerPort:
2607+
description: |-
2608+
Number of port to expose on the pod's IP address.
2609+
This must be a valid port number, 0 < x < 65536.
2610+
format: int32
2611+
maximum: 65535
2612+
minimum: 1
2613+
type: integer
2614+
name:
2615+
description: |-
2616+
Name is an enum which identifies the calico-webhooks Deployment container port by name.
2617+
Supported values are: calico-webhooks
2618+
enum:
2619+
- calico-webhooks
2620+
type: string
2621+
required:
2622+
- containerPort
2623+
- name
2624+
type: object
2625+
type: array
25952626
resources:
25962627
description: |-
25972628
Resources allows customization of limits and requests for compute resources such as cpu and memory.
@@ -2658,6 +2689,13 @@ spec:
26582689
- name
26592690
type: object
26602691
type: array
2692+
hostNetwork:
2693+
description: |-
2694+
HostNetwork forces the webhook pod to use the host's network namespace.
2695+
When true, the webhook pod will run with hostNetwork=true and DNSPolicy=ClusterFirstWithHostNet.
2696+
When nil or omitted, the operator auto-detects whether host networking is required
2697+
(e.g., for EKS/TKG with Calico CNI).
2698+
type: boolean
26612699
nodeSelector:
26622700
additionalProperties:
26632701
type: string

pkg/render/common/components/components.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ func GetContainers(overrides any) []corev1.Container {
117117
return valueToContainers(value)
118118
}
119119

120+
func GetHostNetwork(overrides any) *bool {
121+
value := getField(overrides, "Spec", "Template", "Spec", "HostNetwork")
122+
if !value.IsValid() || value.IsNil() {
123+
return nil
124+
}
125+
return value.Interface().(*bool)
126+
}
127+
120128
func GetDNSPolicy(overrides any) (corev1.DNSPolicy, bool) {
121129
value := getField(overrides, "Spec", "Template", "Spec", "DNSPolicy")
122130

@@ -162,13 +170,16 @@ func valueToContainerPorts(v reflect.Value) []corev1.ContainerPort {
162170
if !portOverrides.IsValid() || portOverrides.IsNil() {
163171
return nil
164172
}
165-
customPorts := portOverrides.Interface().([]operator.APIServerDeploymentContainerPort)
166-
ports := make([]corev1.ContainerPort, 0, len(customPorts))
167-
for _, p := range customPorts {
168-
ports = append(ports, corev1.ContainerPort{
169-
Name: p.Name,
170-
ContainerPort: p.ContainerPort,
171-
})
173+
ports := make([]corev1.ContainerPort, 0, portOverrides.Len())
174+
for i := 0; i < portOverrides.Len(); i++ {
175+
p := portOverrides.Index(i)
176+
port := corev1.ContainerPort{
177+
ContainerPort: int32(p.FieldByName("ContainerPort").Int()),
178+
}
179+
if name := p.FieldByName("Name"); name.IsValid() && name.String() != "" {
180+
port.Name = name.String()
181+
}
182+
ports = append(ports, port)
172183
}
173184
return ports
174185
}
@@ -355,6 +366,12 @@ func applyReplicatedPodResourceOverrides(r *replicatedPodResource, overrides any
355366
r.podTemplateSpec.Spec.PriorityClassName = priorityClassName
356367
}
357368

369+
// If `overrides` has a Spec.Template.Spec.HostNetwork field, and it's non-nil, it sets
370+
// `r.podTemplateSpec.Spec.HostNetwork`.
371+
if hostNetwork := GetHostNetwork(overrides); hostNetwork != nil {
372+
r.podTemplateSpec.Spec.HostNetwork = *hostNetwork
373+
}
374+
358375
// If `overrides` has a Spec.Template.Spec.DNSPolicy field, and it's non-empty, it sets
359376
// `r.podTemplateSpec.Spec.DNSPolicy`.
360377
if dnsPolicy, ok := GetDNSPolicy(overrides); ok {

pkg/render/webhooks/render.go

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -97,50 +97,14 @@ func (c *component) Objects() ([]client.Object, []client.Object) {
9797
},
9898
}
9999

100-
// Network policy to allow traffic to/from the webhook pod.
101-
egressRules := networkpolicy.AppendDNSEgressRules(nil, c.cfg.OpenShift)
102-
egressRules = append(egressRules,
103-
v3.Rule{
104-
Action: v3.Allow,
105-
Protocol: &networkpolicy.TCPProtocol,
106-
Destination: networkpolicy.KubeAPIServerEntityRule,
107-
},
108-
v3.Rule{
109-
Action: v3.Pass,
110-
},
111-
)
112-
np := &v3.NetworkPolicy{
113-
TypeMeta: metav1.TypeMeta{Kind: "NetworkPolicy", APIVersion: "projectcalico.org/v3"},
114-
ObjectMeta: metav1.ObjectMeta{
115-
Name: WebhooksPolicyName,
116-
Namespace: common.CalicoNamespace,
117-
},
118-
Spec: v3.NetworkPolicySpec{
119-
Order: &networkpolicy.HighPrecedenceOrder,
120-
Tier: networkpolicy.TigeraComponentTierName,
121-
Selector: networkpolicy.KubernetesAppSelector(WebhooksName),
122-
Types: []v3.PolicyType{v3.PolicyTypeIngress, v3.PolicyTypeEgress},
123-
Ingress: []v3.Rule{
124-
{
125-
Action: v3.Allow,
126-
Protocol: &networkpolicy.TCPProtocol,
127-
Destination: v3.EntityRule{
128-
Ports: networkpolicy.Ports(6443),
129-
},
130-
},
131-
},
132-
Egress: egressRules,
133-
},
134-
}
135-
136100
// Create the correct security context for the webhook container. By default, it should run as non-root, but in Enterprise
137101
// we need to run as root to be able to write audit logs to the host filesystem.
138102
securtyContext := securitycontext.NewNonRootContext()
139103
if c.cfg.Installation.Variant == operatorv1.TigeraSecureEnterprise {
140104
securtyContext = securitycontext.NewRootContext(c.cfg.Installation.KubernetesProvider.IsOpenShift())
141105
}
142106

143-
// Create the Deployment for the webhook.
107+
// Create the Deployment for the webhook with defaults, then apply overrides.
144108
dep := &appsv1.Deployment{
145109
TypeMeta: metav1.TypeMeta{Kind: "Deployment", APIVersion: "apps/v1"},
146110
ObjectMeta: metav1.ObjectMeta{
@@ -213,6 +177,54 @@ func (c *component) Objects() ([]client.Object, []client.Object) {
213177
rcomp.ApplyDeploymentOverrides(dep, overrides)
214178
}
215179

180+
// Set DNSPolicy based on the final HostNetwork value (after overrides).
181+
if dep.Spec.Template.Spec.HostNetwork {
182+
dep.Spec.Template.Spec.DNSPolicy = corev1.DNSClusterFirstWithHostNet
183+
}
184+
185+
// Read the final container port from the deployment (after overrides) for use in the Service.
186+
containerPort := dep.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort
187+
188+
// Network policy to allow traffic to/from the webhook pod. Skip if host networking is
189+
// enabled, since network policy is ineffective for host-networked pods.
190+
var np *v3.NetworkPolicy
191+
if !dep.Spec.Template.Spec.HostNetwork {
192+
egressRules := networkpolicy.AppendDNSEgressRules(nil, c.cfg.OpenShift)
193+
egressRules = append(egressRules,
194+
v3.Rule{
195+
Action: v3.Allow,
196+
Protocol: &networkpolicy.TCPProtocol,
197+
Destination: networkpolicy.KubeAPIServerEntityRule,
198+
},
199+
v3.Rule{
200+
Action: v3.Pass,
201+
},
202+
)
203+
np = &v3.NetworkPolicy{
204+
TypeMeta: metav1.TypeMeta{Kind: "NetworkPolicy", APIVersion: "projectcalico.org/v3"},
205+
ObjectMeta: metav1.ObjectMeta{
206+
Name: WebhooksPolicyName,
207+
Namespace: common.CalicoNamespace,
208+
},
209+
Spec: v3.NetworkPolicySpec{
210+
Order: &networkpolicy.HighPrecedenceOrder,
211+
Tier: networkpolicy.TigeraComponentTierName,
212+
Selector: networkpolicy.KubernetesAppSelector(WebhooksName),
213+
Types: []v3.PolicyType{v3.PolicyTypeIngress, v3.PolicyTypeEgress},
214+
Ingress: []v3.Rule{
215+
{
216+
Action: v3.Allow,
217+
Protocol: &networkpolicy.TCPProtocol,
218+
Destination: v3.EntityRule{
219+
Ports: networkpolicy.Ports(uint16(containerPort)),
220+
},
221+
},
222+
},
223+
Egress: egressRules,
224+
},
225+
}
226+
}
227+
216228
// Create the Service for the webhook.
217229
svc := &corev1.Service{
218230
ObjectMeta: metav1.ObjectMeta{
@@ -224,7 +236,7 @@ func (c *component) Objects() ([]client.Object, []client.Object) {
224236
{
225237
Port: 443,
226238
Protocol: corev1.ProtocolTCP,
227-
TargetPort: intstr.FromInt(6443),
239+
TargetPort: intstr.FromInt32(containerPort),
228240
},
229241
},
230242
Type: corev1.ServiceTypeClusterIP,
@@ -361,7 +373,12 @@ func (c *component) Objects() ([]client.Object, []client.Object) {
361373
},
362374
}
363375

364-
return []client.Object{sa, np, dep, svc, vwc, cr, crb}, nil
376+
objs := []client.Object{sa}
377+
if np != nil {
378+
objs = append(objs, np)
379+
}
380+
objs = append(objs, dep, svc, vwc, cr, crb)
381+
return objs, nil
365382
}
366383

367384
func (c *component) Ready() bool {

0 commit comments

Comments
 (0)