All Products
Search
Document Center

Elastic Container Instance:Attach a RAM role to an ECI pod

Last Updated:Apr 01, 2026

Assign a Resource Access Management (RAM) role to an Elastic Container Instance-based pod so that applications running in the pod can call other Alibaba Cloud service APIs using Security Token Service (STS) temporary credentials — without storing an AccessKey pair in the pod.

Why use a RAM role

Storing an AccessKey pair directly in a pod (for example, in a configuration file) creates several problems:

  • Credential exposure: A leaked AccessKey pair grants permanent access until manually revoked.

  • Excessive permissions: A shared AccessKey pair is hard to scope to only what each pod needs.

  • High maintenance overhead: Rotating credentials requires updating every pod that stores them.

A RAM role eliminates these problems. The pod assumes the role at runtime and receives short-lived STS credentials that are automatically rotated. To change what a pod can access, update the role's permission policy — no pod restart required.

For background on RAM roles, see RAM role overview.

Prerequisites

Before you begin, ensure that you have:

  • An Elastic Container Instance-based pod (or a Deployment that schedules ECI pods)

  • (Optional) If a RAM user will perform this setup, the RAM user must have the ram:PassRole permission for the target role. See step 3 in Create a RAM role and grant permissions

Create a RAM role and grant permissions

  1. Create a RAM role. For more information, see Create a RAM role for a trusted Alibaba Cloud service. When prompted, select Alibaba Cloud Service as the trusted entity and Elastic Compute Service as the trusted service.

    RAM角色.png

  2. Attach a permission policy to the role.

    1. Create a custom policy. For more information, see Create custom policies.

    2. Attach the policy to the RAM role. For more information, see Grant permissions to a RAM role.

  3. (Optional) Grant a RAM user permission to pass the role. If a RAM user will assign this role to pods, the RAM user needs the ram:PassRole permission scoped to the role. Replace ECIRamRoleTest with your role name.

    {
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "ram:PassRole",
          "Resource": "acs:ram:*:*:role/ECIRamRoleTest"
        }
      ],
      "Version": "1"
    }

Assign the RAM role to a pod

Add the k8s.aliyun.com/eci-ram-role-name annotation to the pod's metadata when creating it. Replace ${your_ram_role_name} with your RAM role name.

Important

Annotations take effect only when the pod is created. Adding or modifying annotations on an existing pod has no effect. For a Deployment, add the annotation under spec.template.metadata, not under the top-level metadata.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
  labels:
    app: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      name: test
      labels:
        app: test
        alibabacloud.com/eci: "true"
      annotations:
        k8s.aliyun.com/eci-ram-role-name: "${your_ram_role_name}"   # Assign the RAM role.
    spec:
      containers:
      - name: test
        image: registry.cn-shanghai.aliyuncs.com/eci_open/centos:7
        command: ["sleep"]
        args: ["3600"]

Verify the configuration

After the pod starts, confirm it can retrieve STS credentials from the instance metadata service.

Run the following command from inside the pod. Replace ${your_ram_role_name} with your RAM role name.

curl http://100.100.100.200/latest/meta-data/ram/security-credentials/${your_ram_role_name}

For example, if your role is named ECIRamRoleTest:

curl http://100.100.100.200/latest/meta-data/ram/security-credentials/ECIRamRoleTest

A successful response looks like this:

{
  "AccessKeyId": "STS.******",
  "AccessKeySecret": "******",
  "Expiration": "2023-06-22T19:13:58Z",
  "SecurityToken": "******",
  "LastUpdated": "2023-06-22T13:13:58Z",
  "Code": "Success"
}

If the response returns Code: Success, the role is correctly assigned and credentials are available. STS credentials are automatically rotated before they expire.

Access Alibaba Cloud services using STS credentials

The following Go example retrieves STS credentials from the metadata service and uses them to list objects in an Object Storage Service (OSS) bucket.

Note

This example demonstrates the pattern for using STS credentials. In production, adapt the code to your business logic and consult the SDK documentation for the service you are calling. Refresh the OSS client before credentials expire to avoid access failures.

package main

import (
	"encoding/json"
	"flag"
	"log"
	"os/exec"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

const (
	securityCredUrl = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
)

var (
	ossEndpoint   string
	ossBucketName string
)

func init() {
	flag.StringVar(&ossEndpoint, "endpoint", "oss-cn-hangzhou-internal.aliyuncs.com", "Please input oss endpoint, Recommended internal endpoint, eg: oss-cn-hangzhou-internal.aliyuncs.com")
	flag.StringVar(&ossBucketName, "bucket", "", "Please input oss bucket name")
}

type AssumedRoleUserCredentialsWithServiceIdentity struct {
	AccessKeyId     string `json:"AccessKeyId" xml:"AccessKeyId"`
	AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"`
	Expiration      string `json:"Expiration" xml:"Expiration"`
	SecurityToken   string `json:"SecurityToken" xml:"SecurityToken"`
	LastUpdated     string `json:"LastUpdated" xml:"LastUpdated"`
	Code            string `json:"Code" xml:"Code"`
}

func main() {
	flag.Parse()

	if ossEndpoint == "" {
		log.Fatal("Please input oss endpoint, eg: oss-cn-hangzhou-internal.aliyuncs.com")
	}
	if ossBucketName == "" {
		log.Fatal("Please input oss bucket name")
	}

	// Retrieve the RAM role name from the metadata service.
	output, err := exec.Command("curl", securityCredUrl).Output()
	if err != nil {
		log.Fatalf("Failed to get RAM role name from metadata service: %s", err)
	}

	// Retrieve STS credentials for the role.
	output, err = exec.Command("curl", securityCredUrl+string(output)).Output()
	if err != nil {
		log.Fatalf("Failed to get security credentials from metadata service: %s", err)
	}

	authServiceIdentity := new(AssumedRoleUserCredentialsWithServiceIdentity)
	if err := json.Unmarshal(output, authServiceIdentity); err != nil {
		log.Fatalf("Failed to unmarshal security credentials: %s", err)
	}

	// Create an OSS client using STS credentials.
	// In production, refresh the client before credentials expire to maintain continuous access.
	ossClient, err := oss.New(ossEndpoint, authServiceIdentity.AccessKeyId,
		authServiceIdentity.AccessKeySecret, oss.SecurityToken(authServiceIdentity.SecurityToken))
	if err != nil {
		log.Fatalf("Failed to create OSS client: %s", err)
	}

	// Get a reference to the bucket.
	bucket, err := ossClient.Bucket(ossBucketName)
	if err != nil {
		log.Fatalf("Failed to get bucket %q: %s", ossBucketName, err)
	}

	// List all objects in the bucket. By default, up to 100 objects are returned per request.
	marker := ""
	for {
		lsRes, err := bucket.ListObjects(oss.Marker(marker))
		if err != nil {
			log.Fatalf("Failed to list objects in bucket %q: %s", ossBucketName, err)
		}
		for _, object := range lsRes.Objects {
			log.Println("Object:", object.Key)
		}
		if lsRes.IsTruncated {
			marker = lsRes.NextMarker
		} else {
			break
		}
	}
}

What's next