Amazon EKS on AWS Secrets and Configuration Provider (ASCP) 

# ASCP

AWS Secrets Manager で管理しているシークレットの情報を Amazon EKS の Pod から取得させるには、**AWS Secrets and Config Provider (ASCP)** を使用します。

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/integrating_csi_driver.html


# 動作環境

- ASCP は EC2 ノードグループを実行する EKS 1.17 以降で動作します。
- *Fargate ノードグループはサポートされていません。*


# 設定

## クラスターの準備

クラスターを準備

```ClusterConfig.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: cluster-test
  region: ap-northeast-1
  version: "1.27"

iam:
  withOIDC: true

nodeGroups:
  - name: node-ec2
    privateNetworking: true
    instanceType: t3.small
    desiredCapacity: 1
    minSize: 1
    maxSize: 2

fargateProfiles:
  - name: node-fargate
    selectors:
      - namespace: default
```

```
eksctl create cluster -f ClusterConfig.yaml
```

クラスターが作成されたことを確認

```
eksctl get cluster
```

```
NAME            REGION          EKSCTL CREATED
cluster-fargate ap-northeast-1  True
```

ノードを確認

```
kubectl get node
```

```
NAME                                                STATUS   ROLES    AGE   VERSION
ip-192-168-138-24.ap-northeast-1.compute.internal   Ready    <none>   60m   v1.27.7-eks-e71965b
```

## secrets-store-csi-driver と ASCP を インストールする

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/integrating_csi_driver.html#integrating_csi_driver_install

secrets-store-csi-driver と ASCP を Helm を使用してインストールします。

```
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm install -n kube-system csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver

helm repo add aws-secrets-manager https://aws.github.io/secrets-store-csi-driver-provider-aws
helm install -n kube-system secrets-provider-aws aws-secrets-manager/secrets-store-csi-driver-provider-aws
```

## テスト用の Secrets Manager のシークレットの作成

テスト用の Secrets Manager のシークレットを準備しておきます。

```
aws --region ap-northeast-1 secretsmanager  create-secret --name Secret001 --secret-string '{"username":"user001", "password":"pass001"}'
```

```
{
    "ARN": "arn:aws:secretsmanager:ap-northeast-1:１２３４５６７８９０１２:secret:Secret001-Yqs0Iu",
    "Name": "Secret001",
    "VersionId": "b8fe16a4-b03d-43e1-9196-0c9f1081420a"
}
```

## Pod のリソースポリシーの作成

Pod が Secret Manager のシークレットにアクセスするためのリソースポリシーを作成します。

```
POLICY_ARN=$(aws --region ap-northeast-1 --query Policy.Arn --output text iam create-policy --policy-name nginx-deployment-policy --policy-document '{
    "Version": "2012-10-17",
    "Statement": [ {
        "Effect": "Allow",
        "Action": ["secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret"],
        "Resource": ["arn:aws:secretsmanager:ap-northeast-1:１２３４５６７８９０１２:secret:Secret001-Yqs0Iu"]
    } ]
}')
```

## サービスアカウントの作成

Pod が使用するサービスアカウントを作成し、リソースポリシーをそのサービスアカウントに関連付けます。

```
eksctl create iamserviceaccount --name nginx-deployment-sa --region=ap-northeast-1 --cluster cluster-test --attach-policy-arn "$POLICY_ARN" --approve --override-existing-serviceaccounts
```

ちなみにサービスアカウントについては、[こちら](https://qiita.com/leomaro7/items/416f6dee4ab3b0b31550) の記事も参考に。

サービスアカウントが作成されていることの確認

```
kubectl get sa 
```

```
NAME                  SECRETS   AGE
nginx-deployment-sa   0         4m11s
```

## SecretProviderClass

[SecretProviderClass](https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/integrating_csi_driver_SecretProviderClass.html) を作成して、Pod にマウントするシークレットを指定します。
ここでは、先程 Secret Manager で作成したシークレット Secret001 を指定します。

```ExampleSecretProviderClass.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass

metadata:
  name: nginx-deployment-aws-secrets

spec:
  provider: aws
  parameters:
    objects: |
        - objectName: "Secret001"
          objectType: "secretsmanager"
```

```
kubectl apply -f ExampleSecretProviderClass.yaml 
```

```
secretproviderclass.secrets-store.csi.x-k8s.io/nginx-deployment-aws-secrets created
```

SecretProviderClass の確認

```
kubectl get SecretProviderClass
```

```
NAME                           AGE
nginx-deployment-aws-secrets   70s
```

# Pod のデプロイ

```ExampleDeployment.yaml
kind: Service
apiVersion: v1

metadata:
  name: nginx-deployment
  labels:
    app: nginx

spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

---
apiVersion: apps/v1
kind: Deployment

metadata:
  name: nginx-deployment
  labels:
    app: nginx

spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      serviceAccountName: nginx-deployment-sa
      volumes:
      - name: secrets-store-inline
        csi:
          driver: secrets-store.csi.k8s.io
          readOnly: true
          volumeAttributes:
            secretProviderClass: "nginx-deployment-aws-secrets"
      containers:
      - name: nginx-deployment
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: secrets-store-inline
          mountPath: "/mnt/secrets-store"
          readOnly: true
```

まず、わざと fargate にデプロイし、Pod の詳細を確認してみます。

```
kubectl apply -f ExampleDeployment.yaml
```

```
kubectl describe pod/nginx-deployment-7bb889c877-2fx28 
```

```
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  6m6s  fargate-scheduler  Pod not supported on Fargate: volumes not supported: secrets-store-inline is of an unsupported volume Type
```

では、fargateprofile　は削除し、EC2 ノードで動作させるように再度、apply してみます。

```
eksctl delete fargateprofile  --name node-fargate --cluster cluster-fargate
```

```
kubectl apply -f ExampleDeployment.yaml
```

```
kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7bb889c877-6krlq   1/1     Running   0          4h9m
nginx-deployment-7bb889c877-988zf   1/1     Running   0          4h9m
```

Pod のデプロイが完了したので動作確認してみます。

```
kubectl exec -it nginx-deployment-7bb889c877-6krlq

cat /mnt/secrets-store/Secret001 
    {"username":"user001", "password":"pass001"}
```