企业级K8S生产环境搭建实录:3管理节点+3计算节点+Harbor高可用架构详解
企业级K8S生产环境搭建实录:3管理节点+3计算节点+Harbor高可用架构详解
最近和几位技术负责人聊天,大家普遍反映一个痛点:从技术博客里学来的Kubernetes部署方案,在个人实验环境跑得挺欢,一旦要搬到公司内部的生产环境,各种问题就冒出来了。节点挂了怎么办?镜像拉取慢得像蜗牛,CI/CD流水线动不动就卡住。更头疼的是,那些教程往往只讲“单管理节点”的简易部署,对于要求服务不中断、数据不丢失的真实业务场景,参考价值有限。这让我意识到,一份聚焦于中小企业真实生产需求、涵盖多节点高可用、安全镜像仓库以及可落地配置细节的指南,确实有其价值。它不是另一个“一键安装”脚本的堆砌,而是试图还原你在机房或云上,面对多台服务器时,需要思考的架构选择、参数调优和故障预案。无论你是计划将内部应用容器化,还是为团队搭建一个稳定的开发和测试平台,希望接下来的内容能提供一条清晰、可复现的路径。
1. 架构设计与核心组件选型
在动手敲命令之前,花些时间厘清架构是避免后期返工的关键。我们构建的是一个典型的中小企业生产级Kubernetes集群,核心目标是在有限的资源下(例如6台物理机或虚拟机),实现控制平面的高可用和数据平面的弹性扩展。
核心架构拓扑可以这样理解:我们将三台服务器作为管理节点(Master Node),它们共同组成集群的“大脑”,运行着API Server、Scheduler、Controller Manager等关键组件。为确保这个大脑不会因单点故障而宕机,这些组件本身将以多副本形式运行,并通过一个负载均衡器(HAProxy) 对外提供统一的访问入口。另外三台服务器作为计算节点(Worker Node),承载实际的应用容器负载。所有节点都需要从统一的镜像仓库拉取容器镜像,这里我们选择功能丰富且支持高可用的Harbor。
注意:将Harbor部署在独立的第七台服务器上是推荐做法。这避免了资源竞争,也便于单独进行安全加固、备份和升级,符合生产环境职责分离的原则。
在这个架构中,有几个容易被新手忽略但至关重要的企业级考量点:
- etcd集群:Kubernetes的所有集群状态数据都存储在etcd中。我们将其部署在三台管理节点上,形成一个3节点的分布式键值数据库集群。这要求我们仔细配置etcd的通信参数,确保其数据一致性和高可用性。
- 负载均衡器(HAProxy):它并非Kubernetes的内部组件,而是一个前置的、独立的服务。它的作用是,将客户端(如kubectl、CI/CD系统)对Kubernetes API的请求,均匀、可靠地分发到后端的三个管理节点的API Server上。即使其中一个管理节点故障,API服务依然可用。
- 容器运行时与镜像加速:我们选用Docker作为容器运行时。在生产环境中,从公共仓库拉取镜像的速度和稳定性是瓶颈,因此必须配置可靠的镜像加速器或内部代理。
为了更清晰地展示集群中各组件的部署位置与交互关系,可以参考下表:
| 组件/角色 | 部署节点 | 数量 | 关键职责 | 高可用实现方式 |
|---|---|---|---|---|
| HAProxy | 可部署于任一节点或独立LB | 1 (可多实例) | 为K8s API Server提供负载均衡 | 结合Keepalived实现VIP漂移 |
| K8s API Server | 所有管理节点 | 3 | 集群API入口,处理所有REST请求 | 通过HAProxy实现流量分发 |
| K8s Scheduler | 所有管理节点 | 3 | 为Pod选择运行的Node | 多副本,领导者选举 |
| K8s Controller Manager | 所有管理节点 | 3 | 维护集群状态(如副本数) | 多副本,领导者选举 |
| etcd | 所有管理节点 | 3 | 存储集群所有配置与状态数据 | 组成3节点Raft集群 |
| Kubelet & Container Runtime | 所有计算节点 | 3 | 管理Pod生命周期,运行容器 | 节点级,无状态,可替换 |
| Harbor (Core) | 独立服务器 | 1 (可集群) | 企业级私有镜像仓库 | 通过外部数据库和存储实现无状态扩展 |
这个架构平衡了复杂度与可靠性。三节点etcd集群可以容忍一个节点故障;三管理节点确保控制平面服务持续可用;计算节点则可以视业务压力随时增减。
2. 基础环境与Kubernetes高可用集群部署
假设你已经准备好了7台安装Ubuntu 22.04 LTS的服务器(或虚拟机),并配置了静态IP和互信SSH。我们从所有节点的通用配置开始。
2.1 系统级统一配置
首先,在所有7台服务器上执行以下操作,为Kubernetes运行准备一个干净、稳定的基础环境。
关闭并禁用SWAP。Kubernetes调度器需要依赖足够的内存资源来做出决策,SWAP的引入会导致性能不稳定和不可预测性。
# 临时关闭当前所有SWAP空间
swapoff -a
# 永久禁用,编辑fstab文件,注释掉包含swap的行
sed -i '/swap/s/^/#/' /etc/fstab
加载内核模块并修改系统参数。容器网络和存储等功能需要特定的内核模块支持。
# 加载必要模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置网络桥接的IP转发及流量处理参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
安装基础工具。确保curl、vim、socat、conntrack等工具可用。
apt-get update && apt-get install -y curl vim socat conntrack ipset
2.2 使用KubeKey构建高可用集群
手动部署一个高可用集群涉及大量繁琐的配置。这里我们选用KubeSphere社区开源的KubeKey工具,它能极大地简化流程,特别是对于etcd和负载均衡器的集成部署。
-
下载并准备KubeKey。在一台作为“部署机”的管理节点(例如
guanlijiedian1)上操作。# 设置下载区域为中国,加速获取 export KKZONE=cn # 下载最新版KubeKey curl -sfL https://get-kk.kubesphere.io | sh - # 赋予执行权限 chmod +x kk -
生成集群配置文件。这里我们指定使用较稳定的Kubernetes v1.26.x版本。
./kk create config --with-kubernetes v1.26.15 --with-kubesphere v3.4.1这个命令会生成一个名为
config-sample.yaml的模板文件。接下来是最关键的一步:根据我们的架构定制这个文件。 -
深度定制
config-sample.yaml。用编辑器打开该文件,你需要重点关注以下几个部分:hosts:列出所有6台K8s节点(3管理+3计算)的详细信息。
hosts: - {name: guanlijiedian1, address: 192.168.1.101, internalAddress: 192.168.1.101, user: root, password: "YourSecurePassword"} - {name: guanlijiedian2, address: 192.168.1.102, internalAddress: 192.168.1.102, user: root, password: "YourSecurePassword"} - {name: guanlijiedian3, address: 192.168.1.103, internalAddress: 192.168.1.103, user: root, password: "YourSecurePassword"} - {name: jisuanjiedian1, address: 192.168.1.111, internalAddress: 192.168.1.111, user: root, password: "YourSecurePassword"} - {name: jisuanjiedian2, address: 192.168.1.112, internalAddress: 192.168.1.112, user: root, password: "YourSecurePassword"} - {name: jisuanjiedian3, address: 192.168.1.113, internalAddress: 192.168.1.113, user: root, password: "YourSecurePassword"}roleGroups:明确定义各节点的角色。etcd: 包含三台管理节点,组成etcd集群。control-plane: 同样包含三台管理节点,运行控制平面组件。worker: 包含三台计算节点。
roleGroups: etcd: - guanlijiedian1 - guanlijiedian2 - guanlijiedian3 control-plane: - guanlijiedian1 - guanlijiedian2 - guanlijiedian3 worker: - jisuanjiedian1 - jisuanjiedian2 - jisuanjiedian3controlPlaneEndpoint:这是高可用的核心配置。你需要提供一个负载均衡器(HAProxy)的访问地址和端口。假设我们在192.168.1.100上部署了HAProxy,监听6443端口。
controlPlaneEndpoint: domain: lb.k8s.local # 内部域名,可选 address: "192.168.1.100" # HAProxy的VIP或主机IP port: 6443etcd:配置etcd集群参数。生产环境建议配置SSL证书认证,KubeKey默认会创建。可以关注数据目录和资源预留。
etcd: type: kubekey # 使用KubeKey内置部署方式 # 数据目录,确保所在磁盘有足够空间和IOPS dataDir: /var/lib/etcdkubernetes:配置容器运行时(我们选Docker)和网络插件(如Calico)。
kubernetes: version: v1.26.15 clusterName: cluster.local containerManager: docker # 指定使用docker etcdBackupDir: /var/backups/k8s-etcd # 配置etcd备份目录 network: plugin: calico calico: ipipMode: Always # 或 CrossSubnet,根据网络环境选择 vxlanMode: Never vethMTU: 1440 # 根据底层网络MTU调整 -
执行集群创建。配置文件确认无误后,开始部署。
./kk create cluster -f config-sample.yaml -y这个过程会持续较长时间(约10-30分钟,取决于网络和机器性能),KubeKey会自动完成所有节点的初始化、组件安装和配置。最终,你会看到集群创建成功的提示,并获取到
kubeconfig文件,通常位于~/.kube/config。
2.3 验证集群与高可用性测试
部署完成后,立即进行验证。
# 查看所有节点状态,应均为Ready
kubectl get nodes -o wide
# 查看所有管理节点上的核心Pod状态(在kube-system命名空间)
kubectl get pods -n kube-system -o wide | grep -E 'apiserver|scheduler|controller-manager|etcd'
# 查看etcd集群成员健康状态(在任一管理节点上执行)
docker exec -it $(docker ps | grep etcd | awk '{print $1}') etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/ssl/etcd/ssl/ca.pem --cert=/etc/ssl/etcd/ssl/node-guanlijiedian1.pem --key=/etc/ssl/etcd/ssl/node-guanlijiedian1-key.pem endpoint health
高可用测试:尝试手动停止其中一个管理节点(如guanlijiedian2)的kube-apiserver容器,或直接重启该节点。在此期间,使用kubectl命令(其访问地址指向HAProxy的VIP)应仍然可以正常操作集群,只是响应可能略有延迟。这证明了负载均衡器和多副本控制平面组件起到了作用。
3. Harbor企业级镜像仓库部署与安全加固
有了稳定的K8s集群,我们需要一个安全、高效的“后勤中心”来存储和管理容器镜像。Harbor正是为此而生。
3.1 Docker环境准备与优化
在独立的Harbor服务器上,我们首先安装Docker。这里不采用系统仓库的版本,而是使用官方二进制包,便于版本控制。
# 下载特定版本的Docker二进制包(以20.10.24为例)
wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.24.tgz
tar -xzvf docker-20.10.24.tgz
# 将二进制文件复制到系统路径
sudo cp docker/* /usr/bin/
# 创建docker组并添加当前用户
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker # 刷新组权限
# 配置systemd服务单元
sudo tee /etc/systemd/system/docker.service <<-'EOF'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=1048576
LimitNPROC=1048576
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
配置镜像加速器:这是提升镜像拉取速度、减轻公网依赖的关键一步。我们以阿里云加速器为例。
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://<你的专属加速器域名>.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"storage-driver": "overlay2",
"live-restore": true
}
EOF
提示:请务必替换
registry-mirrors中的地址为你从阿里云容器镜像服务控制台获取的专属加速器地址。live-restore选项允许Docker守护进程重启时容器继续运行,对生产环境友好。
# 重新加载配置并启动Docker
sudo systemctl daemon-reload
sudo systemctl enable docker --now
# 验证安装
docker version
docker info | grep -A5 "Registry Mirrors"
3.2 Harbor v2.10 安装与核心配置
从Harbor官网下载离线安装包(harbor-offline-installer-v2.10.x.tgz)。
tar -xzvf harbor-offline-installer-v2.10.x.tgz
cd harbor
编辑配置文件harbor.yml。以下是最精简但满足生产基础需求的配置:
# 主机名或IP地址,客户端将用它来访问Harbor
hostname: harbor.yourcompany.com # 或直接使用IP,如192.168.1.200
# HTTP协议(生产环境强烈建议配置HTTPS,此处为简化先使用HTTP)
http:
port: 80
# HTTPS协议(注释掉则禁用)
# https:
# port: 443
# certificate: /your/certificate/path
# private_key: /your/private/key/path
# Harbor管理员密码
harbor_admin_password: Harbor12345 # 首次登录后务必修改!
# Harbor数据库密码
database:
password: root123
max_idle_conns: 50
max_open_conns: 100
# 数据持久化目录
data_volume: /data/harbor
# 日志配置
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
# 外部数据库和Redis(如需高可用,可配置外部实例)
# external_database:
# harbor:
# host: harbor_db_host
# port: 5432
# db_name: harbor
# username: postgres
# password: password
# external_redis:
# host: redis_host
# port: 6379
# password:
安全加固配置(在harbor.yml中):
# 启用内容信任(Notary),确保镜像来源可信
notary:
enabled: true
# 漏洞扫描器(Trivy或Clair),集成安全扫描
trivy:
enabled: true
ignore_unfixed: false
skip_update: false
offline_scan: false
security_check: vuln
# 设置项目配额,防止资源滥用
project_creation_restriction: adminonly # 仅管理员可创建项目
执行安装脚本:
sudo ./install.sh --with-notary --with-trivy
安装成功后,访问 http://harbor.yourcompany.com,使用admin和你在配置文件中设置的密码登录。
3.3 集成Kubernetes与Harbor
要让K8s集群能从私有Harbor拉取镜像,需要在集群中创建镜像拉取密钥(ImagePullSecret)。
- 在Harbor上创建项目,例如
prod。 - 创建机器人账户(Robot Account),赋予其对
prod项目的拉取权限。这比直接使用管理员账户更安全。 - 在Kubernetes中生成Secret:
kubectl create secret docker-registry harbor-registry-secret \ --namespace=default \ --docker-server=harbor.yourcompany.com \ --docker-username=robot$your-robot-account-name \ --docker-password=your-robot-account-token - 在Pod或Deployment中引用该Secret:
apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: template: spec: imagePullSecrets: - name: harbor-registry-secret containers: - name: app image: harbor.yourcompany.com/prod/my-app:v1.0
4. 生产环境运维、排错与优化实践
集群和仓库跑起来只是开始,如何让它稳定、高效地运行才是真正的挑战。
4.1 关键配置参数解析与调优
回顾我们使用的config-sample.yaml,理解几个关键参数对排错和优化至关重要:
etcd的dataDir:确保该目录挂载在性能较好的SSD磁盘上,并监控其磁盘使用率(超过80%需告警)。可以定期备份。kubernetes.network.calico.vethMTU:如果集群节点间网络存在隧道(如云厂商的VPC网络),需要根据底层网络的MTU值调整此参数,通常设置为底层MTU - 50。设置不当会导致网络性能急剧下降或不通。controlPlaneEndpoint:务必确保所有节点(包括计算节点)都能通过该地址(域名或IP)解析并访问到HAProxy。这是集群通信的基石。
4.2 常见故障排查场景
场景一:Pod状态一直Pending。
# 查看Pod的详细事件,通常能直接定位问题,如资源不足、镜像拉取失败
kubectl describe pod <pod-name> -n <namespace>
# 如果事件提示镜像拉取失败,检查:
# 1. 节点是否能解析Harbor域名
# 2. Harbor项目权限和机器人账户令牌是否正确
# 3. 节点上的Docker daemon配置的`insecure-registries`是否包含了Harbor地址(如果使用HTTP)
场景二:节点状态NotReady。
# 登录到问题节点,检查关键服务
systemctl status kubelet
systemctl status docker
journalctl -u kubelet --since "1 hour ago" | tail -100
# 常见原因:磁盘空间不足、内存压力、网络插件(Calico)Pod异常
df -h
free -h
kubectl get pods -n calico-system
场景三:kubectl命令执行缓慢或超时。
这很可能指向控制平面或负载均衡器问题。
# 检查HAProxy状态和日志
# 假设HAProxy运行在192.168.1.100上
ssh root@192.168.1.100 "systemctl status haproxy"
# 分别直接访问三个管理节点的API Server健康端点,检查是否都正常
curl -k https://192.168.1.101:6443/healthz
curl -k https://192.168.1.102:6443/healthz
curl -k https://192.168.1.103:6443/healthz
# 如果某个节点失败,登录该节点检查`kube-apiserver`容器日志
4.3 日常运维建议
- 监控与日志:尽快部署集群监控(如Prometheus + Grafana),监控节点资源、Pod状态、etcd性能指标。集中收集所有组件和应用的日志(如EFK栈)。
- etcd备份:使用
etcdctl定期对etcd数据进行快照备份,并将备份文件传输到异地存储。KubeKey生成的集群,可以编写cronjob来执行备份。# 示例备份命令(需在etcd节点上,且有证书) etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/ssl/etcd/ssl/ca.pem --cert=/etc/ssl/etcd/ssl/node.pem --key=/etc/ssl/etcd/ssl/node-key.pem snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db - Harbor维护:定期清理不再使用的镜像层(通过Harbor UI的垃圾回收功能)。配置Harbor与外部用户目录(如LDAP/AD)集成,统一身份认证。为关键项目设置Webhook,当有新的漏洞扫描结果时通知安全团队。
- 节点管理:对节点进行任何维护(如内核升级、重启)前,先使用
kubectl drain <node-name>安全驱逐Pod。操作完成后,使用kubectl uncordon <node-name>将其重新加入调度。
这套从架构设计到部署、再到运维的完整流程,是我们团队在多个中小型生产环境中反复验证过的。它可能不是最豪华的配置,但在稳定性、可维护性和资源消耗之间取得了不错的平衡。记住,每一个生产集群都有自己的特性,最好的实践是在理解原理的基础上,根据实际的监控数据和故障反馈进行持续调优。刚开始可能会遇到一些坎,比如网络策略冲突、存储卷挂载失败,但每一次问题的解决都会让你对这套系统的掌控力更深一分。
更多推荐
所有评论(0)