Skip to content

Commit 7273557

Browse files
committed
[zh] sync blog: nodeport-dynamic-and-static-allocation
1 parent 6c81a35 commit 7273557

File tree

1 file changed

+308
-0
lines changed

1 file changed

+308
-0
lines changed
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
---
2+
layout: blog
3+
title: "Kubernetes 1.27:为 NodePort Service 分配端口时避免冲突"
4+
date: 2023-05-11
5+
slug: nodeport-dynamic-and-static-allocation
6+
---
7+
<!--
8+
layout: blog
9+
title: "Kubernetes 1.27: Avoid Collisions Assigning Ports to NodePort Services"
10+
date: 2023-05-11
11+
slug: nodeport-dynamic-and-static-allocation
12+
-->
13+
14+
<!--
15+
**Author:** Xu Zhenglun (Alibaba)
16+
-->
17+
**作者:** Xu Zhenglun (Alibaba)
18+
19+
**译者:** [Michael Yao](https://github.com/windsonsea) (DaoCloud)
20+
21+
<!--
22+
In Kubernetes, a Service can be used to provide a unified traffic endpoint for
23+
applications running on a set of Pods. Clients can use the virtual IP address (or _VIP_) provided
24+
by the Service for access, and Kubernetes provides load balancing for traffic accessing
25+
different back-end Pods, but a ClusterIP type of Service is limited to providing access to
26+
nodes within the cluster, while traffic from outside the cluster cannot be routed.
27+
One way to solve this problem is to use a `type: NodePort` Service, which sets up a mapping
28+
to a specific port of all nodes in the cluster, thus redirecting traffic from the
29+
outside to the inside of the cluster.
30+
-->
31+
在 Kubernetes 中,对于以一组 Pod 运行的应用,Service 可以为其提供统一的流量端点。
32+
客户端可以使用 Service 提供的虚拟 IP 地址(或 **VIP**)进行访问,
33+
Kubernetes 为访问不同的后端 Pod 的流量提供负载均衡能力,
34+
但 ClusterIP 类型的 Service 仅限于供集群内的节点来访问,
35+
而来自集群外的流量无法被路由。解决这个难题的一种方式是使用 `type: NodePort` Service,
36+
这种服务会在集群所有节点上为特定端口建立映射关系,从而将来自集群外的流量重定向到集群内。
37+
38+
<!--
39+
## How Kubernetes allocates node ports to Services?
40+
41+
When a `type: NodePort` Service is created, its corresponding port(s) are allocated in one
42+
of two ways:
43+
44+
- **Dynamic** : If the Service type is `NodePort` and you do not set a `nodePort`
45+
value explicitly in the `spec` for that Service, the Kubernetes control plane will
46+
automatically allocate an unused port to it at creation time.
47+
48+
- **Static** : In addition to the dynamic auto-assignment described above, you can also
49+
explicitly assign a port that is within the nodeport port range configuration.
50+
-->
51+
## Kubernetes 如何为 Services 分配节点端口?
52+
53+
`type: NodePort` Service 被创建时,其所对应的端口将以下述两种方式之一分配:
54+
55+
- **动态分配**:如果 Service 类型是 `NodePort` 且你没有为 Service 显式设置 `nodePort` 值,
56+
Kubernetes 控制面将在创建时自动为其分配一个未使用的端口。
57+
58+
- **静态分配**:除了上述动态自动分配,你还可以显式指定 nodeport 端口范围配置内的某端口。
59+
60+
<!--
61+
The value of `nodePort` that you manually assign must be unique across the whole cluster.
62+
Attempting to create a Service of `type: NodePort` where you explicitly specify a node port that
63+
was already allocated results in an error.
64+
-->
65+
你手动分配的 `nodePort` 值在整个集群范围内一定不能重复。
66+
如果尝试在创建 `type: NodePort` Service 时显式指定已分配的节点端口,将产生错误。
67+
68+
<!--
69+
## Why do you need to reserve ports of NodePort Service?
70+
71+
Sometimes, you may want to have a NodePort Service running on well-known ports
72+
so that other components and users inside o r outside the cluster can use them.
73+
-->
74+
## 为什么需要保留 NodePort Service 的端口?
75+
76+
有时你可能想要 NodePort Service 运行在众所周知的端口上,
77+
便于集群内外的其他组件和用户可以使用这些端口。
78+
79+
<!--
80+
In some complex cluster deployments with a mix of Kubernetes nodes and other servers on the same network,
81+
it may be necessary to use some pre-defined ports for communication. In particular, some fundamental
82+
components cannot rely on the VIPs that back `type: LoadBalancer` Services
83+
because the virtual IP address mapping implementation for that cluster also relies on
84+
these foundational components.
85+
86+
Now suppose you need to expose a Minio object storage service on Kubernetes to clients
87+
running outside the Kubernetes cluster, and the agreed port is `30009`, we need to
88+
create a Service as follows:
89+
-->
90+
在某些复杂的集群部署场景中在同一网络上混合了 Kubernetes 节点和其他服务器,
91+
可能有必要使用某些预定义的端口进行通信。尤为特别的是,某些基础组件无法使用用来支撑
92+
`type: LoadBalancer` Service 的 VIP,因为针对集群实现的虚拟 IP 地址映射也依赖这些基础组件。
93+
94+
现在假设你需要在 Kubernetes 上将一个 Minio 对象存储服务暴露给运行在 Kubernetes 集群外的客户端,
95+
协商后的端口是 `30009`,我们需要创建以下 Service:
96+
97+
```yaml
98+
apiVersion: v1
99+
kind: Service
100+
metadata:
101+
name: minio
102+
spec:
103+
ports:
104+
- name: api
105+
nodePort: 30009
106+
port: 9000
107+
protocol: TCP
108+
targetPort: 9000
109+
selector:
110+
app: minio
111+
type: NodePort
112+
```
113+
114+
<!--
115+
However, as mentioned before, if the port (30009) required for the `minio` Service is not reserved,
116+
and another `type: NodePort` (or possibly `type: LoadBalancer`) Service is created and dynamically
117+
allocated before or concurrently with the `minio` Service, TCP port 30009 might be allocated to that
118+
other Service; if so, creation of the `minio` Service will fail due to a node port collision.
119+
-->
120+
然而如前文所述,如果 `minio` Service 所需的端口 (30009) 未被预留,
121+
且另一个 `type: NodePort`(或者也包括 `type: LoadBalancer`)Service
122+
在 `minio` Service 之前或与之同时被创建、动态分配,TCP 端口 30009 可能被分配给了这个 Service;
123+
如果出现这种情况,`minio` Service 的创建将由于节点端口冲突而失败。
124+
125+
<!--
126+
## How can you avoid NodePort Service port conflicts?
127+
Kubernetes 1.24 introduced changes for `type: ClusterIP` Services, dividing the CIDR range for cluster
128+
IP addresses into two blocks that use different allocation policies to [reduce the risk of conflicts](/docs/reference/networking/virtual-ips/#avoiding-collisions).
129+
In Kubernetes 1.27, as an alpha feature, you can adopt a similar policy for `type: NodePort` Services.
130+
You can enable a new [feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
131+
`ServiceNodePortStaticSubrange`. Turning this on allows you to use a different port allocation strategy
132+
for `type: NodePort` Services, and reduce the risk of collision.
133+
-->
134+
## 如何才能避免 NodePort Service 端口冲突?
135+
136+
Kubernetes 1.24 引入了针对 `type: ClusterIP` Service 的变更,将集群 IP 地址的 CIDR
137+
范围划分为使用不同分配策略的两块来[减少冲突的风险](/zh-cn/docs/reference/networking/virtual-ips/#avoiding-collisions)。
138+
在 Kubernetes 1.27 中,作为一个 Alpha 特性,你可以为 `type: NodePort` Service 采用类似的策略。
139+
你可以启用新的[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)
140+
`ServiceNodePortStaticSubrange`。开启此门控将允许你为
141+
`type: NodePort` Service 使用不同的端口分配策略,减少冲突的风险。
142+
143+
<!--
144+
The port range for `NodePort` will be divided, based on the formula `min(max(16, nodeport-size / 32), 128)`.
145+
The outcome of the formula will be a number between 16 and 128, with a step size that increases as the
146+
size of the nodeport range increases. The outcome of the formula determine that the size of static port
147+
range. When the port range is less than 16, the size of static port range will be set to 0,
148+
which means that all ports will be dynamically allocated.
149+
150+
Dynamic port assignment will use the upper band by default, once this has been exhausted it will use the lower range.
151+
This will allow users to use static allocations on the lower band with a low risk of collision.
152+
-->
153+
`NodePort` 的端口范围将基于公式 `min(max(16, 节点端口数 / 32), 128)` 进行划分。
154+
这个公式的结果将是一个介于 16 到 128 的数字,随着节点端口范围变大,步进值也会变大。
155+
此公式的结果决定了静态端口范围的大小。当端口范围小于 16 时,静态端口范围的大小将被设为 0,
156+
这意味着所有端口都将被动态分配。
157+
158+
动态端口分配默认使用数值较高的一段,一旦用完,它将使用较低范围。
159+
这将允许用户在冲突风险较低的较低端口段上使用静态分配。
160+
161+
<!--
162+
## Examples
163+
164+
### default range: 30000-32767
165+
| Range properties | Values |
166+
|-------------------------|-------------------------------------------------------|
167+
| service-node-port-range | 30000-32767 |
168+
| Band Offset | &ensp; `min(max(16, 2768/32), 128)` <br>= `min(max(16, 86), 128)` <br>= `min(86, 128)` <br>= 86 |
169+
| Static band start | 30000 |
170+
| Static band end | 30085 |
171+
| Dynamic band start | 30086 |
172+
| Dynamic band end | 32767 |
173+
-->
174+
## 示例
175+
176+
### 默认范围:30000-32767
177+
178+
| 范围属性 | 值 |
179+
| ----------------------- | ----------------------------------------------------------------------------------------------- |
180+
| service-node-port-range | 30000-32767 |
181+
| 分段偏移量 | &ensp; `min(max(16, 2768/32), 128)` <br>= `min(max(16, 86), 128)` <br>= `min(86, 128)` <br>= 86 |
182+
| 起始静态段 | 30000 |
183+
| 结束静态段 | 30085 |
184+
| 起始动态段 | 30086 |
185+
| 结束动态段 | 32767 |
186+
187+
{{< mermaid >}}
188+
pie showData
189+
title 30000-32767
190+
"Static" : 86
191+
"Dynamic" : 2682
192+
{{< /mermaid >}}
193+
194+
<!--
195+
### very small range: 30000-30015
196+
| Range properties | Values |
197+
|-------------------------|-------------------------------------------------------|
198+
| service-node-port-range | 30000-30015 |
199+
| Band Offset | 0 |
200+
| Static band start | - |
201+
| Static band end | - |
202+
| Dynamic band start | 30000 |
203+
| Dynamic band end | 30015 |
204+
-->
205+
### 超小范围:30000-30015
206+
207+
| 范围属性 | 值 |
208+
| ----------------------- | ----------- |
209+
| service-node-port-range | 30000-30015 |
210+
| 分段偏移量 | 0 |
211+
| 起始静态段 | - |
212+
| 结束静态段 | - |
213+
| 起始动态段 | 30000 |
214+
| 动态动态段 | 30015 |
215+
216+
{{< mermaid >}}
217+
pie showData
218+
title 30000-30015
219+
"Static" : 0
220+
"Dynamic" : 16
221+
{{< /mermaid >}}
222+
223+
<!--
224+
### small(lower boundary) range: 30000-30127
225+
| Range properties | Values |
226+
|-------------------------|-------------------------------------------------------|
227+
| service-node-port-range | 30000-30127 |
228+
| Band Offset | &ensp; `min(max(16, 128/32), 128)` <br>= `min(max(16, 4), 128)` <br>= `min(16, 128)` <br>= 16 |
229+
| Static band start | 30000 |
230+
| Static band end | 30015 |
231+
| Dynamic band start | 30016 |
232+
| Dynamic band end | 30127 |
233+
-->
234+
### 小(下边界)范围:30000-30127
235+
236+
| 范围属性 | 值 |
237+
| ---------------------- | --------------------------------------------------------------------------------------------- |
238+
| service-node-port-range | 30000-30127 |
239+
| 分段偏移量 | &ensp; `min(max(16, 128/32), 128)` <br>= `min(max(16, 4), 128)` <br>= `min(16, 128)` <br>= 16 |
240+
| 起始静态段 | 30000 |
241+
| 结束静态段 | 30015 |
242+
| 起始动态段 | 30016 |
243+
| 结束动态段 | 30127 |
244+
245+
{{< mermaid >}}
246+
pie showData
247+
title 30000-30127
248+
"Static" : 16
249+
"Dynamic" : 112
250+
{{< /mermaid >}}
251+
252+
<!--
253+
### large(upper boundary) range: 30000-34095
254+
| Range properties | Values |
255+
|-------------------------|-------------------------------------------------------|
256+
| service-node-port-range | 30000-34095 |
257+
| Band Offset | &ensp; `min(max(16, 4096/32), 128)` <br>= `min(max(16, 128), 128)` <br>= `min(128, 128)` <br>= 128 |
258+
| Static band start | 30000 |
259+
| Static band end | 30127 |
260+
| Dynamic band start | 30128 |
261+
| Dynamic band end | 34095 |
262+
-->
263+
### 大(上边界)范围:30000-34095
264+
265+
| 范围属性 | 值 |
266+
| -----------------------| -------------------------------------------------------------------------------------------------- |
267+
| service-node-port-range | 30000-34095 |
268+
| 分段偏移量 | &ensp; `min(max(16, 4096/32), 128)` <br>= `min(max(16, 128), 128)` <br>= `min(128, 128)` <br>= 128 |
269+
| 起始静态段 | 30000 |
270+
| 结束静态段 | 30127 |
271+
| 起始动态段 | 30128 |
272+
| 结束动态段 | 34095 |
273+
274+
{{< mermaid >}}
275+
pie showData
276+
title 30000-34095
277+
"Static" : 128
278+
"Dynamic" : 3968
279+
{{< /mermaid >}}
280+
281+
<!--
282+
### very large range: 30000-38191
283+
| Range properties | Values |
284+
|-------------------------|-------------------------------------------------------|
285+
| service-node-port-range | 30000-38191 |
286+
| Band Offset | &ensp; `min(max(16, 8192/32), 128)` <br>= `min(max(16, 256), 128)` <br>= `min(256, 128)` <br>= 128 |
287+
| Static band start | 30000 |
288+
| Static band end | 30127 |
289+
| Dynamic band start | 30128 |
290+
| Dynamic band end | 38191 |
291+
-->
292+
### 超大范围:30000-38191
293+
294+
| 范围属性 | 值 |
295+
| ---------------------- | -------------------------------------------------------------------------------------------------- |
296+
| service-node-port-range | 30000-38191 |
297+
| 分段偏移量 | &ensp; `min(max(16, 8192/32), 128)` <br>= `min(max(16, 256), 128)` <br>= `min(256, 128)` <br>= 128 |
298+
| 起始静态段 | 30000 |
299+
| 结束静态段 | 30127 |
300+
| 起始动态段 | 30128 |
301+
| 结束动态段 | 38191 |
302+
303+
{{< mermaid >}}
304+
pie showData
305+
title 30000-38191
306+
"Static" : 128
307+
"Dynamic" : 8064
308+
{{< /mermaid >}}

0 commit comments

Comments
 (0)