kolla from source

openstack做二次开发后需要重新打包. 本文简述使用kolla打包neutron和neutron_lib的场景.

需求:

二次开发的代码和依赖的包的打包.

项目代码打包:

配置neutron-base源:

/etc/kolla/kolla-build.conf
[neutron-base]
type = git
location = http://your-domain/openstack/neutron.git    # neutron代码项目地址
reference = stein   # 分支

依赖包打包:

依赖包的打包稍微麻烦一些, 比如要自定义neutron_lib===1.25.1, 首先要有个私有pypi仓库, 然后更改pip指向.

使用sonatype nexus做pypi proxy

创建pypi(proxy)作为上游pypi(pypi-douban). remote storage填写上游地址比如http://pypi.douban.com
创建pypi(hosted)作为自用pypi(pypi-local).
创建pypi(group)作为暴露的endpoint(pypi). group members里包含pypi-douban和pypi-local.

上传自定义的包

git tag 1.25.1
python setup.py sdist bdist_wheel
twine upload -r nexus dist/*  --repository-url http://pypi-domain:8081/repository/pypi-local/    # 这里pypi-local地址

修改kolla中pypi地址

cat base_header.j2
{% extends parent_template %}   # parent_template

{% block base_header %}         # 直接设置到base镜像里
RUN mkdir ~/.pip && echo -e "\
[global] \n\
index-url = http://<pypi-domain>:8081/repository/pypi/simple/ \n\
[install] \n\
trusted-host=<pypi-domain> \n\
" > ~/.pip/pip.conf

{% endblock %}

执行打包过程, 并上传到私有docker repo

/usr/local/bin/kolla-build --template-override /path/to/base_header.j2  neutron  -t source   --registry <docker repo>:8080 --push

可选(自定义yum.repo来加速)

配置文件中定义rpm_setup_config 私有.repo或.rpm地址

不推荐:

依赖包打包不推荐使用plugin的实现方式, 这种方式不灵活, 而且要workaround pip安装顺序的问题:

  1. 设置plugin地址
    [neutron-base-plugin-1neutron_lib] # 设置私有依赖包, 前面有个1保证优先安装
    type = local
    location = /path/to/1neutron_lib
  2. 修改config.py
    site-packages/kolla/common/config.py
  3. 代码打tag
    cd /path/to/1neutron_lib; git tag 1.25.1

无浮动IP的虚机出公网流量路径

Neutron构建网络时涉及的知识点比较广, 虚拟化网络实施上又具有非常大的灵活性, 这往往会让接触的同学摸不着头脑. 本文特意对"无浮动IP的虚机出公网流量路径"这一场景进行分享, 同时对涉及到的组件和知识点进行简要介绍, 希望能给对虚拟化网络感兴趣的同学一些帮助.

公司内虚拟化网络实施有很多种方式, 为什么单挑这个场景进行分享呢, 这主要是因为这个场景的链路相对比较长, 涉及到的知识点比较全, 没有硬件厂商的绑定具有通用性.

继续阅读“无浮动IP的虚机出公网流量路径”

prometheus cpu load average

长话短说, prometheus里获取load/CPU个数的方法(如果有更好的方式, 欢迎告知):

(sum (node_load1{}) by (instance) / count(count(node_cpu_frequency_hertz{}) without (mode)) by (instance)) > 0.7

为什么不用下面这种CPU idle查看呢?  因为像商店一样, 有空闲的售货员不代表客户结账不需要等待.

100 - (avg by (instance) (irate(node_cpu_seconds_total{job="consul-prometheus",mode="idle"}[5m])) * 100) > 70

为了提高查询性能, 可以为这个值设置recording rules.

Windows server migration from Xen + LVM to KVM+Ceph(virt-v2v)

旧环境:

XEN+LVM, Centos 5

新环境:

KVM+Ceph, Centos 7

转格式机:

virt-v2v

virt-v2v-copy-to-local

 

目的:把旧环境中的windows服务器迁移到新环境中。

 

工具:

virt-v2v:虚拟化磁盘文件转换工具

virt-v2v-copy-to-local: 将源虚拟化磁盘导出到本地工具,在源为lvm的时候会用到。

 

准备工作:

软件安装:

libguestfs-winsupport, virtio-win, virt-v2v

yum install kvm

systemctl start libvirtd

yum install libguestfs-winsupport

wget https://fedorapeople.org/groups/virt/virtio-win/virtio-win.repo -O /etc/yum.repos.d/virtio-win.repo

yum install virtio-win

yum install virt-v2v

 

免密登录:

转换机登录旧环境宿主机root账号做免密码(转换工具只能用这种方式)。

并在转换机上配置ssh-agent:

eval ssh-agent

ssh-add ~/.ssh/id_rsa

转化步骤:

  1. 旧环境源虚拟机(以instance-00000017为例)关机。

virt-v2v-copy-to-local -q -ic xen+ssh://root@xen.example.com instance-00000017

virt-v2v -i libvirtxml instance-00000017.xml -o local -os /data/image

  1. 新虚拟机(以instance-000007a2为例)关闭

virsh stop instance-000007a2

 

  1. 替换磁盘. ceph中旧磁盘重命名, 之后导入新镜像仍使用原磁盘名称.

获取新虚拟机的UUID如(ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e)

则第一块盘命名为ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk

第二块盘命名为ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk.eph0

 

ceph中重命名旧磁盘

rbd -p rbd rename ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk.bak

rbd -p rbd rename ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk.eph0 ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk.eph0.bak

新镜像导入到ceph

rbd -p rbd import --image-format 2 instance-00000017-sda ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk

rbd -p rbd import --image-format 2 instance-00000017-sdb ff4b7fe8-d56e-4dcc-92f1-6353ea5d977e_disk.eph0

  1. 启动实例

virsh start instance-000007a2

 

到这里已经迁移完成了。可以连接vnc查看。vnc viewer可能需要通过代理服务器。

 

备注:

dd旧版本不支持process参数,会报错,需要增加-q

参考文章:

https://docs.fedoraproject.org/quick-docs/en-US/creating-windows-virtual-machines-using-virtio-drivers.html

https://github.com/coreos/fleet/issues/1480

celery vs taskflow

    运维系统有这样一个需求, 简述一下就是: 执行任务A后执行B和C.B和C都执行完毕后执行任务D.

    由于以前用celery做任务调度, 很自然的查看是不是在celery中能够通过canvas实现(http://docs.celeryproject.org/en/latest/userguide/canvas.html).同时celery支持任务重试,也可以通过flower方便的查看任务执行状态. 貌似, 一切都是好的.

    可是后来在涉及到任务链回退的时候遇到了一些麻烦, 而且有任务竞争的问题. 开始反思是不是celery在任务流这种场景下是不是不合适, 是不是有更好的实现.

    刚开始想到自己实现一个, 大概会用到python的自省, 图(有序无环图)等, 但是工作量有些大了(其实是有些胆怯, 怕写不好哈哈), 最后决定现在找一下有没有现成的轮子.

    在大致查看了一下现有的轮子后, 这篇文章( https://medium.com/@jimbobhickville/be-one-with-the-taskflow-129e05a92bd4 )说服了我.

    taskflow是openstack下的一个工作流引擎, 支持线性流, 无序流, 图流, 而且任务定义和回退方式也很灵活方便.

    这里并不是说celery和taskflow哪个更好, 而是相比下, celery在分布式队列场景是很适合的, 而任务流的场景中, taskflow看上去更胜一筹, 当然2种工具结合起来用也是可以的.

通过外部系统管理saltstack的pillar

如果你现在已经有了一套资产管理系统, 支持账号权限控制, 能很方便的存放一些key/value. 同时也在使用saltstack进行系统管理. 是不是会觉得如果pillar放在资产管理系统会是一个不错的做法?

 

下面这种方式能够让你在资产管理系统中定义pillar, 然后打通到saltstack.

 

知识点:

在saltstack中, ext_pillar的优先级要比定义在master的pillar/foo.sls中高.

 

saltstack官方提供了一个http_json接口, 但是用起来会有2个不方便的地方:

  1. 不支持账号认证(提了个issue, https://github.com/saltstack/salt/issues/36138 ,还没修)
  2. 不支持只获取某个minion的pillar.

 

这就好说了, 既然有了葫芦, 可以比着画个瓢, 支持这2特性.

1. 增加ops_http_json.py

2. 在salt master上增加配置:

  ext_pillar:
    - ops_http_json:
       url: https://ops.ops.com/assets/salt/%s/pillars/
       username: username
       password: password

ops_http_json.py代码如下:

 

# -*- coding: utf-8 -*-
'''
A module that adds data to the Pillar structure retrieved by an http request


Configuring the HTTP_JSON ext_pillar
====================================

Set the following Salt config to setup http json result as external pillar source:

.. code-block:: yaml
  ext_pillar:
    - http_json:
        url: http://example.com/api/%s
        username: basic username
        password: basic password

Module Documentation
====================
'''

# Import python libs
from __future__ import absolute_import
import logging
import re

# Import Salt libs
try:
    from salt.ext.six.moves.urllib.parse import quote as _quote

    _HAS_DEPENDENCIES = True
except ImportError:
    _HAS_DEPENDENCIES = False

# Set up logging
_LOG = logging.getLogger(__name__)


def __virtual__():
    return _HAS_DEPENDENCIES


def ext_pillar(minion_id,
               pillar,  # pylint: disable=W0613
               url,
               username=None,
               password=None):
    '''
    Read pillar data from HTTP response.

    :param str url: Url to request.
    :param str username: username for basic auth
    :param str password: password for basic auth
    :return: A dictionary of the pillar data to add.
    :rtype: dict
    '''

    url = url.replace('%s', _quote(minion_id))

    _LOG.debug('Getting url: %s', url)

    if username and password:
        data = __salt__['http.query'](url=url, username=username, password=password, decode=True, decode_type='json')
    else:
        data = __salt__['http.query'](url=url, decode=True, decode_type='json')

    if 'dict' in data:
        return data['dict']

    _LOG.error("Error on minion '%s' http query: %s\nMore Info:\n", minion_id, url)

    for key in data:
        _LOG.error('%s: %s', key, data[key])

    return {}

postgresql连接池 pgpool vs pgbouncer

长话短说: 如果高TPS要做连接池, pgbouncer.

pgpool可以做failover和连接池, 但是有内存泄露的问题.

pgbouncer: 公司单实例大概在2000TPS, 高峰期内核态:用户态:剩余CPU大概在 2:1:2, 大部分的操作在fork进程上消耗, 用了连接池之后, 内核态占用能直接减小到可以忽略.真是好东西.

教程很容易搜索到, 就不列出来了.

这篇这么短, 再介绍点儿别的吧.

如果想找一个慢日志分析工具, 可以尝试pgbadger

主从同步流复制模式, 如果从库hung, 会导致主库hung.

高并发, 如果CPU不够用了, 分库前可以尝试先加CPU颗数试试.

redis刷磁盘可能会导致瞬时无法连接

业务日志监控中报告, 每天会有大约250次连接redis失败.

通过strace追踪发现.故障的时间点时写磁盘时间超过了10s.一般在10-15s之间. redis第二次重试使用的是10s.

这个实例所有的操作都是INCR, fdatasync block.

strace -Ttt -f -p 11302 -T -e  trace=fdatasync

11309 10:21:31.153900 fdatasync(116)    = 0 <0.034295>

11309 10:21:32.078747 fdatasync(116)    = 0 <7.592478>

11309 10:21:39.774959 fdatasync(116)    = 0 <10.098802>

11309 10:21:49.990623 fdatasync(116)    = 0 <2.026147>

11309 10:21:52.129676 fdatasync(116)    = 0 <0.002802>

治标:

超时时间改为15s.

治本:

正在用watchdog抓一下超过5s的堆栈.

堆栈:

[11302 | signal handler] (1499754857)

--- WATCHDOG TIMER EXPIRED ---

/usr/local/bin/redis-server-2.8 10.160.86.216:6699(logStackTrace+0x3e)[0x445ace]

/lib64/libpthread.so.0(write+0x2d)[0x7f19ef3b06fd]

/lib64/libpthread.so.0(+0xf710)[0x7f19ef3b1710]

/lib64/libpthread.so.0(write+0x2d)[0x7f19ef3b06fd]

/usr/local/bin/redis-server-2.8 10.160.86.216:6699(flushAppendOnlyFile+0x4e)[0x44116e]

/usr/local/bin/redis-server-2.8 10.160.86.216:6699(serverCron+0x3b7)[0x41bb17]

/usr/local/bin/redis-server-2.8 10.160.86.216:6699(aeProcessEvents+0x1e9)[0x416b69]

/usr/local/bin/redis-server-2.8 10.160.86.216:6699(aeMain+0x2b)[0x416deb]

/usr/local/bin/redis-server-2.8 10.160.86.216:6699(main+0x31d)[0x41e49d]

/lib64/libc.so.6(__libc_start_main+0xfd)[0x7f19ef02cd5d]

/usr/local/bin/redis-server-2.8 10.160.86.216:6699[0x415bd9]

[11302 | signal handler] (1499754857) --------

fdatasync会在某个时间点超过10s.

看来因为写磁盘堵塞了, 把机械硬盘换成了SSD, 解决了.

direct reclaim内存回收导致postgresql CPU占用激增

收到报警, Postgresql数据库服务器出现瞬时CPU占用高峰, load/cpu能从0.5瞬间飙升到5以上,每次持续15s-2mins波峰比较严重时候,会导致PHP进程数占满,进而影响API接口的新入请求.

由于每次发生的时间间隔大概2个小时, 但是没有规律. zabbix监控对这种突发最好只做到在1.5分钟后通知, 失去了事故现场.

由于报警延迟, 只能一边开着terminal实时观察, 一边在下次故障发生前排查其他的可能性.

怀疑是最近变更. 近期postgresql刚安装了jieba分词插件. 有可能会导致这个问题.

怀疑是由5%慢请求拖累整个数据库,造成服务器性能不够.这个根据经验是最可能的.

怀疑定时任务导致瞬时大量请求.

怀疑是因为数据量增大后内存热数据不够导致.

怀疑是vacuum或其他后台进程导致.

排查的过程中, 突然抓到事故现场. 立即查看内存和CPU相关指标.

1. _spin_unlock_irqrestore 占用89%CPU时间.

2. 单个sql请求消耗内存大概是25M.

grep Pss /proc/`ps auxf | grep hbforce_v4| grep -ir select | tail -n 1  | awk '{print $2}'`/smaps |awk '{total+=$2}; END {print total}'

3. 内存现状,显示还有大量的cached内存, 系统故障时候伴随着内存也扫描和回收.(低于/proc/zoneinfolow的值时触发回收,回收到high停止)

用到的知识点:

在系统空闲内存低于 watermark[low]时,开始启动内核线程kswapd进行内存回收.直到该zone的空闲内存数量达到watermark[high]后停止回收。如果上层申请内存的速度太快,导致空闲内存降至watermark[min]后,内核就会进行direct reclaim(直接回收),即直接在应用程序的进程上下文中进行回收,再用回收上来的空闲页满足内存申请,因此实际会阻塞应用程序.当前情况下.min-low-high之间只有15320KB的内存差.

而一个postgresql请求中需要分配的内存一般会在25MB左右.会导致直接触发强制回收.

下面是定位出来的触发逻辑:

1.内存不足时,单次申请内存过大,导致直接强制回收.触发compat_zone, 导致自旋锁,这个锁的特点是等待锁的过程中不休眠,而是占着CPU空转.spin_unlock_irqrestore — 禁止内核抢占并屏蔽中断,事先保存中断屏蔽位并事后恢复原状.

2.CPU空转导致新进入的任务堆积,load升高,并占用连接.

3.PHP不能处理导致进程占用,PHP-FPM进程达到最大值时候阻塞新请求进入.

4.API接口超时,导致前端调用失败,显示接口等待或失败.

5.内存回收完毕后释放锁,然后恢复正常.

总结原因是单次内存申请超过了min-low-high间隔,导致强制回收,触发了自旋锁.

调整内核参数解决:

vm.min_free_kbytes = 1081344

vm.vfs_cache_pressure = 200

当时的现场的数据:

[root@DATABASE ~]# cat /proc/zoneinfo

Node 0, zone   Normal

  pages free     20198

        min      15319

        low      19148

        high     22978

[root@DATABASE ~]# free -m

             total       used       free     shared    buffers     cached

Mem:         32109      31778        330          0        256      30215

-/+ buffers/cache:       1307      30802

Swap:        0        0      0

[root@DATABASE ~]# cat /proc/meminfo

MemTotal:       32879936 kB

MemFree:         2506208 kB

Buffers:          892660 kB

Cached:         28122840 kB

SwapCached:            0 kB

Active:         16954896 kB

Inactive:       12560144 kB

Active(anon):    3459900 kB

Inactive(anon):   310148 kB

Active(file):   13494996 kB

Inactive(file): 12249996 kB

Unevictable:           0 kB

Mlocked:               0 kB

SwapTotal:             0 kB

SwapFree:              0 kB

Dirty:              7004 kB

Writeback:             0 kB

AnonPages:        258360 kB

Mapped:          3255272 kB

Shmem:           3271380 kB

Slab:             471896 kB

SReclaimable:     419744 kB

SUnreclaim:        52152 kB

KernelStack:        3680 kB

PageTables:        38140 kB

NFS_Unstable:          0 kB

Bounce:                0 kB

WritebackTmp:          0 kB

CommitLimit:    16439968 kB

Committed_AS:    8292496 kB

VmallocTotal:   34359738367 kB

VmallocUsed:       65256 kB

VmallocChunk:   34359667396 kB

HardwareCorrupted:     0 kB

AnonHugePages:         0 kB

HugePages_Total:       0

HugePages_Free:        0

HugePages_Rsvd:        0

HugePages_Surp:        0

Hugepagesize:       2048 kB

DirectMap4k:        6016 kB

DirectMap2M:     2091008 kB

DirectMap1G:    31457280 kB

[root@DATABASE ~]# numactl --hardware

available: 1 nodes (0)

node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

node 0 size: 32767 MB

node 0 free: 1141 MB

node distances:

node   0

  0:  10

[root@DATABASE ~]# cat /proc/zoneinfo

Node 0, zone   Normal

  pages free     20198

        min      15319

        low      19148

        high     22978

        scanned  0

        spanned  7602176

        present  7498240

[root@DATABASE ~]# sar -B 1

Linux 2.6.32-279.el6.x86_64 (DATABASE) 06/21/2017 _x86_64_ (16 CPU)

12:51:57 AM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff

12:51:58 AM    129.17    612.50  13683.33      0.00  23310.42      0.00   7663.54   7704.17    100.53

12:51:59 AM   1872.34     12.77  17207.45      0.00  29784.04      0.00   2325.53   2325.53    100.00

12:52:00 AM    148.84      0.00  19734.30     11.05  24716.86      0.00   4424.42   4424.42    100.00

12:52:01 AM     84.21      0.00   2047.37     21.05  18484.21      0.00   4347.37   4178.95     96.13

12:52:02 AM   1025.00      0.00  18497.92      2.08  22652.08      0.00   5256.25   5289.58    100.63

12:52:03 AM   2235.79    450.53  52714.74      4.21  87222.11      0.00  24298.95  24297.89    100.00

12:52:05 AM     13.45      6.72  13763.87      0.00  22565.55      0.00   1813.45   1813.45    100.00

12:52:06 AM      8.00      0.00  14222.00      0.00  16852.00      0.00   5255.00   5199.00     98.93

12:52:07 AM  11734.69    114.29 190776.53      1.02 223285.71      0.00  43768.37  43814.29    100.10

12:52:08 AM  58848.98   1559.18 226263.27      0.00 233448.98      0.00   1057.14   1057.14    100.00

12:52:09 AM 108673.47     24.49 140714.29      0.00 142710.20      0.00      0.00      0.00      0.00

12:52:10 AM  65834.34     16.16  41429.29      0.00  42891.92      0.00      0.00      0.00      0.00

12:52:11 AM  59104.17      0.00  59959.38      0.00  60518.75      0.00      0.00      0.00      0.00

12:52:12 AM  56040.40    137.37  46878.79      0.00  40731.31      0.00      0.00      0.00      0.00

对应的是

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----

82  1      0 581128 587036 30372132    0    0 17092   616 63036 2132  1 99  0  0  0

73  1      0 687572 586204 30274540    0    0  1476    24 18942  581  0 100  0  0  0

83  0      0 700872 585844 30250296    0    0   432   588 16374  427  0 100  0  0  0

51  1      0 715412 585816 30238628    0    0  1752    12 16660  508  1 99  0  0  0

87  1      0 726340 585784 30229336    0    0   212     0 17575  480  1 99  0  0  0

88  1      0 742876 585760 30196484    0    0   116     0 25373  712  1 99  0  0  0

80  1      0 753324 585620 30180436    0    0  1328   428 17074  504  1 99  0  0  0

90  0      0 828596 585088 30092832    0    0  1736     8 19115 1378  1 99  0  0  0

86  0      0 835460 585000 30088000    0    0    16     0 17247  461  0 100  0  0  0

82  0      0 888980 584364 29995256    0    0    24     8 18090  574  1 99  0  0  0

 1  1      0 1012756 583688 29915708    0    0 20796   112 19206 4382  6 73 20  1  0

 1  1      0 1018156 583952 29982312    0    0 68868  1520 8720 5912  4  7 85  3  0

 0  1      0 962080 584016 30083852    0    0 101396    24 6240 4274  3  4 89  4  0

 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

 1  1      0 906804 584032 30144308    0    0 61180    16 4026 3513  1  2 93  4  0

这些信息没有在默认的监控中体现出来, 后续又细化zabbix内存监控.

细化的模板在这里

参考文章:

http://blog.2baxb.me/archives/1065

https://engineering.linkedin.com/performance/optimizing-linux-memory-management-low-latency-high-throughput-databases

https://www.kernel.org/doc/gorman/html/understand/understand013.html

http://os.51cto.com/art/201310/412638.htm

http://www.cs.fsu.edu/~baker/devices/lxr/source/2.6.11.8/linux/mm/mempool.c

http://blog.csdn.net/longxibendi/article/details/44625703

https://www.google.com/#newwindow=1&hl=en&q=kswapd+spin_unlock_irqrestore+cpu

https://www.google.com/#q=%22compact_zone%22+spin_unlock_irqrestore