Skip to content

Commit c40a38a

Browse files
authored
Merge pull request #285 from caktus/CU-8689pdzrr-k8s-self-hosted-runner
K8s Self-hosted GitHub Runner
2 parents 4d4f658 + f7ec540 commit c40a38a

File tree

6 files changed

+112
-188
lines changed

6 files changed

+112
-188
lines changed

.github/workflows/deploy.yml

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ on:
77
- develop
88

99
jobs:
10-
deploy:
11-
runs-on:
12-
- self-hosted
13-
- philly-hip
10+
build-push:
11+
runs-on: ubuntu-22.04 # standard (not self-hosted) runner
1412
env:
1513
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
1614
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -23,24 +21,82 @@ jobs:
2321
with:
2422
python-version: '3.10'
2523
cache: 'pip'
26-
cache-dependency-path: 'requirements/*/**.txt'
24+
cache-dependency-path: 'requirements/*/dev.txt'
2725
- name: Install dependencies
2826
id: pip-install
2927
run: |
3028
python -m pip install --upgrade pip wheel pip-tools
31-
pip-sync requirements/base/base.txt requirements/dev/dev.txt
29+
pip-sync requirements/dev/dev.txt
3230
- name: Login to Docker
3331
id: docker-login
3432
run: |
3533
inv aws.docker-login
36-
- name: Build, tag, push, and deploy image
37-
id: build-tag-push-deploy
34+
- name: Set DOCKER_TAG and save to file for artifact upload
35+
run: |
36+
DOCKER_TAG=$(inv image.tag | grep 'Set config.tag to' | cut -d' ' -f4)
37+
echo "DOCKER_TAG=$DOCKER_TAG" >> $GITHUB_ENV
38+
echo "$DOCKER_TAG" > docker-tag.txt
39+
- name: Build, tag, and push image
40+
id: build-tag-push
3841
run: |
3942
[ "$GITHUB_REF" = refs/heads/main ] &&
4043
ENV="production" ||
4144
ENV="staging"
4245
echo "env is $ENV"
43-
inv $ENV image deploy --verbosity=0
46+
export BUILDKIT_PROGRESS=plain
47+
inv $ENV image.build --tag=${{ env.DOCKER_TAG }} image.push --tag=${{ env.DOCKER_TAG }}
48+
- name: Upload docker tag from build-push job
49+
uses: actions/upload-artifact@v4
50+
with:
51+
name: docker_tag
52+
path: docker-tag.txt
53+
54+
# The deploy needs to run from within the cluster, since the cluster
55+
# is not exposed to the public internet. This step is split out into
56+
# its own job to reduce the amount of work done on the self-hosted runner
57+
# and avoid the need to run a privileged docker container (with the
58+
# capability of building a docker container itself).
59+
deploy:
60+
runs-on: arc-runner-set # K8s self-hosted runner
61+
needs: [build-push]
62+
env:
63+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
64+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
65+
AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
66+
# https://github.com/marketplace/actions/slack-github-actions-slack-integration
67+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
68+
steps:
69+
- uses: actions/checkout@v3
70+
- name: Download docker tag from build-push job
71+
uses: actions/download-artifact@v4
72+
with:
73+
name: docker_tag
74+
- name: Set variables
75+
run: |
76+
DOCKER_TAG=$(cat docker-tag.txt)
77+
echo "DOCKER_TAG=$DOCKER_TAG" >> $GITHUB_ENV
78+
- name: Install apt packages
79+
run: |
80+
sudo apt-get update
81+
sudo apt-get install -y git
82+
- uses: actions/setup-python@v4
83+
with:
84+
python-version: '3.10'
85+
cache: 'pip'
86+
cache-dependency-path: 'requirements/*/dev.txt'
87+
- name: Install dependencies
88+
id: pip-install
89+
run: |
90+
python -m pip install --upgrade pip wheel pip-tools
91+
pip-sync requirements/dev/dev.txt
92+
- name: Deploy the image
93+
id: deploy
94+
run: |
95+
[ "$GITHUB_REF" = refs/heads/main ] &&
96+
ENV="production" ||
97+
ENV="staging"
98+
echo "env is $ENV" --verbosity=0
99+
inv $ENV deploy --tag=${{ env.DOCKER_TAG }} --verbosity=0
44100
- uses: act10ns/slack@v1
45101
with:
46102
status: ${{ job.status }}

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77

88
jobs:
99
test:
10-
runs-on: ubuntu-20.04
10+
runs-on: ubuntu-22.04 # standard (not self-hosted) runner
1111
env:
1212
DJANGO_SETTINGS_MODULE: hip.settings.dev
1313
services:

README.md

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,11 @@ As mentioned in the Database setup instructions, you may need to visit
297297

298298
### GitHub Actions Runner
299299

300-
There are [GitHub Actions self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) deployed on a virtual machine within the same VPC. Other runners may be added in the future, if needed.
300+
There are [GitHub Actions self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) deployed in the Kubernetes cluster along side the application.
301301

302302
Setup instructions:
303303

304-
* Obtain a [GitHub PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with the `admin:org` scope that's valid for one week (it needs to be active only for the initial deployment). Add this to a local environment variable `RUNNER_CFG_PAT`:
304+
* Obtain a [GitHub PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with the `repo` scope that's valid for one week (it needs to be active only for the initial deployment). Add this to a local environment variable `RUNNER_CFG_PAT`:
305305

306306
```sh
307307
export RUNNER_CFG_PAT="gh......"
@@ -311,19 +311,5 @@ export RUNNER_CFG_PAT="gh......"
311311

312312
```sh
313313
cd deploy/
314-
# first time: connect as ubuntu user
315-
ansible-playbook -u ubuntu deploy-runner.yml
316-
# second time and beyond
317314
ansible-playbook deploy-runner.yml
318315
```
319-
320-
* The runner can be forcibly reinstalled by passing `-e force_reinstall=yes` or removed by passing `-e force_removal=yes`.
321-
322-
Run OS updates:
323-
324-
```sh
325-
cd deploy/
326-
ansible-playbook run-os-updates.yml
327-
# You may need to specify your username
328-
ansible-playbook -u myusername run-os-updates.yaml
329-
```

deploy/deploy-runner.yml

Lines changed: 44 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,47 @@
11
---
2-
- hosts: runner
3-
become: yes
4-
tags: base
5-
roles:
6-
- caktus.hosting_services.users
2+
- name: Install Actions Runner Controller and configure runner scale set
3+
hosts: cluster
4+
vars:
5+
ansible_connection: local
6+
ansible_python_interpreter: "{{ ansible_playbook_python }}"
7+
runner_namespace: github-runner
8+
chart_version: "0.9.3"
9+
gather_facts: false
710
tasks:
8-
- name: Set hostname
9-
hostname:
10-
name: "{{ inventory_hostname_short }}"
11-
when: inventory_hostname_short is defined and inventory_hostname_short
12-
- name: Add new hostname to /etc/hosts
13-
lineinfile:
14-
path: /etc/hosts
15-
regexp: '^127\.0\.1\.1'
16-
line: '127.0.1.1 {{ inventory_hostname_short }}'
17-
owner: root
18-
group: root
19-
mode: 0644
20-
when: inventory_hostname_short is defined and inventory_hostname_short
11+
# https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller/quickstart-for-actions-runner-controller
12+
#
13+
# Ansible task to automate:
14+
# helm install arc \
15+
# --namespace "${NAMESPACE}" \
16+
# --create-namespace \
17+
# oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
18+
- name: Installing Actions Runner Controller
19+
kubernetes.core.helm:
20+
context: "{{ k8s_context|mandatory }}"
21+
chart_ref: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
22+
chart_version: "{{ chart_version }}"
23+
release_name: arc
24+
release_namespace: "{{ runner_namespace }}"
25+
create_namespace: true
26+
wait: yes
2127

22-
- name: Install GitHub Actions Runner
23-
hosts: runner
24-
tags: runner
25-
become: yes
26-
tasks:
27-
- name: Create runner user
28-
ansible.builtin.user:
29-
name: "{{ github_runner_user }}"
30-
comment: Github Actions Runner
31-
# Install Docker
32-
# https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository
33-
- name: Install dependencies
34-
ansible.builtin.package:
35-
name:
36-
- jq
37-
- ca-certificates
38-
- curl
39-
- gnupg
40-
- lsb-release
41-
- libpq-dev
42-
- python3.10
43-
- python3.10-dev
44-
- name: Add Docker's official GPG key
45-
ansible.builtin.apt_key:
46-
url: https://download.docker.com/linux/ubuntu/gpg
47-
state: present
48-
- name: Add Docker repository
49-
ansible.builtin.apt_repository:
50-
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable
51-
state: present
52-
- name: Install Docker Engine
53-
ansible.builtin.package:
54-
name:
55-
- docker-ce
56-
- docker-ce-cli
57-
- containerd.io
58-
- docker-buildx-plugin
59-
- docker-compose-plugin
60-
update_cache: yes
61-
- name: Task name
62-
stat:
63-
path: /home/{{ github_runner_user }}/runner
64-
register: runner_dir
65-
- name: Set vars
66-
set_fact:
67-
run_removal_tasks: >-
68-
{{
69-
runner_dir.stat.exists
70-
and (
71-
(force_reinstall is defined and force_reinstall == "yes")
72-
or (force_removal is defined and force_removal == "yes")
73-
)
74-
}}
75-
# Various complicated Ansible roles exist, but this just works:
76-
# https://github.com/actions/runner/blob/main/docs/automate.md
77-
- name: Remove the runner
78-
ansible.builtin.shell:
79-
cmd: >
80-
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/remove-svc.sh
81-
| bash -s {{ github_scope }}
82-
chdir: /home/{{ github_runner_user }}
83-
environment:
84-
RUNNER_CFG_PAT: "{{ github_pat }}"
85-
when: run_removal_tasks
86-
ignore_errors: True
87-
- name: Delete the runner
88-
ansible.builtin.shell:
89-
cmd: >
90-
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/delete.sh
91-
| bash -s {{ github_scope }} {{ github_runner_name }}
92-
chdir: /home/{{ github_runner_user }}
93-
environment:
94-
RUNNER_CFG_PAT: "{{ github_pat }}"
95-
when: run_removal_tasks
96-
ignore_errors: True
97-
- name: Remove old runner directory and files
98-
ansible.builtin.file:
99-
path: "{{ item }}"
100-
state: absent
101-
loop:
102-
- /home/{{ github_runner_user }}/runner
103-
when: run_removal_tasks
104-
- name: Add user '{{ github_runner_user }}' to group docker
105-
user:
106-
name: "{{ github_runner_user }}"
107-
groups: docker
108-
append: yes
109-
- name: Restart docker service
110-
ansible.builtin.service:
111-
name: docker
112-
state: restarted
113-
- name: Install the runner [If error, RUNNER_CFG_PAT might be missing or expired! See README.md]
114-
ansible.builtin.shell:
115-
cmd: >
116-
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/create-latest-svc.sh
117-
| bash -s --
118-
-s {{ github_scope }}
119-
-n {{ github_runner_name }}
120-
-l {{ github_runner_location }},self-hosted
121-
-u {{ github_runner_user }}
122-
chdir: /home/{{ github_runner_user }}
123-
environment:
124-
RUNNER_CFG_PAT: "{{ github_pat }}"
125-
when: (not runner_dir.stat.exists) or (force_reinstall is defined and force_reinstall=="yes")
28+
# Ansible task to automate:
29+
# helm install "${INSTALLATION_NAME}" \
30+
# --namespace "${NAMESPACE}" \
31+
# --create-namespace \
32+
# --set githubConfigUrl="https://github.com/caktus/philly-hip" \
33+
# --set githubConfigSecret.github_token="${RUNNER_CFG_PAT}" \
34+
# oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
35+
- name: Configuring a runner scale set
36+
kubernetes.core.helm:
37+
context: "{{ k8s_context|mandatory }}"
38+
chart_ref: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
39+
chart_version: "{{ chart_version }}"
40+
release_name: arc-runner-set
41+
release_namespace: "{{ runner_namespace }}"
42+
create_namespace: true
43+
release_values:
44+
githubConfigUrl: "https://github.com/caktus/philly-hip"
45+
githubConfigSecret:
46+
github_token: "{{ lookup('env', 'RUNNER_CFG_PAT') }}"
47+
wait: yes

deploy/group_vars/all.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,6 @@ cloudformation_stack:
5858

5959
template_parameters:
6060
UseAES256Encryption: "true"
61-
AdministratorIPAddress: "{{ administrator_ip_cidrs[0] }}" # Stack allows only single IP here to SSH to bastion
62-
BastionAMI: "ami-0ad554caf874569d2" # https://cloud-images.ubuntu.com/locator/ec2/ [us-east-1 amd64]
63-
BastionKeyName: rluna_hip
64-
BastionInstanceType: t3.small # Is this a proper size?
65-
BastionType: SSH
6661
CustomerManagedCmkArn: ""
6762
DomainName: "{{ app_name }}-prod.caktus-built.com"
6863
DomainNameAlternates: ""

deploy/host_vars/runner.yml

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)