原文:
annas-archive.org/md5/d798fed6801363e3c493ed91d8bc1298译者:飞龙
第四章. Zones
在本章中,我们将涵盖以下内容:
-
在 zone 中创建、管理和使用虚拟网络
-
使用资源管理器管理 zone
-
实现流量控制
-
从物理 Oracle Solaris 10 主机迁移到 Oracle Solaris 11 Zones
介绍
Oracle Solaris 11 Zones 是一个出色的框架,它虚拟化并整合了一个系统环境,在该环境中有许多应用程序和物理机器运行 Oracle Solaris。用一个粗略的比较,Oracle Solaris 11 zone 类似于 VMware ESX、Linux LXC 和 FreeBSD Jails 提供的其他虚拟化选项,但它具有一些重要的不同之处,例如不允许执行硬件仿真或运行除 Oracle Solaris 11 或之前版本的 Oracle Solaris 之外的任何其他操作系统。
在 Oracle Solaris Zones 中,基本的概念是通过共享或划分(使用资源管理器)现有资源,在主操作系统(父操作系统)内部创建不同的小型操作系统安装(子操作系统)。每个安装将有自己的 init 文件和进程,尽管它与父操作系统共享内核,从而导致比之前提到的解决方案更少的开销。使用 Oracle Solaris 11 的术语,父操作系统是全球 zone,子操作系统是非全球 zone,正如我们稍后将看到的。
Oracle Solaris zone 提供了应用程序隔离、额外的安全层和降低的功耗要求。这种对安全性的关注是必要的,以防止在一个 zone 内运行的应用程序崩溃其他 zone 中的应用程序。这也是非全球 zone 无法查看其他非全球 zone、可以包含额外软件包并具有独立产品数据库来控制其自身安装软件的原因。
进一步讨论前面提到的特点,zone 使得多个应用程序能够共享主机资源,从而降低部署成本。这种资源管理允许我们为非全球 zone 分配特定资源,以创建资源消耗的限制(例如 CPU 和内存),并控制进程、任务或项目使用多少资源。此外,这种资源控制利用了 Oracle Solaris 调度器类 公平共享调度器(FSS),以对 CPU(使用共享)和内存(使用 rcapd 守护进程限制物理内存量)进行控制。
Zone 在 Oracle Solaris 版本 10 中引入,可以分为全球 zone(物理机器安装,即之前提到的父操作系统)和非全球 zone(非正式称为 本地 zone 或简单地称为 zone,即之前提到的子操作系统),在这些 zone 中可以安装和管理应用程序,并进行正确的资源配置。
全球区域(父区域)是一个可启动的区域,直接来自物理硬件,它使得配置、安装、管理和删除非全球区域(子区域)成为可能,因为它也是唯一了解所有现有区域的区域。通常,非全球区域运行与全球区域相同的操作系统,但 Oracle Solaris 11 提供了另一种区域类型,称为品牌化区域,它使得创建和安装一个运行 Oracle Solaris 10 的非全球区域成为可能。
简而言之,在安装非全球区域时,需要提供输入目录以指定区域安装位置、网络接口以及如 IP 地址和网络掩码等网络信息。此外,还需要指定在非全球区域中与网络接口一起使用的 IP 类型。共有两种选择:共享 IP(当网络接口与全球区域共享时使用)和专用 IP(当网络接口专用于非全球区域时使用)。
一旦区域配置完成,下一步就是安装并管理该区域。需要了解的是,非全球区域可以有以下区域状态:
-
undefined:表示区域配置是否未完成或已删除
-
incomplete:表示区域安装在中途被中止
-
configured:表示区域配置是否完成
-
installed:表示区域包和操作系统已安装
-
ready:表示几乎可以运行的区域,并带有相关的区域 ID
-
running:表示一切正常,正在执行中
-
down:表示区域已停止
说实话,日常工作中更常见的状态是configured、installed、running和down。其他状态都是临时状态,我们很少需要关心它们。
因此,状态的顺序是undefined | configured | incomplete | installed | ready | running | down。
通常有专业人士问我:“Oracle Solaris 11 和 Oracle Solaris 10 之间有什么区别?”确实存在一些相关差异。现在,var目录是一个独立的文件系统,默认区域品牌是 Solaris(之前是 native),不再存在稀疏区域的概念,而默认文件系统是 ZFS,并使用 IPS 作为包管理器。然而,在 Oracle Solaris 11 中最重要的区域差异是引入了网络虚拟化,它允许我们使用至少一个网络接口——虚拟网络接口 (VNICs)——和虚拟交换机的概念来控制网络区域资源。例如,一台物理机器可以在全局区域中运行 Oracle Solaris 11,并且有五个非全局区域(z1、z2、z3、z4 和 z5),每个区域都有一个专用的 VNIC 连接到一个虚拟交换机(etherstub),最后一个连接到真实网络接口卡。此外,可以强制执行网络流控制,并配置特定的链路属性以增加带宽控制和效率,从而可以在不同的 VNICs 之间共享网络资源。
可以根据每个 VNIC 创建可能的网络流,并具有特定的属性,隔离和分类类似的数据包,并带有相关联的绑定资源。可能的流属性包括maxbw(定义流的带宽)和优先级(定义流中数据包的优先级为低、中和高)。
所有提到的资源控制(CPU、内存和网络)默认情况下都是禁用的,并由两个资源服务控制:默认资源池服务(svc:/system/pools:default)和动态资源池服务(svc:/system/pools/dynamic:default)。名为pooladm.conf的配置文件位于etc目录下,帮助我们定义池的创建和资源管理行为,它由一个名为poold的守护程序控制整个分配控制和限制,在将创建的池与非全局区域关联后。
现在,我们准备学习关于 Oracle Solaris 11 区域的下一个配方。
创建、管理和使用区域内的虚拟网络
我喜欢这个配方,因为在这里,我们将使用 Oracle Solaris 11 虚拟网络区域的主要功能。简而言之,我们将创建和配置以下场景:
-
zone1|vnic1(192.168.1.51) |vswitch1(etherstub) |net0(192.168.1.144) -
zone2|vnic2(192.168.1.52) |vswitch1(etherstub) |net0(192.168.1.144)
每个区域连接到其相应的虚拟网络接口 (VNIC),两个 VNIC 都连接到同一个etherstub(一种虚拟交换机)。因此,etherstub需要一个虚拟接口(vnic0)。最后,etherstub连接到一个真实接口(net0)。每个区域的zonepath属性和其他属性如下:
-
zonepath zone1:
/myzones/zone1 -
zonepath zone2:
/myzones/zone2 -
IP 类型:专用 IP
准备就绪
本教程需要一台运行 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),至少需要 4 GB 的内存(推荐 8 GB),一个额外的 80 GB 磁盘,以及为该虚拟机配置的双核或更多核心的处理器,以下截图是从我的 VirtualBox 环境中提取的:
https://github.com/OpenDocCN/freelearn-linux-pt5-zh/raw/master/docs/slrs11-adv-adm/img/00022.jpeg
如何操作…
要开始此过程,我们需要通过执行以下命令收集所有当前和相关的系统信息:
root@solaris11-1:~# dladm show-link
LINK CLASS MTU STATE OVER
net1 phys 1500 up --
net0 phys 1500 up --
root@solaris11-1:~# ipadm show-if
IFNAME CLASS STATE ACTIVE OVER
lo0 loopback ok yes --
net0 ip ok yes --
net1 ip ok yes --
root@solaris11-1:~# ipadm show-addr
ADDROBJ TYPE STATE ADDR
lo0/v4 static ok 127.0.0.1/8
net0/v4 static ok 192.168.1.144/24
net1/v4 static ok 192.168.5.77/24
lo0/v6 static ok ::1/128
root@solaris11-1:~# zpool list
NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT
myzones 79.5G 544K 79.5G 0% 1.00x ONLINE -
rpool 79.5G 21.2G 58.3G 26% 1.00x ONLINE -
root@solaris11-1:~# zfs list | grep myzones
myzones 494K 78.3G 31K /myzones
root@solaris11-1:~#
系统有两个网络接口(net0和net1),但只会考虑net0。此外,池(myzones)有大约 80 GB 的可用空间(你可以使用zpool create myzones <磁盘>创建 myzones 池),并且没有文件系统。然后,第一步是创建池并为每个 zone(zone1和zone2)创建一个文件系统,执行以下命令:
root@solaris11-1:~# zpool create myzones c7t2d0
root@solaris11-1:~# zfs create myzones/zone1
root@solaris11-1:~# zfs list myzones/zone1
root@solaris11-1:/myzones# zfs create myzones/zone1
root@solaris11-1:/myzones# zfs create myzones/zone2
root@solaris11-1:/myzones# zfs list | grep zone
myzones 314K 78.3G 33K /myzones
myzones/zone1 31K 78.3G 31K /myzones/zone1
myzones/zone2 31K 78.3G 31K /myzones/zone2
存储需求已满足,接下来,本教程的关键部分是准备所有网络基础设施。为此,必须创建etherstub(vswitch1)和三个 VNIC:vnic0(etherstub),vnic1(zone1),以及vnic2(zone2)。此外,我们需要将所有 VNIC 连接到etherstub(vswitch1)。所有这些任务都可以通过执行以下命令完成:
root@solaris11-1:~# dladm create-etherstub vswitch1
root@solaris11-1:~# dladm show-link
LINK CLASS MTU STATE OVER
net1 phys 1500 up --
net0 phys 1500 up --
vswitch1 etherstub 9000 unknown --
root@solaris11-1:~# dladm create-vnic -l vswitch1 vnic0
root@solaris11-1:~# dladm create-vnic -l vswitch1 vnic1
root@solaris11-1:~# dladm create-vnic -l vswitch1 vnic2
root@solaris11-1:~# dladm show-link
LINK CLASS MTU STATE OVER
net1 phys 1500 up --
net0 phys 1500 up --
vswitch1 etherstub 9000 unknown --
vnic0 vnic 9000 up vswitch1
vnic1 vnic 9000 up vswitch1
vnic2 vnic 9000 up vswitch1
root@solaris11-1:~# dladm show-vnic
LINK OVER SPEED MACADDRESS MACADDRTYPE VID
vnic0 vswitch1 40000 2:8:20:d:b:3b random 0
vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
现在,是时候创建第一个 zone(zone1),使用ip-type=exclusive(这是默认值)并将vnic1作为物理网络接口:
root@solaris11-1:~# zonecfg -z zone1
Use 'create' to begin configuring a new zone.
zonecfg:zone1> create
create: Using system default template 'SYSdefault'
zonecfg:zone1> set autoboot=true
zonecfg:zone1> set zonepath=/myzones/zone1
zonecfg:zone1> add net
zonecfg:zone1:net> set physical=vnic1
zonecfg:zone1:net> end
zonecfg:zone1> info
zonename: zone1
zonepath: /myzones/zone1
brand: solaris
autoboot: true
bootargs:
file-mac-profile:
pool:
limitpriv:
scheduling-class:
ip-type: exclusive
hostid:
fs-allowed:
net:
address not specified
allowed-address not specified
configure-allowed-address: true
physical: vnic1
defrouter not specified
anet:
linkname: net0
lower-link: auto
allowed-address not specified
configure-allowed-address: true
defrouter not specified
allowed-dhcp-cids not specified
link-protection: mac-nospoof
mac-address: random
mac-prefix not specified
mac-slot not specified
vlan-id not specified
priority not specified
rxrings not specified
txrings not specified
mtu not specified
maxbw not specified
rxfanout not specified
vsi-typeid not specified
vsi-vers not specified
vsi-mgrid not specified
etsbw-lcl not specified
cos not specified
pkey not specified
linkmode not specified
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@solaris11-1:~#
要配置zone2,需要执行几乎相同的步骤(省略了 zone 信息的详细内容),执行以下命令:
root@solaris11-1:~# zonecfg -z zone2
Use 'create' to begin configuring a new zone.
zonecfg:zone2> create
create: Using system default template 'SYSdefault'
zonecfg:zone2> set autoboot=true
zonecfg:zone2> set zonepath=/myzones/zone2
zonecfg:zone2> add net
zonecfg:zone2:net> set physical=vnic2
zonecfg:zone2:net> end
zonecfg:zone2> verify
zonecfg:zone2> commit
zonecfg:zone2> exit
要列出最近配置的 zone,执行以下命令:
root@solaris11-1:~# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
- zone1 configured /myzones/zone1 solaris excl
- zone2 configured /myzones/zone2 solaris excl
根据之前的教程,在安装 zone 后第一次登录时,需要通过 11 个屏幕交互式地提供系统配置信息。为了自动化并简化此过程,可以为每个 zone 创建一个系统配置文件,并在每次安装 zone 时提供它。为完成此任务,需要从中获取一些信息:
对于zone1,信息如下:
-
计算机名称:
zone1 -
以太网网络配置:
手动 -
网络接口:
vnic1 -
IP 地址:
192.168.1.51 -
DNS:
不配置 DNS -
备用名称服务器:
无 -
时区:
(你的时区) -
日期和时间:
(当前日期和时间) -
根密码:
(你的选择) -
你的真实姓名:
Alexandre Borges -
用户名:
aborges1 -
密码:
hacker123! -
电子邮件:
anonymous@oracle.com -
互联网访问方式:
无代理
对于zone2,信息如下:
-
计算机名称:
zone2 -
以太网网络配置:
手动 -
网络接口:
vnic2 -
IP 地址:
192.168.1.52 -
DNS:
不配置 DNS -
备用名称服务器:
无 -
时区:
(你的时区) -
日期和时间:
(当前日期和时间) -
根密码:
(你的选择) -
你的真实姓名:
Alexandre Borges -
用户名:
aborges2 -
密码:
hacker123! -
电子邮件:
anonymous@oracle.com -
网络访问方式:
No proxy
创建一个目录来存放区域配置文件,方法如下:
root@solaris11-1:~# mkdir /zone_profiles
通过执行以下命令为 zone1 创建配置文件:
root@solaris11-1:~# sysconfig create-profile -o /zone_profiles/zone1.xml
使用几乎相同的命令,通过执行以下命令为 zone2 创建一个配置文件:
root@solaris11-1:~# sysconfig create-profile -o /zone_profiles/zone2.xml
要可视化系统配置内容,请执行以下命令:
root@solaris11-1:~# more /zone_profiles/zone1.xml
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="sysconfig">
<service version="1" type="service" name="system/config-user">
<instance enabled="true" name="default">
<property_group type="application" name="root_account">
<propval type="astring" name="login" value="root"/>
<propval type="astring" name="password" value="$5$Iabvrv4s$wAqPBNvP7QBZ12ocIdDp/TzNP8Gyv5PBvkTk1QTUEeA"/>
<propval type="astring" name="type" value="role"/>
</property_group>
<property_group type="application" name="user_account">
<propval type="astring" name="login" value="aborges1"/>
<propval type="astring" name="password" value="$5$XfpOXWq9$1roklDSW7LW1Iq0pdpxq5Js16/d4DszHHlZB2AvYRL7"/>
<propval type="astring" name="type" value="normal"/>
<propval type="astring" name="description" value="Alexandre Borges"/>
<propval type="count" name="gid" value="10"/>
<propval type="astring" name="shell" value="/usr/bin/bash"/>
<propval type="astring" name="roles" value="root"/>
<propval type="astring" name="profiles" value="System Administrator"/>
<propval type="astring" name="sudoers" value="ALL=(ALL) ALL"/>
(truncated output)
现在,是时候使用之前配置的系统配置文件安装 zone1 和 zone2 了。因此,为了执行此任务,我们将使用本地仓库(如在第一章,IPS 和启动环境中所学)并执行以下命令:
root@solaris11-1:~# pkg publisher
PUBLISHER TYPE STATUS P LOCATION
solaris origin online F http://solaris11-1.example.com/
root@solaris11-1:~# zoneadm -z zone1 install -c /zone_profiles/zone1.xml
root@solaris11-1:~# zoneadm -z zone2 install -c /zone_profiles/zone2.xml
root@solaris11-1:~# zoneadm list -iv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
- zone1 installed /myzones/zone1 solaris excl
- zone2 installed /myzones/zone2 solaris excl
root@solaris11-1:~#
通过执行以下命令启动这两个区域:
root@solaris11-1:~# zoneadm list -iv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
- zone1 installed /myzones/zone1 solaris excl
- zone2 installed /myzones/zone2 solaris excl
root@solaris11-1:~# zoneadm -z zone1 boot
root@solaris11-1:~# zoneadm -z zone2 boot
在登录到区域之前,检查网络信息是很合适的,可以通过执行以下命令来实现:
root@solaris11-1:~# dladm show-link
LINK CLASS MTU STATE OVER
net1 phys 1500 up --
net0 phys 1500 up --
vswitch1 etherstub 9000 unknown --
vnic0 vnic 9000 up vswitch1
vnic1 vnic 9000 up vswitch1
zone1/vnic1 vnic 9000 up vswitch1
vnic2 vnic 9000 up vswitch1
zone2/vnic2 vnic 9000 up vswitch1
zone1/net0 vnic 1500 up net0
zone2/net0 vnic 1500 up net0
root@solaris11-1:~# dladm show-vnic
LINK OVER SPEED MACADDRESS MACADDRTYPE VID
vnic0 vswitch1 40000 2:8:20:d:b:3b rand 0
vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
zone1/vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone2/vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone1/net0 net0 1000 2:8:20:ac:7d:b1 random 0
zone2/net0 net0 1000 2:8:20:f3:29:68 random 0
root@solaris11-1:~# ipadm show-addr
ADDROBJ TYPE STATE ADDR
lo0/v4 static ok 127.0.0.1/8
net0/v4 static ok 192.168.1.144/24
net1/v4 static ok 192.168.5.77/24
lo0/v6 static ok ::1/128
现在,我们可以登录到区域并通过执行以下命令进行测试:
root@solaris11-1:~# zlogin zone1
[Connected to zone 'zone1' pts/5]
Oracle Corporation SunOS 5.11 11.1 September 2012
root@zone1:~# ping 192.168.1.52
192.168.1.52 is alive
root@zone1:~# exit
logout
[Connection to zone 'zone1' pts/5 closed]
root@solaris11-1:~# zlogin zone2
[Connected to zone 'zone2' pts/5]
Oracle Corporation SunOS 5.11 11.1 September 2012
root@zone2:~# ping 192.168.1.51
192.168.1.51 is alive
root@zone2:~# exit
logout
[Connection to zone 'zone2' pts/5 closed]
root@solaris11-1:~#
一切正常。区域真是太棒了!
该教程概述
这个教程的好消息是我们配置了一个虚拟交换机(etherstub)和三个虚拟网络接口。之后,我们使用这些对象创建了两个区域,并应用了虚拟网络的概念。
使用资源管理器管理区域
安装和配置 Oracle Solaris 11 非全球区域非常棒,正如我们之前提到的,它是一项出色的技术,可以在不干扰其他应用程序的情况下隔离并运行应用程序,如果出现问题,其他应用程序不受影响。然而,仍然存在一个问题。每个非全球区域都在全球区域中运行,仿佛它单独运行一样,但如果其中一个区域独占所有资源(处理器和内存),并且几乎不给其他区域留下任何资源,就会出现不方便的效果。基于这种情况,可以部署一个名为资源管理器的解决方案,以控制每个区域消耗多少资源。
集中关注资源管理器(不考虑区域),在 Oracle Solaris 11 中,有许多形式可以强制实施资源控制。例如,我们可以使用一个项目(/etc/project),该项目由任务组成,每个任务包含一个或多个进程。通过 projadd 命令可以创建一个新项目,可以通过 服务管理工具(SMF)或甚至在打开会话时使用 newtask 命令来创建新任务。启用资源管理器服务并将处理器和内存等资源分配给该项目,有助于为该项目绑定的进程设定一个上限,限制它们可以使用多少资源(处理器和内存)。无论如何,可以通过运行 projects -l 命令列出 Oracle Solaris 11 中现有的项目。
有几种方法可以将资源与项目关联。第一种方法是使用资源控制(rctladm和prctl命令)来管理和查看分配给项目的控制。此方法的缺点是,它通过进程限制使用的资源,防止它们占用更多的处理器或内存(如果需要)。另一个相关且可能的问题是,管理员必须精确知道应用程序使用了多少资源,才能合理地分配资源,因为如果分配给项目或应用程序的资源不足,它可能会停止工作。
控制应用程序能够使用多少资源的第二种有效方法是使用公平共享调度器(FSS)类,它帮助我们根据资源需求调节资源分配(处理器时间)。一个真实的优势是,如果某个应用程序没有使用分配的所有资源(处理器时间),其他应用程序可以使用该应用程序释放出来的空闲资源。因此,这种资源共享就像是一个动态资源控制系统,按照计划分配资源(应用程序分配了份额),并根据需求变化调整其分配。例如,当我个人使用 FSS 时,我会将可用的份额归一化为 100 点,以便于与百分比进行比较。对于项目 A,我分配 30 个份额;对于项目 B,我分配 50 个份额;对于项目 C,我分配 20 个份额。最终,时间处理器的分配是:应用程序 A 得到 30%,应用程序 B 得到 50%,应用程序 C 得到 20%。这很简单,不是吗?
部署资源管理器的第三种方式是使用资源池。基本思想是将资源分配给资源组(或池),然后将该池与项目或应用程序关联。类似于我们为 FSS 解释的内容,处理器集(处理器组)通常分配给资源池,而资源池再分配给项目。资源池提供了更好的灵活性,因为它允许我们根据需求设置应用程序使用的处理器的最小和最大数量。例如,可以将一个到八个核心(或处理器)分配给项目,根据资源需求,使用更少或更多的处理器。此外,特定的处理器(或核心)可以专门分配给处理器集,若需要的话。使用资源池的一个小缺点是,处理器被限制在池内,即使有空闲资源(处理器),也不能被其他应用程序使用。就个人而言,我更喜欢管理和使用 FSS,因为其灵活性和可重用性让你有机会释放资源,供其他应用程序或项目使用。尽管如此,将资源池与 FSS 和项目混合使用并实施受控环境,依然是可行的。
最终,所有这些控制资源的技术都可以在区域上下文中部署,以通过运行的应用程序限制使用的资源,正如我们在这个方案中将要学习的那样。
准备工作
这个方案需要一台虚拟机(VirtualBox 或 VMware),其运行在具有两个或更多核心的处理器上,配备 8GB RAM 和 80GB 硬盘。为了简化以下步骤,我们将使用在之前方案中使用的区域,读者可以认为这个方案是一个简单的延续。
如何进行…
基本上,这个方案由两部分组成。在第一部分,配置资源池;在第二部分,将现有资源池绑定到区域。
首先,我们需要通过运行以下命令收集关于现有区域的信息:
root@solaris11-1:~# zoneadm list -iv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
1 zone2 running /myzones/zone2 solaris excl
2 zone1 running /myzones/zone1 solaris excl
root@solaris11-1:~#
资源池服务可能已经停止。我们可以通过执行以下命令来验证它们:
root@solaris11-1:~# svcs -a | grep pool
disabled 12:23:27 svc:/system/pools:default
disabled 12:23:35 svc:/system/pools/dynamic:default
通过执行以下命令检查每个服务的依赖关系:
root@solaris11-1:~# svcs -d svc:/system/pools:default
STATE STIME FMRI
online 12:23:42 svc:/system/filesystem/minimal:default
root@solaris11-1:~# svcs -d svc:/system/pools/dynamic:default
STATE STIME FMRI
disabled 12:23:27 svc:/system/pools:default
online 12:24:08 svc:/system/filesystem/local:default
由于svc:/system/pools/dynamic:default服务依赖于svc:/system/pools:default,建议通过运行以下命令启用它们:
root@solaris11-1:~# svcadm enable -r svc:/system/pools/dynamic:default
root@solaris11-1:~# svcs -a | grep pool
online 14:30:31 svc:/system/pools:default
online 14:30:37 svc:/system/pools/dynamic:default
root@solaris11-1:~# svcs -p svc:/system/pools/dynamic:default
STATE STIME FMRI
online 14:30:37 svc:/system/pools/dynamic:default
14:30:37 5443 poold
当启用资源池控制时,会创建一个默认池(pool_default)和一个默认处理器集(default_pset),包括系统中的所有资源,可以通过执行以下命令来验证:
root@solaris11-1:~# pooladm
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool pool_default
int pool.sys_id 0
boolean pool.active true
boolean pool.default true
int pool.importance 1
string pool.comment
pset pset_default
pset pset_default
int pset.sys_id -1
boolean pset.default true
uint pset.min 1
uint pset.max 65536
string pset.units population
uint pset.load 211
uint pset.size 4
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 3
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 2
string cpu.comment
string cpu.status on-line
根据此输出,存在一个默认池(pool_default);真实处理器有四个核心(范围 0 到 3),它们都组成了一个处理器集(pset)。然而,这个资源池配置只存在于内存中,并且不在磁盘上持久化。因此,要将其保存到配置文件中,请执行以下命令:
root@solaris11-1:~# pooladm -s
root@solaris11-1:~# more /etc/pooladm.conf
<?xml version="1.0"?>
<!DOCTYPE system PUBLIC "-//Sun Microsystems Inc//DTD Resource Management All//EN" "file:///usr/share/lib/xml/dtd/rm_pool.dtd.1">
<!--
Configuration for pools facility. Do NOT edit this file by hand - use poolcfg(1) or libpool(3POOL) instead.
-->
<system ref_id="dummy" name="default" comment="" version="1" bind-default="true">
<property name="system.poold.objectives" type="string">wt-load</property>
<pool name="pool_default" active="true" default="true" importance="1" comment="" res="pset_-1" ref_id="pool_0">
<property name="pool.sys_id" type="int">0</property>
</pool>
<res_comp type="pset" sys_id="-1" name="pset_default" default="true" min="1" max="65536" units="population" comment="" ref_id="pset_-1">
<property name="pset.load" type="uint">176</property>
<property name="pset.size" type="uint">4</property>
<comp type="cpu" sys_id="1" comment="" ref_id="cpu_1">
<property name="cpu.status" type="string">on-line</property>
</comp>
<comp type="cpu" sys_id="3" comment="" ref_id="cpu_3">
<property name="cpu.status" type="string">on-line</property>
</comp>
<comp type="cpu" sys_id="0" comment="" ref_id="cpu_0">
<property name="cpu.status" type="string">on-line</property>
</comp>
<comp type="cpu" sys_id="2" comment="" ref_id="cpu_2">
<property name="cpu.status" type="string">on-line</property>
</comp>
</res_comp>
</system>
从这一点开始,以下步骤会创建一个包含两个核心的处理器集(pset),创建一个池,并将该处理器集与池关联。稍后,这个池将分配给区域配置,可以显示为:处理器集 | 池 | 区域。
因此,要创建一个包含一个核心最小(pset.min=1)和两个核心最大(pset.max=2)的处理器集(first_pset),请执行以下命令:
root@solaris11-1:~# poolcfg -c 'create pset first_pset (uint pset.min = 1; uint pset.max = 2)'
root@solaris11-1:~# poolcfg -c 'info pset first_pset'
pset first_pset
int pset.sys_id -2
boolean pset.default false
uint pset.min 1
uint pset.max 2
string pset.units population
uint pset.load 0
uint pset.size 0
string pset.comment
现在,我们可以创建一个名为first_pool的池,初始时将所有资源(四个核心处理器)绑定到该池中,方法是运行以下命令:
root@solaris11-1:~# poolcfg -c 'create pool first_pool'
root@solaris11-1:~# poolcfg -c 'info pool first_pool'
pool first_pool
boolean pool.active true
boolean pool.default false
int pool.importance 1
string pool.comment
pset pset_default
pset pset_default
int pset.sys_id -1
boolean pset.default true
uint pset.min 1
uint pset.max 65536
string pset.units population
uint pset.load 176
uint pset.size 4
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 3
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 2
string cpu.comment
string cpu.status on-line
root@solaris11-1:~#
然后,通过执行以下命令将first_pool池分配给first_pset处理器集:
root@solaris11-1:~# poolcfg -c 'associate pool first_pool (pset first_pset)'
root@solaris11-1:~# poolcfg -c 'info pool first_pool'
pool first_pool
boolean pool.active true
boolean pool.default false
int pool.importance 1
string pool.comment
pset first_pset
pset first_pset
int pset.sys_id -2
boolean pset.default false
uint pset.min 1
uint pset.max 2
string pset.units population
uint pset.load 0
uint pset.size 0
string pset.comment
root@solaris11-1:~#
到目前为止,一切正常。现在,我们需要通过执行以下命令检查新池是否已经出现在资源内存配置中:
root@solaris11-1:~# poolcfg -c info
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool pool_default
int pool.sys_id 0
boolean pool.active true
boolean pool.default true
int pool.importance 1
string pool.comment
pset pset_default
pool first_pool
boolean pool.active true
boolean pool.default false
int pool.importance 1
string pool.comment
pset first_pset
pset pset_default
int pset.sys_id -1
boolean pset.default true
uint pset.min 1
uint pset.max 65536
string pset.units population
uint pset.load 176
uint pset.size 4
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 3
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 2
string cpu.comment
string cpu.status on-line
pset first_pset
int pset.sys_id -2
boolean pset.default false
uint pset.min 1
uint pset.max 2
string pset.units population
uint pset.load 0
uint pset.size 0
string pset.comment
我们已经意识到,first_pset配置仍未在池配置文件中持久化。要验证(-n -c选项)并提交(-c选项)新配置,请执行以下命令:
root@solaris11-1:~# pooladm -n -c
root@solaris11-1:~# pooladm -c
root@solaris11-1:~# more /etc/pooladm.conf
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE system PUBLIC "-//Sun Microsystems Inc//DTD Resource Management All//EN" "file:///usr/share/lib/xml/dtd/rm_pool.dtd.1">
<!--
Configuration for pools facility. Do NOT edit this file by hand - use poolcfg(1) or libpool(3POOL) instead.
-->
<system ref_id="dummy" name="default" comment="" version="1" bind-default="true">
<property name="system.poold.objectives" type="string">wt-load</property>
<pool name="pool_default" active="true" default="true" importance="1" comment="" res="pset_-1" ref_id="pool_0">
<property name="pool.sys_id" type="int">0</property>
</pool>
<res_comp type="pset" sys_id="-1" name="pset_default" default="true" min="1" max="65536" units="population" comment="" ref_id="pset_-1">
<property name="pset.load" type="uint">176</property>
<property name="pset.size" type="uint">4</property>
<comp type="cpu" sys_id="1" comment="" ref_id="cpu_1">
<property name="cpu.status" type="string">on-line</property>
</comp>
<comp type="cpu" sys_id="3" comment="" ref_id="cpu_3">
<property name="cpu.status" type="string">on-line</property>
</comp>
<comp type="cpu" sys_id="0" comment="" ref_id="cpu_0">
<property name="cpu.status" type="string">on-line</property>
</comp>
<comp type="cpu" sys_id="2" comment="" ref_id="cpu_2">
<property name="cpu.status" type="string">on-line</property>
</comp>
</res_comp>
<res_comp ref_id="id_0" sys_id="-2" type="pset" name="first_pset" min="1" max="2" units="population" comment="">
<property name="pset.load" type="uint">0</property>
<property name="pset.size" type="uint">0</property>
</res_comp>
<property name="system._next_id" type="uint">2</property>
<pool ref_id="id_1" res="id_0" name="first_pool" active="true" importance="1" comment=""/>
</system>
root@solaris11-1:~#
一切准备就绪。不过,使用-dc选项可以很容易验证该配置仅在内存中(内核状态)是活动的,但它并没有保存在资源池配置文件中(选项-c),如下所示:
root@solaris11-1:~# poolcfg -dc info
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool first_pool
int pool.sys_id 1
boolean pool.active true
boolean pool.default false
int pool.importance 1
string pool.comment
pset first_pset
pool pool_default
int pool.sys_id 0
boolean pool.active true
boolean pool.default true
int pool.importance 1
string pool.comment
pset pset_default
pset first_pset
int pset.sys_id 1
boolean pset.default false
uint pset.min 1
uint pset.max 2
string pset.units population
uint pset.load 0
uint pset.size 2
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
pset pset_default
int pset.sys_id -1
boolean pset.default true
uint pset.min 1
uint pset.max 65536
string pset.units population
uint pset.load 151
uint pset.size 2
string pset.comment
cpu
int cpu.sys_id 3
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 2
string cpu.comment
string cpu.status on-line
root@solaris11-1:~# poolcfg -c info
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool pool_default
int pool.sys_id 0
boolean pool.active true
boolean pool.default true
int pool.importance 1
string pool.comment
pset pset_default
pool first_pool
boolean pool.active true
boolean pool.default false
int pool.importance 1
string pool.comment
pset first_pset
pset pset_default
int pset.sys_id -1
boolean pset.default true
uint pset.min 1
uint pset.max 65536
string pset.units population
uint pset.load 176
uint pset.size 4
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 3
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 2
string cpu.comment
string cpu.status on-line
pset first_pset
int pset.sys_id -2
boolean pset.default false
uint pset.min 1
uint pset.max 2
string pset.units population
uint pset.load 0
uint pset.size 0
string pset.comment
为了解决将资源池配置从内存保存到磁盘的问题,我们可以通过运行以下命令使用-s选项:
root@solaris11-1:~# pooladm -s
root@solaris11-1:~# poolcfg -c info
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool first_pool
int pool.sys_id 1
boolean pool.active true
boolean pool.default false
int pool.importance 1
string pool.comment
pset first_pset
pool pool_default
int pool.sys_id 0
boolean pool.active true
boolean pool.default true
int pool.importance 1
string pool.comment
pset pset_default
pset first_pset
int pset.sys_id 1
boolean pset.default false
uint pset.min 1
uint pset.max 2
string pset.units population
uint pset.load 0
uint pset.size 2
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
pset pset_default
int pset.sys_id -1
boolean pset.default true
uint pset.min 1
uint pset.max 65536
string pset.units population
uint pset.load 201
uint pset.size 2
string pset.comment
cpu
int cpu.sys_id 3
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 2
string cpu.comment
string cpu.status on-line
太棒了!通过执行以下poolstat命令列出活动的资源池:
root@solaris11-1:~# poolstat
pset
id pool size used load
1 first_pool 2 0.00 0.00
0 pool_default 2 0.00 0.17
root@solaris11-1:~# poolstat -r all
id pool type rid rset min max size used load
1 first_pool pset 1 first_pset 1 2 2 0.00 0.00
0 pool_default pset -1 pset_default 1 66K 2 0.00 0.17
将最近创建的池(first_pool)关联到非全局的zone1,可以通过执行以下命令来完成:
root@solaris11-1:~# zonecfg -z zone1 info | grep pool
pool:
root@solaris11-1:~# zonecfg -z zone1 set pool=first_pool
root@solaris11-1:~# zonecfg -z zone1 info | grep pool
pool: first_pool
无法在不重启zone1的情况下激活绑定的资源池,因此执行以下命令:
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
root@solaris11-1:~# zoneadm list -iv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
1 zone2 running /myzones/zone2 solaris excl
3 zone1 running /myzones/zone1 solaris excl
现在,登录到zone1,并通过运行以下命令检查first_pool池是否已激活:
root@solaris11-1:~# zlogin zone1
[Connected to zone 'zone1' pts/3]
Oracle Corporation SunOS 5.11 11.1 September 2012
root@zone1:~# poolcfg -dc info
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool first_pool
int pool.sys_id 1
boolean pool.active true
boolean pool.default false
int pool.importance 1
string pool.comment
pset first_pset
pset first_pset
int pset.sys_id 1
boolean pset.default false
uint pset.min 1
uint pset.max 2
string pset.units population
uint pset.load 540
uint pset.size 2
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
root@zone1:~# psrinfo
0 on-line since 02/01/2014 12:23:05
1 on-line since 02/01/2014 12:23:07
root@zone1:~# psrinfo -v
Status of virtual processor 0 as of: 02/01/2014 15:52:47
on-line since 02/01/2014 12:23:05.
The i386 processor operates at 2470 MHz,
and has an i387 compatible floating point processor.
Status of virtual processor 1 as of: 02/01/2014 15:52:47
on-line since 02/01/2014 12:23:07.
The i386 processor operates at 2470 MHz,
and has an i387 compatible floating point processor.
完美!两个核心已与zone1关联,任何在此区域内运行的应用程序都可以使用这些核心处理器。
要改变资源类型的焦点,有一个非常有趣的方法是限制使用的内存,称为资源限制,这有助于我们限制物理内存、交换内存和锁定内存。
例如,使用相同的zone1,通过执行以下命令来更改其配置:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> add capped-memory
zonecfg:zone1:capped-memory> set physical=1G
zonecfg:zone1:capped-memory> set swap=500M
zonecfg:zone1:capped-memory> end
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@solaris11-1:~# zonecfg -z zone1 info
zonename: zone1
zonepath: /myzones/zone1
brand: solaris
autoboot: true
(truncated)
capped-memory:
physical: 1G
[swap: 500M]
rctl:
name: zone.max-swap
value: (priv=privileged,limit=524288000,action=deny)
root@solaris11-1:~#
根据之前的输出,zone1的物理内存限制为 1GB,已使用的交换空间限制为 500MB。此外,还存在一个关于最大交换空间的奇怪行:
value: (priv=privileged,limit=524288000,action=deny)
该行的解释如下:
-
privileged:只有特权用户(root)才能修改。另一个可能的值是basic(仅所有者可以修改)。 -
deny:此设置可以拒绝任何超过限制值(500 MB)的资源请求。其他选项包括none(即使请求的资源超过限制,也不采取任何行动)和signal(当超过阈值时发送信号)。
资源限制是由 rcapd 守护进程实现的服务,可以通过以下命令启用此服务:
root@solaris11-1:~# svcs -a | grep rcap
disabled 21:56:20 svc:/system/rcap:default
root@solaris11-1:~# svcs -d svc:/system/rcap:default
STATE STIME FMRI
online 21:56:31 svc:/system/filesystem/minimal:default
online 21:56:33 svc:/system/resource-mgmt:default
online 21:56:35 svc:/system/manifest-import:default
root@solaris11-1:~# svcadm enable svc:/system/rcap:default
root@solaris11-1:~# svcs - a | grep rcap
online 22:52:06 svc:/system/rcap:default
root@solaris11-1:~# svcs -p svc:/system/rcap:default
STATE STIME FMRI
online 22:52:06 svc:/system/rcap:default
22:52:06 5849 rcapd
重启 zone1 以使内存限制生效。现在可以通过运行以下命令启用资源限制守护进程,而无需重启:
root@solaris11-1:~# rcapadm -E -n
要监控 rcap 守护进程(rcapd)的操作,请执行以下命令:
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
root@solaris11-1:~# zoneadm list -iv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
1 zone2 running /myzones/zone2 solaris excl
3 zone1 running /myzones/zone1 solaris excl
root@solaris11-1:~# rcapstat -z
id zone nproc vm rss cap at avgat pg avgpg
3 zone1 - 26M 38M 1024M 0K 0K 0K 0K
3 zone1 - 31M 44M 1024M 0K 0K 0K 0K
3 zone1 - 31M 44M 1024M 0K 0K 0K 0K
已使用的物理内存(RSS)低于内存限制值(1024 MB)。如果物理内存增加,则其限制为 1024 MB。好极了!
为了使这个示例更具吸引力,可以进行一些修改。我们从 zone1 中移除 first_pool 资源池(以及任何其他现有池)。另外,first_pool 池将通过 pooladm -x 命令被删除。显然,新的池配置必须通过 pooladm -s 命令保存。以下是步骤:
root@solaris11-1:~# zonecfg -z zone1 clear pool
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
root@solaris11-1:~# pooladm -x
root@solaris11-1:~# pooladm -s
root@solaris11-1:~# pooladm
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool pool_default
int pool.sys_id 0
boolean pool.active true
boolean pool.default true
int pool.importance 1
string pool.comment
pset pset_default
pset pset_default
int pset.sys_id -1
boolean pset.default true
uint pset.min 1
uint pset.max 65536
string pset.units population
uint pset.load 15511
uint pset.size 4
string pset.comment
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 3
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 2
string cpu.comment
string cpu.status on-line
一切已恢复到默认状态,从此以后,zone1 不再有特定关联的资源池。这使得我们可以从现在开始专注于 FSS。
以下命令检查当前的默认内核调度类是什么:
root@solaris11-1:~# dispadmin -d
dispadmin: Default scheduling class is not set
没有默认的调度类。如果我们想使用 FSS,那么最好在全局区域配置它,因为这个设置会被所有非全局区域继承。按照上述说明配置 FSS,执行以下命令:
root@solaris11-1:~# dispadmin -d FSS
root@solaris11-1:~# dispadmin -d
FSS (Fair Share)
此设置仅在系统重启后生效。系统重新启动后,所有进程将被归类为 FSS。然而,如果不重启也要立即生效,请执行以下命令:
root@solaris11-1:~# priocntl -s -c FSS
不幸的是,所有当前进程仍然在其他调度类下运行,只有新进程会采用 FSS 设置。可以通过运行以下命令来验证这一点:
root@solaris11-1:~# ps -efcZ | more
ZONE UID PID PPID CLS PRI STIME TTY TIME CMD
global root 0 0 SYS 96 00:04:41 ? 0:01 sched
global root 5 0 SDC 99 00:04:38 ? 0:07 zpool-rpool
global root 6 0 SDC 99 00:04:42 ? 0:01 kmem_task
global root 1 0 TS 59 00:04:42 ? 0:00 /usr/sbin/init
global root 2 0 SYS 98 00:04:42 ? 0:00 pageout
global root 3 0 SYS 60 00:04:42 ? 0:00 fsflush
global root 7 0 SYS 60 00:04:42 ? 0:00 intrd
global root 8 0 SYS 60 00:04:42 ? 0:00 vmtasks
global root 115 1 TS 59 00:05:09 ? 0:00 /usr/lib/pfexecd
global root 11 1 TS 59 00:04:48 ? 0:13 /lib/svc/bin/svc.startd
global root 13 1 TS 59 00:04:48 ? 0:33 /lib/svc/bin/svc.configd
global root 911 1 TS 59 02:05:55 ? 0:00
(truncated output)
同样,也不需要等到下一次重启。因此,可以通过执行以下命令将所有进程从当前的调度类移动到 FSS:
root@solaris11-1:~# priocntl -s -c FSS -i all
root@solaris11-1:~# ps -efcZ | more
ZONE UID PID PPID CLS PRI STIME TTY TIME CMD
global root 0 0 SYS 96 00:04:41 ? 0:01 sched
global root 5 0 SDC 99 00:04:38 ? 0:12 zpool-rpool
global root 6 0 SDC 99 00:04:42 ? 0:02 kmem_task
global root 1 0 FSS 29 00:04:42 ? 0:00 /usr/sbin/init
global root 2 0 SYS 98 00:04:42 ? 0:00 pageout
global root 3 0 SYS 60 00:04:42 ? 0:01 fsflush
global root 7 0 SYS 60 00:04:42 ? 0:00 intrd
global root 8 0 SYS 60 00:04:42 ? 0:00 vmtasks
global root 115 1 FSS 29 00:05:09 ? 0:00 /usr/lib/pfexecd
global root 11 1 FSS 29 00:04:48 ? 0:13 /lib/svc/bin/svc.startd
global root 13 1 FSS 29 00:04:48 ? 0:33 /lib/svc/bin/svc.configd
(truncated output)
当 FSS 设置为全局区域的默认调度类时,所有非全局区域都会自动采用此配置。验证此配置,请运行以下命令:
root@solaris11-1:~# zlogin zone1
[Connected to zone 'zone1' pts/4]
Oracle Corporation SunOS 5.11 11.1 September 2012
root@zone1:~# ps -efcZ | more
ZONE UID PID PPID CLS PRI STIME TTY TIME CMD
zone1 root 3944 2454 FSS 29 02:06:47 ? 0:00 /usr/sbin/init
zone1 root 4284 2454 FSS 29 02:06:58 ? 0:06 /lib/svc/bin/svc.startd
zone1 root 2454 2454 SYS 60 02:06:29 ? 0:00 zsched
zone1 root 5479 2454 FSS 59 02:48:52 pts/4 0:00 /usr/bin/login -z global -f root
zone1 root 4287 2454 FSS 29 02:07:00 ? 0:21 /lib/svc/bin/svc.configd
zone1 netcfg 4448 2454 FSS 29 02:07:27 ? 0:00 /lib/inet/netcfgd
zone1 root 4922 2454 FSS 29 02:08:21 ? 0:00
(truncated output)
我们可以意识到,zone1 中的所有主进程都处于 FSS 类中。无论如何,建议在非全局设置中显式配置 FSS 类,以防止将来可能的错误。因此,执行以下命令:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> set scheduling-class=FSS
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@solaris11-1:~#
root@solaris11-1:~# zonecfg -z zone2
zonecfg:zone2> set scheduling-class=FSS
zonecfg:zone2> verify
zonecfg:zone2> commit
zonecfg:zone2> exit
root@solaris11-1:~#
最后,现在是使用 FSS 类来为每个区域(zone1 和 zone2)配置共享资源的正确时机。这样,就可以将 CPU 处理的 70% 分配给 zone1,将剩余的 30% 分配给 zone2。以下是操作步骤:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> add rctl
zonecfg:zone1:rctl> set name=zone.cpu-shares
zonecfg:zone1:rctl> add value (priv=privileged, limit=70,action=none)
zonecfg:zone1:rctl> end
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@solaris11-1:~# zonecfg -z zone2
zonecfg:zone2> add rctl
zonecfg:zone2:rctl> set name=zone.cpu-shares
zonecfg:zone2:rctl> add value (priv=privileged,limit=30,action=none)
zonecfg:zone2:rctl> end
zonecfg:zone2> verify
zonecfg:zone2> commit
zonecfg:zone2> exit
这太棒了!通过zonecfg命令,以持久的方式将共享分配给了zone1(70 个共享)和zone2(30 个共享)。要使这两个区域生效,请执行以下命令:
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
root@solaris11-1:~# zoneadm -z zone2 shutdown -r
可以通过以下命令跟踪和监控处理器的使用时间:
root@solaris11-1:~# prstat -Z
PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP
4466 root 216M 98M sleep 59 0 0:00:41 0.7% java/25
4702 root 129M 19M sleep 59 0 0:00:06 0.5% gnome-terminal/2
rcapd/1
5 root 0K 0K sleep 99 -20 0:00:19 0.2% zpool-rpool/138
898 root 53M 18M sleep 53 0 0:00:06 0.1% poold/9
(omitted output)
automountd/2
198 root 1780K 788K sleep 29 0 0:00:00 0.0% utmpd/1
945 root 2392K 1552K sleep 59 0 0:00:00 0.0% ttymon/1
ZONEID NPROC SWAP RSS MEMORY TIME CPU ZONE
0 117 2885M 794M 9.5% 0:03:28 2.5% global
2 28 230M 62M 0.7% 0:00:30 0.1% zone1
1 28 230M 64M 0.7% 0:00:29 0.1% zone2
令人惊讶的是,能够动态地更改zone.cpu-shares属性,而无需重新启动区域,但这种更改是非持久性的(所有更改在重启后会丢失)。可以通过运行以下命令来完成:
root@solaris11-1:~# prctl -n zone.cpu-shares -v 60 -r -i zone zone1
root@solaris11-1:~# prctl -n zone.cpu-shares -P -i zone zone1
zone: 3: zone1
zone.cpu-shares usage 60 - - -
zone.cpu-shares privileged 60 - none -
zone.cpu-shares system 65535 max none -
root@solaris11-1:~# prctl -n zone.cpu-shares -v 40 -r -i zone zone2
root@solaris11-1:~# prctl -n zone.cpu-shares -P -i zone zone2
zone: 4: zone2
zone.cpu-shares usage 40 - - -
zone.cpu-shares privileged 40 - none -
zone.cpu-shares system 65535 max none -
root@solaris11-1:~#
为了在 5 秒钟的间隔内收集来自两个区域的内存和 CPU 信息,请执行以下命令:
root@solaris11-1:~# zonestat -z zone1,zone2 -r physical-memory 5
Collecting data for first interval...
Interval: 1, Duration: 0:00:05
PHYSICAL-MEMORY SYSTEM MEMORY
mem_default 8191M
ZONE USED %USED CAP %CAP
[total] 1464M 17.8% - -
[system] 624M 7.62% - -
zone2 63.9M 0.78% - -
zone1 3561K 0.04% 1024M 0.33%
Interval: 2, Duration: 0:00:10
PHYSICAL-MEMORY SYSTEM MEMORY
mem_default 8191M
ZONE USED %USED CAP %CAP
[total] 1464M 17.8% - -
[system] 624M 7.62% - -
zone2 63.9M 0.78% - -
zone1 3485K 0.04% 1024M 0.33%
Removing all configured shares is quickly executed by running:
root@solaris11-1:~# zonecfg -z zone1 clear cpu-shares
root@solaris11-1:~# zonecfg -z zone2 clear cpu-shares
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
root@solaris11-1:~# zoneadm -z zone2 shutdown -r
根据我们对资源管理器的讨论,存在一个名为dedicated-cpu的区域资源,在该资源中,可以为非全局区域指定一组处理器(或核心)。例如,以下示例向我们展示了zone1可以根据需求使用一个到四个处理器(ncpus=1-4),当与其他区域或配置竞争资源时,该设置的importance值为8。这个智能的设置会创建一个临时池,包含其中所需的处理器。以下是步骤:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> add dedicated-cpu
zonecfg:zone1:dedicated-cpu> set ncpus=1-4
zonecfg:zone1:dedicated-cpu> set importance=8
zonecfg:zone1:dedicated-cpu> end
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
root@solaris11-1:~# zlogin zone1
[Connected to zone 'zone1' pts/2]
Oracle Corporation SunOS 5.11 11.1 September 2012
root@zone1:~# pooladm
system default
string system.comment
int system.version 1
boolean system.bind-default true
string system.poold.objectives wt-load
pool SUNWtmp_zone1
int pool.sys_id 1
boolean pool.active true
boolean pool.default false
int pool.importance 8
string pool.comment
boolean pool.temporary true
pset SUNWtmp_zone1
pset SUNWtmp_zone1
int pset.sys_id 1
boolean pset.default false
uint pset.min 1
uint pset.max 4
string pset.units population
uint pset.load 4
uint pset.size 2
string pset.comment
boolean pset.temporary true
cpu
int cpu.sys_id 1
string cpu.comment
string cpu.status on-line
cpu
int cpu.sys_id 0
string cpu.comment
string cpu.status on-line
真棒!要从 zone1 移除 dedicated-cpu 资源,请执行以下命令:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> remove dedicated-cpu
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
在继续之前,我们必须通过执行以下命令重新启动该区域:
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
另一种控制区域资源的好方法是使用capped-cpu资源,这允许我们指定区域可以使用 CPU 的百分比。要指定的值表示 CPU 的百分比,可以通过执行以下步骤来实现:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> add capped-cpu
zonecfg:zone1:capped-cpu> set ncpus=2.5
zonecfg:zone1:capped-cpu> end
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
根据先前的配置,ncpus=2.5属性意味着 250% 的 CPU 或 2.5 个 CPU。要移除最近添加的资源,请执行以下命令:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> remove capped-cpu
zonecfg:zone1:capped-cpu> end
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
在所有更改之后,我们必须通过执行以下命令来重新启动该区域:
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
这真是太棒了!我们已经进行了许多资源管理的试验,所有的试验都成功了!由于zone1仍然存在资源限制(内存),现在是时候将其移除:
root@solaris11-1:~# zonecfg -z zone1
zonecfg:zone1> remove capped-memory
zonecfg:zone1> verify
zonecfg:zone1> commit
zonecfg:zone1> exit
root@solaris11-1:~# zoneadm -z zone1 shutdown -r
最后,可以通过执行以下命令来禁用资源限制功能:
root@solaris11-1:~# svcs -a | grep rcap
online 18:49:28 svc:/system/rcap:default
root@solaris11-1:~# rcapadm -D
state: disabled
memory cap enforcement threshold: 0%
process scan rate (sec): 15
reconfiguration rate (sec): 60
report rate (sec): 5
RSS sampling rate (sec): 5
root@solaris11-1:~# svcs -a | grep rcap
disabled 19:28:33 svc:/system/rcap:default
禁用资源限制功能的另一种方法是执行以下命令:
root@solaris11-1:~# svcadm disable svc:/system/rcap:default
完美!一切已经恢复到最初的设置。
配方概览
这一部分内容非常长,我们可以学习到很多关于资源管理控制的细节,以及如何限制处理器和内存。在下一章中,我们将讨论网络资源控制。
实施流量控制
在上一小节中,我们处理了处理器和内存的资源控制。在 Oracle Solaris 11 中,网络控制变得越来越重要和相关,使我们能够根据 TCP/IP 服务和端口设置网络流量控制。请继续阅读下一页了解更多信息。
准备工作
本食谱要求一个运行 Oracle Solaris 11 的虚拟机(VMware 或 VirtualBox),配置为一个处理器,4 GB RAM 和一个物理网络接口。为了简化操作,我们将重用与之前食谱相同的环境。
如何操作……
为了能够遵循本节中的步骤,您需要检查当前的环境设置。因此,可以通过运行以下命令收集有关现有虚拟接口、虚拟交换机和网络接口的信息:
root@solaris11-1:~# dladm show-vnic
LINK OVER SPEED MACADDRESS MACADDRTYPE VID
vnic0 vswitch1 40000 2:8:20:d:b:3b random 0
vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
zone1/vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone2/vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone2/net0 net0 1000 2:8:20:f3:29:68 random 0
zone1/net0 net0 1000 2:8:20:ac:7d:b1 random 0
root@solaris11-1:~# dladm show-link
LINK CLASS MTU STATE OVER
net1 phys 1500 up --
net0 phys 1500 up --
vswitch1 etherstub 9000 unknown --
vnic0 vnic 9000 up vswitch1
vnic1 vnic 9000 up vswitch1
zone1/vnic1 vnic 9000 up vswitch1
vnic2 vnic 9000 up vswitch1
zone2/vnic2 vnic 9000 up vswitch1
zone2/net0 vnic 1500 up net0
zone1/net0 vnic 1500 up net0
由于现有的虚拟接口当前分配给非全局区域,请创建一个新的虚拟接口(VNIC),并通过执行以下命令将其与vswitch虚拟交换机关联:
root@solaris11-1:~# dladm create-vnic -l vswitch1 vnic5
root@solaris11-1:~# dladm show-vnic
LINK OVER SPEED MACADDRESS MACADDRTYPE VID
vnic0 vswitch1 40000 2:8:20:d:b:3b random 0
vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
zone1/vnic vswitch1 40000 2:8:20:ef:b6:63 random 0
vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone2/vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone2/net0 net0 1000 2:8:20:f3:29:68 random 0
zone1/net0 net0 1000 2:8:20:ac:7d:b1 random 0
vnic5 vswitch1 40000 2:8:20:c0:9a:f7 random 0
在vnic5上创建两个流量控制:第一个控制端口80的 TCP 流,第二个控制相同端口80的 UDP 流,通过执行以下命令:
root@solaris11-1:~# flowadm show-flow
root@solaris11-1:~# flowadm add-flow -l vnic5 -a transport=tcp,local_port=80 http_tcp_1
root@solaris11-1:~# flowadm add-flow -l vnic5 -a transport=udp,local_port=80 http_udp_1
root@solaris11-1:~# flowadm show-flow
FLOW LINK IPADDR PROTO LPORT RPORT DSFLD
http_tcp_1 vnic5 -- tcp 80 -- --
http_udp_1 vnic5 -- udp 80 -- --
根据之前的输出,我们将流量控制命名为http_tcp_1和http_udp_1;两者都控制 HTTP 数据,并分别使用 TCP 和 UDP 作为传输协议。因此,适合为此 HTTP 流绑定一个新属性,控制最大带宽并将其限制为 50 MBps。为此,请执行以下命令:
root@solaris11-1:~# flowadm set-flowprop -p maxbw=50M http_tcp_1
root@solaris11-1:~# flowadm set-flowprop -p maxbw=50M http_udp_1
root@solaris11-1:~# flowadm show-flowprop
FLOW PROPERTY VALUE DEFAULT POSSIBLE
http_tcp_1 maxbw 50 -- --
http_udp_1 maxbw 50 -- --
root@solaris11-1:~#
我们已将端口80(TCP 和 UDP)的带宽限制设置为最大 50 MBps。可以通过执行以下命令,在两秒的间隔内监控接收的包(如本食谱所示):
root@solaris11-1:~# flowstat -r http_tcp_1 -i 2
FLOW IPKTS RBYTES IDROPS
http_tcp_1 0 0 0
http_tcp_1 0 0 0
http_tcp_1 0 0 0
http_tcp_1 0 0 0
此外,建议您通过运行以下命令分析更完整的视图,包括发送和接收的包:
root@solaris11-1:~# flowstat -i 2
FLOW IPKTS RBYTES IDROPS OPKTS OBYTES ODROPS
http_tcp_1 0 0 0 0 0 0
http_udp_1 0 0 0 0 0 0
http_tcp_1 0 0 0 0 0 0
http_udp_1 0 0 0 0 0 0
http_tcp_1 0 0 0 0 0 0
http_udp_1 0 0 0 0 0 0
最后,要从系统和vnic5接口中移除这两个流量控制,请执行以下命令:
root@solaris11-1:~# flowadm
FLOW LINK IPADDR PROTO LPORT RPORT DSFLD
http_tcp_1 vnic5 -- tcp 80 -- --
http_udp_1 vnic5 -- udp 80 -- --
root@solaris11-1:~# flowadm remove-flow http_tcp_1
root@solaris11-1:~# flowadm remove-flow http_udp_1
root@solaris11-1:~# flowadm show-flow
root@solaris11-1:~# dladm delete-vnic vnic5
root@solaris11-1:~# dladm show-vnic
LINK OVER SPEED MACADDRESS MACADDRTYPE VID
vnic0 vswitch1 40000 2:8:20:d:b:3b random 0
vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
zone1/vnic1 vswitch1 40000 2:8:20:ef:b6:63 random 0
vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone2/vnic2 vswitch1 40000 2:8:20:ce:b0:da random 0
zone2/net0 net0 1000 2:8:20:f3:29:68 random 0
zone1/net0 net0 1000 2:8:20:ac:7d:b1 random 0
食谱概览
本食谱展示了如何在虚拟网络接口(VNICs)上实施、监控和取消配置流量,并将 TCP 和 UDP 协议在端口80上的带宽限制为 50 MBps。
从物理 Oracle Solaris 10 主机迁移到 Oracle Solaris 11 Zones
在考虑如何部署 Oracle Solaris 11 时,会出现两个常见问题。首先,我们该如何处理之前的 Oracle Solaris 10 安装?其次(更糟糕的是),Oracle Solaris 10 Zones 能做什么?
幸运的是,Oracle Solaris 11 为这两种情况提供了最佳解决方案:物理到虚拟(P2V)迁移,将物理的 Oracle Solaris 10 安装迁移到 Oracle Solaris 11 Zone,以及虚拟到虚拟(V2V)迁移,将 Oracle Solaris 10 本地区域迁移到 Oracle Solaris 11 中的 Solaris 10 品牌区域。
准备工作
本教程需要一台虚拟机(VirtualBox 或 VMware)并安装有 Oracle Solaris 11,8 GB 内存,以及足够的磁盘空间(大约 10 GB)。为了简化操作,将使用之前教程中的 myzone 池,如果您已删除它,应该使用 zpool create myzone <disks> 命令重新创建它。此外,必须有一台 Oracle Solaris 10 虚拟机(至少 2 GB 内存和一个至少 15 GB 的虚拟磁盘),用于本次迁移示例。本教程将不展示如何安装这台 Oracle Solaris 10 虚拟机。您可以从 www.oracle.com/technetwork/server-storage/solaris10/downloads/index.html?ssSourceSiteId=ocomau 下载 Oracle Solaris 10 DVD,用于安装和部署。
我们的任务是将一个物理的(全局区域)Oracle Solaris 10 主机(没有任何非全局区域)迁移到 Oracle Solaris 11 区域。将一个 Oracle Solaris 10 原生区域迁移到 Oracle Solaris 11 品牌 10 区域的步骤非常相似,这里不再展示。
如何操作…
为了将一个物理的 Oracle Solaris 10(全局区域)迁移到 Oracle Solaris 11 的 Solaris 10 品牌区域,建议在执行迁移步骤之前收集关于 Oracle Solaris 10 的信息(例如主机名、主机 ID、内存大小、操作系统版本、可用磁盘等)。从现在开始,每次看到 bash-3.2# 提示符时,意味着我们正在处理 Oracle Solaris 10。这些信息可以通过执行以下简单命令收集:
# bash
bash-3.2# uname -a
SunOS solaris10 5.10 Generic_147148-26 i86pc i386 i86pc
bash-3.2# hostname
solaris10
bash-3.2# ping 192.168.1.1
192.168.1.1 is alive
bash-3.2# hostid
37e12f92
bash-3.2# prtconf | grep -i memory
Memory size: 2048 Megabytes
bash-3.2# more /etc/release
Oracle Solaris 10 1/13 s10x_u11wos_24a X86
Copyright (c) 1983, 2013, Oracle and/or its affiliates. All rights reserved.
Assembled 17 January 2013
bash-3.2# ifconfig -a
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
e1000g0: flags=1004843<UP,BROADCAST,RUNNING,MULTICAST,DHCP,IPv4> mtu 1500 index 2
inet 192.168.1.108 netmask ffffff00 broadcast 192.168.1.255
ether 8:0:27:49:c4:39
bash-3.2#
bash-3.2# zpool list
no pools available
bash-3.2# df -h
Filesystem size used avail capacity Mounted on
/dev/dsk/c0t0d0s0 37G 4.2G 33G 12% /
/devices 0K 0K 0K 0% /devices
ctfs 0K 0K 0K 0% /system/contract
proc 0K 0K 0K 0% /proc
mnttab 0K 0K 0K 0% /etc/mnttab
swap 3.1G 992K 3.1G 1% /etc/svc/volatile
objfs 0K 0K 0K 0% /system/object
sharefs 0K 0K 0K 0% /etc/dfs/sharetab
/usr/lib/libc/libc_hwcap1.so.1
37G 4.2G 33G 12% /lib/libc.so.1
fd 0K 0K 0K 0% /dev/fd
swap 3.1G 72K 3.1G 1% /tmp
swap 3.1G 32K 3.1G 1% /var/run
bash-3.2# format
Searching for disks...done
AVAILABLE DISK SELECTIONS:
0\. c0t0d0 <ATA -VBOX HARDDISK -1.0 cyl 5218 alt 2 hd 255 sec 63>
/pci@0,0/pci8086,2829@d/disk@0,0
Specify disk (enter its number): ^D
bash-3.2#
既然我们已经收集了所有来自 Oracle Solaris 10 虚拟机的必要信息,接下来执行 zonep2vchk 命令,以验证 P2V 迁移的兼容性以及此操作是否可行:
bash-3.2# zonep2vchk -b
--Executing Version: 5.10.1.1
- Source System: solaris10
Solaris Version: Oracle Solaris 10 1/13 s10x_u11wos_24a X86
Solaris Kernel: 5.10 Generic_147148-26
Platform: i86pc i86pc
- Target System:
Solaris Version: Solaris 10
Zone Brand: native (default)
IP type: shared
--Executing basic checks
- The following SMF services will not work in a zone:
svc:/network/iscsi/initiator:default
svc:/system/iscsitgt:default
- The following SMF services require ip-type "exclusive" to work in
a zone. If they are needed to support communication after migrating
to a shared-IP zone, configure them in the destination system's global
zone instead:
svc:/network/ipsec/ipsecalgs:default
svc:/network/ipsec/policy:default
svc:/network/routing-setup:default
- When migrating to an exclusive-IP zone, the target system must have an
available physical interface for each of the following source system
interfaces:
e1000g0
- When migrating to an exclusive-IP zone, interface name changes may
impact the following configuration files:
/etc/hostname.e1000g0
/etc/dhcp.e1000g0
- Dynamically assigned IP addresses are configured on the following
interfaces. These addresses are not supported with shared-IP zones.
Use an exclusive-IP zone or replace any dynamically assigned addresses
with statically assigned addresses. These IP addresses could change
as a result of MAC address changes. You may need to modify this
system's address information on the DHCP server and on the DNS,
LDAP, or NIS name servers:
DHCP assigned address on: e1000g0
Basic checks complete. Issue(s) detected: 9
--Total issue(s) detected: 9
没有发现关键性问题(建议您逐行检查此报告),所以我们可以继续执行迁移操作,通过执行以下一系列命令来创建一个区域配置文件:
bash-3.2# mkdir /migration
bash-3.2# zonep2vchk -c > /migration/solaris10.cfg
bash-3.2# vi /migration/solaris10.cfg
bash-3.2# more /migration/solaris10.cfg
create -b
set zonepath=/zones/solaris10
add attr
set name="zonep2vchk-info"
set type=string
set value="p2v of host solaris10"
end
set ip-type=shared
# Uncomment the following to retain original host hostid:
# set hostid=37e12f92
# maximum lwps based on max_uproc/v_proc
set max-lwps=57140
add attr
set name=num-cpus
set type=string
set value="original system had 1 cpus"
end
# Only one of dedicated or capped CPU can be used.
# Uncomment the following to use capped CPU:
# add capped-cpu
# set ncpus=1.0
# end
# Uncomment the following to use dedicated CPU:
# add dedicated-cpu
# set ncpus=1
# end
# Uncomment the following to use memory caps.
# Values based on physical memory plus swap devices:
# add capped-memory
# set physical=2048M
# set swap=6142M
# end
# Original configuration for interface: e1000g0:
# Statically defined ip address: 192.168.1.108 (solaris10)
# * DHCP assigned ip address: 192.168.1.108/24 (solaris10)
# MAC address: Factory assigned: 8:0:27:49:c4:39
# Unable to migrate addresses marked with "*".
# Shared IP zones require statically assigned addresses.
add net
set address=solaris10
set physical=change-me
end
exit
bash-3.2#
从这个文件中,进行了一些修改,具体变化请参见以下命令行(加粗部分,易于理解)。新的迁移配置文件看起来如下输出:
bash-3.2# vi /migration/solaris10.cfg
#create -b
create -t SYSsolaris10
#set zonepath=/zones/solaris10
set zonepath=/myzones/solaris10
add attr
set name="zonep2vchk-info"
set type=string
set value="p2v of host solaris10"
end
set ip-type=shared
remove anet
# Uncomment the following to retain original host hostid:
set hostid=37e12f92
# maximum lwps based on max_uproc/v_proc
set max-lwps=57140
add attr
set name=num-cpus
set type=string
set value="original system had 1 cpus"
end
# Only one of dedicated or capped CPU can be used.
# Uncomment the following to use capped CPU:
# add capped-cpu
# set ncpus=1.0
# end
# Uncomment the following to use dedicated CPU:
# add dedicated-cpu
# set ncpus=1
# end
# Uncomment the following to use memory caps.
# Values based on physical memory plus swap devices:
# add capped-memory
# set physical=2048M
# set swap=1024M
# end
# Original configuration for interface: e1000g0:
# Statically defined ip address: 192.168.1.108 (solaris10)
# * DHCP assigned ip address: 192.168.1.108/24 (solaris10)
# MAC address: Factory assigned: 8:0:27:49:c4:39
# Unable to migrate addresses marked with "*".
# Shared IP zones require statically assigned addresses.
add net
set address=192.168.1.124
set physical=net0
end
exit
在继续操作之前,我们需要通过运行以下命令验证是否只有一个全局区域(我们的初衷是迁移一个没有包含内部区域的 Oracle Solaris 10 主机):
bash-3.2# zoneadm list -iv
ID NAME STATUS PATH BRAND IP
0 global running / native shared
很棒!现在,是时候从原始的 Oracle Solaris 10 全局区域创建一个镜像(solaris10.flar),并排除保存镜像的目录(-x /migration),以防止递归效应,通过执行以下命令:
bash-3.2# flarcreate -S -n solaris10 -x /migration /migration/solaris10.flar
Full Flash
Checking integrity...
Integrity OK.
Running precreation scripts...
Precreation scripts done.
Creating the archive...
8417435 blocks
Archive creation complete.
Running postcreation scripts...
Postcreation scripts done.
Running pre-exit scripts...
Pre-exit scripts done.
等待一段时间后,通过运行以下命令检查已创建的文件:
bash-3.2# ls -lh /migration/solaris10.flar
-rw-r--r-- 1 root root 4.0G Feb 11 17:32 /migration/solaris10.flar
这个 FLAR 镜像将在后续步骤中从 Oracle Solaris 11 机器中使用,且重要的是通过执行以下命令共享其目录:
bash-3.2# share /migration
bash-3.2# share
- /migration rw ""
切换到另一台机器(solaris11-1),该机器运行的是 Oracle Solaris 11,需要创建一个 ZFS 文件系统,将 Oracle Solaris 10 安装迁移到该文件系统作为非全局区域。因此,请执行以下命令:
root@solaris11-1:~# zfs create myzones/solaris10
root@solaris11-1:~# zfs list myzones/solaris10
NAME USED AVAIL REFER MOUNTPOINT
myzones/solaris10 31K 77.4G 31K /myzones/solaris10
由于 solaris10.flar 镜像将被访问,以便将 Oracle Solaris 10 内容从 Oracle Solaris 10 物理主机传输过来,因此必须通过执行以下命令,验证从 Oracle Solaris 11 主机(solaris11-1)连接到 NFS 共享(/migration):
root@solaris11-1:~# showmount -e 192.168.1.108
export list for 192.168.1.108:
/migration (everyone)
root@solaris11-1:~#
是时候执行迁移步骤了。通过运行以下命令,将 NFS 共享挂载到 /mnt:
root@solaris11-1:~# mount -F nfs 192.168.1.108:/migration /mnt
root@solaris11-1:~# df -h | grep migration
192.168.1.108:/migration 37G 8.2G 29G 23% /mnt
使用之前步骤中创建的保存的 Solaris 10 配置文件(solaris10.cfg),在 Oracle Solaris 11 主机(solaris11-1)中创建非全局区域,命令如下:
root@solaris11-1:~# zonecfg -z solaris10 -f /mnt/solaris10.cfg
root@solaris11-1:~# zonecfg -z solaris10 info
zonename: solaris10
zonepath: /myzones/solaris10
brand: solaris10
autoboot: false
bootargs:
pool:
limitpriv:
scheduling-class:
ip-type: shared
hostid: 37e12f92
fs-allowed:
[max-lwps: 57140]
net:
address: 192.168.1.124
allowed-address not specified
configure-allowed-address: true
physical: net0
defrouter not specified
attr:
name: zonep2vchk-info
type: string
value: "p2v of host solaris10"
attr:
name: num-cpus
type: string
value: "original system had 1 cpus"
rctl:
name: zone.max-lwps
value: (priv=privileged,limit=57140,action=deny)
最后,我们通过运行以下命令,使用 solaris10.flar 镜像安装该区域:
root@solaris11-1:~# zoneadm -z solaris10 install -a /mnt/solaris10.flar -u
/myzones/solaris10 must not be group readable.
/myzones/solaris10 must not be group executable.
/myzones/solaris10 must not be world readable.
/myzones/solaris10 must not be world executable.
changing zonepath permissions to 0700.
Progress being logged to /var/log/zones/zoneadm.20140212T033711Z.solaris10.install
Installing: This may take several minutes...
Postprocessing: This may take a while...
Postprocess: Updating the image to run within a zone
Result: Installation completed successfully.
Log saved in non-global zone as /myzones/solaris10/root/var/log/zones/zoneadm.20140212T033711Z.solaris10.install
在上一步之后,建议您通过执行以下命令验证 solaris10 区域是否已正确安装和配置:
root@solaris11-1:~# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
1 zone1 running /myzones/zone1 solaris excl
2 zone2 running /myzones/zone2 solaris excl
- solaris10 installed /myzones/solaris10 solaris10 shared
root@solaris11-1:~# zoneadm -z solaris10 boot
zone 'solaris10': WARNING: net0: no matching subnet found in netmasks(4): 192.168.1.124; using default of 255.255.255.0.
zone 'solaris10': Warning: "/usr/lib/netsvc/rstat/rpc.rstatd" is not installed in the global zone
启动区域后,请再次运行以下命令检查其状态:
root@solaris11-1:~# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
1 zone1 running /myzones/zone1 solaris excl
2 zone2 running /myzones/zone2 solaris excl
4 solaris10 running /myzones/solaris10 solaris10 shared
登录到新区域并验证它是一个 Oracle Solaris 10 安装,如下所示:
root@solaris11-1:~# zlogin solaris10
[Connected to zone 'solaris10' pts/2]
Last login: Tue Feb 11 16:04:11 on console
Oracle Corporation SunOS 5.10 Generic Patch January 2005
# bash
bash-3.2# uname -a
SunOS solaris10 5.10 Generic_Virtual i86pc i386 i86pc
bash-3.2# more /etc/release
Oracle Solaris 10 1/13 s10x_u11wos_24a X86
Copyright (c) 1983, 2013, Oracle and/or its affiliates. All rights reserved.
Assembled 17 January 2013
bash-3.2# ping 192.168.1.1
192.168.1.1 is alive
bash-3.2#
这真是太棒了!我们已经成功将 Oracle Solaris 10 主机迁移到 Oracle Solaris 11 主机中的 solaris10 品牌区域。
过程概述
我们没有使用额外或外部工具,学会了如何通过使用 zonep2vchk、flarcreate 和 zonecfg 命令将 Oracle Solaris 10 物理主机迁移到 Oracle Solaris 11 非全局区域。
参考资料
-
Oracle Solaris SDN 和 网络虚拟化 可参考
www.oracle.com/technetwork/server-storage/solaris11/technologies/networkvirtualization-312278.html -
Oracle Solaris 11.1 管理:Oracle Solaris 区域、Oracle Solaris 10 区域及资源管理 (
docs.oracle.com/cd/E26502_01/html/E29024/toc.html)可参考docs.oracle.com/cd/E26502_01/html/E29024/z.conf.start-2.html#scrolltoc -
在 Oracle Solaris 11.1 中使用虚拟网络 (
docs.oracle.com/cd/E26502_01/html/E28992/toc.html)可参考docs.oracle.com/cd/E26502_01/html/E28992/gdyss.html#scrolltoc
第五章:玩转 Oracle Solaris 11 服务
本章将涵盖:
-
审查 SMF 操作
-
处理清单和配置文件
-
创建 SMF 服务
-
管理 inetd 控制的网络服务
-
排查 Oracle Solaris 11 服务问题
介绍
Oracle Solaris 11 将服务管理设施(SMF)作为一个主要特性。这个框架负责管理和监控所有服务和应用程序。SMF 在 Oracle Solaris 10 中引入,它提供了多种可能性,通过负责多个任务使我们的工作变得更轻松,例如以下任务:
-
启动、停止和重启服务
-
监控服务
-
发现所有服务依赖关系
-
排查服务问题
-
为每个可用服务提供单独的日志
通常,每个系统中有许多服务,并且这些服务按类别组织,如系统、网络、设备和应用程序。通常,一个服务只有一个名为 default 的实例。然而,一个服务可以呈现多个实例(例如,可以有多个 Oracle 实例和多个配置的网络接口,并且这种差异在引用服务时会突出显示。这个引用被称为故障管理资源标识符(FMRI),格式类似于svc:/system/cron:default,其中:
-
svc:这是 SMF 的本地服务 -
system:这是服务类别 -
cron:这是服务名称 -
default:这是实例
负责管理所有 SMF 服务的主要守护进程是svc.startd,它在系统初始化时被调用,读取配置文件/etc/inittab,如下所示:
root@solaris11-1:~# more /etc/inittab
(truncated output)
ap::sysinit:/usr/sbin/autopush -f /etc/iu.ap
smf::sysinit:/lib/svc/bin/svc.startd >/dev/msglog 2<>/dev/msglog </dev/console
p3:s1234:powerfail:/usr/sbin/shutdown -y -i5 -g0 >/dev/msglog 2<>/dev/msglog
root@solaris11-1:~#
svc.startd的另一个目标是确保系统达到适当的里程碑,也就是一组服务上线的状态或级别,这些服务与旧版运行级别状态非常相似。重要的里程碑有单用户(运行级别 S)、多用户(运行级别 2)和多用户服务器(运行级别 3):
root@solaris11-1:~# svcs -a | grep milestone
online 21:54:11 svc:/milestone/unconfig:default
online 21:54:11 svc:/milestone/config:default
online 21:54:12 svc:/milestone/devices:default
online 21:54:23 svc:/milestone/network:default
online 21:54:25 svc:/milestone/name-services:default
online 21:54:25 svc:/milestone/single-user:default
online 0:54:52 svc:/milestone/self-assembly-complete:default
online 0:54:59 svc:/milestone/multi-user:default
online 0:55:00 svc:/milestone/multi-user-server:default
有两个特殊的里程碑,如下所示:
-
all:这是默认的里程碑,其中所有服务都会初始化
-
none:没有初始化任何服务——这可以在 Oracle Solaris 11 维护期间使用
基于前述信息,了解正确的初始化顺序是非常重要的,如下所示:
-
Boot loader:根文件系统归档从磁盘加载到内存中
-
Booter:引导归档(它是一个类似于 Linux 中的
initramfs的 RAM 磁盘映像,包含启动系统所需的所有文件)被加载到内存中并执行。引导加载程序是一个服务:root@solaris11-1:~# svcs -a | grep boot-archive online 21:53:51 svc:/system/boot-archive:default online 0:54:51 svc:/system/boot-archive-update:default
任何boot-archive维护操作必须由bootadm命令完成。
-
Ram disk:内核从引导归档中提取并执行。
-
内核:一个小的根文件系统被挂载,然后从那里加载重要的驱动程序。之后,真正的根文件系统被挂载,剩余的驱动程序被加载,
/sbin/init脚本被执行。 -
Init:
/sbin/init脚本读取/etc/inittab文件,并执行svc.started守护进程。 -
svc.started:这会启动 SMF 服务及其相关进程。所有服务配置通过
svc.configd守护进程从名为repository.db的主服务数据库中读取,该数据库位于/etc/svc目录下,并有相应的备份文件。
审查 SMF 操作
在 Oracle Solaris 11 中管理服务非常简单,因为它的命令语法直观且不多。因此,本节的主要目的是回顾 SMF 管理的操作部分。
准备工作
本食谱需要一台安装了 Oracle Solaris 11 并且具有 4 GB 内存的虚拟机(VirtualBox 或 VMware)。
如何执行…
当管理员负责管理 Oracle Solaris 11 中的服务时,最重要且最常见的任务是列出现有的服务。此操作可以通过执行以下命令来完成:
root@solaris11-1:~# svcs -a | more
STATE STIME FMRI
legacy_run 0:54:59 lrc:/etc/rc2_d/S47pppd
legacy_run 0:54:59 lrc:/etc/rc2_d/S89PRESERVE
disabled 21:53:34 svc:/system/device/mpxio-upgrade:default
disabled 21:53:35 svc:/network/install:default
disabled 21:53:36 svc:/network/ipsec/ike:default
(truncated output)
online 21:53:34 svc:/system/early-manifest-import:default
online 21:53:34 svc:/system/svc/restarter:default
online 21:53:41 svc:/network/socket-config:default
(truncated output)
svcs 命令的目的是列出现有的服务,当指定 -a 选项时,我们希望列出所有的服务。
从前面的输出中,得到以下有用的信息:
-
legacy_run状态是遗留服务的标签,这些服务未被转换到 SMF 框架中。其他可能的状态如下:-
online:这意味着服务正在运行 -
disabled:这意味着服务没有运行 -
offline:这意味着服务已启用,但它要么没有运行,要么无法运行 -
initialized:这意味着服务正在启动 -
degraded:这意味着服务正在运行,但仅部分功能可用 -
maintenance:这意味着服务没有运行,因为存在配置问题
-
-
STIME字段显示服务启动的时间 -
FMRI是引用服务的别名对象
在 Oracle Solaris 11 中,SMF 在查找服务依赖关系(-d 选项)和发现哪些服务依赖于该服务(-D 选项)时表现得非常出色。以下是一些示例:
root@solaris11-1:~# svcs -a | grep auditd
online 0:54:55 svc:/system/auditd:default
root@solaris11-1:~# svcs -d svc:/system/auditd:default
STATE STIME FMRI
online 21:54:25 svc:/milestone/name-services:default
online 21:54:40 svc:/system/filesystem/local:default
online 0:54:53 svc:/system/system-log:default
root@solaris11-1:~# svcs -D svc:/system/auditd:default
STATE STIME FMRI
disabled 21:53:48 svc:/system/console-login:terma
disabled 21:53:49 svc:/system/console-login:termb
online 0:54:55 svc:/system/console-login:default
online 0:54:56 svc:/system/console-login:vt2
online 0:54:56 svc:/system/console-login:vt6
online 0:54:56 svc:/system/console-login:vt3
online 0:54:56 svc:/system/console-login:vt5
online 0:54:56 svc:/system/console-login:vt4
online 0:54:59 svc:/milestone/multi-user:default
另一种寻找服务依赖关系的好方法是使用 svc 命令,如下所示:
root@solaris11-1:~# svcs -l svc:/system/auditd:default
fmri svc:/system/auditd:default
name Solaris audit daemon
enabled true
state online
next_state none
state_time March 5, 2014 00:43:41 AM BRT
logfile /var/svc/log/system-auditd:default.log
restarter svc:/system/svc/restarter:default
contract_id 115
manifest /lib/svc/manifest/system/auditd.xml
dependency require_all/none svc:/system/filesystem/local (online)
dependency require_all/none svc:/milestone/name-services (online)
dependency optional_all/none svc:/system/system-log (online)
从之前的输出中获得一些有用信息,例如知道该服务已启用(online);它有三个服务依赖关系(如 svcs –d 命令所示);并找到它们各自的日志文件(/var/svc/log/system-auditd:default.log),可以使用 more /var/svc/log/system-auditd:default.log 来查看。
通过运行以下命令,可以学习到有关 contract_id 属性(115)的有用信息:
root@solaris11-1:~# ctstat -i 115 -v
CTID ZONEID TYPE STATE HOLDER EVENTS QTIME NTIME
115 0 process owned 11 0 - -
cookie: 0x20
informative event set: none
critical event set: hwerr empty
fatal event set: none
parameter set: inherit regent
member processes: 944
inherited contracts: none
service fmri: svc:/system/auditd:default
service fmri ctid: 115
creator: svc.startd
aux: start
root@solaris11-1:~#
从 auditd 获取的相关进程 ID 是 944,该服务是由 svc.startd 守护进程初始化的。此外,通过使用 FMRI 的简短形式运行以下命令,也可以找到关于进程 ID 的相同信息:
root@solaris11-1:~# svcs -p auditd
STATE STIME FMRI
online 0:54:55 svc:/system/auditd:default
0:54:55 944 auditd
FMRI 的简短形式是一个独特的序列,它使得能够将该服务与其他服务区分开,并且此简短形式始终指向指定服务的默认实例。
一个用于故障排除服务的好 svcs 命令参数如下:
root@solaris11-1:~# svcs -x auditd
svc:/system/auditd:default (Solaris audit daemon)
State: online since March 2, 2014 12:54:55 AM BRT
See: auditd(1M)
See: audit(1M)
See: auditconfig(1M)
See: audit_flags(5)
See: audit_binfile(5)
See: audit_syslog(5)
See: audit_remote(5)
See: /var/svc/log/system-auditd:default.log
Impact: None.
如果有任何已经配置的服务,它应该在运行。但是,如果它没有运行,或者它阻止了其他服务的运行,我们可以通过执行以下命令来找出原因:
root@solaris11-1:~# svcs -xv
上一个命令的输出没有显示任何内容,但可能存在一些损坏的服务。在本章的最后,我们将回到这个问题。
到目前为止,所有任务都集中在收集服务信息上。我们的下一步是学习如何使用 svcadm 命令进行管理。此命令的可用选项如下:
-
svcadm enable <fmri>:这将启用一个服务 -
svcadm enable –r <fmri>:这将递归启用一个服务及其依赖项 -
svcadm disable <fmri>:这将禁用一个服务 -
svcadm disable –t <fmri>:这将暂时禁用一个服务(该服务将在下次启动时启用) -
svcadm restart <fmri>:这将重启一个服务 -
svcadm refresh <fmri>:这将重新读取服务的配置文件 -
svcadm clear <fmri>:这将使服务从维护状态恢复到在线状态 -
svcadm mark maintenance <fmri>:这将把服务置于维护状态
以下是一些示例:
root@solaris11-1:/# svcadm disable auditd
root@solaris11-1:/# svcs -a | grep auditd
disabled 20:33:12 svc:/system/auditd:default
root@solaris11-1:/# svcadm enable auditd
root@solaris11-1:/# svcs -a | grep auditd
online 20:33:35 svc:/system/auditd:default
SMF 还支持通过 SMTP 服务和 SNMP trap 进行通知功能。要启用和配置此功能(使用 SMTP),需要安装通知包,执行此任务可以通过运行以下命令:
root@solaris11-1:/# pkg install smtp-notify
安装 smtp-notify 包后,我们可以启用并配置任何服务,以便在其状态从在线变为维护时,将消息发送到 root@localhost,如下所示:
root@solaris11-1:/# svcadm enable smtp-notify
root@solaris11-1:/# svcs -a | grep smtp-notify
online 20:29:07 svc:/system/fm/smtp-notify:default
root@solaris11-1:~# svccfg -s svc:/system/fm/smtp-notify:default setnotify -g from-online,to-maintenance mailto:root@localhost
要检查是否所有服务的通知服务已正确配置,请执行以下命令:
root@solaris11-1:~# svcs –n
Notification parameters for FMA Events
Event: problem-diagnosed
Notification Type: smtp
Active: true
reply-to: root@localhost
to: root@localhost
Notification Type: snmp
Active: true
Notification Type: syslog
Active: true
Event: problem-repaired
Notification Type: snmp
Active: true
Event: problem-resolved
Notification Type: snmp
Active: true
System wide notification parameters:
svc:/system/svc/global:default:
Event: to-maintenance
Notification Type: smtp
Active: true
to: root@localhost
Event: from-online
Notification Type: smtp
Active: true
to: root@localhost
最后,如果我们检查根邮箱,我们将看到我们的配置结果:
root@solaris11-1:/# mail
From noaccess@solaris11-1.example.com Sun Mar 2 20:29:05 2014
Date: Sun, 2 Mar 2014 05:17:28 -0300 (BRT)
From: No Access User <noaccess@solaris11-1.example.com>
Message-Id: <201403020817.s228HSRC006537@solaris11-1.example.com>
Subject: Fault Management Event: solaris11-1:SMF-8000-YX
To: root@solaris11-1.example.com
Content-Length: 791
SUNW-MSG-ID: SMF-8000-YX, TYPE: defect, VER: 1, SEVERITY: major
EVENT-TIME: Sun Mar 2 05:17:23 BRT 2014
PLATFORM: VirtualBox, CSN: 0, HOSTNAME: solaris11-1
SOURCE: software-diagnosis, REV: 0.1
EVENT-ID: acfbe77f-47fc-6e3b-835a-9005dc8ec70c
DESC: A service failed - a method is failing in a retryable manner but too often.
AUTO-RESPONSE: The service has been placed into the maintenance state.
IMPACT: svc:/system/zones:default is unavailable.
REC-ACTION: Run 'svcs -xv svc:/system/zones:default' to determine the generic reason why the service failed, the location of any logfiles, and a list of other services impacted. Please refer to the associated reference document at http://support.oracle.com/msg/SMF-8000-YX for the latest service procedures and policies regarding this diagnosis.
Oracle Solaris 11 中的一个服务有多个属性,所有这些属性都可以通过 svcprop 命令查看,如下所示:
root@solaris11-1:/# svcprop auditd
preselection/flags astring lo
preselection/naflags astring lo
preselection/read_authorization astring solaris.smf.value.audit
preselection/value_authorization astring solaris.smf.value.audit
queuectrl/qbufsz count 0
queuectrl/qdelay count 0
queuectrl/qhiwater count 0
queuectrl/qlowater count 0
(truncated output)
如果我们要检查审计服务的特定属性,我们需要执行以下命令:
root@solaris11-1:/# svcprop -p audit_remote_server/login_grace_time auditd
30
如果我们进一步操作,可以通过 svccfg 命令与服务的属性进行交互(读取和写入):
root@solaris11-1:/# svccfg
svc:>
第一步是通过运行以下命令序列列出所有可用的服务:
svc:> list
application/cups/scheduler
application/cups/in-lpd
smf/manifest
application/security/tcsd
application/management/net-snmp
(truncated output)
svc:> select auditd
svc:/system/auditd> list
:properties
default
在选择 auditd 服务时,有两种可能性——列出服务的一般属性或列出其 default 实例的私有属性。因此,要列出其一般属性,请执行以下命令:
svc:/system/auditd> listprop
usr dependency
usr/entities fmri svc:/system/filesystem/local
usr/grouping astring require_all
usr/restart_on astring none
(truncated output)
从默认实例列出属性的操作通过执行以下命令完成:
svc:/system/auditd:default> select auditd:default
svc:/system/auditd:default> listprop
preselection application
preselection/flags astring lo
preselection/naflags astring lo
preselection/read_authorization astring solaris.smf.value.audit
preselection/value_authorization astring solaris.smf.value.audit
queuectrl application
(truncated output)
通过运行以下命令,可以列出并更改任何服务的属性:
svc:/system/auditd:default> listprop audit_remote/p_timeout
audit_remote/p_timeout count 5
svc:/system/auditd:default> setprop audit_remote/p_timeout=10
svc:/system/auditd:default> listprop audit_remote/p_timeout
audit_remote/p_timeout count 10
很多时候,在重新配置期间,服务的属性可能会更改为另一个非默认值,最终该服务可能会因为这个新配置而出现问题并进入维护状态。那么,如何恢复属性的旧值呢?
为了解决这个问题,我们可以将此服务的所有属性值恢复为默认值。此任务可以通过使用 SMF 的自动快照(一种备份方式)来执行。因此,请执行以下命令:
svc:/system/auditd:default> revert start
svc:/system/auditd:default> listprop audit_remote/p_timeout
audit_remote/p_timeout count 5
svc:/system/auditd:default> unselect
svc:/system/auditd> unselect
svc:> exit
root@solaris11-1:~#
可用的快照如下:
-
running:每次运行svcadm刷新时都会拍摄此快照 -
start:此快照是在最后一次成功启动时拍摄的 -
initial:此快照是在第一次导入清单时拍摄的
SMF 清单是一个 XML 文件,描述了一个服务、一组实例及其各自的属性。当导入一个清单时,所有配置(包括其属性)都会被加载到服务配置库中。清单的默认位置是 /lib/svc/ 下的 manifest 目录。
另一个有趣且相关的任务是学习如何更改服务的环境变量。以下示例展示了将 TZ 属性的值更改为 Brazil/East:
root@solaris11-1:~# pargs -e `pgrep -f /usr/sbin/auditd`
937: /usr/sbin/auditd
envp[0]: _=*11*/usr/sbin/auditd
envp[1]: LANG=en_US.UTF-8
envp[2]: LC_ALL=
envp[3]: LC_COLLATE=
envp[4]: LC_CTYPE=
envp[5]: LC_MESSAGES=
envp[6]: LC_MONETARY=
envp[7]: LC_NUMERIC=
envp[8]: LC_TIME=
envp[9]: PATH=/usr/sbin:/usr/bin
envp[10]: PWD=/root
envp[11]: SHLVL=2
envp[12]: SMF_FMRI=svc:/system/auditd:default
envp[13]: SMF_METHOD=start
envp[14]: SMF_RESTARTER=svc:/system/svc/restarter:default
envp[15]: SMF_ZONENAME=global
envp[16]: TZ=localtime
envp[17]: A__z="*SHLVL
因此,为了更改并检查 auditd 服务中 TZ 属性的值,请执行以下命令:
root@solaris11-1:~# svccfg -s svc:/system/auditd:default setenv TZ Brazil/East
root@solaris11-1:~# svcadm refresh svc:/system/auditd:default
root@solaris11-1:~# svcadm restart svc:/system/auditd:default
root@solaris11-1:~# pargs -e `pgrep -f /usr/sbin/auditd`
7435: /usr/sbin/auditd
envp[0]: _=*11*/usr/sbin/auditd
envp[1]: LANG=en_US.UTF-8
envp[2]: LC_ALL=
envp[3]: LC_COLLATE=
envp[4]: LC_CTYPE=
envp[5]: LC_MESSAGES=
envp[6]: LC_MONETARY=
envp[7]: LC_NUMERIC=
envp[8]: LC_TIME=
envp[9]: PATH=/usr/sbin:/usr/bin
envp[10]: PWD=/root
envp[11]: SHLVL=2
envp[12]: SMF_FMRI=svc:/system/auditd:default
envp[13]: SMF_METHOD=start
envp[14]: SMF_RESTARTER=svc:/system/svc/restarter:default
envp[15]: SMF_ZONENAME=global
envp[16]: TZ=Brazil/East
envp[17]: A__z="*SHLVL
查找在 SMF 配置库中更改的属性还有一个好方法:
root@solaris11-1:~# svccfg -s auditd listcust -L
start/environment astring admin TZ=Brazil/East
方法概览
在本节中,你学习了 SMF 的基本原理,以及如何使用 svcs 和 svcadm 来管理 SMF 服务。我们还配置了通知服务,使用 SMTP 服务记录任何有趣的事件,例如更改服务状态。最后,使用 svcprop 和 svccfg 命令来获取并查看服务的属性,并通过 svccfg 中的快照功能(listsnap 和 revert 子命令)回滚所有属性到默认值。
处理清单和配置文件
在处理 SMF 服务时,几乎每个服务的配置都集中在两个关键概念上:配置文件和清单。以下方法将教你这些细节。
准备工作
本方法需要运行 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),且内存为 4 GB。
如何操作…
正如我们之前解释的那样,SMF 清单是一个描述服务、实例集及其属性的 XML 文件。当清单被导入时,它的整个配置(包括其属性)将被加载到服务配置库中。通过执行以下命令,可以强制执行导入操作,从而可能将新配置加载到库中:
root@solaris11-1:~# svcadm restart svc:/system/manifest-import:default
清单的默认位置是/lib/svc/下的manifest目录,如下所示:
root@solaris11-1:~# cd /lib/svc/manifest/
root@solaris11-1:/lib/svc/manifest# ls –l
total 27
drwxr-xr-x 10 root sys 17 Dec 23 18:41 application
drwxr-xr-x 2 root sys 2 Sep 19 2012 device
drwxr-xr-x 2 root sys 10 Dec 23 18:54 milestone
drwxr-xr-x 16 root sys 53 Jan 17 07:23 network
drwxr-xr-x 2 root sys 2 Sep 19 2012 platform
drwxr-xr-x 2 root sys 2 Sep 19 2012 site
drwxr-xr-x 8 root sys 73 Dec 23 18:55 system
root@solaris11-1:/lib/svc/manifest# cd application/
root@solaris11-1:/lib/svc/manifest/application# ls –l
total 92
-r--r--r-- 1 root sys 3464 Sep 19 2012 coherence.xml
-r--r--r-- 1 root sys 6160 Sep 19 2012 cups.xml
drwxr-xr-x 2 root sys 11 Dec 23 18:41 desktop-cache
drwxr-xr-x 2 root sys 3 Dec 23 18:41 font
drwxr-xr-x 2 root sys 3 Dec 23 18:41 graphical-login
-r--r--r-- 1 root sys 1762 Sep 19 2012 man-index.xml
drwxr-xr-x 2 root sys 3 Dec 23 18:41 management
drwxr-xr-x 2 root sys 3 Dec 23 18:41 opengl
drwxr-xr-x 2 root sys 7 Dec 23 18:41 pkg
drwxr-xr-x 2 root sys 3 Dec 23 18:41 security
-r--r--r-- 1 root sys 2687 Sep 19 2012 stosreg.xml
-r--r--r-- 1 root sys 1579 Sep 19 2012 texinfo-update.xml
-r--r--r-- 1 root sys 9013 Sep 19 2012 time-slider-plugin.xml
-r--r--r-- 1 root sys 4469 Sep 19 2012 time-slider.xml
drwxr-xr-x 2 root sys 5 Dec 23 18:41 x11
根据输出,服务清单被分类为:
-
application -
device -
milestone -
network -
platform -
site -
system
上述输出列出了所有应用清单作为示例,正如我们将要学习的那样,清单在服务配置中起着非常重要的作用。例如,研究audit.xml清单以了解细节会很有帮助。因此,这一学习将如下进行:
root@solaris11-1:/lib/svc/manifest# cd system/
root@solaris11-1:/lib/svc/manifest/system# cat auditd.xml
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
file.
-->
<service_bundle type='manifest' name='SUNWcsr:auditd'>
<service
name='system/auditd'
type='service'
version='1'>
<single_instance />
<dependency
name='usr'
type='service'
grouping='require_all'
restart_on='none'>
<service_fmri value='svc:/system/filesystem/local' />
</dependency>
<dependency
name='ns'
type='service'
grouping='require_all'
restart_on='none'>
<service_fmri value='svc:/milestone/name-services' />
</dependency>
<dependency
name='syslog'
type='service'
grouping='optional_all'
restart_on='none'>
<service_fmri value='svc:/system/system-log' />
</dependency>
<dependent
name='multi-user'
grouping='optional_all'
restart_on='none'>
<service_fmri value='svc:/milestone/multi-user'/>
</dependent>
<dependent
name='console-login'
grouping='optional_all'
restart_on='none'>
<service_fmri value='svc:/system/console-login'/>
</dependent>
<exec_method
type='method'
name='start'
exec='/lib/svc/method/svc-auditd'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='refresh'
exec='/lib/svc/method/svc-auditd'
timeout_seconds='30'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<!--
auditd waits for c2audit to quiet down after catching a -TERM
before exiting; auditd's timeout is 20 seconds
-->
<exec_method
type='method'
name='stop'
exec=':kill -TERM'
timeout_seconds='30'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<!-- SIGs HUP, TERM, and USR1 are all expected by auditd -->
<property_group name='startd' type='framework'>
<propval name='ignore_error' type='astring'
value='core,signal' />
</property_group>
<property_group name='general' type='framework'>
<!-- to start/stop auditd -->
<propval name='action_authorization' type='astring'
value='solaris.smf.manage.audit' />
<propval name='value_authorization' type='astring'
value='solaris.smf.manage.audit' />
</property_group>
<instance name='default' enabled='true'>
<!--
System-wide audit preselection flags - see auditconfig(1M)
and audit_flags(5).
The 'flags' property is the system-wide default set of
audit classes that is combined with the per-user audit
flags to configure the process audit at login and role
assumption time.
The 'naflags' property is the set of audit classes for
audit event selection when an event cannot be attributed
to an authenticated user.
-->
<property_group name='preselection' type='application'>
<propval name='flags' type='astring'
value='lo' />
<propval name='naflags' type='astring'
value='lo' />
<propval name='read_authorization' type='astring'
value='solaris.smf.value.audit' />
<propval name='value_authorization' type='astring'
value='solaris.smf.value.audit' />
</property_group>
<!--
Audit Queue Control Properties - see auditconfig(1M)
Note, that the default value for all the queue control
configuration parameters is 0, which makes auditd(1M) to
use current active system parameters.
-->
<property_group name='queuectrl' type='application' >
<propval name='qbufsz' type='count'
value='0' />
<propval name='qdelay' type='count'
value='0' />
<propval name='qhiwater' type='count'
value='0' />
<propval name='qlowater' type='count'
value='0' />
<propval name='read_authorization' type='astring'
value='solaris.smf.value.audit' />
<propval name='value_authorization' type='astring'
value='solaris.smf.value.audit' />
</property_group>
<!--
Audit Policies - see auditconfig(1M)
Note, that "all" and "none" policies available as a
auditconfig(1M) policy flags actually means a full/empty set
of other policy flags. Thus they are not configurable in the
auditd service manifest, but set all the policies to true
(all) or false (none).
-->
<property_group name='policy' type='application' >
<propval name='ahlt' type='boolean'
value='false' />
<propval name='arge' type='boolean'
value='false' />
<propval name='argv' type='boolean'
value='false' />
<propval name='cnt' type='boolean'
value='true' />
<propval name='group' type='boolean'
value='false' />
<propval name='path' type='boolean'
value='false' />
<propval name='perzone' type='boolean'
value='false' />
<propval name='public' type='boolean'
value='false' />
<propval name='seq' type='boolean'
value='false' />
<propval name='trail' type='boolean'
value='false' />
<propval name='windata_down' type='boolean'
value='false' />
<propval name='windata_up' type='boolean'
value='false' />
<propval name='zonename' type='boolean'
value='false' />
<propval name='read_authorization' type='astring'
value='solaris.smf.value.audit' />
<propval name='value_authorization' type='astring'
value='solaris.smf.value.audit' />
</property_group>
<!--
Audit Remote Server to allow reception of data sent by the
audit_remote(5) - see audit auditconfig(1M).
'active' is boolean which defines whether the server functionality
is activated or not.
'listen_address' address the server listens on.
Empty 'listen_address' property defaults to listen on all
local addresses.
'listen_port' the local listening port; 0 defaults to 16162 - port
associated with the "solaris-audit" Internet service name - see
services(4).
'login_grace_time' the server disconnects after login grace time
(in seconds) if the connection has not been successfully
established; 0 defaults to no limit, default value is 30 (seconds).
'max_startups' number of concurrent unauthenticated connections
to the server at which the server starts refusing new
connections; default value is 10\. Note that the value might
be specified in "begin:rate:full" format to allow random
early drop mode.
-->
<property_group name='audit_remote_server' type='application' >
<propval name='active' type='boolean'
value='true' />
<propval name='listen_address' type='astring'
value='' />
<propval name='listen_port' type='count'
value='0' />
<propval name='login_grace_time' type='count'
value='30' />
<propval name='max_startups' type='astring'
value='10' />
<property name='read_authorization' type='astring'>
<astring_list>
<value_node value='solaris.smf.manage.audit' />
<value_node value='solaris.smf.value.audit' />
</astring_list>
</property>
<propval name='value_authorization' type='astring'
value='solaris.smf.value.audit' />
</property_group>
<!--
Plugins to configure where to send the audit trail - see
auditconfig(1M), audit_binfile(5), audit_remote(5),
audit_syslog(5)
Each plugin type property group has properties:
'active' is a boolean which defines whether or not
to load the plugin.
'path' is a string which defines name of the
plugin's shared object in the file system.
Relative paths assume a prefix of
"/usr/lib/security/$ISA"
'qsize' is an integer which defines a plugin specific
maximum number of records that auditd will queue
for it. A zero (0) value indicates not defined.
This overrides the system's active queue control
hiwater mark.
and various attributes as defined on the plugin's man page
-->
<property_group name='audit_binfile' type='plugin' >
<propval name='active' type='boolean'
value='true' />
<propval name='path' type='astring'
value='audit_binfile.so' />
<propval name='qsize' type='count'
value='0' />
<propval name='p_dir' type='astring'
value='/var/audit' />
<propval name='p_fsize' type='astring'
value='0' />
<propval name='p_minfree' type='count'
value='1' />
<property name='read_authorization' type='astring'>
<astring_list>
<value_node value='solaris.smf.manage.audit' />
<value_node value='solaris.smf.value.audit' />
</astring_list>
</property>
<propval name='value_authorization' type='astring'
value='solaris.smf.value.audit' />
</property_group>
<property_group name='audit_syslog' type='plugin' >
<propval name='active' type='boolean'
value='false' />
<propval name='path' type='astring'
value='audit_syslog.so' />
<propval name='qsize' type='count'
value='0' />
<propval name='p_flags' type='astring'
value='' />
<property name='read_authorization' type='astring'>
<astring_list>
<value_node value='solaris.smf.manage.audit' />
<value_node value='solaris.smf.value.audit' />
</astring_list>
</property>
<propval name='value_authorization' type='astring'
value='solaris.smf.value.audit' />
</property_group>
<property_group name='audit_remote' type='plugin' >
<propval name='active' type='boolean'
value='false' />
<propval name='path' type='astring'
value='audit_remote.so' />
<propval name='qsize' type='count'
value='0' />
<propval name='p_hosts' type='astring'
value='' />
<propval name='p_retries' type='count'
value='3' />
<propval name='p_timeout' type='count'
value='5' />
<property name='read_authorization' type='astring'>
<astring_list>
<value_node value='solaris.smf.manage.audit' />
<value_node value='solaris.smf.value.audit' />
</astring_list>
</property>
<propval name='value_authorization' type='astring'
value='solaris.smf.value.audit' />
</property_group>
</instance>
<stability value='Evolving' />
<template>
<common_name>
<loctext xml:lang='C'>
Solaris audit daemon
</loctext>
</common_name>
<documentation>
<manpage title='auditd'
section='1M'
manpath='/usr/share/man'/>
<manpage title='audit'
section='1M'
manpath='/usr/share/man'/>
<manpage title='auditconfig'
section='1M'
manpath='/usr/share/man'/>
<manpage title='audit_flags'
section='5'
manpath='/usr/share/man'/>
<manpage title='audit_binfile'
section='5'
manpath='/usr/share/man'/>
<manpage title='audit_syslog'
section='5'
manpath='/usr/share/man'/>
<manpage title='audit_remote'
section='5'
manpath='/usr/share/man'/>
</documentation>
</template>
</service>
</service_bundle>
这个清单(auditd.xml)包含几个在其他清单中也会出现的常见元素。关键元素如下所示:
-
service_bundle:这是auditd守护进程的包名称 -
service:这是服务的名称(system/auditd) -
dependency:这决定了auditd依赖哪些服务 -
dependent:这决定了哪些服务依赖于auditd -
exec_method:这是 SMF 如何启动、停止、重启和刷新auditd守护进程 -
property_group:这些是来自auditd服务及其实例的属性 -
template:这决定了关于auditd服务的可用信息及其所在位置 -
manpage:这决定了与auditd服务相关的 man 页面
配置文件是一个 XML 配置文件,在 Oracle Solaris 11 安装后的第一次系统启动时应用,在此过程中可以自定义将初始化哪些服务和实例。以下是一个目录列表:
root@solaris11-1:~# cd /etc/svc/profile/
root@solaris11-1:/etc/svc/profile# ls -al
total 81
drwxr-xr-x 3 root sys 17 Dec 23 18:56 .
drwxr-xr-x 3 root sys 15 Mar 4 02:49 ..
-r--r--r-- 1 root sys 12262 Sep 19 2012 generic_limited_net.xml
-r--r--r-- 1 root sys 6436 Sep 19 2012 generic_open.xml
lrwxrwxrwx 1 root staff 23 Dec 23 18:56 generic.xml -> generic_limited_net.xml
-r--r--r-- 1 root sys 2581 Sep 19 2012 inetd_generic.xml
lrwxrwxrwx 1 root staff 17 Dec 23 18:56 inetd_services.xml -> inetd_generic.xml
-r--r--r-- 1 root sys 713 Sep 19 2012 inetd_upgrade.xml
lrwxrwxrwx 1 root staff 10 Dec 23 18:56 name_service.xml -> ns_dns.xml
-r--r--r-- 1 root sys 571 Sep 19 2012 ns_dns.xml
-r--r--r-- 1 root sys 478 Sep 19 2012 ns_files.xml
-r--r--r-- 1 root sys 713 Sep 19 2012 ns_ldap.xml
-r--r--r-- 1 root sys 832 Sep 19 2012 ns_nis.xml
-r--r--r-- 1 root sys 1673 Sep 19 2012 ns_none.xml
-r--r--r-- 1 root sys 534 Sep 19 2012 platform_none.xml
lrwxrwxrwx 1 root root 17 Dec 23 18:41 platform.xml -> platform_none.xml
drwxr-xr-x 2 root sys 3 Dec 23 18:56 site
尽管有多个清单,但其中有两个最为重要:generic.xml,它启用所有标准服务,以及generic_limited_net.xml,它禁用大多数互联网服务,除了ssh服务和一些其他远程服务。后者的清单如下:
root@solaris11-1:/etc/svc/profile# more generic_limited_net.xml
<?xml version='1.0'?>
(truncated output)
<!--
svc.startd(1M) services
-->
<service name='system/coreadm' version='1' type='service'>
<instance name='default' enabled='true'/>
</service>
<service name='system/cron' version='1' type='service'>
<instance name='default' enabled='true'/>
</service>
<service name='system/cryptosvc' version='1' type='service'>
<instance name='default' enabled='true'/>
</service>
(truncated output)
<service name='network/ssh' version='1' type='service'>
<instance name='default' enabled='true'/>
</service>
(truncated output)
可以通过不同的方法配置服务并自定义其行为;此外,了解 SMF 框架从哪里读取服务属性非常重要。因此,SMF 收集服务属性的目录和文件如下:
-
manifest:这从/lib/svc/manifest或/var/svc/manifest目录获取属性 -
site-profile:这从/etc/svc/profile/site目录或/etc/svc/profile/下的site.xml配置文件获取属性
配方概述
在这一部分,你了解了很多关于配置文件和清单的细节,例如它们的元素和可用类型。所有这些概念将在下一部分中部署。
创建 SMF 服务
这次,我们要在 Oracle Solaris 11 中创建一个新服务,所选应用程序是 gedit,这是一个图形化编辑器。显然,我们可以使用任何应用程序展示相同的过程,只需进行必要的更改以适应这个示例。
准备就绪
这个配方需要一个安装了 Oracle Solaris 11 并且有 4 GB 内存的虚拟机(VirtualBox 或 VMware)。
如何操作…
第一步是创建一个脚本,启动和停止我们感兴趣的应用程序。/lib/svc/method目录下有多个脚本,我们可以使用其中一个作为模板,但我使用了一个非常基础的模板,如下所示:
root@solaris11-1:~/chapter5# vi gedit_script.sh
#!/sbin/sh
. /lib/svc/share/smf_include.sh
case "$1" in
'start')
DISPLAY=:0.0
export DISPLAY
/usr/bin/gedit &
;;
'stop')
pkill -x -u 0 gedit
;;
*)
echo $"Usage: $0 {start|stop}"
exit 1
;;
esac
exit $SMF_EXIT_OK
这个脚本简单且有效,但我们需要更改其权限,并将其复制到/lib/svc/目录下的method目录,这是服务脚本的默认位置。可以通过以下方式完成此任务:
root@solaris11-1:~/chapter5# chmod u+x gedit_script.sh
root@solaris11-1:~/chapter5# more gedit_script.sh
在下一步中,我们将创建一个清单,但由于从头开始创建非常复杂,我们可以从另一个现有服务获取一个清单并将其复制到主目录中。然后,我们需要做适当的修改以使其适应我们的目标,如下所示:
root@solaris11-1:~# cp /lib/svc/manifest/system/cron.xml /root/chapter5/gedit_script_Manifest.xml
root@solaris11-1:~# cd /root/chapter5
root@solaris11-1:~/chapter5# vi gedit_script_Manifest.xml
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
Copyright 2009 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
file.
-->
<service_bundle type='manifest' name='gedit_script'>
<service
name='application/gedit_script'
type='service'
version='1'>
<single_instance />
<dependency
name='milestone'
type='service'
grouping='require_all'
restart_on='none'>
<service_fmri value='svc:/milestone/multi-user' />
</dependency>
<exec_method
type='method'
name='start'
exec='/lib/svc/method/gedit_script.sh start'
timeout_seconds='120'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec='/lib/svc/method/gedit_script.sh stop'
timeout_seconds='120'>
</exec_method>
<property_group name='startd' type='framework' >
<propval name='duration' type='astring' value='transient' />
</property_group>
<instance name='default' enabled='false' />
<stability value='Unstable' />
<template>
<common_name>
<loctext xml:lang='C'>
graphical editor (gedit)
</loctext>
</common_name>
<documentation>
<manpage title='gedit' section='1' manpath='/usr/share/man' />
</documentation>
</template>
</service>
</service_bundle>
这是一个很长的 XML 文件,但很简单。有些地方需要解释:
-
服务名称是
gedit_script,如下行所示:name='application/gedit_script' -
服务依赖于
milestone多用户,如下片段所示:<dependency name='milestone' type='service' grouping='require_all' restart_on='none'> <service_fmri value='svc:/milestone/multi-user' /> </dependency> -
启动和停止服务的时间限制是
120秒,如下片段所示:<exec_method type='method' name='start' exec='/lib/svc/method/gedit_script.sh start' timeout_seconds='120'> <method_context> <method_credential user='root' group='root' /> </method_context> </exec_method> <exec_method type='method' name='stop' exec='/lib/svc/method/gedit_script.sh stop' timeout_seconds='120'> </exec_method> -
<property_group>部分将服务配置为旧的服务类型(transient),以防止如果gedit_script服务失败,SMF 会自动重启它,如下片段所示:<property_group name='startd' type='framework' > <propval name='duration' type='astring' value='transient' /> </property_group> -
服务的默认状态是禁用的,如以下行所示:
<instance name='default' enabled='false' />
在尝试导入此清单之前,必须验证是否存在语法错误。因此,请执行以下命令:
root@solaris11-1:~/chapter5# svccfg validate gedit_script_Manifest.xml
到目前为止,一切听起来不错。因此,我们可以通过运行以下命令将清单导入到存储库中:
root@solaris11-1:~/chapter5# svccfg import gedit_script_Manifest.xml
注意
之前的命令是一个关键命令,因为每次修改清单时,都必须运行该命令以更新存储库中的新配置。
如果没有错误,服务应该会出现在其他服务中,如下所示:
root@solaris11-1:~/chapter5# svcs -a | grep gedit
disabled 3:50:02 svc:/application/gedit_script:default
太好了!现在是时候启动服务了,执行第二个命令后,gedit 编辑器(图形化编辑器)必须启动(记住,我们已经创建了一个名为gedit_script.sh的脚本来启动gedit编辑器):
root@solaris11-1:~# xhost +
access control disabled, clients can connect from any host
root@solaris11-1:~# svcadm enable svc:/application/gedit_script:default
root@solaris11-1:~# svcs -a | grep gedit
online 15:03:19 svc:/application/gedit_script:default
root@solaris11-1:~#
执行以下命令可以显示此新服务的属性:
root@solaris11-1:~# svcprop svc:/application/gedit_script:default
general/complete astring
general/enabled boolean false
general/entity_stability astring Unstable
general/single_instance boolean true
milestone/entities fmri svc:/milestone/multi-user
milestone/grouping astring require_all
milestone/restart_on astring none
milestone/type astring service
manifestfiles/root_chapter5_gedit_script_Manifest_xml astring /root/chapter5/gedit_script_Manifest.xml
startd/duration astring transient
start/exec astring /lib/svc/method/gedit_script.sh\ start
start/group astring root
start/timeout_seconds count 120
start/type astring method
start/use_profile boolean false
start/user astring root
stop/exec astring /lib/svc/method/gedit_script.sh\ stop
stop/timeout_seconds count 120
stop/type astring method
tm_common_name/C ustring graphical\ editor\ \(gedit\)
tm_man_gedit1/manpath astring /usr/share/man
tm_man_gedit1/section astring 1
tm_man_gedit1/title astring gedit
restarter/logfile astring /var/svc/log/application-gedit_script:default.log
restarter/start_pid count 8097
restarter/start_method_timestamp time 1394042599.387615000
restarter/start_method_waitstatus integer 0
restarter/transient_contract count
restarter/auxiliary_state astring dependencies_satisfied
restarter/next_state astring none
restarter/state astring online
restarter/state_timestamp time 1394042599.397622000
restarter_actions/refresh integer
restarter_actions/auxiliary_tty boolean true
restarter_actions/auxiliary_fmri astring svc:/application/graphical-login/gdm:default
要列出与gedit_script服务相关的环境变量,请执行以下命令:
root@solaris11-1:~# pargs -e `pgrep -f gedit_script`
7919: tail -f /var/svc/log/application-gedit_script:default.log
envp[0]: ORBIT_SOCKETDIR=/var/tmp/orbit-root
envp[1]: SSH_AGENT_PID=6312
envp[2]: TERM=xterm
envp[3]: SHELL=/usr/bin/bash
envp[4]: XDG_SESSION_COOKIE=f8114f3c252db0743fd58c3e0000009e-1394035066.410005-1956267226
envp[5]: GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
envp[6]: WINDOWID=31457283
(truncated output)
最后,要停止gedit_script服务并验证一切是否按预期发生,请执行以下命令:
root@solaris11-1:~# svcadm disable gedit_script
root@solaris11-1:~# svcs -a | grep gedit
disabled 15:26:35 svc:/application/gedit_script:default
太棒了!一切正常!现在让我们来谈谈配置文件。
配置文件也非常重要,它们决定了在启动过程中哪些服务将被启动。因此,适当调整它们以仅启动必要的服务是合理的,这有助于减少黑客攻击面。
以下步骤将创建一个新服务(比gedit_script服务更有趣),使用强大的netcat工具(nc)。这些步骤与之前使用的步骤相同。为了回顾,请参考以下步骤:
-
创建一个脚本。
-
使其可执行。
-
将其复制到
/lib/svc/method。 -
为该服务创建一个清单。
-
验证清单。
-
导入清单。
-
列出服务。
-
启动服务。
-
测试服务。
-
停止服务。
以下是创建新服务的命令顺序。根据我们之前的步骤,第一步是创建一个启动和停止服务的脚本,如下所示:
root@solaris11-1:~/chapter5# vi netcat.sh
#!/sbin/sh
. /lib/svc/share/smf_include.sh
case "$1" in
'start')
/usr/bin/nc -D -d -l -p 6666 -e /sbin/sh &
;;
'stop')
pkill -x -u 0 netcat
;;
*)
echo $"Usage: $0 {start/stop}"
exit 1
;;
esac
exit $SMF_EXIT_OK
授予脚本执行权限,并将其复制到包含其他现有服务脚本的适当目录,如下所示:
root@solaris11-1:~/chapter5# chmod u+x netcat.sh
root@solaris11-1:~/chapter5# cp netcat.sh /lib/svc/method/
下一步是为该服务(netcat)创建一个清单。从现有服务复制清单并进行调整会更容易,如下所示:
root@solaris11-1:~/chapter5# vi netcat_manifest.xml
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
Copyright 2009 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
file.
-->
<service_bundle type='manifest' name='netcat'>
<service
name='application/netcat'
type='service'
version='1'>
<single_instance />
<dependency
name='milestone'
type='service'
grouping='require_all'
restart_on='none'>
<service_fmri value='svc:/milestone/multi-user' />
</dependency>
<exec_method
type='method'
name='start'
exec='/lib/svc/method/netcat.sh start'
timeout_seconds='120'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec='/lib/svc/method/netcat.sh stop'
timeout_seconds='120'>
</exec_method>
<property_group name='startd' type='framework' >
<propval name='duration' type='astring' value='transient' />
</property_group>
<instance name='default' enabled='false' />
<stability value='Unstable' />
<template>
<common_name>
<loctext xml:lang='C'>
hacker tool (nc)
</loctext>
</common_name>
<documentation>
<manpage title='nc' section='1' manpath='/usr/share/man' />
</documentation>
</template>
</service>
</service_bundle>
在继续之前,我们需要验证netcat_manifest.xml清单,完成此步骤后,可以将清单导入到服务库中,命令如下所示:
root@solaris11-1:~/chapter5# svccfg validate netcat_manifest.xml
root@solaris11-1:~/chapter5# svccfg import netcat_manifest.xml
为了验证服务是否已正确导入,请通过运行以下命令检查它是否出现在 SMF 服务列表中:
root@solaris11-1:~/chapter5# svcs -a | grep netcat
disabled 18:56:09 svc:/application/netcat:default
root@solaris11-1:~/chapter5# svcadm enable svc:/application/netcat:default
root@solaris11-1:~/chapter5# svcs -a | grep netcat
online 19:14:17 svc:/application/netcat:default
若要收集关于netcat服务的其他详细信息,请执行以下命令:
root@solaris11-1:~/chapter5# svcs -l svc:/application/netcat:default
fmri svc:/application/netcat:default
name hacker tool (nc)
enabled true
state online
next_state none
state_time March 5, 2014 07:14:17 PM BRT
logfile /var/svc/log/application-netcat:default.log
restarter svc:/system/svc/restarter:default
contract_id
manifest /root/chapter5/netcat_manifest.xml
dependency require_all/none svc:/milestone/multi-user (online)
root@solaris11-1:~/chapter5# svcs -xv svc:/application/netcat:default
svc:/application/netcat:default (hacker tool (nc))
State: online since March 5, 2014 07:14:17 PM BRT
See: man -M /usr/share/man -s 1 nc
See: /var/svc/log/application-netcat:default.log
Impact: None.
可以通过运行以下命令检查特定的netcat 服务日志,查看是否存在任何问题:
root@solaris11-1:~/chapter5# tail -f /var/svc/log/application-netcat:default.log
(truncated output)
[ Mar 5 19:14:16 Enabled. ]
[ Mar 5 19:14:17 Executing start method ("/lib/svc/method/netcat.sh start"). ]
[ Mar 5 19:14:17 Method "start" exited with status 0\. ]
为了测试我们的新服务是否真的有效,请运行以下命令:
root@solaris11-1:~/chapter5# nc localhost 6666
pwd
/root
cd /
pwd
/
cat /etc/shadow
root:$5$oXrpLA3o$UTJJeO.MfjlTBGzJI.yzhHvqhvW.xUWBknpCKHRvP79:16131::::::22560
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
lp:NP:6445::::::
(truncated output)
这太棒了!
我们需要通过执行以下命令检查netcat服务是否能够适当地停止:
root@solaris11-1:~/chapter5# svcadm disable netcat
root@solaris11-1:~/chapter5# svcs -a | grep netcat
disabled 19:27:14 svc:/application/netcat:default
服务的日志文件有助于检查服务状态,如下所示:
root@solaris11-1:~/chapter5# tail -f /var/svc/log/application-netcat:default.log
[ Mar 5 19:14:16 Enabled. ]
[ Mar 5 19:14:17 Executing start method ("/lib/svc/method/netcat.sh start"). ]
[ Mar 5 19:14:17 Method "start" exited with status 0\. ]
^X[ Mar 5 19:27:14 Stopping because service disabled. ]
[ Mar 5 19:27:14 Executing stop method ("/lib/svc/method/netcat.sh stop"). ]
[ Mar 5 19:27:14 Method "stop" exited with status 0\. ]
到目前为止一切正常!下一步是提取当前活动的 SMF 配置文件并对其进行修改,以便现在和系统启动时都能启用netcat服务(<create_default_instance enabled='true'/>)。为此,请执行以下命令:
root@solaris11-1:~/chapter5# svccfg extract > myprofile.xml
root@solaris11-1:~/chapter5# vi myprofile.xml
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='profile' name='profile'>
(truncated output)
<service name='application/netcat' type='service' version='0'>
<create_default_instance enabled='true'/>
<single_instance/>
<dependency name='milestone' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/milestone/multi-user'/>
</dependency>
<exec_method name='start' type='method' exec='/lib/svc/method/netcat.sh start' timeout_seconds='120'>
<method_context>
<method_credential user='root' group='root'/>
</method_context>
</exec_method>
<exec_method name='stop' type='method' exec='/lib/svc/method/netcat.sh stop' timeout_seconds='120'/>
<property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient'/>
</property_group>
<stability value='Unstable'/>
<template>
<common_name>
<loctext xml:lang='C'>hacker tool (nc)</loctext>
</common_name>
<documentation>
<manpage title='nc' section='1' manpath='/usr/share/man'/>
</documentation>
</template>
必须再次重复导入和验证的过程(这次是针对配置文件),可以通过执行以下命令来完成:
root@solaris11-1:~/chapter5# svccfg validate myprofile.xml
root@solaris11-1:~/chapter5# svccfg import my profile.xml
通过执行以下命令再次检查netcat服务的状态:
root@solaris11-1:~/chapter5# svcs -a | grep netcat
online 19:52:18 svc:/application/netcat:default
这简直难以置信!netcat 服务在配置文件中被配置为enabled,并且已被置于online状态。如果我们重启系统,将看到如下输出:
root@solaris11-1:~# svcs -a | grep netcat
online 20:02:50 svc:/application/netcat:default
root@solaris11-1:~# svcs -l netcat
fmri svc:/application/netcat:default
name hacker tool (nc)
enabled true
state online
next_state none
state_time March 5, 2014 08:02:50 PM BRT
logfile /var/svc/log/application-netcat:default.log
restarter svc:/system/svc/restarter:default
manifest /root/chapter5/netcat_manifest.xml
manifest /root/chapter5/myprofile.xml
dependency require_all/none svc:/milestone/multi-user (online)
输出中会显示两个 XML 文件(清单和配置文件)。
配方概览
通过执行所有常规步骤,如创建启动/停止脚本、创建清单、导入并运行服务,创建了一个新服务。此外,你还学会了如何自动修改配置文件,以便在 Oracle Solaris 11 的启动阶段启动服务。
管理 inetd 控制的网络服务
在 Oracle Solaris 11 中,有些服务不属于 SMF 管理范畴,它们由另一个(且较旧的)守护进程:inetd 控制。Inetd 是这些网络服务的官方重启器,在我们管理这些服务的过程中,完成所有任务的主要命令是inetadm。现在是时候看看它是如何工作的了。
准备工作
该过程需要一台运行 Oracle Solaris 11 并且内存为 4GB 的虚拟机(可以使用 VirtualBox 或 VMware)。
如何操作…
最初,有一些有趣的服务可以进行操作。因此,我们必须安装一个好的服务:telnet。执行以下命令:
root@solaris11-1:~# pkg install pkg://solaris/service/network/telnet
要列出现有的 inetd 服务,请执行以下命令:
root@solaris11-1:~# inetadm
ENABLED STATE FMRI
disabled disabled svc:/application/cups/in-lpd:default
disabled disabled svc:/application/x11/xfs:default
disabled disabled svc:/application/x11/xvnc-inetd:default
disabled disabled svc:/network/comsat:default
disabled disabled svc:/network/stdiscover:default
disabled disabled svc:/network/rpc/spray:default
enabled online svc:/network/rpc/smserver:default
enabled online svc:/network/rpc/gss:default
disabled disabled svc:/network/rpc/rex:default
disabled disabled svc:/network/nfs/rquota:default
enabled online svc:/network/security/ktkt_warn:default
disabled disabled svc:/network/stlisten:default
disabled disabled svc:/network/telnet:default
旧的inetd.conf仍然存在,但它已经没有任何与网络服务配置相关的内容了(所有行都被注释掉):
root@solaris11-1:~# more /etc/inet/inetd.conf
#
# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
#
# Legacy configuration file for inetd(1M). See inetd.conf(4).
#
# This file is no longer directly used to configure inetd.
# The Solaris services which were formerly configured using this file
# are now configured in the Service Management Facility (see smf(5))
# using inetadm(1M).
#
# Any records remaining in this file after installation or upgrade,
# or later created by installing additional software, must be converted
# to smf(5) services and imported into the smf repository using
# inetconv(1M), otherwise the service will not be available. Once
# a service has been converted using inetconv, further changes made to
# its entry here are not reflected in the service.
#
要收集关于刚刚安装的telnet服务的更多详细信息,必须执行以下命令:
root@solaris11-1:~# inetadm -l svc:/network/telnet:default
SCOPE NAME=VALUE
name="telnet"
endpoint_type="stream"
proto="tcp6"
isrpc=FALSE
wait=FALSE
exec="/usr/sbin/in.telnetd"
user="root"
default bind_addr=""
default bind_fail_max=-1
default bind_fail_interval=-1
default max_con_rate=-1
default max_copies=-1
default con_rate_offline=-1
default failrate_cnt=40
default failrate_interval=60
default inherit_env=TRUE
default tcp_trace=FALSE
default tcp_wrappers=FALSE
default connection_backlog=10
default tcp_keepalive=FALSE
要启用telnet服务,执行以下命令:
root@solaris11-1:~# inetadm -e svc:/network/telnet:default
root@solaris11-1:~# inetadm | grep telnet
enabled online svc:/network/telnet:default
由于telnet服务有多个属性,可以在故障排除会话中进行更改。例如,为了使telnet服务将所有记录日志到syslog服务中,可以执行以下命令:
root@solaris11-1:~# inetadm -m svc:/network/telnet:default tcp_trace=true
root@solaris11-1:~# inetadm -l telnet | grep tcp_trace
tcp_trace=TRUE
太好了!当telnet服务不再需要时,我们可以禁用它:
root@solaris11-1:~# inetadm -d svc:/network/telnet:default
root@solaris11-1:~# inetadm | grep telnet
disabled disabled svc:/network/telnet:default
很好!是时候在下一个示例中学习另一个非常有趣且不寻常的技巧了。
现在,我们的目标是通过在/etc/inet/下的旧inetd.conf文件中创建一个非常简单的后门服务,并将其转换为 SMF。我们该如何做呢?很简单!第一步是通过执行以下命令,在/etc/inet/下的inetd.conf文件中创建一个服务行:
root@solaris11-1:~# vi /etc/inet/inetd.conf
(truncated output)
backdoor stream tcp6 nowait root /sbin/sh /sbin/sh -a
由于我们已经在inetd.conf文件中创建了上述行,我们必须在/etc/services文件中为该服务分配一个 TCP 端口(最后一行),可以执行以下命令:
root@solaris11-1:~# vi /etc/services
(truncated output)
backdoor 9999/tcp # backdoor
有一个名为inetconf的命令,它可以轻松地将 INET 服务转换为 SMF 服务:
root@solaris11-1:~# inetconv
backdoor -> /lib/svc/manifest/network/backdoor-tcp6.xml
Importing backdoor-tcp6.xml ...svccfg: Restarting svc:/system/manifest-import
为了验证服务是否按照预期转换为 SMF 模型,请执行以下命令:
root@solaris11-1:~# svcs -a | grep backdoor
online 20:36:15 svc:/network/backdoor/tcp6:default
最后,为了测试后门服务是否正常工作,执行以下命令:
root@solaris11-1:~# nc localhost 9999
ls
chapter5
core
Desktop
Documents
Downloads
Public
cd /
pwd
/
grep root /etc/shadow
root:$5$oXepLA3w$UTJJeO.MfVl1BGzJI.yzhHvqhvq.xUWBknCCKHRvP79:16131::::::22560
太棒了!后门服务运行得很好!
更进一步,Oracle Solaris 11 提供了一个名为netservice的命令,它可以通过应用generic_limited_net.xml配置文件并配置某些服务的本地模式属性,打开或关闭大多数网络服务(除了ssh服务),以进行远程访问。我建议你花点时间检查一下这个配置文件。
使用 netservices 命令关闭大多数网络服务以防远程访问很简单,可以通过运行以下命令来完成:
root@solaris11-1:~# netservices limited
restarting svc:/system/system-log:default
restarting svc:/network/smtp:sendmail
要反转每个网络服务的状态(启用或禁用),请运行以下命令:
root@solaris11-1:~# netservices open
restarting svc:/system/system-log:default
restarting svc:/network/smtp:sendmail
配方概述
您学会了如何管理 inetd 服务以及如何将 inetd 服务转换为 SMF 服务。本节的主要命令是 inetadm 和 inetconv。
故障排除 Oracle Solaris 11 服务
在本章的最后一部分,您将学习如何排除正在出现错误的服务,并修复损坏的仓库。
准备工作
要遵循这个步骤,您需要一台虚拟机(使用 VirtualBox 或 VMware),并安装 Oracle Solaris 11,且需要 4 GB 的 RAM。
如何操作……
管理员的主要职责是确保一切正常运行。分析系统的最佳方法是运行以下命令:
root@solaris11-1:~# svcs –xv
目前系统没有问题,但我们可以模拟一个。例如,在下一步中,我们将通过从脚本中删除一个分号来破坏 gedit_script 服务,如下所示:
root@solaris11-1:~# vi /lib/svc/method/gedit_script.sh
#!/sbin/sh
. /lib/svc/share/smf_include.sh
case "$1" in
'start')
DISPLAY=:0.0
export DISPLAY
/usr/bin/gedit &
;-----------------à Remove this semicolon!
'stop')
pkill -x -u 0 gedit
;;
*)
echo $"Usage: $0 {start|stop}"
exit 1
;;
esac
exit $SMF_EXIT_OK
为了继续操作,gedit_script 服务将被禁用并再次启用,通过执行以下命令:
root@solaris11-1:~# svcadm disable svc:/application/gedit_script:default
root@solaris11-1:~# svcs -a | grep gedit_script
disabled 0:22:13 svc:/application/gedit_script:default
root@solaris11-1:~# svcadm enable svc:/application/gedit_script:default
You have new mail in /var/mail/root
root@solaris11-1:~# svcs -a | grep gedit_script
maintenance 0:29:13 svc:/application/gedit_script:default
根据前面的三次输出,我们迅速破坏并重新启动了服务,因此它进入了维护状态。为了收集更多关于服务的信息,以便集中分析可能的原因,执行以下命令:
root@solaris11-1:~# svcs -xv svc:/application/gedit_script:default
svc:/application/gedit_script:default (graphical editor (gedit))
State: maintenance since March 6, 2014 12:29:13 AM BRT
Reason: Start method failed repeatedly, last exited with status 3.
See: http://support.oracle.com/msg/SMF-8000-KS
See: man -M /usr/share/man -s 1 gedit
See: /var/svc/log/application-gedit_script:default.log
Impact: This service is not running.
服务未运行,并且从其日志文件中可以获取更多详细信息,如下所示:
root@solaris11-1:~# tail -f /var/svc/log/application-gedit_script:default.log
[ Mar 6 00:29:13 Enabled. ]
[ Mar 6 00:29:13 Executing start method ("/lib/svc/method/gedit_script.sh start"). ]
/lib/svc/method/gedit_script.sh: line 2: syntax error at line 9: `)' unexpected
[ Mar 6 00:29:13 Method "start" exited with status 3\. ]
太棒了!Oracle Solaris 11 SMF 框架描述了错误发生的确切行号。为了修复问题,我们必须修复损坏的行(通过在我们移除分号的地方再次添加 ;)并将服务恢复到 online 状态。然后,修复语法问题后,运行以下命令:
root@solaris11-1:~# svcadm clear svc:/application/gedit_script:default
root@solaris11-1:~# svcs -a | grep gedit_script
online 0:39:12 svc:/application/gedit_script:default
完美!服务已经恢复到在线状态!
进入最后一个话题,SMF 仓库是通过 svc.configd 守护进程访问的,正是该守护进程控制对服务仓库的所有读写操作。此外,svc.configd 在启动时还会检查仓库的完整性。仓库损坏是很少见的,但确实可能发生,在这种情况下,我们可以在系统处于在线模式或维护模式(通过 sulogin 命令)时修复它。要修复仓库,请运行以下命令:
root@solaris11-1:~# /lib/svc/bin/restore_repository
查看 support.oracle.com/msg/SMF-8000-MY 以获取更多关于使用此脚本恢复 smf(5) 仓库备份副本的信息。
如果存在需要人工干预的问题,脚本将提供指示并退出到您的 shell:
/lib/svc/bin/restore_repository[71]: [: /: arithmetic syntax error
The following backups of /etc/svc/repository.db exist, from
Oldest to newest:
manifest_import-20140117_072325
boot-20140305_132432
manifest_import-20140305_170246
manifest_import-20140305_170535
boot-20140305_180217
boot-20140305_200130
manifest_import-20140305_203615
boot-20140306_005602
备份是根据其类型以及备份创建的时间来命名的。以 boot 开头的备份是在系统启动后第一次对仓库进行更改之前创建的。以 manifest_import 开头的备份是在 svc:/system/manifest-import:default 处理完成后创建的。
备份的时间格式为 YYYYMMDD_HHMMSS。
请从上面的备份仓库列表中输入特定的仓库进行恢复,或选择以下选项之一:
CHOICE ACTION
---------------- ----------------------------------------------
boot restore the most recent post-boot backup
manifest_import restore the most recent manifest_import backup
-seed- restore the initial starting repository (All
customizations will be lost, including those
made by the install/upgrade process.)
-quit- cancel script and quit
Enter response [boot]:
在选择选项之前,你必须了解系统中存在的仓库备份类型:
-
boot-<timestamp>:在boot-<timestamp>中,备份是在系统启动后但在进行任何更改之前创建的。 -
manifest_import-<timestamp>:在manifest_import-<timestamp>中,备份是在svc:/system/manifest-import:default执行后创建的。 -
--seed--:此选项恢复初始仓库。如果我们恢复这个备份,所有已做的服务或更改将丢失!
在这种情况下,我们将选择 boot 选项,如下所示:
Enter response [boot]: boot
After confirmation, the following steps will be taken:
svc.startd(1M) and svc.configd(1M) will be quiesced, if running.
/etc/svc/repository.db
-- renamed --> /etc/svc/repository.db_old_20140306_011224
/etc/svc/repository-boot
-- copied --> /etc/svc/repository.db
and the system will be rebooted with reboot(1M).
Proceed [yes/no]? yes
系统重启后,系统重新上线,一切正常!
备份概览
在本章中,你学习了如何使用 svcs –xv <fmri> 查找服务错误并修复它,如何让服务重新上线(svcadm clear <fmri>),以及在极端情况下,如何使用 /lib/svc/bin/restore_repository 命令恢复仓库。
参考资料
-
Oracle Solaris 管理:常见任务 见
docs.oracle.com/cd/E23824_01/pdf/821-1451.pdf -
Oracle Solaris 11 管理员备忘单 见
www.oracle.com/technetwork/server-storage/solaris11/documentation/solaris-11-cheat-sheet-1556378.pdf
740

被折叠的 条评论
为什么被折叠?



