文章目录
-
- Ingress
-
- 原理介绍
- Ingress-Nginx
-
- 安装ingress-nginx控制器
- 部署ingress
-
- ingress http代理访问
- ingress https代理访问
- Nginx 进行 BasicAuth
- 配置 ingress nginx
- nginx实现重写
Ingress
这篇blog关于ingress讲解的不错:
k8s ingress原理及ingress-nginx部署测试
图解 Kubernetes Ingress
原理介绍
之前所提到的svc仅支持4层负载均衡,也就是说只能通过ip+port的形式实现访问,无法通过域名的方式进行访问。ingress也是k8s中的一种资源类型。其实可以把ingress看做是进阶版的service,有service的功能,可以把内部服务暴露给外部;除此之外,有处理https服务的优势,对于一般的svc来说,如果要想处理https服务就需要在svc管理下的所有pod上都装有ssl证书,使用ingress则会帮助在svc层来处理这些加密请求,然后把解密后的请求下发到内部服务中。也就是说,ingress与外部之间的通讯依然采用https协议,但是到了内部可以不走https,直接走http
Service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制,对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。但是,单独用service暴露服务的方式,在实际生产环境中不太合适:
- ClusterIP的方式只能在集群内部访问。
- NodePort方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理是灾难。
- LoadBalance方式受限于云平台,且通常在云平台部署ELB还需要额外的费用。
所幸k8s还提供了一种集群维度暴露服务的方式,也就是ingress。ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。
上面这段介绍来源于k8s ingress原理及ingress-nginx部署测试 ,个人觉得讲得很不错,通俗易懂。
举个例子,现在集群有api、文件存储、前端3个service,可以通过一个ingress对象来实现图中的请求转发:
要理解ingress,需要区分两个概念,ingress和ingress-controller:
- ingress对象:
指的是k8s中的一个api对象,一般用yaml配置。作用是定义请求如何转发到service的规则,可以理解为配置模板。 - ingress-controller:
具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。
简单来说,ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等。后续以Ingress-Nginx 为controller进行分析
Ingress-Nginx
Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx/
ingress-controller并不是k8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不同的ingress-controller实现.
不管哪一种ingress-controller,实现的机制都大同小异,只是在具体配置上有差异。一般来说,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据ingress对象生成配置并应用新配置到反向代理,比如nginx-ingress就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。
安装ingress-nginx控制器
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
部署ingress
ingress的部署,需要考虑两个方面:
- ingress-controller是作为pod来运行的,以什么方式部署比较好
- ingress解决了把如何请求路由到集群内部,那它自己怎么暴露给外部比较好
常见的一些方式列举(具体的内容可以查看该blog):k8s ingress原理及ingress-nginx部署测试
- Deployment+LoadBalancer模式的Service
- Deployment+NodePort模式的Service
- DaemonSet+HostNetwork+nodeSelector
ingress http代理访问
#deployment、Service、Ingress Yaml 文件
#1. deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:name: nginx-dm
spec:replicas: 2template:metadata:labels:name: nginxspec:containers:- name: nginximage: wangyanglinux/myapp:v1imagePullPolicy: IfNotPresentports:- containerPort: 80
#2. svc
---
apiVersion: v1
kind: Service
metadata:name: nginx-svc
spec:ports:- port: 80targetPort: 80protocol: TCPselector:name: nginx
---
#3. ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: nginx-test
spec:rules:# 定义域名- host: www1.atguigu.comhttp:paths:- path: /backend:serviceName: nginx-svcservicePort: 80
上面的例子:当访问www1.atguigu.com/时,ingress会反向代理到nginx-svc这个服务,然后再由该服务反向代理/通过负载均衡到该svc所指向的pod。
ingress https代理访问
创建证书,以及 cert 存储方式
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj
"/CN=nginxsvc/O=nginxsvc"
# 这句话的意思实际上是把上面创建好的证书和私钥封装到tls-secret(这个名称可以自定义)中,便于在下面的config file使用
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: nginx-test
spec:tls:- hosts:- foo.bar.com#tls-secret 就是使用kubectl命令封装后的东东,有证书和私钥secretName: tls-secretrules:- host: foo.bar.comhttp:paths:- path: /backend:serviceName: nginx-svcservicePort: 80
Nginx 进行 BasicAuth
给nginx加一个基础认证,即浏览器输入绑定的域名后,弹出一个窗口,需要输入用户名和密码,这个用户名和密码就是通过下面的 htpasswd -c 命令设置的
先安装依赖
yum -y install httpd
#创建秘钥文件名为auth 用户名为foo,之后输入两次密码即可
htpasswd -c auth foo
kubectl create secret generic basic-auth --from-file=auth
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: ingress-with-authannotations:nginx.ingress.kubernetes.io/auth-type: basicnginx.ingress.kubernetes.io/auth-secret: basic-authnginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:rules:- host: foo2.bar.comhttp:paths:- path: /backend:serviceName: nginx-svcservicePort: 80
配置 ingress nginx
可以通过annotations字段来设置,比如:
kubernetes.io/ingress.class: nginxnginx.ingress.kubernetes.io/proxy-connect-timeout: '30'nginx.ingress.kubernetes.io/proxy-send-timeout: '500'nginx.ingress.kubernetes.io/proxy-read-timeout: '500'nginx.ingress.kubernetes.io/send-timeout: "500"nginx.ingress.kubernetes.io/enable-cors: "true"nginx.ingress.kubernetes.io/cors-allow-methods: "*"nginx.ingress.kubernetes.io/cors-allow-origin: "*"# 必须重定向流量的目标URL,字符串类型nginx.ingress.kubernetes.io/rewritetarget: http://foo.bar.com:31795/hostname.html#指示位置部分是否仅可访问SSL(当Ingress包含证书时默认为True),boolean类型nginx.ingress.kubernetes.io/sslredirect: True# 即使Ingress未启用TLS,也强制重定向到HTTPS,boolean类型nginx.ingress.kubernetes.io/forcessl-redirect:#定义Controller必须重定向的应用程序根,如果它在'/'上下文中,字符串类型nginx.ingress.kubernetes.io/approot:# 指示Ingress上定义的路径是否使用正则表达式,boolean类型nginx.ingress.kubernetes.io/useregex:
关于 ingress-nginx 更多的配置使用可以参考官方文档相关说明:
- https://github.com/kubernetes/ingress-nginx/tree/master/docs/user-guide/nginx-configuration
- https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#lua-resty-waf
nginx实现重写
# 通过设置annotations实现重写,即当访问re.test.com/时,跳转到已经存在的http://old.test.com/域名上
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: nginx-testannotations:nginx.ingress.kubernetes.io/rewrite-target: http://old.test.com/
spec:rules:- host: re.test.comhttp:paths:- path: /backend:serviceName: nginx-svcservicePort: 80