02 K8s双主安装
00 前提准备
# 设置好主机名并添加hosts解析
主机名 | IP地址 | 身份 |
---|---|---|
master01 | 172.2.25.50 | 主Master |
master02 | 172.2.25.51 | 备Master |
node01 | 172.2.25.52 | 节点1 |
node02 | 172.2.25.53 | 节点2 |
node03 | 172.2.25.54 | 节点3 |
01 使用脚本安装Docker
# Docker脚本文件
https://node-siyuan.oss-cn-beijing.aliyuncs.com/K8s%E6%96%87%E4%BB%B6/docker-install.tar.gz
# 解压并执行Docker安装脚本
[root@master01 opt]# ls
docker-install.tar.gz
[root@master01 opt]# tar -zxvf docker-install.tar.gz
docker-install/
docker-install/download/
docker-install/download/docker-compose-v2.23.0
docker-install/download/docker-20.10.24.tgz
docker-install/download/docker
docker-install/download/docker.service
docker-install/download/daemon.json
docker-install/install-docker.sh
[root@master01 opt]# cd docker-install/
[root@master01 docker-install]# ./install-docker.sh i
02 基础环境搭建
# 临时和永久关闭swap分区
[root@master01 docker-install]# swapoff -a && sysctl -w vm.swappiness=0
vm.swappiness = 0
[root@master01 docker-install]# sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
# 确保各个节点MAC地址或product_uuid唯一
[root@master01 docker-install]# ifconfig ens33 | grep ether | awk '{print $2}'
00:0c:29:5f:82:68
[root@master01 docker-install]# cat /sys/class/dmi/id/product_uuid
4FE74D56-8C86-11D7-9761-FF1D435F8268
# 温馨提示:# 一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。 # Kubernetes使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败。
# 确保网络的连通性
[root@master01 docker-install]# ping -c 3 baidu.com
PING baidu.com (110.242.68.66) 56(84) bytes of data.
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=1 ttl=128 time=40.6 ms
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=2 ttl=128 time=41.1 ms
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=3 ttl=128 time=37.2 ms--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 37.299/39.670/41.103/1.704 ms
# 允许iptable检查桥接流量
cat <<EOF | tee /etc/modules-load.d/k8s.conf
br_netfilter
EOFcat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
# 设置Docker环境
[root@master01 docker-install]# systemctl enable --now docker
[root@master01 docker-install]# cat /etc/docker/daemon.json
{"exec-opts": ["native.cgroupdriver=systemd"]
}
[root@master01 docker-install]# systemctl restart docker.service
03 安装K8s基本包
# K8s的RPM包下载
https://node-siyuan.oss-cn-beijing.aliyuncs.com/K8s%E6%96%87%E4%BB%B6/kubeadmin-rpm-1_23_17.tar.gz
# 解压并安装压缩包
[root@master01 opt]# tar -zxvf kubeadmin-rpm-1_23_17.tar.gz
[root@master01 opt]# yum localinstall -y kubeadmin-rpm-1_23_17/*.rpm
# 设置时区
[root@master01 opt]# ln -svf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 导入Docker镜像(注意:Master和Node分别导入到Master和Node主机,CNI插件所有主机都装上)# Master节点镜像
https://node-siyuan.oss-cn-beijing.aliyuncs.com/K8s%E6%96%87%E4%BB%B6/%E5%88%9D%E5%A7%8B%E5%8C%96K8s%E9%95%9C%E5%83%8F/master-1.23.17.tar.gz# Node节点镜像
https://node-siyuan.oss-cn-beijing.aliyuncs.com/K8s%E6%96%87%E4%BB%B6/%E5%88%9D%E5%A7%8B%E5%8C%96K8s%E9%95%9C%E5%83%8F/slave-1.23.17.tar.gz# CNI插件
https://node-siyuan.oss-cn-beijing.aliyuncs.com/K8s%E6%96%87%E4%BB%B6/%E5%88%9D%E5%A7%8B%E5%8C%96K8s%E9%95%9C%E5%83%8F/cni-v1.5.1-flannel-v0.25.6.tar.gz
# 所有主机导入CNI镜像
[root@master01 opt]# docker load -i cni-v1.5.1-flannel-v0.25.6.tar.gz
30f8e4588c9e: Loading layer [==================================================>] 8.081MB/8.081MB
05bb1aee8d21: Loading layer [==================================================>] 2.836MB/2.836MB
Loaded image: flannel/flannel-cni-plugin:v1.5.1-flannel2
574b3797bb46: Loading layer [==================================================>] 3.223MB/3.223MB
8047f399ca1f: Loading layer [==================================================>] 16.68MB/16.68MB
# Master主机节点导入镜像
[root@master01 opt]# docker load -i master-1.23.17.tar.gz
cb60fb9b862c: Loading layer [==================================================>] 3.676MB/3.676MB
4e0ee8e33055: Loading layer [==================================================>] 1.538MB/1.538MB
f1f1d923ca19: Loading layer [==================================================>] 126.1MB/126.1MB
# Node主机节点导入镜像
[root@node03 opt]# docker load -i slave-1.23.17.tar.gz
1bb475414a7e: Loading layer [==================================================>] 7.67MB/7.67MB
895a9dd950c1: Loading layer [==================================================>] 9.353MB/9.353MB
290b7ce264c5: Loading layer [==================================================>] 14.91MB/14.91MB
# 所有主机开机自启Kubelet
[root@master01 opt]# systemctl enable kubelet
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /usr/lib/systemd/system/kubelet.service.
04 安装Nginx+Keepalived
# 在两个Master节点安装Nginx+Keepalived
[root@master01 opt]# cat /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true[root@master01 opt]# yum -y install epel-release nginx keepalived nginx-mod-stream
# 同时在master01和master02修改Nginx配置文件
[root@master02 opt]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {worker_connections 1024;
}
stream {log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';access_log /var/log/nginx/k8s-access.log main;upstream k8s-apiserver {server 172.2.25.50:6443 weight=5 max_fails=3 fail_timeout=30s;server 172.2.25.51:6443 weight=5 max_fails=3 fail_timeout=30s;}server {listen 16443;proxy_pass k8s-apiserver;}
}
http {include /etc/nginx/mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main;sendfile on;#tcp_nopush on;keepalive_timeout 65;#gzip on;include /etc/nginx/conf.d/*.conf;
}# 重启Nginx
[root@master02 opt]# systemctl restart nginx && systemctl enable nginx
# 编写Keepalived检查脚本
[root@master01 keepalived]# cat /etc/keepalived/check.sh
#!/bin/bash
# 定义日志文件路径
LOG_FILE="/var/log/nginx_keepalived_check.log"
MAX_LINES=1000 # 设置日志保留1000行(因为不做限制日志会无限增大,占用大量磁盘空间)
# 记录日志的函数,带有详细的时间格式,并保留最后1000行日志
log_message() {local time_stamp=$(date '+%Y-%m-%d %H:%M:%S') # 定义时间格式echo "$time_stamp - $1" >> $LOG_FILE# 截取日志文件,只保留最后1000行tail -n $MAX_LINES $LOG_FILE > ${LOG_FILE}.tmp && mv ${LOG_FILE}.tmp $LOG_FILE
}
# 检测 Nginx 是否在运行的函数
check_nginx() {pgrep -f "nginx: master" > /dev/null 2>&1echo $?
}
# 1. 检查 Nginx 是否存活
log_message "正在检查 Nginx 状态..."
if [ $(check_nginx) -ne 0 ]; thenlog_message "Nginx 未运行,尝试启动 Nginx..."# 2. 如果 Nginx 不在运行,则尝试启动systemctl start nginxsleep 2 # 等待 Nginx 启动# 3. 再次检查 Nginx 状态log_message "启动 Nginx 后再次检查状态..."if [ $(check_nginx) -ne 0 ]; thenlog_message "Nginx 启动失败,停止 Keepalived 服务..."# 4. 如果 Nginx 启动失败,停止 Keepalivedsystemctl stop keepalivedelselog_message "Nginx 启动成功。"fi
elselog_message "Nginx 正常运行。"
fi
# 修改Keepalived配置文件
# master01的Keepalived
[root@master01 keepalived]# cat /etc/keepalived/keepalived.conf
global_defs {router_id LVS_DEVEL
}
vrrp_script keepalived_nginx_check { # 这里是上一步骤添加的脚本,在这里进行调用script "/etc/keepalived/check.sh" # 根据自己添加的脚本路径进行修改,建议还是放在这个目录下便于管理
}
vrrp_instance VI_1 {state MASTER # 主修改state为MASTER,备修改为BACKUPinterface ens33 # 修改自己的实际网卡名称virtual_router_id 51 # 主备的虚拟路由ID要相同priority 100 # 优先级,备服务器设置优先级比主服务器的优先级低一些advert_int 1 # 广播包发送间隔时间为1秒authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.2.25.100/24 # 虚拟IP修改为没有占用的IP地址,主备的虚拟IP相同就好}track_script {keepalived_nginx_check # vrrp_script 定义的脚本名,放到这里进行追踪调用,Keepalived 可以根据脚本返回的结果做出相应的动作}
}
# master02的Keepalived
[root@master02 keepalived]# cat /etc/keepalived/keepalived.conf
global_defs {router_id LVS_DEVEL
}vrrp_script keepalived_nginx_check { # 这里是上一步骤添加的脚本,在这里进行调用script "/etc/keepalived/check.sh" # 根据自己添加的脚本路径进行修改,建议还是放在这个目录下便于管理
}
vrrp_instance VI_1 {state BACKUP # 主修改state为MASTER,备修改为BACKUPinterface ens33 # 修改自己的实际网卡名称virtual_router_id 51 # 主备的虚拟路由ID要相同priority 90 # 优先级,备服务器设置优先级比主服务器的优先级低一些advert_int 1 # 广播包发送间隔时间为1秒authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.2.25.100/24 # 虚拟IP修改为没有占用的IP地址,主备的虚拟IP相同就好}track_script {keepalived_nginx_check # vrrp_script 定义的脚本名,放到这里进行追踪调用,Keepalived 可以根据脚本返回的结果做出相应的动作}
}
# 重新启动Keepalived和Nginx配置文件
[root@master01 keepalived]# systemctl daemon-reload && systemctl restart nginx
[root@master01 keepalived]# systemctl restart keepalived && systemctl enable keepalived
05 初始化主机节点并添加节点
# 在第一台节点上执行初始化操作
[root@master01 opt]# kubeadm init --kubernetes-version=v1.23.17 --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=172.22.0.0/16 --service-cidr=172.125.0.0/16 --service-dns-domain=xy.com --apiserver-advertise-address=172.2.25.50
# 如果有多块物理网卡时 --apiserver-advertise-address很有效,单块网卡无需配置此选项。
# 初始化成功,执行这三条命令mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config
# 如果初始化失败执行下面这条命令
[root@master02 ~]# kubeadm reset -f
[root@node01 opt]# kubeadm join 172.2.25.50:6443 --token ttsrma.qm8qjiens2h89b1x \
> --discovery-token-ca-cert-hash sha256:6f27f291bf82d27668ce673672eab3e0b5d315e936c413db5f9447e15cdda1f8
# 拷贝证书到Master02节点,先在master02创建目录
[root@master02 ~]# mkdir -pv /etc/kubernetes/pki/etcd/
# 在Master01拷贝证书到master02节点
[root@master01 ~]# scp -r /etc/kubernetes/pki/ca.crt root@172.2.25.51:/etc/kubernetes/pki/
[root@master01 ~]# scp -r /etc/kubernetes/pki/ca.key root@172.2.25.51:/etc/kubernetes/pki/
[root@master01 ~]# scp -r /etc/kubernetes/pki/sa.key root@172.2.25.51:/etc/kubernetes/pki/
[root@master01 ~]# scp -r /etc/kubernetes/pki/sa.pub root@172.2.25.51:/etc/kubernetes/pki/
[root@master01 ~]# scp -r /etc/kubernetes/pki/front-proxy-ca.crt root@172.2.25.51:/etc/kubernetes/pki/
[root@master01 ~]# scp -r /etc/kubernetes/pki/front-proxy-ca.key root@172.2.25.51:/etc/kubernetes/pki/
[root@master01 ~]# scp -r /etc/kubernetes/pki/etcd/ca.crt root@172.2.25.51:/etc/kubernetes/pki/etcd/
[root@master01 ~]# scp -r /etc/kubernetes/pki/etcd/ca.key root@172.2.25.51:/etc/kubernetes/pki/etcd/
# 在Master01节点生成加入控制节点的Token
[root@master02 keepalived]# rm -rf /etc/kubernetes/pki/ca.crt
[root@master01 keepalived]# kubeadm token create --print-join-command
kubeadm join 172.2.25.50:6443 --token q7yuop.9s8xx2kewdxox52s --discovery-token-ca-cert-hash sha256:6f27f291bf82d27668ce673672eab3e0b5d315e936c413db5f9447e15cdda1f8
06 配置网络
# 编写flannel配置文件
[root@master01 opt]# cat kube-flannel.yml
apiVersion: v1
kind: Namespace
metadata:labels:k8s-app: flannelpod-security.kubernetes.io/enforce: privilegedname: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: flannelname: flannelnamespace: kube-flannel
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:labels:k8s-app: flannelname: flannel
rules:
- apiGroups:- ""resources:- podsverbs:- get
- apiGroups:- ""resources:- nodesverbs:- get- list- watch
- apiGroups:- ""resources:- nodes/statusverbs:- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:labels:k8s-app: flannelname: flannel
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: flannel
subjects:
- kind: ServiceAccountname: flannelnamespace: kube-flannel
---
apiVersion: v1
data:cni-conf.json: |{"name": "cbr0","cniVersion": "0.3.1","plugins": [{"type": "flannel","delegate": {"hairpinMode": true,"isDefaultGateway": true}},{"type": "portmap","capabilities": {"portMappings": true}}]}net-conf.json: |{"Network": "172.22.0.0/16","EnableNFTables": false,"Backend": {"Type": "vxlan"}}
kind: ConfigMap
metadata:labels:app: flannelk8s-app: flanneltier: nodename: kube-flannel-cfgnamespace: kube-flannel
---
apiVersion: apps/v1
kind: DaemonSet
metadata:labels:app: flannelk8s-app: flanneltier: nodename: kube-flannel-dsnamespace: kube-flannel
spec:selector:matchLabels:app: flannelk8s-app: flanneltemplate:metadata:labels:app: flannelk8s-app: flanneltier: nodespec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/osoperator: Invalues:- linuxcontainers:- args:- --ip-masq- --kube-subnet-mgrcommand:- /opt/bin/flanneldenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespace- name: EVENT_QUEUE_DEPTHvalue: "5000"image: docker.io/flannel/flannel:v0.25.6name: kube-flannelresources:requests:cpu: 100mmemory: 50MisecurityContext:capabilities:add:- NET_ADMIN- NET_RAWprivileged: falsevolumeMounts:- mountPath: /run/flannelname: run- mountPath: /etc/kube-flannel/name: flannel-cfg- mountPath: /run/xtables.lockname: xtables-lockhostNetwork: trueinitContainers:- args:- -f- /flannel- /opt/cni/bin/flannelcommand:- cpimage: docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel2name: install-cni-pluginvolumeMounts:- mountPath: /opt/cni/binname: cni-plugin- args:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistcommand:- cpimage: docker.io/flannel/flannel:v0.25.6name: install-cnivolumeMounts:- mountPath: /etc/cni/net.dname: cni- mountPath: /etc/kube-flannel/name: flannel-cfgpriorityClassName: system-node-criticalserviceAccountName: flanneltolerations:- effect: NoScheduleoperator: Existsvolumes:- hostPath:path: /run/flannelname: run- hostPath:path: /opt/cni/binname: cni-plugin- hostPath:path: /etc/cni/net.dname: cni- configMap:name: kube-flannel-cfgname: flannel-cfg- hostPath:path: /run/xtables.locktype: FileOrCreatename: xtables-lock
# 执行yml文件,安装flannel组件
[root@master01 opt]# kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
# 此时,我们使用ip a s查看ip的时候会看到flannel.1和cni0网卡
# 如果缺少,使用命令添加
# fannel网卡cni0网卡缺失解决方案# 问题描述# 部分节点不存在cni0网络设备,仅有flannel.1设备,此时我们需要手动创建cni0网桥设备哟。# 解决方案# 如果有节点没有cni0网卡,建议大家手动创建相应的网桥设备,但是注意网段要一致# 手动创建cni0网卡# 假设 K8s01的flannel.1是172.22.0.0网段。
# 添加网卡,注意网段
[root@node03 ~]# ip link add cni0 type bridge
[root@node03 ~]# ip link set dev cni0 up
[root@node03 ~]# ip addr add 172.22.3.1/24 dev cni0
07 优化
# 使用kubectl工具实现自动补全功能
[root@master01 ~]# kubectl completion bash > ~/.kube/completion.bash.inc
[root@master01 ~]# echo source '$HOME/.kube/completion.bash.inc' >> ~/.bashrc
[root@master01 ~]# source ~/.bashrc
# K8s巡检脚本
[root@master01 opt]# cat xunjian.sh
#!/bin/bash
# 定义颜色代码
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
# 1. 检查master组件状态
echo -e "${YELLOW}=== 检查master组件状态 ===${NC}"
kubectl get cs 2>/dev/null | while read -r line; doif [[ "$line" =~ "NAME" ]]; thencontinuefiif [ -n "$line" ]; thencomponent=$(echo "$line" | awk '{print $1}')status=$(echo "$line" | awk '{print $2}')if [ "$status" != "Healthy" ]; thenecho -e "${RED}警告: $component 状态异常: $status${NC}"elseecho -e "${GREEN}$component 状态正常: $status${NC}"fifi
done
# 2. 检查工作节点状态
echo -e "\n${YELLOW}=== 检查工作节点状态 ===${NC}"
kubectl get nodes -o wide | while read -r line; doif [[ "$line" =~ "NAME" ]]; thencontinuefiif [ -n "$line" ]; thennode=$(echo "$line" | awk '{print $1}')status=$(echo "$line" | awk '{print $2}')if [ "$status" != "Ready" ]; thenecho -e "${RED}警告: 节点 $node 状态异常: $status${NC}"elseecho -e "${GREEN}节点 $node 状态正常: $status${NC}"fifi
done
# 3. 检查flannel组件状态
echo -e "\n${YELLOW}=== 检查flannel组件状态 ===${NC}"
kubectl get pods -n kube-flannel -o wide | while read -r line; doif [[ "$line" =~ "NAME" ]]; thencontinuefiif [ -n "$line" ]; thenpod=$(echo "$line" | awk '{print $1}')status=$(echo "$line" | awk '{print $3}')restarts=$(echo "$line" | awk '{print $4}')node=$(echo "$line" | awk '{print $7}')if [ "$status" != "Running" ]; thenecho -e "${RED}警告: Pod $pod 在节点 $node 上状态异常: $status (重启次数: $restarts)${NC}"elseecho -e "${GREEN}Pod $pod 在节点 $node 上运行正常: $status (重启次数: $restarts)${NC}"fifi
done
# 4. 检查cni0和flannel网卡是否存在
echo -e "\n${YELLOW}=== 检查网络接口 ===${NC}"
for node in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); doecho -e "\n${YELLOW}检查节点 $node:${NC}"if [ "$node" == "master231" ]; then# 如果是本地节点,直接检查cni0_exists=$(ip link show cni0 2>/dev/null | grep -q "cni0" && echo "存在" || echo "不存在")flannel_exists=$(ip link show flannel.1 2>/dev/null | grep -q "flannel.1" && echo "存在" || echo "不存在")else# 如果是远程节点,通过SSH检查(需要配置SSH免密登录)cni0_exists=$(ssh "$node" "ip link show cni0 2>/dev/null | grep -q 'cni0'" 2>/dev/null && echo "存在" || echo "不存在")flannel_exists=$(ssh "$node" "ip link show flannel.1 2>/dev/null | grep -q 'flannel.1'" 2>/dev/null && echo "存在" || echo "不存在")fiif [ "$cni0_exists" != "存在" ]; thenecho -e "${RED}警告: 节点 $node 上缺少cni0接口${NC}"elseecho -e "${GREEN}节点 $node 上cni0接口存在${NC}"fiif [ "$flannel_exists" != "存在" ]; thenecho -e "${RED}警告: 节点 $node 上缺少flannel.1接口${NC}"elseecho -e "${GREEN}节点 $node 上flannel.1接口存在${NC}"fi
done
# 5. 验证网络是否正常
echo -e "\n${YELLOW}=== 验证网络连通性 ===${NC}"
# 测试节点间的网络连通性
nodes=($(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'))
for i in "${!nodes[@]}"; dofor j in "${!nodes[@]}"; doif [ "$i" -ne "$j" ]; thensrc_node="${nodes[$i]}"dest_node="${nodes[$j]}"echo -e "\n测试从 $src_node 到 $dest_node 的网络连通性..."# 获取目标节点的IPdest_ip=$(kubectl get nodes "$dest_node" -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}')if [ "$src_node" == "master231" ]; then# 本地节点测试ping_result=$(ping -c 3 "$dest_ip" | grep -E "packets transmitted|0% packet loss")else# 远程节点测试(需要配置SSH免密登录)ping_result=$(ssh "$src_node" "ping -c 3 $dest_ip" 2>/dev/null | grep -E "packets transmitted|0% packet loss")fiif [[ "$ping_result" =~ "0% packet loss" ]]; thenecho -e "${GREEN}网络连通性正常: $src_node 可以访问 $dest_node ($dest_ip)${NC}"elseecho -e "${RED}警告: 网络连通性问题: $src_node 无法正常访问 $dest_node ($dest_ip)${NC}"echo -e "详细信息: $ping_result"fifidone
done
echo -e "\n${YELLOW}=== 巡检完成 ===${NC}"
相关文章:
02 K8s双主安装
00 前提准备 # 设置好主机名并添加hosts解析主机名IP地址身份master01172.2.25.50主Mastermaster02172.2.25.51备Masternode01172.2.25.52节点1node02172.2.25.53节点2node03172.2.25.54节点3 01 使用脚本安装Docker # Docker脚本文件 https://node-siyuan.oss-cn-beijing.a…...
分别用 语言模型雏形N-Gram 和 文本表示BoW词袋 来实现文本情绪分类
语言模型的雏形 N-Gram 和简单文本表示 Bag-of-Words 语言表示模型简介 (1) Bag-of-Words (BoW) 是什么? *定义:将文本表示为词频向量,忽略词序和语法,仅记录每个词的出现次数。 **示例: 句子1:I love …...
2_Spring【IOC容器中获取组件Bean】
Spring中IOC容器中获取组件Bean 实体类 //接口 public interface TestDemo {public void doSomething(); } // 实现类 public class HappyComponent implements TestDemo {public void doSomething() {System.out.println("HappyComponent is doing something...")…...
一次页面假死分析
现象:系统的几个功能若干次切换,页面假死,无反应 上图,不是每次切换都假死,但非常容易重现,每次页面假死都在getValidatorJSONInfo这个调用后 getValidatorJSONInfo调用已返回,但返回内容页面挂…...
WPS多级标题编号以及样式控制
WPS多级标题编号以及样式控制 上一篇:WPS自动生成图表目录以及样式控制 阅读提示:请先阅读完本篇内容再操作,避免出现其他错误。 初始样式: 1.1 步骤演示 说明:以3级目录为例 标题1样式:黑体,…...
方差是什么?
一、方差是什么? 方差(Variance)是概率论和统计学中衡量数据离散程度(即数据与平均值的偏离程度)的核心指标。 通俗理解:方差越大,数据越“分散”“波动大”;方差越小,数据越“集中”“稳定”。 二、方差的公式(以样本数据为例) 计算步骤: 第一步:求平均值 ( …...
Java核心API实战:从字符串到多线程全解析
Java常用API详解与代码实践 一、字符串处理类 1. String类 // 字符串基础操作 String str "Hello,Java!"; System.out.println(str.substring(7)); // 输出"Java!" System.out.println(str.indexOf("Java")); // 输出7// 正则表达式匹配 Str…...
低代码AI开发新趋势:Dify平台化开发实战
在人工智能快速发展的今天,AI应用的开发方式也在不断演变。从传统的手写代码到如今的低代码甚至零代码开发,技术的进步让更多的非专业开发者也能轻松上手。本文将带你走进Dify平台化开发的世界,探索如何通过这一强大的低代码AI开发平台&#…...
基于First Order Motion与TTS的AI虚拟主播系统全流程实现教程
前言:多模态虚拟主播的技术革命 在AI内容生成领域,虚拟主播技术正经历从2D到3D、从固定模板到个性化定制的跨越式发展。本文将深入解析如何通过Python技术栈构建支持形象定制与声音克隆的AI虚拟主播系统,涵盖从人脸建模到多模态融合的全流程…...
中科院自动化研究所通用空中任务无人机!基于大模型的通用任务执行与自主飞行
作者: Ji Zhao and Xiao Lin 单位:中科院自动化研究所 论文标题:General-Purpose Aerial Intelligent Agents Empowered by Large Language Models 论文链接:https://arxiv.org/pdf/2503.08302 主要贡献 硬件-软件协同设计框…...
DOM知识点
DOM(Document Object Model)即文档对象模型,是用于表示和操作HTML、XML文档的编程接口。以下是关于DOM的一些知识点总结: 基本概念 • DOM将文档解析为一个由节点(Node)组成的树形结构,每个节…...
设备预测性维护的停机时间革命:中讯烛龙如何用AI重构工业设备管理范式
在工业4.0的智能化浪潮中,非计划停机每年吞噬企业3%-8%的产值。中讯烛龙预测性维护系统通过多模态感知矩阵分布式智能体的创新架构,实现设备健康管理的范式跃迁,帮助制造企业将停机时间压缩70%以上。本文将深度解析技术实现路径与行业级实践方…...
JMeter 教程:使用 HTTP 请求的参数列表发送 POST 请求(form 表单格式)
目录 ✅ 教程目的 🛠️ 准备工作 📄 操作步骤 第一步:新建测试计划 第二步:添加 HTTP 请求 第三步:添加参数列表(表单参数) 第四步:添加结果查看器 第五步:运行测…...
**HTTP/HTTPS基础** - URL结构(协议、域名、端口、路径、参数、锚点) - 请求方法(GET、POST) - 请求头/响应头 - 状态码含义
# HTTP/HTTPS基础知识点详解 ## 1. URL结构 ### 协议部分 - http:// - 超文本传输协议,明文传输 - https:// - 安全的超文本传输协议,使用SSL/TLS加密 - 爬虫注意点:HTTPS网站有TLS指纹(JA3指纹),可被用于检测爬虫 ### 域名部分…...
2025抓包工具Reqable手机抓包HTTPS亲测简单好用-快速跑通
前言 自安卓7.0高版本系统不在信任用户证书,https抓包方式市面查找方法太过复杂手机要root等,前置条件要求太高太复杂,看的头痛,今天一台电脑按步骤操作完即可抓包https,给大家搞定抓包https问题。支持直接编辑修改请求参…...
大模型在胫骨平台骨折预测及治疗方案制定中的应用研究
目录 一、引言 1.1 研究背景与目的 1.2 国内外研究现状 1.3 研究方法和创新点 二、大模型预测胫骨平台骨折的原理和方法 2.1 相关大模型介绍 2.2 数据收集与预处理 2.3 模型训练与优化 2.4 模型评估指标 三、术前预测与手术方案制定 3.1 骨折类型和严重程度预测 3.…...
AI图像处理之ComfyUI节点(二)
一、Load Checkpoint节点 功能:用于加载预训练的大模型,如Stable Diffusion等 参数: chechkpoint:选择加载的模型文件(.ckpt或.satetensors格式) MODEL:输出用于图像扩散预测的UNet模型 CLIP&…...
异常日志规范
目录 一、错误码 二、异常处理 三、日志规约 一、错误码 强制: 1、错误码的制订原则:快速溯源、沟通标准化。 1)错误码必须能够快速知晓错误来源,可快速判断是谁的问题。 2)错误码必须能够清晰地比对(…...
pycharm连接github(详细步骤)
【前提:菜鸟学习的记录过程,如果有不足之处,还请各位大佬大神们指教(感谢)】 1.先安装git 没有安装git的小伙伴,看上一篇安装git的文章。 安装git,2.49.0版本-CSDN博客 打开cmd(…...
UESplineThicken节点
SplineThicken 函数用来使非常薄的多边形在渲染时显示为略厚。对于线缆、头发、草和其他此类对象,这种效果非常理想。 SplineThicken节点 该节点始终朝向摄像机 可以控制模型前后宽度 可以连接到wpo上制作特效效果 参考链接 https://dev.epicgames.com/document…...
【C++】map和set的使用
📌 个人主页: 孙同学_ 🔧 文章专栏:C 💡 关注我,分享经验,助你少走弯路 文章目录 1. 序列式容器和关联式容器1.1 序列式容器1.2 关联式容器 2. set系列的使用2.1 set和multiset的参考文档2.2 se…...
MCP实战:在扣子空间用扣子工作流MCP,一句话生成儿童故事rap视频
扣子最近迎来重要更新,支持将扣子工作流一键发布成MCP,在扣子空间里使用。 这个功能非常有用,因为我有很多业务工作流是在扣子平台上做的,两者打通之后,就可以在扣子空间里直接通过对话方式调用扣子工作流了࿰…...
c/c++的opencv直方图初识
C/C OpenCV中的图像直方图:零基础入门指南 📊 大家好!今天我们来聊聊图像处理中一个非常基础且重要的概念——直方图(Histogram)。如果你是OpenCV新手,或者对直方图感觉有点迷糊,别担心,这篇文章会用最简单…...
Spring Boot 与 RabbitMQ 的深度集成实践(一)
引言 ** 在当今的分布式系统架构中,随着业务复杂度的不断提升以及系统规模的持续扩张,如何实现系统组件之间高效、可靠的通信成为了关键问题。消息队列作为一种重要的中间件技术,应运而生并发挥着举足轻重的作用。 消息队列的核心价值在于其…...
Android动态音频柱状图可视化解析:从原理到实现
Android动态音频柱状图可视化解析:从原理到实现 一、整体架构设计二、核心组件设计三、核心代码实现四、交互设计与用户体验五、性能优化与问题解决一、整体架构设计 Android动态音频柱状图可视化解析 在移动应用开发中,音频可视化是增强用户体验的重要手段。无论是音乐播放器…...
vue3大事件项目
这周写完了vue3的大事件项目,从中学到了很多东西,并且解決了一部分bug,現在就和大家分享一下我遇到的问题并且是如何解決的 1. QuillEditor 的 v-model 用法错误 先讲一下quilleditor富文本的基本使用方法: 1.安裝quill依賴&am…...
MapReduce-WordCount实现按照value降序排序、字符小写、识别不同标点
要求: 输入文件的按照空格、逗号、点号、双引号等分词 输入文件的大写字母全部换成小写 文件输出要求按照value值降序排序 Hadoop给的wordcount示例代码以及代码理解 基于map reduce的word count个人理解:输入的文件经过map reduce框架处理后&#…...
c++线段树之单点修改区间最大子段和-----P4513 小白逛公园
题目大意 单点修改查询区间最大字段和 解题思路 如果线段树节点存储的是‘区间最大子段和’,如何合并? 简单的加法或求极值都不行,仔细分析可得,父节点最大字段和可能为: 左子树最大子段和右子树最大子段和左子树最…...
[Java实战]Spring Boot整合Elasticsearch(二十六)
[Java实战]Spring Boot整合Elasticsearch(二十六) 摘要:本文通过完整的实战演示,详细讲解如何在Spring Boot项目中整合Elasticsearch,实现数据的存储、检索和复杂查询功能。包含版本适配方案、Spring Data Elasticsea…...
【深度学习新浪潮】大模型在哪些垂域已经有比较好的落地?
AI大模型在多个垂直领域已实现显著落地,以下结合可验证案例与行业数据展开说明: 一、医疗健康:精准诊断与个性化治疗 呼吸系统疾病诊断 国家呼吸医学中心研发的LungDiag模型,基于公开临床数据集训练,在预印本研究中对肺炎、肺癌等10种疾病的辅助诊断准确率达92%。医联Med…...
软件测试全攻略:从概念到实践
目录 测试指南针--概念篇 1. 什么是软件测试? 2. 软件测试和软件开发的关系是什么? 3. 测试需要哪些能力? 4. 测试流程是什么样的? 5. 什么是单元测试和集成测试? 6. 软件的生命周期是什么样的? 需求…...
linux hungtask detect机制分析
1,机制概述 hungtask detect 是 Linux 内核用于检测长时间阻塞("hung")任务的机制,主要针对因死锁、死循环或资源竞争导致无法调度的任务 触发条件:任务在 TASK_UNINTERRUPTIBLE 状态持续超过预设阈值…...
影刀处理 Excel:智能工具带来的高效变革
1. 高效的数据处理能力 1.1 快速读取与写入数据 影刀在处理 Excel 数据时展现出显著的读取与写入速度优势。传统方法处理大型 Excel 文件时,读取速度可能仅为每秒 100 行左右,而影刀通过优化底层代码和采用高效的文件解析算法,读取速度可达…...
2021ICPC四川省赛个人补题ABDHKLM
Dashboard - The 2021 Sichuan Provincial Collegiate Programming Contest - Codeforces 过题难度: A K D M H B L 铜奖 5 594 银奖 6 368 金奖 8 755 codeforces.com/gym/103117/problem/A 模拟出牌的过程,打表即可 // Code Start Here int t…...
HarmonyOS 影视应用APP开发--配套的后台服务go-imovie项目介绍及使用
网上有小伙伴对影视应用感兴趣,也想搞个自己的免费观影APP玩玩儿。前期博主开源的有uniapp版本和harmonyOS原生版本影视客户端,但是对博主开源的这个影视后台接口服务不太了解,不知道怎么用起来。这里总结介绍下该go-imove后台接口服务项目介…...
JAVA SE 多线程(上)
文章目录 📕1. Thread类及常见方法✏️1.1 创建线程✏️1.2 Thread 的常见构造方法✏️1.3 Thread 的几个常见属性✏️1.4 启动一个线程---start()✏️1.5 中断一个线程---interrupt()✏️1.6 等待一个线程---join()✏️1.7 获取当前线程引用✏️1.8 休眠当前线程 &…...
基于Bootstrap 的网页html css 登录页制作成品
目录 前言 一、网页制作概述 二、登录页面 2.1 HTML内容 2.2 CSS样式 三、技术说明书 四、页面效果图 前言 Bootstrap是一个用于快速开发Web应用程序和网站的前端框架,由Twitter的设计师Mark Otto和Jacob Thornton合作开发。 它基于HTML、CSS和JavaScri…...
AUTOSAR图解==>AUTOSAR_SRS_Transformer
AUTOSAR Transformer 详解 基于AUTOSAR标准的Transformer组件技术解析 目录 1. AUTOSAR Transformer 概述 1.1 Transformer的作用1.2 Transformer在AUTOSAR中的位置2. Transformer架构设计 2.1 整体架构2.2 类结构设计2.3 交互流程3. Transformer类型与实现 3.1 SOME/IP Transf…...
iOS APP启动页及广告页的实现
iOS APP启动页及广告页的实现涉及UI布局、数据加载、倒计时控制、广告跳转等多个关键环节。以下是我的一些使用心得: 1. UI实现方案 双Window方案 原理:同时创建两个Window,主Window位于底层,广告Window覆盖在其上。通过切换mak…...
图绘Linux:基础指令脉络阁
目录 Linux命令行介绍 目录操作 ls 目录所含文件信息 ls 常用选项 pwd 在那个目录下 cd 进入目录 mkdir 创建目录 文件操作 touch 创建普通文件 echo向文件写入 cat 输出文件内容 cp 拷贝文件/目录 mv剪切重命名 rm 删除文件/目录 查找 * 匹配符 man 查找指令 …...
数字格式化库 accounting.js的使用说明
accounting.js 是一个用于格式化数字、货币和金额的轻量级库,特别适合财务和会计应用。以下是其详细使用说明: 安装与引入 通过 npm 安装: bash 复制 下载 npm install accounting 引入: javascript 复制 下载 const accounting …...
ngx_http_proxy_protocol_vendor_module 模块
一、前置要求 启用 PROXY 协议 在 listen 指令中添加 proxy_protocol 参数,例如: server {listen 80 proxy_protocol;listen 443 ssl proxy_protocol;… }商业订阅 本模块仅在 Nginx 商业版中提供。 二、示例配置 http {# 将 GCP 的 PSC 连接 ID 添…...
C++11-(2)
文章目录 (一)C11新增功能1.1 引用折叠1.1.1 在模板中使用引用折叠的场景1.1.2 引用折叠是如何实现的 1.2 完美转发1.3 lambda表达式语法1.3.1 定义1.3.2 lambda的使用场景1.3.3 捕捉列表1.3.4 mutable语法1.3.5 lambda的原理 (一)…...
LeetCode算 法 实 战 - - - 双 指 针 与 移 除 元 素、快 慢 指 针 与 删 除 有 序 数 组 中 的 重 复 项
LeetCode算 法 实 战 - - - 双 指 针 与 移 除 元 素、快 慢 指 针 与 删 除 有 序 数 组 中 的 重 复 项 第 一 题 - - - 移 除 元 素方 法 一 - - - 双 重 循 环方 法 二 - - - 双 指 针方 法 三 - - - 相 向 双 指 针(面 对 面 移 动) 第 二 题 - - -…...
QT6 源(106):阅读与注释重要的基类控件 QWidget,这是其精简版,完整注释版为篇 37
(1)原篇幅 37 为最开始整理,整理的不是太完善。重点不突出。故重新整理,但删除了大量的注释,重在突出本 QWidget类的内部逻辑,更易观察其包含了哪些内容。至于不理解的成员函数与属性,内容已不太…...
【Bluedroid】蓝牙HID DEVICE错误报告处理全流程源码解析
本文基于Android蓝牙协议栈代码,深入解析HID设备在接收非法指令(如无效的SET_REPORT)时的错误处理全流程,涵盖错误映射、协议封装、传输控制三大核心模块。重点剖析以下机制: HID协议规范错误码的动态转换策略 控制通…...
Day29 类的装饰器
类也有修饰器,他的逻辑类似:接收一个类,返回一个修改后的类。例如 添加新的方法或属性(如示例中的 log 方法)。修改原有方法(如替换 init 方法,添加日志)。甚至可以返回一个全新的类…...
学习黑客Active Directory 入门指南(二)
Active Directory 入门指南(二):深入逻辑结构与物理组件 🌳🏢 大家好!欢迎回到 “Active Directory 入门指南” 系列的第二篇。在上一篇中,我们初步认识了Active Directory,了解了其…...
为什么el-select组件在下拉选择后无法赋值
为什么el-select组件在下拉选择后无法赋值 https://blog.csdn.net/ZHENGCHUNJUN/article/details/127325558 这个链接解决了大模型无法解决的问题 大模型能够写基础且高级一些的代码,但是遇到再深入一些的问题,还是得问百度。对于我这种小白来说问题原因…...
FreeRTOS的学习记录(临界区保护,调度器挂起与恢复)
临界区 在 FreeRTOS 中,临界区(Critical Section) 是指程序中一段必须以原子方式执行的代码区域,在此区域内不允许发生任务切换或中断干扰,以保护共享资源或执行关键操作。FreeRTOS 提供了多种机制来实现临界区&#…...