k8s部署springcloud_k8s部署springcloud落地实战步骤

k8s部署springcloud_k8s部署springcloud落地实战步骤_第1张图片

前言

k8s部署springcloud实际落地操作 在我的这篇文章中,我介绍了工作中实际落地的方案,大家都很感兴趣,想要更详细地介绍,这里我在本地用minikube给大家做一个演示。

演示的最终效果如下图,把网关部分和ingress去掉了,这里只演示核心,写了一个提供者和一个消费者,然后把他们注册到外部到注册中心nacos中,然后浏览器访问消费者的时候,消费者用注册中心获取的服务名远程去访问提供者的数据。

同时还会演示nacos配置中心动态修改配置文件的效果。从而达到了,k8s只部署应用服务的目的,而公共组件,数据库,配置中心,中间件等放到k8s外面部署。

具体为什么这样搞可以看我的这篇k8s部署springcloud实际落地操作文章,我认为对于我们来说是最适合的方案了。

k8s部署springcloud_k8s部署springcloud落地实战步骤_第2张图片

准备工作

minikube:我这里的演示环境用的minikube。相当于你们的k8s的部署环境

为了方便大家开发和体验Kubernetes,提供了可以在本地部署的Minikube,minikube安装部署方便,功能和真实环境的Kubernetes功能是一样的。

docker:编译和上传应用程序镜像需要用它,相关于你自己的开发环境。

镜像仓库:镜像仓库用来上传打包好的镜像,然后在其他服务器上可以pull下来,我的镜像仓库中心直接用的docker hub官方的。你可以用阿里的或者私有docker中心。

我的演示电脑是mac

springcloud微服务k8s部署

代码说明

这里先看下provider以及consumer核心代码,如下:

provider的controller代码:

@RestController@Slf4j//实时更新配置中心的配置项@RefreshScopepublic class MainController {//注入配置文件中的配置项,从nacos配置中心实时拉取    @Value("${test}")    private String test;    @GetMapping("helloK8s")    public String helloK8s() {        String ip = getIp();        System.out.println(test);        return "provider--helloK8s test:"+test+" ip: "+ip;    }    //获取本机ip地址    private String getIp(){        InetAddress ia=null;        try {            ia=InetAddress.getLocalHost();            String localname=ia.getHostName();            String localip=ia.getHostAddress();            System.out.println("本机名称是:"+ localname);            System.out.println("本机的ip是 :"+localip);            return localip;        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return "";    }}

consumer的controller代码:

@RestController@Slf4j//实时更新配置中心的配置项@RefreshScopepublic class ConsumerController {    @Autowired    private RestTemplate restTemplate;  //注入配置文件中的配置项,从nacos配置中心实时拉取    @Value("${test}")    private String test;    @GetMapping("/echo/appName")    public String echoProviderName(){        //通过nacos注册中心中的服务名first-provider去访问提供者api        String url = "http://first-provider/helloK8s";        String res = restTemplate.getForObject(url,String.class);        log.info("res is {}",res);        return "consumer---config: " +test+" content:" + res;    }}

然后就是pom docker打包上传的核心配置部分:

1.8wanglining1987test-k8sdocker-repositorydocker.iohttp://192.168.1.105:3375-Xms128m -Xmx128m/tmpHoxton.SR82.2.1.RELEASEcom.spotify                docker-maven-plugin                1.2.0${docker.serverId}${docker.registry}${docker.host}${project.docker.name}/${image.name}:${project.version}java${project.version}${docker.volumes}${docker.java.opts}["sh","-c","java $JAVA_OPTS -jar /${project.build.finalName}.jar"]/${project.build.directory}${project.build.finalName}.jarremove-imagepackageremoveImage                                ${project.docker.name}/${image.name}                            ${project.version}latestremove-tag-imagepackageremoveImage                                ${docker.registry}/${project.docker.name}/${image.name}                            ${project.version}latestbuild-imagepackagebuild${project.docker.name}/${image.name}:${project.version}tag-imagepackagetag${project.docker.name}/${image.name}:${project.version}                                ${docker.registry}/${project.docker.name}/${image.name}:${project.version}                            tag-image-latestdeploytag${project.docker.name}/${image.name}:${project.version}                                ${docker.registry}/${project.docker.name}/${image.name}:latest                            push-imagedeploypush                                ${docker.registry}/${project.docker.name}/${image.name}:${project.version}                            

这里主要是用maven中docker的插件进行镜像的打包,并且上传到镜像中心。

里面的配置我不做过多讲解了,可以自行百度。我这里主要说明一点,里面的配置项

http://192.168.1.105:3375

这里面的地址配置的是访问本地docker deamon的地址,docker的原理其实就是当你执行docker命令的时候,它会把命令发送给docker deamon程序来执行具体的动作。

Daemon是Docker的守护进程,Docker Client通过命令行与Docker Damon通信,完成Docker相关操作

在mac上默认是访问不到docker deamon的,需要一个代理服务转发下,如下:

Docker代理服务(shipyard/docker-proxy)

这是一个非常轻量级的容器,它只是将请求从TCP转发到Docker监听的Unix套接字。

运行如下命令来开启代理转发:

docker run -p 3375:2375 -v /var/run/docker.sock:/var/run/docker.sock -d -e PORT=2375 shipyard/docker-proxy

然后你的代理地址就是本机ip+3375,配置到pom文件中即可。

开始操作

第一步:编译应用程序打包成jar,并编译成docker镜像,然后push到docker仓库中心。

k8s部署springcloud_k8s部署springcloud落地实战步骤_第3张图片

第一步点击package打包,maven插件会自动把代码打成jar包,然后把之前的docker同名镜像删除再重新build新的docker镜像。执行结果如下:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第4张图片

这里的wanglining1987/test-k8s:provider build出来的镜像

第二步点击push,会把上一步打包好的应用镜像上传到仓库中。执行结果如下:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第5张图片

然后同理对consumer工程也执行这个步骤,最终jar包镜像都上传到了docker镜像中心,如下图:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第6张图片

这两个镜像就是上面编译出来的。分别是消费者和生产者镜像。

第二步,启动minikube,并且启动dashboard

启动minikube,并指定阿里镜像中心

minikube start --registry-mirror=https://j3wvoj70.mirror.aliyuncs.com
k8s部署springcloud_k8s部署springcloud落地实战步骤_第7张图片

启动dashboard,执行命令:minikube dashboard

执行结果如下:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第8张图片

执行成功后,会自动跳转到dashboard界面,如下图:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第9张图片

通过dashboard可以方便地管理k8s,比如操作Service,Deployment, pod等,每一步操作都会提示对应那个命令,很好用,提供了很大的方便。

第三步,编写k8s的Deplyment对应的yaml文件,来部署应用到Pod中

yaml文件如下:

apiVersion: apps/v1kind: Deploymentmetadata:  name: first-deployment-2  labels:    app: first-app-labelspec:  # 启动三个实例  replicas: 3  selector:    matchLabels:      app: first-app  template:    metadata:      labels:        app: first-app    spec:      containers:      - name: first-app        # 指定要运行的镜像,启动后,会从镜像中心下载该镜像并运行        image: wanglining1987/test-k8s:provider        ports:        - containerPort: 8080---apiVersion: apps/v1kind: Deploymentmetadata:  name: consumer  labels:    app: consumer-labelspec:  replicas: 1  selector:    matchLabels:      app: consumer-app  template:    metadata:      labels:        app: consumer-app    spec:      containers:      - name: consumer-app        image: wanglining1987/test-k8s:consumer-2        ports:        - containerPort: 8082

创建完成文件名:first-deployment.yaml

启动nacos

运行应用镜像之前,记住先把nacos注册中心启动一下,不然就启动失败了,按照最开始的架构,注册中心是放到k8s外面运行,直接在本机电脑上运行启动nacos即可,不放到k8s中。

运行起来后,可以通过 http://localhost:8848/nacos/去访问nacos管理页面

运行镜像

然后执行如下命令,来把provider和consumer对应的镜像运行起来。

kubectl create -f first-deployment.yaml

运行起来后,在dashboard中看下效果,如下:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第10张图片

上面两个是启动起来的Deployment。点进去可以查看Deployment的详情,具体什么是Deployment就不展开说了,k8s里的概念,有兴趣去百度即可。这里也可以用命令去查看运行的Deployment,没有dashboard来的方便直接。

然后可以去查看Deployment部署的Pod,并且去查看Pod内应用运行的日志:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第11张图片

这里consumer运行了一个实例,provider运行了三个,这个实例数量,也是在上面的first-deployment.yaml文件中指定了。查看pod日志:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第12张图片

还是很方便的。可以看到应用起来了。

检查下nacos注册中心中是否已经注册上应用了,打开注册中心管理界面地址如下图:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第13张图片

可以看到有两个服务注册进去了first-provider和first-consumer,其中first-provider是三个实例,first-consumer是一个,跟前面配置的一致,在进去看下服务详情如下:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第14张图片

观察其IP地址,是k8s分配的内部地址,成功注册到外部的nacos上了,这里需要注意,k8s内的服务是可以访问k8s外部的ip地址的,只是外部的机器没有办法访问k8s内部的服务ip。

剩下最后一步了就是通过浏览器访问下消费者,看看能不能成功调用提供者接口,并返回结果到页面。

部署service暴露出来

接下来要通过浏览器访问消费者,怎么访问呢?直接通过ip肯定不行,都是k8s内部的ip地址。

k8s解决了这个问题,都很多方法,可以是ingress,或者直接通过Service直接暴露出来。

这里简单把k8s官网的对service和pod定义拉下来,供参考:

Kubernetes Pods是有生命周期的。他们可以被创建,而且销毁不会再启动。 如果您使用Deployment来运行您的应用程序,则它可以动态创建和销毁 Pod。

一个Kubernetes的Service是一种抽象,它定义了一组Pods的逻辑集合和一个用于访问它们的策略 - 有的时候被称之为微服务。一个Service的目标Pod集合通常是由Label Selector 来决定的(下面有讲一个没有选择器的Service 有什么用处)。

举个例子,想象一个处理图片的后端运行了三个副本。这些副本都是可以替代的 - 前端不关心它们使用的是哪一个后端。尽管实际组成后端集合的Pod可能会变化,前端的客户端却不需要知道这个变化,也不需要自己有一个列表来记录这些后端服务。Service抽象能让你达到这种解耦。

对于熟悉springcloud微服务的,你就可以把k8s里的这个service和springcloud中的微服务概念去对应,道理是差不多的。k8s可以把service通过几种方式暴露出来,供外部访问,有四种方式如下:

ClusterIP:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是默认的 ServiceType。

NodePort:通过每个节点上的 IP +静态端口(NodePort)暴露服务。 NodePort 服务会路由到自动创建的 ClusterIP 服务。 通过请求 :,你可以从集群的外部访问一个 NodePort 服务。

LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。

ExternalName:通过返回 CNAME 和对应值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。 无需创建任何类型的代理。

这里选择最方便的NodePort方式,对应的Service yaml文件如下:

apiVersion: v1kind: Servicemetadata:  name: consumer-service  labels:    app: consumer-app    role: masterspec:  type: NodePort#type: LoadBalancer  ports:  - port: 8083    targetPort: 8082  selector:    # 这里的consumer-app会去匹配first-deployment.yaml的template部分定义的lable名    # 从而和具体的Pod关联起来了    app: consumer-app

命名:first-service.yaml,然后通过如下命令启动Service

kubectl create -f first-service.yaml

启动成功后,查看dashboard,如下:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第15张图片

可以看到consumer-service启动成功,跟yaml中定义的一致。

然后运行命令:

$minikube service consumer-service --urlhttp://192.168.64.2:32376

会把访问服务的ip地址和端口打印出来,通过http://192.168.64.2:32376就可以访问到consumer-service后面实际对应的应用程序了。

在最开始consumer项目对应的controller中定义了api /echo/appName,把路径拼起来,去浏览器访问:http://192.168.64.2:32376/echo/appName

k8s部署springcloud_k8s部署springcloud落地实战步骤_第16张图片

对照前面provider和consumer代码看下,k8s内部的consumer通过外部的nacos注册中的服务名成功的调用到了provider的接口,并打印输出接口。

代码中还把配置文件中的test变量打印了出来,这个主要是为了测试nacos配置中心的变化能不能更新到k8s内部的服务中的。如下部分

@Value("${test}")private String test;

nacos配置中心中的配置:

k8s部署springcloud_k8s部署springcloud落地实战步骤_第17张图片

文件内容

k8s部署springcloud_k8s部署springcloud落地实战步骤_第18张图片

consumer配置文件

k8s部署springcloud_k8s部署springcloud落地实战步骤_第19张图片

provider配置文件

打印结果中,标红部分是配置中心的配置,也是成功了。

consumer---config: ffff content:provider--helloK8s test:eeeaafff ip: 172.17.0.7

总结

我们的方案使用springcloud全部组件和特性,对开发者开发调试更容易,开发方式也更熟悉。部署的时候只需要部署应用部分,发挥k8s部署扩容方便的优势。结合了两者共同的优势

--后续我会持续输出高质量的文章,我工作中更多实战的东西,以及源码部分的讲解,希望大家多多关注 关注+私信给代码,希望多多支持

你可能感兴趣的:(k8s部署springcloud_k8s部署springcloud落地实战步骤)