K8s的生态这两年越来越复杂,但搭建一套能"日常用起来"的集群,门槛仍然卡在不少细节上——版本兼容、初始化参数、网络插件、晚一个组件就来回报错。我前后帮几个团队搭过环境,也自己反复重装过很多次,最终形成了一个比较固定的套路:原生 Kubernetes 集群用 kubeadm 初始化,然后在其上叠加 KubeSphere,用它的控制台统一管理节点、项目、存储和权限。本文就是这份完整过程的整理。无论你是第一次装,还是已经装过但因为某个环节失败想找个对照,都能按步骤走通。我会尽量把每一步的"为什么"也讲清楚,而不是只是丢命令。
1. 为什么选这套组合:原生K8s和KubeSphere的分工逻辑
1.1 原生K8s只解决调度,不解决"日常操作"
很多人第一次接触 Kubernetes,是被它的概念和生态吸引的:Pod、Deployment、Service、Ingress,听起来很强大。但真正装完一个裸集群之后,你会发现原生的东西并没有解决你"日常操作"的体验问题。
比如说,你要看一个工作负载日志,通常得先用 kubectl 拿到 Pod 名称,再kubectl logs -f pod/xxx。你要看节点状态,得kubectl get nodes -o wide然后盯着终端。要让团队里多个同事共用集群,还得手动处理 RBAC、Namespace、配额这些,每个用户发 kubeconfig,操作非常原始。
这不是说 Kubernetes 不好——它的调度和编排引擎非常可靠。但它的定位是"基础设施底座",不是一个开箱即用的"操作平台"。打个比方:K8s 是发电厂,能稳定供电,但你需要一个配电箱来分流、管理、查看每户用电量。工作负载跑起来了只是第一步,接下来怎么观察、怎么管、怎么限制资源,才是日常运营的重点。
1.2 KubeSphere补上的那一块:控制台、多租户、可插拔组件
KubeSphere 就是一个清晰的配电箱。它的定位简单直接:在已有的 Kubernetes 集群上装一套管理平台,把最常用的能力完整覆盖掉。
- 统一的 Web 控制台,不用每个人都装 kubectl、记命令。
- 多租户体系:企业空间、项目、账号、角色分层,天然适合多人协作。
- 可插拔组件:监控、日志、告警、审计、服务网格、DevOps 流水线,都是独立组件,按需开启。
- 中文界面,对国内团队尤其友好。
这套组合的核心价值是:K8s 负责"能跑",KubeSphere 负责"好用"。生产环境交付时,很多团队也确实会把运维平台直接放在集群里,因为 KubeSphere 本身就是作为容器应用跑在上面的,不额外占用物理资源,只占 Pod 资源。
1.3 适合场景与不适合场景
先说适合谁:中小型团队,想在物理机或云主机上自建一套"能上生产但不折腾"的容器平台;有预算但不想自己写监控、告警模块的团队;需要给多个业务线做资源隔离但又要统一管理入口的平台运维组。也适合刚入门 K8s 的学习者,因为你装完之后有一个界面可以"看到"整个集群状态,理解起来比纯命令行直观得多。
不太适合的场景:如果你是极简主义者,只需要跑两三个静态服务,那原生 K8s 都算过度设计,更不需要 KubeSphere;如果你要做超大规模集群(几千节点以上)深度调优,那 KubeSphere 对这类场景的定制能力不如直接动 K8s 源码和配置来得直接。
确定用这套方案之后,下面的部署过程就完全围绕它展开。
2. 主机规划与系统初始化:提前三十分钟,少踩三小时的坑
2.1 节点规划与版本组合
我这次用的标准配置是三台机器:一台作为 control-plane(控制平面),另外两台作为 worker。你也可以把三台全部作为 control-plane 做高可用,但那是生产进阶玩法,本文先从最小可用模型开始。
下表是一个常见的规划模板,仅供参照,生产环境请按实际资源调整:
| 节点角色 | 主机名建议 | 配置建议 | 磁盘规划 |
|---|---|---|---|
| control-plane | k8s-master | 4C8G | 系统盘50G + 数据盘100G |
| worker-1 | k8s-node1 | 8C16G | 系统盘50G + 数据盘200G |
| worker-2 | k8s-node2 | 8C16G | 系统盘50G + 数据盘200G |
操作系统我建议统一用较新的稳定发行版。我实测过 CentOS 7 的环境,坑比较多,尤其 systemd 版本、iptables 相关行为会和现代 K8s 产生兼容问题。如果你手头不是旧系统,直接选新版本更好。
版本组合方面,以下是我验证过可直接跑通的组合(也是目前社区常用组合):
- Kubernetes v1.28.x(kubeadm、kubelet、kubectl 三件套同版本)
- containerd 1.7.x 作为容器运行时
- Calico v3.27.x 作为网络插件
- KubeSphere v3.4.x 对应 Kubernetes 版本兼容良好
一个需要提前建立的认知:Kubernetes 从某个版本开始,已经不再支持 Docker 作为默认运行时,除非你额外安装 cri-dockerd 适配层。实际工作中我建议直接用 containerd,省一层转换,性能损失也更小。
2.2 三台机器统一的系统初始化操作
以下初始化操作,三台机器都要执行。别看这些步骤琐碎,少了任何一个,后面都会以"莫名其妙的网络不通""初始化失败"等形式找上门。
关闭交换分区
Kubernetes 对 swap 的态度是默认不支持。kubeadm 初始化时会检查节点是否开启了 swap,开启则直接报错。生产实践中关闭 swap 也说得通:Pod 内存配额需要精确控制,swap 会干扰 Pod 内存回收行为。
swapoff -a sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab配置内核模块与网络参数
容器网络依赖内核的桥接防火墙和 overlay 网络模块,必须提前加载。配置文件放在/etc/modules-load.d/k8s.conf:
cat > /etc/modules-load.d/k8s.conf <<EOF overlay br_netfilter EOF modprobe overlay modprobe br_netfilter接着写入网络参数/etc/sysctl.d/k8s.conf,并使其生效:
cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system这些参数的作用是让 Pod 之间的流量经过 iptables 规则时能被正确转发。net.ipv4.ip_forward尤其关键:如果为 0,Pod 出网流量会被内核丢弃,Ping 不通外网、DNS 解析失败这类问题会接踵而来。
防火墙与安全策略
我通常建议在测试环境直接关闭防火墙,减少干扰:
systemctl stop firewalld && systemctl disable firewalld systemctl stop ufw 2>/dev/null; systemctl disable ufw 2>/dev/null生产环境不要照抄这一步。正确姿势是放行以下端口:
| 协议 | 端口 | 用途 |
|---|---|---|
| TCP | 6443 | Kubernetes API Server |
| TCP | 2379-2380 | etcd 客户端通信 |
| TCP | 10250 | kubelet API |
| TCP | 30000-32767 | NodePort 服务端口 |
| TCP/UDP | 8472 | Calico VXLAN |
| TCP | 30880 | KubeSphere 控制台(后文会用到) |
设置 hosts 与免密登录
三台机器互相解析主机名,避免后续加入集群时因 DNS 解析失败导致证书 SAN 校验出问题。修改/etc/hosts,示例:
cat >> /etc/hosts <<EOF 192.168.10.10 k8s-master 192.168.10.11 k8s-node1 192.168.10.12 k8s-node2 EOFSSH 免密登录不是必须的,但强烈建议配置。因为后面会有一些操作需要在主节点向子节点分发配置或验证状态,免密可以省去反复输密码的麻烦。配置方式就用常规方式:在 master 生成密钥,把公钥写到两台 worker 的authorized_keys。
2.3 时间同步与软件源
集群节点时间不同步会导致证书验证失败和日志时间错乱。TLS 证书的签发和校验,对时间偏差非常敏感,偏差超过 5 分钟基本会直接握手失败。确保配置好chronyd或systemd-timesyncd,并确认时间源可用。
软件源方面,不同发行版处理方式不同。我一般习惯把 Kubernetes 官方源配置好,同时把容器镜像的拉取地址搞清楚——后者往往才是新手卡壳的重灾区,后面单独讲。
3. containerd 安装与配置:这是最容易忽略的"隐形地基"
3.1 为什么直接上 containerd
Kubernetes 1.24 之后,kubelet 默认不再直接支持 Docker 作为运行时。虽然可以用 cri-dockerd 兼容,但多一个适配层就多一个故障点。containerd 本来就是 Docker 底层的容器运行时组件,和 Kubernetes 的 CRI(Container Runtime Interface)对接是天经地义的事情。
这里的核心概念是:kubelet 通过 CRI 协议和容器运行时通信。containerd 对这个协议的支持成熟、稳定、资源占用少,因此我建议直接一步到位。
3.2 containerd 的安装步骤
安装 containerd 我用的是官方二进制或系统源方式。以系统源方式为例:
yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y containerd.io安装完成后,先备份默认配置,再生成新配置:
mkdir -p /etc/containerd containerd config default | tee /etc/containerd/config.toml这一步的重点来了。默认配置里SystemdCgroup是 false,如果你不改成 true,kubelet 会报 cgroup 驱动不匹配的错误。修改/etc/containerd/config.toml中的以下位置:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] ... [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = truecgroup 驱动有两个流派:cgroupfs 和 systemd。Kubernetes 官方建议使用 systemd 驱动,因为 systemd 本身也使用 cgroup 管理服务,两者共用一套机制可以避免资源管理冲突。containerd 默认的 cgroup 驱动是 cgroupfs,所以必须显式切换。
3.3 镜像加速与拉不动的处理思路
containerd 的镜像加速配置和 Docker 不同,它只作用于 CRI 插件配置的 mirrors 字段。在config.toml中找到类似这个结构的地方:
[plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://镜像加速地址"]国内网络环境拉取国外镜像经常超时,配置一个可用的加速地址非常必要。这个可以在当前网络环境里找一句稳定可用的加速域名,填入上述 endpoint 中。有一个知识点需要说明:如果配置了多个 endpoint,containerd 会按顺序尝试,第一个失败会切换第二个,所以把国内可达地址放前面,原仓库地址兜底。
配置完成后,重启 containerd:
systemctl restart containerd systemctl enable containerd验证方法:
crictl version能正常显示版本就说明基础环境OK。这里crictl是 Kubernetes 社区提供的 CRI 调试工具,和容器运行时内部指令不同,它更像 kubelet 视角的"客户端",用来验证镜像、容器状态很有用。
3.4 运行时安装完的快速自检清单
每次装完 containerd,我会固定花两分钟做三个检查:
systemctl status containerd检查服务是否 active;crictl pull busybox:1.36拉一个小镜像,确认网络和加速配置生效;cat /etc/containerd/config.toml | grep SystemdCgroup确认 cgroup 驱动是否已是 true。
这三个检查加起来不到三分钟,能过滤掉后续一大批诡异的初始化错误。
4. kubeadm 初始化控制平面:从一条命令到集群可用
4.1 安装 kubeadm、kubelet、kubectl
三台机器统一安装 Kubernetes 三件套。先添加官方源,安装时指定版本。这里必须强调版本一致性:三件套版本必须一样,别一个 1.28 一个 1.27,kubelet 和 API Server 之间的版本漂移会直接导致节点无法注册。
yum install -y kubeadm-1.28.5 kubelet-1.28.5 kubectl-1.28.5 systemctl enable kubelet注意,现在先把 kubelet 设置成 enable,但先不要启动它。kubelet 在 init 完成之前启动会因为找不到配置而反复崩溃重启,这是正常现象,不用管。等一下 init 完成后,配置会由 kubeadm 生成,kubelet 才会正常工作。
4.2 控制平面节点初始化
在 master 节点上执行 kubeadm init。我建议把参数写在命令行上,而不是依赖默认行为,这样每次重装时流程一致、也好回顾。
kubeadm init \ --apiserver-advertise-address=192.168.10.10 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.28.5 \ --service-cidr=10.96.0.0/12 \ --pod-network-cidr=10.244.0.0/16逐项解释参数的含义:
--apiserver-advertise-address指定 Master 节点上 API Server 的广播地址,也就是其他节点访问 API Server 的地址。--image-repository把默认的 gcr.io 镜像仓库替换为国内可访问的仓库地址,这一步如果不做,大概率会卡在拉镜像阶段。--service-cidr是 Service 的虚拟 IP 网段;--pod-network-cidr是 Pod 的网段。这两个网段必须和未来安装的 Calico 配置保持一致,否则网络插件和 kube-proxy 的路由规则就对不上。
我这里选的10.244.0.0/16是 Calico 安装配置中的常用默认值,两者能对上号。10.96.0.0/12是 Service 网段默认值,一般不用改。
执行成功后,末尾会输出这样一段内容,这是正常的成功提示:
Your Kubernetes control-plane has been initialized successfully! ...同时会给出三条后续操作指引。你只需要重点关注 worker 节点加入集群时用到的kubeadm join命令,以kubeadm token create --print-join-command也能重新获取。先按指引配置当前用户的 kubectl 访问权限:
mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config这里如果不替换kubeconfig,直接用 root 操作会提示"Unable to connect to the server: x509: certificate signed by unknown authority",因为客户端缺少集群证书。
4.3 安装 Calico 网络插件
此时集群的节点虽然是 Ready 状态还没达到——Master 节点会一直 NotReady,因为缺少网络插件。Kubernetes 集群的网络要求每个 Pod 有唯一 IP,Pod 间能直接互通,这个能力由 CNI 插件提供。我选 Calico,理由很实际:它是目前生产环境使用率最高的 CNI 之一,支持的网络模式多,排错资料最好找。
Calico 安装一般用 manifest 方式:
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml kubectl apply -f calico.yaml要注意的是,如果之前 kubeadm init 时--pod-network-cidr没有使用默认的10.244.0.0/16,你要在calico.yaml里找到CALICO_IPV4POOL_CIDR环境变量,改成你自己的网段,再 apply。
安装后观察:
kubectl get pods -n kube-system静置一两分钟,Calico 的 Pod 会从 Init 变成 Running。如果卡在 ImagePullBackOff,多半是镜像拉取失败,可以先把镜像手动 Pull 下来再 apply,或者用kubectl set image换国内可达的仓库地址。
4.4 工作节点加入集群
在 master 上执行kubeadm token create --print-join-command,拿到完整的 join 命令。然后在两台 worker 节点上分别执行。该命令的本质是带上一个 Token 和 API Server 地址,向 Master 发起注册请求,同时下载集群证书来完成 TLS 双向认证。
kubeadm join 192.168.10.10:6443 --token <你的token> --discovery-token-ca-cert-hash sha256:<你的hash>加入完成后,回到 master 验证节点状态:
kubectl get nodes如果看到NotReady,先不要急。等 kubelet 拉完节点组件,一般几分钟后会变成Ready。长期 NotReady 时,重点排查网络插件是否 Running、节点间 8472/6443 端口是否通、kubelet 日志是否报错。
此时控制台可以暂时不装,先把集群自身的 Pod 状态捋顺。
5. KubeSphere 的安装:从命令行到图形化平台的最后一公里
5.1 安装方式选型:KK 工具 vs Helm Chart
KubeSphere 官方提供两种核心安装方式:一种是用 KubeKey(KK)工具自动安装,另一种是在已有 K8s 集群上用 Helm 安装。我们已经有现成集群,所以重点讲 Helm/KK 结合的方式,二选一即可。
KK 工具的思路是"一条命令拉起整个平台"。它能检测已有集群、直接部署 KubeSphere 与可选组件,对新手最友好。Helm 方式则更适合已经有 Helm 发行习惯的团队。我建议第一次安装直接用 KK,后面需要升级时再用 Helm 或 Operator 维护。
5.2 下载 KubeKey 并创建最小化部署配置
KubeKey 是 KubeSphere 官方提供的部署工具,它既能装新集群,也能在已有集群上部署 KubeSphere。先下载 KK:
wget https://github.com/kubesphere/kubekey/releases/download/v3.1.7/kubekey-v3.1.7-linux-amd64.tar.gz tar -zxvf kubekey-v3.1.7-linux-amd64.tar.gz chmod +x kk然后生成一套集群配置文件模板:
./kk create config --with-kubesphere v3.4.1 -f mycluster.yaml打开mycluster.yaml,你会看到完整的 host 列表、role 定义和 KubeSphere 可插拔组件开关。因为我们集群已装好,所以 hosts 这段可以不用改,重点看spec.kubesphere下的 enabled 组件。
一个常见误区是试图通过这个配置文件去改已有集群的节点角色或网络,这不会生效——KK 检测到已有集群时,只负责往集群里部署 KubeSphere,不会重新编排节点。
5.3 正式安装与日志观察
执行安装命令,指定已有集群配置文件:
./kk init kubernetes -f mycluster.yaml注意,这里如果配置文件里的节点信息和你实际集群不一致,KK 可能会去连那些不存在的节点,从而卡住。已经装好 K8s 的前提下,我建议换用官方文档中为已有集群准备的安装路径,核心是执行kk init kubernetes前确保配置中的节点地址可 SSH 且 kubeconfig 可用。你也可以直接用 Helm 方式避免节点探测环节。
安装过程会在终端滚动大量日志。一条重要的判断标准:看到类似 "Congratulations" 或安装完成字样的日志,说明成功。安装期间不要关终端,也不要 Ctrl+C 中断,KubeSphere 的组件比较多,中途退出容易残留半初始化状态。
5.4 浏览器登录与组件验证
安装完成后,kubectl 查看 KubeSphere 控制台的访问端口:
kubectl get svc -n kubesphere-system默认情况下,ks-console 服务类型是 NodePort,端口一般是 30880。访问地址就是任意节点的 IP 加端口:http://192.168.10.10:30880。
默认初始账号是admin,初始密码是P@88w0rd。登录后第一时间建议去改密码,并创建自己的管理员账号。进入控制台后,你会看到集群状态仪表盘:节点 CPU/内存使用率、Pod 数量、项目列表、企业空间入口等,这些数据由 KubeSphere 自身的监控组件从节点采集并聚合。
此刻,一个完整的 K8s 集群 + 图形化管理平台的搭建流程就走完了。
6. 实操中反复出现的坑与排查思路
6.1 节点 NotReady 的排查顺序
NotReady 是所有人都会遇到的第一个坎。我的排查顺序固定如下:
kubectl get pods -n kube-system看是否有 Pod 异常,特别是 Calico 和 coredns。Calico 异常时集群必然 NotReady;journalctl -u kubelet -f看 kubelet 日志,报network plugin is not ready一般指向 CNI,报failed to ensure lease exists一般指向 etcd 连接问题;ip a查看节点是否存在 cali 开头的虚拟网卡,如果完全不存在,说明 Calico 没装好或者路由没有下发。
一个典型的伪问题:节点显示 NotReady,但所有 kube-system Pod 都 Running。这种情况多半是 node 的 kubelet 上报条件里有某个项异常,可以用kubectl describe node <节点名>查看 Conditions,哪一项不是 True 就优先处理。
6.2 镜像拉取失败
国内环境拉取 gcr.io 镜像大概率失败。你在 kubeadm init 时指定了--image-repository就能避免控制平面镜像问题。但 Calico、KubeSphere 组件这些不经过 kubeadm 的镜像,仍然可能失败。
排查和解决办法:
- 先
crictl images看本地是否已有该镜像; crictl pull <镜像>手动拉一次,直接看报错;- 如果确认仓库不可达,把 yaml 里的镜像地址替换为国内可达的镜像仓库,再 apply。
替换镜像地址用sed可以批量处理:
sed -i 's#docker.io/calico/calico#你的仓库地址/calico#g' calico.yaml kubectl apply -f calico.yaml6.3 证书相关问题的两个高频场景
场景一:用 kubeadm join 加入节点时提示证书过期或 CA 哈希不匹配。此时只需在 master 重新生成 token 和哈希:
kubeadm token create --print-join-command场景二:KubeSphere 安装后访问控制台报证书错误。KubeSphere 默认使用自签证书,浏览器第一次访问会有 HTTPS 证书警告。如果你配置了自定义域名和证书,需要直接配置 TLS 证书到 ks-console 的 Ingress 里。
6.4 存储和持久化:安装时最容易被忽略的环节
KubeSphere 自带 DevOps、监控、日志等组件,这些组件跑起来后会产生大量持久化数据。默认环境下,PVC 无法动态创建,除非你有 StorageClass。这一步在搭建教程里经常被轻描淡写,但在真实环境中却是第一周就会碰到的大问题。
我的建议是:在安装 KubeSphere 之前或之后尽快部署一个存储插件。目标环境如果是裸机,首选开源的 NFS 动态存储或本地卷方案;如果是虚拟化环境,可以走其自带存储能力。KubeSphere 本身支持多种存储对接,创建企业空间时也能直观地绑定存储类。
没有存储类时,Pod 申请 PVC 会一直处于 Pending 状态,排查时看事件信息是no persistent volumes available for this claim,就是缺少 StorageClass 的典型表现。
6.5 升级与重装注意事项
Kubernetes 小版本升级时,kubeadm 提供了kubeadm upgrade plan和kubeadm upgrade apply,按提示按部就班即可。升级前一定做备份:至少把/etc/kubernetes目录和 etcd 快照备份下来。
KubeSphere 升级走官方提供的KubeSphere Upgrade脚本或 Helm 方式。升级前注意版本兼容矩阵,别直接从 v3.2 跳到 v4.x,先看官方发布的升级路径。
如果整套环境坏了想重装,最干净的操作是:
kubeadm reset rm -rf /etc/kubernetes /var/lib/etcd /var/lib/kubelet然后重新从 containerd 开始。
7. 生产化需要补的作业:装完不是结束,而是开始
7.1 先装监控、日志还是权限
集群跑起来后,第一件事不是急着部署业务,而是把"看不见的部分"补齐。KubeSphere 的控制台已经内置了监控功能,你只需要确认监控组件已经启用。默认安装时监控组件是关闭的,需要在安装配置里把monitoring打开,或者安装完成后到 KubeSphere 的扩展中心去启用。
日志组件同理。生产环境没有日志,排查问题等于盲人摸象。KubeSphere 的日志查询界面可以在企业空间或者项目维度查看容器日志,底层是采集、存储、查询的完整链路,开起来之后才能看到。
顺序建议:
- 开启监控、日志、告警;
- 配置存储类和存储容量;
- 创建企业空间、创建账号、分配角色;
- 最后再部署业务。
这个顺序能确保你后端能力齐备,业务就绪后立刻能用面板观察。
7.2 资源配额与多租户规划
KubeSphere 的多租户模型有三个层级:集群、企业空间、项目。通常建议:一个业务线一个企业空间,一个应用域一个项目。在每个项目上设置资源配额,避免某个团队抢占全部 CPU 和内存。
这一步虽然和搭建关系不大,但对运维体验有决定性影响。没做配额的环境,一个死循环的 Pod 能把整台节点打挂;做了配额的集群,最坏情况只是那个项目内 Pod 调度失败,不会影响全局。
在 KubeSphere 控制台创建项目时,可以直接设置请求和限制值,操作界面比较直观,这里不展开。
7.3 备份策略:至少备份两样东西
无论如何,建议至少备份两样东西:etcd 和 KubeSphere 的配置(ConfigMap/Secret)。etcd 是整个集群状态的唯一权威数据源,备份它等于备份了整个集群的"数据库"。
KubeSphere 层面,主要备份 kubesphere-system 和 kubesphere-monitoring-system 等命名空间下的配置对象。可以写个定时 job 定期导出 yaml。真实工作中,很多数据丢失事故本来都可以靠一份 etcd 快照挽回。
在这里我个人的体会是:搭建流程本身只是半天到一天的事,真正决定集群能否长期稳定的是存储、监控、备份这三件事。装完 KubeSphere 后先别急着欢呼,把这几样补齐,再开始部署业务,你后续的运维会轻松非常多。希望这套完整过程能帮你少走弯路——如果你在搭建时碰到文中没有覆盖的报错,可以先对照我给出的排查链路逐一确认,大多数问题的指向其实很集中。