Skip to content

Commit f40c24a

Browse files
authored
Merge pull request kubernetes#2090 from rikatz/port-range
KEP 2079 - Add PortRange KEP
2 parents 2df8338 + d180bf7 commit f40c24a

File tree

2 files changed

+422
-0
lines changed

2 files changed

+422
-0
lines changed
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
# KEP-2079: Network Policy to support Port Ranges
2+
3+
<!-- toc -->
4+
- [Release Signoff Checklist](#release-signoff-checklist)
5+
- [Summary](#summary)
6+
- [Motivation](#motivation)
7+
- [Goals](#goals)
8+
- [Non-Goals](#non-goals)
9+
- [Proposal](#proposal)
10+
- [User Stories](#user-stories)
11+
- [Story 1 - Opening communication to NodePorts of other cluster](#story-1---opening-communication-to-nodeports-of-other-cluster)
12+
- [Story 2 - Blocking the egress for not allowed insecure ports](#story-2---blocking-the-egress-for-not-allowed-insecure-ports)
13+
- [Story 3 - Containerized Passive FTP Server](#story-3---containerized-passive-ftp-server)
14+
- [Notes/Constraints/Caveats](#notesconstraintscaveats)
15+
- [Risks and Mitigations](#risks-and-mitigations)
16+
- [Design Details](#design-details)
17+
- [Validations](#validations)
18+
- [Test Plan](#test-plan)
19+
- [Graduation Criteria](#graduation-criteria)
20+
- [Alpha](#alpha)
21+
- [Beta](#beta)
22+
- [GA Graduation](#ga-graduation)
23+
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
24+
- [Production Readiness Review Questionnaire](#production-readiness-review-questionnaire)
25+
- [Feature Enablement and Rollback](#feature-enablement-and-rollback)
26+
- [Monitoring Requirements](#monitoring-requirements)
27+
- [Dependencies](#dependencies)
28+
- [Scalability](#scalability)
29+
- [Troubleshooting](#troubleshooting)
30+
- [Implementation History](#implementation-history)
31+
- [Drawbacks](#drawbacks)
32+
- [Alternatives](#alternatives)
33+
<!-- /toc -->
34+
35+
## Release Signoff Checklist
36+
37+
Items marked with (R) are required *prior to targeting to a milestone / release*.
38+
39+
- [ ] (R) Enhancement issue in release milestone, which links to KEP dir in [kubernetes/enhancements] (not the initial KEP PR)
40+
- [ ] (R) KEP approvers have approved the KEP status as `implementable`
41+
- [ ] (R) Design details are appropriately documented
42+
- [ ] (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input
43+
- [ ] (R) Graduation criteria is in place
44+
- [ ] (R) Production readiness review completed
45+
- [ ] Production readiness review approved
46+
- [ ] "Implementation History" section is up-to-date for milestone
47+
- [ ] User-facing documentation has been created in [kubernetes/website], for publication to [kubernetes.io]
48+
- [ ] Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
49+
50+
51+
## Summary
52+
53+
Today the `ports` field in ingress and egress network policies is an array
54+
that needs a declaration of each single port to be contemplated. This KEP
55+
proposes to add a new field that allows a declaration of a port range,
56+
simplifying the creation of rules with multiple ports.
57+
58+
## Motivation
59+
60+
NetworkPolicy object is a complex object, that allows a developer to specify
61+
what's the traffic behavior expected of the application and allow/deny
62+
undesired traffic.
63+
64+
There are a number of user issues like [kubernetes #67526](https://github.com/kubernetes/kubernetes/issues/67526)
65+
and [kubernetes #93111](https://github.com/kubernetes/kubernetes/issues/93111)
66+
where users expose the need to create a policy that allow a range of ports but some
67+
specific port, or also cases that a user wants to create a policy that allows
68+
the egress to other cluster to the NodePort range (eg 32000-32768) and in this case,
69+
the rule should be created specifying each port separately, as:
70+
71+
```
72+
spec:
73+
egress:
74+
- ports:
75+
- protocol: TCP
76+
port: 32000
77+
- protocol: TCP
78+
port: 32001
79+
- protocol: TCP
80+
port: 32002
81+
- protocol: TCP
82+
port: 32003
83+
[...]
84+
- protocol: TCP
85+
port: 32768
86+
```
87+
88+
So for the user:
89+
* To allow a range of ports, each of them must be declared as an item from
90+
`ports` array
91+
* To make an exception needs a declaration of all ports but the exception
92+
93+
Adding a new `endPort` field inside the `ports` will allow a simpler
94+
creation of NetworkPolicy to the user.
95+
96+
### Goals
97+
98+
Add an endPort field in `NetworkPolicyPort`
99+
100+
### Non-Goals
101+
102+
* Support specific `Exception` field.
103+
* Support `endPort` when the starting `port` is a named port.
104+
105+
## Proposal
106+
107+
In NetworkPolicy specification, inside `NetworkPolicyPort` specify a new
108+
`endPort` field composed of a numbered port that defines if this is a range
109+
and when it ends.
110+
111+
### User Stories
112+
113+
#### Story 1 - Opening communication to NodePorts of other cluster
114+
115+
I have an application that communicates with NodePorts of a different cluster
116+
and I want to allow the egress of the traffic only the NodePort range
117+
(eg. 30000-32767) as I don't know which port is going to be allocated on the
118+
other side, but don't want to create a rule for each of them.
119+
120+
#### Story 2 - Blocking the egress for not allowed insecure ports
121+
As a developer, I need to create an application that scrapes informations from
122+
multiple sources, being those sources databases running in random ports, web
123+
applications and other sources. But the security policy of my company asks me
124+
to block communication with well known ports, like 111 and 445, so I need to create
125+
a network policy that allows me to communicate with any port except those two and so
126+
I can be compliant with the company's policy.
127+
128+
#### Story 3 - Containerized Passive FTP Server
129+
As a Kubernetes User, I've received a demand from my boss to run our FTP server in an
130+
existing Kubernetes cluster, to support some of my legacy applications.
131+
This FTP Server must be acessible from inside the cluster and outside the cluster,
132+
but I still need to keep the basic security policies from my company, that demands
133+
the existence of a default deny rule for all workloads and allowing only specific ports.
134+
135+
Because this FTP Server runs in PASV mode, I need to open the Network Policy to ports 21
136+
and also to the range 49152-65535 without allowing any other ports.
137+
138+
139+
### Notes/Constraints/Caveats
140+
141+
* The technology used by the CNI provider might not support port range in a
142+
trivial way as described in [#drawbacks]
143+
144+
### Risks and Mitigations
145+
146+
CNIs will need to support the new field in their controllers. For this case
147+
we'll try to make broader communication with the main CNIs so they can be aware
148+
of the new field.
149+
150+
## Design Details
151+
152+
API changes to NetworkPolicy:
153+
* Add a new field called `EndPort` inside `NetworkPolicyPort` as the following:
154+
```
155+
// NetworkPolicyPort describes a port to allow traffic on
156+
type NetworkPolicyPort struct {
157+
// The protocol (TCP, UDP, or SCTP) which traffic must match. If not specified, this
158+
// field defaults to TCP.
159+
// +optional
160+
Protocol *v1.Protocol `json:"protocol,omitempty" protobuf:"bytes,1,opt,name=protocol,casttype=k8s.io/api/core/v1.Protocol"`
161+
162+
// The port on the given protocol. This can either be a numerical or named
163+
// port on a pod. If this field is not provided, this matches all port names and
164+
// numbers, whether an endPort is defined or not.
165+
// +optional
166+
Port *intstr.IntOrString `json:"port,omitempty" protobuf:"bytes,2,opt,name=port"`
167+
168+
// EndPort defines the last port included in the port range.
169+
// Example:
170+
// endPort: 12345
171+
// +optional
172+
EndPort int32 `json:"port,omitempty" protobuf:"bytes,2,opt,name=endPort"`
173+
}
174+
```
175+
176+
### Validations
177+
The `NetworkPolicyPort` will need to be validated, with the following scenarios:
178+
* If an `EndPort` is specified a `Port` must also be specified
179+
* If `Port` is a string (named port) `EndPort` cannot be specified
180+
* `EndPort` must be equal or bigger than `Port`
181+
182+
### Test Plan
183+
184+
Unit tests:
185+
* test API validation logic
186+
* test API strategy to ensure disabled fields
187+
188+
E2E tests:
189+
* Add e2e tests exercising only the API operations for port ranges. Data-path
190+
validation should be done by CNIs.
191+
192+
193+
### Graduation Criteria
194+
195+
#### Alpha
196+
- Add a feature gated new field to NetworkPolicy
197+
- Communicate CNI providers about the new field
198+
- Add validation tests in API
199+
200+
#### Beta
201+
- `EndPort` has been supported for at least 1 minor release
202+
- Four commonly used NetworkPolicy (or CNI providers) implement the new field,
203+
with generally positive feedback on its usage.
204+
- Feature Gate is enabled by Default.
205+
206+
#### GA Graduation
207+
208+
- At least **four** NetworkPolicy providers (or CNI providers) support the `EndPort` field
209+
- `EndPort` has been enabled by default for at least 1 minor release
210+
211+
### Upgrade / Downgrade Strategy
212+
213+
If upgraded no impact should happen as this is a new field.
214+
215+
If downgraded the CNI wont be able to look into the new field, as this does not
216+
exists and network policies using this field will stop working correctly and
217+
start working incorrectly. This is a fail-closed failure, so it is acceptable.
218+
219+
## Production Readiness Review Questionnaire
220+
221+
### Feature Enablement and Rollback
222+
223+
_This section must be completed when targeting alpha to a release._
224+
225+
* **How can this feature be enabled / disabled in a live cluster?**
226+
- [X] Feature gate (also fill in values in `kep.yaml`)
227+
- Feature gate name: NetworkPolicyEndPort
228+
- Components depending on the feature gate: Kubernetes API Server
229+
230+
* **Does enabling the feature change any default behavior?**
231+
No
232+
233+
* **Can the feature be disabled once it has been enabled (i.e. can we roll back
234+
the enablement)?**
235+
Yes, but CNIs relying on the new field wont recognize it anymore
236+
237+
* **What happens if we reenable the feature if it was previously rolled back?**
238+
Nothing. Just need to check if the data is persisted in `etcd` after the
239+
feature is disabled and reenabled or if the data is missed
240+
241+
* **Are there any tests for feature enablement/disablement?**
242+
243+
TBD
244+
245+
### Monitoring Requirements
246+
247+
_This section must be completed when targeting beta graduation to a release._
248+
249+
* **How can an operator determine if the feature is in use by workloads?**
250+
251+
Operators can determine if NetworkPolicies are making use of EndPort creating
252+
an object specifying the range and validating if the traffic is allowed within
253+
the specified range
254+
255+
* **What are the SLIs (Service Level Indicators) an operator can use to determine
256+
the health of the service?**
257+
Operators would need to monitor the traffic of the Pods to verify if a
258+
specified port range is applied and allowed in their workloads
259+
260+
* **What are the reasonable SLOs (Service Level Objectives) for the above SLIs?**
261+
N/A
262+
263+
* **Are there any missing metrics that would be useful to have to improve observability
264+
of this feature?**
265+
N/A
266+
267+
268+
### Dependencies
269+
270+
* **Does this feature depend on any specific services running in the cluster?**
271+
No
272+
273+
274+
### Scalability
275+
276+
_For alpha, this section is encouraged: reviewers should consider these questions
277+
and attempt to answer them._
278+
279+
_For beta, this section is required: reviewers must answer these questions._
280+
281+
_For GA, this section is required: approvers should be able to confirm the
282+
previous answers based on experience in the field._
283+
284+
* **Will enabling / using this feature result in any new API calls?**
285+
TBD
286+
287+
* **Will enabling / using this feature result in introducing new API types?**
288+
No, unless the new `EndPort` is considered a new API type
289+
290+
* **Will enabling / using this feature result in any new calls to the cloud
291+
provider?**
292+
No
293+
294+
* **Will enabling / using this feature result in increasing size or count of
295+
the existing API objects?**
296+
297+
- API type(s): NetworkPolicyPorts
298+
- Estimated increase in size: 2 bytes for each new `EndPort` specified
299+
- Estimated amount of new objects: N/A
300+
301+
* **Will enabling / using this feature result in increasing time taken by any
302+
operations covered by [existing SLIs/SLOs]?**
303+
N/A
304+
305+
* **Will enabling / using this feature result in non-negligible increase of
306+
resource usage (CPU, RAM, disk, IO, ...) in any components?**
307+
It might get some increase of resource usage by the CNI while parsing the
308+
new field.
309+
310+
### Troubleshooting
311+
312+
_This section must be completed when targeting beta graduation to a release._
313+
314+
* **How does this feature react if the API server and/or etcd is unavailable?**
315+
As this feature is mainly used by CNI providers, the reaction with API server
316+
and/or etcd being unavailable will be the same as before.
317+
318+
* **What are other known failure modes?**
319+
N/A
320+
321+
* **What steps should be taken if SLOs are not being met to determine the problem?**
322+
N/A
323+
324+
## Implementation History
325+
- 2020-10-08 Initial [KEP PR](https://github.com/kubernetes/enhancements/pull/2079)
326+
327+
## Drawbacks
328+
329+
* The technology used by the CNI provider might not support port range in a
330+
trivial way. As an example, OpenFlow did not supported to specify port range
331+
for a while as commented in [kubernetes #67526](https://github.com/kubernetes/kubernetes/issues/67526#issuecomment-415170435).
332+
While this has changed in Open vSwitch v1.6, this still might be a caveat
333+
for other CNIs, like eBPF based CNIs will need to populate their maps in a
334+
different way.
335+
336+
For this cases, CNIs will have to iteract through the Port Range and
337+
populate their packet filtering tables with each port.
338+
339+
## Alternatives
340+
341+
During the development of this KEP there was an alternative implementation
342+
of the `NetworkPolicyPortRange` field inside the `NetworkPolicyPort` as the following:
343+
344+
```
345+
// NetworkPolicyPort describes a port or a range of ports to allow traffic on
346+
type NetworkPolicyPort struct {
347+
// The protocol (TCP, UDP, or SCTP) which traffic must match. If not specified, this
348+
// field defaults to TCP.
349+
// +optional
350+
Protocol *api.Protocol
351+
352+
// The port on the given protocol. This can either be a numerical or named
353+
// port on a pod. If this field is not provided but a Range is
354+
// provided, this field is ignored. Otherwise this matches all port names and
355+
// numbers.
356+
// +optional
357+
Port *intstr.IntOrString
358+
359+
// A range of ports on a given protocol and the exceptions. If this field
360+
// is not provided, this doesn't matches anything
361+
// +optional
362+
Range *NetworkPolicyPortRange
363+
}
364+
```
365+
366+
But the main design suggested in this Kep seems more clear, so this alternative
367+
has been discarded.
368+
369+
Also it has been proposed that the implementation contains an `Except` array and a new
370+
struct to be used in Ingress/Egress rules, but because it would bring much more complexity
371+
than desired the proposal has been dropped right now:
372+
373+
```
374+
// NetworkPolicyPortRange describes the range of ports to be used in a
375+
// NetworkPolicyPort struct
376+
type NetworkPolicyPortRange struct {
377+
// From defines the start of the port range
378+
From uint16
379+
380+
// To defines the end of the port range, being the end included within the
381+
// range
382+
To uint16
383+
// Except defines all the exceptions in the port range
384+
+optional
385+
Except []uint16
386+
```

0 commit comments

Comments
 (0)