你知道K8S暴露服务的方式有哪些吗?

发布于 2021-10-11 07:23

Kubernetes支持多种将外部流量引入集群的方法。ClusterIPNodePortIngress是三种广泛使用的资源,它们都在路由流量中发挥作用。每一个都允许您使用一组独特的功能和折衷方案来公开服务。

背景

默认情况下,Kubernetes上运行的服务都是在自己的 Pod 里过着与世隔绝的生活,外部无法打扰他们。我们可以通过创建  Service 使容器供外部世界可见,这个“外部世界” 即可以整个集群、也可以是整个互联网。

Service将流量路由到Pod内的容器中。Service是一种用于在网络上公开Pod的抽象机制。每个Service有一个类型——ClusterIPNodePortLoadBalancer。这些定义了外部流量如何到达服务。

但是光有Service也不行 ,有时候我们需要将不同域名和URL路径上的流量路由到集群内部,这就需要Ingress帮助才行。

ClusterIP

ClusterIP 是默认的Service类型,不指定Type时默认就是ClusterIP类型的ServiceClusterIP在集群内提供网络连接。它通常无法从外部访问。我们将这些ClusterIP Service用于服务之间的内部网络。

apiVersion: v1
kind: Service
spec:
 metadata:
   name: my-service
  selector:
    app: my-app
  type: ClusterIP
  ports:
    - name: http
      port: 80
      targetPort: 8080
      protocol: TCP

上面的示例定义了一个ClusterIP Service。到ClusterIP 上端口 80 的流量将转发到你的Pod 上的端口 8080  (targetPort配置项),携带 app: my-app标签的 Pod 将被添加到 Service中作为作为服务的可用端点。

可以通过运行 kubectl get svc my-service 查看分配的 IP 地址。集群中的其他服务可以使用 10.96.0.1:80 与这个的 Service 管控的服务进行交互。

➜  kubectl get svc app-service
NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE
my-service        ClusterIP   10.96.0.1        <none>        8080:80/TCP       63d

可以使用 spec.clusterIp 字段手动将 ClusterIP 设置为特定 IP 地址:

spec:
  type: ClusterIP
  clusterIp: 123.123.123.123

NodePort

NodePort在固定端口号上公开向集群外部暴露服务,它允许从集群外部访问该服务,在集群外部需要使用集群的 IP 地址和NodePort指定的端口才能访问。创建NodePort Service将在集群中的每个Node上开放该端口。Kubernetes会自动将端口流量路由到它所连接的服务。下面是一个 NodePort Service 的示例:

apiVersion: v1
kind: Service
spec:
 metadata:
   name: my-service
  selector:
    app: my-app
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 8080
      protocol: TCP

NodePort的定义与ClusterIP Service具有相同的属性。唯一的区别是把类型设置成了:"NodePort"。targetPort字段仍然是必需的,因为NodePortClusterIP提供支持。

创建NodePort Service的同时还会自动创建一个ClusterIP 类型的ServiceNodePort会将端口上的流量路由给ClusterIP 类型的 Service。

这也就是为什么下面我们查看NodePort Service时发现他也是有 ClusterIP 的原因:

➜  kubectl get svc my-service
NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE
my-service        NodePort    10.96.44.244     <none>        8080:30176/TCP    56d

使用上述例子创建NodePort ServiceKubernetes将会从30000-32767这个范围随机分配一个端口作为NodePort端口,不过我们可以通过设置ports.nodePort字段来手动指定端口:

spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
      nodePort: 32000
      protocol: TCP

这个会将 32000 端口上的流量通过Service最终路由给Pod里容器的 8080 端口。

您可以使用NodePort快速设置用于开发环境的服务或在其上公开TCPUDP服务,但是对于公开HTTP服务来说NodePort不是一个的理想选择,因为其使用的都是非HTTP标准的端口,我们需要使用其他替代方案。

Ingress

Ingress 实际上是与Service完全不同的资源,算是Service上面的一层代理,通常在 Service前使用Ingress来提供HTTP路由配置。它让我们可以设置外部 URL、基于域名的虚拟主机、SSL 和负载均衡。

Service前面加Ingress,你的集群中需要有Ingress-Controller才行。有多种控制器可供选择。大多数主要的云提供商都有自己的Ingress-Controller,与他们的负载平衡基础设施相集成。如果是自建K8S集群,通常使用nginx-ingress作为控制器,它使用NGINX服务器作为反向代理来把流量路由给后面的Service

关于控制器Nginx-Ingress的安装部署参考:https://kubernetes.github.io/ingress-nginx/deploy/ 后面介绍Ingress实践的文章也会再细说。

可以使用Ingress 资源类型创建Ingress。kubernetes.io/ingress.class 注释可让你指明正在创建的Ingress分类。如果集群里安装了多个Ingress-Controller这将很有用,也可以将不同的Service分别挂在不同分类的Ingress下面,增加一些高可用性。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: my-service
              servicePort: 80
    - host: another-example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: second-service
              servicePort: 80

上面定义了两个Ingress端点。第一个主机规则将 example.com 流量路由到my-service服务上的端口 80。第二条规则将 another-example.com 流量路由到second-service

如果想使用 HTTPs 访问服务,可以通过在Ingress 规范中设置tls字段来配置 SSL

spec:
  tls:
    - hosts:
      - example.com
      - secretName: my-secret

不过前提是在集群中需要通过Secret对象配置这些域名的证书信息。

当需要处理来自多个域名 和 URL 路径的流量时,应该使用Ingress。它让我们可以使用声明性语句配置路由和ServiceIngress控制器将提供你的路由并将它们映射到服务。

总结

ClusterIPNodePortIngress将流量路由到集群中的服务。每一个都是为不同的用例设计的。ClusterIP更多是为集群内服务的通信而设计,某些向集群外部暴露的TCPUDP服务适合使用NodePort。而如果向外暴露的是HTTP服务,且需要提供域名和URL路径路由能力时则需要在Service上面再加一层Ingress做反向代理才行。

可能你对IngressIngress-Controller还是有一点模糊,后面我在写一篇Ingress的实践文章,给大家扫扫盲。

本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。

相关素材