Privacidad basada en equipos utilizando IAM, VPC, Transit Gateway y DNS

Esta guía de aprendizaje puede incurrir en costes. Utilice Estimador de costes para generar una estimación del coste basada en el uso previsto.

Los microservicios gozan de gran popularidad porque permiten que una empresa organice sus equipos de desarrollo alrededor de los servicios que ofrecen. Este tutorial le guiará a través de los pasos de creación de infraestructura para una arquitectura de microservicios basada en IBM Cloud® Virtual Private Cloud (VPC). En esta arquitectura, las VPC están conectadas entre ellas utilizando IBM Cloud® Transit Gateway. Se accede a un conjunto de microservicios compartidos a través de nombres de host registrados en el IBM Cloud® DNS Services. Cada VPC está gestionada por un equipo independiente aislado por IBM Cloud® Identity and Access Management. Opcionalmente, se puede utilizar un IBM Cloud® Load Balancer para escalar el microservicio compartido.

Objetivos

  • Aprender a aislar una infraestructura utilizando IAM y grupos de recursos
  • Crear las VPC y los recursos asociados como por ejemplo subredes, ACL de red, grupos de seguridad o instancias.
  • Dirígete a los microservicios mediante la resolución de nombres DNS utilizando DNS Services.
  • Conectar las VPC vía Transit Gateway.
  • Configurar de forma transparente un Load Balancer para una aplicación.

Arquitectura abstracta:

de arquitectura del

En el diagrama anterior, el usuario final accede a las aplicaciones. Las aplicaciones aprovechan microservicios compartidos. La empresa tiene equipos DevOps separados que poseen application1, application2 y shared. Un equipo de red se dedica a la conectividad y seguridad de la red. Los equipos de DevOps gestionan instancias de servicio virtual (VSI) que se utilizan para implementar los servicios que crean y a los que dan soporte.

Arquitectura específica

La arquitectura siguiente implementa los requisitos de conectividad y aislamiento definidos por la empresa. Observe que application1, shared y application2 son VPC. La zona única y la subred de cada VPC se pueden ampliar a una implementación multizona más detallada con el tiempo.

Arquitectura de la guía de aprendizaje
Arquitectura de la guía de aprendizaje

Antes de empezar

Esta guía de aprendizaje requiere:

  • CLI de IBM Cloud con estos plugins:
    • Transit Gateway (tg)
    • IBM Cloud VPC (vpc-infrastructure)
    • DNS Services (dns)
  • git para clonar el repositorio de código fuente.
  • terraform para ejecutar los comandos de Terraform.

Encontrará instrucciones para descargar e instalar estas herramientas para su entorno operativo en la guía Introducción a los tutoriales de soluciones.

Además:

  • Compruebe los permisos de usuario. Asegúrese de que la cuenta de usuario tiene permisos suficientes para crear y gestionar recursos de VPC, crear un IBM Cloud® Transit Gateway y crear servicios de IBM Cloud® Transit Gateway. Consulte la lista de permisos necesarios para VPC. También necesitará la capacidad de crear grupos de recursos y recursos de IAM como grupos de acceso, políticas, ID de servicio, ...
  • Necesita una clave SSH para conectarse a los servidores virtuales. Si no tiene una clave SSH, consulte las instrucciones para crear una clave para VPC.

Planifique el entorno de IAM (Identity and Access Management)

El equipo admin concederá permisos a los demás equipos para administrar sus recursos tanto como sea posible. El equipo admin gestionará los usuarios y controlará el acceso, pero no creará ni destruirá los recursos que se muestran en el diagrama de la arquitectura.

Editor, Operador, Visor y Gestor son roles de acceso de IAM. Cada servicio define el significado exacto de los roles y las acciones asociadas.

Equipos:

  • Admin: define la estructura de la cuenta, como por ejemplo grupos de recursos, grupos de acceso, usuarios, roles.
  • Red: cree recursos de red como DNS Services, servicio Transit Gateway, VPC y subredes.
  • Shared: crea VSI y dispositivos de bloque en la VPC compartida. Crea registros de DNS para los servicios compartidos.
  • Application1: crea VSI y dispositivos de bloque en la VPC de application1
  • Application2: crea VSI y dispositivos de bloque en la VPC de application2.

IAM Conceptual

Equipo network

Se ha implementado un modelo de propiedad de equipo conceptual. El equipo de red administra todos los recursos de red y, por lo tanto, la mayor parte de lo que se muestra en el diagrama.

Arquitectura centrada en el equipo de red
Arquitectura centrada en el equipo de red

Equipo shared

El equipo shared crea la VSI en su VPC aislada. Además, el equipo necesita escribir registros en el servicio DNS, ya que las direcciones IP de las VSI se determinan en el momento de la creación. Se requiere acceso de operador a la VPC, a las subredes y a los grupos de seguridad para crear una VSI.

Arquitectura centrada en el equipo compartido
Arquitectura centrada en el equipo compartido

Los equipos de aplicación necesitan el mismo acceso que el equipo compartido, excepto el acceso de gestor a DNS Services.

Acceso del equipo Application:

Arquitectura centrada en el equipo de aplicaciones
Arquitectura centrada en el equipo de aplicaciones

Arquitectura de IAM

Si conoce a fondo los grupos de recursos y los grupos de acceso de IAM, puede echar un vistazo rápido a esta sección y pasar a iniciar los pasos para crear los recursos.

Grupos de acceso

Se creará un grupo de acceso para cada equipo. Se añaden políticas de acceso a los grupos de acceso y, a continuación, se añaden usuarios (miembros del equipo) al grupo de acceso para otorgarles acceso.

La instancia de servicio de Transit Gateway la gestiona exclusivamente el equipo network. Se requiere acceso de Editor para poder crearla. El acceso del gestor a la instancia creada permite que las VPC estén conectadas al Transit Gateway.

En este ejemplo, se creará una única zona DNS, widgets.example.com y se permitirá el acceso a la zona DNS a todas las VPC. La instancia de servicio DNS la crea el equipo network (rol de Editor) y para permitir las zonas se requiere el rol de Gestor. La resolución de DNS en tiempo de ejecución en una instancia de una VPC no requiere acceso de IAM. El equipo compartido necesita listar las instancias de DNS (rol de visor) y añadir un registro A o CNAME (rol de gestor).

El Servicio de infraestructura (IS) de VPC consta de unos 15 tipos de servicio distintos. Algunas sólo conciernen al equipo de red, como las ACL (listas de control de acceso) de red. Otros sólo conciernen a los equipos de microservicios, como las instancias VSI. Pero algunos son editados por el equipo de red y operados por el equipo de microservicios, como las subredes. El equipo de red creará la subred y un equipo de microservicio creará una instancia en una subred. En la tabla siguiente se especifica, para cada grupo de acceso, los tipos de servicio IS de VPC, Transit Gateway y DNS para los fines de esta guía de aprendizaje. El contenido de la tabla son los roles necesarios.

Roles necesarios asignados a equipos en función de sus responsabilidades
Servicio red shared Aplicación
Transit Gateway Editor, Gestor
DNS Editor, Gestor Visor, Gestor
IS: ACL de red Editor
IS: Instancia, volumen, IP flotante, clave SSH, imagen, equilibrador de carga Editor Editor
IS: VPC, Subnet, Grupo de seguridad Editor Operador Operador

Grupos de recursos

El equipo shared y el equipo network están ahora bien separados. Pero, ¿cómo se aísla Application1 de Shared y de Application2? Son Editor para los mismos tipos de servicios.

Aquí es donde los grupos de recursos pueden ayudar. Cada instancia de servicio (es decir, recurso) tiene un atributo de grupo de recursos que se inicializa al crearse y no puede modificarse. En otras palabras, cada recurso está en un grupo de recursos.

Diagrama Grupo de recursos:

Diagrama Grupo de recursos
Diagrama Grupo de recursos

A cada equipo de microservicio se le permitirá el acceso en el grupo de recursos correspondiente. El equipo de la red tendrá acceso a todos estos grupos de recursos.

El grupo de recursos de la red contiene Transit Gateway y el servicio DNS. El equipo de la red tiene acceso a estos recursos. El equipo compartido tendrá acceso de administrador al servicio DNS. El equipo compartido necesita escribir las entradas de DNS para los servicios compartidos.

Más adelante en el tutorial, una vez creados todos los recursos, puede ser informativo abrir la lista de Recursos en la consola IBM Cloud. Es posible filtrar el grupo de recursos.

Crear un entorno de trabajo local

Todas las operaciones se realizarán en un bash shell y haciendo uso de terraform y ibmcloud comando. Encontrará instrucciones para descargar e instalar estas herramientas para su entorno operativo en la guía Introducción a los tutoriales de soluciones.

  1. Git clone el siguiente repositorio:

    git clone https://github.com/IBM-Cloud/vpc-tg-dns-iam
    cd vpc-tg-dns-iam
    

    Verifique que hay un directorio para cada equipo (omitiendo application2 de momento):

    • admin/
    • red/
    • shared/
    • application1/
  2. Cree el archivo terraform.tfvars :

    cp terraform.tfvars.template terraform.tfvars
    

    A continuación, edite terraform.tfvars para establecer estas variables:

    • ssh_key_name- es necesario especificar una clave SSH existente en la ibm_region como se especifica en la sección Antes de empezar.
    • ibm_region- sustituir el valor por defecto, us-south, si es necesario. El mandato de CLI ibmcloud regions mostrará todas las regiones posibles.
    • basename- sustituye el valor por defecto, widget0, por un nombre de 7 caracteres o menos, si es necesario. La mayoría de los recursos que se creen utilizarán este prefijo de nombre.
    • No elimine el comentario de transit_gateway o shared_lb en este momento.
  3. Sólo para usuarios de Windows: Si git no crea el enlace simbólico en su ordenador Windows es necesario copiar el contenido de los archivos a las carpetas del equipo:

    cp variables.tf terraform.tfvars admin
    cp variables.tf terraform.tfvars network
    cp variables.tf terraform.tfvars shared
    cp variables.tf terraform.tfvars application1
    

Una nota sobre cómo convertirse en miembro del equipo

Cada uno de los grupos de acceso de un equipo se puede llenar con usuarios. Pero en lugar de crear usuarios, este tutorial creará un ID de servicio en el grupo de acceso de cada equipo. El usuario es el administrador y se convertirá en un miembro de los distintos grupos de acceso utilizando la clave de la API para el ID de servicio del equipo. Los nombres de ID de servicio son ${basename}-x donde x es network, shared, application1 y application2. Más adelante, llenará un archivo local.env en el directorio de cada equipo con un contenido parecido al siguiente:

export TF_VAR_ibmcloud_api_key=0thisIsNotARealKeyALX0vkLNSUFC7rMLEWYpVtyZaS9

En cada paso cuando usted cd en un directorio de equipo se le recordará a ejecutar: source local.env

Se utilizará Terraform para crear los recursos. Abra admin/main.tf y fíjese en la cláusula provider ibm y la referencia a la ibmcloud_api_key inicializada desde la variable de entorno:

provider ibm {
 ibmcloud_api_key = var.ibmcloud_api_key # initialized with the TF_VAR_ibmcloud_api_key
}

Si necesita utilizar la IBM Cloud CLI como miembro del equipo:

ibmcloud login --apikey $TF_VAR_ibmcloud_api_key

Crear los recursos habilitados para IAM (Equipo Administración)

El equipo admin necesitará tener acceso de administrador a los recursos habilitados para IAM en la cuenta utilizada en esta guía de aprendizaje. Consulte ¿Cómo asigno a un usuario acceso completo como administrador de la cuenta?. El equipo de administración será responsable de crear los recursos de IAM. Las instrucciones siguientes utilizan el mandato ibmcloud iam api-key-create para crear una clave de API para el administrador. Terraform utilizará la clave de la api para realizar tareas en su nombre.

Las claves PI son lo mismo que una contraseña para su cuenta. Mantenga las claves de la api seguras.

  1. Inicialice y verifique la variable de shell basename. Verifique que coincide con el nombre base del archivo terraform.tfvars:

    eval $(grep basename terraform.tfvars | sed -e 's/  *//g' -e 's/#.*//')
    echo basename=$basename
    
  2. Cambie de directorio, genere y especifique su clave de API personal en local.env. Cuando se invoque terraform, utilizará su identidad. Terraform será el administrador:

    cd admin
    echo export TF_VAR_ibmcloud_api_key=$(ibmcloud iam api-key-create $basename-admin --output json | jq .apikey) > local.env
    cat local.env
    source local.env
    
  3. La aplicación del archivo de configuración main.tf Terraform crea los siguientes recursos:

    • Grupos de recursos para cada equipo
    • Grupos de acceso para cada equipo y un ID de servicio en cada grupo de acceso
    • Políticas de grupo de acceso para los grupos de recursos
    • Políticas de grupo de acceso para los recursos
    terraform init
    terraform apply
    
  4. Verifique que se hayan creado los recursos:

    ibmcloud resource groups | grep $basename
    
    ibmcloud iam access-groups | grep $basename
    
    ibmcloud iam service-ids | grep $basename
    
    ibmcloud iam access-group-policies $basename-network
    

    La salida se parecerá a la siguiente:

    $ ibmcloud resource groups | grep $basename
    widget0-application2   36b06a303f224f28ad42aebbb491cc44   false           ACTIVE
    widget0-shared         91518c45e47a427fa4f63edb58e4f227   false           ACTIVE
    widget0-network        bf6e75cd71854576a31056abced2abf0   false           ACTIVE
    widget0-application1   db2f3dc8aacf4a6aa2d2fa07e795cb57   false           ACTIVE
    $ ibmcloud iam access-groups | grep $basename
    widget0-application1   AccessGroupId-26b7ef37-78db-4a2c-a2af-7f6591e73c15   application1 administrators
    widget0-application2   AccessGroupId-8afdec20-f760-4a15-8f3e-296d81818028   application2 administrators
    widget0-network        AccessGroupId-d50b129d-9adc-4fc4-b297-487b3f938ec5   network administrators
    widget0-shared         AccessGroupId-30d73f44-5602-47a7-846e-e6480c9dceff   shared administrators
    $ ibmcloud iam service-ids | grep $basename
    ServiceId-5e919b97-380c-4343-a337-3901cafbd956   widget0-application2                                                                                                       2020-07-15T21:25+0000   2020-07-15T22:03+0000   application 2 service id                                                                                                                                              false
    ServiceId-307df062-f4b7-45f8-8ec8-94ad1ed61730   widget0-network                                                                                                            2020-07-15T21:49+0000   2020-07-15T22:03+0000   network service id                                                                                                                                                    false
    $ ibmcloud iam access-group-policies $basename-network
    Retrieving all policies of access group widget0-network under account 8675309 as jenny@example.com
    OK
    
    Policy ID:   00ceb354-7360-4ad5-9fda-5c03e462c5c0
    Roles:       Editor
    Resources:
                 Resource Group ID     91518c45e47a427fa4f63edb58e4f227
                 Resource Group Name   widget0-shared
                 Service Name          is
                 flowLogCollectorId    *
                 Memo                  Policy applies to the resource(s) within the resource group
    
    Policy ID:   115ebe9f-eea0-4308-9e7f-bb887d64426b
    Roles:       Editor
    Resources:
                 Resource Group ID     db2f3dc8aacf4a6aa2d2fa07e795cb57
                 Resource Group Name   widget0-application1
                 Service Name          is
                 vpnGatewayId          *
                 Memo                  Policy applies to the resource(s) within the resource group
    ...
    
  5. Si lo desea, vaya a la cuenta Grupos de recursos y busque los grupos de recursos.

  6. Si lo desea, vaya a Grupos de acceso para ver los grupos de acceso, haga clic en un grupo de acceso y, a continuación, haga clic en el panel ID de servicio de la parte superior para ver el ID de servicio creado.

Crear las VPC y los DNS (equipo Red)

El equipo de red creará los recursos de red de acuerdo con la arquitectura, asegurándose de que se satisfacen los objetivos de conectividad y de que los equipos están aislados en su VPC. No desean controlar los detalles de las instancias de VPC. Es probable que el número de aplicaciones, el tamaño de los equipos, los registros DNS para microservicios, etc. estén en constante cambio y no sean una preocupación para el equipo de red.

El equipo admin les ha proporcionado la cantidad correcta de permisos para crear los recursos de IS de VPC, el servicio DNS Services y el servicio Transit Gateway.

  1. Cambia de directorio, genera una clave API en el local.env y hazte miembro del grupo de acceso a la red:

    team=network
    cd ../$team
    echo export TF_VAR_ibmcloud_api_key=$(ibmcloud iam service-api-key-create $team $basename-$team --output json | jq .apikey) > local.env
    cat local.env
    source local.env
    
  2. Opcionalmente, abra el archivo variables_network.tf y fíjese en la especificación del bloque CIDR y la disposición de la zona. En el siguiente fragmento, observe que shared y application1 se especifican sin direcciones IP superpuestas:

    variable network_architecture {
      default = {
        shared = {
          cidr        = "10.0.0.0/16"
          cidr_remote = "10.0.0.0/8"
          zones = {
            z1 = {
              zone_id = "1",
              cidr    = "10.0.0.0/24",
            }
            z2 = {
              zone_id = "2",
              cidr    = "10.0.1.0/24",
        ...
        application1 = {
          cidr        = "10.1.0.0/16"
          cidr_remote = "0.0.0.0"
          zones = {
            z1 = {
              zone_id = "1",
              cidr    = "10.1.0.0/24",
            }
            z2 = {
              zone_id = "2",
              cidr    = "10.1.1.0/24",
         ...
    

    Transit Gateway tendrá una conexión con cada VPC y direcciona el tráfico en función de los rangos de CIDR. Por lo tanto, evitar solapamientos garantizará el éxito.

  3. Cree los recursos:

    terraform init
    terraform apply
    
  4. Liste los recursos de VPC

    Los recursos de VPC creados se resumen en salida del mandato subnets, como se muestra a continuación, editado para mayor brevedad. Observe las tres VPC, los bloques CIDR no superpuestos y la pertenencia a grupos de recursos:

    ibmcloud target -r $(grep ibm_region terraform.tfvars | sed -e 's/  *//g' -e 's/#.*//' -e 's/.*=//' -e 's/"//g')
    ibmcloud is subnets --all-resource-groups | grep $basename
    

    La salida se parecerá a la siguiente:

    $ ibmcloud is subnets --all-resource-groups | grep $basename
    widget0-shared-z1           available   10.0.0.0/24    widget0-shared           us-south-1   widget0-shared
    widget0-shared-z2           available   10.0.1.0/24    widget0-shared           us-south-2   widget0-shared
    widget0-shared-z3           available   10.0.2.0/24    widget0-shared           us-south-3   widget0-shared
    widget0-application1-z1     available   10.1.0.0/24    widget0-application1     us-south-1   widget0-application1
    widget0-application1-z2     available   10.1.1.0/24    widget0-application1     us-south-2   widget0-application1
    widget0-application1-z3     available   10.1.2.0/24    widget0-application1     us-south-3   widget0-application1
    widget0-application2-z1     available   10.2.0.0/24    widget0-application2     us-south-1   widget0-application2
    widget0-application2-z2     available   10.2.1.0/24    widget0-application2     us-south-2   widget0-application2
    widget0-application2-z3     available   10.2.2.0/24    widget0-application2     us-south-3   widget0-application2
    
  5. Opcionalmente, navegue a las Virtual Private Clouds y encuentre las VPCs, subredes y todos los demás recursos creados anteriormente.

  6. Opcionalmente, investiga la configuración de Terraform en main.tf para entender la inicialización DNS Services. La instancia y la zona de DNS Services se han creado con el fragmento de código de terraform siguiente:

    resource "ibm_resource_instance" "dns" {
      name              = "${var.basename}-dns"
      resource_group_id = data.ibm_resource_group.shared.id
      location          = "global"
      service           = "dns-svcs"
      plan              = "standard-dns"
    }
    
    resource "ibm_dns_zone" "widgets_example_com" {
      name        = "widgets.example.com"
      instance_id = ibm_resource_instance.dns.guid
      description = "this is a description"
      label       = "this-is-a-label"
    }
    

    Después, se añade la zona a una VPC como una red permitida:

    resource "ibm_dns_permitted_network" "shared" {
      instance_id = ibm_resource_instance.dns.guid
      zone_id     = ibm_dns_zone.widgets_example_com.zone_id
      vpc_crn     = module.vpc_shared.vpc.crn
      type        = "vpc"
    }
    
    
  7. Liste la configuración de DNS. Se ha creado una instancia de DNS Services. Se ha creado la zona widgets.example.com. Por último, se añadió la zona a todas las VPC.

    ibmcloud dns instances
    
    ibmcloud dns zones -i $basename-dns
    
    zone_id=$(ibmcloud dns zones -i $basename-dns --output json | jq -r '.[] | .id')
    ibmcloud dns permitted-networks $zone_id -i $basename-dns
    

    El resultado será parecido a éste:

    $ ibmcloud dns instances
    Retrieving service instances for service 'dns-svcs' ...
    OK
    Name          ID                                     Location   State    Service Name   
    widget0-dns   3b0d5546-5999-4c7e-a757-f5fd21dd44ed   global     active   dns-svcs   
    $ ibmcloud dns zones -i $basename-dns
    Listing zones for service instance 'widget0-dns' ...
    OK
    ID                                               Name                  Status   
    5a1a2295-1c38-49dd-9809-aaaf5a127e79c1b          widgets.example.com   ACTIVE   
    $ zone_id=$(ibmcloud dns zones -i $basename-dns --output json | jq -r '.[] | .id')
    $ ibmcloud dns permitted-networks $zone_id -i $basename-dns
    Listing permitted networks for zone '5a1a2295-1c38-49dd-9809-f5a127e79c1b' ...
    OK
    Name                   ID                                          Type   VPC_CRN                                                                                                               State   
    widget0-shared         r006-353208ab-4e95-46fb-934b-b5566cde8975   vpc    crn:v1:bluemix:public:is:us-south:a/713c783d9a507a53135fe6793c37cc74::vpc:r006-353208ab-4e95-46fb-934b-b5566cde8975   ACTIVE   
    widget0-application1   r006-287258c6-2eb3-4908-b326-6f03c3e47aa6   vpc    crn:v1:bluemix:public:is:us-south:a/713c783d9a507a53135fe6793c37cc74::vpc:r006-287258c6-2eb3-4908-b326-6f03c3e47aa6   ACTIVE   
    widget0-application2   r006-fa51e99e-bd93-4451-a4eb-76eed9939d3c   vpc    crn:v1:bluemix:public:is:us-south:a/713c783d9a507a53135fe6793c37cc74::vpc:r006-fa51e99e-bd93-4451-a4eb-76eed9939d3c   ACTIVE   
    
  8. Opcionalmente, navegue hasta la lista de recursos y busque el DNS Services, haga clic en él e investíguelo.

Crear el microservicio compartido y el registro DNS asociado (Equipo compartido)

  1. Cambia de directorio, genera una clave API en el local.env y hazte miembro del grupo de acceso compartido:

    team=shared
    cd ../$team
    echo export TF_VAR_ibmcloud_api_key=$(ibmcloud iam service-api-key-create $team $basename-$team --output json | jq .apikey) > local.env
    cat local.env
    source local.env
    
  2. Opcionalmente, profundice en este punto en el código fuente de Terraform. El equipo compartido va a proporcionar microservicios. Aunque el equipo network ya ha creado la VPC compartida y algunos recursos de red el equipo shared creará la instancia y elegirá el perfil de la instancia. Se proporciona un script de configuración de Linux y una aplicación de demostración sencilla en el atributo user_data y se tratan en la sección Equipo Application a continuación.

    En main.tf fíjese en estos dos recursos:

    locals {
      network_context = data.terraform_remote_state.network.outputs.shared
    }
    
    resource ibm_is_instance "vsishared" {
      name           = "${var.basename}-shared-vsi"
      vpc            = local.network_context.vpc.id
      resource_group = data.ibm_resource_group.shared.id
      zone           = local.network_context.subnets["z1"].zone
      keys           = [data.ibm_is_ssh_key.ssh_key.id]
      image          = data.ibm_is_image.image.id
      profile        = var.profile[var.generation]
    
      primary_network_interface {
        subnet = local.network_context.subnets["z1"].id
        security_groups = [
          local.network_context.security_group_outbound_all.id, # nodejs is not available on an IBM mirror
          local.network_context.security_group_ibm_dns.id,
          local.network_context.security_group_data_inbound.id,
        ]
      }
      user_data = module.user_data_app.user_data_centos
    }
    
    resource ibm_dns_resource_record "shared" {
      count = var.shared_lb ? 0 : 1 # shared load balancer?
      instance_id = local.network_context.dns.guid
      zone_id     = local.network_context.dns.zone_id
      type        = "A"
      name        = "shared"
      rdata       = ibm_is_instance.vsishared.primary_network_interface[0].primary_ip.address
      ttl         = 3600
    }
    

    local.network_context es la salida generada por el equipo network específicamente para el equipo shared.

  3. Cree los recursos compartidos:

    terraform init
    terraform apply
    
  4. Si lo desea, vaya a Instancias de servidor virtual para VPC y busque la instancia compartida. Pulse en la misma y verifique lo siguiente:

    • La instancia no tiene conectividad entrante de la Internet pública (compruebe los grupos de seguridad)
    • Localice la dirección IP privada
  5. Opcionalmente, navegue hasta la lista de recursos y busque el DNS Services, haga clic en él y busque el registro DNS con el nombre compartido. Observe que el valor es la dirección IP privada de la instancia.

Crear un microservicio de cara al público para una aplicaciónApplication1 Team)

  1. Cambie de directorio, genere una clave de API en local.env y pasará a ser miembro del grupo de acceso application1:

    team=application1
    cd ../$team
    echo export TF_VAR_ibmcloud_api_key=$(ibmcloud iam service-api-key-create $team $basename-$team --output json | jq .apikey) > local.env
    cat local.env
    source local.env
    

    Los recursos del equipo application1 son muy similares a los del equipo shared. De hecho, son un poco más simples ya que - no es necesario poner registros en el DNS Services. La aplicación utiliza la dirección http://shared.widgets.example.com para acceder al microservicio compartido.

  2. Opcionalmente, investigue el código fuente que inicializa la instancia CentOS. Se ha capturado en un módulo Terraform compartido por todos los equipos durante esta fase exploratoria.

    ../common/user_data_app/main.tf:

    locals {
      shared_app_user_data_centos = <<EOS
    #!/bin/sh
    curl -sL https://rpm.nodesource.com/setup_20.x | sudo bash -
    yum install nodejs -y
    cat > /app.js << 'EOF'
    ${file("${path.module}/app.js")}
    EOF
    cat > /lib/systemd/system/a-app.service << 'EOF'
    ${file("${path.module}/a-app.service")}
    EOF
    systemctl daemon-reload
    systemctl start a-app
    EOS
    }
    
    output user_data_centos {
      value = replace(local.shared_app_user_data_centos, "REMOTE_IP", var.remote_ip)
    }
    

    Explicación detallada:

    • Nodejs se instala con los mandatos curl y yum
    • La aplicación nodejs se pone en /app.js.
    • Se crea un servicio systemctl para app.js
    • Se inicia el servicio
  3. Opcionalmente, examine el contenido de app.js. Tiene dos secciones especialmente interesantes. En primer lugar, hay un enlace /info que devuelve una descripción de la instancia que ejecuta la aplicación. ../common/user_data_app/app.js:

    const server = http.createServer((req, res) => {
      switch(req.url) {
      case '/info':
        res.statusCode = 200;
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({
          req_url:  req.url,
          os_hostname:  os.hostname(),
          ipArrays: ips()
        }, null, 3));
        break
      case '/remote':
        getRemote(req, res)
        break
    

    En segundo lugar, el enlace /remote llama a la IP de un servidor remoto y devuelve la descripción de ese remoto junto con las direcciones remote_url y remote_ip utilizadas para acceder al remoto.

    const IP='REMOTE_IP'
    
    function getRemote(req, res) {
      path = '/info'
      remote_url = 'http://' + IP + ':3000' + path
      http.get(remote_url, (resp) => {
        let rawData = '';
        resp.on('data', (chunk) => { rawData += chunk; });
        resp.on('end', () => {
          try {
            console.log(rawData)
            rawObj = JSON.parse(rawData)
            res.statusCode = 200;
            res.end(JSON.stringify({remote_url: remote_url, remote_ip: resp.connection.remoteAddress, remote_info: rawObj}, null, 3))
    

    En nuestro caso el REMOTE_IP será shared.widgets.example.com debido a lo siguiente en common/user_data_app/main.tf:

    output user_data_centos {
      value = replace(local.shared_app_user_data_centos, "REMOTE_IP", var.remote_ip)
    }
    

    Y de nuevo en application1/main.tf:

    module user_data_app {
      source    = "../common/user_data_app"
      remote_ip = "shared.widgets.example.com"
    }
    
  4. Cree los recursos:

    terraform init
    terraform apply
    

    Los resultados serán algo así:

    $ terraform apply
    ...
    Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
    
    Outputs:
    
    ibm1_private_ip = "10.1.0.4"
    ibm1_public_ip = "52.116.140.202"
    test_info = "curl 52.116.140.202:3000/info"
    test_remote = "curl 52.116.140.202:3000/remote"
    

    Pruebe los dos mandatos curl (test_info, test_remote) que se han sugerido anteriormente. Copie las sentencias de la salida.

    curl 52.116.140.202:3000/info
    

    El primero da como resultado algo parecido a lo que se capturó a continuación:

    {
       "req_url": "/info",
       "os_hostname": "widget0-application1-vsi",
       "ipArrays": [
          [
             "10.1.0.4"
          ]
       ]
    }
    

    A continuación, intente el segundo mandato (desde la salida):

    curl 52.116.140.202:3000/remote
    

    Espere, ¡el segundo mandato curl no ha funcionado! Arréglelo en el paso siguiente. Recuerde estos comandos curl, los volverá a utilizar en breve.

Crear Transit Gateway

IBM Cloud Transit Gateway is a network service used to interconnect IBM Cloud VPC resources providing dynamic scalability, high availability and peace of mind that data isn’t traversing the public internet. Anteriormente, los bloques CIDR de cada una de las VPC se han elegido sin solapamiento para permitir que Transit Gateway direccione los paquetes por dirección IP.

  1. Cambie de directorio y pasará a ser miembro del grupo network (utilice la clave de API existente):

    cd ../network
    source local.env
    
  2. Opcionalmente, examine los archivos terraform. Abra el archivo main.tf y verá los recursos de Transit Gateway (ibm_tg). Cada uno tiene un count = var.transit_gateway ? 1 : 0. Se trata de una construcción de terraform que crea una matriz de recursos de longitud 1 o 0 en función del valor de transit_gateway. Una matriz de longitud 0 da como resultado ningún recurso. Por ejemplo:

    resource "ibm_tg_gateway" "tgw"{
      count = var.transit_gateway ? 1 : 0
      name              = "${var.basename}-tgw"
      location          = var.ibm_region
      global            = false
      resource_group    = data.ibm_resource_group.network.id
    }
    
  3. Edite el terraform.tfvars archivo y descomente la línea transit_gateway = true para habilitar el aprovisionamiento de Transit Gateway.

  4. Aplique el cambio

    terraform apply
    
  5. Imprima el Transit Gateway utilizando los mandatos siguientes.

    ibmcloud tg gateways
    GATEWAY_ID=$(ibmcloud tg gateways --output json | sed -e '/^OK$/d' | jq -r '.[]|select(.name=="'$basename-tgw'")|.id')
    ibmcloud tg connections $GATEWAY_ID
    

    Observe las tres conexiones de VPC en la salida. Será algo parecido a lo siguiente:

    $ ibmcloud tg gateways
    Listing gateways under account
    OK
    
    GatewayID           e2801c16-1a6d-4d47-9c58-1a3b3c1d9b1b
    CRN                 crn:v1:bluemix:public:transit:us-south:a/86785309::gateway:e2801c16-1a6d-4d47-9c58-1a3b3c1d9b1b
    Name                widget0-tgw
    Routing             local
    Location            us-south
    Created             2020-07-16T09:09:38.048-07:00
    Resource group ID   bf6e75cd71854576a31056abced2abf0
    Status              available
    
    $ GATEWAY_ID=$(ibmcloud tg gateways --output json | sed -e '/^OK$/d' | jq -r '.[]|select(.name=="'$basename-tgw'")|.id')
    $ ibmcloud tg connections $GATEWAY_ID
    Listing connections for gateway e2801c16-1a6d-4d47-9c58-1a3b3c1d9b1b under account
    OK
    
    Name                    widget0-shared
    Network Type            vpc
    Connection ID           dff6ecfd-388d-471a-908a-98880426fbee
    Status                  attached
    Default Prefix Filter   permit
    NetworkID               crn:v1:bluemix:public:is:us-south:a/86785309::vpc:r006-b08a7c2c-c0ea-4908-b0ab-b96cd8ba221a
    
    Name                    widget0-application1
    Network Type            vpc
    Connection ID           bbce29f9-9ce4-47d4-911d-5341601cea07
    Status                  attached
    Default Prefix Filter   permit
    NetworkID               crn:v1:bluemix:public:is:us-south:a/86785309::vpc:r006-8fdc0e7e-3a98-4f6b-93e0-505c61e3faac
    
    Name                    widget0-application2
    Network Type            vpc
    Connection ID           208c00cc-aee2-498e-8b1c-37ddc276f200
    Status                  attached
    Default Prefix Filter   permit
    NetworkID               crn:v1:bluemix:public:is:us-south:a/86785309::vpc:r006-fa80afa7-b16b-4db7-95dd-69a558db4285
    
  6. Si lo desea, navegue por Transit Gateway y busque la pasarela creada anteriormente.

  7. Ejecute el comando curl que falló anteriormente para verificar que existe una ruta desde la VPC application1 a la VPC compartida. Será algo similar a lo siguiente:

    $ curl 169.48.152.220:3000/remote
    
    {
       "remote_url": "http://shared.widgets.example.com:3000/info",
       "remote_ip": "10.0.0.4",
       "remote_info": {
          "req_url": "/info",
          "os_hostname": "widget0-shared-vsi",
          "ipArrays": [
             [
                "10.0.0.4"
             ]
          ]
       }
    }
    

Inserte un Load Balancer y sustituya el registro de DNS

Adición de un equilibrador de carga a la arquitectura
Adición de un equilibrador de carga a la arquitectura

  1. Cambie de directorio y pasará a ser miembro del grupo de acceso shared (utilice la clave de API existente):

    cd ../shared
    source local.env
    
  2. Opcionalmente, examine los archivos de configuración de terraform. El Load Balancer del servicio de VPC distribuye el tráfico entre varias instancias de servidor dentro de la misma región de su VPC. El equipo shared puede equilibrar la carga entre varias instancias. De momento, la agrupación de equilibrador de carga solo tendrá la instancia creada anteriormente. Véase el lb.tf para la aplicación. En el recurso ibm_is_lb, utilice la cláusula dns para identificar la zona DNS privada para colocar la dirección DNS del equilibrador de carga:

    resource "ibm_is_lb" "shared_lb" {
      ...
      dns {
        instance_crn = local.network_context.dns.crn
        zone_id      = local.network_context.dns.zone_id
      }
    }
    
  3. Proporcione un registro CNAME de DNS shared.widgets.example.com para identificar el equilibrador de carga, para que las aplicaciones sigan funcionando sin cambios de código fuente:

    # shared.widgets.example.com
    resource ibm_dns_resource_record "shared_lb" {
      count = var.shared_lb ? 1 : 0 # shared load balancer?
      instance_id = local.network_context.dns.guid
      zone_id     = local.network_context.dns.zone_id
      type        = "CNAME"
      name        = "shared"
      rdata       = ibm_is_lb.shared_lb[0].hostname
      ttl         = 3600
    }
    

    Se utiliza el mismo count = var.shared_lb ? 1 : 0. El nombre de host del equilibrador de carga será similar a b7911a41-us-south.widgets.example.com. Las aplicaciones utilizarán el registro CNAME.

  4. Edite el archivo terraform.tfvars y descomente shared_lb = true. A continuación, aplique los cambios:

    terraform apply
    
  5. Ejecuta el comando curl .../remote de la sección application1 anterior (ignora la salida que se acaba de generar para el microservicio compartido). Observa que remote_ip es 10.0.1.4, el balanceador de carga, y remote_info es 10.0.0.4, la instancia. Curl un par de veces más y observe que el remote_ip para el balanceador de carga puede cambiar.

    $ curl 169.48.152.220:3000/remote
    
    {
       "remote_url": "http://shared.widgets.example.com:3000/info",
       "remote_ip": "10.0.1.4",
       "remote_info": {
          "req_url": "/info",
          "os_hostname": "widget0-shared-vsi",
          "ipArrays": [
             [
                "10.0.0.4"
             ]
          ]
       }
    }
    

Crear un microservicio de cara al público para una aplicaciónApplication2 Team)

El segundo entorno de equipo de application es idéntico al primero. Opcionalmente, cree application2 modificando application1.

  1. Entre en el directorio ./application1 y cree el directorio application2

    cd ../application1
    mkdir ../application2
    sed -e 's/application1/application2/g' main.tf > ../application2/main.tf
    cp terraform.tfvars variables.tf versions.tf ../application2
    
  2. Cambie de directorio, genere una clave API en el local.env y conviértase en miembro del grupo de acceso application2:

    team=application2
    cd ../$team
    echo export TF_VAR_ibmcloud_api_key=$(ibmcloud iam service-api-key-create $team $basename-$team --output json | jq .apikey) > local.env
    cat local.env
    source local.env
    
  3. Cree los recursos:

    terraform init
    terraform apply
    
  4. Pruebe los mandatos curl

Eliminación de recursos

  1. Destruya los recursos. Puede cambiar cd) a los directorios del equipo en orden, y ejecutar source local.env; terraform destroy. El orden es application2, application1, shared, network, admin. También dispone de un script que hace esto automáticamente:

    cd ..
    ./bin/destroy.sh
    

Ampliación de la guía de aprendizaje

Otras consideraciones

  • El equipo Application proporciona acceso a la aplicación mediante una dirección IP flotante. Considere la posibilidad de conectarla a IBM Cloud Internet Services. Puede gestionar el DNS público y proporcionar seguridad. En Despliegue de cargas de trabajo aisladas en varias ubicaciones y zonas se proporciona un ejemplo.
  • El equipo de aplicaciones puede escalar horizontalmente utilizando un equilibrador de carga como el equipo compartido.
  • El equipo compartido puede añadir instancias adicionales al equilibrador de carga añadiendo instancias al shared/main.tf.
  • El equipo compartido podría cambiar su plataforma de implementación a Kubernetes.

Continuous Delivery

  • Actualmente, la instalación del software se realiza cuando se crea la instancia de VPC. No se ha tenido en cuenta la entrega de nuevas versiones de software a producción.
  • En el caso de los microservicios compartidos, se podría crear una nueva VSI con una nueva versión y, tras la verificación, se podría ajustar el DNS o utilizar el equilibrador de carga compartido para cambiar a la nueva versión.

Automatización, transferencia y desarrollo

  • Para la producción, los equipos pueden tener cada uno su propio espacio de trabajo Schematics. Con Schematics, las configuraciones de terraform se pueden ejecutar directamente en la nube donde se puede compartir el estado y la salida.
  • Los scripts de Terraform se pueden ajustar para permitir entornos de transferencia y desarrollo. Ponga estos entornos en nuevas cuentas.
  • Se puede construir un entorno de despliegue continuo para pasar el código y los entornos de desarrollo a transferencia y a producción. ¿Se necesita retrotraer versiones? ¿Cómo se podría hacer?

Conclusiones

La arquitectura de un sistema está influenciada por el contenido y la propiedad de los recursos de nube. Es importante que los arquitectos de todos los aspectos del sistema aporten sus visiones a la arquitectura. Cada equipo necesita poder controlar los recursos que producen y publican. El aislamiento reducirá la probabilidad de problemas y contendrá el radio de afectación cuando se produzcan problemas.