Kubernetes Ingress实战

2017-04-21 阅读: Kubernetes

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

kubectl apply -f https://rawgit.com/kubernetes/ingress/master/examples/deployment/nginx/kubeadm/nginx-ingress-controller.yaml

deployment "default-http-backend" created
service "default-http-backend" created
deployment "nginx-ingress-controller" created

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

kubectl get pods  --namespace=kube-system -l k8s-app=default-http-backend -o wide
NAME                                    READY     STATUS    RESTARTS   AGE       IP            NODE
default-http-backend-2198840601-4dr3x   1/1       Running   3          6m        10.244.2.13   node3

kubectl get pods  --namespace=kube-system -l k8s-app=nginx-ingress-controller -o wide
NAME                                        READY     STATUS    RESTARTS   AGE       IP              NODE
nginx-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响应。

curl http://node3
default backend - 404

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

创建Ingress

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

nginx1.7.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx1-7
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx1-7
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx1-7-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx1-7
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

nginx1.8.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx1-8
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx1-8
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx1-8-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx1-8
    spec:
      containers:
      - name: nginx
        image: nginx:1.8
        ports:
        - containerPort: 80
kubectl create -f nginx1.7.yaml
service "nginx1-7" created
deployment "nginx1-7" created

kubectl create -f nginx1.8.yaml
service "nginx1-8" created
deployment "nginx1-8" created

 kubectl get pods -o wide
NAME                                   READY     STATUS    RESTARTS   AGE       IP            NODE
nginx1-7-deployment-2912423055-rpclr   1/1       Running   0          10s       10.244.2.29   node3
nginx1-7-deployment-2912423055-s4chf   1/1       Running   0          10s       10.244.0.16   node1
nginx1-8-deployment-2060323882-dj786   1/1       Running   0          5s        10.244.1.36   node2
nginx1-8-deployment-2060323882-r2vbg   1/1       Running   0          5s        10.244.2.30   node3


kubectl get svc -o wide
NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE       SELECTOR
kubernetes   10.96.0.1        <none>        443/TCP   16d       <none>
nginx1-7     10.104.163.171   <none>        80/TCP    46s       app=nginx1-7
nginx1-8     10.108.239.60    <none>        80/TCP    41s       app=nginx1-8

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

test-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  rules:
  - host: n17.my.com
    http:
      paths:
      - backend:
          serviceName: nginx1-7
          servicePort: 80
  - host: n18.my.com
    http:
      paths:
      - backend:
          serviceName: nginx1-8
          servicePort: 80
kubectl create -f test-ingress.yaml
ingress "test" created

kubectl get ing
NAME      HOSTS                   ADDRESS         PORTS     AGE
test      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更新即可。

参考

标题:Kubernetes Ingress实战
本文链接:https://blog.frognew.com/2017/04/kubernetes-ingress.html
转载请注明出处。

目录