今回はGitLabからAmazon EKS上のPodを更新する方法を紹介します。
背景
GitLabからAmazon EKSに接続し、リソースを更新するには、大きく3つの方法があります。
- AWSアクセス情報を使ってkubectlで接続する
- GitLab Agent for Kubernetesをインストールする
- Flux CDなどを使ってGitOpsを利用する
今回はこのうち上2つを紹介します。
検証
準備
検証の前に事前に以下の準備をしておきます。
Amazon EKSの作成は以前使ったCloudFormationファイルを利用しました。
クラスター作成後はAWS CloudShellからクラスターにアクセスして状態を確認します。
[cloudshell-user@ip-10-134-10-124 ~]$ aws eks update-kubeconfig \ > --name eks-cluster \ > --region ap-northeast-1 [cloudshell-user@ip-10-134-10-124 ~]$ kubectl version Client Version: v1.29.3-eks-ae9a62a Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3 Server Version: v1.29.4-eks-036c24b [cloudshell-user@ip-10-134-10-124 ~]$ kubectl get pods -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system aws-node-xfdkd 2/2 Running 0 5m19s kube-system aws-node-z5ll6 2/2 Running 0 5m2s kube-system coredns-676bf68468-pz8fl 1/1 Running 0 10m kube-system coredns-676bf68468-slrrh 1/1 Running 0 10m kube-system kube-proxy-2hppc 1/1 Running 0 5m2s kube-system kube-proxy-mhpkb 1/1 Running 0 5m19s
GitLab Project作成後は以下のマニフェストファイルを事前に配置しておきます。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
AWSアクセス情報を使う場合
GitLabからkubectlを使ってアクセスするには、GitLabからAWS / Kubernetesそれぞれへのアクセス権限を付与する必要があります。
GitLabからAWSへのアクセスはOIDCを利用します。作成は以下のCloudFormationファイルを利用します。
AWSTemplateFormatVersion: '2010-09-09' Description: IAM role for GitLab/EKS integration Parameters: RepositoryPath: Type: String Default: "<GitLab Projectパス>" PJPrefix: Type: String Default: "gitlab-eks" Resources: #OIDCを作成していない場合は以下のコメントを外してください #OIDCProviderForGitLab: # Type: AWS::IAM::OIDCProvider # Properties: # Url: https://gitlab.com # ClientIdList: # - https://gitlab.com # ThumbprintList: # - ffffffffffffffffffffffffffffffffffffffff RoleForGitLabEKS: Type: AWS::IAM::Role Properties: RoleName: !Sub "${PJPrefix}-role" MaxSessionDuration: 3600 AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRoleWithWebIdentity Principal: Federated: !Sub 'arn:aws:iam::${AWS::AccountId}:oidc-provider/gitlab.com' Effect: Allow Condition: ForAnyValue:StringLike: "gitlab.com:sub": - !Sub "project_path:${RepositoryPath}:ref_type:branch:ref:*" Policies: - PolicyName: !Sub "${PJPrefix}-policy" PolicyDocument: Statement: - Effect: Allow Action: - eks:* Resource: - '*'
GitLabからEKSクラスターへのアクセスには、上記で作成したIAMロールがEKSクラスターにアクセスできるよう、EKSクラスター上の aws-auth
ConfigMapを修正するか、Access Entryというリソースを作成します。今回はAccess Entryを利用しました。
※参考:
ここでは準備のときと同様、AWS CloudShellからコマンドを実行します。
#EKSの認証モードを変更する [cloudshell-user@ip-10-134-10-124 ~]$ aws eks update-cluster-config \ > --name eks-cluster \ > --access-config authenticationMode=API_AND_CONFIG_MAP [cloudshell-user@ip-10-134-10-124 ~]$ aws eks describe-cluster \ > --name eks-cluster \ > --region ap-northeast-1 \ > --query 'cluster.accessConfig' { "authenticationMode": "API_AND_CONFIG_MAP" } #IAMロールのアクセスを許可する [cloudshell-user@ip-10-134-10-124 ~]$ aws eks create-access-entry \ > --cluster-name eks-cluster \ > --principal-arn arn:aws:iam::<AWS Account ID>:role/gitlab-eks-role [cloudshell-user@ip-10-134-10-124 ~]$ aws eks associate-access-policy \ > --cluster-name eks-cluster \ > --principal-arn arn:aws:iam::<AWS Account ID>:role/gitlab-eks-role \ > --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \ > --access-scope type=cluster #確認 [cloudshell-user@ip-10-134-10-124 ~]$ aws eks list-access-entries \ > --cluster-name eks-cluster { "accessEntries": [ "arn:aws:iam::<AWS Account ID>:role/gitlab-eks-role", "arn:aws:iam::<AWS Account ID>:user/yamaji" ] } [cloudshell-user@ip-10-134-10-124 ~]$
GitLabからEKSにアクセスするためのAWS側の準備はできたので、GitLab側の設定を行います。
まずは以下のGitLab CI/CD変数を登録します。
AWS_ACCOUNT_ID
: AWSアカウントIDAWS_DEFAULT_REGION
:ap-northeast-1
AWS_IAM_ROLE
:arn:aws:iam::<AWS Account ID>:role/gitlab-eks-role
CI/CD変数を設定後、以下のような .gitlab-ci.yml
を作成します。
variables: AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION AWS_IAM_ROLE: $AWS_IAM_ROLE EKS_CLUSTER_NAME: "eks-cluster" DOCKER_TLS_CERTDIR: "/certs" # 各CLIのインストール、AWSへの接続設定 default: image: docker:24.0.5 services: - docker:24.0.5-dind id_tokens: GITLAB_OIDC_TOKEN: aud: https://gitlab.com before_script: - apk add --no-cache aws-cli - > apk --no-cache add curl && curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x ./kubectl && mv ./kubectl /usr/local/bin/kubectl - > export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role-with-web-identity --role-arn ${AWS_IAM_ROLE} --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}" --web-identity-token ${GITLAB_OIDC_TOKEN} --duration-seconds 3600 --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text)) # EKSへのデプロイを実行 deploy: stage: deploy script: - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME --region $AWS_DEFAULT_REGION - kubectl version - kubectl get pods - kubectl apply -f deployment.yaml
.gitlab-ci.yml
ファイルを作成するとCI/CDパイプラインが実行され、問題なければ成功します。
実行後AWS CloudShellから確認すると、以下のようにPodが作成されたことを確認できます。
[cloudshell-user@ip-10-134-10-124 ~]$ kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-7c79c4bf97-sszcp 1/1 Running 0 3m4s [cloudshell-user@ip-10-134-10-124 ~]$
GitLab Agent for Kubernetesを使う場合
GitLab Agent for KubernetesをKubernetesクラスターにインストールすると、前段で行ったようなAWSの接続設定をせずに、GitLabからKubernetesクラスターにアクセス可能となります。
GitLab Agent for Kubernetesをインストールするため、まずはGitLab UIから 操作
→ Kubernetesクラスター
を選択します。画面遷移後は クラスターに接続
を選択します。
ここでは新しく接続するAgentを用意するため、任意の名前を入力します。
入力後に 登録
を選択します。
次の画面でGitLabとAgentを接続するためのTokenが発行されます。またAgentをインストールするHelmコマンドも表示されるので、どこかにメモしておきます。
Token等の表示画面を閉じると、以下のようにAgentが追加されます。ここではまだインストールしていないので接続されていません。
次にHelmコマンドを使ってAgentをインストールします。再びAWS CloudShellに移動し、以下のようにコマンドを実行します。
#Helmインストール [cloudshell-user@ip-10-134-10-124 ~]$ wget https://get.helm.sh/helm-v3.15.2-linux-amd64.tar.gz [cloudshell-user@ip-10-134-10-124 ~]$ tar -zxvf helm-v3.15.2-linux-amd64.tar.gz [cloudshell-user@ip-10-134-10-124 ~]$ sudo cp -p linux-amd64/helm /usr/local/bin/ [cloudshell-user@ip-10-134-10-124 ~]$ helm version version.BuildInfo{Version:"v3.15.2", GitCommit:"1a500d5625419a524fdae4b33de351cc4f58ec35", GitTreeState:"clean", GoVersion:"go1.22.4"} #Agentインストール [cloudshell-user@ip-10-134-10-124 ~]$ helm repo add gitlab https://charts.gitlab.io "gitlab" has been added to your repositories [cloudshell-user@ip-10-134-10-124 ~]$ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "gitlab" chart repository Update Complete. ⎈Happy Helming!⎈ [cloudshell-user@ip-10-134-10-124 ~]$ helm upgrade --install eks-cluster gitlab/gitlab-agent \ > --namespace gitlab-agent-eks-cluster \ > --create-namespace \ > --set image.tag=v17.2.0-rc1 \ > --set config.token=glagent-S7WtgzAsTr6uQgzM-v6UnoZ8H4szid4oEwGxCa4VYpZzzUMxgw \ > --set config.kasAddress=wss://kas.gitlab.com Release "eks-cluster" does not exist. Installing it now. NAME: eks-cluster LAST DEPLOYED: Tue Jul 9 23:38:08 2024 NAMESPACE: gitlab-agent-eks-cluster STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Thank you for installing gitlab-agent. Your release is named eks-cluster. ## Changelog ### 1.17.0 - The default replica count has been increased from `1` to `2` to allow a zero-downtime upgrade experience. You may use `--set replicas=1` to restore the old default behavior. [cloudshell-user@ip-10-134-10-124 ~]$ #インストール後の確認 [cloudshell-user@ip-10-134-10-124 ~]$ kubectl get ns NAME STATUS AGE default Active 69m gitlab-agent-eks-cluster Active 31s kube-node-lease Active 69m kube-public Active 69m kube-system Active 69m [cloudshell-user@ip-10-134-10-124 ~]$ kubectl get pods -n gitlab-agent-eks-cluster NAME READY STATUS RESTARTS AGE eks-cluster-gitlab-agent-v2-5c79b4c4d5-cj9rx 1/1 Running 0 48s eks-cluster-gitlab-agent-v2-5c79b4c4d5-xh49j 1/1 Running 0 48s
Agentをインストール後にGitLab画面を見ると、Agentの接続ステータスが更新されていることを確認できます。
Agentをインストールしたので、GitLab CI/CDからデプロイしてみます。以下のように .gitlab-ci.yml
を修正し、先ほど使ったIAMロール等を使わないよう変更します。先ほどと比べてかなり量が削減されたことが分かります。
deploy: stage: deploy variables: KUBERNETES_AGENT_NAME: "eks-cluster" image: name: bitnami/kubectl:latest entrypoint: [''] script: - kubectl config use-context $CI_PROJECT_PATH:$KUBERNETES_AGENT_NAME - kubectl apply -f deployment.yaml
.gitlab-ci.yml
を変更するとCI/CDパイプラインが起動し、問題なければ成功します。
ログを見るとGitLabからEKSクラスターにアクセスする様子を確認できます。
検証後はEKSクラスターの削除と合わせてAgentの設定も削除します。