這篇會將上一篇容器化的 Rails App 放到 k8s 裡面運行。
請參考上一篇 從零搭建,如何讓 Rails 跑在 Kubernetes(k8s)(一)
開發前準備
懶人安裝指令:
brew install kubernetes-cli && brew cask install minikube
輸入 kubectl version
檢查版本
Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.3", GitCommit:"435f92c719f279a3a67808c80521ea17d5715c66", GitTreeState:"clean", BuildDate:"2018-11-27T01:14:37Z", GoVersion:"go1.11.2", Compiler:"gc", Platform:"darwin/amd64"}
如果有出現
Unable to connect to the server: dial tcp 192.168.99.100:8443: i/o timeout
或是
The connection to the server localhost:8080 was refused - did you specify the right host or port?
這邊先暫時不用擔心,因為還沒有啟動 k8s 叢集,可以先忽略訊息。
接下來確認 minikube 的版本
minikube version
# minikube version: v0.30.0
都沒問題就可以輸入 minikube start
啟動 k8s 叢集,這裡需要花一點時間,依照電腦規格及網路速度不同會有不同的等待時間,第一次啟動會比較久一些,請耐心等候 XD
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
Downloading Minikube ISO
140.01 MB / 140.01 MB [============================================] 100.00% 0s
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.
啟動完後,可以透過 minikube status
指令獲得當前狀態
minikube: Running
cluster: Running
kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.100
如果不放心,也可以透過 minikube ssh
連進機器看一下
連進去之後輸入 docker ps
,可以看到內部跑大量的 docker container,這就是 k8s 裡面的架構了。
輸入 exit
離開(這時候 k8s 還是正常運行在背景的,不需重新 start)
將上一章節的 Rails app docker image 上傳至 docker hub 雲端
等等建立 container 時要從雲端拉,所以這邊要先上傳。
打包指令
docker build -t niclin/rails-app:v1 .
Push 上去
docker push niclin/rails-app:v1
這邊每個人帳號名稱不一樣,像我的就是 niclin ,要記得替換,如果不知道怎麼操作,可以參考Docker 官方的文件
建立 Database service
先建立 secrets
下方第三條指令的 secret-key-base 是用 rails 的 rake secret
生成
kubectl create secret generic db-user-pass --from-literal=password=mypass
kubectl create secret generic db-user --from-literal=username=postgres
kubectl create secret generic railsapp-secrets --from-literal=secret-key-base=50dae16d7d1403e175ceb2461605b527cf87a5b18479740508395cb3f1947b12b63bad049d7d1545af4dcafa17a329be4d29c18bd63b421515e37b43ea43df64
在專案目錄下新建檔案,路徑為 kube/deployments/db.yaml
(這邊要自己創建資料夾)
檔案內容可以直接複製,這邊沒有要修改的部分
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
generation: 1
labels:
run: db
name: db
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
run: db
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
run: db
spec:
containers:
- env:
- name: DATABASE_USER
value: "postgres"
- name: DATABASE_PASSWORD
value: "mypass"
- name: POSTGRES_DB
value: "rails-app-db"
- name: PGDATA
value: "/var/lib/postgresql/data"
image: postgres
imagePullPolicy: Always
name: db
ports:
- containerPort: 5432
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
這裡雖然可以直接透過 cli 下指令生成相關 service,不過為了避免看教學看到暈掉,這邊直接用檔案管理進行操作,輸入以下指令即可建立
kubectl create -f kube/deployments/db.yaml
接下來查看 pod 狀態
kubectl get pods
要等 STATUS 變成 Running 才算啟動完成,這邊的指令可以加 -w
參數直接觀察變動。
確定狀態啟動後,我們將 database expose 出去
kubectl expose deployment db
這時候我們可以查看是不是有新建立一個 Database 的 service 呢
kubectl get services
建立 Rails App service
在專案目錄下新建檔案,路徑為 kube/deployments/rails.yaml
(這邊要自己創建資料夾)
這邊要注意的是,要把 niclin/rails-app:v1
的 image 來源換成你自己 dokcer hub 上的哦(要拉我的也是可以啦)
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
generation: 1
labels:
run: app
name: app
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
run: app
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
run: app
spec:
containers:
- command:
- rails
- s
- -p
- "3000"
- -b
- 0.0.0.0
image: niclin/rails-app:v1
imagePullPolicy: IfNotPresent
env:
- name: DATABASE_URL
value: "postgres"
- name: DATABASE_NAME
value: "rails-app-db"
- name: DATABASE_PORT
value: "5432"
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: "db-user"
key: "username"
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: "db-user-pass"
key: "password"
- name: SECRET_KEY_BASE
valueFrom:
secretKeyRef:
name: "railsapp-secrets"
key: "secret-key-base"
name: app
ports:
- containerPort: 3000
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
接著輸入指令創建 service
kubectl create -f kube/deployments/rails.yaml
在跑 rake db:migrate 之前,要先拿到 pod name
kubectl get pods
這邊也要等 STATUS 變成 Running 才能繼續下面的 migrate 哦
kubectl exec -it POD_NAME rails db:migrate
# 舉例: kubectl exec -it app-655469bcc8-x9chm rails db:migrate
# 每個人不一樣喔,要自己看自己的 pod name
將 app expose 出去。
kubectl expose deployment app --type=NodePort
在最後這個步驟,沒什麼好說的了,就是打開瀏覽器來看辛苦的成果了,沒意外會看到你在 minikube 分配到的 IP 跑起的 Rails server 畫面了!
minikube service app
最後,你也可以透過 minikube dashboard
指令來查看詳細內容
後記:刪除 Pod 的方式
參考 Kubernetes pod gets recreated when deleted
To list all deployments
kubectl get deployments --all-namespaces
Then to delete the deployment:
kubectl delete -n NAMESPACE deployment DEPLOYMENT
# 我的範例:kubectl delete -n default deployment app