
# 编写IaC脚本
#### IaC目录规划
IaC脚本开发规范请参考[应用平台IaC部署代码开发](https://support.huaweicloud.com/devg-appstage/appstage_06_0013.html)，本实践中，IaC包结构规划如下：
表1IaC Spec包结构说明 
| 位置                             | 描述                                                         |
|:---|:---|
| iacspec                        | IaC压缩包                                                     |
| └── global/                    | 全局默认的IaC描述，包含完整文件结构。                                       |
| │ └── meta.yaml                | 变更策略描述                                                     |
| └── specs/                     | 环境特定的IaC描述，结构与global相同，但仅包含与global有差异的文件。                  |
| │ └── cn_green_cbu_default/    | 研发联调环境，命名采用站点级Cloud Map的名称，可以在环境管理界面查看可选的站点级Cloud Map名称列表。 |
| │ └── DemoOrgidLogin/          | 微服务DemoOrgidLogin。                                         |
| │ └── config/                  | DemoOrgidLogin的配置目录。                                       |
| │ └── aiops_sidecar_param.json | 接入AIOps服务的配置文件。                                            |
| │ └── config_records.yaml      | DemoOrgidLogin的业务配置项。                                      |
| │ └── config_schema.yaml       | 声明DemoOrgidLogin的业务配置项属性，敏感业务配置项需要声明，非敏感配置项可以不声明。          |
| │ └── envs.yaml                | 用于配置和管理DemoOrgidLogin的环境变量。                                |
| │ └── hosts.yaml               | 配置主机域名映射。                                                  |
| │ └── resources.yaml           | DemoOrgidLogin的资源列表。                                       |
| │ └── values.yaml              | 定义DemoOrgidLogin的资源列表中使用的变量。                               |
| │ └── DemoServiceAService/     | 微服务DemoServiceAService                                     |
| │ └── config/                  | ServiceA的配置目录。                                             |
| │ └── aiops_sidecar_param.json | 接入AIOps服务的配置文件。                                            |
| │ └── config_records.yaml      | ServiceA的业务配置项。                                            |
| │ └── config_schema.yaml       | 声明ServiceA的业务配置项属性，敏感业务配置项需要声明，非敏感配置项可以不声明。                |
| │ └── envs.yaml                | 用于配置和管理ServiceA的环境变量。                                      |
| │ └── hosts.yaml               | 配置主机域名映射。                                                  |
| │ └── resources.yaml           | ServiceA的资源列表。                                             |
| │ └── values.yaml              | 定义ServiceA的资源列表中使用的变量。                                     |
| │ └── DemoServiceBService/     | 微服务DemoServiceBService。                                    |
| │ └── config/                  | ServiceB的配置目录。                                             |
| │ └── aiops_sidecar_param.json | 接入AIOps服务的配置文件。                                            |
| │ └── config_records.yaml      | ServiceB的业务配置项。                                            |
| │ └── config_schema.yaml       | 声明ServiceB的业务配置项属性，敏感业务配置项需要声明，非敏感配置项可以不声明。                |
| │ └── envs.yaml                | 用于配置和管理ServiceB的环境变量。                                      |
| │ └── hosts.yaml               | 配置主机域名映射。                                                  |
| │ └── resources.yaml           | ServiceB的资源列表。                                             |
| │ └── values.yaml              | 定义ServiceB的资源列表中使用的变量。                                     |
| └── package.json               | 包描述文件。                                                     |
   
#### 对接SLB的准备工作
在AppStage运维中心[创建SLB实例](https://support.huaweicloud.com/usermanual-wiseeye/appstage_04_0355.html)，[配置SLB节点信息](https://support.huaweicloud.com/usermanual-wiseeye/appstage_04_0357.html)，并[在SLB中创建监听](https://support.huaweicloud.com/usermanual-wiseeye/appstage_04_0367.html)。在本实践中详细操作如下：
1. 创建SLB实例。
   1. 登录[AppStage首页](https://appstage.huaweicloud.com/portal/home)。
   
   2. 在快捷入口选择"运维中心"，进入运维中心。
   
   3. 在顶部导航栏选择服务。
   
   4. 单击![](https://support.huaweicloud.com/bestpractice-appstage/zh-cn_image_0000001835172682.png)，选择"微服务开发 \> 负载均衡"。
   
   5. 选择左侧导航栏的"实例管理"。
   
   6. 在实例列表页面，单击"创建实例"。
   
   7. 在"选择电子流"窗口中，选择以下任一方式：
      - 运维操作记录选择"关联电子流"，并选择要关联的电子流，单击"提交"。
      
      - 运维操作记录选择"紧急问题处理"，并填写紧急原因，单击"提交"。
       
   
   8. 在创建实例页面，配置相关参数，参数说明如[表2]所示。
       表2基本信息参数说明 
      | 参数     | 说明                                                                                                                            |
      |:---|:---|
      | 实例名称   | 实例的名称，本实践中实例名称为jamestest。 字符长度0\~50，可以由字母、数字、下划线、短横线、点组成，不能包含特殊字符。容器部署的实例名称开头只能是字母，结尾只能是字母或数字。 |
      | 可用模式   | 选择可用模式。 自管理模式：采用自己的节点，将公有云ECS作为SLB主机，SLB主机由业务申请、维护，手动挂载ELB。     |
      | SLB版本  | 选择SLB版本。                                                                                                                      |
      | 部署规格   | 选择部署规格，支持2C8G、4C16G、8C32G、16C64G、32C128G。                                                                                     |
      | 单AZ节点数 | 每个AZ部署的节点个数。                                                                                                                  |
      | 注册中心   | 选择一个注册中心，即Cloud Map，将实例注册到注册中心。                                                                                               |
      | 部署区域   | 以实际自管理区域为准，与注册中心无关。                                                                                                           |
      | 部署AZ   | 以实际自管理区域为准，与注册中心无关。                                                                                                           |
         
      
   
   9. 在弹出的对话框中单击"确定"，提交创建实例申请。 在实例列表中会生成一条实例记录，实例状态为"running"。
      
    
2. 配置SLB节点信息。
   自管理模式的SLB实例需要配置节点信息。
   1. 在实例列表中单击实例名称，进入实例详情页面。
   
   2. 选择"SLB节点信息"页签，单击"编辑"。
   
   3. 单击"新增节点"，配置IP和主机名。 IP为SLB所部署的服务器的私网地址。
      在Appstage运维中心主机管理服务中，选择"云服务器管理 \> 弹性云服务器"，查看IP地址和主机名称。
      
   
   4. 单击"保存"。
     
3. 创建监听。
   1. 选择左侧导航栏的"监听管理"，单击"创建监听"。
   
   2. 在"选择电子流"窗口中，选择以下任一方式：
      - 运维操作记录选择"关联电子流"，并选择要关联的电子流，单击"提交"。
      
      - 运维操作记录选择"紧急问题处理"，并填写紧急原因，单击"提交"。
       
   
   3. 配置监听基本信息，关联SLB实例，具体配置请参见[表3]，单击"下一步"。
       表3创建监听参数说明 
      | 参数       | 说明                                                                                                                         |
      |:---|:---|
      | 监听名称（英文） | SLB监听的英文名称。本实践中监听名称为jamestest_listener。 长度\<=50，不能包含-in-字符，不能以in-开头，不能以.conf结尾，不能包含特殊字符。 |
      | 监听名称（中文） | SLB监听的中文名称。                                                                                                                |
      | 注册中心     | 选择监听关联的实例所在的注册中心。                                                                                                          |
      | 所属服务     | 监听所属的服务。                                                                                                                   |
      | 关联SLB实例  | 选择SLB实例，仅能关联同一注册中心下的SLB实例。                                                                                                 |
         
      
   
   4. 在创建后端服务器集群、健康检查、配置监听、配置转发策略、动态路由规则页面，依次单击"下一步"。 此处只需要配置监听基本信息并绑定SLB实例，健康检查及转发策略等其他信息在软件包部署完成后再进行配置。
      
   
   5. 查看总览，单击"保存"。
    
 
#### 编写IaC脚本
1. 在global目录下的meta.yaml中描述ServiceA、ServiceB以及DemoOrgidLogin间的变更流程以及变更策略。并行变更DemoServiceAService、DemoServiceBService及DemoOrgidLogin。 
   ```
   type: WiseCloud::Environment
   applyPipeline: environment-deploy
   pipelines:
     - name: environment-deploy
       action: Serial
       tasks:
         - name: apply-microservices
           action: Parallel
           tasks:
             - name: apply-demoservicea
               action: Apply
               component:
                 name: DemoServiceAService
             - name: apply-demoserviceb
               action: Apply
               component:
                 name: DemoServiceBService
             - name: apply-demoorgidlogin
               action: Apply
               component:
                 name: DemoOrgidLogin
   ```
   
   
2. 在specs目录下的config配置目录中，增加如下内容： 
   - DemoOrgidLogin
     - aiops_sidecar_param.json：
       ```
       {
         "iacConfigName" : "DemoOrgidLoginServiceLog",
         "configItems" : [
           {
             "logSpaceName" : "springclouddemo",
             "accessConfigName" : "demoorgidlogin_run_log_1677484473569",
             "accessConfigDetail" : {
               "logPath" : "/opt/huawei/logs/demoorgidlogin/run",
               "logMode" : "MULTI_LINE",
               "multilineConfig" : {
                 "pattern" : "^\\[[0-9]{4}-[0-9]{2}-[0-9]{2}"
               }
             }
           },
           {
             "logSpaceName" : "springclouddemo",
             "accessConfigName" : "demoorgidlogin_debug_log_1677484428961",
             "accessConfigDetail" : {
               "logPath" : "/opt/huawei/logs/demoorgidlogin/debug",
               "logMode" : "MULTI_LINE",
               "multilineConfig" : {
                 "pattern" : "^\\[[0-9]{4}-[0-9]{2}-[0-9]{2}"
               }
             }
           }
         ]
       }
       ```
       
     
     - 在config_records.yaml配置微服务的业务配置项。
       ```
       #sts
       sts.server.domain: 10.202.251.196:8080  #sts(ACMS)接入地址
       sts.config.path: /opt/huawei/certs/jamesService22A/DemoOrgidLogin/DemoOrgidLogin.ini   #sts(ACMS)微服务证书路径，iac3.0会将证书放在固定路径下，格式为/opt/huawei/certs/服务名/微服务名/微服务名.ini
       #redis
       #注意：在华为云购买Redis必须与服务部署的后端集群在同一个子网，否则网络不通无法访问
       spring.redis.host: 172.16.0.189   #Redis访问地址
       spring.redis.port: 6379  #Redis访问端口
       spring.redis.password: MicroService/jamesService22A/DemoOrgidLogin/spring.redis.password/default  #Redis访问密码，属于敏感配置项，已被STS(ACMS)纳管，配置路径为：MicroService/服务名/微服务名/敏感配置项名称/敏感配置项标签
       #OrgID
       org.url: http://org-app.huawei.com:8080  #OrgID后端访问地址
       org.web-url: https://orgid-beta.xxx.huawei.com   #OrgID前端访问地址
       org.app.cookie-domain: huawei.com   #cookie域名
       org.app.jwt-key: MicroService/jamesService22A/DemoOrgidLogin/org.app.jwt-key/default  #使用Redis储存token的密钥，属于敏感配置项，已被STS(ACMS)纳管，配置路径为：MicroService/服务名/微服务名/敏感配置项名称/敏感配置项标签
       org.app.ent-point-url: http://org-app.huawei.com:8080                                 #登录或登出后页面重定向地址
       org.app.protocol-login.oauth.clientId: fd9f15082b80a6b6c3940c996df9b917f246936244caaee8e4a9ed3404c89364  #OrgID登录时所需的客户端ID，需要在OrgID申请应用获得
       org.app.protocol-login.oauth.clientSecret: MicroService/jamesService22A/DemoOrgidLogin/org.app.protocol-login.oauth.clientSecret/default  #OrgID登录时所需的客户端密钥，需要在OrgID申请应用获得，属于敏感配置项，已被STS(ACMS)纳管，配置路径为：MicroService/服务名/微服务名/敏感配置项名称/敏感配置项标签
       demo.login.url: http://org-app.huawei.com:8080/login                           #demo的登录地址
       #Cloud Map
       nuwa.cloudmap.serverAddr: http://10.202.252.191:8081                           #Cloud Map访问地址
       nuwa.cloudmap.namespaceName: cn_green_cbu_default_9190086000001322775_default  #Cloud Map访问命名空间
       nuwa.cloudmap.version: 1.0.0.100                                               #微服务版本号
       nuwa.cloudmap.clusterName: default                                             #当前注册到Cloud Map集群名
       nuwa.cloudmap.provider.cluster: default                                        #提供服务的其他同样被注册到Cloud Map的微服务集群名
       ```
       
     
     - 在config_schema.yaml中声明微服务的敏感业务配置项。
       ```
       type: object
       properties:
         spring.redis.password:                       #声明spring.redis.password为敏感业务配置项。
           format: sensitive
         org.app.protocol-login.oauth.clientSecret:   #声明org.app.protocol-login.oauth.clientSecret为敏感业务配置项。
           format: sensitive
       ```
       
     
     - 在envs.yaml文件中定义环境变量。
       ```
       - name: NUWA_CLOUDMAP_SERVERADDR
         value: 'http://10.202.252.191:8081'
       ```
       
     
     - 在hosts.yaml中配置主机域名映射。
       ```
       - hostName: org-app.huawei.com    #对接OrgID，OrgID服务的域名解析
         ip: 172.16.0.57                 #OrgID服务的IP
       ```
       
      
   
   - DemoServiceAService和DemoServiceBService，此处以DemoServiceAService为例：
     - aiops_sidecar_param.json：
       ```
       {
         "iacConfigName" : "DemoServiceAServiceLog",
         "configItems" : [
           {
             "logSpaceName" : "springclouddemo",
             "accessConfigName" : "demoserviceaservice_run_log_1677484473569",
             "accessConfigDetail" : {
               "logPath" : "/opt/huawei/logs/demoserviceaservice/run",
               "logMode" : "MULTI_LINE",
               "multilineConfig" : {
                 "pattern" : "^\\[[0-9]{4}-[0-9]{2}-[0-9]{2}"
               }
             }
           },
           {
             "logSpaceName" : "springclouddemo",
             "accessConfigName" : "demoserviceaservice_debug_log_1677484428961",
             "accessConfigDetail" : {
               "logPath" : "/opt/huawei/logs/demoserviceaservice/debug",
               "logMode" : "MULTI_LINE",
               "multilineConfig" : {
                 "pattern" : "^\\[[0-9]{4}-[0-9]{2}-[0-9]{2}"
               }
             }
           }
         ]
       }
       ```
       
     
     - 在config_records.yaml配置微服务的业务配置项。
       ```
       #STS
       sts.server.domain: 10.202.251.196:8080     #STS接入地址
       sts.config.path: /opt/huawei/certs/jamesService22A/DemoServiceAService/DemoServiceAService.ini   #STS微服务证书路径，iac3.0会将证书放在固定路径下，格式为/opt/huawei/certs/服务名/微服务名/微服务名.ini
       #Cloud Map
       nuwa.cloudmap.serverAddr: http://10.202.252.191:8081   #Cloud Map访问地址
       nuwa.cloudmap.namespaceName: cn_green_cbu_default_9190086000001322775_default    #Cloud Map访问命名空间
       nuwa.cloudmap.version: 1.0.0.100          #微服务版本号
       nuwa.cloudmap.clusterName: default        #当前注册到Cloud Map集群名
       nuwa.cloudmap.provider.cluster: default   #提供服务的其他同样被注册到Cloud Map的微服务集群名
       #WiseDBA
       wiseDba.appName: jamesService22A           #在AppStage中创建的服务名称
       wiseDba.groupKey: gauss-SpringCloudDemo2   #WiseDBA纳管的数据库实例名称
       wiseDba.dbName: springclouddemoa           #数据库名称（数据库实例中的Schema名称）
       demo.login.url: http://org-app.huawei.com:8080/login     #demo登录地址
       demo.login.enable: true                                  #是否开启demo登录功能
       demo.service-url.demoOrgidLogin: http://DemoOrgidLogin   #demo登录功能的微服务访问地址
       ```
       
     
     - 在config_schema.yaml中声明微服务的敏感业务配置项。
       ```
       type: object
       ```
       
     
     - 在envs.yaml文件中定义环境变量。
       ```
       - name: NUWA_CLOUDMAP_SERVERADDR
         value: 'http://10.202.252.191:8081'
       ```
       
     
     - 在hosts.yaml中配置主机host，即本地域名和IP的映射。
       ```
       - hostName: localhost.huawei.com
         ip: 127.0.0.1
       ```
       
      
   
   
   
   
3. 在resources.yaml中定义资源。 
   微服务下所有的资源描述都存放于resources.yaml中，此处以DemoOrgidLogin微服务为例，本实践中资源定义如下：
   ```
   - name: DemoOrgidLogin                                     #Cluster Name: 2 <= len <= 16
     type: WiseCloud::MicroService::NuwaContainer
     properties:
       microserviceName: DemoOrgidLogin                       #STS证书中服务的名称
       clusterName:                                           #微服务集群名
         $ref: 'values.yaml#/values/network/slb/cluster_name'
       replicas:                                              #Pod副本数
         $ref: 'values.yaml#/values/MicroService/replicas'
       terminationGracePeriodSeconds: 30                      #优雅下线宽限期
       network:                                               #网络配置
         slbEnable:                                           #是否启用SLB
           $ref: 'values.yaml#/values/network/slbEnable'
       bindSlb:                                               #SLB配置
         - port:                                              #微服务在SLB上暴露的端口
             $ref: 'values.yaml#/values/network/slb/port'
           grayStatus:
             $ref: 'values.yaml#/values/network/slb/grayStatus'
           weight: 1                                          #微服务在SLB上负载的权重
           maxFails: 3                                        #微服务调用的失败次数
           timeout: 2                                         #微服务调用转发的超时时间
           instanceName:                                      #SLB的实例名称
             $ref: 'values.yaml#/values/network/slb/server_name'
           listenerGroupName:                                 #SLB实例关联的监听名称
             $ref: 'values.yaml#/values/network/slb/server_name'
           targetGroup:                                       #微服务注册到SLB上的后端服务器组名
             name:                                            #用于创建RouteRule
               $ref: 'values.yaml#/values/network/slb/cluster_name' 
             loadBalancer:                                    #在routes配置的情况下，loadBalancer也属于必选，不配置routes的话，loadBalancer则是可选，loadBalancer当前仅支持配置roundRobin（加权轮询）且不支持修改为其它策略，如果需修改可登录SLB管理台修改
             strategy: roundRobin
             protocol: HTTPS
       volumes:                                               #挂载信息
         - name: log_volume
           size: 4Gi
           type: local
         - name: data_volume
           size: 4Gi
           type: local
       containers:                                            #容器配置 
         - image:                                             #镜像地址
             $ref: 'values.yaml#/values/container/image'
           flavor:                                            #主容器CPU&memory的规格
             $ref: 'values.yaml#/values/container/flavor'
           stsEnable: true                                    #启用STS
           ports:                                             #在Cloud Map注册中心注册的端口
             $ref: 'values.yaml#/values/container/ports'
           livenessProbe:                                     #服务存活探测
             exec:                                            #命令行检查方式
               command: [ "echo", "hello" ]
           readinessProbe:                                    #是否就绪探测
             exec:                                            #命令行检查方式
               command: [ "echo", "hello" ]
           preStopConfig:                                     #优雅退出处理
             execCommand: [ "echo", "hello" ]
           envs:                                              #配置环境变量
             $ref: 'config/envs.yaml#'
           hostAliases:                                       #配置hosts
             $ref: 'config/hosts.yaml#'
       configs:                                               #配置项的根字段
         private:                                             #private为业务配置项
           schema:                                            #声明敏感业务配置项
             $ref: 'config/config_schema.yaml#'                  
           records:                                           #业务配置项
             $ref: 'config/config_records.yaml#'
   ```
   
   
4. 在微服务的values.yaml中定义微服务的资源参数值，此处以DemoServiceAService为例。 
   ```
   values:
     MicroService:
       replicas: 1
     network:
       slbEnable: true
       slb:
         port: 8081                              #微服务在SLB上暴露的端口，DemoServiceAService为8081
         instance_name: jamestest                #SLB的实例名称
         server_name: jamestest_listener         #SLB实例关联的监听名称
         cluster_name: SpringCloudDemoA-cluster  #当前微服务注册到SLB时的集群名称，可以自定义
         grayStatus: 1
     container:
       image: swr.cn-north-5.myhuaweicloud.com/appartswisedev/demoservicea:snapshot_version
       ports:
         - 6792
       flavor: 0.5C1G
     sidecars:
       AIOpsLog:
         version: 3.3.0.100
         flavor: 0.1C500M
   ```
   
   
5. 修改包描述文件package.json。 
   ```
   {
     "type": "iacspec",                       #代码包类型，支持iacspec和iacpatch两种格式，本实践中为iacspec
     "name": "service/1181355389389103104",   #代码包名称，格式：service/{service-id}
     "version": "snapshot_version"            #代码包版本号
   }
   ```
   
   
 
