在使用supervisord管理nginx的时候,发现nginx提示端口占用后异常退出,

2019-03-15 02:36:37,587 INFO RPC interface 'supervisor' initialized
2019-03-15 02:36:37,587 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2019-03-15 02:36:37,588 INFO supervisord started with pid 9662
2019-03-15 02:36:38,591 INFO spawned: 'nginx' with pid 9664
2019-03-15 02:36:38,595 INFO spawned: 'app-gunicorn' with pid 9665
2019-03-15 02:36:38,616 INFO exited: nginx (exit status 0; not expected)
2019-03-15 02:36:39,610 INFO success: app-gunicorn entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2019-03-15 02:36:39,628 INFO spawned: 'nginx' with pid 9686
nginx: [emerg] bind() to 0.0.0.0:10087 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:10087 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:10087 failed (98: Address in use)
2019-03-15 02:36:40,652 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
nginx: [emerg] bind() to 0.0.0.0:10087 failed (98: Address in use)
nginx: [emerg] bind() to 0.0.0.0:10087 failed (98: Address in use)

手动执行nginx可以正常启动,查询了一番,找到了如下,不能用daemon的方式启动nginx,所以修改nginx配置,添加daemon off; 后恢复正常

Supervisord expects nginx to not fork but remain in foreground. Set daemon to off in the nginx configuration file

背景

项目中需要使用python执行ansible的任务,每项任务均需要获取执行结果并做解析,为了方便调用,对ansible的api调用做了封装并对返回结果做了友好处理,特做记录。

理想中的调用方式

先不考虑封装逻辑,个人作为使用者,希望的一种使用方式如下(伪代码):

if __name__ == "__main__":
    host_list = ['192.168.8.33', '192.168.8.35']
    api = AnsibleApi(host_list, user=root, password=123)
    # 传递playbook的path,执行playbook task
    api.run_playbook(["playbook_path"])
    # 得到执行结果
    return api.get_playbook_result()

即我告诉api,我想在host_list所在的机器上执行playbook_path这个playbook指定的任务,然后我得到一个友好的执行结果

理想中的友好返回

因为ansible会在多个机器执行多个任务,每个机器上的每个任务的执行情况都需要收集,于是作为开发者,更期望得到如下结构的返回结果:

Read on →

case概述

python可以使用多线程处理多个任务,最基本的处理思路如下:

  • 定义一个基类,然后基于该类实现多个子类完成业务功能;
  • 为每个子类的调用分配一个子线程,并调用子线程的业务入口;
  • 运行子线程,主线程实现任务结果处理;

基于以上思路,做了基本的case,代码参考github地址,项目结构如下:

.
└── thread_test
    ├── __init__.py
    ├── collector
    │   ├── __init__.py
    │   ├── c1.py
    │   ├── c2.py
    │   └── collector.py
    ├── threads.py
    └── threads_queue.py

代码简介

定义一个基类,然后基于该类实现多个子类完成业务功能

collector包下定义了collector这个基类,然后c1.py与c2.py分别是实现了该基类的子类,同时使用get_data模拟业务逻辑的入口,

from .collector import Collector

class C1(Collector):
    @classmethod
    def get_data(cls, msg):
        print("i am from ", msg)
        return msg
Read on →

  • task解析json并注册变量给其他task使用

    多个task涉及变量传递时,有时taskA取值是json格式,taskB若想使用json中的数据,可以通过如下方式:

# get config task stdout is json format
- name: "get_config"
  shell: /usr/local/sbin/kubectl get cm global-var -n alauda-system -o json
  register: cms

# use from_json plugin
- set_fact: data=""

- name: "read_config"
  shell: /usr/local/bin/redis-cli -a
  when: data['kind'] == 'ConfigMap'
  • ansible自定义模块执行命令支持管道

    自定义ansible module时,可以默认使用AnsibleModule的实例run_command来执行shell命令,可以指定use_unsafe_shell=True来让ansible支持管道。 use_shell会和shell模块类似,若不指定,默认为False,则以command模块运行,command是比较安全的隧道连接,但是不支持管道

def main():
    """The main function."""
    module = AnsibleModule(argument_spec=dict(),supports_check_mode=False)
    module.run_command("/usr/local/sbin/kubectl get po -n alauda-system |grep alauda-redis|awk \'END{print $1}", use_unsafe_shell=True)
    redis = Redis(module)
    rst = redis.get_redis_status()
    module.exit_json(**rst)
Read on →

  • k8s默认驱逐设置
// DefaultEvictionHard includes default options for hard eviction.
var DefaultEvictionHard = map[string]string{
        "memory.available":  "100Mi",
        "nodefs.available":  "10%",
        "nodefs.inodesFree": "5%",
        "imagefs.available": "15%",
}
  • kubernetes 滚动升级
# run test deploy
[root@k8s-master ~]# kubectl run --image=nginx --port=80 --replicas=2 yxli-nginx
# scale replica
[root@k8s-master ~]# kubectl scale --replicas=1 deploy/yxli-nginx
[root@k8s-master ~]# kubectl get deploy
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
busybox      2         2         2            2           39d
busybox1     1         1         1            1           39d
yxli-nginx   1         1         1            1           2h
# update image
[root@k8s-master ~]# kubectl set image  deploy/yxli-nginx yxli-nginx=nginx:alpine
# 查看升级历史
[root@k8s-master ~]# kubectl rollout history deploy/yxli-nginx
deployments "yxli-nginx"
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
# 回顾至上次版本
[root@k8s-master ~]# kubectl rollout undo deploy/yxli-nginx
[root@k8s-master ~]# kubectl rollout history deploy/yxli-nginx
deployments "yxli-nginx"
REVISION  CHANGE-CAUSE
2         <none>
3         <none>
# 回滚至指定版本
[root@k8s-master ~]# kubectl rolloutundo deployment/lykops-dpm --to-revision=2
Read on →