Ingress简介
ingress 是除了 hostport nodeport clusterIP以及云环境专有的负载均衡器外的访问方式,通常情况下,service和pod的IP可以被集群网络访问。ingress是允许入站连接到达群集服务的规则集合。可以为外部提供可访问服务的URL,PATH路径,流量负载均衡,可被终止的ssl连接,以及基于配置的虚拟主机。
不同于k8s的ingress,我们开发的ingress服务支持rancher,并且定义了软件堆栈, 微服务概念。 可以使用NodeIP,暴露部分端口。通过反向代理,在云环境外访问云环境中的不同域名,不同的路径,不同网络协议的微服务,于是访问云内部的服务,有了一个统一的调用方式。 ingress服务通过接口更新,监听整个容器环境的变化,再配合接口下发转发规则来完成流量中转服务的配置更新。
核心组件,反向代理,负载均衡的选择
产品名 说明
F5 硬件负载性能高,有SDK
HAPROXY 软件性能相对高
NGINX 软件性能相对弱一些, 但功能更全,
配置更灵活, 用户量更大,
支持文档更多。
我们选择了NGINX
nginx升级版本有tingine, openresty
产品名 说明 比较
tingine nginx官方的分支版本 有部分配置
与官方版本不一样
openresty nginx官方的补丁包 拥有nginx官方版
的所有功能。可
以支持LUA+数
据库可实现高
性能路由功能。
我们选择了openresty,方便新增功能,不受限.只要nginx官方支持,我们都能集成enter code here
ingress设计架构
ingress设计图
ingress网络
技术要点
Ingress-Controller (中心处理节点)
▪ mysql 中心数据库
▪restful 提供对外的服务,接口。
1.下发ingress规则配置
2.蓝绿部署功能
3.部署状态....
▪web-socket
通讯的基础,异步的发送任务,同步+超时机制获得执行结果。
Ingress-Agent (监控中节点)
▪sqlite 本地数据库
▪docker-api
进行docker-event监听用户容器的事件。
▪ancher-metadata
获得metadata的容器详细信息。
▪nsenter
直接把网站相关的SSL相关的证书CRT,KEY,配置文件,nsenter --target {{}} --net curl 写到ingress-lb 的nginx.conf的目录中。
Ingress-lb (流量转发节点)
▪restful接口
设置新的配置文件,重新加载
查看当前配置文件
重新加载
▪template模板文件生成nginx配置文件
▪SSL安全隧道
resource manager 统一的管理域名对应的key,crt文件。在系统内部下载,并放到nginx需要的位置,完成SSL中转的功能了。
▪会话保持功能
在多台后端服务器情况下,为了让一个客户只和一台服务器通信的长连接。
IP_HASH nginx自带的方式,根据客户端公网IP不同,分布到后端服务器中去。如果一个局域网的客户同时访问服务器,有相同的公网IP,这时候IP_HASH就不能保证每次访问都能粘滞在同一台服务器。
Cookie Sticky 每台电脑都会有不同的cookie.。在保持长连接的同时,还能分布到不同的后端服务器。
▪流量限制
可以使用不同自定义的template生成扩展新的功能。
第一版本ingress通过 ingress-agent 感知云环境配置变化 + golang模板 + [nginx -s reload ]完成自动配置
nginx的配置文件示例
worker_processes 1;
events {
worker_connections 1024;
}
http {
upstream backend {
sticky;
server 192.168.0.2:80;
server 192.168.0.3:80;
# 每个5秒检测一次, 请求2次正常则标记realserver状态为up, 如果检测3次都失败,
# 则标记realserver的状态为down,超过时间为1秒.
check interval=5000 rise=2 fall=3 timeout=1000 type=http;
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 80;
server_name _;
index index.html;
location / {
# 设置主机名和客户端真实地址,以便服务器获取客户端真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 禁用缓存
proxy_buffering off;
# 反向代理的地址
proxy_pass ;
}
location /status {
check_status;
access_log off;
allow 172.29.73.23;
deny all;
}
}
}
nginx的配置文件模板示例
daemon off;
worker_processes 1;
error_log logs/error.log;
events {
multi_accept on;
worker_connections 1024;
use epoll;
}
stream {
{{ range .Streams }}
upstream {{ .Upstream.Name }} {
{{ range .Upstream.EndPoints }} server {{ .Server }}:{{ .Port }} weight={{ .Weight }} max_fails={{ .MaxFails }} fail_timeout={{ .FailTimeout }}{{ if .Down }} down{{ end }};
{{ end }}}
server {
listen {{ .Server.Listen }}{{ if eq .Server.Protocol "udp" }} udp{{ end }};
proxy_pass {{ .Server.ProxyPass }};
}
{{ end }}
}
http {
{{ range .Https }}
upstream {{ .Upstream.Name }} {
{{ if ne .Upstream.SessionSticky.Name "" }} sticky{{ if ne .Upstream.SessionSticky.Name "" }} name={{ .Upstream.SessionSticky.Name }}{{ end }}{{ if ne .Upstream.SessionSticky.Domain "" }} domain={{ .Upstream.SessionSticky.Domain }}{{ end }}{{ if ne .Upstream.SessionSticky.Path "" }} path={{ .Upstream.SessionSticky.Path }}{{ end }}{{ if ne .Upstream.SessionSticky.Expires "" }} expires={{ .Upstream.SessionSticky.Expires }}{{ end }}{{ if ne .Upstream.SessionSticky.Hash "" }} hash={{ .Upstream.SessionSticky.Hash }}{{ end }}{{ if eq .Upstream.SessionSticky.NoFallback true }} no_fallback{{ end }};{{ end }}
{{ if eq .Upstream.RoutingMode "ip-hash" }} ip_hash; {{ end }}{{ $routing_mode := .Upstream.RoutingMode }}
{{ range .Upstream.EndPoints }} server {{ .Server }}:{{ .Port }} {{ if eq $routing_mode "round-robin" }} weight={{ .Weight }} {{ end }} max_fails={{ .MaxFails }} fail_timeout={{ .FailTimeout }}{{ if .Down }} down{{ end }};
{{ end }}}
server {
listen {{ .Server.Listen }};
server_name {{ .Server.ServerName }};
{{ if .Server.UseSSL }}
# for support ssl
ssl on;
ssl_certificate {{ .Server.SSLCertificate }};
ssl_certificate_key {{ .Server.SSLPrivateKey }};
{{ end }}
{{ range .Server.Locations }}
location {{ .Path }} {
{{ if .UseGzip }}
# for support data zip
gzip on;
gzip_comp_level 5;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript
text/xml application/xml application/xml+rss text/javascript;
gzip_proxied any;
{{ end }}
proxy_pass http://{{ .Host }}/;
# for support backend server.
# 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
{{ end }}
}
{{ end }}
}
测试配置文件是否能被使用
/usr/local/nginx-1.0.6/sbin/nginx -t
重新加载 nginx配置文件
/usr/local/nginx-1.0.6/sbin/nginx -s realod
虽然nginx -s reload 不中断业务,但当连接量很大的时候,可能出现部分访问失败的问题。接下来的工作,修改LUA+redis配置数据转发规则,只要修改nginx监听端口,nginx无需要重启,实现高性能动态配置的修改。