AWS Lambda Intro

1. AWS Lambda 概念

AWS Lambda 属于AWS提供的无服务器架构的计算服务(serverless computing service),用户可以使用 AWS Lambda 支持的语言和相应的运行时环境来创建函数和自包含的应用并上传到 AWS Lambda上去,AWS Lambda会以高效灵活的方式去运行函数和应用。

Lambda 函数可以用来完成很多种计算任务,如网页服务,处理数据流,调用api及和其它的AWS服务集成。

“五服务器架构的计算"指的是用户不需要自己维护服务器基础设施,这意味着AWS Lambda会为用户写的 Lambda函数维护其运行的服务器和运行时环境,用户完全不用考虑。

2. AWS Lambda 是如何工作的

用户创建的每个Lambda函数都运行在各自的容器中。当某个函数被创建后,Lambda 服务就会将其打包到 一个容器当中,然后在一个多租户的集群上来运行该函数,这些集群中的机器都被AWS统一管理。在每个 函数开始运行之前,每个函数的容器都会被分配一定的RAM和CPU。当函数运行完成后,最初分配的RAM值 会被乘以该函数的运行时间。所以用户会为分配的RAM和函数运行的时间付费。

另外,AWS Lambda一个架构上的特点是,一个账户下的多个函数或者多个实例对应的同一个函数都可以 并发执行。这使得AWS Lambda成为高度可伸缩的云计算方案的不二之选。

3. AWS Lambda 支持的语言和运行时环境

  • Node.js 8.10
  • Node.js 10.x (normally the latest LTS version from the 10.x series)
  • Node.js 12.x (normally the latest LTS version from the 12.x series)
  • Python 2.7
  • Python 3.6
  • Python 3.7
  • Python 3.8
  • Ruby 2.5
  • Java 8
    • This includes JVM-based languages that can run on Java 8’s JVM — the latest Clojure 1.10 and Scala 2.12 both run on Java 8 so can be used with AWS Lambda
  • Java 11
  • Go 1.x (latest release)
  • C# — .NET Core 1.0
  • C# — .NET Core 2.1
  • PowerShell Core 6.0

AWS Lambda 支持上述主流的语言,每种语言的运行时环境都由 Amazon Linux 或者 Amazon Linux 2机器来 提供,AWS 为每种支持的语言都提供了SDK,以便于快速开发自己的Lambda 函数。

4. 在AWS 弹性伸缩中使用js api的lambda function实例

在加入到弹性伸缩组中的实例还未提供服务之前修改实例的某些属性,比如加上标签: 弹性伸缩事件 —> Amazon EventBridge —> rule —> Lambda function

4.1 Amazon EC2 Auto Scaling 生命周期内的实例状态之间的过渡

1        EC2 Instance <------------- Detached <------------   Detaching 
2            |      											     |
3            |         [<----EC2_INSTANCE_LAUNCHING--->]          |                           [<------EC2_INSTANCE_TERMINATING------->]
4ASG ---> Pending ---> Pending:Wait ---> Pending:Proceed ---> InService ---> Terminating ---> Terminating:Wait ---> Terminating:Proceed ---> Terminated
5            |    exit standby									 |
6            |  <---------------   Standby	<-------------	 EnteringStandby

4.2 Amazon EventBridge rule

  • Amazon EventBridge rule
 1{
 2  "source": [
 3    "aws.autoscaling"
 4  ],
 5  "detail-type": [ //匹配的事件
 6    "EC2 Instance Launch Successful",
 7    "EC2 Instance-launch Lifecycle Action",
 8    "EC2 Instance-terminate Lifecycle Action"
 9  ],
10  "detail": {
11    "AutoScalingGroupName": [
12      "cake-autoscale-test" //伸缩组名称
13    ]
14  }
15}

当Amazon EventBridge rule匹配到某个伸缩事件后就会调用下面的js lambda,在lambda中判断 此次调用对应的事件名称,根据事件来修改或者新加tag到实例。

  1const AWS = require('aws-sdk');
  2const ec2 = new AWS.EC2();
  3AWS.config.update({ region: 'cn-northwest-1' }); // hard code the region
  4
  5const config = {
  6  debug: true, // if true, print additional info to logs
  7  dryRunApiCalls: false, // if true, changes will not be made to AWS resources
  8};
  9
 10exports.handler = function(event, context) {
 11  try {
 12
 13    let initType = "EC2 Instance-launch Lifecycle Action";
 14    let initDesc = "autoscaling:EC2_INSTANCE_LAUNCHING";
 15    let doneType = "EC2 Instance Launch Successful";
 16    let closeType = "EC2 Instance-terminate Lifecycle Action";
 17    let closeDesc = "autoscaling:EC2_INSTANCE_TERMINATING";
 18
 19    let oneKey = "autoscalingStatus";
 20    let valueInit = "init";
 21    let valueDone = "done";
 22    let valueClose = "closing";
 23
 24    let ifaceTkey = "Srv";
 25    let ifaceTvalueHost = "host";
 26    let ifaceTvalueCake = "cake_web";
 27
 28    let e = event;
 29    let instanceId = e["detail"]["EC2InstanceId"];
 30
 31    console.log("EVENT: \n" + JSON.stringify(event, null, 2));
 32
 33    // ####  Add instances's tags  ####
 34    if (e['detail-type'] === initType &&
 35      e['detail']['LifecycleTransition'] === initDesc) {
 36      createOrModifyTag(instanceId, oneKey, valueInit);
 37      console.log(`\nEC2: Created tag: {Name : ${oneKey}, Value: ${valueInit}}\n`);
 38    }
 39    else if (e['detail-type'] === doneType) {
 40      createOrModifyTag(instanceId, oneKey, valueDone);
 41      console.log(`\nEC2: Modified tag(tag value from "${valueInit}" to "${valueDone}""): {Name : ${oneKey}, Value: ${valueDone}}\n`);
 42      
 43      /* ####  Add NIC's tags #### */
 44      debugMessage("NIC: Calling getInstanceInfoAndAddIfaceID()...");
 45      getInstanceInfoAndAddIfaceID(instanceId, ifaceTkey, ifaceTvalueHost, ifaceTvalueCake);
 46      
 47    }
 48    else if (e['detail-type'] === closeType &&
 49      e['detail']['LifecycleTransition'] === closeDesc) {
 50      createOrModifyTag(instanceId, oneKey, valueClose);
 51      console.log(`\nEC2: Modified tag(tag value from "${valueDone}" to "${valueClose}"): {Name : ${oneKey}, Value: ${valueClose}}\n`);
 52    }
 53    else {
 54      console.log("Something wrong, check log details!");
 55    }
 56  }
 57  catch (err) {
 58    console.log("ERROR: " + err);
 59  }
 60};
 61
 62/* ###### createTags ####### */
 63async function createOrModifyTag(instanceId, key, value) {
 64  let params = {
 65    Resources: [
 66      instanceId
 67    ],
 68    Tags: [{
 69      Key: key,
 70      Value: value
 71    }, ],
 72  };
 73  debugMessage(`EC2: Calling ec2.createTags(${JSON.stringify(params)})`);
 74  let response = await ec2.createTags(params).promise();
 75  return;
 76}
 77
 78/* ######   getNetInterfaceId   ####### */
 79/* ###### createNetInterfaceTag ####### */
 80async function getInstanceInfoAndAddIfaceID(instanceId, ifaceTkey, ifaceTvalueHost, ifaceTvalueCake) {
 81  let iKey = ifaceTkey;
 82  let itvHost = ifaceTvalueHost;
 83  let itvCake = ifaceTvalueCake;
 84
 85  // debug
 86  console.log(`getInstanceInfoAndAddIfaceID: instanceId: ${instanceId}, ifaceTkey: ${ifaceTkey}, ifaceTvalueHost: ${ifaceTvalueHost}, ifaceTvalueCake: ${ifaceTvalueCake}`);
 87
 88  let params = {
 89    InstanceIds: [
 90      instanceId
 91    ],
 92  };
 93
 94  // get instance info which include ifaceid and ifaceindex
 95  debugMessage(`NIC: Calling ec2.describeInstances(${JSON.stringify(params)})`);
 96  let response = await ec2.describeInstances(params).promise();
 97  //let responseD = await ec2.describeInstances(params).promise();
 98  //debugMessage(`NIC: ec2.describeInstances() response:\n ${JSON.stringify(response,null,2)}`);
 99
100  let data = JSON.stringify(response, null, 2);
101  console.log("DescribeEC2 data : " + data);
102  let dataobj = JSON.parse(data);
103
104  //debug
105  console.log(`DescribeEC2 data dataobj is: ${dataobj}`);
106
107  let idAndIndex = {};
108  let ifaceNum = Object.keys(dataobj.Reservations[0].Instances[0].NetworkInterfaces).length;
109  if (ifaceNum !== 0 && ifaceNum !== null && ifaceNum !== undefined) {
110    for (let i = 0; i < ifaceNum; i++) {
111      idAndIndex[dataobj.Reservations[0].Instances[0].NetworkInterfaces[i].Attachment.DeviceIndex] =
112        dataobj.Reservations[0].Instances[0].NetworkInterfaces[i].NetworkInterfaceId;
113    }
114  }
115  else {
116    console.log(`ifaceNum is illegal, it's value is: ${ifaceNum}`);
117  }
118
119  console.log("NIC eth0: " + idAndIndex[0]);
120  if (idAndIndex[1] != undefined) {
121    console.log("NIC eth1: " + idAndIndex[1]);
122  }
123
124  // create tags for iface eth0 and eth1
125  debugMessage(`NIC0: Calling createOrModifyIfaceTag()...`);
126  createOrModifyIfaceTag(idAndIndex[0], iKey, itvCake);
127
128  if (idAndIndex[1] != undefined) {
129    debugMessage(`NIC1: Called createOrModifyIfaceTag()...`);
130    createOrModifyIfaceTag(idAndIndex[1], iKey, itvHost);
131  }
132  return;
133}
134
135/* ###### createOrModifyIfaceTag ####### */
136async function createOrModifyIfaceTag(ifaceID, ifaceTkey, ifaceTvalue) {
137  let params = {
138    Resources: [
139      ifaceID
140    ],
141    Tags: [
142      {
143      Key: ifaceTkey,
144      Value: ifaceTvalue
145      }, 
146    ],
147  };
148  debugMessage(`NIC: Calling ec2.createTags(${JSON.stringify(params)})`);
149  let response = await ec2.createTags(params).promise();
150  return;
151}
152
153/* ###### debugMessage ####### */
154function debugMessage(message) {
155  if (config.debug) {
156    console.log(message);
157  }
158}

FreeBSD账户管理
Apt Update Error