swarm task 的更新流程

swarm 声明了 13 中 task 状态,如下:

TaskStateNew TaskState = 0
TaskStateAllocated TaskState = 64
TaskStatePending TaskState = 128
TaskStateAssigned TaskState = 192
TaskStateAccepted TaskState = 256
TaskStatePreparing TaskState = 320
TaskStateReady TaskState = 384
TaskStateStarting TaskState = 448
TaskStateRunning TaskState = 512
TaskStateCompleted TaskState = 576
TaskStateShutdown TaskState = 640
TaskStateFailed TaskState = 704
TaskStateRejected TaskState = 768

 

1. Orchestrator 判断如果 service 指定的 slot 数量大于正在运行的 slot 数量, 则创建 task,状态为 TaskStateNew;

2. TaskStateAllocated 为 task 收集网络资源之后把状态改成 TaskStateAllocated;

3. TaskStatePending 表示 Scheduler 收到请求但是还未 unassigned,在代码中我未见到有把状态改成 TaskStatePending;

4. Scheduler 收到 task 之后会把 task 调度到合适的 node 上,状态改为 TaskStateAssigned;

5. 进入 Agent 的处理流程:

1). Agent 收到 task,并且获取到 task 的 Controller 之后改成 TaskStateAccepted;

2). 如果状态为 TaskStateAccepted,改成 TaskStatePreparing;

3). 如果状态为 TaskStatePreparing,调用 Controller 的 Prepare 方法,把状态改成 TaskStateReady;

4). 如果状态为 TaskStateReady,改成 TaskStateStarting。

5). 如果状态为 TaskStateStarting,调用 Controller 的 Start 方法,把状态改成 TaskStateRunning;

6). 如果状态为 TaskStateRunning,则调用 Controller 的 Wait 方法,如果 task 执行完了,状态改为 TaskStateCompleted;

当 task 状态有变化,Agent 会通过到 Dispatcher 的 session 把状态汇报给 Dispatcher。

7). 当 task 的 DesiredState 为 TaskStateShutdown 而且状态小于 TaskStateCompleted 时,调用 Controller 的 Shutdown 方法,关闭 task。

task 的 DesiredState 在 task 创建之后是 TaskStateRunning,如果 manager 想关闭 task,把 DesiredState 设置成 TaskStateShutdown(DesiredState 只能被 manager 修改)。

 

Java 程序的发布流程

之前的文章介绍了 Python 和 Nodejs  的发布流程,这里再说一下 Java 的,基本齐全了。

1. git 项目里需要一个 pom.xml 文件,用于打包。

为了区分 production、preonline 和 development,可以使用两种方式 – filtering 和 profile

1). 使用 filtering;

第一,在 pom.xml  里开启 filtering 功能:<filtering>true</filtering>

第二,在 pom.xml 的 build/filters/filter 里写上路径,用变量 env 来表示环境.

[text]
<build>

<filters>
    <filter>src/main/resources/filter.properties.${env}</filter>
</filters>

</build>
[/text]

第三,filter.properties.* 里面写各个环境的配置(比如数据库信息),此时用 mvn 打包:

[shell]mvn clean package -D maven.test.skip=true -Denv=production[/shell]

-D maven.test.skip=true 等同于 -Dmaven.test.skip,表示忽略测试代码。

2). 使用 profile.

类似下面的配置文件:

[text]
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>profile-development.properties</filter>
</filters>
</build>
</profile>
<profile>
<id>production</id>
<build>
<filters>
<filter>profile-production.properties</filter>
</filters>
</build>
</profile>
</profiles>
[/text]

打包命令类似

[shell]mvn clean package -D maven.test.skip=true -Pproduction[/shell]

用 -P 指定 profile 的 id,mvn 会使用对应的 profile,不指定 -P 的话,会使用 activeByDefault=true 的一项(即 development).

 

2. 把 war 包(或 jar 包等) post 到包管理系统,带入参数可以有 项目名、分支号、包名和机房(如果需要),发布的时候发布系统就可以知道发布的项目名,以及分支,以及下载链接(post 之后生成,放在数据库)。

 

3. 发布,拿到包,解压到机器上,放入 tomcat 的 webapp 目录,启动 tomcat.

 

此文有待继续补充。

 

参考:

https://spring.io/guides/gs/maven/

http://archboy.org/2012/05/21/apache-maven-profile-filtering-multiple-build-environments/

Python 程序的发布流程

记录一下 Python 的发布流程。


1.代码的项目里要求有 requirements.txt 文件。

可以使用 链接 中的 pip-tools 来生成 requirements.txt .

例如先在 requirements.in 写入

futures
ujson
tornado
DBUtils
jinja2
redis
MySQL-python

然后运行

pip-compile requirements.in

这个命令生成 requirements.txt,如下:

#
# This file is autogenerated by pip-compile
# Make changes in requirements.in, then run this to update:
#
# pip-compile requirements.in
#
backports.ssl-match-hostname==3.4.0.2 # via tornado
certifi==2015.4.28 # via tornado
dbutils==1.1
futures==3.0.3
jinja2==2.7.3
markupsafe==0.23 # via jinja2
mysql-python==1.2.5
redis==2.10.3
tornado==4.2
ujson==1.33

2.然后执行命令:

mkdir ./wheelhouse;
pip wheel -r requirements.txt -w ./wheelhouse/

在 ./wheelhouse 目录下生成了 .whl 格式的二进制依赖包.


3.把程序打包, 解压到机器上;


4.执行虚拟环境:

virtualenv .venv
source .venv/bin/activate

5.通过执行:

pip install --use-wheel --no-index --find-links=./wheelhouse/ -r requirements.txt

来安装二进制依赖文件.


6.启动程序即可.

Nodejs 的发布流程

nodejs 的发布流程和 Python 相比还要简单些,先看下面的流程:


1.要求在每个 nodejs 项目下面都有 package.json 文件。

package.json 是 本项目的依赖,用 npm install 会把依赖下载到本目录的 node_modules 下。

由于有线上环境和测试环境之分,可以用 npm install –production 或者设置环境变量 NODE_ENV 为 production 之后用 npm install 都只会安装 package.json 文件中 dependencies 的依赖,dependencies 即是线上环境。

否则 npm install 会把 dependencies 和 devDependencies 的依赖都装上,此时用于测试环境。


2.还要求项目下面有一个配置文件用于表示 NODE_ENV 、 PORT 和 LOG 环境变量。

把 NODE_ENV 环境变量写入文件的目的是为了正式环境和测试环境打不同的包,用一样的启动脚本,和 Java 的打包工具 maven 根据配置文件打不同的包的想法类似。

如果 NODE_ENV 是 production,表示只打 dependencies 的依赖,否则都打;PORT 只是用来表示启动端口;LOG 表示日志目录。

我们的配置文件格式如下:

{
    "node_env": "production",
    "port": 8080
}

3.打包。

来个打包脚本示例(封装一下启停脚本 start.sh、stop.sh,打在包里):

#!/bin/bash

project_url=""

export NODE_ENV=""

project_name=`echo $project_url |basename |sed "s/.git//g"`

git clone $project_url
cd $project_name

npm install && \
cd .. && \
cp start.sh stop.sh $project_name && \
tar czf $project_name-`date "+%Y%m%d%H%M%S"`.tgz $project_name

4.打包之后上传到远程服务器(打包应该支持分支选项,发布的时候会用到分支)。


5.开始发布,拿到上面打的包。


6.到目标服务器上解压,执行启动脚本(start.sh),启动脚本示例(使用 forever 启动,文档):

#!/bin/bash

cd $project_dir

export NODE_ENV=$_env
export PORT=$port
export FOREVER_ROOT=`pwd`

forever -l logs/access.log -e logs/error.log -o logs/out.log -a start -c "node –harmony" bin/www

最后,如果想限定依赖的版本 可以用 npm shrinkwrap ,但是发布流程要变,文档。

构建机房运维基础架构(三): 自动装机流程

流程

1. 根据 SN 去 DDNS 请求 ILO IP

2. 设置第二块网卡支持PXE启动 (通过 ssh root@$iloip 设置)。

3. 设置启动顺序,硬盘启动第一优先级,第二块网卡第二优先级。

4. 设置机器从PXE启动一次。

5. 重启

6. 拷贝对应的tftp 配置文件(根据mac地址命名文件名)

7. 机器从第二块网卡启动PXE,通过DHCP获取到IP,DHCP告诉机器 tftp服务器的IP

8. 机器连接tftp服务器,获取内核文件,加载内核,并获取到 tftp配置文件,并根据配置文件去请求 ks 文件。

9. 拿到ks文件,执行装机流程,包括 语言、时区、硬盘格式化、防火墙 等等。

10. 执行到post阶段,开始执行自己的自定义脚本。

11. 我们的装机类型有三种:
1) raw_clean (纯净物理机)
2) kvm_host  (宿主机)
3) kvm_guest (虚拟机)

我们的自定义脚本是post_install.sh ,会自动装好三种 类型的机器;脚本做的最重要的事情有:
1) 通用初始化
2) 获取主机名和IP,并配置到系统
3) 准备好增加本机主机名到DNS的脚本到机器上。
4) 准备puppet执行环境

这个脚本也是最可能需要动的了。

12. post 阶段 之后 是 重启,重启之后DNS脚本自动执行,把自己的主机名增加DNS,然后Puppet 开始执行初始化环境 ( Puppet会自动把资产和监控的客户端安装好,资产的客户端会把机器信息上传到资产系统 )。

 

注意的问题

1. 物理装机我们用DHCP指定的 DNS —

    option domain-name-servers 10.0.12.234;
    option domain-name “nosa.me;

虚拟机装机的时候在virt-install 命令里 要手动指定一个 dns server —

   -x “ip=xxx netmask=xxx gateway=xxx dns=xxx “ 

这样会解析所有的全域名,但是遇到 前缀域名就完蛋了,因为 kickstart 不支持search nosa.me 之类的语法;这个问题导致了我的Puppet 不能工作,初始化失败。

所以可以在post阶段 执行下面这个命令:
  echo “search nosa.me” >>/etc/resolv.conf

此乃大坑。