上篇我們已經安裝好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