K8S原來如此簡單(三)Pod+Deployment

chester·chen發表於2022-03-23

上篇我們已經安裝好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,來驗證是否共用網路。

通過以下命令檢視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來部署。

用途

  1. 方便管理、部署Pod

  2. 橫擴應對高負載

  3. 快速程式更新與回滾

建立

首先我們建立一個檔案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

滾動更新機制

 

  1. 啟動一個新的RS與新pod

  2. 等待新的 pod 進入 Ready 狀態

  3. 建立 Endpoint,將新的 pod 歸入負載均衡運維

  4. 移除與老 pod 相關的 Endpoint,而且將老 pod 狀態設定為 Terminating,此時將不會有新的請求到達老 pod

  5. 給老 pod 傳送 SIGTERM 訊號,而且等待 terminationGracePeriodSeconds 這麼長的時間。(預設為 30 秒)

  6. 超過 terminationGracePeriodSeconds 等待時間直接強制 kill 程式並關閉舊的 pod

 

除了滾動更新,還有一種更新Recreate,這種模式會先殺掉所有正在執行的Pod,然後建立新的Pod

橫向擴充套件

k8s通過 kubectl scale即可快速實現pod的橫向擴充套件

kubectl scale deployment/chesterdeployment -n chesterns --replicas=10

相關文章