在之前的文章 通过 Service 访问 Pod 集群 中,学习了两种方法做 pod 负载,分别是 ClusterIPNodePort ,也提到了 LoadBalancer,仅仅是提了一嘴。

在正常的生产环境中,当使用了 NodePort 类型暴露服务时,每台集群节点的 nodeport 端口都能够去访问,如果想要通过一个入口访问到集群内部的服务,并可以做到每个节点负载时,就可以通过常规的负载服务使用域名负载,如:nginx、LVS、Haproxy、阿里云SLB等。

这样就面临了一个问题,当集群内有多数服务,暴露大量端口时,需要手动一个个的去添加到负载服务中去,增加了运维成本。这种情况就可以使用 LoadBalancer 来解决,唯一的缺点是,该方式不支持开源的负载服务,也就是只能使用公有云的负载ip

作用

与 NodePort 类似,在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes 会请求底层云平台上的负载均衡器,将每个 Node(NodeIP:NodePort)作为后端添加进去

使用公有云的负载时会有一个控制器,当在集群种创建了 LoadBalancer 类型的 Service 时,会被自动发现并添加到负载中。

当服务 type 设置为 LoadBalancer 时,Kubernetes 向集群中的 Pod 提供的功能等同于 type 等于 ClusterIP,并通过使用 Kubernetes pod 的条目对负载均衡器(从外部到 Kubernetes) 进行编程来扩展它。 Kubernetes 服务控制器自动创建外部负载均衡器、健康检查(如果需要)、防火墙规则(如果需要), 并获取云提供商分配的外部 IP 并将其填充到服务对象中。

缺点

仅支持当 Kubernetes 集群在公有云的环境中。当然也有插件可以在非公有云环境支持 LoadBalancer。

以下操作都在公有云服务进行

创建 LoadBalancer 的 service

对于云上的服务来说,只要指定 type 为 LoadBalancer,创建好之后会获取一个临时的公网 ip 来提供访问,临时的时间可以参考云上服务的,按量付费,也可以通过每个云厂商中的 annotations 来配置,需要参考云厂商对于 LoadBalancer 的文档。

apiVersion: v1
kind: Service
metadata:
  name: example
  namespace: test
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local 
  # 表示当客户端访问时,日志中依旧显示客户端ip
  selector:
    key: value # 这里的键值对要与pod中的label一致
  ports:
    - protocol: # TCP/UDP
      port: # Clusterip所使用的端口号
      targetPort:  # pod中容器的服务端口号
      nodePort: # 对外暴露服务的端口号(默认范围 30000-32767)

创建 svc

$ kubectl create -f service.yaml
$ kubectl get svc -n test
NAME               TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
example            LoadBalancer   192.168.17.56   x.x.x.x        80:31156/TCP                 250d

EXTERNAL-IP 即为公网ip,安全组允许的情况下可以直接通过 80 端口访问

结合 Ingress 使用 LoadBalancer

以上的方法有一个弊端就是,每创建一个 svc 就要使用一个公网ip,这也是要钱的啊,所以结合 ingress 来使用再好不过了。是要让 Ingress 的 svc 使用 LoadBalancer,然后通过一个ip,来代理集群中创建的 ingress

部署 ingress 请参考 Kubernetes—Ingress

创建好的 Ingress svc 如下

$ kubectl get svc -n ingress-nginx 
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    192.169.19.80   <none>        80:30273/TCP,443:31866/TCP   3d1h

将 Ingress 的 TYPE 改为 LoadBalancer

kubectl patch svc -n ingress-nginx ingress-nginx-controller --type='json' -p '[{"op": "replace", "path": "/spec/type", "value": "LoadBalancer"}]'

修改完之后将会获取一个临时公网ip,前提是公有云账户里有钱。

有的云厂商是支持指定 loadBalancerIP 的(参考公有云文档才能知道),前提要创建要 LB 的 ip,然后直接指定即可,在 svc 和 ingress 的 svc 中通用,如:

apiVersion: v1
kind: Service
metadata:
  name: example
  namespace: test
spec:
  type: LoadBalancer
  LoadBalancerIP: x.x.x.x     # 公有云SLB ip
  externalTrafficPolicy: Local 
  selector:
    key: value
  ports:
    - protocol: 
      port:
      targetPort:  
      nodePort: 

公司实例

现在我所在的公司因为正在迁移环境,老的环境用的是 nginx,要将公有云的 k8s 下云,所以准备将 ingress 使用 nodeport 暴露,然后由 nginx 代理。

用户访问顺序:域名 -> SLB -> nginx -> ingress -> pod

中间没有 svc 是因为创建的 ingress 里面配置的 svc 已经被 ingress 转换为 upstream。

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0