Introduction

In the previous chapter, we learned how to define the fundamental building blocks of our applications using KubeVela Components. We created a simple backend service, but it was just a raw deployment. In the real world, applications need more than just a running container; they need operational capabilities like scaling, network exposure, health checks, and more.

This chapter dives into KubeVela Traits, the powerful mechanism that allows platform engineers to embed these operational capabilities directly into the Application definition. We’ll explore what Traits are, why they are essential for abstracting Kubernetes complexity, and how they empower developers to declare desired operational behaviors without becoming Kubernetes experts. By the end of this chapter, you’ll be able to scale your applications and expose them to the network using KubeVela Traits.

Core Concepts: KubeVela Traits

Imagine you’re building a house. The Component is like the foundational structure – the walls, roof, and floors. But a house needs more to be livable: plumbing for water, electricity for power, and a front door to welcome guests. In KubeVela, these additional features and operational aspects are handled by Traits.

What are Traits?

A Trait in KubeVela is an operational capability that can be attached to a Component. It describes how a Component should behave or what operational features it should have. Traits are a core part of the Open Application Model (OAM), designed to separate the concerns of application developers from those of platform operators.

  • What it is: A declarative specification for an operational aspect of a component.
  • Why it exists: To abstract away the complex, low-level details of Kubernetes resources (like HorizontalPodAutoscaler, Service, Ingress) and present them as simple, high-level parameters to developers.
  • What problem it solves: It frees developers from needing deep Kubernetes knowledge for common operational tasks, allowing them to focus on application logic. Platform engineers, in turn, can define and standardize these capabilities.

The OAM Philosophy of Traits: Separation of Concerns

The brilliance of OAM, and by extension KubeVela, lies in its clear separation of responsibilities:

flowchart LR PE[Platform Engineer] --> DefineTrait[Define TraitDefinition]; DefineTrait --> KubeVela[KubeVela Control Plane]; Dev[Developer] --> UseTrait[Use Trait in Application YAML]; UseTrait --> KubeVela; KubeVela --> ProvisionResources[Provision Kubernetes Resources];
  • Platform Engineers: They define TraitDefinitions. These definitions specify what a trait does, what parameters it accepts, and how it translates into underlying Kubernetes resources. This allows them to curate a catalog of reusable operational capabilities.
  • Developers: They consume these pre-defined traits by simply listing them in their Application YAML and providing the necessary parameters. They don’t need to know the intricate details of the Kubernetes resources being provisioned.

This separation ensures consistency, reduces errors, and speeds up application delivery.

Common Trait Examples

KubeVela comes with a rich set of built-in traits, and platform engineers can extend this by defining custom traits. Let’s look at a couple of fundamental ones we’ll use today. (Note: These are standard traits available in KubeVela v1.11.0 as of 2026-06-22).

  • scaler Trait: This trait allows you to define the number of replicas for your component. It directly influences the replicas field of a Kubernetes Deployment or can even integrate with a HorizontalPodAutoscaler for dynamic scaling.
  • ingress Trait: This trait is used to expose HTTP/HTTPS services to the outside world, typically by creating Kubernetes Service and Ingress resources. It handles routing external traffic to your application component.
  • service-expose Trait: For internal service exposure within the cluster, this trait creates a Kubernetes Service resource, making your component discoverable by other applications inside the cluster.

Deep Dive: The scaler Trait

The scaler trait is your go-to for controlling how many instances (replicas) of your application component should be running.

When you add a scaler trait with replicas: 3 to a component, KubeVela will ensure that the underlying Kubernetes Deployment for that component maintains three pods. If one pod fails, Kubernetes will automatically start another to maintain the desired count.

How it works: The scaler trait primarily manipulates the replicas field of the Kubernetes Deployment or StatefulSet that KubeVela creates for your component. In more advanced scenarios, a scaler trait definition could also be configured to create a HorizontalPodAutoscaler (HPA) resource, allowing for automatic scaling based on CPU or memory utilization.

Deep Dive: The ingress Trait

To make your web application accessible from outside your Kubernetes cluster, you need an Ingress. The ingress trait simplifies this process dramatically.

Instead of writing complex Kubernetes Service and Ingress YAML, you just tell KubeVela the host, path, and port you want to expose. KubeVela then generates and manages the necessary Kubernetes resources for you.

How it works: When you apply an ingress trait, KubeVela typically performs two main actions:

  1. Creates a Kubernetes Service: This internal service provides a stable network endpoint for your component’s pods within the cluster.
  2. Creates a Kubernetes Ingress: This resource defines how external HTTP/HTTPS traffic should be routed to the Service created in step 1, based on rules like hostnames and URL paths.

⚠️ What can go wrong: For the ingress trait to work, your Kubernetes cluster must have an Ingress controller (like Nginx Ingress, Traefik, or Istio Gateway) installed and running. Without it, the Ingress resource will be created but will not actually route traffic.

Step-by-Step Implementation: Scaling a Component

Let’s take our simple my-web-app component from the previous chapter and add the ability to scale it.

First, let’s look at our base application (assuming you have a similar my-app.yaml from the previous chapter).

# my-app.yaml (Initial version from previous chapter)
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: my-web-app
spec:
  components:
    - name: backend-service
      type: webservice
      properties:
        image: crccheck/hello-world
        port: 8000

Now, let’s add the scaler trait to our backend-service component. We’ll set the replicas to 3.

  1. Modify your my-app.yaml: Open my-app.yaml and locate the backend-service component. Add a traits section under the components.backend-service block, as shown below.

    # my-app.yaml (with scaler trait)
    apiVersion: core.oam.dev/v1beta1
    kind: Application
    metadata:
      name: my-web-app
    spec:
      components:
        - name: backend-service
          type: webservice
          properties:
            image: crccheck/hello-world
            port: 8000
          # --- Start of new addition ---
          traits:
            - type: scaler
              properties:
                replicas: 3
          # --- End of new addition ---

    Explanation:

    • traits:: This new section within the backend-service component is where we declare all the operational capabilities for this component.
    • - type: scaler: We’re adding a trait of type scaler. KubeVela recognizes this type and knows how to handle it.
    • properties:: These are the parameters specific to the scaler trait.
    • replicas: 3: We’re telling KubeVela that we want 3 instances of our backend-service running.
  2. Apply the updated Application: Save the my-app.yaml file and apply it to your Kubernetes cluster using kubectl.

    kubectl apply -f my-app.yaml

    You should see output similar to application.core.oam.dev/my-web-app configured.

  3. Observe the changes: Now, let’s check if KubeVela has correctly scaled our application. We can inspect the underlying Kubernetes Deployment.

    kubectl get deployment backend-service -o wide

    You should see that the READY and AVAILABLE columns show 3/3, confirming that three replicas are running.

    NAME              READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS        IMAGES                     SELECTOR
    backend-service   3/3     3            3           2m      backend-service   crccheck/hello-world       app.oam.dev/component=backend-service

    You can also get a high-level view of your KubeVela application:

    vela ls

    This will show your my-web-app and its components and traits.

Step-by-Step Implementation: Exposing a Component with Ingress

Now that our application can scale, let’s make it accessible from outside the cluster using the ingress trait. We’ll expose it on a specific hostname and path.

  1. Modify your my-app.yaml again: Add another trait, this time the ingress trait, to your backend-service component. We’ll use my-app.example.com as the hostname and / as the path. You’ll also need to ensure the port matches the one your application listens on (which is 8000 in our webservice component properties).

    # my-app.yaml (with scaler and ingress traits)
    apiVersion: core.oam.dev/v1beta1
    kind: Application
    metadata:
      name: my-web-app
    spec:
      components:
        - name: backend-service
          type: webservice
          properties:
            image: crccheck/hello-world
            port: 8000
          traits:
            - type: scaler
              properties:
                replicas: 3
            # --- Start of new addition ---
            - type: ingress
              properties:
                domain: my-app.example.com
                http:
                  "/": 8000 # Map root path to component's port 8000
            # --- End of new addition ---

    Explanation:

    • - type: ingress: We’re adding the ingress trait.
    • properties:: Parameters for the ingress.
    • domain: my-app.example.com: The hostname under which our application will be accessible.
    • http:: Defines HTTP routing rules.
    • "/": 8000: This rule says that any request to the root path (/) on my-app.example.com should be routed to port 8000 of our backend-service component.
  2. Apply the updated Application: Save the my-app.yaml file and apply it.

    kubectl apply -f my-app.yaml
  3. Observe the changes: KubeVela will now create an Ingress resource. You can check for it:

    kubectl get ingress

    You should see an Ingress resource named something like backend-service-ingress.

    NAME                      CLASS    HOSTS                 ADDRESS         PORTS   AGE
    backend-service-ingress   <none>   my-app.example.com    <pending>       80      1m

    The ADDRESS column might show <pending> or an IP address depending on your Ingress controller setup.

    To test connectivity: You’ll need to resolve my-app.example.com to the IP address of your Ingress controller.

    • If you’re running locally (e.g., Minikube, Docker Desktop), you might get an IP from minikube ip or your cluster’s external IP.

    • You can modify your local /etc/hosts file (or C:\Windows\System32\drivers\etc\hosts on Windows) to map my-app.example.com to your Ingress controller’s IP. For example:

      <INGRESS_CONTROLLER_IP> my-app.example.com
    • Once the hostname resolves, you can use curl:

      curl http://my-app.example.com

      You should receive the “Hello World” response from your application!

Mini-Challenge

You’ve successfully scaled and exposed your application externally. Now, let’s imagine another internal service needs to communicate with backend-service without going through the public internet. This is where the service-expose trait comes in handy.

Challenge: Add a service-expose trait to your backend-service component. Configure it to expose your component on port 8000 (which is its internal listening port).

Hint: You can inspect the service-expose trait definition using vela def show service-expose to understand its parameters. You’ll likely need to specify the component’s port.

What to observe/learn: After applying the updated application, check for a new Kubernetes Service resource that KubeVela creates. Note its name and cluster IP. This service will allow other pods within your Kubernetes cluster to reach your backend-service using its internal DNS name (e.g., backend-service.default.svc.cluster.local).

Common Pitfalls & Troubleshooting

  1. Ingress Trait Not Working (Address Pending):

    • Symptom: kubectl get ingress shows <pending> under the ADDRESS column, and you can’t access your application externally.
    • Cause: Your Kubernetes cluster likely doesn’t have an Ingress controller installed (e.g., Nginx Ingress Controller, Traefik, Istio). KubeVela creates the Ingress resource, but nothing is listening for it.
    • Solution: Install an Ingress controller in your cluster. For example, for Nginx Ingress Controller: helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace ingress-nginx --create-namespace.
  2. Incorrect Trait Parameters:

    • Symptom: Application fails to deploy, or the trait doesn’t have the desired effect. KubeVela reports validation errors.
    • Cause: Typos in trait names, incorrect parameter names, or invalid values for trait properties. For example, specifying a non-existent port for the ingress trait.
    • Solution: Double-check the trait definition using vela def show <trait-type> (e.g., vela def show ingress) to verify expected parameters and types. Consult the KubeVela official documentation for built-in trait references.
  3. Application Status “Unhealthy” or “Running but Warning”:

    • Symptom: vela ls shows your application with an unhealthy status.
    • Cause: Underlying Kubernetes resources might be failing. This could be due to issues unrelated to traits (e.g., incorrect image name in the component, resource limits exceeded).
    • Solution: Use vela status my-web-app --detail to get a detailed breakdown of the application’s health, including the status of its components and traits. This command will often point you to the specific Kubernetes resource that is having issues, which you can then inspect with kubectl describe and kubectl logs.

Summary

Congratulations! You’ve successfully leveraged KubeVela Traits to enhance your application’s operational capabilities. Let’s recap the key takeaways:

  • Traits abstract complexity: They allow developers to declare high-level operational requirements (like scaling or exposing) without directly interacting with complex Kubernetes resources like Deployment, Service, or Ingress.
  • Separation of Concerns: Traits embody the OAM principle of separating developer concerns (what the app does) from platform engineering concerns (how the app operates).
  • Extensibility: KubeVela provides a rich set of built-in traits, and platform engineers can easily define custom traits to meet specific organizational needs.
  • Practical Application: You’ve seen how to use the scaler trait to control replica counts and the ingress trait to expose your application to the external network.

By using Traits, KubeVela significantly reduces the cognitive load on developers, allowing them to focus on delivering business value while platform teams ensure consistent, standardized operational practices.

In the next chapter, we’ll explore Policies, which allow platform engineers to enforce governance, security, and compliance rules across applications, adding another layer of control and automation to your application delivery pipeline.

References

This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.