GitLabとGitLab Runnerを同一EKSクラスター上で稼働させつつワーカーノードを分離してみた
Amazon EKSでGitLabをセルフホストしています。
GitLab Runnerを利用するにあたり、同一EKSクラスター上で稼働させつつGitLabとは別のマシン上で動作させたいことがありました。
今回はこの方法についてブログにします。
前提
本記事では、以下を前提とします。
- GitLab・GitLab Runner をEKSにインストール済み
インストール方法については、以下の記事をご参照ください。
なぜGitLabとGitLab Runnerを別ノードで動作させたいのか?
公式ドキュメントには以下の記載があり、別のマシン上で動作させることが推奨されています。
For security and performance reasons, install GitLab Runner on a machine separate from the machine that hosts your GitLab instance.
セキュリティとパフォーマンス上の理由から、GitLab インスタンスをホストするマシンとは別のマシンに GitLab Runner をインストールします。
Install GitLab Runner | GitLab Docsから引用
GitLab Runnerでは、CI/CDのジョブ毎にRunnerノード上にPodが起動します。
同一マシン上で稼働させている場合、GitLab Runnerのジョブ数増加によるリソース逼迫でGitLab自体のパフォーマンスが落ちる可能性があります。
どのレベルでGitLabとGitLab Runnerを分離するか
今回GitLabはEKS上に構築していることを前提としています。
GitLab RunnerもEKS上で構築する場合、分離の選択肢は以下があると思います。
- EKSクラスター単位
- EKSノードグループ単位
ざっくり以下のようなメリット・デメリットがあると思います。
- | EKSクラスター | EKSノードグループ |
---|---|---|
メリット | 分離の複雑性: Kubenetes側のノード分離設定が不要 |
コスト: 単一EKSクラスター料金のみ(72USD/月) 管理: EKSバージョンアップが1回で済む |
デメリット | コスト: EKSクラスター料金が2倍((72USD/月 * 2)) 管理: EKSバージョンアップが2回必要 |
分離の複雑性: Kubenetes側のノード分離設定が必要(Node Afinity/Taints等) |
今回はコストとEKSクラスター管理を重視して、ノードグループ単位の分離としました。
このブログでは、ノードグループ単位の分離を前提として、ノード分離設定について紹介します。
やってみた
GitLab Runner用のマネージドノードグループを作成
任意の方法でGitLab Runner用のマネージドノードグループを作成します。
今回はawscli
を利用する方法を紹介します。
以下のファイルを用意します。
クラスター名
やサブネットID
、ノードIAMロールARN
は各自の環境に合わせて置き換えてください。
動作させるだけであれば、Node Role ARN
は既存マネージドノードグループにアタッチされているノードIAMロールでも問題ありません。
{
"clusterName": "<クラスター名>",
"nodegroupName": "gitlab-runner",
"subnets": [
"<サブネットID A>",
"<サブネットID B>",
"<サブネットID C>"
],
"nodeRole": "<ノードIAMロールARN>",
"scalingConfig": {
"minSize": 1,
"maxSize": 1,
"desiredSize": 1
},
"instanceTypes": [
"t3.medium"
],
"diskSize": 30,
"labels": {
"workload": "gitlab-runner"
},
"taints": [
{
"key": "workload",
"value": "gitlab-runner",
"effect": "NO_SCHEDULE"
}
]
}
GitLab Runner専用のノードとするために、taints
とlabels
を設定しておきます。
GitLab Runnerについては、必要スペックがCI/CDジョブによって異なります。
明示的な推奨スペックは無いため、各自の環境に合わせてインスタンスタイプを選定してください。
以下のコマンドを実行してマネージドノードグループを作成します。
aws eks create-nodegroup \
--region <リージョン> # us-east-2 \
--cli-input-json file://gitlab-runner-nodegroup.json
GitLab Runner用マネージドノードとGitLab用マネージドノード間では通信が必要です。
マネージドノードグループに以下のTerraformコードで作成したSecurityGroupをアタッチします。
resource "aws_security_group" "gitlab_internal_networking" {
name_prefix = "${var.prefix}-internal-networking"
vpc_id = module.vpc.vpc_id
description = "${var.prefix} - Internal Networking Security Group"
tags = {
Name = "${var.prefix}-internal-networking"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_vpc_security_group_ingress_rule" "gitlab_internal_networking" {
security_group_id = aws_security_group.gitlab_internal_networking.id
description = "Open internal networking for VMs and Node Groups"
ip_protocol = "-1"
referenced_security_group_id = aws_security_group.gitlab_internal_networking.id
tags = {
Name = "${var.prefix}-internal-networking"
}
}
resource "aws_vpc_security_group_egress_rule" "gitlab_internal_networking_internet" {
security_group_id = aws_security_group.gitlab_internal_networking.id
description = "Open internet access for VMs"
ip_protocol = "-1"
cidr_ipv4 = "0.0.0.0/0"
tags = {
Name = "${var.prefix}-internal-networking-internet"
}
}
GitLab RunnerマネージドノードグループEC2インスタンス及び、GitLabマネージドノードグループEC2に上記のセキュリティグループをアタッチします。
aws ec2 modify-instance-attribute \
--instance-id <インスタンスID> \
--groups <セキュリティグループID>
今回は手順の簡略化のために、マネージドノードグループ内のEC2インスタンスに直接セキュリティグループをアタッチしています。
この方法はノードのスケールに対応できないため、実環境ではEC2起動テンプレート側でセキュリティグループを設定することを推奨します。(スケールアップ等で新規に作成されたノードに上記のセキュリティグループがアタッチされない)
values.yaml
の更新
values.yaml
を更新します。GitLab URL
やトークン
は置き換えてください。
gitlabUrl: <GitLab URL> # example: https://gitlab.exmaple.com/
runnerRegistrationToken: "<トークン>"
rbac:
create: true
serviceAccount:
create: true
name: "gitlab-runner"
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: workload
operator: In
values:
- gitlab-runner
tolerations:
- key: "workload"
operator: "Equal"
value: "gitlab-runner"
effect: "NoSchedule"
runners:
# tpl: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function
# runner configuration: https://docs.gitlab.com/runner/configuration/advanced-configuration.html
# kubernetes executor: https://docs.gitlab.com/runner/executors/kubernetes/
config: |
[[runners]]
[runners.kubernetes]
[runners.kubernetes.affinity]
[runners.kubernetes.affinity.node_affinity]
[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution]
[[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution.node_selector_terms]]
[[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution.node_selector_terms.match_expressions]]
key = "workload"
operator = "In"
values = ["gitlab-runner"]
[runners.kubernetes.node_tolerations]
"workload=gitlab-runner" = "NoSchedule"
追加したのはNode Affinity
とTolerations
関係の設定です。
これはGitLab Runner用マネージドノードグループを、GitLab Runnerの専用ノードにするための設定です。
- Node Affinity: GitLab Runner用のPodを、workload=gitlab-runnerラベルを持つノードにのみスケジュールする設定
- Tolerations: GitLab Runner用のPodが、workload=gitlab-runner:NoScheduleのTaintを持つノードにスケジュールできるようにする設定
runners
配下でも同様の設定をしています。
これはジョブPodの設定です。GitLab Runnerでは、CI/CDジョブ毎にPodが起動します。(ジョブPod)
ジョブPodはGitLab Runner管理用Podの設定を引き継ぐことはなく、Tolerations
やNode Affinity
を別途設定する必要があります。
上記のように設定することで、ジョブPodもGitLab Runner専用ノードで起動するように設定しています。
Helmリリースの更新
準備ができたら以下のコマンドで、Helmリリースを更新します。
# Dry-run
helm upgrade gitlab-runner gitlab/gitlab-runner \
-f values.yaml \
--dry-run \
-n gitlab-runner
# Run
helm upgrade gitlab-runner gitlab/gitlab-runner \
-f values.yaml \
-n gitlab-runner
動作確認
ノードを管理しているマネージドノードグループを確認します。
kubectl get nodes --label-columns=eks.amazonaws.com/nodegroup
NAME STATUS ROLES AGE VERSION NODEGROUP
ip-10-0-100-67.us-east-2.compute.internal Ready <none> 105m v1.30.9-eks-5d632ec default-20250321091112021200000024
ip-10-0-11-239.us-east-2.compute.internal Ready <none> 105m v1.30.9-eks-5d632ec default-20250321091112021200000024
ip-10-0-19-178.us-east-2.compute.internal Ready <none> 7m50s v1.30.9-eks-5d632ec gitlab-runner
上記から、ip-10-0-19-178.us-east-2.compute.internal
がGitLab Runner用のノードであることが分かりました。
このノードでGitLab Runner用のPodが稼働することを確認します。
kubectl get pods -o wide -n gitlab-runner
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
gitlab-runner-5b6cc88b68-gd5nt 1/1 Running 0 73s 10.0.45.240 ip-10-0-19-178.us-east-2.compute.internal <none> <none>
Podgitlab-runner-5b6cc88b68-gd5nt
のNODE
がip-10-0-19-178.us-east-2.compute.internal
になっているため、GitLab Runner用のノードで起動していることが確認できます。
他のリソースがGitLab Runner用のノードで稼働していないことも確認できました。
kubectl get pods -o wide -n gitlab
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
gitlab-certmanager-7c6f6b775f-gszfh 1/1 Running 0 18m 10.0.118.119 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-certmanager-cainjector-75c88bbb77-spcx9 1/1 Running 0 18m 10.0.118.118 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-certmanager-webhook-86f7d45d4f-8hss6 1/1 Running 0 18m 10.0.40.169 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
gitlab-gitaly-0 1/1 Running 0 18m 10.0.118.121 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-gitlab-exporter-8fd649d5c-cvbk4 1/1 Running 0 18m 10.0.40.167 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
gitlab-kas-65d6c4dc77-5n62r 1/1 Running 2 (17m ago) 18m 10.0.40.170 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
gitlab-kas-65d6c4dc77-s9dx2 1/1 Running 0 17m 10.0.118.123 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-migrations-6ff953e-cqw5c 0/1 Completed 0 18m 10.0.103.48 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-postgresql-0 2/2 Running 0 18m 10.0.40.171 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
gitlab-prometheus-server-c7f9d89dc-nnzzw 2/2 Running 0 18m 10.0.40.172 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
gitlab-redis-master-0 2/2 Running 0 18m 10.0.118.116 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-registry-5499795975-7wx8b 1/1 Running 0 17m 10.0.118.117 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-registry-5499795975-dwkfg 1/1 Running 0 18m 10.0.40.166 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
gitlab-sidekiq-all-in-1-v2-6fdb8b7656-xmjmw 1/1 Running 1 (15m ago) 18m 10.0.118.120 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-toolbox-d76bf6d7-678f2 1/1 Running 0 18m 10.0.40.168 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
gitlab-webservice-default-5bf789cbf5-9hghz 2/2 Running 1 (15m ago) 17m 10.0.118.122 ip-10-0-100-67.us-east-2.compute.internal <none> <none>
gitlab-webservice-default-5bf789cbf5-c2pbq 2/2 Running 1 (15m ago) 18m 10.0.40.165 ip-10-0-11-239.us-east-2.compute.internal <none> <none>
ip-10-0-19-178.us-east-2.compute.internal
で稼働しているPodは無いため、問題なさそうです。
最後に、GitLabで適当なパイプラインを実行して、ジョブ用のPod(Pod名runner-
から始まるもの)がGitLab Runner用のノードで起動するか確認します。
kubectl get pods -o wide -n gitlab-runner
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
gitlab-runner-5fcb7987c4-chwtj 1/1 Running 0 5m32s 10.0.42.1 ip-10-0-19-178.us-east-2.compute.internal <none> <none>
runner-t1htgj4s-project-1-concurrent-0-areczxil 2/2 Running 0 19s 10.0.42.3 ip-10-0-19-178.us-east-2.compute.internal <none> <none>
runner-t1htgj4s-project-1-concurrent-0-hstmi422 2/2 Terminating 0 36s 10.0.42.2 ip-10-0-19-178.us-east-2.compute.internal <none> <none>
すべてのPodがGitLab Runner用ノード(ip-10-0-19-178.us-east-2.compute.internal
)で稼働していることが確認できました。
おまけ: Node Affinity・Tolerationsの確認
Helmチャート側で設定したNode Affinity・Tolerationsの確認方法です。
ジョブPod・GitLab Runner管理用Podでそれぞれ設定されていることが確認できます。
POD_NAME="<Pod名>"
kubectl get pod $POD_NAME -o yaml | grep -A 10 affinity
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: workload
operator: In
values:
- gitlab-runner
kubectl get pod -n gitlab-runner $POD_NAME -o yaml | grep -A 5 tolerations
tolerations:
- effect: NoSchedule
key: workload
operator: Equal
value: gitlab-runner
おわりに
GitLab RunnerとGitLabを同一EKSクラスターで稼働させつつ、ノードを分ける方法についてでした。
この方法を使うことでEKSクラスターを分けることなく、GitLabとGitLab Runnerを別マシンで稼働させることが可能です。
GitLab Runner管理PodとジョブPod、それぞれにNode Affinity・Tolerations設定が必要なことにご注意ください。
特にジョブPodの設定を忘れると、他のノードでジョブPodが動いてノードのリソースを逼迫することがあります。
以上、AWS事業本部の佐藤(@chari7311)でした。