【ingress作用】
在kubernetes集群当中可以使用service的nodeport和loadblancer类型将应用暴露给外部用户使用,除此之外还为我们提供了一个非常重要的资源对象可以用来暴露服务给外部用户。进行小规模应用或者测试,使用nodeport可以满足需求,但是当应用越来越多的时候,nodeport的管理就非常麻烦了,这时候ingress就出现的,避免了管理大量端口。
【ingress是什么】
ingress是kubernetes内置的一个资源对象,是kubernetes集群外部访问集群的一个入口,将外部的请求转发到不同的service上,其实就是相当nginx和haproxy等负载均衡代理服务器。使用nginx也可以做到相同的作用,但是每次有新加入的服务怎么修改nginx配置,这样每次都要手动更改或者滚动更新前端的nginx的pod。
使用consul服务发现工具,利用consul-template去自动刷新nginx的配置确实可以,ingress实际上就是这样实现的,只是ingress不需要第三方的服务了,自己就有服务发现功能。
【ingress的工作原理】
创建的是ingress资源对象,实际上是ingress-controller起作用,ingress controller可以理解为一个监听器,通过不断监听kube-apiserver,实时感知后端service,pod当然也包括ingress的变化,然后ingress controller再结合ingress的配置,更新反向代理负载均衡器。
【ingress实际工作】
看到这里已经了解ingress资源对象只是一个路由请求描述配置文件,要让其真正生效还需要对应的ingress控制器才行。ingress的控制器有很多种,但是使用最多的是ingress-nginx,它是基于nginx的ingress控制器。
【部署ingress-nginx】
1,先下载ingress-nginx包,然后解压数据包。
wget https://github.com/kubernetes/ingress-nginx/archive/nginx-0.28.0.tar.gz
tar -zxvf nginx-0.28.0.tar.gz
[root@master ingress-nginx-nginx-0.28.0]# cd deploy/static/
[root@master static]# ls
configmap.yaml mandatory.yaml namespace.yaml provider rbac.yaml with-rbac.yaml
[root@master static]#
注意:这里使用镜像需要联网拉取,不需要更变镜像名称。
然后执行这个目录下的yaml文件
这里的清单主要定义了一个名称ingress-nginx的命名空间,创建了角色和服务账户,在其空间下创建了几个configmap,最重要的是deployment创建了一个ingress-nginx的pod。
2,然后需要有专门的nodePort service来引入外部流量
这种使用deploy控制管理ingress controller pod,如果没有在pod的模板里暴露端口,则需要创建一个service资源来暴露ingress controller pod的端口来引入外部流量到集群内部。
所以总共有三种方式来引入外部流量
一,创建NodePort类型的service,暴露端口
二,使用depoyment,在定义pod模板的时候使用hostPort,把pod端口映射到主机
三,第三种,定义pod模板时使用hostNetwork直接共享宿主机网络。
部署NodePort的方式:
创建一个nginx-service.yaml文件
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-service
namespace: ingress-nginx
spec:
type: NodePort
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
ports:
- port: 80
name: http
nodePort: 30080
- port: 443
name: https
nodePort: 30443
然后部署后查看service,外部机子访问测试。两个30080和30443都是404,因为还没有主页。
[root@master ingress]# kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-service NodePort 10.108.173.198 <none> 80:30080/TCP,443:30443/TCP 7m19s
部署hostPort方式:
只需要将需要部署的控制器类型更改为daemonSet,在pod模板中spec字段下去掉replicas,然后在spec.template.spec.containers.ports字段加上nodePort字段指定要把容器的端口映射到宿主机上的某个端口;如果暴露的端口时非标准端口,对应k8s集群外部,还需要部署一个反向代理,例如nginx,haproxy,lvs等。
然后访问物理机进行访问测试,访问到两个页面都是404即可。
部署hostNetwork方式:
需要将控制器的类型更改为Daemonset,在pod模板下去除replicas字段,然后再spec.template.spec字段下加上hostNetwork:true即可;以上的控制器都可以通过node标签选择器,选择再哪个node上调度pod。
然后访问物理机进行访问测试,访问到两个页面都是404即可。
3,然后创建需要测试访问的控制器和service。
编辑文件创建测试的depoyment控制器和service。
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 2
strategy:
type: RollingUpdate
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
nodeSelector:
ning: node2
volumes:
- name: test-volume
hostPath:
path: /ning
containers:
- name: myapp
image: nginx:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: test-volume
mountPath: /usr/share/nginx/html
---
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
type: ClusterIP
selector:
app: myapp
ports:
- port: 80
targetPort: 80
[root@master ingress]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
myapp 2/2 2 2 2m2s
[root@master ingress]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 152m
myapp ClusterIP 10.109.134.25 <none> 80/TCP 2m5s
注意:targetPort设置endpoints的端口是需要和服务指定端口相同,service的port可以进行变动。
4,创建完成后的测试pod和控制器现在没有任何关联,需要创建ingress定义反向代理规则,然后进行反向代理。
创建ingress资源,编写yaml文件。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-z
annotations: #注解配置表示把ingress的资源通知给哪个类别的ingress controller。
kubernetes.io/ingress.class: "nginx" #当有多个类别的ingress controller时,这一项特别有用。
spec:
rules: #里面主要字段就只有host和http
- host: www.myapp.com #用于指定虚拟主机的名称,如果不屑将匹配任意名称
http: #http用来定义指向后端的http选择器列表,其值为一个对象,里面只有一个paths
paths: #paths字段用于把请求映射到后端的某个路径,其值为一个对象列表
- path: / #定义path来指定映射后端的路径
backend: #backend用于指定后端pod的service,其值为一个对象
serviceName: myapp #serviceName指定对应的pod的service名称
servicePort: 80 #servicePort指定对应的pod后端的端口
#上面的内容将所有www.myapp.com这个虚拟机的访问全部反向代理至服务器名称为test-ingress-service端口为80的pod上。
然后查看创建结果和ingress-nginx里面是否获取到了结果。
[root@master ~]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-z <none> www.myapp.com 80 11m
[root@master ~]# kubectl describe ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-z <none> www.myapp.com 80 5s
[root@master test]# kubectl describe ingress ingress-z
Name: ingress-z
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
www.myapp.com
/usr/share/nginx/html myapp:80 (10.244.2.4:80,10.244.2.5:80)
Annotations: kubernetes.io/ingress.class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 18s nginx-ingress-controller Ingress default/ingress-z
[root@master ~]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-cff87d767-mbl6m 1/1 Running 0 12m
[root@master ~]# kubectl exec -it nginx-ingress-controller-cff87d767-mbl6m bash -n ingress-nginx
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
bash-5.0$ cd /etc/nginx
bash-5.0$ cat nginx.conf | grep www.myapp.com
## start server www.myapp.com
server_name www.myapp.com ; #这里有结果
## end server www.myapp.com
bash-5.0$ exit
exit
[root@master ~]#
如果有server_name www.myapp.com就说明ingress-nginx已经获取到了。
然后用浏览器访问即可。
记得更改客户机的hosts文件,[k8s集群的ip] www.myapp.com 。
这样就能够访问成功。