Background

这两天被阿里云的CDN广告精准推送到了,看了一下之前买的价格。oss+cdn基础款,5、6年过去了目前也就涨了几块钱,估计双十一/618还能打平。

心动了,果断三下五除二给我的破站安排上。 但是阿里云的自动刷新CDN居然是收费的,好你个增值服务。

刚好我的使用场景已经集成进Drone CI流水线,那就再加一个节点用来同步刷新CDN吧。

Steps

Step1 准备访问密钥

在刷新CDN请求中,需要使用AccessKey ID 和 AccessKey Secret来生成签名,所以这一条要提前做。进入阿里云控制台RAM访问控制中,如果没有角色/用户,可以自行创建。

创建完之后点左侧用户,可以在安全信息管理中获取AccessKey ID 和 AccessKey Secret。

Step2 授予角色CDN访问权限

角色需要有CDN访问权限,才可以进行一系列CDN操作。在权限策略中,搜索CDN,直接添加就好。

Step3 准备阿里云CDN刷新脚本

本质上其实是个GET请求,可以直接使用bash脚本,利用curl发起。下面是个示例脚本:

#!/bin/bash

# 阿里云 AccessKey ID 和 AccessKey Secret
ACCESS_KEY_ID="your-access-key-id"
ACCESS_KEY_SECRET="your-access-key-secret"

# 阿里云 CDN API Url
CDN_ENDPOINT="https://cdn.aliyuncs.com"

# CDN 刷新请求的参数
DOMAIN_NAME="your-cdn-domain.com"
OBJECT_PATHS="/path/to/your/content"

# 生成请求签名
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
signature=$(echo -n "GET&%2F&$(echo -n "AccessKeyId=${ACCESS_KEY_ID}&Action=RefreshObjectCaches&DomainName=${DOMAIN_NAME}&ObjectPath=${OBJECT_PATHS}&Timestamp=${timestamp}&Version=2018-05-10" | urlencode)" | openssl dgst -sha1 -hmac "${ACCESS_KEY_SECRET}&" -binary | base64)

# 发起刷新请求
curl -X GET "${CDN_ENDPOINT}/?AccessKeyId=${ACCESS_KEY_ID}&Action=RefreshObjectCaches&DomainName=${DOMAIN_NAME}&ObjectPath=${OBJECT_PATHS}&Timestamp=${timestamp}&Version=2018-05-10&Signature=${signature}"
  • AccessKeyId 和 AccessKeySecret:你的阿里云 AccessKey ID 和 AccessKey Secret。
  • CDN_ENDPOINT:阿里云 CDN API 请求Url
  • DOMAIN_NAME 和 OBJECT_PATHS:需要刷新的 CDN 域名和对象路径。

然后我发现阿里云开发者门户有提供一些高级语言的SDK使用模板,就换成python来写了,可以使用他的调试工具,效率更高些。

这是我的python脚本:

#!/bin/bash
import time
import json
import os
from aliyunsdkcore.client import AcsClient
from aliyunsdkcdn.request.v20180510.RefreshObjectCachesRequest import RefreshObjectCachesRequest

# 从环境变量获取阿里云的密钥
ACCESS_KEY_ID = os.getenv('ACCESS_KEY_ID')
ACCESS_KEY_SECRET = os.getenv('ACCESS_KEY_SECRET')

print(ACCESS_KEY_ID, ACCESS_KEY_SECRET)

if not ACCESS_KEY_ID or not ACCESS_KEY_SECRET:
    raise ValueError("Missing Access Key or Secret")

# 初始化客户端
client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, 'cn-shanghai')

# 构建请求
request = RefreshObjectCachesRequest()
request.set_accept_format('json')

# 设置刷新类型:文件、目录等
request.set_ObjectPath('')  # 刷新文件或目录的 URL
request.set_ObjectType('Directory')  # 可以是 'File' 或 'Directory'

# 发送请求并获取响应
response = client.do_action_with_exception(request)
response_dict = json.loads(response)

# 打印响应
print(json.dumps(response_dict, indent=4))

Step4 配置Drone CI

drone.yml文件中,直接在当前构建流水线中找个合适的位置来运行上面脚本就好。下面是我的配置:

  - name: refresh-cdn 🚀
    image: python:3.9
    commands:
      - pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
      - pip install aliyun-python-sdk-core aliyun-python-sdk-cdn
      - python ./xxx.py
    environment:
      ACCESS_KEY_ID:
        from_secret: aliyun_access_key_id
      ACCESS_KEY_SECRET:
        from_secret: aliyun_access_key_secret
    when:
      status: [success]

建议 把 AccessKey ID 和 AccessKey Secret 存储在 Drone 的秘密管理中,而不是直接在 drone.yml中。

等流水线执行完,打开资源看能不能正常访问或者看流水线日志来确认CDN有没有成功刷新。

能正常返回请求id和任务id就是成功了,否则会有错误代码输出。

FAQ

  • API 权限:确保你的阿里云账户具有刷新 CDN 缓存的权限。
  • 网络问题:确保 Drone CI 环境能够访问阿里云的 CDN 请求URL。
  • 签名生成:确保生成的签名正确无误,以避免 API 请求失败

Refer