一文了解K8S(Kubernates)
王小工 2024-09-04 16:07:05 阅读 51
K8S(Kubernates) 知识目录
一、K8S
1. 概述
Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态,其服务、支持和工具的使用范围相当广泛。
Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系。 Google 在 2014 年开源了 Kubernetes 项目。 Kubernetes 建立在 Google 大规模运行生产工作负载十几年经验的基础上, 结合了社区中最优秀的想法和实践。
2. 部署架构演进
传统部署时代:物理服务器上运行应用程序。虚拟化部署时代:虚拟机上运行应用程序。容器部署时代:容器类似于 VM,但是更宽松的隔离特性,使容器之间可以共享操作系统(OS)。
3. 能做什么
Kubernetes 为提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足扩展要求、故障转移应用、提供部署模式等。
Kubernetes 提供:
服务发现和负载均衡存储编排自动部署和回滚自动完成装箱计算自我修复密钥与配置管理
Kubernetes组件
Master
kube-apiserver:该组件负责公开了 Kubernetes API,负责处理接受请求的工作。etcd:一致且高度可用的键值存储,用作 Kubernetes 的所有集群数据的后台数据库。kube-scheduler:控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。kube-controller-manager:kube-controller-manager 是控制平面的组件, 负责运行控制器进程。
节点控制器(Node Controller):负责在节点出现故障时进行通知和响应任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成端点分片控制器(EndpointSlice controller):填充端点分片(EndpointSlice)对象(以提供 Service 和 Pod 之间的链接)。服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号(ServiceAccount)。 cloud-controller-manager:
Node
节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。kubelet
kubelet 会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。kube-proxy
kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。容器运行时(Container Runtime)
这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。
Kubernetes 支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。
插件(Addons)
DNS:尽管其他插件都并非严格意义上的必需组件,但几乎所有 Kubernetes 集群都应该有集群 DNS, 因为很多示例都需要 DNS 服务。Web 界面(仪表盘):Dashboard 是 Kubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身, 并进行故障排除。容器资源监控:容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中, 并提供浏览这些数据的界面。集群层面日志:集群层面日志机制负责将容器的日志数据保存到一个集中的日志存储中, 这种集中日志存储提供搜索和浏览接口。网络插件:网络插件 是实现容器网络接口(CNI)规范的软件组件。它们负责为 Pod 分配 IP 地址,并使这些 Pod 能在集群内部相互通信。
二、架构
Kubernetes主要由以下几个核心组件构成:
etcd 保存了整个集群的状态;api server提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等级制;controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;kubelet负责维护容器的生命周期,同时也负责Volume(CSI)和网络(CNI)的管理;Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;
除上述核心组件,还有一些推荐的插件
CoreDNS负责为整个集群提供DNS服务Ingress Controller为服务提供外网入口Prometheus提供资源监控Dashboard提供GUIFederation提供跨可用区的集群
三、核心概念
Kubernetes 是一个基于容器化技术的分布式应用程序编排平台,其核心概念主要包括 Pod、Service、Namespace、Deployment、StatefulSet、DaemonSet、Job 和 CronJob 等。
1. Pod
定义:Pod是Kubernetes中最小的可部署对象,用于托管容器应用程序。一个Pod可以包含一个或多个容器,这些容器共享网络和存储,并共同部署到同一节点上。作用:Pod是Kubernetes管理的最小单元,它提供了一种将容器组合成一个逻辑单元的方式,以便在集群中共同部署和管理。
<code>apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: myapp
spec:
containers:
- name: my-container
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: my-volume
mountPath: "/usr/share/nginx/html"
readOnly: false
volumes:
- name: my-volume
emptyDir: { }
2. Deployment
定义:Deployment是用于定义Pod如何部署和更新的控制器。它允许用户指定副本数量、升级策略等,并确保指定的Pod始终处于预期状态。作用:Deployment通过管理ReplicaSet来确保Pod的副本数量符合预期,并支持滚动更新和回滚操作,使得应用程序的部署和更新更加灵活和可靠。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: my-container
image: nginx:latest
ports:
- containerPort: 80
3. Service
定义:Service是一种抽象,用于定义一组Pod的访问方式。通过Service,可以为一组Pod提供统一的DNS名称和稳定的IP地址,实现负载均衡和服务发现。作用:Service为Pod提供稳定的访问入口,使得客户端能够透明地访问后端Pod集群,同时支持负载均衡和故障转移。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: myapp
4. Namespace
定义:Namespace提供了一种将集群划分为多个虚拟集群的方式。每个Namespace都可以包含自己的资源对象,帮助组织和隔离不同团队或项目的资源。作用:Namespace通过逻辑隔离集群资源,提高了集群的可用性和安全性,使得不同团队或项目可以独立管理自己的资源。
apiVersion: v1
kind: Namespace
metadata:
name: my-namespace
5. Node
定义:Node是Kubernetes集群中的工作节点,负责运行容器化的应用程序。每个Node都有自己的资源和容量,可以托管多个Pod。作用:Node是Kubernetes集群中的计算资源,通过运行Pod来承载应用程序的容器。Node与Master节点协作,共同实现集群的管理和控制。
6. Cluster
定义:Cluster是由多个Node组成的Kubernetes集合,共同管理和运行容器化应用程序。Cluster包括Master节点和Worker节点,Master节点负责集群管理,Worker节点负责运行应用程序。作用:Cluster提供了完整的容器编排和管理能力,通过Master节点和Worker节点的协作,实现了应用程序的自动化部署、扩展和管理。
7. Master节点组件
API Server:集群的统一入口,各组件协调者,处理所有的API请求,并与etcd等后端存储进行交互。Controller Manager:包含多个控制器,负责监控集群状态并确保集群达到预期状态。Scheduler:负责将新创建的Pod分配到集群中的节点上,根据资源需求、策略和约束条件等进行调度决策。etcd:分布式键值存储系统,用于存储集群的配置信息、状态信息等。
8. Worker节点组件
Kubelet:运行在每个工作节点上的代理,负责管理节点上的Pod生命周期,与Master节点上的API Server进行通信。kube-proxy:用于网络代理和负载均衡的组件,维护节点上的网络规则和转发规则。
容器运行时:如Docker、containerd等,负责在节点上创建和运行容器。
四、网络
K8S(Kubernetes)网络是Kubernetes集群中各个组件之间通信的基础。它涉及到多个层面,包括节点网络、Pod网络、Service网络等。
1. K8S网络概述
1.1. 网络层级
节点网络:集群宿主机节点间的网络通信,并负责打通与集群外部的通讯。Pod网络:为集群上的Pod提供网络,通过CNI(Container Network Interface)网络插件来完成,如Flannel、Calico、Cilium等。Service网络:部署集群时指定网段,Service从这里面分配。Service对象的IP地址存在于相关的ipvs、iptables规则中,由K8S集群自行管理。
1.2. 流量类型
Kubernetes网络中主要存在四种流量:同一Pod内的容器间通讯Pod间的通讯Pod与Service的通讯集群外部流量与Service间的通讯
2. Pod网络
2.1. 网络模型
Pod是Kubernetes中的最小调度单元,Pod内的所有容器共享同一个网络命名空间(Linux NET NAMESPACE),因此它们可以直接通过localhost地址加端口号进行通信。
2.2. CNI插件
CNI插件负责将Pod连接到网络中,并满足以下功能要求:
所有Pod间直接通信而不需要通过NAT机制所有节点与Pod间直接通讯而不需要通过NAT机制所有Pod对象都位于同一平面网络内
常见的CNI插件包括Flannel、Calico、Cilium等,它们通过不同的方式实现Pod间的网络通信。
3. Service网络
Service是Kubernetes中用于抽象Pod集合的概念,它为Pod集合提供了一个稳定的访问入口(ClusterIP)。Service的IP地址和端口号被用来将外部流量转发到后端的Pod上。
3.1. Service类型
Service有三种类型:ClusterIP、NodePort和LoadBalancer。
ClusterIP:仅在集群内部可见,用于集群内部的服务发现和负载均衡。NodePort:在集群的每个节点上开放一个静态端口,通过该端口可以访问Service。LoadBalancer:在NodePort的基础上,利用云提供商的负载均衡器将流量转发到NodePort上。
4. Flannel概述
Flannel是CoreOS团队为Kubernetes设计的一个覆盖网络(Overlay Network)工具,它允许集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
4.1 工作原理
Flannel支持多种后端实现,包括VXLAN、host-gw等。以VXLAN为例,其工作原理如下:
当Pod发送数据包时,数据包首先到达宿主机上的cni0网桥。数据包被路由到flannel.1设备进行处理,并进行VXLAN封装。封装后的数据包通过UDP协议的4789端口发送到目标节点。目标节点的内核接收到UDP数据包后,进行拆包并提取内部数据帧,然后将其发送到目标Pod的网络命名空间中。
五、存储
Kubernetes(k8s)的存储系统是其核心功能之一,它提供了多种存储解决方案来满足不同场景下的数据存储需求。Kubernetes的存储可以分为临时存储和持久存储两大类。
1. 临时存储
临时存储通常是短暂的、易失性的,当Pod被删除时,存储中的数据也会被删除。常见的临时存储类型包括:
1.1 EmptyDir:
EmptyDir是一种在Pod中创建的空目录,用于在容器之间共享文件。EmptyDir的数据存储在Pod所在节点的本地磁盘上,因此当Pod被删除时,数据也会被删除。适用于临时数据的存储和容器间的数据共享。
1.2 HostPath:HostPath卷将主机节点上的文件系统路径挂载到容器中。这种存储卷通常用于测试和开发环境,因为它依赖于节点的文件系统,不适合生产环境。可以满足数据持久化需求,但数据会保留在节点上,Pod被销毁也不会删除数据。
2. 持久存储
持久存储是一种长期存储,用于存储应用程序的数据和状态,即使Pod被删除或重新调度,数据也不会丢失。常见的持久存储类型包括:
2.1 NFS(网络文件系统):
NFS卷将网络文件系统挂载到容器中,可以跨多个Pod和节点共享数据。
适用于需要跨节点共享数据的场景。
2.2 ConfigMap和Secret:
ConfigMap和Secret卷将配置文件和密钥挂载到容器中。ConfigMap用于存储配置信息,而Secret用于存储敏感数据,如密码、OAuth令牌和ssh密钥。
适用于需要安全存储和访问配置信息及敏感数据的场景。
2.3 PersistentVolumeClaim(PVC):
PVC卷是一种抽象层,它将Kubernetes集群中的物理存储资源抽象为逻辑存储卷。PVC可以动态地分配和释放存储资源,并且可以在不同的Pod之间共享。
适用于需要动态存储资源的场景。
2.4 StatefulSet:
StatefulSet卷是一种特殊的PVC卷,它可以为有状态应用程序提供稳定的、持久的存储。StatefulSet会为每个Pod分配唯一的持久卷,并且可以按照顺序启动和关闭Pod。
适用于需要稳定存储和有序管理的有状态应用程序。
2.5 动态存储卷和CSI存储插件:
动态存储卷是一种自动化管理存储资源的方法,它可以根据需求动态地创建和删除存储卷。CSI(容器存储接口)存储插件是一种标准化的存储插件接口,可以与多种不同类型的存储后端集成。
适用于需要灵活管理存储资源的场景。
2.6 应用场景
Kubernetes的存储系统具有广泛的应用场景:
持久化数据:用于存储应用程序的持久化数据,如数据库、文件系统等。分布式存储:支持分布式存储解决方案,如Ceph、GlusterFS等。日志和监控:用于存储日志和监控数据,以便进行日志分析和监控。静态资源:如Web应用程序中的图像、CSS文件和JavaScript文件等。镜像仓库:用于存储和管理容器镜像。大数据分析:支持大数据存储和处理,如Hadoop、Spark等。
六、监控和日志
在Kubernetes(K8s)环境中,监控和日志是确保系统稳定性和性能调优的重要部分。以下分别介绍K8s的监控和日志处理机制。
1. K8s监控
监控的重要性
监控是K8s生态中的一部分,主要用于及时暴露问题、防止问题进一步恶化,并帮助运维人员和开发者了解系统运行状态、优化性能。监控指标
资源监控:包括CPU、内存、网络等资源类的指标。性能监控(APM):通过Hook机制在虚拟机层、字节码执行层或应用层进行隐式调用或显示注入,获取更深层次的监控指标,如JVM的GC次数、内存分布、网络连接数等。事件监控:监控K8s中状态转换时产生的normal、warning等事件。
监控工具
Heapster(已废弃):早期K8s版本中常用的监控组件,负责数据采集和聚合,但存在无法定制化开发、bug无人修复等问题,因此被K8s废弃。Metrics-server:作为Heapster的精简版,metrics-server提供资源监控功能,是K8s官方推荐的资源监控解决方案。Prometheus:CNCF云原生社区的一个毕业项目,提供强大的自定义监控能力。通过Prometheus,可以监控资源使用情况、自定义监控指标(如应用在线人数、数据库慢查询等),并支持报警和数据可视化。
监控接口标准
K8s定义了三种不同的监控接口标准,包括Resource Metrics、Custom Metrics和External Metrics,分别对应不同的监控需求和数据来源。
2. 日志
日志的重要性
日志是排查问题的重要途径,通过日志可以了解系统运行状态、定位故障原因。日志来源
主机内核日志:如网栈异常、驱动异常、文件系统异常等。K8s组件日志:如etcd、API server、kube-scheduler、controller-manager、kubelet等组件的日志。应用日志:包括容器内应用的日志。
日志处理方案
节点级日志代理:在每个节点上运行日志代理(如Fluentd、Filebeat等),收集所有容器的日志,并转发到远端存储(如Elasticsearch、Kafka等)。Sidecar容器:在Pod中部署专门的Sidecar容器来读取应用程序的日志文件,并将其重定向到stdout和stderr,或使用Sidecar容器直接将日志发送到远端存储。日志驱动:通过配置Docker的日志驱动(如json-file、syslog等),将日志输出到指定位置或远程服务。
日志收集工具
Fluentd:K8s官方推荐的日志收集工具之一,具有强大的过滤、缓存和路由功能,支持多种插件和扩展。Filebeat:轻量级的日志收集工具,可以与Elasticsearch、Logstash等配合使用,实现日志的收集、处理和存储。
七、K8S 安全
K8S(Kubernetes)安全是保障容器化应用和服务在集群中安全运行的重要方面。Kubernetes的安全机制主要围绕API Server的保护来设计,确保只有经过认证的用户和服务才能与API Server进行交互,并对集群资源进行操作。
1. 认证(Authentication)
认证是安全机制的第一道防线,负责确认请求者的身份。Kubernetes支持多种认证方式:
HTTP Token:客户端通过Token进行身份验证,Token是一个复杂的字符串,每个Token对应一个用户名,存储在API Server能够访问的文件中。HTTP Basic认证:使用用户名和密码进行基本的HTTP认证,用户名和密码通过Base64编码后放在HTTP请求的头部。HTTPS证书认证:基于CA根证书签名的客户端身份验证,实现双向认证(Mutual TLS),确保通信双方的身份。SSH密钥:对于某些操作,如节点登录,可以使用SSH密钥进行认证。
二. 鉴权(Authorization)
鉴权是在认证之后,确定用户或服务的访问权限。Kubernetes支持多种授权策略:
RBAC(基于角色的访问控制):最常用的鉴权方式,允许管理员定义角色(Role)和角色绑定(RoleBinding),以控制对资源的访问。角色可以指定命名空间的资源控制权限,而集群角色(ClusterRole)可以授权所有命名空间的资源控制权限。ABAC(基于属性的访问控制):基于用户、资源和操作的属性来决定访问权限,但设置较为繁琐,一般不常用。**Webhook:**通过调用外部REST服务对用户进行授权,可以在集群外部进行鉴权。AlwaysDeny/AlwaysAllow:分别用于测试环境,拒绝或允许所有请求。
三. 准入控制(Admission Control)
准入控制是在资源被创建或修改之前进行最后的检查,确保资源的创建符合集群的策略和规范。Kubernetes的API Server内置了多个准入控制器插件,如:
LimitRanger:用于命名空间的配额管理。ResourceQuota:限制资源的使用量,如CPU、内存和存储。ServiceAccount:确保Pod中的容器能够以Service Account的身份访问API Server。
此外,还有ValidatingWebhook和MutatingWebhook等插件,用于验证资源对象是否符合集群的策略和规范,以及在资源被持久化之前修改资源对象。
其他安全机制
Service Account:Kubernetes中的一个资源对象,用于代表Pod中的容器访问API Server。Service Account允许Pod以一种安全的方式获取访问令牌,而不需要为每个Pod单独生成证书。Secret:用于存储敏感信息,如密码、OAuth令牌和SSH密钥。Service Account相关的Secret包含了用于认证的Token,这些Token被Pod中的容器用来访问API Server。kubeconfig文件:包含了集群的访问参数(如CA证书、API Server地址)和客户端认证信息(如证书和私钥),用于kubectl等客户端工具与API Server的通信。
安全风险和防护建议:
随着Kubernetes的广泛应用,针对K8S的攻击事件也逐渐增加。为了保护K8S集群的安全,可以采取以下措施:
使用强认证和授权机制:确保只有合法的用户和服务才能访问集群资源。定期更新和修补:及时更新Kubernetes和相关组件的补丁,修复已知漏洞。网络隔离:通过网络策略限制不同组件之间的通信,防止未授权的访问。监控和日志记录:实施全面的监控和日志记录,及时发现并响应潜在的安全威胁。访问控制和最小权限原则:遵循最小权限原则,确保每个用户和服务只拥有完成其任务所必需的最少权限。
八、生态系统
K8S(Kubernetes)生态系统是指围绕Kubernetes构建的一系列工具、插件和服务,这些组件共同协作,为开发者提供了一整套完整的解决方案,以便更轻松地部署、管理和扩展容器化应用。
1. 关键接口与插件
CNI(Container Network Interface):CNI是一个标准,用于定义容器在网络层面的交互和通信。它允许Kubernetes无缝集成各种网络解决方案,如Weave、Calico、Flannel、Cilium等,以提供Pod网络、服务发现、负载均衡等功能。CRI(Container Runtime Interface):CRI是Kubernetes用来与容器运行时进行交互的标准接口。它定义了一套RPC(远程过程调用)API,允许Kubernetes支持多种容器运行时,如Docker、containerd、CRI-O等,提高了系统的灵活性。CSI(Container Storage Interface):CSI是一个标准接口,用于将外部存储系统连接到Kubernetes中。通过CSI,Kubernetes用户可以使用各种存储解决方案,而无需等待Kubernetes本身去集成这些解决方案。
2. 工具与服务
监控与日志:
监控工具:如Prometheus、Grafana等,用于采集Kubernetes Metrics API数据,并进行监控指标的可视化展示。日志收集与分析:如Elasticsearch、Logstash、Kibana(ELK Stack)或类似工具,用于收集、索引、查询容器日志。
存储与数据库:
存储管理工具:如Rook、MinIO、CockroachDB等,提供了持久化存储和数据库支持。
服务网格:
如Istio、Linkerd等工具,用于实现服务发现、请求路由、负载均衡、安全策略等功能,增强了微服务架构的可靠性和安全性。CI/CD:
持续集成和持续部署工具,如Jenkins、GitLab CI/CD、GitHub Actions等,可以结合Kubernetes建立自动化部署流水线,提高开发效率。其他工具:
Helm:用于编写和管理Helm Charts,简化应用部署和版本控制。
Kustomize:提供资源配置的复用与差异化定制功能。
GitOps:通过Flux或Argo CD等工具将Kubernetes配置与应用代码一起纳入版本控制系统,实现基础设施即代码(IaC)和自动化部署。
九、生产实践
1. 集群设计与部署
1.1 使用命名空间(Namespace):
命名空间是Kubernetes中用于逻辑隔离资源的手段。不同命名空间中的资源是相互隔离的,有助于避免资源冲突和访问控制。资源:利用Namespace来组织多套环境的资源隔离,如dev、test、prod环境。配置方式:通过kubectl create namespace 命令或YAML文件创建命名空间。
1.2 部署控制器(Deployment Controller):避免直接使用Pod运行应用,而是通过Deployment、DaemonSet、StatefulSet等控制器来管理Pod。控制器可以提供自动扩缩容、滚动更新、健康检查等功能。
1.3 资源请求与限制:为容器设置资源请求(requests)和限制(limits),以避免资源争用和浪费。资源配置可以确保Pod在分配足够资源的情况下运行,同时也限制了其最大资源使用量。
2.安全与访问控制
2.1 基于角色的访问控制(RBAC):
实施RBAC以控制对集群资源的访问。通过角色(Role)和角色绑定(RoleBinding)为用户和服务账户分配权限。遵循最小权限原则,即仅授予必要的权限。
2.2 网络策略:使用网络策略来限制Pod之间的网络通信,确保集群的安全性。可以基于IP地址、端口、协议等条件来定义网络策略。
2.3 Pod安全策略:实施Pod安全策略来增强Pod的安全性,如禁用特权容器、限制容器运行的目录等。
3. 监控与日志
3.1 监控集群状态:
使用Prometheus、Grafana等工具监控集群状态和性能指标。监控指标包括但不限于CPU使用率、内存使用量、网络带宽等。
3.2 日志收集与分析:使用ELK Stack(Elasticsearch、Logstash、Kibana)或Fluentd等工具收集和分析容器日志。日志数据可以帮助定位问题、分析系统行为等。
4. 升级与维护
4.1 定期升级Kubernetes版本:
定期升级到最新版本以获得新功能、漏洞修复和安全更新。在升级前进行充分的测试以确保应用兼容性。
4.2 自动化升级流程:设计并实现自动化升级流程,以减少人为错误和停机时间。可以使用Kubernetes Operator或GitOps工具来管理升级过程。
5. 资源推荐
5.1 官方文档:
Kubernetes官方文档提供了详尽的指南和最佳实践,是学习和了解Kubernetes的首选资源。访问链接:Kubernetes Documentation
5.2 社区和论坛:参与Kubernetes社区和论坛(如GitHub、Stack Overflow、CNCF Slack等)可以获取最新的信息和解决方案。社区成员经常分享经验、提出问题和解答疑惑。
5.3 在线课程和培训:参加在线课程和培训(如Coursera、Udemy等平台上的Kubernetes课程)可以系统地学习Kubernetes知识并掌握最佳实践。
5.4 工具和插件:探索和使用Kubernetes生态系统中的工具和插件(如Helm、Istio、Prometheus等)可以提升开发和运维效率。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。