目录

 

前言

Ingress基础概念

Ingress的组成

Ingress负载均衡的使用

基础使用

高级使用

HTTPS访问

拓展

二级目录转发

基础认证

TCP四层代理


 

前言

在前面的分享中,我们首先介绍了Kubernetes是基础概念,紧接着是常用的一些基础资源,如:Kubernetes基础资源之Pod容器组、Kubernetes基础资源之Deployment控制器、Kubernetes基础资源之Service服务。

但是这些都只是在集群内部通过Pod或Service的IP来使用,那如何使我们的服务暴露给外部进行访问呢?这里就需要使用到ingress负载均衡了。

 

Ingress基础概念

Ingress通过HTTP和HTTPS的形式暴露集群内部服务,通过指定的域名规则定义,可以将集群外部的流量路由传输到集群内部的服务,最终到达Pod中被我们的应用程序接收和处理。流程图如下:

 

Ingress的组成

Ingress由基础资源Ingress和Ingress Controller组成。如果想要使用Ingress,那么就必须要在集群内部部署一个Ingress Controller组件。

由Ingress Controller来解析处理Ingress中定义的规则,并且动态的监听集群中Ingress规则变化,实时的进行刷新操作。

常用的Ingress Controller组件有如下几种:

PS:我们在v4.0之前使用的是traefik,v4.0之后调整为nginx了。

 

Ingress负载均衡的使用

基础使用

单独Ingress本身是没有任何用处的,必须要转发到后端服务,然后再由服务转发到具体的Pod中。

一个简单的示例如下:

simple-demo.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: demo

  labels:

    app.kubernetes.io/name: demo

    app.kubernetes.io/version: "1.0"

spec:

  replicas: 1

  selector:

    matchLabels:

      app.kubernetes.io/name: demo

      app.kubernetes.io/version: "1.0"

  template:

    metadata:

      labels:

        app.kubernetes.io/name: demo

        app.kubernetes.io/version: "1.0"

    spec:

      containers:

        - name: demo

          image: "harbor.k2software.com.cn/library/nginx:alpine"

          imagePullPolicy: IfNotPresent

          ports:

            - name: http

              containerPort: 80

              protocol: TCP

 

---

apiVersion: v1

kind: Service

metadata:

  name: demo

  labels:

    app.kubernetes.io/name: demo

    app.kubernetes.io/version: "1.0"

spec:

  type: ClusterIP

  ports:

    - port: 80

      targetPort: http

      protocol: TCP

      name: http       # 服务端口名称

  selector:

    app.kubernetes.io/name: demo

    app.kubernetes.io/version: "1.0"

 

---

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: demo

  labels:

    app.kubernetes.io/name: demo

    app.kubernetes.io/version: "1.0"

spec:

  rules:

    - host: "demo.lu.k2paas.com"  # 暴露的域名地址

      http:

        paths:

          - path: /  # 请求路径

            backend:

              serviceName: demo  # 后端服务名称

              servicePort: http  # 服务端口名称,也可以直接填端口号

这是一个很基础简单的例子,正常访问需要提前将Ingress的host写入DNS映射或者本机的hosts文件中,映射的IP为集群内任意节点IP即可。

之后就可以通过浏览器访问http://demo.lu.k2paas.com 了。

 

高级使用

以上的基础使用也能覆盖大多数场景,然而还有些特殊并且常用的场景需要我们继续学习和实践。

这里列几个比较特殊常用的场景:

  • HTTPS访问,随着现在互联网HTTPS越来越普及,我们在正式的生产环境中也基本都需要使用HTTPS化了。
  • 支持基于域名二级目录的转发,在上面示例中,我们只使用了一级目录,也就是path: /,实际中二级也用的不少。
  • 会话保持,由于默认的负载策略是轮询机制的,现需要将登陆的用户每次都请求到同一个pod实例中,就需要会话保持了。
  • 基础认证,因为某些中间件没有带登陆认证,为防止信息泄露,需要添加登陆认证,也可以借助Ingress来实现。
  • 四层 TCP/UDP代理,某些场景因为安全设计,造成的网络限制,需要统一通过负载均衡访问TCP的服务,如:MySQL
  • 跨域处理
  • 白名单
  • 限流
  • 灰度发布

 

HTTPS访问

Ingress支持HTTPS,通过添加tls字段可以很方便快捷的将服务HTTPS化。当然HTTPS的前提是必须要有证书文件,并且需要将证书文件存储到集群的secret资源内。这里为了演示方便,我们直接使用平台自签生成的k2-tls证书。

Ingress添加HTTPS配置如下:

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: demo

  labels:

    app.kubernetes.io/name: demo

    app.kubernetes.io/version: "1.0"

spec:

  tls:

    - hosts:

      - "demo.lu.k2paas.com"

      secretName: k2-tls   # 包含证书文件的secret

  rules:

    - host: "demo.lu.k2paas.com"  # 暴露的域名地址

      http:

        paths:

          - path: /  # 请求路径

            backend:

              serviceName: demo  # 后端服务名称

              servicePort: http  # 服务端口名称,也可以直接填端口号

修改完成后,执行kubectl apply命令更新配置。

我们再分别访问:http://demo.lu.k2paas.com 和 https://demo.lu.k2paas.com 可以看到都可以正常访问了。

拓展

在HTTPS化的过程中,也会有些常用的场景,比如强制全部都使用HTTPS,即使访问的是HTTP请求也要跳转到HTTPS请求。这个也是提高安全性,使用的比较广泛。

在我们这里也可以通过简单的配置就满足该需求。

在Ingress的metadata字段下面添加以下配置即可:

annotations:

  nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

最后重新apply,再访问http://demo.lu.k2paas.com 可以看到,直接被强制重定向跳转到https请求了。

 

二级目录转发

Ingress本身是支持二级目录转发的,只需要修改一下path后面的路径即可,但是我们的后端服务一定也要能处理二级目录。否则就会报错

这里我们使用经过定制的nginx镜像,添加可以处理二级目录的配置。

完整配置如下:

two-path-demo.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: two-path-demo

  labels:

    app.kubernetes.io/name: two-path-demo

    app.kubernetes.io/version: "1.0"

spec:

  replicas: 1

  selector:

    matchLabels:

      app.kubernetes.io/name: two-path-demo

      app.kubernetes.io/version: "1.0"

  template:

    metadata:

      labels:

        app.kubernetes.io/name: two-path-demo

        app.kubernetes.io/version: "1.0"

    spec:

      containers:

        - name: two-path-demo

          image: "harbor.k2software.com.cn/demo/two-path-demo:alpine"

          imagePullPolicy: IfNotPresent

          ports:

            - name: http

              containerPort: 80

              protocol: TCP

 

---

apiVersion: v1

kind: Service

metadata:

  name: two-path-demo

  labels:

    app.kubernetes.io/name: two-path-demo

    app.kubernetes.io/version: "1.0"

spec:

  type: ClusterIP

  ports:

    - port: 80

      targetPort: http

      protocol: TCP

      name: http       # 服务端口名称

  selector:

    app.kubernetes.io/name: two-path-demo

    app.kubernetes.io/version: "1.0"

 

---

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: two-path-demo

  labels:

    app.kubernetes.io/name: two-path-demo

    app.kubernetes.io/version: "1.0"

  annotations:

    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

spec:

  tls:

    - hosts:

      - "two-path-demo.lu.k2paas.com"

      secretName: k2-tls

  rules:

    - host: "two-path-demo.lu.k2paas.com"  # 暴露的域名地址

      http:

        paths:

          - path: /  # 请求路径

            backend:

              serviceName: two-path-demo  # 后端服务名称

              servicePort: http  # 服务端口名称,也可以直接填端口号

          - path: /demo  # 二级请求路径

            backend:

              serviceName: two-path-demo  # 后端服务名称

              servicePort: http  # 服务端口名称,也可以直接填端口号

这里我们在Ingress中又多添加一个path,用于指定二级目录。

定制镜像的配置代码:

https://git.k2software.com.cn/demo/two-path-demo

 

基础认证

在使用Kibana查询访问应用日志时,默认是没有任何认证的,会出现安全问题,因此需要添加认证步骤,这里我们通过Ingress可以简单快速的添加基础认证, 类似的场景都可以参考该方式。

 

TCP四层代理

通过负载均衡的TCP四层代理,我们可以将集群内ClusterIP类型的服务暴露出来,使集群外部也可以访问。

Nginx负载均衡的TCP代理配置是存储在ConfigMap内的,在启动时需要指定配置文件。

编辑nginx

kubectl edit daemonsets -n kube-system nginx-ingress-controller

containers:

      - args:

        - /nginx-ingress-controller

        - --default-backend-service=kube-system/nginx-ingress-default-backend

        - --election-id=ingress-controller-leader

        - --ingress-class=nginx

        - --configmap=default/nginx-ingress-controller

        - --default-ssl-certificate=default/k2-tls

        - --tcp-services-configmap=kube-system/nginx-ingress-controller-tcp

其中关键的就是:- --tcp-services-configmap=kube-system/nginx-ingress-controller-tcp

然后重启nginx-ingress-controller,执行:

kubectl delete pod -n kube-system -l app=nginx-ingress

然后创建配置ConfigMap,内容如下:

apiVersion: v1

kind: ConfigMap

metadata:

  name: nginx-ingress-controller-tcp

  namespace: kube-system

data:

  3306: "paas/mysql-tenant-client-service:3306"

注意其中的name和namespace必须要与启动中的一致。

data中的参数介绍:

  • 最前面的3306就是我们对外暴露的端口
  • paas为被代理服务所在的命名空间
  • mysql-tenant-client-service为被代理的服务名称
  • 最后面的3306是服务的端口号

最后再apply一下这个configmap即可

我们现在就可以在集群外部通过访问集群内任意一个节点的IP:3306就可以访问到MySQL服务了。

 

参考文档:

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/

https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/

https://kubernetes.github.io/ingress-nginx/examples/

Logo

开源、云原生的融合云平台

更多推荐