K8S学习圣经6:资源控制+SpringCloud动态扩容原理和实操
博客园 2023-04-06 12:15:22

文章很长,持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版为您奉上珍贵的学习资源 :


(资料图片仅供参考)

免费赠送 :《尼恩Java面试宝典》持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备免费赠送 :《尼恩技术圣经+高并发系列PDF》,帮你 实现技术自由,完成职业升级, 薪酬猛涨!加尼恩免费领免费赠送 经典图书:《Java高并发核心编程(卷1)加强版》面试必备 + 大厂必备 +涨薪必备 加尼恩免费领免费赠送 经典图书:《Java高并发核心编程(卷2)加强版》面试必备 + 大厂必备 +涨薪必备 加尼恩免费领免费赠送 经典图书:《Java高并发核心编程(卷3)加强版》面试必备 + 大厂必备 +涨薪必备 加尼恩免费领

免费赠送 资源宝库: Java 必备 百度网盘资源大合集 价值>10000元 加尼恩领取

Kubernets学习圣经: 底层原理和实操

说在前面:

现在拿到offer超级难,甚至连面试电话,一个都搞不到。

尼恩的技术社群中(50+),很多小伙伴凭借 “左手云原生+右手大数据”的绝活,拿到了offer,并且是非常优质的offer,据说年终奖都足足18个月。

而云原生的核心组件是 K8S,但是 K8S 又很难。从Java高薪岗位和就业岗位来看,K8S 现在对于 高级工程师, 架构师,越来越重要,下面是一个高薪Java岗位的K8S技能要求:

市面上很多的pdf和视频,都是从技术角度来说的,讲的晦涩难懂。

在这里,尼恩从架构师视角出发,基于自己的尼恩Java 架构师知识体系和知识宇宙,对K8S的核心原理做一个宏观的介绍, 一共十二部分, 组成一本《K8S学习圣经》

《K8S学习圣经》 带大家穿透K8S,实现K8S自由,让大家不迷路。

《K8S学习圣经》的组成

米饭要一口一口的吃,不能急。

结合《K8S学习圣经》,尼恩从架构师视角出发,左手云原生+右手大数据 +SpringCloud Alibaba 微服务 核心原理做一个宏观的介绍。由于内容确实太多, 所以写多个pdf 电子书:

(1) 《 Docker 学习圣经 》PDF (V1已经完成)

(2) 《 SpringCloud Alibaba 微服务 学习圣经 》PDF (V1已经完成)

(3) 《 K8S 学习圣经 》PDF (coding…)

(4) 《 flink + hbase 学习圣经 》PDF (planning …)

以上学习圣经,并且后续会持续升级,从V1版本一直迭代发布。 就像咱们的《 尼恩 Java 面试宝典 》一样, 已经迭代到V60啦。

40岁老架构师尼恩的掏心窝: 通过一系列的学习圣经,带大家穿透“左手云原生+右手大数据 +SpringCloud Alibaba 微服务“ ,实现技术 自由 ,走向颠覆人生,让大家不迷路。

本PDF 《K8S 学习圣经》完整版PDF的 V1版本,后面会持续迭代和升级。供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

以上学习圣经的 基础知识是 尼恩的 《高并发三部曲》,建议在看 学习圣经之前,一定把尼恩的《 Java高并发三部曲 》过一遍,切记,切记。

本部分目录(第六部分)

目录

第六部分:Kubernetes 的资源控制

动态的扩容缩容的重要性

在微服务应用中,在高并发场景下, 需要对 springboot、SpringCloud 、nginx 应用进行动态的扩容缩容

所以动态的扩容缩容 ,是高并发应用的标配。

但是,社群中很多的小伙伴,不懂动态的扩容缩容 底层原理。

没有做过 动态的扩容缩容实操。因此,很容易错过很多 高质量的 offer。

目前业界主流的方案,是基于K8S实现 动态的扩容缩容。

这一个部分, 尼恩带着大家,从Deployment 资源对象 入手,一步一步,带大家最终,完成基于K8S实现 动态的扩容缩容实操。

1:Deployment 资源对象

为了更好地解决Pod编排的问题,k8s在V1.2版本开始,引入了deployment资源对象,

注意:

deployment资源并不直接管理pod,而是通过管理replicaset来间接管理pod,

简单的说:deployment管理replicaset,而 replicaset管理pod。

deployment的主要功能有下面几个:

所以: 我们部署一个应用一般不直接写Pod,而是部署一个Deployment

Deployment 使用场景:Deployment 主要针对无状态服务,有状态服务使用 StatefulSet. 那么,什么是无状态服务, 什么是有状态服务, 这个咱们稍微晚点介绍。

Deploy编写规约

https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/#writing-a-deployment-spec

Deployment的创建

编写一个Deployment的yaml赋予Pod自愈和故障转移能力。 基本格式如下:

下面是一个例子 deployment-demo.yml

apiVersion: apps/v1  #版本号kind: Deployment  #类型metadata:    #元数据  name:   demo-deployment #rs名称  namespace:  default  #所属命名空间  labels:   #标签    controller: deployspec:   #详情描述  replicas: 3 #副本数量  revisionHistoryLimit: 5 #保留历史版本,默认是10  paused: false #暂停部署,默认是false  progressDeadlineSeconds: 600 #部署超时时间(s),默认是600  strategy: #策略    type: RollingUpdate  #滚动更新策略    rollingUpdate:  #滚动更新      maxSurge: 1 #最大额外可以存在的副本数,可以为百分比,也可以为整数      maxUnavailable: 1 #最大不可用状态的pod的最大值,可以为百分比,也可以为整数  selector:  #选择器,通过它指定该控制器管理哪些pod    matchLabels:   #Labels匹配规则      app: nginx-gateway    matchExpressions:   #Expression匹配规则      - {key: app, operator: In, values: [nginx-gateway]}  template:  #模板,当副本数量不足时,会根据下面的模板创建pod副本    metadata:      labels:        app: nginx-gateway    spec:      containers:        - name: nginx-gateway          image: harbor.daemon.io/demo/nginx-gateway:1.0-SNAPSHOT          ports:            - containerPort: 80

通过 下面的命令进行操作:

# 创建  deployment 资源对象, 进一步创建 rs对象, pod 对象kubectl apply  -f deployment-demo.yml# 查看 deployment 资源对象kubectl get deployments# 查看 ReplicaSet 资源对象kubectl get ReplicaSet

使用kubectl get deployments查看 deployment 资源对象

在检查集群中的 Deployment 时,所显示的字段有:

使用 kubectl get ReplicaSet查看 ReplicaSet 资源对象

ReplicaSet 输出中包含以下字段:

注意:

ReplicaSet 的名称始终被格式化为 [Deployment名称]-[随机字符串]

其中的随机字符串是使用 pod-template-hash 作为种子随机生成的。

Deployment 资源、replicaset资源、Pod资源 三者之间的关系

一个Deploy产生三个

Deployment控制RS,RS控制Pod的副本数

ReplicaSet: 只提供了副本数量的控制功能

Deployment: 每部署一个新版本就会创建一个新的副本集,利用他记录状态

Deployment 基本操作

副本扩容

原本定义3个副本,现在扩容到10个副本

kubectl scale deployment demo-deployment --replicas 10

副本缩容

原本定义3个副本,现在缩容到2个副本

kubectl scale deployment demo-deployment --replicas 2

Deployment 更新机制

仅当 Deployment Pod 模板(即 .spec.template )发生改变时,例如模板的标签或容器镜像被更新, 就会触发 Deployment 滚动更新。 其他更新(如对 Deployment 执行扩缩容的操作)不会触发滚动更新动作。

滚动更新 原理:

创建新的rs,准备就绪后,替换旧的rs(此时不会删除,因为revisionHistoryLimit 指定了保留几个版本)

准备:升级镜像

升级一下 nginx 的镜像,并且导入

可以使用命令,将 镜像从1.0更新到2.0

kubectl set image deployment/demo-deployment nginx-gateway=harbor.daemon.io/demo/nginx-gateway:2.0

在线修改yaml

也可以使用 使用edit命令 在线修改yaml

kubectl edit deployment/demo-deploymentdeployment "nginx-deployment" edited

滚动机制相关的命令

查看可用的回滚版本

kubectl rollout history deployment demo-deployment

查看滚动状态

kubectl rollout status  deployments demo-deployment

监控更新过程

kubectl get deployments demo-deployment  --watch

回滚到上一个步骤

kubectl rollout undo deployment/demo-deployment

暂停和恢复

在暂停状态下的更新操作,多次更改,只会触发一次 rolling 记录

kubectl rollout pause deployment/nginx-deployment

回滚策略

记录保留

.spec.revisionHistoryLimit默认设置保留数量为 2。

在 Deployment 中设置来指定保留多少旧的 ReplicaSet。余下的将在后台被当作垃圾收集。

滚动更新数量

.spec.strategy指定新的Pod替换旧的Pod的策略

使用Deployment 进行灰度发布

使用Deployment 进行金丝雀发布(灰度发布)、蓝绿发布、滚动发布 的原理与实操,

请参见《K8S学习圣经》的第九部分。

2:副本资源 RC、副本集RS 资源对象

RC: ReplicasController 副本控制器

RS:ReplicasSet:副本集;

Deployment【滚动更新特性】默认的 控制器的是ReplicasSet 副本集

实际上 RS 和 RC 的功能基本一致,目前唯一的一个区别就是 :

RC 只支持基于等式的 selector(env=dev 或 environment!=qa),但 RS 还支持基于表达式的 selector(version in (v1.0, v2.0)), RS对复杂的运维管理就非常方便了。

虽然ReplicasSet强大,但是我们也不直接写RS;都是直接写Deployment的,Deployment会自动产生RS。Deployment每次的滚动更新都会产生新的RS。

接下来, 咱们还是从RC开始介绍吧。

RC(Replication Controller)

Replication Controller简称 RC,RC 是 Kubernetes 系统中的核心概念之一,简单来说,RC 可以保证在任意时间运行 Pod 的副本数量,能够保证 Pod 总是可用的。

如果实际 Pod 数量比指定的多,那就干掉多余的,

如果实际数量比指定的少就新启动一些 Pod,当 Pod 失败、被删除或者挂掉后,RC 都会去自动创建新的 Pod 来保证副本数量,所以生产场景中,哪怕只有一个pod,也应该使用 RC 来管理我们的 Pod。

就是由于RC的副本控制机制,哪怕运行 Pod 的节点挂了,RC 检测到 Pod 失败了,就会去合适的节点重新启动一个 Pod 就行,不需要我们手动去新建一个 Pod 了。

下面我们使用 RC 来管理一个 Nginx 的 Pod,YAML 文件如下:

上面的 YAML 文件相对于我们之前的 Pod 的格式:

这个 YAML 文件中的意思就是定义了一个 RC 资源对象,它的名字叫 nginx-gateway-rc,保证一直会有 3个 Pod 运行。

注意 spec.selector 和 spec.template.metadata.labels 这两个字段必须相同,否则会创建失败的,

当然我们也可以不写 spec.selector,这样就默认与 Pod 模板中的 metadata.labels 相同了。

所以为了避免不必要的错误的话,不写为好。

然后我们来创建上面的 RC 对象(保存为 nginx-rc-demo.yaml):

kubectl create -f demo-rc.yaml或者kubectl apply -f ndemo-rc.yaml

查看 RC:

kubectl get rc

查看详细的描述信息:

kubectl describe rc nginx-gateway-rc

接下来我们再通过 RC 来修改下 Pod 的副本数量为 4:

kubectl apply -f nginx-rc-demo.yaml

或者执行下面的命令编辑 RC 也可以

kubectl edit rc nginx-rc-demo

RS(Replication Set)

Replication Set简称 RS,随着 Kubernetes 的高速发展,官方已经推荐我们使用 RS 和 Deployment 来代替 RC 了,实际上 RS 和 RC 的功能基本一致,目前唯一的一个区别就是 RC 只支持基于等式的 selector(env=dev 或 environment!=qa),但 RS 还支持基于集合的 selector(version in (v1.0, v2.0)),这对复杂的运维管理就非常方便了。

kubectl 命令行工具中关于 RC 的大部分命令同样适用于我们的 RS 资源对象。

不过我们也很少会去单独使用 RS,它主要被 Deployment 这个更加高层的资源对象使用,除非用户需要自定义升级功能或根本不需要升级 Pod,在一般情况下,我们推荐使用 Deployment 而不直接使用 Replica Set。

ReplicatSet的三个部分

RS 资源对象的创建跟 RC 的创建方法大同小异。

ReplicaSet 需要 apiVersion、kind 和 metadata 字段。

对于 ReplicaSet 而言,其 kind 始终是 ReplicaSet。

然后,ReplicaSet 也需要 .spec 部分。.spec 部分分为replicas 副本数、selector 选择器(选择算符)、Pod模板三个部分:

(1)一个用来标明应该维护的副本个数的数值、

(2)一个用来识别可获得的 Pod 的集合的选择算符、

(3)一个用来指定应该创建新 Pod 以满足副本个数条件时要使用的 Pod 模板。

replicas

你可以通过设置 .spec.replicas 来指定要同时运行的 Pod 个数。 如果实际的pod数量与预期不符合,ReplicaSet 创建、删除 Pod 以与此值匹配。每个 ReplicaSet 都通过根据需要创建和删除 Pod 以使得副本个数达到期望值, 进而实现Pod副本管理价值。

如果你没有指定 .spec.replicas,那么默认值为 1。

当 ReplicaSet 需要创建新的 Pod 时,会使用所提供的 Pod 模板。

selector 选择器

.spec.selector 字段是一个标签选择算符,这些是用来标识要被获取的 Pod 的标签。

在签名的 frontend.yaml 示例中,选择算符为:

matchLabels:  tier: frontend

在 ReplicaSet 中,.spec.template.metadata.labels 的值必须与 spec.selector 值相匹配,否则该配置会被 API 拒绝。

Pod 模板

.spec.template 是一个 Pod 模板, 要求设置标签。

在 demo-rs.yaml 示例中,我们指定了标签 app: nginx-gateway。

对于模板的重启策略 字段,.spec.template.spec.restartPolicy,唯一允许的取值是 Always,这也是默认值.

RS扩容缩容

两种方式:

(1)直接修改 replicaset.yaml文件来扩容缩容

(2)通过 kubectl命令来扩容缩容

方式一:直接修改 replicaset.yaml文件来更新:

通过更新 .spec.replicas 字段,ReplicaSet 可以被轻松地进行扩缩。

ReplicaSet 控制器能确保匹配标签选择器的数量的 Pod 是可用的。

方式二:通过 kubectl命令来扩容缩容:

kubectl scale replicaset nginx-gateway-rs --replicas 5kubectl scale replicaset nginx-gateway-rs --replicas 1

3:DaemonSet 守护集

DaemonSet 用途

DaemonSet用来确保每个node节点(或者指定部分节点)运行一个Pod副本,

这个副本随着node节点的加入而自动创建;若node节点被移除,Pod也将会被移除。

注意:默认master除外,master节点默认不会把Pod调度过去; DaemonSet 无需指定副本数量;因为默认给每个机器都部署一个

应用场景:

DaemonSet 组成结构详解

apiVersion: apps/v1kind: DaemonSetmetadata:  name: example  namespace: kube-system#===========Pod模版部分===============spec:  selector: #如果指定了 .spec.selector,必须与.spec.template.metadata.labels 相匹配    matchLabels:           name: example    #matchExpressions:这个可以自定义更加复杂的Selector      #key: value    #如果 matchLabels 和 matchExpressions 都指定,    #则两个结果之间为 AND 关系  template: # 必填字段    metadata:      labels:        name: example        #这里的labels 必须要和 .spec.selector相匹配,        #这个例子中,都是 name: example    #++++++++++++POD容器设置部分++++++++++++++    spec:      containers:      - name: fluentd-elasticsearch        image: k8s.gcr.io/fluentd-elasticsearch:1.20        volumeMounts:        - name: varlog          mountPath: /var/log        - name: varlibdockercontainers          mountPath: /var/lib/docker/containers          readOnly: true      volumes:      - name: varlog        hostPath:          path: /var/log      - name: varlibdockercontainers        hostPath:          path: /var/lib/docker/containers

调度节点的选择

一共分为三种方式选择调度节点:

方式一:nodeSelector方式

在了解亲和性之前,我们先来了解一个非常常用的调度方式:nodeSelector。

label 标签是 kubernetes 中一个非常重要的概念,用户可以非常灵活的利用 label 来管理集群中的资源,比如最常见的 Service 对象通过 label 去匹配 Pod 资源,而 Pod 的调度也可以根据节点的 label 来进行调度。

现在我们先给节点node打上标签

kubectl label nodes node-01 important=verykubectl get nodes --show-labels

可以上面的 --show-labels参数可以查看上述标签是否生效。

当节点被打上了相关标签后,在调度的时候就可以使用这些标签了,只需要在 Pod 的 spec 字段中添加 nodeSelector 字段,里面是我们需要被调度的节点的 label 标签,比如,下面的 Pod 我们要强制调度到 node-01 这个节点上去,我们就可以使用 nodeSelector 来表示了

指定调度到 important=very 的节点

spec:  nodeSelector:    important=very

方式二:nodeAffinity方式

亲和性又分成节点亲和性(nodeAffinity)和 Pod 亲和性(podAffinity)。

Affinity中文意思 ”亲和性” ,跟nodeSelect 类似,根据节点上的标签来调度 POD 在哪些节点上创建。

nodeAffinity 根据软策略和硬策略分为2种:

requiredDuringSchedulingIgnoredDuringExecution 表示:必须满足条件 。

表示POD 必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。

preferredDuringSchedulingIgnoredDuringExecution 表示:优选条件 。

表示 POD 优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署

硬策略、软策略中间的 IgnoredDuringExecution,表示 POD 部署完成之后,如果节点标签发生了变化,不再满足POD指定的条件,POD也会继续运行

nodeAffinity在匹配label时,可选的操作符有:

示例1

调度到包含标签 “metadata.name” 并且值为“demo-node” 的Node上,

apiVersion: v1kind: Podmetadata:  name: demo-node-affinityspec:  affinity:    nodeAffinity:      requiredDuringSchedulingIgnoredDuringExecution:        nodeSelectorTerms:        - matchExpressions:          - key: metadata.name            operator: In            values:            - demo-node

requiredDuringSchedulingIgnoredDuringExecution 这个代表nodeAffinity必须在每次调度的时候,必须予以考虑的 条件

示例2

调度到包含标签key1并且值为aaa或bbb的Node上,并且优选带有标签key2=ccc的Node(权重+1)

apiVersion: v1kind: Podmetadata:  name: examplespec:  affinity:    nodeAffinity:      requiredDuringSchedulingIgnoredDuringExecution:        nodeSelectorTerms:        - matchExpressions:          - key: key1            operator: In            values:            - aaa            - bbb      preferredDuringSchedulingIgnoredDuringExecution:      #可以设置多个优选条件,不同的优选条件可以设置不一样的权重      - weight: 1        preference:          matchExpressions:          - key: key2            operator: In            values:            - ccc  containers:  - name: with-node-affinity    image: harbor.daemon.io/demo/nginx-gateway:1.0-SNAPSHOT

在 nodeAffinity 的定义处,可以支持更加丰富的语法,比如operator: In(即:部分匹配)。

方式三:podAffinity方式

pod affinity是用来定义pod与pod间的亲和性,

所谓pod与pod的亲和性是指,pod更愿意和那个或那些pod在一起;

与之相反的也有pod更不愿意和那个或那些pod在一起,这种我们叫做pod anti affinity,即pod与pod间的反亲和性;

所谓在一起是指和对应pod在同一个位置,这个位置可以是按主机名划分,也可以按照区域划分,这样一来我们要定义pod和pod在一起或不在一起,定义位置就显得尤为重要,也是评判对应pod能够运行在哪里标准;

podAffinity 提供两种条件选择方式:

示例
apiVersion: v1kind: Podmetadata:  name: with-pod-affinityspec:  affinity:    podAffinity:      requiredDuringSchedulingIgnoredDuringExecution:      - labelSelector:          matchExpressions:          - key: security            operator: In            values:            - S1        topologyKey: failure-domain.beta.kubernetes.io/zone    podAntiAffinity:      preferredDuringSchedulingIgnoredDuringExecution:      - weight: 100        podAffinityTerm:          labelSelector:            matchExpressions:            - key: security              operator: In              values:              - S2          topologyKey: kubernetes.io/hostname  containers:  - name: with-pod-affinity    image: gcr.io/google_containers/pause:2.0

Toleration

DaemonSet 还会给这个 Pod 自动加上另外一个与调度相关的字段,叫作 tolerations

这个字段意味着这个 Pod,会“容忍”(Toleration)某些 Node 的“污点”(Taint)。

示例

apiVersion: v1kind: Podmetadata:  name: with-tolerationspec:  tolerations:  - key: node.kubernetes.io/unschedulable    operator: Exists    effect: NoSchedule

在正常情况下,被标记了 unschedulable“污点”的 Node,是不会有任何 Pod 被调度上去的(effect: NoSchedule)

可是,DaemonSet自动地给被管理的 Pod 加上了这个特殊的 Toleration,就使得这些 Pod 可以忽略这个限制,继而保证每个节点上都会被调度一个 Pod。

当然,如果这个节点有故障的话,这个 Pod 可能会启动失败,而 DaemonSet 则会始终尝试下去,直到 Pod 启动成功。

Toleration作用

通过这样一个 Toleration,调度器在调度这个 Pod 的时候,就会忽略当前节点上的“污点”,从而成功地将网络插件的 Agent 组件调度到这台机器上启动起来。

这种机制,正是我们在部署 Kubernetes 集群的时候,能够先部署 Kubernetes 本身、再部署网络插件的根本原因:因为当时我们所创建的 Weave的 YAML,实际上就是一个 DaemonSet。

4:StatefulSet 有状态集

Deployment 应用我们一般称为无状态应用(stateless) ; StatefulSet 称为有状态副本集

无状态应用:网络 可以变,存储挂载 可以会变,启动 次序 可以会变。主要用途为 就是业务代码(Deployment)

有状态应用:网络或 不可以变,存储挂载或 不可以会变,或 启动 次序 不 可以会变。主要用途为 中间件 MySQL、Redis、MQ 等等

StatefulSet和Deployment一样,可以保证集群中运行指定个数的pod,也支持横向扩展。除此之外StatefulSet中每一个pod会分配一个内部标记用来区分。

尽管StatefulSet的pod确实是从同一个pod模板创建的,但每个pod都是不可互换的。

无论pod被怎样调度,它们的内部标记都不会改变。

StatefulSet的这个特性,使得其下管理的每个pod具有不同的网络标识(可以指定发送请求到具体哪个pod,这些pod之间也可以相互通信),也可以绑定不同的持久化存储(pod重新调度之后,和它绑定的存储仍然是原先那个)。

StatefulSet 使用场景:

对于有如下要求的应用程序,StatefulSet 非常适用:

如果一个应用程序不需要稳定的网络标识,也不需要稳定的存储,也不需要按顺序部署、删除、增加副本,就应该考虑使用 Deployment 这类无状态(stateless)的控制器

StatefulSet的一些限制和要求

StatefulSet示例

demo-stateful.yml配置文件

apiVersion: v1kind: Service #定义一个 无头服务metadata:  name: stateful-nginx  labels:    app: stateful-nginxspec:  ports:    - port: 8008      name: web      targetPort: 8080    #NodePort:任意机器+NodePort都能访问,ClusterIP:集群内能用这个ip、service域名能访问,    #clusterIP: None;不要分配集群ip。headless;无头服务。稳定的域名    #Headless Services是一种特殊的service,其spec:clusterIP表示为None,这样在实际运行时就不会被分配ClusterIP。也被称为无头服务。  clusterIP: None  selector:    app: stateful-nginx---apiVersion: apps/v1kind: StatefulSet #控制器。metadata:  name: stateful-nginxspec:  selector:    matchLabels:      app: stateful-nginx # has to match .spec.template.metadata.labels  serviceName: "stateful-nginx"   #这里一定注意,必须提前有个service名字叫这个的  replicas: 3 # by default is 1  template:    metadata:      labels:        app: stateful-nginx # has to match .spec.selector.matchLabels    spec:      terminationGracePeriodSeconds: 10      containers:        - name: nginx-gateway          image: harbor.daemon.io/demo/nginx-gateway:1.0-SNAPSHOT          ports:            - containerPort: 8008              name: http

创建资源对象,并且查看 pod

查看 svc

DNS解析

整个状态kubelet(DNS内容同步到Pod)和kube-proxy(整个集群网络负责)会同步

curl http://stateful-nginx:8008/ : 负载均衡到sts部署的Pod上

curl http://stateful-nginx:8008/ : 直接访问指定Pod

启动一个容器,做一下测试

kubectl run -i --tty --image busybox:latest dns-test --restart=Never --rm /bin/sh
ping stateful-nginx-0.stateful-nginxping stateful-nginx-0.stateful-nginx.default.svc.cluster.local

StatefulSet 的几个要点

StatefulSet 和Deployment不同的的属性,主要有:

(1)pod管理策略(podManagementPolicy)

(2)updateStrategy: 更新策略

(3)必须配置service

(1)pod管理策略(podManagementPolicy)

podManagementPolicy : 控制Pod创建、升级以及扩缩容逻辑

使用 kubectl explain StatefulSet.spec查看

podManagementPolicy controls how pods are created during initial scale up, when replacing pods on nodes, or when scaling down. The default policy is OrderedReady , where pods are created in increasing order (pod-0, then pod-1, etc) and the controller will wait until each pod is ready before continuing. When scaling down, the pods are removed in the opposite order. The alternative policy is Parallel which will create pods in parallel to match the desired scale without waiting, and on scale down will delete all pods at once. 

配置项位于.spec.podManagementPolicy。用来配置pod的创建和销毁是否可以并行操作。有如下两个配置值:

(2)updateStrategy: 更新策略

使用 kubectl explain StatefulSet.spec查看

用来配置滚动升级的行为。

可供配置的值如下:

(3)对应的headless service

为了确保StatefulSet管理的每个pod的网络标识不同,需要创建对应的headless service。

注意在此之前创建了一个配套的headless service。

dns 的样式

pod-specific-string.serviceName.default.svc.cluster.local

前面的例子

ping stateful-nginx-0.stateful-nginx   # 同一个命名空间ping stateful-nginx-0.stateful-nginx.default.svc.cluster.local    # 跨命名空间

5:Job 任务、CronJob 定时任务

Job 任务

Kubernetes中的 Job负责批处理任务,即仅执行一次的任务。

Job 对象将创建一个或多个 Pod,并确保指定数量的 Pod 可以成功执行到进程正常结束。

再看Job .spec 的核心字段:

当 Job 创建的 Pod 执行成功并正常结束时,Job 将记录成功结束的 Pod 数量。当成功结束的 Pod 达到指定的数量时,Job 将完成执行。删除 Job 对象时,将清理掉由 Job 创建的 Pod

单个 Pod 时,默认 Pod 成功运行后 Job 即结束

job示例

创建job#查看job情况kubectl get job

并行 job 示例

创建job

查看job情况 kubectl get job

CronJob 定时任务

CronJob 是基于 Job 来工作的:

一个CronJob 对象类似于 crontab (cron table) 文件中的一行记录。

该对象根据 Cron 格式定义的时间计划,周期性地创建 Job 对象。

Schedule

所有 CronJob 的 schedule中所定义的时间,都是基于 master 所在时区来进行计算的。

一个 CronJob 在时间计划中的每次执行时刻,都创建 大约 一个 Job 对象。这里用到了 大约 ,是

因为在少数情况下会创建两个 Job 对象,或者不创建 Job 对象。尽管 K8S 尽最大的可能性避免这

种情况的出现,但是并不能完全杜绝此现象的发生。因此,Job 程序必须是 幂等的。

当以下两个条件都满足时,Job 将至少运行一次:

CronJob示例

apiVersion: batch/v1beta1kind: CronJobmetadata:  name: hellospec:  schedule: "*/1 * * * *" # 和linux的cron一样  concurrencyPolicy: Allow # 允许前后多个job同时运行  #可能前一个周期启动的备份job还没有完成,下一个周期的备份就已经开始了  #如果设置为 Forbid 的话,若前一个job没有完成,则后一个job不启动(跳过)  #如果设置为 Replace ,则让后一个job取代前一个,终止前一个启动后一个job  jobTemplate: #Job 模板,必需字段,指定需要运行的任务    spec:      template:        spec:          containers:          - name: hello            image: busybox:latest            args:            - /bin/sh            - -c            - date; echo Hello from the Kubernetes cluster          restartPolicy: OnFailure

Cron格式参考

# ┌───────────── minute (0 - 59)# │ ┌───────────── hour (0 - 23)# │ │ ┌───────────── day of the month (1 - 31)# │ │ │ ┌───────────── month (1 - 12)# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;# │ │ │ │ │                                   7 is also Sunday on some systems)# │ │ │ │ │# │ │ │ │ │# * * * * *

6:HPA(Horizontal Pod Autoscaling)水平自动伸缩

HPA使Pod水平自动缩放,不再需要手动扩容

HPA根据 CPU利用率自动化伸缩,还可以自定义指标自动化伸缩。

尼恩提示:本书《K8S圣经》的后面部分,会介绍更加高级的结合cAdvisor + Prometheus (推荐)实现 QPS 吞吐量 自动化伸缩,那属于高级内容。在学习高级内容之前, 咱们先掌握基础的: 基于metrics-server,实现 CPU 利用率的 简单HPA机制。

HPA 使用场景

Horizontal Pod Autoscaling仅适用于Deployment和ReplicaSet,

HPA由API server和controller共同实现。

Horizontal Pod Autoscaling,kubernetes能够根据监测到的 CPU 利用率(或者在 alpha 版本中支持的应用提供的 metric)自动的扩容 replication controller,deployment 和 replica set。

收集指标插件

HPA依赖到性能指标,收集指标信息插件有metrics-server和heapster,从 v1.8 开始,资源使用情况的监控可以通过 Metrics API的形式获取,具体的组件为Metrics Server,用来替换之前的heapster,heapster从1.11开始逐渐被废弃。

Metrics Server 是 Kubernetes 内置自动缩放管道的可扩展、高效的容器资源指标来源。

Metrics Server 从 Kubelets 收集资源指标,并通过Metrics API在 Kubernetes apiserver 中公开它们,以供 Horizontal Pod Autoscaler和Vertical Pod Autoscaler使用。

HPA - Horizontal Pod Autoscaler 和 VPA - Vertical Pod Autoscaler 是两种扩展容器应用处理能力的方式,HPA 是通过扩展 Pod 的数量实现的,而 VPA 是通过增加单个 Pod 的可用资源实现的。

通常 HPA 可用于水平扩展较容易的情况,例如 Serverless、FaaS、无状态微服务等。而 VPA 适用于水平扩展较复杂的情况,例如消息顺序处理、文件读写、数据库操作等。一般不建议对同一个资源同时应用 HPA 和 VPA。

咱们这里,仅仅关注 HPA。

Metrics API

介绍Metrics-Server之前,必须要提一下Metrics API的概念

Metrics API相比于之前的监控采集方式(hepaster)是一种新的思路,官方希望核心指标的监控应该是稳定的,版本可控的,且可以直接被用户访问(例如通过使用 kubectl top 命令),或由集群中的控制器使用(如HPA),和其他的Kubernetes APIs一样。

官方废弃heapster项目,就是为了将核心资源监控作为一等公民对待,即像pod、service那样直接通过api-server或者client直接访问,不再是安装一个hepater来汇聚且由heapster单独管理。

Metrics server出现后,新的Kubernetes监控架构,变成下图的样子

总体来说,K8S监控流程分为两个pipeline(流水线、或者通道):

核心流程(黑色部分):这是 Kubernetes正常工作所需要的核心度量,从 Kubelet、cAdvisor 等获取度量数据,再由metrics-server提供给Dashboard、HPA控制器等使用。

非核心监控流程(蓝色部分):基于核心度量构建的监控流水线,比如Prometheus可以从metrics-server获取核心度量,从其他数据源(如Node Exporter等)获取非核心度量,再基于它们构建监控告警系统。

core metrics pipeline 核心指标流水线

metrics组件:Kubelet、resource estimator、metrics-server、metrics api

metrics用途:服务于k8s系统核心组件,如调度器调度pod、自动水平扩展,能够提供简单的开箱即用功能,如kubectl top,类似linux top

monitoring pipeline 监控流水线

从系统中收集各种指标并将其暴露给最终用户,也通过适配器暴露给Horizontal Pod Autoscaler(用于自定义指标)和Infrastore。

Kubernetes不会附带monitoring pipeline,用户可以从许多监视系统方案中选择,道通常由每个节点代理和集群级聚合器组成。

kubernetes 的运行只依赖于core metrics

kubernetes 的运行只依赖于core metrics,并且会内置metrics server,而非核心监控流水线Monitoring Pipeline由第三方实现。

再来看看 core metrics、Infrastore、Monitoring Pipeline 的构成:

core metrics

Infrastore

计划用于持久存储core metrics,并为kubernetes dashboard提供数据

Monitoring Pipeline

必需提供的metrics:

可用方案:

40岁老架构师尼恩提示

当然,本书《K8S圣经》的后面部分,会介绍更加高级的结合cAdvisor + Prometheus (推荐)实现 QPS 吞吐量 自动化伸缩,那属于高级内容。

在学习高级内容之前, 咱们先掌握基础的: 基于metrics-server,实现 CPU 利用率的 简单HPA机制。

在 core metrics pipeline 核心指标流水线 中,metrics-server 是一个非常核心的组件。

总之:metrics-server是一个集群范围内的资源数据集和工具,同样的,metrics-server也只是显示数据,并不提供数据存储服务,主要关注的是资源度量API的实现,比如CPU、文件描述符、内存、请求延时等指标,metric-server收集数据给k8s集群内使用,如kubectl,hpa,scheduler等

注意: 通过 Metrics API,只能获取 node 或 pod 当前的使用情况。

并且k8s不会存储这个数据,因此想要获取10分钟前的资源使用量是不行的。

前置条件: 开启聚合路由

启用API Aggregator,API Aggregation 允许在不修改 Kubernetes 核心代码的同时扩展 Kubernetes API,即:将第三方服务注册到 Kubernetes API 中,这样就可以通过 Kubernetes API 来访问第三方服务了,Metrics Server API 就是将自己的服务注册到 Kubernetes API 中。

注:另外一种扩展 Kubernetes API 的方法是使用 CRD(Custom Resource Definition,自定义资源定义)。后面介绍qps 水平伸缩的时候,使用CRD.

检查 API Server 是否开启了 Aggregator Routing

具体来说,就是 查看 API Server 是否具有 --enable-aggregator-routing=true选项。

如果没有则需要添加

首先 ps -ef | grep apiserver

复制到editplus ,查找 enable-aggregator ,发现找不到

修改 API Server 的 kube-apiserver.yaml ,配置开启 Aggregator Routing。

修改 manifests 配置后 API Server 会自动重启生效。

修改 过程中,使用到的命令

复制到 本地scp /etc/kubernetes/manifests/kube-apiserver.yaml   root@192.168.56.121:/vagrant/chapter28/metrics/ 使用editplus 修改, 然后scp 回去 scp /etc/kubernetes/manifests/kube-apiserver.yaml   root@192.168.56.121:/vagrant/chapter28/metrics/ vi 检查一下 再重启   systemctl restart kubelet

systemctl restart kubelet重启之后,能看到 成功开启 Aggregator Routing。

metrics安装方式一:minikube 中启用指标服务器作为插件

一种简单的方式为,在 minikube 中启用指标服务器作为插件

minikube addons enable metrics-server

启动插件的过程中,毫无疑问,一定会有 minikube metrics-server pod 错误

查看 metrics-serverpod 错误,大致如下:

Failed to pull image "k8s.gcr.io/metrics-server-amd64:v0.5.2": rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

这个错误是k8s.gcr.io无法访问,需要替换成在国内的镜像,可以使用阿里云的。

registry.cn-hangzhou.aliyuncs.com/google_containers

完整镜像地址。

registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.5.2

进入 minikube docker 手动pull镜像。

minikube sshdocker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.5.2

为了让metrics-server-deployment能工作需要手动打个tag,并且让pod拉取镜像的规则设置成IfNotPresent。

docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server:v0.5.2 k8s.gcr.io/metrics-server/metrics-server:v0.5.2

最后,修改镜像拉取规则, 防止每次启动,优先去远程拉取。 改为优先使用本地的 镜像,只有本地没有才去远程。

imagePullPolicy: IfNotPresent

还有一种策略: 可以手动修改deployment image地址,尼恩经常这么做。

metrics server安装方式二:手动安装

插件模式太傻瓜, 尼恩建议大家手动安装, 这样能学到 真功夫

首先安装metrics 在 k8s 官网上找到metrics的项目地址:metrics项目地址。将项目下载到本地并安装

wget下载yaml文件

wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.3/components.yaml

这里一定要注意配套的版本, 尼恩在版本上,躺了不止5个以上的坑

Metrics ServerMetrics API group/versionSupported Kubernetes version
0.6.xmetrics.k8s.io/v1beta11.19+
0.5.xmetrics.k8s.io/v1beta1*1.8+
0.4.xmetrics.k8s.io/v1beta1*1.8+
0.3.xmetrics.k8s.io/v1beta11.18-1.21+

如果安装了插件,要自行安装metrics-server,首先要禁用插件。

minikube addons disable metrics-server

metrics-server 的 部署 文件 metrics-server/manifests/base/deployment.yaml

手动安装前, 需要 修改镜像地址、修改imagePullPolicy策略,具体如下图:

修改镜像 个url 路径,以及 tls 认证方式

当然,如果图节省时间,可以直接使用尼恩的 《K8S学习圣经》 的配套版本

执行安装和检查

kubectl apply -f components.yaml

查看metrics-server服务状态

kubectl get pod -n kube-system | grep metrics-server

这里,需要检查接口是否有异常,尼恩在这里,耽误了不少的时间

一直报一个下面的错误

endpoints for service/metrics-server in "kube-system" have no addresses with port name "https"

下一步:检查 API Server 是否可以连通 Metrics Server

kubectl describe svc metrics-server -n kube-system

下一步:执行以下命令,检查节点占用性能情况。

kubectl top nodeskubectl top pods

截止到这里,可以判断 已经安装成功了

执行安装的命令清单

cd /vagrant/chapter28/metrics/063kubectl apply -f components.yamlkubectl get pod -n kube-system | grep metrics-serverkubectl describe apiservice v1beta1.metrics.k8s.iokubectl top nodeskubectl get pods -Akubectl top nodeskubectl top podskubectl get  secret -Akubectl delete --ignore-not-found=true -f manifests/ -f manifests/setup

7:使用HPA对SpringCloud微服务进行自动伸缩

autoscale命令

kubectl autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS[--cpu-percent=CPU] [flags] [options]

Metrics支持的指标

这里使用 cpu指标进行 自动伸缩,

kubectl autoscale deployment  demo-provider-deployment --cpu-percent=50 --min=1 --max=4

为Deployment demo-provider-deployment创建一个autoscaler,当Pod的CPU利用率达到50%的时候,RC的replica数量在1到4之间。

或者说:

为deployment demo-provider-deployment (微服务POD) 创建HPA,其中最小副本数为1,最大副本数为4,保持该deployment的所有Pod的平均CPU使用率不超过50%。

在本例中,deployment的pod的resources.request.cpu为250m (250 milli-cores vCPU),所以HPA将保持所有Pod的平均CPU使用率不超过125m。

这里有个小前提,要伸缩的pod必须进行资源限制:限制监控指标

在微服务应用中, 设置了 resources.request.cpu为250m ,具体如下图所示

创建hpa、查看hpa、删除hpa

创建hpa,默认默认创建的HPA名称和需要自动伸缩的对象名一致,可以通过--name来指定HPA名

kubectl autoscale deployment  demo-provider-deployment --cpu-percent=50 --min=1 --max=4

查看hpa: kubectl get hpa

删除hpa : kubectl delete hpa demo-deployment

kubectl autoscale deployment  demo-provider-deployment --cpu-percent=50 --min=1 --max=4

监控hpa: watch kubectl get hpa

HPA扩容实操

使用wrk 命令,进行压力测试

发现 监控指标猛涨到 400%

然后看到POD的副本,从1个扩容到4个

kubectl get hpakubectl get deploymentkubectl autoscale deployment  demo-provider-deployment --cpu-percent=50 --min=1 --max=4 curl  http://192.168.49.2:32700/demo-provider/swagger-ui.htmlwrk -t12 -c400 -d30s http://192.168.49.2:32700/demo-provider/swagger-ui.html

基于自定义指标的自动扩容

可以基于内存进行扩容实操

还可以基于自定义指标进行扩容实操

但是最佳的方案的: 基于 promethus + qps + K8S的方式进行 CDC 类型的扩容实操。

《K8S学习圣经》后面,使用单独一章,进行专题介绍。

技术自由的实现路径:

实现你的 架构自由:

《吃透8图1模板,人人可以做架构》

《10Wqps评论中台,如何架构?B站是这么做的!!!》

《阿里二面:千万级、亿级数据,如何性能优化? 教科书级 答案来了》

《峰值21WQps、亿级DAU,小游戏《羊了个羊》是怎么架构的?》

《100亿级订单怎么调度,来一个大厂的极品方案》

《2个大厂 100亿级 超大流量 红包 架构方案》

… 更多架构文章,正在添加中

实现你的 响应式 自由:

《响应式圣经:10W字,实现Spring响应式编程自由》

这是老版本 《Flux、Mono、Reactor 实战(史上最全)》

实现你的 spring cloud 自由:

《Spring cloud Alibaba 学习圣经》 PDF

《分库分表 Sharding-JDBC 底层原理、核心实战(史上最全)》

《一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系(史上最全)》

实现你的 linux 自由:

《Linux命令大全:2W多字,一次实现Linux自由》

实现你的 网络 自由:

《TCP协议详解 (史上最全)》

《网络三张表:ARP表, MAC表, 路由表,实现你的网络自由!!》

实现你的 分布式锁 自由:

《Redis分布式锁(图解 - 秒懂 - 史上最全)》

《Zookeeper 分布式锁 - 图解 - 秒懂》

实现你的 王者组件 自由:

《队列之王: Disruptor 原理、架构、源码 一文穿透》

《缓存之王:Caffeine 源码、架构、原理(史上最全,10W字 超级长文)》

《缓存之王:Caffeine 的使用(史上最全)》

《Java Agent 探针、字节码增强 ByteBuddy(史上最全)》

实现你的 面试题 自由:

4000页《尼恩Java面试宝典 》 40个专题

K8S学习圣经6:资源控制+SpringCloud动态扩容原理和实操

2023-04-06 12:15:22

天天微速讯:鹈鹕加时前三分钟以12-0打懵灰熊 加时得分是对手的两倍

2023-04-06 11:19:51

速看:新被套买回来可以直接盖吗(新被套有甲醛吗)

2023-04-06 10:38:08

Karsa扎克打出的五波神仙开团,少一波RNG都赢不了比赛!|环球快播

2023-04-06 09:53:15

简讯:突发!币圈大佬遇刺身亡 啥情况?瑞士政府:削减瑞信高管奖金 考虑追回已发放奖金!重磅数据崩了 美股涨跌不一

2023-04-06 09:05:32

秘法之牙掉落_秘法之牙

2023-04-06 08:03:35

易纲:我国外汇市场具有韧性,有能力实现动态均衡

2023-04-06 05:54:47

萨莉亚 莘庄龙之梦店_关于萨莉亚 莘庄龙之梦店的简介

2023-04-06 01:57:04

泛海控股被法院查封、冻结价值16.82亿元财产 及相关子公司股权

2023-04-05 21:59:38

福建:3女子坐一桌吃饭,隔壁男子主动买单,吃完跑路被老板追到

2023-04-05 20:09:24

圣阳股份(002580.SZ)一季度扣非净利润预增93.35%-135.16%

2023-04-05 16:49:15

2023年清明档票房破亿!任天堂《超级马力欧兄弟大电影》暂列亚军

2023-04-05 15:31:05

全球要闻:学习卡丨为什么“和平年代同样需要英雄情怀”?

2023-04-05 13:46:52

花魁的玩物元媛全文_花魁的玩物元媛 焦点快看

2023-04-05 12:17:59

节气里的中国智慧丨今日,清明-焦点速讯

2023-04-05 10:48:52

科技部就《科技伦理审查办法(试行)》征求意见

2023-04-05 09:12:58

六味地黄丸能不能治早射_六味地黄

2023-04-05 07:52:26

沙特投资380亿美元 打造电游产业中心_当前独家

2023-04-05 05:53:38

皮蛋含有蛋白质有多少?

2023-04-05 02:55:39

实时:大棚菠萝施肥方法及时间 大棚菠萝施肥方法和时间

2023-04-04 23:00:56

世界微头条丨风格洞察与性价比追踪系列(十五):风格“大乱斗”

2023-04-04 21:26:42

企业管理:2023数字化转型下企业内容管理的挑战与应对策略

2023-04-04 20:04:41

行权价格和股票价格的区别_行权价格

2023-04-04 18:45:07

【播资讯】高薪低能!5年2.5亿续约,带队季后赛都进不去!这就是垃圾合同啊

2023-04-04 17:53:38

微速讯:工业和信息化部:1-2月全国锂电总产量超过102GWh 同比增长24%

2023-04-04 17:04:29

萌宠乐园-给孩子一个亲近自然的机会

2023-04-04 16:03:18

全球快资讯丨十岁男士生日送什么礼物好

2023-04-04 15:32:02

优秀人物专访的新闻稿(优秀人物专访新闻稿)

2023-04-04 15:32:01

异动快报:ST摩登(002656)4月4日13点38分触及跌停板

2023-04-04 14:38:03

卫报:美国宇航局新一届登月成员组合 第一位女性和第一位黑人入选 全球观点

2023-04-04 13:26:49

新能源汽车动力电池包(新能源汽车动力电池)

2023-04-04 12:11:18

荔枝的培植技巧(荔枝的培植技巧视频)

2023-04-04 11:26:35

曹操“煮酒论英雄”时,为何称袁术为冢中枯骨?_天天看点

2023-04-04 10:57:09

【环球播资讯】LCD党等了好久,只等来个骁龙782G,网友:等了个寂寞

2023-04-04 10:11:03

交控科技:4月3日融资净买入588.13万元,连续3日累计净买入805.89万元|天天简讯

2023-04-04 08:42:54

勇气去那儿了400字作文(必备17篇) 全球微动态

2023-04-04 07:43:59

秦岚魏大勋官宣?浪姐名单?张静初学霸?成龙接班人?_环球快消息

2023-04-04 05:46:46

哇字组词(哇怎么组词)

2023-04-04 02:54:12

清明时节雨纷纷,北京今起三天多雨,大风降温也来“作伴”

2023-04-03 22:46:06

快看点丨民航业日亏3亿后,2023年将恢复到疫情前75%

2023-04-03 21:09:31

湖人官方宣布:拉塞尔脚部酸痛 本场比赛不会回归-最新

2023-04-03 20:04:37

振华股份2022营业收入35.34亿元,净利润同比增长34.22%

2023-04-03 19:00:28

3月已经在下跌中结束行情,生猪价格在4月中旬开始上涨 快看点

2023-04-03 18:08:40

日本称将加强对高性能半导体制造设备出口管制 中方:已向日方严正交涉

2023-04-03 17:15:23

​云赛智联旗下仪电溯源中标上海市食品安全监管和信息服务平台项目

2023-04-03 16:31:44

全球快资讯:河北赵县万亩梨花盛放 春日限定款美景吸引八方游客

2023-04-03 15:59:18

章集好人 德润心田

2023-04-03 15:15:49

文旅产业为南昌经济注入崭新活力

2023-04-03 14:25:31

浓眉:队友们让我打得很轻松 我们正打出湖人式的篮球

2023-04-03 13:36:57

【我们的家园】四川绵阳:互帮互助互学 民族团结之“花”盛开校园 焦点简讯

2023-04-03 12:44:14

“停更”透露危险信号,B站难留UP主|资讯推荐

2023-04-03 12:32:49

电线杆突然倒下,女子骑车路过被电线勒死!家属索赔95万余元 播资讯

2023-04-03 11:58:00

这五种员工能力再差,领导也喜欢,学习他们,总没坏处

2023-04-03 10:52:38

【全球新视野】收藏!清明假期免票优惠盘点

2023-04-03 10:16:17

599美元香吗?RTX4070价格泄露|世界热点评

2023-04-03 10:23:30

农村送爸爸什么礼物好

2023-04-03 09:05:26

六福珠宝黄金价格今天多少一克(2023年04月02日) 环球快资讯

2023-04-03 08:51:00

筑巢引凤!广州开发区培育创新热土与知识产权人才乐土

2023-04-03 08:42:14

英红九号红条茶_关于英红九号红条茶的简介

2023-04-01 12:04:14

利物浦将迎来9天魔鬼赛程 克洛普无奈球队状态起伏太大

2023-04-01 10:13:08

关于PCL2自定义标记文件 全球快资讯

2023-04-01 09:16:27

世界微资讯!白色车补漆笔使用方法 白色车补漆笔使用方法视频教程

2023-04-01 07:22:45

数字赋能让医疗服务变聪明了

2023-04-01 05:55:46

股票行情快报:江苏雷利(300660)3月31日主力资金净卖出982.44万元_天天要闻

2023-04-01 02:03:02

初级会计学习方式有什么-今日观点

2023-03-31 22:55:47

信达证券发布中信证券研报 业务全面领先 业绩稳健性再显行业龙头优势 投行收入增长亮眼 世界滚动

2023-03-31 21:46:41

深网观察 第740期 | 研考生因航班延误缺考复试?给学校回应点赞!-环球消息

2023-03-31 20:43:55

国家外汇管理局:去年末我国外债规模保持基本稳定|当前简讯

2023-03-31 19:13:23

如何探索“白酒新世界”?华润酒业“三年规划”给出答案-最新快讯

2023-03-31 18:19:08

天天滚动:过年不去用给男朋友家人买礼物吗

2023-03-31 18:36:16

中毅达(600610.SH):上交所中止公司发行股份购买资产审核

2023-03-31 17:44:19

世界观天下!在莫斯科感受“战时”印记

2023-03-31 17:04:59

今晚国内油价或“两连跌”加满一箱省…… 环球视点

2023-03-31 16:11:09

永乐乡:以桃为媒 走好乡村振兴之路

2023-03-31 15:24:49

[一览排名榜单]成都治疗支气管哮喘医院[TOP5排名]成都专业哮喘病医院_世界快资讯

2023-03-31 14:12:16

关于征求团体标准意见的函_当前头条

2023-03-31 13:13:45

媒体人:将足球圈这个房间彻底打扫干净,是中国足球重生必要条件-全球球精选

2023-03-31 12:17:08

火星人:3月30日融资买入721.22万元,融资融券余额5956.05万元

2023-03-31 11:22:39

万科郁亮:房地产市场每年仍有12万亿保底线规模

2023-03-31 10:56:23

走进中国电信博物馆,看5G、AR如何让博物馆更智慧?

2023-03-31 10:09:38

精选!快手All in海外,能否复制Tiktok?

2023-03-31 09:05:45

烟花爆竹零售店设置要合法合规 须与人员密集场所及重点建筑距离百米以上-世界观天下

2023-03-31 08:09:56

学雷锋月收官 看广州社区“花式”志愿服务

2023-03-31 04:54:33

阳光纸业(02002)发布年度业绩,收入95.38亿元 同比增加19.49%

2023-03-31 00:45:05

全球观焦点:外媒:美军两架“黑鹰”直升机在训练中坠毁

2023-03-30 22:18:09

新物种发布 京东超市联手钟薛高开启“甜品雪糕”新势力 首单即集采100万件

2023-03-30 21:02:03

资讯推荐:国内脐橙供应整体偏紧 产地价格持续偏强运行

2023-03-30 20:08:22

当前播报:电纸书吧

2023-03-30 18:56:48

世界观天下!双良节能:子公司签订20.09亿元单晶硅片销售合同

2023-03-30 17:59:17

环球即时:每日一词∣国家级文化产业示范园区 national cultural demonstration zones

2023-03-30 17:17:03

全球头条:外交部:巴西人民币清算安排的建立有利于中国与巴西两国企业和金融机构

2023-03-30 16:22:59

每日视点!丝路视觉(300556)3月30日主力资金净卖出2138.55万元

2023-03-30 15:36:09

隧道内定位不再“漂”,高德推出国内首个完整定位能力的手机隧道导航_天天快资讯

2023-03-30 14:55:34

环球快资讯:77岁的程志因病去世,最后见面的时候已经是发白脸消瘦了!

2023-03-30 13:35:00

环球要闻:女孩生日送什么礼物,最重要的是平价

2023-03-30 12:22:57

​搭乘飞机、高铁和地铁,还需要佩戴口罩吗?|天天观焦点

2023-03-30 11:44:03

上海市未来产业先进核能专家委员会成立|当前速读

2023-03-30 10:50:44

券商降薪!有券商人均年薪降至46万元

2023-03-30 10:14:30

全球快资讯丨昆船智能:3月29日获融资买入586.70万元

2023-03-30 09:34:13

【独家】索爱U10_索爱u1怎么样

2023-03-30 08:53:17