上篇我們已經安裝好k8s1.23叢集,現在我們開始使用k8s部署我們的專案
Pod
Pod 是一組容器集合,是可以在 Kubernetes 中建立和管理的、最小的可部署的計算單元。這些容器共享儲存、網路。
準備Demo
我們要實現多容器Pod所以準備兩個WebAPI專案
新建一個webapi,命名為oneapi,裡面新增TestController,新增兩個api,一個是返回當前pod的ip,另一個是模擬高cpu操作
[ApiController] [Route("[controller]")] public class TestController : ControllerBase { private readonly ILogger<TestController> _logger; public TestController(ILogger<TestController> logger) { _logger = logger; } [HttpGet] public string Get() { var ip = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces().Select(p => p.GetIPProperties()).SelectMany(p => p.UnicastAddresses) .Where(p => p.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !System.Net.IPAddress.IsLoopback(p.Address)) .FirstOrDefault()?.Address.ToString(); return "ip is " + ip; } [HttpGet("highcpu")] public string HighCpu(int minutes) { var now = DateTime.Now; while (DateTime.Now - now <= TimeSpan.FromMinutes(minutes)) { _logger.LogInformation(DateTime.Now.ToString()); } return "ok"; } }
新建第二個webapi,命名為twoapi,裡面同樣新增TestController,實現一個介面,通過localhost呼叫oneapi的ip介面(pod內容器共享儲存、網路)
[ApiController] [Route("[controller]")] public class TestController : ControllerBase { private readonly ILogger<TestController> _logger; private readonly HttpClient _httpclient; public TestController(ILogger<TestController> logger, HttpClient httpclient) { _logger = logger; _httpclient = httpclient; } [HttpGet("calloneapi")] public async Task<string> CallOneApiAsync() { var content = await (await _httpclient.GetAsync("http://localhost:5000/test")).Content.ReadAsStringAsync(); return "one api response is " + content; } }
將這兩個api打成映象,推進阿里雲映象庫
單容器Pod
我們通過以下命令即可快速地部署一個pod,下面所有的映象都使用我們剛剛推送到阿里雲裡的映象
kubectl run oneapi --image=registry.cn-beijing.aliyuncs.com/chester-k8s/oneapi:latest
可通過以下命令檢視pod的狀態
kubectl describe pod oneapi
檢視到pod的私有ip,呼叫oneapi的ip介面,驗證是否部署成功
curl 10.244.36.66:5000/test
多容器Pod
多容器pod容器共享儲存、網路,我們通過yaml檔案來部署一個多容器的pod,來驗證是否共用網路。
apiVersion: v1 kind: Pod metadata: name: chesterapi spec: containers: - name: oneapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/oneapi:latest ports: - containerPort: 5000 - name: twoapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/twoapi:latest ports: - containerPort: 5001
kubectl apply -f pod.yaml
通過以下命令檢視pod
kubectl describe pod chesterapi
通過以下呼叫twoapi的介面驗證pod是否部署成功
curl podip:5001/test/calloneapi
驗證完成,通過以下命令刪除pod
kubectl delete -f pod.yaml
探針
探針用於檢測pod的健康狀態,探針有三種,
-
ExecAction
(藉助容器執行時執行) -
TCPSocketAction
(由 kubelet 直接檢測) -
HTTPGetAction
(由 kubelet 直接檢測)
我們通過http探針,來檢測pod的健康狀態,修改pod.yaml檔案,並直接kubectl apply -f pod.yaml即可驗證
apiVersion: v1 kind: Pod metadata: name: chesterapi spec: containers: - name: oneapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/oneapi:latest ports: - containerPort: 5000 livenessProbe: httpGet: path: /test port: 5000 - name: twoapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/twoapi:latest ports: - containerPort: 5001 livenessProbe: httpGet: path: /test/calloneapi port: 5001
Pod狀態
Pod重啟策略
restartPolicy的選擇值
-
Always:當容器失效時,由kubelet自動重啟該容器。
-
OnFailure:當容器終止執行且退出碼不為0時,由kubelet自動 重啟該容器。
-
Never:不論容器執行狀態如何,kubelet都不會重啟該容器。
我們通過pod.yaml的探針介面地址為一個不存在的地址,並將restartPolicy設定為Never,讓其即使健康檢查失敗,Pod也永不重啟
apiVersion: v1 kind: Pod metadata: name: chesterapi spec: restartPolicy: Never containers: - name: oneapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/oneapi:latest ports: - containerPort: 5000 livenessProbe: httpGet: path: /test1 port: 5000 - name: twoapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/twoapi:latest ports: - containerPort: 5001 livenessProbe: httpGet: path: /test/calloneapi1 port: 5001
通過以下命令部署,並驗證
kubectl apply -f pod.yamlkubectl describe pod -n chesterapi
Deployemnt
說完了pod,我們來看看deployment。生產環境中基本不存在直接定義pod的方式來部署專案,更多的是通過Deployment來部署。
用途
-
方便管理、部署Pod
-
橫擴應對高負載
-
快速程式更新與回滾
建立
首先我們建立一個檔案ns.yaml來定義一個namespace
apiVersion: v1
kind: Namespace
metadata:
name: chesterns
我們通過定義以下一個deployment,實現部署三個pod,模擬負載
apiVersion: apps/v1 kind: Deployment metadata: name: chesterdeployment namespace: chesterns labels: app: chesterapi spec: replicas: 3 selector: matchLabels: app: chesterapi template: metadata: labels: app: chesterapi spec: containers: - name: oneapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/oneapi:latest ports: - containerPort: 5000 livenessProbe: httpGet: path: /test port: 5000 - name: twoapi image: registry.cn-beijing.aliyuncs.com/chester-k8s/twoapi:latest ports: - containerPort: 5001 livenessProbe: httpGet: path: /test/calloneapi port: 5001
通過以下命令部署並呼叫介面
kubectl apply -f deployment.yaml # 部署 kubectl get deployment -n chesterns # 獲取deployment kubectl describe pod -n chesterns # 檢視pod
拿到pod的虛擬ip,開始測試
curl 10.244.36.75:5000/test curl 10.244.36.75:5001/test/calloneapi
滾動更新(RollingUpdate)與回滾
我們可以藉助k8s的滾動更新實現服務的不停機更新,k8s也為我們提供了應對異常回滾的方法,下面就開始模擬
更新映象
kubectl set image deployment/chesterdeployment twoapi=registry.cn-beijing.aliyuncs.com/chester-k8s/oneapi:latest -n chesterns --record
檢視更新狀態
kubectl rollout status deployment/chesterdeployment -n chesterns
檢視更新歷史
kubectl rollout history deployment/chesterdeployment -n chesterns
回滾
kubectl rollout undo deployment/chesterdeployment -n chesterns kubectl rollout undo deployment/chesterdeployment -n chesterns --to-revision=1
滾動更新機制
-
啟動一個新的RS與新pod
-
等待新的 pod 進入 Ready 狀態
-
建立 Endpoint,將新的 pod 歸入負載均衡運維
-
移除與老 pod 相關的 Endpoint,而且將老 pod 狀態設定為 Terminating,此時將不會有新的請求到達老 pod
-
給老 pod 傳送 SIGTERM 訊號,而且等待 terminationGracePeriodSeconds 這麼長的時間。(預設為 30 秒)
-
超過 terminationGracePeriodSeconds 等待時間直接強制 kill 程式並關閉舊的 pod
除了滾動更新,還有一種更新Recreate,這種模式會先殺掉所有正在執行的Pod,然後建立新的Pod
橫向擴充套件
k8s通過 kubectl scale即可快速實現pod的橫向擴充套件
kubectl scale deployment/chesterdeployment -n chesterns --replicas=10