k8s ingress
为什么需要ingress
一组pod 对外暴露服务通过service 有两种方式一个是nodeport 另一个是loadbalancer。但是它们都是有弊端。
nodeport 必须知道节点服务器的地址和端口,如果此节点挂了那么就需要更换其他节点地址,而且每个服务都会对应一个node上的端口配置维护麻烦。而且odeport 实现的是四层转发
loadbalancer 每个 LoadBalancer 服务都需要自己的负载均衡器, 以及独有的公有 IP 地址,一个loadbalancer 只对应一组pod , 而 Ingress 只需要一个公网 IP 就能为许多服务提供访问。使得所有的Pod 都具有统一的入口
ingress控制器和ingress资源
ingress 控制器实际上就是运行在kube-system 空间的一组pod ,可以简单把它理解为一个负责均衡器例如nginx ,ingress 资源可以理解为配置在nginx 上面的conf.d下面的配置文件,定义的是基于后端一个服务的转发规则。
ingress 控制器有很多种,其中 NGINX Ingress Controller 是比较常用的一种,pod 里面运行的就是nginx ,所有的ingress 资源的创建最后都会在此控制器对应的pod 里面生成对应的nginx 配置,另外整个控制器的配置是通过一个configmap实现的,可以查看一下与控制器相同命名空间内是否有一个ingress 命名的configmap,这是控制器的全局配置文件。
Ingress 实现原理
简单理解为在service 基础上加入了一个负载代理。
实现原理
分为ingress 控制器和ingress 资源。ingress是一个负载代理规则,它是通过ingress-controller 实现的。它通过统一的端口(80/443)可实现4/7层负载,为每个服务创建一个域名,ingress 通过域名来识别访问的服务,所有的域名配置解析到这一个唯一的ingress 的IP ,实际与pod 通讯还是会经过service。它的底层实际就是nginx或者其他的负载软件,每一个服务做代理的过程即使为这个服务的pod 创建一个upstream和proxy.
客户端访问流程图
Igress 的创建
$ kubectl get po --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE ... ... kube-system nginx-ingress-controller-gdts 1/1 Running 0 18m
如果没有,需要先创建ingress 控制器,再创建ingress 规则
创建ingress 控制器
通过编写yaml 文件或者命令方式,在yaml 中可以定义对外提供的统一端口。
kubectl apply -f ingress.yaml
kubectl get pods -n ingress-nginx #查看创建的ingress,必须在它自己的命名空间ingress-nginx 中查看
创建Ingress 规则
vi ingress.yaml
apiVersion: extensions/vlbetal kind: Ingress metadata: name: kubia spec: rules: - host: kubia.example.com #将此域名映射为你的服务 http: paths - path: / #域名后的路径 backend: serviceName: kubia-asdf #对应的是service 名称 servicePort:80 #service 对外端口
获取ingress 地址
kubectl get ingresses -n kzf
可以同一个ingress 暴露多个服务
类比nginx 同一个server name 下面多个location 转发不同的后端服务
apiVersion: extensions/vlbetal kind: Ingress metadata: name: kubia spec: rules: - host: kubia.example.com #对于http://kubia.example.com/ 的访问转发到kubia-asdf服务 http: paths - path: / #域名后的路径 backend: serviceName: kubia-asdf #对应的是service 名称 servicePort:80 - path: /foo #对于http://kubia.example.com/foo 访问转发到 bar 服务 backend: serviceName : bar servicePort: 80
dns解析
把任意一个 ingress controler所在的pod 的ip 地址解析为定义的应用程序域名,访问域名后请求到底controller,控制器通过规则和域名找到应用程序实现负载转发。
配置 Ingress 处理 TLS 传输
kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key #私钥和证书现在存储在名为 tls-key 的Secret 中
3、配置ingress
apiVersion: extensions/vlbetal kind: Ingress metadata: name: kubia spec: tls: #这个属性下包含了所有的tls 配置 - hosts: - kubia.example.com #将接收所有来自kubia.example.com 的TLS 连接 secretName: tls secret rules: - host: kubia.example.com http: paths - path: / backend: serviceName: kubia-asdf servicePort:80
ingress-nginx 配置rewrite
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /kzf/$1$2 # nginx.ingress.kubernetes.io/rewrite-target: / name: {{ .Values.projectName }} namespace: {{ .Values.namespace }} spec: rules: - host: pay-server.kzf.k8s.asdf.com http: paths: - path: /jtlq/kzf(/|$)(.*) #访问的ingress的uri ,此处匹配三种情况/jtlq/kzf或/jtlq/kzf/或/jtlq/kzf/... backend: serviceName: pay-server servicePort: 8090 解释: 访问 http://pay-server.kzf.k8s.asdf.com.k8s.asdf.com/jtlq/kzf(/|$)(.*) 转发到后端service pay-server 的8090 端口并且uri 变为/kzf/$1$2, 替换了/jtlq/kzf(/|$)(.*) 注意:路径如果写成这样 - path: /jtlq/kzf/(.*) 那么直匹配 /jtlq/kzf/或/jtlq/kzf/...这两种情况。
ingress 控制器 配置映射片段
nginx ingress 控制器的使用文档详见 https://kubernetes.github.io/ingress-nginx/
如果你想在nginx-controller-pod中生成的nginx.conf文件中添加一些自定义配置,例如配置请求头,gzip 等等,可以通过 snippet,一共分为 http-snippet,server-snippet和location-snippet 等,例如
server-snippet表示会把配置映射到nginx.conf 里面的server 区域,默认情况gzip 是启动的,如果想要配置某个ingress 资源为关闭,配置如下
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/server-snippet: | gzip off;
关于gzip 压缩的验证,可以通过浏览器访问url ,查看的是响应头的 Accept-Encoding ,如果没有此字段表示gzip 关闭了。