cancel
Showing results for 
Search instead for 
Did you mean: 
Create Post

INFRA-AS-CODE - EXAMPLES

Level 10

Over the past 3 posts we have covered what it means, how to start and what is required to begin down the Infra-As-Code journey. Hopefully things have been making sense and you have found them to be of some use. Obviously the main goal is just bringing awareness to what is involved and to help start the discussions around this journey. In the last post I also mentioned that I had created a Vagrant lab for learning and testing out some of the tooling. If you have not checked it out, you can do so by heading over to here. This lab is great for mocking up test scenarios and learning the methodologies involved.

In this post we will take what we have covered in the previous posts and mock up an example to see how the workflow might look. And for our mock example we will be making some configuration changes to a Cisco ACI network environment using Ansible to perform the configuration changes for our desired state.

The details below is what our workflow looks like for this mock-up.

  • - Developer – Writes Ansible playbooks and submits code to Gerrit
  • - Gerrit – Git Repository and Code-Review (Both master and dev branches)
  • - Code-Reviewer – Either signs off on changes or pushes back
  • - Jenkins – CI/CD – Monitors master/dev branches on Git Repository (Gerrit)
  • - Jenkins – Initiates the workflow when a change is detected on master/dev branches

And below outlines what our mock-up example entails from a new request received.

Change request:

  • - Create a new tenant for the example environment, which will consist of some web-servers and DB-servers. The web-servers will need to communicate with the DB-servers over tcp/1433 for MS SQL.
  • - After bringing all of the respective teams together to discuss in detail on the request and identify each object which must be defined, configured and made available for this request to be successful. (Below is what was gathered based on the open discussion)
    • Tenant:
      • § Name: Example1
      • Context name(s) (VRF):
        • § Name: Example1-VRF
      • Bridge-Domains:
        • § Name: Example1-BD
        • § Subnet: 10.0.0.0/24
      • Application Network Profile
        • § Name: Example1-ANP
      • Filters:
        • § Name: Example1-web-filter
        • § Entries:
          • Name: Example1-web-filter-entry-80
            • Proto: tcp
            • Port: 80
            • Name: Example1-web-filter-entry-443
              • Proto: tcp
              • Port: 443
        • § Name: Example1-db-filter
        • § Entries:
          • Name: Example1-db-filter-entry-1433
            • Proto: tcp
            • Port: 1433
      • Contracts:
        • § Name: Example1-web-contract
          • Filters:
            • Name: Example1-web-filter
            • Subjects:
              • Name: Example1-web-contract-subject
        • § Name: Example1-db-contract
          • Filters:
            • Name: Example1-db-filter
            • Subjects:
              • Name: Example1-db-contract-subject

Open discussion:

So based on the open discussion we have come up with the above details on what is required from a Cisco ACI configuration perspective in order to deliver the request as defined. We will use the above information to begin creating our Ansible playbook to implement the new request.

Development:

We are now ready for the development phase of creating our Ansible playbook in order to deliver the environment from the request. And knowing that Gerrit is used for our version control/code repository we need to ensure that we are continually committing our changes to a new dev branch on our Ansible-ACI Git repository as we are developing our playbook.

**Note – Never make changes directly to the master branch…Always create/use a different branch to develop your changes and then merge those into master.

Now we need to pull down our Ansible-ACI Git repository to begin our development.

$mkdir -p ~/Git_Projects/Gerrit

$cd ~/Git_Projects/Gerrit

$git clone git@gerrit:29418/Ansible-ACI.git

$cd Ansible-ACI

$git checkout -b dev

We are now in our dev branch and can now begin our coding.

We now create our new Ansible playbook.

$vi playbook.yml

And as we create our playbook we can begin committing changes as we go. (Follow the steps below on every change you want to commit)

$git add playbook.yml

$git commit -sm “Added ACI Tenants, Contracts and etc.”

$git push

In the example above we used -sm as part of our git commit. The -s adds a sign-off by the user making the changes and the -m designates the message that we are adding as part of our commit. You can also just use the -s and then your editor will open for you to enter your message details.

So we end up coming up with the following playbook which we can now proceed with testing in our test environment.

---

- name: Manages Cisco ACI

  hosts: apic

  connection: local

  gather_facts: no

  vars:

    - aci_application_network_profiles:

        - name: Example1-ANP

          description: Example1 App Network Profile

          tenant: Example1

          state: present

    - aci_bridge_domains:

        - name: Example1-BD

          description: Example1 Bridge Domain

          tenant: Example1

          subnet: 10.0.0.0/24

          context: Example1-VRF

          state: present

    - aci_contexts:

        - name: Example1-VRF

          description: Example1 Context

          tenant: Example1

          state: present

    - aci_contract_subjects:

        - name: Example1-web-contract-subject

          description: Example1 Web Contract subject

          tenant: Example1

          contract: Example1-web-contract

          filters: Example1-web-filter

          state: present

        - name: Example1-db-contract-subject

          description: Example1 DB Contract Subject

          tenant: Example1

          contract: Example1-db-contract

          filters: Example1-db-filter

          state: present

    - aci_contracts:

        - name: Example1-web-contract

          description: Example1 Web Contract

          tenant: Example1

          state: present

    - aci_filter_entries:

        - name: Example1-web-filter-entry-80

          description: Example1 Web Filter Entry http

          tenant: Example1

          filter: Example1-web-filter  #defined in aci_filters

          proto: tcp

          dest_to_port: 80

          state: present

        - name: Example1-web-filter-entry-443

          description: Example1 Web Filter Entry https

          tenant: Example1

          filter: Example1-web-filter  #defined in aci_filters

          proto: tcp

          dest_to_port: 443

          state: present

        - name: Example1-db-filter-entry-1433

          description: Example1 DB Filter MS-SQL

          tenant: Example1

          filter: Example1-db-filter

          proto: tcp

          dest_to_port: 1433

          state: present

    - aci_filters:

        - name: Example1-web-filter

          description: Example1 Web Filter

          tenant: Example1

          state: present

        - name: Example1-db-filter

          description: Example1 DB Filter

          tenant: Example1

          state: present

    - aci_tenants:

        - name: Example1

          description: Example1 Tenant

          state: present

  vars_prompt:  #Prompts for below info upon execution

    - name: "aci_apic_host"

      prompt: "Enter ACI APIC host"

      private: no

      default: "127.0.0.1"

    - name: "aci_username"

      prompt: "Enter ACI username"

      private: no

    - name: "aci_password"

      prompt: "Enter ACI password"

      private: yes

  tasks:

    - name: manages aci tenant(s)

      aci_tenant:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-tenants

      with_items: aci_tenants

    - name: manages aci context(s)

      aci_context:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        tenant: "{{ item.tenant }}"

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-contexts

      with_items: aci_contexts

    - name: manages aci bridge domain(s)

      aci_bridge_domain:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        context: "{{ item.context }}"

        tenant: "{{ item.tenant }}"

        subnet: "{{ item.subnet }}"

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-bridge-domains

      with_items: aci_bridge_domains

    - name: manages aci application network profile(s)

      aci_anp:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        tenant: "{{ item.tenant }}"

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-application-network-profiles

      with_items: aci_application_network_profiles

    - name: manages aci filter(s)

      aci_filter:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        tenant: "{{ item.tenant }}"      

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-filters

      with_items: aci_filters

    - name: manages aci filter entries

      aci_filter_entry:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        tenant: "{{ item.tenant }}"

        filter: "{{ item.filter }}"

        proto: "{{ item.proto }}"

        dest_to_port: "{{ item.dest_to_port }}"

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-filter-entries

      with_items: aci_filter_entries

    - name: manages aci contract(s)

      aci_contract:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        tenant: "{{ item.tenant }}"

        scope: "{{ item.scope|default(omit) }}"

        prio: "{{ item.prio|default(omit) }}"

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-contracts

      with_items: aci_contracts

    - name: manages aci contract subject(s)

      aci_contract_subject:

        name: "{{ item.name }}"

        descr: "{{ item.description|default(omit) }}"

        tenant: "{{ item.tenant }}"

        contract: "{{ item.contract }}"

        filters: "{{ item.filters }}"

        apply_both_directions: "{{ item.apply_both_directions|default('True') }}"

        prio: "{{ item.prio|default(omit) }}"

        state: "{{ item.state }}"

        host: "{{ aci_apic_host }}"

        username: "{{ aci_username }}"

        password: "{{ aci_password }}"

      tags:

        - aci-contract-subjects

      with_items: aci_contract_subjects

Testing:

The assumption here is that we have already configured our Jenkins job to do the following as part of the workflow for our test environment:

  • - Monitor the dev branch on git@gerrit:29418/Ansible-ACI.git for changes.
  • - Trigger a backup of the existing Cisco ACI environment (Read KB on this here)
  • - Execute the playbook.yml Ansible playbook against our Cisco ACI test gear and report back on the status via email as well as what is available from our Jenkins job report. (Ensuring that our test APIC controller is specified as the host)

Now assuming that all of our testing has been successful and we have validated that the appropriate Cisco ACI changes have been implemented successfully. We are now ready to push our new configuration changes up to the master branch for code-review.

Code-Review:

We are now ready to merge our dev branch into our master branch and commit for review. Remember that you should not be the one who also signs off on code-review and the person who does should have knowledge in regards to the change being implemented. So we will assume that the above is true for this mock-up.

So we can now merge the dev branch with our master branch.

$git checkout master

$git merge dev

Now we can push our code up for review.

$git review

Now our new code changes are staged on our Gerrit server ready for someone to either sign-off on the change and merge the new changes in our master branch or push the changes back for additional information. But before we proceed with the sign-off we need to engage our peer-review phase by following the next section.

Peer-Review:

We now should re-engage the original teams and discuss the testing phase results, the actual changes to be made and ensure that there is absolutely nothing missing from the implementation. This is also a good stage to include the person who will be signing off on the change as part of the discussion. In doing so will ensure that they are fully aware of the changes being implemented and have a better understanding in order to proceed or not.

After a successful peer-review the person who is in charge of signing off on the code-review should be ready to proceed or not. So for this mock-up we will assume that all is a go and they proceed with signing off and the changes get merged into our master branch. Those changes are now ready for Jenkins to pick up and implement in production.

Implementation:

So now that all of our configurations have been defined into an Ansible playbook, all testing phases have been successful and our code-review has been signed off on we are now ready to enter the implementation phase in our production environment.

Our production Jenkins workflow should look identical to our testing phase setup so this should be an easy one to setup. The only differences here should be the ACI controller that is configured for our production environment therefore our workflow should look similar to the following.

  • - Monitor the master branch on git@gerrit:29418/Ansible-ACI.git for changes.
  • - Trigger a backup of the existing Cisco ACI environment (Read KB on this here)
  • - Execute the playbook.yml Ansible playbook against our Cisco ACI production gear and report back on the status via email as well as what is available from our Jenkins job report. (Ensuring that our production APIC controller is specified as the host)

And again assuming that our Jenkins workflow ran successfully we should be good and all changes should have been implemented successfully.

Final thoughts

I hope you found the above useful and informational on what a typical Infra-As-Code change might look like. There are some additional methodologies that you may want to implement as part of your workflow as we did with this mock-up. And one of those may be some additional automation steps and/or end-user capabilities. And we will cover some of those items in the next post which will cover next steps in our journey.

9 Comments
MVP
MVP

Good info.

Certainly a different perspective to what I have worked with.  The principles of code review and peer review as part of the process are good to see.

The only thing I didn't see was after implementation testing/validation which should be included as part of the change ticket and procedures for backing out the update.  The backup of the config prior to implementation was good to note.

Level 10

Jfrazier​ - Good catch once again I can definitely count on you and that is awesome...!!!

You are absolutely correct. I need to include the testing/validation from the team/person who submitted the change request in both phases for test and production. Maybe I assumed it was just going to work

MVP
MVP

Sometimes even after you test while in dev things are just enough different in one production instance or another that something doesn't work quite as intended.  Logging and after implementation testing/validation are the only way to be sure.....99.99% of the time.  There is always that odd bit that pops up every third blue moon on a thursday night that may get you still.

Level 20

That's pretty neat actually... or you could just use NCM out of the box with change review built in as well.  Report on it and see dashboards that show your progress.  I'm always down with the open source solution too of course.

Level 21

ecklerwr1​ I would have to agree with you on this bit.  However, we are working toward doing what mrlesmithjr​ suggests for VM's and entire infrastructures on a Hybrid Cloud Platform.  We have already been able to manually do it, now it's just a matter of the automation bits.

Level 20

Wow that sound interesting byrona.  We have recently bought VMware NSX to go with Vcloud Enterprise.  Much of the same kinds of orchestration you are referring to we can do inside the Vcloud suite... now with NSX we'll have the entire network layers also virtualized and more software defined.  Things like security contexts move with the VM's even if vmotioned across the country between datacenters.  It'll be interesting to see how vxLAN and some other things end up working with Orion and our traditional network management tools...  For the network devices though as a fairly recent convert to NCM which we used to replace kiwi it's been amazing replacing both kiwi and another tools we had to use for compliance with NCM on it's own.  NCM definitely doesn't do everything but some things it does very well I'm finding out.

Level 10

Sounds like you are heading down a good path. I have worked with NSX off and on in a production environment for the past 2 years and it is a great solution when it fits your environmental needs. Make sure to look into leveraging the API's to begin your automation and tooling. I have not used NCM in about a year or so, therefore I am not sure on the integration with NSX. NCM is a great configuration management tool but I am not sure if it ties into an automation workflow but it definitely could. Again I have not used it in quite some time. I did write a post in regards to NCM about a year ago which you can checkout here. Would love to hear back on  your progress and any lessons learned as well.

Level 14

I think you could probably get NCM to work and if not I'm sure you could get it on the list for a future release.

MVP
MVP

This is a great series, lots to digest in there