Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify deployment steps #4

Closed
truedat101 opened this issue Feb 17, 2019 · 25 comments
Closed

Verify deployment steps #4

truedat101 opened this issue Feb 17, 2019 · 25 comments
Assignees

Comments

@truedat101
Copy link
Contributor

Need to walk through a real deployment scenario. Make sure a simple HelloWorld example will work.

@truedat101 truedat101 self-assigned this Feb 17, 2019
@truedat101
Copy link
Contributor Author

It seems like something like this:

zip -yr lambda.zip bootstrap

And then upload to AWS normal-ish as a custom lambda.

@truedat101
Copy link
Contributor Author

So none of these work. I expect that I have library dependency issues. I don't expect ldc2 to work but probably gdc will work. Run 'ldd' against the output binary. We should get a list of the libraries needed. Then package up these libraries into a ./lib dir along with the zip. See what https://github.com/awslabs/aws-lambda-cpp#building-and-installing-the-runtime does. I checked and they package up a crap wad of stuff in terms of libraries. sigh . So ... either generate a binary that packages its dependencies (everything statically links), or generate a lib dir of dependencies and add an executable bootstrap script. It's possible gdc has all the dependencies already on the target host. I think what I'm missing is my bootstrap (shell script) is not executable.

@truedat101
Copy link
Contributor Author

Here's the contents of the aws lambda cpp bootstrap:

#!/bin/bash
set -euo pipefail
export AWS_EXECUTION_ENV=lambda-cpp
exec $LAMBDA_TASK_ROOT/lib/ld-linux-x86-64.so.2 --library-path $LAMBDA_TASK_ROOT/lib $LAMBDA_TASK_ROOT/bin/demo ${_HANDLER}

@truedat101
Copy link
Contributor Author

Sort of stuck here. I think I need to try out the Lambda docker image and see what is missing. The use ldd on the libraries to see what is missing. Then maybe need to do something similar to what the C++ lambda does in terms of packaging .so files.

@truedat101
Copy link
Contributor Author

So first step, add a file called bootstrap that is a bash script.

We need this first line to make sure anything in our pipeline that isn't perfect will cause a failure: https://www.reddit.com/r/programming/comments/9ysjnu/safer_bash_scripts_with_set_euxo_pipefail/

Then we should set the AWS_EXECUTION_ENV. Since this is normally a reserved value, I think we can set anything here to indicate the lambda execution environment identifier.

#/bin/bash
set -euo pipefail
export AWS_EXECUTION_ENV=lambd
exec $LAMBDA_TASK_ROOT/lib/ld-linux-x86-64.so.2 --library-path $LAMBDA_TASK_ROOT/lib $LAMBDA_TASK_ROOT/bin/lambd ${_HANDLER}

The LAMBDA_TASK_ROOT is where our little sandbox is stuck handling execution of binaries. Anything we want to run or link to should be found in here. This is where lambda gets tricky when you are testing stuff locally. You can't execute things outside of this area.

@truedat101
Copy link
Contributor Author

Now the trick with the above approach will be to package dependent libraries in LAMBDA_TASK__ROOT/lib. The CPP packager for lambda-cpp is pretty cool, but massively bloated too. According to their own docs, they have to package everything in std libc. And this will be true of any runtime that we create. It's especially true if you run something like a node or python lambda that includes some ridiculous package dependency that pulls in hundreds of MB of stuff. It's possible.

@truedat101
Copy link
Contributor Author

Another weirdness in the lambda-cpp examples are that they don't actual parse the value of the function name the way we do in node or python. It just calls a main, and whatever is defined in main is run. We could implement this more flexible approach later, however, in the scheme of things, you actually want to package up the smallest amount of code possible. Why would you package multiple lambda functions that you might not be using?

@truedat101
Copy link
Contributor Author

So here's what is needed in the lib folder potentially:

./lamb-d
        linux-vdso.so.1 (0x00007fffcae02000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4c36820000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c36420000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4c36c00000)
        libatomic.so.1 => /usr/lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f4c36210000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f4c36000000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4c35c60000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4c35a40000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4c35820000)

@truedat101
Copy link
Contributor Author

So of the above, I think we only don't need the linux-vdso.so.1.

@truedat101
Copy link
Contributor Author

Ok, fixed up packaging. I don't see a clear reason for the error in the lambda, probably a deeper problem. The code actually runs fine locally. The packaging looks ok. I think I'm missing some logic on the lambda glue. My example actually has some garbage in it. All of the values that should get filled in from the environment (ARN, lambda function) all get filled in with some defaults. Fix that and I think this will work.

@truedat101
Copy link
Contributor Author

I see the problem. I created a main app, but I don't actually call runHandler which has all of the lambda magik.

@truedat101
Copy link
Contributor Author

Ok, that's it. Just need to move the "tester" code into unit tests. And then invoke runHandler(handler).

@truedat101
Copy link
Contributor Author

This is the good news: a better result:

lambd.layer.LambDException@source/layer.d(180): Failure to invoke AwsLambdaRuntimeAPI, reason: statusCode = 0

??:? void lambd.layer.runHandler(std.json.JSONValue function(std.json.JSONValue, lambd.layer.LambdaContext)*) [0xd4df502b]
??:? _Dmain [0xd4de0057]
END RequestId: 8a0f664c-f1db-40ab-bf83-46ef9bee00c3

@truedat101
Copy link
Contributor Author

So the problem at the moment is I have some bad curl usage. These are async calls. I need to rewrite the calls. The api is a bit funky with curl, there are a few high level requests, but they don't let you get at the details of the request/response. Fix that and I think this starts working.

@truedat101
Copy link
Contributor Author

Seems that as I've switched build systems, and ldc version, and fixed the usage of curl, I am having library issues finding curl at runtime.

I tired packaging curl libs but this isn't working. And compiling with --static directly didn't work. I think doing a static app is the way to go. I found this post on the forums:https://forum.dlang.org/post/udunaxcalnsrnzoomunq@forum.dlang.org

Clearly the d forums is the only place to look. This is a little frustrating that there are almost no resources anywhere else, due to the fact that there are very few d posts on stack overflow.

I'll try the approach mentioned in the post. Once I've got library issues and an example invoking, I need to fix any bugs in execution.

@truedat101
Copy link
Contributor Author

Hmm, if I add a static target, I get these errors:

warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
ldc2-1.15.0-linux-x86_64/bin/../lib/libphobos2-ldc.a(socket.o):socket.d:function _D3std6socket12InternetHost__T7getHostVAyaa118_0a2020202020202020202020206175746f2078203d2068746f6e6c28706172616d293b0a2020202020202020202020206175746f206865203d20676574686f73746279616464722826782c20342c206361737428696e7429204164647265737346616d696c792e494e4554293b0a2020202020202020TkZQJwMFkZb: warning: Using 'gethostbyaddr' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

@truedat101
Copy link
Contributor Author

truedat101 commented Oct 9, 2019

So I posted the question here https://forum.dlang.org/post/jujyyiyiqcxmgfolduzf@forum.dlang.org

The short answer is as expected. This is a weird area of phobos where it's probably not quite right, but it is as it is, and decisions were made to make libcurl an external library that must be linked in if used for statically built apps and libraries, and there is some special effort.

Above and beyond my usual approach for doing things, use the libraries we have already, use LDD to find the libraries we need, or alternatively build in and link to the libraries we need, this feels like more effort than it is worth for getting to use libcurl.

The best "fast" work around is to go with: https://github.com/adamdruppe/arsd/blob/master/http2.d

I will seek to pull out the std.net.curl calls and switch to http2. Assuming it all builds in, I will fix up the build and packaging and integrate that one file.

@truedat101
Copy link
Contributor Author

Looks like I will indeed need to ship openssl along with this library, which has its own challenges.

truedat101 added a commit that referenced this issue Oct 9, 2019
@truedat101
Copy link
Contributor Author

truedat101 commented Oct 9, 2019

Looks like I will indeed need to ship openssl along with this library, which has its own challenges. Here are the build issues. .dub/obj/lamb-d.o:package.d:function _D4arsd5http216SSL_library_initFZv: error: undefined reference to 'OPENSSL_init_ssl'
.dub/obj/lamb-d.o:package.d:function _D4arsd5http223OpenSSL_add_all_ciphersFZv: error: undefined reference to 'OPENSSL_init_crypto'
.dub/obj/lamb-d.o:package.d:function _D4arsd5http223OpenSSL_add_all_digestsFZv: error: undefined reference to 'OPENSSL_init_crypto'
.dub/obj/lamb-d.o:package.d:function _D4arsd5http222SSL_load_error_stringsFZv: error: undefined reference to 'OPENSSL_init_ssl'
http2.d:8519: error: undefined reference to 'TLS_client_method'
collect2: error: ld returned 1 exit status
Error: /usr/bin/gcc failed with status: 1
/dev/tools/ldc2-1.15.0-linux-x86_64/bin/ldc2 failed with exit code 1.

@truedat101
Copy link
Contributor Author

I've got a way to build the openssl that should link with the http2.d from arsd.

truedat101 added a commit that referenced this issue Nov 5, 2019
@truedat101
Copy link
Contributor Author

Ok, finally, got this stuff static linking without error (but with warning). Fixed up the external deps script.

truedat101 added a commit that referenced this issue Nov 5, 2019
Otherwise it crashes.  Not sure why, but would need to run this a bit
locally or in a container to figure out.  Anyway, do static for now.
truedat101 added a commit that referenced this issue Nov 5, 2019
Still have a problem with my bootstrap.
truedat101 added a commit that referenced this issue Nov 5, 2019
@truedat101
Copy link
Contributor Author

working:

{
  "result": [
    "e21c28fe-066c-44d5-9335-8504bf90d892",
    "2e18d20a-2ca0-476d-9c3a-9c857a038083",
    "64ec22e0-1928-49cc-b36f-c2426f1f1c91",
    "b02db70f-a516-41d2-94ca-95a49dcb417a",
    "25be281b-4f21-427e-b24b-d042390c5ed3",
    "90240eeb-e92f-4350-9ba2-c86f5f6d64c3",
    "27f32832-2ccc-47df-80a1-0c8b795568a8",
    "d6231b22-da81-4fb5-aab5-c7670ea19dd7",
    "00c54ec8-217b-477d-b8e0-7209c1b29d94",
    "97fe1350-85d6-4a02-b87a-860879f173f2",
    "17fd234b-5fa8-4156-89fe-7ef59cff7669",
    "724b31ac-d782-4e53-a286-7c57ccc92540",
    "7fb8ef7b-87a5-4f83-8042-f0b66411e081",
    "60fa4052-3ad6-4f03-ab40-47fd46a654ac",
    "07ef2036-f184-48a3-845e-1196d94e1cdb",
    "2e426b11-5d4f-4553-a4cf-ddc2f4231a1e",
    "beffc461-c9aa-49db-8c26-bffb23f0ad1d",
    "51dae8d3-8b2c-4fbc-b454-be312a8c05a2",
    "fe47d9bc-1549-4989-a5f0-cfbf4fd69f5c",
    "8bac796f-678a-4dfa-a2a8-f690e934192c"
  ]
}

@truedat101
Copy link
Contributor Author

That's sample output from my dummy bootstrap.d example

@truedat101
Copy link
Contributor Author

done.

@truedat101
Copy link
Contributor Author

So making a few notes, interestingly, someone released aws-lambda-d just yesterday. What is interesting is that one is a translation of aws-lambda C++. Which is cool. The library however, looks to depend on curl, which will present some issue when linking as I recall from getting this working. Another issue might be with the copyright, which is held by Amazon, but the code is under Apache. I think it's fine though. In any case, I think it's good for D there are 3 lambda runtimes, two that are modern and one that is a proof of concept from a few years back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant