Iniciando os scripts via Terraform para Netscaler ADC - Parte 2
Olá Pessoal,
Conforme explicado nesse post a idéia seria iniciarmos as tratativas dos arquivos de configuração para fazer o deploy
de algum recurso em nosso Netscaler ADC.
Vale ressaltar, para quem não visualizou nosso post anterior, onde falamos como estruturar o projeto pode conferir nesse link.
Configurar LB and CS no Netscaler ADC
Lembrando que não vou explicar as funcionalidades expostas nesses scripts, por exemplo, como funciona LB(Load Balancer) ou CS(Content Switching), pois acaba ficando fora do contexto sobre o processo de automação nesse momento, porém posteriormente posso ir detalhando os recursos com as explicações de cada funcionalidade.
Para inciarmos como explicado anteriormente precisamos configurar o arquivo provider.tf. Segue o snippet:
terraform {
required_providers {
citrixadc = {
source = "citrix/citrixadc"
version = "1.35.0"
}
}
}
provider "citrixadc" {
# Configuration options
endpoint = "http://IP-or-URL-accesso-ao-Netscaler"
username = "user"
password = "pwd"
# Do not error due to non signed ADC TLS certificate
# Can skip this if ADC TLS certificate is trusted
insecure_skip_verify = true
}
Obs.: Devido a ser um ambiente de laboratório não estamos executando o acesso via https, bem como eu habilitei para fazer o
skip
. Bem como, a versão doregistry
foi a testada em laboratório e pode ser utilizado a versão mais nova se desejarem.
Na sequência precisamos definir quais serão as variáveis que serão consumidas pelo nosso scripts, ou seja, os valores/strings que devem ser inseridos em nosso arquivo de recursos. Nesse caso foi criado o arquivo variables.tf . Segue abaixo:
# Start variable based in global configuration of LB Server
variable "vip_config" {
type = map(string)
description = "Describes the friendly name (key=lbname),VIP(key=vip), port(key=port) and service type (key=servicetype) for the LB"
}
variable "lb_methods" {
type = map(string)
description = "Configure different methods of balacing in Vserver"
}
variable "monitor_config" {
type = map(string)
}
variable "backend_service_config" {
type = map(string)
description = "Describes port(key=port) and service type (key=servicetype) for the backend services"
}
variable "backend_services" {
description = "The list of backend services (ip address:port list)"
type = list(string)
}
# Start variables of all cs server configuration
variable "csvserver_name" {
type = string
description = "CS vserver name"
}
variable "csvserver_ipv46" {
type = string
description = "CS vserver ip"
}
variable "csvserver_servicetype" {
description = "CS vserver Servicetype"
}
variable "csvserver_port" {
type = number
description = "CS vserver Port"
}
variable "cspolicy1_name" {
type = string
description = "CS policy1 name"
}
variable "cspolicy1_rule" {
description = "CS Policy1 Url"
}
variable "cspolicy2_name" {
type = string
description = "CS policy2 name"
}
variable "cspolicy2_rule" {
description = "CS Policy2 Url"
}
variable "cspolicy3_name" {
type = string
description = "CS policy3 name"
}
variable "cspolicy3_rule" {
description = "CS Policy3 Url"
}
variable "cspolicy4_name" {
type = string
description = "CS policy4 name"
}
variable "cspolicy4_rule" {
description = "CS Policy4 Url"
}
variable "sslcertkey_name" {
type = string
description = "SSL CertKey Attribute"
}
variable "sslcertkey_cert" {
description = "SSL Cert Attribute"
}
variable "sslcertkey_key" {
description = "SSL Key Attribute"
}
Obs.: Lembrando que os nomes das variáveis pode ser escolhidos da forma que desejarem e não precisam seguir como meu exemplo, bem como as descrições. A obrigatoriedade é seguir conforme a variável sendo um string, number, mapeamento de string.
Após a criação das variáveis iremos agora popular os valores que cada uma delas irá ser populada em nosso Netscaler ADC. O arquivo criado seria terraform.tfvars e pode ser verificado conforme abaixo:
# General Variables
vip_config = {
vip_service = "10.1.51.1"
vip_servgroup = "10.1.51.2"
vip_csserver = "10.1.51.3"
}
lb_methods = {
main = "LEASTPACKETS"
backup = "LEASTRESPONSETIME"
}
backend_service_config = {
clttimeout = 40
backend_port = 80
}
backend_services = [
"10.0.5.1",
"10.0.6.1",
"10.0.7.1",
]
monitor_config = {
name = "tf_monitor_sip-udp"
interval_ms = 150
response_timeout_ms = 50
}
#
# CS Vserver
csvserver_name = "tf_vserver-cs-SSL"
csvserver_ipv46 = "10.1.60.1"
csvserver_port = 443
csvserver_servicetype = "SSL"
# CS Policy 1
cspolicy1_name = "pol1"
cspolicy1_rule = "HTTP.REQ.URL.SUFFIX.EQ(\"cgi\")"
# CS Policy 2
cspolicy2_name = "pol2"
cspolicy2_rule = "HTTP.REQ.URL.SUFFIX.EQ(\"asp\")"
# CS Policy 3
cspolicy3_name = "pol3"
cspolicy3_rule = "HTTP.REQ.URL.SUFFIX.EQ(\"gif\")"
# CS Policy 4
cspolicy4_name = "pol4"
cspolicy4_rule = "HTTP.REQ.URL.SUFFIX.EQ(\"jpeg\")"
# SSL CertKey
sslcertkey_name = "mykey"
sslcertkey_cert = "/nsconfig/ssl/ns-root.cert"
sslcertkey_key = "/nsconfig/ssl/ns-root.key"
Obs.: Novamente os endereços populados ficam a critério de cada estrutura, bem como as politicas que eu criei dentro do content switching.
Finalmente iremos agora consumir todos esses scripts através de nosso arquivo resources.tf que será a partir dele que será endereçado todos os outros parâmetros definidos. Segue abaixo:
# Adding monitor specific to binding in LB-Server
resource "citrixadc_lbmonitor" "generic_monitor" {
monitorname = var.monitor_config["name"]
type = "SIP-UDP"
interval = var.monitor_config["interval_ms"]
resptimeout = var.monitor_config["response_timeout_ms"]
sipmethod = "INVITE"
sipuri = "sip:sip.test"
respcode = [400]
}
# Configure Service
resource "citrixadc_service" "tf_service" {
name = "tf_service_1"
ip = "10.1.50.1"
servicetype = "HTTP"
port = 80
lbmonitor = citrixadc_lbmonitor.generic_monitor.monitorname
}
# Configure LB Server and parameters
resource "citrixadc_lbvserver" "tf_lb1" {
name = "tf_lb_vserver_1"
ipv46 = var.vip_config["vip_service"]
port = "80"
lbmethod = var.lb_methods["main"]
backuplbmethod = var.lb_methods["backup"]
servicetype = "HTTP"
persistencetype = "SOURCEIP"
tcpprofilename = "nstcp_internal_apps"
}
# Configure Binding of Service to LB Server
resource "citrixadc_lbvserver_service_binding" "tf_binding" {
name = citrixadc_lbvserver.tf_lb1.name
servicename = citrixadc_service.tf_service.name
weight = 5
}
# Configure LB Serv-Group and parameters
resource "citrixadc_lbvserver" "tf_lb2" {
name = "tf_lb_vserv_group_1"
ipv46 = var.vip_config["vip_servgroup"]
port = "80"
lbmethod = var.lb_methods["main"]
backuplbmethod = var.lb_methods["backup"]
servicetype = "HTTP"
}
# Configure Binding of Service Group
resource "citrixadc_servicegroup" "backend" {
servicegroupname = "tf_serv_group_backend"
lbvservers = [citrixadc_lbvserver.tf_lb2.name]
servicetype = "HTTP"
usip = "NO"
clttimeout = var.backend_service_config["clttimeout"]
servicegroupmembers = formatlist(
"%s:%s",
var.backend_services,
var.backend_service_config["backend_port"],
)
comment = "Inserted via Terraform"
}
# Define CS Server
resource "citrixadc_service" "tf_cs_service" {
name = "tf_cs_service_1"
ip = "10.1.50.2"
servicetype = "HTTP"
port = 80
}
resource "citrixadc_lbvserver" "tf_cs_lb1" {
name = "tf_lb_cs_vserver_1"
ipv46 = var.vip_config["vip_csserver"]
port = "80"
lbmethod = var.lb_methods["main"]
backuplbmethod = var.lb_methods["backup"]
servicetype = "HTTP"
state = "ENABLED"
}
resource "citrixadc_lbvserver_service_binding" "tf_cs_binding" {
name = citrixadc_lbvserver.tf_cs_lb1.name
servicename = citrixadc_service.tf_cs_service.name
weight = 5
}
resource "citrixadc_csvserver" "tf_csvserver" {
name = var.csvserver_name
ipv46 = var.csvserver_ipv46
port = var.csvserver_port
servicetype = var.csvserver_servicetype
state = "ENABLED"
stateupdate = "ENABLED"
}
resource "citrixadc_csaction" "csaction_html" {
name = "csaction_HTML"
targetlbvserver = citrixadc_lbvserver.tf_cs_lb1.name
}
resource "citrixadc_csaction" "csaction_image" {
name = "csaction_Image"
targetlbvserver = citrixadc_lbvserver.tf_cs_lb1.name
}
resource "citrixadc_cspolicy" "tf_cspolicy1" {
policyname = var.cspolicy1_name
rule = var.cspolicy1_rule
action = citrixadc_csaction.csaction_html.name
}
resource "citrixadc_cspolicy" "tf_cspolicy2" {
policyname = var.cspolicy2_name
rule = var.cspolicy2_rule
action = citrixadc_csaction.csaction_html.name
}
resource "citrixadc_cspolicy" "tf_cspolicy3" {
policyname = var.cspolicy3_name
rule = var.cspolicy3_rule
action = citrixadc_csaction.csaction_image.name
}
resource "citrixadc_cspolicy" "tf_cspolicy4" {
policyname = var.cspolicy4_name
rule = var.cspolicy4_rule
action = citrixadc_csaction.csaction_image.name
}
resource "citrixadc_csvserver_cspolicy_binding" "tf_bind1" {
name = citrixadc_csvserver.tf_csvserver.name
policyname = citrixadc_cspolicy.tf_cspolicy1.policyname
priority = 100
}
resource "citrixadc_csvserver_cspolicy_binding" "tf_bind2" {
name = citrixadc_csvserver.tf_csvserver.name
policyname = citrixadc_cspolicy.tf_cspolicy2.policyname
priority = 200
}
resource "citrixadc_csvserver_cspolicy_binding" "tf_bind3" {
name = citrixadc_csvserver.tf_csvserver.name
policyname = citrixadc_cspolicy.tf_cspolicy3.policyname
priority = 300
}
resource "citrixadc_csvserver_cspolicy_binding" "tf_bind4" {
name = citrixadc_csvserver.tf_csvserver.name
policyname = citrixadc_cspolicy.tf_cspolicy4.policyname
priority = 400
}
resource "citrixadc_sslcertkey" "tf_sslcertkey" {
certkey = var.sslcertkey_name
cert = var.sslcertkey_cert
key = var.sslcertkey_key
}
resource "citrixadc_sslvserver_sslcertkey_binding" "tf_binding" {
vservername = citrixadc_csvserver.tf_csvserver.name
certkeyname = citrixadc_sslcertkey.tf_sslcertkey.certkey
}
Execução do script via terminal
Após todo esse trabalho desejamos que através de um único comando possamos executar toda essa configuração rapidamente, ou seja, minimizando o tempo deploy
.
Para isso necessitamos acessar nosso projeto que foram populados todos esses arquivos e executar alguns comandos no Terraform. Os comandos abaixo são os básicos para o deploy
e posteriormente a destruição de sua configuração.
# Inicia todo o projeto compilando o pacote do register
$ terraform init
# Verifica se possivelmente existe erros na sua configuração e quais os campos estão sendo preenchidos no Netscaler ADC
$ terraform plan
# Executa a configuração no seu Netscaler ADC
$ terraform apply
Obs.: Apenas relembrando para que você consiga executar esse procedimento a sua maquina local, precisa ter acesso diretamente ao seu Netscaler ADC.
Visualização dos procedimentos
Logo abaixo eu compartilho algumas telas apenas para demonstração da execução dos comandos mencionados anteriormente.
- Terraform Init
- Terraform Plan
- Terraform Apply
Obs.: Neste último printscreen eu obtive o resultado final apenas para demonstrar sobre o status que o terrafom apresenta como tendo recursos adicionados, modificados e destruídos.
- Visualização na GUI do Netscaler ADC
Apenas um breve printscreen da tela do Netscaler ADC com os LBs configurados baseado em nosso arquivo de configuração
.
Conclusão
Acredito que ficou extenso o post devido aos arquivos de configuração, porém achei importante nesse primeiro momento para que possa demonstrar as opções que temos para executar nossa famosa automação.
Logos após nossos posts irei disponibilizar no github
todos esses arquivos para ficarem mais fácil para clonar o repositório.
Atte,
Rodrigo