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 的创建

只有Ingress控制器在集群中运行,Ingress 资源才能正常工作。 不同的 Kubernetes 环境使用不同的控制器实现, 但有些并不提供默认控制器
查看是否存在ingress 控制器
$ kubectl get  po  --all-namespaces
   NAMESPACE     NAME                READY  STATUS  RESTARTS  AGE
 ...      ...
 kube-system  nginx-ingress-controller-gdts  1/1  Running  0    18m
View Code

如果没有,需要先创建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 对外端口
View Code
定义了一个单一规则的 Ingress ,确保 Ingress 控制器收到的所有请求主机 kubia example.com HTTP 请求,将被发送到service 的80 端口 

获取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
View Code

dns解析

把任意一个 ingress controler所在的pod 的ip 地址解析为定义的应用程序域名,访问域名后请求到底controller,控制器通过规则和域名找到应用程序实现负载转发。

配置 Ingress 处理 TLS 传输

客户端和控制器之间的通信是加密的,而控制器和后端 pod 之间的通信不是 。运行在pod 上的应用程序不需要支持 TLS 例如,如果 pod 运行 web务器,则它只能接HTTP 通信,并让 Ingress 控制器负责处理与 TLS 关的所有内容。要使控制器能够这样做,需要将证书和私钥附加到 Ingress 。这两个必 需资源存储在称为 Secret的Kubernetes 资源 中,然后在 Ingress manifest 中引用
 
1、创建或者购买一个证书
2、创建一个secret
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
View Code
注意 Ingress 功能的支持因不同的 Ingress 拉制器实现而异,因此请检查特定实现的文档以确定支持的内容Ingress 个相对较新的 kubemetes 功能,因此可以预期将来会看到许多改进和新功能。虽然目前仅支持 L7 (网络第7层)负载平衡,但也计划支持 L4 (网络第4层)负载平衡
 

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/...这两种情况。
View Code

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 关闭了。

 

 

 

 

posted @ 2019-11-28 20:53  fanggege  阅读(1594)  评论(0编辑  收藏  举报