青云LB(负载均衡)与k8s架构原理分析

原文链接:https://mp.weixin.qq.com/s?__biz=Mzk0NzQwMzgxNQ==&mid=2247484172&idx=1&sn=e507cc9c4103d5c3e23f3c542389005a&chksm=c3762e44f401a7525e258a760059de05b04b068e05890c7b1429371a2b38eade7efdec79b89f&scene=178&cur_album_id=2779138842019856385#rd

注意:是从原文中摘抄部分内容,主要是原理,架构设计方面的,具体操作方面不涉及

对于生产环境,需要考虑集群的高可用性。如果关键组件(例如 kube-apiserver、kube-scheduler 和 kube-controller-manager)在相同的主节点上运行,一旦主节点出现故障,Kubernetes 和 KubeSphere 将不可用。因此,您需要为多个主节点配置负载均衡器,以搭建高可用集群。您可以使用任何云负载均衡器或任何硬件负载均衡器(例如 F5)。此外,您也可以使用 Keepalived+HAproxy 或 NGINX 搭建高可用集群。

负载均衡器创建高可用集群:

使用 Keepalived 和 HAproxy/Nginx 创建高可用 Kubernetes 集群:

高可用方案

通常情况下,我们创建单master的k8s集群是不需要进行高可用配置的,只有在创建高可用的k8s集群时才会采用高可用配置,高可用配置的方案有很多。如下方案:

云上:

使用 Keepalived 和 HAproxy 创建高可用 Kubernetes 集群(有些云可能不支持keepalived)

使用 Keepalived 和 Nginx 创建高可用 Kubernetes 集群(有些云可能不支持keepalived)

可以直接使用云上的lb,比如阿里云slb,腾讯云elb,青云lb等(推荐)

非云上:

使用 Keepalived 和 HAproxy 创建高可用 Kubernetes 集群

使用 Keepalived 和 Nginx 创建高可用 Kubernetes 集群

青云LB负载均衡使用

负载均衡(Load Balancer,简称LB)提供安全快捷的流量分发服务,来自多个公网地址的访问流量经由 LB 可以自动分配到多台云服务器上,并支持自动检测并隔离故障云服务器,提供业务系统的服务能力和可用性。负载均衡支持千万级别并发访问请求,可轻松应对大流量访问,满足业务需求。

  • 创建负载均衡器,指定ip地址或者自动生成IP
  • 进入负载均衡器,创建监听器
  • 选择TCP,6443端口(此端口可调整)
  • 添加master地址与监听 apiserver 6443端口
  • 根据集群的部署位置,您可能需要在安全组中打开端口以确保外部流量不被屏蔽
  • 可以同时配置内置负载均衡器和外置负载均衡器。为外置负载均衡器分配公共 IP 地址后,您可以使用该 IP 地址来访问集群,这里我们只用内置负载均衡器,利用青云VPN进行内网访问即可

注:外置负载均衡器表示的是给配置一个公网IP,内置负载均衡器表示不配置公网IP,仅限集群网络内部使用

k8s集群中三种IP

三种IP概述

  • NodeIP:Node 节点的 IP 地址,即物理机(虚拟机)的 IP 地址。
  • PodIP:Pod 的 IP 地址,即 docker 容器的 IP 地址,也是虚拟 IP 地址。
  • ClusterIP:k8s 虚拟的 Service 的 IP 地址,也是虚拟 IP 地址。

三种IP的理解

  • Node IP:是物理机的IP(或虚拟机IP),代表的是物理节点或者虚拟节点的网络。每个Service都会在Node节点上开通一个端口,外部可以通过 http://NodeIP:NodePort 即可访问 Service 里的 Pod 提供的服务。

  • Pod IP:是每个 Pod 的 IP 地址,Docker Engine根据 docker 网桥的 IP 地址段进行分配的,通常是一个虚拟的二层网络,Pod的ip经常变化,且在k8s集群外无法访问。特点如下:

    1.同Service下的pod可以直接根据PodIP相互通信。
    2.不同Service下的pod在集群间pod通信要借助于 cluster ip。
    3.pod和集群外通信,要借助于node ip。

  • Cluster IP:是 Service 的 IP 地址,此为虚拟 IP 地址,只是出现在service的规则当中,外部网络无法 ping 通,只有kubernetes集群内部访问使用。特点如下:

    1.Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址 Cluster。
    2.IP无法被ping,他没有一个“实体网络对象”来响应 Cluster IP只能结合Service。
    3.Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间。
    4.在不同Service下的pod节点在集群间相互访问可以通过Cluster IP。

三种IP关系图

①:代表外部通过公有云的 LoadBalancer 负载均衡服务访问集群内部服务流程
②:代表外部用户直接访问集群内部 Service 的 ClusterIP 访问集群内部服务流程
③:代表集群内部不同 Service 之间的 Pod 服务访问流程
④:代表集群内部同一个 Service 中 Pod 服务之间访问流程

暴露服务的三种方式

如果需要从集群外部访问服务,即将服务暴露给用户使用,Kubernetes Service 本身提供了两种方式,一种是 NodePort,另外一种是 LoadBalancer。另外 Ingress 也是一种常用的暴露服务的方式。

通过NodePort方式暴露集群内部容器服务

Kubernetes具有强大的副本控制能力,能保证在任意副本(Pod)挂掉时自动从其他机器启动一个新的,还可以动态扩容等,通俗地说,这个Pod可能在任何时刻出现在任何节点上,也可能在任何时刻死在任何节点上;那么自然随着Pod的创建和销毁,Pod IP 肯定会动态变化;那么如何把这个动态的Pod IP暴露出去?这里借助于Kubernetes的 Service 机制,Service 可以以标签的形式选定一组带有指定标 签的Pod,并监控和自动负载他们的Pod IP,那么我们向外暴露只暴露Service IP就行了;如果将服务的类型设置为 NodePort,kube-proxy 就会为这个服务申请一个 30000 以上的端口号(默认情况下),然后在集群所有主机上配置 IPtables 规则,这样用户就能通过集群中的任意节点加上这个分配的端口号访问服务了,这就是 NodePort模式:即在每个节点上开启一个端口,然后转发到内部Pod IP 上,如下图所示:

NodePort 是通常最方便暴露服务的方式,但是缺点也很明显:

  • 基于 SNAT 进行访问,Pod 无法看到真正的 IP。
  • NodePort是将集群中的一个主机作为跳板访问后端服务,所有的流量都会经过跳板机,很容易造成性能瓶颈和单点故障,难以用于生产环境。
  • 端口管理问题:采用NodePort方式暴露服务,服务一旦多起来,NodePort在每个节点上开启的端口数量会极其庞大,一般都是用大端口,不容易记忆,而且难以维护。

注:NodePort 设计之初就不建议用于生产环境暴露服务,所以默认端口都是一些大端口。

通过LoadBalancer方式暴露集群内部容器服务

LoadBalancer通过云厂商的 LB 插件实现,例如青云的LB 插件基于‍cloud-controller-manager这个包实现,阿里云slb插件基于Cloud Controller Manager这个包实现,这些插件会自动选择合适的后端暴露给 LB 插件,然后 LB 插件由此创建对应的负载均衡器,网络流量在云服务端就会被分流,就能够避免 NodePort 方式的单点故障和性能瓶颈。LoadBalancer 是 Kubernetes 设计的对外暴露服务的推荐方式,但是这种方式仅仅限于云厂商提供的 Kubernetes 服务上,对于物理部署或者非云环境下部署的 Kubernetes 集群,这一机制就存在局限性而无法使用。

当然了若是使用青云的QKE集群,开启项目网关时可选创建一个负载均衡器,这里就自动完成绑定了,不需要手动去配置。如下qingcloud-cloud-controller-manager:

注:这种方式是需要ccm(cloud-controller-manager)自动完成lb监听器创建、绑定公网IP。

通过Ingress方式暴露集群内部容器服务

Ingress其实并不是 Kubernetes 服务本身提供的暴露方式,而是借助于软件实现的同时暴露多个服务的一种类似路由器的插件。Ingress 通过域名来区分不同服务,并且通过 annotation 的方式控制服务对外暴露的方式。

Ingress官网定义:Ingress可以把进入到集群内部的请求转发到集群中的一些服务上,从而可以把服务映射到集群外部。Ingress 能把集群内Service 配置成外网能够访问的URL,流量负载均衡,提供基于域名访问的虚拟主机等。

Ingress简单的理解就是你原来需要改Nginx配置,然后配置各种域名对应哪个Service,现在把这个动 作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,而不是每次都是改nginx的配置文件,直接改yaml然后创建或者更新就行了。那么问题来了:”Nginx 应该怎么处理?”

就像矛和盾一样,有矛就有盾,Ingress Controller就是解决”Nginx 应该怎么处理?”的,Ingress Controller 通过与 Kubernetes API 交互,动态的去感知集群中Ingress规则变化,然后读取它,按照它自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下,其原理如下图:

上图配置文件如下:

apiVersion: extensions/v1beta1          #api 版本 
kind: Ingress            #清单类型 
metadata:                #元数据 
  name: ingress-myapp    #ingress 的名称 
  namespace: default     #所属名称空间 
  annotations:           #注解信息     
    kubernetes.io/ingress.class: "nginx" 
spec:      #规格 
  rules:   #定义后端转发的规则 
  - host: myapp.com    #通过域名进行转发 
    http: 
      paths:        
      - path:       #配置访问路径,如果通过url进行转发,需要修改;空默认为访问的路径为"/" 
        backend:    #配置后端服务 
          serviceName: myapp 
          servicePort: 80

实际上Ingress也是Kubernetes API的标准资源类型之一,它其实就是一组基于DNS名称(host)或 URL路径把请求转发到指定的Service 资源的规则。用于将集群外部的请求流量转发到集群内部完成的服 务发布。我们需要明白的是,Ingress资源自身不能进行“流量穿透”,仅仅是一组规则的集合,这些集合规则还需要其他功能的辅助,比如监听某套接字,然后根据这些规则的匹配进行路由转发,这些能够为 Ingress资源监听套接字并将流量转发的组件就是Ingress Controller。

注:Ingress控制器不同于Deployment控制器的是,Ingress控制器不直接运行为kube-controllermanager的一部分,它仅仅是Kubernetes集群的一个附件,类似于CoreDNS,需要在集群上单独部署。



posted @   哈喽哈喽111111  阅读(754)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2022-05-15 中国家庭实际收入是多少?
2020-05-15 filebeat直接给es传输日志,自定义索引名,自定义多个索引文件
点击右上角即可分享
微信分享提示