在Kubernetes中,Pod虽然拥有独立的IP,但会被快速地创建和删除,因此无法直接对外提供服务。而服务(Service)能够解耦前端和后端的关联,从而实现松耦合的微服务设计。本文介绍如何通过控制台和Kubectl创建服务的方式对外发布应用。

控制台操作指导

  1. 登录容器服务管理控制台,在左侧导航栏选择集群
  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择网络 > 服务
  3. 服务页面,单击创建
  4. 创建服务对话框中,配置相关信息。
    配置项描述
    名称设置服务的名称。
    服务类型选择服务类型,即服务访问的方式。包括:
    • 虚拟集群IP:即ClusterIP,通过集群的内部IP暴露服务。选择该值后,服务只能够在集群内部可以访问,此类型为默认的Service类型。
      说明服务类型虚拟集群IP时,支持配置实例间发现服务(Headless Service)。您可以使用无头Service与其他服务发现机制进行接口,无需与Kubernetes的实现捆绑。
    • 节点端口:即NodePort,通过每个Node上的IP和静态端口(NodePort)暴露服务。NodePort服务会路由到ClusterIP服务,该ClusterIP服务会自动创建。通过请求<NodeIP>:<NodePort>,可以从集群的外部访问一个NodePort服务。
      说明 仅ACK集群支持设置节点端口,ASK集群不支持。
    • 负载均衡:即LoadBalancer,阿里云提供的负载均衡服务(SLB),支持选择公网访问或私网访问,可以路由到NodePort服务和ClusterIP服务。
      • 新建SLB:通过单击修改,修改SLB规格。
      • 使用已有SLB: 您可以在已有的列表中选择SLB规格。
      说明 负载均衡类型支持新建SLB和使用已有SLB,且多个Kubernetes Service可以复用同一个SLB,但是存在以下限制:
      • 使用已有的负载均衡实例会强制覆盖已有监听。
      • 通过Service创建的SLB无法复用,可能导致SLB被意外删除。仅支持复用您手动在控制台或调用OpenAPI创建的SLB。
      • 复用同一个SLB的多个Service,避免前端监听端口一致,否则会造成端口冲突。
      • 复用SLB时,Kubernetes将使用监听的名字以及虚拟服务器组的名字将作为唯一标识符。请勿修改监听和虚拟服务器组的名字。
      • 不支持跨集群复用SLB。
    外部流量策略设置外部流量策略。关于外部流量策略详细介绍,请参见外部流量策略功能对比
    • Local:流量只发给本机的Pod。
    • Cluster:流量可以转发到集群中其他节点上的Pod。
    说明 您的服务类型为节点端口负载均衡时,才能设置外部流量策略
    服务关联选择服务要绑定的后端应用。若不进行关联部署,则不会创建相关的Endpoints对象。关于服务关联的详细介绍,请参见services-without-selectors
    端口映射添加服务端口(对应Service YAML文件中的port)和容器端口(对应Service YAML文件中的targetPort),容器端口需要与后端的Pod中暴露的容器端口一致。
    注解为该服务添加一个注解(Annotation),配置负载均衡的参数。支持选择自定义注解阿里云注解。例如,设置service.beta.kubernetes.io/alicloud-loadbalancer-bandwidth:2,表示将该服务的带宽峰值设置为2Mbit/s,从而控制服务的流量。更多参数,请参见通过Annotation配置负载均衡
    标签为该服务添加一个标签,标识该服务。
  5. 单击创建
    服务页面服务列表,可以查看新创建的服务。
    在服务列表操作列,单击目标服务的详情更新删除,对目标服务做相应操作。
    说明 在服务详情页面,您可以单击外部端点后面的链接访问应用。

Kubectl操作指导

Service YAML示例

apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: "intranet"
  labels:
    app: nignx
  name: my-nginx-svc
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer
字段说明
kind定义资源对象为Service。
metadata定义Service的名称、Label和命名空间等基本信息。
metadata.annotations容器服务ACK支持丰富的负载均衡相关的注解(Annotations)。例如,在上面的YAML示例中,service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type指定Service的访问方式为intranet(私网访问)。更多注解,请参见通过Annotation配置负载均衡
spec.selector定义Service的选择器。Service会根据Selector和Pod Label的匹配关系,确定Service所要关联暴露的后端Pod。
spec.ports.port定义Service暴露给ClusterIP的端口,集群内部客户端访问Service的入口,即clusterIP:port
spec.ports.targetPort定义后端Pod的端口。从port进来的流量,经由kube-proxy流入到后端Pod的targetPort上,最后进入容器。
spec.type定义Service的被访问方式。
  • LoadBalancer:使用阿里云负载均衡SLB公开服务。当Service没有指定已有SLB时,默认创建的SLB实例类型为公网。您可以通过设置注解service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-typeintranet,来创建私网访问的Service以及相应的私网SLB。更多信息,请参见通过使用已有SLB的服务公开应用通过使用自动创建SLB的服务公开应用
  • ClusterIP:在集群内部公开服务,可用于集群内部访问。
  • NodePort:使用节点的端口映射到后端Service,集群外可以通过节点IP:NodePort访问。
  • ExternalName:将服务映射到DNS。

创建Service

  1. 参考以上Service YAML示例,创建Service YAML文件。
    下文以创建名为my-nginx-svc.yaml的Service YAML文件为例进行说明。
  2. 通过Kubectl或CloudShell方式连接集群。详细操作,请参见获取集群KubeConfig并通过kubectl工具连接集群在CloudShell上通过kubectl管理Kubernetes集群
  3. 执行以下命令,创建Service。
    kubectl apply -f my-nginx-svc.yaml
  4. 执行以下命令,验证服务是否创建成功。
    kubectl get svc my-nginx-svc

    预期输出:

    NAME           TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)        AGE
    my-nginx-svc   LoadBalancer   172.21.XX.XX   192.168.XX.XX     80:31599/TCP   5m

更新Service

  • 方式1:执行以下命令,更新Service。
    kubectl edit service my-nginx-svc
  • 方式2:手动删除旧的Service,修改YAML文件后,重新创建Service。
    kubectl apply -f my-nginx-svc.yaml

查看Service

执行以下命令,查看Service。

kubectl get service my-nginx-svc

预期输出:

NAME           TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)        AGE
my-nginx-svc   LoadBalancer   172.21.XX.XX   192.168.XX.XX     80:31599/TCP   5m

删除Service

执行以下命令,删除Service。
kubectl delete service my-nginx-svc

外部流量策略功能对比

集群中使用的网络插件不同,外部流量策略功能不同,以下介绍Terway-Eniip和Flannel网络插件的外部流量策略功能对比。
说明 登录容器服务管理控制台,在集群列表页面单击目标集群的名称,在基本信息页签下集群信息区域可以查看集群的网络模式。

Flannel网络插件

Flannel网络插件下,流量经由节点的NodePort转发到Pod中。
  • Local:流量只转发给本机的Pod。
  • Cluster:流量可以转发到集群中其他节点上的Pod。
外部流量策略

Local和Cluster两种外部流量策略详细的区别如下表所示。

比较项LocalCluster
负载均衡后端挂载行为仅Pod所在的节点会挂载到负载均衡后端。所有集群内的节点都将挂载到负载均衡后端。
负载均衡配额负载均衡配额消耗较少。关于负载均衡配额的详细介绍,请参见配额限制由于集群内所有节点都挂载到负载均衡后端,因此会大量消耗负载均衡配额。关于负载均衡配额的详细介绍,请参见配额限制
访问负载均衡地址仅Pod所在节点可以访问负载均衡地址。集群内任意节点均可访问负载均衡地址。
Pod负载均衡

默认Pod之间负载不均衡。

如果您想要实现Pod之间负载均衡,需要指定策略为wrr,即为Service添加service.beta.kubernetes.io/alibaba-cloud-loadbalancer-scheduler:"wrr" annotation。

默认Pod之间负载均衡。
保留来源IP支持。不支持。
会话保持支持。不支持。

Terway-Eniip网络插件

Terway-Eniip网络插件下,无论是Local和Cluster,流量直接转发到Pod中。

terway

Local和Cluster两种外部流量策略详细的区别如下表所示。

比较项LocalCluster
负载均衡后端挂载行为Pod直接挂载到负载均衡后端。
负载均衡配额仅挂载业务Pod,负载均衡配额消耗较少。关于负载均衡配额的详细介绍,请参见配额限制
访问负载均衡地址仅Pod所在节点可以访问负载均衡地址。集群内任意节点均可访问负载均衡地址。
Pod负载均衡默认Pod之间负载均衡。
保留来源IP支持。
会话保持支持。