DEV Community

Thibault CORDIER ☁
Thibault CORDIER ☁

Posted on

Github ARC Runners sur EKS - Assume roles

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 avec Helm 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
Enter fullscreen mode Exit fullscreen mode

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-*'],
                    }),
                ],
            })
        );

Enter fullscreen mode Exit fullscreen mode

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: ['*'],
            })
        ]
        })
);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 :)

Top comments (0)