liu 发布的文章

什么是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,望技术有成后能回来看见自己的脚步


.NET Core部署到linux(CentOS)最全解决方案,常规篇一文,我们详细讲解了传统的.NET Core部署到Linux服务器的方法,学到了Linux在虚拟机下的安装、Xshell,Xftp的使用方法、git在linux下的交互使用以及.net core在linux下的发布与运行全过程。本文讲讲解通过使用Supervisor+Nginx的组合来实现.net core的高效部署。

官网:http://supervisord.org,源码位置:https://github.com/Supervisor/supervisor

Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。

它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。

在linux或者unix操作系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。由于在linux中,每个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端被称为这些进程的控制终端,当控制终端被关闭的时候,相应的进程都会自动关闭。但是守护进程却能突破这种限制,它脱离于终端并且在后台运行,并且它脱离终端的目的是为了避免进程在运行的过程中的信息在任何终端中显示并且进程也不会被任何终端所产生的终端信息所打断。它从被执行的时候开始运转,直到整个系统关闭才退出。

此处的创建守护进程,是指发布在Linux上 asp.net core 程序的dotnet xxx.dll命令的宿主进程创建一个守护进程。在 Linux 上有很多可以管理进程的工具,我们使用 Supervisor 来做这个事情。

原因有两点:

①、它是微软官方文档推荐的,降低学习成本。
②、它并不一定是最好的,但一定是文档最全的。

  • supervisord

主进程,负责管理进程的server,它会根据配置文件创建指定数量的应用程序的子进程,管理子进程的整个生命周期,对crash的进程重启,对进程变化发送事件通知等。同时内置web server和XML-RPC Interface,轻松实现进程管理。。该服务的配置文件在/etc/supervisor/supervisord.conf。

  • supervisorctl

客户端的命令行工具,提供一个类似shell的操作接口,通过它你可以连接到不同的supervisord进程上来管理它们各自的子程序,命令通过UNIX socket或者TCP来和服务通讯。用户通过命令行发送消息给supervisord,可以查看进程状态,加载配置文件,启停进程,查看进程标准输出和错误输出,远程操作等。服务端也可以要求客户端提供身份验证之后才能进行操作。

  • Web Server

superviosr提供了web server功能,可通过web控制进程(需要设置[inethttpserver]配置项)

  • XML-R- #supervisor

一个Linux/Unix系统上的进程监控工具
一个Python开发的通用的进程管理程序
可以管理和监控Linux上面的进程
能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启
不过同daemontools一样,它不能监控daemon进程

相应安装建议以管理员方式登录系统,非管理员请以sudo命令安装。

Linux sudo命令以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行。

1、安装EPEL源的命令如下:

  1. sudo yum -y install epel-release

安装EPEL源

2、执行如下命令安装supervisor:

  1. sudo yum -y install supervisor

安装supervisor

3、设置开机启动:

  1. systemctl enable supervisord

设置开机启动

4、启动supervisord

  1. systemctl start supervisord

5、查看supervisord状态

  1. systemctl status supervisord

查看supervisord状态

通过vi命令或者xftp修改配置文件开启web界面访问,如下图所示,分别取消inet_http_server等四个配置的注释:

  1. vi /etc/supervisord.conf

image-20210114101415192

执行如下命令,重新加载配置文件:

  1. supervisorctl reload

然后在浏览器打开http://你的ip:9001,输入上面我们设置的用户名:user1,密码:123456后,如图所示:

image-20210114101622234

image-20210114101825812

看到上图这个界面,就表示supervisor安装完成了。

切换到/etc/supervisord.d目录,在此目录创建名称为:core50test.ini的ini文件,内容如下:

  1. #表示程序名称,用于在supervisor中显示,无特殊意义。

  2. [program:core50test]

  3. # 输入执行命令,这里表示执行的是dotnet Core50Test.dll

  4. command=/bin/bash -"dotnet Core50Test.dll"

  5. # 应用程序根目录

  6. directory=/root/app_data/core50test/publish

  7. # 是否自动启动,当 supervisor 加载该配置文件的时候立即启动它

  8. autostart=true

  9. # 是否自动重启, 程序异常退出后自动重启

  10. autorestart=true

  11. # 该配置文件输出单个日志文件的大小,默认50M

  12. logfile_maxbytes=50MB

  13. # 日志备份个数

  14. logfile_backups=10

  15. # 记录日志级别

  16. loglevel=info

  17. # 指定标准输出日志文件

  18. stdout_logfile=/root/app_data/data/logs/core50test/core50test.out.log

  19. # 环境变量

  20. environment=ASPNETCORE_ENVIRONMENT=Production

  21. # 启动服务的用户

  22. user=root

  23. # 把stderr重定向到stdout,默认 false

  24. redirect_stderr=true

上述代码包含了注释信息,参考精減版配置如下:

  1. [program:core50test]

  2. command=/bin/bash -"dotnet Core50Test.dll"

  3. directory=/root/app_data/core50test/publish

  4. autostart=true

  5. autorestart=true

  6. logfile_maxbytes=50MB

  7. logfile_backups=10

  8. loglevel=info

  9. stdout_logfile=/root/app_data/data/logs/core50test/core50test.out.log

  10. environment=ASPNETCORE_ENVIRONMENT=Production

  11. user=root

  12. redirect_stderr=true

注意:stdout_logfile指向的文件夹一定要先创建,否则无法启动,上述配置文件中的内容需要根据用户实际情况修改,如我当前登录的用户是:yonghu,你们是其他的就做相应的修改即可。

然后执行如下命令来重新加载配置:

  1. supervisorctl reload

命令执行成功后, 刷新浏览器,可以看到如下界面:

supervisor正在运行的应用

当界面显示running时,则表示我们我们刚刚配置的.net core应用运行起来了。

如下图所示。

image-20210114150451949

我们可以方便的通过supervisor提供的web管理界面对我们的应用进行启动与停止,查看日志等操作,非常的方便,丝般润滑般的爽呀。

Supervisor启动与停止应用

查看日志:

查看日志

  1. ### 查看supervisorctl支持的命令

  2. # supervisorctl help

  3. default commands (type help <topic>):

  4. =====================================

  5. add exit open reload restart start tail

  6. avail fg pid remove shutdown status update

  7. clear maintail quit reread signal stop version

  8.  

  9. ### 查看当前运行的进程列表

  10. # supervisorctl status

Supervisor常用命令

  • update 更新新的配置到supervisord(不会重启原来已运行的程序)

  • reload,载入所有配置文件,并按新的配置启动、管理所有进程(会重启原来已运行的程序)

  • start xxx: 启动某个进程

  • restart xxx: 重启某个进程

  • stop xxx: 停止某一个进程(xxx),xxx为[program:theprogramname]里配置的值

  • stop groupworker: 重启所有属于名为groupworker这个分组的进程(start,restart同理)

  • stop all,停止全部进程,注:start、restart、stop都不会载入最新的配置文

  • reread,当一个服务由自动启动修改为手动启动时执行一下就ok

最常用的几个命令为:

  1. #启动所有

  2. supervisorctl start all

  3.  

  4. # 重启所有

  5. supervisorctl restart all

  6.  

  7. # 停止所有

  8. supervisorctl stop all

  9.  

  10. #PS:要操作某个服务,把all换成服务名即可

  11. #查看服务状态

  12. supervisorctl status

在前面文章中,我们已经可以非常方便的对web应用进行部署与管理了,但还存在一个问题,我们的应用程序默认是绑定的5000端口,如果要指定80端口或者配置域名该怎么处理呢?下面就该nginx登场了。

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

安装方式参考:http://nginx.org/en/linux_packages.html#RHEL-CentOS

安装先决条件:

  1. sudo yum install -y yum-utils

安装yum-utils

设置yum存储库,先创建一下内容的文件:/etc/yum.repos.d/nginx.repo

  1. [nginx-stable]

  2. name=nginx stable repo

  3. baseurl=http://nginx.org/packages/centos/$releasever/$basearch/

  4. gpgcheck=1

  5. enabled=1

  6. gpgkey=https://nginx.org/keys/nginx_signing.key

  7. module_hotfixes=true

  8.  

  9. [nginx-mainline]

  10. name=nginx mainline repo

  11. baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/

  12. gpgcheck=1

  13. enabled=0

  14. gpgkey=https://nginx.org/keys/nginx_signing.key

  15. module_hotfixes=true

image-20210114161247091

默认情况下,使用稳定 nginx 包的存储库。如果要使用主线 nginx 包,请运行以下命令:

  1. yum-config-manager --enable nginx-mainline

运行如下命令安装nginx:

  1. sudo yum install -y nginx

安装nginx

设置开机启动:

  1. systemctl enable nginx

启动nginx:

  1. systemctl start nginx

设置nginx开机启动并启动nginx

此时,就可以在浏览器通过ip访问了:http://你的ip,界面如下:

nginx启动界面

nginx安装完成后,切换到/etc/nginx/conf.d目录,修改default.conf文件内容,如下所示:

  1. server {

  2. listen 80;

  3. server_name localhost;

  4. location / {

  5. proxy_pass http://0.0.0.0:5000;

  6. }

  7. error_page 500 502 503 504 /50x.html;

  8. location = /50x.html {

  9. root /usr/share/nginx/html;

  10. }

  11. }

保存后,执行如下命令,重新加载配置:

  1. nginx -s reload

然后再次访问http://你的ip,一切正常的话应该可以看到如下的界面,表示我们的.NET Core程序已经完美运行在linux系统了。

以nginx方式运行

如果部署后遇到类型下面这样的错误

502网关错误

出现这样的问题,有可能的是因为SeLinux的限制,执行如下命令之后,再刷新页面:

  1. setenforce 0

selinux(security enhanced linux)安全增强型linux系统,它是一个linux内核模块,也是linux的一个安全子系统。

selinux的主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)

如果设置后还是不能解决,可以查看nginx的日志了,默认的日志路径为:/var/log/nginx

通过setenforce 0命令,只是临时实效,重启后会失效。

可以通过修改/etc/selinux/config 文件,将SELINUX=enforcing改为SELINUX=disabled,然后重启,即可永久生效。

image-20210114181544503

通过近两篇文章的介绍,我们需要更新应用,只需要将代码提交到git仓库,然后在服务器中执行git pull和dotnet publish即可。

如果熟悉shell的话,可以通过编写shell命令一键执行应用程序的更新,代码示例:

  1. # !/bin/bash

  2. cd /root/app_data/source/core50test

  3. git pull

  4. dotnet publish -/root/app_data/core50test/publish

  5. supervisorctl restart core50test

将上述的代码保存为sh文件,上传到服务器,并设置权限。如下图所示:

image-20210115155730265

代码提交到git仓库后,执行如下命令:

  1. ./build.sh

执行结果如下图所示:

shell教本部署

更新后重新运行,已经更新。

image-20210115113537048

这儿可能有的小伙伴会遇到一个小小的坑要注意,shell脚本写得没有问题,执行会报类似这样的错误

  1. $'\r':command not found

出现这种问题是因为windows下的文件换行用的是\r\n,而linux系统用的是\n,如果在win下的文档上传到linux,就有可能出现这样的问题,只需用vi打开shell脚本文件,然后使用命令:set ff=unix,保存文件即可。

shell命令 unix格式设置

supervisor一个作为守护线程,用于维护应用程序的生命周期的,nginx则是作为反向代理使用,配置shell可以做到高效部署,非常的方便。