Go微服务架构实战 中篇:4. 基于ingress的限流,路径匹配和重写实战

240 阅读3分钟

Go微服务架构实战-【公粽号:堆栈future】

Go微服务架构实战目录

1. 微服务架构上篇

1. grpc技术介绍

2. grpc+protobuf+网关实战

3. etcd技术介绍

4. 基于etcd的服务发现与注册

5. 基于etcd的分布式锁实战

2. 微服务架构中篇

1. k8s架构介绍

2. 基于k8s的容器化部署

3. 基于k8s的Deployment工作负载

4. 基于k8s的ingress实战

到现在为止我们的服务都是跑在集群内部的,为了让集群外部也能访问,那么我们需要让服务外化,但是因为minikube在mac上是网络不通的,所以我们我们直接就在minikube环境中测试(minikube ssh进入即可)。

1. 创建Pod的service

创建pod的service,类型是NodePort,我们看下svc.yaml:

apiVersion: v1
kind: Service
metadata:
  name: k8sdemo-svc # service的服务名称
spec:
  ports:
    - name: k8sdemo-svc
      port: 8000 # service的端口
      targetPort: 60001 # 容器服务的端口
  selector:
    app: k8sdemo # 关联pod
  type: NodePort # 对外暴露


创建完成之后,我们可以kubectl get svc查看是否创建成功图片

通过上图可以知道service是创建成功的,接下来看下架构图:图片

随便拿一台机器的公网IP+NodePort就可以访问了,我们这里可以在minikube中验证下:http://$(minikube ip):NodePort

docker@minikube:~curl -X POST  http://192.168.49.2:30143/hello -d '{"name": "fromGW"}'
{"message":"Hello fromGW from 172.17.0.16:50009"}

可以看到是没有问题的。我们从图中可以看出service是pod的更高一层抽象,负责服务发现和负载均衡,当某个Pod挂掉的时候,service会发现这个问题然后把请求打到别的Pod上。同样当在创建一个带有相同标签的Pod的时候,它会自动加入到service中,然后service会把流量按照某种负载均衡算法分发到各个Pod中。

2. 创建ingress

先安装ingress-nginx,我们先把ingress-nginx下载到本地,然后把镜像地址替换下,防止下载速度慢。

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/baremetal/deploy.yaml

sed -i 's@k8s.gcr.io/ingress-nginx/controller:v1.0.0\(.*\)@cnsre/ingress-nginx-controller:v1.0.0@' deploy.yaml
sed -i 's@k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0\(.*\)$@cnsre/ingress-nginx-kube-webhook-certgen:v1.0@' deploy.yaml

通过kubectl apply -f deploy.yaml安装。

可以看下是否安装成功:图片

图片目前来看是安装成功的。

接下来创建我们自己的ingress,这个ingress实现的功能就是路径匹配,重写以及限流,这个yam文件内容如下,ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress # ingress对象
metadata:
  name: k8sdemo-ingress-prefix # 验证前缀匹配的
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: hi.k8sdemo.com # 域名
      http:
        paths:
          - path: "/hello" # 前缀匹配
            pathType: Prefix
            backend:
              service:
                name: k8sdemo-svc
                port:
                  number: 8000 # service的端口
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: k8sdemo-ingress-rewrite # 这个ingress是关于验证重写的
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /$2 # 重写注解
spec:
  rules:
    - host: hello.k8sdemo.com
      http:
        paths:
          - pathType: Prefix
            path: "/api(/|$)(.*)"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
            backend:
              service:
                name: k8sdemo-svc  # 如果是/api/hello 去掉前缀api 用/hello访问服务 网关一般这么搞
                port:
                  number: 8000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: k8sdemo-ingress-limit-rate
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "1" # rps:每秒多少请求 超过之后就报错 https status: 503
spec:
  ingressClassName: nginx
  rules:
    - host: hi.k8sdemo.com
      http:
        paths:
          - pathType: Exact # 精确匹配
            path: "/hello" # 针对这个路径限流
            backend:
              service:
                name: k8sdemo-svc
                port:
                  number: 8000                  

通过kubectl apply -f deploy.yaml创建。可以查看下是否创建成功:

图片

可以看到这三个ingress绑定了两个host,接下来申请域名绑定ingress的ip地址,即上图中的192.168.49.2。但因为我们是minikube本地测试,所以绑定hosts就可以了。修改/etc/hosts:

192.168.49.2 hello.k8sdemo.com
192.168.49.2 hi.k8sdemo.com

保存之后我们就可以验证测试了。大致架构图就是:

图片

3. 验证ingress

我们再次看下ingress的svc对外暴露的端口是:图片可以看到是31721,接下来我们通过域名+端口来访问后端服务。

  1. 首先验证通过正常路径匹配访问
docker@minikube:~curl -X POST  http://hi.k8sdemo.com:31721/hello -d '{"name": "fromGW"}'
{"message":"Hello fromGW from 172.17.0.16:50009"}

发现是成功的。

  1. 验证路径重写
docker@minikube:~$ curl -X POST  http://hello.k8sdemo.com:31721/api/hello -d '{"name": "fromGW"}'
{"message":"Hello fromGW from 172.17.0.16:50009"}

发现是成功的。

4. ingress限流

docker@minikube:~$ curl -X POST  http://hi.k8sdemo.com:31721/hello -d '{"name": "fromGW"}'
<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx</center>
</body>
</html>

当我们一秒请求的/hello次数大于1的时候报错,nginx返回503,这样就验证了我们的ingress的限流功能。

5. 总结

本小节算是重点,我们要了解ingress如何暴露服务,如何重写路径以及如何限流等。路径重写很重要,比如接口地址是:http://example.gateway.com/user-center/userinfohttp://example.gateway.com/user-center/userprofile,网关地址是http://example.gateway.com,路由到后端服务是userinfo,那么在网关层为了区分我们的服务,会统一加一层user-center,这样就可以区分不同业务了,但是user-center不是我们想要的,我们用它只是区分业务,所以需要在ingress层做下路径重写,这样到后端的服务就没有了user-center了。

还有基于ingress的限流功能也非常简单,大家可以尝试用起来。

参考:

kubernetes.github.io/ingress-ngi…

堆栈future

使很多处于迷茫阶段的coder能从这里找到光明,堆栈创世,功在当代,利在千秋

公粽号:堆栈future