別の記事で永続ディスク(Persistent Disk)設定方法を紹介しましたが、永続ディスクの制限は複数ノードからマウントして同時に読み書きできない。
本記事では、NFS(Network File System)を利用して、その制限を解決する方法を紹介致します。
実施手順
- Persistent Disk作成
- Persistent Diskフォーマット
- Persistent Diskを使って、NFSサーバ立ち上げ
- NFSを使って、GKE中にストレージを作成
- GKEのストレージマウントのPod作成
最初の2つのステップ(Persistent Disk作成、とPersistent Diskフォーマット)は別の記事で紹介したため、それらの記事を参照してください。
※本手順はGCPとgcloudコマンドの利用経験があることが望ましいです。
ワークフォルダの構成
nfs_on_gke
├── README.md
├── cloudbuild.dummyjob.yaml
├── deployment
│ ├── dummy_job_01.deployment.yaml
│ └── dummy_job_02.deployment.yaml
├── dummyjob.Dockerfile
├── job
│ └── dummyjob.go
├── nfs-container.deployment.yaml
├── nfs-service.deployment.yaml
└── nfs-volume.yaml
1. Persistent Diskを使って、NFSサーバ立ち上げ
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-server
spec:
replicas: 1
selector:
matchLabels:
role: nfs-server
template:
metadata:
labels:
role: nfs-server
spec:
containers:
- name: nfs-server
image: gcr.io/google_containers/volume-nfs:latest
ports:
- name: nfs
containerPort: 2049
- name: mountd
containerPort: 20048
- name: rpcbind
containerPort: 111
securityContext:
privileged: true
volumeMounts:
- mountPath: /exports
name: mypvc
volumes:
- name: mypvc
gcePersistentDisk:
pdName: gce-nfs-disk
fsType: ext4
apiVersion: v1
kind: Service
metadata:
name: nfs-server
spec:
ports:
- name: nfs
port: 2049
- name: mountd
port: 20048
- name: rpcbind
port: 111
selector:
role: nfs-server
type: LoadBalancer
GKEにデプロイ
# クラスタ作成
gcloud container clusters create ds-gke-small-cluster \
--project ds-project \
--zone asia-northeast1-b \
--machine-type n1-standard-1 \
--num-nodes 1 \
--enable-stackdriver-kubernetes
# k8sコントロールツールをインストール
gcloud components install kubectl
kubectl version
# GKEのクラスタにアクセスするため、credentialsを設定
gcloud container clusters get-credentials --zone asia-northeast1-b ds-gke-small-cluster
# デプロイ NFSサーバ
kubectl apply -f nfs-container.deployment.yaml
# 外からアクセスするため、NFSサービスをデプロイ。クラスタ内でアクセスしかない場合、このステップをスキップ
kubectl apply -f nfs-service.deployment.yaml
2. NFSを使って、GKE中にストレージを作成
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-data-volume
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: "xx.xx.xx.xx"
path: "/exports"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs-data-volume
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 10Gi
ボリューム定義実施
# PersistentVolumeとPersistentVolumeClaimを作成。複数接続で読み書きできるaccessModes(ReadWriteMany)
kubectl apply -f nfs-volume.yaml
3. GKEのストレージマウントのPod作成
golangで簡単なジョブを作成する。
ジョブ処理はoutput-pathにサンプル10ファイルを作成する。予定は複数ジョブを稼働して、共有用のNFSにファイルを作成する。
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"time"
)
var jobName = flag.String("job-name", "", "specify job name")
var outputPath = flag.String("output-path", "", "specify output path for job")
func main() {
flag.Parse()
outlog("Dummy Job start ...")
for i := 0; i < 10; i++ {
unixtime := time.Now().Unix()
fileName := fmt.Sprint(*jobName, "_", unixtime, ".txt")
// make a file
file, err := os.Create(*outputPath + "/" + fileName)
if err != nil {
log.Fatal(err)
}
outlog("created a file: ", fileName)
// out some
file.WriteString("hello from " + *jobName)
file.Close()
// sleep to delay process
time.Sleep(2 * time.Second)
}
// list all file in path
outlog("List all files:")
files, err := ioutil.ReadDir(*outputPath)
if err != nil {
log.Fatal(err)
}
for _, file := range files {
outlog(file.Name())
}
outlog("Dummy Job finished.")
}
func outlog(args ...string) {
log.Println(*jobName+":", args)
}
FROM alpine:latest
WORKDIR /app
COPY ./dummyjob /app
steps:
# go build
- name: golang:1.12
dir: .
args: ['go', 'build', '-o', 'dummyjob', 'job/dummyjob.go']
env: ["CGO_ENABLED=0"]
# docker build
- name: 'gcr.io/cloud-builders/docker'
dir: .
args: [
'build',
'-t', '${_GCR_REGION}/${_GCR_PROJECT}/${_GCR_IMAGE_NAME}:${_GCR_TAG}',
'-f', 'dummyjob.Dockerfile',
'--cache-from', '${_GCR_REGION}/${_GCR_PROJECT}/${_GCR_IMAGE_NAME}:${_GCR_TAG}',
'.'
]
# push image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
args: ["push", '${_GCR_REGION}/${_GCR_PROJECT}/${_GCR_IMAGE_NAME}']
substitutions:
# # GCR region name to push image
_GCR_REGION: asia.gcr.io
# # Project ID
_GCR_PROJECT: project-abc123
# # Image name
_GCR_IMAGE_NAME: dummy-job
# # Image tag
_GCR_TAG: latest
イメージをビルドして、2つのジョブをデプロイする
# build dummy-job image on Container Registry
gcloud builds submit --config cloudbuild.dummyjob.yaml
# deploy job
kubectl apply -f deployment/dummy_job_01.deployment.yaml
kubectl apply -f deployment/dummy_job_02.deployment.yaml
2つのジョブはNFSを共有利用できることを稼働ログで確認できます。
NFSを共有して読み書きできることを確認できました。
本記事で利用したソースコードはこちら
https://github.com/itdevsamurai/gke/tree/master/nfs
最後まで読んで頂き、どうも有難う御座います!
DevSamurai 橋本