Menjalankan PHP di AWS Lambda

AWS Lambda memang tidak mengakomodir PHP secara native. Akan tetapi kita bisa menggunakan Custom Runtime-nya agar bisa menjalankan PHP di Lambda. Memang ada beberapa hal yg perlu disiapkan sebelumnya. Untuk itu kita coba prepare yak.

1.AMI

Pertama kita siapkan EC2 dulu dengan AMI yang support untuk Lambda Runtime. Pada saat postingan ini dibuat, bisa menggunakan amzn-ami-hvm-2018.03.0.20201209.1-x86_64-gp2 dengan ami id : ami-0953fe29a5ee6f759 untuk region Jakarta. Pastikan EC2 ini punya IAM profile untuk create IAM Role dan manage Lambda function.

2.Compile PHP di EC2 yang kita buat tadi

Untuk compile PHP ini, jalankan script dibawah:

# Update package dan install dependensi
sudo yum update -y
sudo yum install autoconf bison gcc gcc-c++ libcurl-devel libxml2-devel -y

# Compile OpenSSL dari source, karena Amazon Linux memakai versi yg lebih baru daripada Lambda Execution Environment, yang akan menyebabkan
# masalah kompatibilitas
curl -sL http://www.openssl.org/source/openssl-1.0.1k.tar.gz | tar -xvz
cd openssl-1.0.1k
./config && make && sudo make install
cd ~

# Download source PHP 7.3.0 
mkdir ~/php-7-bin
curl -sL https://github.com/php/php-src/archive/php-7.3.0.tar.gz | tar -xvz
cd php-src-php-7.3.0

# Compile PHP 7.3.0 dengan OpenSSL 1.0.1, dan install ke /home/ec2-user/php-7-bin
./buildconf --force
./configure --prefix=/home/ec2-user/php-7-bin/ --with-openssl=/usr/local/ssl --with-curl --with-zlib
make install

Kalo sudah, coba tes dengan command ini : /home/ec2-user/php-7-bin/bin/php -v
Apabila sukses, akan muncul syntax berikut :

PHP 7.3.0 (cli) (built: Dec 11 2018 17:45:29) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies

3.Persiapan Composer

Untuk composer, kita persiapkan direktori sample  :

mkdir -p ~/php-example/{bin,src}/
cd ~/php-example
touch ./src/{hello,goodbye}.php
touch ./bootstrap && chmod +x ./bootstrap
cp ~/php-7-bin/bin/php ./bin

Kalau sudah, kita install composernya :

curl -sS https://getcomposer.org/installer | ./bin/php
./bin/php composer.phar require guzzlehttp/guzzle

4.Persiapan bootstrap

Setelah selesai kita edit file bootstrap :

#!/opt/bin/php
<?php

// Invoke autoloader composer. Jadi kita bisa menggunakan Guzzle atau third party library yg kita butuhkan.
require __DIR__ . '/vendor/autoload.php';

// Melakukan looping request
do {
    // Meminta runtime API untuk request.
    $request = getNextRequest();

    // Mengambil function name dari _HANDLER environment dan memastikan code-nya tersedia.
    $handlerFunction = array_slice(explode('.', $_ENV['_HANDLER']), -1)[0];
    require_once $_ENV['LAMBDA_TASK_ROOT'] . '/src/' . $handlerFunction . '.php';

    // Eksekusi function dan mendapatkan responnya.
    $response = $handlerFunction($request['payload']);

    // Submit respon kembali ke runtime API.
    sendResponse($request['invocationId'], $response);
} while (true);
function getNextRequest()
{
    $client = new \GuzzleHttp\Client();
    $response = $client->get('http://' . $_ENV['AWS_LAMBDA_RUNTIME_API'] . '/2018-06-01/runtime/invocation/next');

    return [
      'invocationId' => $response->getHeader('Lambda-Runtime-Aws-Request-Id')[0],
      'payload' => json_decode((string) $response->getBody(), true)
    ];
}
function sendResponse($invocationId, $response)
{
    $client = new \GuzzleHttp\Client();
    $client->post(
    'http://' . $_ENV['AWS_LAMBDA_RUNTIME_API'] . '/2018-06-01/runtime/invocation/' . $invocationId . '/response',
       ['body' => $response]
    );
}

5.Buat sample file hello.php dan goodbye.php

Lanjut kita buat sample hello.php :

<?php

function hello($data)
{
    return "Hello, {$data['name']}!";
} Dan goodbye.php :
<?php

function goodbye($data)
{
    return "Goodbye, {$data['name']}!";
} Jadi rekap step 1 - 5, kita membuat :
  • PHP binary di compile di Amazon Linux
  • bootstrap file dalam bentuk PHP untuk menghandle fase Init dan Invoke 
  • vendor directory dengan source code Guzzle
  • Dua function php : hello() dan goodbye()

Lanjut deployment ke Lambda yak :

1.Kita zip file-file yang sudah dibuat tadi :

zip -r runtime.zip bin bootstrap
zip -r vendor.zip vendor/
zip hello.zip src/hello.php
zip goodbye.zip src/goodbye.php

2.Kita buat policy untuk lambda-nya. Buat file /tmp/trust-policy.json :

{
  "Version": "2012-10-17",
  "Statement": [
   {
    "Effect": "Allow",
    "Principal": {
      "Service": "lambda.amazonaws.com"
   },
   "Action": "sts:AssumeRole"
  }
 ]
} kemudian jalankan command ini :
aws iam create-role \
    --role-name LambdaPhpExample \
    --path "/service-role/" \
    --assume-role-policy-document file:///tmp/trust-policy.json Jangan lupa, output ARN-nya dicatet, seperti ini : arn:aws:iam::XXXXXXXXXXXX:role/service-role/LambdaPhpExample Next, kita buat layer vendor dan runtime di Lambda-nya :
aws lambda publish-layer-version \
    --layer-name php-example-runtime \
    --zip-file fileb://runtime.zip \
    --region ap-southeast-3

aws lambda publish-layer-version \
    --layer-name php-example-vendor \
    --zip-file fileb://vendor.zip \
    --region ap-southeast-3

Yang diatas, ARN layernya juga dicatet. Seperti ini contohnya : arn:aws:lambda:us-east-1:XXXXXXXXXXXX:layer:php-example-runtime:1

3.Next, kita lanjut buat function Lambda-nya:

aws lambda create-function \
    --function-name php-example-hello \
    --handler hello \
    --zip-file fileb://./hello.zip \
    --runtime provided \
    --role "arn:aws:iam::XXXXXXXXXXXX:role/service-role/LambdaPhpExample" \
    --region ap-southeast-3 \
    --layers "arn:aws:lambda:us-east-1:XXXXXXXXXXXX:layer:php-example-runtime:1" \
          "arn:aws:lambda:us-east-1:XXXXXXXXXXXX:layer:php-example-vendor:1"

aws lambda create-function \
    --function-name php-example-goodbye \
    --handler goodbye \
    --zip-file fileb://./goodbye.zip \
    --runtime provided \
    --role "arn:aws:iam::XXXXXXXXXXXX:role/service-role/LambdaPhpExample" \
    --region ap-southeast-3 \
    --layers "arn:aws:lambda:us-east-1:XXXXXXXXXXXX:layer:php-example-runtime:1" \
          "arn:aws:lambda:us-east-1:XXXXXXXXXXXX:layer:php-example-vendor:1" Kalo udah, gas test. Untuk test-nya bisa dilakukan via console Lambda, atau via CLI :
aws lambda invoke \
    --function-name php-example-hello \
    --region ap-southeast-3 \
    --log-type Tail \
    --query 'LogResult' \
    --output text \
    --payload '{"name": "World"}' hello-output.txt | base64 --decode

aws lambda invoke \
    --function-name php-example-goodbye \
    --region ap-southeast-3 \
    --log-type Tail \
    --query 'LogResult' \
    --output text \
    --payload '{"name": "World"}' goodbye-output.txt | base64 --decode

Outputnya berupa file hello-output.txt dan goodbye-output.txt yang berisi text Hello, World! dan Goodbye, World!

Leave a Reply

Your email address will not be published. Required fields are marked *