尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

信创ARM64实战:麒麟V10部署K8s与KubeSphere全攻略

信创ARM64实战:麒麟V10部署K8s与KubeSphere全攻略 最近在帮客户做信创环境落地要把Kubernetes 1.30集群和KubeSphere管理平台跑在银河麒麟V10国防版上CPU是鲲鹏920和飞腾S2500混搭的ARM架构。说实话网上关于x86的K8s教程一抓一大把但到了ARM64 国产OS这套组合拳很多资料要么语焉不详要么干脆就缺胳膊少腿踩坑只能自己硬趟。这篇文章就把我们这次完整实施过程记录下来从方案选型、系统初始化到在线部署、离线部署再到KubeSphere平台安装全程实测可用。不管你是要在ARM服务器上搭一套生产环境还是交付一个物理隔离的内网项目这篇都能当作业直接抄。整个项目踩下来最大的感受是信创环境不是能不能用的问题而是“你会不会用”的问题。同样的K8sx86上顺滑得像德芙ARM上稍不留神就是连环坑。但一旦把链路的坑都填平了跑起来比x86还稳——毕竟鲲鹏和飞腾的低功耗多核心天生就是跑容器这块料。1. 项目概述与部署背景1.1 信创环境下的容器化需求这个项目的背景很典型客户要求把业务系统全部容器化改造底层基础设施必须国产化。操作系统锁定了银河麒麟V10国防版芯片指定鲲鹏或飞腾系列。国防版和我们平时用的服务器版SP1/SP2相比多了不少安全加固策略默认配置更保守对我们部署K8s来说等于额外多了一道关卡。这里先交代一下版本差异。银河麒麟V10的桌面版和服务器版内核版本、软件仓库、默认防火墙策略都有区别。国防版在合规和等保方面做得更严默认开启了更多安全模块比如强制访问控制策略、更严格的SELinux配置、USB和内核模块加载的管控等。这些安全特性本身没毛病但在装K8s的时候如果你不知道要放开哪些口子就会卡在莫名其妙的权限报错上。我建议你在拿到机器之后第一件事不是急着装依赖而是先把系统版本、架构、内核版本、安全状态这些基础信息摸清楚。后面所有部署动作都基于这些信息来展开。1.2 架构差异与版本兼容性判断ARM64和AMD64的差别不用我多废话指令集都不一样。但真正影响部署体验的是软件生态的成熟度。K8s官方对ARM64的支持早就GA了问题出在周边组件上。实际部署中我们遇到了这么几类兼容性问题containerd、kubeadm、kubelet这些核心组件官方有多架构二进制直接用没问题。Calico、Flannel这些网络插件镜像都支持multi-arch拉取时自动按平台拉不费心。但有些辅助工具比如特定版本的etcd、metrics-server、CoreDNS如果从非官方源下载容易拿到AMD64的包导致镜像拉下来执行直接报exec format error。关于arm64和amd64的区别我觉得最直观的理解方式就是AMD64的软件按x86指令集编译成二进制机器码ARM64的设备拿到手根本没法定向执行。这不像是Python、Java这类带虚拟机的语言天然跨平台挪过来就能跑。所以凡是涉及二进制文件、容器镜像、预编译的rpm包你就得在心里多问一句这个版本有没有ARM64的1.3 在线与离线部署的场景选择在线部署适合网络环境通畅的场景要么是开发测试环境能直连外网要么是内网配了HTTP代理。离线部署则是给生产环境和涉密内网准备的这些环境通常是物理隔离的连一个字节的外网流量都出不去。这次项目客户明确要求离线交付所以两条路我们都完整走了一遍先在在线环境验证所有组件的正确版本和部署流程再把整个依赖链条导出到离线环境实施。这样做的好处很明显在线环境解决了“这个组件要用哪个版本”的问题离线环境只需要解决“东西怎么带进去”的问题。我做了一张对比表方便你快速理解两种方式的差异对比项在线部署离线部署依赖获取yum拉取、镜像直拉提前下载rpm包和镜像文件部署速度依赖来源不稳定时快时慢只要介质准备好了速度很快环境要求能连外网或走代理完全内网也能装复杂程度低中等需要事先准备离线仓库适合场景测试环境、有网生产涉密内网、物理隔离生产如果条件允许我强烈建议你在有网环境下先跑通一遍在线流程。不是多此一举而是离线部署最怕的就是“不知道需要哪些依赖”有网环境就是最好的“依赖清单生成器”。2. 环境评估与系统初始化2.1 硬件配置与节点规划这次集群规划了3个节点1个控制平面加2个工作节点。硬件情况如下节点角色主机名CPU内存系统盘数据盘masterk8s-m1鲲鹏92032核64G240G SSD500G SSDnode1k8s-n1飞腾S250064核128G240G SSD1T SSDnode2k8s-n2飞腾S250064核128G240G SSD1T SSD生产环境不建高可用有点冒险但这次项目属于试点验证阶段单控制节点够用。如果你要上生产建议至少3个控制平面节点stacked etcd模式就够了没必要上external etcd。反正记住一句话K8s集群最大的可用性瓶颈永远是etcd控制平面多一台就多一分保障。磁盘规划上有个容易忽略的点/var/lib/containerd容器数据目录一定放在独立数据盘上。别把系统盘和数据盘混在一起你不想遇到一次日志爆盘就让整个节点容器全挂。直接在数据盘上创建分区挂载到/var/lib/containerd或者和/var/lib/docker如果用docker类似。操作系统安装时建议直接选择“Server with GUI”或者最小化安装。信创环境很多运维人员习惯桌面版但跑K8s我建议最小化安装少装一个图形界面就少一个攻击面也少一次被奇怪组件干扰的机会。2.2 操作系统基础配置与内核调优系统起来之后第一轮初始化配置我按这个顺序做第一件事关闭firewalld。麒麟V10默认开着firewalldK8s部署过程中需要大量临时端口通信防火墙规则很容易漏配。生产环境当然可以精细化放行端口但初次部署图省心我一般是先关掉firewalld等集群稳定运行后再根据实际端口反向加规则。具体操作systemctl stop firewalld systemctl disable firewalld第二件事关闭SELinux。国防版的SELinux策略比普通版更严格强制模式下containerd和kubelet经常被权限拦截报错信息还特别隐晦。虽然不推荐在生产环境关闭SELinux但说实话K8s核心组件和SELinux的配合本来就还不太成熟先关掉保平安setenforce 0 sed -i s/^SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config第三件事关闭swap。K8s从1.22开始支持swap配置但默认行为还是禁用swap不关会报错kubelet无法启动。建议直接关掉swapoff -a sed -i /swap/d /etc/fstab第四件事加载内核模块和配置sysctl参数。这是最关键的一步很多人部署K8s失败就是因为漏了内核参数cat /etc/modules-load.d/k8s.conf EOF overlay br_netfilter EOF modprobe overlay modprobe br_netfiltercat /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注意ARM64架构下有时候bridge-nf-call-ip6tables这个参数在内核里默认不可用如果执行sysctl时报错找不到文件先确认br_netfilter模块是否加载成功。这是个很小的坑但我在飞腾节点上遇到过。2.3 软件源与时间同步配置麒麟V10自带麒麟yum源但默认配置里有很多源地址指向公网如果你在内网环境下直接yum安装会卡死。操作之前先确认一下源的可用性yum repolist如果网络环境能通外网那直接用默认源就行。如果是离线环境需要提前准备离线rpm仓库后面离线章节详细说。时间同步也不能忽略。K8s对节点间时钟偏差非常敏感偏差超过几十毫秒就会出现奇怪的证书和调度问题。部署前统一用chrony或者ntpdate校准一下yum install -y chrony systemctl enable chronyd systemctl start chronyd chronyc sources -v信创环境内网通常有自己的时间源服务器我建议你把配置改成指向内网NTP服务器而不是默认的centos pool省得外网不通卡时间同步。3. 在线部署Kubernetes 1.303.1 容器运行时containerd的安装与配置K8s自1.24起正式移除dockershim需要按CRI标准对接containerd。ARM64架构下containerd有官方二进制包也可以用麒麟yum源里的版本。不过建议直接用官方二进制版本较新bug修复更及时。安装containerdyum install -y containerd.io或者如果你在离线环境也可以下载ARM64的静态包解压到/usr/localtar -C /usr/local -xzf containerd-1.7.x-linux-arm64.tar.gz装完后生成默认配置mkdir -p /etc/containerd containerd config default /etc/containerd/config.toml然后修改关键配置。用vim编辑config.toml重点改两个地方第一设置sandbox_image为国内可访问的镜像源。默认用的是registry.k8s.io/pause:3.9公网访问经常超时改成registry.aliyuncs.com/google_containers/pause:3.9。第二SystemdCgroup必须设置为true。K8s和containerd的cgroup驱动要一致不然后面kubelet检查cgroup driver不匹配半天都过不去。[plugins.io.containerd.grpc.v1.cri] sandbox_image registry.aliyuncs.com/google_containers/pause:3.9 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] runtime_type io.containerd.runc.v2 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup true重启containerdsystemctl restart containerd systemctl enable containerd验证crictl info能正常输出信息就说明配置成功。顺手把crictl配置一下cat /etc/crictl.yaml EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF3.2 kubeadm、kubelet、kubectl安装K8s 1.30的安装工具官方推荐从pkgs.k8s.io的yum源安装。麒麟V10基于CentOS 8所以用RHEL/CentOS 8的源适配cat /etc/yum.repos.d/kubernetes.repo EOF [kubernetes] nameKubernetes baseurlhttps://pkgs.k8s.io/core:/stable:/v1.30/rpm/ enabled1 gpgcheck1 gpgkeyhttps://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key EOF然后yum install -y kubelet kubeadm kubectl systemctl enable kubelet注意如果yum源连接失败可以检查一下源地址里有没有带release版本号。K8s官方repo的结构里rpm目录下有子目录按CPE版本分类有的环境需要把baseurl调整成https://pkgs.k8s.io/core:/stable:/v1.30/rpm/这样不带子目录的形式才能正常解析。安装完成后验证版本kubeadm version kubelet --version kubectl version --client正常情况下会输出1.30.x版本信息。如果输出的版本和预期不符注意检查yum缓存。我之前遇到过yum缓存了旧版repo数据导致装出来还是1.28。解决办法就是yum clean all和yum makecache。3.3 使用kubeadm初始化集群主节点上初始化之前先准备好kubeadm配置文件统一了参数以后管理方便不用每次打一长串命令行参数。apiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.10.10 bindPort: 6443 nodeRegistration: criSocket: unix:///run/containerd/containerd.sock --- apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.30.2 controlPlaneEndpoint: 192.168.10.10:6443 networking: podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12 imageRepository: registry.aliyuncs.com/google_containers这里特别说下imageRepository这个参数。国内网络拉取registry.k8s.io的镜像时常超时改成阿里的镜像仓库后等于是把官方镜像路径映射到了国内加速地址。注意这个参数设置为registry.aliyuncs.com/google_containers时kubeadm会自动在后面拼上镜像名拉取相当于原来registry.k8s.io/kube-apiserver变成了registry.aliyuncs.com/google_containers/kube-apiserver直接替换拉取源。执行初始化kubeadm init --config kubeadm-config.yaml这一步会拉取一堆镜像包括kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、pause、etcd、coredns输出时间较长。初始化成功后末尾会打印一段join命令记得复制保存。配置kubectl访问权限mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config验证集群状态kubectl get nodes能看到master节点为NotReady状态这是正常的因为还没装网络插件。3.4 网络插件Calico安装K8s的Pod网络方案我推荐Calico它的BGP模式在物理机上性能不错对ARM64架构支持也完善。最重要的是Calico的yaml文件里用的镜像都是multi-arch的在ARM节点上会自动拉arm64版本。直接应用官方提供的manifestkubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml如果在线环境拉取calico相关镜像比较慢可以先手动拉好再改yaml里的镜像地址crictl pull docker.io/calico/cni:v3.26.1 crictl pull docker.io/calico/node:v3.26.1 crictl pull docker.io/calico/kube-controllers:v3.26.1然后修改calico.yaml里对应的image字段为本地已有的镜像。等待所有calico相关pod变成Runningkubectl get pods -n kube-system -w再检查节点状态kubectl get nodes如果节点变成Ready说明网络插件工作正常。3.5 工作节点加入集群工作节点同样需要完成系统初始化、安装containerd并配置、安装kubelet/kubeadm/kubectl这些步骤和主节点一模一样。唯一的区别是主节点用kubeadm init工作节点用kubeadm join。把主节点初始化后生成的join命令在工作节点上执行kubeadm join 192.168.10.10:6443 --token your-token \ --discovery-token-ca-cert-hash sha256:your-hash如果token过期了在主节点上重新生成kubeadm token create --print-join-command回到主节点验证kubectl get nodes -o wide三个节点都Ready在线部署部分就算完成了。4. 离线部署Kubernetes 1.304.1 离线资源准备rpm包与镜像导出离线部署是这次项目交付的重头戏。客户机房是物理隔离的连USB设备的接入都需要审批。我们提前在一台和客户CPU同架构鲲鹏920的在线机器上准备好所有依赖再通过内网传递到目标环境。准备离线包的时间点很重要建议和在线部署保持一致。原因很简单你在在线环境怎么部署成功的就把对应的rpm包版本和镜像tag全部固定下来。版本漂移是离线部署最大的坑没有之一。先导出K8s组件和运行时相关的所有rpm包。如果你在在线环境已经通过yum安装了可以直接使用yumdownloader下载整个依赖链yum install -y yum-utils mkdir /opt/k8s-offline-pkgs cd /opt/k8s-offline-pkgs yumdownloader --resolve kubelet kubeadm kubectl containerd.io注意yumdownloader --resolve会下载所有依赖包不包含无需安装的。如果你不确定是否完整可以用repotrack这个工具它下载所有依赖包包含弱依赖和可选依赖虽然体积更大但更保险。导出镜像这一步我用另一种方式。先准备好所有需要的镜像清单文件一行一个镜像名然后脚本批量拉取保存#!/bin/bash images( registry.aliyuncs.com/google_containers/kube-apiserver:v1.30.2 registry.aliyuncs.com/google_containers/kube-controller-manager:v1.30.2 registry.aliyuncs.com/google_containers/kube-scheduler:v1.30.2 registry.aliyuncs.com/google_containers/kube-proxy:v1.30.2 registry.aliyuncs.com/google_containers/pause:3.9 registry.aliyuncs.com/google_containers/etcd:3.5.12-0 registry.aliyuncs.com/google_containers/coredns:v1.11.1 docker.io/calico/cni:v3.26.1 docker.io/calico/node:v3.26.1 docker.io/calico/kube-controllers:v3.26.1 ) for img in ${images[]}; do ctr -n k8s.io images pull $img ctr -n k8s.io images export ${img//\//_}.tar $img done这里用的ctr命令是containerd自带的镜像管理工具和crictl有区别。crictl主要用于CRI级别的Pod管理ctr展示底层containerd操作但在离线场景下使用ctr做镜像的导入导出更直接避开了CRI层的限制。导出的镜像tar包加上rpm包目录整体打包传走。4.2 搭建离线Yum仓库与私有镜像仓库到目标机器后先把rpm包安装起来。把离线包目录挂载或拷贝到/opt/k8s-offline-pkgs下然后直接用rpm -ivh安装不过这样处理依赖比较麻烦。更好的做法是做一个本地yum仓库yum install -y createrepo createrepo /opt/k8s-offline-pkgs然后写一个本地repo文件vi /etc/yum.repos.d/local-k8s.repo[local-k8s] nameLocal K8s Packages baseurlfile:///opt/k8s-offline-pkgs enabled1 gpgcheck0最后yum clean all yum makecache yum install -y kubelet kubeadm kubectl containerd.io离线环境装containerd的时候注意需要额外安装一些系统依赖比如libseccomp-devel如果报缺依赖就从系统安装镜像或者麒麟软件源的缓存目录找rpm包一起放进来。私有镜像仓库我用的方案是registry:2比Harbor轻量多了离线场景够用。为了让所有节点都能从内网拉镜像选择先在主节点上搭建registry再把镜像推送上去工作节点直接从这个私有仓库pull。在主节点上mkdir -p /data/registry ctr -n k8s.io images pull docker.io/library/registry:2 ctr -n k8s.io run --net-host -v /data/registry:/var/lib/registry --mount typebind,src/data/registry,dst/var/lib/registry docker.io/library/registry:2 registry当然更稳妥的做法是把registry配置成systemd服务避免容器退出后registry不可用。简化版可以直接用docker run方式如果机器上没有装docker用ctr也能启动容器。我们最终是用docker-compose模板跑起来的方便管理。全部节点在/etc/hosts里加上registry地址echo 192.168.10.10 registry.local /etc/hosts所有节点配置containerd的registry镜像加速和私有仓库信任[plugins.io.containerd.grpc.v1.cri.registry.mirrors] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io] endpoint [http://registry.local:5000] [plugins.io.containerd.grpc.v1.cri.registry.configs.registry.local:5000] [plugins.io.containerd.grpc.v1.cri.registry.configs.registry.local:5000.tls] insecure_skip_verify true重启containerd让配置生效。然后回到在线环境导出的镜像tar包在目标机器上往私有仓库推送。先把tar导入containerdctr -n k8s.io images import kube-apiserver_v1.30.2.tar再重新打tag并推送到registryctr -n k8s.io images tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.30.2 registry.local:5000/kube-apiserver:v1.30.2 ctr -n k8s.io images push --plain-http registry.local:5000/kube-apiserver:v1.30.2注意--plain-http参数因为是HTTP的本地仓库不加这个参数推送会失败。所有镜像推送到私有仓库后kubeadm配置文件里的imageRepository改成私有仓库imageRepository: registry.local:5000这里的registry.local:5000只在前面加上了仓库地址kubeadm会自动把kube-apiserver等镜像名拼到后面。如果内部镜像路径层级不同需要调整imageRepository的写法。例如如果镜像都在registry.local:5000/k8s目录下则imageRepository配置为registry.local:5000/k8s。后面init流程和在线部署就完全一样了镜像走私有仓库拉取kubelet组件走本地yum安装全程不需要外网。4.3 离线安装的坑与验证离线部署最容易踩的坑我逐一列一下第一镜像导入不完整。执行kubeadm init后如果发现某个镜像拉取失败可以先检查私有仓库里有没有这个镜像tag。有时候因为脚本bug或网络上传中断某几个镜像没推上去。建议在每个节点上先把需要的镜像在本地导入一份用ctr -n k8s.io images list验证。第二coredns版本不匹配。K8s 1.30默认的coredns镜像版本是v1.11.1如果在线环境导出的镜像清单里写错了版本初始化的时候kubeadm会尝试从配置的imageRepository拉取默认版本导致镜像找不到。建议在kubeadm-config.yaml里显式指定镜像列表或者干脆提前手动拉取所有需要的镜像到本地containerd。第三内存不足导致的etcd启动失败。ARM服务器内存动不动就上百G但虚拟化环境里可能分到的主机内存很小。etcd默认缓存上限较大内存不够可能出现OOM导致apiserver连不上。建议在小内存环境提前给etcd配置limits参数cgroup驱动设为systemd后就用kubeadm的etcd配置来限制。离线集群初始化完成之后验证命令和在线完全一致节点做到ReadyPod做到RunningK8s本身不会关心你是在线还是离线装的。5. KubeSphere平台部署5.1 KubeSphere版本选型与兼容性分析KubeSphere和K8s版本兼容性是要对表的。有些版本在K8s 1.30下会存在CRD版本或API兼容问题。KubeSphere 3.4.x开始比较完整支持K8s 1.26以上的新版本但我们实测用3.4.1或4.1.x对1.30都稳。如果你用过KubeSphere 2.x的老版本升级到3.x后API变化挺大。现在官方主推的版本是v3.4.x和v4.x安装方式也不一样。v3.4系列用KubeKeykk工具安装最方便v4.x则更多推荐用Helm或者KubeKey实际部署根据官方release note选择。KubeSphere最大的价值是把一堆K8s周边组件封装好了。装上之后可视化管理、多租户、DevOps流水线、监控告警这些都有省得自己一个个去装Prometheus、Grafana、Jaeger生态组件全包了。对于信创项目KubeSphere特别讨喜的一点是它同时支持ARM64和AMD64的镜像构建。这对交付验收来说是个加分项等保测评、适配报告都好看很多。5.2 使用KubeKey快速部署KubeKey是KubeSphere官方出的部署工具可以同时装K8s和KubeSphere也可以只负责往已有K8s集群上装KubeSphere。我们这次由于K8s已经手动部署完成所以直接用KubeKey在已有集群上装KubeSphere。先下载kk工具。如果是在线环境直接GitHub release拉最新版。这里建议优先拉v3.0.7以上版本对K8s 1.30的兼容性更好。curl -sfL https://get-kk.kubesphere.io | VERSIONv3.0.7 sh -如果离线环境需要在有网环境下载kk二进制传进去ARM64版本名称后缀是linux-arm64。kk工具直接能检测当前集群状态./kk create cluster --with-kubesphere -v v3.4.1上面这条命令会尝试在你当前节点上新建K8s集群这是kk最常用的模式。但如果集群已经是现成的我们不想让它对K8s做任何操作需要用另一种方式。官方提供的方式是用kubectl apply ks-installer的方式装kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.4.1/kubesphere-installer.yaml kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.4.1/cluster-configuration.yaml离线环境也简单提前下载这两个yaml文件和ks-installer相关的镜像传到内网执行。安装完查看状态kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app in (ks-install, ks-installer) -o jsonpath{.items[0].metadata.name}) -f日志里出现KubeSphere has been installed successfully之后检查所有Pod状态kubectl get pods -A | grep -E kubesphere|ks-正常情况下一大堆Pod会出现在kubesphere-system、kubesphere-controls-system、kubesphere-monitoring-system这些命名空间下等它们全部Running就算装完了。5.3 最小化安装与扩容组件KubeSphere默认安装的是可插拔组件模式初始安装会带一个最小集包括核心控制台、账户体系、超市货架等而像DevOps、灰度发布、监控告警这些重量级组件默认不安装需要主动开启。这里我建议生产环境不要一上来就把所有组件全开先把平台核心跑起来稳定验收后再逐个开启DevOps、告警、日志等模块。每个组件的开启都会拉一批镜像占不小的资源一次性全开容易把集群拖垮。开启组件的入口在管理界面平台管理 - 集群管理 - 自定义资源CRD - clusterconfiguration - ks-installer - 编辑YAML。比如开启DevOps把spec里的devops组件的enabled字段改成true保存后ks-installer会自动干活。ARM64架构下KubeSphere有几个可选组件是有特殊镜像的比如基于二进制审计的组件在ARM上表现为镜像拉不下来。遇到这种情况就暂时不开启该组件等官方更新ARM镜像后再启用。信创项目交付硬性要求是全功能实际操作只能说量力而行有的组件不开不影响整体验收。5.4 KubeSphere访问配置与验证安装完成后通过NodePort访问控制台。默认端口是30880kubectl get svc -n kubesphere-system ks-console访问方式https://任一节点IP:30880默认账号是admin初始密码是P88w0rd。登录后系统会引导你修改密码正式环境务必改掉。控制台正常显示后建议做一个最基本的冒烟测试创建项目namespace部署一个简单的Nginx应用测试通过Service暴露服务启用一个DevOps流水线模板验证CI/CD组件是否正常查看监控面板确认各节点监控数据采集正常这几个动作全部通过KubeSphere平台就算真正可用了。6. 常见问题排查与调优实录6.1 ARM64架构的典型坑ARM64架构最典型的问题就是镜像架构不匹配。常见的报错是exec format error看到这个第一反应就是镜像架构错了。解决方法是检查镜像的manifest确认arm64版本的镜像是否存在crictl inspecti image | grep -i architecture另外etcd容器在ARM64上偶尔有内存对齐的bug表现为运行一段时间后莫名崩溃。解决办法是升级到官方修复过的etcd版本或者给etcd容器设置更合理的资源limit避免内存碎片化。还有一个是网络插件的问题。Flannel在ARM64上跑得好好的但VXLAN模式性能明显比Calico的BGP模式差。我们实测在飞腾S2500上相同负载下Calico的吞吐量比Flannel高出20%以上。所以ARM平台上的K8s网络插件我还是推荐Calico。6.2 银河麒麟V10的系统兼容问题麒麟V10国防版的系统配置有几个和K8s部署容易冲突的点第一systemd版本和cgroup驱动的兼容性。麒麟V10的系统systemd版本较新在设置containerd和kubelet的cgroup驱动时必须统一用systemd。如果用cgroupfs会出现kubelet反复重启、Pod不断重建的问题。第二麒麟自带的audit审计组件可能会大量记录K8s相关进程的访问日志导致/var/log/audit分区爆满。建议在audit规则里放行K8s相关目录或者定期清理日志。第三systemd的StartLimitInterval参数默认限制服务重启频率。kubelet在初始化阶段失败时如果触发systemd重启限制你会看到服务进入了失败状态systemctl status里面全是红色。调整方法mkdir -p /etc/systemd/system/kubelet.service.d cat /etc/systemd/system/kubelet.service.d/override.conf EOF [Service] Restartalways RestartSec10 EOF systemctl daemon-reload第四国防版可能默认开启kdumpcrash内核会预留大块内存这在内存小的节点上非常浪费空间直接从内核启动参数里去掉crashkernel选项释放内存。6.3 性能与稳定性调优建议飞腾S2500有64个核心鲲鹏920通常是32核起跑K8s压力不大但要充分发挥多核优势有几个参数值得调整Kubelet的max-pods建议根据实际业务调整。默认值是110但ARM机器CPU核多内存大Pod密度可以提高一些比如配到200甚至300。调高之前注意检查IP地址资源、容器网卡数量、文件句柄上限是否足够。sed -i s/^KUBELET_EXTRA_ARGS/KUBELET_EXTRA_ARGS--max-pods200/ /etc/sysconfig/kubelet内核网络参数也值得调优。ARM平台的网络吞吐和x86比有些差异适当调大环形缓冲区能降低延迟cat /etc/sysctl.d/99-arm-net.conf EOF net.core.netdev_max_backlog 4096 net.core.somaxconn 4096 net.ipv4.tcp_max_syn_backlog 4096 EOF sysctl --system对etcd节点建议把数据目录放到高可靠高IO的SSD上etcd对IO延迟敏感HDD会导致raft心跳超时引发选主。KubeSphere自带的Prometheus对存储也有IO要求尽量给监控数据单独一块盘。6.4 最终交付的细节整个集群部署完成后交付阶段有几个动作一定要做把集群的证书备份一份放在非系统盘上。K8s默认证书1年有效期到期前记得自动续期或手动更新不然apiserver会不可用。把kubeadm-config.yaml、calico.yaml、ks-installer相关的部署清单全部归档到项目交付目录方便后续版本升级和故障复盘。给所有节点的/etc/hosts加好主机名和IP映射。信创环境经常有多台ARM服务器后续扩容节点时少了hosts映射会导致etcd和KubeDNS解析异常。最后就是写交付文档。包含拓扑图、IP规划、镜像清单、rpm清单、初始化脚本、部署步骤全部一起交付。这些资产在运维接手时比一张“部署成功”的截图重要得多。我在这个项目的实际操作中还有一个体会ARM64信创环境下最浪费时间的事情不是部署本身而是到处找兼容性匹配的组件版本。所以我的习惯是每验证一个组件就把它和K8s版本的兼容矩阵记录下来。磨刀不误砍柴工下次再部署同类环境照着自己的记录走一下午就能把整个集群拉起来。再分享一个小技巧把整个初始化配置写成一个可以重复执行的shell脚本放到内网机器上。不管是装新节点还是修复有问题的节点一条命令跑完基础配置。信创环境服务器多手动配置每个节点连错误都没处找。KubeSphere和K8s的这套组合在麒麟V10和ARM64这块土壤上已经完全能支撑生产业务了。只要把版本兼容性、内核参数、资源规划这些前期功课做扎实后面基本就是复制粘贴的活。
返回列表