云原生技术与应用-Kubernetes服务发布基础

目录

一.service定义

二.K8s 服务发布的核心组件

1. Pod:服务的基本运行单元

2. Service:稳定访问 Pod 的抽象层

3. Deployment:管理 Pod 的部署与更新

三.service的工作原理

四.service的负载均衡机制

1.userspace模式

2.iptables模式

3.ipvs模式

service的四种类型

五.测试service的四种类型

1.ClusterIP

2.NodePort

3.LoadBalancer

4.ExternalName

一.service定义
    service 是 kubernetes 中的一种抽象,用于定义一组 pod 以及访问这一组 pod 的策略、service的作用是将一组 pod 封装为一个虚拟的服务,并提供一个统一的入口,供客户端访问。service 支持负载均衡、服务发现、服务暴露等功能。
    Service 用于为一组提供服务的 Pod 抽象一个稳定的网络访问地址,是 k8s 实现微服务的核心概念。通过 service 的定义设置的访问地址是 DNS 域名格式的服务名称,对于客户端应用来说,网络访问方式并没有改变。Service 还提供了负载均衡器的功能,将客户端请求负载分发到后端提供具体服务的各个Pod 上。Service 主要用于提供网络服务,通过 Service 的定义,能够为客户端应用提供稳定的访问地址(域名或 IP 地址)和负载均衡功能,以及屏蔽后端 EndPoint 的变化,是Kubernetes 实现微服务的核心资源。
    总之,service 是 kubernetes 中一个非常重要的概念,service 用于将外部请求代理到内部 pod上,提供4层负载均衡和服务发现的功能,使得我们可以构建高可用和可扩展的应用程序。

二.K8s 服务发布的核心组件
1. Pod:服务的基本运行单元
    定义:Pod 是 K8s 中最小的部署单元,包含一个或多个紧密关联的容器(通常为一个主容器 + 辅助容器)。
特点:
共享网络命名空间和存储卷,容器间可通过localhost通信。
生命周期短暂,可能因节点故障、扩缩容等原因被重新创建,IP 地址会变化。
2. Service:稳定访问 Pod 的抽象层
  定义:Service 通过标签选择器(Label Selector)将一组功能相同的 Pod 聚合,为其提供固定 IP 和域名,解决 Pod 动态变化的访问问题。
类型:
ClusterIP(默认):仅在集群内部可访问,分配集群内 IP。
NodePort:在每个节点上开放一个端口,通过节点IP:端口从集群外部访问。
LoadBalancer:借助云服务商(如 AWS、阿里云)的负载均衡器,自动创建外部负载均衡器。
ExternalName:将服务映射到 DNS 名称,不创建代理,用于集成外部服务。
3. Deployment:管理 Pod 的部署与更新
   功能:定义 Pod 的副本数、镜像版本、标签等参数。
   支持滚动更新(Rolling Update)、回滚(Rollback)等部署策略,确保服务更新时的可用性。
三.service的工作原理
   在 kubernetes 中,pod的 IP地址是动态变化的,因此无法直接通过pod的IP地址进行访问。service的出现正式为了解决找个问题的。service 会为一组 pod 创建一个虚拟的 IP 地址,通过这个 IP 地址可以访问这组 pod 中的任意一个 pod。当客户端请求这个虚拟 IP 地址时,请求会被负载均衡到一组 pod 中的某一个 pod 上,从而完成对 pod 的访问。service 的实现依赖于 kube-proxy 组件。kube-proxy 会在每个节点上监听 service 的变化,一日有 service 发生变化,kube-proxy 会更新本地的 iptables 规则,从而实现流量的转发和负载均衡。另外,service 还与 CoreDNS 有关。                  CoreDNS 是 kubernetes 集群中的 DNS 解析服务。在 kubernetes中 service 的虚拟 IP 地址还会注册到 CoreDNS 中,从而使得客户端还可以通过 service 名称访问service 的虚拟 IP 地址。在 service 的定义中,可以通过 spec.selector 字段指定哪些 pod 属于这个service,这样,就可以将请求负载均衡到这些 pod 中。

四.service的负载均衡机制
    当一个 Service 对象在 Kubernetes 集群中被定义出来时,集群内的客户端应用就可以通过服务 IP访问到具体的 Pod 容器提供的服务了。从服务 IP 到后端 Pod 的负载均衡机制,则是由每个 node 上的kube-proxy 代理来负责实现的。
     kubeproxy 的代理模式有:userspace、iptables、ipvs 

1.userspace模式
     起初,kube-proxy进程是一个真实的TCP/UDP代理,当某个pod以clusterIp方式访问某个service的时候,这个流量会被 pod 所在的本机的 iptables 转发到本机的 kube-proxy 进程,然后将请求转发到后端某个 pod 上。具体过程为:

kube-proxy 为每个 service 在 node 上打开一个随机端口作为代理端口
建立 iptables 规则,将 custerip 的请求重定向到代理端口(用户空间)
到达代理端口的请求再由 kubeproxy 转发到后端
clusterip 重定向到 kube-proxy 服务的过程存在内核态到用户态的切换,开销很大,因此有了iptables 模式,而 userspace 模式也被废弃了。

2.iptables模式
      这种模式下kube-proxy不再起到proxy的作用。其核心功能:通过 API Server 的 Watch 接口实时跟踪 Service 和 Endpoint 的变更信息,并更新对应的 iptables 规则,Client 的请求流量通过 iptables 的 NAT 机制“直接路由”到目标 Pod。
    不同于 userspace,在 iptables 的模式中,kube-proxy不再负责转发数据包,kube-proxy 主要完成对 iptables 策略的动态管理。数据包的走向完全由 iptables 规则决定,这样的过程不存在内核态到用户态的切换,效率明显会高很多。但是随着 service 的增加,iptables 规则会不断增加,导致内核十分繁忙(等于在读一张很大的没建索引的表)。

3.ipvs模式
   它也是基于 netfilter 实现的,但定位不同:iptables 是为防火墙设计的,IPVS 则专门用于高性能负载均衡,并使用高效的数据结构 Hash 表,允许几乎无限的规模扩张。
ipvs 为负载均衡提供了更多的算法:

rr:轮询
1c:最小连接数
df:目标哈希
sh:源哈希
sed:预计延迟最短
nq:从不排队
    ipvs 使用 ipset 存储 iptables 规则,在査找时类似 hash 表査找,时间复杂度为 0(1),而 iptables 时间复杂度则为 0(n)。时间复杂度用字母 0表示。可以将 ipset 简单理解为 ip 集合,这个集合的内容可以是 IP 地址、IP 网段、端口等,iptabels可以直接添加规则对这个可变集合进行操作,这样做的好处可以大大减少 iptables 规则的数量,从而减少性能损耗。
 

service的四种类型
  ClusterIP(默认类型):这种类型的 Service 仅在 Kubernetes 集群内部可访问,Kubernetes 会为其分配一个集群内部的 IP 地址。当应用程序只需要在集群内部进行通信时,ClusterIP 类型的 Service 是一个合适的选择,例如,微服务架构中各个服务之间的内部调用 。​
  NodePort:NodePort 类型的 Service 会在集群中的每个节点上开放一个特定的端口(端口范围通常为 30000 - 32767)。通过访问节点IP:端口的方式,外部客户端可以从集群外部访问到 Service,进而访问到后端的 Pod 服务。这种方式适用于没有云服务商负载均衡器支持,或者需要快速在本地环境中暴露服务的场景 。​
   LoadBalancer:借助云服务商(如 AWS、阿里云、腾讯云等)提供的负载均衡器服务,LoadBalancer 类型的 Service 会自动创建一个外部负载均衡器。该负载均衡器将外部流量转发到 Service,再由 Service 分发到后端的 Pod。这种类型适用于在生产环境中需要高可用、可扩展的外部服务暴露场景 。​
   ExternalName:ExternalName 类型的 Service 不创建代理,而是将服务映射到一个 DNS 名称。它主要用于集成外部服务,例如,将 Kubernetes 集群内的服务与外部已有的数据库服务进行关联,通过 DNS 名称实现透明访问 。
五.测试service的四种类型
1.ClusterIP
      在 Kubernetes 中,ClusterIP是 Service 的默认类型,它会为服务分配一个集群内部的虚拟 IP(ClusterIP),使得 Pod 之间可以通过该 IP 进行通信。

编写一个clusterip示例

apiVersion: v1
kind: Service
metadata:
  name: my-service       # 服务名称
  namespace: default     # 命名空间(可选)
  labels:
    app: my-app          # 服务标签
spec:
  type: ClusterIP        # 指定为ClusterIP类型(默认可省略)
  selector:
    app: my-app          # 匹配Pod的标签
  ports:
    - protocol: TCP      # 协议类型(TCP/UDP)
      port: 80           # 服务暴露的端口(集群内部访问)
      targetPort: 8080   # 后端Pod的端口

创建 Pod 和 Service
# 创建Pod

kubectl apply -f pod.yaml

# 创建Service

kubectl apply -f service.yaml

查看创建的service

kubectl get svc

kubernetes   ClusterIP   10.104.162.209          80/TCP   120d

访问测试

curl 10.104.162.209:80       ##ClusterIP只在内网有效

2.NodePort
在 Kubernetes 中,NodePort是一种 Service 类型,它在每个节点上开放一个固定端口(30000-32767),外部流量可以通过任一节点的 IP 和该端口访问服务。

编写一个NodePort的示例

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
  namespace: default
  labels:
    app: my-app
spec:
  type: NodePort        # 指定为NodePort类型
  selector:
    app: my-app         # 匹配Pod的标签
  ports:
    - protocol: TCP
      port: 80          # 服务内部端口(供集群内部访问)
      targetPort: 8080  # 后端Pod的端口
      nodePort: 30080   # 节点上暴露的端口(可选,默认自动分配30000-32767)
 

创建serivce 

[root@k8s-master ~]# kubectl create -f webapp-svc-nodeport.yaml

查看创建的service

ku get svc

webapp NodePort 10.98.184.252 8080:30008/TCP 119S

验证访问

##使用本机ip加端口进行访问

192.168.10.101:30008

3.LoadBalancer
在 Kubernetes 中,LoadBalancer是一种高级的 Service 类型,它依赖云服务商或负载均衡器插件自动创建外部负载均衡器,并将流量转发到集群内部。

编写一个LoadBalancer的示例

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
  namespace: default
  labels:
    app: my-app
  annotations:
    # 可选:云服务商特定的注解(如AWS、GKE)
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
  type: LoadBalancer       # 指定为LoadBalancer类型
  selector:
    app: my-app            # 匹配Pod的标签
  ports:
    - protocol: TCP
      port: 80             # 服务暴露的端口(负载均衡器端口)
      targetPort: 8080     # 后端Pod的端口
      nodePort: 30080      # 可选:自动分配的NodePort(LoadBalancer依赖NodePort实现)
  externalTrafficPolicy: Cluster  # 可选:Cluster(默认)或Local

创建serivce 

[root@k8s-master ~]# kubectl create -f webapp-svc-nodeport.yaml

查看创建的service

ku get svc

webapp NodePort 10.98.184.252 8080:30146/TCP 119S

##该模式的端口是随机生成的

验证访问

##使用本机ip加端口进行访问

192.168.10.101:30146

4.ExternalName
      在 Kubernetes 中,ExternalName是一种特殊的 Service 类型,它不分配 ClusterIP 或转发流量到集群内部,而是通过 DNS 别名将服务请求重定向到集群外部的域名。目的完成不同命名空间通信。

1.创建test01命名空间所需要的yaml文件

[root@k8s-master opt]# cat myapp01.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp01
  namespace: test01
spec:
  replicas: 1
  selector: #标签选择器
    matchLabels: #匹配的标签为
      app: myapp01
      release: canary
  template:
    metadata:
      labels:
        app: myapp01 #和上面的myapp要匹配
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http01
          containerPort: 80

[root@k8s-master opt]# cat myapp-svc-extername01.yaml 
kind: Service
apiVersion: v1
metadata:
  name: myapp-svcname02
  namespace: test01
spec:
  type: ExternalName
  externalName: myapp-svc02.test02.svc.cluster.local
AI写代码
cs
运行
[root@k8s-master opt]# cat myapp-svc-headless01.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc01
  namespace: test01
spec:
  selector:
    app: myapp01 #挑选的pod还是myapp01。一个pod可以有多个service
    release: canary
  clusterIP: None #None表示是无头service
  ports:
  - port: 39320 #service ip中的端口
    targetPort: 80 #容器ip中的端口

2.创建test02命名空间所需要的yaml文件

[root@k8s-master opt]# cat myapp-svc-headless02.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc02
  namespace: test02
spec:
  selector:
    app: myapp02 #挑选的pod还是myapp。一个pod可以有多个service
    release: canary
  clusterIP: None #None表示是无头service
  ports:
  - port: 39320 #service ip中的端口
    targetPort: 80 #容器ip中的端口

[root@k8s-master opt]# cat myapp-svc-extername02.yaml 
kind: Service
apiVersion: v1
metadata:
  name: myapp-svcname01
  namespace: test02
spec:
  type: ExternalName
  externalName: myapp-svc01.test01.svc.cluster.local

[root@k8s-master opt]# cat myapp02.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp02
  namespace: test02
spec:
  replicas: 1
  selector: #标签选择器
    matchLabels: #匹配的标签为
      app: myapp02
      release: canary
  template:
    metadata:
      labels:
        app: myapp02 #和上面的myapp要匹配
        release: canary
    spec:
      containers:
      - name: myapp02
        image: ikubernetes/myapp:v1
        ports:
        - name: http02
          containerPort: 80

验证

##查看test01容器的ip地址
[root@k8s-master opt]# ku get pods -n test01 -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
myapp01-696c886d6b-bbvrn   1/1     Running   0          30m   10.244.36.80   k8s-node1            
 
 
##登陆到test02命名空间的容器,访问test01容器的ip
[root@k8s-master opt]# ku exec -it myapp02-55ffcd5f64-xmgq8 -n test02 -- sh
/ # ping 10.244.36.80
PING 10.244.36.80 (10.244.36.80): 56 data bytes
64 bytes from 10.244.36.80: seq=0 ttl=63 time=0.059 ms
64 bytes from 10.244.36.80: seq=1 ttl=63 time=0.121 ms
 

你可能感兴趣的:(云原生,kubernetes,容器)