如何使用 fixed/static NodePort 分配安装 Istio?

How do I install Istio with fixed/static NodePort assignments?

我已经使用以下方法在我的 kubeadm 安装的 Kubernetes 集群上安装了 Istio:

  1. istioctl manifest generate > out.yaml

    此 YAML 文件不包含任何特定的 NodePort。

  2. kubectl apply -f out.yaml

  3. kubectl -n istio-system get service istio-ingressgateway -o yaml

    现在我在 ports 部分看到随机分配的 NodePort 编号,例如:

    [...]
    - name: https
      nodePort: 31680      # <- this is random/dynamically assigned
      port: 443
      protocol: TCP
      targetPort: 443
    [...]
    - name: prometheus
      nodePort: 32646      # <- also this one
      port: 15030
      protocol: TCP
      targetPort: 15030
    [...]
    

Who/what分配这些端口号?这看起来很神奇,我不喜欢 Istio 在我的节点上打开随机端口; 这对我来说是一个安全问题!

我的问题:

我希望有一种方法可以在安装时执行此操作,而不是修补 Istio 动态管理 service/istio-ingressgateway

我发现:

解决您的第一个问题:

这是因为 LoadBalancer 服务类型使用 NodePort。例如,我创建了以下 LoadBalancer 服务:

apiVersion: v1
kind: Service
metadata:
  name: examplelb
spec:
  type: LoadBalancer
  selector:
    app: asd
  ports:
    -
      name: koala
      port: 22223
      targetPort: 22225
    -
      name: grisly
      port: 22224
      targetPort: 22226
    -
      name: polar
      port: 22225
      targetPort: 22227

这是部署后的样子:

$ kubectl apply -f loadbalancer.yaml 
service/examplelb created

$ kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                           AGE
examplelb    LoadBalancer   10.111.8.204    <pending>     22223:31776/TCP,22224:32400/TCP,22225:32539/TCP   6s
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP                                           6d2h
sleep        ClusterIP      10.108.213.84   <none>        80/TCP                                            25h

$ kubectl describe svc examplelb
Name:                     examplelb
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"examplelb","namespace":"default"},"spec":{"ports":[{"name":"koala...
Selector:                 app=asd
Type:                     LoadBalancer
IP:                       10.111.8.204
Port:                     koala  22223/TCP
TargetPort:               22225/TCP
NodePort:                 koala  31776/TCP
Endpoints:                <none>
Port:                     grisly  22224/TCP
TargetPort:               22226/TCP
NodePort:                 grisly  32400/TCP
Endpoints:                <none>
Port:                     polar  22225/TCP
TargetPort:               22227/TCP
NodePort:                 polar  32539/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
$

如您所见,Kubernetes API 自动动态分配每个 NodePort 端口。这在 kubernetes documentation:

中有解释

Type NodePort

If you set the type field to NodePort, the Kubernetes control plane allocates a port from a range specified by --service-node-port-range flag (default: 30000-32767). Each node proxies that port (the same port number on every Node) into your Service. Your Service reports the allocated port in its .spec.ports[*].nodePort field.


这就是为什么在 istio 的默认配置中,例如在您生成的 out.yaml 清单中您可以找到以下 Service 定义:

apiVersion: v1
kind: Service
metadata:
  name: istio-ingressgateway
  namespace: istio-system
  annotations:
  labels:
    app: istio-ingressgateway
    release: istio
    istio: ingressgateway
spec:
  type: LoadBalancer
  selector:
    app: istio-ingressgateway
  ports:
    -
      name: status-port
      port: 15020
      targetPort: 15020
    -
      name: http2
      port: 80
      targetPort: 80
    -
      name: https
      port: 443
    -
      name: kiali
      port: 15029
      targetPort: 15029
    -
      name: prometheus
      port: 15030
      targetPort: 15030
    -
      name: grafana
      port: 15031
      targetPort: 15031
    -
      name: tracing
      port: 15032
      targetPort: 15032
    -
      name: tls
      port: 15443
      targetPort: 15443

这会导致您提到的 NodePort 配置。

根据文档您可以为 NodePort 服务选择特定的端口号。

If you want a specific port number, you can specify a value in the nodePort field. The control plane will either allocate you that port or report that the API transaction failed. This means that you need to take care about possible port collisions yourself. You also have to use a valid port number, one that’s inside the range configured for NodePort use.

Using a NodePort gives you the freedom to set up your own load balancing solution, to configure environments that are not fully supported by Kubernetes, or even to just expose one or more nodes’ IPs directly.

所以通过指定 nodePort:<PORT_NUMBER> 我能够选择一个端口:

apiVersion: v1
kind: Service
metadata:
  name: examplelb
spec:
  type: LoadBalancer
  selector:
    app: asd
  ports:
    -
      name: koala
      port: 22223
      targetPort: 22225
      nodePort: 31913
    -
      name: grisly
      port: 22224
      targetPort: 22226
      nodePort: 31914
    -
      name: polar
      port: 22225
      targetPort: 22227
      nodePort: 31915

结果是:

$ kubectl describe svc examplelb
Name:                     examplelb
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"examplelb","namespace":"default"},"spec":{"ports":[{"name":"koala...
Selector:                 app=asd
Type:                     LoadBalancer
IP:                       10.111.8.204
Port:                     koala  22223/TCP
TargetPort:               22225/TCP
NodePort:                 koala  31913/TCP
Endpoints:                <none>
Port:                     grisly  22224/TCP
TargetPort:               22226/TCP
NodePort:                 grisly  31914/TCP
Endpoints:                <none>
Port:                     polar  22225/TCP
TargetPort:               22227/TCP
NodePort:                 polar  31915/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

解法:

因此,通过添加 nodePort: 注释修改您的 out.yaml 清单,您可以预定义要使用的端口。

希望对您有所帮助。