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 对外提供服务。
毋庸置疑,动态服务部署在 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 能够进行有效监控和故障转移,在一定程度上降低出错几率。当然仁者见仁智者见智,具体还要根据使用场景进行评估和选择。