Ingress是一个API对象,用来管理集群外部访问集群内部的服务(主要为http和https)。Ingress可以提供负载均衡、ssl卸载和虚拟主机的功能。
Ingress控制器
Ingress控制器不同于其他控制,他不属于控制器管理器,而是一个类似coreDns的插件,常用的ingress控制器类型有:
Contour(envoy)、F5、Haproxy、ISTIO、Kong、Nginx、Traefik
可以在集群中部署任意数量的ingress控制器,其实就是部署多个Deployment或者DaemonSet。创建ingress资源时使用ingress-class注释annotate使用哪个ingress controller。
Ingress资源
与其他资源相同,ingress资源也有apiVersion、kind和metadata三个字段。不同的ingress控制器支持不同的annotations,ingress经常使用annotations来配置一些选项,例如rewrite-target。了解支持哪些注释需要查看相关文档。Ingress spec包含配置负载均衡器或代理服务器所需的所有信息。ingress资源仅支持用于HTTP的规则,每个HTTP规则都包含以下信息:
主机(可选):适用于虚拟主机
路径列表(例如,/testpath),每个路径都有一个用servicename和serviceport定义的相关后端。在LoadBalancer将流量导向引用的服务之前,主机和路径必须与传入请求的内容匹配。
后端是服务和端口名称的组合。对与主机和规则路径匹配的入口的HTTP(和HTTPS)请求将发送到列出的后端。
缺省后端ingress.spec.backend,未匹配到任何rule的流量,将路由至缺省后端
Ingress实验
1、部署ingress controller
访问github上的项目网站https://github.com/kubernetes/ingress-nginx
下载deploy目录中的部署文件mandatory.yaml
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
Kubectl apply -f mandatory.yaml
所有涉及的资源:
namespace/ingress-nginx
configmap/nginx-configuration
configmap/tcp-services
configmap/udp-services
serviceaccount/nginx-ingress-serviceaccount
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole
role.rbac.authorization.k8s.io/nginx-ingress-role
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding
deployment.extensions/nginx-ingress-controller
部署完成后,会生产一个nginx-ingress-controller的pod
2、ingress service外部访问
新建NodePort类型的service,这样所有node上都可以监听80和443端口,报文会转发至ingress controller,标签选择器与前面部署ingress控制器的标签一致
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
3、配置后端服务和deployment
新建后端服务testsvc及相关的deployment busybox-httpd
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
run: busybox-httpd
name: busybox-httpd
spec:
replicas: 2
selector:
matchLabels:
run: busybox-httpd
template:
metadata:
labels:
run: busybox-httpd
spec:
containers:
- command:
- /bin/sh
- -c
- ifconfig > index.html && /bin/httpd -f
image: busybox
name: busybox-httpd
---
apiVersion: v1
kind: Service
metadata:
labels:
tier: front
name: testsvc
namespace: default
spec:
selector:
run: busybox-httpd
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
type: ClusterIP
再新建一个后端服务hostnamesvc及相关的deployment busybox-httpd-2
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
run: busybox-httpd-2
name: busybox-httpd-2
spec:
replicas: 2
selector:
matchLabels:
run: busybox-httpd-2
template:
metadata:
labels:
run: busybox-httpd-2
spec:
containers:
- command:
- /bin/sh
- -c
- hostname > index.html && /bin/httpd -f
image: busybox
name: busybox-httpd
---
apiVersion: v1
kind: Service
metadata:
labels:
tier: front
name: hostnamesvc
namespace: default
spec:
selector:
run: busybox-httpd-2
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
type: ClusterIP
5、配置ingress资源
新建ingress资源test-ingress,选择服务testsvc作为后端
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
backend:
serviceName: testsvc
servicePort: 80
查看ingress service,他将HTTP自动分配到NodePort 30746,而endpoint为10.244.1.90:80
在所有节点上,都可以看到这个端口已经监听
查看ingress对象可以看到test-ingress选择了testsvc这个service,并且可以直接获得了service的endpoints,并没有使用service的IP 10.110.72.96.
修改ingress资源test-ingress,设置两个虚拟机主机test1和test2,再新建一个后端服务datesvc及相关的deployment busybox-httpd-3。
注意:如果ingress中没有指定hosts,也可以用IP地址来访问,但ingress-nginx默认要求https,所以这时会遇到访问总是308跳转的问题,需要增加注释nginx.ingress.kubernetes.io/ssl-redirect: "false"来解决。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: test1
http:
paths:
- path:
backend:
serviceName: testsvc
servicePort: 80
- host: test2
http:
paths:
- path:
backend:
serviceName: hostnamesvc
servicePort: 80
- http:
paths:
- path: /
backend:
serviceName: datesvc
servicePort: 80
修改host文件
访问test1、test2和使用ip访问
可以通过查看nginx配置来验证:
kubectl -n ingress-nginx exec -it nginx-ingress-controller-6c885cc56d-8n5nh -- /bin/sh
增加ssl卸载功能
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=SC/L=CHENGDU/O=IT/CN=test1
kubectl create secret tls test1 --cert=tls.crt --key=tls.key
未配置ssl证书的站点默认也有一个证书,缺省用https也可以打开
Hostnetwork的方式:
修改deployment,将kind修改为daemonSet,因为controller必须监听到多个node上
去掉replicas,因为daemonSet不需要replicas
增加daemonset.spec.template.spec.hostNetwork 为true
注意: 部署ingress时需要注意端口不与node上的应用端口冲突,一般建议部署在部分专用node上