--- title: MicroK8s(というより任意のK8s)でIRSAを使えるようにするメモ tags: ["Kubernetes", "MicroK8s", "AWS", "OIDC", "IRSA"] categories: ["Dev", "CaaS", "Kubernetes", "MicroK8s"] date: 2025-06-18T16:40:05Z updated: 2025-06-19T00:10:52Z --- IAM Roles for Service Accounts (IRSA) は、KubernetesのServiceAccountに対してAWSのIAMロールを関連付ける機能です。これにより、PodからAWSサービスに対する認証をより安全に行うことができます。 EKSでは標準でIRSAが利用できますが、他のKubernetes環境でAPI Serverに追加の設定をすれば利用可能です。この記事では、MicroK8sでIRSAを有効にする手順を説明します。 **目次** ### OIDC Issuerの準備 IRSAを利用するためには、まずOIDC Issuerを準備する必要があります。 必要なパブリックエンドポイントは * OpenID Connect Discovery (`.well-known/openid-configuration`) * JSON Web Key Set (上記のJSONのうち`jwks_uri`で指定されるもの) だけなので、JSONファイルを静的に配置するだけでもIRSAで使用するためのOIDC Issuerとして機能します。 今回はGitHubレポジトリにこの2ファイルを置き、OIDC Issuerとして使用します。 まず、作業ディレクトリを作成します: ```bash mkdir oidc-issuer cd oidc-issuer echo private_key.pem > .gitignore ``` 次に、OIDC Issuerで使用する公開鍵・秘密鍵のペアを生成します: ```bash openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -outform PEM -pubout -out public.pem openssl pkcs8 -topk8 -inform PEM -in private.pem -out private_key.pem -nocrypt rm -f private.pem ``` 生成した公開鍵をJWKS形式に変換します。このために、専用のツールを使用します (要: Java 17+): ```bash git clone https://github.com/making/pem-to-jwks.git cd pem-to-jwks && ./mvnw clean package -DskipTests && cd - java -jar pem-to-jwks/target/pem-to-jwks-0.0.1-SNAPSHOT.jar echo pem-to-jwks >> .gitignore ``` 生成された`jwks.json`をGitHubリポジトリに公開します。: ```bash GITHIB_REPO=making/oidc-issuer git init git add -A git commit -m "Initial commit" git branch -M main git remote add origin git@github.com:${GITHIB_REPO}.git git push -u origin main ``` JWKSファイルがGitHub上で正しく公開されているか確認します: ```bash curl -s https://raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main/jwks.json ``` 次にOpenID Connect Discoveryの設定ファイルを作成します: ```bash mkdir -p .well-known cat << EOF > .well-known/openid-configuration { "response_types_supported": [ "id_token" ], "issuer": "https://raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main", "id_token_signing_alg_values_supported": [ "RS256" ], "subject_types_supported": [ "public" ], "jwks_uri": "https://raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main/jwks.json" } EOF ``` `.well-known/openid-configuration`をリポジトリに追加してプッシュします: ```bash git add -A git commit -m "Add OpenID Connect configuration" git push origin main ``` OpenID Connect Discoveryの設定が正しく公開されているか確認します: ```bash curl -s https://raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main/.well-known/openid-configuration ``` ### MicroK8sの設定 MicroK8sでIRSAを使用するために、APIサーバーの設定を変更します。まず、先ほど生成した鍵ファイルをMicroK8sのホスト上に場所にコピーします。ここでは以下のパスに配置したことにします。: * /opt/k8s/public.pem * /opt/k8s/private_key.pem 次に、MicroK8sのAPIサーバー設定を変更してこの鍵とIssuerを使ってService Account Tokenが生成されるようにします: ```bash GITHIB_REPO=making/oidc-issuer cat </dev/null | openssl x509 -fingerprint -sha1 -noout | sed 's/sha1 Fingerprint=//' | sed 's/://g') ``` 取得したフィンガープリントを使用してOIDC Identity Providerの設定ファイルを作成し、AWSに登録します: ```bash cat < oidc-provider.json { "Url": "https://raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main", "ClientIDList": [ "https://kubernetes.default.svc" ], "ThumbprintList": [ "${FINGERPRINT}" ] } EOF aws iam create-open-id-connect-provider --cli-input-json file://oidc-provider.json ``` ### IAMロールの作成 作成したOIDC Identity ProviderのARNを取得します: ```bash OIDC_PROVIDER_ARN=$(aws iam list-open-id-connect-providers --query "OpenIDConnectProviderList[?ends_with(Arn, 'raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main')].Arn" --output text) ``` 特定のServiceAccountに対してIAMロールを作成します。ここでは、`default`ネームスペースの`aws-cli` ServiceAccountを使用します: ```bash NAMESPACE=default SERVICE_ACCOUNT_NAME=aws-cli cat << EOF > k8s_${NAMESPACE}_${SERVICE_ACCOUNT_NAME}-trust-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "${OIDC_PROVIDER_ARN}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringLike": { "raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main:sub": "system:serviceaccount:${NAMESPACE}:${SERVICE_ACCOUNT_NAME}", "raw.githubusercontent.com/${GITHIB_REPO}/refs/heads/main:aud": "https://kubernetes.default.svc" } } } ] } EOF aws iam create-role --role-name k8s_${NAMESPACE}_${SERVICE_ACCOUNT_NAME} --assume-role-policy-document file://k8s_${NAMESPACE}_${SERVICE_ACCOUNT_NAME}-trust-policy.json ``` ### IAMポリシーの設定 作成したIAMロールに対して、S3へのアクセス権限を付与します。この例では、特定のプレフィックスを持つS3バケットへのフルアクセス権限を設定します: ```bash export BUCKET_PREFIX=k8s-${NAMESPACE}-${SERVICE_ACCOUNT_NAME} cat < s3-prefix-full-access-${BUCKET_PREFIX}-policy.json { "Version": "2012-10-17", "Statement": [ { "Sid": "FullAccessTo$(echo ${BUCKET_PREFIX} | sed 's/\-//g')Buckets", "Effect": "Allow", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::${BUCKET_PREFIX}-*", "arn:aws:s3:::${BUCKET_PREFIX}-*/*" ] }, { "Sid": "ListBucketsForConsoleAccess", "Effect": "Allow", "Action": [ "s3:ListAllMyBuckets", "s3:GetBucketLocation" ], "Resource": "*" } ] } EOF aws iam put-role-policy --role-name k8s_${NAMESPACE}_${SERVICE_ACCOUNT_NAME} --policy-name s3-prefix-full-access-${BUCKET_PREFIX} --policy-document file://s3-prefix-full-access-${BUCKET_PREFIX}-policy.json ``` ### テスト用Podの作成 IRSAの動作を確認するため、AWS CLIが実行可能なテスト用のPodを作成します: ```bash export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) export AWS_REGION=ap-northeast-1 cat < aws-cli.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: aws-cli namespace: default --- apiVersion: v1 kind: Pod metadata: name: aws-cli namespace: default spec: serviceAccountName: aws-cli containers: - name: aws-cli image: public.ecr.aws/aws-cli/aws-cli command: [ "sleep", "infinity" ] env: - name: AWS_REGION value: ${AWS_REGION} - name: AWS_ROLE_ARN value: arn:aws:iam::${AWS_ACCOUNT_ID}:role/k8s_default_aws-cli - name: AWS_WEB_IDENTITY_TOKEN_FILE value: /run/secrets/kubernetes.io/serviceaccount/token - name: AWS_ROLE_SESSION_NAME value: k8s-demo restartPolicy: Never --- EOF kubectl apply -f aws-cli.yaml ``` ### AWSサービスアクセスの動作確認 作成したPodに接続してIAMロールでAWSサービスに正しくアクセスできることを確認します: ```bash kubectl exec -ti aws-cli -c aws-cli -- bash ``` Pod内でAWSの認証情報を確認します。IRSAが正しく設定されていれば、IAMロールを使用した認証が行われます: ```bash aws sts get-caller-identity ``` 次のような出力が得られれば成功です: ```json { "UserId": "*********************:k8s-demo", "Account": "*****", "Arn": "arn:aws:sts::*****:assumed-role/k8s_default_aws-cli/k8s-demo" } ``` 設定したIAMポリシーが正しく動作することを確認します。まず、許可されたプレフィックスでS3バケットを作成してみます: ```bash aws s3 mb s3://k8s-default-aws-cli-demo ``` ``` make_bucket: k8s-default-aws-cli-demo ``` 次に、許可されていないプレフィックスでS3バケットを作成してみます: ```bash aws s3 mb s3://k9s-default-aws-cli-demo ``` ``` make_bucket failed: s3://k9s-default-aws-cli-demo An error occurred (AccessDenied) when calling the CreateBucket operation: User: arn:aws:sts::*****:assumed-role/k8s_default_aws-cli/k8s-demo is not authorized to perform: s3:CreateBucket on resource: "arn:aws:s3:::k9s-default-aws-cli-demo" because no identity-based policy allows the s3:CreateBucket action ``` 期待通りアクセスが拒否されました。これで、IAMポリシーによる権限制御が正しく機能していることが確認できました。 ``` exit ``` --- 本稿では、MicroK8sでIRSAを有効にする手順を説明しました。 試してはいませんが、Kindやその他、API Serverの設定が可能なKubernetes環境でも同様の手順でIRSAを有効にできるはずです。 API Serverの設定が許可されてないK8sを使用している場合は、本稿の手法は使えません。代わりにService Account Tokenを外向けに再発行する裏技を使うことで無理やりIRSAを実現することもできました。 興味のある方は https://github.com/categolj/jwt-reissuer のREADMEを参照してください。