k8s中的微服务

什么是微服务

用控制器来完成集群的工作负载,应用则需要通过微服务暴露出去才能被访问

  • Service是一组提供相同服务的Pod对外开放的接口。

  • 借助Service,应用可以实现服务发现和负载均衡。

  • service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)

微服务的类型

微服务类型 作用描述
ClusterIP 默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问
NodePort 将Service通过指定的Node上的端口暴露给外部,访问任意一个NodeIP:nodePort都将路由到ClusterIP
LoadBalancer 在NodePort的基础上,借助cloud provider创建一个外部的负载均衡器,并将请求转发到 NodeIP:NodePort,此模式只能在云服务器上使用
ExternalName 将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定

ipvs模式

  • Service 是由 kube-proxy 组件,加上 iptables 来共同实现的

  • kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源

  • IPVS模式的service,可以使K8s集群支持更多量级的Pod

clusterip

特点:

clusterip模式只能在集群内访问,并对集群内的pod提供健康检测和自动发现功能

示例:

bash 复制代码
 [root@master service]# kubectl create deployment lpy --image myapp:v1 --replicas 2 --dry-run=client -o yaml > lpy.yaml
 [root@master service]# 
 [root@master service]# kubectl apply -f lpy.yaml 
 [root@master service]# kubectl expose deployment lpy --port 80 --target-port 80 --dry-run=client -o yaml >> lpy.yaml
 [root@master service]# vim lpy.yaml
 deployment.apps/lpy created
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   labels:
     app: lpy
   name: lpy
 spec:
   replicas: 2
   selector:
     matchLabels:
       app: lpy
   template:
     metadata:
       creationTimestamp: null
       labels:
         app: lpy
     spec:
       containers:
       - image: myapp:v1
         name: myapp
 ---
 apiVersion: v1
 kind: Service
 metadata:
   creationTimestamp: null
   labels:
     app: lpy
   name: lpy
 spec:
   ports:
   - port: 80
     protocol: TCP
     targetPort: 80
 [root@master service]# kubectl get service
 NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
 kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   9d
 lpy          ClusterIP   10.101.112.198   <none>        80/TCP    30m
 [root@master service]# curl 10.101.112.198
 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

ClusterIP中的特殊模式headless

headless(无头服务)

对于无头Services并不会分配 Cluster IP,kube-proxy不会处理它们, 而且平台也不会为它们进行负载均衡和路由,集群访问通过dns解析直接指向到业务pod上的IP,所有的调度有dns单独完成

bash 复制代码
[root@master service]# vim lpy.yaml
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   labels:
     app: lpy
   name: lpy
 spec:
   replicas: 2
   selector:
     matchLabels:
       app: lpy
   template:
     metadata:
       creationTimestamp: null
       labels:
         app: lpy
     spec:
       containers:
       - image: myapp:v1
         name: myapp
 ---
 apiVersion: v1
 kind: Service
 metadata:
   labels:
     app: lpy
   name: lpy
 spec:
   ports:
   - port: 80
     protocol: TCP
     targetPort: 80
   selector:
     app: lpy
   type: ClusterIP
   clusterIP: None 
 [root@master service]# kubectl apply -f lpy.yaml 
 deployment.apps/lpy created
 service/lpy created
 [root@master service]# kubectl get service
 NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
 kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   9d
 lpy          ClusterIP   None         <none>        80/TCP    4s
 [root@master service]# dig  lpy.default.svc.cluster.local @10.96.0.10
 ​
 / # nslookup lpy
 Server:    10.96.0.10
 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
 ​
 Name:      lpy
 Address 1: 10.244.166.149 10-244-166-149.lpy.default.svc.cluster.local
 Address 2: 10.244.104.16 10-244-104-16.lpy.default.svc.cluster.local
 / # curl lpy
 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

nodeport

NodePort 是 Kubernetes 中用于将集群内 Pod 服务暴露到集群外部的核心服务类型之一,通过在集群节点(通常是 Worker 节点)上分配固定端口,让外部设备可通过 "节点 IP + 固定端口" 访问集群内业务。

它的核心价值是在不依赖外部负载均衡器的情况下,快速实现服务的外部访问,是测试环境和小规模场景中暴露服务的常用方案。

核心工作机制

NodePort 服务的流量转发流程可拆解为 4 个关键步骤:

  1. 端口分配 :创建服务时,K8s 从默认端口范围(30000-32767)分配一个固定端口(即 NodePort),也可手动指定该端口(需确保在范围内且未被占用)。

  2. 节点监听 :集群内所有符合条件的节点(默认所有节点,可通过 nodeSelector 限制)会在该 NodePort 上监听外部请求。

  3. 流量转发:外部请求访问 "任意节点 IP:NodePort" 时,节点通过 iptables 或 IPVS(K8s 支持的两种转发模式)将流量转发到服务关联的 Endpoints(即匹配的 Pod 集合)。

  4. Pod 响应:Pod 处理请求后,通过原路径将响应返回给外部客户端。

bash 复制代码
[root@master service]# vim lpy.yaml
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   labels:
     app: lpy
   name: lpy
 spec:
   replicas: 2
   selector:
     matchLabels:
       app: lpy
   template:
     metadata:
       creationTimestamp: null
       labels:
         app: lpy
     spec:
       containers:
       - image: myapp:v1
         name: myapp
 ---
 apiVersion: v1
 kind: Service
 metadata:
   labels:
     app: lpy
   name: lpy
 spec:
   ports:
   - port: 80
     protocol: TCP
     targetPort: 80
   selector:
     app: lpy
   type: NodePort
 [root@master service]# kubectl apply -f lpy.yaml 
 deployment.apps/lpy created
 service/lpy created
 [root@master service]# kubectl get service
 NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
 kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        9d
 lpy          NodePort    10.111.213.134   <none>        80:30929/TCP   3s
 [root@master service]# for i in {1..5}
 > do
 > curl 192.168.188.141:30929/hostname.html
 > done
 lpy-764f578b9d-x5kcl
 lpy-764f578b9d-n86k5
 lpy-764f578b9d-x5kcl
 lpy-764f578b9d-x5kcl
 lpy-764f578b9d-n86k5

loadbalancer

LoadBalancer 是 Kubernetes 中用于将集群内服务暴露到公网或外部网络的高级服务类型,核心作用是自动关联云厂商(如 AWS、阿里云、腾讯云)的负载均衡器,为外部请求提供统一入口和流量分发能力,解决 NodePort 服务缺乏内置负载均衡的痛点。

MetalLB 是裸金属 Kubernetes 集群中最主流的 LoadBalancer 服务实现工具,它通过 "地址分配 + 流量转发" 两大核心能力,模拟云厂商 LoadBalancer 的功能,无需依赖专用硬件负载均衡器。

MetalLB 的工作原理

MetalLB 由两个核心组件构成,协同完成 LoadBalancer 服务的实现:

  • 控制器(Controller) :运行在集群内部的 Deployment,负责监听 Kubernetes 中的 LoadBalancer 类型 Service。当服务创建时,从预设的 IP 地址池(可是公网 IP 或内网 IP)中分配一个固定 IP(即 Service 的 EXTERNAL-IP),并关联到 Service 对应的 Endpoints(Pod 集合)。

  • 扬声器(Speaker)

    :以 DaemonSet 形式运行在集群所有节点上,负责将分配的 IP 地址和流量转发规则同步到节点网络层。支持两种转发模式:

    • Layer 2 模式:通过 ARP/NDP 协议(适用于 IPv4/IPv6)将分配的 IP 与某个节点的 MAC 地址绑定,外部流量先到达该节点,再由节点转发到 Pod。优点是配置简单、无额外硬件依赖;缺点是单节点流量瓶颈(所有流量先经过绑定节点)。

    • BGP 模式:通过 BGP 协议与集群外部的路由器通信,将 Service 的 IP 地址和 Pod 路由信息同步到路由器,由路由器直接将流量分发到不同节点的 Pod。优点是流量可跨节点负载均衡、无单点瓶颈;缺点是依赖支持 BGP 协议的路由器,配置复杂。

metalLB部署方式

官网:https://metallb.universe.tf/installation/

bash 复制代码
[root@master service]# kubectl edit cm -n kube-system kube-proxy
 apiVersion: kubeproxy.config.k8s.io/v1alpha1
 kind: KubeProxyConfiguration
 mode: "ipvs"
 ipvs:
   strictARP: true
 [root@master service]# kubectl -n kube-system get  pods   | awk '/kube-proxy/{system("kubectl -n kube-system delete pods "$1)}'
 [root@master service]# wget https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
 #上传镜像到harbor
 [root@master ~]# docker pull quay.io/metallb/controller:v0.14.8
 [root@master ~]# docker pull quay.io/metallb/speaker:v0.14.8
 [root@master ~]# docker tag quay.io/metallb/speaker:v0.14.8 reg.timinglee.org/metallb/speaker:v0.14.8
 [root@master ~]# docker tag quay.io/metallb/controller:v0.14.8 reg.timinglee.org/metallb/controller:v0.14.8
 [root@master ~]# docker push reg.timinglee.org/metallb/speaker:v0.14.8
 [root@master ~]# docker push reg.timinglee.org/metallb/controller:v0.14.8
 [root@master service]# kubectl apply -f metallb-native.yaml 
 namespace/metallb-system created
 customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
 ... ...
 [root@master service]# kubectl -n metallb-system get pods
 NAME                          READY   STATUS    RESTARTS   AGE
 controller-65957f77c8-fpnb4   1/1     Running   0          37s
 speaker-hf6bp                 1/1     Running   0          37s
 speaker-npvqg                 1/1     Running   0          37s
 speaker-rzqh9                 1/1     Running   0          37s
 #配置分配地址段
 [root@master service]# vim configmap.yml
 apiVersion: metallb.io/v1beta1
 kind: IPAddressPool
 metadata:
   name: first-pool
   namespace: metallb-system
 spec:
   addresses:
   - 192.168.188.50-192.168.188.99
 ---
 apiVersion: metallb.io/v1beta1
 kind: L2Advertisement
 metadata:
   name: example
   namespace: metallb-system
 spec:
   ipAddressPools:
   - first-pool
 [root@master service]# kubectl apply -f configmap.yml 
 ipaddresspool.metallb.io/first-pool created
 l2advertisement.metallb.io/example created
 [root@master service]# kubectl get services
 NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
 kubernetes   ClusterIP      10.96.0.1       <none>           443/TCP        9d
 lpy          LoadBalancer   10.99.121.116   192.168.188.50   80:31841/TCP   11m
 [root@master service]# curl 192.168.188.50
 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

externalname

  • 开启services后,不会被分配IP,而是用dns解析CNAME固定域名来解决ip变化问题

  • 一般应用于外部业务和pod沟通或外部业务迁移到pod内时

  • 在应用向集群迁移过程中,externalname在过度阶段就可以起作用了。

  • 集群外的资源迁移到集群时,在迁移的过程中ip可能会变化,但是域名+dns解析能完美解决此问题

bash 复制代码
[root@master service]# kubectl apply -f lpy.yaml 
 deployment.apps/lpy created
 service/lpy created
 [root@master service]# kubectl get services
 NAME         TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
 kubernetes   ClusterIP      10.96.0.1    <none>        443/TCP   9d
 lpy          ExternalName   <none>       www.baidu.com   80/TCP    3s
 [root@master service]# kubectl run -it test --image busyboxplus
 If you don't see a command prompt, try pressing enter.
 / # ping lpy
 PING lpy (36.152.44.132): 56 data bytes
 64 bytes from 36.152.44.132: seq=0 ttl=127 time=27.734 ms
 64 bytes from 36.152.44.132: seq=1 ttl=127 time=28.111 ms
 64 bytes from 36.152.44.132: seq=2 ttl=127 time=29.866 ms
 64 bytes from 36.152.44.132: seq=3 ttl=127 time=66.722 ms
 64 bytes from 36.152.44.132: seq=4 ttl=127 time=45.082 ms
 / # nslookup lpy
 Server:    10.96.0.10
 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
 Name:      lpy
 Address 1: 36.152.44.132
 Address 2: 36.152.44.93
 Address 3: 2409:8c20:6:123c:0:ff:b0f6:b2d
 Address 4: 2409:8c20:6:1794:0:ff:b080:87f0
 --- lpy ping statistics ---
 5 packets transmitted, 5 packets received, 0% packet loss
 round-trip min/avg/max = 27.734/39.503/66.722 ms
 [root@node1 ~]# ping www.baidu.com
 PING www.a.shifen.com (36.152.44.93) 56(84) 比特的数据。
 64 比特,来自 36.152.44.93 (36.152.44.93): icmp_seq=1 ttl=128 时间=29.6 毫秒
 64 比特,来自 36.152.44.93 (36.152.44.93): icmp_seq=2 ttl=128 时间=29.3 毫秒
 64 比特,来自 36.152.44.93 (36.152.44.93): icmp_seq=3 ttl=128 时间=32.8 毫秒

Ingress-nginx

官网:

https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters

ingress-nginx简介

Ingress-Nginx 是 Kubernetes 中最主流的 Ingress 控制器实现,核心作用是作为集群的 "流量入口网关",通过统一的域名和路径规则,将外部 HTTP/HTTPS 流量路由到集群内不同的 Service,解决了 NodePort/LoadBalancer 服务需暴露多个端口或 IP 的痛点,是生产环境中管理 HTTP 流量的标准方案。

它基于 Nginx 反向代理实现,将 Kubernetes 的 Ingress 资源定义的路由规则转换为 Nginx 配置,从而实现流量转发、SSL 卸载、路径重写等高级 HTTP 流量管理功能。

  • 一种全局的、为了代理不同后端 Service 而设置的负载均衡服务,支持7层

  • Ingress由两部分组成:Ingress controller和Ingress服务

  • Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。

  • 业界常用的各种反向代理项目,比如 Nginx、HAProxy、Envoy、Traefik 等,都已经为Kubernetes 专门维护了对应的 Ingress Controller。

部署ingress

下载部署文件
bash 复制代码
[root@master ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.2/deploy/static/provider/baremetal/deploy.yaml
打标签上传harbor
bash 复制代码
 [root@master ~]# docker tag registry.k8s.io/ingress-nginx/controller:v1.11.2@sha256:d5f8217feeac4887cb1ed21f27c2674e58be06bd8f5184cacea2a69abaf78dce reg.timinglee.org/ingress-nginx/controller:v1.11.2
 [root@master ~]# docker tag registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.3@sha256:a320a50cc91bd15fd2d6fa6de58bd98c1bd64b9a6f926ce23a600d87043455a3 reg.timinglee.org/ingress-nginx/kube-webhook-certgen:v1.4.3
 [root@master ~]# docker push reg.timinglee.org/ingress-nginx/controller:v1.11.2
 [root@k8s-master ~]# docker push reg.timinglee.org/ingress-nginx/kube-webhook-certgen:v1.4.3
安装ingress
bash 复制代码
#更改镜像位置为harbor仓库位置
 [root@master ~]# vim deploy.yaml
 445         image: ingress-nginx/controller:v1.11.2
 546         image: ingress-nginx/kube-webhook-certgen:v1.4.3
 599         image: ingress-nginx/kube-webhook-certgen:v1.4.3
 [root@master service]# kubectl apply -f deploy.yaml 
 namespace/ingress-nginx created
 serviceaccount/ingress-nginx created
 serviceaccount/ingress-nginx-admission created
 [root@master service]# kubectl -n ingress-nginx get pods
 NAME                                       READY   STATUS    RESTARTS   AGE
 ingress-nginx-controller-b6cbfc9f4-55l9t   1/1     Running   0          59s
 [root@master service]# kubectl -n ingress-nginx get svc
 NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
 ingress-nginx-controller             NodePort    10.98.66.114    <none>        80:31150/TCP,443:32685/TCP   61s
 ingress-nginx-controller-admission   ClusterIP   10.111.141.26   <none>        443/TCP                      61s
 #修改微服务为loadbalancer
 [root@master service]# kubectl -n ingress-nginx edit svc ingress-nginx-controller
 service/ingress-nginx-controller edited
 49   type: LoadBalancer
 [root@master service]# kubectl -n ingress-nginx get svc
 NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
 ingress-nginx-controller             LoadBalancer   10.98.66.114    192.168.188.50   80:31150/TCP,443:32685/TCP   3m20s
 ingress-nginx-controller-admission   ClusterIP      10.111.141.26   <none>           443/TCP                      3m20s
测试ingress
bash 复制代码
 [root@master service]# vim lpy-ingress.yml
 apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata:
   name: test-ingress
 spec:
   ingressClassName: nginx
   rules:
   - http:
       paths:
       - backend:
           service:
             name: lpy-svc
             port:
               number: 80
         path: /
         pathType: Prefix
 [root@master service]# kubectl apply -f lpy-ingress.yml
 [root@master service]# kubectl get ingress
 NAME           CLASS   HOSTS   ADDRESS           PORTS   AGE
 test-ingress   nginx   *       192.168.188.142   80      3m7s

小结

本文介绍了Kubernetes中微服务的几种类型及其特点。主要包括:

  1. ClusterIP:默认类型,仅集群内部访问
  2. NodePort:通过节点端口暴露服务
  3. LoadBalancer:借助云服务商实现负载均衡
  4. ExternalName:通过DNS解析到指定域名
  5. Headless Service:无ClusterIP,直接解析到Pod
  6. Ingress:提供7层HTTP流量管理

详细说明了各类服务的配置方法、工作流程及适用场景,包括使用MetalLB实现裸金属集群的LoadBalancer功能,以及Ingress-Nginx作为HTTP流量网关的部署过程。通过实际YAML示例演示了各类服务的创建和测试方法。

相关推荐
程序员老赵5 小时前
Docker 部署银河麒麟(Kylin Linux)全流程教程
运维·docker
zz-zjx5 小时前
Docker自动化部署与配置详解③
运维·docker·容器
ByteBeacon6 小时前
Argo Workflows:Kubernetes上的工作流引擎
其他·云原生·容器·kubernetes
java_logo6 小时前
Docker 部署 CentOS 全流程指南
linux·运维·人工智能·docker·容器·centos
DarkAthena8 小时前
【Docker】定制化构建一个可以运行GaussDB的kylinv10sp3系统的docker镜像
数据库·docker·容器·gaussdb
daxiang120922058 小时前
k8s高频面试题汇总
云原生·容器·kubernetes
lang201509288 小时前
Spring Boot与K8s集成的核心机制
spring boot·后端·kubernetes
RationalDysaniaer9 小时前
k8s配置与存储
云原生·容器·kubernetes