Guide to enriched DevOps deployment

更新时间:
复制 MD 格式

This topic describes how to enrich the DevOps process for microservices. You will build a complete chain of associated entities, from code repositories and container images to Kubernetes resources and application performance management (APM) services. This provides end-to-end observability.

Scope

Cloud service activation requirements

Permission requirements

Create a Resource Access Management (RAM) user or role with the following permissions:

RAM permissions

{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "devops:List*",
        "devops:Get*"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow", 
      "Action": [
        "cr:Get*",
        "cr:List*"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "log:PostLogStoreLogs",
        "log:Get*",
        "log:List*"
      ],
      "Resource": "*"
    }
  ]
}

Data preparation

Data type

Requirements

DevOps data

  • Host code repositories in Alibaba Cloud DevOps.

  • The members of the development team have joined the organization.

  • Manage code releases using Git tags.

Container image data

  • Push application images to ACR.

  • Image tags map to code versions.

  • The image build flow is automated.

Kubernetes data

  • The application has been deployed in the ACK cluster.

  • The pod uses an image from ACR.

  • Use standardized names for services and namespaces.

Application observable data

Ensure the application is connected to the ARMS agent:

  • The ARMS Agent is installed and configured for your application.

  • Application trace data has been successfully reported.

Deployment steps

The complete code package for these steps is available in umodel_and_codes.zip.

Step 1: Ingest enriched DevOps process data into UModel

  1. Go to the Cloud Monitor 2.0 workspace, click All Features, and then select UModel Explorer to view the currently ingested UModel data.

  2. Replace the parameters and run the following command to upload the DevOps-related UModel definitions and data from the code package.

    export ALIBABA_CLOUD_ACCESS_KEY_ID="your-access-key-id"
    export ALIBABA_CLOUD_ACCESS_KEY_SECRET="your-access-key-secret"
    
    python umodel_batch_uploader.py ../umodel --endpoint metrics.<REGION>.aliyuncs.com --workspace <YOUR_WORKSPACE>
  3. Go to the Cloud Monitor 2.0 workspace, click All Features, and then select UModel Explorer to view the uploaded UModel data.

    • You can filter UModel data by node type or domain. The following figure shows how to filter data to view only the devops domain data.image

    • You can also view the connections between the DevOps UModel data domain and other domains. For more information, see the UModel Explorer documentation.

Step 2: Generate DevOps entity and relationship data

  1. Go to the devops_data_generator directory.

    Command and devops_data_generator overview

    # Clone the code and go to the directory
    cd devops_data_generator
    # Configure application parameters
    cp config/app_config.yaml.sample config/app_config.yaml

    devops_data_generator overview

    The devops_data_generator calls the Alibaba Cloud OpenAPI to automatically collect entity data, such as code repositories, developers, images, and pods, from Alibaba Cloud DevOps, ACR, and CMS. The generator then establishes relationships between these entities and writes the entity and relationship data to EntityStore in Cloud Monitor 2.0.

    Generated data types:

    Entity data:

    • devops.developer - Developer entity

    • devops.code_repository - Code repository entity

    • devops.code_release - Code release entity

    • devops.image_registry - Image repository entity

    • devops.image - Container image entity

    • k8s.pod - Kubernetes pod entity

    Relationship data:

    • developer_manages_code_repository - Relationship indicating a developer manages a code repository

    • code_release_sourced_from_code_repository - Relationship indicating a code release is sourced from a code repository

    • image_sourced_from_code_release - Relationship indicating an image is sourced from a code release

    • image_registry_contains_image - Relationship indicating an image repository contains an image

    • pod_uses_image - Relationship indicating a pod uses an image

    • apm.service_sourced_from_devops.code_repository - Relationship indicating an APM service is sourced from a code repository

    • apm.service_sourced_from_devops.code_release - Relationship indicating an APM service is sourced from a code release

    • devops.developer_manages_apm.service - Relationship indicating a developer manages an APM service

  2. Edit the configuration file.

    Configuration file and parameter descriptions

    # Application configuration file
    
    # Alibaba Cloud access configuration
    aliyun:
      region: "cn-hongkong"
      access_key_id: "<YOUR_ACCESS_KEY_ID>"
      access_key_secret: "<YOUR_ACCESS_KEY_SECRET>"
    
    # DevOps configuration
    devops:
      organization_id: "<YOUR_ORGANIZATION_ID>"  # Replace with your organization ID
      access_key_id: "<YOUR_ACCESS_KEY_ID>"
      access_key_secret: "<YOUR_ACCESS_KEY_SECRET>"
    
    # ACR configuration
    acr:
      instance_id: "<YOUR_ACR_INSTANCE_ID>"  # Replace with your ACR instance ID
      region: "cn-hangzhou"
      access_key_id: "<YOUR_ACCESS_KEY_ID>"
      access_key_secret: "<YOUR_ACCESS_KEY_SECRET>"
    
    # CMS configuration (used to get k8s.pod data)
    cms:
      endpoint: "<YOUR_CMS_ENDPOINT>"
      workspace: "<YOUR_CMS_WORKSPACE>"
      namespace_filter: "<YOUR_NAMESPACE_FILTER>"
      access_key_id: "<YOUR_ACCESS_KEY_ID>"
      access_key_secret: "<YOUR_ACCESS_KEY_SECRET>"
    
    # SLS configuration
    sls:
      endpoint: "cn-hongkong.log.aliyuncs.com"
      access_key_id: "<YOUR_ACCESS_KEY_ID>"
      access_key_secret: "<YOUR_ACCESS_KEY_SECRET>"
      project: "<YOUR_SLS_PROJECT>"
      
      # Logstore mapping configuration
      logstore_mapping:
        entities:
          developer: "<WORKSPACE_NAME>__entity"
          code_repository: "<WORKSPACE_NAME>__entity"
          code_release: "<WORKSPACE_NAME>__entity"
          image_registry: "<WORKSPACE_NAME>__entity"
          image: "<WORKSPACE_NAME>__entity"
        relationships:
          developer_manages_code_repository: "<WORKSPACE_NAME>__topo"
          code_release_sourced_from_code_repository: "<WORKSPACE_NAME>__topo"
          image_sourced_from_image_registry: "<WORKSPACE_NAME>__topo"
          image_sourced_from_code_release: "<WORKSPACE_NAME>__topo"
          image_registry_contains_image: "<WORKSPACE_NAME>__topo"
          pod_uses_image: "<WORKSPACE_NAME>__topo"
          # Static topology relationship
          static_topo: "<WORKSPACE_NAME>__topo"

    Parameter descriptions:

    Configuration section

    Parameter name

    Description

    Example

    Required

    aliyun

    region

    The ID of the Alibaba Cloud region.

    cn-hangzhou

    Yes

    access_key_id

    The ID of the Alibaba Cloud AccessKey pair.

    LTAI5t***

    Yes

    access_key_secret

    The secret of the Alibaba Cloud AccessKey pair.

    nP0foq***

    Yes

    devops

    organization_id

    The ID of the DevOps organization. You can obtain it from the Alibaba Cloud DevOps console.

    62d8f3a0de***

    Yes

    access_key_id

    The ID of the DevOps API AccessKey pair.

    LTAI5t***

    Yes

    access_key_secret

    The secret of the DevOps API AccessKey pair.

    nP0foq***

    Yes

    acr

    instance_id

    The ID of the Container Registry instance.

    cri-67u5tdtph***

    Yes

    region

    The region of the ACR service.

    cn-hangzhou

    Yes

    access_key_id

    The ID of the ACR API AccessKey pair.

    LTAI5t***

    Yes

    access_key_secret

    The secret of the ACR API AccessKey pair.

    nP0foq***

    Yes

    cms

    endpoint

    The API destination of Cloud Monitor 2.0.

    metrics.cn-hangzhou.aliyuncs.com

    Yes

    workspace

    The name of the Cloud Monitor 2.0 workspace.

    o11y-aiops-demo***

    Yes

    access_key_id

    The ID of the CMS API AccessKey pair.

    LTAI5t***

    Yes

    access_key_secret

    The secret of the CMS API AccessKey pair.

    nP0foq***

    Yes

    sls

    endpoint

    The API destination of Simple Log Service.

    cn-hangzhou.log.aliyuncs.com

    Yes

    access_key_id

    The ID of the SLS API AccessKey pair.

    LTAI5t***

    Yes

    access_key_secret

    The secret of the SLS API AccessKey pair.

    nP0foq***

    Yes

    project

    The name of the project to which the Cloud Monitor 2.0 workspace belongs.
    You can find this in the workspace.


    cms-qs-demos-aiops-demo-***

    Yes

    logstore_mapping.entities

    The Logstore for entity data.
    The format is ${workspace_name}__entity,
    where workspace is the name of the Cloud Monitor 2.0 workspace.

    qs-demos-aiops-demo__entity

    Yes

    logstore_mapping.relationships

    The Logstore for relationship data.
    The format is ${workspace_name}__topo,
    where workspace is the name of the Cloud Monitor 2.0 workspace.

    qs-demos-aiops-demo__topo

    Yes

  3. In the root directory of devops_data_generator, run the following command to generate the entity data.

    pip install -r requirements.txt
    # One-time execution
    python main.py --mode single 
  4. Deploy devops_data_generator using one of the three methods described in the following table. Choose the solution that best fits your infrastructure.

    Feature

    Kubernetes CronJob

    Function Compute

    Docker Compose

    Deployment complexity

    Medium

    Low

    Low

    O&M cost

    Medium

    Low (pay-as-you-go)

    Medium

    Scenarios

    Existing K8s cluster

    Serverless scenarios

    Standalone server

    Deploy using a Kubernetes CronJob (Recommended)

    1. Prepare the configuration and image

    # Create a namespace and a ConfigMap
    kubectl create namespace devops-data-generator
    kubectl create configmap devops-generator-config \
      --from-file=config/ \
      -n devops-data-generator
    
    # Build and push the image
    docker build -t your-registry.com/devops-data-generator:v1.0 .
    docker push your-registry.com/devops-data-generator:v1.0

    2. Create the CronJob resource (k8s/cronjob.yaml)

    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: devops-data-generator
      namespace: devops-data-generator
    spec:
      schedule: "*/15 * * * *"  # Runs every 15 minutes. Example frequencies: */5 * * * * (every 5 minutes), 0 * * * * (every hour), 0 2 * * * (at 2:00 AM every day)
      concurrencyPolicy: Forbid
      jobTemplate:
        spec:
          template:
            spec:
              restartPolicy: OnFailure
              containers:
              - name: generator
                image: your-registry.com/devops-data-generator:v1.0
                command: ["python", "main.py", "--mode", "single"]
                volumeMounts:
                - name: config
                  mountPath: /app/config
                resources:
                  limits:
                    memory: "512Mi"
                    cpu: "500m"
              volumes:
              - name: config
                configMap:
                  name: devops-generator-config

    3. Deploy and verify

    # Deploy the CronJob
    kubectl apply -f k8s/cronjob.yaml
    # Manually test the job
    kubectl create job --from=cronjob/devops-data-generator test-job -n devops-data-generator
    # View the logs
    kubectl logs -n devops-data-generator -l app=devops-data-generator --tail=50

    Deploy using Alibaba Cloud Function Compute (container image)

    You can use the custom container image feature of Function Compute to deploy the application by reusing the Docker image.

    1. Build and push the image to ACR

    # Log on to ACR
    docker login --username=${ACR_USERNAME} registry.cn-hangzhou.aliyuncs.com
    # Build the image (add FC adapter)
    docker build -t registry.cn-hangzhou.aliyuncs.com/your-namespace/devops-data-generator:v1.0 .
    # Push the image
    docker push registry.cn-hangzhou.aliyuncs.com/your-namespace/devops-data-generator:v1.0

    2. Create the s.yaml configuration file

    edition: 1.0.0
    name: devops-data-generator-fc
    
    services:
      devops-generator:
        component: fc
        props:
          region: cn-hangzhou
          service:
            name: devops-data-generator-service
            internetAccess: true
          
          function:
            name: data-generator
            description: DevOps data ingestion generator
            # Use a custom container image
            runtime: custom-container
            customContainerConfig:
              image: registry.cn-hangzhou.aliyuncs.com/your-namespace/devops-data-generator:v1.0
              command: ["python", "main.py", "--mode", "single"]
              accelerationType: Default
            timeout: 600
            memorySize: 512
            instanceConcurrency: 1
          
          triggers:
            - name: timer-trigger
              type: timer
              config:
                enable: true
                cronExpression: '0 */15 * * * *'  # Runs every 15 minutes
                payload: '{}'

    3. Deploy and test

    # Install Serverless Devs
    npm install -g @serverless-devs/s
    s config add  # Configure your Alibaba Cloud account
    # Deploy the function
    s deploy
    
    # Manually trigger a test
    s invoke
    
    # View the logs
    s logs -t

    4. Deploy

    s deploy              # Deploy the function
    s invoke --event '{}'  # Test the execution
    s logs -t             # View the logs

    Deploy using Docker Compose

    1. Create docker-compose.yml

    version: '3.8'
    services:
      devops-data-generator:
        build: .
        container_name: devops-data-generator
        restart: unless-stopped
        command: python app.py --host 0.0.0.0 --port 5000
        ports:
          - "5000:5000"
        volumes:
          - ./config:/app/config:ro
          - ./logs:/app/logs
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
          interval: 30s

    2. Start the service and configure a scheduled trigger

    # Start the service
    docker-compose up -d
    
    # Configure a scheduled trigger using crontab
    crontab -e
    # Add: Run every 15 minutes
    */15 * * * * curl -X POST http://localhost:5000/invoke -H "Content-Type: application/json" -d '{"mode":"single"}'

    3. Monitor and maintain

    curl http://localhost:5000/status   # View the status
    docker-compose logs -f              # View the logs
    docker-compose restart              # Restart the service
  5. Verify that the data is correctly uploaded to EntityStore.

    Verification steps

    1. Before you query EntityStore, confirm that the data has been written to the Logstore. You can run a query statement in the entity data (**${workspace}__entity**) and relationship data (**${workspace}__topo**) Logstores.

      * | select count(*) as record_count
    2. Confirm that the required system fields for entities and relationships are complete and correct.

      • Validate required entity fields (in the **${workspace}__entity** Logstore)

        * | extend validation_status=
            case 
                when __domain__ is null or __domain__ = '' then 'domain is missing'
                when __entity_type__ is null or __entity_type__ = '' then 'entity_type is missing'
                when __entity_id__ is null or __entity_id__ = '' then 'entity_id is missing'
                when work_no is null or work_no = '' then 'primary key work_no is missing'
                when name is null or name = '' then 'name field is missing'
                else 'Normal'
            end | where __entity_type__ = 'devops.developer' and validation_status != 'Normal' | project validation_status
      • Statistics by missing field type (in the **${workspace}__entity** Logstore)

        * | 
        where __entity_type__ = 'devops.developer'
          and (
            __domain__ is null or __domain__ = '' or
            __entity_type__ is null or __entity_type__ = '' or
            __entity_id__ is null or __entity_id__ = '' or
            work_no is null or work_no = '' or
            name is null or name = ''
          ) | extend validation_status=
            case 
                when __domain__ is null or __domain__ = '' then 'domain is missing'
                when __entity_type__ is null or __entity_type__ = '' then 'entity_type is missing'
                when __entity_id__ is null or __entity_id__ = '' then 'entity_id is missing'
                when work_no is null or work_no = '' then 'primary key work_no is missing'
                when name is null or name = '' then 'name field is missing'
            end | stats cnt = count(1) by validation_status
      • Validate required relationship fields (in the **${workspace}__topo** Logstore)

        * | extend validation_status = 
            case 
                when __src_domain__ is null or __src_domain__ = '' then 'src_domain is missing'
                when __src_entity_type__ is null or __src_entity_type__ = '' then 'src_entity_type is missing'
                when __src_entity_id__ is null or __src_entity_id__ = '' then 'src_entity_id is missing'
                when __dest_domain__ is null or __dest_domain__ = '' then 'dest_domain is missing'
                when __dest_entity_type__ is null or __dest_entity_type__ = '' then 'dest_entity_type is missing'
                when __dest_entity_id__ is null or __dest_entity_id__ = '' then 'dest_entity_id is missing'
                when __link_type__ is null or __link_type__ = '' then 'link_type is missing'
                else 'Normal'
            end |
        where __link_type__ = 'manages'
          and validation_status != 'Normal'
    3. Log on to the Cloud Monitor 2.0 console, click Entity Explorer, enter the following query statements, and click Query to verify that the entities and relationships are uploaded.

      • Entity query statement: .entity with(domain='devops', type='devops.developer') | limit 0,100.

      • Relationship query statement: .entity_set with(domain='devops', name='devops.developer') | entity-call get_neighbor_entities().

Demonstration of interconnected DevOps entities

After you complete the preceding steps, the defined DevOps entity data is connected. You can log on to the Cloud Monitor 2.0 console to view the following content:

  1. Panoramic entity data overview: Displays complete DevOps entity data, covering the full chain of entities such as code repositories, developers, code releases, container images, Kubernetes pods, and APM services.

    image

  2. Full-link topology relationship diagram: The entity topology view presents the entities and relationships of the entire DevOps chain as a unified topology graph. It provides a high-level overview and supports layered layouts, relationship flow display, anomaly identification, and interactive exploration.

    image

  3. Categorized entity list management: CMS provides a structured entity list view. It supports grouped display by entity type, multi-dimensional filtering and searching, and status monitoring. This view complements the topology graph for a comprehensive visualization experience.

    image

  4. In-depth analysis of a single entity: The single-entity topology view focuses on a specific entity to perform local relationship analysis. It supports upstream and downstream tracing and impact scope analysis. This is useful for scenarios such as fault impact analysis, change risk assessment, and identifying performance bottlenecks.image

FAQ

Troubleshooting guide

If data has been uploaded but cannot be found in EntityStore, you can use the following guide to troubleshoot the issue:

Check item

Using tools

Confirm that data has been written to the Logstore

Query the ${workspace}__entity or ${workspace}__topo Logstore in the SLS console

Check whether the required fields are complete

Query for field completeness in the SLS console

Check whether KeepAlive has expired

Query the expiration status in the SLS console

Verify visibility in EntityStore

Run SQL queries in UModel Explorer

Check for dangling relationships

Run JOIN queries in UModel Explorer

Confirm that data is written to the Logstore

  1. Run the following query statement in the entity data (**${workspace}__entity**) Logstore.

    * | select count(*) as total_count
    where __entity_type__ = 'devops.developer'
  2. Run the following query statement in the relationship data (**${workspace}__topo**) Logstore.

    * | select count(*) as total_count
    where __relation_type__ = 'manages'
    Note

    If the count is 0, the data upload failed. Check the upload code and logs.

Check if required fields are complete

  1. Run the following query statement in the entity data (**${workspace}__entity**) Logstore to confirm that the uploaded data contains all required fields.

    * | extend validation_status=
        case 
            when __domain__ is null or __domain__ = '' then 'domain is missing'
            when __entity_type__ is null or __entity_type__ = '' then 'entity_type is missing'
            when __entity_id__ is null or __entity_id__ = '' then 'entity_id is missing'
            when work_no is null or work_no = '' then 'primary key work_no is missing'
            when name is null or name = '' then 'name field is missing'
            else 'Normal'
        end | where __entity_type__ = 'devops.developer' and validation_status != 'Normal' | project validation_status
  2. Run the following query statement in the relationship data (**${workspace}__topo**) Logstore to confirm that the uploaded data contains all required fields.

    * | extend validation_status =
        case 
            when __src_entity_id__ is null or __src_entity_id__ = '' then 'src_entity_id is missing' 
            when __src_entity_type__ is null or __src_entity_type__ = '' then 'src_entity_type is missing' 
            when __src_domain__ is null or __src_domain__ = '' then 'src_domain is missing' 
            when __dest_entity_id__ is null or __dest_entity_id__ = '' then 'dest_entity_id is missing'
            when __dest_entity_type__ is null or __dest_entity_type__ = '' then 'dest_entity_type is missing' 
            when __dest_domain__ is null or __dest_domain__ = '' then 'dest_domain is missing'
            when __relation_type__ is null or __relation_type__ = '' then 'relation_type is missing'
            else 'Normal'
        end |
    where __relation_type__ = 'manages'
      and validation_status != 'Normal'
    Note
    • If any fields are missing, check the data transformation code to ensure all required fields have values.

    • All field values must be strings.

Check if KeepAlive has expired

Even if data is written to the Logstore, it cannot be queried in EntityStore if its KeepAlive period has expired.

  1. Run the following query statement in the entity data (**${workspace}__entity**) Logstore.

    * | select 
        __entity_id__,
        from_unixtime(__last_observed_time__) as last_observed,
        __keep_alive_seconds__ as keep_alive,
        from_unixtime(__last_observed_time__ + cast(__keep_alive_seconds__ as bigint)) as expire_time,
        case 
            when to_unixtime(now()) > __last_observed_time__ + cast(__keep_alive_seconds__ as bigint)
            then 'expired' 
            else 'not expired' 
        end as status
    where __entity_type__ = 'devops.developer'
    order by __last_observed_time__ desc
    limit 20
  2. Run the following query statement in the relationship data (**${workspace}__topo**) Logstore.

    * | select 
        __src_entity_id__,
        __dest_entity_id__,
        __relation_type__,
        from_unixtime(__last_observed_time__) as last_observed,
        __keep_alive_seconds__ as keep_alive,
        case 
            when to_unixtime(now()) > __last_observed_time__ + cast(__keep_alive_seconds__ as bigint)
            then 'expired' 
            else 'not expired' 
        end as status
    where __relation_type__ = 'manages'
    order by __last_observed_time__ desc
    limit 20
    Note
    • status = 'expired': The entity has expired and cannot be queried in EntityStore.

    • status = 'not expired': The entity should be queryable. If it cannot be found, check for other issues.

    • Solutions:

      • Increase the KeepAlive duration: If entities expire frequently, increase the value of __keep_alive_seconds__.

      • Increase the upload frequency: Shorten the interval of the scheduled task to ensure __last_observed_time__ is updated promptly.

      • KeepAlive configuration principles:

        • Scheduled full ingestion: KeepAlive = 2 × full ingestion epoch.

        • Timed increment: The KeepAlive value is twice the increment period.

Data is not updated promptly

The value of an entity field has changed, but queries still return the old value, or new entities or relationships become visible only after a long delay.

  1. Check the last update time. If delay_minutes is greater than 60, the data update latency exceeds one hour. You need to optimize the upload policy.

    * | select 
        __entity_type__,
        from_unixtime(max(__last_observed_time__)) as last_update,
        date_diff('minute', from_unixtime(max(__last_observed_time__)), now()) as delay_minutes
    group by __entity_type__

Optimization strategies:

Current policy

Data latency

Optimization solution

Scheduled full ingestion (24 hours)

Up to 24 hours

Change to scheduled full ingestion (6 hours) + scheduled incremental ingestion (30 minutes)

Scheduled incremental ingestion (1 hour)

Up to 1 hour

Add a webhook for event-driven, real-time updates

Recommended configurations:

  • Static entities (such as developers): Full ingestion (every 6 hours) + KeepAlive (12 hours)

  • Semi-static entities (such as code repositories): Full ingestion (every 6 hours) + Incremental ingestion (every 30 minutes) + Events + KeepAlive (12 hours)

  • Dynamic entities (such as images): Incremental ingestion (every 15 minutes) + Events + KeepAlive (30 minutes)