ingress高可用搭建 ingress nginx_nginx

1、Ingress-nginx 介绍


1.1、Ingress-nginx 组成

nginx-ingress-controller:Kubernetes 入口控制器,通过 ingress-nginx 能够实现基本的负载均衡、证书卸载、会话加密以及 URL 重写等功能;

ingress 资源对象:能够将 nginx 配置抽象成 Ingress 对象,每添加一个Service,只需要添加相应的 Ingress 规则,添加完成后,nginx-ingress-controller 通过 lua reload 配置,使其自动生效。

1.2、Ingress-nginx 工作原理

Ingress 通过跟 Kubernetes ApiServer 交互,动态感知 ingress 集群规则的变化;读取规则,动态生成相应的 nginx 配置文件,并把配置写到 nginx-ingress-controller 的 Pod 里面,Pod 里面运行着 nginx 服务,最终把配置写到 nginx.conf 中;最后动态 reload 配置,使其自动生效。简单理解就是原先需要修改 Nginx 配置,然后配置不同的转发规则到 Service 这个过程抽象出来变成一个 Ingress 对象,后续 Nginx 的变更再通过 Ingress Controller 与 Kubernetes API 交互,动态的去感知集群中 Ingress 规则变化,再写到 Nginx Pod 里。

1.3、Ingress-nginx 作用

在此之前,曾经总结过 Kubernetes Service 资源类型 Kubernetes里的Service究竟是如何工作的呢?通常情况下,我们会定义一个 Service 来管理一组 Pod 暴露相关的服务,如果要对外暴露服务的话,只需要定义相应的端口即可(NodePort模式),但每增加一个服务,就需要定义了一个 Service 对象并暴露服务的话就需要配置很多端口,不仅后续维护起来就会变的很复杂,而且会存在一定的安全性隐患,所以 Kubernetes 中还使用了 Ingress 的机制,比如使用 Nginx 绑定一个固定端口 80,后续的请求通过转发到 Service 即可。这样如果每次新增服务的话,只需要修改 Ingress 资源对象即可。具体配置见如下示例:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress
spec:
  tls:
  - hosts:
    - cafe.example.com
      secretName: cafe-secret
  rules:
    - host: cafe.example.com
      http:
        paths:
        - path: /tea
          backend:
            serviceName: tea-svc
            servicePort: 80
        - path: /coffee
          backend:
             serviceName: coffee-svc
             servicePort: 80

2、Ingress-nginx 安装

其安装非常简单,执行一条命令即可,具体可以参考:

https://github.com/kubernetes/ingress-nginx/blob/nginx-0.28.0/docs/deploy/index.md

因为镜像需要外网下载,可能会出现镜像下载失败的问题,可以通过在daemon.json 中添加如下代理完成镜像下载。

{
  "registry-mirrors": [
        "https://1nj0zren.mirror.aliyuncs.com",
        "https://docker.mirrors.ustc.edu.cn",
        "http://f1361db2.m.daocloud.io"
  ]
}

3、前后端分离项目使用示例

生产环境高可用 Kubernetes 部署架构,如下图所示; LB 可以通过 nginx 实现,也可以通过 HA + keepalive 实现,具体请根据使用场景选择,Ingress 统一集中集群中的 Service 对外提供服务。当然我们也可以直接使用 Ingress 对外提供服务。

ingress高可用搭建 ingress nginx_ingress高可用搭建_02

毋庸置疑,动态服务部署在 Kubernetes 集群中,但静态页面却有多种选择,可以放在 Ingress 中实现动态调度和灰度发布,也可以放在 LB、甚至 CDN 上提高静态文件加载速度,提升用户体验。放在 LB 上,用法和原生使用一样,这里不在过多介绍。下面主要介绍如何放在 Ingress 上实现动静分离和反向代理。

3.1、镜像制作

静态页面放到 nginx 某个目录下面,通过 nginx 实现静态页面的访问功能。具体 dockerfile 如下所示:

From docker.harbou.com/base/nginx:1.6.2
MAINTAINER  <slj@qq.com>
ADD web.tar.gz  /home/web/
ADD nginx.conf  /usr/nginx/conf/http_vhost/

3.2、前端k8s yaml 文件编写

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
     labels:
      app: web
    spec:
      containers:
      - name: web
        image: docker.habour.com/base/web:2020
        ports:
        - containerPort: 80
        volumeMounts:
          - mountPath: /etc/localtime
            name: date-conf
          - mountPath: /usr/nginx/logs/
            name: nginx-vol-logs
      volumes:
      - name: date-conf
        hostPath:
          path: /etc/localtime
      - name: nginx-vol-logs
        hostPath:
          path: /home/logs/nginx/
---
apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    app: web
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
  selector:
    app: web

3.3、后端k8s yaml 文件编写

后端 yaml 文件这里不是重点,为了不影响阅读,省略不必要的部分。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  selector:
    matchLabels:
      app: cluster
  replicas: 2
  template:
    metadata:
      labels:
        app: cluster
    spec:
      initContainers:
..........
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
  labels:
    app: tomcat-service
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: cluster

3.4、Ingress-nginx yaml 文件编写

因为 Ingress 核心是基于 nginx 实现,所以你可以直接在 Ingress 资源对象中写 nginx 配置,如果需要增加或者实现 nginx 中的功能可以通过添加 annotations 实现,具体可以参考:

https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: http-test
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  tls:
    - hosts:
      - docker.test.com
      secretName: tls-secret
  rules:
  - host: docker.test.com
    http:
      paths:
      - path: /soaw/(.*\.(html|htm|js|css|ico|png|jpg|gif|ipa|apk|eot|svg|ttf|woff|woff2))$
        backend:
          serviceName: web
          servicePort: 80
      - path: /soaw
        backend:
          serviceName: tomcat-service
          servicePort: 80

通过如上的配置可以实现,前端页面路由到 nginx 中,而动态服务路由到后端动态 svc 中,从而实现动静分离,注意如下配置是重点。

nginx.ingress.kubernetes.io/use-regex: "true"

4、总结

本文主要讲解了两个知识点:

第一 、Ingress 这个概念在 Kubernetes 中到底是怎样一种存在,正如本文所介绍的,Ingress 实际上就是对 Kubernetes 反向代理的一种抽象,Ingress 工作在七层,Service 工作在四层,所以如果你想在 Kubernetes 集群中完成 Http 相关的操作时,都必须借助类似 ingress 资源对象来完成。

第二、如何通过 Ingress 完成动静分离,这一部分可能不同的人看到都会有不同的疑问,eg 我的静态页面一直都没有分离,跟我的动态服务放在一起(tomcat webapps 文件夹)。这种情况下,没有特殊需求的话,暂时可以不用考虑 ingress 动静分离,只需要提供一个后端 svc 即可。本文说的主要是针对前后端分离的项目;如果你的前端静态页面不涉及到灰度发布的功能,可以放在最前端 CDN 上,提升用户体验;如果需要考虑灰度发布的功能,建议把静态页面打成镜像,通过 nginx pod 实现静态页面访问功能;因为 Kubernetes 调度不是人为能够预想到的,所以不建议使用静态页面挂载。可能你会说,我可以通过文件共享,比如 ceph、nfs等,把静态页面放在共享存储中访问,如果动态共享存储出现问题,那么将带来一系列的问题,而通过使用 deployment 管理静态页面,出现问题后,Kubernetes 能够进行有效监控和故障转移,在一定程度上降低出错几率。当然仁者见仁智者见智,具体还要根据使用场景进行评估和选择。