高可用 kubernetes 集群部署实践

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
云备份 Cloud Backup,100GB 3个月
简介: Kubernetes(k8s) 凭借着其优良的架构,灵活的扩展能力,丰富的应用编排模型,成为了容器编排领域的事实标准。越来越多的企业拥抱这一趋势,选择 k8s 作为容器化应用的基础设施,逐渐将自己的核心服务迁移到 k8s 之上。

前言

Kubernetes(k8s) 凭借着其优良的架构,灵活的扩展能力,丰富的应用编排模型,成为了容器编排领域的事实标准。越来越多的企业拥抱这一趋势,选择 k8s 作为容器化应用的基础设施,逐渐将自己的核心服务迁移到 k8s 之上。

可用性对基础设施而言至关重要。各大云计算厂商纷纷推出了高可用、可扩展的 k8s 托管服务,其中比较有代表性的有 Amazon EKSAzure Kubernetes Service (AKS)Google Kubernetes Engine阿里云容器服务 Kubernetes 版等。

虽然公有云托管的 k8s 服务百花齐放,但很多企业仍有自建集群的需求。正是这样的原因,促进了一大批出色的 k8s 集群部署方案的诞生,他们的特点如下表所示。

部署方案 特点
Kubeadm 1. 官方出品的部署工具,提供了 k8s 集群生命周期管理的领域知识。
2. 旨在成为更高级别工具的可组合构建块。
Kubespray 1. 支持在裸机和 AWS、GCE、Azure 等众多云平台上部署 k8s。
2. 基于 Ansible Playbook 定义 k8s 集群部署任务。
3. 支持大部分流行的 Linux 发行版。
Kops 1. 仅支持在 AWS、GCE 等少数云平台上部署 k8s。
2. 建立在状态同步模型上,用于 dry-run 和自动幂等性。
3. 能够自动生成 Terraform 配置。
Rancher Kubernetes Engine(RKE) 1. 著名的开源企业级容器管理平台 Rancher 提供的轻量级 k8s 安装工具。
2. 支持在裸机、虚拟机、公有云上部署和管理 k8s 集群。

上述方案中,RKE 在易用性和灵活性上占有优势。本文接下来将介绍如何通过 RKE 部署一套高可用 k8s 集群,文中使用的 RKE 版本为v0.2.2

高可用 k8s 集群架构

首先需要了解高可用 k8s 集群的架构特点,下图是官方推荐的高可用集群架构图。

k8s_arch

其核心思想是让 k8s master 节点中的各类组件具备高可用性,消除单点故障。

  • kube-apiserver - 对外暴露了 k8s API,是整个集群的访问入口。由于 apiserver 本身无状态,可以通过启动多个实例并结合负载均衡器实现高可用。
  • etcd - 用于存储 k8s 集群的网络配置和对象的状态信息,是整个集群的数据中心。可以通过启动奇数个 etcd 实例建立一个冗余的,可靠的数据存储层。
  • kube-scheduler - 为新创建的 pod 选择一个供他们运行的节点。一个集群只能有一个活跃的 kube-scheduler 实例,可以同时启动多个 kube-scheduler 并利用领导者选举功能实现高可用。
  • kube-controller-manager - 集群内部的管理控制中心。一个集群只能有一个活跃的 kube-controller-manager 实例,可以同时启动多个 kube-controller-manager 并利用领导者选举功能实现高可用。

此外,构建集群的时还需要注意下列问题。

  • 节点上 k8s 进程的可靠性。需要让 kubelet、kube-scheduler、kube-controller-manager 等进程在出现故障后能自动重启。
  • 为 worker node 中的非 pod 进程预留资源,防止他们将与 pod 争夺资源导致节点资源短缺。

使用 RKE 构建高可用 k8s 集群

节点规划

构建集群的第一步是将拥有的服务器按节点功能进行划分,下表展示了笔者环境下的节点规划情况。

IP 角色
192.168.0.10 部署节点
192.168.0.11 k8s master - api-server, etcd, scheduler, controller-manager
192.168.0.12 k8s master - api-server, etcd, scheduler, controller-manager
192.168.0.13 k8s master - api-server, etcd, scheduler, controller-manager
192.168.0.14 k8s worker - kubelet, kube-proxy
192.168.0.15 k8s worker - kubelet, kube-proxy
192.168.0.16 k8s worker - kubelet, kube-proxy
192.168.0.17 k8s worker - kubelet, kube-proxy

规划说明:

  1. 单独选择了一台机器192.168.0.10作为部署节点。如果机器数不多,可以将部署节点加入到 k8s 集群中。
  2. 为了保证可用性,择了三台机器部署 k8s master 组件。如果有条件,可以将 etcd 和 master 中的其他组件分开部署,这样可以根据需要更灵活地控制实例个数。例如,在访问压力不大但对数据可靠性要求比较高的情况下,可以专门选择 5 台机器部署 etcd,另外选择 3 台机器部署 master 中的其他组件。
  3. 剩余四台机器作为 k8s worker 节点。节点个数需要根据实际情况动态调整。当有 pod 因资源不足一直处于 pending 状态时,可以对 worker 进行扩容。当 node 的资源利用率较低时,且此 node 上存在的 pod 都能被重新调度到其他 node 上运行时,可以对 worker 进行缩容。

环境准备

在完成节点规划后,需要进行环境准备工作,主要包含以下内容:

  1. 安装 RKE - 需要在部署节点(192.168.0.10)上安装 RKE 二进制包,具体安装方法可参考 download-the-rke-binary
  2. 配置 SSH 免密登录 - 由于 RKE 通过 SSH tunnel 安装部署 k8s 集群,需要配置 RKE 所在节点到 k8s 各节点的 SSH 免密登录。如果 RKE 所在节点也需要加入到 k8s 集群中,需要配置到本机的 SSH 免密登录。
  3. 安装 docker - 由于 RKE 通过 docker 镜像rancher/hyperkube启动 k8s 组件,因此需要在 k8s 集群的各个节点(192.168.0.11 ~ 192.168.0.17 这 7 台机器)上安装 docker。
  4. 关闭 swap - k8s 1.8 开始要求关闭系统的 swap,如果不关闭,默认配置下 kubelet 将无法启动。这里需要关闭所有 k8s worker 节点的 swap。

配置 cluster.yml

在完成环境准备后,需要通过 cluster.yml 描述集群的组成和 k8s 的部署方式。

配置集群组成

配置文件 cluster.yml 中的 nodes 配置项用于描述集群的组成。根据节点规划,对于 k8s master 节点,指定其角色为controlplaneetcd。对于 k8s worker 节点,指定其角色为worker

nodes:
  - address: 192.168.0.1
    user: admin
    role:
      - controlplane
      - etcd
  ...
  - address: 192.168.0.7
    user: admin
    role:
      - worker

设置资源预留

K8s 的 worker node 除了运行 pod 类进程外,还会运行很多其他的重要进程,包括 k8s 管理进程,如 kubelet、dockerd,以及系统进程,如 systemd。这些进程对整个集群的稳定性至关重要,因此需要为他们专门预留一定的资源。

笔者环境中的 worker 设置如下:

  • 节点拥有 32 核 CPU,64Gi 内存和 100Gi 存储。
  • 为 k8s 管理进程预留了 1 核 CPU,2Gi 内存和 1Gi 存储。
  • 为系统进程预留了 1 核 CPU,1Gi 内存和 1Gi 存储。
  • 为内存资源设置了 500Mi 的驱逐阈值,为磁盘资源设置了 10% 的驱逐阈值。

在此场景下,节点可分配的 CPU 资源是 29 核,可分配的内存资源是 60.5Gi,可分配的磁盘资源是 88Gi。对于不可压缩资源,当 pod 的内存使用总量超过 60.5Gi 或者磁盘使用总量超过 88Gi 时,QoS 较低的 pod 将被优先驱逐。对于可压缩资源,如果节点上的所有进程都尽可能多的使用 CPU,则 pod 类进程加起来不会使用超过 29 核的 CPU 资源。

上述资源预留设置在 cluster.yml 中具体形式如下。

services:
  kubelet:
    extra_args:
      cgroups-per-qos: True
      cgroup-driver: cgroupfs
      kube-reserved: cpu=1,memory=2Gi,ephemeral-storage=1Gi
      kube-reserved-cgroup: /runtime.service
      system-reserved: cpu=1,memory=1Gi,ephemeral-storage=1Gi
      system-reserved-cgroup: /system.slice
      enforce-node-allocatable: pods,kube-reserved,system-reserved
      eviction-hard: memory.available<500Mi,nodefs.available<10%

关于资源预留更详细的内容可参考文章 Reserve Compute Resources for System Daemons

部署 k8s 集群

当 cluster.yml 文件配置完成后,可以通过命令rke up完成集群的部署任务。下图展示了通过 RKE 部署的 k8s 集群架构图。

rke_arch

该架构有如下特点:

  1. 集群中的各个组件均通过容器方式启动,并且设置重启策略为always。这样当他们出现故障意外退出后,能被自动拉起。
  2. Master 节点上的 kube-scheduler、kube-controller-manager 直接和本机的 API server 通信。
  3. Worker 节点上的 nginx-proxy 拥有 API server 的地址列表,负责代理 kubelet、kube-proxy 发往 API server 的请求。
  4. 为了让集群具有灾备能力,master 节点上的 etcd-rolling-snapshots 会定期保存 etcd 的快照至本地目录/opt/rke/etcd-snapshots中。

配置负载均衡器

在完成了集群部署后,可以通过 API server 访问 k8s。由于环境中启动了多个 kube-apiserver 实例以实现高可用,需要为这些实例架设一个负载均衡器。这里在192.168.0.10上部署了一台 nginx 实现了负载均衡的功能,nginx.conf 的具体配置如下。

...
stream {
    upstream apiserver {
        server 192.168.0.11:6443 weight=5 max_fails=3 fail_timeout=60s;
        server 192.168.0.12:6443 weight=5 max_fails=3 fail_timeout=60s;
        server 192.168.0.13:6443 weight=5 max_fails=3 fail_timeout=60s;
    }

    server {
        listen 6443;
        proxy_connect_timeout 1s;
        proxy_timeout 10s;
        proxy_pass apiserver;
    }
}
...

这时,通过负载均衡器提供的端口访问 API server 会出现异常Unable to connect to the server: x509: certificate is valid for xxx, not 192.168.0.10。这里需要将负载均衡器的 IP 地址或域名加入到 API server 的 PKI 证书中,可以通过 cluster.yml 中的 authentication 配置项完成此功能。

authentication:
  strategy: x509
  sans:
    - "192.168.0.10"

修改完 cluster.yml 后,运行命令rke cert-rotate

验证

在完成上述所有步骤后,可以通过命令kubectl get nodes查看节点状态。如果所有节点的状态均为 Ready,则表示集群部署成功。

NAME            STATUS    ROLES              AGE    VERSION
192.168.0.11    Ready     controlplane,etcd  1d     v1.13.5
192.168.0.12    Ready     controlplane,etcd  1d     v1.13.5
192.168.0.13    Ready     controlplane,etcd  1d     v1.13.5
192.168.0.14    Ready     worker             1d     v1.13.5
192.168.0.15    Ready     worker             1d     v1.13.5
192.168.0.16    Ready     worker             1d     v1.13.5
192.168.0.17    Ready     worker             1d     v1.13.5

总结

Rancher Kubernetes Engine(RKE)为用户屏蔽了创建 k8s 集群的复杂细节,简化了部署步骤,降低了构建门槛。对于那些有自建 k8s 集群需求的企业是一个不错的选择。

参考资料

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
13天前
|
Kubernetes Cloud Native Docker
云原生时代的容器化实践:Docker和Kubernetes入门
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术成为企业提升敏捷性和效率的关键。本篇文章将引导读者了解如何利用Docker进行容器化打包及部署,以及Kubernetes集群管理的基础操作,帮助初学者快速入门云原生的世界。通过实际案例分析,我们将深入探讨这些技术在现代IT架构中的应用与影响。
55 2
|
13天前
|
Kubernetes 监控 负载均衡
深入云原生:Kubernetes 集群部署与管理实践
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术以其弹性、可扩展性成为企业IT架构的首选。本文将引导你了解如何部署和管理一个Kubernetes集群,包括环境准备、安装步骤和日常维护技巧。我们将通过实际代码示例,探索云原生世界的秘密,并分享如何高效运用这一技术以适应快速变化的业务需求。
47 1
|
23天前
|
Kubernetes 负载均衡 Cloud Native
云原生应用:Kubernetes在容器编排中的实践与挑战
【10月更文挑战第27天】Kubernetes(简称K8s)是云原生应用的核心容器编排平台,提供自动化、扩展和管理容器化应用的能力。本文介绍Kubernetes的基本概念、安装配置、核心组件(如Pod和Deployment)、服务发现与负载均衡、网络配置及安全性挑战,帮助读者理解和实践Kubernetes在容器编排中的应用。
69 4
|
24天前
|
Kubernetes 监控 Cloud Native
云原生应用:Kubernetes在容器编排中的实践与挑战
【10月更文挑战第26天】随着云计算技术的发展,容器化成为现代应用部署的核心趋势。Kubernetes(K8s)作为容器编排领域的佼佼者,以其强大的可扩展性和自动化能力,为开发者提供了高效管理和部署容器化应用的平台。本文将详细介绍Kubernetes的基本概念、核心组件、实践过程及面临的挑战,帮助读者更好地理解和应用这一技术。
58 3
|
25天前
|
Kubernetes 关系型数据库 MySQL
Kubernetes入门:搭建高可用微服务架构
【10月更文挑战第25天】在快速发展的云计算时代,微服务架构因其灵活性和可扩展性备受青睐。本文通过一个案例分析,展示了如何使用Kubernetes将传统Java Web应用迁移到Kubernetes平台并改造成微服务架构。通过定义Kubernetes服务、创建MySQL的Deployment/RC、改造Web应用以及部署Web应用,最终实现了高可用的微服务架构。Kubernetes不仅提供了服务发现和负载均衡的能力,还通过各种资源管理工具,提升了系统的可扩展性和容错性。
71 3
|
1月前
|
Kubernetes 监控 开发者
专家级实践:利用Cloud Toolkit进行微服务治理与容器化部署
【10月更文挑战第19天】在当今的软件开发领域,微服务架构因其高可伸缩性、易于维护和快速迭代的特点而备受青睐。然而,随着微服务数量的增加,管理和服务治理变得越来越复杂。作为阿里巴巴云推出的一款免费且开源的开发者工具,Cloud Toolkit 提供了一系列实用的功能,帮助开发者在微服务治理和容器化部署方面更加高效。本文将从个人的角度出发,探讨如何利用 Cloud Toolkit 来应对这些挑战。
35 2
|
1月前
|
Kubernetes 持续交付 Docker
探索DevOps实践:利用Docker与Kubernetes实现微服务架构的自动化部署
【10月更文挑战第18天】探索DevOps实践:利用Docker与Kubernetes实现微服务架构的自动化部署
84 2
|
15天前
|
Kubernetes 负载均衡 调度
Kubernetes集群管理与编排实践
Kubernetes集群管理与编排实践
|
15天前
|
Kubernetes Cloud Native 前端开发
Kubernetes入门指南:从基础到实践
Kubernetes入门指南:从基础到实践
31 0
|
1月前
|
运维 Kubernetes Cloud Native
云原生时代的容器编排:Kubernetes入门与实践
【10月更文挑战第4天】在云计算的浪潮中,云原生技术以其敏捷、可扩展和高效的特点引领着软件开发的新趋势。作为云原生生态中的关键组件,Kubernetes(通常被称为K8s)已成为容器编排的事实标准。本文将深入浅出地介绍Kubernetes的基本概念,并通过实际案例引导读者理解如何利用Kubernetes进行高效的容器管理和服务部署。无论你是初学者还是有一定经验的开发者,本文都将为你打开云原生世界的大门,并助你一臂之力在云原生时代乘风破浪。
下一篇
无影云桌面