前置作業
取得 DigitalOcean API Token
首先你需要產生一個 DigitalOcean 的 API 金鑰 (Token),讓你的 Kubernets 能夠直接存取 DigitalOcean 的資源,如果你已經有 Token,建議你產生一個新的來專用,您可以連線此網址來取得您自己的 Token。
建立 D igitalOcean 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。
複製並取代 token
與 cluster_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。
建立 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
開立 DigitalOcean 客服單請他們解決。
留言