Github ARC Runners sur EKS – Assume roles

RMAG news

Récemment, nous avons migré nos runners Github en “self-hosted” sur Kubernetes (EKS) via l’opérateur ARC.

L’installation est assez aisée (même si la doc est un peu succincte).

Une fois avoir installé l’opérateur ARC, on installe des CRD AutoScalingRunnerSet dont voici un exemple fichier de values.

githubConfigUrl: “https://github.com/<myorganisation>”
githubConfigSecret: “pre-defined-secret”
maxRunners: 100
runnerScaleSetName: “arc-runner-set-arm”

template:
metadata:
annotations:
karpenter.sh/do-not-disrupt: “true”
spec:
nodeSelector:
kubernetes.io/arch: “arm64”
serviceAccountName: arc-runner-base-role
tolerations:
– key: github/arm
value: “true”
effect: NoSchedule
initContainers:
– name: init-dind-externals
image: ghcr.io/actions/actions-runner:latest
command: [“cp”, “-r”, “-v”, “/home/runner/externals/.”, “/home/runner/tmpDir/”]
volumeMounts:
– name: dind-externals
mountPath: /home/runner/tmpDir
containers:
– name: runner
image: ghcr.io/actions/actions-runner:latest
command: [“/home/runner/run.sh”]
env:
– name: DOCKER_HOST
value: unix:///run/docker/docker.sock
resources:
requests:
cpu: 1
volumeMounts:
– name: work
mountPath: /home/runner/_work
– name: dind-sock
mountPath: /run/docker
readOnly: true

– name: dind
image: public.ecr.aws/docker/library/docker:dind
args:
– dockerd
– –host=unix:///run/docker/docker.sock
– –group=$(DOCKER_GROUP_GID)
env:
– name: DOCKER_GROUP_GID
value: “123”
securityContext:
privileged: true
volumeMounts:
– name: work
mountPath: /home/runner/_work
– name: dind-sock
mountPath: /run/docker
– name: dind-externals
mountPath: /home/runner/externals
volumes:
– name: work
emptyDir: {}
– name: dind-sock
emptyDir: {}
– name: dind-externals
emptyDir: {}

controllerServiceAccount:
name: arc-gha-rs-controller
namespace: arc-systems

La partie importante pour les droits va être de renseigner un spec.serviceAccountName qui sera utilisé par tous les runners qui vont être créés.

Avec AWS CDK, j’ai auparavant créé un serviceAccount et un rôle associé

const arcBaseRole = kubernetesCluster.addServiceAccount(‘arc-base-role’, {
name: ‘arc-runner-base-role’,
namespace: ‘arc-systems’,
});
// Allow to assumeRole in the account starting with arc-runner-*
arcBaseRole.role.attachInlinePolicy(
new Policy(this, ‘arc-base-role-policy’, {
statements: [
new PolicyStatement({
actions: [‘sts:AssumeRole’, ‘sts:TagSession’],
resources: [‘arn:aws:iam::’+ this.account + ‘:role/arc-runner-*’],
}),
],
})
);

Ainsi qu’un rôle à assumer pour ce runner (ici la possibilité de push sur le dépôt ECR.)

const pusherRole = new Role(this, ‘arc-ecr-image-pusher-role’, {
assumedBy: new AccountPrincipal(this.account),
roleName: ‘arc-runner-ecr-image-pusher-role’,
});

pusherRoleI.attachInlinePolicy(
new Policy(this, ‘arc-ecr-image-pusher-policy-base’, {
statements: [
new PolicyStatement({
actions: [
‘ecr:GetAuthorizationToken’,
‘ecr:BatchCheckLayerAvailability’,
‘ecr:GetDownloadUrlForLayer’,
‘ecr:BatchGetImage’,
‘ecr:InitiateLayerUpload’,
‘ecr:UploadLayerPart’,
‘ecr:CompleteLayerUpload’,
‘ecr:PutImage’,
],
resources: [‘*’],
})
]
})
);

Ensuite dans mon job github, plus qu’à préciser le rôle à assumer et voila !

uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-central-1
role-to-assume: arn:aws:iam::${{ secrets.ECR_AWS_ACCOUNT_ID }}:role/arc-runner-ecr-image-pusher-role
role-session-name: ${{ github.workflow }}_${{ github.run_number }}_${{ github.job }}
role-skip-session-tagging: true

Pourquoi j’en ai fait un post ?
Parce que ça n’a pas marché tout de suite, notamment à cause du paramètre : role-skip-session-tagging: true qu’il faut rajouter sous peine de voir le runner répéter le même message en boucle 🙂

Leave a Reply

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