Skip to content

Commit

Permalink
fix: Support Amazon Linux 2023 and Node.js 20 (#487)
Browse files Browse the repository at this point in the history
Resolves the following errors for Lambda runners:

```
/lib64/libm.so.6: version `GLIBC_2.27' not found (required by /tmp/runner/externals/node20/bin/node)
```

```
Cannot get required symbol EVP_rc2_cbc from libssl
```

This upgrades the runtime of Lambda runners to Node.js 20. It should support old actions running on Node 16 and 18, but also 20 that requires glibc 2.27+.

The new Node.js 20 base image runs on Amazon Linux 2023. That requires `dnf` instead of `yum`. Support was added in all components.

Other runner types use Ubuntu by default that should already support Node.js 20.

Resolves #425
  • Loading branch information
kichik authored Dec 27, 2023
1 parent 95704e7 commit 80b4092
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 38 deletions.
17 changes: 15 additions & 2 deletions API.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/image-builders/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export abstract class RunnerImageBuilder extends RunnerImageBuilderBase {
}

const os = props?.os ?? Os.LINUX_UBUNTU;
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2)) {
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2) || os.is(Os.LINUX_AMAZON_2023)) {
return new CodeBuildRunnerImageBuilder(scope, id, props);
} else if (os.is(Os.WINDOWS)) {
return new AwsImageBuilderRunnerImageBuilder(scope, id, props);
Expand Down
2 changes: 1 addition & 1 deletion src/image-builders/codebuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class CodeBuildRunnerImageBuilder extends RunnerImageBuilderBase {
}

private getDefaultBuildImage(): codebuild.IBuildImage {
if (this.os.is(Os.LINUX_UBUNTU) || this.os.is(Os.LINUX_AMAZON_2) || this.os.is(Os.LINUX)) {
if (this.os.is(Os.LINUX_UBUNTU) || this.os.is(Os.LINUX_AMAZON_2) || this.os.is(Os.LINUX_AMAZON_2023) || this.os.is(Os.LINUX)) {
// CodeBuild just runs `docker build` so its OS doesn't really matter
if (this.architecture.is(Architecture.X86_64)) {
return codebuild.LinuxBuildImage.STANDARD_6_0;
Expand Down
34 changes: 27 additions & 7 deletions src/image-builders/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ export abstract class RunnerImageComponent {
'yum update -y',
'yum install -y jq tar gzip bzip2 which binutils zip unzip sudo shadow-utils',
];
} else if (os.is(Os.LINUX_AMAZON_2023)) {
return [
'dnf upgrade -y',
'dnf install -y jq tar gzip bzip2 which binutils zip unzip sudo shadow-utils findutils',
];
} else if (os.is(Os.WINDOWS)) {
return [
'$p = Start-Process msiexec.exe -PassThru -Wait -ArgumentList \'/i https://s3.amazonaws.com/amazoncloudwatch-agent/windows/amd64/latest/amazon-cloudwatch-agent.msi /qn\'',
Expand All @@ -125,7 +130,7 @@ export abstract class RunnerImageComponent {
'adduser --system --disabled-password --home /home/runner --ingroup runner runner',
'echo "%runner ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/runner',
];
} else if (os.is(Os.LINUX_AMAZON_2)) {
} else if (os.is(Os.LINUX_AMAZON_2) || os.is(Os.LINUX_AMAZON_2023)) {
return [
'/usr/sbin/groupadd runner',
'/usr/sbin/useradd --system --shell /usr/sbin/nologin --home-dir /home/runner --gid runner runner',
Expand All @@ -150,7 +155,7 @@ export abstract class RunnerImageComponent {
name = 'AwsCli';

getCommands(os: Os, architecture: Architecture) {
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2)) {
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2) || os.is(Os.LINUX_AMAZON_2023)) {
let archUrl: string;
if (architecture.is(Architecture.X86_64)) {
archUrl = 'x86_64';
Expand Down Expand Up @@ -199,6 +204,11 @@ export abstract class RunnerImageComponent {
'curl -fsSSL https://cli.github.com/packages/rpm/gh-cli.repo -o /etc/yum.repos.d/gh-cli.repo',
'yum install -y gh',
];
} else if (os.is(Os.LINUX_AMAZON_2023)) {
return [
'curl -fsSSL https://cli.github.com/packages/rpm/gh-cli.repo -o /etc/yum.repos.d/gh-cli.repo',
'dnf install -y gh',
];
} else if (os.is(Os.WINDOWS)) {
return [
'cmd /c curl -w "%{redirect_url}" -fsS https://github.com/cli/cli/releases/latest > $Env:TEMP\\latest-gh',
Expand Down Expand Up @@ -234,6 +244,10 @@ export abstract class RunnerImageComponent {
return [
'yum install -y git',
];
} else if (os.is(Os.LINUX_AMAZON_2023)) {
return [
'dnf install -y git',
];
} else if (os.is(Os.WINDOWS)) {
return [
'cmd /c curl -w "%{redirect_url}" -fsS https://github.com/git-for-windows/git/releases/latest > $Env:TEMP\\latest-git',
Expand Down Expand Up @@ -264,7 +278,7 @@ export abstract class RunnerImageComponent {
name = 'GithubRunner';

getCommands(os: Os, architecture: Architecture) {
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2)) {
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2) || os.is(Os.LINUX_AMAZON_2023)) {
let versionCommand: string;
if (runnerVersion.is(RunnerVersion.latest())) {
versionCommand = 'RUNNER_VERSION=`curl -w "%{redirect_url}" -fsS https://github.com/actions/runner/releases/latest | grep -oE "[^/v]+$"`';
Expand Down Expand Up @@ -293,6 +307,8 @@ export abstract class RunnerImageComponent {
commands.push('/home/runner/bin/installdependencies.sh');
} else if (os.is(Os.LINUX_AMAZON_2)) {
commands.push('yum install -y openssl-libs krb5-libs zlib libicu60');
} else if (os.is(Os.LINUX_AMAZON_2023)) {
commands.push('dnf install -y openssl-libs krb5-libs zlib libicu-67.1');
}

return commands;
Expand Down Expand Up @@ -352,6 +368,10 @@ export abstract class RunnerImageComponent {
return [
'yum install -y docker',
];
} else if (os.is(Os.LINUX_AMAZON_2023)) {
return [
'dnf install -y docker',
];
} else if (os.is(Os.WINDOWS)) {
return [
// figure out latest docker version
Expand Down Expand Up @@ -419,7 +439,7 @@ export abstract class RunnerImageComponent {
return [
'update-ca-certificates',
];
} else if (os.is(Os.LINUX_AMAZON_2)) {
} else if (os.is(Os.LINUX_AMAZON_2) || os.is(Os.LINUX_AMAZON_2023)) {
return [
'update-ca-trust',
];
Expand All @@ -438,7 +458,7 @@ export abstract class RunnerImageComponent {
return [
{ source, target: `/usr/local/share/ca-certificates/${name}.crt` },
];
} else if (os.is(Os.LINUX_AMAZON_2)) {
} else if (os.is(Os.LINUX_AMAZON_2) || os.is(Os.LINUX_AMAZON_2023)) {
return [
{ source, target: `/etc/pki/ca-trust/source/anchors/${name}.crt` },
];
Expand All @@ -461,7 +481,7 @@ export abstract class RunnerImageComponent {
name = 'Lambda-Entrypoint';

getCommands(os: Os, _architecture: Architecture) {
if (!os.is(Os.LINUX_AMAZON_2) && !os.is(Os.LINUX_UBUNTU)) {
if (!os.is(Os.LINUX_AMAZON_2) && !os.is(Os.LINUX_AMAZON_2023) && !os.is(Os.LINUX_UBUNTU)) {
throw new Error(`Unsupported OS for Lambda entrypoint: ${os.name}`);
}

Expand Down Expand Up @@ -532,7 +552,7 @@ export abstract class RunnerImageComponent {
*/
_asAwsImageBuilderComponent(scope: Construct, id: string, os: Os, architecture: Architecture) {
let platform: 'Linux' | 'Windows';
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2)) {
if (os.is(Os.LINUX_UBUNTU) || os.is(Os.LINUX_AMAZON_2) || os.is(Os.LINUX_AMAZON_2023)) {
platform = 'Linux';
} else if (os.is(Os.WINDOWS)) {
platform = 'Windows';
Expand Down
5 changes: 5 additions & 0 deletions src/providers/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ export class Os {
*/
public static readonly LINUX_AMAZON_2 = Os.of('Amazon Linux 2');

/**
* Amazon Linux 2023
*/
public static readonly LINUX_AMAZON_2023 = Os.of('Amazon Linux 2023');

/**
* Windows
*/
Expand Down
6 changes: 6 additions & 0 deletions src/providers/docker-images/lambda/linux-x64/runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ cd /tmp/runner
mkdir /tmp/home
export HOME=/tmp/home

# workaround for "Cannot get required symbol EVP_rc2_cbc from libssl"
# lambda docker image for node.js comes with stripped down libssl.so pushed in LD_LIBRARY_PATH
if [ -f /var/lang/lib/libssl.so ]; then
export LD_LIBRARY_PATH=/usr/lib64:$LD_LIBRARY_PATH
fi

# start runner
if [ "${RUNNER_VERSION}" = "latest" ]; then RUNNER_FLAGS=""; else RUNNER_FLAGS="--disableupdate"; fi
./config.sh --unattended --url "${REGISTRATION_URL}" --token "${RUNNER_TOKEN}" --ephemeral --work _work --labels "${RUNNER_LABEL},cdkghr:started:`date +%s`" --name "${RUNNER_NAME}" ${RUNNER_FLAGS}
Expand Down
2 changes: 1 addition & 1 deletion src/providers/ecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ export class EcsRunnerProvider extends BaseProvider implements IRunnerProvider {
return [`(Get-ECRLoginCommand).Password | docker login --username AWS --password-stdin ${thisStack.account}.dkr.ecr.${thisStack.region}.amazonaws.com`];
}
return [
'yum install -y awscli',
'yum install -y awscli || dnf install -y awscli',
`aws ecr get-login-password --region ${thisStack.region} | docker login --username AWS --password-stdin ${thisStack.account}.dkr.ecr.${thisStack.region}.amazonaws.com`,
];
}
Expand Down
10 changes: 5 additions & 5 deletions src/providers/lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,21 +164,21 @@ export class LambdaRunnerProvider extends BaseProvider implements IRunnerProvide
* * `RunnerImageComponent.githubRunner()`
* * `RunnerImageComponent.lambdaEntrypoint()`
*
* Base Docker image: `public.ecr.aws/lambda/nodejs:16-x86_64` or `public.ecr.aws/lambda/nodejs:16-arm64`
* Base Docker image: `public.ecr.aws/lambda/nodejs:20-x86_64` or `public.ecr.aws/lambda/nodejs:20-arm64`
*/
public static imageBuilder(scope: Construct, id: string, props?: RunnerImageBuilderProps) {
if (props?.os && !Os.LINUX_AMAZON_2.is(props.os) && !props?.baseDockerImage) {
// TODO we can support Ubuntu by building our own image https://docs.aws.amazon.com/lambda/latest/dg/nodejs-image.html#nodejs-image-clients
throw new Error('Lambda runner provider only supports Amazon Linux 2. Use a different provider or specify a custom `baseDockerImage` that supports your desired OS.');
}

let baseDockerImage = 'public.ecr.aws/lambda/nodejs:16-x86_64';
let baseDockerImage = 'public.ecr.aws/lambda/nodejs:20-x86_64';
if (props?.architecture === Architecture.ARM64) {
baseDockerImage = 'public.ecr.aws/lambda/nodejs:16-arm64';
baseDockerImage = 'public.ecr.aws/lambda/nodejs:20-arm64';
}

return RunnerImageBuilder.new(scope, id, {
os: Os.LINUX_AMAZON_2,
os: Os.LINUX_AMAZON_2023,
architecture: props?.architecture ?? Architecture.X86_64,
baseDockerImage,
components: [
Expand Down Expand Up @@ -243,7 +243,7 @@ export class LambdaRunnerProvider extends BaseProvider implements IRunnerProvide
const image = this.image = imageBuilder.bindDockerImage();

let architecture: lambda.Architecture | undefined;
if (image.os.is(Os.LINUX_AMAZON_2) || image.os.is(Os.LINUX_UBUNTU)) {
if (image.os.is(Os.LINUX_AMAZON_2) || image.os.is(Os.LINUX_AMAZON_2023) || image.os.is(Os.LINUX_UBUNTU)) {
if (image.architecture.is(Architecture.X86_64)) {
architecture = lambda.Architecture.X86_64;
}
Expand Down
10 changes: 5 additions & 5 deletions test/default.integ.snapshot/github-runners-test.assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@
}
}
},
"f08b29ccb1c2bb19ccb57589e1673fcfce8c26d1ff38f41b1a02520aa7df10ed": {
"66540a3450c33faeefad87df9de8684f624030603c76336933c519972d85a072": {
"source": {
"path": "asset.f08b29ccb1c2bb19ccb57589e1673fcfce8c26d1ff38f41b1a02520aa7df10ed.sh",
"path": "asset.66540a3450c33faeefad87df9de8684f624030603c76336933c519972d85a072.sh",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "f08b29ccb1c2bb19ccb57589e1673fcfce8c26d1ff38f41b1a02520aa7df10ed.sh",
"objectKey": "66540a3450c33faeefad87df9de8684f624030603c76336933c519972d85a072.sh",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
Expand Down Expand Up @@ -235,15 +235,15 @@
}
}
},
"c1b2bad3b26df6d22c995ff795285e1444254b993d1d874e7e23801576fef6ce": {
"56ab2711c690364297c3ddca72cfba9fcaa1b1d4efbef680ce7ef1b06664c45d": {
"source": {
"path": "github-runners-test.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "c1b2bad3b26df6d22c995ff795285e1444254b993d1d874e7e23801576fef6ce.json",
"objectKey": "56ab2711c690364297c3ddca72cfba9fcaa1b1d4efbef680ce7ef1b06664c45d.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
Expand Down
Loading

0 comments on commit 80b4092

Please sign in to comment.