Tous les produits
Search
Centre de documentation

Resource Orchestration Service:ALIYUN::SLB::Listener

Dernière mise à jour :Aug 10, 2026

Crée un écouteur SLB.

Syntaxe

 {
  "Type": "ALIYUN::SLB::Listener",
  "Properties": {
    "MasterSlaveServerGroupId": String,
    "AclStatus": String,
    "Protocol": String,
    "AclId": String,
    "ServerCertificateId": String,
    "HealthCheck": Map,
    "RequestTimeout": Integer,
    "IdleTimeout": Integer,
    "ListenerPort": Integer,
    "HttpConfig": Map,
    "Bandwidth": Integer,
    "AclType": String,
    "BackendServerPort": Integer,
    "Scheduler": String,
    "LoadBalancerId": String,
    "CACertificateId": String,
    "Persistence": Map,
    "VServerGroupId": String,
    "Description": String,
    "PortRange": List,
    "StartListener": Boolean,
    "EnableHttp2": String,
    "Gzip": String,
    "TLSCipherPolicy": String,
    "AclIds": List,
    "ProxyProtocolV2Enabled": Boolean,
    "ConnectionDrainTimeout": Integer,
    "Tags": List,
    "FullNatEnabled": Boolean,
    "ConnectionDrain": String
  }
}

Propriétés

Nom de la propriété

Type

Obligatoire

Mise à jour autorisée

Description

Contraintes

MasterSlaveServerGroupId

String

Non

Non

ID du groupe de serveurs principal/secondaire.

Aucune

AclStatus

String

Non

Oui

Indique s'il faut activer le contrôle d'accès.

Valeurs valides :

  • on (par défaut) : active le contrôle d'accès.

  • off : désactive le contrôle d'accès.

EnableHttp2

String

Non

Oui

Indique s'il faut activer HTTP/2.

Valeurs valides :

  • on : active HTTP/2.

  • off : désactive HTTP/2.

AclId

String

Non

Oui

ID du groupe de politiques de contrôle d'accès associé à l'écouteur.

Ce paramètre est obligatoire lorsque AclStatus est défini sur on.

AclType

String

Non

Oui

Type de la politique de contrôle d'accès.

Valeurs valides :

  • white : transfère uniquement les requêtes provenant des adresses IP ou des blocs CIDR spécifiés dans le groupe de politiques de contrôle d'accès sélectionné. Une liste blanche convient aux applications qui n'autorisent l'accès qu'à partir d'adresses IP spécifiques. L'utilisation d'une liste blanche comporte des risques. Si vous définissez une liste blanche, seules les adresses IP figurant dans celle-ci peuvent accéder à l'écouteur SLB. Si vous activez une liste blanche sans ajouter d'adresses IP au groupe de politiques, l'écouteur SLB ne transfère aucune requête.

  • black : bloque toutes les requêtes provenant des adresses IP ou des blocs CIDR spécifiés dans le groupe de politiques de contrôle d'accès sélectionné. Une liste noire convient aux scénarios où vous souhaitez bloquer l'accès uniquement à partir d'adresses IP spécifiques. Si vous activez une liste noire sans ajouter d'adresses IP au groupe de politiques, l'écouteur SLB transfère toutes les requêtes. Ce paramètre est obligatoire lorsque AclStatus est défini sur on.

Protocol

String

Oui

Non

Protocole de l'écouteur.

Valeurs valides :

  • http

  • https

  • tcp

  • udp

ListenerPort

Integer

Oui

Non

Port frontal de l'instance SLB.

Plage de valeurs : 1 à 65 535.

Bandwidth

Integer

Oui

Oui

Bande passante maximale de l'écouteur.

Plage de valeurs : -1 ou 1 à 1 000.

Unité : Mbps.

Remarques :

  • Pour une instance orientée vers Internet utilisant la méthode de facturation par bande passante, la somme des valeurs de bande passante maximale de tous les écouteurs ne peut pas dépasser la valeur de bande passante spécifiée lors de la création de l'instance SLB. Vous ne pouvez pas définir la bande passante d'un écouteur sur -1.

  • Pour une instance orientée vers Internet utilisant la méthode de facturation par trafic, vous pouvez définir la bande passante d'un écouteur sur -1. Cette valeur indique que la bande passante n'est pas limitée.

BackendServerPort

Integer

Non

Non

Port backend de l'instance SLB.

Plage de valeurs : 1 à 65 535.

FullNatEnabled

Boolean

Non

Oui

Indique s'il faut activer le mode full-NAT. Lorsqu'il est activé, les serveurs backend peuvent accéder aux ressources externes en tant que clients.

Valeur par défaut : false.

Remarque : ce paramètre n'est valide que pour les écouteurs TCP et UDP.

LoadBalancerId

String

Oui

Non

ID de l'instance SLB.

Aucune

HealthCheck

Map

Non

Oui

Paramètres de vérification de l'état de santé.

Pour plus d'informations, consultez Propriétés HealthCheck.

Persistence

Map

Non

Oui

Paramètres de persistance de session.

Pour plus d'informations, consultez Propriétés Persistence.

Scheduler

String

Non

Non

Algorithme de planification.

Valeurs valides :

  • wrr (par défaut) : les serveurs backend ayant des poids plus élevés reçoivent plus de requêtes.

  • wlc : les requêtes sont distribuées séquentiellement aux serveurs backend.

CACertificateId

String

Non

Non

ID du certificat CA.

Ce paramètre n'est valide que pour le protocole HTTPS.

ServerCertificateId

String

Non

Oui

ID du certificat de serveur.

Ce paramètre est obligatoire et n'est valide que pour le protocole HTTPS.

VServerGroupId

String

Non

Oui

ID du groupe de serveurs.

Aucune

RequestTimeout

Integer

Non

Non

Délai d'expiration de la requête.

Plage de valeurs : 1 à 180.

Unité : secondes.

IdleTimeout

Integer

Non

Non

Délai d'expiration des connexions inactives.

Plage de valeurs : 1 à 60.

Unité : secondes.

HttpConfig

Map

Non

Non

Configuration HTTP.

Pour plus d'informations, consultez Propriétés HttpConfig.

Description

String

Non

Non

Description de l'écouteur.

La longueur doit être comprise entre 1 et 80 caractères. Elle peut contenir des lettres, des chiffres, des traits d'union (-), des barres obliques (/), des points (.) et des traits de soulignement (_).

PortRange

List

Non

Non

Plage de ports d'écoute.

Actuellement, seule l'écoute sur tous les ports est prise en charge. Cela signifie que StartPort doit être 1 et EndPort doit être 65 535.

Pour plus d'informations, consultez Propriétés PortRange.

StartListener

Boolean

Non

Non

Indique s'il faut démarrer l'écouteur.

Valeurs valides :

  • true (par défaut) : démarre l'écouteur.

  • false : ne démarre pas l'écouteur.

Gzip

String

Non

Oui

Indique s'il faut activer la compression Gzip.

Valeurs valides :

  • true (par défaut) : activé.

  • false : désactivé.

TLSCipherPolicy

String

Non

Oui

Politique de sécurité TLS.

Chaque politique de sécurité contient les versions TLS et les suites de chiffrement pouvant être utilisées pour HTTPS.

Remarque

Ce paramètre est valide lorsque Protocol est défini sur https.

AclIds

List

Non

Oui

ID des politiques de contrôle d'accès à associer à l'écouteur.

Ce paramètre est obligatoire si le paramètre AclStatus est défini sur on. AclIds a une priorité plus élevée que AclId.

ProxyProtocolV2Enabled

Boolean

Non

Oui

Indique s'il faut utiliser le protocole Proxy pour transmettre les adresses IP des clients aux serveurs backend.

Valeurs valides :

  • true : Oui.

  • false : Non.

ConnectionDrainTimeout

Integer

Non

Oui

Délai d'expiration pour la vidange des connexions.

Unité : secondes.

Plage de valeurs : 10 à 900.

Tags

List

Non

Oui

Les tags.

Pour plus d'informations, consultez Propriétés Tags.

ConnectionDrain

String

Non

Oui

Indique s'il faut activer la vidange des connexions.

Valeurs valides :

  • on : Oui.

  • off : Non.

Syntaxe HealthCheck

"HealthCheck": {
  "Domain": String,
  "Interval": Integer,
  "URI": String,
  "HttpCode": String,
  "HealthyThreshold": Integer,
  "HealthCheckType": String,
  "Timeout": Integer,
  "UnhealthyThreshold": Integer,
  "Port": Integer,
  "Switch": String,
  "HealthCheckMethod": String,
  "Req": String,
  "Exp": String
}

Propriétés HealthCheck

Nom de la propriété

Type

Obligatoire

Mise à jour autorisée

Description

Contraintes

Domain

String

Non

Non

Nom de domaine utilisé pour les vérifications de l'état de santé.

Valeurs valides :

  • $_ip

  • Une chaîne personnalisée de 1 à 80 caractères. Elle peut contenir des lettres, des chiffres, des traits d'union (-) et des points (.).

  • empty

Remarque

Si vous définissez ce paramètre sur $_ip ou le laissez vide, SLB utilise l'adresse IP privée de chaque serveur backend comme nom de domaine pour les vérifications de l'état de santé.

Interval

Integer

Non

Non

Intervalle entre les vérifications de l'état de santé.

Plage de valeurs : 1 à 5.

Unité : secondes.

URI

String

Non

Non

URI utilisé pour les vérifications de l'état de santé.

La valeur doit comporter entre 1 et 80 caractères. Elle doit commencer par une barre oblique (/). Elle peut contenir des lettres, des chiffres, des traits d'union (-), des barres obliques (/), des points (.), des signes pourcent (%), des points d'interrogation (?), des dièses (#) et des esperluettes (&).

HttpCode

String

Non

Non

Code d'état HTTP.

Valeurs valides :

  • http_2xx (par défaut)

  • http_3xx

  • http_4xx

  • http_5xx

Séparez plusieurs codes d'état HTTP par des virgules (,).

HealthyThreshold

Integer

Non

Non

Nombre de vérifications de l'état de santé réussies consécutives requises avant de déclarer un serveur backend sain.

Plage de valeurs : 1 à 10.

HealthCheckType

String

Non

Non

Type de vérification de l'état de santé.

Valeurs valides :

  • tcp

  • http

Timeout

Integer

Non

Non

Délai d'expiration pour une réponse de vérification de l'état de santé.

Plage de valeurs : 1 à 50.

Unité : secondes.

Remarque

Si la valeur Timeout est inférieure à la valeur Interval, la valeur Timeout est ignorée et la valeur Interval est utilisée comme délai d'expiration.

UnhealthyThreshold

Integer

Non

Non

Nombre de vérifications de l'état de santé échouées consécutives requises avant de déclarer un serveur backend non sain.

Plage de valeurs : 1 à 10.

Port

Integer

Non

Non

Port utilisé pour les vérifications de l'état de santé.

Plage de valeurs : 0 à 65 535.

Switch

String

Non

Non

Indique s'il faut activer les vérifications de l'état de santé.

Valeurs valides :

  • on : active les vérifications de l'état de santé.

  • off : désactive les vérifications de l'état de santé.

Remarque

Ce paramètre n'est actuellement valide que pour les protocoles HTTP ou HTTPS. Si vous ne définissez pas Switch, les vérifications de l'état de santé sont désactivées par défaut, sauf si vous avez configuré des éléments de vérification de l'état de santé.

HealthCheckMethod

String

Non

Non

Méthode de vérification de l'état de santé.

Valeurs valides :

  • head

  • get

Remarque

Ce paramètre est valide lorsque Protocol est défini sur https ou http, et Switch est défini sur on.

Req

String

Non

Non

Chaîne de requête pour les vérifications de l'état de santé UDP. Seules les lettres et les chiffres sont autorisés.

La longueur maximale est de 64 caractères.

Exp

String

Non

Non

Chaîne de réponse attendue pour les vérifications de l'état de santé UDP. Seules les lettres et les chiffres sont autorisés.

La longueur maximale est de 64 caractères.

Syntaxe Persistence

"Persistence": {
  "PersistenceTimeout": Integer,
  "CookieTimeout": Integer,
  "XForwardedFor": String,
  "XForwardedFor_SLBID": String,
  "XForwardedFor_proto": String,
  "XForwardedFor_SLBIP": String,
  "Cookie": String,
  "StickySession": String,
  "StickySessionType": String,
  "XForwardedFor_ClientSrcPort": String,
  "XForwardedFor_SLBPORT": String
}

Propriétés Persistence

Nom de la propriété

Type

Obligatoire

Mise à jour autorisée

Description

Contraintes

StickySession

String

Non

Oui

Indique s'il faut activer la persistance de session.

Valeurs valides :

  • on : active la persistance de session.

  • off : désactive la persistance de session.

    Remarque

    Ce paramètre n'est valide que pour les protocoles HTTP et HTTPS.

PersistenceTimeout

Integer

Non

Oui

Délai d'expiration pour la persistance de connexion.

Plage de valeurs : 0 à 1 000.

Valeur par défaut : 0 (désactivé).

Unité : secondes.

CookieTimeout

Integer

Non

Oui

Délai d'expiration du cookie.

Plage de valeurs : 1 à 86 400.

Unité : secondes.

Remarque

Ce paramètre est obligatoire lorsque StickySession est défini sur on et StickySessionType est défini sur insert.

XForwardedFor

String

Non

Oui

Indique s'il faut utiliser l'en-tête X-Forwarded-For pour récupérer l'adresse IP du client.

Valeurs valides :

  • on : récupère l'adresse IP du client à partir de l'en-tête X-Forwarded-For.

  • off (par défaut) : ne récupère pas l'adresse IP du client.

XForwardedFor_proto

String

Non

Oui

Indique s'il faut utiliser l'en-tête X-Forwarded-Proto pour récupérer le protocole de l'écouteur SLB.

Valeurs valides :

  • on : récupère le protocole de l'écouteur SLB à partir de l'en-tête X-Forwarded-Proto.

  • off (par défaut) : ne récupère pas le protocole de l'écouteur SLB.

XForwardedFor_SLBID

String

Non

Oui

Indique s'il faut utiliser l'en-tête SLB-ID pour récupérer l'ID de l'instance SLB.

Valeurs valides :

  • on : récupère l'ID de l'instance SLB à partir de l'en-tête SLB-ID.

  • off (par défaut) : ne récupère pas l'ID de l'instance SLB.

XForwardedFor_SLBIP

String

Non

Oui

Indique s'il faut récupérer l'adresse IP du client à partir de l'en-tête SLB-IP.

Valeurs valides :

  • on : récupère l'adresse IP du client à partir de l'en-tête SLB-IP.

  • off (par défaut) : ne récupère pas l'adresse IP du client.

Cookie

String

Non

Oui

Cookie configuré sur le serveur.

La valeur doit comporter entre 1 et 200 caractères et ne peut pas commencer par un signe dollar ($). Elle peut contenir des lettres et des chiffres, mais ne peut pas contenir de virgules (,), de points-virgules (;) ou d'espaces.

Remarque

Ce paramètre est obligatoire lorsque StickySession est défini sur on et StickySessionType est défini sur server.

StickySessionType

String

Non

Oui

Méthode de gestion des cookies.

Valeurs valides :

  • insert : insère un cookie.

  • server : réécrit un cookie.

Remarque

Ce paramètre est obligatoire lorsque StickySession est défini sur on.

XForwardedFor_ClientSrcPort

String

Non

Oui

Indique s'il faut utiliser l'en-tête X-Forwarded-Client-srcport pour récupérer le port client.

Valeurs valides :

  • on : récupère le port client à partir de l'en-tête X-Forwarded-Client-srcport.

  • off (par défaut) : ne récupère pas le port client.

XForwardedFor_SLBPORT

String

Non

Oui

Indique s'il faut utiliser l'en-tête X-Forwarded-Port pour récupérer le port d'écoute SLB.

Valeurs valides :

  • on : récupère le port d'écoute SLB à partir de l'en-tête X-Forwarded-Port.

  • off (par défaut) : ne récupère pas le port d'écoute SLB.

Syntaxe HttpConfig

"HttpConfig": {
  "ForwardPort": Integer,
  "ListenerForward": String
}

Propriétés HttpConfig

Nom de la propriété

Type

Obligatoire

Mise à jour autorisée

Description

Contraintes

ForwardPort

Integer

Non

Non

Port vers lequel les requêtes HTTP sont transférées pour un écouteur HTTPS.

Plage de valeurs : 1 à 65 535.

Valeur par défaut : 443.

ListenerForward

String

Non

Non

Indique s'il faut activer le transfert HTTP vers HTTPS.

Valeurs valides :

  • on : activé.

  • off (par défaut) : désactivé.

Syntaxe PortRange

"PortRange": [
  {
    "StartPort": Integer,
    "EndPort": Integer
  }
]

Propriétés PortRange

Nom de la propriété

Type

Obligatoire

Mise à jour autorisée

Description

Contraintes

StartPort

Integer

Oui

Non

Port de début.

Valeur : 1.

EndPort

Integer

Oui

Non

Port de fin.

Valeur : 65 535.

Syntaxe Tags

"Tags": [
  {
    "Key": String,
    "Value": String
  }
]

Propriété Tags

Propriété

Type

Obligatoire

Mise à jour autorisée

Description

Contraintes

Key

String

Oui

Non

Clé du tag.

Aucune

Value

String

Non

Non

Valeur du tag.

Aucune

Valeurs de retour

Fn::GetAtt

  • LoadBalancerId : ID unique de l'instance SLB.

  • ListenerPortsAndProtocol : Ports frontaux et protocoles utilisés par l'instance SLB.

  • Arn : Nom de ressource Alibaba Cloud (ARN).

Exemples

Scénario 1 : Créer un écouteur SLB

Création rapide

ROSTemplateFormatVersion: '2015-09-01'
Description: Test SLB Listener
Parameters:
  SlbInstanceId:
    AssociationProperty: ALIYUN::SLB::Instance::InstanceId
    Type: String
Resources:
  Listener:
    Type: ALIYUN::SLB::Listener
    Properties:
      BackendServerPort: 8080
      Bandwidth: 50
      ListenerPort: 80
      LoadBalancerId:
        Ref: SlbInstanceId
      Protocol: https
      Scheduler: wrr
Outputs: {}
{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Description": "Test SLB Listener",
  "Parameters": {
    "SlbInstanceId": {
      "AssociationProperty": "ALIYUN::SLB::Instance::InstanceId",
      "Type": "String"
    }
  },
  "Resources": {
    "Listener": {
      "Type": "ALIYUN::SLB::Listener",
      "Properties": {
        "BackendServerPort": 8080,
        "Bandwidth": 50,
        "ListenerPort": 80,
        "LoadBalancerId": {
          "Ref": "SlbInstanceId"
        },
        "Protocol": "https",
        "Scheduler": "wrr"
      }
    }
  },
  "Outputs": {
  }
}

Scénario 2 : Créer un écouteur SLB avec vérifications de l'état de santé

Création rapide

ROSTemplateFormatVersion: '2015-09-01'
Description: Test SLB Listener
Parameters:
  SlbInstanceId:
    AssociationProperty: ALIYUN::SLB::Instance::InstanceId
    Type: String
Resources:
  Listener:
    Type: ALIYUN::SLB::Listener
    Properties:
      ListenerPort: 80
      Bandwidth: 10
      HealthCheck:
        HttpCode: http_2xx,http_3xx,http_4xx,http_5xx
        HealthCheckType: http
        UnhealthyThreshold: 3
        Timeout: 5
        HealthyThreshold: 3
        Port: 80
        URI: /
        Interval: 5
      LoadBalancerId:
        Ref: SlbInstanceId
      BackendServerPort: 80
      Protocol: http
Outputs: {}
{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Description": "Test SLB Listener",
  "Parameters": {
    "SlbInstanceId": {
      "AssociationProperty": "ALIYUN::SLB::Instance::InstanceId",
      "Type": "String"
    }
  },
  "Resources": {
    "Listener": {
      "Type": "ALIYUN::SLB::Listener",
      "Properties": {
        "BackendServerPort": 8080,
        "Bandwidth": 50,
        "ListenerPort": 80,
        "LoadBalancerId": {
          "Ref": "SlbInstanceId"
        },
        "Protocol": "https",
        "Scheduler": "wrr"
      }
    }
  },
  "Outputs": {
  }
}

Scénario 3 : Créer un service web haute disponibilité

Création rapide

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: Build a high-availability web service that includes dual-zone ECS instances, an SLB instance, and NAS mounts. The service supports automatic configuration synchronization and public network access.
  en: Constructing a highly available web service comprises dual availability zone
    ECS instances, a Load Balancer (SLB), Network Attached Storage (NAS) mounts, automatic
    configuration synchronization, and is accessible via the public internet.
Parameters:
  NasZone1:
    AssociationProperty: 'ALIYUN::ECS::Instance::ZoneId'
    Type: String
    Description:
      zh-cn: Zone 1 must be different from Zone 2.
      en: Availability zone 1 must be different from Availability zone 2.
    Label:
      zh-cn: NAS Zone 1
      en: NAS Availability Zone1
  NasZone2:
    AssociationProperty: 'ALIYUN::ECS::Instance::ZoneId'
    Type: String
    Description:
      zh-cn: Zone 2 must be different from Zone 1.
      en: Availability zone 2 must be different from Availability zone 1.
    Label:
      zh-cn: NAS Zone 2
      en: NAS Availability Zone2
  CommonName:
    Default: high-availability
    Type: String
  InstancePassword:
    Type: String
    Description:
      zh-cn: >-
        The logon password of the server. The password must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters include ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/
      en: >-
        Server login password, Length 8~30, must contain three(Capital letters,
        lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special
        symbol in).
    MinLength: 8
    Label:
      zh-cn: Instance Password
      en: Instance Password
    AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'
    NoEcho: true
    MaxLength: 30
    AssociationProperty: 'ALIYUN::ECS::Instance::Password'
    ConstraintDescription:
      zh-cn: 'The password must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters include ()`~!@#$%^&*_-+=|{}[]:;''<>,.?/'
      en: >-
        Length 8~30, must contain three(Capital letters, lowercase letters,
        numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).
  EcsInstanceType2:
    AssociationProperty: 'ALIYUN::ECS::Instance::InstanceType'
    AssociationPropertyMetadata:
      SystemDiskCategory: cloud_essd
      InstanceChargeType: PostPaid
      ZoneId: '${Zone2}'
    Type: String
    Label:
      zh-cn: Instance Type of Zone 2
      en: Instance Type Of Availability Zone2
  Zone2:
    AssociationProperty: 'ALIYUN::ECS::Instance::ZoneId'
    Type: String
    Description:
      zh-cn: Zone 2 must be different from Zone 1.
      en: Availability zone 2 must be different from Availability zone 1.
    Label:
      zh-cn: vSwitch Zone 2
      en: VSwitch Availability Zone2
  Zone1:
    AssociationProperty: 'ALIYUN::ECS::Instance::ZoneId'
    Type: String
    Description:
      zh-cn: Zone 1 must be different from Zone 2.
      en: Availability zone 1 must be different from Availability zone 2.
    Label:
      zh-cn: vSwitch Zone 1
      en: VSwitch Availability Zone1
  EcsInstanceType1:
    AssociationProperty: 'ALIYUN::ECS::Instance::InstanceType'
    AssociationPropertyMetadata:
      SystemDiskCategory: cloud_essd
      InstanceChargeType: PostPaid
      ZoneId: '${Zone1}'
    Type: String
    Label:
      zh-cn: Instance Type of Zone 1
      en: Instance Type Of Availability Zone1
Rules:
  DifferentZones2:
    Assertions:
      - Assert:
          'Fn::Not':
            'Fn::Equals':
              - Ref: NasZone1
              - Ref: NasZone2
        AssertDescription: NAS Zones must be different
  DifferentZones1:
    Assertions:
      - Assert:
          'Fn::Not':
            'Fn::Equals':
              - Ref: Zone1
              - Ref: Zone2
        AssertDescription: ECS Zones must be different
Outputs:
  ECS1URL:
    Description: ECS 1 URL
    Value:
      'Fn::Sub':
        - >-
          https://ecs.console.alibabacloud.com/#/server/region/${region}?instanceIds=${InstanceID}
        - InstanceID:
            'Fn::Select':
              - '0'
              - 'Fn::GetAtt':
                  - EcsInstanceGroup1
                  - InstanceIds
          region:
            Ref: 'ALIYUN::Region'
  FileSystemId1:
    Description:
      zh-cn: Master NAS
      en: Master NAS
    Value:
      'Fn::Sub':
        - 'https://nas.console.alibabacloud.com/${region}/filesystem/${InstanceID}'
        - InstanceID:
            'Fn::GetAtt':
              - MasterFileSystem
              - FileSystemId
          region:
            Ref: 'ALIYUN::Region'
  ECS2URL:
    Description: ECS 2 URL
    Value:
      'Fn::Sub':
        - >-
          https://ecs.console.alibabacloud.com/#/server/region/${region}?instanceIds=${InstanceID}
        - InstanceID:
            'Fn::Select':
              - '0'
              - 'Fn::GetAtt':
                  - EcsInstanceGroup1
                  - InstanceIds
          region:
            Ref: 'ALIYUN::Region'
  SlbIpAddress:
    Description:
      zh-cn: The public IP address exposed to the Internet.
      en: Public IP Addresses
    Value:
      'Fn::Sub':
        - 'http://${ServerAddress}'
        - ServerAddress:
            'Fn::GetAtt':
              - Slb
              - IpAddress
  FileSystemId2:
    Description:
      zh-cn: Secondary NAS
      en: Backup NAS
    Value:
      'Fn::Sub':
        - 'https://nas.console.alibabacloud.com/${region}/filesystem/${InstanceID}'
        - InstanceID:
            'Fn::GetAtt':
              - BackupFileSystem
              - FileSystemId
          region:
            Ref: 'ALIYUN::Region'
  MountInfo1:
    Description:
      zh-cn: NAS mount directory 1 on the ECS instance
      en: NAS mounting directory 1 on ECS
    Value: '/nas_master'
  MountInfo2:
    Description:
      zh-cn: NAS mount directory 2 on the ECS instance
      en: NAS mounting directory 2 on ECS
    Value: '/nas_backup'
Resources:
  SlbListener:
    Type: 'ALIYUN::SLB::Listener'
    Properties:
      Protocol: http
      HealthCheck:
        HealthCheckType: http
        Interval: 2
        URI: /
        UnhealthyThreshold: 3
        HealthyThreshold: 3
        Timeout: 5
        HttpCode: 'http_2xx,http_3xx,http_4xx,http_5xx'
        Port: 80
      ListenerPort: 80
      Bandwidth: 10
      BackendServerPort: 80
      LoadBalancerId:
        Ref: Slb
    DependsOn:
      - Slb
  EcsSecurityGroup:
    Type: 'ALIYUN::ECS::SecurityGroup'
    Properties:
      SecurityGroupIngress:
        - Priority: 1
          PortRange: 80/80
          NicType: internet
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
      VpcId:
        Ref: EcsVpc
      SecurityGroupEgress:
        - Priority: 1
          PortRange: '-1/-1'
          DestCidrIp: 0.0.0.0/0
          NicType: internet
          IpProtocol: all
        - Priority: 1
          PortRange: '-1/-1'
          DestCidrIp: 0.0.0.0/0
          NicType: intranet
          IpProtocol: all
      SecurityGroupName:
        'Fn::Sub': '${CommonName}_sg'
  MasterNasMountTarget:
    Type: 'ALIYUN::NAS::MountTarget'
    Properties:
      NetworkType: Vpc
      FileSystemId:
        Ref: MasterFileSystem
      VpcId:
        Ref: EcsVpc
      VSwitchId:
        Ref: EcsVSwitch3
      AccessGroupName: DEFAULT_VPC_GROUP_NAME
  EcsVSwitch4:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VSwitchName:
        'Fn::Sub': '${CommonName}_vsw_002'
      VpcId:
        Ref: EcsVpc
      CidrBlock: 192.168.4.0/24
      ZoneId:
        Ref: NasZone2
  MasterFileSystem:
    Type: 'ALIYUN::NAS::FileSystem'
    Properties:
      StorageType: Capacity
      ProtocolType: NFS
      VpcId:
        Ref: EcsVpc
      Description: MasterNAS
      ZoneId:
        Ref: NasZone1
  EcsVSwitch2:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VSwitchName:
        'Fn::Sub': '${CommonName}_vsw_002'
      VpcId:
        Ref: EcsVpc
      CidrBlock: 192.168.2.0/24
      ZoneId:
        Ref: Zone2
  EcsVSwitch3:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VSwitchName:
        'Fn::Sub': '${CommonName}_vsw_002'
      VpcId:
        Ref: EcsVpc
      CidrBlock: 192.168.3.0/24
      ZoneId:
        Ref: NasZone1
  EcsVSwitch1:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VSwitchName:
        'Fn::Sub': '${CommonName}_vsw_001'
      VpcId:
        Ref: EcsVpc
      CidrBlock: 192.168.1.0/24
      ZoneId:
        Ref: Zone1
  BackupFileSystem:
    Type: 'ALIYUN::NAS::FileSystem'
    Properties:
      StorageType: Capacity
      ProtocolType: NFS
      VpcId:
        Ref: EcsVpc
      Description: BackupNAS
      ZoneId:
        Ref: NasZone2
  BackupNasMountTarget:
    Type: 'ALIYUN::NAS::MountTarget'
    Properties:
      NetworkType: Vpc
      FileSystemId:
        Ref: BackupFileSystem
      VpcId:
        Ref: EcsVpc
      VSwitchId:
        Ref: EcsVSwitch4
      AccessGroupName: DEFAULT_VPC_GROUP_NAME
  EcsInstanceGroup1:
    Type: 'ALIYUN::ECS::InstanceGroup'
    Properties:
      SystemDiskCategory: cloud_essd
      VpcId:
        Ref: EcsVpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      SystemDiskSize: 40
      ImageId: aliyun_3_x64_20G_alibase_20230727.vhd
      SpotStrategy: SpotAsPriceGo
      IoOptimized: optimized
      VSwitchId:
        Ref: EcsVSwitch1
      Password:
        Ref: InstancePassword
      InstanceName:
        'Fn::Sub': '${CommonName}_ecs_001'
      InstanceType:
        Ref: EcsInstanceType1
      ZoneId:
        Ref: Zone1
      MaxAmount: 1
  EcsInstanceGroup2:
    Type: 'ALIYUN::ECS::InstanceGroup'
    Properties:
      SystemDiskCategory: cloud_essd
      VpcId:
        Ref: EcsVpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      SystemDiskSize: 40
      ImageId: aliyun_3_x64_20G_alibase_20230727.vhd
      SpotStrategy: SpotAsPriceGo
      IoOptimized: optimized
      VSwitchId:
        Ref: EcsVSwitch2
      Password:
        Ref: InstancePassword
      InstanceName:
        'Fn::Sub': '${CommonName}_ecs_002'
      InstanceType:
        Ref: EcsInstanceType2
      ZoneId:
        Ref: Zone2
      MaxAmount: 1
  EcsVpc:
    Type: 'ALIYUN::ECS::VPC'
    Properties:
      VpcName:
        'Fn::Sub': '${CommonName}_vpc'
      CidrBlock: 192.168.0.0/16
  SlbBackendServerAttachment:
    Type: 'ALIYUN::SLB::BackendServerAttachment'
    Properties:
      BackendServerList:
        'Fn::ListMerge':
          - 'Fn::GetAtt':
              - EcsInstanceGroup1
              - InstanceIds
          - 'Fn::GetAtt':
              - EcsInstanceGroup2
              - InstanceIds
      BackendServerWeightList:
        - 100
        - 100
      LoadBalancerId:
        Ref: Slb
  Slb:
    Type: 'ALIYUN::SLB::LoadBalancer'
    Properties:
      AddressType: internet
      LoadBalancerName:
        'Fn::Sub': '${CommonName}-slb'
      InstanceChargeType: PayByCLCU
      PayType: PayOnDemand
  InstanceRunCommand:
    Type: 'ALIYUN::ECS::RunCommand'
    Properties:
      CommandContent:
        'Fn::Sub': >-
          #!/bin/bash

          if [ ! -f .ros.provision ]; then
            echo "Name: High-availability web service with shared storage" > .ros.provision
          fi


          name=$(grep "^Name:" .ros.provision | awk -F':' '{print $2}' | sed -e
          's/^[[:space:]]*//' -e 's/[[:space:]]*$//')

          if [[ "$name" != "High-availability web service with shared storage" ]]; then
            echo "This instance has already been configured using the one-click deployment of the \"$name\" tutorial. You cannot use the one-click deployment of this tutorial."
            exit 0
          fi


          echo "#########################"

          echo "# Check Network"

          echo "#########################"

          ping -c 2 -W 2 aliyun.com > /dev/null

          if [[ $? -ne 0 ]]; then
            echo "The current instance cannot access the public network."
            exit 0
          fi


          if ! grep -q "^Step1: Prepare Environment$" .ros.provision; then
            echo "#########################"
            echo "# Prepare Environment"
            echo "#########################"
            systemctl status firewalld
            systemctl stop firewalld
            echo "Step1: Prepare Environment" >> .ros.provision
          else
            echo "#########################"
            echo "# Environment has been ready"
            echo "#########################"
          fi


          if ! grep -q "^Step2: Install Nginx and deploy service$"
          .ros.provision; then
            echo "#########################"
            echo "# Install Nginx"
            echo "#########################"
            sudo yum -y install nginx
            sudo wget -O /usr/share/nginx/html/index.html https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20231013/jhgg/index.html
            sudo wget -O /usr/share/nginx/html/lipstick.png https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20230925/zevs/lipstick.png
            sudo systemctl start nginx
            sudo systemctl enable nginx
            echo "Step2: Install Nginx and deploy service" >> .ros.provision
          else
            echo "#########################"
            echo "# Nginx has been installed"
            echo "#########################"
          fi


          if ! grep -q "^Step3: Mount to the ECS" .ros.provision; then
            echo "#########################"
            echo "# Mount to the ECS"
            echo "#########################"
            mkdir /nas_master
            mkdir /nas_backup
            sudo yum install -y nfs-utils
            sudo echo "options sunrpc tcp_slot_table_entries=128" >>  /etc/modprobe.d/sunrpc.conf
            sudo echo "options sunrpc tcp_max_slot_table_entries=128" >>  /etc/modprobe.d/sunrpc.conf
            sudo mount -t nfs -o vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ${MasterNasMountTarget.MountTargetDomain}:/ /nas_master
            sudo mount -t nfs -o vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ${BackupNasMountTarget.MountTargetDomain}:/ /nas_backup
          
            sudo echo "${MasterNasMountTarget.MountTargetDomain}:/ /nas_master nfs vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,_netdev,noresvport 0 0" >> /etc/fstab
            
            sudo echo "${BackupNasMountTarget.MountTargetDomain}:/ /nas_backup nfs vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,_netdev,noresvport 0 0" >> /etc/fstab

            df -h | grep aliyun
          else
            echo "#########################"
            echo "# The ECS has been attached to the Nas"
            echo "#########################"
          fi


          if ! grep -q "^Step4: Shared file$" .ros.provision; then
            echo "#########################"
            echo "# Shared file"
            echo "#########################"
            sudo cp -Lvr /usr/share/nginx/html /nas_master
            sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
            echo "Step4: Shared file" >> .ros.provision
          else
            echo "#########################"
            echo "# File has been Shared"
            echo "#########################"
          fi


          if ! grep -q "^Step5: Install inotify-tools, rsync$" .ros.provision;
          then
            echo "#########################"
            echo "# Install inotify-tools, rsync"
            echo "#########################"
            sudo yum install -y inotify-tools rsync
            echo "Step6: Install inotify-tools, rsync" >> .ros.provision
          else
            echo "#########################"
            echo "# Inotify-tools has been installed"
            echo "#########################"
          fi

          if ! grep -q "^Step6: Install synchronization server$" .ros.provision;
          then
            echo "#########################"
            echo "# Install synchronization server"
            echo "#########################"
            sudo wget -P /etc/systemd/system/ https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20231017/pftz/sync_nas.sh
            sudo wget -P /etc/systemd/system/ https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/en-US/20230925/wmaj/sync_check_switch.sh
            sudo chmod +x /etc/systemd/system/sync_nas.sh
            sudo chmod +x /etc/systemd/system/sync_check_switch.sh
            cat > /etc/systemd/system/sync-check-switch.service << \EOF
          [Unit]

          Description=Sync Check Switch

          After=network.target


          [Service]

          ExecStart=/etc/systemd/system/sync_check_switch.sh

          RestartSec=3

          Restart=always


          [Install]

          WantedBy=default.target

          EOF

            cat > /etc/systemd/system/sync-nas.service << \EOF
          [Unit]

          Description=Sync NAS Service

          After=network.target


          [Service]

          ExecStart=/etc/systemd/system/sync_nas.sh

          Restart=always

          RestartSec=3


          [Install]

          WantedBy=default.target

          EOF

            sudo systemctl daemon-reload
            sudo systemctl start sync-nas.service
            sudo systemctl enable sync-check-switch.service
            sudo systemctl start sync-check-switch.service
            sudo systemctl enable sync-nas.service
            echo "Step6: Install " >> .ros.provision
          else
            echo "#########################"
            echo "# Synchronization server has been installed"
            echo "#########################"
          fi
      Type: RunShellScript
      Sync: true
      InstanceIds:
        - Ref: EcsInstanceGroup1
        - Ref: EcsInstanceGroup2
      Timeout: '300'
Metadata:
  'ALIYUN::ROS::Interface':
    ParameterGroups:
      - Parameters:
          - Zone1
          - Zone2
          - NasZone1
          - NasZone2
        Label:
          default:
            zh-cn: Zone Configuration
            en: Availability Zone
      - Parameters:
          - EcsInstanceType1
          - EcsInstanceType2
          - InstancePassword
        Label:
          default:
            zh-cn: ECS Instance Configuration
            en: Instance Configure
    TemplateTags:
      - 'acs:technical-solution:high-availability-architecture:high-availability-web-service-with-shared-storage-tech_solu_12'
    Hidden:
      - CommonName
{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Description": {
    "zh-cn": "Build a high-availability web service that includes dual-zone ECS instances, an SLB instance, and NAS mounts. The service supports automatic configuration synchronization and public network access.",
    "en": "Constructing a highly available web service comprises dual availability zone ECS instances, a Load Balancer (SLB), Network Attached Storage (NAS) mounts, automatic configuration synchronization, and is accessible via the public internet."
  },
  "Parameters": {
    "NasZone1": {
      "AssociationProperty": "ALIYUN::ECS::Instance::ZoneId",
      "Type": "String",
      "Description": {
        "zh-cn": "Zone 1 must be different from Zone 2.",
        "en": "Availability zone 1 must be different from Availability zone 2."
      },
      "Label": {
        "zh-cn": "NAS Zone 1",
        "en": "NAS Availability Zone1"
      }
    },
    "NasZone2": {
      "AssociationProperty": "ALIYUN::ECS::Instance::ZoneId",
      "Type": "String",
      "Description": {
        "zh-cn": "Zone 2 must be different from Zone 1.",
        "en": "Availability zone 2 must be different from Availability zone 1."
      },
      "Label": {
        "zh-cn": "NAS Zone 2",
        "en": "NAS Availability Zone2"
      }
    },
    "CommonName": {
      "Default": "high-availability",
      "Type": "String"
    },
    "InstancePassword": {
      "Type": "String",
      "Description": {
        "zh-cn": "The logon password of the server. The password must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters include ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/",
        "en": "Server login password, Length 8~30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in)."
      },
      "MinLength": 8,
      "Label": {
        "zh-cn": "Instance Password",
        "en": "Instance Password"
      },
      "AllowedPattern": "[0-9A-Za-z\\_\\-\\&:;'<>,=%`~!@#\\(\\)\\$\\^\\*\\+\\|\\{\\}\\[\\]\\.\\?\\/]+$",
      "NoEcho": true,
      "MaxLength": 30,
      "AssociationProperty": "ALIYUN::ECS::Instance::Password",
      "ConstraintDescription": {
        "zh-cn": "The password must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters include ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/",
        "en": "Length 8~30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in)."
      }
    },
    "EcsInstanceType2": {
      "AssociationProperty": "ALIYUN::ECS::Instance::InstanceType",
      "AssociationPropertyMetadata": {
        "SystemDiskCategory": "cloud_essd",
        "InstanceChargeType": "PostPaid",
        "ZoneId": "${Zone2}"
      },
      "Type": "String",
      "Label": {
        "zh-cn": "Instance Type of Zone 2",
        "en": "Instance Type Of Availability Zone2"
      }
    },
    "Zone2": {
      "AssociationProperty": "ALIYUN::ECS::Instance::ZoneId",
      "Type": "String",
      "Description": {
        "zh-cn": "Zone 2 must be different from Zone 1.",
        "en": "Availability zone 2 must be different from Availability zone 1."
      },
      "Label": {
        "zh-cn": "vSwitch Zone 2",
        "en": "VSwitch Availability Zone2"
      }
    },
    "Zone1": {
      "AssociationProperty": "ALIYUN::ECS::Instance::ZoneId",
      "Type": "String",
      "Description": {
        "zh-cn": "Zone 1 must be different from Zone 2.",
        "en": "Availability zone 1 must be different from Availability zone 2."
      },
      "Label": {
        "zh-cn": "vSwitch Zone 1",
        "en": "VSwitch Availability Zone1"
      }
    },
    "EcsInstanceType1": {
      "AssociationProperty": "ALIYUN::ECS::Instance::InstanceType",
      "AssociationPropertyMetadata": {
        "SystemDiskCategory": "cloud_essd",
        "InstanceChargeType": "PostPaid",
        "ZoneId": "${Zone1}"
      },
      "Type": "String",
      "Label": {
        "zh-cn": "Instance Type of Zone 1",
        "en": "Instance Type Of Availability Zone1"
      }
    }
  },
  "Rules": {
    "DifferentZones2": {
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": {
              "Fn::Equals": [
                {
                  "Ref": "NasZone1"
                },
                {
                  "Ref": "NasZone2"
                }
              ]
            }
          },
          "AssertDescription": "NAS Zones must be different"
        }
      ]
    },
    "DifferentZones1": {
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": {
              "Fn::Equals": [
                {
                  "Ref": "Zone1"
                },
                {
                  "Ref": "Zone2"
                }
              ]
            }
          },
          "AssertDescription": "ECS Zones must be different"
        }
      ]
    }
  },
  "Outputs": {
    "ECS1URL": {
      "Description": "ECS 1 URL",
      "Value": {
        "Fn::Sub": [
          "https://ecs.console.alibabacloud.com/#/server/region/${region}?instanceIds=${InstanceID}",
          {
            "InstanceID": {
              "Fn::Select": [
                "0",
                {
                  "Fn::GetAtt": [
                    "EcsInstanceGroup1",
                    "InstanceIds"
                  ]
                }
              ]
            },
            "region": {
              "Ref": "ALIYUN::Region"
            }
          }
        ]
      }
    },
    "FileSystemId1": {
      "Description": {
        "zh-cn": "Master NAS",
        "en": "Master NAS"
      },
      "Value": {
        "Fn::Sub": [
          "https://nas.console.alibabacloud.com/${region}/filesystem/${InstanceID}",
          {
            "InstanceID": {
              "Fn::GetAtt": [
                "MasterFileSystem",
                "FileSystemId"
              ]
            },
            "region": {
              "Ref": "ALIYUN::Region"
            }
          }
        ]
      }
    },
    "ECS2URL": {
      "Description": "ECS 2 URL",
      "Value": {
        "Fn::Sub": [
          "https://ecs.console.alibabacloud.com/#/server/region/${region}?instanceIds=${InstanceID}",
          {
            "InstanceID": {
              "Fn::Select": [
                "0",
                {
                  "Fn::GetAtt": [
                    "EcsInstanceGroup1",
                    "InstanceIds"
                  ]
                }
              ]
            },
            "region": {
              "Ref": "ALIYUN::Region"
            }
          }
        ]
      }
    },
    "SlbIpAddress": {
      "Description": {
        "zh-cn": "The public IP address exposed to the Internet.",
        "en": "Public IP Addresses"
      },
      "Value": {
        "Fn::Sub": [
          "http://${ServerAddress}",
          {
            "ServerAddress": {
              "Fn::GetAtt": [
                "Slb",
                "IpAddress"
              ]
            }
          }
        ]
      }
    },
    "FileSystemId2": {
      "Description": {
        "zh-cn": "Secondary NAS",
        "en": "Backup NAS"
      },
      "Value": {
        "Fn::Sub": [
          "https://nas.console.alibabacloud.com/${region}/filesystem/${InstanceID}",
          {
            "InstanceID": {
              "Fn::GetAtt": [
                "BackupFileSystem",
                "FileSystemId"
              ]
            },
            "region": {
              "Ref": "ALIYUN::Region"
            }
          }
        ]
      }
    },
    "MountInfo1": {
      "Description": {
        "zh-cn": "NAS mount directory 1 on the ECS instance",
        "en": "NAS mounting directory 1 on ECS"
      },
      "Value": "/nas_master"
    },
    "MountInfo2": {
      "Description": {
        "zh-cn": "NAS mount directory 2 on the ECS instance",
        "en": "NAS mounting directory 2 on ECS"
      },
      "Value": "/nas_backup"
    }
  },
  "Resources": {
    "SlbListener": {
      "Type": "ALIYUN::SLB::Listener",
      "Properties": {
        "Protocol": "http",
        "HealthCheck": {
          "HealthCheckType": "http",
          "Interval": 2,
          "URI": "/",
          "UnhealthyThreshold": 3,
          "HealthyThreshold": 3,
          "Timeout": 5,
          "HttpCode": "http_2xx,http_3xx,http_4xx,http_5xx",
          "Port": 80
        },
        "ListenerPort": 80,
        "Bandwidth": 10,
        "BackendServerPort": 80,
        "LoadBalancerId": {
          "Ref": "Slb"
        }
      },
      "DependsOn": [
        "Slb"
      ]
    },
    "EcsSecurityGroup": {
      "Type": "ALIYUN::ECS::SecurityGroup",
      "Properties": {
        "SecurityGroupIngress": [
          {
            "Priority": 1,
            "PortRange": "80/80",
            "NicType": "internet",
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          }
        ],
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "SecurityGroupEgress": [
          {
            "Priority": 1,
            "PortRange": "-1/-1",
            "DestCidrIp": "0.0.0.0/0",
            "NicType": "internet",
            "IpProtocol": "all"
          },
          {
            "Priority": 1,
            "PortRange": "-1/-1",
            "DestCidrIp": "0.0.0.0/0",
            "NicType": "intranet",
            "IpProtocol": "all"
          }
        ],
        "SecurityGroupName": {
          "Fn::Sub": "${CommonName}_sg"
        }
      }
    },
    "MasterNasMountTarget": {
      "Type": "ALIYUN::NAS::MountTarget",
      "Properties": {
        "NetworkType": "Vpc",
        "FileSystemId": {
          "Ref": "MasterFileSystem"
        },
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "VSwitchId": {
          "Ref": "EcsVSwitch3"
        },
        "AccessGroupName": "DEFAULT_VPC_GROUP_NAME"
      }
    },
    "EcsVSwitch4": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "VSwitchName": {
          "Fn::Sub": "${CommonName}_vsw_002"
        },
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "CidrBlock": "192.168.4.0/24",
        "ZoneId": {
          "Ref": "NasZone2"
        }
      }
    },
    "MasterFileSystem": {
      "Type": "ALIYUN::NAS::FileSystem",
      "Properties": {
        "StorageType": "Capacity",
        "ProtocolType": "NFS",
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "Description": "MasterNAS",
        "ZoneId": {
          "Ref": "NasZone1"
        }
      }
    },
    "EcsVSwitch2": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "VSwitchName": {
          "Fn::Sub": "${CommonName}_vsw_002"
        },
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "CidrBlock": "192.168.2.0/24",
        "ZoneId": {
          "Ref": "Zone2"
        }
      }
    },
    "EcsVSwitch3": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "VSwitchName": {
          "Fn::Sub": "${CommonName}_vsw_002"
        },
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "CidrBlock": "192.168.3.0/24",
        "ZoneId": {
          "Ref": "NasZone1"
        }
      }
    },
    "EcsVSwitch1": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "VSwitchName": {
          "Fn::Sub": "${CommonName}_vsw_001"
        },
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "CidrBlock": "192.168.1.0/24",
        "ZoneId": {
          "Ref": "Zone1"
        }
      }
    },
    "BackupFileSystem": {
      "Type": "ALIYUN::NAS::FileSystem",
      "Properties": {
        "StorageType": "Capacity",
        "ProtocolType": "NFS",
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "Description": "BackupNAS",
        "ZoneId": {
          "Ref": "NasZone2"
        }
      }
    },
    "BackupNasMountTarget": {
      "Type": "ALIYUN::NAS::MountTarget",
      "Properties": {
        "NetworkType": "Vpc",
        "FileSystemId": {
          "Ref": "BackupFileSystem"
        },
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "VSwitchId": {
          "Ref": "EcsVSwitch4"
        },
        "AccessGroupName": "DEFAULT_VPC_GROUP_NAME"
      }
    },
    "EcsInstanceGroup1": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "Properties": {
        "SystemDiskCategory": "cloud_essd",
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "SecurityGroupId": {
          "Ref": "EcsSecurityGroup"
        },
        "SystemDiskSize": 40,
        "ImageId": "aliyun_3_x64_20G_alibase_20230727.vhd",
        "SpotStrategy": "SpotAsPriceGo",
        "IoOptimized": "optimized",
        "VSwitchId": {
          "Ref": "EcsVSwitch1"
        },
        "Password": {
          "Ref": "InstancePassword"
        },
        "InstanceName": {
          "Fn::Sub": "${CommonName}_ecs_001"
        },
        "InstanceType": {
          "Ref": "EcsInstanceType1"
        },
        "ZoneId": {
          "Ref": "Zone1"
        },
        "MaxAmount": 1
      }
    },
    "EcsInstanceGroup2": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "Properties": {
        "SystemDiskCategory": "cloud_essd",
        "VpcId": {
          "Ref": "EcsVpc"
        },
        "SecurityGroupId": {
          "Ref": "EcsSecurityGroup"
        },
        "SystemDiskSize": 40,
        "ImageId": "aliyun_3_x64_20G_alibase_20230727.vhd",
        "SpotStrategy": "SpotAsPriceGo",
        "IoOptimized": "optimized",
        "VSwitchId": {
          "Ref": "EcsVSwitch2"
        },
        "Password": {
          "Ref": "InstancePassword"
        },
        "InstanceName": {
          "Fn::Sub": "${CommonName}_ecs_002"
        },
        "InstanceType": {
          "Ref": "EcsInstanceType2"
        },
        "ZoneId": {
          "Ref": "Zone2"
        },
        "MaxAmount": 1
      }
    },
    "EcsVpc": {
      "Type": "ALIYUN::ECS::VPC",
      "Properties": {
        "VpcName": {
          "Fn::Sub": "${CommonName}_vpc"
        },
        "CidrBlock": "192.168.0.0/16"
      }
    },
    "SlbBackendServerAttachment": {
      "Type": "ALIYUN::SLB::BackendServerAttachment",
      "Properties": {
        "BackendServerList": {
          "Fn::ListMerge": [
            {
              "Fn::GetAtt": [
                "EcsInstanceGroup1",
                "InstanceIds"
              ]
            },
            {
              "Fn::GetAtt": [
                "EcsInstanceGroup2",
                "InstanceIds"
              ]
            }
          ]
        },
        "BackendServerWeightList": [
          100,
          100
        ],
        "LoadBalancerId": {
          "Ref": "Slb"
        }
      }
    },
    "Slb": {
      "Type": "ALIYUN::SLB::LoadBalancer",
      "Properties": {
        "AddressType": "internet",
        "LoadBalancerName": {
          "Fn::Sub": "${CommonName}-slb"
        },
        "InstanceChargeType": "PayByCLCU",
        "PayType": "PayOnDemand"
      }
    },
    "InstanceRunCommand": {
      "Type": "ALIYUN::ECS::RunCommand",
      "Properties": {
        "CommandContent": {
          "Fn::Sub": "#!/bin/bash\nif [ ! -f .ros.provision ]; then\n  echo \"Name: High-availability web service with shared storage\" > .ros.provision\nfi\n\nname=$(grep \"^Name:\" .ros.provision | awk -F':' '{print $2}' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')\nif [[ \"$name\" != \"High-availability web service with shared storage\" ]]; then\n  echo \"This instance has already been configured using the one-click deployment of the \\\"$name\\\" tutorial. You cannot use the one-click deployment of this tutorial.\"\n  exit 0\nfi\n\necho \"#########################\"\necho \"# Check Network\"\necho \"#########################\"\nping -c 2 -W 2 aliyun.com > /dev/null\nif [[ $? -ne 0 ]]; then\n  echo \"The current instance cannot access the public network.\"\n  exit 0\nfi\n\nif ! grep -q \"^Step1: Prepare Environment$\" .ros.provision; then\n  echo \"#########################\"\n  echo \"# Prepare Environment\"\n  echo \"#########################\"\n  systemctl status firewalld\n  systemctl stop firewalld\n  echo \"Step1: Prepare Environment\" >> .ros.provision\nelse\n  echo \"#########################\"\n  echo \"# Environment has been ready\"\n  echo \"#########################\"\nfi\n\nif ! grep -q \"^Step2: Install Nginx and deploy service$\" .ros.provision; then\n  echo \"#########################\"\n  echo \"# Install Nginx\"\n  echo \"#########################\"\n  sudo yum -y install nginx\n  sudo wget -O /usr/share/nginx/html/index.html https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20231013/jhgg/index.html\n  sudo wget -O /usr/share/nginx/html/lipstick.png https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20230925/zevs/lipstick.png\n  sudo systemctl start nginx\n  sudo systemctl enable nginx\n  echo \"Step2: Install Nginx and deploy service\" >> .ros.provision\nelse\n  echo \"#########################\"\n  echo \"# Nginx has been installed\"\n  echo \"#########################\"\nfi\n\nif ! grep -q \"^Step3: Mount to the ECS\" .ros.provision; then\n  echo \"#########################\"\n  echo \"# Mount to the ECS\"\n  echo \"#########################\"\n  mkdir /nas_master\n  mkdir /nas_backup\n  sudo yum install -y nfs-utils\n  sudo echo \"options sunrpc tcp_slot_table_entries=128\" >>  /etc/modprobe.d/sunrpc.conf\n  sudo echo \"options sunrpc tcp_max_slot_table_entries=128\" >>  /etc/modprobe.d/sunrpc.conf\n  sudo mount -t nfs -o vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ${MasterNasMountTarget.MountTargetDomain}:/ /nas_master\n  sudo mount -t nfs -o vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport ${BackupNasMountTarget.MountTargetDomain}:/ /nas_backup\n\n  sudo echo \"${MasterNasMountTarget.MountTargetDomain}:/ /nas_master nfs vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,_netdev,noresvport 0 0\" >> /etc/fstab\n  \n  sudo echo \"${BackupNasMountTarget.MountTargetDomain}:/ /nas_backup nfs vers=3,nolock,proto=tcp,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,_netdev,noresvport 0 0\" >> /etc/fstab\n\n  df -h | grep aliyun\nelse\n  echo \"#########################\"\n  echo \"# The ECS has been attached to the Nas\"\n  echo \"#########################\"\nfi\n\nif ! grep -q \"^Step4: Shared file$\" .ros.provision; then\n  echo \"#########################\"\n  echo \"# Shared file\"\n  echo \"#########################\"\n  sudo cp -Lvr /usr/share/nginx/html /nas_master\n  sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak\n  echo \"Step4: Shared file\" >> .ros.provision\nelse\n  echo \"#########################\"\n  echo \"# File has been Shared\"\n  echo \"#########################\"\nfi\n\nif ! grep -q \"^Step5: Install inotify-tools, rsync$\" .ros.provision; then\n  echo \"#########################\"\n  echo \"# Install inotify-tools, rsync\"\n  echo \"#########################\"\n  sudo yum install -y inotify-tools rsync\n  echo \"Step6: Install inotify-tools, rsync\" >> .ros.provision\nelse\n  echo \"#########################\"\n  echo \"# Inotify-tools has been installed\"\n  echo \"#########################\"\nfi\nif ! grep -q \"^Step6: Install synchronization server$\" .ros.provision; then\n  echo \"#########################\"\n  echo \"# Install synchronization server\"\n  echo \"#########################\"\n  sudo wget -P /etc/systemd/system/ https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20231017/pftz/sync_nas.sh\n  sudo wget -P /etc/systemd/system/ https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/en-US/20230925/wmaj/sync_check_switch.sh\n  sudo chmod +x /etc/systemd/system/sync_nas.sh\n  sudo chmod +x /etc/systemd/system/sync_check_switch.sh\n  cat > /etc/systemd/system/sync-check-switch.service << \\EOF\n[Unit]\nDescription=Sync Check Switch\nAfter=network.target\n\n[Service]\nExecStart=/etc/systemd/system/sync_check_switch.sh\nRestartSec=3\nRestart=always\n\n[Install]\nWantedBy=default.target\nEOF\n\n  cat > /etc/systemd/system/sync-nas.service << \\EOF\n[Unit]\nDescription=Sync NAS Service\nAfter=network.target\n\n[Service]\nExecStart=/etc/systemd/system/sync_nas.sh\nRestart=always\nRestartSec=3\n\n[Install]\nWantedBy=default.target\nEOF\n\n  sudo systemctl daemon-reload\n  sudo systemctl start sync-nas.service\n  sudo systemctl enable sync-check-switch.service\n  sudo systemctl start sync-check-switch.service\n  sudo systemctl enable sync-nas.service\n  echo \"Step6: Install \" >> .ros.provision\nelse\n  echo \"#########################\"\n  echo \"# Synchronization server has been installed\"\n  echo \"#########################\"\nfi"
        },
        "Type": "RunShellScript",
        "Sync": true,
        "InstanceIds": [
          {
            "Ref": "EcsInstanceGroup1"
          },
          {
            "Ref": "EcsInstanceGroup2"
          }
        ],
        "Timeout": "300"
      }
    }
  },
  "Metadata": {
    "ALIYUN::ROS::Interface": {
      "ParameterGroups": [
        {
          "Parameters": [
            "Zone1",
            "Zone2",
            "NasZone1",
            "NasZone2"
          ],
          "Label": {
            "default": {
              "zh-cn": "Zone Configuration",
              "en": "Availability Zone"
            }
          }
        },
        {
          "Parameters": [
            "EcsInstanceType1",
            "EcsInstanceType2",
            "InstancePassword"
          ],
          "Label": {
            "default": {
              "zh-cn": "ECS Instance Configuration",
              "en": "Instance Configure"
            }
          }
        }
      ],
      "TemplateTags": [
        "acs:technical-solution:high-availability-architecture:high-availability-web-service-with-shared-storage-tech_solu_12"
      ],
      "Hidden": [
        "CommonName"
      ]
    }
  }
}

Pour plus d'exemples, consultez les modèles publics contenant cette ressource.