iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 28
0
DevOps

Kubernetes的30天養成計劃系列 第 28

[Day28] k8s應用篇(二):EBS和EFS的使用

前言

今天我們來看個整合性例子,講述了Wordpress與MySQL的結合,同樣的做法分為兩種,第一種是透過EBS去實作它,第二種方法是透過EFS去實作它,那麼接下來我們就開始吧!

由於操作會用到PV,我們這裡小複習一下

複習傳送門:

EBS

這裡之前有提過,我們複習下:

Elastic Block Store (EBS) 是易於使用的高效能區塊儲存服務,專為與Elastic Compute Cloud (EC2) 搭配使用而設計,能以任何規模同時用於輸送量和交易密集型工作負載。各種工作負載 (如關聯式和非關聯式資料庫、企業應用程式、容器化的應用程式、大數據分析引擎、檔案系統和媒體工作流程) 廣泛部署在 EBS 上。

這邊示範如何透過設置EBS達到實作Wordpress結合MySQL的效果。

1. 新增虛擬集群(Namespace)

檢查既有的Namespace

$kubectl get namespaces
NAME          STATUS   AGE
default       Active   17m
kube-public   Active   17m
kube-system   Active   17m

新增一個Namespace

$kubectl create namespace ns-eks
namespace/ns-eks created

檢查既有的Namespace

$kubectl get namespaces
NAME          STATUS   AGE
default       Active   18m
kube-public   Active   18m
kube-system   Active   18m
ns-eks        Active   13s

針對該Namespace,也就是ns-eks,可以發現他有Secret,它這裡有token供Dashboard使用

$kubectl get secret -n ns-eks
NAME                  TYPE                                  DATA   AGE
default-token-vkv4l   kubernetes.io/service-account-token   3      3m17s

2. 新增實體卷(physical volume)

檢查StorageClass

$kubectl get storageclasses --all-namespaces
NAME            PROVISIONER             AGE
gp2 (default)   kubernetes.io/aws-ebs   26m

發現到有gp2,而且這個位置是在我們新增的Namespace上:ns-eks

$kubectl get storageclasses -n ns-eks
NAME            PROVISIONER             AGE
gp2 (default)   kubernetes.io/aws-ebs   28m

如果你發現沒有,可以參考下面新增

$vim gp2-storage-class.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: gp2
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
mountOptions:
  - debug

這邊講解一下參數使用:

kind:元件的種類,如:Pod、Deployment等等

apiVersion:支援的API版本

metadata:這個元件的附加資訊,像是名稱、標籤等等

provisioner:存儲類的供應者,這裡是AWS

parameters:一些其他參數,這裡有定義種類是gp2

reclaimPolicy:指定的回收策略,預設是Delete,也就是當StorageClass掰掰的時候,它會將存儲卷刪掉,Retain則相反,會保留存儲卷

mountOptions:掛載選項,對應被掛載的地方應要支援不然會失敗

如果k8s是1.10版:

  • 套用gp2設置
$kubectl apply -f gp2-storage-class.yaml -n ns-eks
storageclass.storage.k8s.io "gp2" created
  • 將gps設為default
$kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' -n=ns-eks

不是的話就都不用做,應該剛開始就如同筆者畫面所顯示的

$kubectl get storageclasses -n ns-eks
NAME            PROVISIONER             AGE
gp2 (default)   kubernetes.io/aws-ebs   28m

新增PersistentVolumeClaim

$vim pvcs.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

接著apply它

$kubectl apply -f pvcs.yaml -n ns-eks
persistentvolumeclaim/mysql-pv-claim created
persistentvolumeclaim/wp-pv-claim created

檢查PVC狀態

$kubectl get pvc -n ns-eks
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pv-claim   Bound    pvc-6cc434b5-ecee-11e9-a674-0a822e4a246e   20Gi       RWO            gp2            39s
wp-pv-claim      Bound    pvc-6cf53941-ecee-11e9-a674-0a822e4a246e   20Gi       RWO            gp2            39s

注意到他們都已經Bound了,也就是已綁定的狀態,可以用囉!

我們檢查下AWS的EBS

https://ithelp.ithome.com.tw/upload/images/20191013/20120468VDv78NY5NS.png

有的!

3. 部署MySQL後端

新增一個Secret

$kubectl create secret generic mysql-pass --from-literal=password=eks-mysql-pw --namespace=ns-eks
secret/mysql-pass created

檢查Secret狀態

$kubectl get secret -n ns-eks
NAME                  TYPE                                  DATA   AGE
default-token-vkv4l   kubernetes.io/service-account-token   3      67m
mysql-pass            Opaque                                1      66s

我們先新增一個YAML文件,部署MySQLl用的

$vim deploy-mysql.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

接著apply它

$kubectl create -f deploy-mysql.yaml -n ns-eks
service/wordpress-mysql created
deployment.apps/wordpress-mysql created

檢查Pod狀態

$kubectl get po -n ns-eks -o wide
NAME                               READY   STATUS    RESTARTS   AGE    IP              NODE                                               NOMINATED NODE   READINESS GATES
wordpress-mysql-7d4fc77fdc-hfms5   1/1     Running   0          104s   192.168.15.32   ip-192-168-0-191.ap-southeast-1.compute.internal   <none>           <none>

可以注意到這個Pod是跑在ip-192-168-0-191.ap-southeast-1.compute.internal這個節點上的

我們從AWS上對照看看

https://ithelp.ithome.com.tw/upload/images/20191013/201204686SKByRvp1m.png

可以發現到狀態已經從available變成in-use

4. 部署Wordpress

新增wordpress的Deployment

$vim deploy-wordpress-by-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:4.8-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim

接著Create

$kubectl create -f deploy-wordpress-by-deployment.yaml -n ns-eks
service/wordpress created
deployment.apps/wordpress created

檢查Pod狀態

$kubectl get po -n ns-eks -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP               NODE                                                NOMINATED NODE   READINESS GATES
wordpress-dccb8668f-fs97z          1/1     Running   0          49s   192.168.51.242   ip-192-168-36-189.ap-southeast-1.compute.internal   <none>           <none>
wordpress-mysql-7d4fc77fdc-hfms5   1/1     Running   0          16m   192.168.15.32    ip-192-168-0-191.ap-southeast-1.compute.internal    <none>           <none>

這時候我們在切到AWS上去看下

https://ithelp.ithome.com.tw/upload/images/20191013/20120468yMBMlGdCEt.png

可以發現到剛剛available的狀態變成in-use了

檢查Service狀態

$kubectl get svc -n ns-eks
NAME              TYPE           CLUSTER-IP       EXTERNAL-IP                                                                    PORT(S)        AGE
wordpress         LoadBalancer   10.100.215.253   aa6309614ecf211e98b110624e7825ce-1654920643.ap-southeast-1.elb.amazonaws.com   80:32086/TCP   7m34s
wordpress-mysql   ClusterIP      None             <none>                                                                         3306/TCP       23m

接著我們透過EXTERNAL-IP去access它

https://ithelp.ithome.com.tw/upload/images/20191013/201204689O5lbPxacP.png

有了,可以用囉!做一些簡單的設置就能登入了

https://ithelp.ithome.com.tw/upload/images/20191013/20120468YJ1vZBsZfa.png

登入後找Customize

https://ithelp.ithome.com.tw/upload/images/20191013/20120468Cap9lSNroO.png

5. 清除

輸入以下指令刪除

$kubectl delete -f deploy-wordpress-by-deployment.yaml -n ns-eks
service "wordpress" deleted
deployment.apps "wordpress" deleted
$kubectl delete -f deploy-mysql.yaml -n ns-eks
service "wordpress-mysql" deleted
deployment.apps "wordpress-mysql" deleted

刪除EBS

https://ithelp.ithome.com.tw/upload/images/20191013/20120468bGucEIyaI6.png

刪除PVC

$kubectl delete -f pvcs.yaml -n ns-eks
persistentvolumeclaim "mysql-pv-claim" deleted
persistentvolumeclaim "wp-pv-claim" deleted

刪除MySQL的Secret

$kubectl delete secret mysql-pass -n ns-eks
secret "mysql-pass" deleted

EFS

EFS和ENI有提過,我們複習下:

Elastic File System (EFS) :提供簡單、可擴展、全受管的彈性 NFS 檔案儲存,可與 AWS 雲端服務和內部部署資源搭配使用。其建置是為了要隨需擴展至數 PB,且不會中斷應用程式,可隨著新增和移除檔案自動擴展和縮減,無須佈建和管理容量來適應增長。

EFS 提供兩種儲存類別:標準儲存類別和不常存取儲存類別 (EFS IA)。EFS IA 針對每天未存取的檔案提供成本優化的性價比。

Elastic Network Interface(ENI):彈性網路界面是代表虛擬網路卡之 VPC 中的邏輯聯網元件。

可在帳戶中建立並設定網路界面,然後將它們連接到VPC 中的執行個體。

1. 建立EFS

我們先到AWS介面操作,切換到EFS

VPC和Security groups要選eks相關的,好了下一步

https://ithelp.ithome.com.tw/upload/images/20191013/20120468lYMy5zb0Kz.png

新增一個Tag

https://ithelp.ithome.com.tw/upload/images/20191013/20120468IQ7CQKAs6M.png

好了會長這樣

https://ithelp.ithome.com.tw/upload/images/20191013/20120468hmkLnoAJ4P.png

接著我們來檢查下ENI的狀態

https://ithelp.ithome.com.tw/upload/images/20191013/20120468ssn7W94LKi.png

OK,有建立與EFS的連接

2. 建立Namespace及準備存儲

新增Namespace並確認

$kubectl create namespace ns-eks-efs
namespace/ns-eks-efs created
$kubectl get namespace
NAME          STATUS   AGE
default       Active   179m
kube-public   Active   179m
kube-system   Active   179m
ns-eks        Active   161m
ns-eks-efs    Active   51s

建立efs-provisioner

efs-id和server的地方依照建立的EFS修改

https://ithelp.ithome.com.tw/upload/images/20191013/20120468pLAXofO9yr.png

$vim create-efs-provisioner.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: efs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: efs-provisioner
    spec:
      containers:
        - name: efs-provisioner
          image: quay.io/external_storage/efs-provisioner:v0.1.0
          env:
            - name: FILE_SYSTEM_ID
              value: fs-d8c8b999
            - name: AWS_REGION
              value: ap-southeast-1
            - name: PROVISIONER_NAME
              value: eks-course/aws-efs
          volumeMounts:
            - name: pv-volume
              mountPath: /persistentvolumes
      volumes:
        - name: pv-volume
          nfs:
            server: fs-d8c8b999.efs.ap-southeast-1.amazonaws.com
            path: /

好了apply它

$kubectl apply -f create-efs-provisioner.yaml -n ns-eks-efs
deployment.extensions/efs-provisioner created

新增RBAC

$vim create-rbac.yaml
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nfs-provisioner-role-binding
subjects:
  - kind: ServiceAccount
    name: default
    namespace: ns-eks-course-efs
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

好了apply

$kubectl apply -f create-rbac.yaml -n ns-eks-efs
clusterrolebinding.rbac.authorization.k8s.io/nfs-provisioner-role-binding created

建立存儲

$vim create-storage.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: aws-efs
provisioner: eks-course/aws-efs
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: efs-wordpress
  annotations:
    volume.beta.kubernetes.io/storage-class: "aws-efs"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: efs-mysql
  annotations:
    volume.beta.kubernetes.io/storage-class: "aws-efs"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

好了apply它

$kubectl apply -f create-storage.yaml -n ns-eks-efs
storageclass.storage.k8s.io/aws-efs created
persistentvolumeclaim/efs-wordpress created
persistentvolumeclaim/efs-mysql created

接下來的這兩步與前面的EBS類似

3. 部署MySQL後端

新增一個Secret

$kubectl create secret generic mysql-pass --from-literal=password=eks-mysql-pw --namespace=ns-eks-efs
secret/mysql-pass created

接著apply

$kubectl create -f deploy-mysql.yaml -n ns-eks-efs
service/wordpress-mysql created
deployment.apps/wordpress-mysql created

我們同樣也可以檢查他的狀態,無論是從命令行或是AWS

4. 部署Wordpress

Create Wordpress的Deployment

$kubectl create -f deploy-wordpress-by-deployment.yaml -n ns-eks
service/wordpress created
deployment.apps/wordpress created

我們同樣也可以檢查集群及AWS狀態

最後可以透過DNS去access它,得到相同的結果

https://ithelp.ithome.com.tw/upload/images/20191013/20120468eus096l4sd.png

就介紹到這邊囉!

小結

今天我們看到了EBS和EFS不同的使用方式,主要是前半段不同,後半段在設置MySQL和Wordpress基本上大同小異,在設置EBS的時候,我們可以發現,它是綁定EC2的,也就是說一個EBS會對應一台EC2,另外也因為它綁定的緣故,所以它不能跨區域(Area Zone)。再來我們看到了EFS,它建立的時候,會自動幫我們建立一個ENI,並在部署前必須要設置provisioner去串接k8s元件,因為它算是一個NFS的檔案系統(File System),所以它可以做到跨區域,不過也不是沒有缺點的,它比EBS貴,因此我們必須參考我們的使用需求,進而去決定我們想要使用的方案。明天會開始介紹整合性相關的內容,敬請期待!我們明天見。

參考連結

本文同步刊載於https://github.com/x1y2z3456/ironman

感謝您撥冗閱讀此文章,不喜勿噴,有任何問題建議歡迎下方留言:)

說個笑話,希望我能寫滿30天啊(笑


上一篇
[Day27] k8s應用篇(一):Helm部署apps、HPA和CA
下一篇
[Day29] k8s集群篇:HA、Federation
系列文
Kubernetes的30天養成計劃30

尚未有邦友留言

立即登入留言