上次说了内部使用 coredns 实现服务发现的功能,外部服务发现可以通过service的nodeport的方式,对于小规模的应用使用 NodePort,但是当应用越来越多的时候,就会发现对于 NodePort 的管理就非常麻烦了。Kubernetes 还为我们提供了一个非常重要的资源对象可以用来暴露服务给外部用户,那就是 ingress。
ingress就是从kubernetes集群外访问集群的入口,将用户的URL请求转发到不同的service上。ingress相当于nginx反向代理服务器,它包括的规则定义就是URL的路由信息;它的实现需要部署
Ingresscontroller
(比如 traefik ingress-nginx 等),Ingresscontroller
通过apiserver监听ingress和service的变化,并根据规则配置负载均衡并提供访问入口,达到服务发现的作用。
1.未配置ingress:
集群外部 -> NodePort -> K8S Service 直接使用 nginx 就实现了,但是只使用 nginx 这种方式有很大缺陷,每次有新服务加入的时候怎么改 Nginx 配置。不可能让去手动更改或者滚动更新前端的 Nginx Pod 吧。
2.配置ingress:
集群外部 -> Ingress -> K8S Service 只是服务发现的功能自己实现了,不需要使用第三方的服务了,然后再加上一个域名规则定义,路由信息的刷新需要一个靠 Ingress controller 来提供,ingress 本身也需要部署
Ingresscontroller
时暴露NodePort
让外部访问。
3.现在可以供大家使用的 Ingress controller 有很多,比如 traefik、nginx-controller、Kubernetes Ingress Controller for Kong、HAProxy Ingress controller,当然你也可以自己实现一个 Ingress Controller,现在普遍用得较多的是 traefik 和 nginx-controller,traefik 的性能较 nginx-controller 差,但是配置使用要简单许多, traefik 为例给大家介绍 ingress 的使用。
https://traefik.io/
Traefik 是一款开源的反向代理与负载均衡工具。它最大的优点是能够与常见的微服务系统直接整合,可以实现自动化动态配置。目前支持 Docker、Swarm、Mesos/Marathon、 Mesos、Kubernetes、Consul、Etcd、Zookeeper、BoltDB、Rest API 等等后端模型。
通过上边的图可以看出来,通过域名访问后,Traefik 监听k8s里面的apiserver内部的服务,然后定向指向对应的服务。要使用 traefik,我们同样需要部署 traefik 的 Pod,由于我们演示的集群中只有 master 节点有外网网卡,所以我们这里只有 master 这一个边缘节点,我们将 traefik 部署到该节点上即可。
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
运行traefik-rbac.yaml
kubectl apply -f traefik-rbac.yaml
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
tolerations:
- operator: "Exists"
containers:
- image: traefik
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
- name: admin
containerPort: 8080
args:
- --api
- --kubernetes
- --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 8080
name: admin
type: NodePort
traefik 还提供了一个 web ui 工具,就是上面的 8080 端口对应的服务,为了能够访问到该服务,将服务设置成的 NodePort。
创建traefik
kubectl apply -f traefik.yaml
查看创建信息
kubectl get pods -n kube-system -o wide
kubectl get svc -n kube-system
traefik 是暴露的8080端口所以访问后面的暴露的30883端口访问,正常情况下本机需要在host文件下配置对应ip的域名的,为了演示我没配置。
目前的访问方式通过的nodePort的方式
创建ingress.yaml, 为了避免端口更改,这里的 servicePort 的值也可以替换成上面定义的 port 的名字:admin host必须是一个域名,不能是固定的ip,所以要在本地的host文件中添加对应自定义域名对应的ip
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: traefik.idig8.com
http:
paths:
- backend:
serviceName: traefik-ingress-service
servicePort: 8080
运行ingress.yaml
kubectl apply -f ingress.yaml
kubectl get ingress -n kube-system
kubectl get svc -n kube-syste
可以直接访问了 traefik.idig8.com:30894 ,通过ingress访问的traefik。
上面的访问 还是比较麻烦还需要记住端口,如果不想记住端口直接通过域名来访问的话需要修改 traefik.yaml 加入 hostPort: 80
ports:
- name: http
containerPort: 80
hostPort: 80
直接通过域名的方式访问:traefik.idig8.com
kubectl apply -f traefik.yaml
直接通过域名访问: traefik.idig8.com
PS:通过 ingress 对象对外成功暴露了一个服务,下次继续说说traefik更多的用法。通过配置 ingress.yaml 指向traefik中指定的端口,直接访问对应的端口的服务。