EKSクラスタの構築
AWSの公式ドキュメントではCloudFormationなどを駆使して、EKSクラスタを構築する方法が記載されていますが、ここではそれらを隠蔽してくれるeksctlを使います。
eksctlのインストール
$ brew tap weaveworks/tap
$ brew install weaveworks/tap/eksctl
クラスタの作成
ここではp2.xlarge * 1のクラスタを構築します。
$ eksctl create cluster --name gpu-cluster --region ap-northeast-1 --nodes 1 --nodes-min 1 --nodes-max 1 --node-type p2.xlarge --version=1.11
NVIDIA device pluginのインストール
GPUのスケジューリングを有効にするためにNVIDIA device pluginをインストールします。
$ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v1.11/nvidia-device-plugin.yml
(Optional) GPU Mutating Webhookの追加
nvidia.com/gpuリソースを指定しないコンテナからGPUが見えてしまう問題のために、Mutating Admission Webhookを追加します。
クライアントCAの取得・アップロード
EKSではGKEなどと違い、kube-systemのConfigMap:extension-apiserver-authenticationにclient-ca-fileが入っていないので入れておきます。
$ aws eks describe-cluster \
--region=ap-northeast-1 \
--name=gpu-cluster \
--output=text \
--query 'cluster.{certificateAuthorityData: certificateAuthority.data, endpoint: endpoint}' | \
awk '{print $1}' | \
base64 -D
で出力されたCAをConfigMapに入れます。
$ kubectl edit configmap extension-apiserver-authentication -n kube-system
apiVersion: v1
data:
+ client-ca-file: |
+ -----BEGIN CERTIFICATE-----
+ xxxx
+ -----END CERTIFICATE-----
requestheader-allowed-names: '["front-proxy-client"]'
requestheader-client-ca-file: |
-----BEGIN CERTIFICATE-----
xxxx
-----END CERTIFICATE-----
requestheader-extra-headers-prefix: '["X-Remote-Extra-"]'
requestheader-group-headers: '["X-Remote-Group"]'
requestheader-username-headers: '["X-Remote-User"]'
kind: ConfigMap
gpu-mutating-webhookのデプロイ
$ git clone https://github.com/takmatsu/gpu-mutating-webhook.git
$ cd gpu-mutating-webhook
$ kubectl apply -f deployment/namespace.yaml
$ ./deployment/webhook-create-signed-cert.sh
$ cat deployment/mutatingwebhook.yaml | \
deployment/webhook-patch-ca-bundle.sh > \
deployment/mutatingwebhook-ca-bundle.yaml
$ kubectl apply -f deployment/deployment.yaml
$ kubectl apply -f deployment/service.yaml
$ kubectl apply -f deployment/mutatingwebhook-ca-bundle.yaml
(Optional) EFS Provisonerの追加
EKSではデフォルトでPersistent VolumeとしてAWSElasticBlockStoreが使えますが、ReadWriteOnceのみしか使えないため、ReadWriteManyなどが使いたい場合はEFS Provisonerを使用するとRWXなPVがDynamic Provisioningできます。
EFSの作成
aws efs create-file-system --creation-token gpu-nfs --region ap-northeast-1
EFSにSecurityGroupの設定
- EFSのIDの確認
$ aws efs describe-file-systems
- サブネットの確認
$ aws ec2 describe-subnets --filters Name=tag:Name,Values=\*gpu-cluster\* Name=tag:aws\:cloudformation\:logical-id,Values=\*Public\* --query 'Subnets[].{SubnetId: SubnetId}' --output text
- セキュリティグループの確認
$ aws ec2 describe-security-groups --filters Name=group-name,Values=\*gpu-cluster\* --query 'SecurityGroups[].{GroupName: GroupName, GroupId: GroupId}' --output text | grep ClusterSharedNodeSecurityGroup | awk {'print $1'}
- 設定
$ aws efs create-mount-target --file-system-id fs-****** --subnet-id subnet-****** --security-groups sg-******
×サブネット分
efs-provisonerのデプロイ
$ git clone https://github.com/kubernetes-incubator/external-storage.git
$ cd external-storage/aws/efs
- namespaceの作成
$ NAMESPACE=efs-provisioner
$ kubectl create namespace $NAMESPACE
- RBACの設定
$ sed -i '' "s/namespace:.*/namespace: $NAMESPACE/g" ./deploy/rbac.yaml
$ kubectl apply -f deploy/rbac.yaml -n $NAMESPACE
- manifestの編集
$ vi deploy/manifest.yaml
@@ -4,8 +4,8 @@ kind: ConfigMap
metadata:
name: efs-provisioner
data:
- file.system.id: yourEFSsystemid
- aws.region: regionyourEFSisin
+ file.system.id: fs-*****
+ aws.region: ap-northeast-1
provisioner.name: example.com/aws-efs
dns.name: ""
---
@@ -53,7 +53,7 @@ spec:
volumes:
- name: pv-volume
nfs:
- server: yourEFSsystemID.efs.yourEFSregion.amazonaws.com
+ server: fs-*****.efs.ap-northeast-1.amazonaws.com
path: /
- デプロイ
kubectl apply -f deploy/manifest.yaml -n $NAMESPACE
その他
- GPUインスタンスは高いので、使わないときにワーカーノードに使っているAuto Scaling Groupを0にするLambdaなどを書くといいかもしれない、K8sを使っているとステートを持つ情報はコントロールプレーンか外部ストレージに入っているので戻すと自動復旧する(はず)