首页 文章 精选 留言 我的

精选列表

搜索[AI运维],共10000篇文章
优秀的个人博客,低调大师

学习笔记:python watchdog运维监控文件系统事件实战

情况介绍 由于公司准备做Jenkins的前端自动化发布,但是前端的Node.js环境不统一,所以暂时先搁置,采用Ftp上传文件更新项目,因此想到了可以采用文件监控的形式来进行自动化上传。Python语言的优越性就体现出来了,其中有很多很棒的库,本篇即将用到的就是watchdog库。 watchdog库介绍 watchdog用来监控指定目录文件的变化,例如添加删除文件或目录,修改文件内容、重命名文件或目录等,每种变化都会产生一个事件,且有一个特定的事件类与之对应,然后再通过事件处理类来处理对应的事件,至于怎么样处理事件完全可以自定义,只需继承事件处理类的基类并重写对应实例方法。 实战准备 1.Python环境(系统自带Python2.7.5) 2.安装watchdog库(pip install watchdog) 实例演示 #!/usr/bin/python # -*- coding:UTF-8 -*- import time from watchdog.observers import Observer from watchdog.events import RegexMatchingEventHandler import commands class MyHandler(RegexMatchingEventHandler): def __init__(self, regex_list=[r”.*”]): super(MyHandler, self).__init__(regex_list) def on_created(self, event): if event.is_directory: pass else: print(event.event_type, event.src_path) def on_deleted(self, event): if event.is_directory: pass else: print(event.event_type, event.src_path) def on_modified(self, event): if event.is_directory: pass else: print(event.event_type, event.src_path) node = event.src_path.split(‘/’,3)[2] if node == “cp”: commands.getstatusoutput(‘ansible-playbook /mm/node/tasks/node_cp.yml’) elif node == “genpindao”: commands.getstatusoutput(‘ansible-playbook /mm/node/tasks/node_genpindao.yml’) elif node == “login”: commands.getstatusoutput(‘ansible-playbook /mm/node/tasks/node_login.yml’) elif node == “ucenter”: commands.getstatusoutput(‘ansible-playbook /mm/node/tasks/node_ucenter.yml’) else: commands.getstatusoutput(‘ansible-playbook /mm/node/tasks/node.yml -e node=’+node) def on_moved(self, event): print(“move”, event.src_path, event.dest_path) if __name__ == “__main__”: reges = [r”.*\.c”, r”.*\.h”, r”.*\.cpp”] event_handler = MyHandler(reges) observer = Observer() observer.schedule(event_handler, “/node_ftp/”, recursive=True) observer.start() try: while True: time.sleep(2) except KeyboardInterrupt: observer.stop() observer.join() 实例分析 watchdog主要采用观察者模型。主要有三个角色:observer,event_handler,被监控的文件夹。三者原本是独立的,主要通过observer.schedule函数将三者串起来,意思为observer不断检测调用平台依赖代码对监控文件夹进行变动检测,当发现改变时,通知event_handler处理。 关键点: 1.on_modified方法,是文件有变化触发的函数,上传Ftp目录后就需要调用此方法。 2.event是获取具体文件的路径,文中是为了获取具体的项目名称而进行的目录处理。 3.commands.getstatusoutput方法是调用系统的Shell命令。 4.observer.schedule方法第二个参数就是监控的具体的目录。 Tips:最后可以推荐读者有时间可以阅读一下watchdog的源码,写的清晰易懂而且架构很好。

优秀的个人博客,低调大师

CrazyWing:Python自动化运维开发实战 十七、Python异常

导语: 在写代码的时候,经常会遇到异常。python提供了两个功能来处理程序在运行中出现的异常和错误,可以使用该功能来调试python程序。 异常处理 断言(Assertions) 常用异常: Exception 它可以捕获任意(绝大部分)异常。 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类),代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的 python标准异常: 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响程序的正常执行。 一般情况下,在Python无法正常处理程序时就会发生一个异常,异常是Python对象,表示一个错误。 当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。 #!/usr/bin/env python try: print "%d" % (5 / 0) except ZeroDivisionError: print "除数不能为零" else: print "没有报错" print "这是异常之后的代码" #如果没有上面的异常处理,下面的代码是不会执行的 for i in range(10): print i 捕捉异常: try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。 如果你不想在异常发生时结束你的程序,只需在try里捕获它。 语法: try: <语句> #运行别的代码 except <名字>: <语句> #如果在try部份引发了'name'异常 except <名字>,<数据>: <语句> #如果引发了'name'异常,获得附加的数据 else: <语句> #如果没有异常发生 try的工作原理 当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。 1. 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的 except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异 常)。 2. 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的 try,或者到程序的最上层(这样将结束程序,并打印缺省的出错信息)。 3. 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的 话),然后控制流通过整个try语句。 例 打开一个文件,在该文件中的写入内容,且并未发生异常: try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" fh.close() 结果: # python test.py 内容写入文件成功 # cat testfile # 查看写入的内容 这是一个测试文件,用于测试异常!! 例 打开一个文件,在该文件中的内容写入内容,但文件没有写入权限,发生了异常: try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" fh.close() 在执行代码前为了测试方便,先去掉 testfile 文件的写权限 再执行以上代码: $ python test.py #注意这里用的是普通用户 Error: 没有找到文件或读取文件失败 使用except不带任何异常类型 你可以不带任何异常类型使用except,如下实例: try: 正常的操作 ...................... except: 发生异常,执行这块代码 ...................... else: 如果没有异常执行这块代码 以上方式try-except语句捕获所有发生的异常。但这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息。因为它捕获所有的异常。 使用except带多种异常类型 也可以使用相同的except语句来处理多个异常信息: try: 正常的操作 ................ except(Exception1[, Exception2[,...ExceptionN]]]): 发生以上多个异常中的一个,执行这块代码 ...................... else: 如果没有异常执行这块代码 try-finally 语句 try-finally 语句无论是否发生异常都将执行最后的代码。 try: <语句> finally: <语句> #退出try时总会执行 例1: try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") finally: print "Error: 没有找到文件或读取文件失败" 例2: import time try: f=file("文件.py") while True: line = f.read() if len(line)==0: break time.sleep(2) print line, finally: f.close() print "hello" 例3: try: fh = open("testfile", "w") try: fh.write("这是一个测试文件,用于测试异常!!") finally: print "关闭文件" fh.close() except IOError: print "Error: 没有找到文件或读取文件失败" 异常的参数: 一个异常可以带上参数,可作为输出的异常信息参数。你可以通过except语句来捕获异常的参数,如下所示: try: 正常的操作 ...................... except ExceptionType, Argument: 你可以在这输出 Argument 的值... 变量接收的异常值通常包含在异常的语句中。在元组的表单中变量可以接收一个或者多个值。元组通常包含错误字符串,错误数字,错误位置。 例以下为单个异常的实例: #!/usr/bin/python def temp_convert(var): try: return int(var) except ValueError, Argument: print "参数没 有包含数字\n", Argument # 调用函数 temp_convert("xyz") 以上程序执行结果如下: $ python test.py 参数没有包含数字 invalid literal for int() with base 10: 'xyz' 触发异常 可以使用raise语句自己触发异常raise语法格式: raise [Exception [, args [, traceback]]] 语句中Exception是异常的类型(例如,NameError)参数是一个异常参数值。该参数是可选的,如果不提供,异常的参数是"None"。最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。 例一个异常可以是一个字符串,类或对象。 Python的内核提供的异常,大多数都是实例化的类,这是一个类的实例的参数。定义一个异常: def functionName( level ): if level < 1: raise Exception("Invalid level!", level) # 触发异常后,后面的代码就不会再执行 注意:为了能够捕获异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。例如我们捕获以上异常,"except"语句如下: try: 正常逻辑 except "Invalid level!": 触发自定义异常 else: 其余代码 例 #!/usr/bin/python def mye( level ): if level < 1: raise Exception("Invalid level!", level) # 触发异常后,后面的代码就不会再执行 try: mye(0) # 触发异常 except "Invalid level!": print 1 else: print 2 输出结果: $ python test.py Traceback (most recent call last): File "test.py", line 11, in <module> mye(0) File "test.py", line 7, in mye raise Exception("Invalid level!", level) Exception: ('Invalid level!', 0) 用户自定义异常: 通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。以下为与RuntimeError相关的实例,实例中创建了一个类,基类为RuntimeError,用于在异常触发时输出更多的信息。在try语句块中,用户自定义的异常后执行except块语句,变量 e 是用于创建Networkerror类的实例。 class Networkerror(RuntimeError): def __init__(self, arg): self.args = arg 在你定义以上类后,你可以触发该异常,如下所示: try: raise Networkerror("Bad hostname") except Networkerror,e: print e.args 万能异常 在python的异常中,有一个万能异常:Exception,它可以捕获任意异常。例: #cat aa.py s1 = 'hello' try: int(s1) except Exception,e: print e 执行结果: #python aa.py invalid literal for int() with base 10: 'hello' 既然有这个万能异常,其他异常是不是就可以忽略了?当然不是,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行。例: s1 = 'hello' try: int(s1) except KeyError,e: print '键错误' except IndexError,e: print '索引错误' except Exception, e: print '错误' ====================================== assert断言 使用assert断言是学习python一个非常好的习惯,assert断言句语格式及用法很简单。在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件时就崩溃,这时候就需要assert断言的帮助。 assert断言的作用 assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。assert断言语句的语法格式assert expression 一些assert用法的语句供参考: assert 1==1 assert 2+2==2*2 assert len(['my boy',12])<10 assert range(4)==[0,1,2,3] 如何为assert断言语句添加异常参数 assert的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题。格式如下: assert expression [, arguments] 何时使用断言 Python的assert是用来检查一个条件,如果它为真,就不做任何事。如果它为假,则会抛出AssertError并且包含错误信息。例如: py> x = 23 py> assert x > 0, "x is not zero or negative" py> assert x%2 == 0, "x is not an even number" Traceback (most recent call last): File "", line 1, in .... AssertionError: x is not an even number 很多人用assert作为一个很快和容易的方法来在参数错误的时候抛出异常。但这样做是错的,非常错误,有两个原因。首先AssertError不是在测试参数时应该抛出的错误。你不应该像这样写代码: if not isinstance(x, int): raise AssertionError("not an int") 你应该抛出TypeError的错误,assert会抛出错误的异常。 但是,更危险的是,有一个关于assert的困扰:它可以被编译好然后从来不执行,如果你用 –O 或 –oo 选项运行Python,结果不保证assert表达式会运行到。当适当的使用assert时,这是未来,但是当assert不恰当的使用时,它会让代码用-O执行时出错。 那什么时候应该使用assert?没有特定的规则,断言应该用于: 防御型的编程 运行时检查程序逻辑 检查约定 程序常量 检查文档 (在测试代码的时候使用断言也是可接受的,是一种很方便的单元测试方法,你接受这些测试在用-O标志运行时不会做任何事。我有时在代码里使用assert False来标记没有写完的代码分支,我希望这些代码运行失败。尽管抛出NotImplementedError可能会更好。) 关于断言的意见有很多,因为它能确保代码的正确性。如果你确定代码是正确的,那么就没有用断言的必要了,因为他们从来不会运行失败,你可以直接移除这些断言。如果你确定检查会失败,那么如果你不用断言,代码就会通过编译并忽略你的检查。 在以上两种情况下会很有意思,当你比较肯定代码但是不是绝对肯定时。可能你会错过一些非常古怪的情况。在这个情况下,额外的运行时检查能帮你确保任何错误都会尽早地被捕捉到。 另一个好的使用断言的方式是检查程序的不变量。一个不变量是一些你需要依赖它为真的情况,除非一个bug导致它为假。如果有bug,最好能够尽早发现,所以我们为它进行一个测试,但是又不想减慢代码运行速度。所以就用断言,因为它能在开发时打开,在产品阶段关闭。 一个非变量的例子可能是,如果你的函数希望在它开始时有数据库的连接,并且承诺在它返回的时候仍然保持连接,这就是函数的不变量: def some_function(arg): assert not DB.closed() ... # code goes here assert not DB.closed() return result 断言本身就是很好的注释,胜过你直接写注释: # when we reach here, we know that n > 2 你可以通过添加断言来确保它: assert n > 2 断言也是一种防御型编程。你不是让你的代码防御现在的错误,而是防止在代码修改后引发的错误。理想情况下,单元测试可以完成这样的工作,可是需要面对的现实是,它们通常是没有完成的。人们可能在提交代码前会忘了运行测试代码。有一个内部检查是另一个阻挡错误的防线,尤其是那些不明显的错误,却导致了代码出问题并且返回错误的结果。 加入你有一些if…elif 的语句块,你知道在这之前一些需要有一些值: # target is expected to be one of x, y, or z, and nothing else. if target == x: run_x_code() elif target == y: run_y_code() else: run_z_code() 假设代码现在是完全正确的。但它会一直是正确的吗?依赖的修改,代码的修改。如果依赖修改成 target = w 会发生什么,会关系到run_w_code函数吗?如果我们改变了代码,但没有修改这里的代码,可能会导致错误的调用 run_z_code 函数并引发错误。用防御型的方法来写代码会很好,它能让代码运行正确,或者立马执行错误,即使你在未来对它进行了修改。 在代码开头的注释很好的一步,但是人们经常懒得读或者更新注释。一旦发生这种情况,注释会变得没用。但有了断言,我可以同时对代码块的假设书写文档,并且在它们违反的时候触发一个干净的错误 assert target in (x, y, z) if target == x: run_x_code() elif target == y: run_y_code() else: assert target == z run_z_code() 这样,断言是一种防御型编程,同时也是一种文档。我想到一个更好的方案: if target == x: run_x_code() elif target == y: run_y_code() elif target == z: run_z_code() else: # This can never happen. But just in case it does... raise RuntimeError("an unexpected error occurred") 按约定进行设计是断言的另一个好的用途。我们想象函数与调用者之间有个约定,比如下面的: “如果你传给我一个非空字符串,我保证传会字符串的第一个字母并将其大写。” 如果约定被函数或调用这破坏,代码就会出问题。我们说函数有一些前置条件和后置条件,所以函数就会这么写: def first_upper(astring): assert isinstance(astring, str) and len(astring) > 0 result = astring[0].upper() assert isinstance(result, str) and len(result) == 1 assert result == result.upper() return result 按约定设计的目标是为了正确的编程,前置条件和后置条件是需要保持的。这是断言的典型应用场景,因为一旦我们发布了没有问题的代码到产品中,程序会是正确的,并且我们能安全的移除检查。 建议不要用断言的场景: 不要用它测试用户提供的数据 不要用断言来检查你觉得在你的程序的常规使用时会出错的地方。断言是用来检查非常罕见的问题。你的用户不应该看到任何断言错误,如果他们看到了,这是一个bug,修复它。 有的情况下,不用断言是因为它比精确的检查要短,它不应该是懒码农的偷懒方式。 不要用它来检查对公共库的输入参数,因为它不能控制调用者,所以不能保证调用者会不会打破双方的约定。 不要为你觉得可以恢复的错误用断言。换句话说,不用改在产品代码里捕捉到断言错误。 不要用太多断言以至于让代码很晦涩。

优秀的个人博客,低调大师

运维人员的强大工具

sparkhistory Server产生背景 以standalone运行模式为例,在运行Spark Application的时候,Spark会提供一个WEBUI列出应用程序的运行时信息;但该WEBUI随着Application的完成(成功/失败)而关闭,也就是说,Spark Application运行完(成功/失败)后,将无法查看Application的历史记录; Spark history Server就是为了应对这种情况而产生的,通过配置可以在Application执行的过程中记录下了日志事件信息,那么在Application执行结束后,WEBUI就能重新渲染生成UI界面展现出该Application在执行过程中的运行时信息; Spark运行在yarn或者mesos之上,通过spark的history server仍然可以重构出一个已经完成的Application的运行时参数信息(假如Application运行的事件日志信息已经记录下来); sparkhistory Server的配置 1. 在Spark的conf目录下/usr/local/spark-1.6.0-bin-hadoop2.6/conf,将spark-defaults.conf.template改名为spark-defaults.conf mv spark-defaults.conf.template spark-defaults.conf spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6$ ls bin data examples licenses NOTICE README.md work CHANGES.txt derby.log lib logs python RELEASE conf ec2 LICENSE metastore_db R sbin spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6$ cd conf/ spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6/conf$ ls docker.properties.template metrics.properties.template spark-env.sh fairscheduler.xml.template slaves log4j.properties.template spark-defaults.conf.template spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6/conf$mv spark-defaults.conf.template spark-defaults.conf spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6/conf$ ls docker.properties.template metrics.properties.template spark-env.sh fairscheduler.xml.template slaves log4j.properties.template spark-defaults.conf spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6/conf$ 2. 对spark-defaults.conf 配置 spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6/conf$vim spark-defaults.conf spark.eventLog.enabled true spark.eventLog.dir hdfs://SparkSingleNode:9000/historyserverforSpark spark.history.ui.port 18080 spark.history.fs.logDirectory hdfs://SparkSingleNode:9000/historyserverforSpark 3.启动history-server spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6/conf$ cd .. spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6$sbin/start-history-server.sh starting org.apache.spark.deploy.history.HistoryServer, logging to /usr/local/spark/spark-1.5.2-bin-hadoop2.6/sbin/../logs/spark-spark-org.apache.spark.deploy.history.HistoryServer-1-SparkSingleNode.out failed to launch org.apache.spark.deploy.history.HistoryServer: full log in /usr/local/spark/spark-1.5.2-bin-hadoop2.6/sbin/../logs/spark-spark-org.apache.spark.deploy.history.HistoryServer-1-SparkSingleNode.out spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6$ jps 6816 Jps 3876 Worker 6772 HistoryServer 3174 NameNode 5990 CoarseGrainedExecutorBackend 3703 Master 3453 SecondaryNameNode 3293 DataNode 5887 SparkSubmit spark@SparkSingleNode:/usr/local/spark/spark-1.5.2-bin-hadoop2.6$ 4、spark-env.sh 5.在web浏览器中查看http://SparkSingleNode:18080/显示页面 1.6.0 History Server Event log directory: hdfs://Master:9000/historyserverforSpark 成功! 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5922165.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

运维自动化之ansible playbook结合docker安装smokeping

本次介绍ansible的paly book结合docker进行虚拟机里安装2.6.8版本smokeping(apache版本是2.4.7)。 docker版本 1 2 3 4 5 6 7 8 9 10 09:26:53 #dockerversion Clientversion:0.11.1 ClientAPIversion:1.11 Goversion(client):go1.2.1 Gitcommit(client):fb99f99 /0 .11.1 Serverversion:0.11.1 ServerAPIversion:1.11 Gitcommit(server):fb99f99 /0 .11.1 Goversion(server):go1.2.1 Laststableversion:1.1.2,pleaseupdatedocker ansible版本 1 2 09:28:13 #ansible--version ansible1.4.3 1、查看docker已有镜像 1 2 3 4 5 09:25:55 #dockerimages REPOSITORYTAGIMAGEIDCREATEDVIRTUALSIZE ubuntu3.06cee552765289weeksago369.8MB centos53.0e08d23b091899weeksago840.9MB centos63.0e94a3b24a19b9weeksago415.9MB 可以看到有3个镜像,1个是ubuntu,1个centos5,1个centos6.我这里打算使用centos6来弄。 2、加载新容器 1 2 3 4 5 6 09:31:01 #timedockerinspect$(dockerrun-d-p22-p80:80--name="smokeping"centos6:3.0/usr/sbin/sshd-D)|grep-iaddress|awk-F'"''{print$4}' 172.17.0.5 real 0m4.737s user 0m0.038s sys 0m0.054s 可以看到4秒就加载新容器完成,并且镜像为centos6系统,容器名为smokeping,开启了ssh服务,并且暴漏了22与80端口。 下面在从后端看看本机都运行了哪些容器 1 2 3 4 5 6 09:31:29 #dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 56b70c31a07ecentos6:3.0 /usr/sbin/sshd -DAboutaminuteagoUpAboutaminute0.0.0.0:80->80 /tcp ,0.0.0.0:49156->22 /tcp smokeping 846efb9e4d7aubuntu:3.0 /usr/sbin/sshd -D12daysagoUp4days0.0.0.0:49167->22 /tcp ubuntu-test1 b9a9e6f2caedcentos6:3.0 /usr/sbin/sshd -D3weeksagoUp4days0.0.0.0:49166->22 /tcp zabbix-server 978fff134b18centos6:3.0 /usr/sbin/sshd -D4weeksagoUp4days0.0.0.0:49165->22 /tcp centos6-test5 下面是ansible安装smokeping的部分 3、ansible安装smokeping的信息 1 2 3 4 5 09:34:06 #catsmokeping_install/vars/main.yml smokeping_dir: /usr/local/smokeping smokeping_version:2.6.8 smokeping_user:admin smokeping_passwd: '()TF%penst*&MedHU' 可以看到smokeping安装目录是/usr/local/smokeping,安装版本是2.6.8,登陆的账户是admin,登陆密码是()TF%penst*&MedHU 4、下面是安装smokeping的playbook结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 09:36:25 #treesmokeping_* smokeping_delete ├──files │└──delete_smokeping.sh ├──handlers ├──meta │└──main.yml ├──tasks │├──copy.yml │├──delete.yml │└──main.yml ├──templates └──vars ├──main.xml ├──main.yml └──vars └──main.yml smokeping_install ├──files │├──rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm │└──smokeping. tar .gz ├──handlers ├──meta │└──main.yml ├──tasks │├──copy.yml │├──delete.yml │├── install .yml │└──main.yml ├──templates │├──config │└──smokeping.conf └──vars └──main.yml 13directories,18files 5、playbook安装smokeping的内容是 1 2 3 4 5 6 7 8 9 10 09:37:27 #catsmokeping_install.yml --- -hosts: "`host`" remote_user: "`user`" gather_facts:True roles: -common -pcre_install -apache_install -smokeping_install 6、playbook删除smokeping的内容是 1 2 3 4 5 6 7 8 9 09:38:01 #catsmokeping_delete.yml --- -hosts: "`host`" remote_user: "`user`" gather_facts:True roles: -apache_delete -pcre_delete -smokeping_delete 下面是安装与测试过程 7、把docker新容器smokeping的ip加入到ansible的hosts里 1 echo "172.17.0.5" >> /etc/ansible/hosts 8、安装smokeping 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 09:39:10 #timeansible-playbooksmokeping_install.yml--extra-vars"host=172.17.0.5user=root"-k SSHpassword: PLAY[172.17.0.5]************************************************************* GATHERINGFACTS*************************************************************** ok:[172.17.0.5] TASK:[common|Installinitializtionrequiresoftware]*********************** changed:[172.17.0.5] TASK:[pcre_install|CopyPcreSoftwareToRedhatClient]******************** changed:[172.17.0.5] TASK:[pcre_install|UncompressionPcreSoftwareInRedhatClient]*********** changed:[172.17.0.5] TASK:[pcre_install|DeletePcreSoftwareInRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|CopyApacheSoftwareToRedhatClient]**************** changed:[172.17.0.5]=>(item=httpd-2.4.7. tar .gz) changed:[172.17.0.5]=>(item=libiconv. tar .gz) TASK:[apache_install|CreateApacheUserInRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|UncompressionApacheSoftwareToRedhatClient]******* changed:[172.17.0.5] TASK:[apache_install|CopyApacheConfigToRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|CopyApacheVhostConfigToRedhatClient]************ changed:[172.17.0.5] TASK:[apache_install|CopyApacheStartServiceScriptToRedhatClient]*** changed:[172.17.0.5] TASK:[apache_install|CreateLibInstallDir]******************************* ok:[172.17.0.5] TASK:[apache_install|CheckApacheIconvInRedhatClient]****************** changed:[172.17.0.5] TASK:[apache_install|InstallApacheIconvInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|CheckLibInConfigInRedhatClient]***************** failed:[172.17.0.5]=>{ "changed" : true , "cmd" : "grep-c/usr/local/lib//etc/ld.so.conf" , "delta" : "0:00:00.006524" , "end" : "2014-08-1109:40:48.822372" , "item" : "" , "rc" :1, "start" : "2014-08-1109:40:48.815848" } stdout:0 ...ignoring TASK:[apache_install|InstallApacheIconvInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|CreateApacheDir]************************************ changed:[172.17.0.5]=>(item= /data/webroot/apache ) changed:[172.17.0.5]=>(item= /data/webroot/apache/logs ) changed:[172.17.0.5]=>(item= /data/webroot/apache/vhost ) TASK:[apache_install|InstallCheckScriptInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|CreateIndexHtmlToRedhatClient]******************* changed:[172.17.0.5] TASK:[apache_install|StartApacheServiceInRedhatClient]**************** changed:[172.17.0.5] TASK:[apache_install|AddBootStartApacheServiceInRedhatClient]******* changed:[172.17.0.5] TASK:[apache_install|DeleteApachecompressionSoftwareInRedhatClient]*** changed:[172.17.0.5] TASK:[smokeping_install|CreateSmokepingInstallDir]********************** changed:[172.17.0.5] TASK:[smokeping_install|CopySmokepingSoftwareToRedhatClient]********** changed:[172.17.0.5]=>(item=rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm) changed:[172.17.0.5]=>(item=smokeping. tar .gz) TASK:[smokeping_install|InstallEpelYumRepo]***************************** changed:[172.17.0.5] TASK:[smokeping_install|InstallRequireSoftware]************************** changed:[172.17.0.5] TASK:[smokeping_install|UncompressionSmokeping]************************** changed:[172.17.0.5] TASK:[smokeping_install|CopySmokepingConfigToRedhatClient]************ changed:[172.17.0.5] TASK:[smokeping_install|CopySmokepingHttpdConfigToRedhatClient]****** changed:[172.17.0.5] TASK:[smokeping_install|CheckBootStartInRedhatClient]***************** failed:[172.17.0.5]=>{ "changed" : true , "cmd" : "grep-c'/usr/local/smokeping/bin/smokeping--logfile=/var/log/smokeping.log2>&1&'/etc/rc.local" , "delta" : "0:00:00.007325" , "end" : "2014-08-1109:46:03.045378" , "item" : "" , "rc" :1, "start" : "2014-08-1109:46:03.038053" } stdout:0 ...ignoring TASK:[smokeping_install|AddBootStartInRedhatClient]******************* changed:[172.17.0.5] TASK:[smokeping_install|ModifySmokepingDirPermissionInRedhatClient]*** changed:[172.17.0.5] TASK:[smokeping_install|StartSmokepingServiceInRedhatClient]********** changed:[172.17.0.5] TASK:[smokeping_install|RestartApacheServiceInRedhatClient]*********** changed:[172.17.0.5] TASK:[smokeping_install|DeleteInstalledFile]***************************** changed:[172.17.0.5] PLAYRECAP******************************************************************** 172.17.0.5:ok=35changed=33unreachable=0failed=0 real 6m52.934s user 0m15.104s sys 0m1.632s 花费6分52秒完成,花费时间多的主要是yum安装基础库与使用epel安装smokeping依赖库。 9、安装后测试 查看smokeping 由于我做了安全认证,需要输入账户与密码,这个账户与密码就上文第3步的账户与密码 然后默认的其他网络监控(包括1、2、3线电信、移动、联通、铁通与教育网的节点监控已经做好) 如果有其他的监控需要自己来添加即可。 10、删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 09:46:08 #timeansible-playbooksmokeping_delete.yml--extra-vars"host=172.17.0.5user=root"-k SSHpassword: PLAY[172.17.0.5]************************************************************* GATHERINGFACTS*************************************************************** ok:[172.17.0.5] TASK:[apache_delete|StopHttpdServiceInRedHatClient]******************* changed:[172.17.0.5] TASK:[apache_delete|DeleteBootStartInRedHatClient]******************** changed:[172.17.0.5] TASK:[apache_delete|DeleteApacheDirInRedHatClient]******************** changed:[172.17.0.5] TASK:[apache_delete|DeleteApacheServiceScriptInRedHatClient]********* changed:[172.17.0.5] TASK:[apache_delete|DeleteApacheUser]************************************ changed:[172.17.0.5] TASK:[pcre_delete|DeletePcre]********************************************* changed:[172.17.0.5] TASK:[smokeping_delete|StopSmokepingServiceInRedhatClient]************ changed:[172.17.0.5] TASK:[smokeping_delete|DeleteSmokepingDirInRedhatClient]************** changed:[172.17.0.5] TASK:[smokeping_delete|DeleteBootStartInRedhatClient]***************** changed:[172.17.0.5] PLAYRECAP******************************************************************** 172.17.0.5:ok=10changed=9unreachable=0failed=0 real 0m9.326s user 0m2.914s sys 0m0.446s 11、删除后测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 09:59:45 #ssh172.17.0.5 root@172.17.0.5'spassword: root@56b70c31a07e:~ 09:59:57 #ifconfig eth0Linkencap:EthernetHWaddrA6:80:57:2D:D3:F1 inetaddr:172.17.0.5Bcast:0.0.0.0Mask:255.255.0.0 inet6addr:fe80::a480:57ff:fe2d:d3f1 /64 Scope:Link UPBROADCASTRUNNINGMTU:1500Metric:1 RXpackets:84520errors:0dropped:0overruns:0frame:0 TXpackets:86385errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:1000 RXbytes:69075188(65.8MiB)TXbytes:9400662(8.9MiB) loLinkencap:LocalLoopback inetaddr:127.0.0.1Mask:255.0.0.0 inet6addr:::1 /128 Scope:Host UPLOOPBACKRUNNINGMTU:16436Metric:1 RXpackets:2errors:0dropped:0overruns:0frame:0 TXpackets:2errors:0dropped:0overruns:0carrier:0 collisions:0txqueuelen:0 RXbytes:168(168.0b)TXbytes:168(168.0b) root@56b70c31a07e:~ 09:59:59 #ps-ef|grephttpd root10171002010:00pts /0 00:00:00 grep httpd root@56b70c31a07e:~ 10:00:04 #ps-ef|grepsmokeping root10191002010:00pts /0 00:00:00 grep smokeping root@56b70c31a07e:~ 10:00:07 #ll/usr/local/ total40 drwxr-xr-x2rootroot4096Sep232011bin drwxr-xr-x2rootroot4096Sep232011etc drwxr-xr-x2rootroot4096Sep232011games drwxr-xr-x2rootroot4096Sep232011include drwxr-xr-x2rootroot4096Aug1109:40lib drwxr-xr-x2rootroot4096Sep232011lib64 drwxr-xr-x2rootroot4096Sep232011libexec drwxr-xr-x2rootroot4096Sep232011sbin drwxr-xr-x5rootroot4096Sep232011share drwxr-xr-x2rootroot4096Sep232011src root@56b70c31a07e:~ 10:00:11 #cat/etc/rc.local #!/bin/sh # #Thisscriptwillbeexecuted*after*alltheotherinitscripts. #Youcanputyourowninitializationstuffinhereifyoudon't #wanttodothefullSysVstyleinitstuff. touch /var/lock/subsys/local 如果大家想使用我的例子,可以从github里下载(地址是https://github.com/dl528888/ansible-examples/tree/master/smokeping_install),然后放到/etc/ansible目录里,下面是内容 本文转自 reinxu 51CTO博客,原文链接:http://blog.51cto.com/dl528888/1538444,如需转载请自行联系原作者

优秀的个人博客,低调大师

日均百万PV架构第五弹(运维自动化)

概念: puppet基于ruby的开源自动化部署工具 具有可测试性,强一致性部署体验 丰富资源定义完成系统配置全周期流程 内置丰富编程体验完成自主任务 资源标识与通知机制特性 puttet服务器端定义客户端节点所需资源类型,客户端加入部署环境后, 客户端凭借主机名等申请(https)对应服务器资源,服务器编译catelog 后将结果返回客户端,客户端利用这些信息完成系统资源的定义与处理, 并返回结果给服务器. 规划: 172.16.43.200 master.king.com (预装 puppet server) 172.16.43.1 slave1.king.com (预装 puppet agent再无其他资源) 按照之前架构,这次演示slave1.king.com的自动化安装,其他节点的安装配置以附件形式上传 针对slave1.king.com部署实现 -> puppet agent 软件(由cobbler预装) -> hosts 文件(puppet自动化) -> bind 软件及配置文件(puppet自动化) -> haproxy 软件及配置文件(puppet自动化) -> keepalived 软件及配置文件 本地测试阶段(master.king.com) 在master节点编写模块,测试通过后进行主从方式的配置 1 2 #安装puppet yum-y install puppet-2.7.23-1.el6.noarch.rpm 1.在/etc/puppet目录建立如下目录 1 2 mkdir /etc/puppet/manifest/ {haproxy,hosts,keepalived,named}/{files,manifests,templates}-pv mkdir /etc/puppet/modules 2.编辑/etc/puupet/manifests/hosts/files/hosts(host) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #若要部署成前四节的架构,这里需要把每一个点都自动化所以配置文件及其对应的软件都要安装配置 127.0.0.1localhostlocalhost.localdomainlocalhost4localhost4.localdomain4 ::1localhostlocalhost.localdomainlocalhost6localhost6.localdomain6 172.16.43.1slave1.king.com 172.16.43.2slave2.king.com 172.16.43.3slave3.king.com 172.16.43.4slave4.king.com 172.16.43.3imgs1.king.com 172.16.43.3imgs2.king.com 172.16.43.3text1.king.com 172.16.43.3text2.king.com 172.16.43.3dynamic1.king.com 172.16.43.4dynamic2.king.com 172.16.43.200master.king.com 172.16.43.6server.king.com 172.16.43.5proxy.king.com 编辑/etc/puupet/manifests/hosts/files/init.pp, 这是hosts的模块定义 1 2 3 4 5 6 7 8 9 10 11 12 #hosts的init.pp #自动定义资源模块名为hosts #hosts不需要安装软件仅仅是将hosts文件在master/slave模型下复制到slave的某目录中 #所以这里定义的资源类型只有file classhosts{ file { "hosts" : ensure=> file , source => "puppet:///modules/hosts/hosts" , path=> "/etc/hosts" } } 3. 之后配置都如(2)类型配置,代码文件分别为配置文件和模块定义文件(named) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // named.conf options{ // listen-onport53{127.0.0.1;}; // listen-on-v6port53{::1;}; directory "/var/named" ; dump- file "/var/named/data/cache_dump.db" ; statistics- file "/var/named/data/named_stats.txt" ; // memstatistics- file "/var/named/data/named_mem_stats.txt" ; allow-query{172.16.0.0 /16 ;}; recursion yes ; dnssec- enable yes ; dnssec-validation yes ; dnssec-lookasideauto; /*PathtoISCDLVkey*/ bindkeys- file "/etc/named.iscdlv.key" ; managed-keys-directory "/var/named/dynamic" ; }; logging{ channeldefault_debug{ file "data/named.run" ; severitydynamic; }; }; zone "." IN{ type hint; file "named.ca" ; }; include "/etc/named.rfc1912.zones" ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 // named.rfc1912.zones: zone "localhost.localdomain" IN{ type master; file "named.localhost" ; allow-update{none;}; }; zone "localhost" IN{ type master; file "named.localhost" ; allow-update{none;}; }; zone "1.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.0.0.0.ip6.arpa" IN{ type master; file "named.loopback" ; allow-update{none;}; }; zone "1.0.0.127.in-addr.arpa" IN{ type master; file "named.loopback" ; allow-update{none;}; }; zone "0.in-addr.arpa" IN{ type master; file "named.empty" ; allow-update{none;}; }; zone "king.com" IN{ type master; file "king.com.zone" ; }; 1 2 3 4 5 6 7 8 9 10 11 12 13 #king.com.zone $TTL600 @INSOAdns.king.com.adminmail.king.com.( 2014050401 1H 5M 3D 12H) INNSdns dnsINA172.16.43.1 wwwINA172.16.43.88 wwwINA172.16.43.188 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #named的init.pp #定义模块named,dns软件报名为bind,所以package是安装bind软件借助yum源 classnamed{ package{ "bind" : ensure=>present, name=> "bind" , provider=>yum, } #named软件要运行起来需要配置区域文件并且要求改变属主属组 file { "/etc/named.conf" : ensure=> file , require=>Package[ "bind" ], source => "puppet:///modules/named/named.conf" , owner=>named, group=>named, } file { "/etc/named.rfc1912.zones" : ensure=> file , require=>Package[ "bind" ], source => "puppet:///modules/named/named.rfc1912.zones" , owner=>named, group=>named, } file { "/var/named/king.com.zone" : ensure=> file , require=>Package[ "bind" ], source => "puppet:///modules/named/king.com.zone" , owner=>named, group=>named, } #bind软件在package安装了之后,需要启动并设置开启启动,但前提是package已经帮我们装好的bind软件 service{ "named" : ensure=> true , require=>Package[ "bind" ], enable => true , } } 4. haproxy的配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #/etc/haproxy/haproxy.cfg global log127.0.0.1local2 chroot /var/lib/haproxy pidfile /var/run/haproxy .pid maxconn4000 userhaproxy grouphaproxy daemon defaults modehttp logglobal optionhttplog optiondontlognull optionhttp-server-close optionforwardforexcept127.0.0.0 /8 optionredispatch retries3 timeouthttp-request10s timeoutqueue1m timeoutconnect10s timeoutclient1m timeoutserver1m timeouthttp-keep-alive10s timeoutcheck10s maxconn30000 listenstats modehttp bind0.0.0.0:8080 stats enable statshide-version statsuri /haproxyadmin ?stats statsrealmHaproxy\Statistics statsauthadmin:admin statsadmin if TRUE frontendhttp- in bind*:80 modehttp logglobal optionhttpclose optionlogasap optiondontlognull capturerequestheaderHostlen20 capturerequestheaderRefererlen60 aclimg_staticpath_beg-i /images /imgs aclimg_staticpath_end-i.jpg.jpeg.gif.png acltext_staticpath_beg-i/ /static /js /css acltext_staticpath_end-i.html.shtml.js.css use_backendimg_servers if img_static use_backendtext_servers if text_static default_backenddynamic_servers backendimg_servers balanceroundrobin serverimgsrv1imgs1.king.com:6081checkmaxconn4000 serverimgsrv2imgs2.king.com:6081checkmaxconn4000 backendtext_servers balanceroundrobin servertextsrv1text1.king.com:6081checkmaxconn4000 servertextsrv2text2.king.com:6081checkmaxconn4000 backenddynamic_servers balanceroundrobin serverwebsrv1dynamic1.king.com:80checkmaxconn1000 serverwebsrv2dynamic2.king.com:80checkmaxconn1000 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #haproxy的init.pp classhaproxy{ package{ "haproxy" : ensure=>present, name=> "haproxy" , provider=>yum, } file { "/etc/haproxy/haproxy.cfg" : ensure=> file , require=>Package[ "haproxy" ], source => "puppet:///modules/haproxy/haproxy.cfg" , } service{ "haproxy" : ensure=> true , require=>Package[ "haproxy" ], enable => true , } } 5. keepalived的配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 #/etc/keepalived/keepalived.conf global_defs{ notification_email{ root@localhost } notification_email_fromkeepadmin@localhost smtp_connect_timeout3 smtp_server127.0.0.1 router_idLVS_DEVEL_KING } vrrp_scriptchk_haproxy{ script "/etc/keepalived/chk_haproxy.sh" interval2 weight2 } vrrp_instanceVI_1{ interfaceeth0 stateMASTER #BACKUPforslaverouters priority100 #99forBACKUP virtual_router_id173 garp_master_delay1 authentication{ auth_typePASS auth_passking1 } track_interface{ eth0 } virtual_ipaddress{ 172.16.43.88 /16 deveth0 } track_script{ chk_haproxy } } vrrp_instanceVI_2{ interfaceeth0 stateBACKUP #masterforslaverouters priority99 #99formaster virtual_router_id174 garp_master_delay1 authentication{ auth_typePASS auth_passking2 } track_interface{ eth0 } virtual_ipaddress{ 172.16.43.188 /16 deveth0 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #keepalived的init.pp classkeepalived{ package{ "keepalived" : ensure=>present, name=> "keepalived" , provider=>yum, } file { "/etc/keepalived/keepalived.conf" : ensure=> file , require=>Package[ "keepalived" ], source => "puppet:///modules/keepalived/keepalived.conf" , notify=>Exec[ "reload" ], } service{ "keepalived" : ensure=> true , require=>Package[ "keepalived" ], enable => true , } exec { "reload" : command => "/usr/sbin/keepalivedreload" , subscribe=>File[ "/etc/keepalived/keepalived.conf" ], path=> "/bin:/sbin:/usr/bin:/usr/sbin" , refresh=> "/usr/sbin/keepalivedreload" , } } 6. 一切定义完毕进入测试 # 首先所有的包都没有安装 # 使用puppet apply -e 命令在master节点测试安装hosts模块前后 /etc/hosts 文件的变化情况 # 其余模块一次测试 , # 观察keepalived的启动效果,在配置文件中定义的vrrp已经出现 # 观察服务端口是否均已启动 # 本地测试没有异常的情况下,现在考虑将slave1.king.com之前内容情况后,利用puppet自动化部署slave1.king.com节点所需的软件和配置 master/slave测试 puppet master: 1, 安装puppet-server并配置,启动服务 yum -y install puppet-server-2.7.23-1.el6.noarch.rpm puppet master --genconfig >> /etc/puppet/puppet.conf service puppetmaster start puppet agent: 1、安装puppet客户端并配置,启动服务 yum -y install puppet-2.7.23-1.el6.noarch.rpm vim /etc/puppet/puppet.conf,在[agent]中添加server=master.king.com service puppet start # 在master/slave服务启动后,slave1节点会发出请求查询,master会从site.pp文件中查找slave1.king.com该装什么模块 1 2 3 4 5 6 7 8 9 10 11 #/etc/puppet/modules/site.pp #这里就是表示slave1将安装named,keepalived,haproxy,hosts等文件 #当然之前写过的模块还有这里的节点都可以按照面向对象编程里的class一样 #带有继承关系的 node 'slave1.king.com' { includenamed includekeepalived includehaproxy includehosts } #在master/slave服务启动后,agent会根据配置文件中server的位置发起调用安装配置的请求,这才服务器需要将请求签证 # 已达到安全传输的目的 签署证书: master: puppet cert list # 查看所有的客户端的签证请求 puppet cert sign --all # 签署所有请求,那么客户端与服务器就可以进行交互了 # 在稍等片刻后,这些节点将被自动的在slave1.king.com上完成部署,当然也可以手动进行 1 2 #slave1.king.com puppetagent-t # 手动去请求服务器应用完毕的结果 # 部署完毕后vrrp节点信息,此时仅仅部署了一个slave1节点,所以会有两个vrrp的ip地址,详见keepalived的配置文件 # slave1上自动部署完成后的服务端口信息 本文转自My_King1 51CTO博客,原文链接:http://blog.51cto.com/apprentice/1415003,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册