创建包含容器应用和RDS数据库的服务

本文介绍如何在计算巢创建容器应用+RDS数据库的场景的服务。

前提条件

已创建ACK集群。更多信息,请参见创建ACK集群

操作流程

本示例使用一个基本的容器镜像,并在该镜像中预置了数据库初始化脚本,在服务创建的过程中自动初始化数据库并在数据库初始化完成后,向数据库中插入一条包含ComputeNest名字的数据。服务实例创建完成后,可以使用API名称查询数据库并返回结果Hello ComputeNest。步骤如下:

步骤一:准备容器镜像

创建服务前,您需要先准备容器镜像并将已准备好的容器镜像上传至计算巢用于服务商托管镜像的私有镜像仓库中。

  1. 准备容器镜像。

    使用以下任一方法准备本地容器镜像。

    • 直接使用阿里云提供的容器镜像。

      docker pull compute-nest-registry.cn-hangzhou.cr.aliyuncs.com/bestpractice/springboot-demo:demo
    • 重新编写源代码创建容器镜像。

      1. 获取镜像源代码,根据业务需求完成编写。

      2. 在源代码根目录(即pom.xml所在目录)下,使用Maven将程序打包为Jar包,Jar包会自动生成到target目录中。

        mvn install
      3. 构建镜像。

        完成构建后,镜像会自动下载到您本地电脑。

        docker build --build-arg JAR_FILE=target/\*.jar -t <your-image-tag> .
  2. 上传容器镜像至计算巢镜像仓库。

    1. 获取计算巢镜像仓库访问凭证、打标镜像和推送镜像Docker命令。

      1. 登录计算巢控制台

      2. 在左侧导航栏中选择服务部署物,然后单击创建部署物

      3. 在创建部署物界面的部署物类型下,单击获取访问凭证。在弹出的界面中获取登录镜像仓库、打标镜像和推送镜像的命令。获取命令

      4. 在Docker命令行工具,登录镜像仓库、打标镜像和推送镜像。运行命令

步骤二:创建容器镜像部署物

创建服务前,需要先完成容器镜像部署物的创建和发布。

  1. 登录计算巢控制台

  2. 在左侧导航栏中,单击服务部署物。然后在部署物管理界面,单击创建部署物

  3. 在创建部署物界面,填写部署物信息部署物内容设置分发的信息。

    配置项

    配置示例

    部署物名称

    springboot容器部署

    部署物版本名称

    springboot容器部署版本1

    部署物描述

    springboot镜像容器部署物

    部署物类型

    容器镜像

    选择镜像

    • 部署物名称:springbootdemo

    • 部署物版本:latest

  4. 单击发布部署物

    单击发布部署物后,可在部署物管理页面,单击部署物名称,进入部署物详情界面,查看部署物的部署进度。

    当部署物状态为可用时,表示部署物发布成功。

    部署物详情

步骤三:创建服务

  1. 登录计算巢控制台

  2. 在左侧导航栏中,单击我的服务,并在我的服务页面中选择我创建的服务,然后单击创建新服务

  3. 创建新服务界面,根据需求配置相关参数。

    此处只列举创建服务需要特别配置的参数,其他参数配置,请参见创建私有部署服务

    • 录入模板区域的模板内容处,填写服务模板内容。此处描述模板内容中特别配置的参数,详细的模板内容,请参见模板示例

      • 在容器部署时,需要拉取计算巢私有镜像仓库中的镜像。ACK集群需要具备访问计算巢私有镜像仓库的能力。因此在模板中定义了一个dockerconfigjson类型的Secret,并使用计算巢标识符{{ computenest::acr::dockerconfigjson }}。

        ClusterApplication:
          DependsOn: Database
          Type: ALIYUN::CS::ClusterApplication
          Properties:
            ClusterId:
              Ref: ClusterId
            YamlContent:
              Fn::Sub:
                - |
                # 省略...
                  apiVersion: v1
                  data:
                    .dockerconfigjson: {{ computenest::acr::dockerconfigjson }}
                  kind: Secret
                  metadata:
                    name: computenestrepo
                    namespace: ${NameSpace}
                  type: kubernetes.io/dockerconfigjson
                # 省略...
      • 在模板中通过{{ computenest::acrimage::springbootdemo }}标识符将模板中的image关联至计算巢部署物。

        ClusterApplication:
          DependsOn: Database
          Type: ALIYUN::CS::ClusterApplication
          Properties:
            ClusterId:
              Ref: ClusterId
            YamlContent:
              Fn::Sub:
                - |
                # 省略...
                  apiVersion: apps/v1
                  kind: Deployment
                  metadata:
                    labels:
                      app: springboot-demo-deployment
                    name: springboot-demo-deployment
                    namespace: ${NameSpace}
                  spec:
                    progressDeadlineSeconds: 600
                    replicas: 2
                    revisionHistoryLimit: 10
                    selector:
                      matchLabels:
                        app: springboot-demo-pod
                    template:
                      metadata:
                        labels:
                          app: springboot-demo-pod
                      spec:
                        containers:
                          - env:
                              - name: DB_HOST
                                value: ${RdsConnectString}
                              - name: DB_USER
                                value: ${DbUser}
                              - name: DB_PASSWORD
                                value: ${DbPassword}
                            image: {{ computenest::acrimage::springbootdemo }}
                            imagePullPolicy: Always
                            name: springboot-demo-container
                            ports:
                              - containerPort: 8080
                                protocol: TCP
                        imagePullSecrets:
                          - name: computenestrepo
                        restartPolicy: Always
                # 省略...
    • 部署应用区域的容器镜像关联处,关联已创建的镜像部署物,并选择部署物的版本。管理容器镜像

  4. 单击保存服务

  5. 测试服务。

    服务保存后,您需要对创建的服务实例进行测试,保证其正常可用。更多信息,请参见测试服务功能

  6. 发布服务。

    服务测试通过后,再提交审核,审核通过后即可发布上线。更多信息,请参见上线服务

步骤四:创建服务实例并查询数据库

该步骤是服务商以用户的身份验证服务中配置的容器镜像是否能够在服务实例中正确部署。

  1. 创建服务实例。

    更多信息,请参考创建私有部署服务实例

    服务实例部署成功,则表示镜像部署物也已经在服务实例中部署成功。

  2. 查询数据库。

    使用kubectl命令行工具查询LoadBalancer访问端点,并使用获取到的公网IP访问应用,并查看返回结果。返回结果

模板示例

您可以通过如下内容,查看本场景中必须的ROS资源和函数。

本场景详细的模板示例如下。

ROSTemplateFormatVersion: '2015-09-01'
Description:
  en: A simple demo that deploys a RDS instance and a container-base app into ack. The app use RDS instance as a persistence storage.
  zh-cn: 新建一个RDS实例并向ACK中部署容器应用。容器应用使用RDS实例作为数据库。
Parameters:
  ZoneId:
    Type: String
    AssociationProperty: ALIYUN::ECS::Instance:ZoneId
    Description:
      en: Availability zone ID,<br><b>note: <font color='blue'>Before selecting, please confirm that the Availability Zone supports the specification of creating ECS resources</font></b>
      zh-cn: 可用区ID
    Label:
      en: VSwitch Available Zone
      zh-cn: 可用区
  VpcId:
    Type: String
    AssociationProperty: ALIYUN::ECS::VPC::VPCId
  VSwitchId:
    Type: String
    AssociationProperty: ALIYUN::ECS::VSwitch::VSwitchId
    AssociationPropertyMetadata:
      VpcId: ${VpcId}
      ZoneId: ${ZoneId}
  PayType:
    AssociationProperty: ChargeType
    Type: String
    Label:
      en: ECS Instance Charge Type
      zh-cn: 付费类型
    Default: PostPaid
    AllowedValues:
      - PostPaid
      - PrePaid
  PayPeriod:
    Type: Number
    Description:
      en: The subscription period. Unit is months.
      zh-cn: 购买时长,单位(月)
    Label:
      en: The subscription period. Unit is months.
      zh-cn: 购买时长,单位(月)
    Default: 1
    AllowedValues:
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
      - 12
      - 24
      - 36
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Or:
            - Fn::Equals:
                - ${PayType}
                - PrePaid
            - Fn::Equals:
                - ${PayType}
                - undefined
  RdsInstanceClass:
    Label: MySQL 实例规格
    Type: String
    Description:
      zh-cn: 根据数据库引擎的类型和可用的区域支持选择实例规格
      en: 'Select the instance specification based on the type of database engine and the available area support'
    Default: rds.mysql.s2.large
  RdsInstanceStorage:
    Label: 磁盘大小
    Type: Number
    Description:
      zh-cn: RDS 实例大小,范围为 20 - 2000,每 5 个增量,单位为 GB
      en: The size range of RDS instances is 20 - 2000, Incrementing in every 5, unit GB
    MinValue: 20
    MaxValue: 2000
    ConstraintDescription: The size range of RDS instances is 20 - 2000, Incrementing in every 5, unit GB
    Default: 30
  RdsAccountName:
    Type: String
    Label:
      zh-cn: 用户名称
      en: Account Name
    Description:
      zh-cn: MySQL 管理员用户名称
      en: Account Name
    Default: db_root
  RdsAccountPassword:
    Type: String
    NoEcho: true
    Label:
      zh-cn: 用户密码
      en: DB Account Password
    Description:
      zh-cn: |-
        长度为8~32个字符。由大写英文字母、小写英文字母、数字、特殊字符中的任意三种组成。支持的特殊字符如下:
        !@#$&amp;%^*()_+-= 。
      en: |-
        The length is 8 ~ 32 characters. It is composed of uppercase English letters, lowercase English letters, numbers and special characters. The special characters supported are as follows:
        !@#$& amp;%^* ()_+-=  .
  ClusterId:
    Type: String
    Description:
      en: >-
        The ID of Kubernetes ClusterId in which application deployed.
      zh-cn: >-
        部署应用程序的K8s集群ID
    AllowedPattern: '[0-9a-z]+$'
    Label:
      en: Kubernetes ClusterId
      zh-cn: K8s集群ID
    AssociationProperty: ALIYUN::CS::Cluster::ClusterId
    ConstraintDescription:
      en: >-
        must be lowercase letters or numbers
      zh-cn: '集群ID必须由小写字母或者数字组成'
  NameSpace:
    Type: String
    Description:
      en: >-
        The NameSpace in which application deployed.
      zh-cn: >-
        部署应用程序的K8s命名空间
Resources:
  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      VpcId:
        Ref: VpcId
      SecurityGroupIngress:
        - PortRange: '-1/-1'
          Priority: 1
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: all
          NicType: intranet
      SecurityGroupEgress:
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          DestCidrIp: 0.0.0.0/0
          NicType: intranet
  DBInstance:
    Type: ALIYUN::RDS::DBInstance
    Properties:
      ZoneId:
        Ref: ZoneId
      VPCId:
        Ref: VpcId
      VSwitchId:
        Ref: VSwitchId
      Engine: MySQL
      EngineVersion: "5.7"
      DBInstanceClass:
        Ref: RdsInstanceClass
      DBInstanceStorage:
        Ref: RdsInstanceStorage
      PayType:
        Ref: PayType
      PeriodType: Month
      Period:
        Ref: PayPeriod
      SecurityIPList: '0.0.0.0/0'
  RdsAccount:
    DependsOn: DBInstance
    Type: ALIYUN::RDS::Account
    Properties:
      DBInstanceId:
        Ref: DBInstance
      AccountType: Super
      AccountName:
        Ref: RdsAccountName
      AccountPassword:
        Ref: RdsAccountPassword
  RdsParameter:
    Type: ALIYUN::RDS::DBInstanceParameterGroup
    Properties:
      DBInstanceId:
        Ref: DBInstance
      Parameters:
        - Key: innodb_large_prefix
          Value: 'ON'
        - Key: innodb_adaptive_flushing_lwm
          Value: '10'
  Database:
    Type: ALIYUN::RDS::Database
    Properties:
      CharacterSetName: UTF8
      DBInstanceId:
        Ref: DBInstance
      DBName: springboot_demo
    DependsOn:
      - DBInstance
  ClusterApplication:
    DependsOn: Database
    Type: ALIYUN::CS::ClusterApplication
    Properties:
      ClusterId:
        Ref: ClusterId
      YamlContent:
        Fn::Sub:
          - |
            apiVersion: v1
            kind: Namespace
            metadata:
              name: ${NameSpace}
            ---
            apiVersion: v1
            data:
              .dockerconfigjson: {{ computenest::acr::dockerconfigjson }}
            kind: Secret
            metadata:
              name: computenestrepo
              namespace: ${NameSpace}
            type: kubernetes.io/dockerconfigjson
            ---
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              labels:
                app: springboot-demo-deployment
              name: springboot-demo-deployment
              namespace: ${NameSpace}
            spec:
              progressDeadlineSeconds: 600
              replicas: 2
              revisionHistoryLimit: 10
              selector:
                matchLabels:
                  app: springboot-demo-pod
              template:
                metadata:
                  labels:
                    app: springboot-demo-pod
                spec:
                  containers:
                    - env:
                        - name: DB_HOST
                          value: ${RdsConnectString}
                        - name: DB_USER
                          value: ${DbUser}
                        - name: DB_PASSWORD
                          value: ${DbPassword}
                      image: {{ computenest::acrimage::springbootdemo }}
                      imagePullPolicy: Always
                      name: springboot-demo-container
                      ports:
                        - containerPort: 8080
                          protocol: TCP
                  imagePullSecrets:
                    - name: computenestrepo
                  restartPolicy: Always
            ---
            apiVersion: v1
            kind: Service
            metadata:
              labels:
                app: springboot-demo-svc
              name: springboot-demo-svc
              namespace: ${NameSpace}
            spec:
              ports:
                - name: http
                  port: 80
                  protocol: TCP
                  targetPort: 8080
              selector:
                app: springboot-demo-pod
              type: LoadBalancer
          - NameSpace:
              Ref: NameSpace
            DbUser:
              Ref: RdsAccountName
            DbPassword:
              Ref: RdsAccountPassword
            RdsConnectString:
              Fn::GetAtt:
                - DBInstance
                - InnerConnectionString
  AppExternalIp:
    Type: DATASOURCE::CS::ClusterApplicationResources
    Properties:
      Kind: Service
      Name: springboot-demo-svc
      ClusterId:
        Ref: ClusterApplication
      Namespace:
        Ref: NameSpace
      JsonPath: $.status.loadBalancer.ingress
      FirstMatch: true
    DependsOn: ClusterApplication
Outputs:
  ExternalIp:
    Value:
      Ref: AppExternalIp
Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - VpcId
          - ZoneId
          - VSwitchId
        Label:
          en: Network Configuration
          zh-cn: 网络参数配置
      - Parameters:
          - ClusterId
          - NameSpace
        Label:
          en: ACK Configuration
          zh-cn: ACK参数配置
      - Parameters:
          - RdsInstanceClass
          - RdsInstanceStorage
          - RdsAccountName
          - RdsAccountPassword
        Label:
          en: Database Configuration
          zh-cn: 数据库参数配置
      - Parameters:
          - PayType
          - PayPeriod
        Label:
          en: Payment Configuration
          zh-cn: 支付配置