您现在的位置是:首页 >技术杂谈 >传统架构和k8s架构:如何在实际应用中进行选择和搭配?网站首页技术杂谈

传统架构和k8s架构:如何在实际应用中进行选择和搭配?

漠效 2023-05-13 08:00:04
简介传统架构和k8s架构:如何在实际应用中进行选择和搭配?



前言



在如今的互联网时代,传统的架构和部署方式可能已经无法满足不断发展和创新的业务需求。为了更好地提高系统的可靠性、灵活性和可维护性,许多企业开始采用k8s这样的容器编排工具来进行应用程序的部署和管理。但是传统架构真的不可取吗?k8s的优势是哪些?在这篇文章中,我们会深入探讨传统架构和 k8s 架构之间的区别以及如何在实际应用中合理选择,帮助您更好的应对具体的需求。



选了几个标题名,都很好,不忍舍弃,按照小说简介的写法,因此该文章别名又叫:
探讨传统架构和 k8s 架构的优劣与取舍
传统架构 vs.k8s:谁更适合您的业务需求?
论传统架构和k8s架构的对比:如何在实际应用中选择?
选择适合自己的架构:传统架构和Kubernetes该如何取舍?
传统架构 vs k8s架构:哪一个更适合您的业务?——权衡成本、效率和可靠性



什么是传统的架构?



就我个人而言,我自己认为的传统的架构是服务直接运行于单个或多台服务器或虚拟机上,由单独部署的web,中间件和数据库 等互相关联而构成的一套架构,细分开来能分为 web架构,cicd上线架构,日志收集架构,安全架构等,统合起来就构成了整套的系统架构。简单来说就是,我把以传统的方式进行部署的非k8s方式的架构,称为了传统架构。

为了避免可能出错,我专门查了微服务,sprintboot这几个常说的架构的定义。

非k8s架构可以称之为传统架构,非 k8s 架构通常指的是传统方式的部署架构,即使用虚拟机或物理机等传统方式来对应用进行部署和管理。而 k8s 则是一种现代化的容器编排平台,可以更加高效地管理和运行容器化的应用。因此,非 k8s 架构可以被称为传统架构
微服务和SpringBoot是现代化的应用程序开发技术,不属于传统架构。微服务架构是一种将应用程序拆分成多个小型服务的方法,每个服务都有自己的独立部署、扩展和管理。SpringBoot是一个基于Spring框架的快速开发框架,可以帮助开发人员更快地创建和部署应用程序。
虽然微服务和 Spring Boot 等现代化技术可以与 Kubernetes 和其他容器编排平台结合使用,但它们本身并不是传统架构的一部分。传统架构通常指的是单体应用或 monolithic 应用,这些应用通常是以传统方式在虚拟机或物理机上运行的Gx。

大致得出结论微服务和sprintboot术语上来说并不能称之为架构,严格的应该说是新型的应用程序开发技术或者说是新型框架,但是由于其又并不只是提供了新型开发方式或者框架,而是提供了整套的设计和解决方案,因此又被大量开发工程师称为了架构。实际上这和运维体系上的架构并不是一种东西,而是一种新的现代化的开发技术,并且既可以部署在传统的运维架构上(也可以说用传统的方式部署),还能和k8s等方式结合,说它是属于传统架构,新型架构或者k8s架构都不太合适。


性能瓶颈



这类架构,为了压榨载体(服务器)的性能或者说充分释放性能,在遇到性能瓶颈导致的问题时候,是要进行一些参数的调优或者说定制化的配置。

由于linux系统存在着不同的版本,并且不同版本可能运行是不同的内核,因此有部分内核参数调优的参数在不同版本允许设置的范围不同,指望一次性调优达到最优效果几乎是不可能的。所谓最优的效果是在之后的生产中,不会碰到内核方面导致的异常。如果是一直碰不到内核问题,要么是业务没有达到触碰到系统或服务器瓶颈的水平,要么是真的优化的很好。
由于云服务器或者openstack虚拟机,是在实体机上通过虚拟化技术产生的,其需要共享与其他云服务器或虚拟机相同的物理资源,如CPU、内存和网络等,并且由于虚拟化本身的开销,导致在性能方面略逊于实体机,性能的天花板天然低于实体机,因此在云服务器和虚拟机更容易碰到瓶颈或者内核方面的问题,但是由于其易扩展的特性,弥补了它的这一缺点,通过监控,组件或脚本在快要触碰到瓶颈前及时扩展。



调优



# Centos7内核参数调优

cat >> /etc/sysctl.conf << EOF
#net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0

kernel.sysrq = 0
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296

#net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_max_tw_buckets = 10000
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304

net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 65535

net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
#net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 0
#net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000
#net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
#net.ipv4.ip_local_port_range = 25000 65535
net.ipv4.ip_local_port_range = 1024 65500


kernel.sem = 250 32000 100 128
#以下两个参数,如果之后系统要设置limit,从limit设置即可,避免冲突
#fs.aio-max-nr = 1048576
#fs.file-max = 6815744
#一个较高的值可能会导致较差的系统性能,而一个较低的值则可能会增加内存使用率,实际上使用默认值60即可或者不需要设置
#vm.swappiness = 0
EOF
sysctl -p


#limit,最大文件打开数设置
#其中 * 表示对所有用户生效。soft 和 hard 分别表示软限制和硬限制。nofile 表示文件句柄数,因此 * soft nofile 102400 和 * hard nofile 102400 表示软限制和硬限制均为 102400。同理,nproc 表示进程数,因此 * soft nproc 102400 和 * hard nproc 102400 表示软限制和硬限制均为 102400。Gx
echo "ulimit -SHn 102400" >> /etc/rc.local
cat >> /etc/security/limits.conf << EOF
*           soft   nofile       102400
*           hard   nofile       102400
*           soft   nproc        102400
*           hard   nproc        102400
EOF
详细说明

net.ipv4.ip_forward
默认值:0
建议值:0或1,具体取决于系统是否需要作为路由器来传输IP数据包。
理论依据:该参数控制Linux内核是否转发收到的IPv4数据包。如果设置为1,则内核会将数据包转发到其他网络,否则它只会处理本地目标地址的数据包。如果是k8s或者是web服务通常还建议设置为1

net.ipv4.conf.default.rp_filter
默认值:1
建议值:1,在默认情况下不需要更改此参数。
理论依据:该参数指定内核是否应该检查发往接口的入站数据包的源地址是否属于连接到该接口的子网。如果启用了反向路径过滤,则内核会拒绝这样的数据包,并且该功能可以防止某些网络攻击。

net.ipv4.conf.default.accept_source_route
默认值:0
建议值:0,在默认情况下不需要更改此参数。
理论依据:该参数控制内核是否接受从源地址进行的源路由选项的IP数据包。如果启用此选项,则攻击者可以通过在数据包中伪造路由信息来欺骗主机接受和转发数据包。Gx。因此,默认情况下,此选项应为0,以确保主机安全性。

kernel.sysrq
默认值:0
建议值:0,在默认情况下不需要更改此参数。如果启用,该功能可以允许通过按下REISUB键序列来强制重新启动主机。
理论依据:该参数控制Linux内核是否允许sysrq键调用操作。sysrq键是一种特殊的键,可以在系统死机或挂起时触发一些紧急操作。

kernel.core_uses_pid
默认值:1
建议值:1,在默认情况下不需要更改此参数。
理论依据:该参数指定内核是否在生成核心转储文件时包含PID(进程标识符)信息。启用此选项可以帮助对核心转储文件进行更深入的分析。


kernel.msgmnb
默认值:65536
建议值:较大的值,根据应用程序的需要进行调整。
理论依据:该参数指定单个消息队列的最大容量。消息队列是一种进程间通信机制,用于在进程之间传递数据。在高负载环境下,可能需要增加该参数的值以避免消息被阻塞或丢失。


kernel.msgmax
默认值:65536
建议值:较大的值,根据应用程序的需要进行调整。
理论依据:该参数指定单个消息队列中单个消息的最大容量。如果消息的大小超过了此值,则消息将被拒绝并返回错误。


kernel.shmmax
默认值:68719476736
建议值:根据应用程序的需要进行调整。
理论依据:该参数指定系统中共享内存段的最大大小。共享内存是一种特殊的进程间通信机制,它允许多个进程访问同一块物理内存。必须增加该参数的值以支持较大的共享内存段。

kernel.shmall
默认值:4294967296
建议值:根据应用程序的需要进行调整。
理论依据:该参数指定系统中共享内存段的最大数量。必须增加该参数的值以支持更多的共享内存段。


net.ipv4.tcp_max_tw_buckets
默认值:262144
建议值:10000到30000之间
理论依据:该参数指定TCP TIME-WAIT套接字的最大数量。TIME-WAIT状态是一个TCP连接关闭的过渡状态,当连接完全关闭并且在网络上没有任何延迟数据包时,该状态将被清除。在高负载环境下,可能需要增加此参数的值以防止系统中出现大量TIME-WAIT套接字。


net.ipv4.tcp_sack
默认值:1
建议值:1,在默认情况下不需要更改此参数。
最大值:3
理论依据:该参数控制是否启用TCP SACK(选择确认)。SACK允许TCP接收方通知发送方它已经成功接收了哪些数据,并且可以降低传输数据包的数量和网络延迟。


net.ipv4.tcp_window_scaling
默认值:1
建议值:1,在默认情况下不需要更改此参数。
理论依据:该参数控制是否启用TCP窗口缩放。TCP窗口缩放功能允许TCP发送方调整其接收窗口的大小,以适应网络带宽和延迟的变化。


net.ipv4.tcp_rmem
默认值:4096 87380 6291456
建议值:根据应用程序的需要进行调整。
最大值:2147483647
理论依据:该参数指定TCP接收缓冲区的最小值、默认值和最大值。TCP接收方使用接收缓冲区来存储从发送方接收到的数据。在高负载环境下,可能需要增加此参数的值以提高网络性能和吞吐量。
在Linux内核中,很多参数的最大值都是2147483647。这是因为在C语言中,signed int数据类型的大小为4字节(32位),范围从-2147483648到2147483647。由于许多内核参数的值需要使用signed int类型来表示,因此其最大值通常是2147483647。然而,并非所有内核参数的最大值都是2147483647。一些参数(如共享内存大小)可以使用unsigned long类型来表示,这种类型的值通常比signed int类型的值更大。因此,这些参数的最大值也会更高。


net.ipv4.tcp_wmem
默认值:4096 16384 4194304
建议值:根据应用程序的需要进行调整。
最大值:2147483647
理论依据:该参数指定TCP发送缓冲区的最小值、默认值和最大值。TCP发送方使用发送缓冲区来存储将要发送到接收方的数据。在高负载环境下,可能需要增加此参数的值以提高网络性能和吞吐量。

net.core.wmem_default
默认值:212992
建议值:8388608
最大值:2147483647
理论依据:该参数指定内核中所有套接字发送缓存区的默认大小。发送缓冲区用于存储将要通过网络发送的数据。增加此参数的值可提高传输速度和吞吐量。


net.core.rmem_default
默认值:212992
建议值:8388608
最大值:2147483647
理论依据:该参数指定内核中所有套接字接收缓存区的默认大小。接收缓冲区用于存储从网络接收到的数据。增加此参数的值可提高接收速度和吞吐量。


net.core.rmem_max
默认值:212992
建议值:16777216
最大值:2147483647
理论依据:该参数指定内核中所有套接字接收缓存区的最大大小。接收缓冲区用于存储从网络接收到的数据。在高负载环境下,可能需要增加此参数的值以避免丢失数据包或发生其它错误。


net.core.wmem_max
默认值:212992
建议值:16777216
最大值:2147483647
理论依据:该参数指定内核中所有套接字发送缓存区的最大大小。发送缓冲区用于存储将要通过网络发送的数据。在高负载环境下,可能需要增加此参数的值以提高传输速度和吞吐量。

net.core.netdev_max_backlog
默认值:1000
建议值:262144
最大值:2147483647
理论依据:该参数指定网络设备队列中未处理数据包的最大数量。在高负载环境下,可能需要增加此参数的值以避免数据包被丢弃。


net.core.somaxconn
默认值:128
建议值:65535
最大值:2147483647
理论依据:该参数指定系统中每个套接字监听队列的最大长度,即正在等待接受连接的客户端队列的最大长度。增加此参数的值可提高系统同时处理连接请求的能力。


net.ipv4.tcp_max_orphans
默认值:32768
建议值:3276800
最大值:2147483647
理论依据:该参数指定系统中允许TCP套接字处于孤儿状态的最大数量。套接字可能会变成孤儿状态,如果它们的父进程已经退出且没有及时处理这些套接字。增加此参数的值可以提高系统处理套接字的能力。


net.ipv4.tcp_max_syn_backlog
默认值:1024
建议值:262144
最大值:2147483647
理论依据:该参数指定系统中每个监听套接字的最大连接请求队列长度。在高负载环境下,可能需要增加此参数的值以避免连接请求被拒绝。

net.ipv4.tcp_timestamps
默认值:1
建议值:1,在默认情况下不需要更改此参数。
理论依据:该参数控制是否启用TCP时间戳功能。TCP时间戳功能允许发送方和接收方确定数据包在网络上传输的时间。


net.ipv4.tcp_syncookies
默认值:0
建议值:1
理论依据:该参数控制是否启用TCP SYN cookie保护。当服务器接收到大量伪造的TCP SYN连接请求时,可以使用SYN cookie保护机制来防止DoS攻击。


net.ipv4.tcp_synack_retries
默认值:5
建议值:1
最大值:255
理论依据:该参数指定在发送SYN-ACK响应之后尝试重新发送响应的次数。默认情况下,Linux内核将尝试发送5个SYN-ACK响应。


net.ipv4.tcp_syn_retries
默认值:5
建议值:1
最大值:255
理论依据:该参数指定在没有收到远程主机的ACK确认之前尝试重新发送SYN请求的次数。默认情况下,Linux内核将尝试发送5个SYN请求。

net.ipv4.tcp_tw_recycle
默认值:0
建议值:0,在默认情况下不需要更改此参数。
理论依据:该参数控制是否启用TCP TIME-WAIT回收机制。该机制可以使TIME-WAIT套接字更快地返回到可用状态,但可能会导致数据包丢失和其他问题。


net.ipv4.tcp_tw_reuse
默认值:0
建议值:1
最大值:1
理论依据:该参数控制是否允许重新使用TIME-WAIT套接字以减少系统中处于TIME-WAIT状态的套接字数量。启用此功能可能会增加系统处理连接请求的能力。

net.ipv4.tcp_mem
默认值:4096, 87380 或者 131071
无建议值或最大值
理论依据:该参数定义了用于TCP通信缓冲区的最小、默认和最大内存量。对于此参数,默认值为以下三个值之一,具体取决于系统内存量:4096, 87380 或者 131071。无建议值或最大值。根据系统的可用内存和TCP连接数,可以调整这些值。由于TCP缓冲区过度使用可能会导致系统性能下降,因此建议适当设置这些值。

net.ipv4.tcp_fin_timeout
默认值:60
建议值:30
最大值:65535
理论依据:该参数定义了一个TCP连接等待FIN包到达的秒数,在此之后,连接将被关闭。该参数的默认值为60秒,建议值为30秒,最大值可以设置为65535秒。较短的fin超时时间允许更快地回收资源,但也可能导致其他问题,如不必要的连接重置。

net.ipv4.tcp_keepalive_time
默认值:7200
建议值:1200
最大值:32767
理论依据:该参数定义了TCP keepalive探测包之间的时间间隔。默认情况下,此值为7200(即两小时),建议值为1200秒,最大值为32767秒。TCP keepalive用于检测空闲连接并自动关闭它们,并且此参数不应设置得太高,以防止未必要的TCP连接占用系统资源。

net.ipv4.ip_local_port_range
默认值:32768到60999
该参数没有建议值或最大值
理论依据:该参数定义了本地端口号范围,用于分配TCP和UDP连接的端口。默认情况下,此范围为:32768到60999。建议值可以根据应用程序需求而定,例如降低此参数可以减少系统启动的TCP连接数并释放更多端口资源但是常用配置为1024 65535

kernel.sem
默认值:250 32000 100 128
理论依据:该参数指定了内核中的信号量的数量和操作方式。它由四个值组成,分别对应于:semmsl、semmns、semopm和semni。默认值为250 32000 100 128。semmsl 是一次 semop 调用中允许的最大信号量数(默认值为250),semmns 是系统中允许的最大信号量数(默认值为32000),semopm 指定每次 semop 调用中最多使用的操作数(默认值为100),semni 则是系统中允许的最大信号量集合数(默认值为128)。对于大多数系统,建议值可以按照默认值设置。

vm.swappiness
默认值:60
建议值:0
最大值:100 
理论依据:该参数控制了操作系统在内存不足时使用交换空间的程度。默认值为60,建议将其设置为0以避免使用交换空间,最大值为100。Gx它是一个百分比值,表示当可用内存低于"swappiness"时,内核开始将页面交换到磁盘上的交换空间中。一个较高的值可能会导致较差的系统性能,而一个较低的值则可能会增加内存使用率。Gx

以下两个参数,如果之后要设置limit,从limit设置即可,避免冲突
fs.aio-max-nr
默认值:65536
建议值:1048576
最大值:2621440
理论依据:该参数定义了AIO(异步输入/输出)请求的最大数量。默认值为65536,建议值为1048576,最大值可以设置为2621440,在大量IO操作的情况下提高此值可以提高系统性能。

fs.file-max
默认值:10241024
最大值:40961024
理论依据:该参数限制了系统打开的文件描述符的数量。默认值为8192,但是自 CentOS 6 开始,默认值已经增加到了10241024,即1048576。建议值取决于系统的可用内存和需要打开的文件数。最大值可以设置为40961024,即4194304。


limit相关设置或者最大值问题,可参考下方链接内容的最后一部分
https://blog.csdn.net/GX_1_11_real/article/details/120549038


扩展



这个通常是在拿到环境时就写到初始化脚本并运行,然后随着业务的发展遇到问题的时候,根据遇到的坑,排查错误再来进行优化。但是即使优化的再好,对环境的优化始终是有瓶颈的,并不能超过它硬件的性能的一定范围。就像是常说的木桶原理,木桶的容量由最短的那个板子决定。同样地,服务器的性能也取决于其最慢的组件的瓶颈,而架构的瓶颈常出现在其载体(服务器,虚拟机,云服务)的性能上。

解决这种瓶颈,通常还要用另外两种方式进行扩展:

垂直反向扩展(也叫纵向扩展),升级配置,以增加更多的硬件资源来实现性能和容量的提升。增加CPU、内存、存储等硬件资源,从而使应用程序能够处理更多的请求和负载。但是,垂直方向扩展由于单个服务器或虚拟机的硬件资源是有限的,并不能无限制地扩展

水平方向扩展(横向扩展),扩充节点,通过增加应用程序所运行的服务器或虚拟机数量和应用程序的数量,来提高应用程序的性能和容量



随着云服务的兴起,这种传统的架构也逐渐和云服务开始结合,出现了混合云或者只是单纯的配合使用某些云服务,而主体还是企业自己的私有云,只是将某些服务利用公有云的服务进行了扩展。最常见的是CDN,OSS或者NFS等,不需要购买硬件,扩展了自己的性能和服务。当然还有一些企业因为成本或需求,有了更深的结合或者完全投入了云厂商,毕竟优点是有钱基本解决一切,他们可以提供并派人实施方案,很适合创业型的公司或者有想法的老板,之前有人咨询我,我对他基本也是这个建议。

虽然许多工作人员仍然使用传统的(利用服务器或虚拟机)方式来使用或者部署云服务器,仅使用云厂商提供的负载、伸缩功能、WAF等功能,这种方式虽然看起来属于是新瓶装旧酒,但是这样并不能说它是老旧的架构,应该说是一种是基于云服务的云架构。这种方案是无可指责的,无论什么架构或者方法基本上都是出于成本或需求,任何架构或组合都应该根据实际需求和成本来选择,因为每个组织的需求和预算都不尽相同。



总结



缺点:
成本高:传统的架构或者配置方式,从短期来看,成本高昂,不仅需要花钱购买或租赁硬件,还需要投入专业的人员和时间,来维护设备和网络。一般来说搞这种的都是托管到一些大型机房或自建机房(看服务器的规模)

部署和管理困难:由于服务不同,需求不同,安装的各个组件以及环境配置也会不同,对于快速的部署和统一的管理造成了困难,对工作人员应对不同环境的水平要求也高



优点:
定制化:由于传统架构通常是由企业自己建立和运营,所有控制权在企业,因此可以根据自己需求进行定制化的调整或者调整业务

安全性高:由于拥有完全的控制权,实际的数据存储和代码是处在自己服务器中,并且由自己的工作人员来维护安全。对于一些重视数据的企业(一般是拥有独有的视频、文件或用户数据的企业)来说,比放到云服务器和第三方要更安全或放心

成本可控:成本在长期来看便宜。一次投入,大致很长一段时间不用扩充。相对于使用第三方服务或云服务器生产的成本是持续性的,这个更能自己控制成本。换个说法,这2种行为就像全款买房和贷款买房



题外补充



<1>云服务器和线下机房具体成本能差多少?

一般问这个的,有可能是创业公司或者正在准备方案的人。
联系各方面进行调查和出报告是很麻烦的,属于做项目的前期准备了,如果是没入职就给跑腿比较不建议。而如果编一个数字,通常又是不严谨的。因此严谨来说,告知成本计算原理即可。



云服务器和线下机房的成本不同,主要取决于以下几个方面:


购买方式:云服务器通常是以按需付费的方式购买,而线下则需要一次性投入建设成本(也可以租赁服务器或托管机房)。因此,云服务器在开始使用时成本较低,但长期来看,线下机房可能会更划算。


运维成本:云服务器通常由云服务提供商进行运维,而线下机房则需要企业自行运维。如果企业没有足够的技术人员或无法承担高昂的运维成本,则选择云服务器可能更为合适。


规模:对于小型企业而言,使用云服务器可能更为经济实惠,因为它们不需要大规模的计算资源。而对于大型企业来说,线下机房可能更为划算,因为他们可以自己建设规模更大的机房,从而降低成本。


如果开发部门因为某些优惠或其他原因,将新业务直接部署到云上,假如这是一个不知道是否能盈利或者无法预期盈利时间的业务,没有持续大资金支持,放到云上空烧金钱,不如尽早预期一个时间,没有达到目标就下线或者迁移到租赁服务器运行


由于我之前没出过这种对比的报告,并且不知道某些服务具体的价格,只记得整体投入,而且机房不同,合作的方式不一样,价格也会有变动,只能提供基本的计算方式:


1、线下机房中部署和运行应用程序的成本如果按照固定成本和可变成本划分:

固定成本:服务器成本 安全设备成本 机房建设成本或机柜机房租用成本(租金 带宽费用 IP费用 其他服务费)
可变成本:有可能的维修费用 某些第三方服务费用

总成本 = 固定成本 + 可变成本

总成本 =  单台服务器价格X数量 + 机柜费用(付费方式:每年,每月,每季,每列,每排)X机柜数量 +  IP费用XIP数量 + 带宽费 + 人工和硬件维护费


2、云服务

由于方便扩缩容和按量付费的优点,这个基本不能按固定成本和可变成本划分,因为是实例和服务费用是随时可变的,且购买的服务越多,费用越多

基本的计算方式,只计算了服务器投入:
总成本 = (实例数量 × 按量付费单价 × 运行时间) + (实例数量 × 预留实例单价 × 预留实例数量)

总成本 = 虚拟机实例费用 + 存储费用 + 数据传输费用 + 其他服务费用(负载均衡、DNS解析、日志分析等)+ 技术支持费用



<2>一个未盈利或者短期内没盈利的项目,跑在云服务器上,还是自己购买服务器,哪个成本低?

从成本上看,云服务器由于提供了按需付费的模式,并且云服务提供商会提供一些管理工具和技术支持,这使得它们易于使用和维护,几乎可以随时终止,的确成本低(退款政策咨询云厂商,一般来说没使用完的资源给折现)。但是如果对项目所用的资源规模大,并且要长期维持还希望完全掌控硬件资源,则购买自己的服务器可能更划算。租用云服务器和购买自己的服务器各有优缺点,需要综合考虑多个因素,例如项目规模和需求、预算和操作成本等。



什么是k8s架构?



Kubernetes是一个开源的容器编排平台,可以自动化地部署、扩展和管理容器化应用程序。有别于传统的部署方式,k8s可以使用户可以轻松地管理复杂的分布式系统,并实现高可用性、弹性伸缩、自我修复等功能。
k8s架构就是使用了k8s这一套体系中的多种组件、工具、解决方案构成的架构。它也包括日志处理,网络架构,web架构等,但是相较于传统的架构,它更加便捷,并且减少了之前那些各种复杂的应用环境,提供了统一的环境和API,可以运行于各种系统环境,为跨平台部署提供了方便和支持,也为智能化运维或AIOPS创造了良好的生长环境。已知AIOPS、智能运维、自动化运维难点就是因为各种复杂生产环境和需求,而k8s正是解决了环境问题,并且具有自动化部署、自我修复、服务发现和负载均衡、安全和可信等功能。随着2023年AI技术的爆发,Kubernetes也将成为AIOPS领域不可或缺的一部分,AIOPS也不再遥远。

究竟是开发被AI取代的快呢?还是运维被取代的快呢?或是其他行业呢?但是如果AI不去加以节制就运用于各种领域,让它可以访问网络,访问设备,自己开发代码,自己部署,并且开放控制各个领域的设备或者物联网权限,天网或者黑客帝国还有多远呢?有人说这些条件很难都满足,但是真的很难满足吗?也许仅仅只要某些企业为了盈利,抢占市场,为了实现更多且便利的功能,做一些推动,一些调整而已?已知现代的架构基本是向分布式发展的,如果按照某些人的说法,到时候停网停电真的能把它关了吗?
对AI的恐惧,就像看见了小象群,就预计了它们长成了大象后践踏房屋,踩踏人类,这个事件也许会发生也许不会发生。但是由于要对AI进行使用,也许不能像建立保护区一样与人隔离,为什么不像驯象一样,在还在成长的时候就栓链子去束缚呢。由于忙着抢占市场造成内卷和快速迭代,但是对安全限制至今还没有统一的标准或措施,只有AI的能力产生了技术爆炸的效果。人类还在用线控制风筝,结果几个季度后只有风筝迭代成了飞碟,迭代到那一阶段,真的还能只用线控制住吗?要紧急开发对立的AI来对抗吗? 对人类最大的威胁是气候变化和环境破坏吗?应该还有没有道德的经济和没有约束的科技吧。如果毁灭到这种事情上,是人类的愚蠢还是智慧导致的呢?


性能瓶颈



尽管k8s和传统架构在技术和实现上有很大不同,但它们都会面临一些类似的性能瓶颈。
而且由于k8s容器之间要进行网络通信并访问与使用相同的存储资源,使用iptables或ipvs实现转发,网络延迟和存储性能问题变得更加重要。为了优化Kubernetes的性能,不仅需要考虑载体(服务器、虚拟机、云服务器)和还要调整容器本身的配置,还要想办法提高网络性能。其中由于pod或者说容器间的通信,依赖于conntrack链路追踪,对conntrack的优化尤为重要。

在Kubernetes中,Pod之间的网络通信是通过容器网络实现的。当Pod之间需要进行网络通信时,数据包首先会被发送到主机网卡上,然后由kube-proxy转发到目标Pod上。
如果使用的是iptables模式,则kube-proxy会将请求重定向到Service的Cluster IP地址,并启用NAT模式将源IP地址替换为节点IP地址,来实现数据包的转发。当进行大规模Pod之间的网络通信时,可能会出现Conntrack表溢出的问题,表中的连接状态变得混乱或过多,导致一些连接无法建立或丢失数据包,从而影响到网络性能和稳定性。可以通过调整内核参数(例如增大Conntrack表的大小)或使用IPVS模式来避免Conntrack问题。Gx
在使用IPVS模式时,由于IPVS是基于内核层面实现负载均衡的,因此不需要启用NAT,也就不会像iptables模式那样存在Conntrack问题。但是,如果后端Pod中使用了IPVS本身所不支持的协议和特性(例如TCP keepalive等),在进行大规模Pod之间的网络通信时,也可能会导致Conntrack表溢出的问题。因此也需要调整内核参数(例如增大Conntrack表的大小)


调优



node的调优
由于基本可以运行于各平台(云服务器,虚拟机,物理机),各系统(Centos,ubuntu,Windows,mac等)
只以Centos7为例,基本是使用本文第一份的调优,再创建一个文件放置k8s的调优参数


cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-arptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.netfilter.nf_conntrack_tcp_be_liberal=1
net.netfilter.nf_conntrack_tcp_loose=1
net.netfilter.nf_conntrack_max=3200000
net.netfilter.nf_conntrack_buckets=1600512
net.netfilter.nf_conntrack_tcp_timeout_time_wait=30

#重点参数,此处由于第一个系统调优已配置就注释掉
#net.ipv4.ip_forward = 1
#net.ipv4.tcp_syncookies = 1
#net.ipv4.tcp_timestamps=1
#net.ipv4.tcp_tw_reuse = 1
#net.ipv4.tcp_tw_recycle = 0
#net.ipv4.tcp_fin_timeout = 300
#net.ipv4.ip_local_port_range=1024 65500
#net.ipv4.tcp_fin_timeout=30
#net.ipv4.tcp_syncookies=1
EOF
sysctl -p /etc/sysctl.d/k8s.conf

#关闭透明大页
#THP是一种内存管理技术,它可以将物理页面合并成更大的页面,并在需要时进行分割。这可以减少内存碎片并提高系统性能。但是,在某些情况下,THP 可能会导致应用程序出现性能问题或者崩溃。因此,禁用 THP 功能是一种常见的优化措施。
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo never > /sys/kernel/mm/transparent_hugepage/enabled

pod的调优
使用initContainers设置内核参数更简单通用,也可要将设置的内核参数打包到一个镜像中,并使用该镜像作为容器的基础镜像,以便在启动容器时自动加载这些内核参数
pod的瓶颈主要在网络,因此大多是tcp参数和最大文件打开数



      initContainers:
      - name: setsysctl
        image: busybox
        securityContext:
          privileged: true
        command:
        - sh
        - -c
        - |
          sysctl -w net.core.somaxconn=65535
          sysctl -w net.ipv4.ip_local_port_range="1024 65535"
          sysctl -w net.ipv4.tcp_tw_reuse=1
          sysctl -w net.ipv4.tcp_fin_timeout=30
          sysctl -w net.ipv4.tcp_max_syn_backlog=10240
          sysctl -w net.core.somaxconn=10240
          sysctl -w net.ipv4.tcp_syncookies=1
          sysctl -w fs.file-max=1048576
          sysctl -w net.ipv4.tcp_rmem="4096 26214400 26214400"



详细说明

net.bridge.bridge-nf-call-arptables
默认值:0
建议值:1
理论依据:启用此参数可使网络桥接设备通过 arptables 过滤器进行数据包过滤,从而增加网络安全性。

net.bridge.bridge-nf-call-ip6tables
默认值:0
建议值:1
理论依据:启用此参数可使网络桥接设备通过 ip6tables 过滤器进行数据包过滤,从而增加网络安全性。


net.bridge.bridge-nf-call-iptables
默认值:0
建议值:1
理论依据:启用此参数可使网络桥接设备通过 iptables 过滤器进行数据包过滤,从而增加网络安全性。


net.netfilter.nf_conntrack_tcp_be_liberal
默认值:0
建议值:1
理论依据:启用此参数可以允许 nf_conntrack 对于 TCP 流量中的不规范/错误行为采取更宽松的处理方式,从而提高系统的灵活性和兼容性。

net.netfilter.nf_conntrack_tcp_loose
默认值:0
建议值:1
理论依据:启用此参数可以允许 nf_conntrack 对于 TCP 流量中的“松散”(loose)/非法行为采取更宽松的处理方式,从而提高系统的灵活性和兼容性。


net.netfilter.nf_conntrack_max
默认值:65536
建议值:262144
最大值:4194304
理论依据:该参数控制系统在内存中维护的最大 conntrack 条目数。增加此值将增加系统的负载,并可能导致内存资源不足。


net.netfilter.nf_conntrack_buckets
默认值:16384
建议值:524288
最大值:16777216
理论依据:nf_conntrack 使用哈希表来高效地管理 conntrack 条目。该参数定义了哈希表中 bucket 的数量,增加此值可以提高系统的性能,但也会增加内存消耗。

net.netfilter.nf_conntrack_tcp_timeout_time_wait
默认值:60
建议值:30
最大值:120
理论依据:此参数定义了系统在 TIME-WAIT 状态中保留 TCP 连接的秒数。减少此值可以释放系统中的资源,但可能会影响某些应用程序的行为。


net.netfilter.nf_conntrack_buckets未更新问题:
sysctl -p 命令后发现 net.netfilter.nf_conntrack_buckets 参数仍未更新,这可能是因为该参数被其他配置文件覆盖了,可以通过以下方式检查 net.netfilter.nf_conntrack_buckets 参数的值:

<1>查看这个参数的当前值
sysctl net.netfilter.nf_conntrack_buckets 


<2>搜索 /etc/sysctl.conf 和 /etc/sysctl.d/*.conf 文件中是否存在 net.netfilter.nf_conntrack_buckets 的其他配置。例如:
grep -r "net.netfilter.nf_conntrack_buckets" /etc/sysctl.conf /etc/sysctl.d/*.conf

如果找到其他定义 net.netfilter.nf_conntrack_buckets 的条目,检查它们的值,并尝试更新它们为新的值。如果同一参数在多个配置文件中具有不同的值,则最终设置的将是最后读取的值


扩展



尽管k8s可以运行于各种平台,但与传统架构一样,其性能也受到硬件资源的限制。相比传统的服务和虚拟化技术,k8s对服务器或载体的性能压榨水平更高。为了提高系统性能或解决瓶颈问题,我们仍然是采用纵向扩展和横向扩展的方法。

如果是运行于实体服务器,就扩展其硬件和服务器数量。如果是运行于云服务器或虚拟机,就扩展其虚拟硬件(更换或添加更高性能的磁盘),扩展带宽,购买CDN等网络服务或扩充节点。

近年来,由于Kubernetes的普及,各大云厂商都推出了各种工具和方案以对接Kubernetes,并提高其扩展性和易用性。然而,由于Kubernetes运行于虚拟机之上,并且用户在购买服务器时往往难以准确评估所需的硬件性能或购买错实例的型号,导致经常会遇到因为云服务器内存、磁盘、网络导致的问题或者宿主机上虚拟机资源抢占导致的问题,而需要进行实例更换或资源调整的情况。
为了解决这个问题,各家云厂商也提供了自己的Kubernetes方案,用户可以选择自建或使用云厂商提供的一键部署的Kubernetes。然而,由于使用了云厂商自己构建的环境,与普通Kubernetes环境存在某些区别,因此可能会导致新的问题,并增加了学习的难度。此外,由于不同的云厂商之间没有相对统一的标准,因此在一个云厂商的Kubernetes环境中解决的问题和处理经验,不一定适用于其他云厂商(例如各厂商不同的组件问题)。



总结



缺点:
学习难度高:k8s是一种比较复杂的系统,整套体系范围比较广,需要花费一定的时间和精力来学习和掌握。并且由于云厂商之间的竞争,产生了大量只适合自己环境的组件和大量差异化的环境,虽然某些方面来说方便了使用,但是使在运用k8s的技能树上产生了不同的分支,提高了学习成本和难度

部署成本相对较高:由于K8s是一种分布式系统,要部署很多节点,占用资源,相比于简单的架构维护成本可能会比较高。通常跑k8s的服务器不要运行其他的服务,避免影响k8s的稳定。例如:觉得资源压榨不干净,k8s master 空闲,就在宿主机上面还要跑个docker-compose的服务 或者 为了节省资源运行了一套phpcms 这是在自己找事情

安全性问题:K8s中涉及到许多敏感的数据和操作,如密码、证书等。因此,在部署K8s时需要采取一些安全措施,以防止未经授权的访问和操作



优点:
可扩展性:K8s使用分布式系统的设计思想,并且可以水平扩展,因此可以轻松地处理数千个节点和容器。同时,也支持自动扩展,根据应用程序的负载情况来增加或减少资源

自我修复:K8s监控容器状态,并在容器失败时自动重启。如果发现某个节点宕机,K8s会将该节点上的容器重新调度到其他健康的节点上,从而确保应用程序的高可用性

灵活性:K8s支持多种容器运行时,包括Docker、Containerd,同时也支持不同的存储和网络方案。这使得用户可以按照自己的需求选择最适合的容器和存储解决方案

可靠性:K8s提供了强大的监控和日志记录功能,并且支持滚动更新、版本回退等操作,从而确保应用程序的可靠性和稳定性



题外补充



<1>k8s更适合云服务器还是实体机?

Kubernetes适用于各种部署场景,无论是在云服务器还是实体机器上都可以运行。但是,将Kubernetes部署到不同的环境中有不同的考虑因素。

对于云服务器环境,Kubernetes可以提供一些优势。云服务器通常比较易于扩展和管理,可以根据需要快速添加或删除节点,并自动管理负载均衡和存储等资源;云服务器通常具有高可用性和容错性,可以通过自动备份和故障转移来保障数据安全和系统稳定性;云服务器通常具有较好的网络连接和带宽,可以满足分布式应用程序的需要。

但是在一些特定情况下,使用实体机器来部署Kubernetes可能更加合适。例如,当预计服务并发量很大,需要更强的计算能力的情况或者在一些安全性要求较高或离线场所,使用实体机器也可能更为适合。

Kubernetes适用于各种部署场景,包括云服务器和实体机器。在选择环境时,需要考虑应用程序的实际需求,部署环境的限制,成本等,并根据实际情况选择最适合的部署方式。



<2>4-5台服务器要不要部署k8s?

如果只有4-5台服务器,部署k8s较大程度上可能没有必要。因为K8s是一种分布式系统,需要至少3个(master)节点和多个(worker)节点来运行。在建立一个可用的K8s集群时,还需要考虑高可用性、安全性、网络配置等方面的问题。虽然存在单节点K8s集群或者单个Master节点部署方式,但是由于高可用性或者安全性的考虑,并不太推荐。如果资源或成本实在有限,并且要部署,可以使用K3s,Minikube等轻量级的 Kubernetes发行版;或者使用Docker Compose等适合小型的容器应用程序。
实际上还是看具体的服务,需求和成本,选择适合的方案。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。