2023年7月

什么是puppet 编辑

puppet是一种Linux、Unix、windows平台的集中配置管理系统,使用自有的puppet描述语言,可管理配置文件、用户、cron任务、 软件包、 系统服务等。puppet把这些系统实体称之为资源,puppet的设计目标是简化对这些资源的管理以及妥善处理资源间的依赖关系。

puppet采用C/S星状的结构,所有的 客户端和一个或几个服务器交互。每个 客户端周期的(默认半个小时)向服务器发送请求,获得其最新的配置信息,保证和该配置信息同步。每个puppet 客户端每半小时(可以设置)连接一次服务器端, 下载最新的配置文件,并且严格按照配置文件来 配置服务器. 配置完成以后,puppet客户端可以反馈给服务器端一个消息. 如果出错,也会给服务器端反馈一个消息.

为什么要开发puppet

 系统管理员都喜欢自己写点小工具来让自己的工作完成的更快或者更好, 不管是在大企业管理大量的服务器还是只管理两三台机器. 但是很少人会把他们的工具发布出来. 也就是是说极少有工具能被重用,或者说很多工具就只能在所在的组织内部有用.拷贝给别的组织,他们也用不上. 也就是说,每个系统 管理员,在一个新的公司,都会另起炉灶开发一套基于ssh,for循环的"系统"来帮助自己完成系统管理任务.

开发puppet是为了让 系统管理员可以相互交流和共享成熟的工具,避免重复的劳动.通过以下两个特性来实现这一目标:

提供一个简洁的但是强大的框架来完成 系统管理任务

 系统管理任务可以描述成puppet语言,因此可以相互分享代码,就像分享其他语言的代码一样,比如python, c等

因此,作为系统管理员的你可以更快的完成工作,因为你可以用puppet来处理所有的管理细节. 甚至你还可以下载其他管理员的puppet代码来让你的工作完成的更快.

使用puppet 的稳定性

puppet与其他手工操作工具有一个最大的区别就是 puppet的配置具有稳定性,因此你可以多次执行puppet, 一旦你更新了你的配置文件,puppet就会根据配置文件来更改你的机器配置,通常每30分钟检查一次. puppet会让你的系统状态同配置文件所要求的状态保持一致. 比如你配置文件里面要求ssh服务必须开启. 假如不小心ssh服务被关闭了,那么下一次执行puppet的时候,puppet会发现这个异常,然后会开启 ssh 服务. 以使系统状态和配置文件保持一致.puppet就象一个 魔术师,会让你的混乱的系统收敛到puppet配置文件所想要的状态.

可以使用puppet管理服务器的整个生命周期,从初始化到退役.不同于传统的例如sun的Jumpstart或者redhat的Kickstart, puppet可以长年让服务器保持最新状态.只要一开始就正确的配置他们,然后再也不用去管他们.通常puppet用户只需要给机器安装好puppet并让他们运行,然后剩余的工作都由puppet来完成.

2puppet的细节和原理 编辑

puppet的目的是让你只集中于你要管理的目标,而忽略实现的细节,例如命令名,参数或者文件格式. puppet把系统里面的用户, 软件包,服务 看作是"资源", puppet的作用就是管理这些资源以及资源之间的相互联系.

底层支撑工具 Providers,puppet有很多的资源类型,例如文件,用户, 软件包,服务, 不同的 操作系统上对资源的管理命令是不一样的,例如debian下面用 apt-get安装软件,redhat下面用yum安装软件. 因此puppet 对同一资源的管理可以有多个实现,配置资源的时候,可以明确的指定用什么provider. 例如在redhat上配置一个package资源的时候,可以指定provider是yum.

Facter变量

在puppet 客户端分析代码的时候,会把从facter传送过来的对应的值赋值给变量. 你可以单独手工执行facter这个命令,这个命令会打印出它所收集到的关于主机的信息,例如ip地址等等. facter把收集到值发送给puppet服务器端,服务器端就可以根据不同的条件来对不同的节点机器生成不同的puppet配置文件. 最重要的一个就是服务器的主机名.

工作方式与流程

puppet既可以在单机上使用,也可以以c/s结构使用.在大规模使用puppet的情况下,通常使用c/s结构.在这种结构中puppet 客户端只是指运行puppet的服务器,puppet服务器端是只运行puppetmaster的服务器.

puppet 客户端首先会连接到puppet服务器端,并且通过facter工具把客户端的基本配置信息发送给服务器端. 服务器端通过分析客户端的 主机名,通过node 定义,找到该主机的配置代码,然后编译配置代码,把编译好的配置代码发回客户端,客户端执行代码完成配置.并且把代码执行情况反馈给puppet服务器端.

修改系统配置

puppet 通过管理资源的方式来管理系统, 例如管理某个 软件是否要安装,是安装最新的还是安装了就行. 管理某个服务是否开启, 管理某个文件的属性,内容等等. 所有的资源都有对应的几个属性可以设置. 通过设置属性的方式来管理资源. 有一种特殊的属性可以用在所有的资源上面,这种属性叫做 metaparams ( 元参数或者元属性).

资源之间的关系

支持资源之间的关系配置是puppet的关键特性之一. 一个资源的变更可以对另一个资源产生一个动作.例如 /etc/apache.conf这个资源有改动,可以让/etc/init.d/apache 这个资源 reload一下.假如一个资源依赖另一个资源,那么puppet会优先配置被依赖的资源,因此如果你的配置文件没有准备好,对应的服务是不会先启动的.

3puppet 语言资源 编辑

puppet的全部就是管理资源,因此puppet语言的焦点就是处理这些资源,下面是一个基本的管理单个资源的例子.

file {"/etc/hosts": owner = root, group = root, mode = 644}

上面的 例子给出了定义一个资源所需要的所有组件,类型,名字和属性. 定义了一个 file 资源, 资源的title(标题)是 "/etc/hosts", 资源的属性里面设置了该文件属于那个用户和组,以及文件的权限.

也可以在一个大括号里面定义多个资源,通过分号来区分.

避免重复配置

puppet的 编译器会避免在不同的代码段里面管理同一个资源, 如果在不同的代码段对同一个资源进行配置,执行puppet的时候你会得到一个语法错误.puppet探测这种冲突的情况是通过判断资源类型和资源的title(标题); 如果两个资源有相同的资源类型和title; 那么就认为这两个资源是表示同一个资源.

你可以把多个相关的资源定义在一起,组成一个类.可以在其他的代码段include这个类.puppet还支持有限制的类的继承,作用就是在子类里面的属性可以覆盖父类里面的属性.

字符串

几乎所有的东西和符号在puppet里面都被看作是字符串,包括数字和布尔值. 但是如果你用引号把true和false引起来,他们会被当做字符串,例如你想赋值给某个资性"yes"的 字符串.

变量

puppet除facter变量外,也可以自定义变量,但不允许你在同一个类里面对一个变量进行两次赋值.

$myvar = value123

条件语句

Puppet支持常见的条件语句,使得你能根据不同的条件导入不同的资源定义。如if、case、另外puppet从版本0.24.6开始支持比较运算符。

数组

puppet 非常有限的支持 数组这种类型,你可以创建数组,并且给他们赋值,但是你不能删除它们.数组用的最多的情况就是上面ssh例子里面,资源依赖哪种情况. 或者是一次管理多个相同类型的资源.例如:user { [bin, adm]: ensure => present }

函数

puppet提供一些有用的函数,例如template利用erb模板来生成文件内容,这样就可以根据不同主机的情况,生成不同的配置文件.例如配置squid的内存缓存大小,可以利用facter返回的内存值做一个简单的数学计算,然后写入到squid的配置文件,就是通过template来完成的. 另外一个函数include 可以读入另外的puppet配置文件或者类.这样可以把puppet的文件分割的更有规律.

节点

最后一个关于puppet语言的语法是节点定义"node", 节点定义很象类定义,也支持继承特性. 当一个节点(puppet 客户端)连接到puppet服务器端,puppet解析器会查找这个节点的node代码片断,然后利用这个代码片断来生成该客户端的配置代码. puppet里面主机名来标明一个主机,因此主机名在puppet里面相当重要. 如果puppet找不到匹配该主机名的node定义,就会用默认的节点定义来配置该主机. 在node里面使用主机名,需要用单引号把主机名括起来.

node 'server1' { include nginx }

在上面的代码中,如果server1这个主机连接到puppet服务器,puppet服务器就会按照nginx的代码来配置这台服务器.

自定义资源

puppet里面有一个非常有用的语法结构,叫做define, 通过define可以把多个资源包装成一个资源,或者把一个资源包装成一个模型,便于使用.例如,在debian里面管理一个apache 虚拟机非常简单,把一个虚拟 主机的配置文件放到/etc/sites-available/里面,然后做一个 符号链接到/etc/sites-enabled目录. 你可以为你每个 虚拟主机复制同样的配置代码.

版本

puppet 有企业版和社区版,目前版本是2.6。

社区版是免费的,有些常用的功能。

企业版是收费的,支持vmware虚机的部署和审计功能。但如果10个节点以下是免费的。

2013年1月13日,[1]。

参考资料

1.  Puppet 3.0.2 发布,集中式系统管理工具 . 中国Linux联盟 [引用日期2012-12-28] .

-----------------------------------

服务器集中管理工具puppet

https://blog.51cto.com/chenshengang/1353971


一.ansible介绍
常用的自动化运维工具

Puppet —基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱
SaltStack —基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YMAL,使得配置 脚本更简单 Ansible —基于 Pythonparamiko 开发,分布式,无需客户端,轻量级,配置语法使用 YMAL 及 Jinja2 模板语言,更强的远程命令执行操作 其他 DevOps 请参看:https://github.com/geekwolf/sa-scripts/blob/master/devops.md
Ansible 是一个简单的自动化运维管理工具,可以用来自动化部署应用、配置、编排 task(持续 交付、无宕机更新等),采用 paramiko 协议库(fabric 也使用这个),通过 SSH 或者 ZeroMQ 等连 接主机,大概每 2 个月发布一个主版

Ansible 工作机制

Ansible 在管理节点将 Ansible 模块通过 SSH 协议(或者 Kerberos、LDAP)推送到被管理端执 行,执行完之后自动删除,可以使用 SVN 等来管理自定义模块及编排

 

 


由上面的图可以看到 Ansible 的组成由 5 个部分组成:

Ansible:核心引擎

Modules:包括 Ansible 自带的核心模块(core modules)及自定义模块 (custom modules);

                核心模块:ansible模块资源分发到远程节点使其执行特定任务或匹配一个特定的状态。

                自定义模块:如果核心模块不足以完成某种功能,可以添加自定义模块。

Plugins:完成模块功能的补充,包括连接插件、邮件插件等

Playbooks:网上很多翻译为剧本,个人觉得理解为编排更为合理;定义ansible任务的配置文件,可以将多个任务定义在一个剧本中,由ansible自动执行,剧本执行支持多个任务,可以由控制主机运行多个任务,同时对多台远程主机进行管理。

Inventory:定义 Ansible 管理主机的清单

 

ansible功能特性

  • 应用代码自动化部署。

  • 系统管理配置自动化。

  • 支持持续交付自动化。

  • 支持云计算、大数据平台(如AWS、OpenStack、VMWare等)环境。

  • 轻量级,无需在客户端安装agent,更新时只需在控制机上进行一次更新即可。

  • 批量任务执行可以写成脚本,不用分发到远程就可以执行。

  • 使用Python编写,维护更简单,Ruby语法过于复杂。

  • 支持非root用户管理操作,支持sudo。


二.安装ansible

安装前准备:

1.因为ansible是基于python的,所以先检查是否有python,如果没有需要安装(注意版本,版本过低,也可能导致安装失败)。

2.安装ansible前需要安装依赖包

yum -y install epel-release

......

ansible安装:

 yum -y install ansible

.......

 安装完成后需要配置机组:

vim /etc/ansible/hosts

这里我的机组名为[ccdoop],以下是我的另外2台机子的配置(本机为:test1:192.168.254.130)

test2 192.168.254.131

test3 192.168.254.132

到这里ansible就安装完成了。

测试:

ansible all -m ping 

结果:成功!

注:由于本机只有一个组[ccdoop],故用all,如果有多个机组,而你只想测试一个组的话可以把all替换为组名,如:


  本文基于上次尝试之后的进一步尝试,加入Docker容器、编写Dockerfile,并且jexus结合Docker的使用,总结下自己的个人感想。

 

一、环境介绍

  当前的场景有两种方式将Demo实现运行,一种是我将Asp.Net Core项目通过自侦听方式启动,然后外网正常访问,第二种通过功能强大的jexus作为代理,将项目发布后部署到jexus配置下,通过修改配置文件,通过jexus进行反向代理,此时项目本身可以不需要自侦听方式。目前是直接在主机下进行的,并没有加入到Docker容器中。

 

二、Docker中启动网站(暂未加入Dockerfile)

  

  首先,摆在面前的就有一个问题,我是直接根据镜像建立容器,然后在容器中安装Git获取项目、安装jexus部署项目、安装vim修改配置文件,还是直接获取项目后自启动侦听呢。不得不承认这两种情形都是很糟糕的,或许来说功能实现了,但是这个实现的过程是很不值得的,恰巧,我就完完全全走了一遍。

1、加入Docker容器,容器中加入jexus

  通过之前的一篇文章http://www.cnblogs.com/CKExp/p/8159269.html不难将Docker环境搭建起来,此处将不再制造轮子。一步一步分析,首先在容器中安装Git,也就意味着假如我要操作上百个容器那不是意味着我要安装上百次Git,同理jexus,也同理Vim,这是很不值得的,然后我在想,能否将这些个软件写到Dockerfile中呢,可以,但谁又会这么去做呢。不扯远了,单讲讲网站启动,我在容器中通过将网站发布后,重新启动jexus,通过外网访问(ip:端口),可以访问的通,还是很开心的,至少没出什么问题。

dotnet publish -o /var/www/HDShop
sh /usr/jexus/jws restart

  注意,这里的端口已经有了映射关系,我在建立容器的时候就已经指定了容器对外访问端口,所以网站的默认端口已经不合适了,我直接在Programcs中加入了UseUrls("http://*:3456"),容器对外访问端口是2345.

public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://*:3456")
                .UseStartup<Startup>()
                .Build();

 也可以通过curl命令(curl ip:端口)查看能否正常访问,将返回网站页面信息。

 

 2、加入Docker容器,容器中网站启动自侦听

  Demo获取完毕,直接通过自侦听方式启动网站 dotnet run 也是可以正常访问的。通过一组实验之后,我得到了一组信息,包含了我们想要的结果:

  2345:3456 -> 此方式为主机下项目直接共享到容器中,主机可改变,双方可见,容器改变,仅容器可见,对主机文件并无影响 。采用镜像为dotnet ,并未构造自身的镜像

  总结:不采用jexus仍然能够正常运行,jexus只是加强了更多的功能。既然有无jexus对我容器内部的网站启动作用不大,那么我就可以考虑在Docker中除非有特殊情况,否则我是坚决不会将jexus加入到Docker中。当然,主机上的jexus功能还是需要留着的,只是容器中jexus存在的必要性就要考虑了。

 

  直接通过主机上的Git获取项目  

  通过指令将项目共享到容器中,主机上的直接修改将影响中容器内部的修改,而容器中对文件的修改却是隔离主机的,不对实际的文件进行改变。

docker run -dit -p 2345:3456 --privileged=true -v /HDShop:/HDShop microsoft/dotnet

  这样一来,我在主机上获得项目,直接在容器中进行编译,运行,是不错的。那么容器中Git存在的必要性被我否决掉了。通过实际操作,这是很可行的,外网也能正常访问。甚至是说,我接下来的所有操作,都将依赖这种形式。

  同样来讲,我在主机上直接修改,容器中生效,那么容器中在去安装Vim也就不必要了,除非来说容器中的文件要相对主机上的要做一些改动,那么便下载一个Vim把,毕竟容器中可没有Vim。

  敲vim命令时提示说:vim: command not found,这个时候就需要安装vim,可是当你敲apt-get install vim命令时,提示:

        Reading package lists... Done
        Building dependency tree       
        Reading state information... Done
        E: Unable to locate package vim

  这时候需要敲:apt-get update,这个命令的作用是:同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引,这样才能获取到最新的软件包。等更新完毕以后再敲命令:apt-get install vim命令即可。

  在此我遇到了一些问题,不知是日志信息过多还是软件安装将容器中的空间竟然占满了,以至于我想改动配置文件但无法正常保存。看到了几篇文章说docker容器所在目录承载的能力有限建议切换到其他目录下,我没有去尝试,有需要的朋友可以尝试尝试。

  遇到的场景:http://blog.csdn.net/niu_hao/article/details/78873076

  解决方案:https://www.cnblogs.com/HD/p/4807088.html

 

个人推荐方案:

  在没有使用dockerfile的情况下,直接通过手动部署,我推荐将项目直接先获取到主机,然后通过共享到容器中,直接通过主机上的vim和git方便修改文件。容器中不再加入jexus,而是采用自侦听的方式.

  如果直接在容器中下载git、vim和jexus,很费时间和精力。同时浪费了容器的磁盘空间。主机上的jexus可用可不用,推荐还是用上,毕竟功能很多。

 

三、加入Dockerfile

  开始通过Dockerfile来构建镜像,首先是来学习学习Dockerfile:http://blog.csdn.net/qq_29999343/article/details/78318397接下来开始写一个Dockerfile,注意dockerfile文件的放置位置,当我们的项目发布如果就在项目所在文件夹,那么就在发布后的文件夹里协商Dockerfile即可,总之跟着发布后的文件夹跑,我尝试的时候,发布文件夹在其它目录下,然后将Dockerfile建设到项目所在文件夹,然后创建我的镜像,结果是镜像有了,容器创建成功了,也将容器中的服务跑起来了但是直接访问不行。猜想主要还是当前文件夹并非发布后的文件夹造成的。

  编写Dockerfile:https://www.cnblogs.com/savorboard/p/dotnetcore-docker.ht

  1、touch Dockerfile

  2、vim Dockerfile

  3、内容

复制代码

#基于microsoft/aspnetcore镜像构建新镜像
FROM microsoft/aspnetcore

#拷贝当前文件夹内容到容器指定目录
COPY . /hdshop

#设置工作目录
WORKDIR /hdshop

#设置对外暴露端口
EXPOSE 3456# 设置启动后运行指令
CMD ["dotnet","hdshop.dll"]

复制代码

  :wq保存退出

  通过指令docker build -t hdshopimage .  注意末尾的点记得加上,那是指代当前目录,查看当前镜像docker images,根据镜像来构建新容器 docker run --name firstContainer -d -p 2345:3456 hdshopimage,查看当前容器docker ps 或是通过访问容器内运行着的网站,可以发现容器已经有了网站已经跑起来了。

  注意,在写Dockerfile时,其中对外暴露的端口是容器对外暴露的端口,也就是说如果想要实现对内服务端口是80端口或者其它固定端口,那只有我们在程序中进行设置,所以推荐采用程序中的UseUrls("http://*80")进行统一设置内部端口为80端口,Dockerfile对于单机而言由于对外端口的唯一性,假设只在一台服务器上,从一个服务需要创建一个dockerfile来讲,是有点繁琐,但是考虑到时间线的延长,所有Dockerfile都已经写好了,假设一些容器宕机了,可以很快直接利用dockerfile进行新建,那还是很不错得。

 

Docker 容器之间进行互联:

  容器虽然职责是单一任务,但不可避免的会有需要与其它容器进行交互的场景,单台服务器下我们可以通过--link实现容器之间互联,这是通过网关的形式,直接在内网中进行调用,http://blog.csdn.net/halcyonbaby/article/details/42112325

 

四、自我总结经验

  通过编写Dockerfile,实现容器根据脚本自动创建,通过jexus和docker结合使用的尝试,解答了我不少之前的问题,也让我掌握更多容器适应场景。

  

  慢慢地得出一点经验,虽然可能这些经验不一定是正确的,但至少是我经历过的,有过这种经历,可比看几篇文章感觉爽快的多,还是推荐大家手脑并用,只看不做实在是难以体会到其中困难。之后,我想尝试下容器之间的互联操作,这次只是大概了解了一下,并没有过多的尝试。可以想象的到,容器互联之间肯定是有很多坑要踩的。

 

2018-2-13,望技术有成后能回来看见自己的脚步