




已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
PUPPET安装配置 版本V0.1第 20 页 共 20 页 目 录1 Puppet 简介31.1 背景介绍31.2 什么是puppet32 Puppet 架构介绍32.1 基本结构32.2 工作流程33 puppet的安装配置53.1 安装准备53.2 安装步骤53.2.1 CentOS 6.5下添加epel源53.2.2 使用ntp同步时间63.2.3 服务器端安装63.2.4 客户端安装63.2.5 启动puppet73.2.6 简单测试94 两个主要配置文件介绍104.1 主配置文件puppet.conf104.2 主机配置文件site.pp124.3 puppet管理资源列表125 Puppet的简单使用示例155.1 配置一个测试节点155.2 检测配置文件165.3 客户端运行配置175.4 查看运行结果186 FAQ186.1 Client Could not create PID file:186.2 Server Could not find certificate for 186.3 Error 400 on SERVER196.4 连接master报错:dnsdomainname: Unknown host196.5 连接master报错:err: Could not request certificate: getaddrinfo: Name or service not known196.6 连接master的时候出现如下报错:196.7 连接master的时候出现如下报错:197 参考文档201 Puppet 简介1.1 背景介绍系统管理员经常陷入一系列的重复任务中:如升级软件包、管理配置文件、系统服务以及添加新的配置、修复错误等。这些任务通常是重复低效的,解决这类任务的第一反应是让他们自动化,于是出现了定制脚本。由于环境复杂,定制脚本和应用程序一再被重复开发,并且很难适合多种平台,灵活性和功能也很难保证,于是像Puppet这样的自动化配置管理工具便出现了。1.2 什么是puppetPuppet是一个开源的软件自动化配置和部署工具,是基于ruby语言开发的,可以C/S模式或独立运行,支持对所有UNIX及类UNIX系统的配置管理,以及部分Windows Server有限的一些管理。它使用简单且功能强大,正得到越来越多的关注,现在很多大型IT公司都在使用puppet对集群中的软件进行管理和部署。2 Puppet 架构介绍2.1 基本结构Puppet是一个C/S架构的配置管理工具,在中央服务器上安装puppet-server软件包(此服务器称作master)。在需要管理的目标主机上安装puppet客户端软件(目标主机被称作agent)。2.2 工作流程上面已经说了,Puppet是基于C/S架构的。master保存着所有对agent的配置代码,在puppet里面叫做manifest。在agent下载manifest之后,可以根据manifest对服务器进行配置,例如软件包管理,用户管理,和文件管理等等。对puppet master来说,所有事先预定义好的配置信息被组织成puppet module。模块里最重要的核心概念叫做class。Class里面定义的是资源,是对每个节点的资源整合的体现。在puppet上对每个节点进行定义,其实就是定义这个节点大概有多少个类。在master上可以定制每一个被管理对象,称之为node。每一个节点都是puppet基于ssl连接后进行远程管理。每个节点的定义,只能使用FQDN,所以puppet依赖于dns服务。下图就是一个puppet工作流程图。如上图所示,puppet的工作流程如下:(1) 客户端puppet调用facter (运行在agent上的程序包),facter探测出主机的一些变量,例如主机名,内存大小,ip地址等。pupppet把这些信息通过ssl连接发送到服务器端;(2) 服务器端的puppetmaster 检测客户端的主机名,然后找到manifest里面对应的node配置, 并对该部分内容进行解析,facter送过来的信息可以作为变量处理,node牵涉到的代码才解析,其他没牵涉的代码不解析。解析后生成的结果称之为catalog,服务器端然后将catalog发给客户端;(3) 客户端接收到catalog,进行执行应用,客户端把执行结果发送给服务器(4) 服务器端把客户端的执行结果写入日志puppet工作过程中有两点值得注意:l 为了保证安全,agent和master之间是基于ssl和证书的,只有经master证书认证的agent才可以与master通信;l puppet会让系统保持在你所期望的某种状态并一直维持下去,如检测某个文件并保证其一直存在,保证ssh服务始终开启,如果文件被删除了或者ssh服务被关闭了,puppet下次执行时(默认30分钟),会重新创建该文件或者启动ssh服务。3 puppet的安装配置3.1 安装准备l 硬件准备:2台服务器 = 1台master + 1台agentl 软件准备:2台服务器分别安装 CentOS 6.5,64位masterclient主机名serverpuppetclient系统CentOS 6.5CentOS 6.5ip50523.2 安装步骤Puppet的安装方式支持源码安装、yum安装以及ruby的gem安装。官网推荐使用yum来安装puppet,方面以后的升级、管理、维护。本次调研使用的系统是Centos,所以采用yum来安装,但是Centos的默认源中没有puppet包,因此需要先安装epel包。Epel是企业版Linux附加软件包(ExtraPackagesforEnterpriseLinux)的缩写,是一个由特别兴趣小组创建、维护并管理的,针对红帽企业版Linux(RHEL)及其衍生发行版(比如CentOS)的一个高质量附加软件包项目。3.2.1 CentOS 6.5下添加epel源分别在服务器端和客户端安装epel。a. 安装epelrpm -Uvh /pub/epel/6/x86_64/epel-release-6-8.noarch.rpm以上URL请按实际情况修改b. 查看是否安装成功 rpm -q epel-releasec. 导入key rpm -import /etc/pki/rpm-gpg/RPM-GPG-KEY-*d. 重建缓存yum makecache 3.2.2 使用ntp同步时间由于SSL证书依赖时间同步。请注意服务端与客户端保持一致。推荐使用ntp 同步时间。分别在服务器端和客户端执行下面的命令:ntpdate chkconfig ntpd onservice ntpd start3.2.3 服务器端安装1. 修改主机名,修改/etc/hosts,添加下面两行vi /etc/hosts50 server52 puppetclient2. 安装rubyyuminstallrubyruby-rdoc3. 安装puppetyum install puppet-server4. 配置puppet服务,使其保持on状态 chkconfig level 2345 puppet on5. 启动puppetmaster服务service puppetmaster start3.2.4 客户端安装1. 修改主机名,修改/etc/hosts,添加下面两行vi /etc/hosts50 server52 puppetclient2. 安装rubyyuminstallrubyruby-rdoc3. 安装puppetyum install puppet4. 配置puppet服务 chkconfig level 2345 puppet on5. 配置client,修改/etc/puppet/puppet.conf文件的agent部分,添加相关配置vim /etc/puppet/puppet.conf server = server #master服务器的地址runinterval = 3600 #每隔多久的时间进行自动更新,时间单位为秒listen = true #客户端作为一个服务进行监听,允许其它的机器触发puppet运行,允许远程触发puppet的节点配置6. 启动puppet服务service puppet start3.2.5 启动puppetl 启动客户端:service puppet start 或者/etc/init.d/puppetoncev这时客户端会去连服务器端,但是由于连接是在ssl上的,而服务器端还没有sign过客户端的证书,客户端会被断开。到服务器端执行:puppetcalist会显示等待签名的客户端的主机名,本文测试环境运行结果为: puppetclient (AA:BB:AC:22:6B:9D:BA:EE:5A:77:25:30:9D:ED:27:44)。执行签名命令:puppetca-sign本文测试环境运行命令为:puppetca -sign puppetclient本文测试环境运行结果为:notice: Signed certificate request for puppetclientnotice: Removing file Puppet:SSL:CertificateRequest puppetclient at /var/lib/puppet/ssl/ca/requests/puppetclient.pem在服务器端用 puppet cert list all 查看会发现 前面多了一个 + 后,表示 “加入” 成功:puppetca list -all+ puppetclient (51:FC:76:C6:8F:07:5C:3D:B9:58:2A:9A:20:00:40:D8)+ (95:C6:DB:2F:66:93:77:19:4F:F5:54:99:9C:E8:04:96)+ server (19:82:AA:30:A1:FF:CC:8A:A7:57:8A:6D:3D:7B:51:E7)+ (D4:C7:45:32:FE:F5:39:94:0B:B9:0F:F5:13:3B:29:F1) (alt names: DNS:puppet, DNS:, DNS:)这时再到客户端上启动puppetd,即可看到客户在正常地连接server,并且应用Server上为客户端定制的配置策略。启动客户端/etc/init.d/puppetoncevl 启动Server端servicepuppetmasterstart 或者puppet master -verbose -no-daemonize第一次启动建议使用 puppet master -verbose -no-daemonize,这个方式将可以看到启动的整个过程。启动过程会做一些初始化的工作,为master创建本地证书认证中心,证书和key,并打开socket等待client的连接,这样有助于测试和调试错误。用户可以在/etc/puppet/ssl目录看到相关的文件和目录。rootserver puppet# puppet master -verbose -no-daemonizenotice: Starting Puppet master version 2.7.26info: access/catalog/(/+)$: allowing method findinfo: access/catalog/(/+)$: allowing $1 accessinfo: access/node/(/+)$: allowing method findinfo: access/node/(/+)$: allowing $1 accessinfo: access/certificate_revocation_list/ca: allowing method findinfo: access/certificate_revocation_list/ca: allowing * accessinfo: access/report/(/+)$: allowing method saveinfo: access/report/(/+)$: allowing $1 accessinfo: access/file: allowing * accessinfo: access/certificate/ca: adding authentication anyinfo: access/certificate/ca: allowing method findinfo: access/certificate/ca: allowing * accessinfo: access/certificate/: adding authentication anyinfo: access/certificate/: allowing method findinfo: access/certificate/: allowing * accessinfo: access/certificate_request: adding authentication anyinfo: access/certificate_request: allowing method findinfo: access/certificate_request: allowing method saveinfo: access/certificate_request: allowing * accessinfo: access/: adding authentication anyinfo: Inserting default /status (auth true) ACL because none were found in /etc/puppet/auth.confinfo: Expiring the node cache of puppetclientinfo: Not using expired node for puppetclient from cache; expired at Tue Mar 29 04:30:17 -0400 2016info: Caching node for puppetclientnotice: Compiled catalog for puppetclient in environment production in 0.06 secondsinfo: Expiring the node cache of puppetclientinfo: Not using expired node for puppetclient from cache; expired at Tue Mar 29 04:40:18 -0400 2016info: Caching node for puppetclientnotice: Compiled catalog for puppetclient in environment production in 0.01 secondsinfo: Expiring the node cache of puppetclientinfo: Not using expired node for puppetclient from cache; expired at Tue Mar 29 04:50:20 -0400 2016info: Caching node for puppetclientnotice: Compiled catalog for puppetclient in environment production in 0.01 seconds#客户端的puppet.conf中配置了自动刷新时间为10分钟,所以这里看到每隔十分钟自动更新一次客户端信息。3.2.6 简单测试测试内容:在客户端/tmp目录下创建一个testfile文件。编辑/etc/puppet/manifests/site.pp文件,添加如下内容:rootserver puppet# vi manifests/site.pp # create /tmp/testfile if it doesnt exist.class test_class file /tmp/testfile:content = “hello world!”,ensure = present,mode = 644,owner = root,group = root# tell puppet on which client to run the classnode puppetclient include test_class客户端成功生成了testfile文件。另配置项可以直接生效,不需要重启服务。4 两个主要配置文件介绍4.1 主配置文件puppet.conf主配置文件puppet.conf主要用于设置相关的参数、认证文件、文件系统配置文件、插件配置等。Puppet版本不同,配置选项命名方式也有所不同。Puppet 2.6以前的命名方式还以puppetmaster、puppetagent为主。Puppet 2.6以后都以main、master、agent为主。本文调研用的是2.7.26版本。先看如何生成Puppet配置文件puppet.conf:puppetd-genconfig/etc/puppet/puppet.conf puppetmasterd-genconfig/etc/puppet/puppet.conf以上命令会覆盖Puppet.conf原文件。在本地用如下命令查看配置参考手册:puppetdoc-referenceconfiguration如果不知道配置文件在哪个目录下,可以使用以下命令查看:puppetagent-configprintconfdir默认目录是/etc/puppet。由于puppet.conf配置文件内容较多,下面列举了一些核心配置、常用配置选项(不区分Master与Agent):main#通用配置选项 #vardir用来存放缓存数据、配置、客户端传回的报告及文件备份 vardir=/var/lib/puppet #Puppet日志文件配置目录默认为$vardir/log logdir=/var/log/puppet #PID文件目录,默认为$vardir/run rundir=/var/run/puppet #SSL签发认证文件目录,默认为$confdir/ssl ssldir=$vardir/ssl fileserverconfig=/etc/puppet/fileserver.conf manifestdir=/etc/puppet/manifests#可不指定,默认读取此目录 manifest=/etc/puppet/manifests/site.pp#主机文件默认读取 modulepath=/etc/puppet/modules:/usr/share/puppet/modules #模块路径,puppet会在这些目录下寻找模块authconfig=/etc/puppet/namespaceauth.conf #如果开启Listen为true需要配置此文件 pluginsync=true#插件同步配置对facter自定义有效 reportdir=/var/lib/puppet/reports #报告文件生成目录,目录以主机名命令开头 reports=log,foreman#报告的方式与类型 environment=production #运行环境配置,默认为生产环境 agent#客户端配置选项 #关联与检索配置文件目录,默认为$confdir/classes.txt,也可以使用 #(-loadclasses)参数指定classfile=$vardir/classes.txt #本地缓存配置目录,默认为$confdir/localconfig localconfig=$vardir/localconfig runinterval=1800#客户端检测时长,可按需求修改 listen=true#是否监听,执行puppetkick时需要配置 report=true#客户端的报告系统配置,不同于Master #此项的主要目的是将报告发送至Master,主要用于客户端puppet.conf配置 report_port=8140#监听端口,如果服务器配置有防火墙,需开放此端口 report_server=server#默认不填,此时以下面的$server变量值为准 server=#指定Master地址4.2 主机配置文件site.ppsite.pp的目的主要是告诉Puppet去哪里寻找并载入所有主机相关的配置。site.pp默认存放在/etc/puppet/manifests目录中。通常我们在会此文件中定义一些全局变量。生成Puppet主机配置文件site.pp的命令如下:puppetapply-genmanifest/etc/puppet/manifests/site.pp通常不使用以上命令生成site.pp配置文件。主要填写的内容为:#设置环境变量 $fileserver=server#指定全局fileserver变量 $ntpserver= #指定ntpserver变量 Packageprovider=yum#指定软件包的安装方法为yum #可以直接写节点配置文件,在所有Agent上创建其内容为HelloWorld的 #/tmp/temp1.txt文件 #nodedefault #file/tmp/temp1.txt:content=HelloWorld!; # importmodules.pp#加载模块配置文件,可以不配置 importnodes/*.pp#加载主机信息,可以使用通配符,也可以定义多组目录 importtest.puppetclient.pp#加载测试主机4.3 puppet管理资源列表下面是puppet管理资源列表,包括file(文件),user(用户),group(组),package(软件包),mount(挂载),schedule和cron(计划任务),service(服务),tidy(清理),yumrepo(yum仓库),sshkey(ssh认证)等常用资源。 rootserver # puppet describe -lThese are the types known to puppet:augeas - Apply a change or an array of changes to the .computer - Computer object management using DirectorySer .cron - Installs and manages cron jobs #定时任务exec - Executes external commands #命令行执行file - Manages files, including their content, owner . #文件管理filebucket - A repository for backing up filesgroup - Manage groupshost - Installs and manages host entriesinterface - This represents a router or switch interfacek5login - Manage the macauthorization - Manage the Mac OS X authorization databasemailalias - Creates an email alias in the local alias dat .maillist - Manage email listsmcx - MCX object management using DirectoryService .mount - Manages mounted filesystems, including puttin . #磁盘挂载nagios_command - The Nagios type commandnagios_contact - The Nagios type contactnagios_contactgroup - The Nagios type contactgroupnagios_host - The Nagios type hostnagios_hostdependency - The Nagios type hostdependencynagios_hostescalation - The Nagios type hostescalationnagios_hostextinfo - The Nagios type hostextinfonagios_hostgroup - The Nagios type hostgroupnagios_service - The Nagios type servicenagios_servicedependency - The Nagios type servicedependencynagios_serviceescalation - The Nagios type serviceescalationnagios_serviceextinfo - The Nagios type serviceextinfonagios_servicegroup - The Nagios type servicegroupnagios_timeperiod - The Nagios type timeperiodnotify - Sends an arbitrary message to the agent run-t .package - Manage packages #包管理resources - This is a metatype that can manage other reso .router - Manages connected routerschedule - Define schedules for Puppetscheduled_task - Installs and manages Windows Scheduled Tasksselboolean - Manages SELinux booleans on systems with SELi .selmodule - Manages loading and unloading of SELinux poli .service - Manage running services #服务管理ssh_authorized_key - Manages SSH authorized keyssshkey - Installs and manages ssh host keysstage - A resource type for specifying run stagestidy - Remove unwanted files based on specific crite .user - Manage users #用户管理vlan - Manages a VLAN on a router or switchwhit - Whits are internal artifacts of Puppets curr .yumrepo - The client-side description of a yum reposito .zfs - Manage zfszone - Manages Solaris zoneszpool - Manage zpoolsrootserver #下图是puppet的代码结构图,puppet的各个资源管理代码分别在下图的各个节点上。用户可以自己定义资源,通过plugins挂载到puppet master上。但是其代码结构必须与puppet现有结构保持一致。譬如:如目录树显示,定制化的facts应该在lib/facter/下,定制化的types 应该在 lib/puppet/type/下,定制化的providers应该在 lib/puppet/provider/type/下,定制化的 functions应该在 in lib/puppet/parser/functions/下。5 Puppet的简单使用示例在agent的/tmp目录下创建一个以agent主机名命名的txt文件,并写入内容“Hello World!”。5.1 配置一个测试节点一个节点的目录结构可以任意定义,只要在site.pp配置文件中import即可。本调研文档采用如下目录结构配置。节点信息:/etc/puppet/manifests/nodes模块信息:/etc/puppet/modules要按照以上目录结构进行配置,我们需要先创建一个模块信息。1)创建test模块。模块目录为test,class类名也必须是test。test类里面有一个file资源。执行命令如下:$ sudo mkdir p /etc/puppet/modules/test/manifests, templates, files $ sudo vim /etc/puppet/modules/test/manifests/init.pp class test file /tmp/$hostname.txt: content = Hello World!; 注意:每个模块都需要一个目录,puppet会检索配置的所有模块路径。在模块下面的manifests里面存放模块的主配置文件init.pp,puppet在应用类后会首先家长init.pp读取必要的信息。如果init.pp使用templates函数,会读取templates目录下的ERB模块文件,当前变量也会传入templates函数中。所以这个测试案例需要创建2个目录,分别是manifests,和templates。主机名变量值通过facter命令获取,以变量“$hostname”的形式传递给puppetclient。2)在模块配置文件中定义了一个变量 “$hostname”,需要将该变量传给ERB模块文件。此文件存放在test类目录下的templates目录中,文件名与类名保持一致。配置方法如下:$sudovim/etc/puppet/modules/test/templates/test.erb hostname3)通过以上两步我们创建了测试节点所需要的模块信息。现在我们来创建测试节点puppetclient,配置代码如下:$sudovim/etc/puppet/manifests/nodes/ puppetclient.pp nodepuppetclient #加载test类 includetest 4)最后将测试节点载入到Puppet,也就是修改site.pp配置文件。在前面我们讲到了Puppet会首先读取site.pp。因此,在创建客户端节点时需要在site.pp配置文件中设置import,代码如下:$sudovim/etc/puppet/manifests/site.pp #追加如下一行 importnodes/ puppetclient.pp #也可以使用importnodes/*.pp import指令告诉Puppet载入nodes目录中所有以.pp结尾的文件。当Puppet启动时就会载入并处理puppetclient .pp文件了。到此一个测试节点就配置完毕了,接下来我们需要检查配置文件的语法5.2 检测配置文件在完成所有节点的配置后,需要对配置文件的语法进行检查,以避免在客户端运行时因遇到报错而重复修改。检测语法也分两步进行: (1)puppet master服务端检查在puppet master服务端执行puppet parser validate init.pp,如果没有报错信息,表示无语法错误。rootserver nodes# puppet parser validate /etc/puppet/modules/test/manifests/init.pprootserver nodes#(2)puppet agent客户端检查客户端通过执行puppet agent -test -server server noop,检查语法是否正确。-noop参数表示验证配置,但并不实际生效。执行命令及结果如下:rootpuppetclient tmp# puppet agent -test -server server -noopnotice: Ignoring -listen on onetime runinfo: Caching catalog for puppetclientinfo: Applying configuration version 1459413676notice: /Stagemain/Test/File/tmp/puppetclient.txt/ensure: current_value absent, should be file (noop)notice: ClassTest: Would have triggered refresh from 1 eventsnotice: Stagemain: Would have triggered refresh from 1 eventsnotice: Finished catalog run in 0.02 seconds #如上可以看出要创建agent.txt文件,由于采用的是noop模式,代码没有被执行 注意:puppet agent 命令,如果不使-server指定master,agent会读取/etc/puppet/puppet.conf中server参数所指定的master。5.3 客户端运行配置通过上面的检测我们看到语法与代码检测都没有问题。现在准备好了一切,可以在客户端运行了。取消noop参数,执行结果如下:rootpuppetclient tmp# puppet agent -test -server servernotice: Ignoring -listen on onetime runinfo: Caching catalog for puppetclientinfo: Applying configuration version 1459413676notice: /Stagemain/Test/File/tmp/puppetclient.txt/ensure: defined content as md57b57e1a269dc9cb150fa38d238111180notice: Finished catalog run in 0.08 seconds通过以上代码我们可以看到Puppet的配置运行成功,并且提示完成catalog的运行花费的时间是0.08秒。根据日志可以看到客户端运行配置的过程:a) agent缓存主机信息b) 资源应用,/tmp/agent.txt文件被创建,并根据文件内容计算出MD5值c) 完成,并提示整个过程所消耗的时间5.4 查看运行结果在配置执行成功后,我们可以在客户端验证运行结果。客户端运行的结果将会和我们在puppet master服务端所定义的一样,显示的内容如下:rootpuppetclient tmp# cat puppetclient.txt Hello World! 6 FAQ6.1 Client Could not create PID file:rootpuppetclient puppet# /etc/init.d/puppet once -vCould not prepare for execution: Could not create PID file: /var/run/puppet/agent.pid查看下目录和文件的owner,改成puppet6.2 Server Could not find certificate for 客户端没有在服务器sign。rootserver puppet# puppetca -list #显示等待签名的客户端主机名 (AA:BB:AC:22:6B:9D:BA:EE:5A:77:25:30:9D:ED:27:44)rootserver puppet# puppetca -sign #为其签名notice: Signed certificate request for notice: Removing file Puppet:SSL:CertificateRequest at /var/lib/puppet/ssl/ca/requests/.pem6.3 Error 400 on SERVERrootpuppetclient tmp# puppet agent -test -noopnotice: Ignoring -listen on onetime runerr: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not parse for
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 八年级物理上《光的直线传播》教学设计
- 城管年终总结模版
- 护理中级评聘
- 小米3小米电视发布会课件
- 中医情志护理理论与实践
- 中级会计知识点总结模版
- 流动超市商业计划书-超市便利店
- 电视产品培训
- 关爱健康 预防传染病
- 永康国企面试题及答案
- 霍兰德职业兴趣测试题(卷)完整版
- 医院检验科实验室生物安全管理委员会及工作职责
- 福建省市政基础设施工程竣工验收报告(附件2)
- 市政工程监理规划范本(完整版)
- 艾里逊自动变速箱针脚图PPT通用课件
- 交管12123驾照学法减分题库及答案共155题(完整版)
- 5Why分析法经典培训(43页)
- 食品物性学-第二章 食品力学性质和流变学基础
- 2018二建继续教育(市政公用工程)试题库(有答案解析)
- 斜屋面瓦安装施工及方案
- 钢楼梯钢结构施工方案
评论
0/150
提交评论