Các bước chạy Kubernetes Volume (Phần 2)

cloudFun

Chào mừng đến với phần tiếp theo của bài viết “Các bước chạy Kubernetes cơ bản (Phần 1)” bao gồm những kiến thức cơ bản của Kubernetes Volume. Phần thứ 2 này sẽ bao gồm các nội dung sau:
Tìm hiểu về các đối tượng PersistentVolume, PersistentVolumeClaim và cách chúng hoạt động song song
Đi sâu vào các loại cung cấp trong Kubernetes: Static, Dynamic
Tìm hiểu về các lớp lưu trữ và cách chúng cung cấp năng lượng cho việc cung cấp động (dynamic provisioning)
Khám phá các ví dụ có liên quan

public-kubernetes-cloud-providers.png


Điều kiện tiên quyết:
Để làm theo các ví dụ trong bài viết này, cần chuẩn bị như sau:

Code đã có sẵn trên [URL='https://github.com/abhirockzz/kubernetes-in-a-nutshell/blob/master/volumes-2']GitHub
.

Tầm quan trọng của lưu trữ liên tục persistent storeage
Phần trước đã đề cập đến "Sự cần thiết của việc phải lưu trữ liên tục" với thực tế là vòng đời (lifecircle) của Kubernetes Volume được kết hợp chặt chẽ với Pod và các ứng dụng quan trọng cần lưu trữ ổn định, bền bỉ vượt xa Pod hoặc thậm chí là Node Pod đang chạy.

Một ví dụ về phương tiện lưu trữ dài hạn là các file system được nối mạng (NFS, Ceph, GlusterFS…) hoặc các tùy chọn dựa trên cloud, chẳng hạn như Azure Disk, Amazon EBS, GCE Persistent Disk…

Đây là cách có thể gắn NFS (Network File System - Hệ thống tệp mạng) vào Pod bằng cách sử dụng loại Volume nfs. Có thể trỏ đến một cá thể NFS hiện có bằng cách sử dụng thuộc tính server.

spec:
volumes:
- name: app-data
nfs:
server: nfs://localhost
path: "/"
containers:
- image: myapp-docker-image
name: myapp
volumeMounts:
- mountPath: /data
name: app-data


Trong bảng kê khai Pod ở trên, thông tin lưu trữ (đối với NFS) được chỉ định trực tiếp trong Pod (sử dụng phần volume). Điều này ngụ ý rằng các developer cần biết chi tiết về máy chủ NFS, bao gồm cả vị trí của nó… Chắc chắn có phạm vi để cải thiện ở đây và giống như hầu hết mọi thành phần trong phần mềm, nó có thể được thực hiện với một mức độ gián tiếp hoặc trừu tượng khác bằng cách sử dụng các khái niệm về Persistent Volume và Persistent Volume Claim.

Ý tưởng chính xoay quanh "sự phân biệt về nhiệm vụ" và tách rời việc tạo/quản lý lưu trữ khỏi yêu cầu/ điều kiện của nó. Đây là nơi mà PersistentVolumeClaim PersistentVolume phát huy tác dụng:
  • Một PersistentVolumeClaim cho phép người dùng yêu cầu lưu trữ liên tục theo kiểu "khai báo" bằng cách chỉ định các yêu cầu (ví dụ: khối lượng lưu trữ) như một phần của thông số PersistentVolumeClaim.
  • Một PersistentVolume bổ sung cho PersistentVolumeClaim và đại diện cho phương tiện lưu trữ trong cluster Kubernetes. Việc cung cấp lưu trữ thực tế (ví dụ: tạo Azure Disk bằng Azure CLI, Azure port…) và tạo PersistentVolume trong cluster thường được thực hiện bởi admin hoặc trong trường hợp cung cấp Dynamic provisioning, bởi chính Kubernetes (phần này sẽ được phân tích chi tiết ở dưới)
Ngoài việc tách rời và phân tách nhiệm vụ, nó cũng cung cấp tính linh hoạt và tính di động. Ví dụ, khi có nhiều môi trường như dev, test, prodiction…, với PersistentVolume, chỉ cần khai báo các yêu cầu lưu trữ một lần (ví dụ: "ứng dụng của tôi cần 5 GB") và chuyển đổi phương tiện lưu trữ thực tế tùy thuộc vào môi trường, nhờ có PersistentVolumeClaim - điều này có thể là một local disk (đĩa cục bộ) trong môi trường dev, một ổ cứng tiêu chuẩn HDD trong test và SSD trong production. Điều tương tự cũng xảy ra đối với tính di động trong trường hợp multi-cloud, theo đó có thể sử dụng cùng một thông số yêu cầu nhưng chuyển đổi PersistentVolume theo nhà cung cấp cloud.

Các phần sắp tới của bài viết sẽ bao gồm các ví dụ để giúp củng cố các khái niệm này.

Phân tích chi tiết
PersistentVolumeClaim
Một PersistentVolumeClaim chỉ đơn giản là một thành phần Kubernetes khác (tương tự như Pod, Deployment, Configmap…). Tham khảo ví dụ dưới đây:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-volume-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: volume-class


Phần quan trọng nhất là các thông số dẫn chiếu tới một thành phần PersistentVolumeClaimSpec. Đây chính là nơi định nghĩa điều kiện lưu trữ (storeage requirement). Các thuộc tính đáng chú ý:
  • resources – resources tối thiểu mà volume yêu cầu
  • accessModes – cách mà volume được gắn kết (các giá trị hợp lệ là ReadWriteOnce, ReadOnlyMany, ReadWriteMany)
  • storageClassName – tên của StorageClass (StorageClass sẽ được giải thích ở phần sau)
PersistentVolumeClaim có các thuộc tính khác như apiVersion, kind, metadata, status. Đó là “mẫu số chung” cho tất cả các thành phần Kubernetes.

PersistentVolume
Đây là hiển thị của các thông số PersistentVolum đặc trưng:
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pvc
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: volume-class
nfs:
server: nfs://localhost
path: "/"


Tương tự như PersistentVolumeClaim, thông số (thành phần PersistentVolumeSpec) là phần quan trọng nhất của một PersistentVolume, cụ thể:
  • Nhà cung cấp hoặc lưu trữ cụ thể - như nfs, azureDisk, gcePersistentDisk, awsElasticBlockStore… cho phép cung cấp thông tin cụ thể cho phương tiện lưu trữ (NFS, Azure Disk…)
  • accessModes - cách gắn volume
  • capacity - thông tin về tài nguyên và công suất của persistent volume
  • StorageClassName - tên của StorageClass mà persistent volume này thuộc về
  • persistentVolumeReclaimPolicy – là phần xử lý khi xảy ra trường hợp PersistentVolumeClaim tương ứng bị xóa. Các tùy chọn là Retain (giữ lại), Delete Recycle
Để luyện tập kiến thức về Persistent volume, hãy khám phá các thuộc tính nodeAffinity, volumeMode, mountOptions để xác định vai trò của chúng.

PersistentVolume có các thuộc tính khác như apiVersion, kind, metadata, status. Đó là “mẫu số chung” cho tất cả các thành phần Kubernetes.


Làm thế nào để các thành phần làm việc với nhau?
Có hai cách để có thể sử dụng các cấu trúc này để có được dung lượng lưu trữ cho các ứng dụng Kubernetes - StaticDynamic

Trong chế độ "Static", người dùng cần quan tâm đến việc cung cấp bộ nhớ thực (cloud, tại chỗ…) và sau đó tham chiếu nó trong thông số Pod (ứng dụng)

Theo cách "Dynamic", Kubernetes thực hiện rất nhiều việc cung cấp lưu trữ cũng như việc tạo ra PersistentVolume. Tất cả những gì cần làm là cung cấp các yêu cầu lưu trữ bằng cách tạo và sau đó tham chiếu một PersistentVolumeClaim trong thông số Pod.

Cung cấp Dynamic provisioning nên được bật trên một cluster - trong hầu hết các nhà cung cấp, việc này được thực hiện linh động.


Static provisioning
Có hai cách để sử dụng static provisioning:
Một là cung cấp lưu trữ và dử dụng thông tin của nó trực tiếp trong thông số Pod (Pod spec)
93k04uba8lp7ii1ym220.jpg

Như đã đề cập ở phần 1 về các giới hạn của cách tiếp cận đã đề cập. Tại phần 2 này, lời khuyên đưa ra nên thử hướng dẫn tuyệt vời về cách "Tạo và sử dụng volume thủ công với các Azure Disk trong Azure Kubernetes Service (AKS)". Đây là hiển thị nếu làm theo cách này. Bên cạnh ưu điểm là tiện lợi thì hướng dẫn này còn tồn tại một số hạn chế.
spec:
containers:
- image: nginx
name: mypod
volumeMounts:
- name: azure
mountPath: /mnt/azure
volumes:
- name: azure
azureDisk:
kind: Managed
diskName: myAKSDisk
diskURI: /subscriptions/<subscriptionID>/resourceGroups/MC_myAKSCluster_myAKSCluster_eastus/providers/Microsoft.Compute/disks/myAKSDisk


Trong cách tiếp cận thứ hai, thay vì tạo disk và cung cấp chi tiết về nó (azureDisk trong trường hợp này), cần gói gọn thông tin đó trong PersistentVolume. Sau đó, tạo một PersistentVolumeClaim và tham chiếu nó từ thông số Pod và nhường nó cho Kubernetes để làm phù hợp với yêu cầu lưu trữ với những gì có sẵn.
lzmd5fhs8n79f1zrnc64.jpg

Đây là đoạn trích để làm rõ ý tưởng trên.

spec:
volumes:
- name: app-data
persistentVolumeClaim:
claimName: data-volume-claim

Hãy tưởng tượng nó như việc tái cấu trúc một đoạn logic thành phương thức riêng, theo đó lấy một loạt thông tin yêu cầu lưu trữ và đưa nó ra dưới dạng PersistentVolume (tương tự như một phương thức).

Dynamic provisioning
Như đã đề cập trước đó, với Dynamic Provisioning, có thể giảm tải tất cả các công việc nặng cho Kubernetes. Trước khi đi sâu vào phân tích, đây là một ảnh chụp nhanh về cách thức hoạt động của nó.
29x4vq2sb0cg4c62fw5m.jpg

Một trong những khái niệm quan trọng liên quan đến dynamic privisioning là StorageClass.

Storage Class
Tương tự như PersistentVolume đóng gói các chi tiết lưu trữ, StorageClass cung cấp một cách để mô tả "các lớp" lưu trữ. Để sử dụng StorageClass, tất cả những gì cần làm là tham khảo nó từ PersistentVolumeClaim.
Đây là một ví dụ về StorageClass cho Azure Disk
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
labels:
kubernetes.io/cluster-service: "true"
name: default
parameters:
cachingmode: ReadOnly
kind: Managed
storageaccounttype: Standard_LRS
provisioner: kubernetes.io/azure-disk
reclaimPolicy: Delete
volumeBindingMode: Immediate


Các tham số (parameters) chính trong thông số StorageClass là:
  • Provisioner - volume plugin (chi tiết cần tuân theo) quy định việc lưu trữ thực tế
  • Parameters - cặp key value tùy chỉnh có thể được sử dụng làm người cung cấp khi chạy
  • ReclaimPolicy - chính sách đòi lại mà PersistentVolume được tạo (Xóa PV đã bị xóa khi PVC bị xóa, Retain để giữ PV)
  • VolumeBindingMode - cho biết cách cung cấp và ràng buộc PersistentVolumeClaims (giá trị hợp lệ là Immediate WaitForFirstConsumer)

Thông tin trong các tham số này (và một vài thông tin khác như allowVolumeExpansion, allowTopology, mountOptions) được sử dụng runtime để cung cấp dynamic provisioning và tạo PersistentVolume tương ứng.
StorageClass cũng có các thuộc tính khác - apiVersion, kind, metadata. Đây là các mẫu chung cho tất cả các đối tượng Kubernetes.

Nếu một tham số paramerter không được thông qua, value mặc định sẽ được sử dụng.

Chú ý Storage Class mặc định
Một StorageClass có thể được đánh dấu là mặc định sao cho nó được sử dụng (để cung cấp dynamic provisioning) khi một thuộc tính storageClass không được cung cấp trong PersistentVolumeClaim.
Azure Kubernetes Service giúp cho việc cung cấp dynamic provisiong dễ dàng bằng cách thêm vào 2 lớp lưu trữ. Có thể kiểm tra tương tự bằng cách chạy kubectl để lấy lệnh storageclass.
NAME PROVISIONER AGE
default (default) kubernetes.io/azure-disk 6d10h
managed-premium kubernetes.io/azure-disk 6d10h


Thực hành: cung cấp Dynamic provisioning
Để thực hiện cung cấp Dynamic provisioning, cần sử dụng Azure Kubernetes Service. Tạo một PersistentVolumeClaim và một ứng dụng cơ bản (Deployment) dẫn chiếu đến claim đó và theo dõi các thành phần chạy thực tế.
Nếu chưa có tài khoản Azure account, đăng ký miễn phí tại đây.

Thiết lập Kurbernetes
Chỉ cần một lệnh để thiết lập một Kurbernettes cluster trên Azure, nhưng trước đó cần tạo một resource group.
export AZURE_SUBSCRIPTION_ID=[to be filled]
export AZURE_RESOURCE_GROUP=[to be filled]
export AZURE_REGION=[to be filled] (e.g. southeastasia)

Chuyển sang subscription và invoke lệnh az aks create
az account set -s $AZURE_SUBSCRIPTION_ID
az group create -l $AZURE_REGION -n $AZURE_RESOURCE_GROUP

Đến đây, có thể gọi az aks create để tạo cluser mới. Để đơn giản hơn, sử dụng lệnh dưới để tạo một node cluster đơn. Hãy thay đổi thông số theo theo yêu cầu của trường hợp sử dụng.
export AKS_CLUSTER_NAME=[to be filled]
az aks create --resource-group $AZURE_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --node-count 1 --node-vm-size Standard_B2s --node-osdisk-size 30 --generate-ssh-keys

Nhận thông tin xác thực (credentials) AKS cluster bằng cách sử lệnh az aks get-credentials. Theo đó kubectl sẽ trỏ đến cluster mới. Có thể xác nhận tương tự
az aks get-credentials --resource-group $AZURE_RESOURCE_GROUP --name $AKS_CLUSTER_NAME
kubectl get nodes


Nếu quan tâm đến Kubernetes và Container sử dụng Azure, cần tìm hiểu các tài liệu sau về cách sử dụng quickstarts, hướng dẫn và code mẫu để làm quen với service này. Ngoài ra có thể tham khảo thêm các tài liệu sau:

Tạo PersistentVolumeClaim theo App deployment
Đây là các thông số PersistentVolumeClaim sẽ được sử dụng
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: azure-disk-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi

Lưu ý rằng PersistenceVolumeClaim không sử dụng storageClass trước đó để đảm bảo lớp lưu trữ store class default không được sử dụng cho cung cấp dynamic provisioning.
Tạo PersistenceVolumeClaim
kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/volumes-2/azure-disk-pvc.yaml
Lúc này, hiển thị sẽ như sau (STATUS=Pending)
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
azure-disk-pvc Pending default 11s

Sau đó, hiển thị sẽ đổi sang (STATUS = Bound) vì Azure Disk và PersistenceVolumeClaim được tạo tự động.
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
azure-disk-pvc Bound pvc-7b0e2911-df74-11e9-93ab-025752f370d3 2Gi RWO default 36s


Có thể kiểm tra PersistenceVolume được cung cấp dynamic provisioning bằng lệnh kubectl get pv
Xác nhận Azure Disk đã được tạo
AKS_NODE_RESOURCE_GROUP=$(az aks show --resource-group $AZURE_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query nodeResourceGroup -o tsv)
az disk list -g $AKS_NODE_RESOURCE_GROUP

Phần tag sẽ hiển thị tương tự như sau
"tags": {
"created-by": "kubernetes-azure-dd",
"kubernetes.io-created-for-pv-name": "pvc-7b0e2911-df74-11e9-93ab-025752f370d3",
"kubernetes.io-created-for-pvc-name": "azure-disk-pvc",
"kubernetes.io-created-for-pvc-namespace": "default"
}


Tạo app deployment
kubectl apply -f https://raw.githubusercontent.com/abhirockzz/kubernetes-in-a-nutshell/master/volumes-2/app.yaml
Để test, có thể sử dụng ứng dụng Go cơ bản. Những gì ứng dụng làm là đẩy log statments vào một file logz.out trong /mnt/logs. Đây là đường dẫn được gắn vào Pod.
Đợi vài phút để deployment ở trạng thái Running.
kubectl get pods -l=app=logz
NAME READY STATUS RESTARTS AGE
logz-deployment-59b75bc786-wt98d 1/1 Running 0 15s


Để xác nhận, kiểm tra mnt/logs/logz.out trong Pod.
kubectl exec -it $(kubectl get pods -l=app=logz --output=jsonpath={.items..metadata.name}) -- tail -f /mnt/logs/logz.out
Các log (chỉ gồm timestamp) sẽ hiển thị mỗi 3 giây
2019-09-25 09:17:11.960671937 +0000 UTC m=+84.002677518
2019-09-25 09:17:14.961347341 +0000 UTC m=+87.003352922
2019-09-25 09:17:17.960697766 +0000 UTC m=+90.002703347
2019-09-25 09:17:20.960666399 +0000 UTC m=+93.002671980


Đến đây đã hoàn thành các bước thực hiện trên Kubernetes Volume. Đón đọc thêm các bài viết mới nhất tại Cloudfun.

Nguồn: https://dev.to/
 
Top