当前位置: 首页 > news >正文

编排之神-Kubernetes中的微服务介绍及演练

7.Kubernetes中的微服务

7.1 什么是微服务

用控制器来完成集群的工作负载,那么应用如何暴漏出去?

需要通过微服务暴漏出去后才能被访问。

  • Service是一组提供相同服务的Pod对外开放的接口。
  • 借助Service,应用可以实现服务发现和负载均衡。
  • service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)

7.2 微服务的类型

微服务类型作用描述
ClusterIP默认值,k8s系统给service自动分配的虚拟IP,只能在集群内部访问
NodePort将Service通过指定的Node上的端口暴露给外部,访问任意一个NodeIP:nodePort都将路由到ClusterIP
LoadBalancer在NodePort的基础上,借助cloud provider创建一个外部的负载均衡器,并将请求转发到 NodeIP:NodePort,此模式只能在云服务器上使用
ExternalName将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定
7.2.1 示例
# 生成控制器文件并建立控制器
[root@k8s-master ~]# kubectl create deployment dhj --image myapp:v1 --replicas 2 --dry-run=client -o yaml > dhj.yml[root@k8s-master ~]# kubectl apply -f dhj.yml
deployment.apps/dhj created# 生成微服务yaml追加到已有yaml中
[root@k8s-master ~]# kubectl expose deployment dhj --port 80 --target-port 80 --dry-run=client -o yaml >> dhj.yml
[root@k8s-master ~]# vim dhj.yml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: dhjname: dhj
spec:replicas: 2selector:matchLabels:app: dhjtemplate:metadata:creationTimestamp: nulllabels:app: dhjspec:containers:- image: myapp:v1name: myapp
---										# 不同资源间用---隔开apiVersion: v1
kind: Service
metadata:labels:app: dhjname: dhj
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: dhj[root@k8s-master ~]# kubectl apply -f dhj.yml
service/dhj created[root@k8s-master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
dhj          ClusterIP   10.97.95.78      <none>        80/TCP    6s
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   2d17h

image-20250813163226251

7.2.2 微服务默认使用iptables调度
[root@k8s-master ~]# kubectl get services  -o wide
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE     SELECTOR
dhj          ClusterIP   10.97.95.78   <none>        80/TCP    112s    app=dhj			# 集群内部ip为78
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP   2d17h   <none># 可以在火墙中查看到策略信息
[root@k8s-master ~]# iptables -t nat -nL
KUBE-SVC-RV2MKWNOHWTUCXGM  tcp  --  0.0.0.0/0            10.97.95.78          /* default/dhj cluster IP */ tcp dpt:80

image-20250813163652648

image-20250813163555931

7.3 ipvs模式

  • Service 是由 kube-proxy 组件,加上 iptables 来共同实现的
  • kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资源
  • IPVS模式的service,可以使K8s集群支持更多量级的Pod
7.3.1 ipvs模式配置方式
7.3.1.1 在所有节点中安装ipvsadm
[root@k8s-master & node1 & node2 ~]# yum install ipvsadm -y
7.3.1.2 修改master节点的代理配置
[root@k8s-master ~]# kubectl -n kube-system edit cm kube-proxymetricsBindAddress: ""mode: "ipvs"							#设置kube-proxy使用ipvs模式nftables:
image-20250813164316335
7.3.1.3 重启pod

在pod运行时配置文件中采用默认配置,当改变配置文件后已经运行的pod状态不会变化,所以要重启pod

# 强制重启Kubernetes集群中kube-system命名空间下的所有kube-proxy Pod
[root@k8s-master ~]# kubectl -n kube-system get  pods   | awk '/kube-proxy/{system("kubectl -n kube-system delete pods "$1)}'[root@k8s-master ~]# ipvsadm -Ln

image-20250813164650310

切换ipvs模式后,kube-proxy会在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配所有service IP

[root@k8s-master ~]# ip a | tail
10: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group defaultlink/ether 1e:1c:4c:d4:f0:86 brd ff:ff:ff:ff:ff:ffinet 10.96.0.10/32 scope global kube-ipvs0valid_lft forever preferred_lft foreverinet 10.97.95.78/32 scope global kube-ipvs0valid_lft forever preferred_lft foreverinet 10.96.0.1/32 scope global kube-ipvs0valid_lft forever preferred_lft forever
image-20250813164822636

7.4 微服务类型详解

7.4.1 clusterip
7.4.1.1 特点

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

7.4.1.2 示例
[root@k8s-master ~]# vim myapp.yml
apiVersion: v1
kind: Service
metadata:labels:app: dhjname: dhj
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: dhjtype: ClusterIP[root@k8s-master ~]# kubectl apply -f myapp.yml[root@k8s-master ~]# kubectl -n kube-system get svc
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   2d18h# service创建后集群DNS提供解析
[root@k8s-master ~]# dig dhj.default.svc.cluster.local @10.96.0.10
image-20250813174827225
7.4.2 ClusterIP中的特殊模式headless

headless(无头服务)

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

[root@k8s-master ~]# vim dhj.yaml
---
apiVersion: v1
kind: Service
metadata:labels:app: dhjname: dhj
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: dhjtype: ClusterIPclusterIP: None[root@k8s-master ~]# kubectl apply -f dhj.yaml# 测试
[root@k8s-master ~]# kubectl get services dhj
NAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE[root@k8s-master ~]# dig  dhj.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.16.23-RH <<>> dhj.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57964
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: aedae9a56ee16284 (echoed)
;; QUESTION SECTION:
;dhj.default.svc.cluster.local. IN      A;; ANSWER SECTION:												# 直接解析到pod上
dhj.default.svc.cluster.local. 30 IN    A       10.244.1.49
dhj.default.svc.cluster.local. 30 IN    A       10.244.2.51;; Query time: 1 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Aug 13 18:01:26 CST 2025
;; MSG SIZE  rcvd: 160
7.4.3 nodeport

通过ipvs暴漏端口从而使外部主机通过master节点的对外ip:来访问pod业务

7.4.3.1 访问过程

7.4.3.2 示例
[root@k8s-master ~]# vim dhj.yaml
apiVersion: v1
kind: Service
metadata:labels:app: dhj-servicename: dhj-service
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: dhjtype: NodePort[root@k8s-master ~]# kubectl apply -f dhj.yaml[root@k8s-master ~]# kubectl get svc dhj
NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
dhj    NodePort   10.107.181.27   <none>        80:31595/TCP   38s# nodeport默认端口是30000-32767,超出会报错[root@k8s-master ~]# kubectl get svc dhj
NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
dhj    NodePort   10.107.181.27   <none>        80:31595/TCP   3m45s[root@k8s-master ~]# curl 10.107.181.27:80						# 内部访问
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master ~]# curl 172.25.254.100:31595					# 外部访问
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
image-20250813184040130
[root@k8s-master ~]# vim dhj.yaml
apiVersion: v1
kind: Service
metadata:labels:app: dhj-servicename: dhj-service
spec:ports:- port: 80protocol: TCPtargetPort: 80nodePort: 33333selector:app: dhjtype: NodePort[root@k8s-master ~]# vim myapp.yml
[root@k8s-master ~]# kubectl apply -f myapp.yml
The Service "dhj" is invalid: spec.ports[0].nodePort: Invalid value: 33333: provided port is not in the valid range. The range of valid ports is 30000-32767

image-20250813184651779

如果需要使用这个范围以外的端口就需要特殊设定

[root@k8s-master ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
- --service-node-port-range=30000-40000
image-20250813185044158

添加“–service-node-port-range=“ 参数,端口范围可以自定义修改后api-server会自动重启;

等apiserver正常启动后才能操作集群,集群重启自动完成在修改完参数后全程不需要人为干预。

[root@k8s-master ~]# kubectl apply -f myapp.yml
service/dhj configured[root@k8s-master ~]# kubectl get svc dhj
NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
dhj    NodePort   10.107.181.27   <none>        80:33333/TCP   19m
image-20250813185617723
7.4.4 loadbalancer

云平台会为我们分配vip并实现访问,如果是裸金属主机那么需要metallb来实现ip的分配

[root@k8s-master ~]# vim dhj.yaml
apiVersion: v1
kind: Service
metadata:labels:app: dhj-servicename: dhj-service
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: dhjtype: LoadBalancer[root@k8s2 service]# kubectl apply -f myapp.yml# 默认无法分配外部访问IP
[root@k8s-master ~]# kubectl get svc			# pending:表示正在获取(但就是获取不到)
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
dhj          LoadBalancer   10.104.182.179   <pending>     80:33333/TCP   8s
kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP        2d20h# 此时curl一下,发现可以访问,但是在实际的生产环境中一般都是直接访问EXTERNAL-IP的,没有人会去记这么一个奇奇怪怪的端口
[root@k8s-master ~]# curl 172.25.254.100:33333
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a># 此时就会需要一个类似于DHCP分发ip的工具--metallb# LoadBalancer模式适用云平台,裸金属环境需要安装metallb提供支持
image-20250813192103612
7.4.5 metalLB

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

metalLB功能为LoadBalancer分配vip;

类似于DHCP,对外分发IP

7.4.5.1 部署方式
1.(看情况)设置ipvs模式(此处查看一下文件,新版本默认是开着的,要是开着的,就不用管)
[root@k8s-master ~]# kubectl edit cm -n kube-system kube-proxy
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:strictARP: true			#    新添一行[root@k8s-master ~]# kubectl -n kube-system get  pods   | awk '/kube-proxy/{system("kubectl -n kube-system delete pods "$1)}'2.下载部署文件(建议直接使用资源包里面的东西)
# 如果想下载使用下面这个被注释掉的命令
# [root@k8s2 metallb]# wget https://raw.githubusercontent.com/metallb/metallb/v0.13.10.7/config/manifests/metallb-native.yaml3.修改文件中镜像地址,与harbor仓库路径保持一致(此处要是使用资源包就不用管了)
[root@k8s-master ~]# vim metallb-native.yaml
image: metallb/controller:v0.14.8
image: metallb/speaker:v0.14.84.上传镜像到harbor(此处要是使用资源包就不用管了)
[root@k8s-master mnt]# docker load -i metalLB.tag.gz
Loaded image: quay.io/metallb/controller:v0.14.8
Loaded image: quay.io/metallb/speaker:v0.14.8[root@k8s-master mnt]# docker tag quay.io/metallb/controller:v0.14.8 reg.dhj.org/metallb/controller:v0.14.8
[root@k8s-master mnt]# docker tag quay.io/metallb/speaker:v0.14.8   reg.dhj.org/metallb/speaker:v0.14.8[root@k8s-master mnt]# docker push reg.dhj.org/metallb/controller:v0.14.8
[root@k8s-master mnt]# docker push reg.dhj.org/metallb/speaker:v0.14.85.部署服务
[root@k8s-master mnt]# kubectl apply -f metallb-native.yaml
[root@k8s-master mnt]# kubectl -n metallb-system get pods
NAME                          READY   STATUS    RESTARTS   AGE
controller-65957f77c8-d2sc5   0/1     Running   0          4s
speaker-22s8m                 0/1     Running   0          4s
speaker-gxc27                 0/1     Running   0          4s
speaker-jsd7h                 0/1     Running   0          4s6.配置分配地址段
[root@k8s-master ~]# vim configmap.yml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:name: first-pool						# 地址池名称namespace: metallb-system
spec:addresses:- 172.25.254.50-172.25.254.99			# 修改为自己本地地址段(看清自己的ip网段)---										# 两个不同的kind中间必须加分割
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:name: examplenamespace: metallb-system
spec:ipAddressPools:- first-pool							# 使用地址池 [root@k8s-master mnt]# kubectl apply -f configmap.yml[root@k8s-master mnt]# kubectl get svc
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
dhj          LoadBalancer   10.104.182.179   172.25.254.50   80:33333/TCP   44m
kubernetes   ClusterIP      10.96.0.1        <none>          443/TCP        2d20h# 通过分配地址从集群外访问服务
[root@reg harbor]# curl 172.25.254.50
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a># 也可以在浏览器中进行访问,如下图:
image-20250813195629799 image-20250813200440483 image-20250813200545933 image-20250813200619472
7.4.6 externalname
  • 开启services后,不会被分配IP,而是用dns解析CNAME固定域名来解决ip变化问题
  • 一般应用于外部业务和pod沟通或外部业务迁移到pod内时
  • 在应用向集群迁移过程中,externalname在过度阶段就可以起作用了。
  • 集群外的资源迁移到集群时,在迁移的过程中ip可能会变化,但是域名+dns解析能完美解决此问题
7.4.6.1 示例
[root@k8s-master ~]# kubectl create svc externalname dhj-service --external-name www.baidu.com -o yaml > dhj-service.yml
[root@k8s-master ~]# vim dhj-service.yml
apiVersion: v1
kind: Service
metadata:labels:app: dhj-servicename: dhj-service
spec:externalName: www.baidu.comselector:app: dhj-servicetype: ExternalName[root@k8s-master ~]# kubectl apply -f dhj-service.yml[root@k8s-master ~]# kubectl get svc dhj-service
NAME          TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)   AGE
dhj-service   ExternalName   <none>       www.baidu.com   <none>    12s# 测试
[root@k8s-master ~]# kubectl run ceshi --image busyboxplus -it
/ # ping dhj-service.default.svc.cluster.local
PING dhj-service.default.svc.cluster.local (183.2.172.17): 56 data bytes
64 bytes from 183.2.172.17: seq=0 ttl=127 time=64.464 ms
image-20250814100253048
http://www.lryc.cn/news/621410.html

相关文章:

  • (2-10-1)MyBatis的基础与基本使用
  • 大数据项目_基于Python+hadopp的城市空气污染数据关联性可视化分析系统源码_基于机器学习的城市空气污染预测与分析系统的设计与实现
  • C/C++ 进阶:深入解析 GCC:从源码到可执行程序的魔法四步曲
  • 卫星通信链路预算之七:上行载噪比计算
  • 【C#】PNG 和 JPG、JPEG的应用以及三种格式的区别?
  • [系统架构设计师]软件工程基础知识(五)
  • 《量子雷达》第5章 量子雷达发射机 预习2025.8.14
  • “Zen 5”: The AMD High-Performance 4nm x86-64 Microprocessor Core
  • 接口测试用例的编写
  • Avalonia_SukiUI明暗主题切换时部分元素颜色不变
  • vue内置组件
  • 基于wireshark的USB 全速硬件抓包工具USB Sniffer Lite的使用
  • 打靶日常-CSRF
  • pytorch学习笔记-加载现有的网络模型(VGG16)、增加/修改其中的网络层(修改为10分类)
  • 分布式锁—Redisson的公平锁
  • 如何更好地使用AI编程?
  • MySQL窗口函数与PyMySQL以及SQL注入
  • C#笔记啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
  • JavaScript 解构赋值语法详解
  • 开源卫星软件平台LibreCube技术深度解析
  • DAY 42 Grad-CAM与Hook函数
  • 一文讲透Go语言并发模型
  • PHP现代化全栈开发:实时应用与WebSockets实践
  • PIDGenRc函数中lpstrRpc的由来和InitializePidVariables函数的关系
  • 技术速递|通过 GitHub Models 在 Actions 中实现项目自动化
  • 状态管理、网络句柄、功能组和功能组状态的逻辑关系
  • 提升工作效率的利器:GitHub Actions Checkout V5
  • 【力扣56】合并区间
  • Linux软件编程(四)多任务与多进程管理
  • CMake进阶: externalproject_add用于在构建阶段下载、配置、构建和安装外部项目