通过终端节点私网访问OSS资源

私网连接(PrivateLink)能够建立专有网络VPC(Virtual Private Cloud)与阿里云上的服务安全稳定的私有连接,简化网络架构,实现私网访问服务,避免通过公网访问服务带来的潜在安全风险。本文介绍如何通过终端节点私网访问OSS资源。

前提条件

  • 使用终端节点私网访问OSS资源目前处于邀测阶段,需联系技术支持申请使用。

  • 仅华东1(杭州)、华东2(上海)、华北2(北京)、华北6(乌兰察布)、华南1(深圳)、中国香港、新加坡、印度尼西亚(雅加达)地域支持通过终端节点私网访问OSS资源。

  • 已在与终端节点相同的地域创建专有网络VPC和交换机。具体操作,请参见创建专有网络和交换机

  • 已在同一个VPC内创建ECS实例。具体操作,请参见选购ECS实例

费用说明

  • PrivateLink开通时不产生费用。开通成功后,根据实际使用量进行计费,按每小时出账。费用包含实例费和流量处理费。更多信息,请参见计费说明

  • PrivateLink的服务使用方和服务提供方可以是不同的阿里云账号,也支持将所产生的费用归入服务使用方或者服务提供方的账号进行出账。更多信息,请参见付费方说明

应用场景

OSS服务共享给云上VPC

如下图所示,要实现同一地域内通过VPC中的终端节点私网访问云上部署的OSS资源,您需要将OSS作为服务资源加入到终端节点服务中,然后在VPC中创建连接OSS服务的终端节点,实现通过终端节点私网访问OSS服务资源。

image

OSS服务共享给本地数据中心

如下图所示,要实现在本地数据中心私网访问云上部署的OSS服务资源,您需要在同一地域内将OSS服务资源加入到终端节点服务中,然后在VPC中创建连接OSS服务的终端节点,并通过专线、VPN网关或智能接入网关将本地数据中心与VPC连接起来,实现本地数据中心私网访问OSS服务资源。

image

操作步骤

  1. 创建终端节点。

    1. 登录专有网络管理控制台
    2. 在左侧导航栏,单击终端节点

    3. 在顶部菜单栏处,选择任意支持通过终端节点私网访问OSS资源的地域。

    4. 终端节点页面下的接口终端节点页签,单击创建终端节点

    5. 创建终端节点页面,按以下说明配置各项参数,其他参数保留默认配置。

      参数

      说明

      节点名称

      输入自定义终端节点的名称。

      终端节点类型

      选择接口终端节点,表示服务使用方通过接口终端节点访问服务提供方提供的服务。

      终端节点服务

      单击阿里云服务,然后在终端节点服务名称搜索框输入com.aliyuncs.privatelink.cn-hangzhou.oss,并选中该终端节点服务。

      说明

      一个终端节点仅支持关联一个终端节点服务。

      专有网络

      选择需要创建终端节点的专有网络。

      安全组

      选择要与终端节点网卡关联的安全组,安全组可以管控到终端节点网卡的数据通信。

      可用区与交换机

      选择终端节点服务对应的可用区,然后选择该可用区内的交换机。系统会自动在每个交换机下创建一个终端节点网卡。

    6. 单击确认创建

      创建完成后,您需要记录生成的终端节点域名,用于后续访问OSS服务。

      Dingtalk_20240325172953.jpg

  2. 使用终端节点域名访问OSS。

    1. 连接ECS实例。具体步骤,请参见连接ECS实例

    2. 通过ossutil或者SDK以终端节点域名的方式访问OSS。

      ossutil

      1. 在已创建的ECS实例安装1.7.17及以上版本的ossutil。

        具体步骤,请参见安装ossutil

      2. 使用终端节点域名以ossutil的方式访问OSS。

        以将examplebucket下的文件examplefile.txt下载到本地目录/tmp/为例。示例中通过-e选项指定终端节点域名,使用--force-path-style选项指定以Path-Style的方式访问OSS。

        ossutil cp oss://examplebucket/examplefile.txt /tmp/ -e ep-bp1i317e3d65873e****.oss.cn-hangzhou.privatelink.aliyuncs.com --force-path-style

        ossutil支持使用终端节点域名进行访问的操作列表,请参见常用命令

        返回结果如下:

        Succeed: Total num: 1, size: 11. OK num: 1(download 1 objects).
        
        average speed 0(byte/s)
        
        0.188959(s) elapsed

      SDK

      仅以下语言SDK支持使用终端节点域名访问OSS。以下以使用终端节点域名将examplebucket下的文件exampleobject.txt下载到本地为例。

      SDK支持使用终端节点域名进行访问的操作列表,请参见SDK简介

      1. 在已创建的ECS实例搭建Java、Python、Go、C++环境。

      2. 选择以下任意语言SDK以终端节点域名的方式下载OSS资源。

        Java

        import com.aliyun.oss.*;
        import com.aliyun.oss.common.auth.*;
        import com.aliyun.oss.model.GetObjectRequest;
        import java.io.File;
        
        public class Demo {
        
            public static void main(String[] args) throws Exception {
                // Endpoint填写终端节点域名。
                String endpoint = "https://ep-bp1i317e3d65873e****.oss.cn-hangzhou.privatelink.aliyuncs.com";
                //从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。
                EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
                // 填写Bucket名称,例如examplebucket。
                String bucketName = "examplebucket";
                // 填写不包含Bucket名称在内的Object完整路径,例如exampleobject.txt。
                String objectName = "exampleobject.txt";
                String pathName = "D:\\examplefile.txt";
                 
                ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
                // 开启二级域名的访问方式。
                conf.setSLDEnabled(true);
                // 创建OSSClient实例。
                OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider, conf);
                
        
                try {
                    // 下载Object到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。
                    // 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
                    ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));
                } catch (OSSException oe) {
                    System.out.println("Caught an OSSException, which means your request made it to OSS, "
                            + "but was rejected with an error response for some reason.");
                    System.out.println("Error Message:" + oe.getErrorMessage());
                    System.out.println("Error Code:" + oe.getErrorCode());
                    System.out.println("Request ID:" + oe.getRequestId());
                    System.out.println("Host ID:" + oe.getHostId());
                } catch (ClientException ce) {
                    System.out.println("Caught an ClientException, which means the client encountered "
                            + "a serious internal problem while trying to communicate with OSS, "
                            + "such as not being able to access the network.");
                    System.out.println("Error Message:" + ce.getMessage());
                } finally {
                    if (ossClient != null) {
                        ossClient.shutdown();
                    }
                }
            }
        }

        Python

        # -*- coding: utf-8 -*-
        import oss2
        from oss2.credentials import EnvironmentVariableCredentialsProvider
        
        # 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
        auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
        # Endpoint填写终端节点域名。
        # 填写Bucket名称,例如examplebucket。
        # is_path_style=True用于开启二级域名的访问方式。
        bucket = oss2.Bucket(auth, 'https://ep-bp1i317e3d65873e****.oss.cn-hangzhou.privatelink.aliyuncs.com', 'examplebucket', is_path_style=True)
        
        # 填写Object完整路径,完整路径中不包含Bucket名称,例如exampleobject.txt。
        # 下载Object到本地文件,并保存到指定的本地路径D:\\examplefile.txt。如果指定的本地文件存在会覆盖,不存在则新建。
        bucket.get_object_to_file('exampleobject.txt', 'D:\\examplefile.txt')      

        Go

        package main
        
        import (
        	"fmt"
        	"os"
        
        	"github.com/aliyun/aliyun-oss-go-sdk/oss"
        )
        
        func main() {
        	// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。
        	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
        	if err != nil {
        		fmt.Println("Error:", err)
        		os.Exit(-1)
        	}
        	// 创建OSSClient实例。
        	// yourEndpoint填写终端节点域名。
        	// oss.ForcePathStyle(true)用于开启二级域名访问方式。
        	client, err := oss.New("https://ep-bp1i317e3d65873e****.oss.cn-hangzhou.privatelink.aliyuncs.com", "", "", oss.SetCredentialsProvider(&provider),oss.ForcePathStyle(true))
        	if err != nil {
        		fmt.Println("Error:", err)
        		os.Exit(-1)
        	}
        
        	// 填写Bucket名称,例如examplebucket。
        	bucket, err := client.Bucket("examplebucket")
        	if err != nil {
        		fmt.Println("Error:", err)
        		os.Exit(-1)
        	}
        
        	// 下载文件到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。
        	// 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
        	// 依次填写Object完整路径(例如exampleobject.txt)和本地文件的完整路径(例如D:\\examplefile.txt)。Object完整路径中不能包含Bucket名称。
        	err = bucket.GetObjectToFile("exampleobject.txt", "D:\\examplefile.txt")
        	if err != nil {
        		fmt.Println("Error:", err)
        		os.Exit(-1)
        	}
        }

        C++

        #include <alibabacloud/oss/OssClient.h>
        #include <memory>
        #include <fstream>
        using namespace AlibabaCloud::OSS;
        
        int main(void)
        {
            /* 初始化OSS账号信息。*/
                    
            /* 填写终端节点域名。*/
            std::string Endpoint = "https://ep-bp1i317e3d65873e****.oss.cn-hangzhou.privatelink.aliyuncs.com";
            /* 填写Bucket名称,例如examplebucket。*/
            std::string BucketName = "examplebucket";
            /* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampleobject.txt。*/
            std::string ObjectName = "exampleobject.txt";
            /* 下载Object到本地文件examplefile.txt,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。*/
            /* 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。*/
            std::string FileNametoSave = "D:\\examplefile.txt";
        
            /* 初始化网络等资源。*/
            InitializeSdk();
        
            ClientConfiguration conf;	
            /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。*/    
            auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
            /* conf.isPathStyle = true用于开启二级域名访问方式。*/
            conf.isPathStyle = true
            OssClient client(Endpoint, credentialsProvider, conf);
        
            /* 下载Object到本地文件。*/
            GetObjectRequest request(BucketName, ObjectName);
            request.setResponseStreamFactory([=]() {return std::make_shared<std::fstream>(FileNametoSave, std::ios_base::out | std::ios_base::in | std::ios_base::trunc| std::ios_base::binary); });
        
            auto outcome = client.GetObject(request);
        
            if (outcome.isSuccess()) {    
                std::cout << "GetObjectToFile success" << outcome.result().Metadata().ContentLength() << std::endl;
            }
            else {
                /* 异常处理。*/
                std::cout << "GetObjectToFile fail" <<
                ",code:" << outcome.error().Code() <<
                ",message:" << outcome.error().Message() <<
                ",requestId:" << outcome.error().RequestId() << std::endl;
                return -1;
            }
        
            /* 释放网络等资源。*/
            ShutdownSdk();
            return 0;
        }