Jump to content
Welcome to our new Citrix community!
  • Simplifying NetScaler administration with Terraform Modules


    Bhalchandra Chaudhari
    • Validation Status: Work In Progress
      Summary: Parent child configuration structure using Terraform modules for NetScaler configs can reduce code duplication, abstraction for application owners and easier administration.
      Has Video?: No

    For large organizations where NetScaler infrastructure is shared across many teams, and have 100s or 1000s of Apps delivered via NetScaler, maintaining NetScaler app centric configurations and the common/global configurations is big challenge and incurs maintenance overhead. Moreover, the NetScaler configurations need to be maintained for multiple environments such as dev, qa, and prod.

    Citrix ADC Terraform provider can help you to automate and manage the NetScaler configurations declaratively and, in an infrastructure-as-code fashion. Moreover, parent-child structure in Terraform can be employed to create 2 abstraction layers – the child layer containing the configurations of underlying NetScaler entities and the parent layer containing the app-centric configurations along with common NetScaler platform configurations. This approach provide multiple benefits as follows :-

    • Avoid code duplication
    • Abstracts the underlying NetScaler networking configurations
    • Easier administration, config updates and troubleshooting
    • Reduces time to release app updates
    In this article , we will see how this parent-child structure works in Terraform along with an example of ssl offloading

     

    Parent-Child Architecture using Terraform Modules

    Parent-Child terraform terminology works at each terraform directory/module levels. The parent/root directory would be always as current working directory when you calling another terraform child module in that root directory which execute that child module configuration files (can be called as child configuration module). Similar way, organizations need to deal with shared resources which could been utilized by many entities( shared resource child module) which values can be simply pass to root module to be used as reference with root module entities such as SSL vServers, services etc.

    • Modules –
      • are containers for multiple resources that are used together
      • consists of a collection of .tf files kept together in a directory.
    • Root/Parent module-
      • The main way to package and reuse resource configuration
      • Containing all require .tf files in the main working directory
    • Child modules-
      • A submodule which can be called by root or parent modules
      • Can be called multiple times within same root or different root modules
    image.jpg.303ff02ba4d5497b1a7c77d1c58a2532.jpg

     

    SSL Offloading using Terraform Modules

    Below is the SSL offloading created using terraform parent-child deployment –

    Child Modules prepared to call in root/parent module:

    • SSL certificate keypair 
    • SSL cipher group for frontend traffic
    • SSL cipher group for backend traffic
    • SSL virtual server configuration and parameters set
    • SSL load balancing services
    Parent/Root modules:
    • Application specific module e.g., example<.>com
    Below is the directory structure prepared for this deployment –

    ├───citrixadc                                  - Citrix ADC terraform provider files

    ├───example.com                            - application root/parent directory/module

    ├───modules                                   - child module main directory

    │            ├───cipher_svc                               - child (shared) module backend cipher group

    │            ├───cipher_vs                                 - child (shared) module frontend cipher group

    │            ├───lbservice                                  - child (configuration) module load balancing services

    │            ├───lbvs-ssl                                    - child (configuration) module creates SSL vServer & parameters

    │            └───sslcertkeypair                           - child module add SSL certificate keypair

    └───sslcerts                                    - SSL files (cert and key) directory

     

    Above each directory module contain its own terraform files to prepare the configuration plan and helps root module to execute the configuration depends on variable attributes/parameters values.

     

    Below structure depicts each main directory module and sub-directory (child module) with respective terraform files –

     

     

     

    ├───citrixadc

    ├───example.com

    │             provider.tf

    │             resources.tf

    │             terraform.tfvars

    │              variables.tf

    │              versions.tf

    ├───modules

    │   ├───cipher_svc

    │   │                       output.tf

    │   │                       README.md

    │   │                      resources.tf

    │   │

    │   ├───cipher_vs

    │   │                      output.tf

    │   │                      README.md

    │   │                      resources.tf

    │   │

    │   ├───lbservice

    │   │                      output.tf

    │   │                      README.md

    │   │                      resources.tf

    │   │                      variables.tf

    │   │

    │   ├───lbvs-ssl

    │   │                      output.tf

    │   │                      README.md

    │   │                      resources.tf

    │   │                      variables.tf

    │   │

    │   └───sslcertkeypair

    │                           output.tf

    │                           README.md

    │                           resources.tf

    │                           variables.tf

    └───sslcerts

                   bkclab.cer.cert

                   bkclab.cer.key

                   terracert.cert

                   terracert.key

     

    You can find the terraform files of main root module “example”  here , where the resource block of each child module being called to configure require entity for load balancing.

     

    Executing Terraform to push SSL Offloading Configs

    On running terraform init, terraform plan and terraform apply, the module creates all the require entities and binding between them as shown below.

     

    You must run terraform init to initialize all child modules:

    PS C:\Users\bhalchandrac\ssloffload\example.com> terraform init                             

    Initializing modules...

    - ciphergroupname in ..\modules\cipher_svc

    - lbvserverssl in ..\modules\lbvs-ssl

    - loadbalancingservices in ..\modules\lbservice

    - sslcertkeyname in ..\modules\sslcertkeypair

    - vsciphergroupname in ..\modules\cipher_vs

     

    Initializing the backend...

     

    Initializing provider plugins...

    - Finding latest version of citrix/citrixadc...

    - Installing citrix/citrixadc v1.23.1...

    - Installed citrix/citrixadc v1.23.1

     

     

    Run terraform apply to push all the configs to ADC as shown below:

    PS C:\Users\bhalchandrac\article\example.com> terraform apply -var-file="../secret.tfvars" 

     

    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:

      + create

    ……….

    ………

    ………

    Terraform will perform the following actions:

    Do you want to perform these actions?

      Terraform will perform the actions described above.

      Only 'yes' will be accepted to approve.

     

      Enter a value: yes

     

     module.sslcertkeyname.citrixadc_systemfile.sslkey: Creating...

    module.loadbalancingservices.citrixadc_server.tf_server["testserver12"]: Creating...

    module.sslcertkeyname.citrixadc_systemfile.sslcert: Creating...

    module.loadbalancingservices.citrixadc_server.tf_server["testserver11"]: Creating...

    module.lbvserverssl.citrixadc_lbvserver.tf_lbvserverssl: Creating...

    citrixadc_lbvserver.tf_lbvserverhttp: Creating...

    module.ciphergroupname.citrixadc_sslcipher.tf_sslcipher: Creating...

    module.vsciphergroupname.citrixadc_sslcipher.tf_sslcipher: Creating...

    module.loadbalancingservices.citrixadc_server.tf_server["testserver12"]: Creation complete after 4s [id=testserver12]

    module.sslcertkeyname.citrixadc_systemfile.sslcert: Creation complete after 5s [id=/flash/nsconfig/ssl/terracert.cert]

    module.loadbalancingservices.citrixadc_server.tf_server["testserver11"]: Creation complete after 5s [id=testserver11]

    module.loadbalancingservices.citrixadc_service.tf_service["testserver12"]: Creating...

    module.loadbalancingservices.citrixadc_service.tf_service["testserver11"]: Creating...

    module.sslcertkeyname.citrixadc_systemfile.sslkey: Creation complete after 5s [id=/flash/nsconfig/ssl/terracert.key]

    module.sslcertkeyname.citrixadc_sslcertkey.tf_certkeypair: Creating...

    module.lbvserverssl.citrixadc_lbvserver.tf_lbvserverssl: Still creating... [10s elapsed]

    citrixadc_lbvserver.tf_lbvserverhttp: Still creating... [10s elapsed]

    module.ciphergroupname.citrixadc_sslcipher.tf_sslcipher: Still creating... [10s elapsed]

    module.vsciphergroupname.citrixadc_sslcipher.tf_sslcipher: Still creating... [10s elapsed]

    module.loadbalancingservices.citrixadc_service.tf_service["testserver12"]: Creation complete after 6s [id=testserver12-18082]

    module.sslcertkeyname.citrixadc_sslcertkey.tf_certkeypair: Creation complete after 6s [id=terracert]

    citrixadc_lbvserver.tf_lbvserverhttp: Creation complete after 12s [id=example.com:80]

    module.loadbalancingservices.citrixadc_service.tf_service["testserver11"]: Creation complete after 10s [id=testserver11-18082]

    module.lbvserverssl.citrixadc_lbvserver.tf_lbvserverssl: Creation complete after 16s [id=example.com:443]

    citrixadc_lbvserver_service_binding.tf_binding["testserver12"]: Creating...

    citrixadc_lbvserver_service_binding.tf_binding["testserver11"]: Creating...

    module.lbvserverssl.citrixadc_sslvserver.tf_sslvserver: Creating...

    citrixadc_lbvserver_service_binding.tf_binding["testserver11"]: Creation complete after 3s [id=example.com:443,testserver11-18082]

    citrixadc_lbvserver_service_binding.tf_binding["testserver12"]: Creation complete after 3s [id=example.com:443,testserver12-18082]

    module.lbvserverssl.citrixadc_sslvserver.tf_sslvserver: Creation complete after 3s [id=example.com:443]

    citrixadc_sslvserver_sslcertkey_binding.cert_binding: Creating...

    module.ciphergroupname.citrixadc_sslcipher.tf_sslcipher: Still creating... [20s elapsed]

    module.vsciphergroupname.citrixadc_sslcipher.tf_sslcipher: Still creating... [20s elapsed]

    citrixadc_sslvserver_sslcertkey_binding.cert_binding: Creation complete after 3s [id=example.com:443,terracert]

    module.vsciphergroupname.citrixadc_sslcipher.tf_sslcipher: Creation complete after 22s [id=External]

    citrixadc_sslvserver_sslciphersuite_binding.tf_sslvserver_sslciphersuite_binding: Creating...

    citrixadc_sslvserver_sslciphersuite_binding.tf_sslvserver_sslciphersuite_binding: Creation complete after 1s [id=example.com:443,External]

    module.ciphergroupname.citrixadc_sslcipher.tf_sslcipher: Creation complete after 23s [id=Internal]

    citrixadc_sslservice_sslciphersuite_binding.tf_sslservice_sslcipher_binding["testserver12"]: Creating...

    citrixadc_sslservice_sslciphersuite_binding.tf_sslservice_sslcipher_binding["testserver11"]: Creating...

    citrixadc_sslservice_sslciphersuite_binding.tf_sslservice_sslcipher_binding["testserver11"]: Creation complete after 1s [id=testserver11-18082,Internal]

    citrixadc_sslservice_sslciphersuite_binding.tf_sslservice_sslcipher_binding["testserver12"]: Creation complete after 1s [id=testserver12-18082,Internal]

     

    Apply complete! Resources: 18 added, 0 changed, 0 destroyed.

     

    Outputs:

     

    lbservices = [

      "testserver11-18082",

      "testserver12-18082",

    ]

    showsvcciphergroup = "Internal"

    showvsciphergroup = "External"

     

     

    Other things to note

    The child shared modules as mentioned can be run as individual module. The output value of it can be called/referenced in root/parent module. Most of organization uses entities which are shared between multiple entity e.g. ciphergroup. During terraform destroy the shared module configuration should not get destroyed if that is shared with multiple entities, to avoid this type of false positive, run the shared child module individually and pass the value in root module.

     

     

     

     
     
     
     

    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...