Kubernetes: ServiceAccount з AWS IAM Role для Kubernetes Pod

Автор |  25/11/2022
 

Маємо Grafana Loki для логів, до подів якої треба підключити AWS IAM Role з AWS IAM Policy, котра дає доступ до AWS S3 бакету, в якому будуть зберігатися чанки та індекси (про сетап самої Loki з AWS S3 трохи пізніше окремим постом).

IAM ролі для Kubernetes подів працють тим самим чином, як ми це робимо, коли підключаємо IAM-ролі до ЕС2-інстансів – процес всередині пода виконує запит до AWS API, а AWS SDK чи AWS CLI, за допомогою якого робиться запит, виконує запит AssumeRole, якому передається сама IAM Role (див. AWS: ротация ключей IAM пользователей, EC2 IAM Roles и Jenkins).

Щоб перевірити, як воно взагалі буде працювати в Кубері – створимо тестову IAM Role, ServiceAccount з аннотацією цієї ролі, та запустимо под з цим ServiceAccount.

Забігаючи наперед – в самій Локі це все одно працює через якусь альтернативну реальність, тобто навіть коли їй підключаєш вже протестований ServiceAccount – вона валиться з помилками. Треба буде копати.

Документація – IAM roles for service accounts.

Перевірка IAM OIDC identity provider

EKS кластер розгорнутий за допомогою Terraform модуля aws_eks_cluster, і OpenID Connect (OIDC) provider вже має бути налаштований.

Заходимо на сторінку кластера, знаходимо OpenID Connect provider URL:

Або з консолі:

[simterm]

$ aws --profile development --region us-west-2 eks describe-cluster --name dev_data_services --query "cluster.identity.oidc.issuer" --output text
https://oidc.eks.us-west-2.amazonaws.com/id/537***A10

[/simterm]

Копіюємо URL без https://, та перевіряємо в IAM > Identity providers:

Окей, тут все є.

Створення Kubernetes ServiceAccount з AWS IAM role

Для початку, створимо IAM policy, яка дає права на AWS S3 bucket, потім IAM Role з TrustedPolicy, яка дозволяє виконувати AssumeRole, використовуючи OIDC identity provider (IDP) кластеру.

AWS IAM policy

Створюємо тестову політику:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::development-dev-loki-object-store",
                "arn:aws:s3:::development-dev-loki-object-store/*"
            ]
        }
    ]
}

Додаємо її в AWS IAM:

[simterm]

$ aws --profile development iam create-policy --policy-name test-iam-sa-pod-policy --policy-document file://test-iam-sa-pod-policy.json

[/simterm]

Переходимо до ролі.

AWS IAM role та TrustedPolicy

Знаходимо ARN нашого Identity Provier:

URL OIDC identity provider вже знаходили раніше:

[simterm]

$ aws --profile development --region us-west-2 eks describe-cluster --name dev_data_services --query "cluster.identity.oidc.issuer" --output text 
https://oidc.eks.us-west-2.amazonaws.com/id/537***A10

[/simterm]

Створення IAM Role з AWS CLI

Створюємо файл з TustedPolicy, в Principal якої вказуємо ARN IDP, а в Condition – URL OIDC кластеру, якому дозволяємо виконувати запит до sts.amazonaws.com:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::638***021:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/537***A10"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.us-west-2.amazonaws.com/id/537***A10:aud": "sts.amazonaws.com"
                }
            }
        }
    ]
}

Створюємо роль, якій передаємо цю TrustedPolicy:

[simterm]

$ aws --profile development  iam create-role --role-name test-iam-sa-pod-role --assume-role-policy-document file://test-iam-sa-role-trusted-policy.json

[/simterm]

Підключаємо їй IAM Policy з правами на S3, яку створили раніше:

[simterm]

$ aws --profile development iam attach-role-policy --role-name test-iam-sa-pod-role --policy-arn=arn:aws:iam::638***021:policy/test-iam-sa-pod-policy

[/simterm]

Створення IAM Role з AWS Console

Або робимо теж саме через адмінку Амазона – вибираємо тип Web identity, Identity Provider кластеру та Audience:

Додаємо IAM Policy для S3:

Зберігаємо:

Копіюємо ARN ролі:

Створення Kubernetes ServiceAccount

Створюємо маніфест ServiceAccount-у, в анотації якого вказуємо ARN ролі, яку створили:

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-iam-sa-pod-service-account
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::638***021:role/test-iam-sa-pod-role

І переходимо до пода.

Запуск Kubernetes Pod з ServiceAccount

Додаємо опис поду, якому через serviceAccountName підключаємо ServiceAccount, тож повністю маніфест буде виглядати так:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-iam-sa-pod-service-account
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::638***021:role/test-iam-sa-pod-role
---
apiVersion: v1
kind: Pod
metadata:
  name: test-iam-sa-pod
  labels:
    app: test-iam-sa-app
spec:
  containers:
    - name: test-iam-sa
      image: amazon/aws-cli
      command: [ "/bin/bash", "-c", "--" ]
      args: [ "while true; do sleep 30; done;" ]
  serviceAccountName: test-iam-sa-pod-service-account

В поді використовємо docker-образ з AWS CLI, якому передаємо sleep, щоб він працював після запуску.

Деплоїмо ServiceAccount та Pod:

[simterm]

$ kk apply -f test-iam-sa-pod.yaml 
serviceaccount/test-iam-sa-pod-service-account created
pod/test-iam-sa-pod created

[/simterm]

Заходимо в нього:

[simterm]

$ kk exec -ti test-iam-sa-pod -- bash

[/simterm]

І перевіряємо доступ до корзини:

[simterm]

bash-4.2# aws s3 ls development-dev-loki-object-store
                           PRE test/

[/simterm]

Готово.