Runners Program Runners umożliwia uruchamianie kompilacji w Pipelines we własnej infrastrukturze i nie zostanie naliczona opłata za minuty kompilacji wykorzystane przez samodzielnie hostowanych runnerów. Poniższe przewodniki pomagają skonfigurować system operacyjny za pomocą Pipelines, aby używać modułów uruchamiających w repozytoriach.
Obsługiwane platformy
- Linux z architekturą x64 i jądrem Linux 4.0.0+. Runery zostały przetestowane na następujących dystrybucjach Linuksa:
- Windows 10+ lub Windows Server 2019+
- MacOS Catalina 10.15+
Minimalne wymagania
Doker Linuksa:
- 64-bitowa instancja Linux z co najmniej 8 GB pamięci RAM jako hostem dla runnera.
- Docker v19.03 i nowsze
Bitbucket Pipelines umożliwia tworzenie obrazu platformy Docker z pliku Docker w repozytorium i wypychanie go do rejestru platformy Docker przez uruchamianie poleceń platformy Docker w potoku kompilacji. Zanurz się prosto – środowisko potoku jest dostarczane domyślnie i nie musisz go dostosowywać!
Włączenie dostepu do Dockerza Aby umożliwić dostęp do demona Docker, można dodać dockera jako usługę w kroku lub dodać opcję globalną w pliku bitbucket-pipelines.yml.
Żeby skonfigurować Bitbucket Runners komendami ze strony Docker Linux należy: Pierwszy ze sposobów:
- Wyłączyć swap w środowisku Linux
Poniżej znajdują się kroki, aby wyłączyć swap dla większości dystrybucji Linuksa . Jeśli poniższe polecenia nie są zainstalowane, będziesz musiał je zainstalować. Zapoznaj się z dokumentacją dystrybucji, aby skonfigurować swap.
1
sudo swapon -sv
Jeśli zamiana jest włączona, powinieneś zobaczyć dane wyjściowe podobne do następujących:
1
2
NAME TYPE SIZE USED PRIO
/dev/sda3 partition 2G 655.2M -1
-
Jeśli zamiana jest włączona, będziesz musiał ją wyłączyć
-
Skonfiguruj vm.swappiness w środowisku Linux
Poniżej znajdują się kroki, aby skonfigurować vm.swappiness dla większości dystrybucji Linuksa . Jeśli poniższe polecenia nie są zainstalowane, będziesz musiał je zainstalować. Zapoznaj się z dokumentacją dystrybucji, aby skonfigurować swap.
Użyj następującego polecenia, aby sprawdzić wartość vm.swappiness:
1
sudo sysctl -n vm.swappiness
Jeśli wartość swappiness jest inna niż 1 , skonfiguruj ją za pomocą następującego procesu: Uruchom następujące polecenie, upewniając się, że dane wyjściowe są teraz 1:
1
sudo sysctl -n vm.swappiness
Drugi ze sposobów: Ten sposób jest o wiele prostszy. Polega on na tym, że Bitbucket Runners wydaje polecenie, które trzeba po prostu uruchomić w konsoli Linux. Polecenie wygladą nastepująco:
Copy this command with the token to run on the command line
1
docker container run -it -v /tmp:/tmp -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/containers:/var/lib/docker/containers:ro -e ACCOUNT_UUID={c09fffc4-c0e4-4c0d-bd98-ef23d2aa6dca} -e REPOSITORY_UUID={49ca6428-767f-4f57-95ec-84cb0fd05c08} -e RUNNER_UUID={4b3b8bf3-c323-536f-b2ba-797e0aa721b9} -e RUNTIME_PREREQUISITES_ENABLED=true -e OAUTH_CLIENT_ID=sLwWKhotz990WnKjNhNK1ouD5HKKkA9I -e OAUTH_CLIENT_SECRET=8MEOpdDBBFpwENUr518EcEUJWHZFiIh3miEu1OzmZ2AyWMSkB0wCrpdbA9ElfpxC -e WORKING_DIRECTORY=/tmp --name runner-4b3b8bf3-c323-536f-b2ba-797e0aa721b9 docker-public.packages.atlassian.com/sox/atlassian/bitbucket-pipelines-runner:1
Po czym konfiguracja pliku bitbucket-pipelines.yml tworzy się samodzielnie:
1
2
3
4
5
6
7
pipelines:
default:
- step:
runs-on:
- self.hosted
- linux
script:
1
2
3
4
5
6
**Notatka**
Jeśli nie określisz etykiety linux.shell, nasz program planujący przyjmie, że jest to krok Linux Docker i spróbuje uruchomić go jako Linux Docker Runner.
Jeśli wszystkie pasujące Linux Shell Runners są zajęte, Twój krok zostanie umieszczony w kolejce, dopóki jeden nie stanie się ponownie dostępny.
Jeśli nie masz w swoim repozytorium żadnych biegaczy online, które pasują do wszystkich Twoich etykiet, krok się nie powiedzie.
Jak stworzyć Runner?
Utwórz nowy Workspace Runner w Bitbucket
Przejdź do ustawień obszaru roboczego
Kliknij swoje zdjęcie profilowe i wybierz obszar roboczy
Kliknij Ustawienia i przewiń w dół do Workspace Runners i kliknij Dodaj Runnera:
Nadaj swojemu biegaczowi imię i kliknij Dalej.
To da ci wynik polecenia taki:
1
2
3
4
5
6
7
8
9
docker container run -it -v /tmp:/tmp -v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/containers:/var/lib/docker/containers:ro \
-e ACCOUNT_UUID={__ACCOUNT_UUID__} \
-e RUNNER_UUID={__RUNNER_UUID__} \
-e OAUTH_CLIENT_ID=__OAUTH_CLIENT_ID__ \
-e OAUTH_CLIENT_SECRET=__OAUTH_CLIENT_SECRET__ \
-e WORKING_DIRECTORY=/tmp \
--name runner-7deb7740-f86b-50d0-9c85-671fcb3c9038 \
docker-public.packages.atlassian.com/sox/atlassian/bitbucket-pipelines-runner:1
Zapisz go i kliknij Zakończ.
Musisz wyodrębnić zmienne ACCOUNT_UUID, RUNNER_UUID, OAUTH_CLIENT_ID i OAUTH_CLIENT_SECRET z polecenia.
Uważaj na następujące rzeczy:
- Skopiuj ACCOUNT_UUID i RUNNER_UUID bez nawiasów klamrowych.
- Pamiętaj, aby skopiować cały OAUTH_CLIENT_SECRET (może zawierać znaki specjalne, takie jak myślniki lub podkreślenia).
- Zmienne OAUTH muszą zostać przekonwertowane na base64.
Możesz wypełnić następujący skrypt, a później wygenerować zasoby k8s za pomocą tych zmiennych:
1
2
3
4
5
6
7
export ACCOUNT_UUID=__ACCOUNT_UUID__
export RUNNER_UUID=__RUNNER_UUID__
export OAUTH_CLIENT_ID=__OAUTH_CLIENT_ID__
export OAUTH_CLIENT_SECRET=__OAUTH_CLIENT_SECRET__
export BASE64_OAUTH_CLIENT_ID=$(echo -n $OAUTH_CLIENT_ID | base64)
export BASE64_OAUTH_CLIENT_SECRET=$(echo -n $OAUTH_CLIENT_SECRET | base64)
Wdrożenie w Kubernetes
Teraz interesująca część. Zastąp symbole zastępcze ${VAR_NAME} zawartością tych zmiennych.
Ważne:
- użyj zakodowanych w base64 wersji zmiennych OAUTH w pliku secret.yaml
- zachowaj cudzysłowy i nawiasy klamrowe („, {, }”) w liniach job.yaml 17 i 19
Następujące skrypty bash wygenerują pliki secret.yaml i job.yaml w bieżącym katalogu roboczym.
secret.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
cat > ./secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
name: runner-oauth-credentials
labels:
accountUuid: ${ACCOUNT_UUID}
runnerUuid: ${RUNNER_UUID}
data:
oauthClientId: ${BASE64_OAUTH_CLIENT_ID}
oauthClientSecret: ${BASE64_OAUTH_CLIENT_SECRET}
EOF
job.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
cat > ./job.yaml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: runner
spec:
template:
metadata:
labels:
accountUuid: ${ACCOUNT_UUID}
runnerUuid: ${RUNNER_UUID}
spec:
containers:
- name: bitbucket-k8s-runner
image: docker-public.packages.atlassian.com/sox/atlassian/bitbucket-pipelines-runner
env:
- name: ACCOUNT_UUID
value: "{${ACCOUNT_UUID}}"
- name: RUNNER_UUID
value: "{${RUNNER_UUID}}"
- name: OAUTH_CLIENT_ID
valueFrom:
secretKeyRef:
name: runner-oauth-credentials
key: oauthClientId
- name: OAUTH_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: runner-oauth-credentials
key: oauthClientSecret
- name: WORKING_DIRECTORY
value: "/tmp"
volumeMounts:
- name: tmp
mountPath: /tmp
- name: docker-containers
mountPath: /var/lib/docker/containers
readOnly: true
- name: var-run
mountPath: /var/run
- name: docker-in-docker
image: docker:20.10.7-dind
securityContext:
privileged: true
volumeMounts:
- name: tmp
mountPath: /tmp
- name: docker-containers
mountPath: /var/lib/docker/containers
- name: var-run
mountPath: /var/run
restartPolicy: OnFailure
volumes:
- name: tmp
- name: docker-containers
- name: var-run
backoffLimit: 6
completions: 1
parallelism: 1
EOF
job.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
cat > ./job.yaml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: runner
spec:
template:
metadata:
labels:
accountUuid: ${ACCOUNT_UUID}
runnerUuid: ${RUNNER_UUID}
spec:
containers:
- name: bitbucket-k8s-runner
image: docker-public.packages.atlassian.com/sox/atlassian/bitbucket-pipelines-runner
env:
- name: ACCOUNT_UUID
value: "{${ACCOUNT_UUID}}"
- name: RUNNER_UUID
value: "{${RUNNER_UUID}}"
- name: OAUTH_CLIENT_ID
valueFrom:
secretKeyRef:
name: runner-oauth-credentials
key: oauthClientId
- name: OAUTH_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: runner-oauth-credentials
key: oauthClientSecret
- name: WORKING_DIRECTORY
value: "/tmp"
volumeMounts:
- name: tmp
mountPath: /tmp
- name: docker-containers
mountPath: /var/lib/docker/containers
readOnly: true
- name: var-run
mountPath: /var/run
- name: docker-in-docker
image: docker:20.10.7-dind
securityContext:
privileged: true
volumeMounts:
- name: tmp
mountPath: /tmp
- name: docker-containers
mountPath: /var/lib/docker/containers
- name: var-run
mountPath: /var/run
restartPolicy: OnFailure
volumes:
- name: tmp
- name: docker-containers
- name: var-run
backoffLimit: 6
completions: 1
parallelism: 1
EOF
Zastosuj wygenerowane manifesty do Kubernetes:
1
2
3
kubectl create namespace bitbucket-runner --dry-run -o yaml | kubectl apply -f -
kubectl -n bitbucket-runner apply -f secrets.yaml
kubectl -n bitbucket-runner apply -f job.yaml
Jeśli wszystko poszło dobrze, wkrótce zobaczysz biegacza ze statusem ONLINE na stronie Workspace Runners.
Jeśli zdecydujesz się usunąć biegacza z Kubernetes, wykonaj następujące kroki:
1
2
3
kubectl -n bitbucket-runner delete -f job.yaml
kubectl -n bitbucket-runner delete -f secret.yaml
kubectl delete namespace bitbucket-runner
Jak używać tego runnera w potoku Bitbucket?
To całkiem proste, dodaj etykiety runnera do etapu potoku.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pipelines:
custom:
pipeline:
- step:
name: Step1
size: 8x # default 4gb, 8x for 32gb
runs-on:
- 'self.hosted'
- 'my.custom.label'
script:
- echo "This step will run on a self hosted runner with 32 GB of memory.";
- step:
name: Step2
script:
- echo "This step will run on Atlassian's infrastructure as usual.";
Błąd: status 500 w potokach Bitbucket
Ponieważ chcieliśmy zbudować obrazy Dockera (za pomocą Dockera w Dockerze lub dind) w naszym potoku, napotkaliśmy następujący problem:
1
Status 500: {"message":"io.containerd.runc.v2: failed to adjust OOM score for shim: set shim OOM score: write /proc/PROC_ID/oom_score_adj: invalid argument\n: exit status 1: unknown"}
Jak to naprawić
Najpierw próbowałem znaleźć główną przyczynę tego komunikatu o błędzie, ale nie mogłem znaleźć niczego poza kilkoma komentarzami na ten temat, które zostały już naprawione w ostatnim wydaniu containerd, i tak dalej… Postanowiłem więc sprawdzić, czy wersje oprogramowania się zgadzają. Nawet gdy containerd pasował do wymaganej wersji, stwierdziłem, że Docker na serwerach jest nieco przestarzały (19.03), więc postanowiłem go zaktualizować.
Po aktualizacji nadal widziałem wcześniej wspomniane komunikaty o błędach w potokach Bitbucket.
Zweryfikowałem wersję Dockera uruchomioną na serwerze:
1
2
# docker --version
Docker version 20.10.7, build f0df350
Wymieniłem docker w wersji obrazu kontenera docker (dind), aby używał dokładnie tej samej wersji, co zainstalowana w naszym klastrze k8s!
1
2
- name: docker-in-docker
image: docker:20.10.5-dind -> docker:20.10.7-dind
I magicznie błąd zniknął i wszystko działa zgodnie z oczekiwaniami.