ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Docker与Kubespray的国内高可用K8S集群部署实战

基于Docker与Kubespray的国内高可用K8S集群部署实战 简介容器编排是现代云原生架构的核心它通过自动化应用的部署、扩展和管理极大地提升了资源利用率和运维效率。Kubernetes作为容器编排的事实标准其高可用集群的部署却常因网络环境和复杂配置而充满挑战。Kubespray基于Ansible以声明式配置实现了对裸金属和私有云环境的自动化部署其技术价值在于将复杂的证书、网络、存储及高可用组件如etcd的配置过程标准化。结合Docker提供的环境封装能力可以确保部署环境的一致性。针对国内开发者普遍面临的镜像拉取慢、依赖下载困难等网络问题通过预制的资源包将关键组件替换为国内镜像源实现了高效、可靠的离线或加速部署。这一方案特别适用于中小团队在受限网络下自建私有云、搭建CI/CD流水线等应用场景是快速获得生产就绪Kubernetes集群的实用路径。1. 项目概述与核心价值最近在帮几个团队做容器化和微服务架构升级发现一个挺普遍的现象大家一提到要自己搭建生产级的Kubernetes集群第一反应就是“头大”。确实从零开始手动部署一个高可用的K8S集群涉及证书、网络、存储、高可用组件如etcd、负载均衡器等一系列复杂配置任何一个环节出问题都可能导致部署失败或集群不稳定。尤其是在国内网络环境下镜像拉取慢、依赖包下载困难更是让这个过程雪上加霜。我折腾过不少方案从kubeadm到各种一键脚本直到遇到了Kubespray才算是找到了一个在可控性和自动化之间取得良好平衡的利器。这个项目标题“基于docker使用kubespray工具部署高可用K8S集群(国内互联网方案一)部署资源包”其实精准地指向了我们国内开发者最核心的痛点如何在受限的网络环境下高效、可靠地部署一个生产就绪的高可用K8S集群。它不是一个简单的教程而是一个经过验证的、包含特定优化方案的“资源包”。这里的“资源包”意味着它很可能已经为你准备好了经过国内镜像源加速的Docker镜像、必要的二进制文件、以及针对国内网络定制的Kubespray配置。这能帮你跳过最耗时的“下载-等待-失败-重试”循环直接进入部署的核心环节。简单来说这个方案的价值在于它用Docker封装了部署环境用Kubespray实现了自动化编排并通过预制的“资源包”解决了国内网络访问的难题。最终目标是让你能在一组物理机或虚拟机上通过几条命令就得到一个多Master节点的高可用K8S集群。这对于中小团队自建私有云、搭建CI/CD环境、或者进行PaaS平台开发测试都是一个非常实用的起点。2. 核心工具与方案选型解析2.1 为什么是Kubespray在K8S部署工具领域选择很多。kubeadm是官方工具灵活但需要手动处理很多高可用细节kOps在云环境上很强大但对裸金属支持一般Rancher、OpenShift等发行版则封装了更多东西可能不够“原汁原味”。Kubespray前身是Kargo脱颖而出主要是因为它基于Ansible提供了声明式的配置并且对裸金属和私有云环境支持得非常好。它的工作原理很像烹饪你有一份食谱Inventory文件上面列出了所有食材服务器节点和调料配置变量。Kubespray作为厨师Ansible Playbook会按照食谱自动完成从系统初始化、容器运行时安装、到K8S各个组件部署和配置的全过程。它内置了高可用方案可以自动为你部署多个etcd实例和Master节点并配置负载均衡通常使用HAProxy和keepalived。这意味着你不需要手动去拼接这些复杂的部件。对于这个“国内互联网方案一”而言选择Kubespray的深层原因还包括其高度可定制性。它的变量系统非常强大我们可以轻松地将所有需要从国外下载的组件如kube-apiserver镜像、calico插件镜像、系统依赖包的源替换为国内的镜像站如阿里云、华为云、腾讯云的镜像仓库这是解决网络问题的关键。2.2 Docker在其中的角色环境封装与隔离标题中明确提到了“基于docker使用kubespray”。这里Docker扮演的角色不是K8S的容器运行时虽然Kubespary默认也支持Docker作为运行时而是部署执行环境的封装工具。想象一下Kubespray依赖Ansible、Python以及一系列Python库。不同人的开发机环境千差万别Python版本、库版本冲突是家常便饭。“基于Docker”意味着项目提供了一个Docker镜像这个镜像里已经预装好了所有正确版本的部署工具Ansible, Kubespray代码必要的Python包。你只需要在本机安装Docker然后拉取这个镜像并运行一个容器就能获得一个纯净、一致、开箱即用的部署环境。这样做的好处显而易见环境一致性杜绝了“在我机器上好好的”这类问题。快速启动无需在宿主机上折腾Python环境和依赖。易于分发和复用这个Docker镜像本身就是“资源包”的核心部分可以方便地在团队内部分享。2.3 “国内互联网方案一”的深层含义这可能是整个方案最精华的部分。一个标准的Kubespray部署在gcr.io、quay.io畅通无阻的网络环境下是顺畅的。但在国内这些默认的镜像仓库几乎无法访问会导致部署脚本长时间卡住最终失败。“方案一”暗示着作者已经做了针对性的优化。通常这类优化包括镜像仓库替换在Kubespray的配置变量如kube_image_repogcr_image_repodocker_image_repo中将谷歌、Quay等地址批量替换为阿里云、中科大等国内镜像仓库地址。二进制文件预置将kubeletkubectlkubeadm等二进制文件以及etcdcni插件等提前下载好并放入资源包的特定目录。部署时Ansible会直接从本地路径分发这些文件到目标节点完全绕过网络下载。系统包源配置在部署初期自动为所有目标节点配置国内的YUM/APT软件源如阿里云镜像站加速系统级依赖包如docker-cesocatconntrack的安装。离线部署支持这是更彻底的方案。资源包可能包含一个完整的、已经拉取好的Docker镜像Tar包合集。通过docker save和docker load可以在完全离线的环境中导入所有必需的容器镜像。这个“资源包”很可能就是一个压缩文件解压后里面包含了上述所有优化后的配置文件、二进制文件和镜像包以及一个封装好的Docker部署环境。注意使用此类资源包时务必检查其来源是否可靠。镜像和二进制文件的完整性至关重要建议从官方渠道获取哈希值进行校验或自行根据公开的优化方案构建属于自己的资源包。3. 部署前准备与环境规划3.1 硬件与系统资源规划部署一个高可用K8S集群合理的资源规划是成功的第一步。这里我们以部署一个典型的3Master 2Worker节点的高可用集群为例。节点角色与最小配置建议Master节点承担控制平面组件API Server Scheduler Controller Manager和etcd的运行。这是集群的大脑需要更高的稳定性和资源。数量至少3个以实现高可用和etcd集群的奇数仲裁。CPU2核或以上。内存4GB或以上。如果启用更多插件或部署密集需要更多。磁盘40GB系统盘。/var/lib/etcd目录需要单独的磁盘或分区以获得最佳性能建议SSD。Worker节点运行实际工作负载的节点。数量根据业务需求至少2个以实现基础的工作负载分布。CPU/Memory取决于你的应用需求。起步建议2核4GB。磁盘40GB系统盘并为/var/lib/docker和/var/lib/kubelet预留足够空间。网络规划节点网络所有节点必须在同一个二层网络或三层可达的网络内且能通过IP互相访问。Pod网络Kubespray默认使用Calico或Flannel等CNI插件会为Pod分配一个独立的网段如10.233.64.0/18。确保这个网段与你的节点物理网络不冲突。Service网络K8S内部Service的虚拟IP网段如10.233.0.0/18同样不能与物理网络和Pod网络重叠。端口要求确保节点间以下端口互通这是K8S组件通信所必需的Master节点6443 (Kubernetes API) 2379-2380 (etcd) 10250 (kubelet API) 10257 (kube-controller-manager) 10259 (kube-scheduler)等。Worker节点10250 30000-32767 (NodePort服务)等。Kubespray的Ansible通过SSH22端口连接到所有节点执行任务。3.2 部署环境初始化假设我们准备了三台机器作为Master两台作为Worker主机名和IP如下k8s-master-01: 192.168.1.101k8s-master-02: 192.168.1.102k8s-master-03: 192.168.1.103k8s-worker-01: 192.168.1.201k8s-worker-02: 192.168.1.202在所有节点上执行以下初始化操作配置主机名与Hosts# 在每台机器上设置永久主机名以master-01为例 hostnamectl set-hostname k8s-master-01 # 编辑 /etc/hosts 添加所有节点的IP和主机名映射 echo “192.168.1.101 k8s-master-01 192.168.1.102 k8s-master-02 192.168.1.103 k8s-master-03 192.168.1.201 k8s-worker-01 192.168.1.202 k8s-worker-02” /etc/hosts关闭防火墙与SELinux生产环境请根据安全策略调整# 关闭防火墙以CentOS 7为例 systemctl stop firewalld systemctl disable firewalld # 关闭SELinux setenforce 0 sed -i ‘s/^SELINUXenforcing/SELINUXdisabled/’ /etc/selinux/config禁用SwapKubernetes要求禁用Swap以确保内存管理的正确性。swapoff -a sed -i ‘/ swap / s/^\(.*\)$/#\1/g’ /etc/fstab # 注释掉fstab中的swap行配置内核参数与模块加载# 加载br_netfilter模块 modprobe br_netfilter # 配置sysctl参数 cat /etc/sysctl.d/k8s.conf EOF net.bridge.bridge-nf-call-ip6tables 1 net.bridge.bridge-nf-call-iptables 1 net.ipv4.ip_forward 1 EOF sysctl -p /etc/sysctl.d/k8s.conf配置SSH免密登录在部署机即运行Docker容器的那台机器可以是上述节点之一也可以是一台独立的运维机上生成SSH密钥并将公钥分发到所有节点包括自己如果部署机也是集群节点的话。这是Ansible自动化操作的基础。# 在部署机上执行 ssh-keygen -t rsa -b 2048 # 一路回车 for node in k8s-master-01 k8s-master-02 k8s-master-03 k8s-worker-01 k8s-worker-02; do ssh-copy-id $node done3.3 获取并理解“部署资源包”假设你从可靠的渠道获得了一个名为kubespray-offline-package-v2.xx.tar.gz的资源包。解压后目录结构可能如下kubespray-offline-package/ ├── docker-images/ # 所有必需的Docker镜像tar包 │ ├── kube-apiserver.tar │ ├── calico-node.tar │ └── ... ├── binaries/ # 所有必需的二进制文件 │ ├── kubernetes/ │ ├── etcd/ │ └── cni/ ├── kubespray/ # 修改过的Kubespray代码 │ ├── inventory/ # 示例库存文件 │ ├── group_vars/ # 已配置国内镜像源的变量文件 │ └── ... ├── docker-compose.yml # 或一个启动脚本 └── README.md # 部署说明这个结构就是“方案一”的实体。kubespray/group_vars/all/offline.yml或all.yml里关键配置可能已经变成了# 使用国内镜像仓库 gcr_image_repo: “registry.aliyuncs.com/google_containers” kube_image_repo: “registry.aliyuncs.com/google_containers” docker_image_repo: “registry.cn-hangzhou.aliyuncs.com” # 指定从本地文件安装 kubeadm_download_url: “file:///kubespray/binaries/kubernetes/kubeadm” kubelet_download_url: “file:///kubespray/binaries/kubernetes/kubelet”你的任务就是在这个优化好的基础上填写自己的集群信息并启动部署。4. 基于Docker与资源包的集群部署实操4.1 启动部署容器环境我们将部署机作为工作机。首先确保部署机上安装了Docker。然后将资源包上传并解压。# 1. 上传并解压资源包 tar -zxvf kubespray-offline-package-v2.xx.tar.gz cd kubespray-offline-package # 2. 加载离线Docker镜像如果资源包提供了 # 这个镜像包含了Ansible和Kubespray环境 docker load -i kubespray-offline-image.tar # 3. 根据资源包内的指引启动容器 # 常见的方式是使用一个docker run命令将本地目录挂载到容器内 docker run -it --rm \ --name kubespray-deployer \ -v $(pwd)/kubespray:/kubespray \ -v $(pwd)/inventory:/kubespray/inventory/mycluster \ -v ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro \ kubespray-offline:latest bash这条命令做了几件事启动一个临时容器将本地的kubespray目录包含代码和配置挂载到容器的/kubespray将你准备好的库存目录挂载进去并把你的SSH私钥挂载给容器内的root用户使用ro表示只读。最后进入容器的bash shell。实操心得挂载SSH私钥时务必使用只读模式(:ro)防止容器内误操作修改或覆盖你的私钥。也可以选择挂载整个.ssh目录但要注意权限问题。4.2 配置集群库存清单现在你在容器内的/kubespray目录下。进入inventory/mycluster目录这是我们挂载进去的这里存放着定义集群结构的文件。核心文件是inventory.ini或通过inventory/sample复制生成的。我们需要根据之前的规划来修改它。Kubespray使用Ansible的INI格式库存文件。# inventory/mycluster/inventory.ini [all] k8s-master-01 ansible_host192.168.1.101 ip192.168.1.101 k8s-master-02 ansible_host192.168.1.102 ip192.168.1.102 k8s-master-03 ansible_host192.168.1.103 ip192.168.1.103 k8s-worker-01 ansible_host192.168.1.201 ip192.168.1.201 k8s-worker-02 ansible_host192.168.1.202 ip192.168.1.202 [kube_control_plane] k8s-master-01 k8s-master-02 k8s-master-03 [etcd] k8s-master-01 k8s-master-02 k8s-master-03 [kube_node] k8s-worker-01 k8s-worker-02 # 如果Master也承担计算任务不推荐生产可以加到这里 # k8s-master-01 # k8s-master-02 # k8s-master-03 [calico_rr] [k8s_cluster:children] kube_control_plane kube_node[all]列出所有节点并指定Ansible连接用的IP(ansible_host)和节点内部通信IP(ip)通常相同。[kube_control_plane]指定哪些节点作为控制平面Master。[etcd]指定etcd集群成员通常与Master节点重合以实现并置部署。[kube_node]指定工作节点。4.3 关键配置变量调优接下来需要检查并修改组变量文件它们位于inventory/mycluster/group_vars/目录下。资源包可能已经预配置了大部分但我们仍需确认关键项。k8s-cluster.yml核心K8S配置。# inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml # 容器运行时containerd是更新的选择但这里资源包可能针对Docker优化了 container_manager: docker # Kubernetes版本确保资源包中的二进制文件和镜像版本与此一致 kube_version: v1.28.8 # 集群Pod的IP网段CIDR kube_pods_subnet: 10.233.64.0/18 # 集群Service的IP网段CIDR kube_service_addresses: 10.233.0.0/18 # 网络插件Calico性能功能较均衡 kube_network_plugin: calico # DNS域名 cluster_name: cluster.local # 自动为节点打上机架、区域等标签便于调度 topology_labels: trueall.yml全局通用配置。# inventory/mycluster/group_vars/all/all.yml # 离线部署模式开关如果资源包是全离线的这里要打开 offline_deployment: true # 国内镜像源配置资源包应已设置 # gcr_image_repo: “registry.aliyuncs.com/google_containers” # docker_image_repo: “registry.cn-hangzhou.aliyuncs.com” # 系统包管理器源加速系统级软件安装 yum_repo: “http://mirrors.aliyun.com/centos/$releasever/os/$basearch” # 或者使用 apt_deb_repo 对应Debian/Ubuntu # 时区设置 system_timezone: Asia/Shanghaiaddons.yml插件配置可选。你可以在这里启用Ingress Controller如nginx、监控如prometheus、日志如efk等。初次部署建议先保持集群纯净后续再按需添加。# inventory/mycluster/group_vars/k8s-cluster/addons.yml dashboard_enabled: false ingress_nginx_enabled: false prometheus_enabled: false4.4 执行部署命令配置检查无误后就可以开始执行部署了。在容器内的/kubespray目录下运行# 1. 首先测试Ansible到所有节点的连接 ansible -i inventory/mycluster/inventory.ini all -m ping # 如果所有节点都返回“pong”说明SSH连接和Python环境正常。 # 2. 执行集群部署Playbook ansible-playbook -i inventory/mycluster/inventory.ini cluster.yml -b -v-i指定库存文件路径。-b使用become即提权执行需要节点有sudo权限。-v输出详细日志方便排查问题。第一次运行可以加-vvv获取更详细输出。这个cluster.yml剧本是Kubespray的主剧本它会按顺序执行以下核心任务基础准备检查系统、配置仓库、安装基础依赖。容器运行时安装根据container_manager变量安装Docker并配置镜像加速如果docker_image_repo已配置为国内源这里会生效。Kubernetes组件安装从本地路径offline_deployment: true时分发kubeletkubectlkubeadm等二进制文件并拉取或从本地加载容器镜像。控制平面部署在Master节点上部署etcd集群、kube-apiserverkube-controller-managerkube-scheduler并配置高可用负载均衡通常是HAProxykeepalived在Master节点本地以静态Pod或容器方式运行。工作节点加入将Worker节点加入集群。网络插件部署安装并配置Calico建立Pod网络。核心插件部署安装CoreDNS metrics-server等。整个过程视网络和机器性能通常需要10到30分钟。你可以观察Ansible的输出它会清晰地显示当前正在执行的任务和每个节点的状态。4.5 验证集群状态部署完成后需要在任意一个Master节点上验证集群状态。首先从容器内复制管理员kubeconfig文件到本地或者直接在某个Master节点上操作因为kubectl和配置文件已安装。# 在Master节点例如k8s-master-01上执行 # 查看节点状态所有节点应为Ready kubectl get nodes -o wide # 查看所有Pod的状态确保kube-system命名空间下的核心组件都Running kubectl get pods -n kube-system -o wide # 查看集群信息 kubectl cluster-info如果一切正常你将看到一个包含5个Ready节点的集群以及kube-system下所有核心Pod都在运行。5. 部署后配置与优化5.1 配置kubectl命令行访问为了方便从你的本地笔记本或运维机管理集群需要将Master节点上的/etc/kubernetes/admin.conf文件复制到本地并配置环境变量。# 在本地机器非集群节点上操作 # 1. 从Master节点复制配置文件 scp root192.168.1.101:/etc/kubernetes/admin.conf ~/.kube/config-k8s-cluster # 2. 设置KUBECONFIG环境变量或合并到现有config export KUBECONFIG~/.kube/config-k8s-cluster # 也可以写入shell配置文件如 ~/.bashrc # 3. 验证 kubectl get nodes现在你就可以在本地使用kubectl管理这个集群了。5.2 配置容器镜像加速虽然部署时解决了K8S系统组件的镜像源但后续你自己部署应用时拉取docker.io等公共仓库的镜像可能依然很慢。需要在所有节点的Docker配置中增加国内镜像加速器。# 在所有节点上执行 cat /etc/docker/daemon.json EOF { “registry-mirrors”: [ “https://registry.cn-hangzhou.aliyuncs.com” “https://docker.mirrors.ustc.edu.cn” ], “exec-opts”: [“native.cgroupdriversystemd”], “log-driver”: “json-file” “log-opts”: { “max-size”: “100m” }, “storage-driver”: “overlay2” } EOF systemctl daemon-reload systemctl restart docker注意native.cgroupdriver需要与Kubelet的配置一致Kubespray默认已配置为systemd否则节点会报错。5.3 安装Ingress Controller与存储类一个生产可用的集群通常需要入口网关和持久化存储。安装Nginx Ingress Controller# 使用Helm安装需先安装Helm helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helm install ingress-nginx ingress-nginx/ingress-nginx \ --namespace ingress-nginx \ --create-namespace \ --set controller.hostNetworktrue # 如果节点有公网IP可以用这种方式直接暴露80/443端口或者你也可以在Kubespray的addons.yml中预先配置ingress_nginx_enabled: true并重新运行cluster.yml。配置本地存储类示例对于测试或特定场景可以配置一个hostpath存储类注意hostPath不适合多节点生产环境。# local-sc.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumerkubectl apply -f local-sc.yaml对于生产环境你需要根据你的基础设施如云盘、Ceph、NFS、Longhorn等部署对应的CSI驱动和存储类。6. 常见问题排查与运维技巧6.1 部署阶段常见错误部署过程中Ansible任务可能会失败。以下是一些常见问题及排查思路问题1任务“Download containers | Pull required images”卡住或失败。原因虽然配置了国内镜像源但某些特定镜像的标签可能在镜像站不存在或同步延迟。排查查看Ansible错误详情找到是哪个镜像拉取失败。登录对应节点手动执行docker pull image_name:tag看具体报错。检查inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml中的kube_image_repo等变量是否正确。如果资源包提供了离线镜像确认offline_deployment: true已设置并且镜像已正确加载到节点本地docker images查看。问题2节点状态为NotReady。排查# 在问题节点上执行 systemctl status kubelet # 查看kubelet服务是否运行 journalctl -xeu kubelet # 查看kubelet日志常见错误 # - 网络插件未就绪cni config uninitialized # - cgroup驱动不一致driver “cgroupfs“ is different from docker driver “systemd“ # - 证书问题 kubectl describe node node-name # 在Master上查看节点详细事件问题3etcd集群健康检查失败。排查# 在任一Master节点上使用etcdctl检查集群健康状态 docker exec $(docker ps | grep etcd | awk ‘{print $1}’) etcdctl --endpointshttps://127.0.0.1:2379 --cacert/etc/ssl/etcd/ssl/ca.pem --cert/etc/ssl/etcd/ssl/node-$(hostname).pem --key/etc/ssl/etcd/ssl/node-$(hostname)-key.pem endpoint health如果输出显示某个etcd成员不健康检查该成员节点的/var/log/etcd.log日志以及2379、2380端口是否被正确监听和可达。6.2 日常运维命令速查查看集群事件kubectl get events --sort-by‘.lastTimestamp’ -w查看Pod详细日志kubectl logs -f pod-name -n namespace进入Pod调试kubectl exec -it pod-name -n namespace -- /bin/sh查看Pod描述定位失败原因kubectl describe pod pod-name -n namespace强制删除卡在Terminating状态的Podkubectl delete pod pod-name -n namespace --grace-period0 --force查看节点资源使用kubectl top nodes查看Pod资源使用kubectl top pods -A备份etcd在生产环境中定期备份etcd数据至关重要。Kubespray部署的etcd通常以容器运行备份脚本需要进入容器执行命令。6.3 集群升级与节点管理使用Kubespray升级集群 Kubespray也支持集群升级。修改kube_version变量到新版本并确保资源包中有对应版本的二进制和镜像然后运行ansible-playbook -i inventory/mycluster/inventory.ini upgrade-cluster.yml -b注意升级前务必在测试环境验证并详细阅读Kubespray官方文档中关于升级的说明因为不同版本间的升级路径可能有特定要求。添加新节点在新节点上完成“部署前准备”中的所有初始化步骤。在部署机的库存文件inventory.ini中将新节点添加到[all]和[kube_node]或[kube_control_plane]组。运行节点添加剧本ansible-playbook -i inventory/mycluster/inventory.ini scale.yml -b安全删除节点将节点标记为不可调度并排空工作负载kubectl cordon node-name kubectl drain node-name --ignore-daemonsets --delete-emptydir-data在库存文件inventory.ini中移除该节点。运行节点移除剧本如果需要清理ansible-playbook -i inventory/mycluster/inventory.ini remove-node.yml -b -e “nodenode-name”整个基于Docker和Kubespray资源包的部署过程核心思想是将复杂的、易受网络影响的准备工作标准化、离线化通过成熟的自动化工具完成后续的繁琐配置。这个方案极大地降低了在国内环境部署生产级K8S集群的门槛和不确定性。当你成功运行起第一个集群后就可以更深入地研究Kubespray的变量体系定制出完全符合自己业务需求的部署方案了。本文还有配套的精品资源点击获取
返回列表