跳转至

运维-12-综合问题记录

问题1:SSH 虚拟机,报 Cannot allocate memory 异常

问题现象

当通过 ssh 登录虚拟机时,会出现 Cannot allocate memory 异常,具体现象如下:

[root@192e168e3e201 ~]# ssh 192.168.9.66
Last failed login: Thu Aug  2 10:12:05 CST 2018 on tty1
There were 2 failed login attempts since the last successful login.
Last login: Thu Aug  2 10:01:46 2018 from 192.168.9.201
-bash: fork: Cannot allocate memory
-bash-4.2#
-bash-4.2# free -h
-bash: fork: Cannot allocate memory

处理过程

  1. 通过 VNC 方式登录虚拟机。
  2. free 查看内存还比较充足(注意,命令可能要多敲几次才会出来)
-bash-4.2# free
              total        used        free      shared  buff/cache   available
Mem:      528198152    28698836   487266620      151640    12232696   497758644
Swap:             0           0           0

可以看出内存还有不少,应该不是内存使用过多的问题。

  1. 查看最大进程数
-bash-4.2# sysctl kernel.pid_max
kernel.pid_max = 40960
  1. 查看现有进程数
-bash-4.2# ps -eLf |wc -l
40827

由此可以看出进程数基本满了

  1. 修改最大进程数
-bash-4.2# echo "kernel.pid_max=1000000 " >> /etc/sysctl.conf
-bash-4.2# sysctl -p
kernel.pid_max = 1000000
  1. 最后重新 ssh 登录虚拟机,可以成功登录
[root@192e168e3e201 ~]# ssh 192.168.9.66
Last login: Thu Aug  2 14:39:40 2018 from 192.168.9.201
[root@192e168e9e66 ~]#

问题原因

进程数满了,后续 ssh 也会占用一个系统进程,所以 ssh 登录不上去。

问题2:物理机ping其他节点出错,且物理机经常失联

问题现象

从物理机 ping 其他节点时,ping 报如下错误

../../_images/2-1-ping-error.png

而且经常无法 SSH 登录到该机器,ping 也时好时坏。

处理过程

  1. 在物理机查看 arp 表,发现内容不多。

../../_images/2-2-arpinfo.png

  1. 在名称空间统计 arp 表,发现有很多统计数值很大。
  2. 修改下列参数,问题解决
# sysctl -w net.ipv4.neigh.default.gc_thresh1=1024
# sysctl -w net.ipv4.neigh.default.gc_thresh2=2048
# sysctl -w net.ipv4.neigh.default.gc_thresh3=4096
# sysctl -p

问题原因

名称空间的 arp 表过于庞大,发生抖动。

问题3:计算节点CPU负载突然过高

问题现象

一台计算节点 CPU 负载突然过高,并且该计算节点的虚拟机全部无法联网。

../../_images/3-1-cpuinfo.png

处理过程

  1. 跟踪其中一个负载过高虚拟机的进程
# strace -p 19096

../../_images/3-2-strace-error.png

发现出现大量文件描述符错误,为进程读取文件的错误。

  1. 通过 ip a 查看网卡信息,发现 tap 设备消失。
  2. 通过 ovs-vsctl 命令查看 ovs 网桥上的接口信息,发现网桥上的 tap 设备也消失了。
# ovs-vsctl show
  1. 重启该计算节点 neutron 相关的服务。
# systemctl restart neutron-openvswitch-agent neutron-l3-agent neutron-dhcp-agent
  1. 查看 ovs 网桥接口信息发现,tap 设备已经出现。
  2. 查看物理机网卡信息,发现 tap 设备并没有出现。
  3. 重启该节点所有虚拟机以后,虚拟机的 tap 设备出现。
  4. 查看系统负载,发现负载恢复到正常水平。

../../_images/3-3-cup.png

  1. 跟踪一个虚拟机进程,发现不再有文件描述符读取错误信息。

../../_images/3-4-strace-info.png

  1. 检查节点虚拟机联网情况,全部正常。

问题原因

部署时, neutron-ovs-cleanup 服务设置了开机自启动,在计算节点重启以后 neutron-ovs-cleanup 服务自动启动,清理了所有的tap设备,另外 neutron-ovs-cleanup 服务 stop 的时候也会清理掉所有的 tap 设备。

问题4:Dashboard 报错 “Error: Unable to retrieve the project.”

问题现象

使用 admin 登陆 Dashboard,进入页面 http://10.0.192.18/dashboard/admin/images 后,页面报错,信息为:Error: Unable to retrieve the project。

处理过程

  1. 首先检查浏览器 API 返回日志。
"Could not find project: 8d8b91fb518b4013ab6d18eb48c1b3d9 (HTTP 404) (Request-ID: req-e393f927-081b-4ca9-9583-69db92781217)"
  1. 查看所有 Glance images 信息,发现有镜像属于这个项目。
  {
    "status": "active",
    "properties": {
        "instance_uuid": "93deca7a-eb74-48c8-a689-47a7693148c6",
        "image_location": "snapshot",
        "image_state": "available",
        "user_id": "c40bb40d36dd426bb43d92140dba252f",
        "image_type": "snapshot",
        "base_image_ref": "86fed267-c2d2-48c0-a55d-119ad80c8d0f",
        "owner_id": "8d8b91fb518b4013ab6d18eb48c1b3d9"
    },
    "name": "os initial",
    "checksum": "5d3552298cf399e74d22fd2f569331fb",
    "created_at": "2017-03-24T02:12:58Z",
    "disk_format": "raw",
    "updated_at": "2017-03-24T02:44:51Z",
    "visibility": "private",
    "id": "19400cc8-983f-41d2-aec2-58a3f850355a",
    "min_disk": 20,
    "protected": false,
    "architecture": null,
    "container_format": "bare",
    "owner": "8d8b91fb518b4013ab6d18eb48c1b3d9",
    "is_public": false,
    "min_ram": 0,
    "size": 21474836480
}
  1. 检查到该项目已经不存在。
# openstack project show 8d8b91fb518b4013ab6d18eb48c1b3d9
No project with a name or ID of '8d8b91fb518b4013ab6d18eb48c1b3d9' exists.
  1. 检查 keystone log,发现项目删除信息。
2017-04-16 15:30:52.092 1324122 INFO keystone.common.wsgi [req-d2cddac5-8c82-4c2b-b960-4d78b6c060f2 543c04a6caba4b83ad7872f131e0bcee e3d0911c422f4ac2a837bd1b6d7a0d23 - default default] DELETE http://10.0.194.101:10006/v3/projects/8d8b91fb518b4013ab6d18eb48c1b3d9
  1. 判定为删除了项目,但是项目中的资源保留下来,于是出现这个报错。而目前的 OpenStack 集群,如果删除项目,项目下面的资源不会被删除,所以会出现页面报错的情况。
  2. 可以创建一个新的项目,然后将新项目的 id 与旧项目的 id 进行替换。
# openstack project create testproj
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description |                                  |
| domain_id   | default                          |
| enabled     | True                             |
| id          | 69f978beab0e4574a0a1a115ceba66be |
| is_domain   | False                            |
| name        | testproj                         |
| parent_id   | default                          |
+-------------+----------------------------------+

替换项目 id

# update keystone.project set id = '8d8b91fb518b4013ab6d18eb48c1b3d9' where id = '69f978beab0e4574a0a1a115ceba66be';

关联用户与项目

# openstack role add --user c40bb40d36dd426bb43d92140dba252f --project 8d8b91fb518b4013ab6d18eb48c1b3d9 user
  1. 最后验证问题解决。

问题原因

项目已删除,但是所属于该项目的资源并没有提前释放掉。

问题5:计算节点因为内存超配并创建大内存的虚机,导致宿主机内存不足

问题现象

马驹桥 Bss10 省测试集群,zabbix 自动报警 10e129e170e14 主机空闲内存少于 20%。

处理过程

  1. 登录 10e129e170e14 这台机器,查看机器的内存使用情况,发现其中一个虚拟机的进程占用大部分物理内存。
  2. 在主机 10e129e170e14 上使用 balloon 技术,挤出部分内存。
# python auto_balloon.py

auto_balloon.py 具体内容如下:

import base64
import json
import re
import subprocess
import sys
import time

def shell(cmd):
    sp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = sp.communicate()
    return out, err

def guest_exec(dom, inside_cmd):
    qga_cmd = '{"execute":"guest-exec", "arguments":{"path":"sh", ' \
              '"arg": ["-c", \"%s\"],"capture-output":true}}' % inside_cmd
    cmd = 'virsh qemu-agent-command %s \'%s\'' % (dom, qga_cmd)
    out, err = shell(cmd)
    if err:
        raise Exception(err)
    data = json.loads(out)
    time.sleep(1)
    pid = data['return']['pid']
    qga_cmd = '{"execute":"guest-exec-status","arguments":{"pid":%s}}' % pid
    cmd = 'virsh qemu-agent-command %s \'%s\'' % (dom, qga_cmd)
    out, err = shell(cmd)
    if err:
        raise Exception(err)
    data = json.loads(out)
    out_data = data['return']['out-data']
    out_data = base64.b64decode(out_data)
    print(out_data)
    return out_data

def get_dom_inside_mem(dom):
    data = guest_exec(dom, 'free -m')
    for line in data.split('\n'):
        if line.startswith('Mem:'):
            mems = line.split()
            out =  [mems[1], mems[3], mems[-1]]
            return [int(i) for i in out]

def get_dom_mem_stat(dom):
    cmd = 'virsh dommemstat %s' % dom
    out, err = shell(cmd)
    if err:
        raise Exception(err)
    mem_stat = {}
    for line in out.splitlines():
        if len(line) == 0:
            continue
        k, v = line.split()
        mem_stat[k] = int(v)
    return mem_stat

def _get_current_balloon(dom):
    cmd = "virsh qemu-monitor-command %s --hmp --cmd info balloon" % dom
    out, err = shell(cmd)
    if err:
        raise Exception(err)
    actual = re.findall("balloon: actual=(\d*)", out)[0]
    return int(actual)

def _set_balloon(dom, value):
    cmd = "virsh qemu-monitor-command %s --hmp --cmd balloon %s" % (dom, value)
    out, err = shell(cmd)
    if err:
        raise Exception(err)

def reset_dom_balloon(dom, actual, target, max_tries=60):
    print('===start reset %s actual:%s target:%s' % (dom, actual, target))
    _set_balloon(dom, target)
    for i in range(max_tries):
        time.sleep(3)
        value = _get_current_balloon(dom)
        if value <= target:
            break
        print('\t==%s current balloon:%s' % (dom, value))
    _set_balloon(dom, actual)
    print('===end reset %s actual:%s target:%s' % (dom, actual, target))

def balloon_dom(dom, threshold=0.2, drop=0, sleep=5):
    if 0 < drop <= 3:
        guest_exec(dom, 'cat %s > /proc/sys/vm/drop_caches' % drop)
        time.sleep(sleep)
    total, free, available = get_dom_inside_mem(dom)
    mem_stat = get_dom_mem_stat(dom)
    rss = mem_stat['rss'] / 1024.0
    rate = (rss - (total - free)) / total
    if rate > threshold:
        actual = _get_current_balloon(dom)
        target = int((total - free) * (1 + threshold))
        actual03 = int(actual * 0.3)
        target = target if target > actual03 else actual03
        if actual > target:
            reset_dom_balloon(dom, actual, target)

def get_all_dom():
    cmd = 'virsh list --state-running --uuid'
    out, err = shell(cmd)
    if err:
        raise Exception(err)
    return [i for i in out.splitlines() if len(i) > 0]

if __name__ == '__main__':
    domains = []
    if len(sys.argv) > 1:
        domains.extend(sys.argv[1:])
    else:
        domains.extend(get_all_dom())
    print(domains)
    [balloon_dom(i) for i in domains]
  1. 稍后观察 10e129e170e14 节点内存继续上升,遂决定将其上一台活跃度较低 vm 迁移到其他计算节点。
# openstack server migrate cb064d0d-082b-4a80-acf9-6782030461b7 --live 10e129e170e12 --block-migration --disk-overcommit

注解

上面需要迁移的虚拟机有使用本地盘做存储,所以迁移的时候需要添加 block-migration disk-overcommit 这两个参数,当虚拟机使用全是共享存储的时候,迁移的命令则是 openstack server migrate cb064d0d-082b-4a80-acf9-6782030461b7 –live 10e129e168e74。

  1. 查看迁移的虚拟机,发现在新的节点正常运行,而原来的节点内存使用也已经降低。

问题原因

虚机内存使用上升,导致宿主机内存紧张,当物理机内存超配,而在超配的机器上,开大内存虚拟机的时候,此现象尤为明显。

Previous