
Kubernetes 觀念簡介
建立 docker containers
- 建立 container,可以使用 Docker Engine
- 建立 Dockerfile 來執行就可以快速建立需要的 container
- Docker build 可以手動執行,也可以透過像是 jenkins 的 CI/CD 軟體
在 Kubernetes 上面運行應用程式
- 運行新建立的應用在新的 Kubernetes cluster
- 在我們要運行基於 image 之上的 container,我們需要創建 pod definition
- 一個 pod 就是一個應用運行在 Kubernetes 上面
- 一個 pod 包含一個或多個緊密耦合的容器,如此一來可以形成一個應用
- 這些應用們可以輕易的使用本地 port number 跟其它應用溝通
- 我們的應用只包含一個 container
- 創建一個 pod
- 創建一個 pod-helloworld.yml 的檔案
- 使用 kubectl 在 kubernetes cluster 上面創建 pod
- 有用的命令
- kubectl get pod:取得所有在運行的 pods 的資訊
- kubectl describe pod
:描述一個 pod - kubectl expose pod
--port=444 --name=fronted:公開一個 pod 的 port (創建一個新服務) - kubectl port-forward
8080:Port 傳送公開的 pod port 到自己的本地機器 - kubectl attach
-i:連接到特定 pod - kubectl exec
--command:執行一個命令在 pod 上面 - kubectl label pods
myloable=awesome:新增一個標籤到 pod 上面 - kubectl run -i --tty busybox --image=busybox --restart=Never – sh:在 pod 裡面運行一個 sh - 對除錯非常有用
- 先用
minikube start
運行 minikube,再用kubectl create -f first-app/helloworld.yml
創建 pod kubectl describe pod nodehelloworld.example.com
kubectl port-forward nodehelloworld.example.com 8081:3000
curl localhost:8081
就可以看到服務運行了kubectl expose pod nodehelloworld.example.com --type=NodePort --name nodehelloworld-service
minikube service <Service Name> --url
即可以取得服務的 url
有用的 kubectl commands
kubectl attach nodehelloworld.example.com
連接 nodehelloworld.example.comkubectl exec nodehelloworld.example.com -- ls /app
在應用裡面執行命令kubectl exec nodehelloworld.example.com -- touch /app/test.txt
kubectl exec nodehelloworld.example.com -- ls /app
kubectl describe service nodehelloworld-service
kubectl run -i --tty busybox --image=busybox --restart=Never -- sh
新增一個 box 來和 nodehellowrold-service 進行連線telnet 172.17.0.4 3000
GET /
負載平衡服務
- 在真實的世界裡面,必須要可以從 cluster 的外部連線到應用
- 在 AWS 上面,可以輕鬆的新增 外部負載平衡器(external Load Balancer)
- 這個 AWS Load Balancer 將會路由到正確的 Kubernetes pod
- 其它雲端服務商沒有 Load Balancer,但是仍有其它解決方案
- 擁有 haproxy/nginx load balancer 在 cluster 之前
- 或是可以直接將 ports 公開
AWS ELB LoadBalancer 服務
kops create cluster --name=kubernetes.appsoliloquy.com --state=s3://kops-state-b429d --zones=ap-northeast-1a --node-count=2 --node-size=t2.micro --master-size=t2.micro --dns-zone=kubernetes.appsoliloquy.com
kops update cluster kubernetes.appsoliloquy.com --yes --state=s3://kops-state-b429d
kubectl create -f first-app/helloworld.yml
kubectl create -f first-app/helloworld-service.yml
- 進去 EC2 的 Load Balancer,確認資料狀態。
- 進入 Route 53,新增 record,名稱設為 helloworld,Alias 設為 yes,Alias Target 設為 Loadbalancer,點選 create。
- 進入 helloworld.kubernetes.appsoliloquy.com. 就可以看到結果了
Kubernetes 基礎
Node 架構
- Docker 裡面裝有 Pods,Pods 裡面裝有 containers
- container 之間可以簡單地互相溝通
- kubelet 用來管理 pods,在 container 之外,kube-proxy 負責和 iptable 溝通,如果 pod 有問題,它會更新 iptable 的規則
Replication Controller
- 如果應用是 stateless,可以橫向的擴展
- Stateless 就是應用沒有 state,不需要寫入任何本地檔案/保存本地 sessions
- 所有傳統的資料庫(MySQL、Postgres)都是 stateful,它們都有資料庫檔案且不能分到多個 instances
- 大部分的網頁應用可以做成 stateless
- Session 管理 必須要在 container 之外完成
- 任何檔案需要被儲存的都不能儲存在 container 的本機
- 我們的範例應用是 stateless,如果相同的應用執行很多次,也不會改變它的 state
- 更多關於練習的資訊,請看 12factor.net
- 或是看 Learn DevOps: Continuously delivering better software/scalig apps on-premise and in the cloud
- 後面會解釋如何使用 volumes 來運行 stateful 應用
- 這些 stateful 應用不能橫向擴展,但是可以在單一 container 裡面運行它們且縱向擴展 (分配更多 CPU/記憶體/硬碟)
- Kubernetes 的擴展可以透過使用 Replication Controller 來完成
- Replication Controller 可以確保指定數量的 pod relicas 將會隨時運行
- 如果被 relica controller 創建出來的 pod 運行失敗、被刪除或是被終止,那麼 pod 就會自動被取代
- 如果你只想確保一個 pod是永遠運行的,甚至在重新開機之後,那麼使用 Replication Controller 是被推薦的
- 可以只與一個 replica 運行一個 Replication Controller
- 這樣可以確保 pod 總是處於運行狀態
- 在 YAML 裡面設定 kind 為 ReplicationController、spec 裡面的 replicas 設為 2,即可複製應用兩次
Demo:Replication Controller
kubectl create -f replication-controller/helloworld-repl-controller.yml
kubectl describe pod helloworld-controller-cwbbn
複製其中的 controller 檢查狀態kubectl scale --replicas=4 -f replication-controller/helloworld-repl-controller.yml
擴展服務kubectl get rc
kubectl scale --replicas=1 rc/helloworld-controller
kubectl delete rc/helloworld-controller
部署
- Replication Set 是 Replication Controller 的下個世代
- 它支援一種新的 selector,這個 selector 可以做基於過濾的 selection,而過濾是根據 sets of values
- 例如:“environment” 不是 “dev” 就是 “qa”
- 不只根據 equality,就像是 Replication Controlller
- 例如 “environment” == “dev”
- 跟 Replication Controller 相比,Replica Set 是使用 Deployment object
- Kubernetes 裡的部署聲明允許讓應用做部署和更新
- 當使用 deployment object,你就定義了你的應用的 state
- Kubernetes 將會確保 clusters 符合你的 desired state
- 只使用 replication controller 或 replication set 可能會在部署應用的時候很麻煩
- Deployment Obeject 比較容易使用且有更多可能性
- 有 deployment object,你可以:
- 創建一個 deployment(例如:部署一個應用)
- 更新一個 deployment(例如:部署一個新版本)
- 可以做 rolling updates(零停機時間部署)
- Roll back 到上一版本
- 停止/恢復一個 deployment(例如:只推出部分比例)
- 在 YAML 裡面設定 kind 為 Deployment
- 非常有用的命令:
kubectl get deployments
:取得現有的 deployments 資訊kubectl get rs
:取得 replica sets 的資訊kubectl get pods --show-labels
:取得 pods 且顯示連結到這些 pods 的 labelskubectl rollout status deployment/helloworld-deployment
:取得 deployment 狀態kubectl set image deployment/helloworld-deployment k8s-demo=k8s-demo:2
:運行 image label version 2 的 k8s-demokubectl edit deployment/helloworld-deployment
:編輯 deployment objectkubectl rollout status deployment/hellowrold-deployment
:取得 rollout 的狀態kubectl rollout history deployment/helloworld-deployment
:取得 rollout 的歷史kubectl rollout undo deployment/helloworld-deployment
:Rollback 到上一版本kubectl rollout undo deployment/helloworld-deployment --to-revision=n
:Rollback 到任何版本
Demo:部署
kubectl create -f deployment/helloworld.yml
kubectl get deployments
kubectl get rs
kubectl get pods
kubectl get pods --show-labels
kubectl rollout status deployment/helloworld-deployment
kubectl expose deployment helloworld-deployment --type=NodePort
kubectl describe service helloworld-deployment
minikube service helloworld-deployment --url
kubectl set image deployment/helloworld-deployment k8s-demo=wardviaene/k8s-demo:2
kubectl rollout status deployment/helloworld-deployment
curl http://192.168.99.100:32635
curl 剛剛取得的 ip,就會發現變成 Helloworld v2kubectl rollout history deployment/helloworld-deployment
kubectl rollout undo deployment/helloworld-deployment
kubectl rollout status deployment/helloworld-deployment
kubectl edit deployment/helloworld-deployment
,在 spec 的 replica 下面新增revisionHistoryLimit: 100
kubectl set image deployment/helloworld-deployment k8s-demo=wardviaene/k8s-demo:2
kubectl rollout history deployment/helloworld-deployment
kubectl rollout undo deployment/helloworld-deployment --to-revision=8
kubectl rollout history deployment/helloworld-deployment