Ingress Controller 可以用来卸载https 会话和实现七层调度,在应用层实现路由,service只能在四层实现调度。service收集来的后端Pod信息并由Ingress 动态注入到 Ingress Controller当中。

        外部的负载均衡器 --> 共享节点网络的Pod,Ingress 或 service来接入流量 --> 虚拟主机或者Url实现七层调度 --> headless service  --> 后端Pod。


Ingress Controller的两种使用方式:

16299651937213_upload.png

这里使用的是第二种方式:

github地址:aws的eks上也可以用原生的nginx ingressController,直接用yaml文件部署即可。

https://kubernetes.github.io/ingress-nginx/deploy/

资源文件:默认没有使用hostNetwork,添加 containers.hostNetwork: true 在aws等云上不用改,会自动创建alb等资源作为负载均衡器。


国内镜像:

image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.1.0
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1


grafana dashboard:

https://grafana.com/grafana/dashboards/9614


使用 Ingress 实现将服务发布到外网:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations: 
    kubernetes.io/ingress.class: "nginx"
  name: mywebsite-ingress
  namespace: default
spec:
  rules:
  - host: mywebsite.com
    http:
      paths:
      - backend:
          serviceName: myapp-svc
          servicePort: 8080
        path: /

这里还需要创建提供实质服务的 service->deployments。service的名称就是serviceName字段指定的值。

在外部访问还需要添加DNS解析,即host字段中指定的域名。

]# kubectl get svc -n ingress-nginx 
NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.100.37.248   <none>        80:32621/TCP,443:31674/TCP   47m

在windows中也同样添加DNS解析,然后在浏览器中输入:mywebapp.com:32621 即可访问。

        注意:Ingress中path的定义需要与后端真实Service提供的path一致,否者会转发到一个不存在的path上而引发报错。

如果不想加DNS可以使用下面的方法:

curl --resolve mywebsite.com:80:192.168.1.141 http://mywebsite.com/web




安装 Ingress Controller


Ingress Controller有两种工作模式:

        1、Client --> NodePort的service --> Ingress Controller --> Pod

        2、Client --> Ingress Controller --> Pod

可以作为Ingress Controller的有Nginx、Traefik、Envoy。

官网地址:

https://github.com/kubernetes/ingress-nginx

创建Ingress Controller:第一种,以Deployment的方式

gitHub上的yaml文件以及部署方式:根据平台选择不同的部署方式,这里选择裸机版。

https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#bare-metal

部署yaml文件:每次部署时最好去官方取,因为会根据版本而改动。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

查看创建:需要下载镜像,需要等一等

kubectl get pods -n ingress-nginx --watch
kubectl get deployments -n ingress-nginx

还需要创建 NodePort 的 service 资源:新版本的资源文件中包含service资源,不需要创建下面的资源。

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx  # 注意Pod的名称空间
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
  - name: https
    port: 443
    targetPort: 443
  selector:
    app.kubernetes.io/name: ingress-nginx
  type: NodePort

访问:NodeIP:NodePort

curl -I  172.26.253.208:31398

Node节点比较多的情况下可以使用nodeSelector来绑定到节点。



Ingress规则:

1、转发到单个后端服务上:这种情况下Ingress无需定义任何rule。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  backend:
    serviceName: myweb
    servicePort: 8080


2、根据path路径进行转发:

        Ingress中path的定义需要与后端真实Service提供的path一致,否者会转发到一个不存在的path上而引发报错。

示例1:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: mywebsite-ingress
spec:
  rules:
  - host: mywebsite.com
    http:
      paths:
      - path: /mywebsite
        backend:
          serviceName: mywebsite
          servicePort: 8080
      - path: /tomcat
        backend:
          serviceName: tomcat
          servicePort: 8080

示例2:

apiVersion: networking.k8s.io/v1beta1 # 新版本接口类型可以用这种,也可以用原来的那种
kind: Ingress
metadata:
  name: test-ingress
  namespace: default # 与被代理的资源在同一个名称空间下
  annotations:
    kubernetes.io/ingress.class: "nginx" # 指明 ingress-controller 的类型
    nginx.ingress.kubernetes.io/rewrite-target: / # 是否要做URL重定向
spec:
  rules:
  - host: www.123.com # 不定义host使用的是默认的虚拟机,定义host则使用新虚拟机
    http:
      paths:
      - path: /
#        pathType: Prefix
        backend:
          serviceName: myapp-svc
          servicePort: 8080

应用了之后可以查看详情信息:可以看到访问规则,被代理的服务等信息。

kubectl describe ingress test-ingress

配置好了之后可以在浏览器中访问测试:如果定义了域名就用域名来访问,这里的端口是nodePort的端口。

http://www.123.com:31951/

因为ingressController本质上就是个nginx可以进入到Pod内查看配置:

kubectl exec -it -n ingress-nginx ingress-nginx-controller-f8d756996-ndg79 -- cat nginx.conf | grep myapp


3、不同域名转发到不同服务器上:

apiVersion: extensions/v1beta1
kind: Ingress
metadata: 
  name: test
spec:
  rules:
  - host: bbs.demo.com
    http:
      paths:
      - backend:
          serviceName: bbs-svc
          servicePort: 8080
  - host: shop.demo.com
    http:
      paths:
      - backend: 
          serviceName: shop-svc
          servicePort: 8080


4、不使用域名转发规则:

        ingress-controller-ip/demo,注意这种方式会强制使用HTTPS,http会直接301了,可以在annotations中添加 ingress.kubernetes.io/ssl-redirect: "false" 来关闭https。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations: 
    ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - path: /demo
        backend: 
          serviceName: webapp
          servicePort: 8080


5、Ingress的TLS安全设置:

创建证书:

openssl genrsa -out myapp.key 2048
openssl req -new -x509 -key myapp.key -out myapp.crt -subj "/CN=www.456.com" -days 3650

创建secret:

kubectl create secret tls myapp-tls -n default --cert=myapp.crt --key=myapp.key

创建ingress规则:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-tls-myapp
  namespace: default # 同serviceName名称空间
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - www.456.com
    secretName: myapp-tls # secret名称
  rules:
    - host: www.456.com
      http:
        paths:
        - path: /
          backend:
            serviceName: myapp-svc
            servicePort: 8080



ingress官网文档:

https://kubernetes.io/docs/concepts/services-networking/ingress/

ingress-nginx配置的相关文档:

https://github.com/kubernetes/ingress-nginx/tree/master/docs/user-guide/nginx-configuration

configmap:配置全局nginx。

https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/configmap.md

annotations:配置单个规则,可以扩展ingress的功能,如做cookie绑定,会话保持等。

https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md

修改全局配置:

kubectl edit configmaps -n kube-system nginx-configuration

添加日志格式配置:替换了默认的日志格式。配置以键值对的形式添加,下面这个日志格式是loki的nginx 的dashboard模板。

apiVersion: v1
data:
  log-format-upstream: '{"msec": "$msec", "connection": "$connection", "connection_requests":
    "$connection_requests", "pid": "$pid","request_id": "$request_id", "request_length":
    "$request_length", "remote_addr": "$remote_addr","remote_user": "$remote_user","remote_port":
    "$remote_port","time_local": "$time_local","time_iso8601": "$time_iso8601","request":
    "$request","request_uri": "$request_uri","args": "$args","status": "$status","body_bytes_sent":
    "$body_bytes_sent","bytes_sent": "$bytes_sent","http_referer": "$http_referer","http_user_agent":
    "$http_user_agent","http_x_forwarded_for": "$http_x_forwarded_for","http_host":
    "$http_host","server_name": "$server_name", "request_time": "$request_time","upstream":
    "$upstream_addr","upstream_connect_time": "$upstream_connect_time","upstream_header_time":
    "$upstream_header_time","upstream_response_time": "$upstream_response_time","upstream_response_length":
    "$upstream_response_length","upstream_cache_status": "$upstream_cache_status","ssl_protocol":
    "$ssl_protocol","ssl_cipher": "$ssl_cipher", "scheme": "$scheme","request_method":
    "$request_method","server_protocol": "$server_protocol","pipe": "$pipe","gzip_ratio":
    "$gzip_ratio","http_cf_ray": "$http_cf_ray","geoip_country_code": "$geoip_country_code"
    }'
  proxy-body-size: 50m
kind: ConfigMap
metadata:
  labels:
    app: ingress-nginx
  name: nginx-configuration
  namespace: kube-system


Canary金丝雀发布功能:

开启金丝雀发路由功能:

nginx.ingress.kubernetes.io/canary: "true"

路由到指定的header:

nginx.ingress.kubernetes.io/canary-by-header:

路由到指定的header-value:

nginx.ingress.kubernetes.io/canary-by-header-value:

路由到匹配到的header:

nginx.ingress.kubernetes.io/canary-by-header-pattern:

路由到指定的cookie:

nginx.ingress.kubernetes.io/canary-by-cookie:

按照权重路由:

nginx.ingress.kubernetes.io/canary-weight:

优先级:

canary-by-header -> canary-by-cookie -> canary-weight

当启用金丝雀功能时除了下面两个其他的annotation将被忽略:

nginx.ingress.kubernetes.io/load-balance
nginx.ingress.kubernetes.io/upstream-hash-by