【运维篇】Docker使用前的体检

零、GPT解答

2、Docker的性能成本问题:CPU成本、内存成本、网络成本:
Docker的开销相对较小,因为它使用的是操作系统级别的虚拟化,不像虚拟机那样需要为每个实例分配一份操作系统。然而,每个容器都会占用一定的系统资源。

  • CPU成本:Docker容器的CPU开销通常很小。但是,如果你在一个主机上运行大量的容器,那么这些容器可能会争夺CPU资源,从而影响性能。
  • 内存成本:每个Docker容器都需要一些内存来运行。你可以使用Docker的资源限制功能来限制每个容器的内存使用,以防止它们占用太多的系统内存。
  • 网络成本:Docker容器需要一些网络带宽来与外界通信。如果你在一个主机上运行大量的网络密集型容器,那么这些容器可能会争夺网络带宽,从而影响性能。

3、Docker的性能压榨情况: CPU、RAM、TCP/UDP连接句柄数、网络流量限制:

  • CPU:可以使用Docker的CPU限制功能来限制容器对CPU的使用,这可以防止容器过度占用CPU资源。Docker还支持CPU pinning,这允许你将容器限制在特定的CPU内核上运行。
  • RAM:你可以使用Docker的内存限制功能来限制容器对内存的使用。这可以帮助防止容器过度占用内存资源,从而影响系统的其他部分。
  • TCP/UDP连接句柄数:这是由主机操作系统管理的,Docker容器会共享主机的网络堆栈,所以如果你发现连接句柄数有限制,可能需要在主机系统级别进行优化和调整。
  • 网络流量限制:可以使用Docker的网络限制功能,如设备请求和设备限制,来限制容器的网络带宽使用。

4、快速构建、部署Docker的方式: Docker有几种快速构建和部署的方法:

  • 使用Dockerfile:你可以在Dockerfile中定义你的应用程序和它的依赖,然后使用docker build命令来创建镜像。
  • 使用Docker Compose:这是一个工具,可以用来定义和运行多容器的Docker应用程序。你可以在docker-compose.yml文件中定义你的服务,然后使用docker-compose up命令来启动所有服务。
  • 使用Kubernetes:这是一个开源的容器编排平台,可以用来管理和扩展运行在容器中的应用程序。虽然学习曲线较陡,但Kubernetes提供了许多高级特性,如服务发现、负载均衡、自动滚动更新等。

一、Docker的最小系统构建的普遍方式

  • Alpine Linux——安全的、简单的、小巧(基础镜像仅5MB)的Linux发行版
  • scratch ——Docker中的一个特殊镜像,它被定义为一个空的(或最小的)基础镜像。它基本上不包含任何文件,也不包含任何操作系统层面的配置。这就意味着你无法在scratch镜像中使用像 bash,ls 等命令,因为这个镜像中并没有这些命令的二进制文件。需要注意的是,使用 scratch镜像需要你的应用能够静态编译,并且能够直接在容器中运行,而不需要依赖其他的系统库或者环境(即无需其他依赖的可执行文件,在Linux就是bin,在Windows就是exe)。这对于某些编程语言(比如Go)来说很容易做到,但对于其他的一些语言则可能比较困难。

总结

  • 如果需要使用构建最小系统,单单运行二进制文件,那么可以使用 scratch
  • 如果你是需要其他依赖的,比如jre、npm等外部依赖环境,还是使用现有编译好的父镜像来创建的自己的镜像,如openjdk、node、alpine linux、ubuntu、Debian。具体见 https://hub.docker.com

二、Docker的性能成本问题:CPU成本、内存成本、网络成本

Docker的开销相对较小,因为它使用的是操作系统级别的虚拟化,不像虚拟机那样需要为每个实例分配一份操作系统。然而,每个容器都会占用一定的系统资源。

  • CPU成本:Docker容器的CPU开销通常很小。但是,如果你在一个主机上运行大量的容器,那么这些容器可能会争夺CPU资源,从而影响性能。
  • 内存成本:每个Docker容器都需要一些内存来运行。你可以使用Docker的资源限制功能来限制每个容器的内存使用,以防止它们占用太多的系统内存。
  • 网络成本:Docker容器需要一些网络带宽来与外界通信。如果你在一个主机上运行大量的网络密集型容器,那么这些容器可能会争夺网络带宽,从而影响性能。

三、Docker的性能压榨情况: CPU、RAM、TCP/UDP连接句柄数、网络流量限制

默认情况下,Docker不会对容器的CPU、内存和网络带宽使用做硬性限制。如果不设置限制,一个容器可以使用宿主机上可用的所有资源。然而,由于Docker使用了Linux内核的CGroups和Namespaces,这意味着每个容器都会在一个被隔离的环境中运行,从而在一定程度上避免了资源的争夺。

  • CGroups(ControlGroups)是Linux内核中的一个功能,用于管理和限制进程组的资源使用。它允许管理员将一组进程放在一个cgroup中,并为该组分配特定的资源,例如CPU、内存、磁盘IO等。通过CGroups,管理员可以对不同的进程组设置不同的资源限制,从而实现资源的隔离和控制。
  • Namespace是Linux内核提供的另一个功能,用于创建隔离的运行环境。通过使用Namespace,可以隔离进程的文件系统视图、网络栈、用户ID、进程ID等。每个Namespace中的进程只能看到自己所属的Namespace的内容,从而实现了进程之间的隔离。
  • Docker利用Linux内核的CGroups和Namespace技术来构建容器。通过使用CGroups,Docker可以对容器中的资源进行限制,避免不同容器之间的资源争夺。例如,可以限制每个容器使用的CPU时间片、内存大小等。通过使用Namespace,Docker可以为每个容器提供独立的运行环境,使得容器中的进程无法看到宿主机或其他容器的进程和资源。

尽管Docker不会默认限制这些资源,但你可以在启动容器时手动设置这些限制:

  • 对于CPU,可以使用–cpus参数来限制容器可以使用的CPU核心数,或者使用–cpu-shares参数来在多个容器之间分配CPU时间片。
  • 对于内存,可以使用-m或–memory参数来设置容器可以使用的最大内存量。
  • 对于网络带宽,Docker本身并不提供直接的限制方式,但你可以使用tc工具来设置网络带宽的限制。

默认情况下,Docker容器内的TCP/UDP连接的句柄数没有额外的限制,其上限主要取决于宿主机的系统级别设置。
在Linux系统中,TCP/UDP句柄数限制主要受两个因素影响:文件描述符限制和系统范围的网络连接数限制

  1. 文件描述符限制:这是对每个进程打开的文件描述符数量的限制,包括网络套接字。在容器内部,这个值可以通过ulimit命令查看或更改,通常其默认值从宿主机继承。
  2. 系统范围的网络连接数限制:Linux系统还会对整个系统范围内的总网络连接数有一定限制。这个限制是由内核参数net.ipv4.netfilter.ip_conntrack_max等控制的。

所以,如果你在容器中遇到句柄数达到上限的情况,需要同时检查并可能调整这两个地方的设置。如果需要更高的并发连接数,可以考虑提高宿主机和容器的这两个限制。需要注意的是,这些设置可能会对系统的稳定性和性能有影响,因此在调整时需要谨慎,并根据实际情况进行测试。

总结

  1. Docker容器默认不限制CPU、Memory、网络带宽,由于其使用了Linux内核的Cgroups和Namespace技术,故一定程度上隔离了容器间的资源争夺;
  2. 对于特定的需求,你可以自定义容器的资源占用限制,命令如下所示:
docker run --cpus CPU核数 --memory 2GB(最大内存使用量) imageName args....
  1. 对于网络的限制,你可以使用Linux自带的工具类 TC,具体使用方法见 man tc。。
  2. 默认情况下,Docker容器内的TCP/UDP连接的句柄数没有额外的限制,其上限主要取决于宿主机的系统级别设置。想要提高系统并发性能,参考如下配置:

Linux操作系统内核参数

# 系统全局允许分配的最大文件句柄数。 提高这个值可以允许系统同时打开更多的文件和网络连接。
# 2 millions system-wide
sudo sysctl -w fs.file-max=2097152
sudo sysctl -w fs.nr_open=2097152
sudo echo 2097152 > /proc/sys/fs/nr_open

# 允许当前会话 / 进程打开文件句柄数: 提高这个值可以让单个进程同时打开更多的文件或网络连接。
ulimit -n 1048576

 # 持久化 'fs.file-max' 设置到 /etc/sysctl.conf 文件:
 fs.file-max = 1048576
 # /etc/systemd/system.conf 设置服务最大文件句柄数:
 DefaultLimitNOFILE=1048576
 
# /etc/security/limits.conf 持久化设置允许用户 / 进程打开文件句柄数:
*      soft   nofile      1048576
*      hard   nofile      1048576

TCP 协议栈网络参数

# 并发连接 backlog 设置:
# 设置系统监听队列的最大长度。这是等待接受的连接可以排队的最大数量。提高此值可以增加服务器接受新连接的能力。
sudo sysctl -w net.core.somaxconn=32768 
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=16384
sudo sysctl -w net.core.netdev_max_backlog=16384

# 可用知名端口范围:
sudo sysctl -w net.ipv4.ip_local_port_range='1000 65535'

# TCP Socket 读写 Buffer 设置:
sudo sysctl -w net.core.rmem_default=262144
sudo sysctl -w net.core.wmem_default=262144
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
sudo sysctl -w net.core.optmem_max=16777216
    
#sysctl -w net.ipv4.tcp_mem='16777216 16777216 16777216'
sudo sysctl -w net.ipv4.tcp_rmem='1024 4096 16777216'
sudo sysctl -w net.ipv4.tcp_wmem='1024 4096 16777216'

# TCP 连接追踪设置:
sudo sysctl -w net.nf_conntrack_max=1000000
sudo sysctl -w net.netfilter.nf_conntrack_max=1000000
sudo sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30

# TIME-WAIT Socket 最大数量、回收与重用设置:
sudo sysctl -w net.ipv4.tcp_max_tw_buckets=1048576
    
# 注意:不建议开启該设置,NAT 模式下可能引起连接 RST
# sysctl -w net.ipv4.tcp_tw_recycle=1
# sysctl -w net.ipv4.tcp_tw_reuse=1

# FIN-WAIT-2 Socket 超时设置:
sudo sysctl -w net.ipv4.tcp_fin_timeout=15

四、快速构建、部署Docker的方式

Docker有几种快速构建和部署的方法:

  • 使用Dockerfile:你可以在Dockerfile中定义你的应用程序和它的依赖,然后使用docker build命令来创建镜像。
  • 使用Docker Compose:这是一个工具,可以用来定义和运行多容器的Docker应用程序。你可以在docker-compose.yml文件中定义你的服务,然后使用docker-compose up命令来启动所有服务。
  • 使用Kubernetes:这是一个开源的容器编排平台,可以用来管理和扩展运行在容器中的应用程序。虽然学习曲线较陡,但Kubernetes提供了许多高级特性,如服务发现、负载均衡、自动滚动更新等。
  • 使用可视化容器管理——portainer.io,编排容器更加方便简洁,同时本身支持容器化部署

五、 掌握Java开发时,如何快速构建Docker镜像的方式

引入pom plugin,具体代码参考如下所示:

<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>${docker.maven.plugin.version}</version>
    <executions>
        <!--如果想在项目打包时构建镜像添加-->
        <execution>
            <id>build-image</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- Docker 远程管理地址-->
        <dockerHost>${docker.host}</dockerHost>
        <images>
            <image>
                <!--定义镜像名称-->
                <name>${project.name}:${project.version}</name>
                <!--定义镜像构建行为-->
                <build>
                    <!--定义基础镜像-->
                    <from>java:8</from>
                    <args>
                        <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
                    </args>
                    <!--定义哪些文件拷贝到容器中-->
                    <assembly>
                        <!--定义拷贝到容器的目录-->
                        <targetDir>/</targetDir>
                        <!--只拷贝生成的jar包-->
                        <descriptorRef>artifact</descriptorRef>
                    </assembly>
                    <!--定义容器启动命令-->
                    <entryPoint>["java", "-jar","-Dspring.profiles.active=prod","/${project.build.finalName}.jar"]</entryPoint>
                    <!--定义维护者-->
                    <maintainer>KrisYu</maintainer>
                </build>
            </image>
        </images>
    </configuration>
</plugin>

具体命令细节,见官方提供的配置手册

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值