前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >k8s loadbalancer与ingress实践

k8s loadbalancer与ingress实践

作者头像
你大哥
发布2022-01-10 08:00:19
1.5K0
发布2022-01-10 08:00:19
举报
文章被收录于专栏:容器云实践

k8s可以通过三种方式将集群内服务暴露到外网,分别是NodePort、LoadBalancer、Ingress,其中NodePort作为基础通信形式我们在《k8s网络模型与集群通信》中进行了介绍,这里我们主要关注LoadBalancer和Ingress

LoadBalancer

loadbalancer是服务暴露到因特网的标准形式,和nodeport一样我们只需在创建service是指定type为loadbalancer即可,接着Service 的通过status.loadBalancer字段将需要创建的负载均衡器信息发布供负载均衡服务创建。不过loadbalancer是云服务商”专属“,像腾讯云CLB、阿里云SLB,这样在创建service时会自动帮我们创建一个负载均衡器。

大多数云上负载均衡也是基于nodeport,他们的结构如下:

如果要在本地创建一个负载均衡器如何实现呢?

MetalLB[1],一个CNCF沙箱项目,使用标准路由协议(ARP/BGP),实现裸机K8s集群的负载均衡器。

安装方式可参考官方文档:installation[2]

L2(子网)模式的结构,图源[3]

安装后我们获得如下两个组件:

metallb-system/controller deployment。用于处理IP分配的控制器。•metallb-system/speakerdaemonset。集群中每个节点启动一个协议服务守护进程。

接着添加一个configmap配置metallb IP池。

代码语言:javascript
复制
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.1.240-192.168.1.250

这样当我们创建一个loadbalancer类型的service时,EXTERNAL-IP将会从地址池中获取一个用于外部访问的IP 192.168.1.243 当外部流量进入时,ARP将我们的请求地址广播获取所属的service,接着k8s内部 通过iptables 规则和 kube-proxy,将流量从服务端点引导到后端。

代码语言:javascript
复制
#nginx_deployment_service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: metallb-system
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - name: http
          containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  namespace: metallb-system
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

查看service kubectl get svc

代码语言:javascript
复制
NAME     TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
nginx    LoadBalancer   10.96.243.159   192.168.1.243   80:31052/TCP   40h

测试访问:curl 192.168.1.243

代码语言:javascript
复制
# curl 192.168.1.243
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>

负载均衡可以建立在 OSI 网络模型的不同级别上,主要是在 L4(传输层,例如 TCP/UDP)和 L7(应用层,例如 HTTP)上。在 Kubernetes 中,Services是 L4 的抽象,LoadBalancer类型负载均衡依然有局限性,同时我们看到每创建一个service对应的负载均衡器都会消耗一个静态IP,这并不合理。当然k8s中的另一种资源对象ingress可工作在 L7 层实现应用程序协议(HTTP/HTTPS)的负载均衡。

Ingress

Ingress[4] 公开了从集群外部到集群内服务[5]的 HTTP 和 HTTPS 路由。流量路由由 Ingress 资源上定义的规则控制。我们可以将 Ingress 配置为服务提供外部可访问的 URL、负载均衡流量、终止 SSL/TLS,以及提供基于名称的虚拟主机等能力。

我们所说的Ingress包含两个部分:

•ingress k8s资源对象:流量路由规则的控制•ingress-controller控制器:控制器的实现有非常多,可参考官方文档中列表Ingress 控制器[6],这里我们使用k8s官方维护的控制器NGINX Ingress Controller[7]

外部流量进入集群时先经过ingress-controller,然后根据ingress配置的路由规则将请求转发到后端service。

ingress-controller

ingress-controller其实就是守护进程加一个反向代理的应用,守护进程不断监听集群中资源的变化,将ingress中的配置信息生成反向代理配置。在nginx-ingress controller中即生成nginx.conf的配置文件。

在本文中因为我们上面已经配置好了loadbalancer的服务,这样我们创建一个type为LoadBalancer的service关联这组pod,再把域名解析指向该地址,就实现了集群服务的对外暴露。当然你也可以使用NodePortHostnetwork的方式,感兴趣的小伙伴可以进行测试。

ingress-controller不是k8s内部组件,可以通过helm或资源清单方式安装,可查看ingress-nginx deploy[8]

代码语言:javascript
复制
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-
nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml

然后我们编辑service

代码语言:javascript
复制
kubectl edit service/ingress-nginx-controller -n ingress-nginx

修改spec.type为LoadBalancer即可。

这样我们创建好了nginx-ingress controller,下一步就要配置ingress路由规则。

ingress规则

host:k8s.com

基于url的路由:

•/api/v1•/api/v2

这两个url分别路由到不同的service中

代码语言:javascript
复制
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  namespace: training
  annotations:
    ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: k8s.com
    http:
      paths:
      - path: /api/v1
        backend:
          serviceName: service-apiv1
          servicePort: 80
      - path: /api/v2
        backend:
          serviceName: service-apiv2
          servicePort: 80

ingress.kubernetes.io/rewrite-target是nginx-ingress controller的一个注解,当后端服务中暴露的 URL 与 Ingress 规则中指定的路径不同时可以通过此重定向。

查看svc可以看到此时控制器已经获得了一个EXTERNAL-IP

代码语言:javascript
复制
#kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.96.87.23    192.168.1.245   80:32603/TCP,443:31906/TCP   621d
ingress-nginx-controller-admission   ClusterIP      10.96.109.70   <none>          443/TCP                      621d

现在nginx-ingress controller和ingress路由规则都有了。

我们可以进入到nginx-ingress controller pod中查看nginx.conf可以看到此时我们的ingress配置已经被生成为路由规则。

接下来就是指定我们的backend,即上面的server-apiv1/2

我们添加两个用于暴露的service和deployment,和loadbalancer中测试清单一样,我们稍稍修改一下名称即可。

代码语言:javascript
复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-apiv1
  namespace: training
spec:
  selector:
    matchLabels:
      app: nginx-apiv1
  template:
    metadata:
      labels:
        app: nginx-apiv1
    spec:
      containers:
      - name: nginx-apiv1
        image: nginx:latest
        ports:
        - name: http
          containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  namespace: training
  name: service-apiv1
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx-apiv1
  type: NodePort

将nginx-apiv1换成nginx-apiv2创建出另一个service和deployment。

最后修改hosts解析k8s.com

代码语言:javascript
复制
192.168.1.245 k8s.com

使用curl命令测试url路由(记得在pod中添加测试文件,否则虽然url进行了路由但会出现404)。

代码语言:javascript
复制
# curl k8s.com/api/v1/index.html
api v1
# curl k8s.com/api/v2/index.html
api v2

这样我们对ingress有了初步了解,ingress的路由规则可自定项较多也比较繁杂,可通过官方文档进一步学习。

References

[1] MetalLB: https://metallb.universe.tf/ [2] installation: https://metallb.universe.tf/installation/ [3] 图源: https://banzaicloud.com/tags/metallb/ [4] Ingress: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#ingress-v1beta1-networking-k8s-io [5] 服务: https://kubernetes.io/zh/docs/concepts/services-networking/service/ [6] Ingress 控制器: https://kubernetes.io/zh/docs/concepts/services-networking/ingress-controllers/ [7] NGINX Ingress Controller: https://kubernetes.github.io/ingress-nginx/ [8] ingress-nginx deploy: https://kubernetes.github.io/ingress-nginx/deploy/#quick-start

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 容器云实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • LoadBalancer
  • Ingress
  • ingress-controller
  • ingress规则
  • References
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的四七层流量分发服务,访问流量经由 CLB 可以自动分配到多台后端服务器上,扩展系统的服务能力并消除单点故障。轻松应对大流量访问场景。 网关负载均衡(Gateway Load Balancer,GWLB)是运行在网络层的负载均衡。通过 GWLB 可以帮助客户部署、扩展和管理第三方虚拟设备,操作简单,安全性强。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档