<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/rss.xsl" type="text/xsl"?>
<rss version="2.0">
  <channel>
    <title>IT瘾linux推荐</title>
    <link>https://itindex.net/tags/linux</link>
    <description>IT社区推荐资讯 - ITIndex.net</description>
    <language>zh</language>
    <copyright>https://itindex.net/</copyright>
    <generator>https://itindex.net/</generator>
    <docs>http://backend.userland.com/rss</docs>
    <image>
      <url>https://itindex.net/images/logo.gif</url>
      <title>IT社区推荐资讯 - ITIndex.net</title>
      <link>https://itindex.net/tags/linux</link>
    </image>
    <item>
      <title>聊聊容器网络和 iptables</title>
      <link>https://itindex.net/detail/62542-%E5%AE%B9%E5%99%A8-%E7%BD%91%E7%BB%9C-iptables</link>
      <description>&lt;p&gt;大家好，我是张晋涛。&lt;/p&gt;
 &lt;p&gt;上周有小伙伴在群里问到 Docker 和 Iptables 的关系，这里来具体聊聊。&lt;/p&gt;
 &lt;p&gt;Docker 能为我们提供很强大和灵活的网络能力，很大程度上要归功于与 iptables 的结合。在使用时，你可能没有太关注到 iptables 的作用，这是因为 Docker 已经帮我们自动完成了相关的配置。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ dockerd --help |grep iptables
--iptables Enable addition of iptables rules (default true)
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;docker daemon 有个   &lt;code&gt;--iptables&lt;/code&gt; 的参数，便是用来控制是否要自动启用 iptables 规则的，默认已经设置成了开启（true）。所以通常我们不会过于关注到它的工作。&lt;/p&gt;
 &lt;p&gt;本文中，为了避免环境的干扰，我将使用 docker in docker 的环境来进行介绍，可通过如下方式启动该环境：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker run --rm -d --privileged docker:dind
f323aef7b532ba6d575ca6f9444a08f1a55f2447afec2e853954694c034e6ae0
&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;iptables 基础&lt;/h2&gt;
 &lt;p&gt;  &lt;code&gt;iptables&lt;/code&gt; 是一个用于配置 Linux 内核防火墙的工具，可用于检测、修改转发、重定向以及丢弃 IPv4 数据包。它使用了内核的 ip_tables 的功能，所以需要 Linux 2.4+ 版本的内核。&lt;/p&gt;
 &lt;p&gt;同时，iptables 为了便于管理，所以按照不同的目的组织了多张   &lt;strong&gt;表&lt;/strong&gt; ；每张表中又包含了很多预定义的   &lt;strong&gt;链&lt;/strong&gt;；每个链中包含着顺序遍历的   &lt;strong&gt;规则&lt;/strong&gt;；这些规则中又定义了动作的匹配规则和   &lt;strong&gt;目标&lt;/strong&gt;。&lt;/p&gt;
 &lt;p&gt;对于用户而言，我们通常需要交互的就是   &lt;strong&gt;链&lt;/strong&gt;和   &lt;strong&gt;规则&lt;/strong&gt;了。&lt;/p&gt;
 &lt;p&gt;理解 iptables 的主要工作流程有一张比较经典的图：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="img/tables_traverse.jpg" src="https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;em&gt;图片来源：    &lt;a href="https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg"&gt;https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
 &lt;p&gt;上面的小写字母是   &lt;strong&gt;表&lt;/strong&gt;，大写字母则表示   &lt;strong&gt;链&lt;/strong&gt;，从任何网络端口 进来的每一个 IP 数据包都要从上到下的穿过这张图。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;引用自    &lt;a href="https://wiki.archlinux.org/index.php/Iptables"&gt;ArchWiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;不过这不是本篇的重点，所以就不展开了。如果大家对 iptables 的内容感兴趣也欢迎留言，后续可以写一篇完整的。&lt;/p&gt;
 &lt;h2&gt;Docker 网络与 iptables&lt;/h2&gt;
 &lt;p&gt;接下来我们直接看看 Docker 在开启和关闭 iptables 时，具体有什么区别。&lt;/p&gt;
 &lt;h3&gt;关闭 Docker 的 iptables 支持&lt;/h3&gt;
 &lt;p&gt;在本文开头已经为你介绍过 docker daemon 存在一个   &lt;code&gt;--iptables&lt;/code&gt; 的参数，用于控制是否使用 iptables 。我们使用以下命令启动一个 docker daemon 并关闭 iptables 支持。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker run --rm -d --privileged docker:dind dockerd --iptables=false
7135a54c913af5e9ce69a45a0819475503ea9e3c5c673d62d9d38f0f0896179d
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;进入此容器，并查看其所有 iptables 规则：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker exec -it $(docker ps -ql) sh
/ # iptables-save
# Generated by iptables-save v1.8.8 on Mon Dec 12 01:46:38 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2:80]
COMMIT
# Completed on Mon Dec 12 01:46:38 2022
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;可以看到，当 docker daemon 加了   &lt;code&gt;--iptables=false&lt;/code&gt; 的参数时，默认没有任何规则的输出。&lt;/p&gt;
 &lt;h3&gt;开启 Docker 的 iptables 支持&lt;/h3&gt;
 &lt;p&gt;使用以下命令启动一个 docker daemon，这里没有显式的传递   &lt;code&gt;--iptables&lt;/code&gt; 选项，因为默认就是   &lt;code&gt;true&lt;/code&gt; 。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker run --rm -d --privileged docker:dind
c464c5c08ecdf9129afbf217c6462236089fe0a1d11dfe7700c2985a04d8d216
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查看其 iptables 规则：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker exec -it $(docker ps -ql) sh
/ # iptables-save
# Generated by iptables-save v1.8.8 on Mon Dec 12 14:48:16 2022
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [1:40]
:POSTROUTING ACCEPT [1:40]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.18.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
COMMIT
# Completed on Mon Dec 12 14:48:16 2022
# Generated by iptables-save v1.8.8 on Mon Dec 12 14:48:16 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2:80]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Mon Dec 12 14:48:16 2022
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;可以看到，它比刚才关闭 iptables 支持时多了几条链：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;DOCKER&lt;/li&gt;
  &lt;li&gt;DOCKER-ISOLATION-STAGE-1&lt;/li&gt;
  &lt;li&gt;DOCKER-ISOLATION-STAGE-2&lt;/li&gt;
  &lt;li&gt;DOCKER-USER&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;以及增加了一些转发规则，以下将具体介绍。&lt;/p&gt;
 &lt;h3&gt;DOCKER-USER 链&lt;/h3&gt;
 &lt;p&gt;在上述新增的几条链中，我们先来看最先生效的 DOCKER-USER 。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;*filter
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
...
-A DOCKER-USER -j RETURN
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;以上规则是在 filter 表中生效的：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;第一条是    &lt;code&gt;-A FORWARD -j DOCKER-USER&lt;/code&gt; 这表示流量进入 FORWARD 链后，直接进入到 DOCKER-USER 链；&lt;/li&gt;
  &lt;li&gt;最后一条    &lt;code&gt;-A DOCKER-USER -j RETURN&lt;/code&gt; 这表示流量进入 DOCKER-USER 链处理后，（如果无其他处理）可以再 RETURN 回原先的链，进行后续规则的匹配。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;这其实是 Docker 预留的一个链，供用户来自行配置的一些额外的规则的。&lt;/p&gt;
 &lt;p&gt;Docker 默认的路由规则是允许所有客户端访问的，   &lt;strong&gt;如果你的 Docker 运行在公网，或者你希望避免 Docker 中容器被局域网内的其他客户端访问，那么你需要在这里添加一条规则&lt;/strong&gt;。
比如, 你仅仅允许 100.84.94.62 访问，但是要拒绝其他客户端访问：&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;iptables -I DOCKER-USER -i &amp;lt;net interface&amp;gt; ! -s 100.84.94.62 -j DROP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;此外，Docker 在重启之类的操作时候，会进行 iptables 相关规则的清理和重建，但是 DOCKER-USER 链中的规则可以持久化，不受影响。&lt;/p&gt;
 &lt;p&gt;具体的实现均在   &lt;code&gt;docker/libnetwork&lt;/code&gt; 下，以下是关于   &lt;code&gt;DOCKER-USER&lt;/code&gt; 链的相关代码：&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;const userChain = &amp;quot;DOCKER-USER&amp;quot;
func arrangeUserFilterRule() {
if ctrl == nil || !ctrl.iptablesEnabled() {
return
}
iptable := iptables.GetIptable(iptables.IPv4)
_, err := iptable.NewChain(userChain, iptables.Filter, false)
if err != nil {
logrus.Warnf(&amp;quot;Failed to create %s chain: %v&amp;quot;, userChain, err)
return
}
if err = iptable.AddReturnRule(userChain); err != nil {
logrus.Warnf(&amp;quot;Failed to add the RETURN rule for %s: %v&amp;quot;, userChain, err)
return
}
err = iptable.EnsureJumpRule(&amp;quot;FORWARD&amp;quot;, userChain)
if err != nil {
logrus.Warnf(&amp;quot;Failed to ensure the jump rule for %s: %v&amp;quot;, userChain, err)
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;可以看到链名称是固定在代码中的，同时会创建/确保链和规则存在。&lt;/p&gt;
 &lt;h3&gt;DOCKER-ISOLATION-STAGE-1/2 链&lt;/h3&gt;
 &lt;p&gt;DOCKER-ISOLATION-STAGE-1/2 这两条链作用类似，这里一起进行介绍。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;*filter
...
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
...
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
...
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这两条链主要是分两个阶段进行了桥接网络隔离。所谓的桥接网络，通常就是指通过   &lt;code&gt;docker0&lt;/code&gt; 这个由 Docker 创建的接口的网络。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;/ # ifconfig docker0
docker0 Link encap:Ethernet HWaddr 02:42:11:31:97:0D
inet addr:172.18.0.1 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;举个例子进行说明。&lt;/p&gt;
 &lt;p&gt;首先创建一个名为   &lt;code&gt;moelove&lt;/code&gt; 的 network，并查看它的 IP 。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;➜ ~ docker network create moelove
0d3d76dcf81fcf4b9d76ab5a7dec22737b115dddd593c73b27d27f0114cec1e2
➜ ~ docker run --rm -it --network moelove alpine
/ # hostname -i
172.22.0.2
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;然后分别使用默认的 network 和使用前面创建的 network 启动容器，来 ping 上述创建的容器 IP 。&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;➜ ~ docker run --rm -it alpine ping -c1 -w2 172.22.0.2
PING 172.22.0.2 (172.22.0.2): 56 data bytes
--- 172.22.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
➜ ~ docker run --rm -it --network moelove alpine ping -c1 -w2 172.22.0.2
PING 172.22.0.2 (172.22.0.2): 56 data bytes
64 bytes from 172.22.0.2: seq=0 ttl=64 time=0.092 ms
--- 172.22.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.092/0.092/0.092 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;可以看到，如果是相同 network 的容器是可以 ping 成功的，但如果是不同 network 的容器则不能 ping 通。&lt;/p&gt;
 &lt;p&gt;DOCKER-ISOLATION-STAGE-1 会首先匹配来自桥接网络的网桥，目标是不同的接口，如果匹配到就进入 DOCKER-ISOLATION-STAGE-2，
不匹配就返回父链。&lt;/p&gt;
 &lt;p&gt;DOCKER-ISOLATION-STAGE-2 匹配目标是桥接网络的网桥，如果匹配，意味着数据包是来自于一个桥接网络的网桥，
目的地是另一个桥接网络的网桥，并将其 DROP 丢弃掉。不匹配则返回父链。&lt;/p&gt;
 &lt;p&gt;看到这里，你可能会问   &lt;strong&gt;为什么要分两个阶段进行隔离？用一条链直接隔离行不行？&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;答案是行，一条链也能隔离，Docker 很早的版本就是这样做的。&lt;/p&gt;
 &lt;p&gt;但是当时的实在超过 30 个 network 以后，就会导致 Docker 启动很慢。所以后来做了这个优化，
将这部分的复杂度从 O(N^2) 降低到 O(2N) ，Docker 就不再会出现启动慢的情况了。&lt;/p&gt;
 &lt;h3&gt;DOCKER 链&lt;/h3&gt;
 &lt;p&gt;最后我们来看看 DOCKER 链，这是 Docker 中使用最为频繁的一个链，也是规则最多的链，但它却很好理解。
通常情况下，如果不小心删掉了这个链的内容，可能会导致容器的网络出现问题，手动修复下，或者重启 Docker 均可解决。&lt;/p&gt;
 &lt;p&gt;这里我们启动一个容器，并进行端口映射，来看看会有哪些变化。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker exec -it $(docker ps -ql) sh
/ # docker run -p 6379:6379 --rm -d redis:alpine
Unable to find image &amp;apos;redis:alpine&amp;apos; locally
alpine: Pulling from library/redis
c158987b0551: Pull complete
1a990ecc86f0: Pull complete
f2520a938316: Pull complete
ae8c5b65b255: Pull complete
1f2628236ae0: Pull complete
329dd56817a5: Pull complete
Digest: sha256:518c024ec78b3074917bad2d40863e882e5297d65587e6d7c6e0b7281d9b8270
Status: Downloaded newer image for redis:alpine
6bf21bd3de78ce32617bf64a6a730c0fb50e304509a2ec3ef05ceae648334294
/ # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6bf21bd3de78 redis:alpine &amp;quot;docker-entrypoint.s…&amp;quot; 9 seconds ago Up 8 seconds 0.0.0.0:6379-&amp;gt;6379/tcp friendly_spence
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;之后再次执行   &lt;code&gt;iptables-save&lt;/code&gt; ，对比当前的结果与上次的差别：&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt; *filter
+-A DOCKER -d 172.18.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 6379 -j ACCEPT
 *nat
+-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p tcp -m tcp --dport 6379 -j MASQUERADE
+-A DOCKER ! -i docker0 -p tcp -m tcp --dport 6379 -j DNAT --to-destination 172.18.0.2:6379
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Docker 分别在   &lt;code&gt;filter&lt;/code&gt; 表和   &lt;code&gt;nat&lt;/code&gt; 表增加了规则。它的具体含义如下：&lt;/p&gt;
 &lt;p&gt;  &lt;code&gt;filter&lt;/code&gt; 表中新增的这条规则表示：在自定义的   &lt;code&gt;DOCKER&lt;/code&gt; 链中，对于目标地址是 172.18.0.2 且不是从   &lt;code&gt;docker0&lt;/code&gt; 进入的但从   &lt;code&gt;docker0&lt;/code&gt; 出去的，目标端口是 6379 的 TCP 协议则接收。&lt;/p&gt;
 &lt;p&gt;简单点来说就是放行通过   &lt;code&gt;docker0&lt;/code&gt; 流出的，目标为 172.18.0.2:6379 的 TCP 协议的流量。&lt;/p&gt;
 &lt;p&gt;  &lt;code&gt;nat&lt;/code&gt; 表中这两条规则的表示：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;为 172.18.0.2 上目标端口为 6379 的流量执行 MASQUERADE 动作（这里就简单的将它理解为 SNAT 也可以）；&lt;/li&gt;
  &lt;li&gt;在自定义的    &lt;code&gt;DOCKER&lt;/code&gt; 链中，如果入口不是    &lt;code&gt;docker0&lt;/code&gt; 并且目标端口是 6379 则进行 DNAT 动作，将目标地址转换为 172.18.0.2:6379 。简单点来说，这条规则就是为我们提供了 Docker 容器端口转发的能力，将访问主机本地 6379 端口流量的目标地址转换为 172.18.0.2:6379 。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;当然，要提供完整的访问能力，也需要和其他前面列出的其他规则共同配合才能完成。&lt;/p&gt;
 &lt;p&gt;此外，由于 Docker 中还存在多种不同的 network 驱动，在其他模式下还会有一些区别，需要注意。&lt;/p&gt;
 &lt;h2&gt;containerd 与 iptables&lt;/h2&gt;
 &lt;p&gt;随着 Kubernetes 中将 dockershim 彻底移除，已经有很多人将容器运行时切换到了 containerd，甚至有人希望把所有 Docker 环境都替换成 containerd。
但这里其实有一些需要注意的点，比如我们上述的示例，在 containerd 中实际上是无法进行端口映射（端口发布）的。&lt;/p&gt;
 &lt;p&gt;containerd 中可以通过类似上述 docker 的命令来启动相同的容器，比如：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ ctr run docker.io/library/redis:alpine redis-1
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;但它是没有   &lt;code&gt;-p&lt;/code&gt; 或者   &lt;code&gt;-P&lt;/code&gt; 参数的。所以这个端口发布的能力是 Docker 自己专门提供的。&lt;/p&gt;
 &lt;p&gt;如果确实想用这样的功能，怎么做呢？&lt;/p&gt;
 &lt;p&gt;一种方式是自己来管理 iptables 规则，但比较繁琐了。&lt;/p&gt;
 &lt;p&gt;另一种方式，推荐大家可以直接使用   &lt;a href="https://github.com/containerd/nerdctl"&gt;nerdctl&lt;/a&gt; 这是一个专为 containerd 做的，
兼容 Docker CLI 的工具。提供了很多远比默认的   &lt;code&gt;ctr&lt;/code&gt; 工具更丰富的能力。&lt;/p&gt;
 &lt;p&gt;比如可以这样：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ nerdctl run -d --name redis-1 -p 6379:6379 redis:alpine
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;获取其 IP 是 192.168.40.9， 然后检查 iptables 的规则：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ iptables -t nat -L | grep &amp;apos;192.168.40.9&amp;apos;
CNI-66888846605aa0cf860a0834 all -- 192.168.40.9 anywhere
DNAT tcp -- anywhere anywhere tcp dpt:redis to:192.168.40.9:6379
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;发现有类似的规则，让它可以正常访问。&lt;/p&gt;
 &lt;h2&gt;总结&lt;/h2&gt;
 &lt;p&gt;本篇从 Docker 与 iptables 的关系将其，分别剖析了 Docker 启动后会创建的 iptables 规则及其含义。并通过示例介绍了 Docker 端口映射的实际原理，
以及如何利用 nerdctl 配合使用 containerd 进行端口映射。&lt;/p&gt;
 &lt;p&gt;容器的网络内容比较多，不过原理都是相通的，在 Kubernetes 中也包含了类似的内容。&lt;/p&gt;
 &lt;p&gt;好了，以上就是本篇的内容。&lt;/p&gt;
 &lt;p&gt;欢迎大家在评论区留言讨论，也请点赞再看，谢谢。&lt;/p&gt;
 &lt;hr&gt;&lt;/hr&gt;
 &lt;p&gt;欢迎订阅我的文章公众号【MoeLove】&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="TheMoeLove" src="https://gitee.com/tlrr/awesome/raw/master/2020-9-9/1599632564572-mp-qrcode.png"&gt;&lt;/img&gt;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>post Linux Docker Kubernetes</category>
      <guid isPermaLink="true">https://itindex.net/detail/62542-%E5%AE%B9%E5%99%A8-%E7%BD%91%E7%BB%9C-iptables</guid>
      <pubDate>Mon, 12 Dec 2022 00:04:54 CST</pubDate>
    </item>
    <item>
      <title>Linux主机性能测试方法</title>
      <link>https://itindex.net/detail/62452-linux-%E4%B8%BB%E6%9C%BA-%E6%80%A7%E8%83%BD</link>
      <description>&lt;h2&gt;背景&lt;/h2&gt; &lt;p&gt;最近打算用躺家吃灰的树莓派4B搭一个NAS，用来快捷方便地访问和备份一些资源。由于备选的硬件（芯片、硬盘、网线、路由器等）和软件（内网穿透技术）的技术选型比较多，这时候就需要有一个能简单评估服务性能的方法。因此简单搜寻了一下常见方案，方便在技术选型时有个统一的对比标准，并且对一些常见指标能在数量级上有一些感性的理解。&lt;/p&gt; &lt;h2&gt;硬盘&lt;/h2&gt; &lt;p&gt;对于硬盘的读写速度测试，首先我们需要注意根据读写的实现细节不同，测试出的结果会有很大的差别。例如对于读来说，是否走缓存读、缓存的大小如何；对于写来说，是否只写缓存、是否同步等待刷盘、刷盘的时机如何，等等。&lt;/p&gt; &lt;p&gt;在实际测试的时候一定要明确自己使用的是哪种IO模式，否则就会得到一些似是而非的结论。&lt;/p&gt; &lt;h3&gt;设备查询&lt;/h3&gt; &lt;p&gt;在测试硬盘前，我们首先得知道我们有哪些硬盘、分别对应哪些分区。用   &lt;code&gt;lsblk&lt;/code&gt; （list block）命令可以查看当前机器下挂载的块设备：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    1 29.3G  0 disk
└─sda1        8:1    1 29.3G  0 part /media/pi/5615-BDE2
mmcblk0     179:0    0 59.5G  0 disk
├─mmcblk0p1 179:1    0  256M  0 part /boot
└─mmcblk0p2 179:2    0 59.2G  0 part /&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;可以看到，这里的 sda (SATA device a) 表示我外部插入的一个U盘；mmcblk0 (Multimedia card block 0) 表示树莓派自带的一张 SD 卡。这两个类型是 disk，也就是实体磁盘。&lt;/p&gt; &lt;p&gt;每个 disk 会被分成多个 partition，也就是这里的 sda1 和 mmcblk0p1、mmcblk0p2。每个 partition 又会 mount 到不同的文件夹下，用于在文件系统中进行访问。因此对于文件系统本身来说，我们只会关心到 partition 层面。&lt;/p&gt; &lt;p&gt;通过   &lt;code&gt;df&lt;/code&gt; 命令我们也能直接观察到所有分区的挂载情况：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        59G   11G   46G  19% /
devtmpfs        3.5G     0  3.5G   0% /dev
tmpfs           3.7G     0  3.7G   0% /dev/shm
tmpfs           3.7G   65M  3.6G   2% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           3.7G     0  3.7G   0% /sys/fs/cgroup
/dev/mmcblk0p1  253M   32M  221M  13% /boot
tmpfs           738M  4.0K  738M   1% /run/user/1000
/dev/sda1        30G   23M   30G   1% /media/pi/5615-BDE2&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;同时，disk 和 partition 的详细信息也可以通过   &lt;code&gt;fdisk&lt;/code&gt; 命令查看：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo fdisk -l
Disk /dev/mmcblk0: 59.5 GiB, 63864569856 bytes, 124735488 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x140cee6b

Device         Boot  Start       End   Sectors  Size Id Type
/dev/mmcblk0p1        8192    532479    524288  256M  c W95 FAT32 (LBA)
/dev/mmcblk0p2      532480 124735487 124203008 59.2G 83 Linux


Disk /dev/sda: 29.3 GiB, 31457280000 bytes, 61440000 sectors
Disk model: ProductCode
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xf3203eea

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        2048 61439999 61437952 29.3G  7 HPFS/NTFS/exFAT&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;总之，在这里我们只需要搞清楚我们想测试的磁盘和分区分别是哪个即可。&lt;/p&gt; &lt;h3&gt;hdparm&lt;/h3&gt; &lt;p&gt;对于读性能测试，我们一般可以用   &lt;a href="https://sourceforge.net/projects/hdparm/"&gt;hdparm&lt;/a&gt; 工具（hard disk parameter? hardware device parameter?）。Debian下直接 apt 安装即可：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo apt install hdparm -y&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;hdparm目前只支持磁盘读性能测试，提供了三种方式进行测试：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;直接读内存：    &lt;code&gt;sudo hdparm -T [device]&lt;/code&gt; 。&lt;/li&gt;  &lt;li&gt;带buffer读磁盘：    &lt;code&gt;sudo hdparm -t [device]&lt;/code&gt; 。&lt;/li&gt;  &lt;li&gt;不带buffer读磁盘:    &lt;code&gt;sudo hdparm -t --direct [device]&lt;/code&gt; 。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;以我的 mmcblk0 设备为例，跑出来结果分别如下（当然，每次测试建议跑多次取平均值，这里偷个懒）：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo hdparm -T /dev/mmcblk0

/dev/mmcblk0:
 Timing cached reads:   1840 MB in  2.00 seconds = 921.43 MB/sec
 
$ sudo hdparm -t /dev/mmcblk0

/dev/mmcblk0:
 Timing buffered disk reads: 130 MB in  3.04 seconds =  42.74 MB/sec
 
$ sudo hdparm -t --direct /dev/mmcblk0

/dev/mmcblk0:
 Timing O_DIRECT disk reads: 124 MB in  3.01 seconds =  41.17 MB/sec
 &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;显然，走内存读是飞快，不过对于测试磁盘性能来说没有任何意义；不带buffer看起来比带buffer要慢一点点，差别不太大；考虑到现实场景中大多数都是带buffer的读，因此我们在比较时用带buffer读的结果来进行参考即可。&lt;/p&gt; &lt;h3&gt;dd&lt;/h3&gt; &lt;p&gt;dd (data definition? data duplicator?) 是进行磁盘操作、文件生成之类的常用工具。在 gnu 的 coreutils 下，类 Unix 发行版几乎都自带。&lt;/p&gt; &lt;h4&gt;写性能&lt;/h4&gt; &lt;p&gt;一般我们会用 dd 来进行磁盘写性能测试，一般来说也有三种方式：&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;直接写内存：    &lt;code&gt;dd bs=1M count=256 if=/dev/zero of=test&lt;/code&gt; 。&lt;/li&gt;  &lt;li&gt;使用内存做缓存写完后一次性刷盘：   &lt;code&gt;dd bs=1M count=256 if=/dev/zero of=test conv=fdatasync&lt;/code&gt;。&lt;/li&gt;  &lt;li&gt;使用内存做缓存，每写完一部分就刷一次盘：   &lt;code&gt;dd bs=1M count=256 if=/dev/zero of=test oflag=dsync&lt;/code&gt;。&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;还是以我的 mmcblk0 设备为例（当前目录即挂载的 mmcblk0 设备），跑出来结果分别如下（当然，每次测试建议跑多次取平均值，这里还是偷个懒）：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ dd bs=1M count=256 if=/dev/zero of=test
256+0 records in
256+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 1.39574 s, 192 MB/s

$ dd bs=1M count=256 if=/dev/zero of=test conv=fdatasync
256+0 records in
256+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 31.739 s, 8.5 MB/s

$ dd bs=1M count=256 if=/dev/zero of=test oflag=dsync
256+0 records in
256+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 39.694 s, 6.8 MB/s

$ rm test&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;可见写内存不sync的确还是快，不过还是没啥参考意义。考虑到实际情况下大部分程序都是采用 fdatasync 的模式来写，因此我们在比较时用这个数据即可。&lt;/p&gt; &lt;h4&gt;读性能&lt;/h4&gt; &lt;p&gt;当然，有人也会利用 dd 进行读性能测试，比如：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo dd bs=1M count=256 if=/dev/mmcblk0 of=/dev/null
256+0 records in
256+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 6.03649 s, 44.5 MB/s&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;看起来很美好，结果也和 hdparm 差不多。但是当你第二次再跑这个命令的时候，由于写缓存的存在，结果会快特别多：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo dd bs=1M count=256 if=/dev/mmcblk0 of=/dev/null
256+0 records in
256+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 0.267236 s, 1.0 GB/s&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;显然这样的测试是没有意义的。考虑到这种测试方法甚至很难做到幂等，这里还是不建议用 dd 来测试读性能。&lt;/p&gt; &lt;h3&gt;小结&lt;/h3&gt; &lt;p&gt;对于磁盘读性能测试，建议使用   &lt;code&gt;sudo hdparm -t [device]&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;对于磁盘写性能测试，建议使用   &lt;code&gt;dd bs=1M count=256 if=/dev/zero of=test conv=fdatasync&lt;/code&gt;。&lt;/p&gt; &lt;h2&gt;网络&lt;/h2&gt; &lt;p&gt;网速测试一般分两种，一种是测试当前设备对普通公网设备的读写速度；另一种是点对点测试两个服务器之间的速度。&lt;/p&gt; &lt;h3&gt;speedtest&lt;/h3&gt; &lt;p&gt;speedtest 工具在各地都有测速服务器，通过命令行（speedtest-cli）或者网页（https://speedtest.cn，https://speedtest.net）都可以进行网速上下行的测试。这里以命令行为例：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo apt install speedtest-cli -y

$ speedtest-cli
Retrieving speedtest.net configuration...
Testing from China Mobile (183.192.82.69)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by Chinamobile-5G (Shanghai) [8.49 km]: 6.054 ms
Testing download speed................................................................................
Download: 128.24 Mbit/s
Testing upload speed......................................................................................................
Upload: 22.88 Mbit/s&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;虽然多次测试可能会访问到不同的测试点、导致结果有区别，不过其实也大差不差了。&lt;/p&gt; &lt;p&gt;在使用时偶尔会遇到返403，不要慌，多试几下一般就好了 。&lt;/p&gt; &lt;h3&gt;iperf3&lt;/h3&gt; &lt;p&gt;如果我们并不是想测试公网网速，而是测试两个服务器之间点对点的网速。这时用   &lt;a href="https://iperf.fr/iperf-doc.php#doc"&gt;iperf3&lt;/a&gt; 工具就好。&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo apt install iperf3 -y # Debian 下
$ brew install iperf3        # MacOS 下&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;需要注意，除了 iperf3 之外，还有一个 iperf。这两个版本分别由不同组织开发，前后也不兼容。虽然似乎 iperf3 有坑，不过似乎功能多一点，尤其是支持了下行带宽测试（iperf 只支持上行带宽测试），所以这里还是用 iperf3。&lt;/p&gt; &lt;p&gt;iperf3 是 C/S 架构，服务端开启 server ，客户端开启 client，然后互相通信进行测速。以我在家的树莓派和一个在 HK 的 Azure 主机为例：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ iperf3 -s -p 5555                   # azure 主机上开启 server

$ iperf3 -c 104.208.65.181 -p 5555    # pi 上开启 client 并连接 server&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;测试完成后，client 上会有报告：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ iperf3 -c 104.208.65.181 -p 5555
Connecting to host 104.208.65.181, port 5555
[  5] local 192.168.1.2 port 35994 connected to 104.208.65.181 port 5555
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  8.68 MBytes  72.8 Mbits/sec    0   2.95 MBytes
[  5]   1.00-2.00   sec  1.25 MBytes  10.5 Mbits/sec  2018    252 KBytes
[  5]   2.00-3.00   sec  2.50 MBytes  21.0 Mbits/sec  1076    286 KBytes
[  5]   3.00-4.00   sec  3.75 MBytes  31.5 Mbits/sec  861    237 KBytes
[  5]   4.00-5.00   sec  2.50 MBytes  21.0 Mbits/sec   99    187 KBytes
[  5]   5.00-6.00   sec  1.25 MBytes  10.5 Mbits/sec    0    206 KBytes
[  5]   6.00-7.00   sec  2.50 MBytes  21.0 Mbits/sec    0    215 KBytes
[  5]   7.00-8.00   sec  2.50 MBytes  21.0 Mbits/sec    0    218 KBytes
[  5]   8.00-9.00   sec  2.50 MBytes  21.0 Mbits/sec    0    218 KBytes
[  5]   9.00-10.00  sec  2.50 MBytes  21.0 Mbits/sec    0    220 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  29.9 MBytes  25.1 Mbits/sec  4054             sender
[  5]   0.00-10.09  sec  26.5 MBytes  22.1 Mbits/sec                  receiver

iperf Done.&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这里可以看出 client 对 server 的上行带宽大约是 22Mbit/sec。&lt;/p&gt; &lt;p&gt;类似的，server配置不变，client加上 -R 参数后可以测试出 server 对 client 的下行带宽：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ iperf3 -c 104.208.65.181 -p 5555 -R
Connecting to host 104.208.65.181, port 5555
Reverse mode, remote host 104.208.65.181 is sending
[  5] local 192.168.1.2 port 36000 connected to 104.208.65.181 port 5555
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  6.47 MBytes  54.3 Mbits/sec
[  5]   1.00-2.00   sec  25.7 MBytes   216 Mbits/sec
[  5]   2.00-3.00   sec  13.2 MBytes   111 Mbits/sec
[  5]   3.00-4.00   sec  16.3 MBytes   137 Mbits/sec
[  5]   4.00-5.00   sec  12.4 MBytes   104 Mbits/sec
[  5]   5.00-6.00   sec  14.4 MBytes   121 Mbits/sec
[  5]   6.00-7.00   sec  14.0 MBytes   117 Mbits/sec
[  5]   7.00-8.00   sec  13.9 MBytes   116 Mbits/sec
[  5]   8.00-9.00   sec  11.5 MBytes  96.7 Mbits/sec
[  5]   9.00-10.00  sec  11.3 MBytes  95.2 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.09  sec   142 MBytes   118 Mbits/sec  2560             sender
[  5]   0.00-10.00  sec   139 MBytes   117 Mbits/sec                  receiver

iperf Done.&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这里可以看出 server 对 client 的下行带宽大约是 117Mbit/sec。&lt;/p&gt; &lt;h2&gt;CPU&amp;amp;内存&lt;/h2&gt; &lt;h3&gt;sysbench&lt;/h3&gt; &lt;p&gt;对于CPU和内存的性能测试，可以使用   &lt;a href="https://github.com/akopytov/sysbench"&gt;sysbench&lt;/a&gt; 工具。&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sudo apt install sysbench -y # Debian 下
$ brew install sysbench        # MacOS 下&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;对于我的树莓派测试如下：&lt;/p&gt; &lt;p&gt;CPU单线程测试，可以看出单核每秒操作数大约1483：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sysbench cpu --threads=1 run
sysbench 1.0.18 (using system LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time


Prime numbers limit: 10000

Initializing worker threads...

Threads started!

CPU speed:
    events per second:  1483.17

General statistics:
    total time:                          10.0002s
    total number of events:              14839

Latency (ms):
         min:                                    0.67
         avg:                                    0.67
         max:                                    1.88
         95th percentile:                        0.68
         sum:                                 9992.91

Threads fairness:
    events (avg/stddev):           14839.0000/0.00
    execution time (avg/stddev):   9.9929/0.00
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;内存读写测试，可以看出读写速度约是 1814MiB 每秒：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ sysbench memory run
sysbench 1.0.18 (using system LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time


Running memory speed test with the following options:
  block size: 1KiB
  total size: 102400MiB
  operation: write
  scope: global

Initializing worker threads...

Threads started!

Total operations: 18590983 (1858174.07 per second)

18155.26 MiB transferred (1814.62 MiB/sec)


General statistics:
    total time:                          10.0001s
    total number of events:              18590983

Latency (ms):
         min:                                    0.00
         avg:                                    0.00
         max:                                    0.20
         95th percentile:                        0.00
         sum:                                 4463.57

Threads fairness:
    events (avg/stddev):           18590983.0000/0.00
    execution time (avg/stddev):   4.4636/0.00
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;需要注意的是，对 MacOS 的 CPU benchmark 似乎有坑，测试出来的结果异常的大，不具有参考价值。&lt;/p&gt; &lt;h3&gt;md5sum&lt;/h3&gt; &lt;p&gt;虽然 sysbench 的基准测试看起来比较靠谱，但是实际环境下，真正的执行效率还跟执行的指令啥的都有挺大关系。比如，我们以执行 md5 的速度来对比 CPU 的执行效率：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;$ dd if=/dev/zero bs=1M count=1024 | md5sum
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 5.81996 s, 184 MB/s
cd573cfaace07e7949bc0c46028904ff  -&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;通过   &lt;code&gt;dd&lt;/code&gt; 命令向   &lt;code&gt;md5sum&lt;/code&gt; 持续发送 1GB 的数据进行计算，计算的速度也可以看成是 CPU 单核性能的一种指标。（考虑到管道操作是单线程，这个指令其实也只能用到一个核）&lt;/p&gt; &lt;p&gt;然后，如果我们多找几个 CPU 进行以下对比，我们就会发现一些神奇的现象：&lt;/p&gt; &lt;h4&gt;Cortex-A72（ARM）&lt;/h4&gt; &lt;ul&gt;  &lt;li&gt;sysbench 单线程：1479.99 event/s&lt;/li&gt;  &lt;li&gt;dd + md5sum：184 MB/s&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;Neoverse-N1（ARM）&lt;/h4&gt; &lt;ul&gt;  &lt;li&gt;sysbench 单线程：3497.70 event/s&lt;/li&gt;  &lt;li&gt;dd + md5sum：424 MB/s&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz（x86_64）&lt;/h4&gt; &lt;ul&gt;  &lt;li&gt;sysbench 单线程：820.19 event/s&lt;/li&gt;  &lt;li&gt;dd + md5sum：409 MB/s&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;Intel(R) Xeon(R) CPU E5-26xx v4（x86_64）&lt;/h4&gt; &lt;ul&gt;  &lt;li&gt;sysbench 单线程：927.74 event/s&lt;/li&gt;  &lt;li&gt;dd + md5sum：459 MB/s&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;Intel(R) Xeon(R) Platinum 8255C CPU @ 2.50GHz（x86_64）&lt;/h4&gt; &lt;ul&gt;  &lt;li&gt;sysbench 单线程：1054.30 event/s&lt;/li&gt;  &lt;li&gt;dd + md5sum：515 MB/s&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;可以发现 ARM 架构的机器在 sysbench 上表现几乎都比 X86_64 的机器好很多，但是实际跑 md5sum 却相差不大甚至差不少。&lt;/p&gt; &lt;p&gt;可见不同架构间二者的指标并不完全正相关；不过相同架构间二者的指标还是基本正相关的。&lt;/p&gt; &lt;h2&gt;参考资料&lt;/h2&gt; &lt;p&gt;  &lt;a href="https://romanrm.net/dd-benchmark"&gt;dd-benchmark&lt;/a&gt;  &lt;a href="https://man7.org/linux/man-pages/man8/hdparm.8.html"&gt; &lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;a href="https://man7.org/linux/man-pages/man8/hdparm.8.html"&gt;man-hdparm&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;a href="https://iperf.fr/iperf-doc.php#doc"&gt;iperf&lt;/a&gt;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux Raspberry Pi</category>
      <guid isPermaLink="true">https://itindex.net/detail/62452-linux-%E4%B8%BB%E6%9C%BA-%E6%80%A7%E8%83%BD</guid>
      <pubDate>Thu, 13 Oct 2022 17:11:12 CST</pubDate>
    </item>
    <item>
      <title>Linux文件系统inode详解</title>
      <link>https://itindex.net/detail/62362-linux-%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F-inode</link>
      <description>&lt;h2&gt;文件系统&lt;/h2&gt;
 &lt;p&gt;文件系统是操作系统中负责管理持久数据的子系统，说简单点，就是负责把用户的文件存到磁盘硬件中，因为即使计算机断电了，磁盘里的数据并不会丢失，所以可以持久化的保存文件。&lt;/p&gt;
 &lt;p&gt;文件系统的基本数据单位是文件，它的目的是对磁盘上的文件进行组织管理，那组织的方式不同，就会形成不同的文件系统。&lt;/p&gt;
 &lt;p&gt;Linux 最经典的一句话是：「一切皆文件」，不仅普通的文件和目录，就连块设备、管道、socket 等，也都是统一交给文件系统管理的。&lt;/p&gt;
 &lt;p&gt;Linux 文件系统会为每个文件分配两个数据结构：索引节点（index node）和目录项（directory entry），它们主要用来记录文件的元信息和目录层次结构。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="357" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/inode.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;索引节点，也就是inode，用来记录文件的元信息，比如 inode 编号、文件大小、访问权限、创建时间、修改时间、数据在磁盘的位置等等。索引节点是文件的唯一标识，它们之间一一对应，也同样都会被存储在硬盘中，所以索引节点同样占用磁盘空间。&lt;/li&gt;
  &lt;li&gt;目录项，也就是dentry，用来记录文件的名字、索引节点指针以及与其他目录项的层级关联关系。多个目录项关联起来，就会形成目录结构，但它与索引节点不同的是，目录项是由内核维护的一个数据结构，不存放于磁盘，而是缓存在内存。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;由于索引节点唯一标识一个文件，而目录项记录着文件的名，所以目录项和索引节点的关系是多对一，也就是说，一个文件可以有多个目录。比如，硬链接的实现就是多个目录项中的索引节点指向同一个文件。&lt;/p&gt;
 &lt;p&gt;注意，目录也是文件，也是用索引节点唯一标识，和普通文件不同的是，普通文件在磁盘里面保存的是文件数据，而目录文件在磁盘里面保存子目录或文件。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;目录项和目录是一个东西吗？&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;虽然名字很相近，但是它们不是一个东西，目录是个文件，持久化存储在磁盘，而目录项是内核一个数据结构，缓存在内存。&lt;/p&gt;
 &lt;p&gt;如果查询目录频繁从磁盘读，效率会很低，所以内核会把已经读过的目录用目录项这个数据结构缓存在内存，下次再次读到相同的目录时，只需从内存读就可以，大大提高了文件系统的效率。&lt;/p&gt;
 &lt;p&gt;注意，目录项这个数据结构不只是表示目录，也是可以表示文件的。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;文件数据是如何存储在磁盘的呢？&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;磁盘读写的最小单位是扇区，扇区的大小只有 512字节，那么如果数据大于512字节时候，磁盘需要不停地移动磁头来查找数据，我们知道一般的文件很容易超过512字节那么如果把多个扇区合并为一个块，那么磁盘就可以提高效率了。那么磁头一次读取多个扇区就为一个块“block”（Linux上称为块，Windows上称为簇）。所以，文件系统把多个扇区组成了一个逻辑块，每次读写的最小单位就是逻辑块（数据块），Linux 中的逻辑块大小为 4KB，也就是一次性读写 8 个扇区，这将大大提高了磁盘的读写的效率。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="333" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/filesystem.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;文件系统记录的数据，除了其自身外，还有数据的权限信息，所有者等属性，这些信息都保存在inode中，那么谁来记录inode信息和文件系统本身的信息呢，比如说文件系统的格式，inode与data的数量呢？那么就有一个超级区块（supper block）来记录这些信息了。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="601" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/supper-block.png" width="720"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;superblock：记录此 filesystem 的整体信息，包括inode/block的总量、使用量、剩余量， 以及文件系统的格式与相关信息等&lt;/li&gt;
  &lt;li&gt;inode：记录文件的属性信息，可以使用stat命令查看inode信息。&lt;/li&gt;
  &lt;li&gt;block：实际文件的内容，如果一个文件大于一个块时候，那么将占用多个block，但是一个块只能存放一个文件。（因为数据是由inode指向的，如果有两个文件的数据存放在同一个块中，就会乱套了）&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;img alt="" height="254" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/data.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;node用来指向数据block，那么只要找到inode，再由inode找到block编号，那么实际数据就能找出来了。&lt;/p&gt;
 &lt;p&gt;索引节点是存储在硬盘上的数据，为了加速文件的访问，通常会把索引节点加载到内存中。我们不可能把超级块和索引节点区全部加载到内存，这样内存肯定撑不住，所以只有当需要使用的时候，才将其加载进内存，它们加载进内存的时机是不同的：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;超级块：当文件系统挂载时进入内存；&lt;/li&gt;
  &lt;li&gt;索引节点区：当文件被访问时进入内存；&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;虚拟文件系统&lt;/h2&gt;
 &lt;p&gt;文件系统的种类众多，而操作系统希望对用户提供一个统一的接口，于是在用户层与文件系统层引入了中间层，这个中间层就称为虚拟文件系统（Virtual File System，VFS）。VFS 定义了一组所有文件系统都支持的数据结构和标准接口，这样程序员不需要了解  &lt;a href="https://www.biaodianfu.com/linux-windows-mac-os-file_systems.html"&gt;文件系统&lt;/a&gt;的工作原理，只需要了解 VFS 提供的统一接口即可。在 Linux 文件系统中，用户空间、系统调用、虚拟机文件系统、缓存、文件系统以及存储之间的关系如下图：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="630" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/vfs.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;Linux 支持的文件系统也不少，根据存储位置的不同，可以把文件系统分为三类：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;磁盘的文件系统，它是直接把数据存储在磁盘中，比如 Ext 2/3/4、XFS 等都是这类文件系统。&lt;/li&gt;
  &lt;li&gt;内存的文件系统，这类文件系统的数据不是存储在硬盘的，而是占用内存空间，我们经常用到的/proc 和 /sys 文件系统都属于这一类，读写这类文件，实际上是读写内核中相关的数据。&lt;/li&gt;
  &lt;li&gt;网络的文件系统，用来访问其他计算机主机数据的文件系统，比如 NFS、SMB 等等。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;文件系统首先要先挂载到某个目录才可以正常使用，比如 Linux 系统在启动时，会把文件系统挂载到根目录。&lt;/p&gt;
 &lt;p&gt;Linux 采用为分层的体系结构，将用户接口层、文件系统实现和存储设备的驱动程序分隔开，进而兼容不同的文件系统。虚拟文件系统（Virtual File System, VFS）是 Linux 内核中的软件层，它在内核中提供了一组标准的、抽象的文件操作，允许不同的文件系统实现共存，并向用户空间程序提供统一的文件系统接口。下面这张图展示了 Linux 虚拟文件系统的整体结构：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="391" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/vfs-architecture.png" width="640"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;从上图可以看出，用户空间的应用程序直接、或是通过编程语言提供的库函数间接调用内核提供的 System Call 接口（如open()、write()等）执行文件操作。System Call 接口再将应用程序的参数传递给虚拟文件系统进行处理。&lt;/p&gt;
 &lt;p&gt;每个文件系统都为 VFS 实现了一组通用接口，具体的文件系统根据自己对磁盘上数据的组织方式操作相应的数据。当应用程序操作某个文件时，VFS 会根据文件路径找到相应的挂载点，得到具体的文件系统信息，然后调用该文件系统的对应操作函数。&lt;/p&gt;
 &lt;p&gt;VFS 提供了两个针对文件系统对象的缓存 INode Cache 和 DEntry Cache，它们缓存最近使用过的文件系统对象，用来加快对 INode 和 DEntry 的访问。Linux 内核还提供了 Buffer Cache 缓冲区，用来缓存文件系统和相关块设备之间的请求，减少访问物理设备的次数，加快访问速度。Buffer Cache 以 LRU 列表的形式管理缓冲区。&lt;/p&gt;
 &lt;p&gt;VFS 的好处是实现了应用程序的文件操作与具体的文件系统的解耦，使得编程更加容易：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;应用层程序只要使用 VFS 对外提供的read()、write()等接口就可以执行文件操作，不需要关心底层文件系统的实现细节；&lt;/li&gt;
  &lt;li&gt;文件系统只需要实现 VFS 接口就可以兼容 Linux，方便移植与维护；&lt;/li&gt;
  &lt;li&gt;无需关注具体的实现细节，就实现跨文件系统的文件操作。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;了解 Linux 文件系统的整体结构后，下面主要分析 Linux VFS 的技术原理。由于文件系统与设备驱动的实现非常复杂，笔者也未接触过这方面的内容，因此文中不会涉及具体文件系统的实现。&lt;/p&gt;
 &lt;h3&gt;VFS 结构&lt;/h3&gt;
 &lt;p&gt;Linux 以一组通用对象的角度看待所有文件系统，每一级对象之间的关系如下图所示：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="427" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/vfs-object.png" width="640"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;fd 与 file&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;每个进程都持有一个fd[]数组，数组里面存放的是指向file结构体的指针，同一进程的不同fd可以指向同一个file对象；&lt;/p&gt;
 &lt;p&gt;file是内核中的数据结构，表示一个被进程打开的文件，和进程相关联。当应用程序调用open()函数的时候，VFS 就会创建相应的file对象。它会保存打开文件的状态，例如文件权限、路径、偏移量等等。&lt;/p&gt;
 &lt;pre&gt;// https://elixir.bootlin.com/linux/v5.4.93/source/include/linux/fs.h#L936 结构体已删减
struct file {
    struct path                   f_path;
    struct inode                  *f_inode;
    const struct file_operations  *f_op;
    unsigned int                  f_flags;
    fmode_t                       f_mode;
    loff_t                        f_pos;
    struct fown_struct            f_owner;
}

// https://elixir.bootlin.com/linux/v5.4.93/source/include/linux/path.h#L8
struct path {
    struct vfsmount  *mnt;
    struct dentry    *dentry;
}
&lt;/pre&gt;
 &lt;p&gt;从上面的代码可以看出，文件的路径实际上是一个指向 DEntry 结构体的指针，VFS 通过 DEntry 索引到文件的位置。&lt;/p&gt;
 &lt;p&gt;除了文件偏移量f_pos是进程私有的数据外，其他的数据都来自于 INode 和 DEntry，和所有进程共享。不同进程的file对象可以指向同一个 DEntry 和 Inode，从而实现文件的共享。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;DEntry 与 INode&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;Linux文件系统会为每个文件都分配两个数据结构，目录项（DEntry, Directory Entry）和索引节点（INode, Index Node）。&lt;/p&gt;
 &lt;p&gt;DEntry 用来保存文件路径和 INode 之间的映射，从而支持在文件系统中移动。DEntry 由 VFS 维护，所有文件系统共享，不和具体的进程关联。dentry对象从根目录“/”开始，每个dentry对象都会持有自己的子目录和文件，这样就形成了文件树。举例来说，如果要访问”/home/beihai/a.txt”文件并对他操作，系统会解析文件路径，首先从“/”根目录的dentry对象开始访问，然后找到”home/“目录，其次是“beihai/”，最后找到“a.txt”的dentry结构体，该结构体里面d_inode字段就对应着该文件。&lt;/p&gt;
 &lt;pre&gt;// https://elixir.bootlin.com/linux/v5.4.93/source/include/linux/dcache.h#L89 结构体已删减
struct dentry {
    struct dentry *d_parent;     // 父目录
    struct qstr d_name;          // 文件名称
    struct inode *d_inode;       // 关联的 inode
    struct list_head d_child;    // 父目录中的子目录和文件
    struct list_head d_subdirs;  // 当前目录中的子目录和文件
}
&lt;/pre&gt;
 &lt;p&gt;每一个dentry对象都持有一个对应的inode对象，表示 Linux 中一个具体的目录项或文件。INode 包含管理文件系统中的对象所需的所有元数据，以及可以在该文件对象上执行的操作。&lt;/p&gt;
 &lt;pre&gt;// https://elixir.bootlin.com/linux/v5.4.93/source/include/linux/fs.h#L628 结构体已删减
struct inode {
    umode_t                 i_mode;          // 文件权限及类型
    kuid_t                  i_uid;           // user id
    kgid_t                  i_gid;           // group id

    const struct inode_operations    *i_op;  // inode 操作函数，如 create，mkdir，lookup，rename 等
    struct super_block      *i_sb;           // 所属的 SuperBlock

    loff_t                  i_size;          // 文件大小
    struct timespec         i_atime;         // 文件最后访问时间
    struct timespec         i_mtime;         // 文件最后修改时间
    struct timespec         i_ctime;         // 文件元数据最后修改时间（包括文件名称）
    const struct file_operations    *i_fop;  // 文件操作函数，open、write 等
    void                    *i_private;      // 文件系统的私有数据
}
&lt;/pre&gt;
 &lt;p&gt;虚拟文件系统维护了一个 DEntry Cache 缓存，用来保存最近使用的 DEntry，加速查询操作。当调用open()函数打开一个文件时，内核会第一时间根据文件路径到 DEntry Cache 里面寻找相应的 DEntry，找到了就直接构造一个file对象并返回。如果该文件不在缓存中，那么 VFS 会根据找到的最近目录一级一级地向下加载，直到找到相应的文件。期间 VFS 会缓存所有被加载生成的dentry。&lt;/p&gt;
 &lt;p&gt;INode 存储的数据存放在磁盘上，由具体的文件系统进行组织，当需要访问一个 INode 时，会由文件系统从磁盘上加载相应的数据并构造 INode。一个 INode 可能被多个 DEntry 所关联，即相当于为某一文件创建了多个文件路径（通常是为文件建立硬链接）。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;SuperBlock&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;SuperBlock 表示特定加载的文件系统，用于描述和维护文件系统的状态，由 VFS 定义，但里面的数据根据具体的文件系统填充。每个 SuperBlock 代表了一个具体的磁盘分区，里面包含了当前磁盘分区的信息，如文件系统类型、剩余空间等。SuperBlock 的一个重要成员是链表s_list，包含所有修改过的 INode，使用该链表很容易区分出来哪个文件被修改过，并配合内核线程将数据写回磁盘。SuperBlock 的另一个重要成员是s_op，定义了针对其 INode 的所有操作方法，例如标记、释放索引节点等一系列操作。&lt;/p&gt;
 &lt;pre&gt;// https://elixir.bootlin.com/linux/v5.4.93/source/include/linux/fs.h#L1425 结构体已删减
struct super_block {
    struct list_head    s_list;               // 指向链表的指针
    dev_t               s_dev;                // 设备标识符
    unsigned long       s_blocksize;          // 以字节为单位的块大小
    loff_t              s_maxbytes;           // 文件大小上限
    struct file_system_type    *s_type;       // 文件系统类型
    const struct super_operations    *s_op;   // SuperBlock 操作函数，write_inode、put_inode 等
    const struct dquot_operations    *dq_op;  // 磁盘限额函数
    struct dentry        *s_root;             // 根目录
}
&lt;/pre&gt;
 &lt;p&gt;SuperBlock 是一个非常复杂的结构，通过 SuperBlock 我们可以将一个实体文件系统挂载到 Linux 上，或者对 INode 进行增删改查操作。所以一般文件系统都会在磁盘上存储多份 SuperBlock，防止数据意外损坏导致整个分区无法读取。&lt;/p&gt;
 &lt;h3&gt;inode 内容&lt;/h3&gt;
 &lt;p&gt;inode包含很多的文件元信息，但不包含文件名，例如：字节数、属主UserID、属组GroupID、读写执行权限、时间戳等。而文件名存放在目录当中，但Linux系统内部不使用文件名，而是使用inode号码识别文件。对于系统来说文件名只是inode号码便于识别的别称。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;stat&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;查看inode信息&lt;/p&gt;
 &lt;pre&gt;[root@localhost ~]# mkdir test
[root@localhost ~]# echo &amp;quot;this is test file&amp;quot; &amp;gt; test.txt
[root@localhost ~]# stat test.txt
  File: ‘test.txt’
  Size: 18              Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 33574994    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2019-08-28 19:55:05.920240744 +0800
Modify: 2019-08-28 19:55:05.920240744 +0800
Change: 2019-08-28 19:55:05.920240744 +0800
 Birth: -
&lt;/pre&gt;
 &lt;p&gt;三个主要的时间属性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;ctime：change time是最后一次改变文件或目录（属性）的时间，例如执行chmod，chown等命令。&lt;/li&gt;
  &lt;li&gt;atime：access time是最后一次访问文件或目录的时间。&lt;/li&gt;
  &lt;li&gt;mtime：modify time是最后一次修改文件或目录（内容）的时间。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;file&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;查看文件类型&lt;/p&gt;
 &lt;pre&gt;[root@localhost ~]# file test
test: directory
[root@localhost ~]# file test.txt
test.txt: ASCII text
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;inode 号码&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;表面上，用户通过文件名打开文件，实际上，系统内部将这个过程分为三步：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;系统找到这个文件名对应的inode号码；&lt;/li&gt;
  &lt;li&gt;通过inode号码，获取inode信息；&lt;/li&gt;
  &lt;li&gt;根据inode信息，找到文件数据所在的block，并读出数据。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;其实系统还要根据inode信息，看用户是否具有访问的权限，有就指向对应的数据block，没有就返回权限拒绝。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;ls -i&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;直接查看文件i节点号，也可以通过stat查看文件inode信息查看i节点号。&lt;/p&gt;
 &lt;pre&gt;[root@localhost ~]# ls -i
33574991 anaconda-ks.cfg      2086 test  33574994 test.txt
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;inode 大小&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;inode也会消耗硬盘空间，所以格式化的时候，操作系统自动将硬盘分成两个区域。一个是数据区，存放文件数据；另一个是inode区，存放inode所包含的信息。每个inode的大小，一般是128字节或256字节。通常情况下不需要关注单个inode的大小，而是需要重点关注inode总数。inode总数在格式化的时候就确定了。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;df -i&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;查看硬盘分区的inode总数和已使用情况&lt;/p&gt;
 &lt;pre&gt;[root@localhost ~]# df -i
Filesystem               Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/centos-root 8910848 26029 8884819    1% /
devtmpfs                 230602   384  230218    1% /dev
tmpfs                    233378     1  233377    1% /dev/shm
tmpfs                    233378   487  232891    1% /run
tmpfs                    233378    16  233362    1% /sys/fs/cgroup
/dev/sda1                524288   328  523960    1% /boot
tmpfs                    233378     1  233377    1% /run/user/0
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;文件的读写&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;文件系统在打开一个文件时，要做的有：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;系统找到这个文件名对应的inode：在目录表中查找该文件名对应的项，由此得到该文件相对应的 inode 号&lt;/li&gt;
  &lt;li&gt;通过inode号，获取到磁盘中的inode信息，其中最重要的内容是磁盘地址表&lt;/li&gt;
  &lt;li&gt;通过inode信息中的磁盘地址表，文件系统把分散存放的文件物理块连接成文件的逻辑结构。在磁盘地址表中有 13 个块号，文件将以块号在磁盘地址表中出现的顺序依次读取相应的块。找到文件数据所在的block，读出数据。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;根据以上流程，我们可以发现，inode应该是有一个专门的存储区域的，以方便系统快速查找。事实上，一块磁盘创建的时候，操作系统自动将硬盘分成两个区域：存放文件数据的数据区，与存放inode信息的inode区（inode table）。&lt;/p&gt;
 &lt;p&gt;每个inode的大小一般是128B或者256B。inode节点的总数，在格式化时就给定，一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中，每个inode节点的大小为128字节，每1KB就设置一个inode，那么inode table的大小就会达到128MB，占整块硬盘的12.8%。&lt;/p&gt;
 &lt;p&gt;也就是说，每个分区的inode总数从格式化之后就固定了，因此有可能会出现存储空间没有占满，但因为小文件太多而耗尽了inode的情况。这个时候就只能清除inode占用高的文件或者目录或修改inode数量了，当然，inode的调整需要重新格式化磁盘，需要确保数据已经得到有效备份后，再进行此操作。&lt;/p&gt;
 &lt;p&gt;这时候又产生了新的问题：文件创建时要为文件分配哪一个inode号呢？即如何保证分配的inode号没有被占用？  &lt;br /&gt;
既然是”是否被占用”的问题，使用位图是最佳方案，像bmap记录block的占用情况一样。标识inode号是否被分配的位图称为inodemap简称为imap。这时要为一个文件分配inode号只需扫描imap即可知道哪一个inode号是空闲的。&lt;/p&gt;
 &lt;p&gt;(位图法就是bitmap的缩写。所谓bitmap，就是用每一位来存放某种状态，适用于大规模数据，但数据状态又不是很多的情况。)  &lt;br /&gt;
类似bmap块位图一样，inode号是预先规划好的。inode号分配后，文件删除也会释放inode号。分配和释放的inode号，像是在一个地图上挖掉一块，用完再补回来一样。  &lt;br /&gt;
imap存在着和bmap和inode table一样需要解决的问题：如果文件系统比较大，imap本身就会很大，每次存储文件都要进行扫描，会导致效率不够高。同样，优化的方式是将文件系统占用的block划分成块组，每个块组有自己的imap范围，以减少检索时间。&lt;/p&gt;
 &lt;p&gt;利用df -i命令可以查看inode数量方面的信息&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;文件的操作&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;系统对文件的操作会可能影响inode：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;复制：创建一个包含全部数据与新inode号的新文件&lt;/li&gt;
  &lt;li&gt;移动：在同一磁盘下移动时，所在目录改变，node号与实际数据存储的块的位置都不会变化。跨磁盘移动当然会删除本磁盘的数据并创建一条新的数据在另一块磁盘中。&lt;/li&gt;
  &lt;li&gt;硬链接： 同一个inode号代表的文件有多个文件名，即可以用不同的文件名访问同一份数据，但是它们指向的inode编号是相同的，并且文件元数据中链接数会增加。不可以对目录创建硬链接。&lt;/li&gt;
  &lt;li&gt;软链接： 软链接的本质是一个链接文件，其中存储的了对另一个文件的指针。所以对一个文件创建软链接，inode号不相同，创建软链接文件的链接数不会增加。可以对目录创建软链接。&lt;/li&gt;
  &lt;li&gt;删除：当删除文件时，会先检查inode中的链接数。如果链接数大于1，就只会删掉一个硬链接，不影响数据。如果链接数等于1，那么这个inode就会被释放掉，对应的inode指向的块也会被标记为空闲的（数据不会被置零，所以硬盘数据被误删除后，若没有新数据写入可恢复）。如果是软链接，原文件被删除后链接文件就变成了悬挂链接（dangling link），无法正常访问了。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;利用inode还可以删除一些文件名中有转义字符或控制字符的文件，最典型的就是开头为减号-的文件。这种无法直接用rm命令来搞，就可以先查出它们的inode编号再删除：   &lt;code&gt;find ./ -inum 10086 -exec rm {} \&lt;/code&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;特有现象&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;由于inode号码与文件名分离，导致一些Unix/Linux系统具备以下几种特有的现象。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;文件名包含特殊字符，可能无法正常删除。这时直接删除inode，能够起到删除文件的作用；   &lt;code&gt;find ./* -inum 节点号 -delete&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;移动文件或重命名文件，只是改变文件名，不影响inode号码；&lt;/li&gt;
  &lt;li&gt;打开一个文件以后，系统就以inode号码来识别这个文件，不再考虑文件名。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;这种情况使得软件更新变得简单，可以在不关闭软件的情况下进行更新，不需要重启。因为系统通过inode号码，识别运行中的文件，不通过文件名。更新的时候，新版文件以同样的文件名，生成一个新的inode，不会影响到运行中的文件。等到下一次运行这个软件的时候，文件名就自动指向新版文件，旧版文件的inode则被回收。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;inode 耗尽故障&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;由于硬盘分区的inode总数在格式化后就已经固定，而每个文件必须有一个inode，因此就有可能发生inode节点用光，但硬盘空间还剩不少，却无法创建新文件。同时这也是一种攻击的方式，所以一些公用的文件系统就要做磁盘限额，以防止影响到系统的正常运行。至于修复，很简单，只要找出哪些大量占用i节点的文件删除就可以了。&lt;/p&gt;
 &lt;h2&gt;硬链接与软连接&lt;/h2&gt;
 &lt;p&gt;Linux系统中有一种比较特殊的文件称之为链接（link）。通俗地说，链接就是从一个文件指向另外一个文件的路径。linux中链接分为俩种，硬链接和软链接。简单来说，硬链接相当于源文件和链接文件在磁盘和内存中共享一个inode，因此，链接文件和源文件有不同的dentry，因此，这个特性决定了硬链接无法跨越文件系统，而且我们无法为目录创建硬链接。软链接和硬链接不同，首先软链接可以跨越文件系统，其次，链接文件和源文件有着不同的inode和dentry，因此，两个文件的属性和内容也截然不同，软链接文件的文件内容是源文件的文件名。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="442" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/hardlink.png" width="640"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;硬链接是多个目录项中的「索引节点」指向一个文件，也就是指向同一个 inode，但是 inode 是不可能跨越文件系统的，每个文件系统都有各自的 inode 数据结构和列表，所以硬链接是不可用于跨文件系统的。由于多个目录项都是指向一个 inode，那么只有删除文件的所有硬链接以及源文件时，系统才会彻底删除该文件。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="389" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/hard-link.png" width="720"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;软链接相当于重新创建一个文件，这个文件有独立的 inode，但是这个文件的内容是另外一个文件的路径，所以访问软链接的时候，实际上相当于访问到了另外一个文件，所以软链接是可以跨文件系统的，甚至目标文件被删除了，链接文件还是在的，只不过指向的文件找不到了而已。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="375" src="https://www.biaodianfu.com/wp-content/uploads/2022/08/soft-link.png" width="720"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;软硬链接实现的原理不同
   &lt;ul&gt;
    &lt;li&gt;硬链接是建立一个目录项，包含文件名和文件的inode，但inode是原来文件的inode号，并不建立其所对应得数据。所以硬链接并不占用inode。&lt;/li&gt;
    &lt;li&gt;软连接也创建一个目录项，也包含文件名和文件的inode，但它的inode指向的并不是原来文件名所指向的数据的inode，而是新建一个inode，并建立数据，数据指向的是原来文件名，所以原来文件名的字符数，即为软连接所占字节数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;软硬链接所能创建的目标有区别
   &lt;ul&gt;
    &lt;li&gt;因为每个分区各有一套不同的inode表，所以硬链接不能跨分区创建而软连接可以,因为软连接指向的书文件名。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;硬链接不能指向目录
   &lt;ul&gt;
    &lt;li&gt;如果说目录有硬链接那么可能引入死循环，但是你可能会疑问软连接也会陷入循环啊，答案当然不是，因为软连接是存在自己的数据的，可以查看自己的文件属性，既然可以判断出来软连接，那么自然不会陷入循环，并且系统在连续遇到8个符号连接后就停止遍历。但是硬链接可就不行了，因为他的inode号一致，所以就判断不出是硬链接，所以就会陷入死循环了。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;参考链接：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://wingsxdu.com/posts/linux/vfs/"&gt;Linux 虚拟文件系统&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://devconnected.com/understanding-hard-and-soft-links-on-linux/"&gt;Understanding Hard and Soft Links on Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;div&gt;
  &lt;h3&gt;相关文章:&lt;/h3&gt;  &lt;ol&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/hello-world.html" rel="bookmark" title="C&amp;#35821;&amp;#35328;&amp;#20043;Hello World&amp;#31243;&amp;#24207;&amp;#32534;&amp;#35793;"&gt;C语言之Hello World程序编译 &lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/fastfm.html" rel="bookmark" title="Python&amp;#22240;&amp;#23376;&amp;#20998;&amp;#35299;&amp;#24211;&amp;#65306;fastFM"&gt;Python因子分解库：fastFM &lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/linux-windows-mac-os-file_systems.html" rel="bookmark" title="Linux/Windows/Mac OS&amp;#25991;&amp;#20214;&amp;#31995;&amp;#32479;"&gt;Linux/Windows/Mac OS文件系统 &lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>器→工具 工具软件 Linux</category>
      <guid isPermaLink="true">https://itindex.net/detail/62362-linux-%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F-inode</guid>
      <pubDate>Sat, 13 Aug 2022 09:50:00 CST</pubDate>
    </item>
    <item>
      <title>Linux 打算合併 /dev/random 與 /dev/urandom 遇到的問題</title>
      <link>https://itindex.net/detail/62186-linux-dev-random</link>
      <description>&lt;p&gt;在   &lt;a href="https://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt; 上看到「  &lt;a href="https://news.ycombinator.com/item?id=30848973"&gt;Problems emerge for a unified /dev/*random (lwn.net)&lt;/a&gt;」的，原文是「  &lt;a href="https://lwn.net/Articles/889452/"&gt;Problems emerge for a unified /dev/*random&lt;/a&gt;」(付費內容，但是可以透過 Hacker News 上的連結直接看)。&lt;/p&gt;
 &lt;p&gt;標題提到的兩個 device 的性質會需要一些背景知識，可以參考維基百科上面「  &lt;a href="https://en.wikipedia.org/wiki//dev/random"&gt;/dev/random&lt;/a&gt;」這篇的說明，兩個都是   &lt;a href="https://en.wikipedia.org/wiki/Cryptographically-secure_pseudorandom_number_generator"&gt;CSPRNG&lt;/a&gt;，主要的分別在於   &lt;code&gt;/dev/urandom&lt;/code&gt; 通常不會 block：&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;The    &lt;code&gt;/dev/urandom&lt;/code&gt; device typically was never a blocking device, even if the pseudorandom number generator seed was not fully initialized with entropy since boot.&lt;/p&gt;&lt;/blockquote&gt;
 &lt;p&gt;而   &lt;code&gt;/dev/random&lt;/code&gt; 不保證不會 block，有可能會因為 entropy 不夠而卡住：&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;   &lt;code&gt;/dev/random&lt;/code&gt; typically blocked if there was less entropy available than requested; more recently (see below, different OS&amp;apos;s differ) it usually blocks at startup until sufficient entropy has been gathered, then unblocks permanently.&lt;/p&gt;&lt;/blockquote&gt;
 &lt;p&gt;然後順便講一下，因為這是 crypto 相關的設計修改，加上是 kernel level 的界面，安全性以及相容性都會是很在意的點，而 Hacker News 上的討論裡面很多是不太在意這些的，你會看到很多「很有趣」的想法在上面討論 XDDD&lt;/p&gt;
 &lt;p&gt;回到原來的文章，Jason A. Donenfeld (Linux kernel 裡 RNG maintainer 之一，不過近期比較知名的事情還是   &lt;a href="https://www.wireguard.com/"&gt;WireGuard&lt;/a&gt; 的發明人) 最近不斷的在改善 Linux kernel 裡面這塊架構，這次打算直接拿   &lt;code&gt;/dev/random&lt;/code&gt; 換掉   &lt;code&gt;/dev/urandom&lt;/code&gt;：「  &lt;a href="https://lwn.net/Articles/884875/"&gt;Uniting the Linux random-number devices&lt;/a&gt;」。&lt;/p&gt;
 &lt;p&gt;不過換完後   &lt;a href="https://www.google.com/"&gt;Google&lt;/a&gt; 的 Guenter Roeck 就在抱怨在   &lt;a href="https://www.qemu.org/"&gt;QEMU&lt;/a&gt; 環境裡面炸掉了：&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;This patch (or a later version of it) made it into mainline and causes a large number of qemu boot test failures for various architectures (arm, m68k, microblaze, sparc32, xtensa are the ones I observed). Common denominator is that boot hangs at &amp;quot;Saving random seed:&amp;quot;. A sample bisect log is attached. Reverting this patch fixes the problem.&lt;/p&gt;&lt;/blockquote&gt;
 &lt;p&gt;他透過   &lt;a href="https://git-scm.com/docs/git-bisect"&gt;git bisect&lt;/a&gt; 找到發生問題的 commit，另外從卡住的訊息也可以大概猜到在虛擬機下 entropy 不太夠。&lt;/p&gt;
 &lt;p&gt;另外從他們三個 (加上   &lt;a href="https://en.wikipedia.org/wiki/Linus_Torvalds"&gt;Linus&lt;/a&gt;) 在 mailing list 上面討論的訊息可以看到不少交流：「  &lt;a href="https://lwn.net/ml/linux-kernel/YjoC5kQMqyC%2F3L5Y@zx2c4.com/"&gt;Re: [PATCH v1] random: block in /dev/urandom&lt;/a&gt;」，包括嘗試「餵」entropy 進   &lt;code&gt;/dev/urandom&lt;/code&gt; 的 code...&lt;/p&gt;
 &lt;p&gt;後續看起來還會有一些嘗試，但短期內看起來應該還是會先分開...&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Computer Linux Murmuring OS Security</category>
      <guid isPermaLink="true">https://itindex.net/detail/62186-linux-dev-random</guid>
      <pubDate>Sun, 03 Apr 2022 12:33:00 CST</pubDate>
    </item>
    <item>
      <title>Metasploit Framework 6.1.32+20220303 (macOS, Linux, Windows) -- 渗透测试框架</title>
      <link>https://itindex.net/detail/62141-metasploit-framework-macos</link>
      <description>&lt;p&gt;请访问原文链接：  &lt;a href="https://sysin.org/blog/metasploit-framework-6/" title="Metasploit Framework 6.1.32+20220303 (macOS, Linux, Windows) -- &amp;#28183;&amp;#36879;&amp;#27979;&amp;#35797;&amp;#26694;&amp;#26550;"&gt;Metasploit Framework 6.1.32+20220303 (macOS, Linux, Windows) -- 渗透测试框架&lt;/a&gt;，查看最新版。原创作品，转载请保留出处。&lt;/p&gt; &lt;p&gt;作者主页：  &lt;a href="https://sysin.org"&gt;www.sysin.org&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="img" src="https://www.metasploit.com/includes/images/metasploit-logo.svg"&gt;&lt;/img&gt;&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://sysin.org/#&amp;#19990;&amp;#30028;&amp;#19978;&amp;#26368;&amp;#24191;&amp;#27867;&amp;#20351;&amp;#29992;&amp;#30340;&amp;#28183;&amp;#36879;&amp;#27979;&amp;#35797;&amp;#26694;&amp;#26550;" title="&amp;#19990;&amp;#30028;&amp;#19978;&amp;#26368;&amp;#24191;&amp;#27867;&amp;#20351;&amp;#29992;&amp;#30340;&amp;#28183;&amp;#36879;&amp;#27979;&amp;#35797;&amp;#26694;&amp;#26550;"&gt;&lt;/a&gt;世界上最广泛使用的渗透测试框架&lt;/h2&gt; &lt;p&gt;知识就是力量，尤其是当它被分享时。作为开源社区和 Rapid7 之间的合作，Metasploit 帮助安全团队做的不仅仅是验证漏洞、管理安全评估和提高安全意识；它使防守队员能够始终领先比赛一步（或两步）。&lt;/p&gt; &lt;p&gt;  &lt;img alt="dashboard" src="https://res.cloudinary.com/spiralyze/image/upload/f_auto/RAPID7/1401:%20Metasploit%20Trial%20-%20Redesign/Dashboard_1440.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://sysin.org/#&amp;#29256;&amp;#26412;&amp;#27604;&amp;#36739;" title="&amp;#29256;&amp;#26412;&amp;#27604;&amp;#36739;"&gt;&lt;/a&gt;版本比较&lt;/h2&gt; &lt;h3&gt;  &lt;a href="https://sysin.org/#Open-Source-Metasploit-Framework" title="Open Source: Metasploit Framework"&gt;&lt;/a&gt;Open Source: Metasploit Framework&lt;/h3&gt; &lt;p&gt;  &lt;a href="https://github.com/rapid7/metasploit-framework/wiki/Nightly-Installers" rel="noopener" target="_blank"&gt;Download&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;  &lt;a href="https://sysin.org/#Commercial-Support-Metasploit-Pro" title="Commercial Support: Metasploit Pro"&gt;&lt;/a&gt;Commercial Support: Metasploit Pro&lt;/h3&gt; &lt;p&gt;  &lt;img alt="metasploit-editions-compare" src="https://sysin.org/metasploit-editions-compare.webp"&gt;&lt;/img&gt;&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://sysin.org/#&amp;#19979;&amp;#36733;&amp;#22320;&amp;#22336;" title="&amp;#19979;&amp;#36733;&amp;#22320;&amp;#22336;"&gt;&lt;/a&gt;下载地址&lt;/h2&gt; &lt;p&gt;macOS：metasploit-framework-VERSION.x86_64.pkg  &lt;br /&gt;Windows：metasploit-framework-VERSION-x64.msi  &lt;br /&gt;Linux deb x64：metasploit-framework_VERSION_amd64.deb  &lt;br /&gt;Linux deb x86：metasploit-framework_VERSION_i386.deb  &lt;br /&gt;Linux deb arm64：metasploit-framework_VERSION_arm64.deb  &lt;br /&gt;Linux rpm x64：metasploit-framework-VERSION.el6.x86_64.rpm&lt;/p&gt; &lt;p&gt;百度网盘链接：  &lt;a href="https://pan.baidu.com/s/14jnv2S4EhzdHr3cWnwfNJA" rel="noopener" target="_blank"&gt;https://pan.baidu.com/s/14jnv2S4EhzdHr3cWnwfNJA&lt;/a&gt;  提取码：17p9&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Download macOS Linux Windows Security</category>
      <guid isPermaLink="true">https://itindex.net/detail/62141-metasploit-framework-macos</guid>
      <pubDate>Fri, 04 Mar 2022 15:03:00 CST</pubDate>
    </item>
    <item>
      <title>解决Docker镜像爆满的问题</title>
      <link>https://itindex.net/detail/62114-docker-%E9%95%9C%E5%83%8F-%E9%97%AE%E9%A2%98</link>
      <description>&lt;h2&gt;  &lt;p&gt;使用过docker的人都知道，在正常情况下。我们使用multi-stage构建利用docker镜像缓存机制，可以加快构建速度。&lt;/p&gt;  &lt;p&gt;但是缓存的镜像一多，没有及时释放磁盘空间，磁盘就容易爆满。&lt;/p&gt;  &lt;table&gt;   &lt;tr&gt;    &lt;td&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;    &lt;td&gt;     &lt;pre&gt;[root@report ~]# df -h      &lt;br /&gt;文件系统        容量  已用  可用 已用% 挂载点      &lt;br /&gt;devtmpfs        909M     0  909M    0% /dev      &lt;br /&gt;tmpfs           919M   24K  919M    1% /dev/shm      &lt;br /&gt;tmpfs           919M  752K  919M    1% /run      &lt;br /&gt;tmpfs           919M     0  919M    0% /sys/fs/cgroup      &lt;br /&gt;/dev/vda1        50G  9.6G   38G   21% /      &lt;br /&gt;tmpfs           184M     0  184M    0% /run/user/0      &lt;br /&gt;+overlay          50G  9.6G   38G   21% /var/lib/docker/overlay2/eefc0488163e0d222c384c54041549023a998e3fefeea1c672f0cb9b0f1e78a1/merged      &lt;br /&gt;shm              64M     0   64M    0% /var/lib/docker/containers/ceb6efe9a7cd0563af63ee0b37fb7d7d4f387a46691e7d1d6109876a22fc8b6d/mounts/shm      &lt;br /&gt;+overlay          50G  9.6G   38G   21% /var/lib/docker/overlay2/038df81678b0660a7f3e9eaade223fdd541beff0799bed64437eabe525c4088d/merged      &lt;br /&gt;+overlay          50G  9.6G   38G   21% /var/lib/docker/overlay2/1bd852511b0179c8cc31b9e5a3b6ccf66da6d990a98a1b5ca7874e556f1e384e/merged      &lt;br /&gt;shm              64M     0   64M    0% /var/lib/docker/containers/83e5b18fe998f7ed3ceb4b6328ee427748cd8fd8f1de313222286e3bc125bb15/mounts/shm      &lt;br /&gt;[root@report ~]# docker system df      &lt;br /&gt;TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE      &lt;br /&gt;Images          12        8         3.453GB   903.7MB (26%)      &lt;br /&gt;Containers      9         3         120.3MB   13.79MB (11%)      &lt;br /&gt;Local Volumes   1         1         292.6MB   0B (0%)      &lt;br /&gt;Build Cache     0         0         0B        0B      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;  &lt;p&gt;如果每次构建完手动   &lt;code&gt;docker rmi&lt;/code&gt;又达不到加快构建速度的效果。&lt;/p&gt;  &lt;p&gt;尤其是在持续集成环境中，大家公用一个build machine的时候。大家各自打扫门前雪，更加不会有人care磁盘会不会被占满。 &lt;/p&gt;  &lt;h2&gt;   &lt;a href="https://blog.hufeifei.cn/#fang-fa"&gt;#&lt;/a&gt;方法&lt;/h2&gt;  &lt;p&gt;为了一劳永逸的解决这个问题，最好的办法莫过于通过定时任务来清理旧的image。 这个方法听起来高大上，用起来简单的很。 运行crontab -e命令编辑定时任务。 &lt;/p&gt;  &lt;table&gt;   &lt;tr&gt;    &lt;td&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;    &lt;td&gt;     &lt;pre&gt;crontab -e      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;  &lt;p&gt;在打开的文本编辑器最后添加如下一行，然后保存退出。&lt;/p&gt;  &lt;table&gt;   &lt;tr&gt;    &lt;td&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;    &lt;td&gt;     &lt;pre&gt;0 1 * * * docker image prune -a --force --filter &amp;quot;until=48h&amp;quot;      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;  &lt;p&gt;然后执行下面的命令使定时任务生效。&lt;/p&gt;  &lt;table&gt;   &lt;tr&gt;    &lt;td&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;    &lt;td&gt;     &lt;pre&gt;systemctl restart crond.service      &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;  &lt;p&gt;其实，到这里，整个配置就结束了。接下来我们简单解释一下。   &lt;br /&gt;上面的定时任务是每天夜里1点钟删除2天（48h）之前的image。   &lt;br /&gt;具体的操作时间，具体的image保留时间，可以根据自己的情况修改。&lt;/p&gt;&lt;/h2&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux运维 Linux</category>
      <guid isPermaLink="true">https://itindex.net/detail/62114-docker-%E9%95%9C%E5%83%8F-%E9%97%AE%E9%A2%98</guid>
      <pubDate>Sun, 13 Feb 2022 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>基于 Ubuntu 20.04 部署 1.23版K8S 集群</title>
      <link>https://itindex.net/detail/62033-ubuntu-k8s-%E9%9B%86%E7%BE%A4</link>
      <description>&lt;p&gt;从今天开始，我将开始连载《图解 K8S》入门系列文章&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;
  更多系列文章，可以微信搜索公众号： 写点代码的明哥，回复 k8s 获取全系列教程
&lt;/p&gt;&lt;/blockquote&gt;
 &lt;p&gt;本篇是做为系列的第一篇文章，先来带大家一起搭建一个可用的 K8S 环境。&lt;/p&gt;
 &lt;p&gt;K8S 环境的搭建，是很多想学习 K8S 的人止于在入门之外的第一道门槛，不少人在这一道关上就被直接被劝退了。&lt;/p&gt;
 &lt;p&gt;为什么呢？主要有如下三点：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;strong&gt;网络问题&lt;/strong&gt;：K8S 是 Google 开发的，官方最新镜像都在墙外，安装时下载不了镜像&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;机器问题&lt;/strong&gt;：K8S 运行的组件非常多，对于机器本身有要求，配置不能低，如果要搭建集群，还需要多台机器，是笔不小的开销。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;运维问题&lt;/strong&gt;：K8S 的部署安装和维护，涉及到不少 Linux 及网络相关的内容，需要有一定的运维能力&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;不过在如今，其实已经出现了非常多的 K8S 部署工具，有的是图形化界面安装，也有的甚至做到了一条命令安装。&lt;/p&gt;
 &lt;p&gt;这些工具，给新手提供了一个比较友好的部署解决方案，不过很遗憾的是，我大多没有用过，因为我认为这些工具隐藏了太多原生的 K8S 部署细节，比如安装了哪些组件，是怎么安装的？组件之间的依赖关系，网络是如何走的？&lt;/p&gt;
 &lt;p&gt;而这些细节，对于我们以后进行环境的维护、问题的排查会不小的帮助。&lt;/p&gt;
 &lt;p&gt;因此，我个人从一开始就不建议新手去使用那些太高级的部署工具。。&lt;/p&gt;
 &lt;p&gt;但也不能没有部署工具，所有的组件都手动安装，我想会逼疯很多新手。&lt;/p&gt;
 &lt;p&gt;因此，我这边选用官方推荐的 kubeadm 工具进行演示，带大家一起搭建个可用的 K8S 环境。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115160335896.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h2&gt;1. 环境说明&lt;/h2&gt;
 &lt;p&gt;K8S 环境，可以分为单节点和多节点集群环境两种。&lt;/p&gt;
 &lt;p&gt;单节点的话，部署非常简单，对于一般的学习概念来说，也是够用了，除了一些需要多节点支持的功能，比如 DeamonSet ，比如调度策略验证等&lt;/p&gt;
 &lt;p&gt;而线上生产的环境，都应该是分布式的集群，只是这一套环境搭建下来需要多台的机器。&lt;/p&gt;
 &lt;p&gt;你可以在自己的电脑上创建几台虚拟机，本文我以我的 mac （16 G）为例，创建两台虚拟机，实际上带三台也没有问题，如此你是 windows ，请确保你的配置。&lt;/p&gt;
 &lt;p&gt;当然也可以选择去各大云厂商那里购买机器，个人感觉应该要不少钱，愿意投资的可以上。&lt;/p&gt;
 &lt;p&gt;由于后续肯定会用得上多节点，因此本篇只讲下多节点的集群搭建方法，如果你觉得自己当前想先试试水先学习一下一些基本的内容，可以在本文的评论区留言一下，我考虑剥离出一篇个单节点的 K8S 搭建方法，方法都大同小异。&lt;/p&gt;
 &lt;h2&gt;2. 集群架构&lt;/h2&gt;
 &lt;p&gt;K8S 中节点节点的角色，可以分为两种：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;一种是 控制节点，也即 Master 节点，主要运行控制平面的组件，如 kube-apiserver 等&lt;/li&gt;
  &lt;li&gt;一种是 计算节点，也即 Worker 节点，主要运行业务上的组件，比如 web server 等&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;Master 节点是整个集群的大脑，一个集群只有一个 Master 节点肯定是不行的，通常来说，要至少三个，做下高可用。&lt;/p&gt;
 &lt;p&gt;但由于我们仅仅是学习之用，没有集群稳定安全性考虑，这里就不需要浪费资源去搞高可用。&lt;/p&gt;
 &lt;p&gt;因此，我的集群是一个 Master 节点，N 个 Worker 节点（下文中仅演示一个 worker 的部署，多个 worker 类似），管理网段是 172.20.20.0/24，ip 如图所示&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115154309179.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h2&gt;3. 网络环境&lt;/h2&gt;
 &lt;p&gt;集群的安装需要联网下载很多的镜像，因此在开始安装之前请保证你的所有节点都可以正常联网。&lt;/p&gt;
 &lt;p&gt;对于在云厂商购买的云主机来说，都有公网 ip，这个自不用担心。&lt;/p&gt;
 &lt;p&gt;可对于在本地电脑上创建的虚拟机做为 K8S 节点的朋友，可以跟着我一起操作。&lt;/p&gt;
 &lt;p&gt;我的个人电脑是 最新款（2021）的 Macbook M1 Pro 内存仅有 16 G，现在我的电脑上已经安装好Mac 上的桌面虚拟化软件  Parallels Desktop，在 Parallels Desktop 的入口就可以下载 Ubuntu 20.04 ，请注意，这边下载的是桌面版的 Linux，本来我机器配置就不高，再使用桌面版的，实在太消耗资源了。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220114000344874.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;可以在这里下载服务器版的 Ubuntu：https://ubuntu.com/download/server/arm，会小很多，只有 1.1G。&lt;/p&gt;
 &lt;p&gt;下载完成后，可以自行安装，相信大多数人都知道如何操作，明哥这里就不会多费口舌，不懂的在留言区交流吧&lt;/p&gt;
 &lt;p&gt;等虚拟机安装完成后，别着急启动，可以先配置下网段。&lt;/p&gt;
 &lt;p&gt;如下图所示 点  &lt;code&gt;网络&lt;/code&gt; -&amp;gt;   &lt;code&gt;高级&lt;/code&gt;，再点打开   &lt;code&gt;网络首选项&lt;/code&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220114234334048.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;将桥接（Shared）的网络改为 172.20.20.0/24，也即 172.20.20.1-172.20.20.254&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220114234430742.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;一旦你修改后，Paralles Desktop 就会感知，并修改本机上 bridge100 的 ip 地址为 172.20.20.0/24 里的 ip，这里分配的 ip 是 172.20.20.2，与虚拟机的网络在同一网段，如此一来，宿主机就能和虚拟机进行通信。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220114234653073.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;网络配置好后，正常启动虚拟机，可以看到虚拟机已经自动配置上 172.20.20.3 的 ip，这是怎么做到的呢？&lt;/p&gt;
 &lt;p&gt;原来在 netplan 的配置文件中 /etc/netplan/00-installer-config.yaml，配置了 enp0s5 启用 dhcp 获取 ip。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image-20220114233633735" src="http://image.iswbm.com/image-20220114233633735.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这种动态获取的 ip，会导致同一节点在不同时间、场景下获取到的 ip 可能是不一样的。&lt;/p&gt;
 &lt;p&gt;对于 K8S 集群环境来说，管理网络的 ip 应该固定的，否则会造成通信的混乱。&lt;/p&gt;
 &lt;p&gt;因此我们应该把规划好的 ip 地址写死到配置文件中，写好后，使用 netplan apply 使之生效&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220114234038804.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;由于 ip 发生了变化，因此重启网络后，当前的 ssh 连接会断网,退出后，再次使用 172.20.20.200 就可以再次登陆，会发现 enp0s5 的 ip 已经按预期配置成 172.20.20.200 了。&lt;/p&gt;
 &lt;p&gt;尝试 ping 114.114.114.114 ，发现网络是不通的，这是为什么呢？&lt;/p&gt;
 &lt;p&gt;原来上面在 netplan 的配置文件中并没有指明网关地址，那网关地址是多少呢？&lt;/p&gt;
 &lt;p&gt;此时我们回想之间 bridge100 的 ip 是 172.20.20.2 ，为什么不是我们定义的 172.20.20.0/24 网段的第一个 ip 172.20.20.1  呢？&lt;/p&gt;
 &lt;p&gt;这是因为这个 ip 被 PD 拿去做网关了，因此我们只要往配置文件中加上网关再重新 netplan apply 即可&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115104935290.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;完整的配置文件如下&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;# /etc/netplan/00-installer-config.yaml
network:
  ethernets:
    enp0s5:
      dhcp4: no
      addresses: [172.20.20.200/24]
      optional: true
      gateway4: 172.20.20.1
      nameservers:
        addresses: [114.114.114.114]
  version: 2
&lt;/code&gt;&lt;/pre&gt;
 &lt;h2&gt;4. 基础环境&lt;/h2&gt;
 &lt;h3&gt;4.1 关闭 swapoff&lt;/h3&gt;
 &lt;p&gt;在旧版的 k8s 中 kubelet 都要求关闭 swapoff ，但最新版的 kubelet 其实已经支持 swap ，因此这一步其实可以不做。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;iswbm@master:~sudo swapoff -a

# 修改/etc/fstab，注释掉swap那行，持久化生效
iswbm@master:~ sudo vim /etc/fstab
&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;4.2 修改时区&lt;/h3&gt;
 &lt;p&gt;修改一下时区，由原来的 UTC 变成了 CST，中间差了 8 个小时&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;iswbm@master:~date
Sat 15 Jan 2022 02:22:44 AM UTC
iswbm@master:~ sudo timedatectl set-timezone Asia/Shanghai
iswbm@master:~$ date
Sat 15 Jan 2022 10:22:55 AM CST
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;修改后，如果想使得系统日志的时间戳也立即生效，由重启 rsyslog&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;iswbm@master:~$ sudo systemctl restart rsyslog
&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;4.3 设置内核参数&lt;/h3&gt;
 &lt;p&gt;首先确认你的系统已经加载了 br_netfilter 模块，默认是没有该模块的，需要你先安装 bridge-utils&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;sudo apt-get install -y bridge-utils
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;然后再使用 modprobe 加载一下， lsmod 就能看到 br_netfilter 模块，此时再确认一下 内核参数 net.bridge.bridge-nf-call-iptables 是否为 1。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115110938052.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在Ubuntu 20.04 Server上，这个值就是1。如果你的系统上不一致，使用下面的命令来修改：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;cat &amp;lt;&amp;lt;EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
&lt;/code&gt;&lt;/pre&gt;
 &lt;h2&gt;5. 基础软件&lt;/h2&gt;
 &lt;blockquote&gt;  &lt;p&gt;
  本小节的步骤在 master 及 worker 执行
&lt;/p&gt;&lt;/blockquote&gt;
 &lt;h3&gt;5.1  安装 Docker&lt;/h3&gt;
 &lt;p&gt;目前的 Ubuntu 已经有提供 Docker 的安装包，直接安装即可&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;# 安装 docker
iswbm@master:~sudo apt install docker.io

# 启动 docker 
iswbm@master:~ sudo systemctl start docker

# 开机自启
iswbm@master:~$ sudo systemctl enable docker
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;如果是旧版的 Ubuntu 还是建议按照官网(https://docs.docker.com/engine/install/ubuntu/)的操作去安装&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115111904248.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;但  ubuntu 20.04 源里提供的 Docker 版本还是比较新的，是 20.10.7，可以直接使用，我从 Docker 官网里看到的当前最新 Docker 版本是 20.10.12，只是差了几个小版本，区别不大。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;iswbm@master:~$ docker --version
Docker version 20.10.7, build 20.10.7-0ubuntu5~20.04.2
&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;5.2 安装 kubeadm kubectl&lt;/h3&gt;
 &lt;p&gt;以下操作在 master和 worker 节点 上执行，由于谷歌的源和 repo 在国内的是无法访问的，因此这里需要切换为 阿里源。&lt;/p&gt;
 &lt;p&gt;按顺序执行如下几条命令&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;# 安装基础软件并设置源
iswbm@master:~sudo apt-get install -y ca-certificates curl software-properties-common apt-transport-https curl
iswbm@master:~ curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
iswbm@master:~sudo tee /etc/apt/sources.list.d/kubernetes.list &amp;lt;&amp;lt;EOF
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

# 刷新软件列表，然后直接安装
iswbm@master:~ sudo apt-get update
iswbm@master:~sudo apt-get install -y kubelet kubeadm kubectl

# 阻止自动更新(apt upgrade时忽略)。所以更新的时候先unhold，更新完再hold。
iswbm@master:~ sudo apt-mark hold kubelet kubeadm kubectl
&lt;/code&gt;&lt;/pre&gt;
 &lt;h2&gt;6. 构建集群&lt;/h2&gt;
 &lt;h3&gt;6.1 部署 master&lt;/h3&gt;
 &lt;p&gt;网上 90% 的文章，都是使用 kubeadm init 加各种参数实现的部署，只要一条命令即可实现，就像这样&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;sudo kubeadm init --pod-network-cidr 172.16.0.0/16 \
    --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
    --apiserver-advertise-address 172.20.20.200 \
    --apiserver-bind-port 6443 
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;但这样的部署命令，在较新版本的 k8s （maybe 1.22 +）中是会部署失败的。&lt;/p&gt;
 &lt;p&gt;原因是 kubeadm 默认会将kubelet 的 cgroupDriver 字段设置为 systemd，&lt;/p&gt;
 &lt;p&gt;如果设置为 systemd ，kubelet 会启动不了。&lt;/p&gt;
 &lt;p&gt;经过我的摸索，kubeadm init 应该使用配置文件的方式进行部署&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;iswbm@master:~$ sudo kubeadm init --config kubeadm-config.yaml
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;而如果你安装的是旧版的 k8s ，则不用使用上面的方式，直接&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;sudo kubeadm init --pod-network-cidr 172.16.0.0/16 \
    --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
    --apiserver-advertise-address 172.20.20.200 \
    --apiserver-bind-port 6443 \
    --token-ttl 0
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;关于 kubeadm 更多常用的参数及中文解释我整理如下&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115114541775.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;咱们的目的是学习，对版本没有要求，就直接上最新版，因此只能用这种方式安装&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;iswbm@master:~$ sudo kubeadm init --config kubeadm-config.yaml
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;而这个 kubeadm-config.yaml 配置文件从哪里获取呢？我准备好一个，可以直接点这里进行下载 https://wwe.lanzout.com/iITg2yt0imd&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;
     &lt;code&gt;kubeadm config print init-defaults&lt;/code&gt; 打印默认配置
&lt;/p&gt;&lt;/blockquote&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115123827184.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;执行完成后，会提醒你做三件事&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115124857562.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第一件事：配置环境变量&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;以便你能正常使用 kubectl 进行集群的操作，对于常规用户用如下命令&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;mkdir -p HOME/.kube
sudo cp -i /etc/kubernetes/admin.confHOME/.kube/config
sudo chown (id -u):(id -g) $HOME/.kube/config
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;对于 root 用户，执行如下命令&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;export KUBECONFIG=/etc/kubernetes/admin.conf
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;第二件事：将节点加入集群&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;后面我们要将 worker 节点加入集群，就要执行这条命令&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;sudo kubeadm join 172.20.20.200:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:4e4a7d0e848ae6c047d163fbe07f0e6975d71cc156d7705649241a59bbecaa04
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;这条命令是有有效期的，需要的时候，可以执行如下命令进行获取&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;kubeadm token create --print-join-command
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;到此，你的集群已经安装好了，可以查看一下集群的基本情况&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115125016189.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第三件事：部署网络插件&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;这个我在图中没有圈出来，但它也是非常重要的，我放到   &lt;strong&gt;6.3 部署 calico&lt;/strong&gt; 这节里去做。&lt;/p&gt;
 &lt;h3&gt;6.2 部署 worker&lt;/h3&gt;
 &lt;p&gt;相比 master ，worker 的部署就简单许多了。&lt;/p&gt;
 &lt;p&gt;只要安装好了 docker、kubelet、kubeadm 软件，就可以执行前面的 join 命令直接加入集群&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;sudo kubeadm join 172.20.20.200:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:4e4a7d0e848ae6c047d163fbe07f0e6975d71cc156d7705649241a59bbecaa04
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;完成之后，再到 master 上查看 node ，若可以看到 worker 说明成功将 worker 加入集群中&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115143416848.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;6.3 部署 Calico&lt;/h3&gt;
 &lt;p&gt;上面其他我们已经部署好了 K8S 集群，但是由于还没有安装网络插件，因此整个集群实际上还是不能工作的，通过 kubectl get nodes 可以看到虽然已经有两个节点，但 Status 却都还是 NotReady 。&lt;/p&gt;
 &lt;p&gt;K8S 的网络插件有很多，常见的有   &lt;code&gt;flannel&lt;/code&gt;、  &lt;code&gt;calico&lt;/code&gt;、  &lt;code&gt;cilium&lt;/code&gt;、  &lt;code&gt;kube-ovn&lt;/code&gt; 等等。&lt;/p&gt;
 &lt;p&gt;更多支持的 CNI 可以在官方文档上找到列表：https://kubernetes.io/docs/concepts/cluster-administration/addons/&lt;/p&gt;
 &lt;p&gt;我大概数了一下，多达 16 个网络插件，太可怕了。&lt;/p&gt;
 &lt;p&gt;K8S 拥有如此多多的 CNI 网络插件，该如何做好CNI的技术选型，一个团队需要投入大量的精力进行调研。&lt;/p&gt;
 &lt;p&gt;Flannel 是 由CoreOS开发 的，K8S 最基础的网络插件，但是功能有限，一般仅供初学者学习使用，在生产中不推荐使用。&lt;/p&gt;
 &lt;p&gt;而其他的，Calico 是比较主流的选择（实际上我们公司使用的是 kube-ovn），因此我这里选择 Calico 进行安装&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="img" src="https://cdn.thenewstack.io/media/2020/03/51d8b8c6-ebpf-dp.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;安装 Calico 只需要一条命令即可。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;kubectl apply -f https://docs.projectcalico.org/v3.21/manifests/calico.yaml
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;安装完成后，会创建出这几个 Pod&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;iswbm@master:~$ kubectl get pod -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-85b5b5888d-dbptz   1/1     Running   0          3m33s
kube-system   calico-node-8jt69                          1/1     Running   0          3m33s
kube-system   calico-node-t69qb                          1/1     Running   0          3m33s
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;同时之前由于没有安装网络插件而失败的 coredns pod 也开始成功拉起了&lt;/p&gt;
 &lt;p&gt;网络 ok 后，再次确认下集群的环境&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;所有的 Pod 均已 Running&lt;/li&gt;
  &lt;li&gt;所有的 node 均已 Ready&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115151114215.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h2&gt;7. 验收集群&lt;/h2&gt;
 &lt;p&gt;关于 Pod 的概念，我将在后面慢慢介绍，现在你只要知道，Pod 是一个 K8S 最核心的资源对象，是最小的调度单位。&lt;/p&gt;
 &lt;p&gt;如果可以在 K8S 集群里，成功创建一个 Pod ，那就说明，你这个集群是健康的、可用的。&lt;/p&gt;
 &lt;p&gt;使用如下命令就可以创建一个最简单的 nginx pod&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;simple.pod 的 yaml 简单内容如下&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;执行后，通过 kubectl get pod 可以 观察到状态的变化&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115152133782.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;通过加   &lt;code&gt;-o wide&lt;/code&gt; 可以查看 pod 的 ip，再使用 curl，就可以访问这个 nginx 服务&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://image.iswbm.com/image-20220115152504605.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;至此，我们创建了第一个 pod 的，集群搭建完成。&lt;/p&gt;
 &lt;p&gt;恭喜你，已经完成了你学习 K8S 最艰难的一步 —   &lt;strong&gt;环境搭建&lt;/strong&gt;&lt;/p&gt;
 &lt;h2&gt;8. 写在最后&lt;/h2&gt;
 &lt;p&gt;本文虽然是在 mac 操作系统下进行演示，但机器对于搭建 K8S 集群本身并没有什么区别，最多也就虚拟机网络配置那里有所区别，但我相信这些对于正经的程序员来说，绝对不是什么难题。&lt;/p&gt;
 &lt;p&gt;本文完整复现了 K8S 集群的搭建过程，经历了   &lt;code&gt;自己搭建&lt;/code&gt; – &amp;gt;   &lt;code&gt;问题排查解决&lt;/code&gt; – &amp;gt;  &lt;code&gt;素材收集整理&lt;/code&gt; -&amp;gt;   &lt;code&gt;撰写文章&lt;/code&gt; ，全文经过多次修缮，前前后后一共花费了 6 个多小时的时间，才形成此文，可以达到让一个没有运维能力的纯新手也能无痛学习。&lt;/p&gt;
 &lt;p&gt;一篇文章的产出，需要经过如此长的时间，更新频率自然小很多，其实我也在考虑，之后要以一种怎样的风格来完成这个系列，是类似这样的万字长文呢？还是日更级别的，每天 5 分钟学习 K8S 呢？&lt;/p&gt;
 &lt;p&gt;对于我来说，我更倾向于前者，这样才能有条件把一个知识给讲透，而且能让你感受到我写这个系列的诚意。&lt;/p&gt;
 &lt;p&gt;但从读者的角度来看，应该是后者，更新频率太低，读者的脑子会断层，一个星期前的新知识，现在可能忘得差不多了。&lt;/p&gt;
 &lt;p&gt;你是怎么想的呢？欢迎你在评论区给我建议。&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;
  更多系列文章，可以微信搜索公众号： 写点代码的明哥，回复 k8s 获取全系列教程
&lt;/p&gt;&lt;/blockquote&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Kubernetes k8s Linux 投资 网络</category>
      <guid isPermaLink="true">https://itindex.net/detail/62033-ubuntu-k8s-%E9%9B%86%E7%BE%A4</guid>
      <pubDate>Sat, 15 Jan 2022 16:16:19 CST</pubDate>
    </item>
    <item>
      <title>Linux性能：为什么你应该添加交换空间swap</title>
      <link>https://itindex.net/detail/61885-linux-%E6%80%A7%E8%83%BD-%E4%BA%A4%E6%8D%A2</link>
      <description>&lt;img alt="Linux&amp;#24615;&amp;#33021;&amp;#65306;&amp;#20026;&amp;#20160;&amp;#20040;&amp;#20320;&amp;#24212;&amp;#35813;&amp;#28155;&amp;#21152;&amp;#20132;&amp;#25442;&amp;#31354;&amp;#38388;swap" src="https://www.myfreax.com/content/images/2021/11/linux-swap.jpeg"&gt;&lt;/img&gt; &lt;p&gt;我们知道使用Linux交换空间而不是 RAM（内存）会严重降低性能。那么，有人可能会问，既然我有足够多的可用内存，删除交换空间不是更好吗？简短的回答是不会。启用交换空间会带来性能优势，即使您有足够多的内存。&lt;/p&gt; &lt;p&gt;即使安装了足够多的服务器内存，您也会经常发现在长时间正常运行后会使用交换空间。请参阅以下来自具有大约一个月正常运行时间的实时聊天服务器的示例：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;              total        used        free      shared  buff/cache   available
Mem:           3.7G        1.0G        445M         84M        2.2G        2.2G
Swap:          1.8G        308M        1.5G&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;strong&gt;   &lt;code&gt;free -h&lt;/code&gt;&lt;/strong&gt;这里的输出显示使用了 308M 的交换空间。当我运行swapping检查时，没有迹象表明正在进行或不合时宜的swap I/O活动。此外，kswap服务并没有消耗太多 CPU 时间。实际上，在top（按 CPU 时间排序的顶级进程）中找不到kswap进程。为了确认，我使用了  &lt;a href="https://www.myfreax.com/ps-command-in-linux/"&gt;ps命令&lt;/a&gt;：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;ps -A | grep kswap
40 ? 00:00: 29 kswapd0&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;...所以在这种情况下，与许多情况一样，swap使用不会降低Linux服务器的性能。现在，让我们看看交换空间实际上如何改善Linux服务器性能。&lt;/p&gt; &lt;h2&gt;在具有足够RAM的系统上交换空间的优点&lt;/h2&gt; &lt;img alt="Linux&amp;#24615;&amp;#33021;&amp;#65306;&amp;#20026;&amp;#20160;&amp;#20040;&amp;#20320;&amp;#24212;&amp;#35813;&amp;#28155;&amp;#21152;&amp;#20132;&amp;#25442;&amp;#31354;&amp;#38388;swap" src="https://www.myfreax.com/content/images/2021/11/image-11.png"&gt;&lt;/img&gt; &lt;p&gt;即使仍有可用的 RAM，Linux系统使用一些swap也是正常的并且是一件好事。Linux 内核会将  &lt;strong&gt;   &lt;em&gt;几乎从未使用过的内存页面&lt;/em&gt;&lt;/strong&gt;移动到交换空间中，以确保在内存中为更频繁使用的内存页面提供更多可缓存空间（一个页面就是一块内存）。当内核被迫不断地将内存页面移入和移出内存和交换空间swap时，交换使用会成为一个性能问题。&lt;/p&gt; &lt;p&gt;另一个优点是swap让管理员有时间对低内存问题做出反应。我们经常会注意到服务器运行缓慢，并且在登录时会注意到大量交换。如果没有交换（如下一节所述），内存不足会产生更加突然和严重的连锁反应。所以我会建议将交换空间设置为您最大进程的大小。比如mysql在my.cnf中配置的内存。&lt;/p&gt; &lt;p&gt;有些人建议不要交换或交换大小略大于总RAM。如果您能为此提出正当理由，那么这可能是您的选择。但是，这在服务器上几乎不是这种情况，您应该在您的决定与  &lt;strong&gt;Swap&lt;/strong&gt;对您的特定应用程序的影响之间取得平衡。  &lt;strong&gt;Swap不会改变服务器所需的 RAM 量&lt;/strong&gt;。它旨在改善系统的性能。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;总结：&lt;/strong&gt;  &lt;br /&gt;— 即使仍有可用的RAM，Linux内核也会将几乎从未使用过的内存页移动到交换空间中。  &lt;br /&gt;— 最好换出一段时间不活动的内存页，将经常使用的数据保留在缓存中，这应该发生在服务器最空闲的时候，这是内核的目标。  &lt;br /&gt;— 避免将交换空间设置得太大，否则会导致性能问题、中断或响应时间延长。&lt;/p&gt; &lt;h2&gt;当可用内存不足时，交换空间与不使用交换空间&lt;/h2&gt; &lt;p&gt;与上面的情况不同，如果您没有足够的内存，则在任何内存需求高峰期间，交换将被频繁使用并且明显更多。如果您没有足够的内存并且没有交换空间，这通常会导致无法为需要更多内存页的请求分配内存。作为最后的手段，内核将部署   &lt;a href="http://www.oracle.com/technetwork/articles/servers-storage-dev/oom-killer-1911807.html" rel="noopener noreferrer"&gt;OOM杀手&lt;/a&gt;来攻击高内存进程（通常是 MySQL、java 等）。&lt;/p&gt; &lt;p&gt;要更详细地了解Linux交换空间  &lt;strong&gt;Swap&lt;/strong&gt;，请阅读  &lt;a href="https://www.kernel.org/" rel="noopener noreferrer"&gt;Kernel.org&lt;/a&gt;文档中的  &lt;a href="https://www.kernel.org/doc/gorman/html/understand/understand014.html" rel="noopener noreferrer"&gt;交换管理&lt;/a&gt;和Page Frame  &lt;a href="https://www.kernel.org/doc/gorman/html/understand/understand013.html" rel="noopener noreferrer"&gt;回收&lt;/a&gt;章节。如果您的交换空间“已使用”始终为“0”，那么您确实有大量自由可用的 RAM，在这种情况下，删除交换空间可能是最好的。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;总结：&lt;/strong&gt;  &lt;br /&gt;—   &lt;strong&gt;Swap&lt;/strong&gt; I/O的扩展性很差。如果仅在服务器空闲时无法交换内存页，则应调整或禁用  &lt;strong&gt;Swap&lt;/strong&gt;。  &lt;br /&gt;— 禁用  &lt;strong&gt;Swap&lt;/strong&gt;后，性能问题会很快变得明显，OOM杀手可能会抓住你！:)&lt;/p&gt; &lt;p&gt;为了进行比较，以下是在同一服务器上使用来自  &lt;a href="https://sourceforge.net/projects/procps-ng/files/Production/" rel="noopener noreferrer"&gt;procps-ng-3.3.1&lt;/a&gt;的旧版free的输出：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;             total       used       free     shared    buffers     cached
Mem:          3.7G       3.3G       445M         0B       4.2M       1.7G
-/+ buffers/cache:       1.6G       2.1G
Swap:         1.8G       308M       1.5G&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;内核缓存压力和交换&lt;/h2&gt; &lt;p&gt;现在您已启用交换。考虑按照以下指南调整服务器的缓存压力和swap   &lt;a href="https://access.redhat.com/solutions/103833" rel="noopener noreferrer"&gt;vm.swappiness&lt;/a&gt;。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;vfs_cache_pressure &lt;/strong&gt; – 控制内核回收内存的频率，用于缓存目录和inode对象。（默认值 = 100，推荐值 50 到 200）&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;swappiness – &lt;/strong&gt;此值用于定义内核交换内存页面的积极程度。较高的值会增加攻击性；较低的值会减少交换量。（默认值 = 60，推荐值在 1 到 60 之间）删除 0 值的交换，但在大多数情况下通常不推荐。&lt;/p&gt; &lt;p&gt;要编辑，您可以在  &lt;strong&gt;/etc/sysctl.conf&lt;/strong&gt;文件中添加或替换这些行 。例如，如果您在升级前内存不足，您可以尝试以下操作：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;vm.swappiness=10
vm.vfs_cache_pressure=200&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这将增加缓存压力，这似乎有些适得其反，因为缓存对性能有好处。但是，过于频繁的交换会显着降低服务器的整体性能。因此，不在内存中保留尽可能多的缓存将有助于减少交换活动。此外，将 vm.swappiness设置为10或低至 1，将减少磁盘交换。&lt;/p&gt; &lt;p&gt;在具有大量可用内存的服务器上，使用以下命令：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;vm.swappiness=10
vm.vfs_cache_pressure=50&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这将降低缓存压力。由于缓存对性能有好处，我们希望将缓存数据在内存中保留更长时间。由于缓存会变大，我们仍然希望减少交换以不增加交换 I/O。&lt;/p&gt; &lt;p&gt;要使用这些命令检查当前值，请使用：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;sudo cat /proc/sys/vm/swappiness
sudo cat /proc/sys/vm/vfs_cache_pressure&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;要在不重新启动的情况下临时启用这些设置，请使用以下命令：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;sudo sysctl -w vm.swappiness=10
sudo sysctl -w vm.vfs_cache_pressure=50&lt;/code&gt;&lt;/pre&gt; &lt;a href="https://www.myfreax.com/tag/swap/"&gt;  &lt;div&gt;   &lt;div&gt;swap - myfreax&lt;/div&gt;   &lt;div&gt;&lt;/div&gt;   &lt;div&gt;    &lt;img alt="Linux&amp;#24615;&amp;#33021;&amp;#65306;&amp;#20026;&amp;#20160;&amp;#20040;&amp;#20320;&amp;#24212;&amp;#35813;&amp;#28155;&amp;#21152;&amp;#20132;&amp;#25442;&amp;#31354;&amp;#38388;swap" src="https://www.myfreax.com/assets/images/favicon-192.png?v=fe03fbbefe"&gt;&lt;/img&gt;myfreax 15 Dec 2020 • 4 min readmyfreax&lt;/div&gt;&lt;/div&gt;  &lt;div&gt;   &lt;img alt="Linux&amp;#24615;&amp;#33021;&amp;#65306;&amp;#20026;&amp;#20160;&amp;#20040;&amp;#20320;&amp;#24212;&amp;#35813;&amp;#28155;&amp;#21152;&amp;#20132;&amp;#25442;&amp;#31354;&amp;#38388;swap" src="https://www.myfreax.com/content/images/size/w600/2020/12/how-to-add-swap-space-on-ubuntu-20-04.jpg"&gt;&lt;/img&gt;&lt;/div&gt;&lt;/a&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>linux swap 交换空间 性能 内存</category>
      <guid isPermaLink="true">https://itindex.net/detail/61885-linux-%E6%80%A7%E8%83%BD-%E4%BA%A4%E6%8D%A2</guid>
      <pubDate>Tue, 09 Nov 2021 14:08:02 CST</pubDate>
    </item>
    <item>
      <title>Burp Suite Pro 2021.10 (macOS, Linux) -- 查找、发现和利用漏洞</title>
      <link>https://itindex.net/detail/61867-burp-suite-pro</link>
      <description>&lt;p&gt;请访问原文链接：  &lt;a href="https://sysin.org/blog/burp-suite-pro-2021/" title="Burp Suite Pro 2021 (macOS, Linux) -- &amp;#26597;&amp;#25214;&amp;#12289;&amp;#21457;&amp;#29616;&amp;#21644;&amp;#21033;&amp;#29992;&amp;#28431;&amp;#27934;"&gt;Burp Suite Pro 2021 (macOS, Linux) -- 查找、发现和利用漏洞&lt;/a&gt;，查看最新版。原创作品，转载请保留出处。&lt;/p&gt; &lt;p&gt;作者：gc(at)sysin.org，主页：  &lt;a href="https://sysin.org"&gt;www.sysin.org&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://sysin.org/#&amp;#31616;&amp;#20171;" title="&amp;#31616;&amp;#20171;"&gt;&lt;/a&gt;简介&lt;/h2&gt; &lt;p&gt;Burp Suite Professional 是一套用于测试 web 安全性的高级工具集 —- 所有这些都在一个产品中。从一个基本的拦截代理到尖端的 Burp 扫描器，使用 Burp Suite Pro，正确的工具只需点击一下就可以了。&lt;/p&gt; &lt;p&gt;我们强大的自动化让您有更多的机会做您最擅长的，而 Burp Suite 处理容易实现的目标。先进的手动工具将帮助你识别目标更微妙的盲点。&lt;/p&gt; &lt;p&gt;Burp Suite Pro 是由一个研究团队开发的。这意味着在我们发布之前，发现成果已经包含在我们的最新更新中。我们的 pentesting 工具将使您的工作更快，同时让您了解最新的攻击向量。&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://sysin.org/#&amp;#21151;&amp;#33021;&amp;#20171;&amp;#32461;" title="&amp;#21151;&amp;#33021;&amp;#20171;&amp;#32461;"&gt;&lt;/a&gt;功能介绍&lt;/h2&gt; &lt;h3&gt;  &lt;a href="https://sysin.org/#Manual-penetration-testing-features-&amp;#25163;&amp;#21160;&amp;#28183;&amp;#36879;&amp;#27979;&amp;#35797;&amp;#21151;&amp;#33021;" title="Manual penetration testing features &amp;#25163;&amp;#21160;&amp;#28183;&amp;#36879;&amp;#27979;&amp;#35797;&amp;#21151;&amp;#33021;"&gt;&lt;/a&gt;Manual penetration testing features 手动渗透测试功能&lt;/h3&gt; &lt;p&gt;  &lt;img alt="Burp Suite Pro proxy interception" src="https://portswigger.net/burp/pro/features/images/proxy-interception.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Intercept everything your browser sees&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;A powerful proxy/history lets you modify all HTTP(S) communications passing through your browser.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Manage recon data&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;All target data is aggregated and stored in a target site map - with filtering and annotation functions.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Expose hidden attack surface&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Find hidden target functionality with an advanced automatic discovery function for “invisible” content.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Test for clickjacking attacks&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Generate and confirm clickjacking attacks for potentially vulnerable web pages, with specialist tooling.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Work with WebSockets&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;WebSockets messages get their own specific history - allowing you to view and modify them.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Break HTTPS effectively&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Proxy even secure HTTPS traffic. Installing your unique CA certificate removes associated browser security warnings.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Manually test for out-of-band vulnerabilities&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Make use of a dedicated client to incorporate Burp Suite’s out-of-band (OAST) capabilities during manual testing.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Speed up granular workflows&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Modify and reissue individual HTTP and WebSocket messages, and analyze the response - within a single window.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Quickly assess your target&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Determine the size of your target application. Auto-enumeration of static and dynamic URLs, and URL parameters.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Assess token strength&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Easily test the quality of randomness in data items intended to be unpredictable (e.g. tokens).&lt;/p&gt; &lt;hr&gt;&lt;/hr&gt; &lt;h3&gt;  &lt;a href="https://sysin.org/#Advanced-custom-automated-attacks-&amp;#39640;&amp;#32423;-&amp;#33258;&amp;#23450;&amp;#20041;&amp;#33258;&amp;#21160;&amp;#25915;&amp;#20987;" title="Advanced/custom automated attacks &amp;#39640;&amp;#32423;/&amp;#33258;&amp;#23450;&amp;#20041;&amp;#33258;&amp;#21160;&amp;#25915;&amp;#20987;"&gt;&lt;/a&gt;Advanced/custom automated attacks 高级/自定义自动攻击&lt;/h3&gt; &lt;ul&gt;  &lt;li&gt;Faster brute-forcing and fuzzing&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Deploy custom sequences of HTTP requests containing multiple payload sets. Radically reduce time spent on many tasks.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Query automated attack results&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Capture automated results in customized tables, then filter and annotate to find interesting entries/improve subsequent attacks.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Construct CSRF exploits&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Easily generate CSRF proof-of-concept attacks. Select any suitable request to generate exploit HTML.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Facilitate deeper manual testing&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;See reflected/stored inputs even when a bug is not confirmed. Facilitates testing for issues like XSS.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Scan as you browse&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The option to passively scan every request you make, or to perform active scans on specific URLs.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Automatically modify HTTP messages&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Settings to automatically modify responses. Match and replace rules for both responses and requests.&lt;/p&gt; &lt;p&gt;  &lt;img alt="Burp Suite Pro Intruder payload positions" src="https://portswigger.net/burp/pro/features/images/payload.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;hr&gt;&lt;/hr&gt; &lt;h3&gt;  &lt;a href="https://sysin.org/#Automated-scanning-for-vulnerabilities-&amp;#33258;&amp;#21160;&amp;#25195;&amp;#25551;&amp;#28431;&amp;#27934;" title="Automated scanning for vulnerabilities &amp;#33258;&amp;#21160;&amp;#25195;&amp;#25551;&amp;#28431;&amp;#27934;"&gt;&lt;/a&gt;Automated scanning for vulnerabilities 自动扫描漏洞&lt;/h3&gt; &lt;p&gt;  &lt;img alt="Burp Suite Pro scan results" src="https://portswigger.net/burp/pro/features/images/scan-results.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Harness pioneering AST technology&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;High signal: low noise. Scan with pioneering, friction-free,   &lt;a href="https://portswigger.net/burp/application-security-testing/oast" rel="noopener" target="_blank"&gt;out-of-band-application security testing (OAST)&lt;/a&gt;.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Conquer client-side attack surfaces&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Hybrid AST and built-in JavaScript analysis engine help to find holes in client-side attack surfaces.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Fuel vulnerability coverage with research&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Cutting-edge scan logic from PortSwigger Research combines with coverage of over 100 generic bugs.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Fine-tune scan control&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Get fine-grained control, with a user-driven scanning methodology. Or, run “point-and-click” scans.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Remediate bugs effectively&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Custom descriptions and step-by-step remediation advice for every bug, from   &lt;a href="https://portswigger.net/research" rel="noopener" target="_blank"&gt;PortSwigger Research&lt;/a&gt;.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Configure scan behavior&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Customize what you audit, and how. Skip specific checks, fine-tune insertion points, and much more.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Navigate difficult applications&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Crawl more complex targets. Burp Suite’s crawler identifies locations based on content - not just URL.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Effectively apply IAST&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Source identification and vulnerability reporting simplified, with optional code instrumentation.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Experience browser-driven scanning&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Browser-driven scanning is already striding toward better coverage of tricky targets like AJAX-heavy single page apps.&lt;/p&gt; &lt;hr&gt;&lt;/hr&gt; &lt;h3&gt;  &lt;a href="https://sysin.org/#Productivity-tools-&amp;#29983;&amp;#20135;&amp;#21147;&amp;#24037;&amp;#20855;" title="Productivity tools &amp;#29983;&amp;#20135;&amp;#21147;&amp;#24037;&amp;#20855;"&gt;&lt;/a&gt;Productivity tools 生产力工具&lt;/h3&gt; &lt;ul&gt;  &lt;li&gt;Deep-dive message analysis&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Show follow-up, analysis, reference, discovery, and remediation in a feature-rich HTTP editor.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Utilize both built-in and custom configurations&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Access predefined configurations for common tasks, or save and reuse custom configurations.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Multiply project options&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Auto-save all working projects to disk, and add configurations to pre-saved projects.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Make code more readable&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Automatically pretty-print code formats including JSON, JavaScript, CSS, HTML, and XML.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Easily remediate scan results&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;See source, discovery, contents, and remediation, for every bug, with aggregated application data.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Simplify scan reporting&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Customize with HTML/XML formats. Report all evidence identified, including issue details.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Speed up data transformation&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Decode or encode data, with multiple built-in operations (e.g. Hex, Octal, Base64).&lt;/p&gt; &lt;p&gt;  &lt;img alt="Burp Suite Pro pretty-printing" src="https://portswigger.net/burp/pro/features/images/pretty-print.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;hr&gt;&lt;/hr&gt; &lt;h3&gt;  &lt;a href="https://sysin.org/#Extensions-&amp;#25193;&amp;#23637;" title="Extensions &amp;#25193;&amp;#23637;"&gt;&lt;/a&gt;Extensions 扩展&lt;/h3&gt; &lt;p&gt;  &lt;img alt="PortSwigger BApp Store" src="https://portswigger.net/burp/pro/features/images/bapp-store.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Create custom extensions&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Extender API ensures universal adaptability. Code custom extensions to make Burp work for you.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Logger++&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;For in-depth vulnerability detail, ordered and arranged in an easily accessible table, make use of   &lt;a href="https://portswigger.net/bappstore/470b7057b86f41c396a97903377f3d81" rel="noopener" target="_blank"&gt;Logger++&lt;/a&gt;.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Autorize&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;When testing for authorization vulnerabilities, save time and perform repeat requests with   &lt;a href="https://portswigger.net/bappstore/f9bbac8c4acf4aefa4d7dc92a991af2f" rel="noopener" target="_blank"&gt;Autorize&lt;/a&gt;.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Turbo Intruder&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Configured in Python, with a custom HTTP stack,   &lt;a href="https://portswigger.net/bappstore/9abaa233088242e8be252cd4ff534988" rel="noopener" target="_blank"&gt;Turbo Intruder&lt;/a&gt; can unleash thousands of requests per second.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;J2EE Scan&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Expand your Java-specific vulnerability catalogue and hunt the most niche bugs, with   &lt;a href="https://portswigger.net/bappstore/7ec6d429fed04cdcb6243d8ba7358880" rel="noopener" target="_blank"&gt;J2EEScan&lt;/a&gt;.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Access the extension library&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The   &lt;a href="https://portswigger.net/bappstore" rel="noopener" target="_blank"&gt;BApp Store&lt;/a&gt; customizes and extends capabilities. Over 250 extensions, written and tested by Burp users.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Upload Scanner&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Adapt Burp Scanner’s attacks by uploading and testing multiple file-type payloads, with   &lt;a href="https://portswigger.net/bappstore/b2244cbb6953442cb3c82fa0a0d908fa" rel="noopener" target="_blank"&gt;Upload Scanner&lt;/a&gt;.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;AuthMatrix&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Run   &lt;a href="https://portswigger.net/bappstore/30d8ee9f40c041b0bfec67441aad158e" rel="noopener" target="_blank"&gt;AuthMatrix&lt;/a&gt; with Autorize to define your access-level vulnerability authorization check.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Param Miner&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Quickly find unkeyed inputs with   &lt;a href="https://portswigger.net/bappstore/17d2949a985c4b7ca092728dba871943" rel="noopener" target="_blank"&gt;Param Miner&lt;/a&gt; - can guess up to 65,000 parameter names per second.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;Backslash Powered Scanner&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Find research-grade bugs, and bridge human intuition and automation, with   &lt;a href="https://portswigger.net/bappstore/9cff8c55432a45808432e26dbb2b41d8" rel="noopener" target="_blank"&gt;Backslash Powered Scanner&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://sysin.org/#&amp;#19979;&amp;#36733;&amp;#22320;&amp;#22336;" title="&amp;#19979;&amp;#36733;&amp;#22320;&amp;#22336;"&gt;&lt;/a&gt;下载地址&lt;/h2&gt; &lt;p&gt;官方版本：Professional / Community 2021.10  &lt;br /&gt;  百度网盘链接：  &lt;a href="https://pan.baidu.com/s/1jlqpII0Ibu2jwrk82je3JA" rel="noopener" target="_blank"&gt;https://pan.baidu.com/s/1jlqpII0Ibu2jwrk82je3JA&lt;/a&gt;  提取码：pjtm&lt;/p&gt; &lt;p&gt;本站特别版：今天刚刚发布，需要测试验证后更新。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;Burp Suite Pro for macOS    &lt;br /&gt;百度网盘链接：&lt;/p&gt;   &lt;p&gt;集成 keygen，直接运行，无需额外安装 Java    &lt;br /&gt;    &lt;img alt="burp-dmg" src="https://sysin.org/burp-dmg.png"&gt;&lt;/img&gt;&lt;/p&gt;   &lt;p&gt;修复原版图标，Big Sur 图标适配    &lt;br /&gt;    &lt;img alt="burp-icon" src="https://sysin.org/burp-icon.png"&gt;&lt;/img&gt;&lt;/p&gt;   &lt;p&gt;已知问题：首次运行窗口会变得非常小，拖拽，下次启动即可正常。应用程序运行显示的图标是 java 的图标，比较丑陋，因为破解使用 java loader 导致。&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;Burp Suite Pro for Linux    &lt;br /&gt;百度网盘链接：&lt;/p&gt;   &lt;p&gt;安装：    &lt;code&gt;chmod +x burpsuitepro-linux-2021.10.bin &amp;amp;&amp;amp; sudo ./burpsuitepro-linux-2021.10.bin&lt;/code&gt;&lt;/p&gt;   &lt;p&gt;集成安装、注册和卸载    &lt;br /&gt;    &lt;img alt="burp-install" src="https://sysin.org/burp-install.png"&gt;&lt;/img&gt;&lt;/p&gt;   &lt;p&gt;主界面一览    &lt;br /&gt;    &lt;img alt="burp-main" src="https://sysin.org/burp-main.png"&gt;&lt;/img&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Security macOS Linux HTTP</category>
      <guid isPermaLink="true">https://itindex.net/detail/61867-burp-suite-pro</guid>
      <pubDate>Tue, 02 Nov 2021 10:34:22 CST</pubDate>
    </item>
    <item>
      <title>多租户环境中的 TCP 限速（基于 iptables）</title>
      <link>https://itindex.net/detail/61857-%E5%A4%9A%E7%A7%9F%E6%88%B7-%E7%8E%AF%E5%A2%83-tcp</link>
      <description>&lt;p&gt;我们有个服务以类似 SideCar 的方式和应用一起运行，SideCar 和应用通过 Unix Domain Socket 进行通讯。为了方便用户，在开发的时候不必在自己的开发环境中跑一个 SideCar，我用 socat 在一台开发环境的机器上 map UDS 到一个端口。这样用户在开发的时候就可以直接通过这个 TCP 端口测试服务，而不用自己开一个 SideCar 使用 UDS 了。&lt;/p&gt;
 &lt;p&gt;因为所有人都要用这一个地址做开发，所以就有互相影响的问题。虽然性能还可以，几十万 QPS 不成问题，但是总有憨憨拿来搞压测，把资源跑满，影响别人。我在使用说明文档里用红色大字写了这是开发测试用的，不能压测，还是有一些视力不好的同事会强行压测。隔三差五我就得去解释一番，礼貌地请同事不要再这样做了。&lt;/p&gt;
 &lt;p&gt;最近实在累了。研究了一下直接给这个端口加上 per IP 的 rate limit，效果还不错。方法是在   &lt;a href="https://making.pusher.com/per-ip-rate-limiting-with-iptables/index.html" rel="bookmark"&gt;Per-IP rate limiting with iptables&lt;/a&gt; 学习到的，这个公司是提供一个多租户的 SaaS 服务，也有类似的问题：有一些非正常用户 abuse 他们的服务，由于 abuse 发生在连接建立阶段，还没有进入到业务代码，所以无法从应用的层面进行限速，解决发现就是通过 iptables 实现的。详细的实现方法可以参考这篇文章。&lt;/p&gt;
 &lt;p&gt;iptables 本身是无状态的，每一个进入的 packet 都单独判断规则。rate limit 显然是一个有状态的规则，所以要用到 module:   &lt;code&gt;hashlimit&lt;/code&gt;。（原文中还用到了   &lt;code&gt;conntrack&lt;/code&gt;，他是想只针对新建连接做限制，已经建立的连接不限制速度了。因为这个应用内部就可以控制了，但是我这里是想对所有的 packet 进行限速，所以就不需要用到这个 module）&lt;/p&gt;
 &lt;p&gt;完整的命令如下：&lt;/p&gt; &lt;pre&gt;$ iptables --new-chain SOCAT-RATE-LIMIT
$ iptables --append SOCAT-RATE-LIMIT \
    --match hashlimit \
    --hashlimit-mode srcip \
    --hashlimit-upto 50/sec \
    --hashlimit-burst 100 \
    --hashlimit-name conn_rate_limit \
    --jump ACCEPT
$ iptables --append SOCAT-RATE-LIMIT --jump DROP
$ iptables -I INPUT -p tcp --dport 1234 --jump SOCAT-RATE-LIMIT&lt;/pre&gt; &lt;p&gt;第一行是新建一个 iptables Chain，做 rate limit；&lt;/p&gt;
 &lt;p&gt;第二行处理如果在 rate limit 限额内，就接受包；否则跳到第三行，直接将包 DROP；&lt;/p&gt;
 &lt;p&gt;最后将新的 Chain 加入到 INPUT 中，对此端口的流量进行限制。&lt;/p&gt;
 &lt;p&gt;有关 rate limit 的算法，主要是两个参数：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;code&gt;--hashlimit-upto&lt;/code&gt; 其实本质上是 1s 内可以进入多少 packet，   &lt;code&gt;50/sec&lt;/code&gt; 就是    &lt;code&gt;20ms&lt;/code&gt; 一个 packet；&lt;/li&gt;
  &lt;li&gt;那如何在    &lt;code&gt;10ms&lt;/code&gt; 发来 10个packet，后面一直没发送，怎么办？这个在测试情景下也比较常见，不能要求用户一直匀速地发送。所以就要用到    &lt;code&gt;--hashlimit-burst&lt;/code&gt;。字面意思是瞬间可以发送多少 packet，但实际上，可以理解这个参数就是可用的 credit。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;两个指标配合起来理解，就是每个 ip 刚开始都会有   &lt;code&gt;burst&lt;/code&gt; 个 credit，每个 ip 发送来的 packet 都会占用   &lt;code&gt;burst&lt;/code&gt; 里面的 credit，用完了之后再发来的包就会被直接 DROP。这个 credit 会以   &lt;code&gt;upto&lt;/code&gt; 的速度一直增加，但是最多增加到   &lt;code&gt;burst&lt;/code&gt;（初始值），之后就   &lt;em&gt;use it or lost it&lt;/em&gt;.&lt;/p&gt;
 &lt;p&gt;举个例子，假如   &lt;code&gt;--hashlimit-upto 50/sec --hashlimit-burst 20&lt;/code&gt; 的话，某个 IP 以匀速每 ms 一个 packet 的速度发送，最终会有多少 packets 被接受？答案是 70. 最初的 20ms，所有的 packet 都会被接受，因为   &lt;code&gt;--hashlimit-burst&lt;/code&gt; 是 20，所以最初的 credit 是 20. 这个用完之后就要依赖   &lt;code&gt;--hashlimit--upto 50/sec&lt;/code&gt; 来每 20ms 获得一个 packet credit 了。所以每 20ms 可以接受一个。&lt;/p&gt;
 &lt;p&gt;这是限速之后的效果，非常明显：&lt;/p&gt;
 &lt;p&gt;  &lt;a href="https://www.kawabangga.com/wp-content/uploads/2021/10/ratelimit-spex.png"&gt;   &lt;img alt="" height="484" src="https://www.kawabangga.com/wp-content/uploads/2021/10/ratelimit-spex.png" width="1856"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The post   &lt;a href="https://www.kawabangga.com/posts/4594"&gt;多租户环境中的 TCP 限速（基于 iptables）&lt;/a&gt; first appeared on   &lt;a href="https://www.kawabangga.com"&gt;卡瓦邦噶！&lt;/a&gt;.&lt;/p&gt; &lt;div&gt;  &lt;h3&gt;相关文章:&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/3215"&gt;uWSGI socket 队列被占满的问题&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/1665"&gt;Apache2 “AH00558: apache2: Could not reliably…&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/3407"&gt;DNS 解析的原理&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/2740"&gt;HTTP连接池（基于Python的requests和urllib3）&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="https://www.kawabangga.com/posts/864"&gt;做一件事，做好它。——苹果&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux hashlimit iptables rate limit socat</category>
      <guid isPermaLink="true">https://itindex.net/detail/61857-%E5%A4%9A%E7%A7%9F%E6%88%B7-%E7%8E%AF%E5%A2%83-tcp</guid>
      <pubDate>Sat, 30 Oct 2021 16:19:15 CST</pubDate>
    </item>
    <item>
      <title>本地elasticsearch-head插件的安装与使用</title>
      <link>https://itindex.net/detail/61722-elasticsearch-head-%E6%8F%92%E4%BB%B6</link>
      <description>&lt;p&gt;上一篇谈到在Ubuntu16.04中安装elasticsearch，这一篇我们来谈谈如何在本地机器中安装elasticsearch-head插件，进行ES可视化管理&lt;/p&gt; &lt;h1&gt;  &lt;a href="http://www.duanmuxu.top/#&amp;#29615;&amp;#22659;&amp;#37197;&amp;#32622;" title="&amp;#29615;&amp;#22659;&amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;环境配置&lt;/h1&gt; &lt;ul&gt;  &lt;li&gt;Node JS版本：10.16.0&lt;/li&gt;  &lt;li&gt;虚拟机中已经安装好elasticsearch，版本：5.6.8&lt;/li&gt;&lt;/ul&gt; &lt;h1&gt;  &lt;a href="http://www.duanmuxu.top/#&amp;#23433;&amp;#35013;elasticsearch-head" title="&amp;#23433;&amp;#35013;elasticsearch-head"&gt;&lt;/a&gt;安装elasticsearch-head&lt;/h1&gt; &lt;h2&gt;  &lt;a href="http://www.duanmuxu.top/#&amp;#23433;&amp;#35013;NodeJS" title="&amp;#23433;&amp;#35013;NodeJS"&gt;&lt;/a&gt;安装NodeJS&lt;/h2&gt; &lt;p&gt;elasticsearch-head 是在nodejs环境下运行的，因此必须提前安装好NodeJS，安装教程可参考此篇博客，够详细了：  &lt;a href="https://blog.csdn.net/zhangkaidsy/article/details/86645070?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&amp;utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1" rel="noopener" target="_blank"&gt;NodeJS 安装及环境配置&lt;/a&gt;&lt;/p&gt; &lt;p&gt;安装好后，在cmd命令行中键入&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;node -v     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;得到如下版本信息，便安装成功&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;C:\Users\Administrator&amp;gt;node -v     &lt;br /&gt;v10.16.0     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h2&gt;  &lt;a href="http://www.duanmuxu.top/#&amp;#23433;&amp;#35013;grunt" title="&amp;#23433;&amp;#35013;grunt"&gt;&lt;/a&gt;安装grunt&lt;/h2&gt; &lt;p&gt;运行elasticsearch-head需要借助grunt命令，因此需要安装grunt。打开命令行窗口进入nodejs 安装目录，运行以下命令&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;npm install -g grunt  -cli     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;如果没有报错就安装成功&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;PS D:\nodejs&amp;gt; npm install -g grunt-cli     &lt;br /&gt;D:\nodejs\node_global\grunt -&amp;gt; D:\nodejs\node_global\node_modules\grunt-cli\bin\grunt     &lt;br /&gt;+ grunt-cli@1.3.2     &lt;br /&gt;added 150 packages from 121 contributors in 23.241s     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h2&gt;  &lt;a href="http://www.duanmuxu.top/#&amp;#19979;&amp;#36733;elasticsearch-head" title="&amp;#19979;&amp;#36733;elasticsearch-head"&gt;&lt;/a&gt;下载elasticsearch-head&lt;/h2&gt; &lt;p&gt;进入网址：   &lt;a href="https://github.com/mobz/elasticsearch-head" rel="noopener" target="_blank"&gt;https://github.com/mobz/elasticsearch-head&lt;/a&gt; 下载整个项目到本地目录下并进行解压，我将解压后的目录放在了D盘&lt;/p&gt;                 &lt;div&gt;                      &lt;div&gt;&lt;/div&gt;                      &lt;img alt="&amp;#19979;&amp;#36733;ES-head" src="https://img-blog.csdnimg.cn/20200410013027371.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjU4NjM3Mw==,size_16,color_FFFFFF,t_70#pic_center" title=""&gt;&lt;/img&gt;                &lt;/div&gt;                 &lt;div&gt;下载ES-head&lt;/div&gt;                             &lt;div&gt;                      &lt;div&gt;&lt;/div&gt;                      &lt;img alt="&amp;#35299;&amp;#21387;&amp;#21518;&amp;#30340;head&amp;#25991;&amp;#20214;" src="https://img-blog.csdnimg.cn/20200410013057434.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjU4NjM3Mw==,size_16,color_FFFFFF,t_70#pic_center" title=""&gt;&lt;/img&gt;                &lt;/div&gt;                 &lt;div&gt;解压后的head文件&lt;/div&gt;             &lt;p&gt;Gruntfile.js 是个配置文件，里面可以配elasticsearch-head在本地的端口&lt;/p&gt; &lt;h2&gt;  &lt;a href="http://www.duanmuxu.top/#npm&amp;#23433;&amp;#35013;elasticsearch-head" title="npm&amp;#23433;&amp;#35013;elasticsearch-head"&gt;&lt;/a&gt;npm安装elasticsearch-head&lt;/h2&gt; &lt;p&gt;使用命令行进入elasticsearch-head 目录，执行下述命令&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;npm install     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;进行npm安装，如果没有报错则安装成功&lt;/p&gt;                 &lt;div&gt;                      &lt;div&gt;&lt;/div&gt;                      &lt;img alt="npm&amp;#23433;&amp;#35013;" src="https://img-blog.csdnimg.cn/202004100131289.png#pic_center" title=""&gt;&lt;/img&gt;                &lt;/div&gt;                 &lt;div&gt;npm安装&lt;/div&gt;             &lt;p&gt;如果提示&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;npm ERR! code ELIFECYCLE     &lt;br /&gt;npm ERR! errno 1     &lt;br /&gt;npm ERR! phantomjs-prebuilt@2.1.16 install: `node install.js`     &lt;br /&gt;npm ERR! Exit status 1     &lt;br /&gt;npm ERR!     &lt;br /&gt;npm ERR! Failed at the phantomjs-prebuilt@2.1.16 install script.     &lt;br /&gt;npm ERR! This is probably not a problem with npm. There is likely additional logging output above.     &lt;br /&gt;     &lt;br /&gt;npm ERR! A complete log of this run can be found in:     &lt;br /&gt;npm ERR!     D:\nodejs\node_cache\_logs\2020-04-09T15_58_31_720Z-debug.log     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;这种错误，则先执行以下命令&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;npm install phantomjs-prebuilt@2.1.14 --ignore-scripts     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;安装成功后再执行 npm install，就会发现没有报错了&lt;/p&gt; &lt;h1&gt;  &lt;a href="http://www.duanmuxu.top/#&amp;#20462;&amp;#25913;&amp;#34394;&amp;#25311;&amp;#26426;&amp;#20013;&amp;#30340;elasticsearch&amp;#37197;&amp;#32622;" title="&amp;#20462;&amp;#25913;&amp;#34394;&amp;#25311;&amp;#26426;&amp;#20013;&amp;#30340;elasticsearch&amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;修改虚拟机中的elasticsearch配置&lt;/h1&gt; &lt;p&gt;先将运行中的ES停掉，如果有的话，然后进入编辑虚拟机中的/usr/local/elasticsearch-5.6.8/conf/elasticsearch.yml 文件，添加下述两行代码&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;http.cors.enabled: true     &lt;br /&gt;http.cors.allow-origin: &amp;quot;*&amp;quot;     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;ul&gt;  &lt;li&gt;http.cors.enabled：表示是否支持跨域，默认为false&lt;/li&gt;  &lt;li&gt;http.cors.allow-origin：当设置允许跨域，默认为*,表示支持所有域名，如果我们只是允许某些网站能访问，那么可以使用正则表达式。比如只允许本地地址。 /https?:\/\/localhost(:[0-9]+)?/&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;编辑完后保存并退出，重新运行虚拟机中的ES&lt;/p&gt; &lt;h1&gt;  &lt;a href="http://www.duanmuxu.top/#&amp;#36816;&amp;#34892;elasticsearch-head" title="&amp;#36816;&amp;#34892;elasticsearch-head"&gt;&lt;/a&gt;运行elasticsearch-head&lt;/h1&gt; &lt;p&gt;上述安装和配置都完成后，在本地主机命令行中键入 grunt server 运行elasticsearch-head，得到如下提示则运行成功&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;PS D:\elasticsearch-head-master&amp;gt; grunt server     &lt;br /&gt;Running &amp;quot;connect:server&amp;quot; (connect) task     &lt;br /&gt;Waiting forever...     &lt;br /&gt;Started connect web server on http://localhost:9100     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;此时就可以在浏览器中输入   &lt;a href="http://localhost:9100" rel="noopener" target="_blank"&gt;http://localhost:9100&lt;/a&gt; 打开elasticsearch-head  &lt;br /&gt;然后在连接栏中输入 虚拟机IP:9200 进行连接，便能连接上虚拟机中的ES&lt;/p&gt;                 &lt;div&gt;                      &lt;div&gt;&lt;/div&gt;                      &lt;img alt="&amp;#25171;&amp;#24320;ES-head" src="https://img-blog.csdnimg.cn/20200410013319692.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjU4NjM3Mw==,size_16,color_FFFFFF,t_70#pic_center" title=""&gt;&lt;/img&gt;                &lt;/div&gt;                 &lt;div&gt;打开ES-head&lt;/div&gt;                             &lt;div&gt;                      &lt;div&gt;&lt;/div&gt;                      &lt;img alt="&amp;#36830;&amp;#25509;&amp;#34394;&amp;#25311;&amp;#26426;&amp;#20013;&amp;#30340;ES" src="https://img-blog.csdnimg.cn/20200410013438935.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjU4NjM3Mw==,size_16,color_FFFFFF,t_70#pic_center" title=""&gt;&lt;/img&gt;                &lt;/div&gt;                 &lt;div&gt;连接虚拟机中的ES&lt;/div&gt;             &lt;p&gt;完结撒花。&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>ElasticSearch Linux ElasticSearch</category>
      <guid isPermaLink="true">https://itindex.net/detail/61722-elasticsearch-head-%E6%8F%92%E4%BB%B6</guid>
      <pubDate>Fri, 10 Apr 2020 01:36:47 CST</pubDate>
    </item>
    <item>
      <title>Kubernetes 切换到 Containerd</title>
      <link>https://itindex.net/detail/61478-kubernetes-%E5%88%87%E6%8D%A2-containerd</link>
      <description>&lt;h2&gt;  &lt;a href="https://mritd.com/#&amp;#19968;&amp;#12289;&amp;#29615;&amp;#22659;&amp;#20934;&amp;#22791;" title="&amp;#19968;&amp;#12289;&amp;#29615;&amp;#22659;&amp;#20934;&amp;#22791;"&gt;&lt;/a&gt;一、环境准备&lt;/h2&gt; &lt;ul&gt;  &lt;li&gt;Ubuntu 20.04 x5&lt;/li&gt;  &lt;li&gt;Etcd 3.4.16&lt;/li&gt;  &lt;li&gt;Kubernetes 1.21.1&lt;/li&gt;  &lt;li&gt;Containerd 1.3.3&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#1-1&amp;#12289;&amp;#22788;&amp;#29702;-IPVS" title="1.1&amp;#12289;&amp;#22788;&amp;#29702; IPVS"&gt;&lt;/a&gt;1.1、处理 IPVS&lt;/h3&gt; &lt;p&gt;由于 Kubernetes 新版本 Service 实现切换到 IPVS，所以需要确保内核加载了 IPVS modules；以下命令将设置系统启动自动加载 IPVS 相关模块，执行完成后需要重启。&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;22      &lt;br /&gt;23      &lt;br /&gt;24      &lt;br /&gt;25      &lt;br /&gt;26      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# Kernel modules       &lt;br /&gt;cat &amp;gt; /etc/modules-load.d/50-kubernetes.conf &amp;lt;&amp;lt;EOF       &lt;br /&gt;# Load some kernel modules needed by kubernetes at boot       &lt;br /&gt;nf_conntrack       &lt;br /&gt;br_netfilter       &lt;br /&gt;ip_vs       &lt;br /&gt;ip_vs_lc       &lt;br /&gt;ip_vs_wlc       &lt;br /&gt;ip_vs_rr       &lt;br /&gt;ip_vs_wrr       &lt;br /&gt;ip_vs_lblc       &lt;br /&gt;ip_vs_lblcr       &lt;br /&gt;ip_vs_dh       &lt;br /&gt;ip_vs_sh       &lt;br /&gt;ip_vs_fo       &lt;br /&gt;ip_vs_nq       &lt;br /&gt;ip_vs_sed       &lt;br /&gt;EOF       &lt;br /&gt;       &lt;br /&gt;# sysctl       &lt;br /&gt;cat &amp;gt; /etc/sysctl.d/50-kubernetes.conf &amp;lt;&amp;lt;EOF       &lt;br /&gt;net.ipv4.ip_forward=1       &lt;br /&gt;net.bridge.bridge-nf-call-iptables=1       &lt;br /&gt;net.bridge.bridge-nf-call-ip6tables=1       &lt;br /&gt;fs.inotify.max_user_watches=525000       &lt;br /&gt;EOF       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;重启完成后务必检查相关 module 加载以及内核参数设置:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;22      &lt;br /&gt;23      &lt;br /&gt;24      &lt;br /&gt;25      &lt;br /&gt;26      &lt;br /&gt;27      &lt;br /&gt;28      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# check ipvs modules       &lt;br /&gt;➜ ~ lsmod | grep ip_vs       &lt;br /&gt;ip_vs_sed              16384  0       &lt;br /&gt;ip_vs_nq               16384  0       &lt;br /&gt;ip_vs_fo               16384  0       &lt;br /&gt;ip_vs_sh               16384  0       &lt;br /&gt;ip_vs_dh               16384  0       &lt;br /&gt;ip_vs_lblcr            16384  0       &lt;br /&gt;ip_vs_lblc             16384  0       &lt;br /&gt;ip_vs_wrr              16384  0       &lt;br /&gt;ip_vs_rr               16384  0       &lt;br /&gt;ip_vs_wlc              16384  0       &lt;br /&gt;ip_vs_lc               16384  0       &lt;br /&gt;ip_vs                 155648  22 ip_vs_wlc,ip_vs_rr,ip_vs_dh,ip_vs_lblcr,ip_vs_sh,ip_vs_fo,ip_vs_nq,ip_vs_lblc,ip_vs_wrr,ip_vs_lc,ip_vs_sed       &lt;br /&gt;nf_conntrack          139264  1 ip_vs       &lt;br /&gt;nf_defrag_ipv6         24576  2 nf_conntrack,ip_vs       &lt;br /&gt;libcrc32c              16384  5 nf_conntrack,btrfs,xfs,raid456,ip_vs       &lt;br /&gt;       &lt;br /&gt;# check sysctl       &lt;br /&gt;➜ ~ sysctl -a | grep ip_forward       &lt;br /&gt;net.ipv4.ip_forward = 1       &lt;br /&gt;net.ipv4.ip_forward_update_priority = 1       &lt;br /&gt;net.ipv4.ip_forward_use_pmtu = 0       &lt;br /&gt;       &lt;br /&gt;➜ ~ sysctl -a | grep bridge-nf-call       &lt;br /&gt;net.bridge.bridge-nf-call-arptables = 1       &lt;br /&gt;net.bridge.bridge-nf-call-ip6tables = 1       &lt;br /&gt;net.bridge.bridge-nf-call-iptables = 1       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#1-2&amp;#12289;&amp;#23433;&amp;#35013;-Containerd" title="1.2&amp;#12289;&amp;#23433;&amp;#35013; Containerd"&gt;&lt;/a&gt;1.2、安装 Containerd&lt;/h3&gt; &lt;p&gt;Containerd 在 Ubuntu 20 中已经在默认官方仓库中包含，所以只需要 apt 安装即可:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# 其他软件包后面可能会用到，所以顺手装了       &lt;br /&gt;apt install containerd bridge-utils nfs-common tree -y       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;安装成功后可以通过执行   &lt;code&gt;ctr images ls&lt;/code&gt; 命令验证，  &lt;strong&gt;本章节不会对 Containerd 配置做说明，Containerd 配置文件将在 Kubernetes 安装时进行配置。&lt;/strong&gt;&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://mritd.com/#&amp;#20108;&amp;#12289;&amp;#23433;&amp;#35013;-kubernetes" title="&amp;#20108;&amp;#12289;&amp;#23433;&amp;#35013; kubernetes"&gt;&lt;/a&gt;二、安装 kubernetes&lt;/h2&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-1&amp;#12289;&amp;#23433;&amp;#35013;-Etcd-&amp;#38598;&amp;#32676;" title="2.1&amp;#12289;&amp;#23433;&amp;#35013; Etcd &amp;#38598;&amp;#32676;"&gt;&lt;/a&gt;2.1、安装 Etcd 集群&lt;/h3&gt; &lt;p&gt;Etcd 对于 Kubernetes 来说是核心中的核心，所以个人还是比较喜欢在宿主机安装；宿主机安装情况下为了方便我打包了一些   &lt;strong&gt;   &lt;code&gt;*-pack&lt;/code&gt;&lt;/strong&gt; 的工具包，用于快速处理:&lt;/p&gt; &lt;p&gt;安装 CFSSL 和 ETCD&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# 下载安装包       &lt;br /&gt;wget https://github.com/mritd/etcd-pack/releases/download/v3.4.16/etcd_v3.4.16.run       &lt;br /&gt;wget https://github.com/mritd/cfssl-pack/releases/download/v1.5.0/cfssl_v1.5.0.run       &lt;br /&gt;       &lt;br /&gt;# 安装 cfssl 和 etcd       &lt;br /&gt;chmod +x *.run       &lt;br /&gt;./etcd_v3.4.16.run install       &lt;br /&gt;./cfssl_v1.5.0.run install       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;安装完成后，  &lt;strong&gt;自行调整    &lt;code&gt;/etc/cfssl/etcd/etcd-csr.json&lt;/code&gt; 相关 IP&lt;/strong&gt;，然后执行同目录下   &lt;code&gt;create.sh&lt;/code&gt; 生成证书。&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;22      &lt;br /&gt;23      &lt;br /&gt;24      &lt;br /&gt;25      &lt;br /&gt;26      &lt;br /&gt;27      &lt;br /&gt;28      &lt;br /&gt;29      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;➜ ~ cat /etc/cfssl/etcd/etcd-csr.json       &lt;br /&gt;{       &lt;br /&gt;    &amp;quot;key&amp;quot;: {       &lt;br /&gt;        &amp;quot;algo&amp;quot;: &amp;quot;rsa&amp;quot;,       &lt;br /&gt;        &amp;quot;size&amp;quot;: 2048       &lt;br /&gt;    },       &lt;br /&gt;    &amp;quot;names&amp;quot;: [       &lt;br /&gt;        {       &lt;br /&gt;            &amp;quot;O&amp;quot;: &amp;quot;etcd&amp;quot;,       &lt;br /&gt;            &amp;quot;OU&amp;quot;: &amp;quot;etcd Security&amp;quot;,       &lt;br /&gt;            &amp;quot;L&amp;quot;: &amp;quot;Beijing&amp;quot;,       &lt;br /&gt;            &amp;quot;ST&amp;quot;: &amp;quot;Beijing&amp;quot;,       &lt;br /&gt;            &amp;quot;C&amp;quot;: &amp;quot;CN&amp;quot;       &lt;br /&gt;        }       &lt;br /&gt;    ],       &lt;br /&gt;    &amp;quot;CN&amp;quot;: &amp;quot;etcd&amp;quot;,       &lt;br /&gt;    &amp;quot;hosts&amp;quot;: [       &lt;br /&gt;        &amp;quot;127.0.0.1&amp;quot;,       &lt;br /&gt;        &amp;quot;localhost&amp;quot;,       &lt;br /&gt;        &amp;quot;*.etcd.node&amp;quot;,       &lt;br /&gt;        &amp;quot;*.kubernetes.node&amp;quot;,       &lt;br /&gt;        &amp;quot;10.0.0.11&amp;quot;,       &lt;br /&gt;        &amp;quot;10.0.0.12&amp;quot;,       &lt;br /&gt;        &amp;quot;10.0.0.13&amp;quot;       &lt;br /&gt;    ]       &lt;br /&gt;}       &lt;br /&gt;       &lt;br /&gt;# 复制到 3 台 master       &lt;br /&gt;➜ ~ for ip in `seq 1 3`; do scp /etc/cfssl/etcd/*.pem root@10.0.0.1$ip:/etc/etcd/ssl; done       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;证书生成完成后调整每台机器的 Etcd 配置文件，然后修复权限启动。&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# 复制配置       &lt;br /&gt;for ip in `seq 1 3`; do scp /etc/etcd/etcd.cluster.yaml root@10.0.0.1$ip:/etc/etcd/etcd.yaml; done       &lt;br /&gt;       &lt;br /&gt;# 修复权限       &lt;br /&gt;for ip in `seq 1 3`; do ssh root@10.0.0.1$ip chown -R etcd:etcd /etc/etcd; done       &lt;br /&gt;       &lt;br /&gt;# 每台机器启动       &lt;br /&gt;systemctl start etcd       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;启动完成后通过   &lt;code&gt;etcdctl&lt;/code&gt; 验证集群状态:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# 稳妥点应该执行 etcdctl endpoint health       &lt;br /&gt;➜ ~ etcdctl member list       &lt;br /&gt;55fcbe0adaa45350, started, etcd3, https://10.0.0.13:2380, https://10.0.0.13:2379, false       &lt;br /&gt;cebdf10928a06f3c, started, etcd1, https://10.0.0.11:2380, https://10.0.0.11:2379, false       &lt;br /&gt;f7a9c20602b8532e, started, etcd2, https://10.0.0.12:2380, https://10.0.0.12:2379, false       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-2&amp;#12289;&amp;#23433;&amp;#35013;-kubeadm" title="2.2&amp;#12289;&amp;#23433;&amp;#35013; kubeadm"&gt;&lt;/a&gt;2.2、安装 kubeadm&lt;/h3&gt; &lt;p&gt;kubeadm 国内用户建议使用 aliyun 的安装源:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# kubeadm       &lt;br /&gt;apt-get install -y apt-transport-https       &lt;br /&gt;curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -       &lt;br /&gt;cat &amp;lt;&amp;lt;EOF &amp;gt;/etc/apt/sources.list.d/kubernetes.list       &lt;br /&gt;deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main       &lt;br /&gt;EOF       &lt;br /&gt;apt update       &lt;br /&gt;       &lt;br /&gt;# ebtables、ethtool kubelet 可能会用，具体忘了，反正从官方文档上看到的       &lt;br /&gt;apt install kubelet kubeadm kubectl ebtables ethtool -y       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-3&amp;#12289;&amp;#23433;&amp;#35013;-kube-apiserver-proxy" title="2.3&amp;#12289;&amp;#23433;&amp;#35013; kube-apiserver-proxy"&gt;&lt;/a&gt;2.3、安装 kube-apiserver-proxy&lt;/h3&gt; &lt;p&gt;kube-apiserver-proxy 是我自己编译的一个仅开启四层代理的 Nginx，其主要负责监听   &lt;code&gt;127.0.0.1:6443&lt;/code&gt; 并负载到所有的 Api Server 地址(  &lt;code&gt;0.0.0.0:5443&lt;/code&gt;):&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;wget https://github.com/mritd/kube-apiserver-proxy-pack/releases/download/v1.20.0/kube-apiserver-proxy_v1.20.0.run       &lt;br /&gt;chmod +x *.run       &lt;br /&gt;./kube-apiserver-proxy_v1.20.0.run install       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;安装完成后根据 IP 地址不同自行调整 Nginx 配置文件，然后启动:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;22      &lt;br /&gt;23      &lt;br /&gt;24      &lt;br /&gt;25      &lt;br /&gt;26      &lt;br /&gt;27      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;➜ ~ cat /etc/kubernetes/apiserver-proxy.conf       &lt;br /&gt;error_log syslog:server=unix:/dev/log notice;       &lt;br /&gt;       &lt;br /&gt;worker_processes auto;       &lt;br /&gt;events {       &lt;br /&gt;        multi_accept on;       &lt;br /&gt;        use epoll;       &lt;br /&gt;        worker_connections 1024;       &lt;br /&gt;}       &lt;br /&gt;       &lt;br /&gt;stream {       &lt;br /&gt;    upstream kube_apiserver {       &lt;br /&gt;        least_conn;       &lt;br /&gt;        server 10.0.0.11:5443;       &lt;br /&gt;        server 10.0.0.12:5443;       &lt;br /&gt;        server 10.0.0.13:5443;       &lt;br /&gt;    }       &lt;br /&gt;       &lt;br /&gt;    server {       &lt;br /&gt;        listen        0.0.0.0:6443;       &lt;br /&gt;        proxy_pass    kube_apiserver;       &lt;br /&gt;        proxy_timeout 10m;       &lt;br /&gt;        proxy_connect_timeout 1s;       &lt;br /&gt;    }       &lt;br /&gt;}       &lt;br /&gt;       &lt;br /&gt;systemctl start kube-apiserver-proxy       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-4&amp;#12289;&amp;#23433;&amp;#35013;-kubeadm-config" title="2.4&amp;#12289;&amp;#23433;&amp;#35013; kubeadm-config"&gt;&lt;/a&gt;2.4、安装 kubeadm-config&lt;/h3&gt; &lt;p&gt;kubeadm-config 是一系列配置文件的组合以及 kubeadm 安装所需的必要镜像文件的打包，安装完成后将会自动配置 Containerd、ctrictl 等:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;wget https://github.com/mritd/kubeadm-config-pack/releases/download/v1.21.1/kubeadm-config_v1.21.1.run       &lt;br /&gt;chmod +x *.run       &lt;br /&gt;       &lt;br /&gt;# --load 选项用于将 kubeadm 所需镜像 load 到 containerd 中       &lt;br /&gt;./kubeadm-config_v1.21.1.run install --load       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h4&gt;  &lt;a href="https://mritd.com/#2-4-1&amp;#12289;containerd-&amp;#37197;&amp;#32622;" title="2.4.1&amp;#12289;containerd &amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;2.4.1、containerd 配置&lt;/h4&gt; &lt;p&gt;Containerd 配置位于   &lt;code&gt;/etc/containerd/config.toml&lt;/code&gt;，其配置如下:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;22      &lt;br /&gt;23      &lt;br /&gt;24      &lt;br /&gt;25      &lt;br /&gt;26      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;version = 2       &lt;br /&gt;# 指定存储根目录       &lt;br /&gt;root = &amp;quot;/data/containerd&amp;quot;       &lt;br /&gt;state = &amp;quot;/run/containerd&amp;quot;       &lt;br /&gt;# OOM 评分       &lt;br /&gt;oom_score = -999       &lt;br /&gt;       &lt;br /&gt;[grpc]       &lt;br /&gt;  address = &amp;quot;/run/containerd/containerd.sock&amp;quot;       &lt;br /&gt;       &lt;br /&gt;[metrics]       &lt;br /&gt;  address = &amp;quot;127.0.0.1:1234&amp;quot;       &lt;br /&gt;       &lt;br /&gt;[plugins]       &lt;br /&gt;  [plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;]       &lt;br /&gt;    # sandbox 镜像       &lt;br /&gt;    sandbox_image = &amp;quot;k8s.gcr.io/pause:3.4.1&amp;quot;       &lt;br /&gt;    [plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;.containerd]       &lt;br /&gt;      snapshotter = &amp;quot;overlayfs&amp;quot;       &lt;br /&gt;      default_runtime_name = &amp;quot;runc&amp;quot;       &lt;br /&gt;      [plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;.containerd.runtimes]       &lt;br /&gt;        [plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;.containerd.runtimes.runc]       &lt;br /&gt;          runtime_type = &amp;quot;io.containerd.runc.v2&amp;quot;       &lt;br /&gt;          # 开启 systemd cgroup       &lt;br /&gt;          [plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;.containerd.runtimes.runc.options]       &lt;br /&gt;            SystemdCgroup = true       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h4&gt;  &lt;a href="https://mritd.com/#2-4-2&amp;#12289;crictl-&amp;#37197;&amp;#32622;" title="2.4.2&amp;#12289;crictl &amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;2.4.2、crictl 配置&lt;/h4&gt; &lt;p&gt;在切换到 Containerd 以后意味着以前的   &lt;code&gt;docker&lt;/code&gt; 命令将不再可用，containerd 默认自带了一个   &lt;code&gt;ctr&lt;/code&gt; 命令，同时 CRI 规范会自带一个   &lt;code&gt;crictl&lt;/code&gt; 命令；  &lt;code&gt;crictl&lt;/code&gt; 命令配置文件存放在   &lt;code&gt;/etc/crictl.yaml&lt;/code&gt; 中:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;runtime-endpoint: unix:///run/containerd/containerd.sock       &lt;br /&gt;image-endpoint: unix:///run/containerd/containerd.sock       &lt;br /&gt;pull-image-on-create: true       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h4&gt;  &lt;a href="https://mritd.com/#2-4-3&amp;#12289;kubeadm-&amp;#37197;&amp;#32622;" title="2.4.3&amp;#12289;kubeadm &amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;2.4.3、kubeadm 配置&lt;/h4&gt; &lt;p&gt;kubeadm 配置目前分为 2 个，一个是用于首次引导启动的 init 配置，另一个是用于其他节点 join 到 master 的配置；其中比较重要的 init 配置如下:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;22      &lt;br /&gt;23      &lt;br /&gt;24      &lt;br /&gt;25      &lt;br /&gt;26      &lt;br /&gt;27      &lt;br /&gt;28      &lt;br /&gt;29      &lt;br /&gt;30      &lt;br /&gt;31      &lt;br /&gt;32      &lt;br /&gt;33      &lt;br /&gt;34      &lt;br /&gt;35      &lt;br /&gt;36      &lt;br /&gt;37      &lt;br /&gt;38      &lt;br /&gt;39      &lt;br /&gt;40      &lt;br /&gt;41      &lt;br /&gt;42      &lt;br /&gt;43      &lt;br /&gt;44      &lt;br /&gt;45      &lt;br /&gt;46      &lt;br /&gt;47      &lt;br /&gt;48      &lt;br /&gt;49      &lt;br /&gt;50      &lt;br /&gt;51      &lt;br /&gt;52      &lt;br /&gt;53      &lt;br /&gt;54      &lt;br /&gt;55      &lt;br /&gt;56      &lt;br /&gt;57      &lt;br /&gt;58      &lt;br /&gt;59      &lt;br /&gt;60      &lt;br /&gt;61      &lt;br /&gt;62      &lt;br /&gt;63      &lt;br /&gt;64      &lt;br /&gt;65      &lt;br /&gt;66      &lt;br /&gt;67      &lt;br /&gt;68      &lt;br /&gt;69      &lt;br /&gt;70      &lt;br /&gt;71      &lt;br /&gt;72      &lt;br /&gt;73      &lt;br /&gt;74      &lt;br /&gt;75      &lt;br /&gt;76      &lt;br /&gt;77      &lt;br /&gt;78      &lt;br /&gt;79      &lt;br /&gt;80      &lt;br /&gt;81      &lt;br /&gt;82      &lt;br /&gt;83      &lt;br /&gt;84      &lt;br /&gt;85      &lt;br /&gt;86      &lt;br /&gt;87      &lt;br /&gt;88      &lt;br /&gt;89      &lt;br /&gt;90      &lt;br /&gt;91      &lt;br /&gt;92      &lt;br /&gt;93      &lt;br /&gt;94      &lt;br /&gt;95      &lt;br /&gt;96      &lt;br /&gt;97      &lt;br /&gt;98      &lt;br /&gt;99      &lt;br /&gt;100      &lt;br /&gt;101      &lt;br /&gt;102      &lt;br /&gt;103      &lt;br /&gt;104      &lt;br /&gt;105      &lt;br /&gt;106      &lt;br /&gt;107      &lt;br /&gt;108      &lt;br /&gt;109      &lt;br /&gt;110      &lt;br /&gt;111      &lt;br /&gt;112      &lt;br /&gt;113      &lt;br /&gt;114      &lt;br /&gt;115      &lt;br /&gt;116      &lt;br /&gt;117      &lt;br /&gt;118      &lt;br /&gt;119      &lt;br /&gt;120      &lt;br /&gt;121      &lt;br /&gt;122      &lt;br /&gt;123      &lt;br /&gt;124      &lt;br /&gt;125      &lt;br /&gt;126      &lt;br /&gt;127      &lt;br /&gt;128      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# /etc/kubernetes/kubeadm.yaml       &lt;br /&gt;apiVersion: kubeadm.k8s.io/v1beta2       &lt;br /&gt;kind: InitConfiguration       &lt;br /&gt;# kubeadm token create       &lt;br /&gt;bootstrapTokens:       &lt;br /&gt;- token: &amp;quot;c2t0rj.cofbfnwwrb387890&amp;quot;       &lt;br /&gt;nodeRegistration:       &lt;br /&gt;  # CRI 地址(Containerd)       &lt;br /&gt;  criSocket: unix:///run/containerd/containerd.sock       &lt;br /&gt;  kubeletExtraArgs:       &lt;br /&gt;    runtime-cgroups: &amp;quot;/system.slice/containerd.service&amp;quot;       &lt;br /&gt;    rotate-server-certificates: &amp;quot;true&amp;quot;       &lt;br /&gt;localAPIEndpoint:       &lt;br /&gt;  advertiseAddress: &amp;quot;10.0.0.11&amp;quot;       &lt;br /&gt;  bindPort: 5443       &lt;br /&gt;# kubeadm certs certificate-key       &lt;br /&gt;certificateKey: 31f1e534733a1607e5ba67b2834edd3a7debba41babb1fac1bee47072a98d88b       &lt;br /&gt;---       &lt;br /&gt;apiVersion: kubeadm.k8s.io/v1beta2       &lt;br /&gt;kind: ClusterConfiguration       &lt;br /&gt;clusterName: &amp;quot;kuberentes&amp;quot;       &lt;br /&gt;kubernetesVersion: &amp;quot;v1.21.1&amp;quot;       &lt;br /&gt;certificatesDir: &amp;quot;/etc/kubernetes/pki&amp;quot;       &lt;br /&gt;# Other components of the current control plane only connect to the apiserver on the current host.       &lt;br /&gt;# This is the expected behavior, see: https://github.com/kubernetes/kubeadm/issues/2271       &lt;br /&gt;controlPlaneEndpoint: &amp;quot;127.0.0.1:6443&amp;quot;       &lt;br /&gt;etcd:       &lt;br /&gt;  external:       &lt;br /&gt;    endpoints:       &lt;br /&gt;    - &amp;quot;https://10.0.0.11:2379&amp;quot;       &lt;br /&gt;    - &amp;quot;https://10.0.0.12:2379&amp;quot;       &lt;br /&gt;    - &amp;quot;https://10.0.0.13:2379&amp;quot;       &lt;br /&gt;    caFile: &amp;quot;/etc/etcd/ssl/etcd-ca.pem&amp;quot;       &lt;br /&gt;    certFile: &amp;quot;/etc/etcd/ssl/etcd.pem&amp;quot;       &lt;br /&gt;    keyFile: &amp;quot;/etc/etcd/ssl/etcd-key.pem&amp;quot;       &lt;br /&gt;networking:       &lt;br /&gt;  serviceSubnet: &amp;quot;10.66.0.0/16&amp;quot;       &lt;br /&gt;  podSubnet: &amp;quot;10.88.0.1/16&amp;quot;       &lt;br /&gt;  dnsDomain: &amp;quot;cluster.local&amp;quot;       &lt;br /&gt;apiServer:       &lt;br /&gt;  extraArgs:       &lt;br /&gt;    v: &amp;quot;4&amp;quot;       &lt;br /&gt;    alsologtostderr: &amp;quot;true&amp;quot;       &lt;br /&gt;#    audit-log-maxage: &amp;quot;21&amp;quot;       &lt;br /&gt;#    audit-log-maxbackup: &amp;quot;10&amp;quot;       &lt;br /&gt;#    audit-log-maxsize: &amp;quot;100&amp;quot;       &lt;br /&gt;#    audit-log-path: &amp;quot;/var/log/kube-audit/audit.log&amp;quot;       &lt;br /&gt;#    audit-policy-file: &amp;quot;/etc/kubernetes/audit-policy.yaml&amp;quot;       &lt;br /&gt;    authorization-mode: &amp;quot;Node,RBAC&amp;quot;       &lt;br /&gt;    event-ttl: &amp;quot;720h&amp;quot;       &lt;br /&gt;    runtime-config: &amp;quot;api/all=true&amp;quot;       &lt;br /&gt;    service-node-port-range: &amp;quot;30000-50000&amp;quot;       &lt;br /&gt;    service-cluster-ip-range: &amp;quot;10.66.0.0/16&amp;quot;       &lt;br /&gt;#    insecure-bind-address: &amp;quot;0.0.0.0&amp;quot;       &lt;br /&gt;#    insecure-port: &amp;quot;8080&amp;quot;       &lt;br /&gt;    # The fraction of requests that will be closed gracefully(GOAWAY) to prevent       &lt;br /&gt;    # HTTP/2 clients from getting stuck on a single apiserver.       &lt;br /&gt;    goaway-chance: &amp;quot;0.001&amp;quot;       &lt;br /&gt;#  extraVolumes:       &lt;br /&gt;#  - name: &amp;quot;audit-config&amp;quot;       &lt;br /&gt;#    hostPath: &amp;quot;/etc/kubernetes/audit-policy.yaml&amp;quot;       &lt;br /&gt;#    mountPath: &amp;quot;/etc/kubernetes/audit-policy.yaml&amp;quot;       &lt;br /&gt;#    readOnly: true       &lt;br /&gt;#    pathType: &amp;quot;File&amp;quot;       &lt;br /&gt;#  - name: &amp;quot;audit-log&amp;quot;       &lt;br /&gt;#    hostPath: &amp;quot;/var/log/kube-audit&amp;quot;       &lt;br /&gt;#    mountPath: &amp;quot;/var/log/kube-audit&amp;quot;       &lt;br /&gt;#    pathType: &amp;quot;DirectoryOrCreate&amp;quot;       &lt;br /&gt;  certSANs:       &lt;br /&gt;  - &amp;quot;*.kubernetes.node&amp;quot;       &lt;br /&gt;  - &amp;quot;10.0.0.11&amp;quot;       &lt;br /&gt;  - &amp;quot;10.0.0.12&amp;quot;       &lt;br /&gt;  - &amp;quot;10.0.0.13&amp;quot;       &lt;br /&gt;  timeoutForControlPlane: 1m       &lt;br /&gt;controllerManager:       &lt;br /&gt;  extraArgs:       &lt;br /&gt;    v: &amp;quot;4&amp;quot;       &lt;br /&gt;    node-cidr-mask-size: &amp;quot;19&amp;quot;       &lt;br /&gt;    deployment-controller-sync-period: &amp;quot;10s&amp;quot;       &lt;br /&gt;    experimental-cluster-signing-duration: &amp;quot;8670h&amp;quot;       &lt;br /&gt;    node-monitor-grace-period: &amp;quot;20s&amp;quot;       &lt;br /&gt;    pod-eviction-timeout: &amp;quot;2m&amp;quot;       &lt;br /&gt;    terminated-pod-gc-threshold: &amp;quot;30&amp;quot;       &lt;br /&gt;scheduler:       &lt;br /&gt;  extraArgs:       &lt;br /&gt;    v: &amp;quot;4&amp;quot;       &lt;br /&gt;---       &lt;br /&gt;apiVersion: kubelet.config.k8s.io/v1beta1       &lt;br /&gt;kind: KubeletConfiguration       &lt;br /&gt;failSwapOn: false       &lt;br /&gt;oomScoreAdj: -900       &lt;br /&gt;cgroupDriver: &amp;quot;systemd&amp;quot;       &lt;br /&gt;kubeletCgroups: &amp;quot;/system.slice/kubelet.service&amp;quot;       &lt;br /&gt;nodeStatusUpdateFrequency: 5s       &lt;br /&gt;rotateCertificates: true       &lt;br /&gt;evictionSoft:       &lt;br /&gt;  &amp;quot;imagefs.available&amp;quot;: &amp;quot;15%&amp;quot;       &lt;br /&gt;  &amp;quot;memory.available&amp;quot;: &amp;quot;512Mi&amp;quot;       &lt;br /&gt;  &amp;quot;nodefs.available&amp;quot;: &amp;quot;15%&amp;quot;       &lt;br /&gt;  &amp;quot;nodefs.inodesFree&amp;quot;: &amp;quot;10%&amp;quot;       &lt;br /&gt;evictionSoftGracePeriod:       &lt;br /&gt;  &amp;quot;imagefs.available&amp;quot;: &amp;quot;3m&amp;quot;       &lt;br /&gt;  &amp;quot;memory.available&amp;quot;: &amp;quot;1m&amp;quot;       &lt;br /&gt;  &amp;quot;nodefs.available&amp;quot;: &amp;quot;3m&amp;quot;       &lt;br /&gt;  &amp;quot;nodefs.inodesFree&amp;quot;: &amp;quot;1m&amp;quot;       &lt;br /&gt;evictionHard:       &lt;br /&gt;  &amp;quot;imagefs.available&amp;quot;: &amp;quot;10%&amp;quot;       &lt;br /&gt;  &amp;quot;memory.available&amp;quot;: &amp;quot;256Mi&amp;quot;       &lt;br /&gt;  &amp;quot;nodefs.available&amp;quot;: &amp;quot;10%&amp;quot;       &lt;br /&gt;  &amp;quot;nodefs.inodesFree&amp;quot;: &amp;quot;5%&amp;quot;       &lt;br /&gt;evictionMaxPodGracePeriod: 30       &lt;br /&gt;imageGCLowThresholdPercent: 70       &lt;br /&gt;imageGCHighThresholdPercent: 80       &lt;br /&gt;kubeReserved:       &lt;br /&gt;  &amp;quot;cpu&amp;quot;: &amp;quot;500m&amp;quot;       &lt;br /&gt;  &amp;quot;memory&amp;quot;: &amp;quot;512Mi&amp;quot;       &lt;br /&gt;  &amp;quot;ephemeral-storage&amp;quot;: &amp;quot;1Gi&amp;quot;       &lt;br /&gt;---       &lt;br /&gt;apiVersion: kubeproxy.config.k8s.io/v1alpha1       &lt;br /&gt;kind: KubeProxyConfiguration       &lt;br /&gt;# kube-proxy specific options here       &lt;br /&gt;clusterCIDR: &amp;quot;10.88.0.1/16&amp;quot;       &lt;br /&gt;mode: &amp;quot;ipvs&amp;quot;       &lt;br /&gt;oomScoreAdj: -900       &lt;br /&gt;ipvs:       &lt;br /&gt;  minSyncPeriod: 5s       &lt;br /&gt;  syncPeriod: 5s       &lt;br /&gt;  scheduler: &amp;quot;wrr&amp;quot;       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;init 配置具体含义请自行参考官方文档，相对于 init 配置，join 配置比较简单，  &lt;strong&gt;不过需要注意的是如果需要 join 为 master 则需要    &lt;code&gt;controlPlane&lt;/code&gt; 这部分，否则请注释掉    &lt;code&gt;controlPlane&lt;/code&gt;。&lt;/strong&gt;&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# /etc/kubernetes/kubeadm-join.yaml       &lt;br /&gt;apiVersion: kubeadm.k8s.io/v1beta2       &lt;br /&gt;kind: JoinConfiguration       &lt;br /&gt;controlPlane:       &lt;br /&gt;  localAPIEndpoint:       &lt;br /&gt;    advertiseAddress: &amp;quot;10.0.0.12&amp;quot;       &lt;br /&gt;    bindPort: 5443       &lt;br /&gt;  certificateKey: 31f1e534733a1607e5ba67b2834edd3a7debba41babb1fac1bee47072a98d88b       &lt;br /&gt;discovery:       &lt;br /&gt;  bootstrapToken:       &lt;br /&gt;    apiServerEndpoint: &amp;quot;127.0.0.1:6443&amp;quot;       &lt;br /&gt;    token: &amp;quot;c2t0rj.cofbfnwwrb387890&amp;quot;       &lt;br /&gt;    # Please replace with the &amp;quot;--discovery-token-ca-cert-hash&amp;quot; value printed       &lt;br /&gt;    # after the kubeadm init command is executed successfully       &lt;br /&gt;    caCertHashes:       &lt;br /&gt;    - &amp;quot;sha256:97590810ae34a82501717e33acfca76f16044f1a365c5ad9a1c66433c386c75c&amp;quot;       &lt;br /&gt;nodeRegistration:       &lt;br /&gt;  criSocket: unix:///run/containerd/containerd.sock       &lt;br /&gt;  kubeletExtraArgs:       &lt;br /&gt;    runtime-cgroups: &amp;quot;/system.slice/containerd.service&amp;quot;       &lt;br /&gt;    rotate-server-certificates: &amp;quot;true&amp;quot;       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-5&amp;#12289;&amp;#25289;&amp;#36215;-master" title="2.5&amp;#12289;&amp;#25289;&amp;#36215; master"&gt;&lt;/a&gt;2.5、拉起 master&lt;/h3&gt; &lt;p&gt;在调整好配置后，拉起 master 节点只需要一条命令:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;kubeadm init --config /etc/kubernetes/kubeadm.yaml --upload-certs --ignore-preflight-errors=Swap       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;拉起完成后记得保存相关 Token 以便于后续使用。&lt;/p&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-6&amp;#12289;&amp;#25289;&amp;#36215;&amp;#20854;&amp;#20182;-master" title="2.6&amp;#12289;&amp;#25289;&amp;#36215;&amp;#20854;&amp;#20182; master"&gt;&lt;/a&gt;2.6、拉起其他 master&lt;/h3&gt; &lt;p&gt;在第一个 master 启动完成后，使用   &lt;code&gt;join&lt;/code&gt; 命令让其他 master 加入即可；  &lt;strong&gt;需要注意的是    &lt;code&gt;kubeadm-join.yaml&lt;/code&gt; 配置中需要替换    &lt;code&gt;caCertHashes&lt;/code&gt; 为第一个 master 拉起后的    &lt;code&gt;discovery-token-ca-cert-hash&lt;/code&gt; 的值。&lt;/strong&gt;&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;kubeadm join 127.0.0.1:6443 --config /etc/kubernetes/kubeadm-join.yaml --ignore-preflight-errors=Swap       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-7&amp;#12289;&amp;#25289;&amp;#36215;&amp;#20854;&amp;#20182;-node" title="2.7&amp;#12289;&amp;#25289;&amp;#36215;&amp;#20854;&amp;#20182; node"&gt;&lt;/a&gt;2.7、拉起其他 node&lt;/h3&gt; &lt;p&gt;node 节点拉起与拉起其他 master 节点一样，唯一不同的是需要注释掉配置中的   &lt;code&gt;controlPlane&lt;/code&gt; 部分。&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;12      &lt;br /&gt;13      &lt;br /&gt;14      &lt;br /&gt;15      &lt;br /&gt;16      &lt;br /&gt;17      &lt;br /&gt;18      &lt;br /&gt;19      &lt;br /&gt;20      &lt;br /&gt;21      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# /etc/kubernetes/kubeadm-join.yaml       &lt;br /&gt;apiVersion: kubeadm.k8s.io/v1beta2       &lt;br /&gt;kind: JoinConfiguration       &lt;br /&gt;#controlPlane:       &lt;br /&gt;#  localAPIEndpoint:       &lt;br /&gt;#    advertiseAddress: &amp;quot;10.0.0.12&amp;quot;       &lt;br /&gt;#    bindPort: 5443       &lt;br /&gt;#  certificateKey: 31f1e534733a1607e5ba67b2834edd3a7debba41babb1fac1bee47072a98d88b       &lt;br /&gt;discovery:       &lt;br /&gt;  bootstrapToken:       &lt;br /&gt;    apiServerEndpoint: &amp;quot;127.0.0.1:6443&amp;quot;       &lt;br /&gt;    token: &amp;quot;c2t0rj.cofbfnwwrb387890&amp;quot;       &lt;br /&gt;    # Please replace with the &amp;quot;--discovery-token-ca-cert-hash&amp;quot; value printed       &lt;br /&gt;    # after the kubeadm init command is executed successfully       &lt;br /&gt;    caCertHashes:       &lt;br /&gt;    - &amp;quot;sha256:97590810ae34a82501717e33acfca76f16044f1a365c5ad9a1c66433c386c75c&amp;quot;       &lt;br /&gt;nodeRegistration:       &lt;br /&gt;  criSocket: unix:///run/containerd/containerd.sock       &lt;br /&gt;  kubeletExtraArgs:       &lt;br /&gt;    runtime-cgroups: &amp;quot;/system.slice/containerd.service&amp;quot;       &lt;br /&gt;    rotate-server-certificates: &amp;quot;true&amp;quot;       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;kubeadm join 127.0.0.1:6443 --config /etc/kubernetes/kubeadm-join.yaml --ignore-preflight-errors=Swap       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h3&gt;  &lt;a href="https://mritd.com/#2-8&amp;#12289;&amp;#20854;&amp;#20182;&amp;#22788;&amp;#29702;" title="2.8&amp;#12289;&amp;#20854;&amp;#20182;&amp;#22788;&amp;#29702;"&gt;&lt;/a&gt;2.8、其他处理&lt;/h3&gt; &lt;p&gt;由于 kubelet 开启了证书轮转，所以新集群会有大量 csr 请求，批量允许即可:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;kubectl get csr | grep Pending | awk &amp;apos;{print $1}&amp;apos; | xargs kubectl certificate approve       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;同时为了 master 节点也能负载 pod，需要调整污点:&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;kubectl taint nodes --all node-role.kubernetes.io/master-       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;后续 CNI 等不在本文内容范围内。&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://mritd.com/#&amp;#19977;&amp;#12289;Containerd-&amp;#24120;&amp;#29992;&amp;#25805;&amp;#20316;" title="&amp;#19977;&amp;#12289;Containerd &amp;#24120;&amp;#29992;&amp;#25805;&amp;#20316;"&gt;&lt;/a&gt;三、Containerd 常用操作&lt;/h2&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;1      &lt;br /&gt;2      &lt;br /&gt;3      &lt;br /&gt;4      &lt;br /&gt;5      &lt;br /&gt;6      &lt;br /&gt;7      &lt;br /&gt;8      &lt;br /&gt;9      &lt;br /&gt;10      &lt;br /&gt;11      &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;   &lt;td&gt;    &lt;div&gt;     &lt;pre&gt;      &lt;code&gt;# 列出镜像       &lt;br /&gt;ctr images ls       &lt;br /&gt;       &lt;br /&gt;# 列出 k8s 镜像       &lt;br /&gt;ctr -n k8s.io images ls       &lt;br /&gt;       &lt;br /&gt;# 导入镜像       &lt;br /&gt;ctr -n k8s.io images import xxxx.tar       &lt;br /&gt;       &lt;br /&gt;# 导出镜像       &lt;br /&gt;ctr -n k8s.io images export kube-scheduler.tar k8s.gcr.io/kube-scheduler:v1.21.1       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h2&gt;  &lt;a href="https://mritd.com/#&amp;#22235;&amp;#12289;&amp;#36164;&amp;#28304;&amp;#20179;&amp;#24211;" title="&amp;#22235;&amp;#12289;&amp;#36164;&amp;#28304;&amp;#20179;&amp;#24211;"&gt;&lt;/a&gt;四、资源仓库&lt;/h2&gt; &lt;p&gt;本文中所有   &lt;code&gt;*-pack&lt;/code&gt; 仓库地址如下:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;a href="https://github.com/mritd/cfssl-pack"&gt;https://github.com/mritd/cfssl-pack&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://github.com/mritd/etcd-pack"&gt;https://github.com/mritd/etcd-pack&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://github.com/mritd/kube-apiserver-proxy-pack"&gt;https://github.com/mritd/kube-apiserver-proxy-pack&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://github.com/mritd/kubeadm-config-pack"&gt;https://github.com/mritd/kubeadm-config-pack&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Kubernetes Linux Kubernetes</category>
      <guid isPermaLink="true">https://itindex.net/detail/61478-kubernetes-%E5%88%87%E6%8D%A2-containerd</guid>
      <pubDate>Sat, 29 May 2021 23:01:00 CST</pubDate>
    </item>
    <item>
      <title>市面上流行的 ELK 就是 ElasticSearch + Logstash + Kibana 索引 收集 圖表化</title>
      <link>https://itindex.net/detail/60663-%E6%B5%81%E8%A1%8C-elk-elasticsearch</link>
      <description>&lt;h2&gt;前言&lt;/h2&gt;
 &lt;p&gt;Elasticsearch 是專門數據儲存、分析、索引  &lt;br /&gt;
Kibana 是專門 Web 介面，讓 Elasticsearch 內容來圖表化  &lt;br /&gt;
Logstash 是專門資料收集、過濾、儲存到 Elasticsearch&lt;/p&gt;
 &lt;p&gt;現今多出了 Beats 家族，主要是來當作輕量化 Logstash 的角色， Beats 是用 Golang 寫的，佔用資源更少  &lt;br /&gt;
Beats 成員有 Filebeat / Metricbeat / Packetbeat / Winlogbeat / Heartbeat ，用於不同情境的資料抓取&lt;/p&gt;
 &lt;h2&gt;測試環境&lt;/h2&gt;
 &lt;p&gt;Centos7  &lt;br /&gt;
ELK 版本是 7.7.1&lt;/p&gt;
 &lt;h2&gt;流程架構&lt;/h2&gt;
 &lt;pre&gt;&amp;lt;---- cleint 端---&amp;gt;     &amp;lt;--------------------- server 端 -----------------------&amp;gt;
host ----&amp;gt; Filebeat --&amp;gt; Redis --&amp;gt; Logstash --&amp;gt; Elasticsearch --&amp;gt; Kibna --&amp;gt; Nginx --&amp;gt; manager
&lt;/pre&gt;
 &lt;p&gt;用 Filebeat 抓 host 的 apache access_log 資料，丟到 Redis 裡，再讓 Logstash 去 Redis 拿出來轉丟給 Elasticsearch  &lt;br /&gt;
再透過 Kibna 來瀏覽結果 (而 Nginx 就 proxy 了 Kibana)&lt;/p&gt;
 &lt;p&gt;Redis 綁定 6379 port  &lt;br /&gt;
Elasticsearch 綁定 9200 port  &lt;br /&gt;
Nginx 綁定 8080 port&lt;/p&gt;
 &lt;h2&gt;安裝 ELK 需要 java&lt;/h2&gt;
 &lt;p&gt;yum -y install java java-devel&lt;/p&gt;
 &lt;p&gt;或到 https://www.oracle.com/java/technologies/javase-jre8-downloads.html 下載 jre-XXXXXXX-linux-x64.rpm&lt;/p&gt;
 &lt;p&gt;而 ELK 是下載個自的 RPM 檔&lt;/p&gt;
 &lt;p&gt;https://www.elastic.co/downloads/elasticsearch  &lt;br /&gt;
https://www.elastic.co/downloads/kibana  &lt;br /&gt;
https://www.elastic.co/downloads/logstash&lt;/p&gt;
 &lt;p&gt;wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.7.1-x86_64.rpm  &lt;br /&gt;
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.7.1-x86_64.rpm  &lt;br /&gt;
wget https://artifacts.elastic.co/downloads/logstash/logstash-7.7.1.rpm&lt;/p&gt;
 &lt;p&gt;yum localinstall -y elasticsearch-7.7.1-x86_64.rpm  &lt;br /&gt;
yum localinstall -y kibana-7.7.1-x86_64.rpm  &lt;br /&gt;
yum localinstall -y logstash-7.7.1.rpm&lt;/p&gt;
 &lt;h2&gt;設定 Elasticsearch&lt;/h2&gt;
 &lt;p&gt;編輯  &lt;br /&gt;
vi /etc/elasticsearch/elasticsearch.yml  &lt;br /&gt;
或&lt;/p&gt;
 &lt;pre&gt;cat &amp;lt;&amp;lt; EOF &amp;gt;&amp;gt; /etc/elasticsearch/elasticsearch.yml
network.host: localhost # 如果 LISTEN 其它介面就 network.host: [&amp;quot;localhost&amp;quot;, &amp;quot;1.1.1.1&amp;quot;]
http.port: 9200
EOF
&lt;/pre&gt;
 &lt;p&gt;測試啟動 (並可直接觀查結果，有沒有設定錯誤)&lt;/p&gt;
 &lt;pre&gt;sudo -u elasticsearch /usr/share/elasticsearch/bin/elasticsearch -v&lt;/pre&gt;
 &lt;p&gt;測試結果&lt;/p&gt;
 &lt;pre&gt;curl -X GET &amp;apos;http://localhost:9200&amp;apos;&lt;/pre&gt;
 &lt;p&gt;成功的話出現這個&lt;/p&gt;
 &lt;pre&gt;{
    &amp;quot;name&amp;quot; : &amp;quot;ssorc.tw&amp;quot;,
    &amp;quot;cluster_name&amp;quot; : &amp;quot;elasticsearch&amp;quot;,
    &amp;quot;cluster_uuid&amp;quot; : &amp;quot;SHos4GDQQSacAd5HgoiQLg&amp;quot;,
    &amp;quot;version&amp;quot; : {
        &amp;quot;number&amp;quot; : &amp;quot;7.5.2&amp;quot;,
        &amp;quot;build_flavor&amp;quot; : &amp;quot;default&amp;quot;,
        &amp;quot;build_type&amp;quot; : &amp;quot;rpm&amp;quot;,
        &amp;quot;build_hash&amp;quot; : &amp;quot;8bec50e1e0ad29dad5653712cf3bb580cd1afcdf&amp;quot;,
        &amp;quot;build_date&amp;quot; : &amp;quot;2020-01-15T12:11:52.313576Z&amp;quot;,
        &amp;quot;build_snapshot&amp;quot; : false,
        &amp;quot;lucene_version&amp;quot; : &amp;quot;8.3.0&amp;quot;,
        &amp;quot;minimum_wire_compatibility_version&amp;quot; : &amp;quot;6.8.0&amp;quot;,
        &amp;quot;minimum_index_compatibility_version&amp;quot; : &amp;quot;6.0.0-beta1&amp;quot;
    },
    &amp;quot;tagline&amp;quot; : &amp;quot;You Know, for Search&amp;quot;
}
&lt;/pre&gt;
 &lt;p&gt;其它可用的資訊查看&lt;/p&gt;
 &lt;pre&gt;curl -X GET &amp;apos;http://localhost:9200/_cat/nodes&amp;apos;
curl -X GET &amp;apos;http://localhost:9200/_cat/master&amp;apos;
curl -X GET &amp;apos;http://localhost:9200/_cat/indices&amp;apos;
curl -X GET &amp;apos;http://localhost:9200/_cat/health&amp;apos;&lt;/pre&gt;
 &lt;p&gt;後面可加 ?v 看詳細資訊&lt;/p&gt;
 &lt;h2&gt;設定 Kibana&lt;/h2&gt;
 &lt;p&gt;編輯  &lt;br /&gt;
vi /etc/kibana/kibana.yml&lt;/p&gt;
 &lt;p&gt;或 ↓ (可不加，都保持預設即可)&lt;/p&gt;
 &lt;pre&gt;cat &amp;lt;&amp;lt; EOF &amp;gt;&amp;gt; /etc/kibana/kibana.yml
server.port: 5601
server.host: &amp;quot;localhost&amp;quot;
#elasticsearch.url: &amp;quot;http://localhost:9200&amp;quot;
elasticsearch.hosts: [&amp;quot;http://localhost:9200/&amp;quot;]
EOF&lt;/pre&gt;
 &lt;p&gt;測試啟動&lt;/p&gt;
 &lt;pre&gt;/usr/share/kibana/bin/kibana --allow-root&lt;/pre&gt;
 &lt;p&gt;成功的話，最後訊息會是&lt;/p&gt;
 &lt;pre&gt;log [09:50:41.508] [info][server][Kibana][http] http server running at http://localhost:5601&lt;/pre&gt;
 &lt;h2&gt;透過 nginx 瀏覽 kibana&lt;/h2&gt;
 &lt;p&gt;yum -y install nginx httpd-tools&lt;/p&gt;
 &lt;p&gt;vi /etc/nginx/conf.d/ssorc.tw.conf&lt;/p&gt;
 &lt;pre&gt;server {
    listen 8080;

    server_name ssorc.tw;
    access_log logs/access.log;
    error_log logs/error.log;
    auth_basic &amp;quot;Restricted Access&amp;quot;;
    auth_basic_user_file /etc/nginx/htpasswd.kibana;

    location / {
        proxy_pass http://localhost:5601;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection &amp;apos;upgrade&amp;apos;;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;        
    }
}
&lt;/pre&gt;
 &lt;p&gt;限制登入需帳密&lt;/p&gt;
 &lt;pre&gt;htpasswd -c /etc/nginx/htpasswd.kibana admin&lt;/pre&gt;
 &lt;p&gt;啟動&lt;/p&gt;
 &lt;pre&gt;systemctl start nginx&lt;/pre&gt;
 &lt;p&gt;瀏覽 http://ssorc.tw:8080  &lt;br /&gt;
瀏覽 http://ssorc.tw:8080/status&lt;/p&gt;
 &lt;p&gt;它一開始會出現樣版，可以先不用理會它，是可以匯入它預設的 sample 啦，看看漂介的畫面 ，可事後刪除就好 (現在比較友善的介面了)&lt;/p&gt;
 &lt;h2&gt;安裝 redis&lt;/h2&gt;
 &lt;p&gt;安裝參考    &lt;a href="https://ssorc.tw/6997/%e6%89%8b%e5%8b%95%e7%b7%a8%e8%ad%af%e5%ae%89%e8%a3%9d-redis-phpiredis-phpredisadmin/"&gt;手動編譯安裝 Redis + phpiredis + phpRedisAdmin&lt;/a&gt;&lt;/p&gt;
 &lt;h2&gt;設定 filebeat&lt;/h2&gt;
 &lt;p&gt;wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.7.1-x86_64.rpm  &lt;br /&gt;
yum localinstall -y filebeat-7.7.1-x86_64.rpm&lt;/p&gt;
 &lt;p&gt;vi /etc/filebeat/filebeat.yml&lt;/p&gt;
 &lt;pre&gt;- type: log
  enabled: true
  paths:
    - /var/log/httpd/access_log
  tail_files: true # tail file
  fields:
    log_source: access_log  # 新增欄位變數， log_source 是變數，access_log 是值 ，可供 logstash 過濾用

- type: log
  enabled: true
  paths:
    - /var/log/httpd/error_log
  tail_files: true # tail file
  fields:
    log_source: error_log

output.redis:
  hosts: [&amp;quot;localhost&amp;quot;]
  key: &amp;quot;apache_logs&amp;quot;
  data_type: &amp;quot;list&amp;quot;

#output.elasticsearch:         # 註解
  #hosts: [&amp;quot;localhost:9200&amp;quot;]   # 註解
&lt;/pre&gt;
 &lt;p&gt;測試啟動&lt;/p&gt;
 &lt;pre&gt;/usr/share/filebeat/bin/filebeat -environment systemd -c /etc/filebeat/filebeat.yml -path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat&lt;/pre&gt;
 &lt;p&gt;不過先停止 filebeat ，先測試登入 redis 查看是否有資料&lt;/p&gt;
 &lt;pre&gt;/usr/local/redis/bin/redis-cli&lt;/pre&gt;
 &lt;p&gt;輸入 ， 一開始是沒有的，會是 (empty list or set)&lt;/p&gt;
 &lt;pre&gt;&amp;gt; keys *&lt;/pre&gt;
 &lt;p&gt;再啟動 filebeat&lt;/p&gt;
 &lt;p&gt;就會在 redis 裡看到 (記得瀏覽網頁，才會有資料讓 filebeat 塞到 redis)&lt;/p&gt;
 &lt;pre&gt;1) &amp;quot;apache_logs&amp;quot;&lt;/pre&gt;
 &lt;p&gt;接著再利用 logstash 從 redis 取資料來塞入 elasticsearch，成功的話 redis 就不會看到資料了，因為都被拿走了&lt;/p&gt;
 &lt;p&gt;(以前看到 logstash 就嚇死了，一堆亂七八槽、鬼畫符的設定檔內容，根本不想弄那麼複雜)&lt;/p&gt;
 &lt;h2&gt;設定 logstash&lt;/h2&gt;
 &lt;p&gt;vi /etc/logstash/conf.d/apache.conf&lt;/p&gt;
 &lt;pre&gt;input {
  redis {
    host =&amp;gt; &amp;quot;localhost&amp;quot;
    port =&amp;gt; 6379
    key =&amp;gt; &amp;quot;apache_logs&amp;quot; # 同上面的 filebeat 的 key 名稱
    data_type =&amp;gt; &amp;quot;list&amp;quot;
  }
}

filter {
}

output {
  if [fields][log_source] == &amp;apos;access_log&amp;apos; { # 這裡跟 filebeat.yml 裡設定的 fields log_source 一樣
    elasticsearch {
      hosts =&amp;gt; [&amp;quot;localhost:9200&amp;quot;]
      index =&amp;gt; &amp;quot;apache_access_log&amp;quot; # 如果 log_source 是 access_log 在 elasticsearch 的 index 名稱就是 apache_access_log
    }
  }
  if [fields][log_source] == &amp;apos;error_log&amp;apos; {
    elasticsearch {
      hosts =&amp;gt; [&amp;quot;localhost:9200&amp;quot;]
      index =&amp;gt; &amp;quot;apache_error_log&amp;quot;
    }
  }
}
&lt;/pre&gt;
 &lt;p&gt;測試啟動&lt;/p&gt;
 &lt;pre&gt;sudo -u logstash /usr/share/logstash/bin/logstash --path.settings /etc/logstash --verbose&lt;/pre&gt;
 &lt;h2&gt;登入 Kibana&lt;/h2&gt;
 &lt;p&gt;在左邊的功能按鈕下方會看到 Management  &lt;br /&gt;
這裡分成  &lt;br /&gt;
Elasticsearch 的 Index Management (已經有 Index，也就是 apache_access_log 與 apache_error_log)  &lt;br /&gt;
與  &lt;br /&gt;
Kibana 的 Index Patterns (還沒有 Index)&lt;/p&gt;
 &lt;p&gt;  &lt;a href="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-24-39.png"&gt;   &lt;img alt="ELK-Elasticsearch-Logstash-Kibana" height="684" src="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-24-39.png" width="953"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;所以要在 Kibana 建立 Create index pattern  &lt;br /&gt;
在 Index pattern 輸入 apache_access_log ，然後 Next setp (下一步)  &lt;br /&gt;
在 Time Filter field name 選擇 @timestamp 就可以 create 了&lt;/p&gt;
 &lt;p&gt;  &lt;a href="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-28-01-1.png"&gt;   &lt;img alt="ELK-Elasticsearch-Logstash-Kibana" height="536" src="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-28-01-1.png" width="950"&gt;&lt;/img&gt;&lt;/a&gt;  &lt;br /&gt;
接著到 Discover 看顯示結果了&lt;/p&gt;
 &lt;p&gt;  &lt;a href="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-30-24-1.png"&gt;   &lt;img alt="ELK-Elasticsearch-Logstash-Kibana" height="619" src="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-30-24-1.png" width="1041"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;h2&gt;最後記得設置開機啟動&lt;/h2&gt;
 &lt;p&gt;/etc/init.d/redis start  &lt;br /&gt;
systemctl enable elasticsearch kibana nginx filebeat logstash&lt;/p&gt;
 &lt;h2&gt;後記&lt;/h2&gt;
 &lt;p&gt;其實 Beats 家族是可以直接把資料餵給 ElasticSearch 的，試過後，真心覺得主機負載就降了許多 ， logstash 太佔資源了  &lt;br /&gt;
上面提到的流程架構也是網路上的文章都這樣搞，多了 Redis 也是怕 Logstash 弄丟了資料，也適合大型網路流量的情境吧&lt;/p&gt;
 &lt;p&gt;(少了 logstash 的負載就是差這麼多)&lt;/p&gt;
 &lt;p&gt;  &lt;a href="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-46-33.png"&gt;   &lt;img alt="ELK-Elasticsearch-Logstash-Kibana" height="241" src="https://ssorc.tw/wp-content/uploads/2020/06/2020-06-12T11-46-33.png" width="597"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;h2&gt;Q&amp;amp;A&lt;/h2&gt;
 &lt;p&gt;Q  &lt;br /&gt;
可能需要刪除 index，在啟動 kibana 會有一些錯誤，然後 restart kibana  &lt;br /&gt;
A  &lt;br /&gt;
curl -X DELETE http://localhost:9200/.kibana_task_manager_1  &lt;br /&gt;
curl -X DELETE http://localhost:9200/.kibana_1&lt;/p&gt;
 &lt;p&gt;Q  &lt;br /&gt;
啟動 kibana 時產生錯誤  &lt;br /&gt;
FATAL Error: [config validation of [elasticsearch].url]: definition for this key is missing  &lt;br /&gt;
A  &lt;br /&gt;
#elasticsearch.url: “http://localhost:9200” # 註解這個  &lt;br /&gt;
elasticsearch.hosts: [“http://localhost:9200/”] # 加入這個&lt;/p&gt;
 &lt;p&gt;Q  &lt;br /&gt;
Kibana server is not ready yet  &lt;br /&gt;
A  &lt;br /&gt;
因為 kibana 與 elasticsearch 版本不一樣&lt;/p&gt;
 &lt;p&gt;Q  &lt;br /&gt;
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]  &lt;br /&gt;
A  &lt;br /&gt;
vi /etc/security/limits.conf  &lt;br /&gt;
* soft nofile 65536  &lt;br /&gt;
* hard nofile 65536&lt;/p&gt;
 &lt;p&gt;Q  &lt;br /&gt;
[1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured  &lt;br /&gt;
A  &lt;br /&gt;
因為 vi /etc/elasticsearch/elasticsearch.yml  &lt;br /&gt;
把  &lt;br /&gt;
network.host: localhost  &lt;br /&gt;
改成了  &lt;br /&gt;
network.host: [“localhost”, “1.1.1.1”]  &lt;br /&gt;
所以要加入  &lt;br /&gt;
cluster.initial_master_nodes: [“node-1”, “node-2″]&lt;/p&gt;
 &lt;p&gt;Q  &lt;br /&gt;
有時後主機可能會設置 /tmp noexec ，又 logstash 會需要 exec  &lt;br /&gt;
所以另起 tmpdir  &lt;br /&gt;
A  &lt;br /&gt;
mkdir /var/lib/logstash/tmp/  &lt;br /&gt;
chmod 1777 /var/lib/logstash/tmp/  &lt;br /&gt;
chown logstash.logstash -R /var/lib/logstash/tmp/  &lt;br /&gt;
vi /etc/default/logstash  &lt;br /&gt;
vi /etc/logstash/startup.options  &lt;br /&gt;
LS_JAVA_OPTS=”-Djava.io.tmpdir=/var/lib/logstash/tmp/”&lt;/p&gt;
 &lt;p&gt;這篇文章   &lt;a href="https://ssorc.tw/8011/%e5%b8%82%e9%9d%a2%e4%b8%8a%e6%b5%81%e8%a1%8c%e7%9a%84-elk-%e5%b0%b1%e6%98%af-elasticsearch-logstash-kibana-%e7%b4%a2%e5%bc%95-%e6%94%b6%e9%9b%86-%e5%9c%96%e8%a1%a8%e5%8c%96/" rel="nofollow"&gt;市面上流行的 ELK 就是 ElasticSearch + Logstash + Kibana 索引 收集 圖表化&lt;/a&gt; 最早出現於   &lt;a href="https://ssorc.tw" rel="nofollow"&gt;SSORC.tw&lt;/a&gt;。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux Beats elasticsearch ELK Filebeat</category>
      <guid isPermaLink="true">https://itindex.net/detail/60663-%E6%B5%81%E8%A1%8C-elk-elasticsearch</guid>
      <pubDate>Fri, 12 Jun 2020 11:41:53 CST</pubDate>
    </item>
    <item>
      <title>ProxySQL+Mysql实现数据库读写分离实战</title>
      <link>https://itindex.net/detail/60438-proxysql-mysql-%E6%95%B0%E6%8D%AE%E5%BA%93</link>
      <description>&lt;p&gt;前面也写过几篇关于Mysql数据的文章：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://segmentfault.com/a/1190000021100914"&gt;MySQL集群高可用架构之MHA&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://segmentfault.com/a/1190000020693588"&gt;MySQL 同步复制及高可用方案总结&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://segmentfault.com/a/1190000020751216"&gt;官方工具｜MySQL Router 高可用原理与实战&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;今天给大家带来的是关于数据库读写分离相关的实战操作。&lt;/p&gt;
 &lt;h2&gt;ProxySQL介绍&lt;/h2&gt;
 &lt;p&gt;ProxySQL是一个高性能的MySQL中间件，拥有强大的规则引擎。具有以下特性：  &lt;a href="http://www.proxysql.com/" rel="nofollow noreferrer"&gt;http://www.proxysql.com/&lt;/a&gt;&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;1、连接池，而且是multiplexing     &lt;br /&gt;2、主机和用户的最大连接数限制     &lt;br /&gt;3、自动下线后端DB&lt;/p&gt;
  &lt;ul&gt;
   &lt;li&gt;延迟超过阀值&lt;/li&gt;
   &lt;li&gt;ping 延迟超过阀值&lt;/li&gt;
   &lt;li&gt;网络不通或宕机&lt;/li&gt;
&lt;/ul&gt;
  &lt;p&gt;4、强大的规则路由引擎&lt;/p&gt;
  &lt;ul&gt;
   &lt;li&gt;实现读写分离&lt;/li&gt;
   &lt;li&gt;查询重写&lt;/li&gt;
   &lt;li&gt;sql流量镜像&lt;/li&gt;
&lt;/ul&gt;
  &lt;p&gt;5、支持prepared statement     &lt;br /&gt;6、支持Query Cache     &lt;br /&gt;7、支持负载均衡，与gelera结合自动failover&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;h2&gt;整体环境介绍&lt;/h2&gt;
 &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000022074104" title=""&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;1、系统环境&lt;/h4&gt;
 &lt;p&gt;三台服务器系统环境一致如下&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;[root@db1 ~]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
[root@db1 ~]# uname -r
3.10.0-693.el7.x86_64&lt;/code&gt;&lt;/pre&gt;
 &lt;h4&gt;2、IP地址与软件版本&lt;/h4&gt;
 &lt;blockquote&gt;  &lt;ul&gt;
   &lt;li&gt;proxy  192.168.22.171&lt;/li&gt;
   &lt;li&gt;db1     192.168.22.173&lt;/li&gt;
   &lt;li&gt;db2    192.168.22.174&lt;/li&gt;
   &lt;li&gt;mysql  5.7.17&lt;/li&gt;
   &lt;li&gt;proxy  sql 1.4.8&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;
 &lt;h4&gt;3、关闭防火墙、selinux&lt;/h4&gt;
 &lt;pre&gt;  &lt;code&gt;systemctl stop firewalld  #停止防火墙服务
systemctl disable firewalld  #禁止开机自启动
sed -i &amp;apos;s#SELINUX=enforcing#SELINUX=disabled#g&amp;apos;  /etc/selinux/conf  &amp;amp;&amp;amp; reboot
#用sed命令替换的试修改selinux的配置文件&lt;/code&gt;&lt;/pre&gt;
 &lt;h4&gt;4、mysql安装与主从同步&lt;/h4&gt;
 &lt;p&gt;安装请参考以下文章&lt;/p&gt;
 &lt;p&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI0MDQ4MTM5NQ==&amp;mid=2247484330&amp;idx=1&amp;sn=5e3e35bb5793258b86c096485fe02246&amp;chksm=e91b66b6de6cefa09740c86b70ef62d943298ef874fec0af1d66254701479196f6f785569cf2&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;   &lt;strong&gt;LAMP架构应用实战——MySQL服务&lt;/strong&gt;&lt;/a&gt;  &lt;/p&gt;
 &lt;p&gt;主从同步请参以下文章&lt;/p&gt;
 &lt;p&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzI0MDQ4MTM5NQ==&amp;mid=2247484506&amp;idx=1&amp;sn=e2ae27f5b561485011846237bd74707b&amp;chksm=e91b6146de6ce850798c2fe564a5ff5a7096437ffde458b848350720bb39ff46e01a190c0e41&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;   &lt;strong&gt;Linux系统MySQL数据库主从同步实战过程&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;h2&gt;安装布署过程&lt;/h2&gt;
 &lt;h3&gt;1、数据库主从同步&lt;/h3&gt;
 &lt;h5&gt;查看主从同步状态&lt;/h5&gt;
 &lt;pre&gt;  &lt;code&gt;mysql&amp;gt; show slave status\G
*************************** 1. row ***************************               
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.22.173                  
Master_User: rep                  
Master_Port: 3306                
Connect_Retry: 60              
Master_Log_File: master-log.000001
Read_Master_Log_Pos: 154               
Relay_Log_File: db2-relay-bin.000002
Relay_Log_Pos: 321        
Relay_Master_Log_File: master-log.000001  
Slave_IO_Running: Yes            
Slave_SQL_Running: Yes              
Replicate_Do_DB:           
Replicate_Ignore_DB:            
Replicate_Do_Table:        
Replicate_Ignore_Table:       
Replicate_Wild_Do_Table:   
Replicate_Wild_Ignore_Table:                    
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 526
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No 
Master_SSL_CA_File: 
Master_SSL_CA_Path: 
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No 
Last_IO_Errno: 0 
Last_IO_Error: 
Last_SQL_Errno: 0 
Last_SQL_Error:
Replicate_Ignore_Server_Ids: 
Master_Server_Id: 1 
Master_UUID: 70a61633-63ae-11e8-ab86-000c29fe99ea 
Master_Info_File: /mysqldata/master.info
SQL_Delay: 0 
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates 
Master_Retry_Count: 86400 
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl: 
Master_SSL_Crlpath: 
Retrieved_Gtid_Set: 
Executed_Gtid_Set: 
Auto_Position: 0 
Replicate_Rewrite_DB:
Channel_Name: 
Master_TLS_Version:
1 row in set (0.00 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;h5&gt;检测主从同步&lt;/h5&gt;
 &lt;pre&gt;  &lt;code&gt;[root@db1 ~]# mysql -uroot -p -e &amp;quot;create database testdb;
&amp;quot;Enter password: 
[root@db1 ~]# mysql -uroot -p -e &amp;quot;show  databases;&amp;quot; |grep testdb
Enter password: 
testdb
#db2上查看是否同步
mysql&amp;gt; show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| testdb             |
+--------------------+
5 rows in set (0.01 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;2、准备proxySQL软件&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;[root@proxy ~]# wget https://github.com/sysown/proxysql/releases/download/v1.4.8/proxysql-1.4.8-1-centos7.x86_64.rpm
[root@proxy ~]# ll proxysql-1.4.8-1-centos7.x86_64.rpm 
-rw-r--r-- 1 root root 5977168 Apr 10 11:38 proxysql-1.4.8-1-centos7.x86_64.rpm&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;3、安装配置&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;[root@proxy ~]# yum install -y proxysql-1.4.8-1-centos7.x86_64.rpm
[root@proxy ~]# rpm -ql  proxysql
/etc/init.d/proxysql    #启动脚本
/etc/proxysql.cnf       #配置文件，仅在第一次(/var/lib/proxysql/proxysql.db文件不存在)启动时有效。启#动后可以在proxysql管理端中通过修改数据库的方式修改配置并生效(官方推荐方式。)
/usr/bin/proxysql       #主程序文件
/usr/share/proxysql/tools/proxysql_galera_checker.sh
/usr/share/proxysql/tools/proxysql_galera_writer.pl&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;4、配置文件详解&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;[root@proxy ~]# egrep -v &amp;quot;^#|^$&amp;quot; /etc/proxysql.cnf
datadir=&amp;quot;/var/lib/proxysql&amp;quot;     #数据目录
admin_variables=
{    
admin_credentials=&amp;quot;admin:admin&amp;quot;   #连接管理端的用户名与密码 
mysql_ifaces=&amp;quot;0.0.0.0:6032&amp;quot;       #管理端口，用来连接proxysql的管理数据库
}
mysql_variables=
{    
threads=4      #指定转发端口开启的线程数量    
max_connections=2048    
default_query_delay=0
default_query_timeout=36000000
have_compress=true
poll_timeout=2000
interfaces=&amp;quot;0.0.0.0:6033&amp;quot;        #指定转发端口，用于连接后端mysql数据库的，相当于代理作用
default_schema=&amp;quot;information_schema&amp;quot;
stacksize=1048576
server_version=&amp;quot;5.5.30&amp;quot;          #指定后端mysql的版本
connect_timeout_server=3000 
monitor_username=&amp;quot;monitor&amp;quot;
monitor_password=&amp;quot;monitor&amp;quot;
monitor_history=600000
monitor_connect_interval=60000
monitor_ping_interval=10000
monitor_read_only_interval=1500 
monitor_read_only_timeout=500  
ping_interval_server_msec=120000 
ping_timeout_server=500
commands_stats=true 
sessions_sort=true 
connect_retries_on_failure=10
}
mysql_servers =
(
)
mysql_users:
(
)
mysql_query_rules:
(
)
scheduler=
(
)
mysql_replication_hostgroups=
(
)

#因此我们使用官方推荐的方式来配置proxy sql&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;5、启动服务并查看&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;[root@proxy ~]# /etc/init.d/proxysql
startStarting ProxySQL: DONE!
[root@proxy ~]# ss -lntup|grep proxy
tcp    LISTEN     0   128   *:6032      *:*    users:((&amp;quot;proxysql&amp;quot;,pid=1199,fd=23))
tcp    LISTEN     0   128   *:6033      *:*    users:((&amp;quot;proxysql&amp;quot;,pid=1199,fd=22))
tcp    LISTEN     0   128   *:6033      *:*    users:((&amp;quot;proxysql&amp;quot;,pid=1199,fd=21))
tcp    LISTEN     0   128   *:6033      *:*    users:((&amp;quot;proxysql&amp;quot;,pid=1199,fd=20))
tcp    LISTEN     0   128   *:6033      *:*    users:((&amp;quot;proxysql&amp;quot;,pid=1199,fd=19))

#可以看出转发端口6033是启动了四个线程&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;6、在mysql上配置账号并授权&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;mysql&amp;gt; GRANT ALL ON *.* TO &amp;apos;proxysql&amp;apos;@&amp;apos;192.168.22.%&amp;apos; IDENTIFIED BY &amp;apos;123456&amp;apos;;
Query OK, 0 rows affected, 1 warning (0.03 sec)
mysql&amp;gt; flush privileges;
Query OK, 0 rows affected (0.02 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;7、proxysql默认数据库说明&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;[root@proxy ~]# yum install mysql -y
[root@proxy ~]# mysql -uadmin -padmin -h127.0.0.1 -P6032
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.30 (ProxySQL Admin Module)
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
Type &amp;apos;help;&amp;apos; or &amp;apos;\h&amp;apos; for help. Type &amp;apos;\c&amp;apos; to clear the current input statement.
MySQL [(none)]&amp;gt; show databases;
+-----+---------------+-------------------------------------+
| seq | name          | file                                |
+-----+---------------+-------------------------------------+
| 0   | main          |                                     |
| 2   | disk          | /var/lib/proxysql/proxysql.db       |
| 3   | stats         |                                     |
| 4   | monitor       |                                     |
| 5   | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+---------------+-------------------------------------+
5 rows in set (0.00 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;blockquote&gt;
  &lt;strong&gt;main：&lt;/strong&gt;内存配置数据库，表里存放后端db实例、用户验证、路由规则等信息。表名以 runtime_开头的表示proxysql当前运行的配置内容，不能通过dml语句修改，只能修改对应的不以 runtime_ 开头的（在内存）里的表，然后 LOAD 使其生效， SAVE 使其存到硬盘以供下次重启加载。    &lt;br /&gt;  &lt;strong&gt;disk：&lt;/strong&gt;是持久化到硬盘的配置，sqlite数据文件。    &lt;br /&gt;  &lt;strong&gt;stats：&lt;/strong&gt;是proxysql运行抓取的统计信息，包括到后端各命令的执行次数、流量、processlist、查询种类汇总/执行时间等等。    &lt;br /&gt;  &lt;strong&gt;monitor：&lt;/strong&gt;库存储 monitor 模块收集的信息，主要是对后端db的健康/延迟检查。&lt;/blockquote&gt;
 &lt;h3&gt;8、proxysql的配置系统&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;ProxySQL具有一个复杂但易于使用的配置系统，可以满足以下需求：&lt;/strong&gt;&lt;/p&gt;
 &lt;blockquote&gt;1、允许轻松动态更新配置（这是为了让ProxySQL用户可以在需要零宕机时间配置的大型基础架构中使用它）。与MySQL兼容的管理界面可用于此目的。    &lt;br /&gt;2、允许尽可能多的配置项目动态修改，而不需要重新启动ProxySQL进程    &lt;br /&gt;3、可以毫不费力地回滚无效配置    &lt;br /&gt;4、这是通过多级配置系统实现的，其中设置从运行时移到内存，并根据需要持久保存到磁盘。&lt;/blockquote&gt;
 &lt;h6&gt;3级配置由以下几层组成：&lt;/h6&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://segmentfault.com/img/bVbEMxA" title="image.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;参考文章：  &lt;a href="https://github.com/sysown/proxysql/wiki/Configuring-ProxySQL" rel="nofollow noreferrer"&gt;https://github.com/sysown/pro...&lt;/a&gt;&lt;/p&gt;
 &lt;h3&gt;9、配置proxysql管理用户&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;proxysql默认的表信息如下&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;MySQL [main]&amp;gt; show tables;
+--------------------------------------------+
| tables                                     |
+--------------------------------------------+
| global_variables                           |
| mysql_collations                           |
| mysql_group_replication_hostgroups         |
| mysql_query_rules                          |
| mysql_query_rules_fast_routing             |
| mysql_replication_hostgroups               |
| mysql_servers                              |
| mysql_users                                |
| proxysql_servers                           |
| runtime_checksums_values                   |
| runtime_global_variables                   |
| runtime_mysql_group_replication_hostgroups |
| runtime_mysql_query_rules                  |
| runtime_mysql_query_rules_fast_routing     |
| runtime_mysql_replication_hostgroups       |
| runtime_mysql_servers                      |
| runtime_mysql_users                        |
| runtime_proxysql_servers                   |
| runtime_scheduler                          |
| scheduler                                  |
+--------------------------------------------+
20 rows in set (0.00 sec)

#这里是使用insert into语句来动态配置，而可以不需要重启
MySQL [(none)]&amp;gt; insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(1,&amp;apos;db1&amp;apos;,&amp;apos;3306&amp;apos;,1,&amp;apos;Write Group&amp;apos;);
Query OK, 1 row affected (0.01 sec)

MySQL [(none)]&amp;gt; insert intomysql_servers(hostgroup_id,hostname,port,weight,comment) values(2,&amp;apos;db2&amp;apos;,&amp;apos;3307&amp;apos;,1,&amp;apos;Read Group&amp;apos;);
Query OK, 1 row affected (0.00 sec)

MySQL [(none)]&amp;gt; select * from mysql_servers;
+--------------+----------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| hostgroup_id | hostname | port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment     |
+--------------+----------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
| 1            | db1      | 3306 | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              | Write Group |
| 2            | db2      | 3307 | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              | Read Group  
|+--------------+----------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+-------------+
2 rows in set (0.00 sec)

#接下来将刚刚在mysql客户端创建的用户写入到proxy sql主机的mysql_users表中，它也是用于proxysql客户端访问数据库，默认组是写组，当读写分离规则出现问题时，它会直接访问默认组的数据库。
MySQL [main]&amp;gt; INSERT INTO mysql_users(username,password,default_hostgroup) VALUES (&amp;apos;proxysql&amp;apos;,&amp;apos;123456&amp;apos;,1);
Query OK, 1 row affected (0.00 sec)

MySQL [main]&amp;gt; select * from mysql_users;
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+
| username | password | active | use_ssl | default_hostgroup | default_schema | schema_locked | transaction_persistent | fast_forward | backend | frontend | max_connections |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+
| proxysql | 123456   | 1      | 0       | 1                 | NULL           | 0             | 1                      | 0            | 1       | 1        | 10000           |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+1 
row in set (0.00 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;h6&gt;在mysql上添加监控的用户&lt;/h6&gt;
 &lt;pre&gt;  &lt;code&gt;mysql&amp;gt; GRANT SELECT ON *.* TO &amp;apos;monitor&amp;apos;@&amp;apos;192.168.22.%&amp;apos; IDENTIFIED BY &amp;apos;monitor&amp;apos;;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql&amp;gt; flush privileges;
Query OK, 0 rows affected (0.00 sec)

#在proxysql主机端配置监控用户
MySQL [main]&amp;gt; set mysql-monitor_username=&amp;apos;monitor&amp;apos;;
Query OK, 1 row affected (0.00 sec)

MySQL [main]&amp;gt; set mysql-monitor_password=&amp;apos;monitor&amp;apos;;
Query OK, 1 row affected (0.00 sec)

#参考文章：https://github.com/sysown/proxysql/wiki/ProxySQL-Configuration&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;10、配置proxysql的转发规则&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;MySQL [main]&amp;gt; insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(1,1,&amp;apos;^SELECT.*FOR UPDATE$&amp;apos;,1,1);
Query OK, 1 row affected (0.01 sec)

MySQL [main]&amp;gt; insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(2,1,&amp;apos;^SELECT&amp;apos;,2,1);
Query OK, 1 row affected (0.00 sec)

MySQL [main]&amp;gt; select rule_id,active,match_digest,destination_hostgroup,apply from mysql_query_rules;
+---------+--------+----------------------+-----------------------+-------+
| rule_id | active | match_digest         | destination_hostgroup | apply |
+---------+--------+----------------------+-----------------------+-------+
| 1       | 1      | ^SELECT.*FOR UPDATE$ | 1                     | 1     |
| 2       | 1      | ^SELECT              | 2                     | 1     |
+---------+--------+----------------------+-----------------------+-------+
2 rows in set (0.00 sec)

#配置查询select的请求转发到hostgroup_id=2组上（读组）#征对select * from table_name  for update这样的修改语句，我们是需要将请求转到写组，也就是hostgroup_id=1#对于其它没有被规则匹配的请求全部转发到默认的组（mysql_users表中default_hostgroup）&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;11、更新配置到RUNTIME中&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;由上面的配置系统层级关系可以得知所有进来的请求首先是经过RUNTIME层&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;MySQL [main]&amp;gt; load mysql users to runtime;
Query OK, 0 rows affected (0.00 sec)

MySQL [main]&amp;gt; load mysql servers to runtime;
Query OK, 0 rows affected (0.02 sec)

MySQL [main]&amp;gt; load mysql query rules to runtime;
Query OK, 0 rows affected (0.00 sec)

MySQL [main]&amp;gt; load mysql variables to runtime;
Query OK, 0 rows affected (0.00 sec)

MySQL [main]&amp;gt; load admin variables to runtime;
Query OK, 0 rows affected (0.00 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;12、将所有配置保存至磁盘上&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;所有配置数据保存到磁盘上，也就是永久写入/var/lib/proxysql/proxysql.db这个文件中&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;MySQL [main]&amp;gt; save mysql users to disk;
Query OK, 0 rows affected (0.03 sec)

MySQL [main]&amp;gt; save mysql servers to disk;
Query OK, 0 rows affected (0.04 sec)

ySQL [main]&amp;gt; save mysql query rules to disk;
Query OK, 0 rows affected (0.03 sec)

MySQL [main]&amp;gt; save mysql variables to disk;
Query OK, 94 rows affected (0.02 sec)

MySQL [main]&amp;gt; save admin variables to disk;
Query OK, 31 rows affected (0.02 sec)

MySQL [main]&amp;gt; load mysql users to runtime;
Query OK, 0 rows affected (0.00 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;13、测试读写分离&lt;/h3&gt;
 &lt;pre&gt;  &lt;code&gt;[root@proxy ~]# mysql -uproxysql -p123456 -h 127.0.0.1 -P 6033
Welcome to the MariaDB monitor.Commands end with ; or \g.
Your MySQL connection id is 2Server version: 5.5.30 (ProxySQL)

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type &amp;apos;help;&amp;apos; or &amp;apos;\h&amp;apos; for help. Type &amp;apos;\c&amp;apos; to clear the current input statement.

MySQL [(none)]&amp;gt; show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| testdb             |
+--------------------+
5 rows in set (0.02 sec)#这才是我们真正的数据库啊&lt;/code&gt;&lt;/pre&gt;
 &lt;h5&gt;创建数据与表，测试读写分离情况&lt;/h5&gt;
 &lt;pre&gt;  &lt;code&gt;MySQL [(none)]&amp;gt; create database test_proxysql;
Query OK, 1 row affected (0.02 sec)

MySQL [(none)]&amp;gt; use test_proxysql;
Database changed

MySQL [test_proxysql]&amp;gt; create table test_tables(name varchar(20),age int(4));
Query OK, 0 rows affected (0.07 sec)

MySQL [test_proxysql]&amp;gt; insert into test_tables values(&amp;apos;zhao&amp;apos;,&amp;apos;30&amp;apos;);
Query OK, 1 row affected (0.09 sec)

MySQL [test_proxysql]&amp;gt; select * from test_tables;
+------+------+
| name | age  |
+------+------+
| zhao |   30 |
+------+------+
1 row in set (0.02 sec)&lt;/code&gt;&lt;/pre&gt;
 &lt;h5&gt;在proxysql管理端查看读写分离&lt;/h5&gt;
 &lt;pre&gt;  &lt;code&gt;MySQL [main]&amp;gt; select * from stats_mysql_query_digest;
+-----------+--------------------+----------+--------------------+------------------------------------------------------+------------+------------+------------+----------+----------+----------+
| hostgroup | schemaname         | username | digest             | digest_text                                          | count_star | first_seen | last_seen  | sum_time | min_time | max_time |
+-----------+--------------------+----------+--------------------+------------------------------------------------------+------------+------------+------------+----------+----------+----------+
| 2         | test_proxysql      | proxysql | 0x57CF7EC26C91DF9A | select * from test_tables                            |1          | 1527667635 | 1527667635 | 14253    | 14253    | 14253    |
| 1         | information_schema | proxysql | 0x226CD90D52A2BA0B | select @@version_comment limit ?                     | 1          | 1527667214 | 1527667214 | 0        | 0        | 0        |
| 1         | test_proxysql      | proxysql | 0xFF9877421CFBDA6F | insert into test_tables values(?,?)                  | 1          | 1527667623 | 1527667623 | 89033    | 89033    | 89033    |
| 1         | information_schema | proxysql | 0xE662AE2DEE853B44 | create database test-proxysql                        | 1          | 1527667316 | 1527667316 | 8470     | 8470     | 8470     |
| 1         | information_schema | proxysql | 0x02033E45904D3DF0 | show databases                                       | 1          | 1527667222 | 1527667222 | 19414    | 19414    | 19414    |
| 1         | information_schema | proxysql | 0xB9EF28C84E4207EC | create database test_proxysql                        | 1          | 1527667332 | 1527667332 | 15814    | 15814    | 15814    |
| 2         | information_schema | proxysql | 0x620B328FE9D6D71A | SELECT DATABASE()                                    | 1          | 1527667342 | 1527667342 | 23386    | 23386    | 23386    |
| 1         | test_proxysql      | proxysql | 0x02033E45904D3DF0 | show databases                                       | 1          | 1527667342 | 1527667342 | 2451     | 2451     | 2451     |
| 1         | test_proxysql      | proxysql | 0x59F02DA280268525 | create table test_tables                             | 1          | 1527667360 | 1527667360 | 9187     | 9187     | 9187     |
| 1         | test_proxysql      | proxysql | 0x99531AEFF718C501 | show tables                                          | 1          | 1527667342 | 1527667342 | 1001     | 1001     | 1001     |
| 1         | test_proxysql      | proxysql | 0xC745E37AAF6095AF | create table test_tables(name varchar(?),age int(?)) | 1          | 1527667558 | 1527667558 | 68935    | 68935    | 68935    |
+-----------+--------------------+----------+--------------------+------------------------------------------------------+------------+------------+------------+----------+----------+----------+
11 rows in set (0.01 sec)#从上述结果就可以看出读写分离配置是成功的，读请求是转发到2组，写请求转发到1组&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000022074105" title=""&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h5&gt;整个读写分离的架构配置到此就完成了，但是此架构存在需要优化的地方，那就是  &lt;code&gt;此架构存在单点问题&lt;/code&gt;。实际生产环境中可采用  &lt;code&gt;MHA+ProxySQL+Mysql&lt;/code&gt;这类架构解决此问题，请持续关注!&lt;/h5&gt;
 &lt;p&gt;感谢此文对你有帮助的话，请点个赞然后转发支持一下，感谢大家！&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>mysql linux 运维 程序员</category>
      <guid isPermaLink="true">https://itindex.net/detail/60438-proxysql-mysql-%E6%95%B0%E6%8D%AE%E5%BA%93</guid>
      <pubDate>Thu, 19 Mar 2020 17:13:36 CST</pubDate>
    </item>
    <item>
      <title>被忽视的time命令</title>
      <link>https://itindex.net/detail/60205-time-%E5%91%BD%E4%BB%A4</link>
      <description>&lt;p&gt;如果要选 Linux 下最容易被忽视的命令，time 应该算一个。简单来说，它是一个用来计算命令运行时间的工具，之所以说它容易被忽视，一方面很多人根本不知道 time 的存在，而是习惯在命令启动前后记录两个时间戳，然后手动计算命令运行时间；另一方面很多人虽然知道 time 的存在，但是却并没有真正理解它的含义。&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;下面让我们通过若干例子来理解 time 的真正含义：&lt;/p&gt;
 &lt;pre&gt;shell&amp;gt; time ls

real	0m0.003s
user	0m0.001s
sys	0m0.002s&lt;/pre&gt;
 &lt;p&gt;大概意思是 ls 命令运行花了 0.003 秒，其中用户态花了 0.001 秒，内核态花了 0.002 秒，看上去似乎「real = user + sys」？此等式是否成立，在回答这个问题之前我们不妨看看 real、user、sys 的确切含义，如下定义源自   &lt;a href="https://stackoverflow.com/questions/556405/what-do-real-user-and-sys-mean-in-the-output-of-time1" rel="noopener noreferrer" target="_blank"&gt;Stackoverflow&lt;/a&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;div&gt;
    &lt;div&gt;Real is wall clock time – time from start to finish of the call. This is all elapsed time including time slices used by other processes and time the process spends blocked (for example if it is waiting for I/O to complete).&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
  &lt;li&gt;User is the amount of CPU time spent in user-mode code (outside the kernel) within the process. This is only actual CPU time used in executing the process. Other processes and time the process spends blocked do not count towards this figure.&lt;/li&gt;
  &lt;li&gt;Sys is the amount of CPU time spent in the kernel within the process. This means executing CPU time spent in system calls within the kernel, as opposed to library code, which is still running in user-space. Like ‘user’, this is only CPU time used by the process.&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;总的来说，real 是我们直观感受到的消耗的时间，如果命令运行时被堵塞了，那么堵塞时间也是被统计在内的， user 统计在用户态态模式下消耗的 CPU 时间，如果命令运行时被堵塞了，那么堵塞时间并不被统计在内，sys 统计在内核态模式下消耗的 CPU 时间，如果命令运行时被堵塞了，那么堵塞时间并不被统计在内。&lt;/p&gt;
 &lt;p&gt;看上去是否统计堵塞时间是区分 real 和 user、sys 的关键，看看下面这个 sleep 例子：&lt;/p&gt;
 &lt;pre&gt;shell&amp;gt; time sleep 1

real	0m1.002s
user	0m0.001s
sys	0m0.001s&lt;/pre&gt;
 &lt;p&gt;那么除了堵塞时间，还有别的关键点么，让我们再看看下面两个例子：&lt;/p&gt;
 &lt;pre&gt;shell&amp;gt; time find /etc -type f | xargs -n1 -I{} cat {} &amp;gt; /dev/null

real	0m2.050s
user	0m0.626s
sys	0m1.533s

shell&amp;gt; time find /etc -type f | xargs -n1 -I{} -P2 cat {} &amp;gt; /dev/null

real	0m1.079s
user	0m0.681s
sys	0m1.486s
&lt;/pre&gt;
 &lt;p&gt;前后两个例子的区别在于后者在使用 xargs 的时候通过「-P」选项激活了多进程，换句话说，后者可以同时用到多个 CPU。&lt;/p&gt;
 &lt;p&gt;了解了相关知识之后，我们通过 real、user、sys 的大小就可以判断程序的行为：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;如果 real 远远大于 user + sys，那么说明程序可能有严重的堵塞问题。&lt;/li&gt;
  &lt;li&gt;如果 real 基本等于 user + sys，那么说明程序可能没有用到多 CPU 能力，&lt;/li&gt;
  &lt;li&gt;如果 real 远远小于 user + sys，那么说明程序可能用到了多 CPU 能力。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;怎么样？看似简单的 time 命令，是不是远比你想的要复杂得多！&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Technical Linux</category>
      <guid isPermaLink="true">https://itindex.net/detail/60205-time-%E5%91%BD%E4%BB%A4</guid>
      <pubDate>Sun, 08 Dec 2019 11:57:36 CST</pubDate>
    </item>
    <item>
      <title>MySQL 同步复制及高可用方案总结</title>
      <link>https://itindex.net/detail/60091-mysql-%E5%90%8C%E6%AD%A5-%E5%A4%8D%E5%88%B6</link>
      <description>&lt;h3&gt;1.前言&lt;/h3&gt;
 &lt;p&gt;mysql作为应用程序的数据存储服务，要实现mysql数据库的高可用。必然要使用的技术就是数据库的复制，如果主节点出现故障可以手动的切换应用到从节点，这点相信运维同学都是知道，并且可以实现的。但是这种情况只是手动的切换，对可用性有要求的业务需要分别实现主库和从库的高可用，保障在数据库出现down机的情况下，可以自动实现数据库的故障转移，保障应用的可用性和用户体验。&lt;/p&gt;
 &lt;p&gt;本文将会对一些常用的数据库高可用方案进行介绍，根据你不同的场景，选择合适的高可用方案即可。&lt;/p&gt;
 &lt;h3&gt;2.MMM高可用方案&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;2.1.Mysql-MMM介绍&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;MMM(Master-Master replication managerfor Mysql，Mysql主主复制管理器)是一套灵活的脚本程序，基于perl实现，用来对mysql replication进行监控和故障迁移，并能管理mysql Master-Master复制的配置(同一时间只有一个节点是可写的)。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;2.2.组件&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;mmm_mond：监控进程，负责所有的监控工作，决定和处理所有节点角色活动。此脚本需要在监管机上运行。&lt;/p&gt;
 &lt;p&gt;mmm_agentd：运行在每个mysql服务器上的代理进程，完成监控的探针工作和执行简单的远端服务设置。此脚本需要在被监管机上运行。&lt;/p&gt;
 &lt;p&gt;mmm_control：一个简单的脚本，提供管理mmm_mond进程的命令。&lt;/p&gt;
 &lt;p&gt;mysql-mmm的监管端会提供多个虚拟IP（VIP），包括一个可写VIP，多个可读VIP，通过监管的管理，这些IP会绑定在可用mysql之上，当某一台mysql宕机时，监管会将VIP迁移至其他mysql。&lt;/p&gt;
 &lt;p&gt;在整个监管过程中，需要在mysql中添加相关授权用户，以便让mysql可以支持监理机的维护。授权的用户包括一个mmm_monitor用户和一个mmm_agent用户，如果想使用mmm的备份工具则还要添加一个mmm_tools用户。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;2.3.架构图&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;正常工作时：  &lt;br /&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000020693591?w=605&amp;h=461" title=""&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;主节点故障时：  &lt;br /&gt;  &lt;img alt="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154036.png" src="https://segmentfault.com/img/bVbyZvD" title="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154036.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;2.4.MMM优点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）高可用性，扩展性好，出现故障自动转移，对于主主同步，在同一时间只提供一台数据库写操作，保证数据的一致性。  &lt;br /&gt;（2）配置简单，容易操作。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;2.5.MMM缺点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）需要一台备份服务器，浪费资源  &lt;br /&gt;（2）需要多个虚拟IP  &lt;br /&gt;（3）agent可能意外终止，引起裂脑。&lt;/p&gt;
 &lt;h3&gt;3.MHA介绍&lt;/h3&gt;
 &lt;p&gt;MHA（Master High Availability）目前在MySQL高可用方面是一个相对成熟的解决方案，它由日本DeNA公司youshimaton（现就职于Facebook公司）开发，是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中，MHA能做到在0~30秒之内自动完成数据库的故障切换操作，并且在进行故障切换的过程中，MHA能在最大程度上保证数据的一致性，以达到真正意义上的高可用。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;3.1.MHA架构介绍&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;该软件由两部分组成：MHA Manager（管理节点）和MHA Node（数据节点）。MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群，也可以部署在一台slave节点上。MHA Node运行在每台MySQL服务器上，MHA Manager会定时探测集群中的master节点，当master出现故障时，它可以自动将最新数据的slave提升为新的master，然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。&lt;/p&gt;
 &lt;p&gt;在MHA自动故障切换过程中，MHA试图从宕机的主服务器上保存二进制日志，最大程度的保证数据的不丢失(配合mysql半同步复制效果更佳)，但这并不总是可行的。例如，如果主服务器硬件故障或无法通过ssh访问，MHA没法保存二进制日志，只进行故障转移而丢失了最新的数据。使用MySQL 5.5的半同步复制，可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志，MHA可以将最新的二进制日志应用于其他所有的slave服务器上，因此可以保证所有节点的数据一致性。&lt;/p&gt;
 &lt;p&gt;注意：目前MHA主要支持一主多从的架构，要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器，一主二从，即一台充当master，一台充当备用master，另外一台充当从库，因为至少需要三台服务器，出于机器成本的考虑，淘宝也在该基础上进行了改造，目前淘宝TMHA已经支持一主一从。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;3.2.MHA架构图&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;正常工作时架构图：  &lt;br /&gt;  &lt;img alt="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154220.png" src="https://segmentfault.com/img/bVbyZyh" title="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154220.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;主库down机时架构：  &lt;br /&gt;  &lt;img alt="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154249.png" src="https://segmentfault.com/img/bVbyZym" title="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154249.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;3.3.故障转移过程&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）从宕机崩溃的master保存二进制日志事件（binlog events）;  &lt;br /&gt;（2）识别含有最新更新的slave；  &lt;br /&gt;（3）应用差异的中继日志（relay log）到其他的slave；  &lt;br /&gt;（4）应用从master保存的二进制日志事件（binlog events）；  &lt;br /&gt;（5）提升一个slave为新的master；  &lt;br /&gt;（6）使其他的slave连接新的master进行复制；  &lt;br /&gt;（7）在新的master启动vip地址，保证前端请求可以发送到新的master。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;3.4.MHA优点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）不需要备份服务器  &lt;br /&gt;（2）不改变现有环境  &lt;br /&gt;（3）操作非常简单  &lt;br /&gt;（4）可以进行日志的差异修复  &lt;br /&gt;（5）可以将任意slave提升为master&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;3.5.MHA缺点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）需要全部节点做ssh秘钥  &lt;br /&gt;（2）MHA出现故障后配置文件会被修改，如果再次故障转移需要重新修改配置文件。  &lt;br /&gt;（3）自带的脚本还需要进一步补充完善，且用perl开发，二次开发困难。&lt;/p&gt;
 &lt;h3&gt;4.DRBD+（heartbeat,corosync）&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;4.1.方案简介&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;本方案采用Heartbeat或者corosync双机热备软件来保证数据库的高稳定性和连续性，数据的一致性由DRBD这个工具来保证（如果可以尽量放到分布式存储上面）。默认情况下只有一台mysql在工作，当主mysql服务器出现问题后，系统将自动切换到备机上继续提供服务，当主数据库修复完毕，又将服务切回继续由主mysql提供服务。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;4.2.组件&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;Heartbeat,corosync作为心跳检测机制，监控primary节点的状态。当主节点宕掉之后，迅速提升secondary节点为新的主节点，并切换IP；  &lt;br /&gt;drbd负责数据同步&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;4.3.架构图&lt;/strong&gt;  &lt;br /&gt;  &lt;img alt="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154253.jpg" src="https://segmentfault.com/img/bVbyZyr" title="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154253.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;4.4.数据同步过程&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;mysql进行刷盘时，会通过不同的sync方式，最终将数据写入disk；  &lt;br /&gt;drbd收到刷盘成功的信息后，将对应的磁盘块位置，和变更动作，通过网络传递至secondary节点；&lt;/p&gt;
 &lt;p&gt;secondary的drbd接收到变更信息后，将这些信息落盘；&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;4.5.切换过程&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;前提：secondary节点的mysql服务不启动；&lt;/p&gt;
 &lt;p&gt;heartbeat检测到primary的mysql服务停止，则摘掉IP、umount掉数据盘、将primary切换为secondary；&lt;/p&gt;
 &lt;p&gt;在原来的secondary上，提升drbd同步为primary，挂载数据盘，启动mysql服务、绑定IP；&lt;/p&gt;
 &lt;p&gt;从库跟着IP和端口自动进行迁移；&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;4.6.方案优点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）历史悠久、安全性高、稳定性高、可用性高、出现故障自动切换。  &lt;br /&gt;（2）数据一致性强&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;4.7.方案缺点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）需要一台备份服务器，浪费资源  &lt;br /&gt;（2）不方便扩展  &lt;br /&gt;（3）无论drbd还是headbetart，corosync都可能发生裂脑&lt;/p&gt;
 &lt;h3&gt;5.Mysql route介绍&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;5.1.什么是mysql route&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;MySQL Router是处于应用client和dbserver之间的轻量级代理程序，它能检测，分析和转发查询到后端数据库实例，并把结果返回给client。是mysql-proxy的一个替代品。其架构图和功能如下。  &lt;br /&gt;  &lt;img alt="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154257.png" src="https://segmentfault.com/img/bVbyZyx" title="&amp;#24494;&amp;#20449;&amp;#22270;&amp;#29255;_20191015154257.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;（1）Router实现读写分离，程序不是直接连接数据库IP，而是固定连接到mysql router。MySQL Router对前端应用是透明的。应用程序把MySQL Router当作是普通的mysql实例，把查询发给MySQL Router,而MySQL Router会把查询结果返回给前端的应用程序。&lt;/p&gt;
 &lt;p&gt;（2）从数据库服务器故障，业务可以正常运行。由MySQL Router来进行自动下线不可用服务器。程序配置不需要任何修改。&lt;/p&gt;
 &lt;p&gt;（3）主数据库故障，由MySQL Router来决定主从自动切换，业务可以正常访问。程序配置不需要做任何修改。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;5.2.读写分离原理&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;MySQL Router接受前端应用程序请求后，根据不同的端口来区分读写，把连接读写端口的所有查询发往主库，把连接只读端口的select查询以轮询方式发往多个从库，从而实现读写分离的目的。读写返回的结果会交给MySQL Router,由MySQL Router返回给客户端的应用程序。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;5.3.Mysql router用途&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;MySQL Router的主要用途是读写分离，主主故障自动切换，负载均衡，连接池等。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;5.4.Mysql router主主故障自动切换的坑&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;Mysql router主主故障切换功能经过测试没有问题，但是有一个比较大的坑需要注意，主库发生切换之后，从库的连接的master服务器地址不会发生改变，需要自己写脚本进行判断。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;5.5.优点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）基于DAL层实现mysql的高可用。  &lt;br /&gt;（2）可以同时实现主主故障切换和读写分离。  &lt;br /&gt;（3）插件式架构允许用户进行额外的功能扩展。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;5.6.缺点&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;（1）高可用功能需要进一步完善：存在主库切换之后，从库不会自动切换主库地址的坑。  &lt;br /&gt;（2）读写情况使用不同端口，需要修改应用程序。&lt;/p&gt;
 &lt;h3&gt;6.mysql Cluster&lt;/h3&gt;
 &lt;p&gt;国内用的非常少，主要因为一下三点：  &lt;br /&gt;（1）需要更改存储引擎  &lt;br /&gt;（2）付费  &lt;br /&gt;（3）国内几乎没有使用案例&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;优点：&lt;/strong&gt;  &lt;br /&gt;高可用，可用率达99.999%&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;6.1.结束语&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;上面的高可用方案，只是我自己比较熟悉的，而且也是应用比较多的。mysql毕竟发展了有20多年了，各种高可用方案还是很多的，其他的高可用方案各位钥匙有兴趣，可以自己研究。&lt;/p&gt;
 &lt;blockquote&gt;版权申明：作者：西门飞冰，一名90后it男，一直在北京工作，热爱运动，热爱冒险，热爱旅行。由作者原创投稿，版权归原创者所有。除非无法确认，我们都会标明作者及出处，如有侵权烦请告知，我们会立即删除并表示歉意，谢谢。&lt;/blockquote&gt;
 &lt;p&gt;关注 民工哥技术之路 微信公众号对话框回复关键字：1024 可以获取一份最新整理的技术干货：包括系统运维、数据库、redis、MogoDB、电子书、Java基础课程、Java实战项目、架构师综合教程、架构师实战项目、大数据、Docker容器、ELK Stack、机器学习、BAT面试精讲视频等。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>mysql linux centos</category>
      <guid isPermaLink="true">https://itindex.net/detail/60091-mysql-%E5%90%8C%E6%AD%A5-%E5%A4%8D%E5%88%B6</guid>
      <pubDate>Tue, 15 Oct 2019 15:41:19 CST</pubDate>
    </item>
    <item>
      <title>CPU 使用率低高负载的原因，看看这篇！</title>
      <link>https://itindex.net/detail/60047-cpu-%E8%B4%9F%E8%BD%BD-%E5%8E%9F%E5%9B%A0</link>
      <description>&lt;h1&gt;原因总结&lt;/h1&gt;
 &lt;p&gt;产生的原因一句话总结就是：等待磁盘I/O完成的进程过多，导致进程队列长度过大，但是cpu运行的进程却很少，这样就体现到负载过大了，cpu使用率低。&lt;/p&gt;
 &lt;p&gt;下面内容是具体的原理分析：  &lt;br /&gt;在分析负载为什么高之前先介绍下什么是负载、多任务操作系统、进程调度等相关概念。&lt;/p&gt;
 &lt;h1&gt;什么是负载&lt;/h1&gt;
 &lt;p&gt;什么是负载：负载就是cpu在一段时间内正在处理以及等待cpu处理的进程数之和的统计信息，也就是cpu使用队列的长度统计信息，这个数字越小越好（如果超过CPU核心*0.7就是不正常）&lt;/p&gt;
 &lt;p&gt;负载分为两大部分：CPU负载、IO负载&lt;/p&gt;
 &lt;p&gt;例如，假设有一个进行大规模科学计算的程序，虽然该程序不会频繁地从磁盘输入输出，但是处理完成需要相当长的时间。因为该程序主要被用来做计算、逻辑判断等处理，所以程序的处理速度主要依赖于cpu的计算速度。此类cpu负载的程序称为“计算密集型程序”。&lt;/p&gt;
 &lt;p&gt;还有一类程序，主要从磁盘保存的大量数据中搜索找出任意文件。这个搜索程序的处理速度并不依赖于cpu，而是依赖于磁盘的读取速度，也就是输入输出（input/output,I/O）.磁盘越快，检索花费的时间就越短。此类I/O负载的程序，称为“I/O密集型程序”。&lt;/p&gt;
 &lt;h1&gt;什么是多任务操作系统&lt;/h1&gt;
 &lt;p&gt;Linux操作系统能够同时处理几个不同名称的任务。但是同时运行多个任务的过程中，cpu和磁盘这些有限的硬件资源就需要被这些任务程序共享。即便很短的时间间隔内，需要一边在这些任务之间进行切换到一边进行处理，这就是多任务。&lt;/p&gt;
 &lt;p&gt;运行中的任务较少的情况下，系统并不是等待此类切换动作的发生。但是当任务增加时，例如任务A正在CPU上执行计算，接下来如果任务B和C也想进行计算，那么就需要等待CPU空闲。也就是说，即便是运行处理某任务，也要等到轮到他时才能运行，此类等待状态就表现为程序运行延迟。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;uptime输出中包含“load average”的数字
[root@localhost ~]# uptime
 11:16:38 up  2:06, 4 users, load average: 0.00, 0.02, 0.05

&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;Load average从左边起依次是过去1分钟、5分钟、15分钟内，单位时间的等待任务数，也就是表示平均有多少任务正处于等待状态。在load average较高的情况下，这就说明等待运行的任务较多，因此轮到该任务运行的等待时间就会出现较大的延迟，即反映了此时负载较高。&lt;/p&gt;
 &lt;h1&gt;进程调度&lt;/h1&gt;
 &lt;p&gt;什么是进程调度：&lt;/p&gt;
 &lt;p&gt;进程调度也被一些人称为cpu上下文切换意思是：CPU切换到另一个进程需要保存当前进程的状态并恢复另一个进程的状态：当前运行任务转为就绪（或者挂起、中断）状态，另一个被选定的就绪任务成为当前任务。进程调度包括保存当前任务的运行环境，恢复将要运行任务的运行环境。  &lt;br /&gt;在linux内核中，每一个进程都存在一个名为“进程描述符”的管理表。该进程描述符会调整为按照优先级降序排序，已按合理的顺序运行进程（任务）。这个调整即为进程调度器的工作。  &lt;br /&gt;调度器划分并管理进程的状态，如：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;等待分配cpu资源的状态。&lt;/li&gt;
  &lt;li&gt;等待磁盘输入输出完毕的状态。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;下面在说一下进程的状态区别：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="clipboard.png" src="https://segmentfault.com/img/bVbx0uC?w=652&amp;h=250" title="clipboard.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;下面举例来说明进程状态转变：&lt;/p&gt;
 &lt;p&gt;这里有三个进程A、B、C同时运行。首先，每个进程在生成后都是可运行状态，也就是running状态的开始，而不是现在运行状态，由于在linux内核中无法区别正在运行的状态和可运行的等待状态，下面将可运行状态和正在运行状态都称为running状态。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;进程A：running&lt;/li&gt;
  &lt;li&gt;进程B：running&lt;/li&gt;
  &lt;li&gt;进程C：running&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;running的三个进程立即成为调度对象。此时，假设调度器给进程A分配了CPU的运行权限。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;进程A：running （正在运行）&lt;/li&gt;
  &lt;li&gt;进程B：running&lt;/li&gt;
  &lt;li&gt;进程C：running&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;进程A分配了CPU，所以进程A开始处理。进程B和C则在此等待进程A迁出CPU。假设进程A进行若干计算之后，需要从磁盘读取数据。那么在A发出读取磁盘数据的请求之后，到请求数据到达之前，将不进行任何工作。此状态称为“因等待I/O操作结束而被阻塞”。在I/O完成处理前，进程A就一直处于等待中，就会转为不可中断睡眠状态（uninterruptible），并不使用CPU。于是调度器查看进程B和进程C的优先级计算结果，将CPU运行权限交给优先级较高的一方。这里假设进程B的优先级高于进程C。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;进程A：uninterruptible （等待磁盘输入输出/不可中断状态）&lt;/li&gt;
  &lt;li&gt;进程B：running （正在运行）&lt;/li&gt;
  &lt;li&gt;进程C：running&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;进程B刚开始运行，就需要等待用户的键盘输入。于是B进入等待用户键盘输入状态，同样被阻塞。结果就变成了进程A和进程B都是等待输出，运行进程C。这时进程A和进程B都是等待状态，但是等待磁盘输入输出和等待键盘输入为不同的状态。等待键盘输入是无限期的事件等待，而读取磁盘则是必须短时间内完成的事件等待，这是两种不同的等待状态。各进程状态如下所示：  &lt;br /&gt;进程A：uninterruptible （等待磁盘输入输出/不可中断状态）  &lt;br /&gt;进程B：interruptible （等待键盘输入输出/可中断状态）  &lt;br /&gt;进程C：running （正在运行）&lt;/p&gt;
 &lt;p&gt;这次假设进程C在运行的过程中，进程A请求的数据从磁盘到达了缓冲装置。紧接着硬盘对内核发起中断信号，内核知道磁盘读取完成，将进程A恢复为可运行状态。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;进程A：running （正在运行）&lt;/li&gt;
  &lt;li&gt;进程B：interruptible （等待键盘输入输出/可中断状态）&lt;/li&gt;
  &lt;li&gt;进程C：running （正在运行）&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;此后进程C也会变为某种等待状态。如CPU的占用时间超出了上限、任务结束、进入I/O等待。一旦满足这些条件，调度器就可以完成从进程C到进程A的进程状态切换。&lt;/p&gt;
 &lt;h1&gt;负载的意义&lt;/h1&gt;
 &lt;p&gt;负载表示的是“等待进程的平均数”。在上面的进程状态变换过程中，除了running状态，其他都是等待状态，那么其他状态都会加入到负载等待进程中吗？&lt;/p&gt;
 &lt;p&gt;事实证明，只有进程处于运行态（running）和不可中断状态（interruptible）才会被加入到负载等待进程中，也就是下面这两种情况的进程才会表现为负载的值。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;即便需要立即使用CPU，也还需等待其他进程用完CPU&lt;/li&gt;
  &lt;li&gt;即便需要继续处理，也必须等待磁盘输入输出完成才能进行&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;下面描述一种直观感受的场景说明为什么只有运行态（running）和可中断状态（interruptible）才会被加入负载。&lt;/p&gt;
 &lt;p&gt;如：在很占用CPU资源的处理中，例如在进行动画编码的过程中，虽然想进行其他相同类型的处理，结果系统反映却变得很慢，还有从磁盘读取大量数据时，系统的反映也同样会变的很慢。但是另一方面，无论有多少等待键盘输入输出操作的进程，也不会让系统响应变慢。&lt;/p&gt;
 &lt;h1&gt;什么场景会造成CPU低而负载确很高呢？&lt;/h1&gt;
 &lt;p&gt;通过上面的具体分析负载的意义就很明显了，负载总结为一句话就是：需要运行处理但又必须等待队列前的进程处理完成的进程个数。具体来说，也就是如下两种情况：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;等待被授权予CPU运行权限的进程&lt;/li&gt;
  &lt;li&gt;等待磁盘I/O完成的进程&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;cpu低而负载高也就是说等待磁盘I/O完成的进程过多，就会导致队列长度过大，这样就体现到负载过大了，但实际是此时cpu被分配去执行别的任务或空闲，具体场景有如下几种。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;场景一：磁盘读写请求过多就会导致大量I/O等待&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;上面说过，cpu的工作效率要高于磁盘，而进程在cpu上面运行需要访问磁盘文件，这个时候cpu会向内核发起调用文件的请求，让内核去磁盘取文件，这个时候会切换到其他进程或者空闲，这个任务就会转换为不可中断睡眠状态。当这种读写请求过多就会导致不可中断睡眠状态的进程过多，从而导致负载高，cpu低的情况。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;场景二：MySQL中存在没有索引的语句或存在死锁等情况&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;我们都知道MySQL的数据是存储在硬盘中，如果需要进行sql查询，需要先把数据从磁盘加载到内存中。当在数据特别大的时候，如果执行的sql语句没有索引，就会造成扫描表的行数过大导致I/O阻塞，或者是语句中存在死锁，也会造成I/O阻塞，从而导致不可中断睡眠进程过多，导致负载过大。  &lt;br /&gt;具体解决方法可以在MySQL中运行show full processlist命令查看线程等待情况，把其中的语句拿出来进行优化。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;场景三：外接硬盘故障，常见有挂了NFS，但是NFS server故障&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;比如我们的系统挂载了外接硬盘如NFS共享存储，经常会有大量的读写请求去访问NFS存储的文件，如果这个时候NFS Server故障，那么就会导致进程读写请求一直获取不到资源，从而进程一直是不可中断状态，造成负载很高。&lt;/p&gt;
 &lt;p&gt;结束语：大概内容就是这样，如果有朋友遇到其他场景，欢迎留言补充。&lt;/p&gt;
 &lt;blockquote&gt;作者：西门飞冰，一名90后it男，一直在北京工作，热爱运动，热爱冒险，热爱旅行。&lt;/blockquote&gt;
 &lt;p&gt;关注 民工哥技术之路 微信公众号对话框回复关键字：1024 可以获取一份最新整理的技术干货。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/bVbwU76?w=670&amp;h=776" title="&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>linux centos</category>
      <guid isPermaLink="true">https://itindex.net/detail/60047-cpu-%E8%B4%9F%E8%BD%BD-%E5%8E%9F%E5%9B%A0</guid>
      <pubDate>Sun, 22 Sep 2019 16:12:42 CST</pubDate>
    </item>
    <item>
      <title>SSH与Linux主机交互文件传输工具lrzsz安装使用教程</title>
      <link>https://itindex.net/detail/59666-ssh-linux-%E4%B8%BB%E6%9C%BA</link>
      <description>&lt;p&gt;以前传文件，奶牛一直是喜欢搭个web，然后直接把服务器文件扔上去然后从本地下载，或者用Bitvise SSH的SFTP工具来传输，直到忘了多久之前看到一个教学视频里面，有直接通过一条命令来传输本地文件到服务器上。最近无意中又看到了这个软件，名字叫lrzsz，推荐搭配Xshell这个SSH工具来使用。&lt;/p&gt;
 &lt;h2&gt;lrzsz安装&lt;/h2&gt;
 &lt;p&gt;CentOS下安装：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;yum -y install lrzsz&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;Ubuntu下安装：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;apt-get install lrzsz&lt;/code&gt;&lt;/pre&gt;
 &lt;h2&gt;lrzsz使用教程&lt;/h2&gt;
 &lt;p&gt;lrzsz分开是两个命令，一个是rz，一个是sz。rz是用来从本地文件传输到服务器端，sz是用来从服务器端拉取文件到本地的。&lt;/p&gt;
 &lt;p&gt;使用方法也很简单：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;sz filename
rz&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;其中sz后面直接加文件路径或者当前路径下的文件名即可，rz直接回车在Xshell下会直接弹出对话框来选择需要上传的文件的。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux Ubuntu Windows CentOS lrzsz</category>
      <guid isPermaLink="true">https://itindex.net/detail/59666-ssh-linux-%E4%B8%BB%E6%9C%BA</guid>
      <pubDate>Fri, 07 Jun 2019 00:40:23 CST</pubDate>
    </item>
    <item>
      <title>使用 cgroups 限制指定进程的内存使用</title>
      <link>https://itindex.net/detail/59324-cgroups-%E9%99%90%E5%88%B6-%E8%BF%9B%E7%A8%8B</link>
      <description>&lt;p&gt;本文来自  &lt;a href="https://blog.lilydjwg.me/"&gt;依云&amp;apos;s Blog&lt;/a&gt;，转载请注明。&lt;/p&gt; &lt;p&gt;
	最近我的系统有这么个问题：在备份或者系统更新等高 I/O 负载的时候，系统整体性能下降严重，界面经常卡到动不了。经过分析发现此时比平常多了许多磁盘读操作。平常的时候磁盘读操作是很少的，会有大量的缓存命中，反倒是写操作一直都有（因为我本地搭了个  &lt;a href="https://wzyboy.im/post/1084.html"&gt;监控系统&lt;/a&gt;）。啊对，分析用到的磁盘性能数据就是来自于这个监控系统。&lt;/p&gt;
 &lt;p&gt;
	所以原因很清楚了：备份和系统更新不仅造成了大量缓存未命中，还占用了本来存放着热数据的缓存，导致常规使用的缓存命中率也急速下降，结果我的机械硬盘就忙不过来了。&lt;/p&gt;
 &lt;p&gt;
	那么，要是能够限制这些操作占用的缓存，性能不就能好一点吗？那些新读进来的数据反正是短期内再也用不到了，缓存起来也只是浪费有限的内存空间啊。&lt;/p&gt;
 &lt;p&gt;
	研究了一下 /sys/fs/cgroup/memory/memory.stat，看起来 cgroups 内存限制是包含缓存部分的，于是就试试呗。正好 systemd 直接就能设置了：&lt;/p&gt;
 &lt;pre&gt;
$ sudo systemd-run -p MemoryMax=512M --scope pacman -Syu
&lt;/pre&gt;
 &lt;p&gt;
	本来我是设置的 256M 限制，结果发现 dkms 编译内核模块的时候超级慢，还用掉了不少 swap……于是分了 512M。效果还是不错的，常规操作偶尔还是卡一卡（毕竟还是有一些 I/O 操作），但比起不限制的时候要少很多。&lt;/p&gt;
 &lt;p&gt;
	要注意一点的是，不使用 cgroups v2 的话（Arch Linux 默认），这个命令不能加 --user 以在用户级的 systemd 下跑的。而使用 cgroups v2 的话，lxc 和 docker 都跑不了……&lt;/p&gt;
 &lt;p&gt;
	备份也是类似的，而且因为 rsync 自己用不到多少内存，这个效果更好：&lt;/p&gt;
 &lt;pre&gt;
$ systemd-run -p MemoryMax=256M --scope ./backup-my-system
&lt;/pre&gt;
 &lt;p&gt;
	终于又一次在半小时内完成了备份 QAQ 之前动不动就一两小时的。&lt;/p&gt;
 &lt;p&gt;
	我也不知道为什么这个问题近期才出现，总之现在是缓解了。（接下来有空继续计划换 SSD 硬盘的事情～&lt;/p&gt;

      &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux</category>
      <guid isPermaLink="true">https://itindex.net/detail/59324-cgroups-%E9%99%90%E5%88%B6-%E8%BF%9B%E7%A8%8B</guid>
      <pubDate>Sat, 02 Mar 2019 23:51:26 CST</pubDate>
    </item>
    <item>
      <title>实用技巧：教你如何在没有网络的Linux机器上快速安装软件</title>
      <link>https://itindex.net/detail/59110-%E6%8A%80%E5%B7%A7-%E6%B2%A1%E6%9C%89-%E7%BD%91%E7%BB%9C</link>
      <description>&lt;p&gt;相信很多人遇到过这样的问题：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;你需要在公司的一台服务器上安装xxx软件，例如vsftpd；&lt;/li&gt;
  &lt;li&gt;该服务器无法连接公网；&lt;/li&gt;
  &lt;li&gt;这台服务器很可能是一个最简安装的Linux（意味着该机器可能有很多常见的软件依赖缺失），你也搞不清楚究竟是不是最简安装的，只能用   &lt;code&gt;uname -a&lt;/code&gt; 或者   &lt;code&gt;/etc/redhat-release&lt;/code&gt; 看到发行版本；&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;于是，你应该怎么安装想要的软件？&lt;/p&gt;
 &lt;p&gt;下面以带有浓重的感情色彩，总结三种方案。&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;TIPS：本文以CentOS 7为例，探讨几种安装方式。其他发行版，可参见拓展阅读给出的方案。&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;a&gt;&lt;/a&gt;
 &lt;h2&gt;  &lt;a href="http://www.itmuch.com/#&amp;#26368;&amp;#22303;&amp;#20294;&amp;#26368;&amp;#26497;&amp;#23458;&amp;#30340;&amp;#26041;&amp;#27861;" title="&amp;#26368;&amp;#22303;&amp;#20294;&amp;#26368;&amp;#26497;&amp;#23458;&amp;#30340;&amp;#26041;&amp;#27861;"&gt;&lt;/a&gt;最土但最极客的方法&lt;/h2&gt; &lt;p&gt;一些人可能会下载源码，然后上传到服务器上编译安装。编译有问题会报错，一般要么是缺包（比较多），要么是冲突（相对较少）。那就分析日志，缺包就找包，冲突就换包；找到包后再上传到服务器上搞，周而复始，直到完成。&lt;/p&gt;
 &lt;p&gt;个人对这种做法非常不喜欢——&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;效率太差；&lt;/li&gt;
  &lt;li&gt;操作复杂繁琐，中间可能会中断若干次。环节越多，出现失误的可能性越大；&lt;/li&gt;
  &lt;li&gt;对于服务器，没有十足的把握谁敢这么操作……&lt;/li&gt;
  &lt;li&gt;对于不同版本的CentOS / RedHat，很多依赖的包名都变了……有的包还挺难找的……&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;我14年前后，在一台无网络的机器上编译安装过MySQL（公司的测试环境，可以随便玩），花了小半天……感受是：这种方式只有脾气好、并且富有极客精神、不怕苦不怕累，还无敌有信心不弄坏公司服务器，并且还得还闲的蛋疼的大神才能hold住，对于我等凡人，恐怕是不大适用的。&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;PS. 可能有人说高手不都应该编译安装吗？我个人觉得这种顶多也就算个伪高手——真正的高手看重的是解决方法是否有效，才不care你是一行命令自动安装，还是用18页命令编译安装……&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;h2&gt;  &lt;a href="http://www.itmuch.com/#&amp;#19981;&amp;#37027;&amp;#20040;&amp;#22303;&amp;#20063;&amp;#19981;&amp;#37027;&amp;#20040;&amp;#26497;&amp;#23458;&amp;#30340;&amp;#26041;&amp;#27861;" title="&amp;#19981;&amp;#37027;&amp;#20040;&amp;#22303;&amp;#20063;&amp;#19981;&amp;#37027;&amp;#20040;&amp;#26497;&amp;#23458;&amp;#30340;&amp;#26041;&amp;#27861;"&gt;&lt;/a&gt;不那么土也不那么极客的方法&lt;/h2&gt; &lt;p&gt;这种方案应该是一半以上童鞋都会选择的——RPM包安装方式。先找到相关的RPM包，然后用  &lt;code&gt;rpm -ivh rpm包名&lt;/code&gt; 安装。&lt;/p&gt;
 &lt;p&gt;RPM可在  &lt;a href="http://rpmfind.net/" rel="external" target="_blank"&gt;http://rpmfind.net/&lt;/a&gt; 上找到，我是说大部分。&lt;/p&gt;
 &lt;p&gt;一般来讲，该方案问可以很好的解决问题，但极端场景下也会跪。原因依然是缺包……&lt;/p&gt;
 &lt;p&gt;RPM并不一定包含软件所有的依赖，有时候可能一个软件依赖了若干个RPM，你得通通找到，然后一起安装……&lt;/p&gt;
 &lt;h2&gt;  &lt;a href="http://www.itmuch.com/#&amp;#20010;&amp;#20154;&amp;#26368;&amp;#21916;&amp;#27426;&amp;#20063;&amp;#26368;&amp;#31616;&amp;#21333;&amp;#30340;&amp;#26041;&amp;#27861;" title="&amp;#20010;&amp;#20154;&amp;#26368;&amp;#21916;&amp;#27426;&amp;#20063;&amp;#26368;&amp;#31616;&amp;#21333;&amp;#30340;&amp;#26041;&amp;#27861;"&gt;&lt;/a&gt;个人最喜欢也最简单的方法&lt;/h2&gt; &lt;p&gt;借助  &lt;code&gt;yum-plugin-downloadonly&lt;/code&gt; 。这是个人最喜欢的方法，简单粗暴高效。&lt;/p&gt;
 &lt;p&gt;下面附带完整的安装步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;p&gt;准备1台和服务器    &lt;strong&gt;最简安装&lt;/strong&gt;了    &lt;strong&gt;同版本Linux&lt;/strong&gt;的机器，记为机器B，    &lt;strong&gt;机器B需要能联网&lt;/strong&gt; 。&lt;/p&gt;
   &lt;blockquote&gt;
    &lt;p&gt;TIPS：可以是实体机、虚拟机或者Docker容器，看你的喜好。&lt;/p&gt;
    &lt;p&gt;个人建议用Docker准备，一分钟就可以准备好了。Docker相关课程可在我的公众号，或者博客搜索一下，有全套系列。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;p&gt;远程上机器B。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;p&gt;在机器B上执行如下命令：&lt;/p&gt;
   &lt;table&gt;    &lt;tr&gt;     &lt;td&gt;      &lt;pre&gt;       &lt;div&gt;1&lt;/div&gt;       &lt;div&gt;2&lt;/div&gt;       &lt;div&gt;3&lt;/div&gt;       &lt;div&gt;4&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;     &lt;td&gt;      &lt;pre&gt;       &lt;div&gt;# 安装yum-plugin-downloadonly插件&lt;/div&gt;       &lt;div&gt;yum install -y yum-plugin-downloadonly&lt;/div&gt;       &lt;div&gt;# 把vsftpd换成你想要的包名&lt;/div&gt;       &lt;div&gt;yum install --downloadonly &amp;lt;vsftpd&amp;gt;&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;p&gt;下载的软件在：&lt;/p&gt;
   &lt;table&gt;    &lt;tr&gt;     &lt;td&gt;      &lt;pre&gt;       &lt;div&gt;1&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;     &lt;td&gt;      &lt;pre&gt;       &lt;div&gt;/var/cache/yum/x86_64/7/base/packages/&lt;/div&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
   &lt;p&gt;该目录里会存放你想安装的软件所需要的所有RPM包。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;p&gt;将所有RPM包拷贝到服务器上安装既可。如果安装过程中提示xxx已安装是否需要覆盖，全部选否。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;是不是非常简单？应该也有很多童鞋知道这种方法的，本身也不是什么秘密。但就我的感知，很可能更多的人不知道，好几个人问我了，所以分享一下。&lt;/p&gt;
 &lt;h2&gt;  &lt;a href="http://www.itmuch.com/#&amp;#20854;&amp;#20182;&amp;#26041;&amp;#27861;" title="&amp;#20854;&amp;#20182;&amp;#26041;&amp;#27861;"&gt;&lt;/a&gt;其他方法&lt;/h2&gt; &lt;p&gt;  &lt;code&gt;Yumdownloader&lt;/code&gt; ，用法和  &lt;code&gt;yum-plugin-downloadonly&lt;/code&gt; 大同小异。用本行高亮的部分作为关键词自行搜索吧。&lt;/p&gt;
 &lt;h2&gt;  &lt;a href="http://www.itmuch.com/#&amp;#25299;&amp;#23637;&amp;#38405;&amp;#35835;" title="&amp;#25299;&amp;#23637;&amp;#38405;&amp;#35835;"&gt;&lt;/a&gt;拓展阅读&lt;/h2&gt; &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;    &lt;p&gt;怎样在 CentOS 里下载 RPM 包及其所有依赖包:     &lt;a href="https://blog.csdn.net/linuxnews/article/details/53244315" rel="external" target="_blank"&gt;https://blog.csdn.net/linuxnews/article/details/53244315&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
   &lt;li&gt;    &lt;p&gt;Ubuntu其实也有类似的命令     &lt;code&gt;apt-get install -d --reinstall 包名&lt;/code&gt; ，这样既可只下载包，而不安装包了，然后拷贝到无网络的机器上安装既可。&lt;/p&gt;
&lt;/li&gt;
   &lt;li&gt;apt一键下载所有依赖的包：    &lt;a href="https://blog.csdn.net/junbujianwpl/article/details/52811153" rel="external" target="_blank"&gt;https://blog.csdn.net/junbujianwpl/article/details/52811153&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>工作 Linux 生产技巧</category>
      <guid isPermaLink="true">https://itindex.net/detail/59110-%E6%8A%80%E5%B7%A7-%E6%B2%A1%E6%9C%89-%E7%BD%91%E7%BB%9C</guid>
      <pubDate>Sat, 22 Dec 2018 03:11:49 CST</pubDate>
    </item>
    <item>
      <title>使用树莓派和VLAN交换机组建单臂路由器，通过SS代理上网</title>
      <link>https://itindex.net/detail/58769-%E6%A0%91%E8%8E%93%E6%B4%BE-vlan-%E4%BA%A4%E6%8D%A2%E6%9C%BA</link>
      <description>&lt;h2&gt;  &lt;a href="https://liangshuang.name/#&amp;#30446;&amp;#26631;" title="&amp;#30446;&amp;#26631;"&gt;&lt;/a&gt;目标&lt;/h2&gt; &lt;p&gt;创建一个代理网关，所有通过有线或者无线连接通过该网关上网的设备可以：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;根据域名判断是走国内的DNS还是国外的DNS，走国外DNS时，通过SS代理请求，防止DNS污染&lt;/li&gt;
  &lt;li&gt;根据目标IP地址自动选择线路，国外流量都走SS代理&lt;/li&gt;
&lt;/ul&gt;
 &lt;a&gt;&lt;/a&gt;
 &lt;h2&gt;  &lt;a href="https://liangshuang.name/#&amp;#20934;&amp;#22791;" title="&amp;#20934;&amp;#22791;"&gt;&lt;/a&gt;准备&lt;/h2&gt; &lt;ul&gt;
  &lt;li&gt;一个SS服务器，Linode或者Digital Ocean上5刀/月的服务器就够用了，SS服务器的架设方法请自行百度。&lt;/li&gt;
  &lt;li&gt;一个运行最新版本Raspbian的树莓派3B+。理论上任何安装Linux并带有线网卡和无线网卡的设备都可以，只是不同的Linux发行版配置会稍有不同。选择树莓派3B+因为其自带有线和无线网卡，官方的Raspbian运行稳定、内核版本高（ipset在低版本内核中很难安装），缺点是网卡不是千兆的。我在KVM虚拟机中运行的Arch和Orange Pi Zero Plus上运行的Armbian上都成功搭建过类似的网关。&lt;/li&gt;
  &lt;li&gt;一个支持VLAN Tagging（802.1Q）功能的交换机。我用的是   &lt;code&gt;必联BL-SG108M&lt;/code&gt;，八口千兆，淘宝卖140，价格公道，功能够用。也可以使用一个USB有线网卡配一个普通的交换机，除VLAN之外，其他配置类似，但这种配置就不是单臂路由器了。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;  &lt;a href="https://liangshuang.name/#&amp;#32593;&amp;#32476;&amp;#25299;&amp;#25169;&amp;#19982;&amp;#20132;&amp;#25442;&amp;#26426;&amp;#37197;&amp;#32622;" title="&amp;#32593;&amp;#32476;&amp;#25299;&amp;#25169;&amp;#19982;&amp;#20132;&amp;#25442;&amp;#26426;&amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;网络拓扑与交换机配置&lt;/h2&gt; &lt;img src="https://liangshuang.name/2018/09/05/router-on-a-stick-with-raspberrypi-shadowsocks/topology.jpg"&gt;&lt;/img&gt;
 &lt;p&gt;  &lt;em&gt;网络拓扑图&lt;/em&gt;&lt;/p&gt;
 &lt;p&gt;将交换机端口分为两个VLAN，VLAN2和VLAN3（这个设备很诡异，VLAN1不允许删除或修改）。端口1至端口6为VLAN2，端口6至端口8为VLAN3，交换机通过端口1连接家里的路由器，树莓派连接端口6（跨两个VLAN）。此时，空闲的端口2～5为非代理端口，直接走家里的路由器，端口7、8为代理端口，数据会通过树莓派网关进行转发，可以根据需要调整VLAN2与VLAN3的端口数量。&lt;/p&gt;
 &lt;img src="https://liangshuang.name/2018/09/05/router-on-a-stick-with-raspberrypi-shadowsocks/vlan-config.png"&gt;&lt;/img&gt;
 &lt;p&gt;  &lt;em&gt;VLAN配置&lt;/em&gt;&lt;/p&gt;
 &lt;img src="https://liangshuang.name/2018/09/05/router-on-a-stick-with-raspberrypi-shadowsocks/vlan-port-config.png"&gt;&lt;/img&gt;
 &lt;p&gt;  &lt;em&gt;VLAN Tag配置&lt;/em&gt;&lt;/p&gt;
 &lt;p&gt;在配置交换机前，需要先设置交换机的IP地址为局域网内可用的地址。VLAN划分好后，可以设置端口隔离，但是因为没有找到官方详细的说明，我按照自己的想法将端口1～5和7、8进行了隔离，运行中没有碰到问题，但是VLAN3内的设备无法访问交换机的管理页面。&lt;/p&gt;
 &lt;h2&gt;  &lt;a href="https://liangshuang.name/#&amp;#37197;&amp;#32622;&amp;#32593;&amp;#20851;" title="&amp;#37197;&amp;#32622;&amp;#32593;&amp;#20851;"&gt;&lt;/a&gt;配置网关&lt;/h2&gt; &lt;p&gt;树莓派网关需要运行DNS服务（dnsmasq），代理服务（shadowsocks-libev）及无线AP服务（hostapd）并且需要通过iptables和ipset进行NAT转发。&lt;/p&gt;
 &lt;h3&gt;  &lt;a href="https://liangshuang.name/#&amp;#31995;&amp;#32479;&amp;#37197;&amp;#32622;" title="&amp;#31995;&amp;#32479;&amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;系统配置&lt;/h3&gt; &lt;p&gt;更新系统到最新的状态：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;apt update     &lt;br /&gt;apt dist-upgrade -y     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;安装需要的软件包：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;apt install -y vim git dnsutils lsof bridge-utils hostapd dnsmasq ipset ntp haveged python-m2crypto shadowsocks-libev     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;修改时区并启用NTP服务：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;rm -rf /etc/localtime     &lt;br /&gt;ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime     &lt;br /&gt;systemctl enable ntp     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h3&gt;  &lt;a href="https://liangshuang.name/#&amp;#32593;&amp;#32476;&amp;#37197;&amp;#32622;" title="&amp;#32593;&amp;#32476;&amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;网络配置&lt;/h3&gt; &lt;p&gt;修改  &lt;code&gt;/etc/network/interfaces&lt;/code&gt;的内容如下：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;auto eth0.2     &lt;br /&gt;iface eth0.2 inet manual     &lt;br /&gt;    vlan-raw-device eth0     &lt;br /&gt;     &lt;br /&gt;iface eth0.3 inet manual     &lt;br /&gt;    vlan-raw-device eth0     &lt;br /&gt;     &lt;br /&gt;auto br0     &lt;br /&gt;iface br0 inet manual     &lt;br /&gt;    bridge_ports eth0.2     &lt;br /&gt;     &lt;br /&gt;auto br1     &lt;br /&gt;iface br1 inet manual     &lt;br /&gt;    bridge_ports eth0.3     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;这里配置了两个VLAN，号码需要和前边交换机的号码对应，同时建了两个网桥，方便今后添加更多的接入方式，br0为外网，br1为内网。&lt;/p&gt;
 &lt;p&gt;Raspbian使用dhcpcd来配置网络地址，修改  &lt;code&gt;/etc/dhcpcd.conf&lt;/code&gt;，在文件最后添加如下内容：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;denyinterfaces eth0 eth0.2 eth0.3     &lt;br /&gt;     &lt;br /&gt;interface br1     &lt;br /&gt;static ip_address=192.168.51.1/24     &lt;br /&gt;static routers=192.168.51.1     &lt;br /&gt;static domain_name_servers=192.168.51.1     &lt;br /&gt;nogateway     &lt;br /&gt;     &lt;br /&gt;interface wlan0     &lt;br /&gt;nohook wpa_supplicant     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;上边配置中用了  &lt;code&gt;192.168.51.0/24&lt;/code&gt;这个网段，可以根据需要自行调整，  &lt;code&gt;nogateway&lt;/code&gt;可以保证使用br0为默认网关而不是br1。&lt;/p&gt;
 &lt;h3&gt;  &lt;a href="https://liangshuang.name/#SS&amp;#26381;&amp;#21153;" title="SS&amp;#26381;&amp;#21153;"&gt;&lt;/a&gt;SS服务&lt;/h3&gt; &lt;p&gt;SS全家桶客户端一共有三个服务：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;shadowsocks-libev-local：socks5正向代理服务，非代理VLAN中的终端可以通过这个socks5代理上网，配合Proxychains与Switch Omega这类的软件使用。&lt;/li&gt;
  &lt;li&gt;shadowsocks-libev-redir：socks5透明代理服务，所有需要代理的网路流量都会根据iptables规则转发到这个服务的监听端口。&lt;/li&gt;
  &lt;li&gt;shadowsocks-libev-tunnel：本地端口转发工具，这里用于解决dns污染问题。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;下边是三个服务的配置：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;19     &lt;br /&gt;20     &lt;br /&gt;21     &lt;br /&gt;22     &lt;br /&gt;23     &lt;br /&gt;24     &lt;br /&gt;25     &lt;br /&gt;26     &lt;br /&gt;27     &lt;br /&gt;28     &lt;br /&gt;29     &lt;br /&gt;30     &lt;br /&gt;31     &lt;br /&gt;32     &lt;br /&gt;33     &lt;br /&gt;34     &lt;br /&gt;35     &lt;br /&gt;36     &lt;br /&gt;37     &lt;br /&gt;38     &lt;br /&gt;39     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; /etc/shadowsocks-libev/local.json     &lt;br /&gt;{     &lt;br /&gt;    &amp;quot;server&amp;quot;: &amp;quot;SS服务器的IP地址&amp;quot;,     &lt;br /&gt;    &amp;quot;server_port&amp;quot;: SS服务端口号,     &lt;br /&gt;    &amp;quot;local_address&amp;quot;: &amp;quot;0.0.0.0&amp;quot;,     &lt;br /&gt;    &amp;quot;local_port&amp;quot;: 1080,     &lt;br /&gt;    &amp;quot;password&amp;quot;: &amp;quot;SS服务器的密码&amp;quot;,     &lt;br /&gt;    &amp;quot;timeout&amp;quot;: 300,     &lt;br /&gt;    &amp;quot;method&amp;quot;: &amp;quot;aes-256-cfb&amp;quot;,     &lt;br /&gt;    &amp;quot;fast_open&amp;quot;: false     &lt;br /&gt;}     &lt;br /&gt;EOT     &lt;br /&gt;cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; /etc/shadowsocks-libev/redir.json     &lt;br /&gt;{     &lt;br /&gt;    &amp;quot;server&amp;quot;: &amp;quot;SS服务器的IP地址&amp;quot;,     &lt;br /&gt;    &amp;quot;server_port&amp;quot;: SS服务端口号,     &lt;br /&gt;    &amp;quot;local_address&amp;quot;: &amp;quot;0.0.0.0&amp;quot;,     &lt;br /&gt;    &amp;quot;local_port&amp;quot;: 1088,     &lt;br /&gt;    &amp;quot;password&amp;quot;: &amp;quot;SS服务器的密码&amp;quot;,     &lt;br /&gt;    &amp;quot;timeout&amp;quot;: 300,     &lt;br /&gt;    &amp;quot;method&amp;quot;: &amp;quot;aes-256-cfb&amp;quot;,     &lt;br /&gt;    &amp;quot;mode&amp;quot;: &amp;quot;tcp_and_udp&amp;quot;,     &lt;br /&gt;    &amp;quot;fast_open&amp;quot;: false     &lt;br /&gt;}     &lt;br /&gt;EOT     &lt;br /&gt;cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; /etc/shadowsocks-libev/tunnel.json     &lt;br /&gt;{     &lt;br /&gt;    &amp;quot;server&amp;quot;: &amp;quot;SS服务器的IP地址&amp;quot;,     &lt;br /&gt;    &amp;quot;server_port&amp;quot;: SS服务端口号,     &lt;br /&gt;    &amp;quot;local_address&amp;quot;: &amp;quot;0.0.0.0&amp;quot;,     &lt;br /&gt;    &amp;quot;local_port&amp;quot;: 15353,     &lt;br /&gt;    &amp;quot;password&amp;quot;: &amp;quot;SS服务器的密码&amp;quot;,     &lt;br /&gt;    &amp;quot;timeout&amp;quot;: 300,     &lt;br /&gt;    &amp;quot;method&amp;quot;: &amp;quot;aes-256-cfb&amp;quot;,     &lt;br /&gt;    &amp;quot;tunnel_address&amp;quot;: &amp;quot;8.8.8.8:53&amp;quot;,     &lt;br /&gt;    &amp;quot;mode&amp;quot;: &amp;quot;tcp_and_udp&amp;quot;,     &lt;br /&gt;    &amp;quot;fast_open&amp;quot;: false     &lt;br /&gt;}     &lt;br /&gt;EOT     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;停止默认的SS服务并启用上边的三个代理服务：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;systemctl stop shadowsocks-libev     &lt;br /&gt;systemctl disable shadowsocks-libev     &lt;br /&gt;systemctl enable shadowsocks-libev-local@local     &lt;br /&gt;systemctl enable shadowsocks-libev-redir@redir     &lt;br /&gt;systemctl enable shadowsocks-libev-tunnel@tunnel     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h3&gt;  &lt;a href="https://liangshuang.name/#DNS&amp;#26381;&amp;#21153;" title="DNS&amp;#26381;&amp;#21153;"&gt;&lt;/a&gt;DNS服务&lt;/h3&gt; &lt;p&gt;很多的大型网站，在国内外会提供不同的版本，如果我们都用国外的DNS来解析，可能会看到非中国的版本或者被解析到国外的服务器而影响浏览速度。所以需要使用一个列表来指定所有的国内网站走国内的DNS：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;git clone --depth 1 https://github.com/felixonmars/dnsmasq-china-list.git     &lt;br /&gt;cp dnsmasq-china-list/accelerated-domains.china.conf dnsmasq-china-list/bogus-nxdomain.china.conf /etc/dnsmasq.d/     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;接下来配置dnsmasq并启用服务：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;cat &amp;lt;&amp;lt; EOT &amp;gt;&amp;gt; /etc/dnsmasq.conf     &lt;br /&gt;strict-order     &lt;br /&gt;no-resolv     &lt;br /&gt;no-poll     &lt;br /&gt;server=127.0.0.1#15353     &lt;br /&gt;interface=br1     &lt;br /&gt;dhcp-range=192.168.51.50,192.168.51.100,255.255.255.0,24h     &lt;br /&gt;cache-size=10240     &lt;br /&gt;local=/ss/     &lt;br /&gt;domain=ss     &lt;br /&gt;expand-hosts     &lt;br /&gt;conf-dir=/etc/dnsmasq.d     &lt;br /&gt;EOT     &lt;br /&gt;     &lt;br /&gt;systemctl enable dnsmasq     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h3&gt;  &lt;a href="https://liangshuang.name/#&amp;#37197;&amp;#32622;&amp;#26080;&amp;#32447;AP" title="&amp;#37197;&amp;#32622;&amp;#26080;&amp;#32447;AP"&gt;&lt;/a&gt;配置无线AP&lt;/h3&gt; &lt;p&gt;配置hostapd：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;19     &lt;br /&gt;20     &lt;br /&gt;21     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; /etc/hostapd/hostapd.conf     &lt;br /&gt;interface=wlan0     &lt;br /&gt;bridge=br1     &lt;br /&gt;driver=nl80211     &lt;br /&gt;ssid=SS     &lt;br /&gt;hw_mode=g     &lt;br /&gt;channel=7     &lt;br /&gt;wmm_enabled=0     &lt;br /&gt;macaddr_acl=0     &lt;br /&gt;auth_algs=1     &lt;br /&gt;ignore_broadcast_ssid=0     &lt;br /&gt;wpa=2     &lt;br /&gt;wpa_passphrase=ssproxy1234     &lt;br /&gt;wpa_key_mgmt=WPA-PSK     &lt;br /&gt;wpa_pairwise=TKIP     &lt;br /&gt;rsn_pairwise=CCMP     &lt;br /&gt;EOT     &lt;br /&gt;     &lt;br /&gt;echo &amp;apos;DAEMON_CONF=&amp;quot;/etc/hostapd/hostapd.conf&amp;quot;&amp;apos; &amp;gt;&amp;gt; /etc/default/hostapd     &lt;br /&gt;     &lt;br /&gt;systemctl enable hostapd     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;树莓派3B+的无线网卡支持2.4G与5G模式，这里使用的是2.4G模式，以确保最好的兼容性（  &lt;code&gt;hw_mode=g&lt;/code&gt;），无线网络的名称为  &lt;code&gt;SS&lt;/code&gt;，密码为  &lt;code&gt;ssproxy1234&lt;/code&gt;，可以根据需要自行修改，另外也要注意频段最好避开家里路由器的频段，这里的频段是7（  &lt;code&gt;channel=7&lt;/code&gt;）。&lt;/p&gt;
 &lt;h3&gt;  &lt;a href="https://liangshuang.name/#&amp;#37197;&amp;#32622;iptables&amp;#19982;ipset" title="&amp;#37197;&amp;#32622;iptables&amp;#19982;ipset"&gt;&lt;/a&gt;配置iptables与ipset&lt;/h3&gt; &lt;p&gt;下载国内IP地址列表并加入ipset：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;curl -sL http://f.ip.cn/rt/chnroutes.txt | egrep -v &amp;apos;^$|^#&amp;apos; &amp;gt; chinaip.txt     &lt;br /&gt;ipset -N chinaip hash:net     &lt;br /&gt;for i in `cat chinaip.txt`; do echo ipset -A chinaip $i &amp;gt;&amp;gt; chinaip.sh; done     &lt;br /&gt;bash chinaip.sh     &lt;br /&gt;ipset -S &amp;gt; /etc/ipset.chinaip     &lt;br /&gt;rm -rf chinaip.txt chinaip.sh     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;配置iptables规则：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;19     &lt;br /&gt;20     &lt;br /&gt;21     &lt;br /&gt;22     &lt;br /&gt;23     &lt;br /&gt;24     &lt;br /&gt;25     &lt;br /&gt;26     &lt;br /&gt;27     &lt;br /&gt;28     &lt;br /&gt;29     &lt;br /&gt;30     &lt;br /&gt;31     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;iptables -F     &lt;br /&gt;iptables -X     &lt;br /&gt;iptables -t nat -F     &lt;br /&gt;iptables -t nat -X     &lt;br /&gt;iptables -t mangle -F     &lt;br /&gt;iptables -t mangle -X     &lt;br /&gt;iptables -t raw -F     &lt;br /&gt;iptables -t raw -X     &lt;br /&gt;iptables -P INPUT ACCEPT     &lt;br /&gt;iptables -P FORWARD ACCEPT     &lt;br /&gt;iptables -P OUTPUT ACCEPT     &lt;br /&gt;iptables -t nat -N shadowsocks     &lt;br /&gt;iptables -t nat -A shadowsocks -d 0/8 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d 127/8 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d 10/8 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d 169.254/16 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d 172.16/12 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d 192.168/16 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d 224/4 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d 240/4 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -d SS服务器地址 -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -m set --match-set chinaip dst -j RETURN     &lt;br /&gt;iptables -t nat -A shadowsocks -p tcp -j REDIRECT --to-ports 1088     &lt;br /&gt;iptables -t nat -A shadowsocks -p udp ! --dport 53 -j REDIRECT --to-ports 1088     &lt;br /&gt;iptables -t nat -A OUTPUT -p tcp -j shadowsocks     &lt;br /&gt;iptables -t nat -A OUTPUT -p udp ! --dport 53 -j shadowsocks     &lt;br /&gt;iptables -t nat -A PREROUTING -p tcp -s 192.168.51/24 -j shadowsocks     &lt;br /&gt;iptables -t nat -A PREROUTING -p udp ! --dport 53 -s 192.168.51/24 -j shadowsocks     &lt;br /&gt;iptables -t nat -A POSTROUTING -s 192.168.51/24 -j MASQUERADE     &lt;br /&gt;     &lt;br /&gt;iptables-save &amp;gt; /etc/iptables.up.rules     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;注意替换上边命令中的“SS服务器地址”。&lt;/p&gt;
 &lt;p&gt;当网络连接启动时，自动加载以上规则：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; /etc/network/if-pre-up.d/iptables     &lt;br /&gt;#!/bin/sh     &lt;br /&gt;/sbin/ipset -R &amp;lt; /etc/ipset.chinaip     &lt;br /&gt;/sbin/iptables-restore &amp;lt; /etc/iptables.up.rules     &lt;br /&gt;EOT     &lt;br /&gt;     &lt;br /&gt;chmod +x /etc/network/if-pre-up.d/iptables     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h3&gt;  &lt;a href="https://liangshuang.name/#&amp;#35843;&amp;#25972;&amp;#20869;&amp;#26680;&amp;#21442;&amp;#25968;" title="&amp;#35843;&amp;#25972;&amp;#20869;&amp;#26680;&amp;#21442;&amp;#25968;"&gt;&lt;/a&gt;调整内核参数&lt;/h3&gt; &lt;p&gt;调整内核，允许转发并参考SS的文档做相应的优化：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;19     &lt;br /&gt;20     &lt;br /&gt;21     &lt;br /&gt;22     &lt;br /&gt;23     &lt;br /&gt;24     &lt;br /&gt;25     &lt;br /&gt;26     &lt;br /&gt;27     &lt;br /&gt;28     &lt;br /&gt;29     &lt;br /&gt;30     &lt;br /&gt;31     &lt;br /&gt;32     &lt;br /&gt;33     &lt;br /&gt;34     &lt;br /&gt;35     &lt;br /&gt;36     &lt;br /&gt;37     &lt;br /&gt;38     &lt;br /&gt;39     &lt;br /&gt;40     &lt;br /&gt;41     &lt;br /&gt;42     &lt;br /&gt;43     &lt;br /&gt;44     &lt;br /&gt;45     &lt;br /&gt;46     &lt;br /&gt;47     &lt;br /&gt;48     &lt;br /&gt;49     &lt;br /&gt;50     &lt;br /&gt;51     &lt;br /&gt;52     &lt;br /&gt;53     &lt;br /&gt;54     &lt;br /&gt;55     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; /etc/sysctl.d/50-ss.conf     &lt;br /&gt;# max open files     &lt;br /&gt;fs.file-max = 1024000     &lt;br /&gt;# max read buffer     &lt;br /&gt;net.core.rmem_max = 67108864     &lt;br /&gt;# max write buffer     &lt;br /&gt;net.core.wmem_max = 67108864     &lt;br /&gt;# default read buffer     &lt;br /&gt;net.core.rmem_default = 65536     &lt;br /&gt;# default write buffer     &lt;br /&gt;net.core.wmem_default = 65536     &lt;br /&gt;# max processor input queue     &lt;br /&gt;net.core.netdev_max_backlog = 4096     &lt;br /&gt;# max backlog     &lt;br /&gt;net.core.somaxconn = 4096     &lt;br /&gt;     &lt;br /&gt;# resist SYN flood attacks     &lt;br /&gt;net.ipv4.tcp_syncookies = 1     &lt;br /&gt;# reuse timewait sockets when safe     &lt;br /&gt;net.ipv4.tcp_tw_reuse = 1     &lt;br /&gt;# turn off fast timewait sockets recycling     &lt;br /&gt;net.ipv4.tcp_tw_recycle = 0     &lt;br /&gt;# short FIN timeout     &lt;br /&gt;net.ipv4.tcp_fin_timeout = 30     &lt;br /&gt;# short keepalive time     &lt;br /&gt;net.ipv4.tcp_keepalive_time = 1200     &lt;br /&gt;# outbound port range     &lt;br /&gt;net.ipv4.ip_local_port_range = 10000 65000     &lt;br /&gt;# max SYN backlog     &lt;br /&gt;net.ipv4.tcp_max_syn_backlog = 4096     &lt;br /&gt;# max timewait sockets held by system simultaneously     &lt;br /&gt;net.ipv4.tcp_max_tw_buckets = 5000     &lt;br /&gt;# TCP receive buffer     &lt;br /&gt;net.ipv4.tcp_rmem = 4096 87380 67108864     &lt;br /&gt;# TCP write buffer     &lt;br /&gt;net.ipv4.tcp_wmem = 4096 65536 67108864     &lt;br /&gt;# turn on path MTU discovery     &lt;br /&gt;net.ipv4.tcp_mtu_probing = 1     &lt;br /&gt;     &lt;br /&gt;# for high-latency network     &lt;br /&gt;# net.ipv4.tcp_congestion_control = cubic     &lt;br /&gt;# forward ipv4     &lt;br /&gt;net.ipv4.ip_forward = 1     &lt;br /&gt;EOT     &lt;br /&gt;     &lt;br /&gt;cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; /etc/security/limits.conf     &lt;br /&gt;*               soft    nofile           512000     &lt;br /&gt;*               hard    nofile           1024000     &lt;br /&gt;EOT     &lt;br /&gt;     &lt;br /&gt;echo &amp;quot;ulimit -SHn 1024000&amp;quot; &amp;gt;&amp;gt; /etc/profile     &lt;br /&gt;     &lt;br /&gt;sysctl --system     &lt;br /&gt;     &lt;br /&gt;ulimit -n 512000     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;h2&gt;  &lt;a href="https://liangshuang.name/#&amp;#24635;&amp;#32467;" title="&amp;#24635;&amp;#32467;"&gt;&lt;/a&gt;总结&lt;/h2&gt; &lt;p&gt;全部配置完成后，重启树莓派，终端通过网线连接交换机的7、8口，或者连接名称为  &lt;code&gt;SS&lt;/code&gt;的无线网络，都可以自动的代理上网了。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux Linux VPN Network</category>
      <guid isPermaLink="true">https://itindex.net/detail/58769-%E6%A0%91%E8%8E%93%E6%B4%BE-vlan-%E4%BA%A4%E6%8D%A2%E6%9C%BA</guid>
      <pubDate>Wed, 05 Sep 2018 20:03:45 CST</pubDate>
    </item>
    <item>
      <title>Linux 查看进程消耗内存情况总结</title>
      <link>https://itindex.net/detail/58725-linux-%E8%BF%9B%E7%A8%8B-%E6%B6%88%E8%80%97</link>
      <description>&lt;p&gt;在Linux中，有很多命令或工具查看内存使用情况，今天我们来看看如何查看进程消耗、占用的内存情况，Linux的内存管理和相关概念要比Windows复杂一些。在此之前，我们需要了解一下Linux系统下面有关内存的专用名词和专业术语概念： &lt;/p&gt;
 &lt;h2&gt;物理内存和虚拟内存 &lt;/h2&gt;
 &lt;p&gt;物理内存：就是系统硬件提供的内存大小，是真正的内存，一般叫做内存条。也叫随机存取存储器（random access memory，RAM）又称作“随机存储器”，是与CPU直接交换数据的内部存储器，也叫主存(内存)。 &lt;/p&gt;
 &lt;p&gt;虚拟内存：相对于物理内存，在Linux下还有一个虚拟内存的概念，虚拟内存就是为了满足物理内存的不足而提出的策略，它是利用磁盘空间虚拟出的一块逻辑内存，用作虚拟内存的磁盘空间被称为交换空间（Swap Space）。Linux会在物理内存不足时，使用虚拟内存，内核会把暂时不用的内存块信息写到虚拟内存，这样物理内存就得到了释放，这块儿内存就可以用于其他目的，而需要用到这些内容的时候，这些信息就会被重新从虚拟内存读入物理内存。 &lt;/p&gt;
 &lt;h2&gt;Linux的buffers与cached&lt;/h2&gt;
 &lt;p&gt;在Linux中经常发现空闲的内存很少，似乎所有的内存都被消耗殆尽了，表面上看是内存不够用了，很多新手看到内存被“消耗殆尽”非常紧张，其实这个是因为Linux系统将空闲的内存用来做磁盘文件数据的缓存。这个导致你的系统看起来处于内存非常紧急的状况。但是实际上不是这样。这个区别于Windows的内存管理。Linux会利用空闲的内存来做cached &amp;amp; buffers。 &lt;/p&gt;
 &lt;p&gt;buffers是指用来给块设备做的缓冲大小（块设备的读写缓冲区），它只记录文件系统的metadata以及 tracking in-flight pages.&lt;/p&gt;
 &lt;p&gt;Buffers are associated with a specific block device, and cover caching of filesystem metadata as well as tracking in-flight pages. The cache only contains parked file data. That is, the buffers remember what’s in directories, what file permissions are, and keep track of what memory is being written from or read to for a particular block device. The cache only contains the contents of the files themselves.&lt;/p&gt;
 &lt;p&gt;cached是作为page cache的内存, 文件系统的cache。你读写文件的时候，Linux内核为了提高读写性能与速度，会将文件在内存中进行缓存，这部分内存就是Cache Memory(缓存内存)。即使你的程序运行结束后，Cache Memory也不会自动释放。这就会导致你在Linux系统中程序频繁读写文件后，你会发现可用物理内存会很少。其实这缓存内存(Cache Memory)在你需要使用内存的时候会自动释放，所以你不必担心没有内存可用&lt;/p&gt;
 &lt;p&gt;Cached is the size of the page cache. Buffers is the size of in-memory block I/O buffers. Cached matters; Buffers is largely irrelevant.&lt;/p&gt;
 &lt;p&gt;Cached is the size of the Linux page cache, minus the memory in the swap cache, which is represented by SwapCached (thus the total page cache size is Cached + SwapCached). Linux performs all file I/O through the page cache. Writes are implemented as simply marking as dirty the corresponding pages in the page cache; the flusher threads then periodically write back to disk any dirty pages. Reads are implemented by returning the data from the page cache; if the data is not yet in the cache, it is first populated. On a modern Linux system, Cached can easily be several gigabytes. It will shrink only in response to memory pressure. The system will purge the page cache along with swapping data out to disk to make available more memory as needed.&lt;/p&gt;
 &lt;p&gt;Buffers are in-memory block I/O buffers. They are relatively short-lived. Prior to Linux kernel version 2.4, Linux had separate page and buffer caches. Since 2.4, the page and buffer cache are unified and Buffers is raw disk blocks not represented in the page cache—i.e., not file data. The Buffers metric is thus of minimal importance. On most systems, Buffers is often only tens of megabytes. &lt;/p&gt;
 &lt;h2&gt;Linux共享内存&lt;/h2&gt;
 &lt;p&gt;共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存，就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候，其它进程都会察觉到这个。其实所谓共享内存，就是多个进程间共同地使用同一段物理内存空间，它是通过将同一段物理内存映射到不同进程的虚拟空间来实现的。由于映射到不同进程的虚拟空间中，不同进程可以直接使用，不需要像消息队列那样进行复制，所以共享内存的效率很高。共享内存可以通过mmap()映射普通文件机制来实现，也可以System V共享内存机制来实现，System V是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信，也就是说每个共享内存区域对应特殊文件系统shm中的一个文件。&lt;/p&gt;
 &lt;p&gt;另外，我们还必须了解RSS、PSS、USS等相关概念：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;VSS – Virtual Set Size 虚拟耗用内存（包含共享库占用的内存）&lt;/li&gt;
  &lt;li&gt;RSS – Resident Set Size 实际使用物理内存（包含共享库占用的内存）&lt;/li&gt;
  &lt;li&gt;PSS – Proportional Set Size 实际使用的物理内存（比例分配共享库占用的内存）&lt;/li&gt;
  &lt;li&gt;USS – Unique Set Size 进程独自占用的物理内存（不包含共享库占用的内存）&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;RSS（Resident set size），使用top命令可以查询到，是最常用的内存指标，表示进程占用的物理内存大小。但是，将各进程的RSS值相加，通常会超出整个系统的内存消耗，这是因为RSS中包含了各进程间共享的内存。&lt;/p&gt;
 &lt;p&gt;PSS（Proportional set size）所有使用某共享库的程序均分该共享库占用的内存时，每个进程占用的内存。显然所有进程的PSS之和就是系统的内存使用量。它会更准确一些，它将共享内存的大小进行平均后，再分摊到各进程上去。 &lt;/p&gt;
 &lt;p&gt;USS(Unique set size )进程独自占用的内存，它是PSS中自己的部分，它只计算了进程独自占用的内存大小，不包含任何共享的部分。 &lt;/p&gt;
 &lt;p&gt;所以下面介绍的命令，有些查看进程的虚拟内存使用，有些是查看进程的RSS或实际物理内存。在讲述的时候，我们会标注这些信息。&lt;/p&gt;
 &lt;h2&gt;top命令查看&lt;/h2&gt;
 &lt;p&gt;执行top命令后，执行SHIFT +F ，可以选择按某列排序，例如选择n后，就会按字段%MEM排序&lt;/p&gt;
 &lt;p&gt;  &lt;a href="http://www.importnew.com/29782.html/73542-20180901000856187-1964157136" rel="attachment wp-att-29783"&gt;   &lt;img alt="" src="http://incdn1.b0.upaiyun.com/2018/09/89bf056dcfc083f3af16b780e26d869d.png" title="73542-20180901000856187-1964157136"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;当然也可以使用shift+m 或大写键M 让top命令按字段%MEM来排序，当然你也可以按VIRT（虚拟内存）、SWAP（进程使用的SWAP空间）、RES(实际使用物理内存,当然这里由于涉及共享内存缘故，你看到的实际内存非常大)&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;%MEM — Memory usage (RES) &lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;A task’s currently used share of available physical memory&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;VIRT — virtual memory&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out. (Note: you can define the STATSIZE=1 environment variable and the VIRT will be calculated from the /proc/#/state VmSize field.)&lt;/p&gt;
 &lt;p&gt;VIRT = SWAP + RES&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;SWAP — Swapped size (kb)&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;The swapped out portion of a task’s total virtual memory image.&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;RES — Resident size (kb) &lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;RES = CODE + DATA.&lt;/p&gt;
 &lt;p&gt;是否有人会觉得奇怪，为什么%MEM这一列的值加起来会大于100呢？ 这个是因为这里计算的时候包含了共享内存的缘故，另外由于共享内存的缘故，你看到进程使用VIRT或RES都非常高。由于大部分的物理内存通常在多个应用程序之间共享，名为实际使用物理内存（RSS，对应top命令里面的RES）的这个标准的内存耗用衡量指标会大大高估内存耗用情况。&lt;/p&gt;
 &lt;p&gt;  &lt;a href="http://www.importnew.com/29782.html/73542-20180901000856895-857545179" rel="attachment wp-att-29784"&gt;   &lt;img alt="" src="http://incdn1.b0.upaiyun.com/2018/09/dd4e66a9b8ac110baa3353be91d2f987.png" title="73542-20180901000856895-857545179"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;h2&gt;ps命令查看&lt;/h2&gt;
 &lt;p&gt;使用ps命令找出占用内存资源最多的20个进程（数量可以任意设置）&lt;/p&gt;
 &lt;pre&gt;# ps aux | head -1;ps aux |grep -v PID |sort -rn -k +4 | head -20
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
oracle   32147 11.0 51.2 13252080 12666320 ?   Rs   Aug24 163:16 ora_s000_SCM2
oracle   32149 14.2 50.9 13250344 12594264 ?   Ss   Aug24 210:41 ora_s001_SCM2
oracle   32153  4.2 49.6 13250820 12279432 ?   Ss   Aug24  62:27 ora_s003_SCM2
oracle   32155  2.5 48.6 13250268 12040732 ?   Ss   Aug24  38:21 ora_s004_SCM2
oracle   32157  1.2 44.5 13250296 11011708 ?   Ss   Aug24  18:31 ora_s005_SCM2
oracle   32151  2.7 39.7 13350436 9829944 ?    Ss   Aug24  41:18 ora_s002_SCM2
oracle   32159  0.5 38.9 13250704 9625764 ?    Ss   Aug24   8:18 ora_s006_SCM2
oracle   32161  0.2 26.3 13250668 6507244 ?    Ss   Aug24   3:38 ora_s007_SCM2
oracle   32129  0.0 25.5 13299084 6324644 ?    Ss   Aug24   1:25 ora_dbw0_SCM2
oracle   32181  0.0 15.8 13250152 3913260 ?    Ss   Aug24   0:56 ora_s017_SCM2
oracle   32145  2.7 15.3 13255256 3786456 ?    Ss   Aug24  40:11 ora_d000_SCM2
oracle   32127  0.0 15.2 13248996 3762860 ?    Ss   Aug24   0:05 ora_mman_SCM2
oracle   32163  0.0 14.2 13250108 3525160 ?    Ss   Aug24   1:04 ora_s008_SCM2
oracle   32165  0.0  8.1 13250172 2007704 ?    Ss   Aug24   0:37 ora_s009_SCM2
oracle   32169  0.0  6.6 13250060 1656864 ?    Ss   Aug24   0:08 ora_s011_SCM2
oracle   32177  0.0  6.0 13250148 1498760 ?    Ss   Aug24   0:12 ora_s015_SCM2
oracle   32187  0.0  5.1 13250084 1267384 ?    Ss   Aug24   0:06 ora_s020_SCM2
oracle   32179  0.0  5.1 13250584 1280156 ?    Ss   Aug24   0:05 ora_s016_SCM2
oracle   32167  0.0  5.0 13250060 1248668 ?    Ss   Aug24   0:08 ora_s010_SCM2
oracle   32175  0.0  3.4 13250596 857380 ?     Ss   Aug24   0:03 ora_s014_SCM2&lt;/pre&gt;
 &lt;pre&gt;#ps -eo pmem,pcpu,rss,vsize,args | sort -k 1 -n -r | less&lt;/pre&gt;
 &lt;p&gt;查看进程占用的实际物理内存（与smem看到实际物理内存大小有出入，这里解释一下：SIZE: 进程使用的地址空间, 如果进程映射了100M的内存, 进程的地址空间将报告为100M内存. 事实上, 这个大小不是一个程序实际使用的内存数. 所以这里看到的内存跟smem看到的大小有出入）&lt;/p&gt;
 &lt;pre&gt;ps -eo size,pid,user,command --sort -size | awk &amp;apos;{ hr=$1/1024 ; printf(&amp;quot;%13.2f Mb &amp;quot;,hr) } { for ( x=4 ; x&amp;lt;=NF ; x++ ) { printf(&amp;quot;%s &amp;quot;,$x) } print &amp;quot;&amp;quot; }&amp;apos; |cut -d &amp;quot;&amp;quot; -f2 | cut -d &amp;quot;-&amp;quot; -f1&lt;/pre&gt;
 &lt;p&gt;  &lt;a href="http://www.importnew.com/29782.html/73542-20180901000857559-500188632" rel="attachment wp-att-29785"&gt;   &lt;img alt="" src="http://incdn1.b0.upaiyun.com/2018/09/31791cf5f3e0eced31ab7d65ac8530dc.png" title="73542-20180901000857559-500188632"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;pre&gt;ps aux | awk &amp;apos;{print $6/1024 &amp;quot; MB\t\t&amp;quot; $11}&amp;apos; | sort -n&lt;/pre&gt;
 &lt;h2&gt;smem命令查看&lt;/h2&gt;
 &lt;p&gt;关于smem命令，这里不做介绍，直接参考链接  &lt;a href="http://www.cnblogs.com/kerrycode/p/5079319.html"&gt;Linux监控工具介绍系列——smem&lt;/a&gt;&lt;/p&gt;
 &lt;pre&gt;#smem -rs pss&lt;/pre&gt;
 &lt;p&gt;  &lt;a href="http://www.importnew.com/29782.html/73542-20180901000858209-178412334" rel="attachment wp-att-29786"&gt;   &lt;img alt="" src="http://incdn1.b0.upaiyun.com/2018/09/d3451d209043e8ef34acc615489000bd.png" title="73542-20180901000858209-178412334"&gt;&lt;/img&gt;&lt;/a&gt; &lt;/p&gt;
 &lt;h2&gt;pmap命令查看&lt;/h2&gt;
 &lt;pre&gt;# ps -ef | grep tomcat
# pmap 32341&lt;/pre&gt;
 &lt;p&gt;  &lt;a href="http://www.importnew.com/29782.html/73542-20180901000858801-1652232463" rel="attachment wp-att-29787"&gt;   &lt;img alt="" src="http://incdn1.b0.upaiyun.com/2018/09/335245483eb81aec430390a17489144e.png" title="73542-20180901000858801-1652232463"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;pre&gt;# pmap -x 32341&lt;/pre&gt;
 &lt;p&gt;The -x option can be used to provide information about the memory allocation and mapping types per mapping. The amount of resident, non-shared anonymous, and locked memory is shown for each mapping。&lt;/p&gt;
 &lt;p&gt;  &lt;a href="http://www.importnew.com/29782.html/73542-20180901000859394-1767185932" rel="attachment wp-att-29788"&gt;   &lt;img alt="" src="http://incdn1.b0.upaiyun.com/2018/09/04f6f281e0c2e5a2b9b7bb91cc090c8c.png" title="73542-20180901000859394-1767185932"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;h2&gt;python脚本查看&lt;/h2&gt;
 &lt;p&gt;网上有个python脚本计算程序或进程的内存使用情况，地址位于https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py&lt;/p&gt;
 &lt;p&gt;python ps_mem.py&lt;/p&gt;
 &lt;p&gt;  &lt;a href="http://www.importnew.com/29782.html/73542-20180901000900114-1571331438" rel="attachment wp-att-29789"&gt;   &lt;img alt="" src="http://incdn1.b0.upaiyun.com/2018/09/767164b8530432a55d578f5772778b69.png" title="73542-20180901000900114-1571331438"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;pre&gt;[root@mylnx03 ~]# python ps_mem.py -h
Usage: ps_mem [OPTION]...
Show program core memory usage
 
  -h, -help                   Show this help
  -p &amp;lt;pid&amp;gt;[,pid2,...pidN]     Only show memory usage PIDs in the specified list
  -s, --split-args            Show and separate by, all command line arguments
  -t, --total                 Show only the total value
  -d, --discriminate-by-pid   Show by process rather than by program
  -S, --swap                  Show swap information
  -w &amp;lt;N&amp;gt;                      Measure and show process memory every N seconds
[root@mylnx03 ~]# python ps_mem.py  -p 32341
 Private  +   Shared  =  RAM used       Program
 
411.2 MiB + 184.0 KiB = 411.4 MiB       java
---------------------------------
                        411.4 MiB
=================================&lt;/pre&gt;
 &lt;h2&gt;参考资料：&lt;/h2&gt;
 &lt;ul&gt;
  &lt;li&gt;https://stackoverflow.com/questions/131303/how-to-measure-actual-memory-usage-of-an-application-or-process&lt;/li&gt;
  &lt;li&gt;http://www.cnblogs.com/kerrycode/p/5079319.html&lt;/li&gt;
  &lt;li&gt;https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;h3&gt;相关文章&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/28604.html"&gt;linux 内存的分配和释放&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/29534.html"&gt;运行 tail | grep 后按下 Ctrl – C 的过程中发生了什么&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/29525.html"&gt;误删除dev下特殊文件怎么办&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/29492.html"&gt;Linux查看分区文件系统类型总结&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/29242.html"&gt;Linux 中如何通过设备号找到设备&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/29163.html"&gt;linux 查杀 stopped 进程&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/29158.html"&gt;linux 定时休眠&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/29048.html"&gt;使用 lynis 进行 linux 漏洞扫描&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/28994.html"&gt;linux 如何更改网卡 MAC 地址&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/28964.html"&gt;linux 重要日志说明&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>基础技术 Linux 内存管理</category>
      <guid isPermaLink="true">https://itindex.net/detail/58725-linux-%E8%BF%9B%E7%A8%8B-%E6%B6%88%E8%80%97</guid>
      <pubDate>Mon, 10 Sep 2018 22:07:26 CST</pubDate>
    </item>
    <item>
      <title>在 Linux 上用 DNS 实现简单的负载均衡</title>
      <link>https://itindex.net/detail/58480-linux-dns-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1</link>
      <description>&lt;blockquote&gt;  &lt;p&gt;DNS 轮询将多个服务器映射到同一个主机名，并没有为这里展示的魔法做更多的工作。&lt;/p&gt;&lt;/blockquote&gt;
 &lt;p&gt;如果你的后端服务器是由多台服务器构成的，比如集群化或者镜像的 Web 或者文件服务器，通过负载均衡器提供了单一的入口点。业务繁忙的大型电商在高端负载均衡器上花费了大量的资金，用它来执行各种各样的任务：代理、缓存、状况检查、SSL 处理、可配置的优先级、流量整形等很多任务。&lt;/p&gt;
 &lt;p&gt;但是你并不需要做那么多工作的负载均衡器。你需要的是一个跨服务器分发负载的简单方法，它能够提供故障切换，并且不太在意它是否高效和完美。DNS 轮询和使用轮询的子域委派是实现这个目标的两种简单方法。&lt;/p&gt;
 &lt;p&gt;DNS 轮询是将多台服务器映射到同一个主机名上，当用户访问   &lt;code&gt;foo.example.com&lt;/code&gt; 时多台服务器都可用于处理它们的请求，使用的就是这种方式。&lt;/p&gt;
 &lt;p&gt;当你有多个子域或者你的服务器在地理上比较分散时，使用轮询的子域委派就比较有用。你有一个主域名服务器，而子域有它们自己的域名服务器。你的主域名服务器将所有的到子域的请求指向到它们自己的域名服务器上。这将提升响应时间，因为 DNS 协议会自动查找最快的链路。&lt;/p&gt;
 &lt;h3&gt;DNS 轮询&lt;/h3&gt;
 &lt;p&gt;轮询和旅鸫鸟robins没有任何关系，据我相熟的图书管理员说，它最初是一个法语短语，  &lt;em&gt;ruban rond&lt;/em&gt;、或者   &lt;em&gt;round ribbon&lt;/em&gt;。很久以前，法国政府官员以不分级的圆形、波浪线、或者直线形状来在请愿书上签字，以盖住原来的发起人。&lt;/p&gt;
 &lt;p&gt;DNS 轮询也是不分级的，简单配置一个服务器列表，然后将请求转到每个服务器上。它并不做真正的负载均衡，因为它根本就不测量负载，也没有状况检查，因此如果一个服务器宕机，请求仍然会发送到那个宕机的服务器上。它的优点就是简单。如果你有一个小的文件或者 Web 服务器集群，想通过一个简单的方法在它们之间分散负载，那么 DNS 轮询很适合你。&lt;/p&gt;
 &lt;p&gt;你所做的全部配置就是创建多条 A 或者 AAAA 记录，映射多台服务器到单个的主机名。这个 BIND 示例同时使用了 IPv4 和 IPv6 私有地址类：&lt;/p&gt; &lt;pre&gt;fileserv.example.com. IN A 172.16.10.10
fileserv.example.com. IN A 172.16.10.11
fileserv.example.com. IN A 172.16.10.12

fileserv.example.com. IN AAAA fd02:faea:f561:8fa0:1::10
fileserv.example.com. IN AAAA fd02:faea:f561:8fa0:1::11
fileserv.example.com. IN AAAA fd02:faea:f561:8fa0:1::12&lt;/pre&gt; &lt;p&gt;Dnsmasq 在   &lt;code&gt;/etc/hosts&lt;/code&gt; 文件中保存 A 和 AAAA 记录：&lt;/p&gt; &lt;pre&gt;172.16.1.10 fileserv fileserv.example.com
172.16.1.11 fileserv fileserv.example.com
172.16.1.12 fileserv fileserv.example.com
fd02:faea:f561:8fa0:1::10 fileserv fileserv.example.com
fd02:faea:f561:8fa0:1::11 fileserv fileserv.example.com
fd02:faea:f561:8fa0:1::12 fileserv fileserv.example.com&lt;/pre&gt; &lt;p&gt;请注意这些示例都是很简化的，解析完全合格域名有多种方法，因此，关于如何配置 DNS 请自行学习。&lt;/p&gt;
 &lt;p&gt;使用   &lt;code&gt;dig&lt;/code&gt; 命令去检查你的配置能否按预期工作。将   &lt;code&gt;ns.example.com&lt;/code&gt; 替换为你的域名服务器：&lt;/p&gt; &lt;pre&gt;$ dig @ns.example.com fileserv A fileserv AAA&lt;/pre&gt; &lt;p&gt;它将同时显示出 IPv4 和 IPv6 的轮询记录。&lt;/p&gt;
 &lt;h3&gt;子域委派和轮询&lt;/h3&gt;
 &lt;p&gt;子域委派结合轮询要做的配置会更多，但是这样有一些好处。当你有多个子域或者地理位置比较分散的服务器时，就应该去使用它。它的响应时间更快，并且宕机的服务器不会去响应，因此客户端不会因为等待回复而被挂住。一个短的 TTL，比如 60 秒，就能帮你做到。&lt;/p&gt;
 &lt;p&gt;这种方法需要多台域名服务器。在最简化的场景中，你需要一台主域名服务器和两个子域，每个子域都有它们自己的域名服务器。在子域服务器上配置你的轮询记录，然后在你的主域名服务器上配置委派。&lt;/p&gt;
 &lt;p&gt;在主域名服务器上的 BIND 中，你至少需要两个额外的配置，一个区声明以及在区数据文件中的 A/AAAA 记录。主域名服务器中的委派应该像如下的内容：&lt;/p&gt; &lt;pre&gt;ns1.sub.example.com. IN A 172.16.1.20
ns1.sub.example.com. IN AAAA fd02:faea:f561:8fa0:1::20
ns2.sub.example.com. IN A 172.16.1.21
ns2.sub.example.com. IN AAA fd02:faea:f561:8fa0:1::21

sub.example.com. IN NS ns1.sub.example.com.
sub.example.com. IN NS ns2.sub.example.com.&lt;/pre&gt; &lt;p&gt;接下来的每台子域服务器上有它们自己的区文件。在这里它的关键点是每个服务器去返回它  &lt;strong&gt;自己的&lt;/strong&gt; IP 地址。在   &lt;code&gt;named.conf&lt;/code&gt; 中的区声明，所有的服务上都是一样的：&lt;/p&gt; &lt;pre&gt;zone &amp;quot;sub.example.com&amp;quot; {
    type master;
    file &amp;quot;db.sub.example.com&amp;quot;;
};&lt;/pre&gt; &lt;p&gt;然后数据文件也是相同的，除了那个 A/AAAA 记录使用的是各个服务器自己的 IP 地址。SOA 记录都指向到主域名服务器：&lt;/p&gt; &lt;pre&gt;; first subdomain name server
$ORIGIN sub.example.com.
$TTL 60
sub.example.com  IN SOA ns1.example.com. admin.example.com. (
        2018123456      ; serial
        3H              ; refresh
        15              ; retry
        3600000         ; expire
)

sub.example.com. IN NS ns1.sub.example.com.
sub.example.com. IN A  172.16.1.20
ns1.sub.example.com.  IN AAAA  fd02:faea:f561:8fa0:1::20
; second subdomain name server
$ORIGIN sub.example.com.
$TTL 60
sub.example.com  IN SOA ns1.example.com. admin.example.com. (
        2018234567      ; serial
        3H              ; refresh
        15              ; retry
        3600000         ; expire
)

sub.example.com. IN NS ns1.sub.example.com.
sub.example.com. IN A  172.16.1.21
ns2.sub.example.com.  IN AAAA  fd02:faea:f561:8fa0:1::21&lt;/pre&gt; &lt;p&gt;接下来生成子域服务器上的轮询记录，方法和前面一样。现在你已经有了多个域名服务器来处理到你的子域的请求。再说一次，BIND 是很复杂的，做同一件事情它有多种方法，因此，给你留的家庭作业是找出适合你使用的最佳配置方法。&lt;/p&gt;
 &lt;p&gt;在 Dnsmasq 中做子域委派很容易。在你的主域名服务器上的   &lt;code&gt;dnsmasq.conf&lt;/code&gt; 文件中添加如下的行，去指向到子域的域名服务器：&lt;/p&gt; &lt;pre&gt;server=/sub.example.com/172.16.1.20
server=/sub.example.com/172.16.1.21
server=/sub.example.com/fd02:faea:f561:8fa0:1::20
server=/sub.example.com/fd02:faea:f561:8fa0:1::21&lt;/pre&gt; &lt;p&gt;然后在子域的域名服务器上的   &lt;code&gt;/etc/hosts&lt;/code&gt; 中配置轮询。&lt;/p&gt;
 &lt;p&gt;获取配置方法的详细内容和帮助，请参考这些资源：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="http://www.thekelleys.org.uk/dnsmasq/doc.html"&gt;Dnsmasq&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://shop.oreilly.com/product/9780596100575.do"&gt;DNS and BIND, 5th Edition&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;通过来自 Linux 基金会和 edX 的免费课程   &lt;a href="https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux"&gt;“Linux 入门” &lt;/a&gt; 学习更多 Linux 的知识。&lt;/p&gt;
 &lt;p&gt;  &lt;a href="http://blog.jobbole.com/114157/"&gt;在 Linux 上用 DNS 实现简单的负载均衡&lt;/a&gt;，首发于  &lt;a href="http://blog.jobbole.com"&gt;文章 - 伯乐在线&lt;/a&gt;。&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>IT技术 Linux</category>
      <guid isPermaLink="true">https://itindex.net/detail/58480-linux-dns-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1</guid>
      <pubDate>Mon, 25 Jun 2018 22:02:42 CST</pubDate>
    </item>
    <item>
      <title>深挖NUMA</title>
      <link>https://itindex.net/detail/57606-numa</link>
      <description>&lt;p&gt;首先列出本站之前相关的几篇帖子：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="http://www.litrin.net/2014/06/18/linux%e7%9a%84numa%e6%9c%ba%e5%88%b6/" rel="noopener" target="_blank"&gt;Linux的NUMA机制&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.litrin.net/2017/08/03/numa%e5%af%b9%e6%80%a7%e8%83%bd%e7%9a%84%e5%bd%b1%e5%93%8d/" rel="noopener" target="_blank"&gt;NUMA对性能的影响&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.litrin.net/2016/05/18/cgroup%e7%9a%84cpuset%e9%97%ae%e9%a2%98/" rel="noopener" target="_blank"&gt;cgroup的cpuset问题&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;这次，就来深入了解下NUMA。&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;就如之前说的，在若干年前，对于x86架构的计算机，那时的内存控制器还没有整合进CPU，所有内存的访问都需要通过北桥芯片来完成。此时的内存访问如下图所示，被称为UMA（  &lt;em&gt;uniform memory access, 一致性内存访问&lt;/em&gt;  &lt;strong&gt; &lt;/strong&gt;）。这样的访问对于软件层面来说非常容易实现：总线模型保证了所有的内存访问是一致的，不必考虑由不同内存地址之前的差异。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="228" src="http://www.litrin.net/wp-content/uploads/2017/10/39352-figure-1.jpg" width="500"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;之后的x86平台经历了一场从“拼频率”到“拼核心数”的转变，越来越多的核心被尽可能地塞进了同一块芯片上，各个核心对于内存带宽的争抢访问成为了瓶颈；此时软件、OS方面对于SMP多核心CPU的支持也愈发成熟；再加上各种商业上的考量，x86平台也顺水推舟的搞了NUMA（Non-  &lt;em&gt;uniform memory access, 非一致性内存访问&lt;/em&gt;）。&lt;/p&gt;
 &lt;p&gt;在这种架构之下，每个Socket都会有一个独立的内存控制器IMC（  &lt;em&gt;integrated memory controllers, 集成内存控制器&lt;/em&gt;），分属于不同的socket之内的IMC之间通过QPI link通讯。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="167" src="http://www.litrin.net/wp-content/uploads/2017/10/39353-figure-2.jpg" width="500"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;然后就是进一步的架构演进，由于每个socket上都会有多个core进行内存访问，这就会在每个core的内部出现一个类似最早SMP架构相似的内存访问总线，这个总线被称为IMC bus。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="166" src="http://www.litrin.net/wp-content/uploads/2017/10/39354-figure-3.jpg" width="500"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;于是，很明显的，在这种架构之下，两个socket各自管理1/2的内存插槽，如果要访问不属于本socket的内存则必须通过QPI link。也就是说内存的访问出现了本地/远程（local/remote）的概念，内存的延时是会有显著的区别的。这也就是  &lt;a href="http://www.litrin.net/2017/08/03/numa%e5%af%b9%e6%80%a7%e8%83%bd%e7%9a%84%e5%bd%b1%e5%93%8d/"&gt;之前那篇文章&lt;/a&gt;中提到的为什么NUMA的设置能够明显的影响到JVM的性能。&lt;/p&gt;
 &lt;p&gt;回到当前世面上的CPU，工程上的实现其实更加复杂了。以  &lt;a href="https://ark.intel.com/products/96899/Intel-Xeon-Processor-E5-2699A-v4-55M-Cache-2_40-GHz"&gt;Xeon 2699 v4系列CPU的标准&lt;/a&gt;来看，两个Socket之之间通过各自的一条9.6GT/s的QPI link互访。而每个Socket事实上有2个内存控制器。双通道的缘故，每个控制器又有两个内存通道（channel），每个通道最多支持3根内存条（DIMM）。理论上最大单socket支持76.8GB/s的内存带宽，而两个QPI link，每个QPI link有9.6GT/s的速率（~57.6GB/s）事实上QPI link已经出现瓶颈了。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="188" src="http://www.litrin.net/wp-content/uploads/2017/10/NUMA.png" width="930"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;嗯，事情变得好玩起来了。&lt;/p&gt;
 &lt;p&gt;核心数还是源源不断的增加，Skylake桌面版本的  &lt;a href="https://ark.intel.com/products/126699/Intel-Core-i9-7980XE-Extreme-Edition-Processor-24_75M-Cache-up-to-4_20-GHz"&gt;i7 EE&lt;/a&gt;已经有了18个core，下一代的Skylake Xeon妥妥的超越22个Core。为了塞进更多的core，原本核心之间类似环网的设计变成了复杂的路由。由于这种架构上的变化，导致内存的访问变得更加复杂。两个IMC也有了local/remote的区别，在保证兼容性的前提和性能导向的纠结中，系统允许用户进行更为灵活的内存访问架构划分。于是就有了“NUMA之上的NUMA”这种妖异的设定（SNC）。&lt;/p&gt;
 &lt;p&gt;回到Linux，内核  &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/mm?h=v4.13.10"&gt;mm&lt;/a&gt;/  &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/mm/mmzone.c?h=v4.13.10"&gt;mmzone.c&lt;/a&gt; ,   &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/include?h=v4.13.10"&gt;include&lt;/a&gt;/  &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/include/linux?h=v4.13.10"&gt;linux&lt;/a&gt;/  &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/include/linux/mmzone.h?h=v4.13.10"&gt;mmzone.h&lt;/a&gt;文件定义了NUMA的数据结构和操作方式。&lt;/p&gt;
 &lt;p&gt;Linux Kernel中NUMA的调度位于  &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/kernel?h=v4.13.10"&gt;kernel&lt;/a&gt;/  &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/kernel/sched?h=v4.13.10"&gt;sched&lt;/a&gt;/  &lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/kernel/sched/core.c?h=v4.13.10"&gt;core.c&lt;/a&gt;函数int sysctl_numa_balancing&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;在一个启用了NUMA支持的Linux中，Kernel不会将任务内存从一个NUMA node搬迁到另一个NUMA node。&lt;/li&gt;
  &lt;li&gt;一个进程一旦被启用，它所在的NUMA node就不会被迁移，为了尽可能的优化性能，在正常的调度之中，CPU的core也会尽可能的使用可以local访问的本地core，在进程的整个生命周期之中，NUMA node保持不变。&lt;/li&gt;
  &lt;li&gt;一旦当某个NUMA node的负载超出了另一个node一个阈值（默认25%），则认为需要在此node上减少负载，不同的NUMA结构和不同的负载状况，系统见给予一个延时任务的迁移——类似于漏杯算法。在这种情况下将会产生内存的remote访问。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;通常情况下，用户可以通过numactl来进行NUMA访问策略的手工配置，cgroup中cpuset.mems也可以达到指定NUMA node的作用。以numactl命令为例，它有如下策略：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;–interleave=nodes //允许进程在多个node之间交替访问&lt;/li&gt;
  &lt;li&gt;–membind=nodes //将内存固定在某个node上，CPU则选择对应的core。&lt;/li&gt;
  &lt;li&gt;–cpunodebind=nodes //与membind相反，将CPU固定在某（几）个core上，内存则限制在对应的NUMA node之上。&lt;/li&gt;
  &lt;li&gt;–physcpubind=cpus //与cpunodebind类似，不同的是物理core。&lt;/li&gt;
  &lt;li&gt;–localalloc //本地配置&lt;/li&gt;
  &lt;li&gt;–preferred=node //按照推荐配置&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;对于某些大内存访问的应用，比如Mongodb，将NUMA的访问策略制定为interleave=all则意味着整个进程的内存是均匀分布在所有的node之上，进程可以以最快的方式访问本地内存。&lt;/p&gt;
 &lt;p&gt;最后一句：  &lt;strong&gt;那种一个业务就能跑满整台server的时代是再也回不来了！&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux 硬件相关 服务器 系统架构</category>
      <guid isPermaLink="true">https://itindex.net/detail/57606-numa</guid>
      <pubDate>Tue, 31 Oct 2017 12:19:18 CST</pubDate>
    </item>
    <item>
      <title>linux nohup.out文件过大解决方法</title>
      <link>https://itindex.net/detail/57405-linux-nohup-out</link>
      <description>&lt;p&gt;先说一下  &lt;a href="http://lib.csdn.net/base/linux" rel="nofollow" target="_blank"&gt;Linux&lt;/a&gt;重定向：&lt;/p&gt; 
 &lt;p&gt;0、1和2分别表示标准输入、标准输出和标准错误信息输出，可以用来指定需要重定向的标准输入或输出。  &lt;br /&gt; 在一般使用时，默认的是标准输出，既1.当我们需要特殊用途时，可以使用其他标号。例如，将某个程序的错误信息输出到log文件中：./program 2&amp;gt;log。这样标准输出还是在屏幕上，但是错误信息会输出到log文件中。  &lt;br /&gt; 另外，也可以实现0，1，2之间的重定向。2&amp;gt;&amp;amp;1：将错误信息重定向到标准输出。  &lt;br /&gt; Linux下还有一个特殊的文件/dev/null，它就像一个无底洞，所有重定向到它的信息都会消失得无影无踪。这一点非常有用，当我们不需要回显程序的所有信息时，就可以将输出重定向到/dev/null。&lt;/p&gt; 
 &lt;p&gt;如果想要正常输出和错误信息都不显示，则要把标准输出和标准错误都重定向到/dev/null， 例如：&lt;/p&gt; 
 &lt;p&gt;# ls 1&amp;gt;/dev/null 2&amp;gt;/dev/null&lt;/p&gt; 
 &lt;p&gt;还有一种做法是将错误重定向到标准输出，然后再重定向到 /dev/null，例如：&lt;/p&gt; 
 &lt;p&gt;# ls &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;/p&gt; 
 &lt;p&gt;注意：此处的顺序不能更改，否则达不到想要的效果，此时先将标准输出重定向到 /dev/null，然后将标准错误重定向到标准输出，由于标准输出已经重定向到了/dev/null，因此标准错误也会重定向到/dev/null，于是一切静悄悄:-)&lt;/p&gt; 
 &lt;p&gt; &lt;/p&gt; 
 &lt;p&gt;由于使用nohup时，会自动将输出写入nohup.out文件中，如果文件很大的话，nohup.out就会不停的增大，这是我们不希望看到的，因此，可以利用/dev/null来解决这个问题。&lt;/p&gt; 
 &lt;p&gt;nohup ./program &amp;gt;/dev/null 2&amp;gt;log &amp;amp;&lt;/p&gt; 
 &lt;p&gt;如果错误信息也不想要的话：&lt;/p&gt; 
 &lt;p&gt;nohup ./program &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Linux命令相关</category>
      <guid isPermaLink="true">https://itindex.net/detail/57405-linux-nohup-out</guid>
      <pubDate>Wed, 30 Aug 2017 09:59:18 CST</pubDate>
    </item>
    <item>
      <title>Linux下正确删除海量文件的姿势</title>
      <link>https://itindex.net/detail/56689-linux-%E6%AD%A3%E7%A1%AE-%E5%88%A0%E9%99%A4</link>
      <description>&lt;p&gt;这里说的“海量”并不是指体积大，而是指数量，比如一个目录下有数百万个小文件。&lt;/p&gt;
 &lt;p&gt;最近在优化服务器时发现postfix下的maildrop目录和clientmqueue目录下发现有大量的文件，进入这些目录里使用ls命令是愚蠢的做法，而直接执行  &lt;code&gt;rm *&lt;/code&gt;，没有任何反应，文件数量也没有减少，也就是说，在海量文件目录里直接使用rm命令进行删除是无效的。&lt;/p&gt;
 &lt;p&gt;那么正确的方法是什么呢？有两种方法可选：  &lt;br /&gt;
第一种：&lt;/p&gt;
 &lt;pre&gt;find /path/to/directory -type f -exec rm {} \;&lt;/pre&gt;
 &lt;p&gt;第二种：&lt;/p&gt;
 &lt;pre&gt;ls -1 /path/to/directory | xargs -I{} rm {}&lt;/pre&gt;
 &lt;p&gt;上面这两种方法可以成功的删除海量文件，速度也很快。但还有一种更好的方法，比如要删除上面提到的clientmqueue目录，里面全部是一个一个的邮件，用下面的方法：&lt;/p&gt;
 &lt;pre&gt;service sendmail stop
cd /var/spool
mv clientmqueue clientmqueue-todelete
mkdir clientmqueue
chown --reference=clientmqueue-todelete clientmqueue
chmod --reference=clientmqueue-todelete clientmqueue
service sendmail start
rm -rf clientmqueue-todelete&lt;/pre&gt;
 &lt;p&gt;上面的方法是将目录重命名，然后使用了   &lt;code&gt;--reference&lt;/code&gt; 引用参数来重建目录，然后删除重命名的目录。直接删除目录的方法速度是十分的快。也可以留着备份不删。更安全。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>技术技巧 linux 删文件</category>
      <guid isPermaLink="true">https://itindex.net/detail/56689-linux-%E6%AD%A3%E7%A1%AE-%E5%88%A0%E9%99%A4</guid>
      <pubDate>Thu, 16 Feb 2017 18:16:37 CST</pubDate>
    </item>
    <item>
      <title>如何判断自己的VPS是那种虚拟技术实现的？目前主流基本是Kvm</title>
      <link>https://itindex.net/detail/55251-vps-%E8%99%9A%E6%8B%9F%E6%8A%80%E6%9C%AF-%E7%9B%AE%E5%89%8D</link>
      <description>&lt;p&gt;  &lt;a href="http://defcon.cn/wp-content/uploads/2016/02/kvm.png" rel="example_group"&gt;   &lt;img alt="" height="93" src="http://defcon.cn/wp-content/uploads/2016/02/kvm.png" width="300"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;我们知道VPS的虚拟技术有许多种，如Openvz、Xen、VMware vSphere、Hyper-V、KVM及Xen的HVM与PV等。在Xen中pv是半虚拟化，hvm是全虚拟化，pv只能用于linux内核的系统，hvm可以虚拟所有常见操作系统(Linux+windows)，理论效率比pv略低，另外hvm需要cpu虚拟化指令支持，pv无此要求。而Openvz是一个类似于Linux-VServer的操作系级全虚拟化解决方案，目前基于Xen和Openvz的VPS服务商比较多。&lt;/p&gt;
 &lt;p&gt;那么如何判断买到的是哪种虚拟技术的VPS呢？价格上，Openvz一般比Xen便宜得多，但稳定性和用途范围就不及Xen和Kvm了。&lt;/p&gt;
 &lt;h3&gt;1、通过系统目录判断&lt;/h3&gt;
 &lt;p&gt;执行命令：ls -al /proc&lt;/p&gt;
 &lt;p&gt;一般Openvz的话，则会有vz目录，Xen的话则会有xen目录。&lt;/p&gt;
 &lt;h3&gt;2、通过网卡信息判断&lt;/h3&gt;
 &lt;p&gt;执行命令：ifconfig&lt;/p&gt;
 &lt;p&gt;一般Openvz的话，则会有venet0或venet0:x网卡标识，Xen的话一般则是eth0。&lt;/p&gt;
 &lt;h3&gt;3、通过VPS控制面板判断&lt;/h3&gt;
 &lt;p&gt;流行的VPS面板包括SolusVM、vePortal等，会显示具体的虚拟技术。&lt;/p&gt;
 &lt;h3&gt;4、通过virt-what命令判断&lt;/h3&gt;
 &lt;p&gt;CentOS或RedHat系统的话，执行命令：yum install -y virt-what&lt;/p&gt;
 &lt;p&gt;ubuntu（debian系）：sudo apt-get install virt-what&lt;/p&gt;
 &lt;p&gt;virt-what是一个判断当前环境所使用的虚拟技术的脚本，常见的虚拟技术基本上都能正常识别出来。&lt;/p&gt;
 &lt;p&gt;安装好virt-what后，执行命令：sudo virt-what&lt;/p&gt;
 &lt;p&gt;根据返回的信息，即可判断出当前VPS所使用的虚拟技术。&lt;/p&gt;
 &lt;p&gt;腾讯云、UCLOUD云、青云都是基于KVM的，阿里后面的也转成KVM架构了，Linode也转成KVM了（注明：非原创，转载于互联网，有删减）&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>渗透测试 KVM Linux WordPress</category>
      <guid isPermaLink="true">https://itindex.net/detail/55251-vps-%E8%99%9A%E6%8B%9F%E6%8A%80%E6%9C%AF-%E7%9B%AE%E5%89%8D</guid>
      <pubDate>Tue, 23 Feb 2016 11:05:28 CST</pubDate>
    </item>
    <item>
      <title>Linux TCP Flaw 安全性問題的暫時解法</title>
      <link>https://itindex.net/detail/55900-linux-tcp-flaw</link>
      <description>&lt;p&gt;Linux TCP 實作   &lt;a href="https://tools.ietf.org/html/rfc5961" target="_blank"&gt;RFC 5961&lt;/a&gt;，但是 RFC 5961 本身設計會導致有安全性問題，而這個影響範圍很廣泛，使用 TCP 都會受到影響，ex: HTTP、FTP、SSH、Telnet、DNS、SMTP ... 等。&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;h2&gt;Linux TCP Flaw 安全性問題的暫時解法&lt;/h2&gt;
 &lt;p&gt;此 TCP 漏洞會造成的問題可見下述影片&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;說明：   &lt;a href="http://www.cs.ucr.edu/~zhiyunq/pub/sec16_TCP_pure_offpath.pdf" target="_blank"&gt;Off-Path TCP Exploits: Global Rate Limit Considered Dangerous&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;下述整理自此篇新聞：  &lt;a href="http://thehackernews.com/2016/08/linux-tcp-packet-hacking.html" target="_blank"&gt;Linux TCP Flaw allows Hackers to Hijack Internet Traffic and Inject Malware Remotely&lt;/a&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;此 TCP Flaw 的問題，發生的環境：Kernel &amp;gt;= 3.6 and Kernel &amp;lt; 4.7&lt;/li&gt;
  &lt;li&gt;註：此篇討論    &lt;a href="https://forum.manjaro.org/t/linux-tcp-flaw/7262/3" target="_blank"&gt;Linux tcp flaw? - General Discussion - Manjaro&lt;/a&gt; 說到 Kernel 4.7 後，此問題就解決了。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;TCP Flaw Kernel 剛好符合這個條件的臨時解法&lt;/h3&gt;
 &lt;ol&gt;
  &lt;li&gt;vim /etc/sysctl.conf # 於檔案最下方加入下述：   &lt;br /&gt;
net.ipv4.tcp   &lt;em&gt;challenge&lt;/em&gt;ack_limit = 999999999&lt;/li&gt;
  &lt;li&gt;sysctl -p # 使用 root 執行&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;此問題為何只有 Linux 會發生，而 Windows、OS X 和 FreeBSD 都沒有此問題？&lt;/p&gt;
 &lt;p&gt;此篇新聞的作者認為：因為他們沒有完整實作 RFC 5961... XD&lt;/p&gt;
 &lt;h4&gt;相關網頁&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="http://www.zdnet.com/article/linux-tcp-flaw-lets-anyone-hijack-internet-traffic/" target="_blank"&gt;Linux TCP flaw lets &amp;apos;anyone&amp;apos; hijack Internet traffic&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.theregister.co.uk/2016/08/10/linux_tor_users_open_corrupted_communications/" target="_blank"&gt;Linux security backfires: Flaw lets hackers inject malware into downloads, disrupt Tor users, etc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://blogs.akamai.com/2016/08/vulnerability-in-the-linux-kernels-tcp-stack-implementation.html" target="_blank"&gt;Vulnerability in the Linux kernel&amp;apos;s tcp stack implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;The post   &lt;a href="http://blog.longwin.com.tw/2016/08/linux-tcp-flaw-%e5%ae%89%e5%85%a8%e6%80%a7%e5%95%8f%e9%a1%8c%e7%9a%84%e6%9a%ab%e6%99%82%e8%a7%a3%e6%b3%95/" rel="nofollow"&gt;Linux TCP Flaw 安全性問題的暫時解法&lt;/a&gt; appeared first on   &lt;a href="http://blog.longwin.com.tw" rel="nofollow"&gt;Tsung&amp;apos;s Blog&lt;/a&gt;.&lt;/p&gt;
 &lt;img alt="" height="1" src="http://feeds.feedburner.com/~r/tsungblog/~4/oeqoVeOLHOI" width="1"&gt;&lt;/img&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>News crack flaw hack linux</category>
      <guid isPermaLink="true">https://itindex.net/detail/55900-linux-tcp-flaw</guid>
      <pubDate>Tue, 16 Aug 2016 08:13:49 CST</pubDate>
    </item>
    <item>
      <title>缓存更新的套路</title>
      <link>https://itindex.net/detail/55810-%E7%BC%93%E5%AD%98-%E6%9B%B4%E6%96%B0-%E5%A5%97%E8%B7%AF</link>
      <description>&lt;p&gt;  &lt;img alt="cache" height="158" src="http://coolshell.cn//wp-content/uploads/2016/07/cache-300x158.png" width="300"&gt;&lt;/img&gt;看到好些人在写更新缓存数据代码时，  &lt;strong&gt;先删除缓存，然后再更新数据库&lt;/strong&gt;，而后续的操作会把数据再装载的缓存中。  &lt;strong&gt;然而，这个是逻辑是错误的&lt;/strong&gt;。试想，两个并发操作，一个是更新操作，另一个是查询操作，更新操作删除缓存后，查询操作没有命中缓存，先把老数据读出来后放到缓存中，然后更新操作更新了数据库。于是，在缓存中的数据还是老的数据，导致缓存中的数据是脏的，而且还一直这样脏下去了。&lt;/p&gt;
 &lt;p&gt;我不知道为什么这么多人用的都是这个逻辑，当我在微博上发了这个贴以后，我发现好些人给了好多非常复杂和诡异的方案，所以，我想写这篇文章说一下几个缓存更新的Design Pattern（让我们多一些套路吧）。&lt;/p&gt;
 &lt;p&gt;这里，我们先不讨论更新缓存和更新数据这两个事是一个事务的事，或是会有失败的可能，我们先假设更新数据库和更新缓存都可以成功的情况（我们先把成功的代码逻辑先写对）。&lt;/p&gt;
 &lt;p&gt;更新缓存的的Design Pattern有四种：Cache aside, Read through, Write through, Write behind caching，我们下面一一来看一下这四种Pattern。&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;h4&gt;Cache Aside Pattern&lt;/h4&gt;
 &lt;p&gt;这是最常用最常用的pattern了。其具体逻辑如下：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;失效&lt;/strong&gt;：应用程序先从cache取数据，没有得到，则从数据库中取数据，成功后，放到缓存中。&lt;/li&gt;
&lt;/ul&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;命中&lt;/strong&gt;：应用程序从cache中取数据，取到后返回。&lt;/li&gt;
&lt;/ul&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;更新&lt;/strong&gt;：先把数据存到数据库中，成功后，再更新缓存。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;a href="http://coolshell.cn//wp-content/uploads/2016/07/cacheaside.png"&gt;   &lt;img alt="cacheaside" height="431" src="http://coolshell.cn//wp-content/uploads/2016/07/cacheaside.png" width="694"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;（  &lt;a href="https://vladmihalcea.com/2015/04/20/a-beginners-guide-to-cache-synchronization-strategies/" target="_blank"&gt;图片来源&lt;/a&gt;）&lt;/p&gt;
 &lt;p&gt;注意，我们的更新是先更新数据库，成功后，直接更新缓存。那么，这种方式是否可以没有文章前面提到过的那个问题呢？我们可以脑补一下。&lt;/p&gt;
 &lt;p&gt;一个是查询操作，一个是更新操作的并发，首先，没有了删除cache数据的操作了，而是先更新了数据库中的数据，此时，缓存依然有效，所以，并发的查询操作拿的是没有更新的数据，但是，更新操作马上更新了缓存的数据，后续的查询操作就可以得到被更新的数据了。而不会像文章开头的那个逻辑产生的问题，后结的查询操作一直都在取老的数据。&lt;/p&gt;
 &lt;h4&gt;Read/Write Through Pattern&lt;/h4&gt;
 &lt;p&gt;我们可以看到，在上面的Cache Aside套路中，我们的应用代码需要维护两个数据存储，一个是缓存（Cache），一个是数据库（Repository）。所以，应用程序比较啰嗦。而Read/Write Through套路是把更新数据库（Repository）的操作由缓存自己代理了，所以，对于应用层来说，就简单很多了。  &lt;strong&gt;可以理解为，应用认为后端就是一个单一的存储，而存储自己维护自己的Cache。&lt;/strong&gt;&lt;/p&gt;
 &lt;h5&gt;Read Through&lt;/h5&gt;
 &lt;p&gt;Read Through 套路就是在查询操作中更新缓存，也就是说，当缓存失效的时候（过期或LRU换出），Cache Aside是由调用方负责把数据加载入缓存，而Read Through则用缓存服务自己来加载，从而对应用方是透明的。&lt;/p&gt;
 &lt;h5&gt;Write Through&lt;/h5&gt;
 &lt;p&gt;Write Through 套路和Read Through相仿，不过是在更新数据时发生。当有数据更新的时候，如果没有命中缓存，直接更新数据库，然后返回。如果命中了缓存，则更新缓存，然后再由Cache自己更新数据库（这是一个同步操作）&lt;/p&gt;
 &lt;p&gt;下图自来Wikipedia的  &lt;a href="https://en.wikipedia.org/wiki/Cache_(computing)"&gt;Cache词条&lt;/a&gt;。其中的Memory你可以理解为就是我们例子里的数据库。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="Write-through_with_no-write-allocation" height="620" src="http://coolshell.cn//wp-content/uploads/2016/07/460px-Write-through_with_no-write-allocation.svg_.png" width="460"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;Write Behind Caching Pattern&lt;/h4&gt;
 &lt;p&gt;Write Behind 又叫 Write Back。  &lt;strong&gt;一些了解Linux操作系统内核的同学对write back应该非常熟悉，这不就是Linux文件系统的Page Cache的算法吗？是的，你看基础这玩意全都是相通的。&lt;/strong&gt;所以，基础很重要，我已经不是一次说过基础很重要这事了。&lt;/p&gt;
 &lt;p&gt;Write Back套路，一句说就是，在更新数据的时候，只更新缓存，不更新数据库，而我们的缓存会异步地批量更新数据库。这个设计的好处就是让数据的I/O操作飞快无比（因为直接操作内存嘛 ），因为异步，write backg还可以合并对同一个数据的多次操作，所以性能的提高是相当可观的。&lt;/p&gt;
 &lt;p&gt;但是，其带来的问题是，数据不是强一致性的，而且可能会丢失（我们知道Unix/Linux非正常关机会导致数据丢失，就是因为这个事）。在软件设计上，我们基本上不可能做出一个没有缺陷的设计，就像算法设计中的时间换空间，空间换时间一个道理，有时候，强一致性和高性能，高可用和高性性是有冲突的。软件设计从来都是取舍Trade-Off。&lt;/p&gt;
 &lt;p&gt;另外，Write Back实现逻辑比较复杂，因为他需要track有哪数据是被更新了的，需要刷到持久层上。操作系统的write back会在仅当这个cache需要失效的时候，才会被真正持久起来，比如，内存不够了，或是进程退出了等情况，这又叫lazy write。&lt;/p&gt;
 &lt;p&gt;在wikipedia上有一张write back的流程图，基本逻辑如下：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="Write-back_with_write-allocation" height="820" src="http://coolshell.cn//wp-content/uploads/2016/07/Write-back_with_write-allocation.png" width="640"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;h4&gt;再多唠叨一些&lt;/h4&gt;
 &lt;p&gt;1）上面讲的这些Design Pattern，其实并不是软件架构里的mysql数据库和memcache/redis的更新策略，这些东西都是计算机体系结构里的设计，比如CPU的缓存，硬盘文件系统中的缓存，硬盘上的缓存，数据库中的缓存。  &lt;strong&gt;基本上来说，这些缓存更新的设计模式都是非常老古董的，而且历经长时间考验的策略&lt;/strong&gt;，所以这也就是，工程学上所谓的Best Practice，遵从就好了。&lt;/p&gt;
 &lt;p&gt;2）有时候，我们觉得能做宏观的系统架构的人一定是很有经验的，其实，宏观系统架构中的很多设计都来源于这些微观的东西。比如，云计算中的很多虚拟化技术的原理，和传统的虚拟内存不是很像么？Unix下的那些I/O模型，也放大到了架构里的同步异步的模型，还有Unix发明的管道不就是数据流式计算架构吗？TCP的好些设计也用在不同系统间的通讯中，仔细看看这些微观层面，你会发现有很多设计都非常精妙……所以，  &lt;strong&gt;请允许我在这里放句观点鲜明的话——如果你要做好架构，首先你得把计算机体系结构以及很多老古董的基础技术吃透了&lt;/strong&gt;。&lt;/p&gt;
 &lt;p&gt;3）在软件开发或设计中，我非常建议在之前先去参考一下已有的设计和思路，  &lt;strong&gt;看看相应的guideline，best practice或design pattern，吃透了已有的这些东西，再决定是否要重新发明轮子&lt;/strong&gt;。千万不要似是而非地，想当然的做软件设计。&lt;/p&gt;
 &lt;p&gt;4）上面，我们没有考虑缓存（Cache）和持久层（Repository）的整体事务的问题。比如，更新Cache成功，更新数据库失败了怎么吗？或是反过来。关于这个事，如果你需要强一致性，你需要使用“两阶段提交协议”——prepare, commit/rollback，比如Java 7 的  &lt;a href="http://docs.oracle.com/javaee/7/api/javax/transaction/xa/XAResource.html" target="_blank"&gt;XAResource&lt;/a&gt;，还有MySQL 5.7的   &lt;a href="http://dev.mysql.com/doc/refman/5.7/en/xa.html" target="_blank"&gt;XA Transaction&lt;/a&gt;，有些cache也支持XA，比如  &lt;a href="http://www.ehcache.org/documentation/3.0/xa.html" target="_blank"&gt;EhCache&lt;/a&gt;。当然，XA这样的强一致性的玩法会导致性能下降，关于分布式的事务的相关话题，你可以看看《  &lt;a href="http://coolshell.cn/articles/10910.html" target="_blank"&gt;分布式系统的事务处理&lt;/a&gt;》一文。&lt;/p&gt;
 &lt;p&gt;（全文完）&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; 
&lt;/p&gt; &lt;p align="center"&gt;  &lt;img src="http://coolshell.cn//wp-content/uploads/2009/04/qrcode_for_gh_dd9d8c843f20_860-300x300.jpg"&gt;&lt;/img&gt;  &lt;br /&gt;关注CoolShell微信公众账号可以在手机端搜索文章&lt;/p&gt;
 &lt;div&gt;
  &lt;p align="center"&gt;   &lt;strong&gt;（转载本站文章请注明作者和出处     &lt;a href="http://coolshell.cn/"&gt;酷 壳 – CoolShell.cn&lt;/a&gt; ，请勿用于任何商业用途）&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;
 &lt;div&gt;——===   &lt;strong&gt;访问    &lt;a href="http://coolshell.cn/404/" target="_blank"&gt;酷壳404页面&lt;/a&gt; 寻找遗失儿童。&lt;/strong&gt; ===——&lt;/div&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;h3&gt;相关文章&lt;/h3&gt;   &lt;ul&gt;    &lt;li&gt;     &lt;small&gt;2013年02月01日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/8961.html"&gt;从面向对象的设计模式看软件设计&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;small&gt;2012年05月03日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/7236.html"&gt;用Unix的设计思想来应对多变的需求&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;small&gt;2012年03月26日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/6950.html"&gt;需求变化与IoC&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;small&gt;2013年07月05日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/9949.html"&gt;IoC/DIP其实是一种管理思想&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;small&gt;2013年07月30日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/10249.html"&gt;7个示例科普CPU Cache&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;small&gt;2009年03月02日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/21.html"&gt;101个设计模式&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;small&gt;2011年05月03日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/4626.html"&gt;读书笔记：对线程模型的批评&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;small&gt;2010年11月26日&lt;/small&gt;      &lt;a href="http://coolshell.cn/articles/3320.html"&gt;JDK里的设计模式&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Unix/Linux 程序设计 cache Design design pattern</category>
      <guid isPermaLink="true">https://itindex.net/detail/55810-%E7%BC%93%E5%AD%98-%E6%9B%B4%E6%96%B0-%E5%A5%97%E8%B7%AF</guid>
      <pubDate>Wed, 27 Jul 2016 16:25:28 CST</pubDate>
    </item>
    <item>
      <title>[译] 如何使用Monit部署服务器监控系统</title>
      <link>https://itindex.net/detail/53571-monit-%E6%9C%8D%E5%8A%A1%E5%99%A8-%E7%9B%91%E6%8E%A7</link>
      <description>&lt;p&gt;很多Linux系统管理员依赖一个集中式的远程监控系统（比如  &lt;a href="http://xmodulo.com/monitor-common-services-nagios.html" rel="nofollow"&gt;Nagios&lt;/a&gt;或者  &lt;a href="http://xmodulo.com/monitor-linux-servers-snmp-cacti.html" rel="nofollow"&gt;Cacti&lt;/a&gt;）来检查他们网络基础设备的健康状况。虽然集中式监控让管理员的生活更简单了，然而处理很多机器和服务时，专用的监控中心显然成为了一个单点故障，如果监控中心挂了或者因为什么原因（比如硬件或者网络故障）不可访问了，你就会失去整个网络基础设备情况的任何信息。&lt;/p&gt;

 &lt;p&gt;一个给你的监控系统增加冗余度的方法是安装独立的监控软件（作为后备），至少在网络中的关键/核心服务器上。这样在集中式监控系统挂掉的情况，你还有能力通过后备的监控方式来获取核心服务器的运行状况。&lt;/p&gt;

 &lt;h3&gt;Monit是什么？&lt;/h3&gt;

 &lt;p&gt;  &lt;a href="http://mmonit.com/monit/" rel="nofollow"&gt;Monit&lt;/a&gt;是一个跨平台的用来监控Unix/linux系统（比如Linux、BSD、OSX、Solaris）的工具。Monit特别易于安装，而且非常轻量级（只有500KB大小），并且不依赖任何第三方程序、插件或者库。然而，Monit可以胜任全面监控、进程状态监控、文件系统变动监控、邮件通知和对核心服务的自定义动作等场景。易于安装、轻量级的实现以及强大的功能，让Monit成为一个理想的后备监控工具。&lt;/p&gt;

 &lt;p&gt;我已经在一些机器使用Monit几年了，而且我对它的可靠性非常满意。甚至作为全面的监控系统，对任何Linux系统管理员来说Monit也是非常有用和强大的。在这篇教程中，我会展示如何在一个本地服务器部署Monit（作为后备监控系统）来监控常见的服务。在部署过程中，我只会展示我们用到的部分。&lt;/p&gt;

 &lt;h3&gt;在Linux安装Monit&lt;/h3&gt;

 &lt;p&gt;Monit已经被包含在多数Linux发行版的软件仓库中了。&lt;/p&gt;

 &lt;p&gt;Debian、Ubuntu或者Linux Mint：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;$ sudo aptitude install monit
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;Fedora或者CentOS/RHEL：&lt;/p&gt;

 &lt;p&gt;在CentOS/RHEL中，你必须首先启用  &lt;a href="https://linux.cn/article-2324-1.html" rel="nofollow"&gt;EPEL&lt;/a&gt;或者  &lt;a href="http://xmodulo.com/how-to-set-up-rpmforge-repoforge-repository-on-centos.html" rel="nofollow"&gt;Repoforge&lt;/a&gt;软件仓库.&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;# yum install monit
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;Monit自带一个文档完善的配置文件，其中包含了很多例子。主配置文件在/etc/monit.conf（Fedora/CentOS/RHEL 中），或者/etc/monit/monitrc（Debian/Ubuntu/Mint 中）。Monit配置文件有两部分：“Global”（全局）和“Services”（服务）。&lt;/p&gt;

 &lt;h3&gt;Global Configuration: Web Status Page （全局配置：Web状态页面）&lt;/h3&gt;

 &lt;p&gt;Monit可以使用邮件服务来发送通知，也可以使用HTTP/HTTPS页面来展示。我们先使用如下配置的web状态页面吧：&lt;/p&gt;

 &lt;ul&gt;
  &lt;li&gt;Monit监听1966端口。&lt;/li&gt;
  &lt;li&gt;对web状态页面的访问是通过SSL加密的。&lt;/li&gt;
  &lt;li&gt;使用monituser/romania作为用户名/口令登录。&lt;/li&gt;
  &lt;li&gt;只允许通过localhost、myhost.mydomain.ro和在局域网内部（192.168.0.0/16）访问。&lt;/li&gt;
  &lt;li&gt;Monit使用pem格式的SSL证书。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;之后的步骤，我会使用一个基于Red Hat的系统。在基于Debian的系统中的步骤也是类似的。&lt;/p&gt;

 &lt;p&gt;首先，在/var/cert生成一个自签名的证书（monit.pem）：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;# mkdir /var/certs
# cd /etc/pki/tls/certs
# ./make-dummy-cert monit.pem
# cp monit.pem /var/certs
# chmod 0400 /var/certs/monit.pem 
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;现在将下列代码片段放到Monit的主配置文件中。你可以创建一个空配置文件，或者基于自带的配置文件修改。&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;set httpd port 1966 and
     SSL ENABLE
     PEMFILE  /var/certs/monit.pem
     allow monituser:romania
     allow localhost
     allow 192.168.0.0/16
     allow myhost.mydomain.ro
&lt;/code&gt;&lt;/pre&gt;

 &lt;h3&gt;Global Configuration: Email Notification （全局配置：邮件通知）&lt;/h3&gt;

 &lt;p&gt;然后，我们来设置Monit的邮件通知。我们至少需要一个可用的  &lt;a href="http://xmodulo.com/mail-server-ubuntu-debian.html" rel="nofollow"&gt;SMTP服务器&lt;/a&gt;来让Monit发送邮件。这样就可以（按照你的实际情况修改）：&lt;/p&gt;

 &lt;ul&gt;
  &lt;li&gt;邮件服务器的机器名：smtp.monit.ro&lt;/li&gt;
  &lt;li&gt;Monit使用的发件人：monit@monit.ro&lt;/li&gt;
  &lt;li&gt;邮件的收件人：guletz@monit.ro&lt;/li&gt;
  &lt;li&gt;邮件服务器使用的SMTP端口：587（默认是25）&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;有了以上信息，邮件通知就可以这样配置：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;set mailserver  smtp.monit.ro port 587
set mail-format {
 from: monit@monit.ro
 subject: $SERVICE $EVENT at $DATE on $HOST
 message: Monit $ACTION $SERVICE $EVENT at $DATE on $HOST : $DESCRIPTION.

       Yours sincerely,
          Monit

  }

set alert guletz@monit.ro
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;就像你看到的，Monit会提供几个内部变量（  &lt;code&gt;$DATE&lt;/code&gt;、  &lt;code&gt;$EVENT&lt;/code&gt;、  &lt;code&gt;$HOST&lt;/code&gt;等），你可以按照你的需求自定义邮件内容。如果你想要从Monit所在机器发送邮件，就需要一个已经安装的与sendmail兼容的程序（如postfix或者ssmtp）。&lt;/p&gt;

 &lt;h3&gt;Global Configuration: Monit Daemon （全局配置：Monit守护进程）&lt;/h3&gt;

 &lt;p&gt;接下来就该配置Monit守护进程了。可以将其设置成这样：&lt;/p&gt;

 &lt;ul&gt;
  &lt;li&gt;在120秒后进行第一次检测。&lt;/li&gt;
  &lt;li&gt;每3分钟检测一次服务。&lt;/li&gt;
  &lt;li&gt;使用syslog来记录日志。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;如下代码段可以满足上述需求。&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;set daemon 120
   with start delay 240
set logfile syslog facility log_daemon
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;我们必须定义“idfile”，Monit守护进程的一个独一无二的ID文件；以及“eventqueue”，当monit的邮件因为SMTP或者网络故障发不出去，邮件会暂存在这里；以及确保/var/monit路径是存在的。然后使用下边的配置就可以了。&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;set idfile /var/monit/id
set eventqueue
     basedir /var/monit
&lt;/code&gt;&lt;/pre&gt;

 &lt;h3&gt;测试全局配置&lt;/h3&gt;

 &lt;p&gt;现在“Global”部分就完成了。Monit配置文件看起来像这样：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;#  Global Section

# status webpage and acl&amp;apos;s
set httpd port 1966 and
     SSL ENABLE
     PEMFILE  /var/certs/monit.pem
     allow monituser:romania
     allow localhost
     allow 192.168.0.0/16
     allow myhost.mydomain.ro

# mail-server
set mailserver  smtp.monit.ro port 587
# email-format
set mail-format {
 from: monit@monit.ro
 subject: $SERVICE $EVENT at $DATE on $HOST
 message: Monit $ACTION $SERVICE $EVENT at $DATE on $HOST : $DESCRIPTION.

       Yours sincerely,
          Monit

  }

set alert guletz@monit.ro

# delay checks
set daemon 120
   with start delay 240
set logfile syslog facility log_daemon

# idfile and mail queue path
set idfile /var/monit/id
 set eventqueue
     basedir /var/monit
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;现在是时候验证我们的工作了，你可以通过运行如下命令来验证存在的配置文件（/etc/monit.conf）：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;# monit -t

Control file syntax OK
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;如果monit提示任何错误，请再检查下配置文件。幸运的是，错误/警告信息是可以帮助你发现问题的，比如：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;monit: Cannot stat the SSL server PEM file &amp;apos;/var/certs/monit.pem&amp;apos; -- No such file or directory
/etc/monit/monitrc:10: Warning: hostname did not resolve &amp;apos;smtp.monit.ro&amp;apos;
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;一旦你确认配置文件没问题了，可以启动monit守护进程，然后等2到3分钟：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;# service monit start
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;如果你使用的是systemd，运行：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;# systemctl start monit
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;现在打开一个浏览器窗口，然后访问  &lt;code&gt;https://&amp;lt;monit_host&amp;gt;:1966&lt;/code&gt;。将  &lt;code&gt;&amp;lt;monit_host&amp;gt;&lt;/code&gt;替换成Monit所在机器的机器名或者IP地址。&lt;/p&gt;

 &lt;p&gt;如果你使用的是自签名的SSL证书，你会在浏览器中看到一个警告信息。继续访问即可。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="" src="https://farm8.staticflickr.com/7596/16737206479_96b9f7dfdb_c.jpg"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;你完成登录后，就会看到这个页面。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="" src="https://farm8.staticflickr.com/7594/16303369973_6019482dea_c.jpg"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;在这个教程的其余部分，我们演示监控一个本地服务器和常见服务的方法。你会在  &lt;a href="http://mmonit.com/wiki/Monit/ConfigurationExamples" rel="nofollow"&gt;官方wiki页面&lt;/a&gt;看到很多有用的例子。其中的多数是可以直接复制粘贴的！&lt;/p&gt;

 &lt;h3&gt;Service Configuration: CPU/Memory Monitoring （服务配置：CPU、内存监控）&lt;/h3&gt;

 &lt;p&gt;我们先来监控本地服务器的CPU、内存占用。复制如下代码段到配置文件中。&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;check system localhost
    if loadavg (1min) &amp;gt; 10 then alert
    if loadavg (5min) &amp;gt; 6 then alert
    if memory usage &amp;gt; 75% then alert
    if cpu usage (user) &amp;gt; 70% then alert
    if cpu usage (system) &amp;gt; 60% then alert
    if cpu usage (wait) &amp;gt; 75% then alert
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;你可以很容易理解上边的配置。最上边的check是指每个监控周期（全局配置里设置的120秒）都对本机进行下面的操作。如果满足了任何条件，monit守护进程就会使用邮件发送一条报警。&lt;/p&gt;

 &lt;p&gt;如果某个监控项不需要每个周期都检查，可以使用如下格式，它会每240秒检查一次平均负载。&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;if loadavg (1min) &amp;gt; 10 for 2 cycles then alert
&lt;/code&gt;&lt;/pre&gt;

 &lt;h3&gt;Service Configuration: SSH Service Monitoring （服务配置：SSH服务监控）&lt;/h3&gt;

 &lt;p&gt;先检查我们的sshd是否安装在/usr/sbin/sshd：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;check file sshd_bin with path /usr/sbin/sshd
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;我们还想检查sshd的启动脚本是否存在：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;check file sshd_init with path /etc/init.d/sshd
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;最后，我们还想检查sshd守护进程是否存活，并且在监听22端口：&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;check process sshd with pidfile /var/run/sshd.pid
   start program  &amp;quot;/etc/init.d/sshd start&amp;quot;
   stop program  &amp;quot;/etc/init.d/sshd stop&amp;quot;
   if failed port 22 protocol ssh then restart
   if 5 restarts within 5 cycles then timeout
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;我们可以这样解释上述配置：我们检查是否存在名为sshd的进程，并且有一个保存其pid的文件存在（/var/run/sshd.pid）。如果任何一个不存在，我们就使用启动脚本重启sshd。我们检查是否有进程在监听22端口，并且使用的是SSH协议。如果没有，我们还是重启sshd。如果在最近的5个监控周期（5x120秒）至少重启5次了，sshd就被认为是不能用的，我们就不再检查了。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="" src="https://farm9.staticflickr.com/8685/16735725998_62c26a24bc_c.jpg"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;h3&gt;Service Configuration: SMTP Service Monitoring （服务配置：SMTP服务监控）&lt;/h3&gt;

 &lt;p&gt;现在我们来设置一个检查远程SMTP服务器（如192.168.111.102）的监控。假定SMTP服务器运行着SMTP、IMAP、SSH服务。&lt;/p&gt;

 &lt;pre&gt;  &lt;code&gt;check host MAIL with address 192.168.111.102
   if failed icmp type echo within 10 cycles then alert
   if failed port 25  protocol smtp then alert
             else if recovered then exec &amp;quot;/scripts/mail-script&amp;quot;
   if failed port 22  protocol ssh  then alert
   if failed port 143 protocol imap then alert
&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;我们检查远程主机是否响应ICMP协议。如果我们在10个周期内没有收到ICMP回应，就发送一条报警。如果监测到25端口上的SMTP协议是异常的，就发送一条报警。如果在一次监测失败后又监测成功了，就运行一个脚本（/scripts/mail-script）。如果检查22端口上的SSH或者143端口上的IMAP协议不正常，同样发送报警。&lt;/p&gt;

 &lt;h3&gt;总结&lt;/h3&gt;

 &lt;p&gt;在这个教程，我演示了如何在本地服务器设置Monit，当然这只是Monit功能的冰山一角。你可以花些时间阅读Monit的man手册（写得很好）。Monit可以为任何Linux系统管理员做很多事情，并且具有非常优美和易于理解的语法。如果你将一个集中式的远程监控系统和Monit一同使用，你会得到一个更可靠的监控系统。你感觉Monit怎么样？&lt;/p&gt;

 &lt;hr&gt;&lt;/hr&gt;
 &lt;p&gt;via:   &lt;a href="http://xmodulo.com/server-monitoring-system-monit.html" rel="nofollow"&gt;http://xmodulo.com/server-monitoring-system-monit.html&lt;/a&gt;&lt;/p&gt;

 &lt;p&gt;作者：  &lt;a href="http://xmodulo.com/author/iulian" rel="nofollow"&gt;Iulian Murgulet&lt;/a&gt;  &lt;br /&gt;
译者：  &lt;a href="https://github.com/goreliu" rel="nofollow"&gt;goreliu&lt;/a&gt;  &lt;br /&gt;
校对：  &lt;a href="https://github.com/wxy" rel="nofollow"&gt;wxy&lt;/a&gt;&lt;/p&gt;

 &lt;p&gt;本文由   &lt;a href="https://github.com/LCTT/TranslateProject" rel="nofollow"&gt;LCTT&lt;/a&gt; 原创翻译，  &lt;a href="http://linux.cn/" rel="nofollow"&gt;Linux中国&lt;/a&gt; 荣誉推出&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>linux linux运维 监控 主机监控</category>
      <guid isPermaLink="true">https://itindex.net/detail/53571-monit-%E6%9C%8D%E5%8A%A1%E5%99%A8-%E7%9B%91%E6%8E%A7</guid>
      <pubDate>Mon, 01 Jun 2015 18:40:25 CST</pubDate>
    </item>
  </channel>
</rss>

