Resource Access Management (RAM) ロールは、特定の権限を持ち、Elastic Container Instance ベースのPodによってアシュームできる仮想ユーザーです。これにより、Podは対応する権限を取得できます。このトピックでは、PodにRAMロールを割り当てる方法について説明します。このようにして、Pod上のアプリケーションは、Security Token Service (STS) クレデンシャルに基づいて他のAlibaba CloudサービスのAPIにアクセスできます。
背景情報
Podにデプロイされたアプリケーションは、Alibaba CloudアカウントまたはRAMユーザーのAccessKeyペアを使用して、オブジェクトストレージサービス (OSS)、仮想プライベートクラウド (VPC)、ApsaraDB RDSなどの他のAlibaba CloudサービスのAPIにアクセスできます。API操作を便利に呼び出すために、一部のユーザーはAccessKeyペアをPodに書き込みます。たとえば、AccessKeyペアを構成ファイルに書き込みます。ただし、この方法は、情報漏洩、メンテナンスの複雑さの増加、過剰な権限などの問題を引き起こす可能性があります。
インスタンスRAMロールは、これらの問題を防ぐことができます。RAMロールを使用すると、PodにAccessKeyペアを保存する必要がなくなります。Podの権限を変更する場合、PodによってアシュームされるRAMロールの権限のみを変更する必要があります。これにより、AccessKeyペアの漏洩のリスクが軽減されます。RAMロールの詳細については、RAMロールの概要を参照してください。
RAMロールを作成し、ロールに権限を付与する
RAMロールを作成します。詳細については、信頼できるAlibaba CloudサービスのRAMロールを作成するを参照してください。
RAMロールを作成するときは、信頼できるエンティティとしてAlibaba Cloudサービスを、信頼できるサービスとしてElastic Compute Serviceを選択します。

RAMロールに権限ポリシーをアタッチします。
ポリシーを作成します。詳細については、カスタムポリシーの作成を参照してください。
RAMロールにポリシーをアタッチします。詳細については、RAMロールへの権限の付与を参照してください。
(オプション) RAMユーザーにRAMロールの使用を許可します。
RAMユーザーにRAMロールを使用させる場合は、RAMユーザーに
ram:passRole権限があることを確認してください。次のコードは、権限の詳細を示しています。ECIRamRoleTestはRAMロールの名前です。RAMロールのram:PassRole権限は、RAMユーザーに付与されます。{ "Statement": [ { "Effect": "Allow", "Action": "ram:PassRole", "Resource": "acs:ram:*:*:role/ECIRamRoleTest" } ], "Version": "1" }
PodにRAMロールを割り当てる
Podを作成するときに、k8s.aliyun.com/eci-ram-role-nameアノテーションを使用して、PodにRAMロールを割り当てることができます。このようにして、PodはRAMロールをアシュームしてAlibaba Cloudサービスにアクセスできます。
アノテーションは、Podの構成ファイルのメタデータに追加する必要があります。たとえば、Deploymentを作成するときは、spec.template.metadataセクションにアノテーションを追加する必要があります。
Elastic Container Instanceの機能を使用するには、Elastic Container InstanceベースのPodを作成するときにのみアノテーションを追加できます。Podを更新するときにアノテーションを追加または変更しても、これらのアノテーションは有効になりません。
例:
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}" # RAMロールを割り当てます。
spec:
containers:
- name: test
image: registry.cn-shanghai.aliyuncs.com/eci_open/centos:7
command: ["sleep"]
args: ["3600"]STSトークンの取得
PodのメタデータURLにアクセスして、RAMロールのSTSトークンを取得できます。STSトークンを使用して、RAMロールの権限を実行し、リソースを使用できます。STSトークンは自動的かつ定期的に更新されます。
curl http://100.100.100.200/latest/meta-data/ram/security-credentials/${your_ram_role_name}${your_ram_role_name}を実際のRAMロール名に置き換えます。この例では、ECIRamRoleTestをRAMロールの名前として使用します。サンプルコマンド:
curl http://100.100.100.200/latest/meta-data/ram/security-credentials/ECIRamRoleTestコマンド出力でSTSトークンを取得できます。例:
{
"AccessKeyId" : "STS.******",
"AccessKeySecret" : "******",
"Expiration" : "2023-06-22T19:13:58Z",
"SecurityToken" : "******",
"LastUpdated" : "2023-06-22T13:13:58Z",
"Code" : "Success"
}STSトークンに基づいてAlibaba Cloudサービスにアクセスする
次の例は、STSトークンを使用してSDK for Goを使用してAlibaba Cloudサービスにアクセスする方法を示しています。この例では、取得したSTSトークンを使用してOSSバケットにアクセスし、バケットにリストされているすべてのオブジェクトを表示できます。
次のサンプルコードは、STSトークンを使用してAlibaba Cloudサービスにアクセスする方法を示すためだけに使用されます。実際のシナリオでは、ビジネス要件に基づいてコードを記述してください。詳細については、使用するクラウドサービスのSDKを参照してください。
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", "OSSエンドポイントを入力してください。内部エンドポイントを推奨します。例:oss-cn-hangzhou-internal.aliyuncs.com")
flag.StringVar(&ossBucketName, "bucket", "", "OSSバケット名を入力してください")
}
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("OSSエンドポイントを入力してください。例:oss-cn-hangzhou-internal.aliyuncs.com")
}
if ossBucketName == "" {
log.Fatal("OSSエンドポイントを入力してください")
}
output, err := exec.Command("curl", securityCredUrl).Output()
if err != nil {
log.Fatalf("メタサーバーからRAMロール名を取得できませんでした: %s", err)
}
output, err = exec.Command("curl", securityCredUrl+string(output)).Output()
if err != nil {
log.Fatalf("メタサーバーからセキュリティクレデンシャルを取得できませんでした: %s", err)
}
authServiceIdentity := new(AssumedRoleUserCredentialsWithServiceIdentity)
if err := json.Unmarshal(output, authServiceIdentity); err != nil {
log.Fatalf("AssumedRoleUserCredentialsWithServiceIdentityへのUnmarshalに失敗しました: %s", err)
}
// OSSクライアントインスタンスを作成します。本番環境でOSSクライアントを使用する場合は、STSトークンの有効期限が切れ、Alibaba Cloudサービスへのアクセスに失敗しないように、OSSクライアントを定期的に更新する必要があります。
ossClient, err := oss.New(ossEndpoint, authServiceIdentity.AccessKeyId,
authServiceIdentity.AccessKeySecret, oss.SecurityToken(authServiceIdentity.SecurityToken))
if err != nil {
log.Fatalf("新しいOSSクライアントの作成に失敗しました: %s", err)
}
// バケットを取得します。
bucket, err := ossClient.Bucket(ossBucketName)
if err != nil {
log.Fatalf("バケット %q の取得に失敗しました: %s", ossBucketName, err)
}
// バケット内のオブジェクトを一覧表示します。
marker := ""
for {
lsRes, err := bucket.ListObjects(oss.Marker(marker))
if err != nil {
log.Fatalf("バケット %q からオブジェクトを一覧表示できませんでした: %s", ossBucketName, err)
}
// リストされたオブジェクトを表示します。デフォルトでは、一度に最大100個のオブジェクトが返されます。
for _, object := range lsRes.Objects {
log.Println("Bucket: ", object.Key)
}
if lsRes.IsTruncated {
marker = lsRes.NextMarker
} else {
break
}
}
}