当ECS实例或部署在ECS实例上的应用需要访问其他云资源时,必须配置访问凭证,阿里云服务会通过访问凭证验证您的身份信息和访问权限。实例RAM角色允许您将一个角色关联到ECS实例,实现在实例内部自动获取并刷新临时访问凭证,无需直接暴露AccessKey,减少密钥泄露的风险。同时,也可借助RAM角色精细化控制资源访问权限,避免权限过度分配。本文介绍在ECS中无需AccessKey直接访问日志服务SDK的操作步骤。
实例RAM角色是一种可信实体为阿里云服务的RAM角色,即允许云服务扮演的角色,用于解决跨服务访问问题。关于RAM角色的详细说明,请参见什么是RAM角色。
阿里云访问密钥(AccessKey)是调用API访问云资源的安全口令,您可以使用AccessKey签名API请求内容以通过服务端的安全验证。关于AccessKey的详细说明,请参见访问密钥。
日志服务自定义权限策略信息请参见RAM自定义授权示例。
使用限制
步骤一:创建ECS实例RAM角色并授予给ECS
通过控制台创建和授予
登录RAM控制台,创建实例RAM角色。
创建可信实体为阿里云服务的RAM角色。
选择身份管理 > 角色,单击创建角色,按照界面提示完成角色创建。注意以下参数(其他参数按需填写,可参见创建普通服务角色):
可信实体类型:选择阿里云服务。
角色类型:选择普通服务角色。
受信服务:选择云服务器。
为已创建的实例RAM角色授权。
将系统策略或已创建的自定义权限策略授权给RAM用户,使其拥有相关的资源访问或操作权限。例如,给角色赋予日志服务的只读权限(AliyunLogReadOnlyAccess)。
说明支持添加系统策略或自定义策略。若系统策略不满足您的需求,可新建自定义策略。具体操作,请参见创建自定义权限策略。
授予实例RAM角色给ECS实例。
登录ECS管理控制台。
在左侧导航栏,选择 。
在页面左侧顶部,选择目标资源所在的资源组和地域。
找到要操作的ECS实例,选择
。在对话框中,选择创建好的实例RAM角色,单击确定。
通过API创建和授予
创建并配置实例RAM角色
调用CreateRole接口创建实例RAM角色。
按如下策略设置参数AssumeRolePolicyDocument:
{ "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": [ "ecs.aliyuncs.com" ] } } ], "Version": "1" }
(可选)调用CreatePolicy接口新建权限策略。
如果您已有可用权限策略,可跳过该步骤。
PolicyDocument
(权限策略)需按如下设置:{ "Statement": [ { "Action": [ "oss:Get*", "oss:List*" ], "Effect": "Allow", "Resource": "*" } ], "Version": "1" }
调用AttachPolicyToRole接口为实例RAM角色授权。
调用AttachInstanceRamRole接口将RAM角色授予ECS实例。
步骤二:访问日志服务SDK
Java
Java SDK
在Maven工程中使用日志服务Java SDK,只需在pom.xml中加入相应依赖。更多信息,请参见Java SDK。
重要Java SDK最低版本号为0.6.110。
<dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>aliyun-log</artifactId> <version>0.6.110</version> </dependency>
Client
类入参取消AccessKey,传入步骤一创建的实例RAM角色名称。import com.aliyun.openservices.log.exception.LogException; import com.aliyun.openservices.log.response.GetProjectResponse; public class Main { public static void main(String[] args) throws LogException { // 这里将RoleName替换成上面创建的 ram 角色名 Client client = new Client("cn-hangzhou.log.aliyuncs.com", "RoleName"); GetProjectResponse resp = client.GetProject("your-project"); System.out.println(resp.GetProjectDescription()); } }
Java Producer
在Maven工程中使用日志服务Aliyun Log Java Producer,只需在pom.xml中加入相应依赖。更多信息,请参见Aliyun Log Java Producer。
重要Java Producer最低版本号为0.3.22。
<dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>aliyun-log-producer</artifactId> <version>0.3.22</version> </dependency>
配置日志项目中
ProjectConfig
入参取消AccessKey,传入步骤一创建的实例RAM角色名称。import com.aliyun.openservices.aliyun.log.producer.*; import com.aliyun.openservices.aliyun.log.producer.errors.ProducerException; import com.aliyun.openservices.log.common.LogItem; import com.aliyun.openservices.log.common.auth.CredentialsProvider; import com.aliyun.openservices.log.common.auth.ECSRoleCredentialsProvider; public class ExampleUsage { public static void main(String[] args) throws ProducerException, InterruptedException { String endpoint = "cn-hangzhou.log.aliyuncs.com"; String project = "your-project"; String logStore = "your-logstore"; // 配置ProducerConfig Config producerConfig = new ProducerConfig(); // 创建Producer Producer producer = new LogProducer(new ProducerConfig()); // 这里将 your-ecs-ram-role-name 替换成上面创建的 ram 角色名 CredentialsProvider provider = new ECSRoleCredentialsProvider("your-ecs-ram-role-name"); // 配置日志项目 ProjectConfig projectConfig = new ProjectConfig(project, endpoint, provider, null); producer.putProjectConfig(projectConfig); // send logs producer.send(project, logStore, buildLogItem()); producer.send(project, logStore, null, null, buildLogItem()); producer.send(project, logStore, "", "", buildLogItem()); producer.close(); } public static LogItem buildLogItem() { LogItem logItem = new LogItem(); logItem.PushBack("k1", "v1"); logItem.PushBack("k2", "v2"); return logItem; } }
Java Consumer
在Maven工程中使用日志服务Aliyun LOG Java Consumer,只需在pom.xml中加入相应依赖。更多信息,请参见通过消费组消费数据。
重要Java Consumer最低版本号为0.6.47。
<dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>loghub-client-lib</artifactId> <version>0.6.47</version> </dependency>
创建消费者
LogHubConfig
入参取消AccessKey,传入步骤一创建的实例RAM角色名称。import com.aliyun.openservices.log.common.auth.ECSRoleCredentialsProvider; import com.aliyun.openservices.log.common.auth.CredentialsProvider; import com.aliyun.openservices.loghub.client.ClientWorker; import com.aliyun.openservices.loghub.client.config.LogHubConfig; import com.aliyun.openservices.loghub.client.exceptions.LogHubClientWorkerException; public class Main { private static String Endpoint = "cn-hangzhou.log.aliyuncs.com"; private static String Project = "your-project"; private static String Logstore = "your-logstore"; private static String ConsumerGroup = "consumerGroupX"; public static void main(String[] args) throws LogHubClientWorkerException, InterruptedException { // 这里将 your-ecs-ram-role-name 替换成上面创建的 ram 角色名 CredentialsProvider provider = new ECSRoleCredentialsProvider("your-ecs-ram-role-name"); LogHubConfig config = new LogHubConfig(ConsumerGroup, "consumer_1", Endpoint, Project, Logstore, provider, LogHubConfig.ConsumePosition.BEGIN_CURSOR); config.setMaxFetchLogGroupSize(1000); ClientWorker worker = new ClientWorker(new SampleLogHubProcessorFactory(), config); Thread thread = new Thread(worker); thread.start(); Thread.sleep(60 * 60 * 1000); worker.shutdown(); Thread.sleep(30 * 1000); } }
Go
无AccessKey访问日志服务Go SDK,Go SDK最低版本号为 0.1.83。升级Go SDK,请参见安装或升级SDK。
Go SDK
provider
入参传入步骤一创建的实例RAM角色名称。
package main
import (
"fmt"
sls "github.com/aliyun/aliyun-log-go-sdk"
)
func main() {
// 日志服务的服务入口。此处以杭州为例,其它地域请根据实际情况填写。
Endpoint := "cn-chengdu.log.aliyuncs.com"
// 这里将 your-ecs-ram-role-name 替换成上面创建的 ram 角色名
provider := sls.NewEcsRamRoleCredentialsProvider("your-ecs-ram-role-name")
// 创建日志服务Client。
client := sls.CreateNormalInterfaceV2(Endpoint, provider)
resp, err := client.GetProject("your-project")
if err != nil {
panic(err)
}
fmt.Println(resp.Description)
}
Go Producer
配置ProducerConfig中provider
入参传入步骤一创建的实例RAM角色名称。
package main
import (
"fmt"
"os"
"os/signal"
"sync"
"time"
sls "github.com/aliyun/aliyun-log-go-sdk"
"github.com/aliyun/aliyun-log-go-sdk/producer"
"github.com/gogo/protobuf/proto"
)
func main() {
producerConfig := producer.GetDefaultProducerConfig()
producerConfig.Endpoint = "cn-hangzhou.log-aliyuncs.com"
// 这里将 your-ecs-ram-role-name 替换成上面创建的 ram 角色名
provider := sls.NewEcsRamRoleCredentialsProvider("your-ecs-ram-role-name")
producerConfig.CredentialsProvider = provider
producerInstance := producer.InitProducer(producerConfig)
ch := make(chan os.Signal)
signal.Notify(ch, os.Kill, os.Interrupt)
producerInstance.Start()
var m sync.WaitGroup
for i := 0; i < 10; i++ {
m.Add(1)
go func() {
defer m.Done()
for i := 0; i < 1000; i++ {
log := producer.GenerateLog(uint32(time.Now().Unix()), map[string]string{"content": "test", "content2": fmt.Sprintf("%v", i)})
err := producerInstance.SendLog("log-project", "log-store", "topic", "127.0.0.1", log)
if err != nil {
fmt.Println(err)
}
}
}()
}
m.Wait()
fmt.Println("Send completion")
if _, ok := <-ch; ok {
fmt.Println("Get the shutdown signal and start to shut down")
producerInstance.Close(60000)
}
}
Go Consumer
CredentialsProvider
入参传入步骤一创建的实例RAM角色名称。
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
sls "github.com/aliyun/aliyun-log-go-sdk"
consumerLibrary "github.com/aliyun/aliyun-log-go-sdk/consumer"
"github.com/go-kit/kit/log/level"
)
func main() {
option := consumerLibrary.LogHubConfig{
Endpoint: "cn-hangzhou.log-aliyuncs.com",
// 这里将 your-ecs-ram-role-name 替换成上面创建的 ram 角色名
CredentialsProvider: sls.NewEcsRamRoleCredentialsProvider("your-ecs-ram-role-name"),
Project: "your-project",
Logstore: "your-logstore",
ConsumerGroupName: "your-consumer-group",
ConsumerName: "your-consumer-group-consumer-1",
CursorPosition: consumerLibrary.END_CURSOR,
}
consumerWorker := consumerLibrary.InitConsumerWorkerWithCheckpointTracker(option, process)
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
consumerWorker.Start()
if _, ok := <-ch; ok {
level.Info(consumerWorker.Logger).Log("msg", "get stop signal, start to stop consumer worker", "consumer worker name", option.ConsumerName)
consumerWorker.StopAndWait()
}
}
// 数据消费处理逻辑
func process(shardId int, logGroupList *sls.LogGroupList, checkpointTracker consumerLibrary.CheckPointTracker) (string, error) {
fmt.Println(shardId, logGroupList)
checkpointTracker.SaveCheckPoint(false)
return "", nil
}
相关文档
当您的自建应用部署在阿里云ECS服务器上,且需要访问KMS应用时,可以使用ECS实例RAM角色访问KMS。具体操作,请参见使用ECS实例RAM角色安全访问KMS。
当ECS不需要某些资源访问权限时,可以通过移除实例RAM角色的权限来实现。具体操作,请参见为RAM角色移除权限。
访问阿里云OpenAPI时,如果在代码中硬编码明文AK,容易因代码仓库权限管理不当造成AK泄露,建议您通过非AccessKey硬编码的方式编程,使用访问凭证访问阿里云OpenAPI,可参见使用访问凭据访问阿里云OpenAPI最佳实践和凭据的安全使用方案。