Category: Back To Basics

  • The Benchmark Trap: Why Your Storage Numbers Lie — and How to Get Honest Ones

    A vendor datasheet promises a million IOPS. You buy the array, point your workload at it, and it’s slow. The number wasn’t a lie — it was just irrelevant to you. That gap, between an impressive benchmark and a disappointing production system, is where a lot of infrastructure money quietly goes to die.

    I’ve spent a large part of my career with fio, vdbench, and HammerDB open in front of me. The tools are easy. Getting an honest number out of them is not. Here’s the field guide I wish more teams had before they trusted a benchmark — their own or a vendor’s.

    The number isn’t wrong. It’s answering a different question.

    Peak IOPS on a datasheet is a real measurement — of a workload that looks nothing like yours. Tiny block size, unlimited queue depth, a working set small enough to live entirely in cache, reads only, measured for ten seconds. Your production is a 70/30 read-write mix, 16K blocks, a working set far larger than cache, and it has to stay fast at 2 a.m. on day 400. Same tool, different universe. Before you argue about whose array is faster, make sure you’re both describing the same planet.

    The traps that inflate a benchmark

    Most misleading numbers come from a short list of mistakes:

    • The working set fits in cache. You benchmarked DRAM, not the media. Size the dataset several times larger than the controller cache or you’re measuring the wrong component.
    • No steady state. Flash gets slower once garbage collection kicks in. A 60-second run flatters an SSD that looks very different an hour later. Precondition the device, then measure.
    • Queue-depth theater. Cranking queue depth to 256 maximizes IOPS and obliterates latency. It produces a big number and an unusable response time.
    • Wrong block size or mix. The datasheet uses 4K reads; your database does 8K–16K with real writes. Model the actual mix or the result is fiction.
    • A single sample. One run is an anecdote. The variance across five runs is the actual story.

    An honest fio job to start from

    [global]
    ioengine=libaio
    direct=1
    runtime=600
    time_based=1
    ramp_time=60              # reach steady state before recording
    group_reporting=1
    
    [db-like]
    rw=randrw
    rwmixread=70              # 70/30 read-write, like an OLTP database
    bs=16k                    # your real block size, not 4k
    iodepth=32               # realistic, not a vanity QD of 256
    numjobs=4
    size=200g                # larger than the array's cache
    percentile_list=99:99.9  # report the tail, not just the average

    Every knob here is a decision about honesty. direct=1 bypasses the page cache so you measure storage, not memory. ramp_time throws away the artificially fast warm-up. size forces cache misses. percentile_list is the one most people skip — and it’s the one that matters most.

    Read the right metrics

    Peak IOPS is the vanity metric. What actually predicts whether production will be happy:

    • Latency at your target throughput — not throughput at unlimited latency. Those are different questions with very different answers.
    • Tail latency (p99, p99.9). Your users feel the worst 1% of requests, not the average. A great mean with an ugly tail is a bad system wearing a good costume.
    • Consistency over time. Does it hold at steady state, or degrade as the device fills and ages?

    One reframing kills most bad purchases: fix a latency budget — say, 1 ms at p99 — and ask “how many IOPS can it sustain at or under that?” Suddenly the million-IOPS array and the “slower” one often trade places.

    Why this is a leadership discipline, not a lab chore

    Benchmarking is how you replace opinion with evidence. In a room full of vendor claims and strong personalities, the person holding a reproducible number wins the decision — and deserves to. That’s also why a benchmark is a conviction with a review date: you state a performance expectation strongly enough to plan around it, and you re-run it when the firmware, the workload, or the scale changes. A claim without a benchmark is just an opinion. A benchmark you can’t reproduce is just a different opinion with a chart attached.

    The takeaway

    Don’t ask “how fast is it.” Ask “how fast is it, running my workload, at my latency budget, at steady state, averaged over five runs.” The tools will answer honestly if you ask honestly. Everything else is marketing with a monospaced font.

    The full fio job file is on GitHub: github.com/waghmaredb/vexpose-labs. If you benchmark enterprise storage or databases for a living, I’d like to compare methodologies — reach me on LinkedIn or X.

  • How to Benchmark Enterprise Storage: Fio and Vdbench Explained

    How to Benchmark Enterprise Storage: Fio and Vdbench Explained

    Enterprise storage arrays from vendors like Dell EMC, NetApp, and Pure Storage are the foundation of mission-critical IT environments. Ensuring these systems deliver consistent, high performance under real-world workloads is essential for application reliability and business continuity. In this post, we’ll explore how to benchmark enterprise storage using two industry-leading tools- Fio and Vdbench– with practical configuration examples and best practices.

    Why Benchmarking Enterprise Storage is Unique

    Enterprise arrays are not just fast disks-they’re complex systems with:

    • Multiple controllers and cache layers
    • Advanced data protection (RAID, erasure coding)
    • High-speed protocols (Fibre Channel, iSCSI, NVMe-oF)
    • Storage tiering and virtualization
    • Multi-protocol (block, file) support

    Benchmarking these systems is different from testing a single SSD or HDD. You must simulate production-like workloads, test at scale, and observe performance under both normal and failure conditions.

    Best Practices for Enterprise Storage Benchmarking

    • Simulate real-world workloads: Use realistic mixes of random/sequential I/O, read/write ratios, and block sizes.
    • Test at scale: Ensure test data sets exceed cache sizes and run with sufficient concurrency.
    • Run long-duration tests: Observe steady-state performance, not just short-term cache hits.
    • Monitor the full stack: Track storage, network, and server metrics.
    • Document everything: Record hardware/software versions, configurations, and test parameters.
    • Include failure scenarios: Simulate controller or network failures to test resilience.

    Fio: Flexible I/O Tester

    Fio is a versatile, scriptable tool ideal for generating a wide range of I/O workloads against enterprise storage.

    Example Fio Job File for Enterprise Storage
    text[global]
    ioengine=libaio
    direct=1
    rw=randrw
    rwmixread=70
    bs=8k
    iodepth=64
    numjobs=8
    size=100G
    runtime=3600
    time_based
    group_reporting
    filename=/dev/sdx # Replace with your LUN or device

    [verify]
    verify=crc32

    What this does:

    • Simulates a 70% read/30% write random workload with 8KB blocks.
    • Runs 8 parallel jobs with a queue depth of 64 for 1 hour.
    • Uses direct I/O to bypass the OS cache.
    • Verifies data integrity with CRC32.

    Run it with:

    sudo fio enterprise_test.fio

    Tips:

    • Use multiple devices or files to simulate multi-volume workloads.
    • Adjust concurrency (numjobs, iodepth) to match your environment.
    • Use --output-format=json for detailed reporting.

    Vdbench: Enterprise Workload Generator

    Vdbench is designed for complex, multi-host enterprise storage validation and offers granular workload definition and data validation.

    Example Vdbench Configuration
    text# Storage Definitions for multiple LUNs
    sd=sd1,lun=/dev/sdb,size=100g,openflags=o_direct
    sd=sd2,lun=/dev/sdc,size=100g,openflags=o_direct
    sd=sd3,lun=/dev/sdd,size=100g,openflags=o_direct
    sd=sd4,lun=/dev/sde,size=100g,openflags=o_direct

    # Workload Definition: 67% read, 33% write, 8KB random
    wd=wd1,sd=(sd1-sd4),xfersize=8k,rdpct=67,seekpct=100

    # Run Definition: max I/O, 24 hours, 1s reporting
    rd=rd1,wd=wd1,iorate=max,elapsed=86400,interval=1

    Run it with:

    vdbench -f enterprise_vdbench.conf

    Advanced tips:

    • Use the hd section to define multiple hosts for distributed testing.
    • Simulate failures (e.g., disconnect a path or controller) during the run to observe failover behavior.
    • Use fsd and fwd for NAS/file workloads.

    Key Steps for Success

    1. Profile your workload: Know your application’s I/O patterns. (capture the workload IO pattern)
    2. Prepare your environment: Use dedicated test LUNs/volumes.
    3. Configure your tools: Use Fio or Vdbench job files that match your workload.
    4. Run and monitor: Capture storage, host, and network metrics.
    5. Analyze results: Look for steady-state performance, latency spikes, and the impact of failures.
    6. Document and repeat: Ensure tests are reproducible and results are transparent.

    Conclusion

    Benchmarking enterprise-class storage is about more than just peak numbers-it’s about understanding how your array performs under pressure, during failures, and with your real workloads. Tools like Fio and Vdbench provide the flexibility, power, and validation features needed for accurate, actionable results. By following best practices and using realistic configurations, you can ensure your storage infrastructure is ready for the demands of the modern enterprise.

    References:

    • SNIA Storage Performance Testing Guide
    • Fio and Vdbench Official Documentation
  • Murphy’s Law – How to stall your Kubernetes enterprise rollout.

    Murphy’s Law – How to stall your Kubernetes enterprise rollout.

    In the world of software development, Murphy’s law holds an unassailable truth: Anything that can go wrong, will go wrong. As a proud member of this masochistic club, you might be looking for innovative ways to stall your Kubernetes enterprise rollout. Maybe you want to add a little chaos to your routine CI/CD workflow, or perhaps you’re just a thrill-seeker who loves the high stakes game of orchestration roulette. Either way, you’ve come to the right place. Sit back, relax, and let us guide you through the delightful maze of missteps and detours that will ensure your Kubernetes enterprise rollout is anything but a walk in the park.

    Ah, Kubernetes! The open-source platform that’s become the equivalent of a Hollywood blockbuster in the tech world. It’s like the Iron Man of container orchestration, bringing together an array of superpowers including automation, scaling, and management of container deployment. Enterprises are lining up to get their tickets, excited by the promises of streamlined application deployment. But before you go head over heels for Kubernetes, remember, even Iron Man had his quirks. Navigating the CI/CD waterfall can sometimes feel more like a rollercoaster ride without a seatbelt. So before you charge headfirst into your enterprise rollout, take a moment to consider Murphy’s Law – anything that can go wrong, will go wrong. So buckle up, my friends, it’s going to be a wild ride.

    This Photo by Unknown Author is licensed under CC BY-NC

    Indeed, Kubernetes is a boon for developers, cloud-native architects, and business owners alike. Its versatility and flexibility can make you feel like a superhero orchestrating seamless deployments. But when it comes to deploying and scaling in Enterprise data centers, Kubernetes might just swap its Iron Man suit for a Godzilla costume, spawning fresh challenges born out of its cloud-native architecture. This transition can lead to excessive mental gymnastics as you grapple with these new beasts of burden. So, if you’re feeling like a deer caught in the headlights, staring down the Kubernetes-python poised to gobble up your Enterprise applications, fear not! This blog is your sanctuary, your guide, your ‘how-to-tame-your-dragon’ manual. Stay with us, as we venture into the labyrinth of Kubernetes deployment and come out the other side grinning. 🙂

    Let’s dive into the 10 ways you might unintentionally stall your enterprise Kubernetes rollout, and inadvertently send your organization spiraling back to the ‘golden age’ of monolithic architecture:

    1. Do Not Plan Your Deployment: Some may argue that the beauty of Kubernetes lies in its simplicity, and indeed, the internet is abundant with blogs and videos promoting the notion that the deployment process is a walk in the park. Following such advice without investing time in understanding your unique use case could be a significant pitfall. Kubernetes deployments require thoughtful planning, taking into account the intricacies of workload requirements, resource allocation, and network architecture. The idea of “Kubernetes is the easy button for everything” is a perilous assumption that can easily derail your enterprise rollout. Always remember, while Kubernetes does a spectacular job in many aspects, it’s not a one-size-fits-all solution for every enterprise problem.

    This Photo by Unknown Author is licensed under CC BY-SA

    2. Avoid Using Certified Kubernetes Distributions: Now this one’s a head-scratcher, isn’t it? Here’s the thing, though: Kubernetes is powerful, flexible, and can be customized to a dizzying degree. However, this does not mean you should do everything from scratch. Consider this – why would you build your car when you can buy a perfectly good one off the lot? Certified Kubernetes distributions, like Red Hat OpenShift or VMware Tanzu, come with the assurance of being properly configured, tested, and meeting industry standards. They’re like your ready-to-drive cars, offering robust features and world-class support. By choosing to bypass these options, you’re essentially signing up for unnecessary headaches that could easily stall your enterprise rollout. Remember, Kubernetes is a tool, not an ideology. There’s no virtue in unnecessary complexities.

    Image from CNCF landscape

    3. Do NOT Implement Security Best Practices: This one’s a classic misstep in the tech world. Yes, Kubernetes is inherently secure, but that doesn’t mean it’s invincible. If you’re looking to stall your enterprise rollout, then by all means, ignore security best practices. However, if you’re keen on a smoothly functioning system, pay close attention to security measures like access control, network segmentation, and encryption. It’s akin to leaving your car unlocked in a crowded parking lot — sure, it might have an immobilizer and alarm system, but why invite trouble? Access control ensures only authorized personnel can interact with your Kubernetes clusters, network segmentation limits the blast radius of potential breaches, and encryption keeps your sensitive data safe in transit and at rest. Failing to implement these measures is like leaving the keys in your car with the engine running – a surefire way to invite mischief. Remember, in the world of Kubernetes deployments, security is not an afterthought, it’s a primary driver of successful CI/CD pipelines and enterprise rollouts.

    Image courtesy - https://www.google.com/url?sa=i&url=https%3A%2F%2Fsnyk.io%2Flearn%2Fcloud-application-security%2F&psig=AOvVaw0cLWWp0MtGNoPo1idw-iL7&ust=1691737538095000&source=images&cd=vfe&opi=89978449&ved=0CBIQjhxqFwoTCPCrh8vD0YADFQAAAAAdAAAAABAE

    4. Forget about Using CI/CD Pipelines: There’s a certain masochistic charm in choosing not to use CI/CD pipelines in your enterprise rollout. After all, who needs automation when you can manually deploy your applications, right? CI/CD pipelines, or Continuous Integration/Continuous Deployment pipelines, are like that studious classmate who always double-checks their work before submitting it – they automate the deployment process and ensure that all changes are thoroughly examined and validated before entering the production environment. If you’re a fan of chaos and unpredictability (and potentially stalling your Kubernetes enterprise rollout), then by all means, go ahead and give CI/CD pipelines a pass. However, if you value efficiency, reliability, and sanity, incorporating CI/CD pipelines into your operations could be a game-changer. They ensure a streamlined, error-free process that keeps your applications updated and secure, allowing your team to focus on what truly matters – building and improving your products. But hey, if you’re in the market for a bit of pandemonium, feel free to ignore this advice!

    image courtesy - https://devrant.com/rants/1535091/ci-cd-in-a-nutshell

    5. Visibility/Observability, what’s that?: There’s something rather intriguing about stumbling in the dark, isn’t there? For those of you who enjoy a good surprise, why not apply this approach to your Kubernetes deployment? Think about it, with no comprehensive monitoring solution in place, every day is like a thrilling game of hide-and-seek with your application’s performance, capacity, and availability. However, if you (like most sane people) prefer to know what’s happening under the hood, it’s time to incorporate a robust monitoring solution into your Kubernetes enterprise rollout. Think of it as a reliable co-pilot that keeps an eye on the road while you’re busy steering the ship. It helps you identify potential roadblocks or speed bumps, ensuring your journey toward a successful enterprise rollout is as smooth as possible. So go ahead, embrace the unknown, or better yet, ensure your unknowns are known with a comprehensive monitoring solution. But remember, no pressure; after all, it’s only your Kubernetes deployment we’re talking about here!

    image courtesy - https://linkedin.github.io/school-of-sre/level101/metrics_and_monitoring/observability/

    6. Don’t care about Config Management Tools: If you’re fond of unpredictability and enjoy the thrill of variance, throwing caution to the wind when it comes to config management could be your next adrenaline spike! Who needs tools like Ansible or Puppet that automate the configuration of your Kubernetes deployment and ensure consistent settings across your environment? Why make life easier and your enterprise rollout smoother when you can indulge in the chaotic symphony of inconsistency? Sure, these tools can simplify the management of your Kubernetes configuration, reduce errors, and ensure uniformity across your deployment, but where’s the fun in that? So sit back, relax, and let the inconsistencies rollick through your deployment, because who wouldn’t love a good configuration surprise?

    image courtesy - https://www.atlassian.com/microservices/microservices-architecture/configuration-management

    7. Forget about Disaster Recovery: If you’re the type who loves to live on the edge, why not take a leap of faith with your Kubernetes rollout too? After all, implementing disaster recovery measures like backup and recovery procedures is like carrying an umbrella all the time just because it might rain. Sure, these measures could prevent your enterprise from figuratively getting drenched in the event of an unexpected outage or data loss, but what’s a little water, right? Having a disaster recovery plan could mean the difference between a minor hiccup and a full-fledged organizational crisis during a catastrophe, but let’s face it, who doesn’t love a little game of Russian Roulette with their Kubernetes deployment? So, go ahead and roll the dice. After all, disaster recovery is just for those who aren’t fans of suspense, right?

    image courtesy - https://www.sungardas.com/en-us/blog/how-to-create-a-dr-plan-you-can-be-confident-in/

    8. Train Your Staff (or Don’t): Now, here’s a real knee-slapper: education. Nothing quite like seeing your team scramble around like a bunch of cats on a hot tin roof because they don’t know their Pods from their Nodes. Who needs well-trained staff, conversant with Kubernetes best practices, when you can bask in the glorious pandemonium of mismanaged deployments instead? Sure, giving your employees the necessary skills to effectively manage and operate your Kubernetes deployment might lead to fewer issues, greater efficiency, and a more successful enterprise rollout. But let’s be real, why stifle the potential theatre of the absurd that could result from untrained staff wrestling a mammoth like Kubernetes? Life is a stage, after all, and in your Kubernetes drama, training is just too mainstream a script. So, sit back, grab some popcorn, and enjoy the show!

    image courtesy - https://www.makemebetter.net/learning-to-go-with-the-flow/

    9. Live in the Past: Here’s a revolutionary idea – rolling with the times. You could, if you’re feeling particularly adventurous, actually stay up-to-date with the latest Kubernetes releases and security patches. That, of course, would imply that you’re interested in ensuring your deployment operates with the latest features and security updates. But hey, who doesn’t love a little nostalgia? Sure, you could prioritize keeping your enterprise rollout in line with the newest, slickest versions of Kubernetes, ensuring that your CI/CD pipelines are as cutting-edge as they come, but isn’t there a certain charm in running your enterprise on an antiquated version that’s as outdated as a floppy disk in an AI lab? After all, cybersecurity threats, outdated functionalities, and inefficiencies are just minor speed bumps on the road of enterprise rollouts. So, why not kick back, ignore those pesky update notifications, and let your Kubernetes deployment bask in the warm glow of obsolescence? Just remember – living in the past is only fun until the ghosts of security vulnerabilities and outdated features come knocking on your door.

    10. Embrace Impermanence (non-persistence): In the grand scheme of things, isn’t Kubernetes is supposed to be ephemeral? Why should your data be any different? Go ahead, live dangerously. Don’t bother with planning for data persistence in your Kubernetes rollout. Imagine the thrill of living on the edge, knowing that you could lose all your data the moment a pod goes down or the system crashes. Sure, you could use the Kubernetes Persistent Volume (PV) and Persistent Volume Claim (PVC) architecture to ensure your data survives even when your pods don’t, but where’s the fun in that? Data persistence is so pedestrian. Remember, the goal here is to stall your Kubernetes enterprise rollout, not to make it robust, resilient, and reliable. So, go ahead, and throw caution (and your data) to the wind. It’s only important business information after all, right?

    image courtesy - https://cloudtweaks.com/2016/11/4-cloud-tools-help-business-save-money/

    But hey, here’s a novel idea – what if you actually wanted to succeed in your cloud-native strategy? I know, I know, it sounds a bit radical given our prior conversation. But bear with me. For those of you who enjoy sailing smoothly on the seas of enterprise IT, without the thrill of hitting every possible iceberg, Dell has created a glorious solution. A tool, that’s as much a life preserver as it is a nautical chart, guiding you safely through the treacherous waters of Kubernetes enterprise rollouts. This magic wand is called the Container Storage Modules (CSM). 

    https://dell.github.io/csm-docs/docs/

    This isn’t just any tool – it’s your co-pilot on the journey to a seamless Kubernetes implementation. It’s like having a Swiss army knife for enterprise data management. The CSM ensures that your data persistence strategies are as solid as a rock, ensuring that no pod crash or system failure can sweep your data into the abyss. With CSM, you can laugh in the face of data loss, secure in the knowledge that your enterprise information is safe and sound. So, for the daredevils who actually like to succeed in their endeavors, the Dell Technologies CSM is the perfect tool to ensure your Kubernetes enterprise rollout is as smooth and trouble-free as a hot knife through butter.

    I hope this post proves helpful, regardless of which direction you choose for your enterprise cloud journey. If you’re inclined to thrill and enjoy the odd game of Russian roulette with your data, you now have some innovative strategies to stall your Kubernetes rollout. However, if your preference is smooth as a jazz tune and your data as secure as Dell’s Project Fort Zero, then Dell’s Container Storage Modules (CSM) is the tool you need. The CSM is your beacon in the foggy world of Kubernetes enterprise rollout, ensuring that no data loss or system failure can derail your cloud-native strategy. It’s your data’s best friend, your enterprise’s lifeline, and your ticket to a successful Kubernetes implementation.

    Enjoy the journey, and remember – with the right tools and strategies, Murphy’s Law doesn’t stand a chance!

  • Installation of docker fails on CentOS 8 with Error – package containerd.io-1.2.10-3.2.el7.x86_64 is excluded

    Installation of docker fails on CentOS 8 with Error – package containerd.io-1.2.10-3.2.el7.x86_64 is excluded

    I recently came across a strange issue while installing Docker on CentOS (version 8) machine.

    Issue

    When I tried below options to install docker on my machine I got the same error every time.

    Installation Commands Used

    yum install -y -q docker-ce
    or
    yum install -y docker-ce.x86_64
    or
    yum install docker-ce

    Error message received

    Error:
     Problem: package docker-ce-3:19.03.8-3.el7.x86_64 requires containerd.io >= 1.2.2-3, but none of the providers can be installed
      - cannot install the best candidate for the job
      - package containerd.io-1.2.10-3.2.el7.x86_64 is excluded
      - package containerd.io-1.2.13-3.1.el7.x86_64 is excluded
      - package containerd.io-1.2.2-3.3.el7.x86_64 is excluded
      - package containerd.io-1.2.2-3.el7.x86_64 is excluded
      - package containerd.io-1.2.4-3.1.el7.x86_64 is excluded
      - package containerd.io-1.2.5-3.1.el7.x86_64 is excluded
      - package containerd.io-1.2.6-3.3.el7.x86_64 is excluded

    Resolution

    To resolve this issue, first we need to manually install the containerd.io package.

    [root@test_centos8 /]# yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
    Last metadata expiration check: 0:02:53 ago on Thu 02 Apr 2020 09:29:41 AM UTC.
    containerd.io-1.2.6-3.3.el7.x86_64.rpm                                                                                                                                 18 MB/s |  26 MB     00:01
    Dependencies resolved.
    ======================================================================================================================================================================================================
     Package                                               Architecture                    Version                                                            Repository                             Size
    ======================================================================================================================================================================================================
    Installing:
     containerd.io                                         x86_64                          1.2.6-3.3.el7                                                      @commandline                           26 M
    Installing dependencies:
     container-selinux                                     noarch                          2:2.124.0-1.module_el8.1.0+272+3e64ee36                            AppStream                              47 k
     checkpolicy                                           x86_64                          2.9-1.el8                                                          BaseOS                                348 k
     libselinux-utils                                      x86_64                          2.9-2.1.el8                                                        BaseOS                                243 k
     policycoreutils                                       x86_64                          2.9-3.el8_1.1                                                      BaseOS                                377 k
     policycoreutils-python-utils                          noarch                          2.9-3.el8_1.1                                                      BaseOS                                250 k
     python3-audit                                         x86_64                          3.0-0.13.20190507gitf58ec40.el8                                    BaseOS                                 85 k
     python3-libselinux                                    x86_64                          2.9-2.1.el8                                                        BaseOS                                283 k
     python3-libsemanage                                   x86_64                          2.9-1.el8                                                          BaseOS                                127 k
     python3-policycoreutils                               noarch                          2.9-3.el8_1.1                                                      BaseOS                                2.2 M
     python3-setools                                       x86_64                          4.2.2-1.el8                                                        BaseOS                                600 k
     rpm-plugin-selinux                                    x86_64                          4.14.2-25.el8                                                      BaseOS                                 73 k
     selinux-policy                                        noarch                          3.14.3-20.el8                                                      BaseOS                                602 k
     selinux-policy-targeted                               noarch                          3.14.3-20.el8                                                      BaseOS                                 15 M
    Enabling module streams:
     container-tools                                                                       rhel8
    
    Transaction Summary
    ======================================================================================================================================================================================================
    Install  14 Packages
    
    Total size: 46 M
    Total download size: 20 M
    Installed size: 158 M
    Downloading Packages:
    (1/13): libselinux-utils-2.9-2.1.el8.x86_64.rpm                                                                                                                       2.4 MB/s | 243 kB     00:00
    (2/13): container-selinux-2.124.0-1.module_el8.1.0+272+3e64ee36.noarch.rpm                                                                                            375 kB/s |  47 kB     00:00
    (3/13): checkpolicy-2.9-1.el8.x86_64.rpm                                                                                                                              2.5 MB/s | 348 kB     00:00
    (4/13): python3-audit-3.0-0.13.20190507gitf58ec40.el8.x86_64.rpm                                                                                                      2.5 MB/s |  85 kB     00:00
    (5/13): policycoreutils-2.9-3.el8_1.1.x86_64.rpm                                                                                                                      3.0 MB/s | 377 kB     00:00
    (6/13): python3-libsemanage-2.9-1.el8.x86_64.rpm                                                                                                                      2.2 MB/s | 127 kB     00:00
    (7/13): policycoreutils-python-utils-2.9-3.el8_1.1.noarch.rpm                                                                                                         685 kB/s | 250 kB     00:00
    (8/13): python3-libselinux-2.9-2.1.el8.x86_64.rpm                                                                                                                     810 kB/s | 283 kB     00:00
    (9/13): rpm-plugin-selinux-4.14.2-25.el8.x86_64.rpm                                                                                                                   288 kB/s |  73 kB     00:00
    (10/13): python3-setools-4.2.2-1.el8.x86_64.rpm                                                                                                                       1.1 MB/s | 600 kB     00:00
    (11/13): selinux-policy-3.14.3-20.el8.noarch.rpm                                                                                                                      936 kB/s | 602 kB     00:00
    (12/13): python3-policycoreutils-2.9-3.el8_1.1.noarch.rpm                                                                                                             1.3 MB/s | 2.2 MB     00:01
    (13/13): selinux-policy-targeted-3.14.3-20.el8.noarch.rpm                                                                                                             3.0 MB/s |  15 MB     00:05
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Total                                                                                                                                                                 2.8 MB/s |  20 MB     00:07
    Running transaction check
    Transaction check succeeded.
    Running transaction test
    Transaction test succeeded.
    Running transaction
      Preparing        :                                                                                                                                                                              1/1
      Installing       : python3-libselinux-2.9-2.1.el8.x86_64                                                                                                                                       1/14
      Installing       : libselinux-utils-2.9-2.1.el8.x86_64                                                                                                                                         2/14
      Installing       : policycoreutils-2.9-3.el8_1.1.x86_64                                                                                                                                        3/14
      Running scriptlet: policycoreutils-2.9-3.el8_1.1.x86_64                                                                                                                                        3/14
      Installing       : rpm-plugin-selinux-4.14.2-25.el8.x86_64                                                                                                                                     4/14
      Installing       : selinux-policy-3.14.3-20.el8.noarch                                                                                                                                         5/14
      Running scriptlet: selinux-policy-3.14.3-20.el8.noarch                                                                                                                                         5/14
      Running scriptlet: selinux-policy-targeted-3.14.3-20.el8.noarch                                                                                                                                6/14
      Installing       : selinux-policy-targeted-3.14.3-20.el8.noarch                                                                                                                                6/14
      Running scriptlet: selinux-policy-targeted-3.14.3-20.el8.noarch                                                                                                                                6/14
      Installing       : python3-libsemanage-2.9-1.el8.x86_64                                                                                                                                        7/14
      Installing       : python3-setools-4.2.2-1.el8.x86_64                                                                                                                                          8/14
      Installing       : python3-audit-3.0-0.13.20190507gitf58ec40.el8.x86_64                                                                                                                        9/14
      Installing       : checkpolicy-2.9-1.el8.x86_64                                                                                                                                               10/14
      Installing       : python3-policycoreutils-2.9-3.el8_1.1.noarch                                                                                                                               11/14
      Installing       : policycoreutils-python-utils-2.9-3.el8_1.1.noarch                                                                                                                          12/14
      Running scriptlet: container-selinux-2:2.124.0-1.module_el8.1.0+272+3e64ee36.noarch                                                                                                           13/14
      Installing       : container-selinux-2:2.124.0-1.module_el8.1.0+272+3e64ee36.noarch                                                                                                           13/14
      Running scriptlet: container-selinux-2:2.124.0-1.module_el8.1.0+272+3e64ee36.noarch                                                                                                           13/14
      Installing       : containerd.io-1.2.6-3.3.el7.x86_64                                                                                                                                         14/14
      Running scriptlet: containerd.io-1.2.6-3.3.el7.x86_64                                                                                                                                         14/14
      Running scriptlet: container-selinux-2:2.124.0-1.module_el8.1.0+272+3e64ee36.noarch                                                                                                           14/14
      Running scriptlet: containerd.io-1.2.6-3.3.el7.x86_64                                                                                                                                         14/14
      Verifying        : container-selinux-2:2.124.0-1.module_el8.1.0+272+3e64ee36.noarch                                                                                                            1/14
      Verifying        : checkpolicy-2.9-1.el8.x86_64                                                                                                                                                2/14
      Verifying        : libselinux-utils-2.9-2.1.el8.x86_64                                                                                                                                         3/14
      Verifying        : policycoreutils-2.9-3.el8_1.1.x86_64                                                                                                                                        4/14
      Verifying        : policycoreutils-python-utils-2.9-3.el8_1.1.noarch                                                                                                                           5/14
      Verifying        : python3-audit-3.0-0.13.20190507gitf58ec40.el8.x86_64                                                                                                                        6/14
      Verifying        : python3-libselinux-2.9-2.1.el8.x86_64                                                                                                                                       7/14
      Verifying        : python3-libsemanage-2.9-1.el8.x86_64                                                                                                                                        8/14
      Verifying        : python3-policycoreutils-2.9-3.el8_1.1.noarch                                                                                                                                9/14
      Verifying        : python3-setools-4.2.2-1.el8.x86_64                                                                                                                                         10/14
      Verifying        : rpm-plugin-selinux-4.14.2-25.el8.x86_64                                                                                                                                    11/14
      Verifying        : selinux-policy-3.14.3-20.el8.noarch                                                                                                                                        12/14
      Verifying        : selinux-policy-targeted-3.14.3-20.el8.noarch                                                                                                                               13/14
      Verifying        : containerd.io-1.2.6-3.3.el7.x86_64                                                                                                                                         14/14
    
    Installed:
      containerd.io-1.2.6-3.3.el7.x86_64   container-selinux-2:2.124.0-1.module_el8.1.0+272+3e64ee36.noarch checkpolicy-2.9-1.el8.x86_64                         libselinux-utils-2.9-2.1.el8.x86_64
      policycoreutils-2.9-3.el8_1.1.x86_64 policycoreutils-python-utils-2.9-3.el8_1.1.noarch                python3-audit-3.0-0.13.20190507gitf58ec40.el8.x86_64 python3-libselinux-2.9-2.1.el8.x86_64
      python3-libsemanage-2.9-1.el8.x86_64 python3-policycoreutils-2.9-3.el8_1.1.noarch                     python3-setools-4.2.2-1.el8.x86_64                   rpm-plugin-selinux-4.14.2-25.el8.x86_64
      selinux-policy-3.14.3-20.el8.noarch  selinux-policy-targeted-3.14.3-20.el8.noarch
    
    Complete!

    Once containerd.io package is installed you can go ahead and install the docker without any error.

    [root@test_centos8 /]# yum install docker-ce
    Last metadata expiration check: 0:19:09 ago on Thu 02 Apr 2020 09:29:41 AM UTC.
    Dependencies resolved.
    ======================================================================================================================================================================================================
     Package                                                Architecture                           Version                                         Repository                                        Size
    ======================================================================================================================================================================================================
    Installing:
     docker-ce                                              x86_64                                 3:19.03.8-3.el7                                 docker-ce-stable                                  25 M
    Installing dependencies:
     iptables                                               x86_64                                 1.8.2-16.el8                                    BaseOS                                           586 k
     libcgroup                                              x86_64                                 0.41-19.el8                                     BaseOS                                            70 k
     libnetfilter_conntrack                                 x86_64                                 1.0.6-5.el8                                     BaseOS                                            65 k
     libnfnetlink                                           x86_64                                 1.0.1-13.el8                                    BaseOS                                            33 k
     libnftnl                                               x86_64                                 1.1.1-4.el8                                     BaseOS                                            83 k
     docker-ce-cli                                          x86_64                                 1:19.03.8-3.el7                                 docker-ce-stable                                  40 M
    
    Transaction Summary
    ======================================================================================================================================================================================================
    Install  7 Packages
    
    Total download size: 65 M
    Installed size: 276 M
    Is this ok [y/N]: y
    Downloading Packages:
    (1/7): libnetfilter_conntrack-1.0.6-5.el8.x86_64.rpm                                                                                                                  1.0 MB/s |  65 kB     00:00
    (2/7): libcgroup-0.41-19.el8.x86_64.rpm                                                                                                                               1.0 MB/s |  70 kB     00:00
    (3/7): libnfnetlink-1.0.1-13.el8.x86_64.rpm                                                                                                                           1.0 MB/s |  33 kB     00:00
    (4/7): libnftnl-1.1.1-4.el8.x86_64.rpm                                                                                                                                2.3 MB/s |  83 kB     00:00
    (5/7): iptables-1.8.2-16.el8.x86_64.rpm                                                                                                                               3.3 MB/s | 586 kB     00:00
    (6/7): docker-ce-19.03.8-3.el7.x86_64.rpm                                                                                                                             8.2 MB/s |  25 MB     00:02
    (7/7): docker-ce-cli-19.03.8-3.el7.x86_64.rpm                                                                                                                          10 MB/s |  40 MB     00:03
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Total                                                                                                                                                                  14 MB/s |  65 MB     00:04
    warning: /var/cache/dnf/docker-ce-stable-091d8a9c23201250/packages/docker-ce-19.03.8-3.el7.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY
    Docker CE Stable - x86_64                                                                                                                                              39 kB/s | 1.6 kB     00:00
    Importing GPG key 0x621E9F35:
     Userid     : "Docker Release (CE rpm) <docker@docker.com>"
     Fingerprint: 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35
     From       : https://download.docker.com/linux/centos/gpg
    Is this ok [y/N]: y
    Key imported successfully
    Running transaction check
    Transaction check succeeded.
    Running transaction test
    Transaction test succeeded.
    Running transaction
      Preparing        :                                                                                                                                                                              1/1
      Installing       : libnfnetlink-1.0.1-13.el8.x86_64                                                                                                                                             1/7
      Running scriptlet: libnfnetlink-1.0.1-13.el8.x86_64                                                                                                                                             1/7
      Installing       : libnetfilter_conntrack-1.0.6-5.el8.x86_64                                                                                                                                    2/7
      Running scriptlet: libnetfilter_conntrack-1.0.6-5.el8.x86_64                                                                                                                                    2/7
      Installing       : docker-ce-cli-1:19.03.8-3.el7.x86_64                                                                                                                                         3/7
      Running scriptlet: docker-ce-cli-1:19.03.8-3.el7.x86_64                                                                                                                                         3/7
      Installing       : libnftnl-1.1.1-4.el8.x86_64                                                                                                                                                  4/7
      Running scriptlet: libnftnl-1.1.1-4.el8.x86_64                                                                                                                                                  4/7
      Running scriptlet: iptables-1.8.2-16.el8.x86_64                                                                                                                                                 5/7
      Installing       : iptables-1.8.2-16.el8.x86_64                                                                                                                                                 5/7
      Running scriptlet: iptables-1.8.2-16.el8.x86_64                                                                                                                                                 5/7
      Running scriptlet: libcgroup-0.41-19.el8.x86_64                                                                                                                                                 6/7
      Installing       : libcgroup-0.41-19.el8.x86_64                                                                                                                                                 6/7
      Running scriptlet: libcgroup-0.41-19.el8.x86_64                                                                                                                                                 6/7
      Installing       : docker-ce-3:19.03.8-3.el7.x86_64                                                                                                                                             7/7
      Running scriptlet: docker-ce-3:19.03.8-3.el7.x86_64                                                                                                                                             7/7
      Verifying        : iptables-1.8.2-16.el8.x86_64                                                                                                                                                 1/7
      Verifying        : libcgroup-0.41-19.el8.x86_64                                                                                                                                                 2/7
      Verifying        : libnetfilter_conntrack-1.0.6-5.el8.x86_64                                                                                                                                    3/7
      Verifying        : libnfnetlink-1.0.1-13.el8.x86_64                                                                                                                                             4/7
      Verifying        : libnftnl-1.1.1-4.el8.x86_64                                                                                                                                                  5/7
      Verifying        : docker-ce-3:19.03.8-3.el7.x86_64                                                                                                                                             6/7
      Verifying        : docker-ce-cli-1:19.03.8-3.el7.x86_64                                                                                                                                         7/7
    
    Installed:
      docker-ce-3:19.03.8-3.el7.x86_64     iptables-1.8.2-16.el8.x86_64             libcgroup-0.41-19.el8.x86_64     libnetfilter_conntrack-1.0.6-5.el8.x86_64     libnfnetlink-1.0.1-13.el8.x86_64
      libnftnl-1.1.1-4.el8.x86_64          docker-ce-cli-1:19.03.8-3.el7.x86_64
    
    Complete!

    Once docker is successfully installed you can run docker -v to check the installed version.

    [root@test_centos8 /]# docker -v
    Docker version 19.03.8, build afacb8b

    Hope this helps everyone (and saves productive time).

  • Database Performance Benchmark using HammerDB

    Database Performance Benchmark using HammerDB

    I have been using HammerDB for database performance bench-marking . This is very useful tool if you’re getting into any proof of concepts (POC) or testing of new database infrastructure stack before production roll-out.

    In this blog post we will discuss around using HammerDB to generate OLTP (TPC-C workload) on Microsoft SQL database. In my example I had Microsoft SQL and HammerDB server created on AWS EC2 instances. But from HammerDB perspective it doesn’t matter as far as it can communicate to database instance.

    We will follow 5 simple steps to run synthetic workload on MS SQL database. So let’s get started.

    Step 1 – Installing the HammerDB Application

    Before you get started make sure that –

    • HammerDB and MS SQL server are on same network/VLAN
    • MS SQL server is installed and running
    • Login to MS SQL console and create new SQL database. Make sure that new database is created on the target storage disks. If you create database in C drive, then you might not get expected performance due to disk bottleneck.
    Microsoft SQL database console
    • Download HammerDB installer (Click image below)
    HammerDB download link
    • Once HammerDB installer is downloaded, go ahead and install the same. Below are the links for installation steps.

    At this point you should have

    • MS SQL server ready with test database created on desired target storage disks
    • HammerDB installed and running

    Step 2 – Configuration of Schema Build

    We will need to created OLTP workload schema as per TPC-C specifications. Follow below steps for building OLTP schema on target database

    • Open the HammerDB console
    HammerDB – Console
    • Under Benchmark navigation page, double-click on SQL Server. In Benchmark Options pop-up window select SQL Server and TPC-C options. Then click Ok. Click Ok once again to confirm the selection.
    HammerDB – Selecting SQL database and TPC-C workload
    • Under Benchmark navigation now you can see SQL Server selected with TPC-C options.
    HammerDB – SQL server and TPC-C benchmark
    • Expand TPC-C under SQL Server and then expand Schema Build
    HammerDB – TPC-C Schema Build
    • Double-click on Options under Schema Build. Pop-up window of TPC-C Build Options will open. In this window enter below details, and then click Ok
      • SQL Server – IP address or hostname of SQL server. Keep (local) if HammerDB is installed on the SQL server.
      • Authentication – Use Windows Authentication if you want logged-in user credentials to be used for SQL server, else select SQL authentication and enter credentials.
      • SQL Server Database – Name of the database which we had created in Step 1
      • Number of Warehouses – Enter the value to number of warehouses you have chosen for your testing. Preferably select number of warehouses equal to number of cores on the server
      • Virtual Users to Build Schema – Set this value equal to number of warehouses.
    HammerDB – TPC-C Build Options
    • In the Benchmark pane double-click on Build
    HammerDB – TPC-C Schema Build
    • Click Yes to confirm creating schema in the target SQL database.
    • HammerDB will now start creating virtual user threads and create schema in the target database. This process takes some time. You can monitor the status in top-right corner of HammerDB console. (TPC-C creation in top-right)
    HammerDB – TPC-C Schema Creation in process
    • Once completed you can see that the status is changed to Complete
    HammerDB – TPC-C Schema Creation Completed

    Step 3 – Configure Driver Script

    Follow below steps to configure HammerDB driver script

    • Expand the Driver Script from Benchmark navigation pane and double-click on Options
    HammerDB – Driver Script
    • In the TPC-C Driver Options pop-up window enter below details, and then click Ok
      • SQL Server – Keep it same as Step 2
      • Authentication – Keep it same as Step 2
      • Total Transactions Per User – Keep default value. This value will set the number of transactions each virtual user will process before logging off
      • TPC-C Driver Script – Keep this option as Timed Driver Script. This will run the workload for finite time as specified in Minutes for Test Duration
      • Minutes of Rampup Time – The rampup time defines the time in minutes for the monitoring virtual user to wait for the virtual users running the workload to connect to the database. 2 minutes in my case. You can increase this number if you’ve higher number of virtual users.
      • Minutes for Test Duration – The Minutes for Test Duration is shown as duration in the Driver Script. This does not include rampup time.
      • Use All Warehouses – Keep this option checked.
    HammerDB – Driver Script Options
    • In the Benchmark navigation double-click on Load (under Driver Script). You need to Load the Driver Script every time you make changes to Driver Script Options.
    HammerDB – Driver Script Load

    Step 4 – Create Virtual User

    Once HammerDB driver script is loaded, follow below steps to create virtual user.

    • Expand Virtual User from Benchmark pane
    HammerDB – Virtual User
    • Double-click on Options. In the pop-up window enter below details, and then click Ok.
      • Virtual Users – Keep number of users same as Step 2
      • Keep Other inputs as default
    HammerDB – Virtual User Options
    • In the Benchmark navigation pane double-click on Create under Virtual User. This will create virtual users and keep them idle.
    HammerDB – Virtual User Create

    At this point we are ready to start OLTP workload on target database.

    Step 5 – Run HammerDB OLTP (TPC-C) Workload

    Follow below steps to run the OLTP workload and monitor the TPMs.

    • In Benchmark pane double-click on Run (Under Virtual User).
    HammerDB – Run OLTP (TPC-C) workload
    • Now Virtual Users will start logging into the target database and begin running their workload. You can monitor the status under Virtual User 1-MONITOR
    HammerDB – Starting OLTP (TPC-C) Workload – In Progress
    • While workload is running you can monitor the real-time TPM (Transactions Per Minute) by clicking on Transaction Counter
    HammerDB – Transaction Counter
    • Once workload is completed you can see the status in top-right corner as well as under Virtual User 1-MONITOR
    HammerDB – Starting OLTP (TPC-C) Workload – Completed
    • Once the workload is completed note down TEST RESULT under Virtual User 1-MONITOR
    HammerDB – OLTP (TPC-C) TEST RESULT

    You can run multiple tests and take average across them for realistic performance numbers.

    Apart from MS SQL (used in this blog post) HammerDB supports running OLTP (TPC-C) and OLAP (TPC-H) on Oracle, IBM DB2, MySQL, PostgreSQL, MariaDB and Redis.

    I hope this helps everyone.

  • Linux – Creating Local RAID5 using fdisk

    This blogs lists the steps around creating RAID5 volume on Linux using local disks.

    We will start by installing software RAID on Linux system

    # yum install mdadm
    Loaded plugins: ulninfo
    Resolving Dependencies
    --> Running transaction check
    ---> Package mdadm.x86_64 0:4.1-1.0.1.el7 will be installed
    --> Processing Dependency: libreport-filesystem for package: mdadm-4.1-1.0.1.el7.x86_64
    --> Running transaction check
    ---> Package libreport-filesystem.x86_64 0:2.1.11-43.0.1.el7 will be installed
    --> Finished Dependency Resolution
    
    Dependencies Resolved
    
    ================================================================================
     Package                  Arch       Version               Repository      Size
    ================================================================================
    Installing:
     mdadm                    x86_64     4.1-1.0.1.el7         ol7_latest     435 k
    Installing for dependencies:
     libreport-filesystem     x86_64     2.1.11-43.0.1.el7     ol7_latest      40 k
    
    Transaction Summary
    ================================================================================
    Install  1 Package (+1 Dependent package)
    
    Total download size: 475 k
    Installed size: 1.0 M
    Is this ok [y/d/N]: y
    Downloading packages:
    (1/2): libreport-filesystem-2.1.11-43.0.1.el7.x86_64.rpm   |  40 kB   00:00
    (2/2): mdadm-4.1-1.0.1.el7.x86_64.rpm                      | 435 kB   00:00
    --------------------------------------------------------------------------------
    Total                                              1.8 MB/s | 475 kB  00:00
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : libreport-filesystem-2.1.11-43.0.1.el7.x86_64                1/2
      Installing : mdadm-4.1-1.0.1.el7.x86_64                                   2/2
      Verifying  : mdadm-4.1-1.0.1.el7.x86_64                                   1/2
      Verifying  : libreport-filesystem-2.1.11-43.0.1.el7.x86_64                2/2
    
    Installed:
      mdadm.x86_64 0:4.1-1.0.1.el7
    
    Dependency Installed:
      libreport-filesystem.x86_64 0:2.1.11-43.0.1.el7
    
    Complete!

    Now let’s identify disks which we will use for creating RAID5 volume. These disks can be local or storage LUNs. You can list the disks using running below command. In this example we will use 5 local disks – /dev/xvd(b-f)

    # fdisk -l | grep /dev/
    Disk /dev/xvda: 53.7 GB, 53687091200 bytes, 104857600 sectors
    /dev/xvda1   *        2048     4098047     2048000   83  Linux
    /dev/xvda2         4098048    86018047    40960000   83  Linux
    /dev/xvda3        86018048   104857599     9419776   82  Linux swap / Solaris
    Disk /dev/xvdd: 53.7 GB, 53687091200 bytes, 104857600 sectors
    Disk /dev/xvde: 53.7 GB, 53687091200 bytes, 104857600 sectors
    Disk /dev/xvdb: 53.7 GB, 53687091200 bytes, 104857600 sectors
    Disk /dev/xvdc: 53.7 GB, 53687091200 bytes, 104857600 sectors
    Disk /dev/xvdf: 53.7 GB, 53687091200 bytes, 104857600 sectors
    

    Before you begin make sure that selected drives do not have existing RAID configured.

    # mdadm -E /dev/xvd[b-f]
    mdadm: No md superblock detected on /dev/xvdb.
    mdadm: No md superblock detected on /dev/xvdc.
    mdadm: No md superblock detected on /dev/xvdd.
    mdadm: No md superblock detected on /dev/xvde.
    mdadm: No md superblock detected on /dev/xvdf.

    Next step is to create partition on selected disks using fdisk. Follow below steps for each selected disks – /dev/xvd(b-f) in this example

    # fdisk /dev/xvdc
    Welcome to fdisk (util-linux 2.23.2).
    
    Changes will remain in memory only, until you decide to write them.
    Be careful before using the write command.
    
    Device does not contain a recognized partition table
    Building a new DOS disklabel with disk identifier 0x6845b853.
    
    Command (m for help): n
    Partition type:
       p   primary (0 primary, 0 extended, 4 free)
       e   extended
    Select (default p): p
    Partition number (1-4, default 1): 1
    First sector (2048-104857599, default 2048):
    Using default value 2048
    Last sector, +sectors or +size{K,M,G} (2048-104857599, default 104857599):
    Using default value 104857599
    Partition 1 of type Linux and of size 50 GiB is set
    
    Command (m for help): t
    Selected partition 1
    Hex code (type L to list all codes): fd
    Changed type of partition 'Linux' to 'Linux raid autodetect'
    
    Command (m for help): p
    
    Disk /dev/xvdc: 53.7 GB, 53687091200 bytes, 104857600 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk label type: dos
    Disk identifier: 0x6845b853
    
        Device Boot      Start         End      Blocks   Id  System
    /dev/xvdc1            2048   104857599    52427776   fd  Linux raid autodetect
    
    Command (m for help): w
    The partition table has been altered!
    
    Calling ioctl() to re-read partition table.
    Syncing disks.

    Once you’ve successfully created the partitions for all disks, you can verify the changes using below command

    # mdadm -E /dev/xvd[b-f]
    /dev/xvdb:
       MBR Magic : aa55
    Partition[0] :    104855552 sectors at         2048 (type fd)
    /dev/xvdc:
       MBR Magic : aa55
    Partition[0] :    104855552 sectors at         2048 (type fd)
    /dev/xvdd:
       MBR Magic : aa55
    Partition[0] :    104855552 sectors at         2048 (type fd)
    /dev/xvde:
       MBR Magic : aa55
    Partition[0] :    104855552 sectors at         2048 (type fd)
    /dev/xvdf:
       MBR Magic : aa55
    Partition[0] :    104855552 sectors at         2048 (type fd)

    Now create RAID device (/dev/md1 in below example) using all the newly created disk partitions

    # mdadm --create /dev/md1 --level=5 --raid-devices=5 /dev/xvdb1 /dev/xvdc1 /dev/xvdd1 /dev/xvde1 /dev/xvdf1
    mdadm: Defaulting to version 1.2 metadata
    mdadm: array /dev/md1 started.

    Note that it takes some time to complete the RAID creation. You can monitor the progress using below command. Below command will show you current % completed.

    # cat /proc/mdstat
    Personalities : [raid6] [raid5] [raid4]
    md1 : active raid5 xvdf1[5] xvde1[3] xvdd1[2] xvdc1[1] xvdb1[0]
          209575936 blocks super 1.2 level 5, 512k chunk, algorithm 2 [5/4] [UUUU_]
          [=>...................]  recovery =  7.2% (3808256/52393984) finish=13.1min speed=61363K/sec
    
    unused devices: <none>
    

    But you prefer to watch screen till 100% completion then run below command. Result of this command will be persistent on the screen and will show you real time progress.

    # watch -n1 cat /proc/mdstat
    Every 1.0s: cat /proc/mdstat                            Mon Dec  2 09:41:04 2019
    
    Personalities : [raid6] [raid5] [raid4]
    md1 : active raid5 xvdf1[5] xvde1[3] xvdd1[2] xvdc1[1] xvdb1[0]
          209575936 blocks super 1.2 level 5, 512k chunk, algorithm 2 [5/4] [UUUU_]
          [==>..................]  recovery = 13.9% (7335304/52393984) finish=12.1mi
    n speed=61622K/sec
    
    unused devices: <none>

    Once RAID creation is 100% you can run below command to see the summary of the RAID device configuration. RAID device is /dev/md1 in below example with 5 devices – /dev/xvd(b-f)1

    # mdadm --detail /dev/md1
    /dev/md1:
               Version : 1.2
         Creation Time : Mon Dec  2 09:39:05 2019
            Raid Level : raid5
            Array Size : 209575936 (199.87 GiB 214.61 GB)
         Used Dev Size : 52393984 (49.97 GiB 53.65 GB)
          Raid Devices : 5
         Total Devices : 5
           Persistence : Superblock is persistent
    
           Update Time : Mon Dec  2 09:53:20 2019
                 State : clean
        Active Devices : 5
       Working Devices : 5
        Failed Devices : 0
         Spare Devices : 0
    
                Layout : left-symmetric
            Chunk Size : 512K
    
    Consistency Policy : resync
    
                  Name : ip-10-10-10-207:1  (local to host ip-10-10-10-207)
                  UUID : 07f28a7b:3c70d798:1deecf9a:292ddd2c
                Events : 18
    
        Number   Major   Minor   RaidDevice State
           0     202       17        0      active sync   /dev/xvdb1
           1     202       33        1      active sync   /dev/xvdc1
           2     202       49        2      active sync   /dev/xvdd1
           3     202       65        3      active sync   /dev/xvde1
           5     202       81        4      active sync   /dev/xvdf1
    

    At this point we have RAID5 device created (/dev/md1). Now we need to create file system. In below example we are creating EXT4 file system

    # mkfs.ext4 /dev/md1
    mke2fs 1.42.9 (28-Dec-2013)
    Filesystem label=
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    Stride=128 blocks, Stripe width=512 blocks
    13099008 inodes, 52393984 blocks
    2619699 blocks (5.00%) reserved for the super user
    First data block=0
    Maximum filesystem blocks=2199912448
    1599 block groups
    32768 blocks per group, 32768 fragments per group
    8192 inodes per group
    Superblock backups stored on blocks:
            32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
            4096000, 7962624, 11239424, 20480000, 23887872
    
    Allocating group tables: done
    Writing inode tables: done
    Creating journal (32768 blocks): done
    Writing superblocks and filesystem accounting information: done
    

    Once the file system is created on RAID5 device, create the mount point and mount the RAID5 device on the same.

    # mkdir /mnt/ebs_r5
    # mount /dev/md1 /mnt/ebs_r5
    # df -h
    Filesystem        Size  Used Avail Use% Mounted on
    devtmpfs           32G     0   32G   0% /dev
    tmpfs              32G     0   32G   0% /dev/shm
    tmpfs              32G   17M   32G   1% /run
    tmpfs              32G     0   32G   0% /sys/fs/cgroup
    /dev/xvda2         39G  2.9G   34G   8% /
    /dev/xvda1        1.9G  234M  1.6G  13% /boot
    tmpfs             6.3G     0  6.3G   0% /run/user/1000
    /dev/md1          197G   61M  187G   1% /mnt/ebs_r5

    Also make sure you’ve added entry for new mount point in the /etc/fstab file. So that mount point will be persistent across system reboots.

    # vi etc/fstab
    /dev/md1                /mnt/ebs_r5              ext4    defaults        0 0
    

    Lastly most important step is to save the RAID configuration. Run below command to make sure RAID configuration is saved.

    # mdadm --detail --scan --verbose >> /etc/mdadm.conf

    At this point you’ve successfully created RAID5 device on Linux.

  • Linux – Configure iSCSI Initiator

    This blog is not to explain what is iSCSI but rather a reference to steps which an administrator should follow for configuring iSCSI on their Linux host (CentOS in my case)

    Prerequisites

    1. Make sure Linux host has IP connectivity to storage appliance which is acting as iSCSI target
    2. Storage appliance has iSCSI configured and service is running

    Steps

    Install iSCSI initiator on Linux host. Below is the example

    # yum install iscsi-initiator-utils
    Loaded plugins: ulninfo
    Resolving Dependencies
    --> Running transaction check
    ---> Package iscsi-initiator-utils.x86_64 0:6.2.0.874-11.0.1.el7 will be installed
    --> Processing Dependency: iscsi-initiator-utils-iscsiuio >= 6.2.0.874-11.0.1.el7 for package: iscsi-initiator-utils-6.2.0.874-11.0.1.el7.x86_64
    --> Running transaction check
    ---> Package iscsi-initiator-utils-iscsiuio.x86_64 0:6.2.0.874-11.0.1.el7 will be installed
    --> Finished Dependency Resolution
    
    Dependencies Resolved
    
    =======================================================================================================================================================
     Package                                          Arch                     Version                                  Repository                    Size
    =======================================================================================================================================================
    Installing:
     iscsi-initiator-utils                            x86_64                   6.2.0.874-11.0.1.el7                     ol7_latest                   428 k
    Installing for dependencies:
     iscsi-initiator-utils-iscsiuio                   x86_64                   6.2.0.874-11.0.1.el7                     ol7_latest                    93 k
    
    Transaction Summary
    =======================================================================================================================================================
    Install  1 Package (+1 Dependent package)
    
    Total download size: 521 k
    Installed size: 2.6 M
    Is this ok [y/d/N]: y
    Downloading packages:
    (1/2): iscsi-initiator-utils-6.2.0.874-11.0.1.el7.x86_64.rpm                                                                    | 428 kB  00:00:00
    (2/2): iscsi-initiator-utils-iscsiuio-6.2.0.874-11.0.1.el7.x86_64.rpm                                                           |  93 kB  00:00:00
    -------------------------------------------------------------------------------------------------------------------------------------------------------
    Total                                                                                                                  1.1 MB/s | 521 kB  00:00:00
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : iscsi-initiator-utils-iscsiuio-6.2.0.874-11.0.1.el7.x86_64                                                                          1/2
      Installing : iscsi-initiator-utils-6.2.0.874-11.0.1.el7.x86_64                                                                                   2/2
      Verifying  : iscsi-initiator-utils-6.2.0.874-11.0.1.el7.x86_64                                                                                   1/2
      Verifying  : iscsi-initiator-utils-iscsiuio-6.2.0.874-11.0.1.el7.x86_64                                                                          2/2
    
    Installed:
      iscsi-initiator-utils.x86_64 0:6.2.0.874-11.0.1.el7
    
    Dependency Installed:
      iscsi-initiator-utils-iscsiuio.x86_64 0:6.2.0.874-11.0.1.el7
    
    Complete!

    Once iSCSI package is installed then edit the iSCSI configuration file and enable node.startup = automatic. You will need to find node.startup in the config file and remove the # from start of the line. This will make sure that iSCSI is logging to target automatically on startup

    vi /etc/iscsi/iscsid.conf
    
    node.startup = automatic

    Now configure the iSCSI service to start automatically. Run below command

    # systemctl enable iscsid
    Created symlink from /etc/systemd/system/multi-user.target.wants/iscsid.service to /usr/lib/systemd/system/iscsid.service.
    

    Start iSCSI service

    # systemctl start iscsid

    Now at this point you’ve iSCSI enabled on your Linux server. If you want to view iSCSI initiator name of your server then run below command. Note that in most cases iSCSI initiator name will reflect into logged in initiators on your storage appliance in some cases you’ll need to provide the initiator name.

    # cat /etc/iscsi/initiatorname.iscsi
    InitiatorName=iqn.1988-12.com.oracle:b0ed4f9c9b9d

    Now let’s discover iSCSI target nodes using your storage system iSCSI IP address.

    # iscsiadm -m discovery -t st -p 172.16.1.11
    172.16.1.11:3260,2 iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.a2
    172.16.1.12:3260,1 iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.b2

    You can run below commands to list discovered iSCSI nodes

    # iscsiadm -m node
    172.16.1.11:3260,2 iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.a2
    172.16.1.12:3260,1 iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.b2
    
    or 
    
    # ls /var/lib/iscsi/send_targets
    172.16.1.11,3260
    
    # ls /var/lib/iscsi/nodes
    iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.a2
    iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.b2
    

    Once iSCSI nodes are discovered you can run below command to login into iSCSI target

    # iscsiadm -m node --targetname "iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.a2" --portal "172.16.1.11:3260" --login
    Logging in to [iface: default, target: iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.a2, portal: 172.16.1.11,3260] (multiple)
    Login to [iface: default, target: iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.a2, portal: 172.16.1.11,3260] successful.
    
    # iscsiadm -m node --targetname "iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.b2" --portal "172.16.1.12:3260" --login
    Logging in to [iface: default, target: iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.b2, portal: 172.16.1.12,3260] (multiple)
    Login to [iface: default, target: iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.b2, portal: 172.16.1.12,3260] successful.

    At this stage you’ve Linux host configured as iSCSI initiator and logged in successfully to target storage. Now you can ask storage admin to create LUNs and assign to Linux host.

    Once LUNs are assigned to Linux host you can run below command to scan new devices

    # iscsiadm -m session --rescan
    Rescanning session [sid: 1, target: iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.a2, portal: 172.16.1.11,3260]
    Rescanning session [sid: 2, target: iqn.1992-04.com.emc:cx.asfnsdbgfkdjfgdk.b2, portal: 172.16.1.12,3260]

    You can view new devices using fdisk -l or multipath -l command

  • Ansible Master – Enabling SSH Key Based Authentication

    Ansible Master – Enabling SSH Key Based Authentication

    This section seems pretty straight-forward but is the must for all the Ansible deployments.

    Follow below steps to get through the password maze in Ansible environments

    Firstly we will need to generate the SSH authentication keys. This needs to be done on the server from which you want to login to other hosts. In my case it’s Ansible master server.

    Generate your key – Run the ssh-keygen command (as below). By default system will create and store the SSH key into /root/.ssh/id_rsa, which you can change. Passphrase is optional and you can leave it blank.

    Note that if you already have generated the SSH key you have option to overwrite the same, but make sure that earlier key is not used anywhere for authentication. Below example shows option to replace existing SSH keys

    [root@ansible-master ~]# ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/root/.ssh/id_rsa):
    /root/.ssh/id_rsa already exists.
    Overwrite (y/n)? y
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /root/.ssh/id_rsa.
    Your public key has been saved in /root/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:D52Rvc2F7JMlbikpj7G96Ys3bSLRUz4tNmsfNP4E2Vg root@ansible-master
    The key's randomart image is:
    +---[RSA 2048]----+
    |                 |
    |           o . . |
    |          o . + E|
    |         . o B.@ |
    |        S =.+o&+.|
    |         o.BooOoo|
    |          +.o+ B.|
    |          ..+o=.o|
    |          .+=* .o|
    +----[SHA256]-----+
    

    If you want to use existing keys then you can simply read the existing key which is saved in the file. Below is the example of the reading existing public key

    [root@ansible-master ~]# cat /root/.ssh/id_rsa.pub
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDoN5+wFiV3Nold4Y7KDGkvIGBqulvdDxDm3qPj7SGsHsnEZKKxbQtO2QJNDJW2tXhLLDxY7vnyQ3xiL0bXbUTkeHHANFY7yZnMH4LH1k51yAkgDdVzKYUdvVJ81qRmYaJUJnLCsKvZMFmg7/KzecuA1QU8WVDLCH02HiRsmqVPaykcR2EOKCgX7i92Q/khZycR66GvoKcVwU9LuDLlADQt9GTaFDFiXPITNayvXkWvL7bwe9arqMCJzmEpvveglJI+vLvh5793yxrszTScTuMpjvpp4Nz5Tk0NSvQqo73yiHAsFF6M7l2hnVskyj3cAOL1dzxmopC/E1qd3DrWSOX root@ansible-master
    

    Once you have generated the SSH key next step is to add the key into target system.

    For copying the SSH keys into target system simply follow below process.

    [root@ansible-master ~]# ssh-copy-id root@192.168.1.101
    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    The authenticity of host '192.168.1.101 (192.168.1.101)' can't be established.
    ECDSA key fingerprint is SHA256:qnOPcE09JqKALwLLaL+SqNMy2oubvhF/EevGCcK9S9A.
    ECDSA key fingerprint is MD5:4d:65:b7:e0:e8:09:41:a8:f9:4c:2d:b6:47:55:b2:09.
    Are you sure you want to continue connecting (yes/no)? yes
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    root@192.168.1.101's password:
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh 'root@192.168.1.101'"
    and check to make sure that only the key(s) you wanted were added.
    

    You’ll notice in the command output that this process has added the key into the target system. Note that 192.168.1.101 in above example is target system in which I wanted Ansible master to login without username and password.

    Once the SSH keys are added into the target system now you can try SSH into the target system and it won’t ask for password anymore.

    [root@ansible-master ~]# ssh root@192.168.1.101
    Last login: Tue Nov 26 09:01:16 2019 from gateway
    [root@target-system ~]#
    

    Hope this saves time for many of us.