【k8s系列】Kubernetes Service 深度解析:从基础到实战

news2024/11/23 4:17:44

一、前言

在当今的云原生世界中,Kubernetes 已经成为容器编排和管理的事实标准。它提供了一种强大的方式来部署、扩展和管理容器化应用。然而,随着应用规模的扩大和复杂性的增加,如何有效地暴露和管理这些应用的网络服务成为了一个关键问题。Kubernetes Service 正是解决这一问题的利器。

Kubernetes Service 是一种抽象,它定义了一组逻辑 Pod 集合和访问它们的策略。通过 Service,开发者可以轻松地将应用暴露给集群内部或外部的用户,而无需关心 Pod 的具体位置和数量。这种抽象不仅简化了网络配置,还提供了负载均衡、服务发现和稳定网络标识等关键功能。

本文将分享一些笔者在这块的知识点学习过程,便于感兴趣的小伙伴可以快速理解Kubernetes组件的基础应用。

二、Kubernetes Service 简介

(1)Service 的基本概念和作用

Kubernetes Service 是一种抽象,它定义了一组逻辑 Pod 集合和访问它们的策略。Service 通过一个稳定的 IP 地址和端口,将流量路由到后端的 Pod 集合。这种抽象使得应用的网络配置变得简单和一致,无论 Pod 的具体位置和数量如何变化。Service 具有以下关键特征:

  • 唯一指定的名字:每个 Service 都有一个唯一的名字,例如 mysql-server。这个名字在集群内部可以被用作 DNS 名称,方便服务发现。

  • 虚拟IP和端口号:Service 被分配了一个虚拟 IP 地址(Cluster IP)和一个端口号。这个虚拟 IP 地址是稳定的,不会随着 Pod 的变化而改变。

  • 远程服务能力:Service 提供了某种远程服务能力,例如数据库服务、缓存服务或 Web 服务。

  • 映射到容器应用:Service 被映射到提供这种服务能力的一组容器应用(Pod)上。

Service 在 Kubernetes 中扮演着至关重要的角色,其主要作用包括:

  • 服务发现:Service 提供了一种机制,使得集群内的其他组件和服务可以发现和访问它。

  • 负载均衡:Service 可以将流量均匀地分发到后端的多个 Pod 上,从而实现负载均衡。

  • 稳定的网络标识:Service 提供了一个稳定的 IP 地址和 DNS 名称,即使后端的 Pod 发生变化,客户端也可以通过这个标识稳定地访问服务。

(2)Service与Pod的关系

在 Kubernetes 中,Service 定义了一个服务的访问入口地址,前端应用(Pod)通过这个入口地址访问背后的一组由 Pod 副本组成的集群。Service 与后端的 Pod 副本集群通过 Label Selector 实现“无缝对接”。而 其中Replication Controller(RC)的作用是确保 Service 的服务能力和服务质量达到预期标准。

通过将系统中的所有服务建模为 Kubernetes Service,我们的系统由多个提供不同业务能力且彼此独立的微服务单元组成。这些服务之间通过 TCP/IP 进行通信,从而拥有了强大的分布式能力、弹性扩展能力和容错能力。

每个 Pod 都会被分配一个单独的 IP 地址,并且每个 Pod 提供一个独立的 Endpoint(Pod IP + ContainerPort)供客户端访问。多个 Pod 副本组成一个集群来提供服务。

此外,Kubernetes 在每个节点上安装 kube-proxy。kube-proxy 进程实际上是一个智能的软件负载均衡器,负责将对 Service 的请求转发到后端的某个 Pod 实例上,并在内部实现服务的负载均衡和会话保持机制。

Kubernetes 在这块使用了一个非常巧妙的设计方法:每个 Service 被分配了一个全局唯一的虚拟 IP 地址,称为 Cluster IP。这样,每个服务就变成了具备唯一 IP 地址的“通信节点”,服务调用变成了最基础的 TCP 网络通信问题。

Pod 的 Endpoint 地址会随着 Pod 的销毁和重新创建而改变,因为新的 Pod 地址与之前的不同。而 Service 一旦被创建,Kubernetes 就会自动为它分配一个可用的 Cluster IP,并且在 Service 的整个生命周期内,它的 Cluster IP 不会发生改变。因此,只需将 Service 的名称与 Service 的 Cluster IP 地址做一个 DNS 域名映射即可解决问题。

(3)Service的定义

Kubernetes 中的 Service 是一个对象(与 Pod 或 ConfigMap 类似)。我们可以使用 Kubernetes API 创建、查看或修改 Service 定义。 通常我们会使用 kubectl 这类工具来替我们发起这些 API 调用。

例如,假定有一组 Pod,每个 Pod 都在侦听 TCP 端口 9376,并且它们还被打上 app.kubernetes.io/name=MyApp 标签。我们可以定义一个 Service 来发布该 TCP 侦听器。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376

参数解析:

参数说明
apiVersion指定 API 版本,对于 Service 通常是 v1
kind指定资源类型,这里是 Service
metadata包含 Service 的元数据,如名称 name
spec定义 Service 的详细规格。
selector选择器,用于指定与 Service 关联的 Pod 的标签。
ports定义 Service 的端口配置。
protocol协议,通常是 TCP 或 UDP。
portService 的端口号。
targetPortPod 的端口号,流量将被转发到这个端口。
typeService 的类型,可以是 ClusterIP、NodePort、LoadBalancer 或 ExternalName。

因此上面的service表示系统将创建一个名为 "my-service" 的、 服务类型默认为 ClusterIP 的 Service。 该 Service 指向带有标签 app.kubernetes.io/name: MyApp 的所有 Pod 的 TCP 端口 9376。

Kubernetes 为该 Service 分配一个 IP 地址(称为 “集群 IP”),供虚拟 IP 地址机制使用。

需要说明的是:Service 能够将任意入站 port 映射到某个 targetPort。 默认情况下,出于方便考虑,targetPort 会被设置为与 port 字段相同的值。

除此以外,在Service中也能引用Pod中定义的端口名程:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app.kubernetes.io/name: proxy
spec:
  containers:
  - name: nginx
    image: nginx:stable
    ports:
      - containerPort: 80
        name: http-web-svc
​
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app.kubernetes.io/name: proxy
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80
    targetPort: http-web-svc

即使在 Service 中混合使用配置名称相同的多个 Pod,各 Pod 通过不同的端口号支持相同的网络协议, 此机制也可以工作。这一机制为 Service 的部署和演化提供了较高的灵活性。 例如,我们可以在后端软件的新版本中更改 Pod 公开的端口号,但不会影响到客户端。

Service 的默认协议是 TCP; 我们还可以使用其他受支持的任何协议。

由于许多 Service 需要公开多个端口,所以 Kubernetes 为同一 Service 定义多个端口。 每个端口定义可以具有相同的 protocol,也可以具有不同协议。

(4)Service的类型

Kubernetes 提供了四种主要的 Service 类型:

  • ClusterIP

    ClusterIP 是默认的 Service 类型。它为 Service 分配一个集群内部的虚拟 IP 地址,使得集群内的其他组件和服务可以访问它。这种类型适用于集群内部的服务发现和通信。我们可以使用 Ingress或者 Gateway API向公共互联网公开服务。

    其他几种 Service 类型在 ClusterIP 类型的基础上进行构建。如果我们定义的 Service 将 .spec.clusterIP 设置为 "None",则 Kubernetes 不会为其分配 IP 地址。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: my-app
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376
      type: ClusterIP

    在创建 Service 的请求中,我们可以通过设置 spec.clusterIP 字段来指定自己的集群 IP 地址。我们所选择的 IP 地址必须是合法的 IPv4 或者 IPv6 地址,并且这个 IP 地址在 API 服务器上所配置的 service-cluster-ip-range CIDR 范围内。 如果我们尝试创建一个带有非法 clusterIP 地址值的 Service,API 服务器会返回 HTTP 状态码 422, 表示值不合法。

  • NodePort

    NodePort 类型是在每个节点上开放一个端口,通过这个端口将流量转发到 Service。这种类型适用于需要从集群外部访问服务的场景。 为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址, 相当于我们请求了 type: ClusterIP 的 Service。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: my-app
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376
          nodePort: 30007
      type: NodePort

    如果我们将 type 字段设置为 NodePort,则 Kubernetes 控制平面将在 --service-node-port-range 标志所指定的范围内分配端口(默认值:30000-32767)。 每个节点将该端口(每个节点上的相同端口号)上的流量代理到我们的 Service。 我们的 Service 在其 .spec.ports[*].nodePort 字段中报告已分配的端口。

    使用 NodePort 可以让我们自由设置自己的负载均衡解决方案, 配置 Kubernetes 不完全支持的环境, 甚至直接公开一个或多个节点的 IP 地址。

    对于 NodePort 类型 Service,Kubernetes 额外分配一个端口(TCP、UDP 或 SCTP 以匹配 Service 的协议)。 集群中的每个节点都将自己配置为监听所分配的端口,并将流量转发到与该 Service 关联的某个就绪端点。 通过使用合适的协议(例如 TCP)和适当的端口(分配给该 Service)连接到任何一个节点, 我们就能够从集群外部访问 type: NodePort 服务。

  • LoadBalancer

    使用云平台的负载均衡器将流量分发到 Service。Kubernetes 不直接提供负载均衡组件; 我们必须提供一个,或者将我们的 Kubernetes 集群与某个云平台集成。这种类型适用于需要外部负载均衡器的场景。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app.kubernetes.io/name: MyApp
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376
      clusterIP: 10.0.171.239
      type: LoadBalancer
    status:
      loadBalancer:
        ingress:
        - ip: 192.0.2.127

    来自外部负载均衡器的流量将被直接重定向到后端各个 Pod 上,云平台决定如何进行负载平衡。要实现 type: LoadBalancer 的服务,Kubernetes 通常首先进行与请求 type: NodePort 服务类似的更改。cloud-controller-manager 组件随后配置外部负载均衡器, 以将流量转发到所分配的节点端口。

  • ExternalName

    将服务映射到 externalName 字段的内容(例如,映射到主机名 api.test.com)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。 集群不会为之创建任何类型代理。这种类型适用于需要将集群内部的服务映射到外部服务的场景。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      type: ExternalName
      externalName: my.database.com

    服务 API 中的 type 字段被设计为层层递进的形式 - 每层都建立在前一层的基础上。 但是,这种层层递进的形式有一个例外。 我们可以在定义 LoadBalancer Service 时禁止负载均衡器分配 NodePort

    通过设置 Service 的 spec.allocateLoadBalancerNodePortsfalse,我们可以对 LoadBalancer 类型的 Service 禁用节点端口分配操作。 这仅适用于负载均衡器的实现能够直接将流量路由到 Pod 而不是使用节点端口的情况。 默认情况下,spec.allocateLoadBalancerNodePortstrue,LoadBalancer 类型的 Service 也会继续分配节点端口。如果某已有 Service 已被分配节点端口,如果将其属性 spec.allocateLoadBalancerNodePorts 设置为 false,这些节点端口不会被自动释放。 我们必须显式地在每个 Service 端口中删除 nodePorts 项以释放对应的端口。

(5)Service与kube-proxy

在 Kubernetes 中,kube-proxy 是一个关键的组件,它运行在每个节点上,负责维护节点上的网络规则,使得从集群内部或外部的流量能够正确地路由到 Service 及其后端的 Pod。

当一个 Service 被创建时,kube-proxy 会监听到这个事件,并根据 Service 的配置在节点上创建相应的网络规则。这些网络规则通常包括 iptables 规则或 IPVS 规则,用于将流量从 Service 的虚拟 IP 地址(Cluster IP)转发到后端的 Pod。比如当一个nginx的 Service 被创建时,kube-proxy 会在每个节点上创建相应的 iptables 规则,将发往service 的 Cluster IP 和端口 80 的流量转发到后端的 Pod。

kube-proxy 的工作原理

  1. 分布式代理:每个 Node 节点上都会运行一个 kube-proxy 服务进程。kube-proxy 通过查询和监听 API Server 中 Service 与 Endpoints 的变化,为每个 Service 都建立一个“服务代理对象”,并自动同步。

  2. 服务代理对象:服务代理对象是 kube-proxy 程序内部的一种架构,它包括一个用于监听此服务请求的 SocketServer。SocketServer 的端口是随机选择一个本地空闲端口。此外,kube-proxy 内部创建了一个负载均衡器 LoadBalancer。

  3. 负载均衡:对于每个 TCP 类型的 Kubernetes Service,kube-proxy 都会在本地 Node 节点上建立一个 SocketServer 来负责接收请求,然后均匀发送到后端某个 Pod 的端口上。这个过程默认采用 Round Robin (rr) 负载均衡算法。

  4. 动态更新:kube-proxy 通过持续监控 API Server 中 Service 与 Endpoints 的变化,针对发生变化的 Service 列表,kube-proxy 会逐个处理。如果没有设置集群 IP,则不做任何处理;否则,kube-proxy 会为该 Service 的所有端口定义列表分配服务代理对象,并为该 Service 创建相关的 iptables 规则,更新负载均衡组件中对应 Service 的转发地址列表。

  5. 会话保持:在某些情况下,kube-proxy 还可以实现会话保持(Session Affinity),即确保来自同一个客户端的请求总是被转发到同一个后端 Pod。这对于需要保持会话状态的应用非常有用。

    比如咱们希望 my-service 实现客户端 IP 会话保持,可以在 Service 的 YAML 定义中添加 sessionAffinity 字段:

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: my-app
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376
      type: ClusterIP
      sessionAffinity: ClientIP

    这样,kube-proxy 会根据客户端的 IP 地址将请求转发到同一个后端 Pod。

kube-proxy在启动时和监听到Service或Endpoint的变化后,会在本机Iptables的NAT表中添加4条规则链。

  • KUBE-PORTABLS-CONTAINER: 从容器中通过Cluster IP和端口号访问service

  • KUBE-PORTALS-HOST: 从主机中通过Cluster IP和端口号访问service

  • KUBE-NODEPORT-CONTAINER: 从容器中通过NODE IP和端口号访问service

  • KUBE-NODEPORT-HOST: 从主机中通过Node IP和端口号访问service

三、Kubernetes Service的基础使用

手动创建一个Service的配置文件,并配置上外部访问:

root@master01:/opt/cri-docker-file# vi redis-service.yaml
root@master01:/opt/cri-docker-file# cat redis-service.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: redis-pod
  labels:
    app: redis
spec:
  containers:
    - name: redis
      image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/redis:7.0.14
      ports:
        - containerPort: 6379
          name: redis-pod
---        
apiVersion: v1
kind: Service
metadata:
  name: redis-service
  labels:
    app: redis
spec:
  selector:
    app: redis
  ports:
    - protocol: TCP
      port: 6379
      targetPort: redis-pod
      nodePort: 30079
  type: NodePort

这里为了方便redis服务的应用直接将pod部分也一起写在同一个yaml文件下了。然后可以查看一下pod的执行情况以及service的信息:

#创建pod和service
root@master01:/opt/cri-docker-file# kubectl apply -f redis-service.yaml 
pod/redis-pod created
service/redis-service created
#查看pod创建情况,容器正在创建
root@master01:/opt/cri-docker-file# kubectl get pods -n default
NAME        READY   STATUS              RESTARTS   AGE
redis-pod   0/1     ContainerCreating   0          13s
#查看所有service信息
root@master01:/opt/cri-docker-file# kubectl get services
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.1.0.1       <none>        443/TCP          15d
redis-service   NodePort    10.1.241.126   <none>        6379:30079/TCP   56s
#根据label名称查看其中存在的service
root@master01:/opt/cri-docker-file# kubectl get service -l app=redis
NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
redis-service   NodePort   10.1.241.126   <none>        6379:30079/TCP   3m7s
#查看指定service的具体信息
root@master01:/opt/cri-docker-file# kubectl describe svc redis-service
Name:                     redis-service
Namespace:                default
Labels:                   app=redis
Annotations:              <none>
Selector:                 app=redis
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.1.241.126
IPs:                      10.1.241.126
Port:                     <unset>  6379/TCP
TargetPort:               redis-pod/TCP
NodePort:                 <unset>  30079/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
#重新查看pod的运行情况,已经正常。
root@master01:/opt/cri-docker-file# kubectl get pods -n default
NAME        READY   STATUS    RESTARTS   AGE
redis-pod   1/1     Running   0          2m25s

此时就可以在内外部访问redis服务了:

#内部访问
root@master01:/opt/cri-docker-file# kubectl exec -it redis-pod -- /bin/bash
root@redis-pod:/data# redis-cli
127.0.0.1:6379> ping
PONG

外部访问连接也OK:

最后如果不需要使用该服务了,就可以进行删除操作:

root@master01:/opt/cri-docker-file# kubectl delete service redis-service
service "redis-service" deleted

如果涉及配置更新操作,基本与pod相似,需要修改yaml配置文件后重新应用。

四、总结

笔者看来,其实这块组要还是理解pod与service之间的关系比较重要,包括创建Kubernetes服务的过程,应用起来其实相对简单。Kubernetes Service 的核心价值一直都在于其简化了网络配置和管理,提供了强大的服务发现、负载均衡和故障恢复机制,使得开发者能够更加高效地构建和运维云原生应用。随着 Kubernetes 的不断发展和完善,相信Service 将继续在云原生领域发挥其重要作用,推动应用架构和运维模式的持续创新~

如有分析不对的地方欢迎指正~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2097046.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Google Gemini 使用 | 中小型企业借助谷歌 Gemini 提高生产力的 5 种方法

Gemini Business for Workspace 融合了谷歌最强 AI 技术&#xff0c;并集成到办公产品组件中的解决方案。 无论是中型的家族企业&#xff0c;还是刚起步的小型创业团队&#xff0c;你们是否觉得一天 24 小时根本不够用&#xff1f;既要忙着客户维系和拉新&#xff0c;又要管理员…

pda移动护理终端医用手持机

随着物联网技术的发展&#xff0c;智能设备之间形成了紧密的网络互联。 医疗行业越来越注重智能设备的使用&#xff0c;医用手持机可以采集病人、药品、材料等信息&#xff0c;很大程度地改善了医院患者的管理&#xff0c;进一步提升医护人员的工作效率。 医护人员通过使用pda移…

【开学季】告别一次性AI写作工具,打造你自己的专属AI助手!

新学期的钟声敲响&#xff0c;校园里充满了书本的香气和求知的热情。&#x1f4da;可许多学生和职场人士&#xff0c;仍然依赖那些一次性的AI写作工具来完成自己的写作任务。我想问你&#xff1a;为什么不尝试自己构建一个属于自己的AI写作工作流呢&#xff1f;&#x1f914; 前…

机器学习:自然语言处理之关键词提取(TF-IDF)

目录 前言 一、TF-IDF 1.TF 2.IDF 3.TF-IDF计算法则 4.TF-IDF的本质 二、代码实现 1.导入库 2.读取文本数据 3. 初始化TfidfVectorizer并转换文本数据 4. 获取词汇表并创建 DataFrame 5.处理每篇文章的特征 总结 前言 TF-IDF&#xff08;Term Frequency-Inverse D…

MySql字段有null值与其他值的比较

MySql字段有null值与其他值的比较 SELECT count(1)在这里插入代码片FROM LAW_ENFORCEMENT_TROUBLE TBWHERE TB.STATUS 1AND TB.DUTY_LIMIT_DATE < NOW()AND TB.TROUBLE_STATUS ! 2查出结果为0条&#xff0c;但是应该为3条&#xff0c;查看表数据发现&#xff0c;TROUBLE_S…

常见图像图片属性的介绍与说明

图像属性是指图像的一些基本特征和参数&#xff0c;它们定义了图像的外观和存储方式。以下是一些常见的图像属性&#xff1a; 1. 分辨率&#xff1a; 分辨率通常以像素数&#xff08;如800x600&#xff09;来表示&#xff0c;指的是图像的宽度和高度上的像素点数。分辨率越高&…

mysql5.7 TIMESTAMP NOT NULL DEFAULT ‘0000-00-00 00:00:00‘ 换版8版本 引发的问题

mysql5.7 TIMESTAMP NOT NULL DEFAULT 0000-00-00 00:00:00 换版引发的问题 问题背景sql_mode上机演示5.78.4 问题背景 在项目mysql版本由5.7 换版到8.4版本后&#xff0c;我们进行回归测试时&#xff0c;却发现一个积年代码报错了&#xff0c;是数据库插入报的错 xxx can not…

自用Office 365家庭版全家桶 + OneDrive 1TB拼车,40/年,来长期拼的!

自用Office 365家庭版全家桶 OneDrive 1TB拼车&#xff0c;40/年&#xff0c;来长期拼的! &#x1f50d;1.背景描述&#x1f50d;&#x1f421;2. 常见问题解答&#x1f421;【问】是正版吗&#xff1f;【问】跟普通版本有什么区别&#xff1f;【问】会不会是假货? &#x1f…

1、Java简介+DOS命令+java的编译运行(字节码/机器码、JRE/JVM/JDK/JIT的区别)+一个简单的Java程序

前言&#xff1a;本文属于黑马程序员和javaguide的混合笔记&#xff0c;仅作学习分享使用&#xff0c;建议感兴趣的小伙伴去看黑马原视频或javaguide原文。如有侵权&#xff0c;请联系删除。 Java类型&#xff1a; JavaSE 标准版&#xff1a;以前称为J2SE&#xff0c;主要用来…

掌握一招:‌输入什么命令,‌轻松查看电脑IP地址?‌

在日常使用电脑的过程中&#xff0c;‌无论是进行网络设置、‌远程连接还是解决网络问题&#xff0c;‌了解并查看自己的电脑IP地址都是一项基础且重要的操作。‌对于许多用户来说&#xff0c;‌可能并不清楚如何快速准确地获取这一信息。‌本文将为你揭秘一个简单实用的命令&a…

【数据结构与算法】:十大经典排序算法

文章目录 前言一、冒泡排序&#xff08;Bubble Sort&#xff09;1.1 冒泡排序原理1.2 冒泡排序代码1.3 输出结果 二、选择排序&#xff08;Selection Sort&#xff09;2.1 选择排序原理2.2 选择排序代码2.3 输出结果 三、插入排序&#xff08;Insertion Sort&#xff09;3.1 插…

可重入VI,VI模板和动态VI之间的差异 转

可重入VI 当您想要同时运行同一VI的多个实例时&#xff0c;将使用可重入VI。当VI不可重入时&#xff0c;VI只有一个数据空间。因此&#xff0c;一次只能有一个调用者运行VI&#xff0c;因此调用者可能必须“等待轮到它”时才能使用VI。这是VI的默认选项&#xff0c;但您可以将V…

精通大模型:八本必读书籍,一篇搞定所有知识点!

如果你想深入了解大模型领域&#xff0c;无论是为了学术研究还是实际应用&#xff0c;选择合适的书籍是非常重要的。以下是精选的八本大模型相关书籍&#xff0c;涵盖了从基础理论到高级实践的内容&#xff0c;可以帮助你构建全面的知识体系。 《大模型应用开发极简入门》 简介…

Hadoop之HDFS的原理和常用命令及API(java)

1、简介 书接上回&#xff0c;上篇博文中介绍如何安装Hadoop和基本配置&#xff0c;本文介绍Hadoop中分布式文件组件--HDFS&#xff0c;在HDFS中&#xff0c;有namenode、datanode、secondnamenode这三个角色&#xff0c;本文将详细介绍这几个组件是如何进行协作的&#xff0c;…

PHP一键预约便捷高效咨询小程序系统源码

一键预约&#xff0c;开启便捷高效咨询新时代 —— 你的专属咨询小程序 &#x1f680; 【开篇&#xff1a;告别繁琐&#xff0c;拥抱便捷新体验】 在这个快节奏的时代&#xff0c;时间就是金钱&#xff0c;效率就是生命。你还在为寻找咨询服务而四处奔波&#xff0c;或是为了预…

社区团购小程序系统源码+界面diy+分销+团长+供应商+拼团+菜谱+秒杀+预售+配送,开启社区营销新模式

社区团购小程序类似美团优选,兴盛优选平台.是一款针对小区居民开发的在线购物平台&#xff0c;旨在为用户提供便捷、实惠的购物体验&#xff1b;同时还提供了“限时抢购”和“优惠券营销”等多种实惠的购物体验&#xff0c;是小区居民们的不二之选。 一、 特点与优势 社区化运…

SprinBoot+Vue健康管管理微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…

k8s - Volume 简介和HostPath的使用

K8S 的持久化 K8S 实现持久化存储的方法有很多种 例如 卷 (Volume), 持久卷(PV), 临时卷(EV) 等&#xff0c; 还有很多不常用的选项上图没有列出来 其中Volume 本身也分很多种 包括 Secret, configMap(之前的文章covered了)&#xff0c; hostPath, emptyDir等 本文主要focus…

[工具使用]ellisys

工具打开&#xff1a; 1.连接ellisys电源&#xff0c;ellisys Computer接口USB连接电脑&#xff0c;Logic接口与板子出信号的GPIO口连接 工具配置 1.点击"Configure" 2.在打开的Recording options中选择Wireless选项卡 2.选择Wired选项卡​ i.勾选Logic transit…

十五、多线程(基础)

文章目录 一、线程介绍1.1 程序1.2 进程1.3 线程 二、线程使用2.1 创建线程的两种方式2.2 继承Thread类创建线程2.3 实现Runnable接口创建线程2.4 多线程执行2.5 继承Thread vs 实现 Runnable的区别2.6 线程终止 三、线程方法3.1 常用方法3.2 用户线程和守护线程 四、线程生命周…