高可用集群篇-- K8S快速入门及集群部署

Posted 爱是与世界平行

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高可用集群篇-- K8S快速入门及集群部署相关的知识,希望对你有一定的参考价值。

一、K8s快速入门

1.1 简介

1.1.1 Kubernetes是什么

  • Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化; Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。
  • 容器因具有许多优势而变得流行起来。下面列出的是容器的一些好处:
    • 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率
    • 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性),支持可靠且频繁的 容器镜像构建和部署
    • 关注开发与运维的分离:在构建/发布时而不是在部署时创建应用程序容器镜像, 从而将应用程序与基础架构分离
    • 可观察性不仅可以显示操作系统级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号
    • 跨开发、测试和生产的环境一致性:在便携式计算机上与在云中相同地运行
    • 跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行
    • 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序
    • 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行
    • 资源隔离:可预测的应用程序性能
    • 资源利用:高效率和高密度

1.1.2 为什么要使用Kubernetes

容器是打包和运行应用程序的好方式。在生产环境中,你需要管理运行应用程序的容器,并确保不会停机。 例如,如果一个容器发生故障,则需要启动另一个容器。如果系统处理此行为,会不会更容易?

这就是 Kubernetes 来解决这些问题的方法! Kubernetes 为你提供了一个可弹性运行分布式系统的框架 Kubernetes 会满足你的扩展要求、故障转移、部署模式等。 例如,Kubernetes 可以轻松管理系统的 Canary 部署

Kubernetes 为你提供:

  • 服务发现和负载均衡

    Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  • 存储编排

    Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等

  • 自动部署和回滚

    你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态 更改为期望状态。例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。

  • 自动完成装箱计算

    Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源

  • 自我修复

    Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的 运行状况检查的容器,并且在准备好服务之前不将其通告给客户端

  • 密钥与配置管理

    Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥

1.1.3 Kubernetes不是什么

Kubernetes 不是传统的、包罗万象的 PaaS(平台即服务)系统。 由于 Kubernetes 在容器级别而不是在硬件级别运行,它提供了 PaaS 产品共有的一些普遍适用的功能, 例如部署、扩展、负载均衡、日志记录和监视

但是,Kubernetes 不是单体系统,默认解决方案都是可选和可插拔的。 Kubernetes 提供了构建开发人员平台的基础,但是在重要的地方保留了用户的选择和灵活性

Kubernetes:

  • 不限制支持的应用程序类型。 Kubernetes 旨在支持极其多种多样的工作负载,包括无状态、有状态和数据处理工作负载。 如果应用程序可以在容器中运行,那么它应该可以在 Kubernetes 上很好地运行。
  • 不部署源代码,也不构建你的应用程序。 持续集成(CI)、交付和部署(CI/CD)工作流取决于组织的文化和偏好以及技术要求。
  • 不提供应用程序级别的服务作为内置服务,例如中间件(例如,消息中间件)、 数据处理框架(例如,Spark)、数据库(例如,mysql)、缓存、集群存储系统 (例如,Ceph)。这样的组件可以在 Kubernetes 上运行,并且/或者可以由运行在 Kubernetes 上的应用程序通过可移植机制(例如, 开放服务代理)来访问。
  • 不要求日志记录、监视或警报解决方案。 它提供了一些集成作为概念证明,并提供了收集和导出指标的机制。
  • 不提供或不要求配置语言/系统(例如 jsonnet),它提供了声明性 API, 该声明性 API 可以由任意形式的声明性规范所构成。
  • 不提供也不采用任何全面的机器配置、维护、管理或自我修复系统。
  • 此外,Kubernetes 不仅仅是一个编排系统,实际上它消除了编排的需要。 编排的技术定义是执行已定义的工作流程:首先执行 A,然后执行 B,再执行 C。 相比之下,Kubernetes 包含一组独立的、可组合的控制过程, 这些过程连续地将当前状态驱动到所提供的所需状态。 如何从 A 到 C 的方式无关紧要,也不需要集中控制,这使得系统更易于使用 且功能更强大、系统更健壮、更为弹性和可扩展

1.1.4 Kubernetes工作示例

  • 自动部署

  • 自动恢复

  • 水平伸缩

1.2 架构原理&核心概念

1.2.1 整体主从方式

1.2.2 Master节点架构

  • 架构图

    • kube-apiserver
      
      • 对外暴露k8s的api接口,是外界进行资源操作的唯一入口
      • 提供认证、授权、访问控制、API注册和发现等机制
    • etcd
      
      • etcd是兼具一致性和高可用性的键值数据库,可以作为保存Kubernetes所有集群数据的后台数据库
      • Kubernetes集群的 etcd数据库通常需要有个备份计划
    • kube-scheduler
      
      • 主节点上的组件,该组件监视那些新创建的未指定运行节点的Pod,并选择节点让Pod在上面运行
      • 所有对k8s的集群操作,都必须经过主节点进行调度
    • kube-controller-manager
      
      • 在主节点上运行控制器的组件
      • 这些控制器包括:
        • 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
        • 副本控制器(Replication Controller):负责为系统中的每个副本控制器对象维护正确数量的Pod
        • 端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入Service 与 Pod)
        • 服务账户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认账户和API访问令牌

1.2.3 Node节点架构

  • 节点组件在每个节点上运行,维护运行的Pod并提供Kubernetes运行环境

  • 架构图

    • kubelet
      
      • 一个集群中每个节点上运行的代理;它保证容器都运行在Pod中
      • 负责维护容器的生命周期,同时也负责Volume(CSI)和网络(CNI)的管理
    • kube-proxy
      
      • 负责为Service提供cluster内部的服务发现和负载均衡
    • 容器运行环境(Container Runtime)

      • 容器运行环境是负责运行容器的软件
      • Kubernetes支持多个容器运行环境docker、containerd、cri-o、rktlet以及任何实现Kubernetes CRI(容器运行环境接口)
    • fluentd
      
      • 是一个守护进程,它有助于提供集群层面日志

1.3 完整概念

  • 整体架构图

    • Container:容器,可以是docker启动的一个容器

    • Pod

      • k8s使用Pod来组织一组容器
      • 一个Pod中的所有容器共享同一网络
      • Pod是k8s中的最小部署单元
    • Volume

      • 声明在Pod容器中可访问的文件目录
      • 可以被挂载在Pod中一个或多个容器指定路径下
      • 支持多种后端存储抽象(本地存储、分布式存储、云存储…)
    • Controllers:更高层次对象,部署和管理Pod

      • ReplicaSet:确保预期的Pod副本数量
      • Deplotment:无状态应用部署
      • StatefulSet:有状态应用部署
      • DaemonSet:确保所有Node都运行在一个指定Pod
      • Job:一次性任务
      • Cronjob:定时任务
    • Deployment

      • 定义一组Pod的副本数目、版本等

      • 通过控制器(Controller)维持Pod数目(自动回复失败的Pod)

      • 通过控制器以指定的策略控制版本(滚动升级、回滚等)

    • Service

      • 定义一组Pod的访问策略

      • Pod的负载均衡,提供一个或者多个Pod的稳定访问地址

      • 支持多种方式(ClusterIP、NodePort、LoadBalance

    • Label:标签,用于对象资源的查询、筛选

    • Namespace:命名空间,逻辑隔离

      • 一个集群内部的逻辑隔离机制(鉴权、资源)
      • 每个资源都属于一个namespace
      • 同一个namespace所有资源名不能重复
      • 不同namespace可以资源名重复
  • API

    我们通过kubernetes的API来操作整个集群

    可以通过 kubectluicurl最终发送 http+json/yaml方式的请求给API server,然后控制k8s集群;k8s里的所有资源对象都可以采用 yamlJSON格式的文件定义或者描述

1.4 流程叙述

  • 1、通过Kubectl提交一个创建RC(Replication Controller)的请求,该请求通过APIServer被写入etcd
  • 2、此时 Controller Manager 通过 API Server的监听资源变化的接口监听到此RC事件
  • 3、分析之后,发现当前集群中还没有它所对应的Pod实例
  • 4、于是根据RC里的Pod模板定义生成一个Pod对象,通过APIServer写入etcd
  • 5、此事件被Scheduler发现,它立即执行一个复杂的调度流程,为这个新Pod选定一个落户的Node,然后通过API Server将这一结果写入到etcd
  • 6、目标Node上运行的Kubelet进程通过API Server监测到这个新生的Pod,并按照它的定义,启动该Pod并任劳任怨的负责它的下半生,直到Pod生命结束
  • 7、随后我们通过Kubectl提交一个新的映射到该Pod的Service的创建请求
  • 8、ControllerManager 通过Label标签查询到关联的Pod实例,然后生成Service的Endpoints信息,并通过APIServer写入到etcd
  • 9、接下来所有Node上运行的Proxy进程通过API Server查询并监听 Service对象与其对应的Endpoints信息,建立一个软件方式的负载均衡器来实现Service访问到后端Pod的流量转发功能

k8s里的所有资源对象都可以采用 yaml 或 JSON 格式的文件定义或描述

二、k8s集群安装

2.1 Kubeadm

  • kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具;这个工具能通过两条指令完成一个kubernetes集群的部署

    kubeadm安装文档

    • 1、创建一个Master节点

      $ kubeadm init
      
    • 2、将一个Node节点加入到当前集群中

      $ kubeadm join <Master节点的IP和端口>
      

2.1.1 前置要求

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
  • 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
  • 集群中所有机器之间网络互通
  • 可以访问外网,需要拉取镜像
  • 禁止swap分区

2.1.2部署步骤

  • 1、在所有节点上安装 Docker 和 kubeadm

  • 2、部署Kubernetes Master

  • 3、部署容器网络插件

  • 4、部署 kubernetes Node,将节点加入 Kuberbetes集群中

  • 5、部署 Dashboard Web 页面,可视化查看Kubernetes资源

2.1.3 环境准备

2.1.3.1 准备工作

  • VMware 克隆两个虚拟机,准备三个虚拟机

    # vi /etc/sysconfig/network-scripts/ifcfg-ens33
    
    192.168.83.133
    192.168.83.134
    192.168.83.135
    

2.1.3.2 设置linux网络环境(三个节点都执行)

  • 关闭防火墙

    systemctl stop firewalld
    systemctl disable firewalld
    
  • 关闭 selinux

    #设置安全策略暂不开启
    sed -i 's/enforcing/diabled/' /etc/selinux/config
    setenforce 0
    
  • 关闭swap(内存交换)

    #临时
    swapoff -a  
    
    #永久
    sed -ri 's/.*swap.*/#&/' /etc/fstab
    验证是否生效: free -g ,swap必须为0
    
  • 添加主机名与ip对应关系

    #设置对应的hostname
    hostnamectl set-hostname k8s-node1
    
    
    vim /etc/hosts
    
    192.168.83.133  k8s-node1
    192.168.83.134  k8s-node2
    192.168.83.135  k8s-node3
    

    确保在每个虚拟机中,ping各自的节点名称都能ping通

  • 将桥接的ipv4流量传递到iptables的链

    cat > /etc/sysctl.d/k8s.conf << EOF   
    net.bridge.bridge-nf-call-ip6tables=1
    net.bridge.bridge-nf-call-iptables=1
    EOF
    
    sysctl --system
    

2.1.3.3 所有节点安装

  • docker、kubeadm、kubelet、kubectl

    Kubernetes 默认 CRI(容器运行时)为Docker ,因此先按照Docker

  • 添加阿里云yum源

    cat > /etc/yum.repos.d/kubernetes.repo << EOF
    [kubernetes]
    name=Kubernetes
    baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
    enabled=1
    gpgcheck=0
    repo_gpgcheck=0
    gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    EOF
    
  • 指定版本安装

    yum list|grep kube
    #基于1.1.7版本的kubernetes
    yum install -y kubelet-1.17.3 kubeadm-1.17.3 kubectl-1.17.3
    
    #安装完成执行
    systemctl enable kubelet
    systemctl start kubelet
    

2.1.4 部署 k8s-master

2.1.4.1 master节点初始化

  • 将k8s资源文件拷贝进k8s-node1

  • 初始化master节点

    kubeadm init \\
    --apiserver-advertise-address=192.168.83.133 \\
    --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \\
    --kubernetes-version v1.17.3 \\
    --service-cidr=10.96.0.0/16 \\
    --pod-network-cidr=10.244.0.0/16
    

执行结果

继续按照控制台提示执行提示命令

#启动完成,这句话拷贝出来备用(*),两小时内有效
kubeadm join 192.168.83.133:6443 --token f9s477.9qh5bg4gd7xy9f67 \\
  --discovery-token-ca-cert-hash sha256:8d6007a15b9dfa0940d2ca8fbf2929a108c391541ae59f9c75d66352bdd0aba6

2.1.5 安装Pod网络插件

  • 利用k8s文件夹中的 kube-flannel.yml

    kubectl apply -f kube-flannel.yml
    

    kubectl get pods --all-namespaces
    

2.1.6 加入k8s集群

  • 查看master状态

    kubectl get nodes
    

  • node2和node3节点加入集群

    #master启动时,日志打印出的内容
    kubeadm join 192.168.83.133:6443 --token f9s477.9qh5bg4gd7xy9f67 \\
        --discovery-token-ca-cert-hash sha256:8d6007a15b9dfa0940d2ca8fbf2929a108c391541ae59f9c75d66352bdd0aba6
    

  • 如果存在NotReady状态,网络问题,可以执行以下命令,监控pod进度

    kubectl get pod -n kube-system -o wide
    

    等待3-10分钟,完全都是running以后,再次查看

三、入门操作Kubernetes集群

3.1 基本操作体验

3.1.1 部署一个tomcat

#主节点 运行创建一个deployment部署
kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 

#获取到tomcat信息
kubectl get pods -o wide
  • 查看节点 和 pod 信息

3.1.1.1 模拟tomcat容器宕机(手动stop 容器)

  • 观察是否会重新拉起tomcat容器

3.1.1.2 模拟node3 节点宕机(关闭虚拟机)

  • 检测过程可能会比较慢,大约5分钟左右,耐心等待

简单的容灾恢复测试

3.2 暴露访问

  • Pod的80映射容器的8080;service会代理Pod的80

    kubectl expose deployment tomcat6 --port=80 --target-port=8080 --type=NodePort
    
  • 获取service

    kubectl get svc
    

3.3 动态扩容测试

  • 获取部署信息

    kubectl get deployment
    

  • 扩容

    kubectl scale --replicas=3 deployment tomcat6
    

扩容了多份,所以无论访问那个node的指定端口,都可以访问到tomcat6

  • 缩容(改变副本数量)

    kubectl scale --replicas=1 deployment tomcat6
    

3.4 删除

  • 获取到所有的资源

    kubectl get all
    

  • 删除部署

    kubectl delete deployment.apps/tomcat6
    
  • 删除service

    kubectl delete service/tomcat6
    

四、k8s细节

4.1 kubectl

4.1.1 kubectl文档

4.1.2 资源类型

4.1.3 格式化输出

  • 所有 kubectl 命令的默认输出格式都是人类可读的纯文本格式。要以特定格式向终端窗口输出详细信息,可以将 -o--output 参数添加到受支持的 kubectl 命令中

    格式化输出

4.1.4 常用操作

  • 常用操作文档地址
    • kubectl apply - 以文件或标准输入为准应用或更新资源
    • kubectl get - 列出一个或多个资源
    • kubectl describe - 显示一个或多个资源的详细状态,默认情况下包括未初始化的资源
    • kubectl delete - 从文件、stdin 或指定标签选择器、名称、资源选择器或资源中删除资源
    • kubectl exec - 对 pod 中的容器执行命令
    • kubectl logs - 打印 Pod 中容器的日志

4.1.5 命令参考

五、yaml语法

5.1 yml模板

  • 图解

  • 查看上面的tomcat6创建命令对应的yaml内容

    kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml
    

  • 生成yaml文件

    kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml > tomcat6.yaml
    

修改文件中的,副本1 改为3 vim tomact6.yaml

运行yaml文件

  kubectl apply -f tomcat6.yaml

  • 端口暴露也可以使用yaml文件代替冗长命令

    kubectl expose deployment tomcat6 --port=80 --target-port=8080 --type=NodePort --dry-run -o yaml
    

六、入门操作

6.1 Pod

  • Pod 是 Kubernetes 应用程序的基本执行单元,即它是 Kubernetes 对象模型中创建或部署的最小和最简单的单元。Pod 表示在 集群 上运行的进程。

    Pod 封装了应用程序容器(或者在某些情况下封装多个容器)、存储资源、唯一网络 IP 以及控制容器应该如何运行的选项。 Pod 表示部署单元:Kubernetes 中应用程序的单个实例,它可能由单个 容器 或少量紧密耦合并共享资源的容器组成。

    Docker 是 Kubernetes Pod 中最常用的容器运行时,但 Pod 也能支持其他的容器运行时

    Kubernetes 集群中的 Pod 可被用于以下两个主要用途:

    • 运行单个容器的 Pod。”每个 Pod 一个容器”模型是最常见的 Kubernetes 用例;在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
    • 运行多个协同工作的容器的 Pod。 Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。 这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众,而另一个单独的“挂斗”(sidecar)容器则刷新或更新这些文件。 Pod 将这些容器和存储资源打包为一个可管理的实体。 Kubernetes 博客 上有一些其他的 Pod 用例信息。更多信息请参考:
    • 分布式系统工具包:容器组合的模式
    • 容器设计模式

    每个 Pod 表示运行给定应用程序的单个实例。如果希望横向扩展应用程序(例如,运行多个实例),则应该使用多个 Pod,每个应用实例使用一个 Pod 。在 Kubernetes 中,这通常被称为 副本。通常使用一个称为控制器的抽象来创建和管理一组副本 Pod

6.2 控制器

6.3 Deployment&Service

  • 二者关系

  • 简单来说

    • Deployment 是master节点保存的一个部署信息
    • Service暴露Pod,对Pod的一种负载均衡
  • Service的意义:统一应用访问入口;管理一组Pod,防止Pod失联(服务发现);定义一组Pod的访问策略

    现在Service我们使用NodePort的方式暴露,这样访问每个节点的端口,都可以访问到这个Pod,如果节点宕机,就会出现问题

6.4 labels和selectors

  • 标签与选择器(类比javascript中控件的id、class与选择器的关系)

  • 关系图解

6.5 Ingress

  • 基于nginx

  • 利用yaml方式启动之前的tomcat6容器,并暴露访问端口

    tomcat6-deployment.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: tomcat6
      name: tomcat6
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: tomcat6
      template:
        metadata:
          labels:
            app: tomcat6
        spec:
          containers:
          - image: tomcat:6.0.53-jre8
            name: tomcat
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: tomcat6
      name: tomcat6
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: tomcat6
      type: NodePort
    
  • 运行yaml文件

      kubectl apply -f tomcat6-deployment.yaml
    

    • 任意三个节点地址的30658端口,都可以访问到tomcat
  • 通过Service发现Pod进行关联,基于域名访问;通过Ingress Controller实现Pod负载均衡‘;支持TCP/UDP 4层负载均衡和HTTP 7层负载均衡

    • 步骤1:运行文件(在k8s文件夹中,该文件已准备好),创建Ingress Controller

      kubectl apply -f  ingress-controller.yaml
      

    • 步骤2:创建 Ingress 规则

      #创建ingress-tomcat6.yaml文件
      apiVersion: extensions/v1beta1
      kind: Ingress 
      metadata: 
        name: web 
      spec:
        rules:
        - host: tomcat6.touch.air.mall.com
          http:
            paths:
              - backend:
                 serviceName: tomcat6
                 servicePort: 80
      
      
      #应用ingress规则
      kubectl apply -f ingress-tomcat6.yaml
      #查看信息
      kubectl get all
      

    • 配置本地域名解析 C:\\Windows\\System32\\drivers\\etc\\hosts

以上是关于高可用集群篇-- K8S快速入门及集群部署的主要内容,如果未能解决你的问题,请参考以下文章

Flink系列部署篇:Native k8s部署高可用Flink集群实战

k8s 入门系列之集群安装篇

k8s入门系列之集群安装篇

kubespray -- 快速部署高可用k8s集群

使用kube-vip部署高可用K8S集群

快速搭建kubernetes高可用集群(3master+3worker+负载均衡)