Submariner 部署全过程
Submariner 部署全过程
部署集群配置
broker 集群:
pod-cidr:11.244.0.0/16
service-cidr 11.96.0.0/12
broker 172.100.0.109
node 172.100.0.108
集群 1( pve3 ):
pod-cidr:10.244.0.0/16
service-cidr 10.96.0.0/12
k8s-master 172.100.0.106
node1 172.100.0.104
node2 172.100.0.105
集群 2 ( pve2 ):
pod-cidr:10.244.0.0/16
service-cidr 10.96.0.0/12
k8s-master 172.110.0.102
k8s-node1 172.110.0.105
subctl 安装
下载 subctl 二进制文件,并部署到相应路径:
# github 地址
https://github.com/submariner-io/get.submariner.io
# 运行命令
curl -Ls https://get.submariner.io | bash
export PATH=$PATH:~/.local/bin
echo export PATH=\$PATH:~/.local/bin >> ~/.profile
source ~/.profile
如果运行 curl 命令的时候报错请求403的问题,可以先把网页的命令代码存到 .sh 文件中,再用 bash 命令执行
curl -L https://get.submariner.io -o install_submariner.sh
bash install_submariner.shsubctl uninstal


部署 Broker
Broker 集群可以是专用集群,也可以是连接的集群之一。执行 subctl deploy-broker 命令部署 Broker,Broker 只包含了一组 CRD,并没有部署 Pod 或者 Service。
subctl deploy-broker# 删除submariner
subctl uninstall --kubeconfig /root/.kube/config3 broker-info.subm --yes
subctl uninstall --kubeconfig /root/.kube/configheader broker-info.subm --yes
subctl uninstall deploy-broker /root/.kube/config

部署完成后,会生成 broker-info.subm 文件,文件以 Base64 加密,其中包含了连接 Broker 集群 API Server 的地址以及证书信息,还有 IPsec 的密钥信息
加入集群
执行 subctl join 命令将 集群1 和 集群2 两个集群加入 Broker 集群。使用 --clusterid 参数指定集群 ID,每个集群 ID 需要唯一。提供上一步生成的 broker-info.subm 文件用于集群注册
subctl join broker-info.subm --clusterid pve2
subctl join broker-info.subm --clusterid pve3
但是这里虚拟机上的文件无法下载上传,没有 broker 集群的证书文件集群没有加入权限


使用 scp 命令进行主机与主机之间的文件传输
scp file 远程用户名@远程服务器IP:~/
# 冒号和目录之间无空格


会提示我们选择一个节点作为 Gateway Node,集群1 选择 node1 节点作为 Gateway,集群2 选择 k8s-node1 节点作为 Gateway。之后会分别使用这两个节点的地址在两个集群间建立隧道连接



命令查看集群间连接情况,发现链接并未建立
subctl show connections

查看 submariner 的节点运行状态,发现网关 Pod 运行异常
集群网段 CIDR 异常
查看 Pod 信息和日志发现,网关节点创建失败,无法在IP地址为[“10.244.0.0/16”]的主机上找到CNI接口。初步判断是集群为 Pod 分配网段出现问题
kubectl describe pod <Pod名称> <命名空间>
kubectl logs <Pod名称> <命名空间>


更改k8s网段 CIDR
涉及到pod网段的位置包括
cilium
controller-manager
kube-proxy
# 查看 cilium 配置文件
kubectl edit configmap cilium-config -n kube-system
# 重启 cilium
kubectl rollout restart daemonset cilium -n kube-system
# 删除 pod 重启
kubectl get daemonset -n kube-system
kubectl delete pods -l k8s-app=cilium -n kube-system


# 修改controller-manager的配置
vim /etc/kubernetes/manifests/kube-controller-manager.yaml

# 修改kube-proxy的配置
kubectl edit cm kube-proxy -n kube-system

重启,再次创建 pod 网段未更改

由于系统初始化的 coredns pod 的 IP 是根据网络插件的 CIDR 来分配 IP 的,所以需要在集群初始化时,更改插件的 CIDR配置
helm uninstall cilium -n kube-system

# 生成网络插件配置文件
helm show values cilium/cilium > values.yaml
更改 cilium 的 values.yaml 配置文件相关网段部分

# 根据配置文件安装插件helm install cilium cilium/cilium --namespace kube-system -f values.yaml

更改后 Pod 的 IP 的 CIDR 为网络插件的设置

启用globalnet 建立隧道
在不启用 globalnet 的情况下,CIDR 用重叠的两个集群之间,是无法建立连接的,因为 pod 之间的 IP 可能会出现重复无法辨别的情况

在不启用 globalnet 的情况下,CIDR 完全不重叠的两个集群之间是可以建立连接的,且建立好之后,直接通过 Pod 的 IP 就可以进行通信


如果想在 CIDR 有重复的集群之间建立连接,需要启用 globalnet
# 建立 broker
subctl --kubeconfig ~/.kube/config deploy-broker --globalnet# 加入
subctl join broker-info.subm --clusterid pve3 --globalnet --cable-driver vxlan --health-check=false# 指定网关节点,打标签
kubectl label nodes cluster1 submariner.io/gateway=true
# 查看集群注册信息
kubectl get clusters.submariner.io -n submariner-k8s-broker
# 删除
kubectl delete clusters.submariner.io <cluster-name> -n submariner-k8s-broker

查看日志,隧道和路由成功建立

启用 globalnet 后,虚拟 CIDR 可以 自定义设置,但是设置的虚拟网段的地址不能重叠,否则同样无法建立隧道

还有一点,由于网络插件 Cilium 的网络配置 主要支持 vxlan,submariner 建立 IPsec 隧道,隧道状态为 error。(据说,更改一下网络插件的相关设置可以解决这个问题,但目前还没有尝试,使用 vxlan 建立隧道)


以上问题都解决之后,就可以正常建立隧道通信了,globalnet 会为每一个集群自动分配不重叠的 CIDR

我们在一个集群中创建一个 nginx 的测试服务,并把它导出,其他集群会自动创建 导入服务(需要有相同的命名空间,否则无法导入)




验证测试
# 进入pod
kubectl exec -it <your-pod> -- bash
apt update
# 安装 nslookup
apt install -y dnsutils
终端测试


如果终端无法解析 DNS,在配置中添加 coredns 网址
sudo nano /etc/resolv.conf






终端可以解析 DNS网址,也可以跨集群访问
Pod 内部测试
# 安装网络工具
apt-get install iputils-ping dnsutils -y
iputils-ping # 包含 ping 工具。
dnsutils # 包含 nslookup 工具。


Pod 内部可以解析 DNS 网址,但是无法访问
网络插件 Cilium 更换 Calico
集群使用 submariner ,通过网络检测发现 Cilium 插件可能兼容性不太好
subctl diagnose all

翻阅官网查询得知,submariner 官方已经测试的CNI插件并不包括 Cilium

Cilium 彻底卸载
helm uninstall cilium -n kube-system

# 检查集群中的所有 CNI 插件(集群的每个节点都需要删除)
sudo ls /etc/cni/net.d/# 删除
sudo rm /etc/cni/net.d/05-cilium.conflist
sudo rm /etc/cni/net.d/10-flannel.conflist.cilium_bak

ifconfig
sudo reboot



Calico安装
calico官网地址:https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart
安装Tigera Calico操作符和自定义资源定义:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/tigera-operator.yaml
如果报错连接不上的话将文件手动下载下来再执行
wget https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml
或者
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yamlkubectl create -f tigera-operator.yaml
下载下来后不能用 kubectl apply -f 来执行,会报错
The CustomResourceDefinition “installations.operator.tigera.io” is invalid: metadata.annotations: Too long: must have at most 262144 bytes
意思是 annotation 长度过长了,原因是 apply 和 create 的处理不同
改配置文件中这个选项的长度就不改了,不用 apply 使用 create
这里没有报错就没有问题
但运行完之后要查看一下 tigera-operator 运行是否正常,如果状态为Running 则继续执行下面的步骤
这里可能会出现 容器创建失败 的情况,查看日志一般是因为镜像拉取失败,查看配置文件关于镜像的部分,这里需要单独拉取镜像
第二步将配置文件下载下来,因为要改内容:
# 下载客户端资源文件
curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/custom-resources.yaml
这个文件中的 192.168.0.0 为 init 时指定的 --pod-network-cidr:

# 或者修改pod的网段地址
sed -i 's/cidr: 192.168.0.0/cidr: 10.244.0.0/16' custom-resources.yaml
最后根据这个文件创建资源,执行下面这行命令:
kubectl create -f custom-resources.yaml
这里如果你的集群无法拉取国外镜像,可以尝试配置镜像加速器
sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#' /etc/containerd/config.tomlmkdir /etc/containerd/certs.d/docker.io/ -p# 这里的加速器地址可以选择阿里云的镜像加速地址
cat >/etc/containerd/certs.d/docker.io/hosts.toml <<EOF
[host."https://dbxvt5s3.mirror.aliyuncs.com",host."https://registry.docker-cn.com"]
capabilities = ["pull"]
EOF#重启containerd
systemctl restart containerd
如果,配置了镜像加速器依然无法拉取,这时就需要比较繁琐复杂的过程了(因为我没有找到国内的可以镜像源地址,所以选择在本地拉取dockerhub 镜像传到个人镜像仓库再进行拉取,当然也可以打包直接传到主机)
需要拉取的镜像如下:
docker.io/calico/typha:v3.28.0
docker.io/calico/apiserver:v3.28.0
docker.io/calico/cni:v3.28.0
docker.io/calico/csi:v3.28.0
docker.io/calico/kube-controllers:v3.28.0
docker.io/calico/node-driver-registrar:v3.28.0
docker.io/calico/node:v3.28.0
docker.io/calico/pod2daemon-flexvol:v3.28.0
需要注意的是,如果你采用这种方式,不要只在主节点拉取镜像,部分镜像也需要在工作节点拉取
# 本地拉取镜像
docker pull docker.io/calico/typha:v3.28.0# 上传阿里云私人仓库
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/leung_qw/typha:[镜像版本号]docker push registry.cn-hangzhou.aliyuncs.com/leung_qw/typha:[镜像版本号]# 拉取镜像
sudo ctr -n k8s.io image pull registry.cn-hangzhou.aliyuncs.com/leung_qw/typha:v3.28.0sudo ctr -n k8s.io image tag registry.cn-hangzhou.aliyuncs.com/leung_qw/typha:v3.28.0 docker.io/calico/typha:v3.28.0# 查看镜像
sudo ctr -n k8s.io image list | grep calico

上传到私人镜像仓库,拉取后更改 tag



主机拉取镜像的时候,一定要带-n k8s.io 的命名空间,否则会出现,无法检测到本机镜像的情况


其他镜像如法炮制
如果,你在一台主机上已经有了上面的镜像,也可以将镜像打包,传给其他节点导入
# 镜像打包
sudo ctr -n k8s.io images export <path-to-tar-file> <image-name>:<tag>
# 例如
sudo ctr -n k8s.io images export typha.tar docker.io/calico/typha:v3.28.0# 传递文件
scp file 远程用户名@远程服务器IP:/path/to/destination
# 例如
scp typha.tar public@172.100.0.104:~/# 导入镜像
sudo ctr -n k8s.io images import typha.tar
使用 cilium 插件时的 submariner 以及 更换 calico 后
subctl diagnose all


将 k8s 集群的 CNI 插件更换 Calico 后,正常情况下,所有的节点均处于Running 状态,但是当集群加入 submariner 后,vx-submariner 隧道建立后,会导致 calico-node 状态异常

查询日志发现是隧道虚拟网卡无法建立 BGP ,Calico 主要靠 BGP 负责网络路由功能,在集群节点之间分发路由信息


calico-node 状态的异常会导致,集群内部的通信无法到达网关节点

Calicoctl 安装
版本号选择自己安装的版本
# 查看calico版本
kubectl get deployment -n kube-system calico-kube-controllers -o yaml | grep image
# 下载二进制文件
curl -O -L https://github.com/projectcalico/calico/releases/download/v3.28.0/calicoctl-linux-amd64
安装 calicoctl
# 添加可执行权限
chmod +x calicoctl-linux-amd64
# 安装
sudo mv calicoctl-linux-amd64 /usr/local/bin/calicoctl
# 设置环境变量
export CALICO_DATASTORE_TYPE=kubernetes
export CALICO_KUBECONFIG=~/.kube/config
如果不希望每次执行 calicoctl 之前都需要设置环境变量,可以将环境变量信息写到永久写入到 /etc/calico/calicoctl.cfg 文件(~/.kube/config 要更换成自己的路径)
mkdir -vp /etc/calico
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:datastoreType: "kubernetes" kubeconfig: "home/public/.kube/config"

# 通过~/.kube/config连接kubernetes集群,查看已运行节点
DATASTORE_TYPE=kubernetes KUBECONFIG=~/.kube/config calicoctl get nodes# 或者(如果写入环境变量后)
calicoctl get nodes

配置 Calico IPPools 并且重新部署 submariner
重新部署submariner,一定要卸载干净,仅仅使用subctl uninstall会有部分遗留。执行命令后要注意一下 submariner-operator 命名空间是否删除
如果 submariner-operator 命名空间处于 Terminating 状态长时间未被删除,这可能是因为有某些资源仍然存在,或者有 Finalizer 阻止了删除。
移除 Finalizers。Finalizers 会阻止命名空间被删除。
获取命名空间的详细信息:
kubectl get namespace submariner-operator -o json > namespace.json
编辑 JSON 文件:
打开 namespace.json 文件,找到 spec.finalizers 字段,将其删除。
{"apiVersion": "v1","kind": "Namespace","metadata": {"name": "submariner-operator","finalizers": ["kubernetes"]},"spec": {"finalizers": []}
}
删除 finalizers 部分,然后保存文件。
应用修改后的文件:
kubectl replace --raw "/api/v1/namespaces/submariner-operator/finalize" -f namespace.json
使用 kubectl删除命名空间
kubectl delete namespace submariner-operator --grace-period=0 --force
broker 集群删除集群注册信息
kubectl get clusters.submariner.io -n submariner-k8s-brokerkubectl delete clusters.submariner.io pve2 -n submariner-k8s-broker
重新部署 submariner
submariner 官网提到,当前使用 Calico 目前仅支持 VXLAN 封装技术,且,启用 globalnet 选项后,最好不使用默认的虚拟CIDR,自定义虚拟IP范围


subctl deploy-broker --globalnet --globalnet-cidr-range 100.0.0.0/8subctl join broker-info.subm --clusterid pve2 --globalnet --globalnet-cidr 100.1.0.0/16 --cable-driver vxlan --health-check=falsesubctl join broker-info.subm --clusterid pve3 --globalnet --globalnet-cidr 100.2.0.0/16 --cable-driver vxlan --health-check=false
配置 Calico IPPools
ippool是 Calico 资源,它定义了Calico可以使用的IP地址范围。例如,当IP池中的Pod需要到达IP池外的资源(例如Internet)时,通常使用源网络地址转换(SNAT)。由于我们不希望Calico在集群之间对流量进行NAT转换,因此我们将在每个集群中为其他集群的pod cidr 创建 ippool。当发送到集群集中的其他集群时,这将禁用SNAT,但仍然允许pod使用NAT与Internet通信。
根据 submariner 部署的情况,对 Service CIDR,Pod CIDR,Global CIDR 建立 IPPools,这样可以解决 BGP 无法在虚拟网卡建立的问题。
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:name: globalpve3cluster
spec:cidr: 100.2.0.0/16vxlanMode: Always # 启用 VXLAN 封装 natOutgoing: falsedisabled: true
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:name: svcpve3cluster
spec:cidr: 10.96.0.0/12natOutgoing: falsedisabled: true
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:name: podpve3cluster
spec:cidr: 10.244.0.0/16natOutgoing: falsedisabled: true
calicoctl create -f podpve3cluster.yaml
calicoctl create -f svcpve3cluster.yaml
calicoctl create -f globalpve3cluster.yaml
calicoctl get ippool

subctl diagnose all

验证测试




`
相关文章:
Submariner 部署全过程
Submariner 部署全过程 部署集群配置 broker 集群: pod-cidr:11.244.0.0/16 service-cidr 11.96.0.0/12 broker 172.100.0.109 node 172.100.0.108 集群 1( pve3 ): pod-cidr:10.244.0.0/16 service-…...
驼峰命名法
一、驼峰命名法简介 驼峰命名法(Camel Case)是一种在编程和人类语言中广泛使用的书写方式,通过将单词连接在一起,并使每个单词的首字母大写来表示复合词或短语。这种命名法有小驼峰法和大驼峰法两种变种。 二、小驼峰命名法&…...
Android IME输入法启动显示隐藏流程梳理
阅读Android AOSP 12版本代码,对输入法IME整体框架模块进行学习梳理,内容包含输入法框架三部分IMM、IMMS、IMS的启动流程、点击弹出流程、显示/隐藏流程,以及常见问题和调试技巧。 1. IME整体框架 IME整体分为三个部分…...
Java 入门指南:JVM(Java虚拟机)——类的生命周期与加载过程
文章目录 类的生命周期类加载过程1)载入(Loading)2)验证(Verification)文件格式验证符号引用验证 3)准备(Preparation)4)解析(Resolution…...
Unity射击游戏开发教程:(36)敌人关卡生成器的设计和开发
丰富多样地游戏关卡生成器能自动生成不同的关卡地图和游戏内容,以增加游戏的可玩性和挑战性。关卡生成可以基于随机算法或者预设的规则生成不同的地图布局、敌人位置、道具位置等。 定义关卡生成器WaveSpawner 如何设置通用的 Wave Spawner?我将此 Wave Spawner 脚本附加到…...
AI对汽车行业的冲击和比亚迪新能源汽车市场占比
人工智能(AI)对汽车行业的冲击正在迅速改变该行业的面貌,从智能驾驶到生产自动化,再到个性化的消费者体验,AI带来的技术革新在各个层面影响着汽车产业。与此同时,新能源汽车市场,特别是以比亚迪…...
2024年中国电子学会青少年软件编程(Python)等级考试(一级)核心考点速查卡
考前练习: 2024年06月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 解析-CSDN博客 2024年03月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答…...
游戏开发引擎__游戏场景(灯光,摄像机)
1.灯光 重要参数介绍 类型: 控制灯光的类型,有“定向”“点”“区域”和“聚光”4种模式。颜色: 控制灯光的颜色。模式: 控制灯光的光照模式,有“实时”“混合”和“烘焙”3种模式。强度: 控制灯光的明亮程度。间接乘数: 改变间接光的强度。阴影类型: …...
2024 Snap 新款ar眼镜介绍
2024 snap 新款ar眼镜介绍 2024 Snap 新款ar眼镜介绍 咨询合作 DataBall 项目,欢迎加以下微信。 助力快速掌握数据集的信息和使用方式。...
uni-app生命周期
目录 一、页面生命周期 1、onLoad 【常用】 2、onShow【常用】 3、onReady【常用】 4、onHide【常用】 5、onPullDownRefresh【常用】 6、onReachBottom【常用】 二、应用生命周期 1、onLaunch【常用】 2、onShow【常用】 3、onHide【常用】 三、组件生命周期 1、…...
LabVIEW机械产品几何精度质检系统
随着制造业的发展,对产品质量的要求越来越高,机械产品的几何精度成为衡量其品质的重要指标。为了提高检测效率和精度,开发了一套基于LabVIEW的几何精度质检系统,该系统不仅可以自动化地进行几何尺寸的测量,而且能实时分…...
java 检测图片链接有没有效
实际需求:发送调用微信图片发送接口前检验图片有效性。 在 Java 中,检测图片链接是否有效可以通过发送 HTTP 请求来判断服务器返回的状态码。通过 HttpURLConnection 类,可以轻松地实现这个功能。以下是一个简单的示例代码来检测图片链接是否…...
测试工程师学历路径:从功能测试到测试开发
现在软件从业者越来越多,测试工程师的职位也几近饱和,想要获得竞争力还是要保持持续学习。基本学习路径可以从功能测试-自动化测试-测试开发工程师的路子来走。 功能测试工程师: 1、软件测试基本概念: 学习软件测试的定义、目的…...
JavaEE---Spring IOC(2)
DI之三种注入 属性注入 构造方法注入 Setter注入 当程序中同一个类有多个对象的时候会报错解决方法如下: AutoWired和Resource的区别...
Oracle字符集
select userenv(language) from dual;如果显示如下,一个汉字占用两个字节 SIMPLIFIED CHINESE_CHINA.ZHS16GBK如果显示如下,一个汉字占用三个字节 SIMPLIFIED CHINESE_CHINA.AL32UTF8可以用以下语句查询一个汉字占用的字节长度 select lengthb(你) fr…...
RabbitMQ 常见使用模式详解
RabbitMQ 常见使用模式详解 RabbitMQ 是一个强大的消息队列中间件,支持多种消息通信模式,能够适应不同的业务场景。在这篇文章中,我们将详细介绍 RabbitMQ 的几种常见使用方法及其对应的场景。 1. 发布/订阅(Publish/Subscribe&a…...
JavaEE初阶——初识EE(Java诞生背景,CPU详解)
阿华代码,不是逆风,就是我疯,你们的点赞收藏是我前进最大的动力!!希望本文内容能帮到你! 目录 零:Java的发展背景介绍 一:EE的概念 二:计算机的构成 1:CU…...
iOS界面布局:屏幕尺寸与安全区域全面指南
引言 随着iPhone和iPad的更新迭代,iOS设备的屏幕尺寸和设计也在不断变化。无论是iPhone X系列的刘海屏,还是最新的iPhone 14,开发者都需要面对适配不同设备布局的问题。在项目开发中,导航栏、状态栏、TabBar的高度以及安全区域的…...
javascript-代码执行原理
js 是解释型语言 js 引擎执行流程 分为两个阶段: 语法分析执行阶段执行阶段涉及的数据结构: 调用栈。处理执行上下文和执行代码内存堆。给对象分配内存任务队列。暂存待执行的任务,分为宏任务队列和微任务队列语法分析 词法分析 > 语法分析 > 代码生成(字节码) …...
【C++ | tips】const Date* operator() const中这两个const有什么区别?他们的作用是什么?
const Date* operator&() const { return this; } 我们要明白operator&()这个函数是做什么的。 在C中,&操作符通常用于获取一个对象的地址。但是,有时候我们想要自定义这个行为,比如说,我们想要控制别人怎么获取…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
