泛解析之伤

1.历史原因重要项目没有做指定解析

2.修改之前检查有疏漏

高并发服务器重启iptables要小心

最近有台服务器因iptables规则需要调整,但重启过后网络立马就不通了。不通之后查看了/var/log/messages发现有如下报错 :cry:

 

Jun 10 10:18:57 dl1JZV33X kernel: ip_tables: (C) 2000-2006 Netfilter Core Team
Jun 10 10:18:57 dl1JZV33X kernel: nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:11 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:16 dl1JZV33X kernel: __ratelimit: 8330 callbacks suppressed
Jun 10 10:19:16 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:16 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:16 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:16 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:16 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:16 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.
Jun 10 10:19:16 dl1JZV33X kernel: nf_conntrack: table full, dropping packet.

原来iptables跟踪记录表满了,

我们看到第一行,重启iptables之后nf_conntrack值变成65535了,查看了系统sysctl 参数这两个值并不是65535, 上网搜索发现很多遇到这个问题,这可能是个bug
临时解决方法:

1.尽量不要重启iptables

2.重启iptables,重启之后执行

sysctl -w "net.netfilter.nf_conntrack_max=655350"
sysctl -w "net.netfilter.nf_conntrack_tcp_timeout_established=600"

重新手动指定跟踪表最大值

3.最重要的是防火墙要和LB分开,业务真的不能都混在一起,太容易出问题了。。。
参考文档:

http://hi.baidu.com/higkoo/item/1014ff9eab79fa1d924f41ef

 

tcp_rw_recycle引起数据包丢弃

最近发现LB服务器tw非常高,8W+TCP连接有6W左右都是TIME_WAIT状态,我们知道单个IP使用端口最多是(65535-1024)个,所以想打开tcp_tw_recycle把TIME_WAIT状态快速回收,一个不起眼的参数却引起了系统故障。

问题现象:

南京IDC连北京接口有的机器是有时通,有时不通,无法telnet端口,另一条专线线路正常。

问题分析

分析从南京IDC到北京IDC间有两种途径:从防火墙NAT出去和专线。分析出问题线路一段一段分析,每段进行抓包分析,最后在服务器发现只有从防火墙过来TCP三次握手第一个数据包SYN,后续的包均被丢弃。如下图:

抓包图

 

查看tcp_recycle代码:

#define TCP_PAWS_MSL     60              /* Per-host timestamps are invalidated
                                         * after this time. It should be equal
                                         * (or greater than) TCP_TIMEWAIT_LEN
                                         * to provide reliability equal to one
                                         * provided by timewait state.
                                         */
#define TCP_PAWS_WINDOW 1               /* Replay window for per-host
                                         * timestamps. It must be less than
                                         * minimal timewait lifetime.
                /* VJ's idea. We save last timestamp seen
                 * from the destination in peer table, when entering
                 * state TIME-WAIT, and check against it before
                 * accepting new connection request.
                 *
                 * If "isn" is not zero, this request hit alive
                 * timewait bucket, so that all the necessary checks
                 * are made in the function processing timewait state.
                 */
                if (tmp_opt.saw_tstamp &&
                    tcp_death_row.sysctl_tw_recycle &&
                    (dst = inet_csk_route_req(sk, &fl4, req)) != NULL &&
                    fl4.daddr == saddr &&
                    (peer = rt_get_peer((struct rtable *)dst, fl4.daddr)) != NULL) {
                        inet_peer_refcheck(peer);
                        if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
                            (s32)(peer->tcp_ts - req->ts_recent) >
                                                        TCP_PAWS_WINDOW) {
                                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
                                goto drop_and_release;
                        }
                }

发现有7种情况会引起丢包:

1 tcp的option有 time stamp字段.
2 tcp_tw_recycle有设置。
3 在路由表中是否存在完全相同的流(如果打开了xfrm的话,还要比较端口,默认xfrm应该是打开的),如果存在则直接返回.
4 并且数据包的源地址和新请求的源地址相同.
5 根据路由表以及源地址能够查找到保存的peer(这个可以看我以前的blog,也就是保存了一些连接统计信息).
6 当前时间(接收到syn)比最后一次的时间(time stamp)小于60秒.
7 已经存在peer的最近一次时间戳要大于当前请求进来的时间戳.

结合我们情况分析,我们因服务器timewait过多对tcp_tw_recycle进行调整过。所以,如果客户端是NAT出来的,并且我们server端有打开tcp_tw_recycle ,并且time stamp也没有关闭,那么假设第一个连接进来,然后关闭,此时这个句柄处于time wait状态,然后很快(小于60秒)又一个客户端(相同的源地址)发一个syn包,此时linux内核就会认为这个数据包异常的,因此就会丢掉这个包。

找到问题就容易解决了。

问题解决

我们直接把lb上面的tcp_timestamps(默认打开)关了,这样问题也就解决了。值得注意的是,当tcp_timestamp关闭后,tcp_tw_reuse和tcp_tw_recycle均不起作用了。查阅相关文档后,我尝试把tcp_timestamps打开,并关闭tcp_tw_recycle和tcp_tw_reuse,但打开一会用netstat -s |grep timestamp就发现因timestamp拒绝掉的包有所上升,原因未知,所以目前解决方法还是把tcp_timestamp给关闭的。

这次参数调整没有仔细阅读相关说明,另外发现几乎所以中文文档针对time_wait过多情况都是调整tcp_tw_recycle和tcp_tw_reuse参数。但是,我后来查阅了一下国外大多数文档,都明确说明tcp_tw_recyle打开要慎重。英文原文是:It should not be changed without advice/request of technical experts.  有时候调优文档也真够坑爹的。另外这个问题在LVS的NAT环境也有同样的问题。

关于如何处理tcp_tw_wait过多情况,我会另开一篇说明。

 

 

参考文档:

http://ju.outofmemory.cn/entry/96

http://blog.sina.com.cn/s/blog_781b0c850100znjd.html

http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html

修改rvm源到国内

当你安装完 RVM 的时候,可以尝试一下这个执行这行:

sed -i ‘s!ftp.ruby-lang.org/pub/ruby!ruby.taobao.org/mirrors/ruby!’ $rvm_path/config/db

这样会将 RVM 的 ruby 源代码下载连接改到 ruby.taobao.org 上面,使得安装过程更快。

用cloud-init制作的镜像root无法登陆问题

自己在做CentOS6.4镜像时,cloud-init安装版本为 0.7.2 ,一切安装配置好后,glance上传完成后使用该镜像创建虚机,绑定floating ip后,用xshell登陆该虚机就出现了问题,就是root用户名输入回车后发现只能用public key公钥登陆,而不能用密码认证登陆。

进vnc控制台发现在/etc/ssh/sshd_config发现“PasswordAuthentication no” ,怪不得登陆不了。难道是做的镜像里面ssh默认都是“PasswordAuthentication no”禁止密码认证的???

回想之前做了那么多镜像也没有要修改ssh配置的。算了,还是重新修改一下镜像吧,我修改为 “PasswordAuthentication yes”然后上传到OpenStack中,创建虚机,噢,发现root还是没法用密码认证登陆,再次查看/etc/ssh/sshd_config,竟然发现“PasswordAuthentication no” !!! 奇怪了,发现我原来修改的“PasswordAuthentication yes”也不见了,而是它自己增加了一行“PasswordAuthentication no”,纠结中。。。

这时猛然想起跟有可能是cloud-init搞的鬼,在安装好cloud-init后,会生成/etc/cloud/cloud.cfg配置文件,找到该文件,就在配置文件置顶的前五行内,就赫然显示其配置限制了登陆方式:

users:
– defaults
disable_root:1
ssh_pwauth: 0

cloud-init默认配置是这样滴,ssh_pwauth 为 0 是关闭状态,就是禁止password认证。终于找到原因了,继续改镜像吧,修改为 ssh_pwauth: 1 ,重新创建虚机绑定floating ip,ssh远程登陆,root可以用密码正常登陆。 找到sshd_config配置文件,发现里面多了“PasswordAuthentication yes”,看来的确是cloud-init搞的鬼。 回想一下上次测试,莫名其妙加了“PasswordAuthentication no”也是由于cloud-init没有开启password认证搞的鬼。

不过还有一个问题,在cloud.cfg配置中,disable_root:1 这一项猜测应该是限制禁止root用户ssh远程登陆的,按理应该会在sshd_config配置文件中加上 “PermitRootLogin no”,但是在sshd_config里也没有发现这一项,而且我刚才是可以使用root远程登陆。这一点有点奇怪,难道是这个配置没有生效?

于是我手动改为 disable_root:0 尝试一下,结果依然root可以ssh远程登陆,sshd_config配置中依然是“PermitRootLogin yes” 。

这个问题有点奇怪,也可能是我把这个配置理解错了。

也有可能是cloud-init心情不好,为了做镜像保险起见,还是修改为下面这样配置吧,哪天等它心情好了还能继续让我用root登陆!!

users:
– defaults
disable_root:0
ssh_pwauth: 1

目前这个禁止root用户登陆的问题暂时不影响虚机的正常登陆,如果哪位朋友遇到过或者知道是什么原因,希望可以交流学习一下。

对了,如果不是自己做镜像,是从官方网站直接下载的,默认镜像里应该安装了cloud-init,我测试过一个官方镜像,cloud-init默认也是禁止密码登陆的,知道了是cloud-init配置的原因,就可以下载镜像后手动修改一下cloud.cfg配置,然后再自己使用。

还有如果不知道官方镜像root密码,可以按照之前介绍的使用Config Drive注入metadata修改root密码。

修改root密码:
#cloud-config
chpasswd:
list: |
root:123456
expire: False
ssh_pwauth: True

Windows下使用xmanager远程访问管理 linux

安装所有图形化桌面包,然后配置:

# GDM configuration storage

[daemon]

[security]
DisallowTCP=false
AllowRoot=true
AllowRemoteRoot=true
[xdmcp]
Enable=1
Port=177
[greeter]

[chooser]

[debug]

gdm-restart 重启服务

netstat -an | grep 177 查看177端口状态,确保服务正常开启,至此X-MANAGER连接配置成功

openstack中vm的DNS问题

openstack中的vm实例使用的resolv.conf配置不知道为什么会指向dhcp的虚拟网关地址,这样导致一些内部域名解析不了,查看了openstack文档需要在/etc/nova/nova.conf文件在添加:

dns_server=172.20.1.250

killall dnsmasq

/etc/init.d/openstack-nova-network restart

这样就可以 了。

启动后进程多 了个地址:

dns_server

 

 

 

参考地址:http://docs.openstack.org/grizzly/openstack-compute/admin/content/dnsmasq.html

 

openstack镜像快速制作

以前用KVM手动一步步安装虚拟机然后做镜像,现在想想真是弱爆了,现在有更神器了。OZ介绍我就不多写了,我是参照沙克的文档做的

http://www.chenshake.com/oz-making-centos-mirror/

但这里有个地方要注意,从网上复制下来的ks文件里面有windows下回车符,里面脚本怎么都执行不成功 ,用dos2unix转换一下就OK了

你只需yum -y install oz (要EPEL源)

然后你只需要配置2个文件,一个模板文件,一个ks文件。另外,你也可以根据你的需要设置一下你oz的配置文件 ,如下:

 

 cat /etc/oz/oz.cfg 
[paths]
output_dir = /var/lib/libvirt/images
data_dir = /var/lib/oz
screenshot_dir = /var/lib/oz/screenshots
# sshprivkey = /etc/oz/id_rsa-icicle-gen

[libvirt]
uri = qemu:///system
#镜像格式
image_type = qcow2
# type = kvm,这边要设置你的网桥
bridge_name = br0
# cpus = 1
# memory = 1024

[cache]
original_media = yes
modified_media = no
jeos = no

[icicle]
safe_generation = no

模板文件如下:

<template>
   <name>centos_63_x86_64</name>
   <description>CentOS 6.3 x86_64 template</description>
   <os>
      <name>CentOS-6</name>
      <version>3</version>
      <arch>x86_64</arch>
      <install type='url'>
         <url>http://10.10.10.100/cobbler/ks_mirror/CentOS6.3-x86_64/</url>
      </install>
   </os>
  <disk>
    <size>10</size>
  </disk>
</template>

ks文件如下:

#version=DEVEL
# Firewall configuration
firewall --enabled --service=ssh

repo --name="repo0" --baseurl=http://mirrors.kernel.org/centos/6/os/x86_64
repo --name="repo1" --baseurl=http://mirrors.kernel.org/centos/6/updates/x86_64
repo --name="repo2" --baseurl=http://mirrors.kernel.org/fedora-epel/6/x86_64
repo --name="repo3" --baseurl=http://repos.fedorapeople.org/repos/openstack/cloud-init/epel-6
# Root password
rootpw --iscrypted --iscrypted $1$tuniu$bbKnWN9KQ7Kb31rdBvDfo.

# System authorization information
auth --useshadow --enablemd5
# System keyboard
keyboard us
# System language
lang en_US.UTF-8
# SELinux configuration
selinux --disabled
# Installation logging level
logging --level=info
# Reboot after installation
reboot
# System services
services --disabled="avahi-daemon,iscsi,iscsid,firstboot,kdump" --enabled="network,sshd,rsyslog,tuned"
# System timezone
timezone --isUtc Asia/Shanghai
# Network information
network  --bootproto=dhcp --device=eth0 --onboot=on
# System bootloader configuration
bootloader --append="console=ttyS0,115200n8 console=tty0" --location=mbr --driveorder="sda" --timeout=1
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all  
# Disk partitioning information
#part / --fstype="ext4" --grow --size=1
part /boot --fstype ext4 --size=200
part swap --size=1024
part / --fstype ext4 --size=4198 --grow

%post
# make sure firstboot doesn't start
echo "RUN_FIRSTBOOT=NO" > /etc/sysconfig/firstboot

cat <<EOL >> /etc/rc.local
if [ ! -d /root/.ssh ] ; then
    mkdir -p /root/.ssh
    chmod 0700 /root/.ssh
    restorecon /root/.ssh
fi
EOL

cat <<EOL >> /etc/ssh/sshd_config
UseDNS no
PermitRootLogin without-password
EOL

# bz705572
ln -s /boot/grub/grub.conf /etc/grub.conf

# bz688608
sed -i 's|\(^PasswordAuthentication \)yes|\1no|' /etc/ssh/sshd_config

# allow sudo powers to cloud-user
echo -e 'cloud-user\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers

# bz983611
echo "NOZEROCONF=yes" >> /etc/sysconfig/network

# set virtual-guest as default profile for tuned
echo "virtual-guest" > /etc/tune-profiles/active-profile

#bz 1011013
# set eth0 to recover from dhcp errors
cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
DEVICE="eth0"
BOOTPROTO="dhcp"
ONBOOT="yes"
TYPE="Ethernet"
USERCTL="yes"
PEERDNS="yes"
IPV6INIT="no"
PERSISTENT_DHCLIENT="1"
EOF

#bz912801
# prevent udev rules from remapping nics
touch /etc/udev/rules.d/75-persistent-net-generator.rules

#setup getty on ttyS0
echo "ttyS0" >> /etc/securetty
cat <<EOF > /etc/init/ttyS0.conf
start on stopped rc RUNLEVEL=[2345]
stop on starting runlevel [016]
respawn
instance /dev/ttyS0
exec /sbin/agetty /dev/ttyS0 115200 vt100-nav
EOF

# lock root password
#passwd -d root
#passwd -l root

# let's randomise the root password
#head -n1 /dev/urandom | md5sum| awk {'print $1'} | passwd --stdin root

# clean up installation logs"
yum clean all
rm -rf /var/log/yum.log
rm -rf /var/lib/yum/*
rm -rf /root/install.log
rm -rf /root/install.log.syslog
rm -rf /root/anaconda-ks.cfg
rm -rf /var/log/anaconda*
%end

%packages --nobase --excludedocs
wget
vim
cloud-init
cloud-utils

%end

两个文件下载

file

Feed