函数计算自动化运维实战1 -- 定时任务

简介: 阿里云函数计算是一个事件驱动的全托管计算服务。设置定时触发器,可以在某个时间点触发函数执行或者每隔5分钟触发函数一次;这样就可定时执行自定义的功能,比如这个功能就是运维脚本或者任务

函数计算

阿里云函数计算是一个事件驱动的全托管计算服务。通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传。函数计算会为您准备好计算资源,以弹性、可靠的方式运行您的代码,并提供日志查询,性能监控,报警等功能。借助于函数计算,您可以快速构建任何类型的应用和服务,无需管理和运维。更棒的是,您只需要为代码实际运行消耗的资源付费,而代码未运行则不产生费用。

函数计算中的TimeTrigger

触发器是触发函数执行的方式。有时候您不想手动调用函数执行,您希望当某件事情发生时自动触发函数的执行,这个事情就是事件源。您可以通过配置触发器的方式设置事件源触发函数执行。

例如,设置定时触发器,可以在某个时间点触发函数执行或者每隔5分钟触发函数一次;函数计算timetrigger

专题传送门 => 函数计算进行自动化运维专题

定时任务自动化场景分析

定时任务示例场景1

某些账号ak需要定期更换,以确保ak安全;
在下面的代码示例中,授权service具有访问kms权限的能力,使用kms,先对一个具有创建和删除ak权限的ak加密密文解密,获取具有创建和删除ak权限的AK, 之后利用这个AK进行ak的创建和删除操作

说明: 除了使用kms加密解密来获取较大权限的AK, 通过函数计算环境变量的设置也是一种很好的方法

操作步骤

注:记得给函数的service的role设置访问kms权限

  • 给函数配置定时器,详情可参考定时触发函数
    image
  • 函数代码(函数计算已经内置了相关sdk,直接使用下面的代码即可)
# -*- coding: utf-8 -*-
import logging, time, json
from aliyunsdkcore import client
from aliyunsdkram.request.v20150501.CreateAccessKeyRequest import CreateAccessKeyRequest
from aliyunsdkram.request.v20150501.DeleteAccessKeyRequest import DeleteAccessKeyRequest
from aliyunsdkkms.request.v20160120.EncryptRequest import EncryptRequest
from aliyunsdkkms.request.v20160120.DecryptRequest import DecryptRequest
from aliyunsdkcore.auth.credentials import StsTokenCredential

# ak Encrypt content
AK_CiphertextBlob = "NmQyY2ZhODMtMTlhYS00MTNjLTlmZjAtZTQxYTFiYWVmMzZmM1B1NXhTZENCNXVWd1dhdTNMWVRvb3V6dU9QcVVlMXRBQUFBQUFBQUFBQ3gwZTkzeGhDdHVzMWhDUCtZeVVuMWlobzlCa3VxMlErOXFHWWdXXXHELLwL1NSZTFvUURYSW9lak5Hak1lMnF0R2I1TWUxMEJiYmkzVnBwZHlrWGYzc3kyK2tQbGlKb2lHQ3lrZUdieHN2eXZwSVYzN2Qyd1cydz09"

USER_NAME = "ls-test" # sub-account name
LOGGER = logging.getLogger()

def handler(event, context):
  creds = context.credentials
  sts_token_credential = StsTokenCredential(creds.access_key_id, creds.access_key_secret, creds.security_token)
  # this demo ecs and function in same region, if not in same region, you need change region_id to your ecs instance's region_id
  clt = client.AcsClient(region_id=context.region, credential=sts_token_credential)
  request = DecryptRequest()
  request.set_CiphertextBlob(AK_CiphertextBlob)
  response = _send_request(clt, request)
  ak_info = json.loads(response.get("Plaintext","{}"))
  if not ak_info:
    return "KMS Decrypt ERROR"
  ak_id = ak_info["ak_id"]
  ak_secret = ak_info["ak_secret"]
  LOGGER.info("Decrypt sucessfully with key id: {}".format(response.get("KeyId","{}")))

  clt2 = client.AcsClient(ak_id, ak_secret, context.region)
  request = CreateAccessKeyRequest()
  request.set_UserName(USER_NAME) # 给子账号ls-test创建AK
  response = _send_request(clt2, request)
  create_ak_id = response.get("AccessKey",{}).get("AccessKeyId")
  if not create_ak_id:
    return
  LOGGER.info("create ak {} sucess!".format(create_ak_id))
  
  time.sleep(10)
  
  request = DeleteAccessKeyRequest()
  request.set_UserName(USER_NAME)  
  request.set_UserAccessKeyId(create_ak_id)
  response = _send_request(clt2, request)
  LOGGER.info("delete ak {} sucess!".format(create_ak_id))
  
  return "OK"
  
# send open api request
def _send_request(clt, request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action_with_exception(request)
        LOGGER.debug(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        LOGGER.error(e)

AK 存在环境变量版本

# -*- coding: utf-8 -*-
import os, logging, time, json
from aliyunsdkcore import client
from aliyunsdkram.request.v20150501.CreateAccessKeyRequest import CreateAccessKeyRequest
from aliyunsdkram.request.v20150501.DeleteAccessKeyRequest import DeleteAccessKeyRequest

USER_NAME = "ls-test" # sub-account name
LOGGER = logging.getLogger()

def handler(event, context):
  ak_id = os.environ['AK_ID']
  ak_secret = os.environ['AK_SECRET']
  clt = client.AcsClient(ak_id, ak_secret, context.region)
  request = CreateAccessKeyRequest()
  request.set_UserName(USER_NAME) # 给子账号USER_NAME创建AK
  response = _send_request(clt, request)
  create_ak_id = response.get("AccessKey", "").get("AccessKeyId")
  if not create_ak_id:
    return
  LOGGER.info("create ak {} sucess!".format(create_ak_id))
  
  time.sleep(5)
  
  request = DeleteAccessKeyRequest()
  request.set_UserName(USER_NAME)  
  request.set_UserAccessKeyId(create_ak_id)
  response = _send_request(clt, request)
  LOGGER.info("delete ak {} sucess!".format(create_ak_id))
  
  return "OK"
  
# send open api request
def _send_request(clt, request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action_with_exception(request)
        LOGGER.info(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        LOGGER.error(e)

定时任务示例场景2

定期检查自己ecs对应暴露的端口,确保安全,比如你的ecs是一个网站服务器,可能只需要对外暴露80/443端口就行,如果出现0.0.0.0/0这种允许所有人访问其他端口,需要出现报警或者自动修复

操作步骤

注:记得给函数的service的role设置管理ecs权限

# -*- coding: utf-8 -*-
import logging
import json, random, string, time
from aliyunsdkcore import client
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
from aliyunsdkecs.request.v20140526.DescribeSecurityGroupAttributeRequest import DescribeSecurityGroupAttributeRequest
from aliyunsdkcore.auth.credentials import StsTokenCredential

LOGGER = logging.getLogger()
clt = None

# 需要检查的ecs列表, 修改成你的ecs id 列表
ECS_INST_IDS = ["i-uf6h07zdscdg9g55zkxx", "i-uf6bwkxfxh847a1e2xxx"]

def handler(event, context):
  creds = context.credentials
  global clt
  sts_token_credential = StsTokenCredential(creds.access_key_id, creds.access_key_secret, creds.security_token)
  # this demo ecs and function in same region, if not in same region, you need change region_id to your ecs instance's region_id
  clt = client.AcsClient(region_id=context.region, credential=sts_token_credential)
  invalid_perssions = {}
  for ecs_id in ECS_INST_IDS:
    ret = check_and_modify_security_rule(ecs_id)
    if ret:
      invalid_perssions[ecs_id] = ret
  return invalid_perssions

def check_and_modify_security_rule(instance_id):
  LOGGER.info("check_and_modify_security_rule, instance_id  is %s ", instance_id)
  request = DescribeInstancesRequest()
  request.set_InstanceIds(json.dumps([instance_id]))
  response = _send_request(request)
  SecurityGroupIds = []
  if response is not None:
    instance_list = response.get('Instances', {}).get('Instance')
    for item in instance_list:
      SecurityGroupIds = item.get('SecurityGroupIds', {}).get("SecurityGroupId", [])
      break
  if not SecurityGroupIds:
    LOGGER.error("ecs {} do not have SecurityGroupIds".format(instance_id))
    return 
  
  invalid_perssions = []
  
  for sg_id in SecurityGroupIds:
    request = DescribeSecurityGroupAttributeRequest()
    request.set_SecurityGroupId(sg_id)
    response = _send_request(request)
    LOGGER.info("Find a securityGroup id {}".format(sg_id))
    permissions = response.get("Permissions", {}).get("Permission",[])
    if not permissions:
      continue
    for permission in permissions:
        if permission["Direction"] == "ingress" and permission["SourceCidrIp"] == "0.0.0.0/0" \
              and permission["PortRange"] not in ["443/443", "80/80"]:
        LOGGER.error("ecs {0} , SecurityGroup id {1}, have a risk, need fix; permission = {2}".format(instance_id, sg_id, permission))
        invalid_perssions.append(permission)
        
  return invalid_perssions

# send open api request
def _send_request(request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action_with_exception(request)
        LOGGER.debug(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        LOGGER.error(e)
 
相关实践学习
函数计算部署PuLID for FLUX人像写真实现智能换颜效果
只需一张图片,生成程序员专属写真!本次实验在函数计算中内置PuLID for FLUX,您可以通过函数计算+Serverless应用中心一键部署Flux模型,快速体验超写实图像生成的魅力。
从 0 入门函数计算
在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
目录
相关文章
|
3月前
|
人工智能 自然语言处理 搜索推荐
2026打工人必备偷懒工具:OpenClaw(Clawdbot)阿里云极速部署+5大高效AI工作流分享
在AI工具遍地的今天,很多人手里握着OpenClaw这样的“数字员工”,却只把它当普通搜索引擎使用,浪费了其强大的自动化能力。其实,OpenClaw的核心价值在于通过简单提示词搭建专属工作流,让AI替你处理开会准备、定期复盘、学习成长、副业创作等重复工作,让效率提升5倍以上。
1080 131
|
3月前
|
存储 人工智能 安全
2026年OpenClaw部署使用从入门到精通:3步部署+3大必装Skill+几个实战案例
2026年初,一只名为Molty的小龙虾图标席卷全球科技圈——OpenClaw(曾用名Clawd、Moltbot)以72小时狂揽6万+GitHub Stars的速度引爆市场,如今星标数已突破18万,成为现象级AI工具。它颠覆了传统AI助手“只聊天不干活”的局限,能通过Telegram、飞书等10+平台远程操控设备,完成网站重建、文件管理、代码开发等复杂任务,被用户誉为“住在手机里的全能管家”。
3783 2
|
供应链 前端开发 JavaScript
《Solidity 简易速速上手小册》第10章:区块链项目实战(2024 最新版)(上)
《Solidity 简易速速上手小册》第10章:区块链项目实战(2024 最新版)
668 0
|
存储 人工智能 搜索推荐
详解MySQL字符集和Collation
MySQL支持了很多Charset与Collation,并且允许用户在连接、Server、库、表、列、字面量多个层次上进行精细化配置,这有时会让用户眼花缭乱。本文对相关概念、语法、系统变量、影响范围都进行了详细介绍,并且列举了有可能让字符串发生字符集转换的情况,以及来自不同字符集的字符串进行比较等操作时遵循的规则。对于最常用的基于Unicode的字符集,本文介绍了Unicode标准与MySQL中各个字符集的关系,尤其详细介绍了当前版本(8.0.34)默认字符集utf8mb4。
|
存储 传感器 数据采集
大数据
大数据是指数据量庞大(Volume)、增长迅速(Velocity)、类型多样(Variety)、价值密度低(Value)但潜力巨大的数据集。其来源包括互联网、物联网及企业内部数据。处理技术涵盖采集、预处理、存储、分析与可视化。应用领域涉及商业智能、金融、医疗、交通及公共服务等,助力决策优化与创新。
1114 8
|
算法
浅谈剪枝算法
浅谈剪枝算法
487 0
|
缓存 JSON 数据处理
Python进阶:深入理解import机制与importlib的妙用
本文深入解析了Python的`import`机制及其背后的原理,涵盖基本用法、模块缓存、导入搜索路径和导入钩子等内容。通过理解这些机制,开发者可以优化模块加载速度并确保代码的一致性。文章还介绍了`importlib`的强大功能,如动态模块导入、实现插件系统及重新加载模块,展示了如何利用这些特性编写更加灵活和高效的代码。掌握这些知识有助于提升编程技能,充分利用Python的强大功能。
1053 4
|
关系型数据库 MySQL Linux
虚拟机下安装mysql(按相应步骤操作 / 图文)下
虚拟机下安装mysql(按相应步骤操作 / 图文)下
1414 0
|
XML Java Maven
Springboot Starter 是如何工作的?
Springboot Starter 是 Springboot 项目的一部分,简化了依赖管理和自动配置,通过 Maven 或 Gradle 引入相关依赖并自动配置应用程序。其核心特性包括依赖管理、自动配置及条件注解。Starter 的设计思维体现了模块化、约定优于配置、依赖注入等原则,提高了开发效率,但也存在调试复杂、过度依赖等问题。
782 3
|
前端开发 IDE 编译器
《Solidity 简易速速上手小册》第7章:智能合约的部署与交互(2024 最新版)(上)
《Solidity 简易速速上手小册》第7章:智能合约的部署与交互(2024 最新版)
485 0

相关产品

  • 函数计算