Create a container and RDS service

更新时间:
复制 MD 格式

This topic describes how to create a service in Compute Nest that combines a container application with ApsaraDB RDS.

Prerequisites

You have an existing Container Service for Kubernetes (ACK) cluster. For more information, see Create an ACK cluster.

Procedure

This example uses a basic container image with a preset database initialization script. During service instance creation, the database is automatically initialized, and a record containing the name ComputeNest is inserted. After the service instance is created, you can query the application to get the result Hello ComputeNest. The procedure includes the following steps:

Step 1: Prepare a container image

Before you create the service, prepare a container image and upload it to the private image repository in Compute Nest for service providers.

  1. Prepare a container image.

    Use one of the following methods to prepare a local container image.

    • Use a container image provided by Alibaba Cloud.

      docker pull compute-nest-registry.cn-hangzhou.cr.aliyuncs.com/bestpractice/springboot-demo:demo
    • Create a container image from source code.

      1. Get the image source code and modify it based on your business requirements.

      2. In the root directory of the source code, where the pom.xml file is located, use Maven to package the application into a JAR file. The JAR file is automatically generated in the target directory.

        mvn install
      3. Build the image.

        After the build is complete, the image is available on your local machine.

        docker build --build-arg JAR_FILE=target/\*.jar -t <your-image-tag> .
  2. Upload the container image to the Compute Nest image repository.

    1. Obtain the access credentials for the Compute Nest image repository and the Docker commands to tag and push the image.

      1. Log on to the Compute Nest console.

      2. In the left-side navigation pane, choose Service Deployment Package, and then click Create Deployment Package.

      3. On the Create deployment package page, under Deployment Package Type, click Obtain Access Credential. In the dialog box that appears, copy the commands to log on to the image repository, tag the image, and push it.

      4. In your Docker CLI, log on to the image repository, tag the image, and push the image.

        docker login compute-nest-registry.cn-hangzhou.cr.aliyuncs.com --username=cr_temp_user --password=eyJhdXRoVG9rZW5JZGVudGlmaWVyIjoiMTY3MDkzODgyMjU4xxx
        WARNING! Using --password via the CLI is insecure. Use --password-stdin.
        Login Succeeded
        docker tag computenest/springbootdemo compute-nest-registry.cn-hangzhou.cr.aliyuncs.com/1563457855xxx/springbootdemo:latest
        docker push compute-nest-registry.cn-hangzhou.cr.aliyuncs.com/1563457855xxx/springbootdemo:latest
        The push refers to repository [compute-nest-registry.cn-hangzhou.cr.aliyuncs.com/1563457855xxx/springbootdemo]
        3a3d2d6d0277: Layer already exists
        ceaf9e1ebef5: Layer already exists
        9b9b7f3d56a0: Layer already exists
        f1b5933fe4b5: Layer already exists
        latest: digest: sha256:1eff431284561801f5d3e88f84a68c99c338e5d2122a9ebe096c2d1128e5f913 size: 1159

Step 2: Create a container image deployment package

Before you create the service, you must create and publish the container image deployment package.

  1. Log on to the Compute Nest console.

  2. In the left-side navigation pane, choose Service Deployment Package. On the Packages page, click Create Deployment Package.

  3. On the Create deployment package page, configure the parameters in the Basic Information, Deployment Package Content, and Distribution Settings sections.

    Parameter

    Example

    Deployment package name

    springboot-container-deployment

    Deployment package version name

    springboot-container-deployment-v1

    Deployment package description

    Springboot container image deployment package

    Deployment package type

    Container image

    Select image

    • Image Name: springbootdemo

    • Image Version: latest

  4. Click Publish Deployment Package.

    After you click Publish Deployment Package, you can go to the Packages page. Click the name of the deployment package to view its deployment progress on the details page.

    When the status changes to Available, the deployment package is published.

Step 3: Create a service

  1. Log on to the Compute Nest console.

  2. In the left-side navigation pane, click My Services. On the My Services page, click the Created Services tab, and then click Create Service.

  3. On the Create Service page, configure the parameters as required.

    This section describes only the key parameters for this example. For details on other parameters, see Create a private service.

    • In the Template section, enter the service template in the Template Content field. The following snippets highlight key configurations in the template. For the complete template, see Template example.

      • To deploy the container, the ACK cluster must pull the image from the private Compute Nest image repository. To enable this, the template defines a Kubernetes Secret of the type dockerconfigjson and populates it using the Compute Nest identifier {{ computenest::acr::dockerconfigjson }}.

        ClusterApplication:
          DependsOn: Database
          Type: ALIYUN::CS::ClusterApplication
          Properties:
            ClusterId:
              Ref: ClusterId
            YamlContent:
              Fn::Sub:
                - |
                # Omitted for brevity...
                  apiVersion: v1
                  data:
                    .dockerconfigjson: {{ computenest::acr::dockerconfigjson }}
                  kind: Secret
                  metadata:
                    name: computenestrepo
                    namespace: ${NameSpace}
                  type: kubernetes.io/dockerconfigjson
                # Omitted for brevity...
      • The template uses the {{ computenest::acrimage::springbootdemo }} identifier to associate the image property with the Compute Nest deployment package.

        ClusterApplication:
          DependsOn: Database
          Type: ALIYUN::CS::ClusterApplication
          Properties:
            ClusterId:
              Ref: ClusterId
            YamlContent:
              Fn::Sub:
                - |
                # Omitted for brevity...
                  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
                # Omitted for brevity...
    • In the Deploy Application section, click Associate Container Image to link the created image deployment package. In the Associate container image dialog box, the identifier field is automatically populated with {{ computenest::acrimage::springbootdemo }} from the template. From the Select deployment package drop-down list, select springboot-container-deployment. From the version drop-down list, select v1. Click Save, and then click OK.

  4. Click Save Service.

  5. Test the service.

    After you save the service, you must test the service instance to ensure it works correctly. For more information, see Test a service.

  6. Publish the service.

    After the service passes all tests, submit it for review. Once approved, you can publish the service. For more information, see Publish a service.

Step 4: Create an instance and query the database

In this step, the service provider, acting as a user, validates that the container image configured in the service deploys correctly to the service instance.

  1. Create a service instance.

    For more information, see Create a private service instance.

    A successful deployment of the service instance confirms that the deployment package was also deployed successfully.

  2. Query the database.

    Use the kubectl CLI to find the LoadBalancer service endpoint. Then, use the public IP address to access the application and view the result.

    ~ % kubectl get svc -n springboot-demo
    NAME                    TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    springboot-demo-svc     LoadBalancer   10.xxx       47.xxx        80:31171/TCP   26m
    ~ % wget -cq http://47.xxx -O -
    Hello ComputeNest

Template example

The following sections list the required Resource Orchestration Service (ROS) resources and functions for this scenario.

The following is the complete template for this example.

ROSTemplateFormatVersion: '2015-09-01'
Description:
  en: Deploys an ApsaraDB RDS instance and a container-based application to an ACK cluster. The application uses the RDS instance for persistent storage.
  zh-cn: 新建一个RDS实例并向ACK中部署容器应用。容器应用使用RDS实例作为数据库。
Parameters:
  ZoneId:
    Type: String
    AssociationProperty: ALIYUN::ECS::Instance:ZoneId
    Description:
      en: The ID of the availability zone.<br><b>Note: <font color='blue'>Before you make a selection, confirm that the availability zone has the required instance types.</font></b>
      zh-cn: 可用区ID
    Label:
      en: VSwitch availability 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, in months.
      zh-cn: 购买时长,单位(月)
    Label:
      en: The subscription period, in 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 instance specification
    Type: String
    Description:
      zh-cn: 根据数据库引擎的类型和可用的区域支持选择实例规格
      en: 'Select an instance specification that is supported by the database engine and availability zone.'
    Default: rds.mysql.s2.large
  RdsInstanceStorage:
    Label: Disk size
    Type: Number
    Description:
      zh-cn: RDS 实例大小,范围为 20 - 2000,每 5 个增量,单位为 GB
      en: The disk size for the RDS instance, in GB. The value must be between 20 and 2000, in increments of 5.
    MinValue: 20
    MaxValue: 2000
    ConstraintDescription: The disk size for the RDS instance, in GB. The value must be between 20 and 2000, in increments of 5.
    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 password must be 8 to 32 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. The supported special characters are: !@#$&%^*()_+-= .
  ClusterId:
    Type: String
    Description:
      en: >-
        The ID of the ACK cluster where the application is deployed.
      zh-cn: >-
        部署应用程序的K8s集群ID
    AllowedPattern: '[0-9a-z]+$'
    Label:
      en: Kubernetes cluster ID
      zh-cn: K8s集群ID
    AssociationProperty: ALIYUN::CS::Cluster::ClusterId
    ConstraintDescription:
      en: >-
        Must contain only lowercase letters and digits.
      zh-cn: '集群ID必须由小写字母或者数字组成'
  NameSpace:
    Type: String
    Description:
      en: >-
        The namespace in the ACK cluster where the application is 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: 支付配置