Kubernetes容器部署与应用实战(项目式微课版)_第1页
Kubernetes容器部署与应用实战(项目式微课版)_第2页
Kubernetes容器部署与应用实战(项目式微课版)_第3页
Kubernetes容器部署与应用实战(项目式微课版)_第4页
Kubernetes容器部署与应用实战(项目式微课版)_第5页
已阅读5页,还剩633页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

项目1部署Kubernetes集群《Kubernetes容器编排与管理教程》1-1

目录/Contents1-2安装运维containerd容器引擎部署基于containerd容器引擎的k8s集群1-3部署多Master节点的k8s高可用集群项目1部署Kubernetes集群王亮刚刚入职一家电子商务公司的信息中心,为了简化应用程序的打包、交付和部署过程,提高开发人员和运维人员的工作效率,公司决定使用Kubernetes容器编排技术部署各类业务系统,项目经理要求王亮安装运维containerd容器引擎,基于containerd容器引擎部署单Master节点的Kubernetes集群和多Master节点的Kubernetes高可用集群。项目1部署Kubernetes集群任务1-1安装运维containerd容器引擎任务描述必备知识使用VMware创建CentOS8模板机安装containerd容器引擎使用nerdctl工具运维镜像和容器1.1.11.1.21.1.31.1.41.1.5学习目标【知识目标】(1)了解containerd容器引擎的特点。(2)掌握containerd容器引擎和Kubernetes的关系。【技能目标】(1)能够使用VMware安装CentOS8模板机。(2)能够安装containerd容器引擎。(3)能够运维containerd容器引擎。1.1.1任务描述从Kubernetes1.24版本开始,containerd成为Kubernetes的默认容器引擎,所以在部署Kubernetes集群时,首先要掌握containerd的安装和运维,公司项目经理要求王亮制作CentOS8模板机,使用模板机构建一台服务器,在服务器上安装运维containerd容器引擎。1.1.2必备知识1.containerd容器引擎的特点containerd是一个轻量级的容器运行时引擎,具备如下特点。(1)与容器编排平台集成containerd作为容器编排系统(如Kubernetes)的基础组件,用于管理容器的生命周期。它提供了符合OCI(OpenContainerInitiative,开放容器倡议)标准的接口,可以集成到不同的容器编排平台中。(2)轻量级和高性能由于containerd的设计目标是轻量级和高性能,它相比于一些功能更为复杂的容器引擎,如Docker,具有更小的资源消耗和更高的运行效率。(3)模块化架构(此处表述改成以下文字)containerd的架构设计模块化,它由多个组件组成,包括容器运行时、镜像服务、快照管理、网络管理等。(4)简化的功能集containerd提供了一组基本的功能,如容器的创建、启动、停止、删除等,而且它的设计更加注重稳定性和可靠性。相比于Docker这样功能更为丰富的容器引擎,containerd更专注于容器生命周期的管理。(5)开源和社区支持containerd是一个开源项目,拥有一个活跃的社区,用户可以自由地获取源代码、提交问题和贡献代码,containerd在容器技术领域具有较好的可持续性和发展潜力。1.1.2必备知识2.containerd容器引擎和Kubernetes的关系containerd是一个用于管理容器生命周期的轻量级容器运行时引擎。而Kubernetes是一个用于自动化容器化应用程序部署、扩展和管理的开源容器编排平台,它们的关系如下。(1)容器运行时引擎containerd提供了用于创建、运行和管理容器的基本功能,它负责启动容器、监控容器的运行状态,以及在需要时执行停止、删除容器等相关操作。在Kubernetes中,containerd可以作为容器运行时的一种选择,负责管理Pod中的容器。(2)Kubernetes的容器运行时Kubernetes支持多种容器运行时,包括Docker、containerd、CRI-O等。通过Kubernetes的容器运行时接口,Kubernetes可以与不同的容器运行时进行通信和交互。因此,Kubernetes可以利用containerd提供的容器管理功能,来实现对容器的生命周期管理。(3)容器编排与管理Kubernetes提供了丰富的功能,包括自动扩展、负载均衡、服务发现、故障恢复等,用于管理容器化应用程序的整个生命周期。它利用容器运行时(如containerd)来管理容器,并通过自己的控制平面来实现对容器集群的编排和管理。因此,containerd和Kubernetes是紧密相关的,它们在容器生态系统中扮演的角色是不同的。Kubernetes负责对容器集群进行编排和管理,containerd作为Kubernetes的一个容器运行引擎,用于支持Kubernetes对容器生命周期的管理。1.1.3使用VMware创建CentOS8模板机1.安装CentOS8操作系统(1)创建虚拟机(2)编辑虚拟机设置(3)安装操作系统具体过程见微课。1.1.3使用VMware创建CentOS8模板机2.登录配置模板机(1)本地登录(2)远程登录(3)配置基础YUM源(4)其他配置具体过程见微课。1.1.4安装containerd容器引擎1.使用模板机创建服务器在本地磁盘的某个盘符下创建目录项目1,在项目1下建立目录任务1,在VMware中,选择“文件”菜单下的“打开”选项,选择保存好的CentOS8.ova文件,在弹出的“导入虚拟机”对话框中输入主机名称containerd,保存到“项目1\任务1”目录,如图1-20所示。

图1-20使用模板机创建服务器1.1.4安装containerd容器引擎2.安装containerd容器引擎(1)安装依赖包(2)添加containerd仓库(3)使用YUM安装containerd(4)启动containerd容器引擎具体过程见微课。

1.1.5使用nerdctl工具运维镜像和容器1.安装配置nerdctl(1)安装nerdctl(2)配置nerdctl具体过程见微课。

1.1.5使用nerdctl工具运维镜像和容器2.运维镜像和容器(1)拉取镜像

(6)删除镜像和容器(2)运行容器

(7)保存和导入镜像(3)进入容器

具体过程见微课。(4)测试容器应用(5)构建镜像

任务1-2部署基于Containerd容器引擎的k8s集群任务描述必备知识部署k8s集群基础环境部署K8s集群组件1.2.11.2.21.2.31.2.4学习目标【知识目标】(1)了解Kubernetes不使用Docker作为默认容器引擎的原因。(2)掌握Kubernetes的架构以及各个组件的功能。【技能目标】(1)能够部署单Master节点的k8s集群。(2)能够测试k8s集群的可用性。【素养目标】(1)通过学习Kubernetes与Docker容器引擎的关系,培养动态看待事物发展的习惯。(2)通过部署Kubernetes集群,培养认真仔细和解决问题的能力。1.2.1任务描述在单台服务器上,可以通过容器技术提升应用部署的效率,但无法实现服务器集群环境下容器编排和自动化部署,实现服务的弹性伸缩高可用。公司技术负责人要求王亮构建一台Master控制节点服务器,二台Node工作节点服务器,部署基础containerd容器引擎的Kubernetes集群。1.2.2必备知识1.Kubernetes不使用Docker作为默认运行时的原因containerd是一个轻量级的容器运行时引擎,具备如下特点。(1)灵活性和可扩展性Kubernetes是一个容器编排平台,其设计目标是能够与多种容器运行时进行交互,而不是与特定的容器运行时紧密耦合。Kubernetes通过CRI(ContainerRuntimeInterface,容器运行接口)与容器运行时进行通信。这样可以实现更高的灵活性和可扩展性,使得Kubernetes可以支持多种容器运行时,如Docker、containerd、CRI-O等。(2)标准化和生态系统支持Kubernetes的目标是成为一个通用的容器编排平台,而不是与特定的容器技术绑定。因此,通过与CRI进行交互,Kubernetes可以更好地支持和整合不同的容器技术,从而促进标准化和生态系统的发展。(3)容器运行时的多样性和演进容器技术在不断演进和发展,出现了许多不同的容器运行时,Kubernetes通过与CRI进行交互,可以更灵活地适应不同的容器运行时,并且能够在容器技术发展的过程中保持对未来变化的适应性。尽管Kubernetes不直接使用Docker作为默认容器运行时,但它仍然能够与Docker容器兼容,并且可以通过其他容器运行时来运行容器,这种设计决策使得Kubernetes在容器技术领域的应用更加灵活和持久。1.2.2必备知识2.Kubernetes架构和各个组件功能Kubernetes采用主从分布式架构,由Master控制节点(也称管理节点)和Node工作节点组成,由控制节点发出命令,然后Node工作节点完成任务。Kubernetes集群的架构如图1-27所示。

图1-27Kubernetes架构1.2.2必备知识(1)Master要对集群资源进行调度管理,Master需要安装APIServer(应用程序编程接口服务器)、ControllerManager(控制器管理服务)、Scheduler(调度服务器)、Etcd(集群状态存储)、Kubectl等组件。①APIServerAPIServer(应用程序接口服务)主要用来处理REST请求操作,确保它们生效,执行相关业务逻辑,更新Etcd存储中的相关对象。APIServer是所有REST命令的入口,它的相关结果状态将被保存在Etcd存储中;APIServer同时是集群的网关,客户端通过APIServer访问集群。(删除后边这句)客户端需要通过认证,并使用APIServer作为访问NodePod以及Service的通道。②ControllerManagerControllerManager用于管理和控制Kubernetes集群,执行多种生命周期管理功能,如命名空间的创建和生命周期管理、事件垃圾收集、已终止Pod的垃圾收集、级联删除垃圾收集以及Node的垃圾收集。同时,它还负责执行API业务逻辑,例如Pod的弹性扩容,提供自愈能力、扩展、应用生命周期管理、服务发现、路由和服务绑定等功能。Kubernetes默认提供多种控制器管理服务,包括ReplicationController(副本控制器)、NamespaceController(命名空间控制器)、ServiceController(服务发现控制器)等。③SchedulerScheduler组件为容器自动选择主机,依据请求资源的可用性、服务请求的质量等约束条件,Scheduler监控未绑定的Pod,并将其绑定至特定的Node。1.2.2必备知识④EtcdKubernetes默认使用Etcd作为集群整体存储,Etcd是一个简单的分布式键值对存储数据库,用来共享配置和服务发现。集群的所有状态都存储在Etcd中,Etcd具有监控的能力,因此当信息发生变化时,Etcd就能够快速地通知集群中相关组件。⑤KubectlKubectl可以安装在Master上,也可以安装在Node上,它用于通过命令行与APIServer交互,进而对Kubernetes进行操作,实现在集群中对各种资源的增删改查等操作。1.2.2必备知识(2)工作节点(Node)Node是真正的工作节点,运行容器应用,Node工作节点上需要运行Kubelet、容器引擎、Kube-Proxy(kube代理)等组件。①KubeletKubelet是Kubernetes中最主要控制器,负责驱动容器执行层和整个容器生命周期。在Kubernetes中,Pod是基本的执行单元,它可以包括多个容器和存储数据卷,将一个或者多个容器打包成单一的Pod应用,由Master负责调度。在Node节点上由Kubelet启动Pod内的容器或者数据卷,Kubelet负责管理Pod、容器、镜像、数据卷等,实现集群对工作节点的管理,并将容器运行状态汇报给APIServer。②容器引擎每一个Node工作节点都会运行容器引擎,负责下载镜像、运行容器。Kubernetes本身并不提供容器引擎环境,但提供了接口,可以插入所选择的容器引擎环境,本书采用containerd作为Kubernetes的容器引擎。③Kube-Proxy在Kubernetes中,Kube-Proxy负责为Pod创建代理服务,Kube-Proxy通过Iptables或者IPVS规则将客户端访问请求路由到后端的Pod。1.2.3部署k8s集群基础环境1.创建3台服务器首先在本地磁盘创建三个目录master、node1、node2,然后使用CentOS8.ova模板机创建名称为master、node1、node2的服务器,保存到对应的磁盘目录中。方法是鼠标“右键”单击模板机文件,选择“使用VMwareWorkstation打开”,在“导入虚拟机”对话框中,填写虚拟机的名称和存储路径,单击“导入”按钮即可,如图1-28所示。本教材将使用模板机创建的虚拟机叫作服务器。

图1-28创建服务器1.2.3部署k8s集群基础环境1.创建3台服务器三台服务器的硬件配置如表下所示。三台服务器的网卡及IP地址配置如下所示,配置过程不再赘述,具体请参照微课视频。

服务器名称CPU核数

内存(G)硬盘(G)master2核心4100node12核心4100node22核心4100服务器名称网卡名称

连接到网络网络模式IP地址网关DNSmasterens160VMnet8NAT网络0node1ens160VMnet8NAT网络0node2ens160VMnet8NAT网络01.2.3部署k8s集群基础环境2.配置基础环境(三台服务器)(1)使用SecurtCrt工具登录到master和node1、node2节点,首先修改三台主机的名称。(2)配置名称解析(3)关闭防火墙、selinux、交换分区(4)修改内核参数具体过程见微课。1.2.4部署K8s集群组件1.配置安装源(三台服务器)(1)安装依赖(2)添加containerd仓库(3)配置阿里云的Kubernetes源具体过程见微课。1.2.4部署K8s集群组件2.安装Containerd容器引擎(三台服务器)(1)安装启动Containerd

(2)修改Containerd配置(3)安装配置nerdctl具体过程见微课。1.2.4部署K8s集群组件3.安装Kubeadm、Kubelet、Kubectl(三台服务器)在三台服务器上安装kubeadm用来初始化集群,kubelet用于在集群每个节点上启动Pod和容器,ubelet用于与集群通信的命令行工具,这里以Master节点为例,如下所示。[root@master~]#yuminstallkubelet-1.29.0kubeadm-1.29.0kubectl-1.29.0–y安装完成后,启动kubelet并设置为开机自启动,如下所示。[root@master~]#systemctlstartkubelet&&systemctlenablekubelet1.2.4部署K8s集群组件4.集群初始化(Master控制节点)(1)控制节点初始化集群

(6)查看容器运行时(2)创建相关目录和文件(Master控制节点)(3)工作节点加入集群

(7)查看集群组件及工作状态(4)控制节点加入集群

(8)配置kubectl命令自动补(5)安装网络组件

具体过程见微课。任务1-3部署多Master节点的k8s高可用集群任务描述必备知识扩展单Master节点为多Master节点配置负载均衡1.3.11.3.21.3.31.3.4学习目标【知识目标】(1)部署Kubernetes高可用集群的原因。(2)Kubernetes高可用集群的实现机制。【技能目标】(1)能够部署多Master节点的K8s集群。(2)能够配置Haproxy负载均衡策略。【素养目标】(1)通过学习高可用集群的实现策略,培养从整体和全局角度观察事物的能力。(2)通过部署多Master的Kubernetes集群,培养运维过程中保证系统高可用运行的意识。1.3.1任务描述单Master控制节点的Kubernetes集群可以编排和管理容器,但如果Master节点出现故障,集群就无法正常运行了,为了保证集群的高可用性,实现负载均衡,公司技术负责人要求王亮构建两台Master控制服务器,二台Node工作服务器的Kubernetes集群,同时部署Haproxy服务实现负载均衡访问集群。1.3.2必备知识1.部署Kubernetes高可用集群的原因部署Kubernetes高可用集群的原因如下。(1)容错性高可用集群可以确保即使某个节点或组件发生故障,集群仍然可以继续正常运行。方法是在多个节点上部署APIServer、ControllerManager和Scheduler。(2)负载均衡Kubernetes高可用集群在多个节点上部署相同组件,然后通过负载均衡来分发流量,从而提高性能并减少单点故障的风险。(3)扩展性高可用集群可以更轻松地进行扩展,满足业务不断增长的需求。通过添加更多的节点或扩展现有节点的资源,增加集群的容量和性能。(4)可靠性和稳定性通过使用冗余的节点和组件,高可用集群可以提供更高的可靠性和稳定性,即使在节点故障或维护期间,集群也可以保持可用性。(5)自动恢复功能高可用集群通常配备了自动恢复功能,可以在检测到故障时自动执行故障转移和恢复操作,从而减少对管理员干预的需求。1.3.2必备知识2.Kubernetes高可用集群的实现机制多Master节点的高可用Kubernetes集群架构如下所示。如上图所示,在Kubernetes高可用集群中,运行了三个Master节点,每个Master节点都会运行API服务器、控制器管理器和调度器(图中使用中文即可)、etcd等控制平⾯组件。当某个Master节点出现故障,其他的Master节点仍然可以继续提供服务,整个集群的管理和控制工作不会受到影响。具体的实现方式请看下页1.3.2必备知识(1)负载均衡器负载均衡服务将请求调度到多个Master节点上的APIServer。确保所有发往APIServer的请求都能被成功的路由到⼀个可用的Master节点。(2)Etcd集群Kubernetes使用Etcd作为集群的数据存储。当实现Kubernetes的高可用时,Etcd部署在每个Master节点,形成数据库集群并且进行数据实时同步,若某个节点崩溃,数据可以从其他节点进行恢复。(3)领导者选举ControllerManager和Scheduler在多个节点上运行,但不采⽤负载均衡模式。这些组件是通过领导者选举机制,只有一个领导者处于活动状态,避免出现调度不一致问题。若当前领导者崩溃,另⼀个副本会被选举为新的领导者,以此保持高可用性。1.3.3扩展单Master节点为多Master节点将任务二中实现的单Master节点集群扩展为多Master节点,需要在集群中添加一个Master节点,实现双Master节点,当用户使用命令行或者图形化界面访问负载均衡服务IP地址加6443端口时,跳转到Master节点或者master1节点的APIServer接口,然后再根据高可用集群的工作机制部署应用到工作节点,如下所示。

1.3.3扩展单Master节点为多Master节点1.创建2台服务器在任务二单Master集群的基础上,再创建两台服务器,其中一台作为Master节点加入集群,另一台安装Haproxy负载均衡服务。

服务器名称CPU核数

内存硬盘master12核心4G100Ghaproxy2核心4G100G服务器名称网卡名称

连接到网络网络模式IP地址网关DNSmaster1ens160VMnet8NAT网络1node1ens160VMnet8NAT网络1.3.3扩展单Master节点为多Master节点2.master1节点加入集群(1)配置加入的服务器名称(2)配置master1节点加入集群成为控制节点(3)加入到集群具体过程见微课。

1.3.4配置负载均衡2.master1节点加入集群(1)安装haproxy服务(2)配置Haproxy(4)验证集群高可用性具体过程见微课。

项目小结

从Kubernetes1.24版本开始,为了提升Kubernetes平台的运行效率,不再使用Docker作为默认的容器运行时,而是采用了轻量级的效率更高的containerd作为默认容器运行时,所以在任务一中介绍了containerd容器引擎的安装与运维,熟悉Docker的读者可以很快适应containerd的使用,在任务二中基于containerd容器运行时部署了单Master节点的Kubernetes集群,由于在生产环境中,单Master集群容器出现单点故障问题,所以在任务三种,部署了多Master节点的Kubernetes集群,配置了负载均衡服务。

项目2使用集群核心资源部署服务《Kubernetes容器编排与管理教程》2-1

目录/Contents2-2使用Kubectl命令部署服务基于Yaml脚本部署服务2-3部署任务和守护型应用项目2使用集群核心资源部署服务公司决定在Kubernetes集群上部署Nginx服务,发布公司对外宣传网站,为了实时掌握集群工作状态,需要部署应用监控各个节点的硬件信息。项目经理要求王亮使用Kubectl命令行和Yaml脚本两种方式创建管理Pod、Deployment、Service资源,部署发布Nginx服务。基于Job、Cronjob、Daemonset控制器资源部署任务和守护型应用。项目2使用集群核心资源部署服务任务2-1使用Kubectl命令部署服务任务描述必备知识使用Pod部署Nginx服务使用Deployment控制器部署Nginx服务使用Service服务发现访问后端Pod2.1.12.1.22.1.32.1.42.1.5学习目标【知识目标】(1)掌握Kubectl常用命令的用法。(2)掌握Pod、Deployment、Service等核心资源的作用。【技能目标】(1)能够使用Kubectl命令创建Pod。(2)能够使用Kubectl创建Deployment控制器。(3)能够使用Service服务发现访问Pod服务。(4)会使用探针检测Pod健康性。【素养目标】(1)通过学习Kubenetes集群资源,养成将复杂系统拆解成多个组件的能力。(2)通过创建Pod、Deployment和Service资源,学会通过事物之间逻辑关系理解事物。2.1.1任务描述用户可以通过命令行、图形化界面、脚本等方式操作Kubernetes集群,部署各种服务和业务。公司项目经理要求王亮使用Kubectl命令行工具创建和运维Pod、Deployment、Service等集群资源,部署和发布Nginx网站服务。2.1.2必备知识1.Kubernetes核心资源在Kubernetes中,核心资源是集群的基础设施和运行应用程序的基本构件。这些核心资源定义了应用程序的部署、网络、存储和配置等方面,使得应用程序能够在Kubernetes集群中可靠地运行和扩展。以下是一些常用的Kubernetes资源类型。(1)PodPod是Kubernetes中最小的部署单元,在一个Pod中,通常会有一个应用程序容器,以及辅助日志收集器、监控代理等辅助容器,这些容器共享Pod网络和存储资源,共同协作来完成特定任务,以下是一些关于Pod的重要特性。①共享网络命名空间Pod内的所有容器共享相同的网络命名空间,它们可以通过localhost直接进行通信,无须额外的网络配置。②共享存储卷Pod可以挂载一个或多个存储卷,这些存储卷可以被Pod中的所有容器访问,容器之间可以共享数据,数据可以在容器重启时实现持久化。③生命周期管理Pod有自己的生命周期,它可以被创建、启动、停止和删除。当Pod被删除时,其中的所有容器也会被一并删除。④弹性扩展通过创建多个Pod实例并将它们放置在不同节点上,可以实现应用程序的水平扩展和负载均衡。2.1.2必备知识⑤资源调度Kubernetes调度器负责将Pod调度到集群中的不同节点上,根据资源需求、节点负载等因素进行智能调度。⑥监控和日志Kubernetes提供了丰富的监控和日志功能,可以对Pod进行实时监控和日志收集,帮助诊断和调试应用程序问题。(2)Deployment控制器Deployment是Kubernetes中的一种资源对象,用于管理Pod的部署和更新。它提供了一种声明性方式来定义应用程序的期望状态。,Deployment使用ReplicaSet来管理Pod的副本,支持滚动更新和回滚操作,Deployment控制器的特点如下。①声明性配置Deployment可以使用声明性的Yaml文件来定义应用程序的部署配置,包括Pod模板、副本数量等信息。这种方式更加清晰、可维护,并且支持版本控制。②自动化部署Deployment可以自动创建和管理Pod副本,确保它们按照定义的配置进行部署,用户只需定义期望的状态,Kubernetes会按照期望的状态自动处理。2.1.2必备知识③滚动更新Deployment支持滚动更新,可以在不中断服务的情况下逐步将新版本的Pod部署到集群中,用户可以定义更新策略,如并行更新的最大副本数、延迟等。④回滚操作如果新版本的Pod部署后出现了问题,Deployment可以快速回滚到之前的稳定版本,这种回滚操作不会中断服务。⑤扩展性和高可用性Deployment可以轻松地扩展应用程序的副本数量,满足不同的负载需求,还可以与其他Kubernetes资源,如HorizontalPodAutoscaler结合使用,实现自动水平扩展。⑥版本管理Deployment可以管理应用程序的不同版本,每个版本都对应一个Deployment对象,用户可以查看和管理应用程序的历史部署状态。(3)Service服务发现Service用于定义一组Pod的访问方式,提供服务发现和负载均衡功能,Service允许用户将一组具有相同功能的Pod组织成一个逻辑单元,为它们分配一个稳定的虚拟IP地址和DNS(域名解析)名称,用户或者其他应用程序可以通过这些标识来访问Pod中的容器服务。Service将请求均衡地分发到后端Pod实例上,以实现负载均衡和高可用性。Kubernetes使用内置的负载均衡器来管理Service,确保请求能够均衡地分发到各个Pod实例上,提高应用程序的性能和可靠性。2.1.2必备知识①Service服务实现的机制由于Pod存在生命周期,有销毁,有重建,无法提供一个固定的访问接口给客户端,而且用户不可能记住所有同类型的Pod地址,这样Service资源对象就出现了。Service基于标签选择器将一组Pod定义成一个逻辑单元,并通过自己的IP地址和端口调度代理请求到组内的Pod对象,如下所示,它向客户端隐藏了真实处理用户请求的Pod资源,就像是由Service直接处理并响应一样。Service对象的IP地址也称为ClusterIP,它位于为Kubernetes集群配置指定的IP地址范围之内,是虚拟的IP地址,它在Service对象创建之后保持不变,并且能够被同一集群中的Pod资源所访问。Service端口用于接受客户端请求,并将请求转发至后端的Pod应用的相应端口,这样的代理机制,也称为端口代理,它是基于TCP/IP协议栈的传输层(删除这句)。

Service对象的IP地址是虚拟地址,在集群内部可以访问,无法响应集群外部的访问请求,解决该问题的办法是在单一的节点上做端口暴露或让Pod资源共享工作节点的网络命名空间,除此之外,还可以使用NodePort类型的Service资源,或者是有7层负载均衡能力的Ingress资源。2.1.2必备知识②Service服务的实现原理在Kubernetes集群中,每个Node工作节点运行一个Kube-proxy组件,这个组件进程始终监视着ApiServer中有关Service的变动信息,获取任何一个与Service资源相关的变动状态,通过Watch监视,一旦有Service资源相关的变动,Kube-proxy使用Iptables或者IPVS规则在当前node节点上实现资源调度,如下所示。③Iptables代理模式客户端访问ServiceIP时,ServiceIP根据Iptables的规则直接将请求转发到各Pod上,因为使用Iptables来完成转发,也存在不可忽视的性能损耗,如果集群中存在上万的Pod,那么Node上的Iptables规则将会非常庞大,代理转发的性能就会受影响。2.1.2必备知识④IPVS代理模式(以下内容统改)Kubernetes自1.9-alpha版本引入了IPVS代理模式,当客户端请求到达内核空间时,IPVS根据规则将请求转发到各Pod上。Kube-proxy会监视Service对象和后端Pod,确保IPVS状态与期望一致。如果某个后端Pod发生变化,对应的信息会立即反映到ApiServer上,而Kube-proxy通过Watch(监视)Etcd数据库中的信息变化,将它立即转为IPVS或者Iptables规则,这些动作都是动态和实时的,如下所示。图中翻译userspace(用户空间)、kernelspace(内核空间)2.1.2必备知识⑤Servie服务类型ClusterIP:ClusterIPService是默认的Service类型。ClusterIPService创建一个集群内部的虚拟IP,只有集群内部的其他对象可以访问该Service。这种类型的Service对外部世界是不可见的。NodePort:NodePortService为每个Node节点在一个固定的端口上暴露Service。通过任何Node节点的IP地址和该端口来访问Service。NodePortService也会创建一个ClusterIP,允许从集群内部访问Service。LoadBalancer:LoadBalancerService将外部负载均衡器(如云提供商的负载均衡器)流量引导到集群中的Service。这种类型的Service通常在云环境中使用,通过公共IP地址向外部暴露服务。ExternalName:ExternalNameService允许将Service映射到集群外部的任意DNS名称。当集群内的应用程序需要访问集群外部的服务时,可以使用ExternalNameService。Headless:HeadlessService是一种特殊类型的Service,它将DNS解析直接映射到其后端Pod的IP地址,这对于需要直接访问每个Pod的场景非常有用,通常应用在集群部署有状态服务时。(4)Volume数据卷Volume存储卷是用于持久化数据的抽象概念,它可以附加一个或多个容器到Pod中,Volumes提供了在容器之间共享和存储数据的机制,包括空目录、主机路径、网络存储(并列没问题)等。(5)Configmap和SecretConfigmap和Secret用于管理应用程序的配置信息和敏感数据,configmap用于存储键值对形式的配置数据,而secret则用于存储敏感信息,如密码、令牌等。(6)Namespace命名空间Namespace是Kubernetes中用于将集群资源进行逻辑隔离的机制,通过Namespace可以将不同的资源分组到不同的命名空间中,以便进行管理和控制访问权限。2.1.2必备知识(7)ServiceaccountServiceaccount是用于身份验证和授权的实体,允许Pod与KubernetesAPI进行交互并访问其他集群资源,每个Pod都会关联一个Serviceaccount,用于确定其操作权限。Kubernetes集群还包括一些其他的核心资源,当使用时再进行具体讲解。2.Kubectl命令行工具Kubectl是Kubernetes的命令行工具,用于与Kubernetes集群进行交互,管理集群中的资源,在使用Kubectl命令操作集群时,首先要通过.kube/config中的证书和私钥配置进行客户端认证,成功登录到集群后才可以操作集群资源,以下是Kubectl命令的格式和一些常见用法。(1)命令格式Kubectl的命令格式为Kubectl[Command][TYPE][NAME][flags]其中Command是要执行的命令,如Get、Run、Create、Delete等,TYPE是操作的资源类型,如Pod、Service、Deployment等,NAME是资源的名称,flags是可选的标志参数,用于指定额外的选项,例如--Namespace、--Output等(2)常见用法Kubectl的常见用法如下。①查看资源列表查看某种资源时使用命令Kubectlget<资源类型>,如查看所有Pod,使用KubectlgetPod。②查看特定资源的详细信息查看某个资源的详细信息时,使用命令Kubectldescribe<资源类型><资源名称>,如查看资源类型为Pod,名称为my-Pod的详细信息的命令为KubectldescribePodmy-Pod。2.1.2必备知识③创建资源使用Kubectl命令创建资源有2种方式,一种是基于命令创建资源,另一种是基于脚本创建资源,经常使用的是基于脚本创建资源。基于命令创建资源的方式为Kubectlcreate<资源类型><资源名称><选项>,基于脚本创建资源的命令为Kubectlapply-f<资源配置文件.Yaml>。④删除资源使用Kubectl删除资源的命令为Kubectldelete<资源类型><资源名称>,如KubectldeletePodmy-Pod的作用是删除了名称为my-Pod的Pod资源⑤在容器内部执行命令可以进入到Pod内的容器中执行命令,如在名称为my-Pod的Pod内部启动/bin/bash,命令为Kubectlexec-itmy-Pod/bin/bash。⑥查看日志查看Pod日志命令格式为Kubectllogs<Pod-name>,使用Kubectllogsmy-Pod可以查看my-Pod的日志。其他Kubectl命令在使用时再具体讲解。2.1.3

使用Pod部署Nginx服务1.运维Pod(1)创建Pod (6)进入容器执行相关操作(2)查看Pod运行状态

(7)删除pod(3)访问Pod中容器服务

具体过程见微课。(4)查看Pod描述信息(5)在工作节点使用查询运行容器2.1.3使用Pod部署Nginx服务2.修改nerdctl操作的默认命名空间在node2工作节点,使用nerdctl查看拉取的nginx:alpine镜像发现查看不到拉取下来的nginx:alpine镜像,原因是kuernetes使用containerd容器引擎拉取镜像时,默认将镜像存储到k8s.io命名空间下,所以在使用nerdctl查询、拉取、删除、构建镜像时,要加上k8s.io命名空间,如查询nginx:alpine镜像的命令如下。[root@node1~]#nerdctl-nk8s.ioimages|grepnginx

2.1.3使用Pod部署Nginx服务2.修改nerdctl操作的默认命名空间从结果中发现,查询时加上k8s.io命名空间后,镜像就显示出来了,tag为none的镜像留作备份,当镜像被误删除时,标签为none的不会被删除,需要时可以快速恢复镜像。查询、拉取、删除和构建镜像时常用的操作,每次加上k8s.io命名空间比较烦琐,所以可以通过修改命令别名的方式,实现当使用nerdctl时,默认命名空间就是k8s.io,所以在所有节点上加入nerdctl命令别名操作,如下所示。

2.1.3使用Pod部署Nginx服务2.修改nerdctl操作的默认命名空间[root@master~]#echo"aliasnerdctl='nerdctl--namespace=k8s.io'">>.bashrc[root@node1~]#echo"aliasnerdctl='nerdctl--namespace=k8s.io'">>.bashrc[root@node2~]#echo"aliasnerdctl='nerdctl--namespace=k8s.io'">>.bashrc使用“ctrl+d”注销登录后,就可以方便地使用nerdctl操作k8s.io命名空间的镜像就不需要加上-nk8s.io了,如查询镜像直接使用nerdctlimages即可。

2.1.4使用Deployment控制器部署Nginx服务1.运维Deployment控制器(1)创建Deployment控制器,运行3个Pod(2)查看运行的Deployment控制器和Pod(3)Pod自动恢复(4)Pod扩缩容具体过程见微课。

2.1.4使用Deployment控制器部署Nginx服务2.升级回退服务版本(1)查看服务版本(2)升级运行容器的镜像版本(3)回退版本具体过程见微课。

2.1.4使用Deployment控制器部署Nginx服务3.删除Deployment控制器如果业务停止服务,需要将所有的Pod删除,可以直接删除Deployment控制器,通过控制器创建的Pod也同时被删除了,删除d1控制器,命令如下。[root@master~]#kubectldeletedeploymentd1由于后续还要使用到d1控制器,所以不要执行以上命令。

2.1.5使用Service服务发现访问后端Pod通过Deployment控制器创建了多个Pod后,每次访问Pod服务时,都需要使用特定Pod的IP地址,无法实现通过统一的IP地址访问Pod,通过创建Service服务发现可以为多个Pod设置统一的访问入口,访问Service服务的IP地址后,就可以负载均衡的访问后端的Pod服务了。

2.1.5使用Service服务发现访问后端Pod1.集群内创建使用Service(1)创建Service服务发现(2)访问服务发现具体过程见微课。

2.1.5使用Service服务发现访问后端Pod2.集群外访问服务通过访问服务发现d1已经实现了在集群内部访问服务,如果想在集群外部访问集群内部服务,可以设置服务发现d1的类型为NodePort类型,首先使用命令打开d1的编辑文件,如下所示。[root@master~]#kubectleditserviced1将第30行的type:ClusterIP修改为type:NodePort,保存退出后,再次查看Service服务发现

,结果如下所示。

2.1.5使用Service服务发现访问后端Pod2.集群外访问服务从上图中可以发现,服务发现的外部访问端口已经设置为30269,在Windows上,打开浏览器,通过集群任意节点的IP地址加上30269就可以轮询访问3个Pod中Nginx服务了,结果如图下所示。

任务2-2基于Yaml脚本部署服务任务描述必备知识使用Yaml脚本创建Pod使用Yaml脚本创建Deployment控制器编写Yaml脚本创建Service服务发现2.2.12.2.22.2.32.2.42.2.5利用探针检测Pod健康性2.2.6学习目标【知识目标】(1)掌握使用Yaml创建资源的优势。(2)掌握使用Yaml创建资源的常用字段。【技能目标】(1)能够编写Yaml脚本创建Pod。(2)能够编写Yaml脚本创建Deployment控制器。(3)能够编写Yaml脚本创建Service服务发现。【素养目标】(1)通过学习编写Yaml脚本创建资源,学会不断探索,精益求精的素养。(2)通过学习编写Yaml的基本语法,培养仔细认真,做事规范的素养。2.2.1任务描述使用命令行部署服务和应用,不便于审计和修改,当某个运维人员使用命令在集群上部署应用后,当应用出现问题时,需要重新敲命令解决问题,费时费力。在生产环境中,使用Yaml脚本方式部署服务可以提高运维效率,公司项目经理要求王亮编写Yaml脚本,使用Pod、Deployment、Service等资源部署和发布Nginx服务。2.2.2必备知识1.使用Yaml创建资源的优势在生产环境下,使用Yaml脚本方式部署应用是一种常见做法,这种方式具有以下5个优点。(1)可维护性Yaml脚本可以轻松地保存在版本控制系统中,方便管理和跟踪变更,确保对资源的修改有记录可查,也方便团队协作。(2)可重复性使用Yaml脚本创建资源,可以轻松地重复部署相同的配置,确保在不同环境部署的一致性。(3)可读性相对于其他编程语言或配置文件,Yaml格式文本具备可读性,团队成员更容易理解和修改配置。(4)灵活性Yaml脚本支持丰富的语法,可以描述各种类型的资源和配置。(5)自动化部署可以通过Yaml脚本完成自动化部署任务,提高部署的效率和可靠性。2.2.2必备知识2.编写Yaml脚本创建资源时的常用字段

(1)服务版本使用apiVerison关键字定义某个资源API版本。(2)资源类型使用kind关键字定义资源的类型,如创建Pod时,定义资源类型为Pod。(3)元数据元数据是创建资源的基本信息,使用metadata关键字定义资源的元数据,包括资源的名称、标识、注解等信息。(4)定义资源主体内容使用spec关键字定义资源的主体内容,使用它定义资源的详细信息,这部分内容最为复杂。2.2.2必备知识3.Yaml脚本基本规范(1)结构表示使用缩进表示字段的层级关系,同一层级的字段左侧保持对齐,通常使用两个或四个空格的缩进,不使用制表符(Tab)进行缩进。(2)键值对使用冒号加空格来分隔键和值,键是唯一的,通常是字符串。(3)列表(数组)使用短横线加空格来表示列表项,列表项通常会缩进,表示属于上一级的列表。(4)对象(映射)对象是一组键值对的集合,对象的每个键值对都会缩进,表示属于上一级的对象。(5)数据类型支持字符串、布尔值、整数、浮点数、null、时间、日期等数据类型,字符串通常不需要引号,但如果包含特殊字符,则需要用单引号或双引号括起来,使用true/false表示布尔值,使用null表示空值。(6)注释使用井号#开头表示注释,注释内容不会被解析。2.2.2必备知识(7)多文档支持使用三个短横线来分隔一个文件中的多个文档。(8)复杂结构当定义资源时,可以嵌套使用列表、字典等类型,用于定义复杂结构。(9)Yaml脚本示例这是一个简单的Yaml示例,展示了一些基本的格式。#这是一个注释person:#字典的开始

name:JohnDoe#字符串

age:30#整数

married:true#布尔值children:#列表的开始-name:lucyage:20-name:wangmingage:252.2.3

使用Yaml脚本创建Pod1.查看资源定义字段(1)资源类型和服务版本

(2)字段名称

(3)字段数据类型

(4)查看某个字段的子字段具体过程见微课。2.2.3

使用Yaml脚本创建Pod2.编写创建Pod的Yaml脚本(1)编写Yaml脚本

(6)删除资源

(2)代码语义

具体过程见微课。(3)代码语法

(4)创建pod1(5)修改资源2.2.4使用Yaml脚本创建Deployment控制器在世界生产环境下,一般通过创建Deployment控制器来控制Pod资源的数量,自动化实现Pod资源的扩缩容和业务自动恢复等功能,下面介绍使用Yaml脚本创建Deployment控制器。2.2.4使用Yaml脚本创建Deployment控制器1.查看资源定义字段首先查看deployment控制器的资源类型、版本和定义资源的字段,命令如下。[root@master~]#kubectlexplaindeployment在返回结果中,发现deployment控制器的资源类型KIND为Deployment,资源属于的GROUP组为apps,服务版本VERSION为v1,所以deployment资源类型的Api版本为apps/v1(组名/服务版本),定义资源的字段同样为apiVersion、kind、metadata、spec、status等5个字段。2.2.4使用Yaml脚本创建Deployment控制器1.查看资源定义字段由于spec字段具体负责创建资源的细节,所以继续查看spec下的子字段,命令如下。[root@masterproject2]#kubectlexplaindeployment.spec在返回的结果中,发现有spec下的selector字段和template字段是必须定义的,如下所示。selector<LabelSelector>-required-template<PodTemplateSpec>-required-其中template定义的是Pod资源,在定义Pod标签后,使用selector设置与Pod一致的标签。2.2.4使用Yaml脚本创建Deployment控制器2.编写创建Deployment的Yaml脚本(1)编写Yaml脚本

(6)删除资源(2)代码语义

具体过程见微课。(3)代码语法(4)创建deployment控制器(5)修改资源2.2.5编写Yaml脚本创建Service服务发现1.查看资源定义字段首先查看service服务发现的资源类型、版本和定义资源的字段,命令如下。[root@master~]#kubectlexplainservice在返回结果中,发现deployment控制器的资源类型KIND为Service,服务版本VERSION为v1,定义资源的字段同样为apiVersion、kind、metadata、spec、status等5个字段。2.2.5编写Yaml脚本创建Service服务发现2.编写创建Service的Yaml脚本(1)在project2目录下创建s1.yaml(6)在集群外部访问应用(2)代码语义

具体过程见微课。(3)代码语法(4)创建service服务发现(5)修改在集群外部访问服务2.2.6利用探针检测Pod健康性1.探针的作用Pod(去掉)探针是Kubernetes中用于监视容器健康状态的一种机制,它可以帮助Kubernetes判断何时应该重启容器、替换容器或者将容器从服务负载均衡器中移除。在Pod中定义的探针主要有两种类型:存活探针和就绪探针。(1)存活探针(LivenessProbe)用于检测容器是否存活。如果存活探针失败,Kubernetes将会重启Pod。(2)就绪探针(ReadinessProbe)用于检测容器是否准备好接受流量。如果就绪探针失败,Kubernetes将会暂时将该容器从服务负载均衡器中移除,直到探针再次成功。2.2.6利用探针检测Pod健康性2.定义探针方式存活探针和就绪探针可以通过以下方式定义。(1)HTTP探针定期向容器的特定地址发出HTTP请求,根据响应判断探针是否成功。(2)TCP探针检查容器的特定端口是否处于打开状态。如果端口处于打开状态,则探针成功,否则探针失败。(3)命令探针在容器内部执行特定命令,并根据命令的执行结果判断探针是否成功。如果命令执行成功,则探针成功,否则探针失败。2.2.6利用探针检测Pod健康性2.定义探针方式(1)编写Yaml脚本(2)代码语义(3)代码语法(4)执行探针并测试效果具体过程见微课。任务2-3部署任务和守护型应用任务描述必备知识使用Job控制器部署一次性任务使用CronJob控制器部署周期性任务使用DaemonSet控制器部署节点守护型应用2.3.12.3.22.3.32.3.42.3.5学习目标【知识目标】(1)掌握Job和CronJob控制器的作用。(2)掌握DaemonSet控制器的作用。【技能目标】(1)能够使用Job和CronJob控制器部署一次性和周期性应用。(2)能够使用DaemonSet控制器部署守护型应用。【素养目标】(1)通过学习不同控制器的作用,培养基于场景使用不同技术的素养。(2)通过学习任务和守护型控制器,培养多元化思考的素养。2.3.1任务描述使用Job控制器可以执行批量的任务处理,确保每个任务都能够成功完成,使用DaemonSet控制器可以执行守护型任务,收集各个节点的运行状态、日志等信息,公司项目经理要求王亮编写Yaml脚本,创建Job、CronJob、DaemonSet控制器,部署任务和守护型应用。2.3.2必备知识1.Job和CronJob控制器的应用场景Job控制器适用于一次性任务和错误处理,而CronJob控制器适用于基于时间表的定时任务调度,它们都为Kubernetes用户提供了灵活可靠的方式来管理和执行各种类型的任务,具体应用场景如下。(1)Job控制器①批量处理任务对于需要一次性执行的任务,如数据处理、数据清洗、图像处理等,使用Job控制器可以确保任务成功完成。②定时任务某些任务可能不需要按照固定的时间表运行,而是在需要时启动一次。这些任务可以使用Job控制器来实现,确保任务在需要时能够启动并成功完成。③错误处理和重试Job控制器允许指定任务失败后重试次数和间隔时间,这对于处理临时性错误或网络问题非常有用。④并行处理通过配置并行Job,可以同时运行多个任务副本,加速任务的完成速度,特别适用于大规模数据处理和计算密集型任务。2.3.2必备知识(2)CronJob控制器①定时任务调度与传统的cron作业类似,CronJob控制器允许用户基于时间表调度任务,如每小时、每天、每周等执行特定的任务。②定期数据备份可以使用CronJob控制器定期执行数据库备份、文件系统备份等任务,以确保数据的安全性和可恢复性。③定期报告生成使用CronJob控制器可以定期完成生成报告、汇总数据等工作,节省人力和时间成本。④定期清理任务通过CronJob控制器可以定期完成清理过期数据、临时文件等工作,保持系统的清洁和稳定。2.3.2必备知识2.DaemonSet控制器的应用场景①日志收集器在每个节点上运行日志收集器,将节点日志发送到集中的日志存储系统,以便监控和故障排除。②监控代理在每个节点上运行监控代理,收集节点和容器的性能指标,并将其发送到监控系统,以监视集群的健康状态。③安全扫描器在每个节点上运行安全扫描器,定期检查节点和容器中的漏洞和安全问题,确保集群的安全性。④服务代理在每个节点上运行服务代理,将流量路由到集群内部的服务,提供负载均衡和服务发现功能。2.3.3使用Job控制器部署一次性任务1.查看资源定义字段首先查看Job控制器的资源类型、版本和定义资源的字段,命令如下。[root@master~]#kubectlexplainjob从返回结果中发现,job控制器的资源类型KIND为Job,资源属于的GROUP组为batch,服务版本VERSION为v1,所以job资源类型的Api版本为batch/v1(组名/服务版本)。定义资源的字段为apiVersion、kind、metadata、spec、status等5个字段。2.3.3

使用Job控制器部署一次性任务2.编写创建Job的Yaml脚本(1)编写脚本

(2)代码语义

(3)创建Job控制器并查看效果具体过程见微课。2.3.4使用CronJob控制器部署周期性任务1.查看资源定义字段CronJob控制器和Job控制器的定义非常类似,Job控制器用来执行一次性任务,CronJob控制器用来执行周期性任务,首先查看CronJob控制器的资源类型、版本和定义资源的字段,命令如下。[root@master~]#kubectlexplaincronjob从返回结果中发现job控制器的资源类型KIND为CronJob,资源属于的GROUP组为batch,服务版本VERSION为v1,所以cronjob资源类型的Api版本为batch/v1(组名/服务版本)。定义资源的字段为apiVersion、kind、metadata、spec、status等5个字段。2.3.4使用CronJob控制器部署周期性任务2.编写创建Job的Yaml脚本(1)编写脚本(2)代码语义(3)创建CronJob控制器并验证效果具体过程见微课。2.3.5使用DaemonSet控制器部署节点守护型应用1.查看资源定义字段使用DaemonSet控制器可以在集群中的每个节点上创建Pod,主要用于收集节点信息,包括软硬件运行状态、日志等信息,查看DaemonSet控制器的资源类型、服务版本和定义资源的字段,命令如下。[root@master~]#kubectlexplaindaemonset从返回结果中发现daemonset控制器的资源类型KIND为DaemonSet,资源属于的GROUP组为apps,服务版本VERSION为v1,所以cronjob资源类型的Api版本为apps/v1(组名/服务版本)。定义资源的字段为apiVersion、kind、metadata、spec、status等5个字段。2.编写创建DaemonSet的Yaml脚本(1)编写脚本(2)代码语义(3)创建DaemonSet控制器并验证效果具体过程见微课。2.3.5使用DaemonSet控制器部署节点守护型应用项目小结

Pod是Kubernetes容器云平台的基本组织单位,每个Pod中包含一个或者多个容器,在集群中部署Pod可以实现用户部署应用的需求,单独部署Pod无法实现业务的冗余备份和自动扩缩容,通过控制器可以部署多个Pod,实现对Pod的管理。在部署了多个Pod后,部署Service服务发现可以实现Pod中业务的统一接口和负载均衡访问。Job控制器可以通过串行或者并行方式执行一次性任务,CronJob控制器应用在执行周期性任务的场景,DaemonSet控制器可以在集群中的每个节点部署Pod,经常应用在收集节点数据信息的场景。

项目3认证授权用户访问集群资源《Kubernetes容器编排与管理教程》3-1

目录/Contents3-2认证授权Useraccount系统账户认证授权ServiceAccount服务账户项目3认证授权用户访问集群资源

公司有多个管理人员需要登录和操作Kubernetes集群,同时为方便集群运维,管理员基于Pod容器部署了Dashboard图形化界面程序(删除),项目经理要求王亮首先创建用于管理人员登录系统的Useraccount系统账户并授予相应权限,实现管理人员的登录和运维。同时为Dashboard图形化程序创建ServiceAccount账户并授予相应权限,实现通过Dashboard图形化界面运维集群资源。项目3认证授权用户访问集群资源任务3-1认证授权Useraccount系统账户任务描述必备知识使用Useraccount系统账户登录集群配置RBAC授权Useraccount系统账户权限使用ResourceQuota实现用户资源配额管理3.1.13.1.23.1.33.1.43.1.5学习目标【知识目标】(1)掌握UserAccount系统账户的配置方法。(2)掌握在Kubernetes集群申请用户证书的流程。(3)掌握Names

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论