中文官网参考

本文所使用的内核-5.4.6-1.el7.elrepo.x86_64

安装docker(如果之前安装过请清理干净)
官方建议建议版本18.0.6

yum install docker-ce-18.06.1.ce-3.el7.x86_64

关闭防火墙

#: 暂时关闭防火墙systemctl stop firewalldservice  iptables stop#:永久关闭防火墙systemctl disable firewalldchkconfig iptables off

在v1.13,Kubernetes支持最多5000个节点的集群。更具体地说,我们支持满足以下所有条件的配置:

该页面介绍了用于配置高可用性(HA)Kubernetes集群的拓扑的两个选项。
您可以设置一个HA群集:

堆叠式etcd拓扑(Stacked etcd topology)

堆叠式HA群集是一种拓扑,其中etcd提供的分布式数据存储群集堆叠在由运行控制平面组件的kubeadm管理的节点所形成的群集之上。

每个控制平面节点运行的一个实例kube-apiserver,kube-scheduler和kube-controller-manager。kube-apiserver使用负载均衡器将暴露给工作程序节点。

每个控制平面节点都创建一个本地etcd成员,并且此etcd成员仅与kube-apiserver此节点的进行通信。本地kube-controller-manager 和kube-scheduler实例也是如此。

这种拓扑将相同节点上的控制平面和etcd成员耦合在一起。与具有外部etcd节点的集群相比,建立起来更容易,并且复制管理起来也更容易。

但是,堆叠的群集存在耦合失败的风险。如果一个节点发生故障,则etcd成员和控制平面实例都将丢失,并且冗余也会受到损害。您可以通过添加更多控制平面节点来减轻这种风险。

因此,您应该为HA集群至少运行三个堆叠的控制平面节点。

这是kubeadm中的默认拓扑。使用kubeadm init和时,会在控制平面节点上自动创建一个本地etcd成员kubeadm join --control-plane。

外部etcd拓扑(External etcd topology)

具有外部etcd的HA群集是一种拓扑,其中etcd提供的分布式数据存储群集位于由运行控制平面组件的节点形成的群集的外部。

像堆叠ETCD拓扑结构,在外部ETCD拓扑中的每个控制平面节点运行的一个实例kube-apiserver,kube-scheduler和kube-controller-manager。并且kube-apiserver使用负载平衡器将其暴露给工作程序节点。但是,etcd成员在单独的主机上运行,​​并且每个etcd主机都与kube-apiserver每个控制平面节点的通讯。

该拓扑将控制平面和etcd成员解耦。因此,它提供了一种HA设置,其中丢失控制平面实例或etcd成员的影响较小,并且不会像堆叠的HA拓扑那样对集群冗余产生太大影响。

但是,此拓扑所需的主机数量是堆栈HA拓扑的两倍。对于具有此拓扑的HA群集,至少需要三台用于控制平面节点的主机和三台用于etcd节点的主机。

Kubeadm默认在由控制平面节点上的kubelet管理的静态pod中运行单个成员etcd集群。这不是高可用性设置,因为etcd群集仅包含一个成员,无法维持任何成员不可用。此任务完成了创建由三个成员组成的高可用性etcd集群的过程,当使用kubeadm设置kubernetes集群时,该集群可以用作外部etcd。

安装部署开始

本文选择堆叠式etcd拓扑(Stacked etcd topology)

192.168.1.46 test1(node)
192.168.1.47 test2(master-HA)
192.168.1.48 test3(master-HA)
192.168.1.18 test4(master-HA)
192.168.1.45(HA-Proxy放在此服务器)

前提:修改本地/etc/hosts文件
#将以下内容追加(>>)到 /etc/hosts文件

cat <<EOF >> /etc/hosts
192.168.1.46 test1
192.168.1.47 test2
192.168.1.48 test3
192.168.1.18 test4EOF

官网

1、基础:验证MAC地址和product_uuid对于每个节点都是唯一的
  • 您可以使用以下命令获得网络接口的MAC地址ip link或ifconfig -a
  • 可以使用以下命令检查product_uuid sudo cat /sys/class/dmi/id/product_uuid

Kubernetes使用这些值来唯一地标识集群中的节点。如果这些值不是每个节点唯一的,则安装过程可能会失败。

2.1、基础:使用本机软件包管理进行安装kubelect

加载国内阿里源(提醒不要用官方源,国内用不了一直报错: 网络不可达"正在尝试其它镜像。)

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

注:如果上边这个源不好用,再用下面的镜像源

cat <<LEO > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
LEO

2.2、通过运行setenforce 0并sed …有效禁用SELinux,将其设置为许可模式。
这是允许容器访问主机文件系统所必需的,例如Pod网络所需要的。您必须执行此操作,直到kubelet中的SELinux支持得到改善。

修改 /etc/selinux/config 文件方法:SELINUX=disabled通过命令临时修改(重启会丢失):setenforce 0
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
sed -i 's/^SELINUX=disable$/SELINUX=permissive/' /etc/selinux/config

2.3、安装kubelet、kubeadm、kubectl

yum install -y kubelet-1.13.0 kubeadm-1.13.0 kubectl-1.13.0 kubernetes-cni-0.6.0 --disableexcludes=kubernetes

设置kubelet开机自启动

systemctl enable --now kubelet

2.4、RHEL / CentOS 7上的一些用户报告了由于绕过iptables而导致流量无法正确路由的问题。您应该确保 net.bridge.bridge-nf-call-iptables在sysctl配置中将其设置为1

cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

手动加载配置文件使生效

sysctl -p /etc/sysctl.d/k8s.conf
sysctl --system

2.5、br_netfilter在执行此步骤之前,请确保已加载模块。这可以通过运行来查看(lsmod # 显示已载入系统的模块)。(只针对3.几的内核,升级到4.4或是更高版本就没有此模块了,但不影响)

lsmod | grep br_netfilter

要显式加载,请调用modprobe br_netfilter。

modprobe br_netfilter

2.6、如需要重新启动kubelet:(命令参考跳过)

systemctl daemon-reload && systemctl restart kubelet && systemctl enable kubelet.service

2.7、安装 ebtables ethtool,否则后边执行 kubeadm init 的时候会报错

yum install ebtables ethtool -y

2.8、永久关闭swap(可不执行)

swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab

开启关闭(执行swapoff -a)

swapoff -a
swapon -a
3、第一步:

3.1、为kube-apiserver创建负载均衡器
①.创建一个解析DNS的kube-apiserver负载均衡器。安装HA

  • 在云环境中,应将控制平面节点放在TCP转发负载平衡器之后。该负载平衡器将流量分配到其目标列表中的所有运行状况良好的控制平面节点。apiserver的运行状况检查是对kube-apiserver侦听的端口的TCP检查(默认值:6443)。
  • 不建议在云环境中直接使用IP地址。
  • 负载平衡器必须能够与apiserver端口上的所有控制平面节点进行通信。它还必须允许其侦听端口上的传入流量。
  • HAProxy可用作负载平衡器。
  • 确保负载均衡器的地址始终与kubeadm的地址匹配ControlPlaneEndpoint。

②.将一个控制平面节点添加到负载均衡器并测试连接:

nc -v LOAD_BALANCER_IP PORT

3.2、配置SSH(如配置好ssh请跳过该步)—— 根据跟人情怀可以不配置
如果要从一台计算机控制所有节点,则需要SSH。

4、第二步:下载1.13所需的镜像

查看所需的镜像:

kubeadm config images list

创建文件setup_image.sh 编写脚本批量下载镜像,并修改镜像tag与google的k8s镜像名称一致

#!/bin/bash
# 定义镜像集合数组
images=(kube-apiserver:v1.13.0kube-controller-manager:v1.13.0kube-scheduler:v1.13.0kube-proxy:v1.13.0pause:3.1etcd:3.2.24
)
# 循环从国内Docker镜像库 https://hub.docker.com 中下载镜像
for img in ${images[@]};
do# 从国内源下载镜像docker pull mirrorgooglecontainers/$img# 改变镜像名称docker tag  mirrorgooglecontainers/$img k8s.gcr.io/$img# 删除源始镜像docker rmi  mirrorgooglecontainers/$img#echo '================'
done# 有一个在Docker Hub中找不到,换个下载仓库
docker pull coredns/coredns:1.2.6
docker tag  coredns/coredns:1.2.6 k8s.gcr.io/coredns:1.2.6
docker rmi  coredns/coredns:1.2.6
5、第三步:堆叠的控制平面和etcd节点(Stacked etcd topology)

第一个控制平面节点的步骤
官网配置文件kubeadm-config.yaml
5.1.在第一个控制平面节点上,创建一个名为的配置文件kubeadm-config.yaml:

apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
apiServer:certSANs:- "192.168.1.45"
controlPlaneEndpoint: "192.168.1.45:6444"
networking:podSubnet: "10.244.0.0/16"
  • kubernetesVersion应该设置为Kubernetes版本使用。本示例使用stable。
  • controlPlaneEndpoint 应与负载均衡器的地址或DNS和端口匹配。
  • 建议将kubeadm,kubelet,kubectl和Kubernetes的版本匹配。
  • 设置networking这个对象 中podSubnet这个字段是为Calico/Flannel 等CNI插件所使用,创建pod的ip网段。
  • 其他网络插件自动参考官网推荐的网络

5.2、确保节点处于干净状态(参考文章后面卸载)

sudo kubeadm init --config=kubeadm-config.yaml

您应该看到类似以下内容:

...
You can now join any number of machines by running the following on each node
as root:kubeadm join 192.168.1.45:6444 --token j04n3m.octy8zely83cy2ts --discovery-token-ca-cert-hash    sha256:84938d2a22203a8e56a787ec0c6ddad7bc7dbd52ebabc62fd5f4dbea72b14d1f

将此输出复制到文本文件。稍后您将需要它来将其他控制平面节点加入集群。

5.3、应用Flannel CNI插件:
您必须安装一个Pod Network插件,以便您的Pod可以相互通信。

kubernetes 提供了很多种网络组件选择,有 Calico、Canal、Flannel、Kube-router、Romana、Weave Net 可以使用,本文采用其中的Flannel,官方比较推荐Calico/Flannel

k8s是1.13版本的则需要用以下的命令安装 flannel
(kube-flannel-rbac.yml / kube-flannel.yml)本文末尾提供了文件详情

docker pull quay.io/coreos/flannel:v0.10.0-amd64
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.11.0/Documentation/k8s-manifests/kube-flannel-rbac.yml
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.11.0/Documentation/kube-flannel.yml

4、查看

kubectl get pod -n kube-system -w

建议仅在第一个节点完成初始化之后才加入新的控制平面节点。

6、第四步:将证书文件从第一个控制平面节点复制到其余节点:

以下操作的前提:已经执行3.2的操作
在以下示例中,将其替换CONTROL_PLANE_IPS为其他控制平面节点的IP地址。
(本文)配置:

USER=root
CONTROL_PLANE_IPS="192.168.1.47 192.168.1.48"
for host in ${CONTROL_PLANE_IPS}; doscp /etc/kubernetes/pki/ca.crt "${USER}"@$host:scp /etc/kubernetes/pki/ca.key "${USER}"@$host:scp /etc/kubernetes/pki/sa.key "${USER}"@$host:scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crtscp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.keyscp /etc/kubernetes/admin.conf "${USER}"@$host:
done

官方模板:

USER=ubuntu # customizable
CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8"
for host in ${CONTROL_PLANE_IPS}; doscp /etc/kubernetes/pki/ca.crt "${USER}"@$host:scp /etc/kubernetes/pki/ca.key "${USER}"@$host:scp /etc/kubernetes/pki/sa.key "${USER}"@$host:scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crtscp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.keyscp /etc/kubernetes/admin.conf "${USER}"@$host:
done

注意:仅复制以上列表中的证书。kubeadm将负责为加入的控制平面实例生成带有所需SAN的其余证书。如果错误地复制了所有证书,则由于缺少所需的SAN,其他节点的创建可能会失败

7、第五步:其余控制平面节点的步骤

在上一步复制到的节点服务器上进行操作。
(本文)配置:

USER=root
mkdir -p /etc/kubernetes/pki/etcd
mv /${USER}/ca.crt /etc/kubernetes/pki/
mv /${USER}/ca.key /etc/kubernetes/pki/
mv /${USER}/sa.pub /etc/kubernetes/pki/
mv /${USER}/sa.key /etc/kubernetes/pki/
mv /${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
mv /${USER}/front-proxy-ca.key /etc/kubernetes/pki/
mv /${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
mv /${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
mv /${USER}/admin.conf /etc/kubernetes/admin.conf

官方模板

USER=ubuntu # customizable
mkdir -p /etc/kubernetes/pki/etcd
mv /home/${USER}/ca.crt /etc/kubernetes/pki/
mv /home/${USER}/ca.key /etc/kubernetes/pki/
mv /home/${USER}/sa.pub /etc/kubernetes/pki/
mv /home/${USER}/sa.key /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/
mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
mv /home/${USER}/admin.conf /etc/kubernetes/admin.conf

此过程将所有请求的文件写入文件夹/etc/kubernetes。

kubeadm join使用 5.2所执行kubeadm init在第一个节点上生成的join命令,在此节点上启动。

sudo kubeadm 192.168.1.45:6444 --token j04n3m.octy8zely83cy2ts --discovery-token-ca-cert-hash sha256:84938d2a22203a8e56a787ec0c6ddad7bc7dbd52ebabc62fd5f4dbea72b14d1f --experimental-control-plane

注意添加了--experimental-control-plane标志。该标志使该控制平面节点自动加入集群。

建议:一个一个添加

查看

kubectl get pod -n kube-system -w

最后:对其余的控制平面节点重复这些步骤(可用ansible完善)



二、外部etcd拓扑(External etcd topology)

第一步、设置etcd集群

官网地址
注意:HOST0是我们所运行以下操作的所在服务器
HOST0=10.0.0.6
HOST1=10.0.0.7
HOST2=10.0.0.8
通用方法是在一个节点上生成所有证书,而仅将必要的文件分发到其他节点。

1、重复上面第三步之前的基础配置。(不包括第三步以后的操作)
2、将kubelet配置为etcd的服务管理器。

由于etcd是需要首先创建的,因此您必须通过创建优先于kubeadm提供的kubelet单位文件的优先级的新单位文件来覆盖服务优先级。

cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
#  Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs".
ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd
Restart=always
EOF
systemctl daemon-reload
systemctl restart kubelet
3、生成证书颁发机构

如果您已经有一个CA,那么唯一的操作就是将CA crt和 key文件复制到/etc/kubernetes/pki/etcd/ca.crt和 /etc/kubernetes/pki/etcd/ca.key。复制完这些文件后,继续执行下一步,“为每个成员创建证书”。

如果您还没有CA,请在HOST0服务器上运行此命令(在生成了kubeadm的配置文件之前)。

kubeadm init phase certs etcd-ca

这将创建两个文件

  • /etc/kubernetes/pki/etcd/ca.crt
  • /etc/kubernetes/pki/etcd/ca.key
[root@test4 etcd_topology]# kubeadm init phase certs etcd-ca
I0114 16:15:34.301386   20728 version.go:94] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get https://dl.k8s.io/release/stable-1.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
I0114 16:15:34.301472   20728 version.go:95] falling back to the local client version: v1.13.0
[certs] Generating "etcd/ca" certificate and key
[root@test4 etcd_topology]# ll /etc/kubernetes/pki/etcd/
总用量 8
-rw-r--r-- 1 root root 1017 1月  14 16:15 ca.crt
-rw------- 1 root root 1679 1月  14 16:15 ca.key
[root@test4 etcd_topology]#
4、为kubeadm创建配置文件。

使用以下脚本为将在其上运行etcd成员的每个主机生成一个kubeadm配置文件。

cat kubeadm_conf.sh

# Update HOST0, HOST1, and HOST2 with the IPs or resolvable names of your hosts
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8# Create temp directories to store files that will end up on other hosts.
mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/ETCDHOSTS=(${HOST0} ${HOST1} ${HOST2})
NAMES=("infra0" "infra1" "infra2")for i in "${!ETCDHOSTS[@]}"; do
HOST=${ETCDHOSTS[$i]}
NAME=${NAMES[$i]}
cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
apiVersion: "kubeadm.k8s.io/v1beta1"
kind: ClusterConfiguration
etcd:local:serverCertSANs:- "${HOST}"peerCertSANs:- "${HOST}"extraArgs:initial-cluster: ${NAMES[0]}=https://${ETCDHOSTS[0]}:2380,${NAMES[1]}=https://${ETCDHOSTS[1]}:2380,${NAMES[2]}=https://${ETCDHOSTS[2]}:2380initial-cluster-state: newname: ${NAME}listen-peer-urls: https://${HOST}:2380listen-client-urls: https://${HOST}:2379advertise-client-urls: https://${HOST}:2379initial-advertise-peer-urls: https://${HOST}:2380
EOF
done
5、为每个成员创建证书

cat cert.sh

kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST2}/
# cleanup non-reusable certificates
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -deletekubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST1}/
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -deletekubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
# No need to move the certs because they are for HOST0# clean up certs that should not be copied off this host
find /tmp/${HOST2} -name ca.key -type f -delete
find /tmp/${HOST1} -name ca.key -type f -delete
6、复制证书和kubeadm配置

证书已生成,现在必须将其移至其各自的主机。
根据自身配置顺序执行以下命令

export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8USER=rootHOST=${HOST1}scp -r /tmp/${HOST}/* ${USER}@${HOST}:ssh ${USER}@${HOST}# sudo -s 环境用的是当前用户本身的环境 加上-E选项后,用户可以在sudo执行时保留当前用户已存在的环境变量,不会被sudo重置USER@HOST $ sudo -Esroot@HOST $ chown -R root:root pkiroot@HOST $ mv pki /etc/kubernetes/

结果如下,确保文件都存在

[root@test3 ~]# tree /etc/kubernetes/pki
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd├── ca.crt├── healthcheck-client.crt├── healthcheck-client.key├── peer.crt├── peer.key├── server.crt└── server.key1 directory, 9 files
[root@test3 ~]#
7、创建静态吊舱清单

既然证书和配置已经准备就绪,该创建清单了。在每台主机上运行kubeadm命令以为etcd生成静态清单。

# HOST0服务器
root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
# HOST1服务器
root@HOST1 $ kubeadm init phase etcd local --config=kubeadmcfg.yaml
# HOST2服务器
root@HOST2 $ kubeadm init phase etcd local --config=kubeadmcfg.yaml

执行结果:

[root@test4 etcd_topology]# kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
I0114 18:19:10.062078   23292 version.go:94] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get https://dl.k8s.io/release/stable-1.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
I0114 18:19:10.062203   23292 version.go:95] falling back to the local client version: v1.13.0
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"[root@test2 ~]# kubeadm init phase etcd local --config=kubeadmcfg.yaml
I0115 15:42:57.668343   12951 version.go:94] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get https://dl.k8s.io/release/stable-1.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
I0115 15:42:57.668472   12951 version.go:95] falling back to the local client version: v1.13.0
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[root@test2 ~]#
8、可选:检查集群运行状况——可跳过此步

官方提供的校验方式如下:

docker run --rm -it \
--net host \
-v /etc/kubernetes:/etc/kubernetes quay.io/coreos/etcd:${ETCD_TAG} etcdctl \
--cert-file /etc/kubernetes/pki/etcd/peer.crt \
--key-file /etc/kubernetes/pki/etcd/peer.key \
--ca-file /etc/kubernetes/pki/etcd/ca.crt \
--endpoints https://${HOST0}:2379 cluster-health
...
cluster is healthy
  • 设置${ETCD_TAG}为etcd图像的版本标签。例如v3.2.24。
  • 设置${HOST0}为要测试的主机的IP地址。

(本文)使用的校验方式参考如下:
修改ip与镜像name:版本,即可使用

docker run --rm -it \
--net host \
-v /etc/kubernetes:/etc/kubernetes k8s.gcr.io/etcd:3.2.24 etcdctl \
--cert-file /etc/kubernetes/pki/etcd/peer.crt \
--key-file /etc/kubernetes/pki/etcd/peer.key \
--ca-file /etc/kubernetes/pki/etcd/ca.crt \
--endpoints https://192.168.1.18:2379 cluster-health

操作执行结果如下:

[root@test4 leo_k8s_HA]# docker images | grep k8s.gcr.io/etcd
k8s.gcr.io/etcd                                                             3.2.24                     3cab8e1b9802        16 months ago       220MB
[root@test4 leo_k8s_HA]# docker run --rm -it \
> --net host \
> -v /etc/kubernetes:/etc/kubernetes k8s.gcr.io/etcd:3.2.24 etcdctl \
> --cert-file /etc/kubernetes/pki/etcd/peer.crt \
> --key-file /etc/kubernetes/pki/etcd/peer.key \
> --ca-file /etc/kubernetes/pki/etcd/ca.crt \
> --endpoints https://192.168.1.18:2379 cluster-health
member 1003c8d5d6bbfb62 is healthy: got healthy result from https://192.168.180.48:2379
member 73be5fbb48e5cf05 is healthy: got healthy result from https://192.168.181.18:2379
member f1ab2a68a948c889 is healthy: got healthy result from https://192.168.180.47:2379
cluster is healthy
[root@test4 leo_k8s_HA]#
第二步、设置第一个控制平面节点

1、将以下文件从群集中的任何etcd节点复制到第一个控制平面节点:

export CONTROL_PLANE="root@192.168.1.18"
scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}":
scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}":
scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":

替换CONTROL_PLANE的值user@host(本机的)。

2、创建一个kubeadm-config.yaml具有以下内容的文件:
官方参考:
cat kubeadm-config.yaml

apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
apiServer:certSANs:- "LOAD_BALANCER_DNS"
controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT"
etcd:external:endpoints:- https://ETCD_0_IP:2379- https://ETCD_1_IP:2379- https://ETCD_2_IP:2379caFile: /etc/kubernetes/pki/etcd/ca.crtcertFile: /etc/kubernetes/pki/apiserver-etcd-client.crtkeyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
  • 这里堆叠的etcd与外部etcd之间的区别在于,我们在kubeadm配置中使用了该external字段etcd。对于堆叠式etcd拓扑,这是自动管理的。

  • 将模板中的以下变量替换为群集的适当值:

  • LOAD_BALANCER_DNS

  • LOAD_BALANCER_PORT

  • ETCD_0_IP

  • ETCD_1_IP

  • ETCD_2_IP

(本文)使用的配置如下:
cat kubeadm-config.yaml

apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
apiServer:certSANs:- "192.168.180.45"
controlPlaneEndpoint: "192.168.180.45:6444"
networking:podSubnet: "10.244.0.0/16"
etcd:external:endpoints:- https://192.168.181.18:2379- https://192.168.180.47:2379- https://192.168.180.48:2379caFile: /etc/kubernetes/pki/etcd/ca.crtcertFile: /etc/kubernetes/pki/apiserver-etcd-client.crtkeyFile: /etc/kubernetes/pki/apiserver-etcd-client.key

3、init加载k8s集群在此节点上运行。

sudo kubeadm init --config kubeadm-config.yaml

4、应用Flannel CNI插件:
您必须安装一个Pod Network插件,以便您的Pod可以相互通信。

kubernetes 提供了很多种网络组件选择,有 Calico、Canal、Flannel、Kube-router、Romana、Weave Net 可以使用,本文采用其中的Flannel,官方比较推荐Calico/Flannel

k8s是1.13版本的则需要用以下的命令安装 flannel
(kube-flannel-rbac.yml / kube-flannel.yml)本文末尾提供了文件详情

docker pull quay.io/coreos/flannel:v0.10.0-amd64
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.11.0/Documentation/k8s-manifests/kube-flannel-rbac.yml
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.11.0/Documentation/kube-flannel.yml

5、其余控制平面节点的步骤
除了未创建本地etcd成员外,这些步骤与堆叠式etcd设置相同。

总结一下:
步骤与堆叠式etcd设置相同:

  • 确保第一个控制平面节点已完全初始化。
  • 使用保存到文本文件中的连接命令将每个控制平面节点连接在一起。建议一次加入一个控制平面节点。
  • 不要忘记–certificate-key默认情况下,解密密钥从会在两个小时后过期。

该标志–experimental-control-plane不应添加到node节点。



常用命令
1、# 重新生成链接 Token

[root@k8s-master deploy]# kubeadm token create --print-join-command

2、运行journalctl -xefu kubelet 命令查看systemd日志



export -p //列出当前的环境变量值

对kubeadm进行故障排除

1、 注如果yum安装报错:

  • 重新建立rpm库里的记录,生成新镜像缓存
    yum clean all
    rpm --rebuilddb
    yum makecache

2、如果出现如下的报错

failed to load Kubelet config file /var/lib/kubelet/config.yaml, error failed to read kubelet config file "/var/lib/kubelet/config.yaml", error: open /var/lib/kubelet/config.yaml: no such file or directory

忽略以上的报错,设置为开机自启动即可,因为此时的配置还没初始化完成,所以此时不能启动kubelet,等后续kubeadm启动成功后再查看
原因:kubelet每隔几秒钟重新启动一次,因为它在崩溃循环中等待kubeadm告诉它该怎么做。此崩溃循环是正常现象。初始化母版后,kubelet将正常运行。

3、清理网络

systemctl stop kubelet
systemctl stop docker
ifconfig cni0 down
ip link delete cni0
ifconfig flannel.1 down
ip link delete flannel.1
rm -rf /var/lib/cni/
rm -f /etc/cni/net.d/*
systemctl start docker
systemctl  restart kubelet

4、出现以下错误

OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec:

是由于在docker中没有base命令,可以将base改为sh

5、k8s连接不上集群
报错信息为

Unable to connect to the server: EOF

查看日志
journalctl -f -u kubelet

12月 31 11:44:26 test3 kubelet[29987]: E1231 11:44:26.447695   29987 reflector.go:134]  k8s.io/kubernetes/pkg/kubelet/kubelet.go:453: Failed to list *v1.Node: Get https://192.168.180.45:6444/api/v1/nodes?fieldSelector=metadata.name%3Dtest3&limit=500&resourceVersion=0: EOF

从错误日志判断来看,是Master上的kubelet在与同一节点上的kube-apiserver通信过程中,发现这个apiserver返回的tls证书不对(因为此node上的证书是从其他node上拷贝过来的)
待解决:

6、kubeadm ini初始化报错

[root@test4 init]# kubeadm init --config kubeadm-config.yaml
I0115 10:59:07.105432     903 version.go:94] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable.txt": Get https://dl.k8s.io/release/stable.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
I0115 10:59:07.105540     903 version.go:95] falling back to the local client version: v1.13.0
[init] Using Kubernetes version: v1.13.0
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:[ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists[ERROR Port-10250]: Port 10250 is in use
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`

解决办法:



拆除

要撤消什么kubeadm做,你应该先排出节点,并确保该节点将其关闭之前是空的。
使用适当的凭证与控制平面节点通信,请运行:

驱逐节点
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
恢复节点
kubectl uncordon  <node name>
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
kubectl delete node <node name>

然后,在要删除的节点上,重置所有kubeadm安装状态:

kubeadm reset

reset之后提示以下信息

[reset] Deleting contents of stateful directories: [/var/lib/etcd /var/lib/kubelet /var/lib/dockershim /var/run/kubernetes /var/lib/cni]The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.dThe reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.

重置过程不会重置或清除iptables规则或IPVS表。如果您希望重置iptables,则必须手动进行:

iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

如果要重置IPVS表,则必须运行以下命令:

ipvsadm -C

如果您想重新开始,只需运行kubeadm init或kubeadm join使用适当的参数即可。



删除干净k8s

systemctl stop kubelet
yum remove -y kubelet kubeadm kubectl kubernetes-cnimodprobe -r ipip
#Linux lsmod命令用于显示已载入系统的模块。
lsmod

Module:模块的名称。 这通常是模块文件的名称,减去扩展名(.o或.ko),但它可能有一个自定义名称,可以在使用insmod命令插入模块时将其指定为选项。
Size:驻留模块使用的内存量,以字节为单位。
Used by:此列包含一个数字,表示正在使用的模块实例数。 如果该数字为零,则当前未使用该模块。 数字后面的文本表示有关使用模块的内容的任何可用信息:这通常是设备名称,文件系统标识符或另一个模块的名称。

rm -rf ~/.kube/
rm -rf /etc/kubernetes/
rm -rf /etc/systemd/system/kubelet.service.d
rm -rf /etc/systemd/system/kubelet.service
rm -rf /usr/bin/kube*
rm -rf /etc/cni
rm -rf /opt/cni
rm -rf /var/lib/etcd
rm -rf /var/etcd

再次安装k8s1.13版本

yum install -y kubelet-1.13.0 kubeadm-1.13.0 kubectl-1.13.0 kubernetes-cni-0.6.0

本文涉及的相应的文件

kube-flannel-rbac.yml(文件内容)

[root@test4 flannel]# cat kube-flannel-rbac.yml
# Create the clusterrole and clusterrolebinding:
# $ kubectl create -f kube-flannel-rbac.yml
# Create the pod using the same namespace used by the flannel serviceaccount:
# $ kubectl create --namespace kube-system -f kube-flannel-legacy.yml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: flannel
rules:- apiGroups:- ""resources:- podsverbs:- get- apiGroups:- ""resources:- nodesverbs:- list- watch- apiGroups:- ""resources:- nodes/statusverbs:- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: flannel
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: flannel
subjects:- kind: ServiceAccountname: flannelnamespace: kube-system

kube-flannel.yml(文件内容)

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: flannel
rules:- apiGroups:- ""resources:- podsverbs:- get- apiGroups:- ""resources:- nodesverbs:- list- watch- apiGroups:- ""resources:- nodes/statusverbs:- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: flannel
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: flannel
subjects:
- kind: ServiceAccountname: flannelnamespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:name: flannelnamespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:name: kube-flannel-cfgnamespace: kube-systemlabels:tier: nodeapp: flannel
data:cni-conf.json: |{"name": "cbr0","plugins": [{"type": "flannel","delegate": {"hairpinMode": true,"isDefaultGateway": true}},{"type": "portmap","capabilities": {"portMappings": true}}]}net-conf.json: |{"Network": "10.244.0.0/16","Backend": {"Type": "vxlan"}}
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:name: kube-flannel-ds-amd64namespace: kube-systemlabels:tier: nodeapp: flannel
spec:template:metadata:labels:tier: nodeapp: flannelspec:hostNetwork: truenodeSelector:beta.kubernetes.io/arch: amd64tolerations:- operator: Existseffect: NoScheduleserviceAccountName: flannelinitContainers:- name: install-cniimage: quay.io/coreos/flannel:v0.10.0-amd64command:- cpargs:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistvolumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/containers:- name: kube-flannelimage: quay.io/coreos/flannel:v0.10.0-amd64command:- /opt/bin/flanneldargs:- --ip-masq- --kube-subnet-mgrresources:requests:cpu: "100m"memory: "50Mi"limits:cpu: "100m"memory: "50Mi"securityContext:privileged: trueenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespacevolumeMounts:- name: runmountPath: /run- name: flannel-cfgmountPath: /etc/kube-flannel/volumes:- name: runhostPath:path: /run- name: cnihostPath:path: /etc/cni/net.d- name: flannel-cfgconfigMap:name: kube-flannel-cfg
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:name: kube-flannel-ds-arm64namespace: kube-systemlabels:tier: nodeapp: flannel
spec:template:metadata:labels:tier: nodeapp: flannelspec:hostNetwork: truenodeSelector:beta.kubernetes.io/arch: arm64tolerations:- operator: Existseffect: NoScheduleserviceAccountName: flannelinitContainers:- name: install-cniimage: quay.io/coreos/flannel:v0.10.0-arm64command:- cpargs:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistvolumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/containers:- name: kube-flannelimage: quay.io/coreos/flannel:v0.10.0-arm64command:- /opt/bin/flanneldargs:- --ip-masq- --kube-subnet-mgrresources:requests:cpu: "100m"memory: "50Mi"limits:cpu: "100m"memory: "50Mi"securityContext:privileged: trueenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespacevolumeMounts:- name: runmountPath: /run- name: flannel-cfgmountPath: /etc/kube-flannel/volumes:- name: runhostPath:path: /run- name: cnihostPath:path: /etc/cni/net.d- name: flannel-cfgconfigMap:name: kube-flannel-cfg
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:name: kube-flannel-ds-armnamespace: kube-systemlabels:tier: nodeapp: flannel
spec:template:metadata:labels:tier: nodeapp: flannelspec:hostNetwork: truenodeSelector:beta.kubernetes.io/arch: armtolerations:- operator: Existseffect: NoScheduleserviceAccountName: flannelinitContainers:- name: install-cniimage: quay.io/coreos/flannel:v0.10.0-armcommand:- cpargs:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistvolumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/containers:- name: kube-flannelimage: quay.io/coreos/flannel:v0.10.0-armcommand:- /opt/bin/flanneldargs:- --ip-masq- --kube-subnet-mgrresources:requests:cpu: "100m"memory: "50Mi"limits:cpu: "100m"memory: "50Mi"securityContext:privileged: trueenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespacevolumeMounts:- name: runmountPath: /run- name: flannel-cfgmountPath: /etc/kube-flannel/volumes:- name: runhostPath:path: /run- name: cnihostPath:path: /etc/cni/net.d- name: flannel-cfgconfigMap:name: kube-flannel-cfg
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:name: kube-flannel-ds-ppc64lenamespace: kube-systemlabels:tier: nodeapp: flannel
spec:template:metadata:labels:tier: nodeapp: flannelspec:hostNetwork: truenodeSelector:beta.kubernetes.io/arch: ppc64letolerations:- operator: Existseffect: NoScheduleserviceAccountName: flannelinitContainers:- name: install-cniimage: quay.io/coreos/flannel:v0.10.0-ppc64lecommand:- cpargs:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistvolumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/containers:- name: kube-flannelimage: quay.io/coreos/flannel:v0.10.0-ppc64lecommand:- /opt/bin/flanneldargs:- --ip-masq- --kube-subnet-mgrresources:requests:cpu: "100m"memory: "50Mi"limits:cpu: "100m"memory: "50Mi"securityContext:privileged: trueenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespacevolumeMounts:- name: runmountPath: /run- name: flannel-cfgmountPath: /etc/kube-flannel/volumes:- name: runhostPath:path: /run- name: cnihostPath:path: /etc/cni/net.d- name: flannel-cfgconfigMap:name: kube-flannel-cfg
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:name: kube-flannel-ds-s390xnamespace: kube-systemlabels:tier: nodeapp: flannel
spec:template:metadata:labels:tier: nodeapp: flannelspec:hostNetwork: truenodeSelector:beta.kubernetes.io/arch: s390xtolerations:- operator: Existseffect: NoScheduleserviceAccountName: flannelinitContainers:- name: install-cniimage: quay.io/coreos/flannel:v0.10.0-s390xcommand:- cpargs:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.conflistvolumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/containers:- name: kube-flannelimage: quay.io/coreos/flannel:v0.10.0-s390xcommand:- /opt/bin/flanneldargs:- --ip-masq- --kube-subnet-mgrresources:requests:cpu: "100m"memory: "50Mi"limits:cpu: "100m"memory: "50Mi"securityContext:privileged: trueenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespacevolumeMounts:- name: runmountPath: /run- name: flannel-cfgmountPath: /etc/kube-flannel/volumes:- name: runhostPath:path: /run- name: cnihostPath:path: /etc/cni/net.d- name: flannel-cfgconfigMap:name: kube-flannel-cfg

阿里云镜像源

registry.cn-hangzhou.aliyuncs.com/google_containers/

centos7:Kubernetes高可用集群安装部署(版本1.13)——堆叠的控制平面和etcd节点/外部etcd节点相关推荐

  1. 使用kubeadm安装kubernetes高可用集群

    kubeadm安装kubernetes高可用集群搭建  第一步:首先搭建etcd集群 yum install -y etcd 配置文件 /etc/etcd/etcd.confETCD_NAME=inf ...

  2. k8s1.18多master节点高可用集群安装-超详细中文官方文档

    kubernetes安装系列文章 kubernetes1.17.3安装-超详细的安装步骤 安装kubernetes1.17.3多master节点的高可用集群 k8s1.18单master节点高可用集群 ...

  3. 二进制方式搭建Kubernetes高可用集群(超丰富的组件概念理论总结)

    二进制方式部署Kubernetes高可用集群 文章目录 二进制方式部署Kubernetes高可用集群 1.环境准备 1.1.Kubernetes高可用集群部署方式 1.2.Kubernetes集群弃用 ...

  4. 容器编排——Kubeadm在线或离线搭建kubernetes高可用集群

    目录 1.架构简介: 2.集群架构图: 3.集群服务器: 4.修改主机名称: 5.修改hosts配置文件: 6.关闭selinux: 7.关闭防火墙: 8.关闭swap: 9.设置iptables网桥 ...

  5. 记一次 Centos7.x Hadoop3.x集群安装部署 Pig 0.17.0

    基本信息 官网 http://pig.apache.org/ 下载地址 http://www.apache.org/dyn/closer.cgi/pig https://mirror.bit.edu. ...

  6. Nacos高可用集群解决方案-Docker版本

    Nacos高可用集群解决方案-Docker版本 参考文章: (1)Nacos高可用集群解决方案-Docker版本 (2)https://www.cnblogs.com/hellxz/p/nacos-c ...

  7. 一键部署Kubernetes高可用集群

    三台master,四台node,系统版本为CentOS7 IP ROLE 172.60.0.226 master01 172.60.0.86 master02 172.60.0.106 master0 ...

  8. docker 如何加入kubernetes_使用 Kind 在 5 分钟内快速部署一个 Kubernetes 高可用集群...

    什么是 Kind Kind(Kubernetes in Docker) 是一个Kubernetes孵化项目,Kind是一套开箱即用的Kubernetes环境搭建方案.顾名思义,就是将Kubernete ...

  9. k8s高可用集群搭建部署

    简介 k8s普通搭建出来只是单master节点,如果该节点挂掉,则整个集群都无法调度,K8s高可用集群是用多个master节点加负载均衡节点组成,外层再接高可用分布式存储集群例如ceph集群,实现计算 ...

  10. K8S高可用集群架构部署 dashborad插件部署 Nginx实现动静分离 K8S在线升级

    K8S官方文档 注意:该集群每个master节点都默认由kubeadm生成了etcd容器,组成etcd集群.正常使用集群,etcd的集群不能超过一半为down状态. docker的namespace: ...

最新文章

  1. matlab7.1(ERROR STARTING DESKTOP)解决
  2. 软件开发管理规范流程图
  3. linux怎么进入root文件,linux下安装ROOT过程
  4. 2020年AI怎么发展?听加州大学、谷歌、英伟达、IBM怎么说
  5. [文摘]Maven安装jar包的命令
  6. mysql+翻页性能,mysql 翻页优化
  7. leetcode算法题--合并两个排序的链表
  8. c# 泛型有什么作用?
  9. lda主题评论文本python_利用python做LDA文本分析,该从哪里入手呢?
  10. boost::hana::always用法的测试程序
  11. Activiti 接收任务活动
  12. c++基础学习(10)--(文件、流、异常处理、动态内存、命名空间)
  13. 到底什么是“无源物联网”?
  14. Linux面试题(总结最全面的面试题!!!)
  15. 关于sourcetree这是一个无效源路径的解决办法
  16. 二等分计算机打印机尺寸,241两等分打印纸尺寸 电脑打印纸,规格241mm等份是2等份,是多大的纸呀?...
  17. Linux的编辑器、编译器、配置文件、及其安装方法的理解
  18. 用metasploit(msf)复现MS17-010(经典的永恒之蓝)SMB漏洞
  19. Python下selenium的get()方法大量时间超时报错TimeOut
  20. 电脑钢琴模拟器(初学WINDOW库)

热门文章

  1. 2021级新生个人训练赛第23场 问题 A: 朋友
  2. 基于Linux的SPI驱动框架源码分析(全文3万字)
  3. aue4格式如何打开
  4. 爱不是施舍,唯独爱不应该施舍。
  5. 2023最详细的Selenium+Pytest自动化测试框架实战,零基础能看懂
  6. win2000/xp忘记密码的方法(转)
  7. 《Android-查看手机内CPU手机型号设备信息等以及adb常用命令》---记录几个命令
  8. python不允许标点符号_Python处理中文标点符号大集合
  9. 手动集成Tencent SDK遇到的坑!!!
  10. AudioRecorder实时录制mp3格式音频