Uploading a Public Key to a VM

Obtaining Public Key First, check to see if you already have a public key for your machine: ls ~/.ssh If you don’t see an id_rsa.pub file, create a public/private key pair on the machine that will access the VM: ssh-keygen

Uploading

For the next step, you’ll need to use a machine that can access the VM – using the public key generated in the step above, SSH into the VM and run the following: scp /path/to/public_key username@server:~ mv id_rsa.pub ~/.ssh/authorized_keys

Verification

Finally, going back to the machine you want to SSH with, SSH into the VM to make sure access is working: ssh username@hostname You should be able to log into without a password.]]>

Setting up Remote State with Terraform and Azure

Create the Azure Storage Account The first step is creating a storage account that will host the state information for the entire tenant. Create the following in order:

  1. Resource group (specifically for the Storage Account)
  2. Storage Account
  3. A container/blob for the Storage Account
In terms of working with multiple projects, I personally like to use multiple storage accounts for each major project you’ll be building out. This gives a separate access key for each project.

Setting up Backend Config

First, create a file called backend.tf and populate with the following:
terraform {
    backend "azure" {}
}
Second, create a file called beconf.tfvars, and populate it with the following:
resource_group_name = “” storage_account_name = “” container_name = “” key = “” access_key = “” Once this is done, initialize the backend with the following command: terraform init -backend-config="beconf.tfvars" Verify everything is set up with the following:

Running Terraform

Once the backend configuration is set, the next step is running Terraform itself. I suggest running it alongside a tfvars file that defines environment-specific information: terraform apply -var-file="dev.tfvars"

Checking into Source Code

Now that you’re using remote state for Terraform, you don’t have to worry about checking in your state file into source code. Just in case you’re doing this on a fresh Terraform setup, add the following to your .gitignore file:
.terraform
be.tfvars



Reference
https://medium.com/@trstringer/use-azure-blob-storage-for-remote-terraform-state-5f809b95215a]]>		

Git Repo Best Practices

Forcing Pull Request Merges to master When creating a repo, it’s a good idea to keep the master branch deployable and clean at all times. A good way to do this is to not allow direct commits to the branch. In turn, if you have a CI/CD process in place, you can have more confidence that checking things into master can result in a deployment. In a system using trunk-based deployment, you may decide to automatically deploy all changes from master into production. You can do this in Github with the following steps: Go to the repo, and go to ‘Settings’. Click on ‘Branches’. Create the rule: Once this is done, if you try to commit directly to master, you’ll see the following: ]]>

Setting up WordPress in Azure with SSL for ~$8 a Month

  • Basic plan (allowing for Always on and SSL): ~$50/month
  • MySQL for Azure: ~$25
  • With this solution, you will create everything on one virtual machine, allowing for dynamic scaling as needed for the machine. This does of course come with some downside:

    • You will need to handle backing up of both the files on the server and the data in the database.

    Creating the VM

    First, create the VM and Resource Group:

    • RG name: <app>-<env>-<location>-rg
    • VM name: <app>-<env>-<location>-vm
    • Image: Ubuntu 18.04 LTS
    • VM size: B1s
    • VNet name: <app>-<env>-<location>-vnet
    • Diagnostics Storage Account: <app><env><location>vmdiag
    • Allow Inbound Port Access for HTTP, HTTPS, SSH
    • Login access through Azure Active Directory

    Once the VM is created, access the NSG and add a restriction to IP to only allow your local IP to access:

    Access VM and Install LAMP Server

    Retrieve the public IP address and SSH into the server:

    ssh <user>@<public_ip>

    Install LAMP Server:

    sudo apt update && sudo apt install lamp-server^

    To ensure the installation happened successfully, run the following commands:

    apache2 -v
    mysql -V
    php -v

    Once LAMP server is installed, verify that you can connect to HTTP using the public IP address – you should see the Apache2 Ubuntu Default Page:

     

    Set up MySQL

    Once the web server is running, the next step is configuring MySQL. Run the following command, installing the Validate Password Plugin and using “Medium” policy:

    sudo mysql_secure_installation

    When installing, use medium strength, and default yes to all options except “Disallow root login remotely?” Generate a password.
    The next step is configuring access to MySQL through external servers (such as from a VPN). This assumes you’ll be using the NSG from Azure to restrict access based on desired IP addresses.
    Run a query to allow access:

    sudo mysql -u root -p
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION; FLUSH PRIVILEGES;

    Edit MySQL configuration:

    sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

    Comment out the line that says ‘bind-address’.
    After making that change, restart MySQL:

    sudo service mysql restart

    Finally, create an NSG rule that allows for external access to port 3306:

    Once the installation is done, let’s verify that the MySQL server can be accessed. I usually use MySQL Workbench and connect to the server using the following information:

    • Hostname: public IP

    After MySQL is set up, set up any database that may be needed.
    Here, you’ll want to set up the WordPress database server, whether you are starting fresh or migrating from an old instance.
    If running into an issue with packet size, run the following command in MySQL and restart:

    sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

    The final step is creating a DB user specifically for the WordPress installation – this use would only have access to the specific database that WordPress uses. Create a user with the following:

    • Allow access to the DB used for the WordPress installation.

    Installing WordPress

    After finishing setting up the LAMP server, next is installing WordPress. Assuming you’ve downloaded the source, you can use the following:

    scp -r .\wordpress-download\ vmadmin@YOUR_SERVER_IP:~

    Now you’ll need to SSH into the server and move the files into /var/www/html:

    sudo mv -v ~/wordpress-download/* /var/www/html/

    Before doing the 5-minute install, run the following to allow for Apache to have write permissions:
    Check the group that Apache is running under:

    cat /etc/apache2/apache2.conf | grep ^Group -B 2
    cat /etc/apache2/envvars | grep GROUP
    # Give that group access
    sudo chown -R www-data:www-data /var/www/html
    sudo find /var/www/html -type d -exec chmod 755 {} \;
    sudo find /var/www/html -type f -exec chmod 644 {} \;
    

    Now perform the 5-minute install to ensure everything is working, you can access the site using the IP address to ensure everything in place.
    While doing this, make sure you can do the following:

    • Configure Apache to use .htaccess files. Change the following in apache2.conf to change AllowOverride to All:
      • <Directory /var/www/>
          Options Indexes FollowSymLinks
          AllowOverride None
          Require all granted
        </Directory>
    • Access a page outside of the home page (sudo a2enmod rewrite && sudo systemctl restart apache2)
    • Upload a media file to test uploads

    Enabling Mail (using G Suite)

    First, set up DNS to use email. For this example, we are using Google Suite for email. Add the following 5 MX records:

    • Host: @
    • Records (priority-URL)
      • 1-ASPMX.L.GOOGLE.COM.
      • 5-ALT1.ASPMX.L.GOOGLE.COM.
      • 5-ALT2.ASPMX.L.GOOGLE.COM.
      • 10-ALT3.ASPMX.L.GOOGLE.COM.
      • 10-ALT4.ASPMX.L.GOOGLE.COM.

    Then, do the following:
    https://wpforms.com/how-to-securely-send-wordpress-emails-using-gmail-smtp/

    Setting up SSL

    Once the web server can be reached and LAMP is installed, the next step is securing the site using SSL. Run the following to enable SSL, enable the SSL site, and restart Apache:

    sudo a2enmod ssl
    sudo a2ensite default-ssl
    sudo systemctl reload apache2

    Once that’s done, access the public IP using HTTPS – you should get an insecure cert warning.
    Now that we’ve determined the port is listening, let’s set up Let’s Encrypt. Using CertBot usually makes this much easier. Since in this case, we’re using Apache and Ubuntu 18.04, we just need to populate those values and run the commands provided by CertBot:

    With these commands, you’ll also need to set up DNS for the domain to use. With the public IP address, create the following:

    • create an A record with the host as @ and the IP address as the web server IP address.

    After this finishes, run the CertBot job to create the certificate. After that finishes, allow for the ability to redirect to HTTPS using the CertBot plugin.
    Reference:

    ]]>

    Server Performance Metrics: 8 You Should Be Considering

    This post was originally featured at Raygun.

    With the DevOps movement entering the spotlight, more and more developers concern themselves with the end-to-end delivery of web applications. This includes the deployment, performance, and maintenance of the application.

    As an application gains more users in a production environment, it’s increasingly critical that you understand the role of the server. To determine the health of your applications, you may find it useful to gather performance metrics for the servers running your web applications.

    All different types of web servers (like Apache, IIS, Azure, AWS, and NGINX, for example) have similar server performance metrics. Most of my experience in this realm lies in Microsoft Azure, which provides an easy-to-use interface for finding and collecting data. Working with Microsoft Azure gives the capability to host applications in either Azure App Services (PaaS), or Azure Virtual Machines (IaaS). This setup gets you a view of the different metrics for the application or server running.

    Because of all this experience I’ve had in the last few months, I’ve found what I think is eight of the most useful server performance metrics. These metrics can be divided into two categories: **app performance metrics and user experience metrics.

    Let’s start by looking at the metrics under the app performance umbrella.

    App performance metrics

    App performance metrics are specific to the speed of the web applications that are running. If you’re having issues with an application performing slowly, these metrics are a good place to start.

    Metric 1: Requests per second

    Requests per second (also called throughput) is just like it sounds—it’s the number of requests your server receives every second. This is a fundamental metric that measures the main purpose of a web server, which is receiving and processing requests. Large-scale applications can reach up to about 2,000 requests per second.

    Given enough load, any server can fall. When considering the impact, remember that requests are just that: a single request to the server. This metric doesn’t consider what’s happening in each of these requests.

    This brings us to our next metric.

    Metric 2: Data in and data out

    The next metric I suggest you look at is your data in and data out. The data in metric is the size of the request payload going to the web server. For this metric, a lower rate is better (lower meaning that small payloads being sent into the server). A high data-in measurement can indicate the application is requesting more information than it needs.

    Data out is the response payload being sent to clients. As websites have been getting larger over time, this causes an issue especially for those with slower network connections. Bloated response payloads lead to slow websites, and slow websites will dissatisfy your users. With enough slowness, these users abandon the website and move on. Google suggests pages that take three or more seconds for mobile users to load have about a 53% chance of users abandoning before load completion.

    Metric 3: Average response time

    Defined directly, the average response time (ART) is the average time the server takes to respond to all requests given to it. This metric is a strong indicator of the overall performance of the application, giving an impression of the application usability. In general, the lower this number is, the better. But there are studies showing that the ceiling limit for a user navigating through an application is around one second.

    When considering ART, remember what the acronym stands for—it’s just an average. Like all metrics determined with an average, high outliers can throw the number off completely and make the system seem slower than is. ART is most helpful when used alongside our next metric on the list.

    Metric 4: Peak response time

    Similar to the average response time, the peak response time (PRT) is the measurement of the longest responses for all requests coming through the server. This is a good indicator of performance pain points in the application.

    PRT will not only give you an idea of which portions of your applications are causing hangups; it will also help you find the root cause of these hangups. For example, if there’s a certain slow web page or a particularly slow call, this metric can give you an idea of where to look.

    Metric 5: Hardware utilization

    Next, let’s talk about overall hardware utilization. Any application or server running is limited by the resources allocated to it. Therefore, keeping track of the utilization of resources is key, primarily to determine if a resource bottleneck exists. You have three major aspects of a server to consider:

    • the processor
    • the RAM (memory)
    • the disk space and usage

    When considering these, you’re looking for what can become a bottleneck for the whole system. As any physical (or virtual!) computer running with these components will show, performance is only as strong as its weakest link. This metric can tell you what the bottleneck is and what physical component can be updated to improve performance.

    For example, you may run into issues when trying to render data from a physical hard drive. That will cause a bottleneck in the I/O interactions between gathering files and presenting them to the user. While the hard drive spins and gathers data, the other physical components do nothing. An upgrade to a solid-state drive would improve the performance of the entire application because the bottleneck will disappear.

    Metric 6: Thread count

    The next metric—the thread count of a server—tells you how many concurrent requests are happening in the server at a particular time. This metric will help you understand what the general load of a server looks like from a request level. It will also give you an idea of the load placed on the server when running multiple threads.

    A server can generally be configured with a maximum thread count allowed. By doing this, you’re setting a max limit of requests that can happen at one time. If the thread count passes this maximum value, all remaining requests will be deferred until there’s space available in the queue to process them. If these deferred requests take too long, they’ll generally time out.

    It’s worth noting that increasing the max thread count generally relies on having the appropriate resources available for use.

    User experience metrics

    Now that we’ve covered the app performance metrics, let’s discuss a few that are user experience centered. These server performance metrics can measure your users’ overall satisfaction when using your web applications.

    Metric 7: Uptime

    Although not directly related to its performance, the uptime of the server is a critical metric. Uptime is the percentage that the server is available for use. Ideally, you’re aiming for 100% uptime, and you’ll see many cases of 99.9% uptime (or more) when looking at web hosting packages. It’s not uncommon for software projects to abide by a service level agreement that dictates a particular server uptime rate.

    If uptime metrics checking isn’t something your server can provide built in, there are plenty of third-party services, such as Updown.io, that can do it for you. These services can even give you a visual depiction of their report:

    And here’s an interesting fact. Calculating the monthly allowed downtime shows

    • 99%: ~7 hours
    • 99.9%:  ~45 minutes
    • 99.999%:  30 seconds

    Metric 8: HTTP server error rate

    The HTTP server error rate is a performance metric that doesn’t directly relate to application performance, but it’s a very critical one. It returns the count of internal server errors (or HTTP 5xx codes) being returned to clients. These errors are returned from malfunctioning applications when you have an exception or other error not being handled correctly.

    A good practice is to set up an alert whenever these kinds of errors occur. Because 500 errors are almost completely preventable, you can be certain you have a robust application. Being notified of all HTTP server errors allows you to stay on top of any errors occurring. This prevents the issue of having errors build up in the application over time.

    How to measure server performance

    Measuring server performance with an Application Performance Monitoring (APM) tool like [Raygun APM](https://raygun.com/platform/apm) is the easiest and most accurate way of measuring the health of your software. APM should be, giving your team greater context and diagnostic tools into your biggest application performance questions. Discover and pinpoint the root cause of performance issues with greater speed and accuracy than traditional APM solutions.

    Keep your finger on the pulse

    These are the server performance metrics I’ve personally found to be the most valuable. If you collect and monitor this kind data on both your users’ experience and your app performance, very little will fall between the cracks.

    Did I mention any metrics that you’re not currently using? Consider trying them out. After all, metrics are your best way to keep your eye on your server performance—and, by extension, your application’s health.

    ]]>

    Upgrading Jenkins On Azure

    Jenkins Azure Marketplace to create the Jenkins instance.  This assumes you’ve already created a Jenkins virtual machine on Azure.  In addition, the initial set up should be complete.   If not, you can check out some more information within the Microsoft documentation.

    SSH into the Virtual Machine

    If you’ve been using this instance, you should be familiar with SSH forwarding and being able to access Jenkins using localhost.  If this is new, you can read this Jenkins article on the security setup for the Azure Jenkins Marketplace instance.
    Use this command in a command line interface to log in to your virtual machine:

    ssh -L 127.0.0.1:8080:localhost:8080 <username>@<domain_name>

    Replace the following:

    • Username – the server admin username created when creating the Azure VM.
    • Domain Name – the domain name to access the virtual machine.

    You’ll be asked for a password – use the password provided alongside the username when creating the virtual machine.
    After logging in you’ll see a screen like below.  This verifies you are connected to the virtual machine.
    logged into the virtual machine
    Access http://localhost:8080 and verify you can access the Jenkins interface:
    Jenkins interface via localhost

    Download Newest JAR

    After logging into the server, you’ll use the following command to download the latest version of Jenkins:

    sudo wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war

    Assuming all is successful, you should see the following
    Downloaded newest Jenkins JAR
    After downloading the .war file, copy it to the Jenkins directory:

    sudo mv jenkins.war /usr/share/jenkins/jenkins.war

    (if you need to know the location of the WAR file on the server, you can check it in Manage Jenkins -> System Information)
    And finally, with the new .war in place, restart Jenkins:

    sudo systemctl restart jenkins

    Verification of the installation is simple. Access Jenkins and check the bottom right to see the updated version number:
    Checked for latest Jenkins installation

    Reference

    Upgrade Jenkins server to a new version
    https://wiki.jenkins.io/display/JENKINS/Automated+Upgrade]]>

    Living In A DevOps World (Part 2: Implementation)

    This post was originally featured at DevOps.com.
    Part one of this article focused on some of the more behind-the-scenes benefits of an Agile DevOps approach. In part two the focus turns to some of the other traditional problems that a well-executed DevOps approach can address, and how doing so can benefit an organization in more ways than just a technical perspective.
    By way of quick review, DevOps was born out of the Lean and Agile software development methodologies when it became clear that, while those methodologies did indeed speed up the development process, a bottleneck still occurred when push came to shove and new code had to be moved to quality assurance and production environments.
    DevOps was created to more seamlessly connect the development and operations processes, making code migration, testing and promotion to production a more efficient process. To accomplish this, the DevOps approach had to find solutions for some of the issues that caused operational delays, and create new ways to organize, implement and continuously optimize the operations process.

    Overproduction/Overprocessing

    For those who have been in development and/or operations for any length of time, it quickly becomes clear that there is a multitude of operational safety checks that serve to protect a production environment. While that is vitally important, it was also clear that there had grown an “over” problem around many operational procedures, and in many cases that manifested itself in the development process. That includes overproduction, when making or requesting more than was needed from requirements and/or operations perspective to clear arbitrary operations process hurdles.
    Alternatively, overprocessing, when development and operations resources do more work (as opposed to just enough, as Lean and Agile would suggest) than required to smooth the transition of code and functions from development to operations. This created waste regarding time, resources and budgets that were not proportional to the benefits derived from following the operations process.
     

    Motion and Transportation

     
    Similarly, DevOps also sought to solve the operational problems of both motion and transportation. That is, the amount of excess work required to deliver new code to meet the operational requirements for code migration. The friction caused by such requirements slowed the motion and momentum of the development process. The same is true of transportation, or the difficulty in moving code between environments such as testing, quality assurance and production.
     
    In both cases, development and project momentum was sacrificed for what often turned out to be a series of artificial hurdles that had long since become less effective or even obsolete parts of the operations process.
     

    Correction and Inventory

     
    In most instances, all of the above resulted in the final maladies of the pre-DevOps development and operational ways. The first was the number of in-flight corrections required when timelines were squeezed, and the rush was on to get to production. Unfortunately, this went hand in hand with the ultimate problem of good code being sacrificed for expedient delivery, often resulting in inadequate functionality, system outages and, in the end, lost market opportunity and revenue.
     

    3 Keys to DevOps Success

    Any successful DevOps implementation must address three critical factors in this order: culture, organization and tools.

    Culture

    It’s critically important to connect an organization’s values to the DevOps process. Valuing quality, timeliness and organizational alignment of goals and objectives is the first step toward DevOps success. Such cultural values translate directly into a DevOps organization.
    Providing empowerment and accountability to DevOps team members helps to build ownership among the team, and trust from their customers in the rest of the organization. It also helps to provide a physical environment that fosters collaboration, teamwork and continued learning. Co-working spaces and collaboration tools such as Slack are a good start. Attending external conferences to broaden perspectives and to bring new ideas back to the team is often beneficial. From there, brown bag lunch sessions where ideas and experiences can be shared, frequent post-mortems on implementations to hone best practices, and even internal mini-conferences where several departments come together for a day to discuss DevOps practices are all effective ways to build a strong DevOps culture.

    Organization

    Any good DevOps organization is two-sided; that is it has to work from the top down and from the bottom up at the same time.
    The top-down part is in the ability to “see the system” from a macro level, allowing for process understanding and insights from a business workflow perspective. This helps to identify the pain points and bottlenecks in the current process that can be optimized through the DevOps process.
    Once that’s accomplished, the bottom-up work begins. Identifying things such as inconsistencies in code deployment environments that cause delivery issues, elimination of manual and custom built deployment processes and quarantining inefficient and poorly written code until it can be redone or eliminated are all part of optimizing the time, quality, resources and success factors for deploying production systems on schedule. It’s also important here to continually audit the current processes with an eye toward eliminating the processes that are no longer required or useful but have been kept in place out of the fear of  “breaking something we don’t understand.” If nobody understands it, then it shouldn’t be in production software.

    Automation Tools

    The final factor for DevOps success is to have the right toolset.
    Communication: Any DevOps team requires the ability to quickly and directly communicate with other team members sans meetings. For this purpose, tools such Slack (real-time chat), Skype (video chat), and Confluence (for storing persistent information) are pretty good options.
    Planning, Monitoring & Consistency: For the team’s planning needs, a tool such as Trello that can provide Kanban board functionality is worth a look. For issue tracking and monitoring of any system’s overall health, tools such as Jira and NewRelic respectively provide some good functionality. Likewise, consistency is vital in a DevOps world, and using automation to ensure that all systems are configured as desired across different environments is a crucial best practice. For this, a tool such as Ansible is worth a review.
    Integration & Deployment: For continuous integration of systems in development and as a way to tighten the feedback loop for developers to determine if the central build used for deployment to production is working as intended, the Jenkins toolset might be a good fit. And finally, when it comes making any deployment process as painless as possible, a tool such as Docker that can handle created containers for an application that includes all dependencies, reducing the complexity of deployment to multiple environments, is a solid way to go.
    The point of all of this is to create an environment—culturally, technically and physically—where DevOps can succeed, grow and thrive. Organizations that can create an effective and efficient DevOps environment have also created a competitive advantage for themselves.]]>

    Living In A DevOps World (Part 1: Recognition)

    This post was originally featured on DevOps.com.
    DevOps has evolved into a conceptual and working model for more effective software implementation. However, there are differences of opinion on the real-world value of any approach to date.  This includes the question of the best way to implement a real-world DevOps environment. This two-part article will focus on what an agile DevOps approach is meant and not meant to address.
    DevOps sits at the nexus of three essential business technology functions: software development, quality assurance and operations. A short and concise definition of DevOps proposed in 2015 seems as appropriate as any:

    DevOps is a set of practices intended to reduce the time between committing a change to a system and the change being placed into regular production while ensuring high quality.

    The definition was suggested in the book, “DevOps: A Software Architect’s Perspective,” and the authors have hit upon the essence of the practice. The key, of course, is how to put that concept into practice.
    The first step on the journey to effective DevOps is the recognition that the concept is the result of the rise of the Lean and Agile software development methodologies. Those methodologies, among other things, emphasize the following:

    • A focus on customer value.
    • The elimination of waste.
    • Reduced cycle time (accomplishing work faster, releasing faster).
    • Shared learning.
    • Avoiding batching (don’t do things until required).
    • Theory of constraints (break things up, focus on individual issues).
    • Continuous integration, testing and delivery.
    • Faster time to market.

    DevOps in Practice

    Something had to be invented to adhere to the principles above; that something was DevOps.  Over time, an effective practice should address any number of business technology pain points. The following short list of those pain points and their respective solutions should prove instructive.

    System Downtime

    System outages are inevitable as long as systems are designed, tested and implemented—even with increased automation—by imperfect beings. DevOps changes the focus from trying to create applications that never fail to designing systems that can recover quickly.  This decreases aggregate systems outage time over the life cycle of any application or system.

    Stagnation

    This was a staple of traditional systems development and is most closely associated with the waterfall methodology for systems development. After requirements were created, the development team would be locked away for weeks, months or even years before emerging with “fully” working software.  This software inevitably no longer satisfied rapidly evolving business requirements. DevOps fits hand-in-glove with the Agile practice of short windows of incremental changes instead of long release cycles, providing value to customers as quickly as possible.

    Team Conflict

    Having been borne from the cultural combination of Agile and Lean, DevOps has taken on the problem of functional silos that are often erected between development, operations and the business customers. It follows the methodological approaches of collaboration and teamwork first to understand what others know and to leverage the best of it to solve business problems more rapidly. There is also a cultural bent toward experimentation, continual learning and constant improvement. This leads to blameless post-mortems, where collaborative discussion replace finger pointing and blame.

    Knowledge Silos

    Functional silos have led to compartmentalized knowledge. If the old game was that knowledge is power, the new game in the DevOps world is that knowledge is freely exchanged as an enabler to solving business problems. DevOps addresses the problem of information being lost in translation between the development and operations functions by eliminating the functional barricades and making knowledge sharing the highest form of collaboration.

    Inefficiency

    Waiting for things to happen used to be a standard operating procedure in the pre-DevOps world. Project plans were created and managed to account for the time it takes for new code to be moved into a testing, quality or even production environment. This was a momentum killer for projects and at times a morale killer for developers waiting to see what changes they might need to make to their code.
    The combined Agile and DevOps approach rewrites the traditional approach to code migration, smoothing and eliminating wait times.  Projects can flow more seamlessly from start to finish. This also keeps business resources—testers, approvers, etc.—more engaged as a result of a constant flow of new functions and features to test and use.  There is a financial aspect to this as well. Reducing speed to market with new functionality, reducing or eliminating idle hands—be they technical or business—and delighting customers with a steady stream of enhancements and features all go directly to an organization’s top and bottom lines.
    That, after all, is in many ways what the DevOps approach is all about. All of these critical areas become the means to accomplish it. Part two of this article will focus on some more of the benefits of a DevOps approach, and how to achieve them.]]>