Kubernetes集群安装

Kubernetes集群安装

环境准备

192.168.1.53 k8s-master

192.168.1.52 k8s-node-1

192.168.1.51 k8s-node-2

设置三台机器的主机名:

Master上执行:
[root@localhost ~]#  hostnamectl --static set-hostname  k8s-masterNode1上执行:
[root@localhost ~]# hostnamectl --static set-hostname  k8s-node-1Node2上执行:
[root@localhost ~]# hostnamectl --static set-hostname  k8s-node-2

在三台机器上设置hosts,均执行如下命令:

echo '192.168.1.53    k8s-master
192.168.1.53    etcd
192.168.1.53    registry
192.168.1.52    k8s-node-1
192.168.1.51    k8s-node-2' >> /etc/hostscat /etc/hosts

关闭三台机器上的防火墙

systemctl disable firewalld.service
systemctl stop firewalld.service

安装相关工具
k8s-master k8s-node-1 k8s-node-2 上都执行

yum install -y kubelet kubeadm kubectl kubernetes-cni
可能不能访问源,添加源#docker yum源
cat >> /etc/yum.repos.d/docker.repo <<EOF
[docker-repo]
name=Docker Repository
baseurl=http://mirrors.aliyun.com/docker-engine/yum/repo/main/centos/7
enabled=1
gpgcheck=0
EOF#kubernetes yum源
cat >> /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
EOFvim /etc/resolv.conf 最后增加
nameserver 8.8.8.8yum install -y kubelet kubeadm kubectl kubernetes-cni# kubectl delete node --all卸载 sudo yum remove kubelet kubeadm kubectl kubernetes-cni
kubelet --version
kubeadm version
systemctl enable docker.service
systemctl enable kubelet.servicesystemctl start kubelet
systemctl status kubelet 查看状态 启动失败
禁用SELinux,让容器可以读取主机文件系统
setenforce 0
vim /etc/sysconfig/selinux
SELINUX=disabled

和docker vim /usr/lib/systemd/system/docker.service的用户systemd一致就可以了,不需要修改
–exec-opt native.cgroupdriver=systemd

在k8s-master上执行

kubeadm init --apiserver-advertise-address=192.168.1.53 --kubernetes-version=v1.11.3 --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=swap 执行报错echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptablessystemctl enable docker.service 有警告的
systemctl enable kubelet.service 有警告的 

k8s-master 上执行------------参看node的这个文件配置,这里有的配置可能多余-------

vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf  
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"
Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin"
Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt"
Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
Environment="KUBELET_EXTRA_ARGS=--fail-swap-on=false"
Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true --cert-dir=/var/lib/kubelet/pki"
#Environment="KUBELET_EXTRA_ARGS=--v=2 --fail-swap-on=false --pod-infra-container-image=k8s.gcr.io/pause-amd64:3.1"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
#EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGSsystemctl daemon-reload
systemctl start kubelet
systemctl status kubelet
journalctl -xefu kubelet 查看日志添加下载源
cat /etc/docker/daemon.json 
{"registry-mirrors": ["http://68e02ab9.m.daocloud.io"]
}
systemctl restart docker

https://hub.docker.com/r/warrior/

先下载镜像  -----------使用下面的镜像版本,这里版本不对应-----

docker pull warrior/pause-amd64:3.0
docker tag warrior/pause-amd64:3.0 gcr.io/google_containers/pause-amd64:3.0
docker pull warrior/etcd-amd64:3.0.17
docker tag warrior/etcd-amd64:3.0.17 gcr.io/google_containers/etcd-amd64:3.0.17
docker pull warrior/kube-apiserver-amd64:v1.6.0
docker tag warrior/kube-apiserver-amd64:v1.6.0 gcr.io/google_containers/kube-apiserver-amd64:v1.6.0
docker pull warrior/kube-scheduler-amd64:v1.6.0
docker tag warrior/kube-scheduler-amd64:v1.6.0 gcr.io/google_containers/kube-scheduler-amd64:v1.6.0
docker pull warrior/kube-controller-manager-amd64:v1.6.0docker tag warrior/kube-controller-manager-amd64:v1.6.0 gcr.io/google_containers/kube-controller-manager-amd64:v1.6.0
docker pull warrior/kube-proxy-amd64:v1.6.0
docker tag warrior/kube-proxy-amd64:v1.6.0  gcr.io/google_containers/kube-proxy-amd64:v1.6.0docker pull gysan/dnsmasq-metrics-amd64:1.0
docker tag gysan/dnsmasq-metrics-amd64:1.0 gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
docker pull warrior/k8s-dns-kube-dns-amd64:1.14.1
docker tag warrior/k8s-dns-kube-dns-amd64:1.14.1 gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.1docker pull warrior/k8s-dns-dnsmasq-nanny-amd64:1.14.1
docker tag warrior/k8s-dns-dnsmasq-nanny-amd64:1.14.1 gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.1
docker pull warrior/k8s-dns-sidecar-amd64:1.14.1
docker tag warrior/k8s-dns-sidecar-amd64:1.14.1 gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.1 
docker pull awa305/kube-discovery-amd64:1.0 
docker tag awa305/kube-discovery-amd64:1.0 gcr.io/google_container/kube-discovery-amd64:1.0 
docker pull gysan/exechealthz-amd64:1.2
docker tag gysan/exechealthz-amd64:1.2 gcr.io/google_container/exechealthz-amd64:1.2kubeadm init --apiserver-advertise-address=192.168.1.53 --kubernetes-version=v1.11.3 --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=allkubeadm config images list --kubernetes-version=v1.11.3
三台机器上下载镜像 ----------------------------------------------------
docker pull mirrorgooglecontainers/kube-apiserver-amd64:v1.11.3
docker tag  mirrorgooglecontainers/kube-apiserver-amd64:v1.11.3 k8s.gcr.io/kube-apiserver-amd64:v1.11.3
docker pull mirrorgooglecontainers/kube-controller-manager-amd64:v1.11.3
docker tag mirrorgooglecontainers/kube-controller-manager-amd64:v1.11.3 k8s.gcr.io/kube-controller-manager-amd64:v1.11.3
docker pull mirrorgooglecontainers/kube-scheduler-amd64:v1.11.3
docker tag mirrorgooglecontainers/kube-scheduler-amd64:v1.11.3 k8s.gcr.io/kube-scheduler-amd64:v1.11.3
docker pull mirrorgooglecontainers/etcd-amd64:3.2.18
docker tag mirrorgooglecontainers/etcd-amd64:3.2.18 k8s.gcr.io/etcd-amd64:3.2.18docker pull mirrorgooglecontainers/kube-proxy-amd64:v1.11.3 
docker tag mirrorgooglecontainers/kube-proxy-amd64:v1.11.3  k8s.gcr.io/kube-proxy-amd64:v1.11.3     
docker pull mirrorgooglecontainers/pause:3.1 
docker tag mirrorgooglecontainers/pause:3.1  k8s.gcr.io/pause:3.1
docker pull mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.10.0
docker tag mirrorgooglecontainers/kubernetes-dashboard-amd64:v1.10.0 k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0
docker pull coredns/coredns:1.1.3
docker tag coredns/coredns:1.1.3  k8s.gcr.io/coredns:1.1.3
docker pull mirrorgooglecontainers/k8s-dns-sidecar-amd64:1.14.11
docker tag mirrorgooglecontainers/k8s-dns-sidecar-amd64:1.14.11 k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.11
docker pull mirrorgooglecontainers/k8s-dns-kube-dns-amd64:1.14.11
docker tag mirrorgooglecontainers/k8s-dns-kube-dns-amd64:1.14.11 k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.11
docker pull mirrorgooglecontainers/pause-amd64:3.1
docker tag mirrorgooglecontainers/pause-amd64:3.1 k8s.gcr.io/pause-amd64:3.1出现如下信息,表示安装成功
kubeadm join 192.168.1.53:6443 --token e1d3u3.ilw4fb5cpt51xjf0 --discovery-token-ca-cert-hash sha256:72d07cb010102ae7f1733753a1ac07d0a402125f3326a41056174c69de6fe228安装成功后,按提示执行下面命令                                
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

k8s-node-1 k8s-node-2执行

echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptableskubeadm join 192.168.1.53:6443 --token e1d3u3.ilw4fb5cpt51xjf0 --discovery-token-ca-cert-hash sha256:72d07cb010102ae7f1733753a1ac07d0a402125f3326a41056174c69de6fe228 --ignore-preflight-errors=swap因为测试主机上还运行其他服务,关闭swap可能会对其他服务产生影响,所以这里修改kubelet的启动参数 --fail-swap-on=false 去掉这个限制
vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf  
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local"
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
Environment="KUBELET_EXTRA_ARGS=--fail-swap-on=false"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
#EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_DNS_ARGS $KUBELET_CGROUP_ARGS $KUBELET_EXTRA_ARGSsystemctl daemon-reload 
systemctl start kubelet 启动失败没有关系 执行下面命令会去启动 生成配置文件 
kubeadm join 192.168.1.53:6443 --token e1d3u3.ilw4fb5cpt51xjf0 --discovery-token-ca-cert-hash sha256:72d07cb010102ae7f1733753a1ac07d0a402125f3326a41056174c69de6fe228 --ignore-preflight-errors=swap然后查看状态启动成功了
systemctl status kubelet
journalctl -xefu kubelet 查看日志

master 上执行

https://blog.csdn.net/zhuchuangang/article/details/76572157/ 参考 安装flannel

kubectl get nodes 状态为NotReady 网络不通mkdir /docker
cd /docker/
kubectl --namespace kube-system apply -f https://raw.githubusercontent.com/coreos/flannel/v0.8.0/Documentation/kube-flannel-rbac.ymlwget https://raw.githubusercontent.com/coreos/flannel/v0.8.0/Documentation/kube-flannel.yml
yum -y install wgetcat kube-flannel.yml 
---
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","type": "flannel","delegate": {"isDefaultGateway": true}}net-conf.json: |{"Network": "10.244.0.0/16","Backend": {"Type": "vxlan"}}
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:name: kube-flannel-dsnamespace: kube-systemlabels:tier: nodeapp: flannel
spec:template:metadata:labels:tier: nodeapp: flannelspec:hostNetwork: truenodeSelector:beta.kubernetes.io/arch: amd64tolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoScheduleserviceAccountName: flannelcontainers:- name: kube-flannelimage: quay.io/coreos/flannel:v0.8.0-amd64command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ]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/- name: install-cniimage: quay.io/coreos/flannel:v0.8.0-amd64command: [ "/bin/sh", "-c", "set -e -x; cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/10-flannel.conf; while true; do sleep 3600; done" ]volumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/volumes:- name: runhostPath:path: /run- name: cnihostPath:path: /etc/cni/net.d- name: flannel-cfgconfigMap:name: kube-flannel-cfgkubectl --namespace kube-system apply -f ./kube-flannel.yml
kubectl get cskubectl get nodes 过一会状态为Ready了

参考链接:
https://blog.csdn.net/zhuchuangang/article/details/76572157/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/12071.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3+vite项目部署服务器,选择非根目录访问

背景 vue3vite项目&#xff0c;需要部署服务器。 但是根目录已经部署了另外一个项目A了&#xff0c;这个时候要在部署另外一个项目B。 问题 比如你的地址是http://test.com 之前直接输入http://test.com即可访问A项目 如果B项目也这么干的话就冲突了 访问A&#xff1a;http…

哪款骨传导耳机最值得入手?精选5款顶尖配置的骨传导耳机,闭眼入也不踩雷!

作为一名有着多年工作经验的数码博主&#xff0c;我见证了无数因盲目追求新颖而引发的听力问题。在此&#xff0c;我必须郑重提醒大家&#xff0c;虽然市面上充斥着众多声称能提供卓越音质和佩戴舒适度的骨传导耳机品牌&#xff0c;但它们之间存在大量劣质产品&#xff0c;这类…

centos7安装zabbix-server

zabbixan-server安装 环境安装zabbix安装zabbix配置apachezabbix-UI前端配置修改zabbix为中文语言 环境 准备&#xff1a; centos7系统、mysql数据库/MariaDB数据库 mysql数据库可参照&#xff1a;https://blog.csdn.net/weixin_61367575/article/details/138774428?spm1001.…

算法-卡尔曼滤波之卡尔曼滤波的第二个方程:预测方程(状态外推方程)

在上一节中&#xff0c;使用了静态模型&#xff0c;我们推导出了卡尔曼滤波的状态更新方程&#xff0c;但是在实际情况下&#xff0c;系统都是动态&#xff0c;预测阶段&#xff0c;前后时刻的状态是改变的&#xff0c;此时我们引入预测方程&#xff0c;也叫状态外推方程&#…

企业为什么进行大数据迁移以及注意事项

在当今数字化时代&#xff0c;数据的迁移成为了企业优化其数据架构、提高数据处理能力、确保业务连续性和数据安全的关键步骤。企业可能出于多种原因&#xff0c;如成本效益、性能提升、系统升级、数据集中管理或云服务集成等&#xff0c;选择将数据从一个存储系统迁移到另一个…

Spring Boot 整合讯飞星火3.5通过接口Api接口实现聊天功能(首发)复制粘贴即可使用,后续更新WebSocket实现聊天功能

程序员必备网站&#xff1a; 天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/ 1.pom.xml <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.72</version></dependency><depen…

html5关于WebSocket的一些特点与用例

WebSocket通信机制是一种在单个TCP连接上进行全双工通信的协议&#xff0c;它允许服务器主动向客户端推送数据&#xff0c;而无需等待客户端的请求。以下是WebSocket通信的主要机制&#xff1a; 握手协议&#xff1a;WebSocket通信的第一步是通过HTTP协议进行握手。当客户端发…

C++ QT设计模式:访问者模式

基本概念 访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许你在不改变被访问类的前提下&#xff0c;定义对其进行操作的新操作。 实现的模块有&#xff1a; ObjectStructure&#xff08;对象结构&#xff09;&#xff1a;用于存储…

轻松拿下指针(5)

文章目录 一、回调函数是什么二、qsort使用举例三、qsort函数的模拟实现 一、回调函数是什么 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当这个指针被⽤来调⽤其所指向的函数 时&#x…

计算模型的边界

https://github.com/libigl/libigl.git 这是几何计算库&#xff0c;可以计算出模型的边界 #define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <igl/boundary_loop.h>#include <igl/list_to_matrix.h>int main(){std::vector<std::vector<…

肺部营养“救星”,让每次呼吸更自由

​#肺科营养#朗格力#班古营养#复合营养素#肺部营养# 正常的健康人,每天自由幸福的呼吸。但是对于肺病患者来说,特别是慢阻肺人群,每一次呼吸都可能是一场挑战,每一口气都显得弥足珍贵。 肺病患者号称沉默的“呼吸杀手”,它虽然沉默,但不代表它没能力,除了引起肺功能下降,氧气…

云商店如何让更多企业摘到技术普惠的“果实”?

文 | 智能相对论 作者 | 沈浪 现阶段&#xff0c;越是工业体系发达的地区&#xff0c;越需要加速技术普惠的步伐。比如&#xff0c;在苏州&#xff0c;华为云就在联合当地政府、企业伙伴打造以华为云云商店为重要链接的智能化商业增长底座。 华为云云商店以“电商式”的购物…

Git学习——迁移单一仓库至其他代码托管平台

Git学习——迁移单一仓库至其他代码托管平台 简介流程总结 简介 因需迁移单一代码仓库至其他代码托管平台&#xff0c;要迁移的包括仓库内容以及所有历史记录和推送日志。 本文中的方法同样适用于在同一代码托管平台中克隆仓库。 流程 1. 创建新仓库&#xff1a; 在目的平台…

软件需求规格文档 (SRS) 模版

文章目录 软件需求规格文档 (SRS) - 范例1. 引言1.1 目的1.2 范围1.3 定义、缩写和术语1.4 参考文献1.5 总体描述 2. 系统概述2.1 系统环境2.2 系统功能概述2.3 用户特性2.4 假设与约束 3. 功能需求3.1 用户身份验证模块3.1.1 总体概述3.1.2 具体需求3.1.2.1 登录功能描述3.1.2…

OpenAI春季发布会-免费多模态GPT4O-简介

前言 2024.5.14&#xff0c;OpenAI宣布即将发布一款性能更为强大的大模型GPT4o&#xff0c;虽然没有爆出些超级酷炫无敌吊炸天的新玩意&#xff0c;但是这次的多模态模型&#xff0c;大家可以免费用了~~&#xff08;但是&#xff09; 虽然是免费使用&#xff0c;但官方发布会上…

逆向学习记录--第一天

NSSCTF工坊逆向综合基础第二题 考查知识点&#xff1a;ida的使用与编程能力 wp&#xff1a; 运行一下&#xff0c;没有东西&#xff1b; 查壳是64位&#xff0c;没有壳 直接ida打开 代码解析&#xff1a;输入flag&#xff0c;对flag进行用key进行轮换之后再加12&#xff…

鸿蒙 DevEcoStudio:用户名密码获取保存

【使用首选项实现用户名密码保存获取】 打开src/main/ets/entryability路径下的EntryAbility.ts文件 在 export default class EntryAbility extends UIAbility {onCreate(want, launchParam) {hilog.info(0x0000, testTag, %{public}s, Ability onCreate);下边添加内容&…

C++:左值(引用)右值(引用)

〇、前言 本文会讨论C中的左值&#xff0c;右值&#xff0c;左值引用&#xff0c;右值引用&#xff0c;以及会理清它们之间的关系。 一、左值与右值 &#xff08;一&#xff09;概述 1. 左值是一般指表达式结束后依然存在的持久化对象。右值指表达式结束时就不再存在的临时…

334_C++_std::bind中使用shared_from_this()

std::bind(&HttpClient::getPwd, shared_from_this(), std::placeholders::_1, std::placeholders::_2);[ HttpClient继承自NetObj,NetObj是父类,NetObj受到std::shared_pt

分析 vs2019 c++ 中的 decltype 与 declval

&#xff08;1&#xff09; decltype 可以让推断其参数的类型。按住 ctrl 点击 decltype &#xff0c;会发现无法查阅 其定义 &#xff1a; &#xff08;2&#xff09; 但 STL 库里咱们可以查阅函数 declval 的 定义&#xff0c;很短&#xff0c;摘抄如下&#xff1a; templat…