前置作業

取得 DigitalOcean API Token

首先你需要產生一個 DigitalOcean 的 API 金鑰 (Token),讓你的 Kubernets 能夠直接存取 DigitalOcean 的資源,如果你已經有 Token,建議你產生一個新的來專用,您可以連線此網址來取得您自己的 Token。

建立 DigitalOcean K8S cluster 1.14

接者請選擇左側選單的 Kubernetes,然後選擇右側上方 “Create” -> “Cluster”,會進入 K8S 的建立畫面,選用 1.14 版 (或是更新的版本)。

  • Datacenter Region:資料中心的地區目前地點不多,就依照你自己的喜好選擇。
  • Pool Name:自訂名稱,或保留預設
  • Machine Type:預設即可
  • Node Plan:預設即可
  • Number Nodes:如果你作為練習,可以建立 1 台幾可,正常架構下,需要 3 台以上的備援,每個 Node 就是一台 VM,所以是依照 VM 的等級收費。
  • Add Tag:可以設定標籤
  • Choose a name:自訂叢集名稱

選擇好之後建立即可。

取得 Kubernetes 設定檔

在 Kubernates 建立好之後,你可以直接在本機使用 kubectl 的指令來控制遠端的 Master,你需要從 DigitalOcean 下載 kubeconfig 檔。

使用在之前步驟所取得 Token,修改下列程式就可以抓到 kubeconfig 檔,cluster_id 的取得方式在瀏覽器就是點選叢集之後,網址列最後的部份就是 cluster_id。

DigitalOcean Cluster ID

複製並取代 tokencluster_id

#!/bin/bash

token="xxxxxxxxxx"
cluster_id="xxxx-xxxxx-xxxx-xxxxx"

curl -s -X GET --url \ 
https://api.digitalocean.com/v2/kubernetes/clusters/$cluster_id/kubeconfig \
  -H "authorization: Bearer $token" \
  -o wp-digitalocean-kubeconfig.yaml

執行指令後,工作目錄下就會有一個 wp-digitalocean-kubeconfig.yaml 的檔案。把他覆蓋 ~/.kube/config,你就可以用 kubectl 指令直接控制 DigitalOcean 的 K8S 環境。

用戶端環境

用戶端的 kubectl 最好跟 Server 是一樣的版本,如果你需要升級到 1.14 的版本可以參考我的作法,其他版本請參考 Kubernetes 官方文件

# curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl

# chmod u+x kubectl
# mv kubectl /bin

;驗證 Server 與 Client 的環境是否一致
# kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.2", GitCommit:"66049e3b21efe110454d67df4fa62b08ea79a19b", GitTreeState:"clean", BuildDate:"2019-05-16T16:23:09Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.2", GitCommit:"66049e3b21efe110454d67df4fa62b08ea79a19b", GitTreeState:"clean", BuildDate:"2019-05-16T16:14:56Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}

安裝 Digitalocean-cloud-controller-manager

接者就開始在你的 K8S 中安裝一些必要的 POD,首先要安裝的是 DigitalOcean-cloud-controller-manager,會需要你的 Token,請依照下方說明進行。

; 從 Git Repository 複製下來 
# git clone https://github.com/digitalocean/digitalocean-cloud-controller-manager.git

; 進入目錄
# cd digitalocean-cloud-controller-manager/releases

; 複製 secret.yml 檔
# cp secret.yml.tmpl secret.yml

; 請 export 你的 TOKEN
# export DIGITALOCEAN_ACCESS_TOKEN=XXXXXXXXXXXX

; 請修改 secret.yaml 檔中的 TOKEN 變數,改成你的
# vim secret.yml

; 建立 Secret
# kubectl apply -f secret.yml

; 查看 Secret 有沒有建立成功
# kubectl -n kube-system get secrets

; 建立 digitalocean-cloud-controller-manager
# kubectl create -f v0.1.14.yml
deployment "digitalocean-cloud-controller-manager" created
serviceaccount "cloud-controller-manager" created
clusterrole "system:cloud-controller-manager" created
clusterrolebinding "system:cloud-controller-manager" created

安裝 csi-digitalocean

csi-digitalocean 是用來控制 digitalocean 的 volumes 的,讓你在宣告 (claim) pv 的時,就會直接建立 digitalocean 的 volumes (當然空間是要錢的)。

csi-digitalocean 的官方網頁: https://github.com/digitalocean/csi-digitalocean

csi 的官方說明:A Container Storage Interface (CSI) Driver for DigitalOcean Block Storage. The CSI plugin allows you to use DigitalOcean Block Storage with your preferred Container Orchestrator.

; 直接執行指令即可
# kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v1.1.0.yaml

複製 WordPress 的 YAML 檔

整個 K8S 運作的方式,Pod 佈署的方法、設定等等,都是透過 yaml 檔的方式設定,然後用 kubectl 指令套用設定檔,Kubernetes 就會知道要怎麼運作,所以你要把所有 yaml 檔都保存好。

從 GitHub 下載 YAML 檔

groovemonkey 有針對 DigitalOcean 寫好了很多 yaml 檔,複製下來稍微改一下就可以使用,但是因為 DigitalOcean 的 Volumes 目前不支援 ReadWriteMany,只能用 ReadWriteOnce 的方式掛載,所以你的 WordPress Pod 只能開一個出來,無法作到水平擴張。

我依照他的 yaml 檔去修改了一些東西,並加了一個 NFS Server 來分享 Volumes,我們就可以透過 ReadWriteMany 的方式同時掛載給多個 Pods。

我的 GitHub:https://github.com/haway/k8s-digitalocean-wordpress

# git clone https://github.com/haway/k8s-digitalocean-wordpress
# cd k8s-digitalocean-wordpress

建立環境變數

從 Git Clone 專案後,首先要設定一些環境變數,稍後在 Pods 建立起來的時候會使用到,你需要建立幾個環境變數:

  • MYSQL_DATABASE
  • MYSQL_USER
  • MYSQL_PASSWORD
  • MYSQL_ROOT_PASSWORD
  • WORDPRESS_DB_USER

設定 MySQL_DATABASE 這個環境變數,就會在 MySQL 建立的時候自動幫你建立這個資料庫。設定的方式要把你的值用 base64 編碼編過

# echo -n "YourString" | base64
範例
# echo -n "wordpress" | base64
d29yZHByZXNz
# echo -n "adminpassword" | base64
YWRtaW5wYXNzd29yZA==

貼到 secrets/wp-mysql-secrets.yaml 內:

apiVersion: v1
kind: Secret
metadata:
  name: wp-db-secrets
  namespace: default
type: Opaque
data:
  MYSQL_ROOT_PASSWORD: YWRtaW5wYXNzd29yZA
  MySQL_DATABASE: d29yZHByZXNz
  MySQL_USER: d29yZHByZXNz
  MySQL_PASSWORD: MTIzcXdl
  WORDPRESS_DB_USER: d29yZHByZXNz

執行 kubectl create -f wp-mysql-secrets.yaml,然後檢查是否生效。

# kubectl get secrets
NAME                  TYPE      DATA      AGE
wp-db-secrets         Opaque    1         1d

建立 MySQL

建立 MySQL 所需要的空間(Volume)

# kubectl create -f manifests/mysql-volume-claim.yaml
persistentvolumeclaim "mysql-volume" created

# kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
mysql-volume   Bound    pvc-fd3a3f2f-7acd-11e9-bdf1-ea6b706733ac   5Gi        RWO            do-block-storage   9s

進入網頁後台會看到建立了一個 Volume。

DigitalOcean volumes

建立 MySQL 的 Replicaset 與 Service:

# kubectl apply -f manifests/mysql-replicaset.yaml 
replicaset.extensions/mysql created

# kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
mysql-2hfv4   1/1     Running   0          62s

# kubectl apply -f manifests/mysql-service.yaml
service/mysql created
# kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.245.0.1      <none>        443/TCP    53m
mysql        ClusterIP   10.245.104.48   <none>        3306/TCP   9s

; 如果需要進入 MySQL Pod 內,可用下列方法:
# kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
mysql-2hfv4   1/1     Running   0          2m18s
# kubectl exec -it mysql-2hfv4 -- bash
root@mysql-2hfv4:/# 

建立 NFS Server

因為 DigitalOcean 的 Volume 只支援 ReadWriteOnce,無法使用 ReadWriteMany。要支援 ReadWriteMany 的才能同時給多個 Pods 使用。

所以我們再建立一個 NFS 伺服器將 DigitalOcean 的 Volume 用 NFS 的方式分享出來,才能掛成 ReadWriteMany。

建立一個要給 NFS 使用的空間 (Volume):

# kubecte create -f manifests/nfs-rc.yaml

nfs-rc.yaml 中已經包括對 Kubernetes claim(宣告) 一個空間,PVC 名稱是 wordpress-volume-nfs,預設是 2G,你可以修改 YAML 檔來變更空間大小。同樣也會宣告一個 ReplicationController(RC) 的 NFS Server 並直接將剛剛宣告的空間使用 NFS 的方式分享出去。

同樣的,登入 DO 後台可以看到對應的 Volmue。

# kubectl create -f manifests/wordpress-datavolume-claim.yaml 
persistentvolumeclaim/wordpress-volume created

載入 Apache 設定檔

接者我們要把 Apache 設定檔載入 Kubernetes 內:

# kubectl create cm --from-file configs/apache.conf apache-config
configmap/apache-config created

建立 WordPress

初始化 WordPress 空間

接者我們要再次宣告 WordPress 所要使用的 PVC,此處有一個問題,正常來說,應該是指定 NFS 的 Hostname 即可,但是這目前是一個 Bug,沒有辦法用 Hostname 或是 Service IP ,而必須要用 NFS 的 Pod IP 來連線,所以你必須要先查出 NFS Pod 的 IP,然後寫入 WordPress 的空間要求 YAML 檔內。在你建立 WordPress 的空間 (wordpress-datavolume-claim) 後,此空間就會去自動掛載 NFS 伺服器所分享出來的空間。

; 請先用 kubectl get pods 找出 NFS Pod 的 IP 位址

; 修改 wordpress-datavolume-claim.yaml 內的 server IP
# vi manifests/wordpress-datavolume-claim.yaml 

# kubectl create -f manifests/wordpress-datavolume-claim.yaml 
persistentvolumeclaim/wordpress-volume created

建立 WordPress 的 Deployment

接者就可以把 WordPress 的 Pods 利用 Deployment 建立起來,你可以調整 replicas 來隨時變更 Pods 的數目。

# kubectl apply -f manifests/wordpress-deployment.yaml
deployment.apps/wordpress created
# kubectl get deployment
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
wordpress   0/1     1            0           16s
# kubectl get pods
NAME                         READY   STATUS              RESTARTS   AGE
mysql-2hfv4                  1/1     Running             1          43m
wordpress-556d8685d6-z8dvg   0/1     ContainerCreating   0          23s

;等待 Pod 跑起來就可以摟

建立 Load Balancers

最後,設定 DigitalOcean 的 Load Balancers 就可以了,這是要付費的,每個月 10 美金,但不建立就不能提供對外連線。

# kubectl apply -f manifests/DO-loadbalancer.yaml
service/wordpress-lb created

# kubectl get services
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
kubernetes     ClusterIP      10.245.0.1      <none>          443/TCP        100m
mysql          ClusterIP      10.245.104.48   <none>          3306/TCP       46m
wordpress-lb   LoadBalancer   10.245.17.83    138.68.38.202   80:32602/TCP   3m11s

登入後台就可以看到建立了一個 Load Balancers。

!!完成!!

錯誤訊息

Error validating

# kubectl apply -f manifests/mysql-volume-claim.yaml
error: error validating "manifests/mysql-volume-claim.yaml": error validating data: field dataSource: is required; if you choose to ignore these errors, turn validation off with --validate=false

解決方式 1: 使用 –validate 參數

# kubectl apply --validate=false  -f manifests/mysql-volume-claim.yaml

解決方式 2: 升級 kubectl 指令。主因是因為版本不對,所以請升級 kubectl 的版本。

卡住的 DO-LoadBalancer

Pending LoadBalancer

開立 DigitalOcean 客服單請他們解決。

最後修改日期: 2019-10-29

作者

留言

留言