文章目录
本地搭K8s集群
https://blog.csdn.net/xuezhiwu001/article/details/128444657
bilibili
什么是声明式API?
声明式API是一种编程接口,它允许用户定义期望的系统状态或目标结果,而不是详细说明如何达到这一状态的具体步骤。在声明式API的上下文中,用户通过编写描述性的配置或声明(通常是JSON或YAML格式的文件),来表达他们希望的资源结构或应用行为。API或相关系统随后负责比较当前状态与期望状态,并自动执行必要的操作以达到或维持预期状态。
这种方法对比命令式API的一个主要区别在于:
命令式API要求用户通过一系列明确的指令来控制系统的每个动作,比如创建、更新、删除资源等。
声明式API则让用户声明最终目标,系统负责管理和执行达到该目标所需的步骤。
声明式API的优势包括简化复杂系统的管理、提高自动化水平、减少人为错误、以及增强系统的可预测性和可维护性。这种API风格在现代云计算和基础设施管理领域特别流行,如Kubernetes中的资源配置就是声明式API的一个典型应用,用户通过定义Pod、Service等资源的配置文件来声明应用的部署需求,Kubernetes系统会确保实际运行状态与这些声明相匹配。
kubectl apply
在Kubernetes中,资源配置是一个典型的声明式API的应用场景。用户通过创建或更新描述资源期望状态的配置文件(通常是YAML或JSON格式),来声明他们希望集群达到的状态,而不是一步步地指示Kubernetes如何去改变或管理这些资源。Kubernetes会自动管理和调整,以确保实际状态与用户的声明一致。下面通过一个简单的例子来说明这一点:
例子:部署一个Nginx Web服务器
假设你希望在Kubernetes集群上部署一个Nginx Web服务器。你会创建一个名为nginx-deployment.yaml的YAML文件,内容可能如下:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.10
ports:
- containerPort: 80
在这个YAML文件中,你声明了以下几点:
- 你想要创建一个Deployment资源(kind: Deployment),这是Kubernetes用来管理无状态应用副本的机制。
- 你希望这个Deployment管理的Nginx实例有3个副本(replicas: 3),即运行3个相同的Nginx容器。
- 容器使用的镜像是nginx:1.19.10,并且容器会在80端口监听。
接下来,你通过命令kubectl apply -f nginx-deployment.yaml
来应用这个配置。Kubernetes接收到这个声明后,会检查当前集群状态与你声明的状态之间的差异,并采取行动来创建或更新资源,直到集群状态与你的声明匹配。如果之后你修改了YAML文件并再次执行kubectl apply,Kubernetes会自动识别变化并相应地调整集群状态,比如增加或减少副本数量,或是更新容器镜像版本。
这个过程展示了声明式API的核心理念:你只关注表述目标状态,而Kubernetes负责实现这一状态。
详细命令式与声明式介绍:https://blog.csdn.net/m0_45406092/article/details/135572137
Etcd数据库有什么特性,为什么K8S选用了Etcd数据库?
todo (待拓展,raft算法,和别的键值系统的比较)
etcd是一个分布式、可靠的键值存储系统,它用于保存和管理集群配置数据。etcd的主要特性如下:
-
分布式:etcd使用Raft一致性算法来保证数据的分布式一致性。这意味着,即使在网络分区或节点故障的情况下,etcd也能提供可靠的数据存储。
-
强一致性:etcd保证每次读操作都会返回最新的值,这对于保持集群状态的准确性非常重要。
-
高可用性:etcd支持多节点部署,可以在某些节点发生故障时继续提供服务。这有助于确保集群的稳定性和可用性。
-
可观察性:etcd提供了丰富的监控指标和日志,以便对其进行监控和故障排查。
-
安全性:etcd支持TLS加密通信,以及客户端证书验证和角色访问控制,以保护存储的数据安全。
Kubernetes(K8s)选择etcd作为其主要数据库,主要基于以下原因:
-
一致性:Kubernetes集群需要一个强一致性存储系统来保存和管理集群状态,以确保所有组件使用相同的配置数据。etcd的强一致性保证了这一要求。
-
高可用性:Kubernetes集群需要具有高可用性的数据库,以确保在某些节点发生故障时,集群可以继续运行。etcd的高可用性特性满足了这一需求。
-
可扩展性:etcd可以水平扩展,以支持大量的客户端请求和存储需求。这使得etcd能够支持大规模的Kubernetes集群。
-
社区支持:etcd的开发和维护由CoreOS社区支持,这意味着etcd可以得到及时的更新和修复,以满足Kubernetes集群的需求。
因此,综合考虑etcd的特性和Kubernetes的需求,etcd成为了Kubernetes的理想选择。
K8S中一个node的生命周期是怎样的?
Kubernetes中的一个Node(节点)的生命周期大致可以分为以下阶段:
-
注册:当一个节点启动时,kubelet(Kubernetes节点代理)会尝试向Kubernetes API服务器注册节点。kubelet将节点的元数据(如节点名称、硬件信息、操作系统信息等)发送给API服务器,API服务器将节点添加到集群中。
-
配置:节点注册成功后,Kubernetes控制平面会为节点分配一些初始配置,如分配Pod CIDR地址范围(用于分配Pod的IP地址)等。
-
调度:Kubernetes调度器会根据集群的资源需求和调度策略,将Pod调度到合适的节点上运行。当一个Pod被调度到节点上时,kubelet会接收到调度通知。
-
运行:kubelet收到调度通知后,会开始准备Pod运行的环境,如创建网络接口、挂载存储卷等。随后,kubelet会启动Pod中的容器,并将其连接到相应的网络和存储。
-
监控:kubelet会周期性地向API服务器报告节点的状态,如节点的健康状况、资源利用率等。此外,kubelet还会监控Pod的运行状态,并在需要时重启失败的容器。
-
维护:Kubernetes控制平面会根据集群的策略执行一些维护操作,如节点升级、扩容、缩容等。在执行这些操作时,Kubernetes会尽量保证节点上的Pod不受影响。
-
注销:当一个节点需要从集群中移除时,管理员可以通过kubectl命令或API操作将节点标记为不可调度(避免新的Pod调度到该节点上)并逐出节点上的Pod。在Pod完全逐出后,节点可以被安全地从集群中删除。
整个过程中,Kubernetes会通过控制平面的各种组件(如API服务器、控制器、调度器等)协同工作,以确保节点的生命周期得以顺利进行。同时,节点上的kubelet也会与控制平面进行通信,以接收指令和报告状态。
服务发现机制介绍
todo 嗯,介绍的不够详细
在微服务架构中,服务发现是一种关键机制,允许服务相互发现并与其他服务通信。随着服务实例的数量和位置不断变化,服务发现机制确保了服务间通信的持续可用性和负载均衡。服务发现机制通常分为两大类:客户端发现和服务端发现。
- 客户端发现(Client-side discovery):
在客户端发现模式下,服务实例负责将自己的网络位置(如IP地址和端口)注册到服务注册表(Service Registry)。客户端向服务注册表查询所需服务的网络位置,然后直接与服务实例通信。
客户端发现的优点是消除了中间代理层,降低了网络延迟。但是,缺点是客户端需要实现服务发现逻辑和负载均衡策略,这可能导致代码重复和客户端库的依赖。
例子:Netflix Eureka, Apache ZooKeeper
- 服务端发现(Server-side discovery):
与客户端发现不同,服务端发现将服务发现和负载均衡逻辑转移到服务代理(Service Proxy)或负载均衡器(Load Balancer)中。服务实例将自己的网络位置注册到服务注册表,客户端向服务代理发起请求。服务代理查询服务注册表以获取服务实例的网络位置,并根据负载均衡策略将请求转发给合适的服务实例。
服务端发现简化了客户端,客户端无需实现服务发现和负载均衡逻辑。但是,引入服务代理可能会增加网络延迟和故障点。
例子:Kubernetes Service, Amazon ELB
Kubernetes的服务发现:
在Kubernetes中,可以通过Service资源来实现服务发现。Kubernetes Service充当服务实例的抽象层,提供一个稳定的IP地址和DNS名称。当客户端需要访问服务时,它们可以使用Service的IP地址或DNS名称。在后台,Kubernetes根据标签选择器(Label Selector)将Service与一组Pod(服务实例)关联,并在请求到达Service时将其转发到后端的Pod。
Kubernetes Service支持多种类型,包括ClusterIP(集群内部访问)、NodePort(集群外部通过节点端口访问)、LoadBalancer(通过云提供商的负载均衡器访问)和ExternalName(通过外部DNS名称访问)。
Kubernetes的服务发现机制简化了客户端,无需关心服务实例的具体网络位置和数量。同时,Kubernetes的控制平面负责管理服务注册表和负载均衡策略,确保服务发现的可靠性和性能。
docker的实现原理介绍
Docker的实现原理基于一系列底层技术和设计哲学,共同构成了其轻量级、高效的容器化平台。以下是Docker实现的核心要点:
- Linux内核特性利用:
- 命名空间(Namespace):Docker利用Linux内核的Namespace技术来实现资源和环境的隔离。命名空间提供了独立的视图,包括PID(进程ID)、NET(网络)、IPC(进程间通信)、UTS(主机名和域名)、MNT(文件系统挂载点)和USER(用户ID和组ID),使得每个容器认为自己是在一个独立的系统中运行。
- 控制组 (Control Groups, cgroups):Docker使用cgroups来限制、记录和隔离容器的资源使用情况,包括CPU、内存、磁盘I/O和网络资源,确保单个容器不会过度消耗资源影响其他容器或宿主机。
-
联合文件系统(UnionFS):
Docker使用UnionFS(如OverlayFS、AUFS等)实现镜像的分层存储。镜像是只读的,容器运行时在其上添加一个可写层。这种分层机制使得镜像的构建和传输高效,同时也支持快速的容器创建和销毁。
-
Docker镜像和容器:
镜像:Docker镜像是一个包含应用程序及其依赖、配置和运行时环境的只读模板。镜像是分层构建的,每一层代表对前一层的更改,这样可以复用基础层,减少存储空间和提高构建速度。
容器:容器是从镜像创建的运行实例,拥有自己的文件系统、网络配置、进程空间和资源限制。容器启动时,会在镜像的顶部添加一个可写层,保存运行时的更改。
- 客户端-服务器架构:
Docker采用C/S架构,Docker守护进程(Docker daemon)运行在宿主机上,负责创建、运行、管理和监控容器。Docker客户端(如命令行工具)通过API(如RESTful API)与守护进程通信,发送命令并接收响应。
-
网络管理:
Docker提供了灵活的网络模型,包括桥接网络(默认)、主机网络、无网络、容器网络和自定义网络。每种网络模式为容器提供了不同的网络隔离和连接方式,确保容器间的通信符合应用需求。
-
存储卷:
Docker支持数据卷(volumes),这是一种独立于容器生命周期的持久化存储方式,可以将数据存储在宿主机的特定目录或网络存储上,使得容器数据得以持久保存,且便于容器间共享。
通过上述技术,Docker实现了应用的快速打包、标准化部署和跨环境一致性,降低了运维复杂度,加速了开发和部署流程。
如果只是使用Linux命名空间进行分离,那么容器将很容易实现,docker相比于容器的核心竞争力在哪里?
虽然Linux命名空间是Docker实现容器化技术的基础之一,它提供了资源和进程的隔离能力,但Docker相比仅使用命名空间的原始容器化方法,增加了许多高级功能和便利性,构成了其核心竞争力。以下是Docker相较于仅使用Linux命名空间的容器技术所具有的几个关键优势:
-
标准化的构建和分发:Docker通过Dockerfile定义了一个标准化的构建过程,使得应用程序及其依赖、环境配置可以被封装成可重复构建的镜像。这些镜像可以方便地在任何支持Docker的平台上运行,确保了环境一致性。
-
易于使用的工具链:Docker提供了一套强大的CLI工具,使得创建、运行、管理和分享容器变得非常简单。用户可以通过简单的命令行操作完成复杂的容器管理任务,而不需要深入理解底层技术细节。
-
丰富的生态系统:Docker拥有庞大的社区支持和生态系统,包括Docker Hub这样的公共镜像仓库,里面存储了数以万计的预构建镜像,覆盖了各种常用软件和服务,用户可以直接使用或在其基础上定制,大大节省了开发和部署时间。
-
网络和存储管理:Docker提供了更高级的网络和存储管理功能。它支持多网络驱动,允许用户定义复杂的网络拓扑,并通过数据卷机制实现了数据持久化和容器间的数据共享,而不仅仅是命名空间提供的基本资源隔离。
-
轻量级和高效的资源管理:除了利用命名空间进行隔离外,Docker还借助cgroups进行资源限制和度量,确保容器在资源使用上既轻量又可控,不会过度消耗宿主机资源。
-
跨平台兼容性:尽管Docker起源于Linux,但它已经发展出了跨平台的支持,包括在Windows和macOS上的Docker Desktop,使得非Linux用户也能轻松地使用容器技术。
-
服务编排和集群管理:Docker Swarm和后来的Kubernetes集成,使得Docker不仅可以用于单机容器管理,还能轻松扩展到大规模的集群部署和自动化的服务编排,进一步提升了其在企业级应用中的价值。
因此,Docker不仅仅是一个简单的容器运行时,而是一整套围绕容器化技术构建的解决方案,它通过提供一站式的开发、部署和管理工具,极大地简化了容器化应用的生命周期管理。
Nginx介绍
Nginx 是一款高性能、轻量级的开源 HTTP 和反向代理服务器,同时也支持 IMAP/POP3/SMTP 邮件代理服务。它由伊戈尔·赛索耶夫在2004年为俄罗斯访问量第二的网站Rambler.ru开发,并在同年10月4日发布了第一个公开版本0.1.0。Nginx以它的稳定性、丰富的功能集、简单易懂的配置文件以及较低的系统资源消耗而广受好评。
Nginx的特点包括:
-
事件驱动架构:Nginx采用异步、事件驱动的处理模型,可以高效地处理大量并发连接,特别是在处理静态文件、HTTP请求和反向代理等方面表现出色,能够支持数以百万计的并发连接。
-
反向代理服务器:作为反向代理,Nginx接收客户端请求,并将请求转发给后端服务器处理,然后将结果返回给客户端,这在负载均衡、内容缓存和SSL终止等方面非常有用。-
- 反向代理服务器是一种特殊的网络服务,它介于客户端(如用户的浏览器)和目标服务器(如Web服务器)之间,但其工作方式与正向代理相反。在正向代理中,客户端通常知道代理的存在,并通过代理服务器访问外部资源;而在反向代理场景下,客户端往往不知道代理的存在,对客户端而言,代理服务器就像是目标服务器本身。
-
负载均衡:Nginx能够将流量分发到多个后端服务器,实现负载均衡,提高服务的可用性和响应速度。它支持多种负载均衡策略,如轮询、最少连接数、哈希等。
-
Web缓存:Nginx可以作为前端缓存服务器,缓存静态内容和动态内容,减少对后端服务器的请求,提高网站性能和用户体验。
-
模块化设计:Nginx具有高度模块化设计,用户可以根据需要选择和加载不同的功能模块,如HTTP、HTTPS、TLS/SSL、Gzip压缩等,易于扩展和定制。
-
邮件代理服务器:除了HTTP服务,Nginx还能够作为邮件代理服务器,处理邮件协议(IMAP、POP3、SMTP)的代理任务。
-
安全性和稳定性:Nginx通过各种安全机制保护服务器免受攻击,如限制连接速率、支持SSL/TLS加密等,同时其稳定的表现使其成为高流量网站的首选。
Nginx广泛应用于各种场景,从个人博客到大型企业级网站、内容分发网络(CDN)、API网关等,是现代互联网基础设施中不可或缺的一部分。由于其开源的特性,社区活跃,不断有新的模块和功能被开发出来,以适应不断变化的互联网需求。
Nginx在K8S中负责什么模块?
在Kubernetes (K8s) 中,Nginx 通常作为 Ingress Controller 的实现来部署,负责以下关键模块和功能:
-
外部访问入口:Nginx Ingress Controller 作为集群的入口点,管理并路由来自外部的HTTP和HTTPS流量到集群内的不同服务。它根据Ingress资源定义的规则来决定如何将流量导向到正确的服务。
-
负载均衡:Nginx 可以根据配置实现请求的负载均衡,将流入的流量智能地分配到后端的多个服务实例,以保证服务的高可用性和扩展性。
-
SSL/TLS 终端:Nginx 能够处理SSL/TLS加密,实现SSL卸载,即在用户请求到达后端服务之前,先在Nginx处终止SSL连接,然后以未加密的形式将请求转发给后端,这简化了后端服务的配置,并提高了安全性。
-
路由和重定向:基于Ingress规则,Nginx可以基于URL路径、主机名、请求头等条件来路由流量到不同的服务。它还可以执行URL重写和路径前缀剥离等操作。
-
访问控制:通过配置Nginx,可以实施基于IP地址的访问控制列表(ACL),限制或允许特定来源的请求访问服务。
-
缓存和压缩:Nginx可以配置为缓存静态内容或响应,减少后端服务器负载,同时支持对响应内容进行压缩,以提高传输效率。
-
日志与监控:Nginx生成详细的访问和错误日志,这些日志对于监控、故障排查和分析流量模式至关重要。结合如NGINX Amplify之类的工具,可以进一步增强监控能力。
-
微服务间的通信:在微服务架构中,Nginx Ingress Controller 可以帮助实现服务间的通信路由,支持复杂的微服务网络架构。
通过这些功能,Nginx Ingress Controller 在Kubernetes环境中扮演着至关重要的角色,不仅提供了一种灵活且强大的方式来管理进入集群的流量,还促进了服务的可观察性、安全性和性能优化。
如何排查K8S中OOM的问题?
在Kubernetes(K8s)中,OOM(Out of Memory)问题通常表现为容器被Kubernetes的kubelet组件杀死,因为容器使用的内存超过了其分配的限制。排查K8s中OOM问题的方法有:
-
检查Pod状态:首先,使用
kubectl get pods
命令查看Pod的状态。如果Pod中的某个容器因为OOM被杀死,Pod的状态将显示为OOMKilled
。 -
查看Pod事件:使用
kubectl describe pod
命令查看Pod的详细信息和相关事件。在事件列表中,你可能会看到类似于The node was low on resource: memory
的警告信息,表示节点上的内存资源不足。 -
查看容器日志:使用
kubectl logs
命令查看容器的日志。有时,你可以在日志中找到导致OOM的操作或错误。 -
分析资源使用:使用
kubectl top
命令检查Pod和节点的资源使用情况。对于容器内的资源使用,你可以使用kubectl exec
命令进入容器,并使用top
、ps
等工具分析进程的资源占用。这可以帮助你发现哪些进程或操作导致了OOM。 -
调整资源限制:根据分析结果,你可以调整Pod的资源请求和限制。通过设置
resources.requests.memory
和resources.limits.memory
字段,你可以为容器分配更多的内存资源,或限制其内存使用以防止OOM。同时,请确保节点上有足够的可用内存来满足Pod的需求。 -
优化应用程序:对于消耗大量内存的应用程序,你需要对其进行性能分析和优化,以降低内存占用。这可能包括减少缓存大小、限制并发请求、使用更高效的数据结构和算法等。对于Java等内存敏感的应用,使用JVM参数调整堆大小,启用GC日志,并使用JVisualVM、JProfiler等工具进行分析。
-
使用Vertical Pod Autoscaler(VPA):VPA是一个Kubernetes插件,可以根据历史资源使用情况自动调整Pod的资源请求和限制。通过部署VPA,你可以减少人工干预的需要,并确保Pod始终具有合适的资源配置。
总之,排查K8s中OOM问题需要分析Pod的状态、事件、日志和资源使用情况,并根据分析结果调整资源限制或优化应用程序。通过这些方法,你可以有效地解决和预防OOM问题。
容器开发相比与虚拟机开发,有哪些优劣势?
容器和虚拟机都是用于隔离应用程序和其依赖项的技术,但它们在实现方式和性能方面有很大的不同。以下是容器开发相对于虚拟机开发的优势和劣势:
优势:
-
启动速度快:容器直接运行在宿主机的操作系统上,因此启动速度非常快,通常只需几秒钟。而虚拟机需要启动一个完整的操作系统,启动时间可能需要几分钟。
-
资源占用小:容器共享宿主机的操作系统和内核,因此它们的资源开销相对较小。虚拟机需要为每个实例分配独立的操作系统和内核,这会导致更高的资源占用。
-
更高的密度和可伸缩性:由于容器的资源开销较小,你可以在同一台物理机上部署更多的容器实例。这使得容器更适合大规模、高密度的部署。同时,容器启动速度快,可以快速地响应负载变化,提高应用程序的可伸缩性。
-
良好的可移植性:容器将应用程序及其依赖项打包在一起,确保在不同环境中的一致性。这使得容器可以轻松地迁移到不同的宿主机、操作系统和云平台,简化了应用程序的部署和管理。
-
更简单的版本控制和部署:容器镜像可以方便地进行版本控制、构建和发布。通过Dockerfile或其他构建工具,你可以自动化创建、测试和部署容器,从而简化开发和运维流程。
劣势:
-
安全性:容器与宿主机操作系统共享内核,这可能导致潜在的安全风险。虽然有一些容器隔离技术(如namespaces、cgroups等),但它们相对于虚拟机提供的硬件级隔离仍然较弱。因此,在安全性要求较高的场景下,虚拟机可能是更好的选择。
-
操作系统支持有限:由于容器共享宿主机的内核,它们只能运行与宿主机相同或兼容的操作系统。这意味着你不能在同一台服务器上运行不同类型的操作系统(如Linux和Windows)。而虚拟机可以在同一台服务器上运行不同的操作系统,提供了更高的灵活性。
总之,容器开发相较于虚拟机开发具有启动速度快、资源占用小、可移植性强等优势,但在安全性和操作系统支持方面可能存在劣势。根据具体的应用场景和需求,你可以选择最适合的技术进行开发和部署。
容器隔离的不安全,有哪些根源上的原因?
容器隔离的不安全主要源于它们与宿主机共享操作系统内核以及隔离技术相对于虚拟机的不足。以下是导致容器隔离不安全的一些根源原因:
-
共享内核:容器与宿主机共享操作系统内核,这意味着容器中的进程可以直接访问内核资源和系统调用。如果容器中的应用程序存在漏洞或被攻击者利用,可能会影响到整个宿主机和其他容器。而虚拟机提供了完全独立的操作系统和内核,因此具有更强的隔离性。
-
Namespaces隔离不足:容器使用namespaces技术来隔离进程、文件系统、网络等资源。然而,namespaces并没有提供完全的隔离,一些资源仍然可以在不同的namespaces之间共享。例如,PID namespaces允许容器中的进程访问宿主机上的其他进程,这可能导致潜在的安全风险。
-
Cgroups资源限制不足:容器使用cgroups技术来限制和隔离资源使用,如CPU、内存、磁盘IO等。然而,cgroups并没有完全隔离这些资源,容器中的恶意程序仍然可能通过资源竞争或其他手段影响宿主机和其他容器的性能。
-
容器权限管理:通常,容器中的进程以root用户身份运行,这意味着它们具有较高的权限,可能会影响到宿主机和其他容器。虽然可以通过用户namespaces技术来限制容器进程的权限,但这可能导致兼容性和性能问题。
-
容器镜像安全性:容器镜像可能包含未知的漏洞或恶意代码,这可能导致容器运行时的安全风险。虽然可以通过镜像扫描、签名等技术来确保镜像的安全性,但这需要额外的管理和维护工作。
总之,容器隔离的不安全主要源于共享内核、隔离技术不足以及权限管理等问题。为了提高容器的安全性,需要采取一系列措施,如使用安全的镜像、限制容器权限、加强隔离技术等。同时,在某些安全要求较高的场景下,虚拟机可能是更合适的选择。