mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
translated
This commit is contained in:
parent
cbddc5f66e
commit
cfb12376be
@ -1,407 +0,0 @@
|
||||
translating---geekpi
|
||||
|
||||
Part 4 - LXD 2.0: Resource control
|
||||
======================================
|
||||
|
||||
This is the fourth blog post [in this series about LXD 2.0][0].
|
||||
|
||||
As there are a lot of commands involved with managing LXD containers, this post is rather long. If you’d instead prefer a quick step-by-step tour of those same commands, you can [try our online demo instead][1]!
|
||||
|
||||
![](https://linuxcontainers.org/static/img/containers.png)
|
||||
|
||||
### Available resource limits
|
||||
|
||||
LXD offers a variety of resource limits. Some of those are tied to the container itself, like memory quotas, CPU limits and I/O priorities. Some are tied to a particular device instead, like I/O bandwidth or disk usage limits.
|
||||
|
||||
As with all LXD configuration, resource limits can be dynamically changed while the container is running. Some may fail to apply, for example if setting a memory value smaller than the current memory usage, but LXD will try anyway and report back on failure.
|
||||
|
||||
All limits can also be inherited through profiles in which case each affected container will be constrained by that limit. That is, if you set limits.memory=256MB in the default profile, every container using the default profile (typically all of them) will have a memory limit of 256MB.
|
||||
|
||||
We don’t support resource limits pooling where a limit would be shared by a group of containers, there is simply no good way to implement something like that with the existing kernel APIs.
|
||||
|
||||
#### Disk
|
||||
|
||||
This is perhaps the most requested and obvious one. Simply setting a size limit on the container’s filesystem and have it enforced against the container.
|
||||
|
||||
And that’s exactly what LXD lets you do!
|
||||
Unfortunately this is far more complicated than it sounds. Linux doesn’t have path-based quotas, instead most filesystems only have user and group quotas which are of little use to containers.
|
||||
|
||||
This means that right now LXD only supports disk limits if you’re using the ZFS or btrfs storage backend. It may be possible to implement this feature for LVM too but this depends on the filesystem being used with it and gets tricky when combined with live updates as not all filesystems allow online growth and pretty much none of them allow online shrink.
|
||||
|
||||
#### CPU
|
||||
|
||||
When it comes to CPU limits, we support 4 different things:
|
||||
|
||||
* Just give me X CPUs
|
||||
|
||||
In this mode, you let LXD pick a bunch of cores for you and then load-balance things as more containers and CPUs go online/offline.
|
||||
|
||||
The container only sees that number of CPU.
|
||||
* Give me a specific set of CPUs (say, core 1, 3 and 5)
|
||||
|
||||
Similar to the first mode except that no load-balancing is happening, you’re stuck with those cores no matter how busy they may be.
|
||||
* Give me 20% of whatever you have
|
||||
|
||||
In this mode, you get to see all the CPUs but the scheduler will restrict you to 20% of the CPU time but only when under load! So if the system isn’t busy, your container can have as much fun as it wants. When containers next to it start using the CPU, then it gets capped.
|
||||
* Out of every measured 200ms, give me 50ms (and no more than that)
|
||||
|
||||
This mode is similar to the previous one in that you get to see all the CPUs but this time, you can only use as much CPU time as you set in the limit, no matter how idle the system may be. On a system without over-commit this lets you slice your CPU very neatly and guarantees constant performance to those containers.
|
||||
|
||||
It’s also possible to combine one of the first two with one of the last two, that is, request a set of CPUs and then further restrict how much CPU time you get on those.
|
||||
|
||||
On top of that, we also have a generic priority knob which is used to tell the scheduler who wins when you’re under load and two containers are fighting for the same resource.
|
||||
|
||||
#### Memory
|
||||
|
||||
Memory sounds pretty simple, just give me X MB of RAM!
|
||||
|
||||
And it absolutely can be that simple. We support that kind of limits as well as percentage based requests, just give me 10% of whatever the host has!
|
||||
|
||||
Then we support some extra stuff on top. For example, you can choose to turn swap on and off on a per-container basis and if it’s on, set a priority so you can choose what container will have their memory swapped out to disk first!
|
||||
|
||||
Oh and memory limits are “hard” by default. That is, when you run out of memory, the kernel out of memory killer will start having some fun with your processes.
|
||||
|
||||
Alternatively you can set the enforcement policy to “soft”, in which case you’ll be allowed to use as much memory as you want so long as nothing else is. As soon as something else wants that memory, you won’t be able to allocate anything until you’re back under your limit or until the host has memory to spare again.
|
||||
|
||||
#### Network I/O
|
||||
|
||||
Network I/O is probably our simplest looking limit, trust me, the implementation really isn’t simple though!
|
||||
|
||||
We support two things. The first is a basic bit/s limits on network interfaces. You can set a limit of ingress and egress or just set the “max” limit which then applies to both. This is only supported for “bridged” and “p2p” type interfaces.
|
||||
|
||||
The second thing is a global network I/O priority which only applies when the network interface you’re trying to talk through is saturated.
|
||||
|
||||
#### Block I/O
|
||||
|
||||
I kept the weirdest for last. It may look straightforward and feel like that to the user but there are a bunch of cases where it won’t exactly do what you think it should.
|
||||
|
||||
What we support here is basically identical to what I described in Network I/O.
|
||||
|
||||
You can set IOps or byte/s read and write limits directly on a disk device entry and there is a global block I/O priority which tells the I/O scheduler who to prefer.
|
||||
|
||||
The weirdness comes from how and where those limits are applied. Unfortunately the underlying feature we use to implement those uses full block devices. That means we can’t set per-partition I/O limits let alone per-path.
|
||||
|
||||
It also means that when using ZFS or btrfs which can use multiple block devices to back a given path (with or without RAID), we effectively don’t know what block device is providing a given path.
|
||||
|
||||
This means that it’s entirely possible, in fact likely, that a container may have multiple disk entries (bind-mounts or straight mounts) which are coming from the same underlying disk.
|
||||
|
||||
And that’s where things get weird. To make things work, LXD has logic to guess what block devices back a given path, this does include interrogating the ZFS and btrfs tools and even figures things out recursively when it finds a loop mounted file backing a filesystem.
|
||||
|
||||
That logic while not perfect, usually yields a set of block devices that should have a limit applied. LXD then records that and moves on to the next path. When it’s done looking at all the paths, it gets to the very weird part. It averages the limits you’ve set for every affected block devices and then applies those.
|
||||
|
||||
That means that “in average” you’ll be getting the right speed in the container, but it also means that you can’t have a “/fast” and a “/slow” directory both coming from the same physical disk and with differing speed limits. LXD will let you set it up but in the end, they’ll both give you the average of the two values.
|
||||
|
||||
### How does it all work?
|
||||
|
||||
Most of the limits described above are applied through the Linux kernel Cgroups API. That’s with the exception of the network limits which are applied through good old “tc”.
|
||||
|
||||
LXD at startup time detects what cgroups are enabled in your kernel and will only apply the limits which your kernel support. Should you be missing some cgroups, a warning will also be printed by the daemon which will then get logged by your init system.
|
||||
|
||||
On Ubuntu 16.04, everything is enabled by default with the exception of swap memory accounting which requires you pass the “swapaccount=1” kernel boot parameter.
|
||||
|
||||
### Applying some limits
|
||||
|
||||
All the limits described above are applied directly to the container or to one of its profiles. Container-wide limits are applied with:
|
||||
|
||||
```
|
||||
lxc config set CONTAINER KEY VALUE
|
||||
```
|
||||
|
||||
or for a profile:
|
||||
|
||||
```
|
||||
lxc profile set PROFILE KEY VALUE
|
||||
```
|
||||
|
||||
while device-specific ones are applied with:
|
||||
|
||||
```
|
||||
lxc config device set CONTAINER DEVICE KEY VALUE
|
||||
```
|
||||
|
||||
or for a profile:
|
||||
|
||||
```
|
||||
lxc profile device set PROFILE DEVICE KEY VALUE
|
||||
```
|
||||
|
||||
The complete list of valid configuration keys, device types and device keys can be [found here][1].
|
||||
|
||||
#### CPU
|
||||
|
||||
To just limit a container to any 2 CPUs, do:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu 2
|
||||
```
|
||||
|
||||
To pin to specific CPU cores, say the second and fourth:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu 1,3
|
||||
```
|
||||
|
||||
More complex pinning ranges like this works too:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu 0-3,7-11
|
||||
```
|
||||
|
||||
The limits are applied live, as can be seen in this example:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec zerotier -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
processor : 3
|
||||
stgraber@dakara:~$ lxc config set zerotier limits.cpu 2
|
||||
stgraber@dakara:~$ lxc exec zerotier -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
```
|
||||
|
||||
Note that to avoid utterly confusing userspace, lxcfs arranges the /proc/cpuinfo entries so that there are no gaps.
|
||||
|
||||
As with just about everything in LXD, those settings can also be applied in profiles:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec snappy -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
processor : 3
|
||||
stgraber@dakara:~$ lxc profile set default limits.cpu 3
|
||||
stgraber@dakara:~$ lxc exec snappy -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
```
|
||||
|
||||
To limit the CPU time of a container to 10% of the total, set the CPU allowance:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu.allowance 10%
|
||||
```
|
||||
|
||||
Or to give it a fixed slice of CPU time:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu.allowance 25ms/200ms
|
||||
```
|
||||
|
||||
And lastly, to reduce the priority of a container to a minimum:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu.priority 0
|
||||
```
|
||||
|
||||
#### Memory
|
||||
|
||||
To apply a straightforward memory limit run:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory 256MB
|
||||
```
|
||||
|
||||
(The supported suffixes are kB, MB, GB, TB, PB and EB)
|
||||
|
||||
To turn swap off for the container (defaults to enabled):
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory.swap false
|
||||
```
|
||||
|
||||
To tell the kernel to swap this container’s memory first:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory.swap.priority 0
|
||||
```
|
||||
|
||||
And finally if you don’t want hard memory limit enforcement:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory.enforce soft
|
||||
```
|
||||
|
||||
#### Disk and block I/O
|
||||
|
||||
Unlike CPU and memory, disk and I/O limits are applied to the actual device entry, so you either need to edit the original device or mask it with a more specific one.
|
||||
|
||||
To set a disk limit (requires btrfs or ZFS):
|
||||
|
||||
```
|
||||
lxc config device set my-container root size 20GB
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec zerotier -- df -h /
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
encrypted/lxd/containers/zerotier 179G 542M 178G 1% /
|
||||
stgraber@dakara:~$ lxc config device set zerotier root size 20GB
|
||||
stgraber@dakara:~$ lxc exec zerotier -- df -h /
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
encrypted/lxd/containers/zerotier 20G 542M 20G 3% /
|
||||
```
|
||||
|
||||
To restrict speed you can do the following:
|
||||
|
||||
```
|
||||
lxc config device set my-container root limits.read 30MB
|
||||
lxc config device set my-container root.limits.write 10MB
|
||||
```
|
||||
|
||||
Or to restrict IOps instead:
|
||||
|
||||
```
|
||||
lxc config device set my-container root limits.read 20Iops
|
||||
lxc config device set my-container root limits.write 10Iops
|
||||
```
|
||||
|
||||
And lastly, if you’re on a busy system with over-commit, you may want to also do:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.disk.priority 10
|
||||
```
|
||||
|
||||
To increase the I/O priority for that container to the maximum.
|
||||
|
||||
#### Network I/O
|
||||
|
||||
Network I/O is basically identical to block I/O as far the knobs available.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec zerotier -- wget http://speedtest.newark.linode.com/100MB-newark.bin -O /dev/null
|
||||
--2016-03-26 22:17:34-- http://speedtest.newark.linode.com/100MB-newark.bin
|
||||
Resolving speedtest.newark.linode.com (speedtest.newark.linode.com)... 50.116.57.237, 2600:3c03::4b
|
||||
Connecting to speedtest.newark.linode.com (speedtest.newark.linode.com)|50.116.57.237|:80... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 104857600 (100M) [application/octet-stream]
|
||||
Saving to: '/dev/null'
|
||||
|
||||
/dev/null 100%[===================>] 100.00M 58.7MB/s in 1.7s
|
||||
|
||||
2016-03-26 22:17:36 (58.7 MB/s) - '/dev/null' saved [104857600/104857600]
|
||||
|
||||
stgraber@dakara:~$ lxc profile device set default eth0 limits.ingress 100Mbit
|
||||
stgraber@dakara:~$ lxc profile device set default eth0 limits.egress 100Mbit
|
||||
stgraber@dakara:~$ lxc exec zerotier -- wget http://speedtest.newark.linode.com/100MB-newark.bin -O /dev/null
|
||||
--2016-03-26 22:17:47-- http://speedtest.newark.linode.com/100MB-newark.bin
|
||||
Resolving speedtest.newark.linode.com (speedtest.newark.linode.com)... 50.116.57.237, 2600:3c03::4b
|
||||
Connecting to speedtest.newark.linode.com (speedtest.newark.linode.com)|50.116.57.237|:80... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 104857600 (100M) [application/octet-stream]
|
||||
Saving to: '/dev/null'
|
||||
|
||||
/dev/null 100%[===================>] 100.00M 11.4MB/s in 8.8s
|
||||
|
||||
2016-03-26 22:17:56 (11.4 MB/s) - '/dev/null' saved [104857600/104857600]
|
||||
```
|
||||
|
||||
And that’s how you throttle an otherwise nice gigabit connection to a mere 100Mbit/s one!
|
||||
|
||||
And as with block I/O, you can set an overall network priority with:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.network.priority 5
|
||||
```
|
||||
|
||||
### Getting the current resource usage
|
||||
|
||||
The [LXD API][2] exports quite a bit of information on current container resource usage, you can get:
|
||||
|
||||
* Memory: current, peak, current swap and peak swap
|
||||
* Disk: current disk usage
|
||||
* Network: bytes and packets received and transferred for every interface
|
||||
|
||||
And now if you’re running a very recent LXD (only in git at the time of this writing), you can also get all of those in “lxc info”:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc info zerotier
|
||||
Name: zerotier
|
||||
Architecture: x86_64
|
||||
Created: 2016/02/20 20:01 UTC
|
||||
Status: Running
|
||||
Type: persistent
|
||||
Profiles: default
|
||||
Pid: 29258
|
||||
Ips:
|
||||
eth0: inet 172.17.0.101
|
||||
eth0: inet6 2607:f2c0:f00f:2700:216:3eff:feec:65a8
|
||||
eth0: inet6 fe80::216:3eff:feec:65a8
|
||||
lo: inet 127.0.0.1
|
||||
lo: inet6 ::1
|
||||
lxcbr0: inet 10.0.3.1
|
||||
lxcbr0: inet6 fe80::f0bd:55ff:feee:97a2
|
||||
zt0: inet 29.17.181.59
|
||||
zt0: inet6 fd80:56c2:e21c:0:199:9379:e711:b3e1
|
||||
zt0: inet6 fe80::79:e7ff:fe0d:5123
|
||||
Resources:
|
||||
Processes: 33
|
||||
Disk usage:
|
||||
root: 808.07MB
|
||||
Memory usage:
|
||||
Memory (current): 106.79MB
|
||||
Memory (peak): 195.51MB
|
||||
Swap (current): 124.00kB
|
||||
Swap (peak): 124.00kB
|
||||
Network usage:
|
||||
lxcbr0:
|
||||
Bytes received: 0 bytes
|
||||
Bytes sent: 570 bytes
|
||||
Packets received: 0
|
||||
Packets sent: 0
|
||||
zt0:
|
||||
Bytes received: 1.10MB
|
||||
Bytes sent: 806 bytes
|
||||
Packets received: 10957
|
||||
Packets sent: 10957
|
||||
eth0:
|
||||
Bytes received: 99.35MB
|
||||
Bytes sent: 5.88MB
|
||||
Packets received: 64481
|
||||
Packets sent: 64481
|
||||
lo:
|
||||
Bytes received: 9.57kB
|
||||
Bytes sent: 9.57kB
|
||||
Packets received: 81
|
||||
Packets sent: 81
|
||||
Snapshots:
|
||||
zerotier/blah (taken at 2016/03/08 23:55 UTC) (stateless)
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
The LXD team spent quite a few months iterating over the language we’re using for those limits. It’s meant to be as simple as it can get while remaining very powerful and specific when you want it to.
|
||||
|
||||
Live application of those limits and inheritance through profiles makes it a very powerful tool to live manage the load on your servers without impacting the running services.
|
||||
|
||||
### Extra information
|
||||
|
||||
The main LXD website is at: <https://linuxcontainers.org/lxd>
|
||||
Development happens on Github at: <https://github.com/lxc/lxd>
|
||||
Mailing-list support happens on: <https://lists.linuxcontainers.org>
|
||||
IRC support happens in: #lxcontainers on irc.freenode.net
|
||||
|
||||
And if you don’t want or can’t install LXD on your own machine, you can always [try it online instead][3]!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.stgraber.org/2016/03/26/lxd-2-0-resource-control-412/
|
||||
|
||||
作者:[Stéphane Graber][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.stgraber.org/author/stgraber/
|
||||
[0]: https://www.stgraber.org/2016/03/11/lxd-2-0-blog-post-series-012/
|
||||
[1]: https://github.com/lxc/lxd/blob/master/doc/configuration.md
|
||||
[2]: https://github.com/lxc/lxd/blob/master/doc/rest-api.md
|
||||
[3]: https://linuxcontainers.org/lxd/try-it
|
406
translated/tech/LXD/Part 4 - LXD 2.0--Resource control.md
Normal file
406
translated/tech/LXD/Part 4 - LXD 2.0--Resource control.md
Normal file
@ -0,0 +1,406 @@
|
||||
LXD 2.0 系列(四):资源控制
|
||||
======================================
|
||||
|
||||
这是 [LXD 2.0 系列介绍文章][0]的第四篇。
|
||||
|
||||
因为lxd容器管理有很多命令,因此这篇文章会很长。 如果你想要快速地浏览这些相同的命令,你可以[尝试下我们的在线演示][1]!
|
||||
|
||||
![](https://linuxcontainers.org/static/img/containers.png)
|
||||
|
||||
### 可用资源限制
|
||||
|
||||
LXD提供了不同的资源限制。其中一些绑定到容器本身,如内存配额,CPU限制和I/O优先级。一些与特定设备绑定,如I/O带宽或磁盘使用限制。
|
||||
|
||||
与所有LXD配置一样,资源限制可以在容器运行时动态更改。某些可能无法启用,例如,如果设置的内存值小于当前内存使用,但LXD将会重试并且报告失败。
|
||||
|
||||
所有限制也可以通过配置文件继承,在这种情况下每个受影响的容器将受到该限制的约束。也就是说,如果在默认配置文件中设置limits.memory=256MB,则使用默认配置文件(通常是所有配置文件)的每个容器的内存限制为256MB。
|
||||
|
||||
我们不支持资源限制池,其中的限制将由一组容器共享,因为我们没有什么好的方法由现有的内核API实现这些功能。
|
||||
|
||||
#### 磁盘
|
||||
|
||||
这或许是最需要和最明显的需求。 只需设置容器文件系统的大小限制,并对容器强制执行。
|
||||
|
||||
这就是LXD让你做的!
|
||||
不幸的是,这比它听起来复杂得多。 Linux没有基于路径的配额,而大多数文件系统只有基于用户和组的配额,这对容器没有什么用处。
|
||||
|
||||
如果你正在使用ZFS或btrfs存储后端,这意味着现在LXD只能支持磁盘限制。也有可能为LVM实现此功能,但这取决于与它一起使用的文件系统,并且如果结合实时更新那会变得棘手起来,因为并不是所有的文件系统都允许在线增长,几乎没有一个允许在线收缩。
|
||||
|
||||
#### CPU
|
||||
|
||||
当涉及到CPU的限制,我们支持4种不同的东西:
|
||||
|
||||
*只给我X个CPU核心
|
||||
|
||||
在这种模式下,你让LXD为你选择一组核心,然后为更多的容器和CPU的上线/下线提供负载均衡。
|
||||
|
||||
容器只看到这个数量的CPU核心。
|
||||
*给我一组特定的CPU核心(例如,核心1,3和5)
|
||||
|
||||
类似于第一种模式,除了没有发生负载均衡,你会被限制在那些核心,无论它们有多忙。
|
||||
*给我你拥有的20%
|
||||
|
||||
在这种模式下,你可以看到所有的CPU,但调度程序将限制你使用20%的CPU时间,但这只有在负载状态才会这样!所以如果系统不忙,你的容器可以跑得很欢。当其他的容器也开始使用CPU时,它会被限制。
|
||||
*每测量200ms,给我50ms(并且不超过)
|
||||
|
||||
此模式与上一个模式类似,你可以看到所有的CPU,但这一次,无论系统可能是多么空闲,你只能使用你设置的极限时间下的尽可能多的CPU时间。在没有过量使用的系统上,这可使你可以非常整齐地分割CPU,并确保这些容器的持续性能。
|
||||
|
||||
另外还可以将前两个中的一个与最后两个之一相结合,即请求一组CPU,然后进一步限制这些CPU的CPU时间。
|
||||
|
||||
除此之外,我们还有一个通用的优先级调节方式,可以告诉调度器当你处于负载状态时,两个争夺资源的容器谁会取得胜利。
|
||||
|
||||
#### 内存
|
||||
|
||||
内存听起来很简单,只是给我多少MB的内存!
|
||||
|
||||
它绝对可以那么简单。 我们支持这种限制以及基于百分比的请求,比如给我10%的主机内存!
|
||||
|
||||
另外我们在上层支持一些额外的东西。 例如,你可以选择在每个容器上打开或者关闭swap,如果打开,还可以设置优先级,以便你可以选择哪些容器先将内存交换到磁盘!
|
||||
|
||||
内存限制默认是“hard”。 也就是说,当内存耗尽时,内核将会开始杀掉你的那些进程。
|
||||
|
||||
或者,你可以将强制策略设置为“soft”,在这种情况下,只要没有别的进程的情况下,你将被允许使用尽可能多的内存。一旦别的进程想要这块内存,你将无法分配任何内存直到你低于你的限制或者主机内存再次有空余。
|
||||
|
||||
#### 网络 I/O
|
||||
|
||||
网络I/O可能是我们最简单的限制,但是相信我,实现真的不简单!
|
||||
|
||||
我们支持两种限制。 第一个是对网络接口的速率限制。 你可以设置入口和出口的限制,或者只是设置“最大”限制然后应用到出口和入口。这个只支持“桥接”和“p2p”类型接口。
|
||||
|
||||
第二种是全局网络I/O优先级,仅当你的网络接口趋于饱和的时候再使用。
|
||||
|
||||
#### 块 I/O
|
||||
|
||||
我把最古怪的放在最后。对于用户看起来它可能简单,但有一些情况下,它的结果并不会和你的预期一样。
|
||||
|
||||
我们在这里支持的基本上与我在网络I/O中描述的相同。
|
||||
|
||||
你可以直接设置磁盘的读写IO频率和速率,并且有一个全局的块I/O优先级,它会通知I/O调度程序更倾向哪个。
|
||||
|
||||
奇怪的是如何以及在哪里应用这些限制。不幸的是,我们用于实现这些功能的底层使用的是完整的块设备。这意味着我们不能为每个路径设置每个分区的I/O限制。
|
||||
|
||||
这也意味着当使用可以支持多个块设备的ZFS或btrfs(带或者不带RAID)回到指定的路径,我们并不知道这个路径是哪个块设备提供的。
|
||||
|
||||
这意味着,完全有可能,实际上有可能,容器使用的磁盘可能来自于多个不同的物理磁盘(绑定挂载或直接挂载)。
|
||||
|
||||
这就使限制变得很奇怪。为了使限制生效,LXD具有猜测给定路径对应块设备的逻辑,这其中包括询问ZFS和btrfs工具,甚至可以在发现一个文件系统中的循环挂载的文件时递归地找出它们。
|
||||
|
||||
这个逻辑虽然不完美,但通常会产生一组应该应用限制的块设备。LXD接着记录并移动到下一个路径。当遍历完所有的路径,它就得到了非常奇怪的部分。它会平均你为相应块设备设置的限制,然后应用这些。
|
||||
|
||||
这意味着你将在容器中“平均”地获得正确的速度,但这也意味着你不能对来自同一个物理磁盘的“/fast”和一个“/slow”目录应用不同的速度限制。 LXD允许你设置它,但最后,它会给你这两个值的平均值。
|
||||
|
||||
### 它怎么工作?
|
||||
|
||||
除了网络限制是通过较旧但是良好的“tc”实现的,上述大多数限制是通过Linux内核的cgroup API来实现的。
|
||||
|
||||
LXD在启动时会检测你在内核中启用了哪些cgroup,并且将只应用内核支持的限制。 如果你缺少一些cgroups,守护进程会输出警告,接着你的init系统将会记录这些。
|
||||
|
||||
在Ubuntu 16.04上,默认情况下除了内存交换审计外将会启用所有限制,它需要你通过“swapaccount = 1”这个内核引导参数启用它。
|
||||
|
||||
### 应用这些限制
|
||||
|
||||
上述所有限制都能够直接或者用某个配置文件应用于容器。容器范围的限制可以使用:
|
||||
|
||||
```
|
||||
lxc config set CONTAINER KEY VALUE
|
||||
```
|
||||
|
||||
对应配置文件:
|
||||
|
||||
```
|
||||
lxc profile set PROFILE KEY VALUE
|
||||
```
|
||||
|
||||
当指定特定设备时:
|
||||
|
||||
```
|
||||
lxc config device set CONTAINER DEVICE KEY VALUE
|
||||
```
|
||||
|
||||
对应配置文件
|
||||
|
||||
```
|
||||
lxc profile device set PROFILE DEVICE KEY VALUE
|
||||
```
|
||||
|
||||
完整有效的配置键、设备类型和设备键可以[看这里][1]。
|
||||
|
||||
#### CPU
|
||||
|
||||
要限制使用任意两个cpu核心可以这么做:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu 2
|
||||
```
|
||||
|
||||
要指定特定的cpu核心,也就是之前说的第二和第四种:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu 1,3
|
||||
```
|
||||
|
||||
更加复杂的情况还可以设置范围:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu 0-3,7-11
|
||||
```
|
||||
|
||||
The limits are applied live, as can be seen in this example:
|
||||
限制实时生效,你可以看下面的例子
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec zerotier -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
processor : 3
|
||||
stgraber@dakara:~$ lxc config set zerotier limits.cpu 2
|
||||
stgraber@dakara:~$ lxc exec zerotier -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
```
|
||||
|
||||
注意,为了避免完全混淆用户空间,lxcfs会重排/proc/cpuinfo中的条目,以便没有错误。
|
||||
|
||||
就像LXD中的一切,这些设置也可以应用在配置文件中:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec snappy -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
processor : 3
|
||||
stgraber@dakara:~$ lxc profile set default limits.cpu 3
|
||||
stgraber@dakara:~$ lxc exec snappy -- cat /proc/cpuinfo | grep ^proces
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
```
|
||||
|
||||
要限制容器使用10%的cpu时间,要设置下cpu allowance:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu.allowance 10%
|
||||
```
|
||||
|
||||
或者给他一个固定的cpu切片时间:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu.allowance 25ms/200ms
|
||||
```
|
||||
|
||||
最后,要将容器的cpu优先级调到最低:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.cpu.priority 0
|
||||
```
|
||||
|
||||
#### 内存
|
||||
|
||||
要直接应用内存限制运行下面的命令:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory 256MB
|
||||
```
|
||||
|
||||
(支持的后缀后KB、MB、GB、TB、PB、EB)
|
||||
|
||||
要关闭容器的内存交换(默认启用):
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory.swap false
|
||||
```
|
||||
|
||||
告诉内核首先交换指定容器的内存:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory.swap.priority 0
|
||||
```
|
||||
|
||||
如果你不想要强制的内存限制:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.memory.enforce soft
|
||||
```
|
||||
|
||||
#### 磁盘和块I/O
|
||||
|
||||
不像CPU和内存,磁盘和I/O限制是直接作用在实际的设备上的,因此你需要编辑原始设备或者屏蔽某个具体的设备。
|
||||
|
||||
要设置磁盘限制(需要btrfs或者ZFS):
|
||||
|
||||
```
|
||||
lxc config device set my-container root size 20GB
|
||||
```
|
||||
|
||||
比如:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec zerotier -- df -h /
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
encrypted/lxd/containers/zerotier 179G 542M 178G 1% /
|
||||
stgraber@dakara:~$ lxc config device set zerotier root size 20GB
|
||||
stgraber@dakara:~$ lxc exec zerotier -- df -h /
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
encrypted/lxd/containers/zerotier 20G 542M 20G 3% /
|
||||
```
|
||||
|
||||
要限制速度,你可以:
|
||||
|
||||
```
|
||||
lxc config device set my-container root limits.read 30MB
|
||||
lxc config device set my-container root.limits.write 10MB
|
||||
```
|
||||
|
||||
或者限制IO频率:
|
||||
|
||||
```
|
||||
lxc config device set my-container root limits.read 20Iops
|
||||
lxc config device set my-container root limits.write 10Iops
|
||||
```
|
||||
|
||||
最后你在一个过量使用的繁忙系统上,你或许想要:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.disk.priority 10
|
||||
```
|
||||
|
||||
将那个容器的I/O优先级调到最高。
|
||||
|
||||
#### 网络 I/O
|
||||
|
||||
只要机制可用,网络I/O基本等同于块I/O。
|
||||
|
||||
比如:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc exec zerotier -- wget http://speedtest.newark.linode.com/100MB-newark.bin -O /dev/null
|
||||
--2016-03-26 22:17:34-- http://speedtest.newark.linode.com/100MB-newark.bin
|
||||
Resolving speedtest.newark.linode.com (speedtest.newark.linode.com)... 50.116.57.237, 2600:3c03::4b
|
||||
Connecting to speedtest.newark.linode.com (speedtest.newark.linode.com)|50.116.57.237|:80... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 104857600 (100M) [application/octet-stream]
|
||||
Saving to: '/dev/null'
|
||||
|
||||
/dev/null 100%[===================>] 100.00M 58.7MB/s in 1.7s
|
||||
|
||||
2016-03-26 22:17:36 (58.7 MB/s) - '/dev/null' saved [104857600/104857600]
|
||||
|
||||
stgraber@dakara:~$ lxc profile device set default eth0 limits.ingress 100Mbit
|
||||
stgraber@dakara:~$ lxc profile device set default eth0 limits.egress 100Mbit
|
||||
stgraber@dakara:~$ lxc exec zerotier -- wget http://speedtest.newark.linode.com/100MB-newark.bin -O /dev/null
|
||||
--2016-03-26 22:17:47-- http://speedtest.newark.linode.com/100MB-newark.bin
|
||||
Resolving speedtest.newark.linode.com (speedtest.newark.linode.com)... 50.116.57.237, 2600:3c03::4b
|
||||
Connecting to speedtest.newark.linode.com (speedtest.newark.linode.com)|50.116.57.237|:80... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 104857600 (100M) [application/octet-stream]
|
||||
Saving to: '/dev/null'
|
||||
|
||||
/dev/null 100%[===================>] 100.00M 11.4MB/s in 8.8s
|
||||
|
||||
2016-03-26 22:17:56 (11.4 MB/s) - '/dev/null' saved [104857600/104857600]
|
||||
```
|
||||
|
||||
这就是如何将一个千兆网的连接速度限制到仅仅100Mbit/s的!
|
||||
|
||||
和块I/O一样,你可以设置一个总体的网络优先级:
|
||||
|
||||
```
|
||||
lxc config set my-container limits.network.priority 5
|
||||
```
|
||||
|
||||
### 获取当前资源使用率
|
||||
|
||||
[LXD API][2]可以导出目前容器资源使用情况的一点信息,你可以得到:
|
||||
|
||||
* 内存:当前、峰值、目前内存交换和峰值内存交换
|
||||
* 磁盘:当前磁盘使用率
|
||||
* 网络:每个接口传输的字节和包数。
|
||||
|
||||
另外如果你使用的是非常新的LXD(在写这篇文章时的git版本),你还可以在“lxc info”中得到这些信息:
|
||||
|
||||
```
|
||||
stgraber@dakara:~$ lxc info zerotier
|
||||
Name: zerotier
|
||||
Architecture: x86_64
|
||||
Created: 2016/02/20 20:01 UTC
|
||||
Status: Running
|
||||
Type: persistent
|
||||
Profiles: default
|
||||
Pid: 29258
|
||||
Ips:
|
||||
eth0: inet 172.17.0.101
|
||||
eth0: inet6 2607:f2c0:f00f:2700:216:3eff:feec:65a8
|
||||
eth0: inet6 fe80::216:3eff:feec:65a8
|
||||
lo: inet 127.0.0.1
|
||||
lo: inet6 ::1
|
||||
lxcbr0: inet 10.0.3.1
|
||||
lxcbr0: inet6 fe80::f0bd:55ff:feee:97a2
|
||||
zt0: inet 29.17.181.59
|
||||
zt0: inet6 fd80:56c2:e21c:0:199:9379:e711:b3e1
|
||||
zt0: inet6 fe80::79:e7ff:fe0d:5123
|
||||
Resources:
|
||||
Processes: 33
|
||||
Disk usage:
|
||||
root: 808.07MB
|
||||
Memory usage:
|
||||
Memory (current): 106.79MB
|
||||
Memory (peak): 195.51MB
|
||||
Swap (current): 124.00kB
|
||||
Swap (peak): 124.00kB
|
||||
Network usage:
|
||||
lxcbr0:
|
||||
Bytes received: 0 bytes
|
||||
Bytes sent: 570 bytes
|
||||
Packets received: 0
|
||||
Packets sent: 0
|
||||
zt0:
|
||||
Bytes received: 1.10MB
|
||||
Bytes sent: 806 bytes
|
||||
Packets received: 10957
|
||||
Packets sent: 10957
|
||||
eth0:
|
||||
Bytes received: 99.35MB
|
||||
Bytes sent: 5.88MB
|
||||
Packets received: 64481
|
||||
Packets sent: 64481
|
||||
lo:
|
||||
Bytes received: 9.57kB
|
||||
Bytes sent: 9.57kB
|
||||
Packets received: 81
|
||||
Packets sent: 81
|
||||
Snapshots:
|
||||
zerotier/blah (taken at 2016/03/08 23:55 UTC) (stateless)
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
LXD团队花费了几个月的时间来迭代我们使用的这些限制语言。 它是为了在保持强大和功能明确的基础上同时保持简单。
|
||||
|
||||
实时的应用限制和继承配置文件,使其成为一种非常强大的工具,可以在不影响正在运行的服务的情况下实时管理服务器上的负载。
|
||||
|
||||
### 额外的信息
|
||||
|
||||
LXD主站: <https://linuxcontainers.org/lxd>
|
||||
Github上的页面: <https://github.com/lxc/lxd>
|
||||
邮件列表: <https://lists.linuxcontainers.org>
|
||||
IRC:#lxcontainers on irc.freenode.net
|
||||
|
||||
如果你不想在你的机器上安装LXD,你可以[在线尝试下][3]
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.stgraber.org/2016/03/26/lxd-2-0-resource-control-412/
|
||||
|
||||
作者:[Stéphane Graber][a]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 组织翻译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.stgraber.org/author/stgraber/
|
||||
[0]: https://www.stgraber.org/2016/03/11/lxd-2-0-blog-post-series-012/
|
||||
[1]: https://github.com/lxc/lxd/blob/master/doc/configuration.md
|
||||
[2]: https://github.com/lxc/lxd/blob/master/doc/rest-api.md
|
||||
[3]: https://linuxcontainers.org/lxd/try-it
|
Loading…
Reference in New Issue
Block a user