在上一篇(一)服务注册与发现Eureka的集群搭建与配置 中,我们将基本的Eureka搭建完毕,接下来就需要搭建好对外暴露服务的Api服务,在我的项目中,使用的zuul作为api-gateway,接下来我将详细讲解,在工程中是如何配置并对外暴露端口提供服务的。

一.搭建zuul网关服务

首先我们需要搭建好自己的微服务Zuul工程,具体的搭建我这就不具体细说,这里并不需要对我们本身的微服务进行特殊的修改及配置,唯一一个注意的点就是需要将端口设置为k8s集群中配置好的端口范围。

K8S中NodePort方式暴露服务的端口的默认范围(30000-32767)

 二. 配置K8s文件

1. 控制器的选择

Zuul网关与eureka服务不同的是,它可以作为无状态服务进行部署,因此本文将采用deployment的方式进行部署,同时这也是最常见的方式之一。

Deployment 是最常用的用于部署无状态服务的方式。Deployment 控制器使得您能够以声明的方式更新 Pod(容器组)和 ReplicaSet(副本集)。例如,以滚动更新为例,假设有 3 个容器组,现需要将他们的容器镜像更新为新的版本。

声明的方式,您只需要执行: 

  • 使用 kubectl 更新 Deployment 定义中 spec.template.spec.containers[ ].image 字段

这边暂不详述滚动更新操作,后续会进行扩展,感兴趣的也可以自己去了解查询。

2. 配置文件详解

(一)api-gateway.yaml文件配置

---
apiVersion: apps/v1
kind: Deployment
metadata:
    name: api-gateway-deployment
    namespace: box
spec:
    selector:
      matchLabels:
        app: api-gateway
    replicas: 3
    template:
        metadata:
            labels:
                app: api-gateway
        spec:
            containers:
            - name: api-gateway
              image: harbor.box.com/box/api-gateway
              imagePullPolicy: Always
              ports:
              - containerPort: 19899
              env:
              - name: eureka.client.service-url.defaultZone
                value:
                   "http://eureka-0.eureka.box.svc.cluster.local:8761/eureka,http://eureka-1.eureka.box.svc.cluster.local:8761/eureka,http://eureka-2.eureka.box.svc.cluster.local:8761/eureka"
              - name: global.versionEnable
                value:
                   "false"
              volumeMounts:
              - mountPath: /apps/logs/box
                name: box-logs
            volumes:
            - name: box-logs  #日志挂载
              hostPath:
                 path: /apps/logs/box

 采用了deployment的部署方式,同时通过env对容器的环境变量进行配置,这里可以根据自己工程中需要的配置进行添加修改。

(二)api-gateway-nodePort.yaml文件配置

# ------------------- Api-Gateway ------------------- #
apiVersion: v1
kind: Service
metadata:
    labels:
      app: api-gateway
    name: api-gateway
    namespace: box
spec:
    type: NodePort
    sessionAffinity: ClientIP
    sessionAffinityConfig: #配置session保持
      clientIP:
        timeoutSeconds: 50800
    ports:
    - port: 19899 #服务端口
      protocol: TCP
      targetPort: 19899 #容器端口
      nodePort: 31000 #对外node节点端口
    selector:
      app: api-gateway

### 当不设置session保持时,service向后台pod转发规则是轮询。当设置了session保持之后,k8s会根据访问的ip来把请求转发给他以前访问过的pod,这样session就保持住了。 

如何将集群内部服务对外暴露?

将集群外部流量导入到集群内的有三种方式,只是实现方式不同。分别是NodePort,LoadBalancer 和 Ingress 。这三种方式各有利弊。

LoadBalancer 服务是暴露服务到 internet 的标准方式。在 GKE 上,这种方式会启动一个Network Load Balancer,它将给你一个单独的 IP 地址,转发所有流量到你的服务。

如果你想要直接暴露服务,这就是默认方式。所有通往你指定的端口的流量都会被转发到对应的服务。它没有过滤条件,没有路由等。这意味着你几乎可以发送任何种类的流量到该服务,像 HTTP,TCP,UDP,Websocket,gRPC 或其它任意种类。

这个方式的最大缺点是每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是非常昂贵的。

 Ingress 事实上不是一种服务类型。相反,它处于多个服务的前端,扮演着“智能路由”或者集群入口的角色。

默认 ingress 控制器是启动一个HTTP(s)Load Balancer。它允许你基于路径或者子域名来路由流量到后端服务。例如,你可以将任何发往域名 foo.yourdomain.com 的流量转到 foo 服务,将路径 yourdomain.com/bar/path 的流量转到 bar 服务。

如果你想要使用同一个 IP 暴露多个服务,这些服务都是使用相同的七层协议(典型如 HTTP),那么Ingress 就是最有用的。如果你使用本地的 GCP 集成,你只需要为一个负载均衡器付费,且由于 Ingress是“智能”的,你还可以获取各种开箱即用的特性(比如 SSL,认证,路由,等等)。 NodePort方式的选择及缺点

NodePort的选择及缺点

NodePort 服务是引导外部流量到你的服务的最原始方式。NodePort,正如这个名字所示,在所有节点(虚拟机)上开放一个特定端口,任何发送到该端口的流量都被转发到对应服务。

NodePort 服务主要有两点区别于普通的“ClusterIP”服务。第一,它的类型是“NodePort”。有一个额外的端口,称为 nodePort,它指定节点上开放的端口值 。如果你不指定这个端口,系统将选择一个随机端口。大多数时候我们应该让 Kubernetes 来选择端口。

k8s+docker k8s+docker+网关getway_K8s

缺点:

  1. 每个端口只能是一种服务
  2. 端口范围只能是 30000-32767
  3. 如果节点/VM 的 IP 地址发生变化,你需要能处理这种情况。

由于本文中部署的环境中,仅需要api-gateway对外暴露服务,其余都是在集群内部访问,且机器并不会变化,同时采用了其他高可用手段保证服务的高可用,因此采用了NodePort方式进行部署,推荐还是使用ingress进行配置。

三. K8s服务运行

在部署了K8s集群的机器上,进行部署操作。环境需具备docker和harbor仓库,其次每个节点对harbor的都可以访问到,否则会导致镜像拉取失败。

1.将jar包上传并打包成镜像并上传至仓库。

docker build -t="harbor.box.com/box/api-gateway" .
 
docker push harbor.box.com/box/api-gateway

2.启动k8s配置文件

kubectl apply -f api-gateway-nodePort.yaml
 
kubectl apply -f api-gateway.yaml

3. 查看pod是否启动:

kubectl get po -n box -o wide

 如下图所示,可以看到api-gateway都已经正常启动 -n 后面的参数可以改成box也就是上文中配置的namespace,这边的截图为我本地项目中跑的namespace名字

k8s+docker k8s+docker+网关getway_K8s_02

4. 查看service 可以看到分配的ip及映射的端口

kubectl get svc -n box -o wide

k8s+docker k8s+docker+网关getway_k8s+docker_03

四. 实现效果

打开eureka界面可以看到api已经注册上去 同时使用curl接口访问本地ip+映射的端口+服务接口,可以看到成功返回。

k8s+docker k8s+docker+网关getway_SpringBoot_04

五. 总结

到这里 我们就搭建好一个基于k8s集群+docker的SpringCloud组件Zuul集群,下一节我将讲述我是如何搭建其他普通微服务的,比较简单 因为都是集群内部的访问。如果有疑问,欢迎留言区留言。

本文参考:

http://dockone.io/article/4884