kubernetes笔记: ingress
by 伊布
What is Ingress?
internet
|
------------
[ Services ]
service通常只是在集群内部有效,从集群外是无法访问到的。
在kubernets的世界里,服务要对集群外暴漏,有这么几种方式:
- NodePort
- LoadBalancer
- External IPs
- Ingress
之前比较常用的是NodePort,搭配keepalived可以获得一定程度的HA。NodePort、LoadBalance、External IPs可以认为是L4的,而Ingress则是L7的。与前者通常使用iptables、LVS等手段不同,Ingress通常是基于nginx的,可以认为是一个openresty。
internet
|
[ Ingress ]
--|-----|--
[ Services ]
Ingress是一种资源,和Pod、Configmap等等类似,也需要一个controller来管理。
kubernetes的ingress是这样玩的:集群部署时,创建一个或多个ingress controller,他们会去监听api server;当用户创建Ingress时,controller会通过api server获取新创建的Ingress的信息(主要是vhost、路径、service+port。注意ingress-nginx会直接将service翻译为endpoint,减少了service这一层转换),根据nginx模板生成新的nginx配置文件(主要是proxy_pass到RS),最后reload nginx重新加载配置。在下面的几个示例中,将看到这个过程。
Ingress controller可以有不同的实现,目前社区可以用的主要是 ingress-nginx和ingress-gce。
我们采用的是ingress-nginx。
ingress types
来看看ingress有哪些类型。
single service ingress
单服务,无vhost,无路径。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
backend:
serviceName: testsvc
servicePort: 80
这种情况下,所有到该ingress的流量(/
后的所有http请求。),都会转到 testsvc:80。感觉应该不怎么会用到。
upstream argo-http-svc-80 {
least_conn;
keepalive 32;
server 10.244.3.118:8080 max_fails=0 fail_timeout=0;
}
server {
location / {
proxy_pass http://argo-http-svc-80;
proxy_redirect off;
}
Simple fanout
fanout是个很有意思的词。简单理解就是这种ingress会将用户的请求根据路径fanout到多个Real Server去。例如下例,发给foo.bar.com的请求会根据url进行路由。
foo.bar.com -> 178.91.123.132 -> / foo s1:80
/ bar s2:80
编排文件如下。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: s1
servicePort: 80
- path: /bar
backend:
serviceName: s2
servicePort: 80
nginx配置。
upstream argo-s1-80 {
least_conn;
keepalive 32;
server 10.244.3.118:8080 max_fails=0 fail_timeout=0;
}
upstream argo-s2-80 {
least_conn;
keepalive 32;
server 10.244.3.147:8080 max_fails=0 fail_timeout=0;
}
## start server foo.bar.com
server {
server_name foo.bar.com ;
listen 80;
listen [::]:80;
set $proxy_upstream_name "-";
location / {
# proxy balabala
proxy_pass http://upstream-default-backend;
proxy_redirect off;
}
location /foo {
# proxy balabala
proxy_pass http://argo-s1-80;
proxy_redirect off;
}
location /bar {
# proxy balabala
proxy_pass http://argo-s2-80;
proxy_redirect off;
}
注意!如果ingress中没有指定hosts,也可以用IP地址来访问,但ingress-nginx默认要求https,所以这时会遇到访问总是308跳转的问题。
例如下面这个ingress。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mini-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /mini
backend:
serviceName: nginx
servicePort: 80
访问/mini路径时,总是返回308重定向.
此时的nginx.conf对应的配置如下,可以看到,如果redirect_to_https,则会跳转到https。
location ~* ^/mini\/?(?<baseuri>.*) {
# enforce ssl on server side
if ($redirect_to_https) {
return 308 https://$best_http_host$request_uri;
}
怎么解决呢?在issues/1567给了一个比较好的办法:指定 nginx.ingress.kubernetes.io/ssl-redirect
为false,也就是不要对http强制跳转。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: geth
annotations:
namespace: xxp
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /eth
backend:
serviceName: geth
servicePort: 8545
ingress-nginx的处理
Name based virtual hosting
nginx可以根据用户请求的hosts,来转发到对应的Real Server。如下图。注意IP地址、端口号都是不变的。
foo.bar.com --| |-> foo.bar.com s1:80
| 178.91.123.132 |
bar.foo.com --| |-> bar.foo.com s2:80
编排文件
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: s1
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: s2
servicePort: 80
对应的nginx配置。
upstream argo-http-svc-80 {
least_conn;
keepalive 32;
server 10.244.3.118:8080 max_fails=0 fail_timeout=0;
}
upstream argo-http-svc2-80 {
least_conn;
keepalive 32;
server 10.244.3.147:8080 max_fails=0 fail_timeout=0;
}
server {
server_name bar.foo.com ;
listen 80;
listen [::]:80;
set $proxy_upstream_name "-";
location / {
# proxy balabala
proxy_pass http://argo-http-svc2-80;
proxy_redirect off;
}
}
## end server bar.foo.com
server {
server_name foo.bar.com ;
listen 80;
listen [::]:80;
location / {
# proxy balabala
proxy_pass http://argo-http-svc-80;
proxy_redirect off;
}
}
## end server foo.bar.com
Multiple ingress controllers
某些情况下我们可能希望区分不同的ingress(例如不同区域、不同配置、不同环境),此时k8s集群上会有多个ingress controller,创建Ingress时,需要指定希望哪个controller来处理该请求。
不同的ingress controller,通过 ingress-class
来区分。
spec:
template:
spec:
containers:
- name: nginx-ingress-internal-controller
args:
- /nginx-ingress-controller
- '--default-backend-service=ingress/nginx-ingress-default-backend'
- '--ingress-class=nginx'
- '--configmap=ingress/nginx-ingress-controller'
创建ingress时,指定不同的ingress-class
。
metadata:
name: foo
annotations:
kubernetes.io/ingress.class: "gce"
metadata:
name: foo
annotations:
kubernetes.io/ingress.class: "nginx"
Ref:
Subscribe via RSS