Jump to content
Welcome to our new Citrix community!
  • How to speed up NetScaler Baseconfig with Terraform Modules


    Konstantinos Kaltsas
    • Validation Status: Validated
      Summary: How to speed up NetScaler Baseconfig with Terraform modules and NetScaler Automation Toolkit
      Has Video?: No

    How to speed up NetScaler Baseconfig with Terraform modules

    Submitted May 26, 2023

    Author: Arne Marien, Lead Consultant, Provectus Technologies GmbH

     

    At Provectus Technologies, we offer a NetScaler as a Service model that is fundamentally based on the GitOps concept.  To make the service efficient, scalable and to reduce errors, the NetScaler configurations are fully managed through Terraform. To be able to maintain the Terraform code for such a growing environment, we developed some Terraform modules for different use cases.

     

    Using Terraform modules for NetScaler configuration can provide several benefits:

     

    Reusability

    Terraform modules can be reused across different projects, environments, and teams. By creating reusable modules for NetScaler configurations, you can save time and effort by avoiding the need to recreate configurations from scratch every time.

     

    Consistency

    Terraform modules can ensure consistency in NetScaler configurations across different environments and stages. By using the same modules for different environments, you can ensure that your NetScaler configurations are consistent, reducing the risk of errors and making it easier to stage your changes.

     

    Collaboration

    Terraform modules can help for collaboration among teams working on NetScaler configurations. By creating modules that can be easily shared and reused, teams can work together more efficiently, reducing the need for duplicative work and improving overall productivity.

    Maintainability

    Terraform modules can make it easier to maintain NetScaler configurations over time. By breaking configurations down into modules, it becomes easier to update and modify configurations as needed. This can help reduce the time and effort required to maintain NetScaler configurations.

     

    A Module can be structured in the following Terraform files:

    • main.tf
    • variables.tf
    • output.tf

     

    The main.tf contains the description of all resources that are necessary for a baseconfig. The variables.tf describes the variables that are required to create the resources. These must be passed when invoking the module. The output.tf contains the output of any resources after the execution of the module.

     

    A first example

    Baseconfig Sub-Module

    The main.tf contains the Terraform provider name and version required for the module to work and the two resources we want to add using this module.

     

    main.tf>terraform {  required_version = ">= 1.3.0"  required_providers {    citrixadc = {      source  = "citrix/citrixadc"      version = ">= 1.30.0"    }  }} resource "citrixadc_nsip" "nsip" {  for_each                    = { for ip in var.nsip : ip.ipaddress => ip }  ipaddress                   = each.value.ipaddress  netmask                     = each.value.netmask  type                        = each.value.type  mgmtaccess                  = each.value.mgmtaccess} resource "citrixadc_route" "route" {  for_each = { for route in var.route : route.network => route }  network  = each.value.network  netmask  = each.value.netmask  gateway  = each.value.gateway  depends_on = [    citrixadc_nsip.nsip  ]}

     

    The variables.tf specifies the variables required by the resources, that must be provided when the module is called. All optional attributes are provided with the optional(<type>, <default-value>) function and do not have to be provided to the module. The specification of default or optional values makes the module easier to use and more robust.

     

    variables.tf>variable "nsip" {  description = "List of NSIPs"  type = list(object({    ipaddress                   = string    netmask                     = string    type                        = optional(string, null)    mgmtaccess                  = optional(string, null)  }))} variable "route" {  description = "Adds routes"  type = list(object({    network    = string    netmask    = string    gateway    = string  }))}

    Root-Module

    To invoke the module, root module is required. This root-module contains the information of the environments and refers to all sub-modules which are required for the configuration.

     

    The main.tf of the root module specifies the provider configuration including the Terraform backend for managing the Terraform state, as well as the submodules. The source must refer to the sub-module. This can be in the same file system but can also refer to a Git repository.

     

    Note: The NetScaler credentials required for the provider should only be set for local tests in the root module itself and should never be committed to a repository. The credentials should always be set as environment variables.

    main.tf>provider "citrixadc" {  insecure_skip_verify = true  endpoint = "https://<ns-ip>"  username = "<username>"  password = "<password>"} terraform {  backend "local" {}  required_providers {    citrixadc = {      source = "citrix/citrixadc"    }  }} module "baseconfig" {  source         = "<path-to-my-module>"  nsip           = var.nsip  route          = var.route}

    The variables.tf of the root module contains the information for an environment. The structure of the variables must match the specifications from the sub-module and contain at least the required variables. All optional values do not have to be passed mandatory.

     

    variables.tf>variable "nsip" {  description = "Adds NSIPs"  type        = list(any)  default = [    {      ipaddress = "10.1.0.10"      netmask   = "255.255.255.0"type      = "SNIP"    },    {      ipaddress  = "10.2.0.10"      netmask    = "255.255.255.0"      mgmtaccess = "ENABLED"      gui        = "SECUREONLY"      type       = "SNIP"    }  ]} variable "route" {  description = "Adds routes"  type        = list(any)  default = [{    network = "172.1.0.0"    netmask = "255.255.255.0"    gateway = "10.1.0.1"  }]}

    Folder Structure

    With a growing environment and multiple modules, the directory structure is very important. A good structure may look like the following:

     

    .└── terraform    ├── environments    │   ├── dev    │   │   └── baseconfig    │   │       ├── main.tf    │   │       └── variables.tf    │   └── prod    └── modules        └── netscaler            ├── baseconfig            │   ├── main.tf            │   ├── outputs.tf            │   └── variables.tf            ├── csvserver            └── lbvserver

    Different environments such as DMZ and LAN as well as stages such as DEV and PROD can be mapped in environments. Modules contains the sub-modules such as baseconfig, which are invoked by the root-modules in environments.

     

    Module execution

    Now we have everything for our first Terraform module in a clear structure. To run Terraform now, we only have to execute the known commands in the directory of the root module. Make sure that the source path points to the baseconfig module. Otherwise, an error will occur during initialization.

     

    module "baseconfig" {  source            = "./../../../modules/netscaler/baseconfig/"  nsip              = var.nsip  route             = var.route}

    When the path is correct, the baseconfig can be executed via the commands terraform init, terraform plan, terraform apply.

     

    Module Versioning

    There are some good reasons why Terraform code should be located in a Git repository. One of them is the ability to have multiple versions of the code available. Terraform modules can grow over time, as there are maybe more requirered resources or other changes. To avoid that adjustments to modules immediately affect all environments, there is the possibility to refer to a certain version of my sub-module in the root module. This means that I can use version 1.1 with some changes in the DEV Stage, but still use version 1.0 in PROD.

    To do this, we first need to add our module to a Git repository.

     

    ~git initgit add .git commit -m "Initial commit of my module"git remote add origin "<Git repo remote URL>"git push origin main

     

    Afterwards we can set a tag to this specific version of the module.

     

    ~git tag -a v1.0 -m "Module Version 1.0"git push --follow-tags

    Now the current state of the baseconfig module is marked as version 1.0. To use exactly this version, the source in the root module must be adjusted. This differs depending on the service used. For a generic Git repository, this works like this:

     

    module "baseconfig" {  source = "git::https://example.com/network.git//modules/baseconfig?ref=tags/1.0"  nsip   = var.nsip  route  = var.route}

     

     

    What's next?

    There are more modules

    This was the first example of how Terraform modules can significantly simplify NetScaler configuration. Especially in growing environments this allows to build always the same consistent configurations. This does not only apply to base configurations. Services such as load balancing, content switching, or Gateway with Advanced Authentication can also be built as modules. Thinking even further, the underlying infrastructure, such as a NetScaler in Azure or AWS, can also be created automated and reusable via module.

     

    How to get started with NetScaler Automation Toolkit?

    1. Visit the hands-on labs for Terraform with NetScaler to get your self familiar with NetScaler Automation Toolkit.

     

    2. Setup your private lab by following NetScaler's Get Started guides for Terraform.

     

     

    3. Follow the Beginners Guide to get comfortable with common commands.

     

     

    4. Be part of the Community. Pick a common NetScaler use-case / configuration, create a Terraform template and publish it on NetScaler Community.

     

    Additional resources for NetScaler Automation Toolkit?

    Visit the following links to get more details on using Terraform with NetScaler.

    About the Author

    Arne Marien is a Consultant focusing on Application Delivery and especially on NetScaler working at Provectus Technologies GmbH . Provectus is a founder-managed IT service provider based in Munich. The business enabler has empowered Corporate and medium-sized companies to meet the requirements of digitalization, since 2001. The core approach involves cloud technologies, digital workplace, and process optimization. More than 110 experts operate under constant compliance, stability, availability & unlimited security.


    User Feedback

    Recommended Comments

    There are no comments to display.



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

×
×
  • Create New...