无法通过HTTP API设置Azure自动缩放公式的认证问题
嘿,看起来你在手动构造Azure Batch API的签名时踩了个常见的坑——签名不匹配导致403认证失败,咱们一步步拆解问题解决它:
一、先搞清楚签名不匹配的核心原因
Azure Batch的SharedKey签名规则非常严格,你构造的StringToSign必须和服务器端生成的完全一致。你提到服务器的签名字符串包含数字237,大概率是你遗漏了某个关键的格式细节,常见的坑点有这几个:
1. 请求头的顺序和格式错误
Azure要求StringToSign必须严格遵循固定模板:
HTTP_VERB\n CONTENT_ENCODING\n CONTENT_LANGUAGE\n CONTENT_LENGTH\n CONTENT_MD5\n CONTENT_TYPE\n DATE\n IF_MODIFIED_SINCE\n IF_MATCH\n IF_NONE_MATCH\n IF_UNMODIFIED_SINCE\n RANGE\n CANONICALIZED_HEADERS\n CANONICALIZED_RESOURCE
你现在的StringToSign把ocp-date放错位置了——它属于自定义头,应该放在CANONICALIZED_HEADERS区域,而且要注意:
- 自定义头必须全小写(比如
ocp-date不能写成Ocp-Date) - 格式是
headername:headervalue,每个头单独占一行 - 写完自定义头后要加一个空行,再写CANONICALIZED_RESOURCE
2. 标准化资源(Canonicalized Resource)构造错误
这是最容易出错的地方,标准化资源的格式要求:/accountname/path?query_string
而且必须满足:
- 所有查询参数按字母顺序排序(比如你的
api-version要排在timeout前面,不能反过来) - 参数名和值要完整保留,不能遗漏
你之前把资源路径和查询参数混在一起,完全不符合规则,这肯定会导致签名不匹配。
二、修正后的StringToSign示例
按照正确规则,你的StringToSign应该是这样的(注意空行和顺序):
POST application/json;odata=minimalmetadata ocp-date:wed, 30 dec 2020 13:02:22 GMT /myaccountname/pools/scalingpool/enableautoscale api-version:2020-09-01.12.0 timeout:30
⚠️ 重要提醒:ocp-date的值要和你curl请求里的完全一致,包括日期格式(必须是RFC1123格式),而且服务器会校验时间差不能超过15分钟,否则也会返回403。
三、修正Python签名代码的关键细节
你之前的签名代码有个致命错误:Azure Batch的账号密钥是Base64编码的,不能直接encode成utf-8,必须先解码成字节再用于HMAC计算!正确的代码应该是:
import hmac import hashlib import base64 # 替换成你的真实账号密钥(Base64格式) account_key = "your_base64_account_key" # 替换成上面构造的正确StringToSign string_to_sign = """POST application/json;odata=minimalmetadata ocp-date:wed, 30 dec 2020 13:02:22 GMT /myaccountname/pools/scalingpool/enableautoscale api-version:2020-09-01.12.0 timeout:30""" # 先解码账号密钥为字节 secret_key = base64.b64decode(account_key) # 生成HMAC签名 signature = hmac.new(secret_key, string_to_sign.encode('utf-8'), hashlib.sha256) # 转成Base64字符串 b64_signature = base64.b64encode(signature.digest()).decode('ascii') print(b64_signature)
四、关于按工作日/时段缩放的需求
你提到不想用HPA或Cluster Autoscaler,而是按时间规则维护机器,其实Azure Batch的自动缩放公式本身就支持时间表达式,完全能满足你的需求。比如下面的公式可以实现工作日8-18点保持5个节点,其余时间缩到1个:
$TargetDedicatedNodes = (time().weekday >= 1 && time().weekday <= 5 && time().hour >= 8 && time().hour <= 18) ? 5 : 1;
把这个公式放到你的autoscaling_pool_scalingpool.json里,格式要正确:
{ "autoScaleFormula": "$TargetDedicatedNodes = (time().weekday >= 1 && time().weekday <=5 && time().hour >=8 && time().hour <=18) ? 5 : 1;" }
另外,别忘了检查你的Batch账号权限——确保它拥有Batch Contributor角色,并且已经分配到对应的集群或资源组(rg2)上,权限不足也会导致403。
最后再核对一遍curl请求里的所有头和参数,确保和StringToSign里的内容完全匹配,应该就能解决问题了!
内容的提问来源于stack exchange,提问作者phanxen

