microk8s处理微服务之间的调用

microk8s处理微服务之间的调用,第1张

通过在 microk8s上部署授权服务 ,我们基本上走通了微服务通过配置中心服务(config-central)加载配置并启自己的流程。

在microk8s上部署微服务,现在仅剩下一个需要处理的问题,微服务之间通的互相调用。这里我们用我们微服务集群里的base-service 和 diagnose-service来尝试整个流程。

base服务主要提供平台的基础数据,像配置授权服务一样,我们需要写configmap、deployment、service三个yaml配置文件。

整体上与授权服务没多大区别,但又两个地方这次需要特别注意:

1 标黄的context-path的配置, springboot20 需要使用:

   serverservletcontext-path= xxxx  

   如果仍沿用10的配置, 启动时contexnt将为‘’。

2  必须正确配置virtualHostName, 这个参数配置,会导致ribbion找不到base服务, 我就因为填写错误,被整了一两天,后来在介绍Ribbon原理的一篇文章里,发现:

 DiscoveryEnabledNIWSServerList

 从eureka服务获取服务列表,服务集群必须由VipAddress标识

Base服务的Deployment文件,没有什么特别的,和Authorize基本一样:

Service文件,我们仍旧定义为Nodeport方便测试:

部署完成后,我们使用port-forward 命令做个端口映射。

microk8s kubectl port-forward pod/baseservice-79946b574d-kqf8x 8000:9043

通过浏览器访问localhost:8000端口,就可以访问服务了。

部署完base服务,我们来看看怎么让diagnose服务调用base服务。

1 需要在diagnose服务的入口,声明@enableEurekaClient 和 @enableFeignClients

2 建立feign的接口文件

Name 是我们需要需要调用的微服务名,这个名字一定要注意:

1 都使用小写, 因为k8s对服务名有要求。

2  这个一定对应的是相应服务的virtualHostName, 否者找不着。

当然需要加载相应的cloud包,最好通过springboot提供的工具生成。

现在需要来写配置文件configmap,这个配置文件与base服务差不多,唯一区别就是标黄的

部分, 确保自动获取打开,另外使用主动加在服务。

通过上面的配置,我们在启动服务就可以看到,baseservice将被从注册中心获取并房子啊serverlist里。

Deployment和service的书写与base服务没有任何区别,这里就省略了。完成部署后,我们通过postman做测试,可以正确返回结果。

Notes: diagnose服务的conext因为没有正确配置,所以IP和端口后直接接了restful请求路径了,这个需要注意。

检查base服务,可以看到,确实调用了接口。

至此,服务间的调用初步走通了,现在我们还需要做一件事,就是将base服务在注册中心注册的IP改为k8s中的服务名称,只需要在configmap中增加如下属性:eurekainstanceip-address= baseservice

然后,更新配置文件和deployment文件,重启服务。查看base服务注册中的记录,可以看到hostname和ipaddr已经正确显示服务名称。

重新通过postman调用diagnose服务发现,报错,调用base服务没响应。只好重启diagonose服务,查看日志:

启动后,服务列表已经正确填充了base服务:baseservice:9043

现在重新测试接口,正常返回结果。看来需要正确的设置,feign得自动刷新参数,否则发生服务名变化后,本地缓存不能及时清理,会导致无法正常工作。

走到这里,基本上在microk8s上部署服务,并实现服务间的调用就完成了。在整个验证过程中,深深地体会了,spring cloud的不好用:虽然看起来简单,但 一不小心就可能配置错误, 而且很多功能其实k8s已经提供,完全可以掠过。 k8s中的服务,已经提供了loadbalance的作用, feign的使用其实已经没有意义。

所以,虽然将旧的虚拟机环境的微服务迁移到k8s上,基本是走通了。但是我们还需要做的更进一步,剔除springcloud的功能。

这样,让开发工程师,从繁杂的配置中解脱出来,完全可以增减团队效率。

"KManager"是一款用于管理和监控Kubernetes集群的开源工具。以下是一些常见的KManager命令:

kubectl km deploy: 部署KManager到Kubernetes集群。

kubectl km port-forward: 将KManager本地端口映射到集群中的端口。

kubectl km logs: 查看KManager的日志。

kubectl km status: 检查KManager的状态。

kubectl km upgrade: 升级KManager到新版本。

kubectl km uninstall: 卸载KManager。

除了上述命令外,KManager还支持其他一些命令和选项,具体可以参考KManager的文档和帮助文档。

通过 kubectl 工具创建新的Pod,kubectl 会将pod对象信息(json格式)提交给apiserver。

而apiserver连接etcd则没有进行抓包,之前抓了几次貌似都是tcp包看不出来啥内容,后面有空再研究研究吧。

这几个tcp包是apiserver推给scheduler的事件,主要是告诉scheduler:有新的pod创建了。

scheduler向apiserver提交bingding *** 作,将pod binding到timo节点上,并且是调度成功的,后面的事情那就是kubelet去执行的了。

查看一下集群的节点。

有的朋友很疑惑,为啥NotReady也能调度成功,这是因为我将nodekubernetesio/not-ready污点给干掉了,生产环境肯定不能这样做的。

另外这个并不是完整的集群,controller-manager和kube-proxy以及网络插件都没有,主要目的是想研究一下pod的创建过程的交互细节是怎么样的,集群之间也没有使用证书通信,低版本的kubernetes可以使用8080非加密端口,这样抓包就可以看到内容了。

从上面抓包的内容看出来几个问题。

1、kubectl创建pod是将json格式的对象信息提交给apiserver的。

2、apiserver将pod信息存入etcd后就会生成对应的事件,然后将事件通知给scheduler(从抓包也看出来是apiserver主动通知的,apiserver和scheduler之间使用watch机制)。

3、scheduler监听到事件后,向apiserver提交binding *** 作,将pod binding到指定的node上。

如果朋友们有兴趣,可以安装低版本的Kubernetes来抓包分析看看。

测试yaml:

测试yaml:

端口转发利用的是Socat的功能,这是个神奇的工具,你值得拥有: Socat

之前都是直接将pod上的应用暴露出去,这种方式在实际的生产环境中基本不可取,标准的搞法是基于Service。

Service有三种类型:ClusterIP、NodePort、LoadBalancer。

首先,先了解下Service中端口的概念:

port/nodeport/targetport

port ——Service暴露在Cluster IP上的端口,也就是虚拟IP要绑定的端口。port是提供给集群内部客户端访问Service的入口。

nodeport ——K8s集群暴露给集群外部客户访问Service的入口。

targetport ——是Pod内容器的端口。从port和nodeport上进入的数据最终会经过Kube-proxy流入到后端pod里容器的端口,如果targetport没有显示声明,那么会默认转发到Service接受请求的端口(和port端口保持一致)。

通过Service暴露内部服务的方式有四种:ClusterIP、NodePort、LoadBalancer、Ingress

ClusterIP其实是Service的缺省类型,就是默认类型,例如之前部署的dashboard插件其实就使用是这种类型,可以通过如下指令来分辨:

所以,这种类型的Service本身是不会对集群外暴露服务的,但是却单单可以通过K8s Proxy API来访问。Proxy API是一种特殊的API,Kube-APIServer只代理这类API的>

  一个pod是一组紧密相关的容器,是一起运行在同一个工作节点上,以及同一个Linux命名空间中。每个pod就像是一个独立的逻辑机器,拥有自己的IP、主机名、进程等,运行一个独立的应用程序。

  pod是逻辑主机,一个pod的所有容器都运行在同一个逻辑机器上,其他pod中的容器,即使运行在同一个工作节点上,也会出现在不同的节点上。即一个pod包含多个容器时,这些容器总是运行在同一个工作节点上,一个pod绝不可能跨多个工作节点。

举例

  每个pod自有IP,包含1个或多个容器,每个容器运行一个应用进程

查看pod命令

$ kubectl get pods

READY:0/1 表示pod的单个容器显示为未就绪的状态;相反,1/1表示已就绪;

STATUS: Pending 表示pod处于挂起状态;相反,Running表示pod处于运行状态;

  运行应用两大步骤:1)构建镜像并推送至镜像仓库中;2)K8s创建pod进行调度;

流程:

1)本地构建镜像;

2)推送镜像至镜像仓库;

3)kubectl创建并部署应用;

4)kubectl发出REST请求至REST API服务器;

5)创建pod并调度到工作节点;

6)kubelet收到通知;

7)kubelet告知Docker运行镜像;

8)Docker从镜像仓库中拉取镜像;

9)Docker创建并运行容器;

  如果单个容器中运行多个不相关的进程,保持所有进程运行、管理它们的日志将很难,需要包含一种在进程崩溃时能够自动重启的机制,同事,这些进程都将记录到相同的标准输出中,很难确定每个进程分别记录的内容。

  不能讲多个进程聚集在一个单独的容器中,需要pod将容器绑定在一起,并将它们作为一个单元进行管理,在包含容器的pod下,可以同时运行一些密切现骨干的进程,并为其提供相同的环境,此时这些进程就好像全部运行于单独的容器中,同时保持一定的隔离性。

  k8s可以通过配置docker让一个pod内的所有容器共享相同的Linux命名空间(network、UTS命名空间、IPC命名空间),从而使容器都共享相同的主机名、网络名和IPC通信。

  同一个pod中的容器运行的多个进程不能绑定到相同的端口号,否则会端口冲突(每个pod都有独立的端口空间,不同pod中的容器不会有端口冲突现象。)

  同一个pod中的容器具有相同的loopback网络接口,所以容器可以通过localhost与同一个pod中的其他容器进行通信。

注意

  容器不应该包含多个进程,pod也不应该包含多个并不需要运行在同一主机上的容器。如下图:

1)yaml中使用的kubernetes API版本和yaml描述的资源类型;

2)metadata:包括名称、命名空间、标签和关于该容器的其他信息;

3)spec:包含pod内容的实际说明,如pod的容器、卷和其他数据;

4)status:包含运行中的pod的当前信息,如pod所处的条件、每个容器的描述和状态,以及内部IP和其他基本信息。

描述信息:

1)该文件遵循Kubernetes API的v1版本;

2)描述的资源类型是pod;

3)资源名称为kubia-manual;

4)该pod由基于luksa/kubia镜像的单个容器组成;

5)容器名称为kubia;

6)容器监听的端口是8080;

按名称删除

$ kubectl delete po pod_name

其中, pod_name 为pod名称;删除命令指示uk8s终止该pod中所有容器,k8s向进程发送一个SIGTERM信号并等待一定的秒数(默认30s),使得其正常关闭,若未及时关闭,则通过SIGKILL终止进程。

删除多个pod

$ kubectl delete po pod_name1 pod_name2

多个pod删除使用空格隔开;

按照标签删除

$ kubectl depete po -l tag_key=tag_value

其中, tag_key 为标签健, tag_value 为标签值;

按照整个命名空间删除

$ kubectl delete ns namespace_name

其中, namespace_name 为命名空间名称

kubeadm 是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,通过kubeadm的方式安装集群比二进制的方式安装高效不少。建议初次使用k8s使用此方式安装,二进制的方式会很快令人失去信心。

在开始之前,部署Kubernetes集群机器需要满足以下几个条件:

dnsmasq安装可参考我的另一篇 文章

ha1节点配置

ha2节点配置

在两台ha节点都执行

启动后查看ha的网卡信息(有一台可看到vip)

两台ha节点的配置均相同,配置中声明了后端代理的两个master节点服务器,指定了haproxy运行的端口为16443等,因此16443端口为集群的入口

两台ha都启动

检查端口

Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。kubelet控制容器,kubeadm控制加入平面。

镜像加速

由于版本更新频繁,这里指定版本号部署:

在master1 *** 作

按照提示配置环境变量,使用kubectl工具:

按照提示保存以下内容,一会要使用:

查看集群状态

从官方地址获取到flannel的yaml,在master1上执行

安装flannel网络

检查

从master1复制密钥及相关文件到master2

master3 *** 作同上

执行在master1上init后输出的join命令,需要带上参数 --control-plane 表示把master控制节点加入集群

检查状态

在node1、2、3上执行

向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:

检查状态

在Kubernetes集群中创建一个pod,验证是否正常运行:

访问地址: >

首先先说说比较常规的nacos的服务注册与发现。

用spring cloud为例,ali集成了spring-cloud和nacos,因此加入以下依赖

然后我们配置nacos server的地址,并通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能,在 applicationproperties 中配置 Nacos server 的地址,启动服务之后,服务会将自己的元数据注册到nacos上,最主要的是服务名,ip,端口,namespace等。服务注册成功后,服务将与注册中心维持心跳,心跳机制可以保证当服务中的某个实例不健康之后,服务中心将该实例剔除,以保证服务正常提供服务。

当服务注册上去之后,消费者就可以调用服务了,那么消费者是怎么发现服务的呢,消费者向注册中心订阅某个服务,并提交一个监听器,当服务提供方实例发生变化,比如ip变了,消费者会收到通知,更新本地的服务列表,nacos client获取到服务列表之后,通过负载均衡,spring一般都是结合ribbon,获取一个可用的实例,得到它的ip和端口号,以及服务路由,然后进行调用。

由于客户端将获取到的服务实例保存在一个 map 中,而该 map 中的内容是由调度任务定时去更新的,存在一定的延时。

一般来说,在k8s中一个服务有多个实例,是通过pod去部署的,多个实例则有多个pod,每一个pod都会有自己的容器组ip,在集群内,直接通过这个容器ip和端口是可以访问服务的,但是每次服务重启,也就是pod销毁重建的时候,ip也会改变。k8s并没有一个注册中心让我们注册实例的ip和端口到服务下面,并且其他服务通过这个注册中心去发现服务。在k8s里是通过service去实现的。

这是一个service定义的例子, 这个 Service 将被指派一个 IP 地址(通常称为 “Cluster IP”),上述的selector代表这个service代理的pod选择器,也就是说具有这个app标签的选择器的一组pod,可以通过service这个统一的访问入口去做服务发现。

比如说我们现在有一组pod叫base-opc-biz

查看它的service

信息包括 :name,namespace,selector,labels等基础信息

type 是ClusterIP,IP这个值 即是在集群内部,其他所有的pod都可以通过这个虚拟的ip来访问service,service就会将这个请求负载均衡到后端的所有pod上去。

Port 是访问service的端口

TargetPort 是代理的pod的端口

Endpoints 是当前service代理的所有pod的ip地址,当某个pod被销毁重建的时候,这里的ip地址也会随之变化

集群内其他pod访问我们创建的service有三种方式:

1、 通过clusterIp+port直接去访问

2、 同一个namespace直接访问服务名,不同的 namespace 里面,我们可以通过 service 名字加“”kube-dns可以解决Service的发现问题,k8s将Service的名称当做域名注册到kube-dns中,通过Service的名称就可以访问其提供的服务。

Kubernetes 集群中部署了一套 DNS 服务,通过 kube-dns 的服务名暴露 DNS 服务。您可执行以下命令查看 kube-dns 的服务详情。

kubectl get svc kube-dns -n kube-system

服务后端是两个名为 coredns(下文会介绍 CoreDNS 解析原理) 的 Pod。您可执行以下命令查看 coredns 的 Pod 详情。

kubectl get deployment coredns -n kube-system

3、 通过环境变量访问,在同一个 namespace 里的 pod 启动时,kubelet 会为每个活跃的 Service 添加一组环境变量,会把 service 的一些 IP 地址、端口,以及一些简单的配置,通过环境变量的方式放到 K8s 的 pod 里面。因此我们可以通过环境变量去直接访问。

上面三种方式都是在k8s集群内部互相访问的情况,对我们应用的某些部分,可能希望将 Service 暴露在一个外部 IP 地址上。 Kubernetes 支持两种实现方式:NodePort 和 LoadBalancer。

我们看下我们原本的service 的yaml文件

把type改成NodePort 或者 LoadBalancer

然后重新创建service,再看看信息

发现有了EXTERNAL-IP,这个ip是一个公网的ip,因此我们就不只可以在集群上访问我们的服务了。

以上就是关于microk8s处理微服务之间的调用全部的内容,包括:microk8s处理微服务之间的调用、kmanager命令、Kubernetes | 抓包浅浅的分析一下Pod的创建过程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9437534.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存