kubernetes IngressController
Ingress Controller 可以用来卸载https 会话和实现七层调度,在应用层实现路由,service只能在四层实现调度。service收集来的后端Pod信息并由Ingress 动态注入到 Ingress Controller当中。
外部的负载均衡器 --> 共享节点网络的Pod,Ingress 或 service来接入流量 --> 虚拟主机或者Url实现七层调度 --> headless service --> 后端Pod。
Ingress Controller的两种使用方式:
这里使用的是第二种方式:
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 https://grafana.com/grafana/dashboards/20275-ingress-nginx-dashboard/
使用 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