GitLab RunnerのKubernetes Executorのジョブ内で利用するServiceAccountを変更したときのメモ。
前置き
GitLab RunnerをHelmでインストールした場合、GitLab Runnerは標準でKubernetes Executorでジョブを実行する。Kubernetes Executorはジョブ実行用のPodを起動する。
以下、ジョブを実行した時のログである。
Running with gitlab-runner 14.7.0 (98daeee0)
on gitlab-runner-gitlab-runner-69495c846c-2th5p aXyxVB79
Preparing the "kubernetes" executor
00:00
Using Kubernetes namespace: gitlab
Using Kubernetes executor with image harbor.hoge/tkg/docker-aws-kp ...
Using attach strategy to execute scripts...
Preparing environment
Waiting for pod gitlab/runner-axyxvb79-project-2-concurrent-0dpx7t to be running, status is Pending
Running on runner-axyxvb79-project-2-concurrent-0dpx7t via gitlab-runner-gitlab-runner-69495c846c-2th5p...
runner-axyxvb79-project-2-concurrent-0dpx7t
というPodでジョブを実行している事が分かる。
これのServiceAccountは以下となっている。
k get pod -n gitlab runner-axyxvb79-project-2-concurrent-0dpx7t -o yaml | grep -w serviceAccount
serviceAccount: default
これはどういうことかというと、このコンテナ内でkubectlを実行した場合、以下の条件下で動作する。
- 接続先ホスト:環境変数
KUBERNETES_SERVICE_HOST
で定義されたホスト - 接続先ポート:環境変数
KUBERNETES_SERVICE_PORT
で定義されたポート - RBACの権限:PodのServiceAccount(上の例では
default
)に紐付いた権限
KUBECONFIG
はなく、起動時に自動で付与される環境変数を元にkubectlはクラスタへの接続を試みる。
これは、GitLabのジョブ内でkubectlを叩くと、Namespaceがgitlab内のService Account defaultの権限相当で同じクラスタ内の操作が出来ることになる。
今の権限を確認する。
SUBJECT SCOPE ROLE
:(省略)
gitlab:default cluster-wide ClusterRole/cluster-admin
cluster-adminがついているので、クラスタに対して何でも出来ることになる。まずい状態である。
ServiceAccountの変更
ServiceAccountの作成
現状、GitLabのProjectごとにNamespaceを切った運用としているため、ProjectごとにServiceAccountを作成し、そのProjectで必要な権限のみをServiceAccountに付与するようにする。
cicd
というProjectではkpackを利用したイメージのbuildのみGitLab Runner上で実行したいため、cicd
というNamespace上にServiceAccountを作成して、ビルドに必要な権限のみ持つRoleをbindする。
最初にkp-account
というServiceAccountを作成する。
kubectl create sa kp-account -n cicd
次に、以下のようなClusterRoleをbuild-service-user-role
という名前で予め用意していたので、こちらをbindする。
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
secrets [] [] [create update patch delete]
configmaps [] [] [get list create update delete patch watch]
builders.kpack.io [] [] [get list watch create patch update delete deletecollection]
images.kpack.io [] [] [get list watch create update delete patch]
pods/log [] [] [get list watch]
pods [] [] [get list watch]
clusterbuilders.kpack.io [] [] [get list watch]
clusterstacks.kpack.io [] [] [get list watch]
clusterstores.kpack.io [] [] [get list watch]
customstacks.stacks.stacks-operator.tanzu.vmware.com [] [] [get list watch]
serviceaccounts [] [default] [get update patch]
builds.kpack.io [] [] [patch get list watch update]
$ kubectl create clusterrolebinding kp-account-binding --clusterrole build-service-user-role --serviceaccount cicd:kp-account
clusterrolebinding.rbac.authorization.k8s.io/kp-account-binding created
GitLab Runnerの設定変更
GitLab RunnerをHelmでインストールした場合、gitlab-runner-gitlab-runner
のようなGitLab Runnerの設定が入ったConfigMapが存在する。こちらを修正していく。
kubectl edit cm gitlab-runner-gitlab-runner -n gitlab
でConfigMapを開き、runners.kubernetes
にservice_account_overwrite_allowed
とnamespace_overwrite_allowed
を追加する。
config.template.toml: |
[[runners]]
[runners.kubernetes]
namespace = "gitlab"
image = "ubuntu:16.04"
Shared = true
service_account_overwrite_allowed = ".*"
namespace_overwrite_allowed = ".*"
これにより、.gitlab-ci.yml
で環境変数を設定すると、利用するServiceAccountやジョブ用Podが稼働するNamespaceを変更することが出来るようになる。パラメタの詳細についてはKubernetes executorの説明ページを参考のこと。
.gitlab-ci.ymlの修正
.gitlab-ci.yml
のvariablesでNamespaceとServiceAccountをそれぞれ上書きするよう環境変数を設定する。
variables:
KUBERNETES_NAMESPACE_OVERWRITE: cicd
KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: kp-account
これでgitlab Namespaceのdefault ServiceAccountではなく、cicd Namespaceのkp-accountというServiceAccountに権限が変更される。
実機確認
先程作成したServiceAccountでは、podのlistは取得できるが、deploymentのlistは取得できない。実際に取得できなくなったことを確認する。
.gitlab-ci.yml
に以下のようなコードを記載しておく。
build-image:
image: harbor.hoge/tkg/docker-aws-kp
stage: build-image
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
script:
- |
set -xe
kubectl get pod
kubectl get deploy
実行結果はこちら。deploymentのみ権限不足で失敗した。
++ kubectl get pod -n cicd
NAME READY STATUS RESTARTS AGE
runner-serpks1d-project-2-concurrent-084vms 2/2 Running 0 5s
++ kubectl get deploy -n cicd
Error from server (Forbidden): deployments.apps is forbidden: User "system:serviceaccount:cicd:kp-account" cannot list resource "deployments" in API group "apps" in the namespace "cicd"
ERROR: Job failed: command terminated with exit code 1
なお、先ほどの環境変数をコメントアウトすると以下の結果となる。
++ kubectl get pod -n cicd
No resources found in cicd namespace.
++ kubectl get deploy -n cicd
No resources found in cicd namespace.
これにより、ServiceAccountが適切に設定されていることが分かる。