2018/06:经过一年多的发展Kubernetes的Ingress发生了很大的变化,这篇的很多地方都不适用了。因此决定结合我们目前的使用情况重新写几篇Kubernetes Ingress相关的分享,链接如下,内容是比较入门和初级的实操,请高手勿喷。

Ingress和Ingress Controller

前面写过一篇《从集群外部访问Kubernetes Service》,介绍了从Kubernetes集群外部访问Service的方式。本篇将实践一下使用Ingress将Kubernetes集群外部的流量接入到集群内。

一般来说Kubernetes集群中的节点位于互联网防火墙后边,在集群的前面有一个边界路由器(Edge router)用来实现集群的防火墙策略。边界路由器可以是云服务商提供或物理硬件管理的网关。Kubernetes集群的网络是一组物理或逻辑链接,使用Kubernetes的网络模型实现集群内的通信,我们的集群网络使用的是Overlay模型的flannel。在集群内通过虚拟IP访问服务。 对于集群外部的请求,所有到达边界路由器的流量会被丢弃或转发到其他地方。

Ingress可以授权和控制从集群外部访问集群内的Service。Ingress是授权进入集群并访问集群内Service的规则集合。 通过Ingress可以给Service配置外部可访问的URL、负载均衡、终止SSL、 按域名访问的虚拟主机等功能。

Ingress也是通过Kubernetes API创建的,但只是创建一个Ingress没有任何意义,需要先创建一个Ingress Controller。 Ingress Controller负责实现Ingress,通常是一个负载均衡器,也可以配置为边界路由器或者其他前端,这样就可以高可用的方式接入外部流量。

运行一个Ingress Controller

我们的Kubernetes集群是使用kubeadm初始化的,所以参考这里Deploying the Nginx Ingress controller on kubeadm clusters

1kubectl apply -f https://rawgit.com/kubernetes/ingress/master/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml
2
3deployment "default-http-backend" created
4service "default-http-backend" created
5deployment "nginx-ingress-controller" created

部署成功后,创建了如下两个Pod:

1kubectl get pods  --namespace=kube-system -l k8s-app=default-http-backend -o wide
2NAME                                    READY     STATUS    RESTARTS   AGE       IP            NODE
3default-http-backend-2198840601-4dr3x   1/1       Running   3          6m        10.244.2.13   node3
4
5kubectl get pods  --namespace=kube-system -l k8s-app=nginx-ingress-controller -o wide
6NAME                                        READY     STATUS    RESTARTS   AGE       IP              NODE
7nginx-ingress-controller-3697895370-ljhzm   1/1       Running   8          7m        192.168.61.43   node3

其中default-http-backend-2198840601-4dr3x作为 Nginx Ingress Controller默认的后端,处理所有404请求。因为我们还没有任何ingress规则生效,此时请求http://node3,将由此pod响应。

1curl http://node3
2default backend - 404

Nginx Ingress Controller的Pod被调度到node3上,作为负载均衡器监听80和443端口,将外部请求接入。

创建Ingress

集群部署两个服务nginx1-7和nginx1-8:

nginx1.7.yaml

 1apiVersion: v1
 2kind: Service
 3metadata:
 4  name: nginx1-7
 5spec:
 6  ports:
 7    - port: 80
 8      targetPort: 80
 9  selector:
10    app: nginx1-7
11---
12apiVersion: apps/v1beta1
13kind: Deployment
14metadata:
15  name: nginx1-7-deployment
16spec:
17  replicas: 2
18  template:
19    metadata:
20      labels:
21        app: nginx1-7
22    spec:
23      containers:
24      - name: nginx
25        image: nginx:1.7.9
26        ports:
27        - containerPort: 80

nginx1.8.yaml

 1apiVersion: v1
 2kind: Service
 3metadata:
 4  name: nginx1-8
 5spec:
 6  ports:
 7    - port: 80
 8      targetPort: 80
 9  selector:
10    app: nginx1-8
11---
12apiVersion: apps/v1beta1
13kind: Deployment
14metadata:
15  name: nginx1-8-deployment
16spec:
17  replicas: 2
18  template:
19    metadata:
20      labels:
21        app: nginx1-8
22    spec:
23      containers:
24      - name: nginx
25        image: nginx:1.8
26        ports:
27        - containerPort: 80
 1kubectl create -f nginx1.7.yaml
 2service "nginx1-7" created
 3deployment "nginx1-7" created
 4
 5kubectl create -f nginx1.8.yaml
 6service "nginx1-8" created
 7deployment "nginx1-8" created
 8
 9 kubectl get pods -o wide
10NAME                                   READY     STATUS    RESTARTS   AGE       IP            NODE
11nginx1-7-deployment-2912423055-rpclr   1/1       Running   0          10s       10.244.2.29   node3
12nginx1-7-deployment-2912423055-s4chf   1/1       Running   0          10s       10.244.0.16   node1
13nginx1-8-deployment-2060323882-dj786   1/1       Running   0          5s        10.244.1.36   node2
14nginx1-8-deployment-2060323882-r2vbg   1/1       Running   0          5s        10.244.2.30   node3
15
16
17kubectl get svc -o wide
18NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE       SELECTOR
19kubernetes   10.96.0.1        <none>        443/TCP   16d       <none>
20nginx1-7     10.104.163.171   <none>        80/TCP    46s       app=nginx1-7
21nginx1-8     10.108.239.60    <none>        80/TCP    41s       app=nginx1-8

假设这两个服务要暴露到集群外部。要创建一个ingress:

test-ingress.yaml

 1apiVersion: extensions/v1beta1
 2kind: Ingress
 3metadata:
 4  name: test
 5spec:
 6  rules:
 7  - host: n17.my.com
 8    http:
 9      paths:
10      - backend:
11          serviceName: nginx1-7
12          servicePort: 80
13  - host: n18.my.com
14    http:
15      paths:
16      - backend:
17          serviceName: nginx1-8
18          servicePort: 80
1kubectl create -f test-ingress.yaml
2ingress "test" created
3
4kubectl get ing
5NAME      HOSTS                   ADDRESS         PORTS     AGE
6test      n17.my.com,n18.my.com   192.168.61.43   80        14s

在客户机上配置host正确解析n17.my.com和n18.my.com,分别打开这两个地址可以请求到对应的nginx服务。

注意这里ingress中的规则是基于名称的虚拟主机,如果需要添加新的虚拟主机,可以修改test-ingress.yaml,使用kubectl replace -f更新即可。

参考