Category: Linux

  • Very High snmpd CPU Usage and 1000s of IP Addresses

    Clipper_fistFor a while now we have been experiencing SNMP timeouts from our central monitoring server to a set of new and recently deployed servers. We at first attributed the issue to the network driver being a bit different than what we have used in the past (latest greatest hardware) and then to the fact that we are completely gutting our production network in situ. Normalization of the driver across this application farm made no difference and the issue began to get worse, spreading to just about all servers in this one specific service tier. As it was not impacting any other servers it wasn’t surprising that we could not find an issue at the network layer so we had to keep digging.

    In our environment this tier is unique for two reasons:

    1. Very high IO per server. On the order of 10,000 write ops to disk per second at peak load.
    2. Thousands of private IPs per system (added as ip rules – not virtual addresses on interface devices).

    The first issue was in fact an issue, just not for SNMP.

    The snmpd process was getting lost in the noise generated by the high system load the disk IO was causing (lots or concurrent processes in this app). The team quickly addressed this issue and scaled the IO subsystem substantially to meet the growing workload. After this change the system load dropped from over 1000 to under 10 (1 minute average) during peak utilization on these servers.

    Unfortunately snmpd was still timing out. However, now with the noise of all those blocked processes out of the way, running a top showed the snmpd process stuck at 100 percent cpu usage for very long period of times. In fact, periods of less than 100 percent cpu were noted for their rarity.

    That led us to difference number two. Recently we had been normalizing our system configurations which resulted in the whole tier of afflicted servers having even more IPs assigned. Ok great the team thought – we know where that lives in net-snmp – the IP-MIB. Our assumption was that net-snmp should only refresh this MIB based on client requests and for some reason our monitoring solution was requesting all the IPs from the IP-MIB portion. That would certainly explain the timeouts we thought. Step one was try the latest net-snmp just in case it was bug on our old default 5.4 install. No change. So the team’s next step to trouble shooting this was to essentially block access to the ip-mibIP-MIB part of the OID tree.

    We tried various versions of:

    view systemview excluded ip.ipAddressIfIndex.ipv4

    view systemview excluded ip.ipAddressType.ipv4

    view systemview excluded .1.3.6.1.2.1.4.20.1

    and so on to no effect. Next we did the obvious test – block all client access. No change – snmpd was still consuming 100% of a cpu all the time. Now what?

    Unfortunately we were not on Solaris so no DTrace. However, strace did provide the clues needed to make progress. The strace of the snmpd process was almost entirely ioctl calls to the interface devices to fetch the IP addresses associated with them. These calls themselves were not so much the issue as the response time of the ioctl calls were in microseconds. A continuous snmpget was executed against a system while the strace was generated and the strace output compared to client experience. Client time outs lined up exactly with when the ioctl “storm” would start. As the system time consumed was tiny by snmpd during this, the issue had to be in the user-land component of net-snmp.

    One thing the strace showed was snmpd was almost alway determining all the IPs on each interface in what looked like a very tight loop. There was perhaps two to three seconds between each storm. In addition, each subsequent ioctl call involved more and more IPs per call – almost displaying an O(n^2) behavior as the list of IPs in the previous call were then being listed again with only the addition of another IP. So now we knew snmpd was, for some reason, always rebuilding the .1.3.6.1.2.1.4 tree and doing it a nasty way.

    The first thing that jumped to mind was somewhere the caching we assumed Net-SNMP would do on the ip table was misconfigured. We attacked the nsCacheTable and its ilk from all directions. No luck and no change in behavior. At this point a more thorough web search found two similar postings describing high snmpd cpu usage. One for system with a very large BGP routing table and another for a system with thousands of VLANs. Neither indicated a solution though the BGP postings indicated that sorting within snmpd was not very efficient. At this point your author started to change some of the cache constants within the net-snmp source code to see if the polling cycle on the interfaces would change. It did not.

    Time to turn on debug :
    The snmpd daemon that comes with Net-SNMP has a pretty thorough debug mode. So thorough in fact we went to that step last as in our environment the full debug mode generates about 75MB of log data every five seconds (remember all those ip addresses). We had tried various documented methods to only have it run debug on certain sub-modules like the IP-MIB, but we could not find an actual working command line option. The documented examples on the net-snmp wiki pages did not work at all on our build for some reason. So we were forced to deal with the fire hose of logging everything.

    With full debug on (-DALL) snmpd was started. Five seconds or so was all that was needed to generate a trace that would help us track down the issue. The net-snmpd agent code is full of logging code like below:

    DEBUGMSGTL(("access:ipaddress:container", "processing %d interfaces\n", interfaces));

    which will generate a message like:

    trace: _netsnmp_ioctl_ipaddress_container_load_v4(): ip-mib/data_access/ipaddress_ioctl.c, 171:
    access:ipaddress:container: processing 4 interfaces

    This makes it very easy to find where in the code the message was generated and simplifies tracing the application (relatively – there are 100s of modules). So at this point we did the tedious task of simply walking the log file in parallel with walking the code, focusing obviously on the interface and IP portions. Along the way numerous little hooks and debug messages were dropped into the code and snmpd recompiled. This helped us along the way to at least realizing the real problem was much larger than what we wanted to tackle. Essentially, the table access and cache components just will not work when one has 1000s of IP addresses. Best we could tell, snmpd is resorting the IP oid tree after each and every IP address it comes across. If you follow the snippets of debug out put below you will see how it does a table compare after each and every IP on a small test system. On our production box with over 7000 IPs snmpd is spending all its time doing index compares. The full debug snippet is available if anyone wants it.

    Realizing there was no way for us to quickly and safely modify either the cache code which honestly, we couldn’t figure out why the IP table was called as often as it was. Even interface stats (.1.2.1.3.6.1.2.1.2.2) were being refreshed at a much higher refresh rate than nsCacheTable would imply] or the table and index code we decided to cut the monster off at the head – the call into the “access:ipaddress:container” portion of the code. Through a bit of debugging your author determined the head of the monster was the _netsnmp_ioctl_ipaddress_container_load_v4 function in the ip-mib/ipAddressTable/ipAddressTable_interface.c source file. This function seemed to lead to the discovery of all the IP addresses associated with an interface and hence all the sorting, indexing, and other madness we were experiencing.

    Solution
    The solution is neither pretty nor elegant and is a bit of the nuclear fly-swatter type. The function identified above loops over all the physical interfaces with IP addresses assigned. In our case that is the loopback and a set of bonded interfaces on various VLANs. Lucky for us, the 1000s of IPs we have on each server are on a set of dedicated bonds on their own VLANs. These are completely separate from the base server VLAN and other “user experienced” addresses. In addition, there is nothing related to these addresses in SNMP that we have ever used or need to use via snmp. As we determined, our monitoring software didn’t even know these IPs existed nor really ever hit anything in the IP-MIB table. All it ever knew or cared about was the base IP assigned to each bonded interface.

    So in our case, the obvious solution was to just not even process these bonded interfaces to determine what IP addresses were on them. We found some references in the code to essentially leverage ablack list but we could not figure out how to use it. As such we did the next best thing – modified the code of the loop in the _netsnmp_ioctl_ipaddress_container_load_v4 to just skip a set of known bonds – essentially do something like:

    [code language=”css”]

    if (strcmp(ifrp->ifr_name,”bond1.16″) == 0) { DEBUGMSGTL((“access:ipaddress:skipping”, ” interface %d, %s\n”, i, ifrp->ifr_name)); continue; }
    [/code]

    The full diff is below. Note the code was written so it would be easy to generate a patch based on our automation tools (i.e. if new bonds come and go) and to be obvious to folks without much C experience to know what to change. Not super efficient but good enough. After making this change snmpd CPU usage went from a continuous 100 percent to under 0.5 percent. Better yet – no more timeouts! All we lost was access to the portion go the IP table for the excluded interfaces. Something we didn’t use anyways.

    We still don’t know why snmpd was determined to rebuild the ip-mib continuously. As our use case is probably pretty rare it is not surprising there are so few reports of this behavior.

    [code language=”css”]

    — ipaddress_ioctl.c.new +++ ipaddress_ioctl.c.orig @@ -165,11 +165,6 @@ DEBUGMSGTL((“access:ipaddress:container”, ” interface %d, %s\n”, i, ifrp->ifr_name)); – /* Ops was here */ – – DEBUGMSGTL((“access:ipaddress:containerSPNew”, – ” interface %d, %s\n”, i, ifrp->ifr_name)); – if (AF_INET != ifrp->ifr_addr.sa_family) { DEBUGMSGTL((“access:ipaddress:container”, ” skipping %s; non AF_INET family %d\n”, @@ -177,36 +172,6 @@ continue; } – /* Working around issue with 6000 IPs on a host – * So we exclude known problem interfaces – */ – – if (strcmp(ifrp->ifr_name,”bond1.16″) == 0) { – DEBUGMSGTL((“a ccess:ipaddress:skipping”, – ” interface %d, %s\n”, i, ifrp->ifr_name)); – continue; – } – – if (strcmp(ifrp->ifr_name,”bond1.20″) == 0) { – DEBUGMSGTL((“access:ipaddress:skipping”, – ” interface %d, %s\n”, i, ifrp->ifr_name)); – continue; – } – – if (strcmp(ifrp->ifr_name,”bond1.24″) == 0) { – DEBUGMSGTL((“access:ipaddress:skipping”, – ” interface %d, %s\n”, i, ifrp->ifr_name)); – continue; – } – – if (strcmp(ifrp->ifr_name,”bond1.28″) == 0) { – DEBUGMSGTL((“access:ipaddress:skipping”, – ” interface %d, %s\n”, i, ifrp->ifr_name)); – continue; – } – – /* End Ops Hack */ – /* */ entry = netsnmp_access_ipaddress_entry_create();

    [/code]

  • Poor Man’s eSATA Drive Hot Swap without AHCI or Hotplug Support Under Linux

     

     

    ServerRoomFireWeb

    Unfortunately, hot-swapping an eSATA drive is a bit more complicated than hot swapping a USB drive.

    First off,  your BIOS needs to support AHCI (click here for more info on AHCI), and your SATA controller also needs to support it as well. Secondly your OS, needs to specifically support hot plug, and in the case of Windows 7, it wont boot if you change to AHCI after the OS has been installed.

    So, In my case I need to update firmware on lots of SATA SSDs and want to do so without rebooting, and without worrying about changing bios settings. So in order to keep things simple, I followed the procedure below.

    First, you need to detect your drive. So watch dmesg to see what drive letter is assigned to your new disk upon initial connection.

    #dmesg

    [86527.985994]  sdd: unknown partition table
    [86528.012820] sd 8:0:0:0: [sdd] Assuming drive cache: write through
    [86528.012823] sd 8:0:0:0: [sdd] Attached SCSI disk
    [86528.456281] device label btrfs devid 1 transid 11 /dev/sdd

    Then, when its time to remove the disk device to the following. Subsitute your disk device letters.

    # echo 1 > /sys/block/sdd/device/delete

    Now you are free to swap your disk. No reboot, no bios changes, required.

  • X11 No Worky – Worky

    Christmas Ape from Space

     

     

     

     

     

     

    Yikes, was banging my head against a wall trying to get X11 forwarding working on my RHEL 6.1 box. Every time I ssh’d in and attempted to pop an X window back to my fedora desktop, I was greeted with the error message below.

    # Error: no display specified

    Ok, I thought to myself — X11 forwarding is not enabled in sshd — let’s go fix it. However, when I checked /etc/ssh/sshd_config, I found that X11 forwarding was enabled. See the config item below, these needs to exist, and not set to no.

    X11Forwarding yes

    Ok so let’s check what the display variable is set to. So I ran the command below, which returned absolutely nothing, which meant that it’s not set to anything at all.

    # echo $DISPLAY

    So I check my local box and check to make sure that forwarding is enabled. Which it is

    #grep X11 /etc/ssh/ssh_config
    ForwardX11 yes

    After I bit of research on google – I found a bugzilla that suggested I make sure that the following rpm was installed – xorg-x11-xauth.x86_64.  It wasn’t..

    yum install xorg-x11-xauth.x86_64

    Then logout and back in again. You will be now be greeted by the line below.

    /usr/bin/xauth:  creating new authority file /root/.Xauthority

    Now check your display variable.

    # echo $DISPLAY
    localhost:10.0

    Ah, much better.

     

     

     

  • RHEL6 – Simple Iptables How To

    Firewall supportYour mother and I were talking last night about how important it is to properly configure Iptables, and how despite that fact, many just choose to disable it. So today we are going to discuss iptables.

    Overview:

    By far the easiest way to setup a simple firewall using Iptables is to use system-config-firewall, or system-config-firewall-tui. I prefer this method as iptables can be a bit confusing on the command line and in its config file (/etc/sysconfig/iptables) is not exactly user friendly. At the very least you can create a basic set of rules and then customize by hand. Lets take a look at the file in its default form on my RHEL 6 box.

    But before we do that, lets review a couple of terms that we need to know.

    1. INPUT – are inbound packets
    2. OUTPUT are outbound packets
    3. FORWARD – packets from another machine that the firewall should forward (like to a vm on the host).
    4. ACCEPT – the packet is accepted
    5. DROP – the packet is dropped as if it never existed
    6. REJECT – the packed is rejected and and error message is returned to sender
    7. RULE – the basic building block — tells the firewall what to do with a packet
    8. CHAIN – a list of all rules which will be checked in order from first to last
    9. POLICY – the default action, like accept, drip, reject, forward

    Now that you have memorized the list above, here is my /etc/sysconfig/iptables.

    # Firewall configuration written by system-config-firewall
    # Manual customization of this file is not recommended.
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT
    -A INPUT -j REJECT –reject-with icmp-host-prohibited
    -A FORWARD -j REJECT –reject-with icmp-host-prohibited.

    Now lets run system-config-firewall tui and enable apache and ftp, plus we want to configure our box to respond to ICMP ping requests. This process is pretty self explanitory once you start.

    Once that is done lets view /etc/sysconfig/iptables again.

    # Firewall configuration written by system-config-firewall
    # Manual customization of this file is not recommended.
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -p icmp -m icmp –icmp-type echo-request -j REJECT –reject-with icmp-host-prohibited
    -A INPUT -p icmp -m icmp –icmp-type echo-reply -j REJECT –reject-with icmp-host-prohibited
    -A INPUT -p icmp -m icmp –icmp-type destination-unreachable -j REJECT –reject-with icmp-host-prohibited
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT
    -A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT
    -A INPUT -m state –state NEW -m tcp -p tcp –dport 21 -j ACCEPT
    -A INPUT -m state –state NEW -m tcp -p tcp –dport 443 -j ACCEPT
    -A INPUT -j REJECT –reject-with icmp-host-prohibited
    -A FORWARD -j REJECT –reject-with icmp-host-prohibited
    COMMIT

    Iptables Command:

    The iptables command can be used in several different ways.

    List the current rules in use, similar to viewing the /etc/sysconfig/iptables file

    #iptables -L

    To set a default policy use iptables -P, in the example below we are setting the default INPUT policy to DROP.

    #iptables -P INPUT DROP

    Now lets say we want to delete all our existing rules, note that i did not say policy

    #iptables -F

    To add a rule use iptables -a, for example lets say you have a default policy of INPUT DROP but we want to accept all established and related packets. Note that -m must be used when adding rules to a chain as it forces modprobe to load any necessary modules.

    #iptables -A INPUT -m state –state ESTABLISHED, RELATED

    Now lets say that we want to reject all packets from 192.168.10.10. Note -j specifies the action that the rule is to take — in the case below, REJECT

    #iptables -A INPUT -s 192.168.10.10 -j REJECT

    Now lets say we want to ACCEPT all ICMP traffic from our local subnet. The -p is protocol

    #iptables -A INPUT -p ICMP -s 192.168.1.0/24 -j ACCEPT

    Please note that under RHEL you can use following commands to save firewall rules.Make sure that you do this before you restart iptables.

    #service iptables save

  • RHEL6 – Snapshotting an LVM Volume

    Oh-snapSnapshotting in the context of LVM is the process of taking a point-in-time image of a filesystem and creating a separate copy of that filesystem on another filesystem… using LVM of course.

    Snapshoting can be useful if you need to take a backup of a filesystem but want the filesystem to be a quiesced state when you do so. Using LVM and snapshots you just backup the snapshot of the original filesystem.

    First lets create the “master” filesystem using /dev/sdc1 which has partitioned as Linux LVM in fdisk.

    So create the physical volume

    >pvcreate /dev/sdc1

    Then create a volume group containing the physical volume

    >vgcreate test_vg /dev/sdc1

    Then create a logical volume called v1 which is 5gb in size. Note that this volume group is 10gb in total size.

    >lvcreate -n v1 -L 5G test_vg

    Then create a filesystem on that volume

    >mkfs -t ext4 /dev/test_vg/v1

    Then mount this volume to /v1 and put some data in it.

    >mkdir /v1

    >mount /dev/test_vg/v1 /v1

    >cp /var/tmp/VMwareTools-8.3.2-257589.tar /v1

    Ok, now that we have a logical volume with some data in it, lets make a snapshot of it.

    First lets make a mountpoint for our snapshot

    >mkdir /v2

    Now lets make the snapshot of /dev/test_vg/v1. Note that a snapshot volume can be as large or a small as you like but it must be large enough to hold all the changes that occur on the original volume during the lifetime of the snapshot. In this example I am creating a snapshot of 4gb.

    >lvcreate -n snapvol -L 4G -s /dev/test_vg/v1

    Using lvs or lvscan you can take a look at the snapshot volume.

    >lvscan

      ACTIVE   Original ‘/dev/test_vg/v1’ [5.00 GiB] inherit
      ACTIVE   Snapshot ‘/dev/test_vg/snapvol’ [4.00 GiB] inherit

    Now lets mount the snapshot readonly.

    >mount -o ro /dev/test_vg/snapvol /v2

    Now you can browse the contents of the snapshot, unmount it and mount it as needed. And back it up as well. Make sure that you remove the snapshot when done backing it up

    >lvremove /dev/test_vg/snapvol

  • RHEL6 – Accessing ISCSI Disks with Iscsiadm

    Pdp-8ISCSI is scsi (Small Computer System Interface) over IP. Where SCSI is the protocol and IP is the transport mechanism. This is going to be a quick and dirty overview of how to login to and mount an iscsi disk. This will not be an overview of how to share out a disk via iscsi. I may get around to writing that post, but it will not be today.

    Before we get started we need to understand a few simple terms.

    • ISCSI Initiator – the client that needs access to the ISCSI disk.
    • ISCSI Target – the remote disk.
    • ISCSI Target Portal – the server that is providing the Target to the Initiator
    • IQN – The “ISCSI Qualified Name” or more simply a unique name for the Initiator and the Target

    Now lets get down to business.

    First on the Target you must install the ISCSI utils.

    >yum -y install iscsi-initiator-utils.x86_64

    Then discover the any ISCSI targets provided by the Target Portal. In this case the IP address of my target portal will be 192.168.0.55.

    >iscsiadm -m discovery -t st -p 192.168.0.55.

    In the example above -m puts iscsiadm is discovery mode, -t st tells iscsiadm to look for a SCSI target, and -p is the target portal. The output of the above command will be the IQN of the target disk.

    For this example we will say that the IQN is

    iqn.2001-05.com.equallogic:6-8a0900-5e1812101-1cf000245514a8da-disk1

    Then log into the ISCSI target

    >iscsiadm -m node -T iqn.2001-05.com.equallogic:6-8a0900-5e1812101-1cf000245514a8da-disk1 -p 192.168.0.55 -l

    In the example above we are setting the mode to node, -T prefaces the ISCSI target, -p the portal, and -l means login.

    Now you need to identify which device is the iscsi target by looking at the output of dmesg or tail the messages file.

  • RHEL6 – Managing Swap Space

    54af9-6a00e551c39e1c8834017ee46a8c54970d-piSwap space on a Linux box is an area on disk that is used to hold inactive memory pages. This occurs when the system needs more memory then is currently available, so it swaps these inactive memory pages to disk.

    To create additional swap space on the fly you are either going to need a spare disk or free partition on a disk that you can use.

    First, using fdisk,  you will need to make sure that the partition type for the disk (or partition) is set to 82.

    Then setup the swap area using mkswap. In this example I am using /dev/sdb2, but your setup is bound to be different.

    >mkswap /dev/sdb2

    Then determine the UUID of the new swap space.

    >blkid /dev/sdb2

    Then add an entry to the /etc/fstab, so that the swap space is mounted at boottime. The show in the example below is the output of the blkid command above.

    >UUID=7b05f0a9-18d5-42e5-b259-78ba3a8cc1b7 swap                    swap    defaults        0 0

    Then activate your new swap space

    >swapon -a

    Then check to make sure everything worked by checkign for your new swap partition in the output of the command below.

    >swapon -s

    /dev/sdb2                             partition       4193276 7480    0