openeuler 22.03 lts sp4 使用 cri-o 和 静态 pod 的方式部署 k8s-v1.32.0 高可用集群

ops/2025/2/4 11:22:53/

前情提要

整篇文章会非常的长…可以选择性阅读,另外,这篇文章是自己学习使用的,用于生产,还请三思和斟酌

  • 静态 pod 的部署方式和二进制部署的方式是差不多的,区别在于 master 组件的管理方式是 kubectl 还是 systemctl
  • 有 kubeadm 工具,为什么还要用静态 pod 的方式部署?
    • kubeadm init 节点一旦灾难性异常了,整个 k8s 集群都难逃一死(我曾经干活干迷瞪了,要 reset 一个 worker 节点,不小心在 kubeadm init 节点执行 kubeadm reset 命令,整个集群都废了,好在是测试环境,pod 服务都有持久化和相关的 yaml 文件兜底,直接重建 k8s 集群了
  • 有二进制部署的方式,为什么还要用静态 pod 的方式部署?
    • 统一采集 pod 日志也能同时采集 master 组件的日志,不需要额外的处理
    • pod 的 request 和 limit 颗粒度更小,能更好的调整 master 组件的资源使用限制

相关概念

The differences between Docker, containerd, CRI-O and runc

  • 此图概述了 Docker、Kubernetes、CRI、OCI、containerd 和 runc 如何在这个生态系统中协同工作

在这里插入图片描述

OCI

**Open Container Initiative (OCI):**一组容器标准,用于描述镜像格式、运行时和分发的规范

  • OCI 是为容器世界创建一些标准的首批工作之一
  • 它由 Docker 和其他公司于 2015 年成立
  • OCI 得到了许多科技公司的支持,并维护着容器映像格式以及容器应如何运行的规范

CRI

**Container Runtime Interface (CRI) in Kubernetes:**是 Kubernetes 用来控制创建和管理容器的不同运行时的接口

  • CRI 使 Kubernetes 更容易使用不同的容器运行时
  • Kubernetes 项目不需要单独为每个运行时添加支持,而是描述了 Kubernetes 将如何与任何运行时交互
  • 只要给定的容器运行时实现 CRI API,运行时就可以按照自己的喜好创建和启动容器

在这里插入图片描述

containerd 和 CRI-O 都实现了 CRI 规范,都可以用来当作容器运行时

Docker

  • 容器化就是从 Docker 开始的,对很多人来说 “Docker” 这个名字本身就是 “容器” 的代名词
  • 它是管理容器的最流行的工具
  • 现在被命名为 Docker Engine
  • docker 命令实际上调用了一些较低级别的工具来完成繁重的工作

在这里插入图片描述

  • docker-cli:这是一个命令行工具,它是用来完成 docker 命令的 pull, build, run, exec 等进行交互。
  • containerd:这是高级别的容器运行时,一个管理和运行容器的守护进程。它推送和拉取镜像,管理存储和网络,并监督容器的运行。
  • runc:这是低级别的容器运行时(实际创建和运行容器的东西)。它包括 libcontainer,一个用于创建容器的基于 Go 的本地实现。
dockershim

由于 Docker 比 Kubernetes 更早,没有实现 CRI,这就是 dockershim 存在的原因,它支持将 Docker 被硬编码到 Kubernetes 中

  • 随着容器化成为行业标准,Kubernetes 项目增加了对额外运行时的支持,比如通过 Container Runtime Interface (CRI) 容器运行时接口来支持运行容器
  • dockershim 将会从 Kubernetes 1.24 中完全移除
    • 所有支持 OCI 规范的镜像,containerd 和 CRI-O 都可以运行

containerd

containerd 是来自 Docker 的高级容器运行时

  • containerd 诞生于原始 Docker 项目的一部分,之后被捐赠给云原生计算基金会(CNCF)
  • 在内部,Docker Engine 使用 containerd,所以安装 docker 的时候会同时安装 containerd

CRI-O

CRI-O 是一个轻量级的容器运行时

  • 它诞生于 Red Hat、IBM、Intel、SUSE 和其他公司
  • 专注于 Kubernetes 的需求,提供一个精简的容器运行时
  • 由 Kubernetes 使用的 kubelet 来管理和调用,直接通过 Kubernetes 的 CRI 接口与容器交互

runc

一个轻量级的容器运行时,负责创建和运行容器实例,是实现 OCI 接口的最低级别的容器运行时

  • 容器提供所有低级功能,并与现有的低级 Linux 功能(如命名空间和控制组)交互,使用这些功能来创建和运行容器进程

关系总结

  • runc: 容器运行时的低层实现,负责直接启动和运行容器
  • containerd: 容器运行时管理工具,负责容器的生命周期管理,通常通过 runc 来启动容器
  • CRI-O: 为 Kubernetes 提供的容器运行时实现
  • Docker: 一个容器平台,使用 containerd 作为容器运行时,包含了容器构建、管理和运行的完整工具链

开始部署

环境介绍

使用 podman 是因为比 docker 更轻量,没有 deamon 守护进程,只是一个命令文件,自身不占用系统资源,配置私有仓库什么的,也不存在重启服务,和 docker 一样的语法

组件版本
OSopenEuler 22.03 (LTS-SP4)
podman3.4.4
k8s1.32.0
cri-o1.23.2
etcd3.5.16-0
pause3.10
calicov3.26.0
corednsv1.11.3
haproxy2.9.8
keepalived2.3.1

机器 ip 和对应的服务

IPHOSTNAMESERVICE/ROLE
192.168.182.129k8s-master-01k8s-master+keepalived+haproxy
192.168.182.130k8s-master-02k8s-master+keepalived+haproxy
192.168.182.131k8s-master-03k8s-master+keepalived+haproxy
192.168.182.132k8s-worker-04k8s-worker
192.168.182.133k8s-worker-05k8s-worker
192.168.182.200/VIP

系统初始化相关

  • 如果是虚拟机还没就绪,可以先启动一台机器,执行完初始化后,直接克隆机器更方便快捷
  • 如果机器已经就绪了,下面的初始化操作,每个机器都需要执行
  • 下面的操作省略了静态 ip 时间同步的操作,大家自己操作一下
关闭防火墙
systemctl disable firewalld --now
关闭 selinux
setenforce 0
sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
关闭 swap
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
开启内核模块
# 针对于 kube-proxy 使用 ipvs 模式的
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
# 常规要开启的
modprobe nf_conntrack
modprobe br_netfilter
modprobe overlay
开启模块自动加载服务
cat > /etc/modules-load.d/k8s-modules.conf <<EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter
overlay
EOF

设置为开机自启

systemctl enable systemd-modules-load && systemctl restart systemd-modules-load
sysctl 内核参数调整
cat <<EOF > /etc/sysctl.d/kubernetes.conf
# 开启数据包转发功能(实现vxlan)
net.ipv4.ip_forward=1
# iptables对bridge的数据进行处理
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-arptables=1
# 不允许将TIME-WAIT sockets重新用于新的TCP连接
net.ipv4.tcp_tw_reuse=0
# socket监听(listen)的backlog上限
net.core.somaxconn=32768
# 最大跟踪连接数,默认 nf_conntrack_buckets * 4
net.netfilter.nf_conntrack_max=1000000
# 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.swappiness=0
# 计算当前的内存映射文件数。
vm.max_map_count=655360
# 内核可分配的最大文件数
fs.file-max=6553600
# 持久连接
net.ipv4.tcp_keepalive_time=600
net.ipv4.tcp_keepalive_intvl=30
net.ipv4.tcp_keepalive_probes=10
EOF

立即生效

sysctl -p /etc/sysctl.d/kubernetes.conf

特殊操作:/etc/sysctl.conf 文件里面的 net.ipv4.ip_forward=0 会覆盖掉上面子配置文件里面的值

  • 猜测是因为 /etc/openEuler_security/security.conf 文件里面配置了 301@m@/etc/sysctl.conf@net.ipv4.ip_forward=@0,但是不确定修改后会影响哪些,还是打算直接修改 /etc/sysctl.conf ,这样就不会导致机器重启,kubelet 起不来的情况
sed -i 's|^net.ipv4.ip_forward.*|net.ipv4.ip_forward=1|g' /etc/sysctl.conf
sysctl -p
清空 iptables 规则
iptables -F && \
iptables -X && \
iptables -F -t nat && \
iptables -X -t nat && \
iptables -P FORWARD ACCEPT
安装各种依赖和工具
yum install -y vim wget curl tar net-tools jq bash-completion tree bind-utils telnet unzip nc
修改 .bashrc 文件

具体参考我之前的博客:关于 openeuler 22.03-LTS-SP4 scp 失败问题的记录,主要影响的是 scp 命令,具体的,看大家自己选择

安装 kubectl 和 kubelet

k8s 官方也没有 openeuler 的源,但是可以直接使用 kubernetes-el7 的源来安装,下面是配置 kubernetes-el7

  • 由于 Kubernetes 官方变更了仓库的存储路径以及使用方式,如果需要使用 1.28 及以上版本,请使用新版配置方法进行配置:https://developer.aliyun.com/mirror/kubernetes
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/repodata/repomd.xml.key
EOF

后面会用 kubeadm 来生成 kubeconfig 证书

  • 新版本的 k8s 仓库,安装 kubeadm 不再自动安装 kubelet 和 kubectl 了,这里需要都装一下
  • 新版本的 k8s 仓库,安装 kubeadm 也不再自动安装 conntrack-tools 了,kube-proxy 依赖 conntrack
yum install -y kubeadm-1.32.0 kubelet-1.32.0 kubectl-1.32.0 conntrack-tools

利用 kubeadm 提前拉取镜像

kubeadm config images pull --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --kubernetes-version 1.32.0
安装 CRI-O
  • openeuler 的 EPOL 里面自带 cri-o,直接 yum 安装即可
  • crictl 可以在后期用来查看容器状态,日志等操作
yum install -y cri-o crictl
配置 cri-o

默认配置文件是 /etc/crio/crio.conf

[crio.image]
pause_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.10"
# 指定 cgroup 是 systemd,虽然参数默认是 systemd,这里再加一下也不影响
[crio.runtime]
cgroup_manager = "systemd"
# 默认配置文件里面是 true
[crio.metrics]
enable_metrics = false

启动 cri-o 并配置开机自启

systemctl enable crio.service --now
配置 crictl

检查 /etc/crictl.yaml 里面的内容

runtime-endpoint: "unix:///var/run/crio/crio.sock"
安装 podman
yum install -y podman

修改配置文件 /etc/containers/registries.conf

  • 让不带仓库的镜像自动指定 docker.io 这个仓库前缀,podman 不指定镜像仓库的时候,本地显示是 localhost/
unqualified-search-registries = ["docker.io"]

重启 crio,让 crio 重新加载 /etc/containers/registries.conf

systemctl restart crio.service

到这一步,就可以克隆机器了

配置变量

创建目录

mkdir -p /appdata/k8s_deploy

配置变量,避免一些目录名称或者 ip 和我不一样,后面还要一个个检查和修改,后面全部使用变量来替代,尽可能通过 cv 就可以完成部署

cat > /appdata/k8s_deploy/k8s.env <<EOF
# 部署文件的存放目录
deploy_home="/appdata/k8s_deploy"
# k8s master 节点
k8s_master_nodes='
192.168.182.129
192.168.182.130
192.168.182.131
'# k8s worker 节点
k8s_worker_nodes='
192.168.182.132
192.168.182.133
'# 所有节点
all_nodes="
\${k8s_master_nodes}
\${k8s_worker_nodes}
"
# 临时的证书目录
cert_dir=\${deploy_home}/certs
# 定义 k8s 目录
k8s_home=/etc/kubernetes
# k8s 证书目录
k8s_cert=\${k8s_home}/certs
# k8s kubeconfig 目录
kubeconfig_dir=\${k8s_home}/kubeconfig
# k8s 静态 pod 目录
manifest_dir=\${k8s_home}/manifests
# k8s 静态 pod 配置文件目录
pod_config=\${k8s_home}/static_pod_config
# k8s 高可用域名,自己定义
k8s_vip_url=apiserver.ha.icu
# k8s 高可用 vip 地址
k8s_vip_ip=192.168.182.200
# haproxy 端口
k8s_vip_port=8443
# 宿主机网卡名称
interface_name=ens33
# k8s svc 的 ip 段
svc_ip_range=10.96.0.1
# apiserver 中 svc 的网段配置,上下两个变量必须是同一个网段的
svc_cluster_ip_range=10.96.0.0/12
# coredns 的 ip 地址
cluster_dns=10.96.0.10
# k8s pod 的网段
cluster_cidr=172.22.0.0/16
EOF

将 source 命令加入到 ~/.bashrc 目录下面,防止终端断开后,变量为空

cat >> ~/.bashrc <<EOF
source /appdata/k8s_deploy/k8s.env
EOF
source ~/.bashrc

证书制作

创建证书目录

for i in ${k8s_master_nodes};do ssh ${i} "mkdir -p ${k8s_cert}";done
mkdir -p ${deploy_home}/{templates,certs}
ca 证书
  • 注:kubeadm 在创建证书的时候有三个 ca 证书,我这边就一个 ca 通用了,没啥影响

生成一个 2048 位的 ca.key 文件

openssl genrsa -out ${cert_dir}/ca.key 2048

在 ca.key 文件的基础上,生成 ca.crt 文件(用参数 -days 设置证书有效期,单位:天)

openssl req -x509 -new -nodes \
-key ${cert_dir}/ca.key \
-subj "/CN=kubernetes" \
-addext "keyUsage=critical,digitalSignature,keyEncipherment,keyCertSign" \
-addext "subjectAltName=DNS:kubernetes" \
-days 36525 \
-out ${cert_dir}/ca.crt

检查证书到期时间

openssl x509 -text -in ${cert_dir}/ca.crt | grep -A 2 Validity
分发 ca 证书到所有 master 节点
for i in ${k8s_master_nodes};do scp ${cert_dir}/{ca.crt,ca.key} ${i}:${k8s_cert}/;done
apiserver 相关证书
kube-apiserver.crt

生成一个 2048 位的 kube-apiserver.key 文件

cert_name='kube-apiserver'
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

证书配置文件模板

cat > ${deploy_home}/templates/server-csr.cnf.tmp <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn[ dn ]
CN = kubernetes[ req_ext ]
subjectAltName = @alt_names[ v3_ext ]
basicConstraints=critical, CA:FALSE
keyUsage=critical, digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName = @alt_names[ alt_names ]
EOF

生成证书配置文件

sed "s|CN =.*|CN = ${cert_name}|g" ${deploy_home}/templates/server-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnfidx_num=1;
for dnsurl in ${k8s_master_nodes} ${k8s_vip_ip} ${k8s_vip_url} kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local;
do echo "DNS.${idx_num} = ${dnsurl}" >> ${cert_dir}/${cert_name}-csr.cnf;let idx_num++;
doneidx_num=1;
for hostip in ${k8s_master_nodes} ${k8s_vip_ip} ${svc_ip_range};
do echo "IP.${idx_num} = ${hostip}" >> ${cert_dir}/${cert_name}-csr.cnf;let idx_num++;
done

生成 kube-apiserver.csr 证书

openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 apiserver.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
kube-apiserver-kubelet-client.crt

生成一个 2048 位的 kube-apiserver-kubelet-client.key 文件

cert_name='kube-apiserver-kubelet-client'
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

证书配置文件模板

cat > ${deploy_home}/templates/client-csr.cnf.tmp <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn[ dn ][ v3_ext ]
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature,keyEncipherment
extendedKeyUsage=clientAuth
EOF

生成 kube-apiserver-kubelet-client.csr 证书

cat ${deploy_home}/templates/client-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnf
openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-subj "/O=system:masters/CN=${cert_name}" \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 kube-apiserver-kubelet-client.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
front-proxy-client.crt
  • 这个证书是 apiserver 的代理身份验证和身份识别相关的,比如 metrics-server 等代理的部署会依赖

生成一个 2048 位的 front-proxy-client.key 文件

cert_name=front-proxy-client
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

生成 front-proxy-client.csr 证书

cat ${deploy_home}/templates/client-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnf
openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-subj "/CN=${cert_name}" \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 front-proxy-client.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
kube-apiserver-etcd-client.crt

生成一个 2048 位的 kube-apiserver-etcd-client.key 文件

cert_name=kube-apiserver-etcd-client
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

生成 kube-apiserver-etcd-client.csr 证书

cat ${deploy_home}/templates/client-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnf
openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-subj "/O=system:masters/CN=${cert_name}" \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 kube-apiserver-etcd-client.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
sa.pub

生成 sa.key 私钥

openssl genpkey -algorithm RSA -out ${cert_dir}/sa.key -pkeyopt rsa_keygen_bits:2048

生成 sa.pub 公钥文件

openssl rsa -pubout -in ${cert_dir}/sa.key -out ${cert_dir}/sa.pub
验证证书链

返回 ok 说明证书链没问题

for i in kube-apiserver kube-apiserver-etcd-client kube-apiserver-kubelet-client front-proxy-client;do openssl verify -CAfile ${cert_dir}/ca.crt ${cert_dir}/${i}.crt;done
分发 apiserver 相关证书到 master 节点
for i in ${k8s_master_nodes};do scp ${cert_dir}/{kube-apiserver*.crt,kube-apiserver*.key,front-proxy-client.crt,front-proxy-client.key,sa.key,sa.pub} ${i}:${k8s_cert}/;done
etcd 相关证书
  • 注:kubeadm 在创建证书的时候,etcd 会创建 server,peer 和 ca 三个证书,ca 已经通用了,剩下的两个证书也可以通用,就不重复创建了

生成一个 2048 位的 kube-etcd.key 文件

cert_name='kube-etcd'
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

证书配置文件模板

cat > ${deploy_home}/templates/serverAndClient-csr.cnf.tmp <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn[ dn ]
CN = kubernetes[ req_ext ]
subjectAltName = @alt_names[ v3_ext ]
basicConstraints=critical, CA:FALSE
keyUsage=critical, digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth, clientAuth
subjectAltName = @alt_names[ alt_names ]
EOF

生成证书配置文件

for i in ${k8s_master_nodes};do sed "s|CN =.*|CN = ${i}|g" ${deploy_home}/templates/serverAndClient-csr.cnf.tmp > ${cert_dir}/${cert_name}-${i}-csr.cnf;done
idx_num=1;
for i in ${k8s_master_nodes};
dofor dnsurl in ${k8s_master_nodes} localhost;doecho "DNS.${idx_num} = ${dnsurl}" >> ${cert_dir}/${cert_name}-${i}-csr.cnf;let idx_num&#

http://www.ppmy.cn/ops/155552.html

相关文章

UE PlayerController、AIController

19. APlayerController 定义和功能 定义&#xff1a;APlayerController是Unreal Engine中用于处理玩家输入并将其转化为游戏世界中的动作的类。它是连接玩家和游戏角色&#xff08;通常是Pawn&#xff09;之间的桥梁&#xff0c;负责接收输入并通过Possess方法控制Pawn。 功能…

如何在Windows、Linux和macOS上安装Rust并完成Hello World

如何在Windows、Linux和macOS上安装Rust并完成Hello World 如果你刚刚开始学习Rust&#xff0c;第一步就是安装Rust并运行你的第一个程序&#xff01;本文将详细介绍如何在Windows、Linux和macOS上安装Rust&#xff0c;并编写一个简单的“Hello, World!”程序。 1. 安装Rust …

【axios二次封装】

axios二次封装 安装封装使用 安装 pnpm add axios封装 // 进行axios二次封装&#xff1a;使用请求与响应拦截器 import axios from axios import { ElMessage } from element-plus//创建axios实例 const request axios.create({baseURL: import.meta.env.VITE_APP_BASE_API,…

Spring 面试题【每日20道】【其二】

1、Spring MVC 具体的工作原理&#xff1f; 中等 Spring MVC 是 Spring 框架的一部分&#xff0c;专门用于构建基于Java的Web应用程序。它采用模型-视图-控制器&#xff08;MVC&#xff09;架构模式&#xff0c;有助于分离应用程序的不同方面&#xff0c;如输入逻辑、业务逻辑…

人工智能学习(五)之机器学习逻辑回归算法

深入剖析机器学习逻辑回归算法 一、引言 在机器学习领域&#xff0c;逻辑回归是一种极为经典且应用广泛的算法。虽说名字里带有 “回归”&#xff0c;但它主要用于解决分类问题&#xff0c;在医学、金融、互联网等多个领域都发挥着关键作用。例如&#xff0c;在医学上辅助判断…

无法将“mklink”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

mklink : 无法将“mklink”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后再试一次。 所在位置 行:1 字符: 1这是因为 在老版本系统中可以是用mklink来创建软连接&#xff0c;但在最…

php接口连接数据库

框架&#xff1a;https://www.thinkphp.cn/doc 创建网站 域名自己写 创建文件夹&#xff0c;“test”拉取框架&#xff0c;地址栏输入 composer create-project topthink/think5.1.* tp5 会自动创建一个tp5文件夹 根目录选择刚刚创建拉框架的文件夹 以test为示例 “D:\test\…

Maven全解析:Maven 进阶

pom.xml 文件&#xff1a; 定义了项目的基本信息&#xff0c;用于描述项目如何构建&#xff0c;声明项目依赖 坐标&#xff1a; 构建的唯一标识含义&#xff1a; groupId&#xff1a;组织标识。一般为&#xff1a;公司网址的反写 项目名artifactId&#xff1a;项目名称。一…