什么是微服务

用控制器来完成集群的工作负载,应用则需要通过微服务暴露出去才能被访问
-
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 个关键步骤:
-
端口分配 :创建服务时,K8s 从默认端口范围(
30000-32767)分配一个固定端口(即 NodePort),也可手动指定该端口(需确保在范围内且未被占用)。 -
节点监听 :集群内所有符合条件的节点(默认所有节点,可通过
nodeSelector限制)会在该 NodePort 上监听外部请求。 -
流量转发:外部请求访问 "任意节点 IP:NodePort" 时,节点通过 iptables 或 IPVS(K8s 支持的两种转发模式)将流量转发到服务关联的 Endpoints(即匹配的 Pod 集合)。
-
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中微服务的几种类型及其特点。主要包括:
- ClusterIP:默认类型,仅集群内部访问
- NodePort:通过节点端口暴露服务
- LoadBalancer:借助云服务商实现负载均衡
- ExternalName:通过DNS解析到指定域名
- Headless Service:无ClusterIP,直接解析到Pod
- Ingress:提供7层HTTP流量管理
详细说明了各类服务的配置方法、工作流程及适用场景,包括使用MetalLB实现裸金属集群的LoadBalancer功能,以及Ingress-Nginx作为HTTP流量网关的部署过程。通过实际YAML示例演示了各类服务的创建和测试方法。