kubernetes學習筆記 (二):k8s初體驗

本文采用本地k8s v1.10.3版本開發,若是尚未搭建可參照 kubernetes學習筆記 (一):搭建本地k8s開發環境進行搭建node

搭建本地Docker鏡像倉庫

  1. docker pull docker.io/registry 拉取registry的鏡像到本機
  2. docker run -d -p 5000:5000 --name=registry --restart=always --privileged=true --log-driver=none -v /home/data/registrydata:/tmp/registry registry 運行剛剛拉取的registry
  3. 在Docker for Mac中找到Docker -> Preferences -> Daemon,在insecure registries中填入本身剛剛搭建的本地倉庫 http://localhost:5000

準備一個Docker鏡像

  1. 隨意使用什麼語言寫一個http接口,例如Nodejs:
@Get('whoami')
    async whoAmI() {
        debug('whoAmI called with %O', {});

        return { serverType: Config.SERVER_TYPE };
    }
複製代碼
  1. 編寫對應的DockerFile
FROM node:8
WORKDIR /root

RUN mkdir -p /root/app

COPY package.json /root/app/
COPY dist /root/app/dist

WORKDIR /root/app

RUN npm config set registry https://registry.npm.taobao.org/ ;\
    npm config set disturl https://npm.taobao.org/dist/ ;\
    npm i --production

CMD [ "node", "/root/app/dist/main.js" ]

EXPOSE 80

複製代碼
  1. 編譯、打標籤,並推送到本地倉庫中
echo 'Building to dits ...'
tsc

echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.1 .

echo 'Pushing ...'
docker push localhost:5000/gateapp

echo 'Docker list images ...'
docker images
複製代碼

最後你會看到localhost:5000/gateapp:0.0.1的鏡像已經在你的機器中啦,下面會用到docker

Kubernetes中的重要概念

  1. Cluster: Cluster是計算、存儲和網絡資源的集合,Kubernetes利用這些資源運行各類基於容器的應用
  2. Master: Master是Kubernetes的大腦,它的主要職責是調度,即決定將應用放在那裏運行。
  3. Node: Node的職責是運行容器應用。Node由Master管理,Node負責監控並彙報容器的狀態,同時根據Master的要求管理容器的生命週期。
  4. Pod: Pod是Kubernetes中最小工做單元。每一個Pod包含一個或多個容器。Pod中的容器會做爲一個總體被Master調度到一個Node上運行。
  5. Controller:Kubernetes一般不會直接建立Pod,而是經過Controller來管理Pod。Controller中定義了Pod的部署特性,好比有幾個副本、在什麼樣的Node上運行等。爲了知足不一樣的業務場景,Kubernetes提供了多種Controller,包括Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等,後面會逐個學習這些Controller
  6. Service:Service定義外界訪問一組特定Pod的方式。

建立Deployment部署應用

  1. 新建一個yaml文件,如:
apiVersion: extensions/v1beta1 # kubectl api的版本
kind: Deployment # kubernetes的資源類型
metadata:
    name: gate-deployment-dev
spec:
    replicas: 2 # 運行的Pod副本數量
    template:
        metadata:
            labels:
                app: gate-app-dev
        spec:
            containers:
                - name: gateapp
                  image: localhost:5000/gateapp:0.0.1 # Docker鏡像地址(上面建立的)
                  env: # 鏡像啓動時的環境變量
                      - name: NODE_ENV
                        value: 'development'
                      - name: HTTP_PORT
                        value: '80' # 容器http的端口 須要本身代碼中實現
複製代碼
  1. 經過kubectl apply -f xxx.yaml就能夠部署上面的Deployment的了,也能夠打開Kubernetes的Dashboard點擊建立,輸入yaml文件中的內容進行建立。通過一段時間後,在Dashboard面板中能夠看到,1個部署 gate-deployment-dev,一個副本集 gate-deployment-dev-775d556ffb,兩個容器組 gate-deployment-dev-775d556ffb-2tlgn、gate-deployment-dev-775d556ffb-sfqrq,能夠點擊查看每一個資源的信息,大部份內容都是自解釋的。數據庫

    在部署Deployment後,Kubernetes大體執行了如下幾個過程:npm

    • 用戶建立Deployment
    • Deployment建立了一個副本集(ReplicaSet)gate-deployment-dev-775d556ffb
    • ReplicaSet建立了兩個Pod,與咱們定義的replicas: 2 一致

建立Service

此時上面的鏡像提供的接口還不能供外界訪問,須要建立一個對應的Servicejson

  1. 新建立一個yaml文件或者在上一個yaml文件中添加 --- 隔開
  2. 編輯如下內容:
apiVersion: v1 # kubectl api的版本
kind: Service # kubernetes的資源類型
metadata:
    name: gate-svc-dev
spec:
    type: NodePort # service的類型 ClusterIp類型 只有Cluster內部節點和Pod能夠訪問 NodePort Cluster外部能夠經過<NodeIp>:<NodePort>訪問 LoadBalancer負載均衡
    selector:
        app: gate-app-dev # 與上面的template中定義的label一致
    ports:
        - protocol: TCP # 只有TCP 或 UDP
          port: 80 # clusterIp 監聽的端口
          nodePort: 30000 # Node 監聽的端口取值範圍 30000-32767
          targetPort: 80 # Pod 監聽的端口
複製代碼
  1. kubectl apply -f xxx.yaml 或者在Dashboard中建立api

  2. 觀察Dashboard面板,會發現多了一個名字叫gate-svc-dev的服務,提供了監聽了30000端口安全

  3. curl http://localhost:30000/whoami 能夠看到接口已經能夠訪問了bash

    須要注意的是:網絡

    • 爲何須要Service?app

      Deployment等其餘Controller動態建立和銷燬Pod來保證應用的健壯性,也就是Pod是脆弱的,應用是健壯的,咱們不應指望Pod的健壯性。每一個Pod都有本身的ClusterIp地址,當Pod發生故障被新的Pod替代時,ClusterIp頗有可能發生變化,因此若是直接讓外界訪問Pod就有問題了。

    • Service和Pod如何映射?

      經過上面的yaml定義能夠看出,Service經過 label標籤選擇器選擇對應的一堆Pod。當請求被髮送到Service上時,Service採用了某種分配策略把流量轉發到了某一個Pod上面進行處理。

    • Service有哪些類型?

      1. ClusterIp:Service經過Cluster內部的IP對外提供服務,只有Cluster內的節點和Pod能夠訪問,這是默認的類型。
      2. NodePort: Service經過Cluster節點的靜態端口對外提供服務。Cluster外部能夠經過<NodeIp>:<NodePort>訪問Service
      3. LoadBalancer: cloud provider特有的對外提供服務,後續線上部署時會講到

滾動更新

滾動更新是一次只更新一小部分副本,成功後再更新更多的副本,最終完成全部副本的更新。滾動更新最大的好處就是零停機,保證了業務的連續性。

  1. 對本地代碼進行一點改動
  2. 編譯、打標籤,並推送到本地倉庫中
echo 'Building to dits ...'
tsc

echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.2 .

echo 'Pushing ...'
docker push localhost:5000/gateapp

echo 'Docker list images ...'
docker images
複製代碼

這時候能夠看到有0.0.1 和 0.0.2兩個版本的鏡像

  1. 在Dashboard中編輯Deployment,把image: localhost:5000/gateapp:0.0.1改爲image: localhost:5000/gateapp:0.0.2,點擊更新

  2. 等待一段時間,再觀察全部的Pod都被更新成0.0.2版本的了,是否是很方便!

    反覆執行上面的步驟,不難發現更新過程當中Kubernets都作了什麼:

    • Deployment的鏡像被更新爲0.0.2版本
    • 新建立了一個名稱爲gate-deployment-dev-594468997c的ReplicaSet副本集,鏡像爲0.0.2
    • 新的ReplicaSet增長了一個Pod
    • 舊的ReplicaSet減小了一個Pod
    • 逐漸的新的ReplicaSet接管了全部舊ReplicaSet的Pod,滾動更新完成
  3. 自定義滾動更新行爲

strategy:
        rollingUpdate: # 滾動更新策略
            maxSurge: 10% # 數值越大 滾動更新時新建立的副本數量越多
            maxUnavailble: 10% # 數值越大 滾動更新時銷燬的舊副本數量越多
    replicas: 2 # 運行的Pod副本數量
複製代碼
- maxSurge:此參數控制滾動更新中副本總數超過DESIRED的數量或最大比例,數值越大 滾動更新時新建立的副本數量越多
- maxUnavailble:此參數控制滾動更新中,不可用的副本佔DESIRED的最大數量或最大利弊,數值越大 滾動更新時銷燬的舊副本數量越多
複製代碼

那若是更新過程出錯了怎麼辦?請接着往下看

健康檢查

Kubernetes有很強大的自愈能力,默認的實現方式是重啓發生故障的容器,此外用戶可使用Liveness、 Readiness的探測機制設置更爲精細的健康檢查,進而真正實現零停機部署、避免部署無效的鏡像、更加安全的滾動升級

  1. 編輯以前的Deployment.yaml,例如:
image: localhost:5000/gateapp:0.0.13
                  readinessProbe: # 一種健康檢查決定是否加入到service 對外服務
                      httpGet:
                          scheme: HTTP # 支持http https
                          path: /healthy
                          port: 80 # 與你的pod端口一致
                      initialDelaySeconds: 10 # 容器啓動多久後開始檢查
                      periodSecods: 5 # 幾秒檢查一次
複製代碼
  • readinessProbe便是使用Readiness健康探測機制,當檢查不經過時(例如接口返回的狀態碼不是200-400之間),Kubernetes就不會把容器添加到Service中供外界訪問,觀察Pod的狀態爲Not Ready。 initialDelaySeconds是決定容器啓動多久後開始檢查,一般要比啓動時間再長一些;periodSecods是多久檢查一次,連續3次探測失敗後,Ready將變成不可用,Kubernets把這個Pod從Service中下線

  • LiveNess的配置項和Readiness的同樣,不一樣之處在於探測失敗後的行爲。前者會重啓容器,後者會設置Pod不可用,並從Service中下線。

  • LiveNess和Readiness的探測是獨立使用的,兩者沒有依賴,能夠單獨使用也能夠同時使用。通常狀況下使用LiveNess判斷容器是否須要重啓實現自愈;Readiness判斷容器是否已經準備好對外提供服務。

  1. 自定義健康檢查的代碼: 自定義/healthy get接口,好比數據庫鏈接等等
@Get('healthy')
    async checkHealthy(@Res() res: Response) {
        let isHealthy = false;

        // some code to check healthy begin
        isHealthy = true;
        // check end

        const data = {
            isHealthy,
        };

        debug('執行健康檢查結果 %O', data);

        res.status(isHealthy ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR).json(data);
    }
複製代碼

一塊兒來學習Kubernetes

相信看完以上的文章,你也會認爲Kubernetes真的很是強大,是很是值得學習的。筆者也是小白一個,從0開始學習的,若是你也想一塊兒,能夠加入咱們的羣。

相關文章
相關標籤/搜索