kubernetes的负载均衡和Ingress的使用

987 阅读6分钟

一、负载均衡在Kubernetes服务中的作用

负载均衡是Kubernetes(K8s)中一个非常重要的概念,它允许将网络流量分配到多个工作负载实例中,从而提高应用程序的可用性和性能。在K8s中,可以使用服务(Service)和Ingress对象来实现负载均衡。

服务是一种抽象,定义了一组Pod及其共享的策略,这些Pod通常属于同一应用程序,执行相似的功能,例如Web后端或数据库。服务可以暴露一个内部DNS名称和稳定的IP地址,以便其他应用程序可以访问该组Pod。当请求发送到服务时,Kubernetes会自动将请求转发到其中一个Pod。

二、Kubernetes中的负载均衡器如何工作

Kubernetes中的负载均衡器是通过使用kube-proxy实现的。kube-proxy是一个运行在Kubernetes节点上的代理,它监听Kubernetes API服务器以查找新的服务并为每个服务创建一个虚拟IP地址。当有请求发送到该IP地址时,kube-proxy会根据一定的规则将请求转发到正确的Pod。

当使用Ingress时,负载均衡由Ingress控制器实现。Ingress是一种API对象,它向Kubernetes集群外部公开服务,同时提供路由规则以将流量分配到服务中的不同Pod。Ingress控制器可以根据规则将流量分配到不同的服务,并使用负载均衡算法将流量分配到服务中的不同Pod。

总之,Kubernetes中的负载均衡器在确保应用程序高可用性和性能方面扮演着重要角色,而服务和Ingress对象是实现负载均衡的关键组件。

三、使用Kubernetes中的服务和负载均衡器进行负载均衡的简单示例

  1. 创建一个Deployment对象,用于启动一个简单的Web应用程序。这个应用程序会响应HTTP请求并返回一条简单的消息。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: nginx
        ports:
        - containerPort: 80
  1. 创建一个Service对象,对上面的Deployment进行暴露,使得外部能够访问到该应用程序。
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  selector:
    app: webapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer

注意,在上面的配置文件中,type字段被设置为LoadBalancer,这将会告诉Kubernetes为该Service创建一个负载均衡器。由于我们使用了云提供商的Kubernetes集群,Kubernetes会自动将负载均衡器配置为云提供商特定的类型。

  1. 部署这些资源并确认它们已经正常运行
$ kubectl apply -f deployment.yaml
$ kubectl apply -f service.yaml

# 等待负载均衡器的IP地址被分配
$ kubectl get service webapp-service
  1. 现在,可以使用上述步骤中获取的IP地址来访问Web应用程序了。例如,可以通过浏览器或curl工具来访问:
$ curl http://<webapp-service-external-ip>

每次请求都会随机地被转发到部署的三个Pod之一上,从而实现了负载均衡。

四、什么是Ingress?

Service对集群之外暴露服务的主要方式有两种:NotePort和LoadBalancer,但是这两种方式,都有一定的缺点:

  • NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显
  • LB方式的缺点是每个service需要一个LB,浪费、麻烦,并且需要kubernetes之外设备的支持

基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。工作机制大致如下图表示:

image.png

实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务。在这里有两个核心概念:

  • ingress:kubernetes中的一个对象,作用是定义请求如何转发到service的规则
  • ingress controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,比如Nginx, Contour, Haproxy等等

Ingress(以Nginx为例)的工作原理如下:

  1. 用户编写Ingress规则,说明哪个域名对应kubernetes集群中的哪个Service
  2. Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx反向代理配置
  3. Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新
  4. 到此为止,其实真正在工作的就是一个Nginx了,内部配置了用户定义的请求转发规则

image.png

五、使用Kubernetes中的Ingress对象进行负载均衡

  1. 创建一个Deployment对象,用于启动一个简单的Web应用程序。这个应用程序会响应HTTP请求并返回一条简单的消息。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: nginx
        ports:
        - containerPort: 80
  1. 创建一个Service对象,对上面的Deployment进行暴露,使得外部能够访问到该应用程序。
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  selector:
    app: webapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

注意,在上面的配置文件中,我们没有设置Service的type字段,因为我们不需要使用Kubernetes自动创建的负载均衡器。

  1. 创建一个Ingress对象,将流量路由到上述Service中。在下面的示例中,我们将所有的流量路由到webapp-service服务中,并定义了一个基于域名的路由规则。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /webapp
        pathType: Prefix
        backend:
          service:
            name: webapp-service
            port:
              number: 80

在上述配置文件中,我们使用了Nginx Ingress控制器,并定义了一个host字段,该字段指定了将要路由的请求域名。然后,我们定义了一个基于路径的路由规则,该规则将任何以/example.com/webapp开头的请求路由到我们创建的webapp-service服务中。

  1. 部署这些资源并确认它们已经正常运行
$ kubectl apply -f deployment.yaml
$ kubectl apply -f service.yaml
$ kubectl apply -f ingress.yaml

# 等待Ingress IP地址被分配
$ kubectl get ingress webapp-ingress
  1. 现在,可以通过浏览器或curl工具来访问Web应用程序了。例如,可以使用以下URL来访问:
http://example.com/webapp

类似于服务和负载均衡器的例子,每次请求都会随机地被转发到部署的三个Pod之一上,从而实现了负载均衡。