1. 程式人生 > 其它 >一文帶你瞭解K8S 容器編排(上)

一文帶你瞭解K8S 容器編排(上)


K8S目前是業界容器編排領域的事實標準,是幾乎所有云原生架構的首選。目前隨著雲原生架構越來越流行,測試開發人員需要掌握K8S技術棧已經成為越來越迫切的需求。

Kubernetes 開源於 2014 年,是谷歌 10 多年大規模容器管理系統 Borg 的開源版本。Kubernetes 這個單詞在首字母 K 和尾字母 s 之間有 8 個字母,因此稱為 K8S。這種稱謂方式和 i18n(internationalization)是一致的,如果做過本地化國際化的人應該對 i18n 這樣的叫法很熟悉。對於一個剛剛接觸容器的初學者來說,搞清楚容器編排是什麼,搞清楚 K8S 是什麼是一件非常不容易的事情,編排二字賦予了它非常多的意義。

大多數人理解 K8S 是容器叢集的管理技術,這個描述是不完整的,如果 K8S 僅僅是一個管理多臺節點上容器的管理軟體的話,那麼業界直接稱呼為容器叢集就好了。而不是像現在這樣稱其為容器編排領域的事實標準,谷歌和 Linux 也不會為了它一起創辦了 CNCF 雲原生基金會。所以 K8S 除了是一個容器叢集管理軟體外它還提供了針對容器的網路,排程,許可權,資源,安全,硬體等管理和設計的能力。 接下來通過 2 個案例來帶大家體驗一下其中的奧妙。

01

在實際介紹 K8S 的容器編排例項前需要先了解一下 K8S 中最基本的資源型別--POD。可以說 POD 是 K8S 中最重要的資源,其他一切的資源都是圍繞著 POD 併為其提供服務的。用一句話說明 POD 的定義:POD 是由多個容器組成的邏輯概念,這些容器共同配合對外提供服務, 同時 POD 也是 K8S 中最小的排程單位,POD 中的容器必須排程在同一臺機器上不可分割。這麼說比較抽象,用一個例項來展示一下 POD 到底是什麼。通過下載並配置 jenkins 中 K8S 的外掛來打通兩者之間的通訊,使得 jenkins 在執行 pipeline 時可以動態的在 K8S 中建立 POD 並在其中一個容器中通過 jnlp 動態的建立並向 jenkins 註冊 slave 節點(容器), 後續這個 pipeline 中所有的任務都將在這個 POD 中的容器中執行。通過這樣的機制實現了更強大的 jenkins pipeline 的高可用和負載均衡架構。從此實現了在 K8S 中可以動態建立 jenkins 的 slave 節點執行任務的能力, 並在任務結束後回收這些資源。

yaml
apiVersion: "v1"
kind: "Pod"
metadata:
  name: "sdk-test-109-hpf67-tr47k-95sch"
spec:
  containers:
  - command:
    - "cat"
    image: "registry.gaofei.com/qa/python3"
    name: "python3"
    tty: true
    volumeMounts:
    - mountPath: "/home/jenkins/agent"
      name: "workspace-volume"
      readOnly: false
    image: "registry.gaofei.com/tester_jenkins_slave:v1"
    name: "jnlp"
    volumeMounts:
    - mountPath: "/home/jenkins/agent"
      name: "workspace-volume"
      readOnly: false
  volumes:
  - emptyDir:
      medium: ""
    name: "workspace-volume"

上面是 jenkins 動態建立 POD 的配置檔案,這其中為了更方便說明我刪除了很多其他干擾項,只留下了最需要關注的部分。可以看到 containers 欄位中定義兩個容器。其中名字為 jnlp 的容器是由 jenkins 提供用來與 jenkins 建立通訊並註冊 slave 節點用的。對 jenkins slave 節點配置比較熟悉的人對此應該並不陌生,除了 jnlp 外 jenkins 還支援 ssh 等協議形式的 slave 通訊機制。

另外一個名字為 python3 的容器使用的就是官方提供的 python3 映象,它的任務是用來執行測試任務。也就是說在這個 POD 中分工是明確的,jnlp 容器負責註冊 jenkins slave 節點並與之保持通訊。而 python3 容器擁有 python 的執行環境所以可以在獲取程式碼後執行諸如 pytest 這樣的測試任務。實際上如果需要可以定義更多的容器,比如要測試一款 python sdk 的相容性的時候, 可以再定義一個 python2.6 的容器,這樣在 pipeline 中可以通過切換不同的容器達到切換執行環境的目的以便測試 sdk 在 python3 和 python2 上的相容性。

下面我貼一下 jenkins pipeline 中的定義,還是照例刪減了其他干擾項。

groovy
pipeline{
    parameters {
        choice(name: 'PLATFORM_FILTER', choices: ['python352', 'python368', 'python376','all'], description: '選擇測試的 python 版本')
    }
    agent{
        kubernetes{
            yaml """
            apiVersion: v1
            kind: Pod
            metadata:
              labels:
                qa: python3
            spec:
              containers:
              - name: python352
                image: python:3.5.2
                command:
                - cat
                tty: true
              - name: python368
                image: python:3.6.8
                command:
                - cat
                tty: true
              - name: python376
                image: python:3.7.6
                command:
                - cat
                tty: true
              - name: jnlp
                image: registry.gaofie.com/tester_jenkins_slave:v1
            """
        }
    }
    stages{
        stage('sdk 相容性測試'){
            matrix {
                when { anyOf {
                    expression { params.PLATFORM_FILTER == 'all' }
                } }
                axes {
                    axis {
                        name 'PLATFORM'
                        values 'python352', 'python368','python376'


                    }
                }
                stages{
                    stage('相容性測試開始 '){
                        steps{
                          container("${PLATFORM}"){
                              echo "Testing planform ${PLATFORM}"
                              sh """
                              pip3 install -i http://pypi.xxx.com/4paradigm/dev/ --trusted-host pypi.xxx.com 'sdk[builtin-operators]'
                              pip3 install -r requirements.txt
                              cd test
                              python3 -m pytest -n 5
                              """
                          }
                        }
                    }
                }
            }


        }
    }
}

通過上面的 Pipeline 的配置可以看到通過 container 指令,可以在 pipeline 中任意的切換容器(執行環境)來完成 Python 的相容性測試。這裡可能有人可能會問執行環境可以通過切換容器來完成,但是各個容器之間是怎麼共享檔案和程式碼的呢?畢竟要執行測試必須先獲取程式碼, 那這些容器是怎麼獲取程式碼執行測試的,又是通過什麼方式合併每個容器中的測試報告的呢?這個問題可以抽象成一個 POD 中的容器是怎麼共享檔案的。在學習 Docker 的時候知道在啟動容器的時候可以通過-v 這個引數來將容器中的某個目錄或檔案掛載到宿主機上, 而在 POD 中的玩法也類似。回到上面 Jenkins 啟動的 POD 的定義中來:

yaml
    image: "registry.gaofei.com/tester_jenkins_slave:v1"
    name: "jnlp"
    volumeMounts:
    - mountPath: "/home/jenkins/agent"
      name: "workspace-volume"
      readOnly: false
  volumes:
  - emptyDir:
      medium: ""
    name: "workspace-volume"

上面是 POD 中關於資料卷的一段定義, 可以看到 jenkins 建立的 POD 定義中自動添加了一個臨時的共享目錄,而 POD 中所有的容器都會掛載這個目錄。通過這樣的形式達到了所有容器共享檔案的目的。
而這個目錄就是 Jenkins 的 Workspace。相信熟悉 Jenkins 的人對此目錄不會感到陌生。

mpdir.jpg 'tempdir')

實際上多個容器間的合作不僅可以共享目錄,也可以共享網路或者程序名稱空間。還記得學習 Docker 的時候使用的 container 網路模式麼, 實際上 POD 中的容器都是預設通過 container 模式將網路連線在一起的,很多軟體應用比如 mock server,流量複製,service mesh 都是通過在 POD 中額外定義一個 proxy 容器劫持業務容器的網路。

而如果你想使用 jvm-sandbox 這種位元組碼注入工具的話還可以通過開啟 POD 中 shareProcessNamespace 這個引數來共享程序名稱空間,使得 jvm-sandbox 容器中可以看到業務容器的程序並以 jvm-attach 的方式進行位元組碼注入。而這種通過啟動多個容器互相協作配合的玩法有一個專業名詞叫"side car"。
所以回過頭來看看什麼是 POD,什麼是容器編排?從這裡的角度看 POD 是容器之間的一種協作模式,多個容器組成一個 POD,而一個 POD 提供了多種機制,包括但不限於共享和限制目錄,網路,程序,資源等機制來讓容器之間的協作更加順暢, 而這也是容器編排的表現之一, 不僅僅是執行, 而是多個容器配合在一起更好的執行。

希望通過這篇文章,你能對K8S容器編排了有了初步的瞭解,在下篇文章中,我們將通過介紹 K8S 中專門執行批處理程式的資源型別:JOB 的機制再來體會一下容器編排在其他方面的威力。

本週六(5月15號)下午,我也將線上跟大家分享關於K8S容器編排的更多內容,歡迎大家來跟我一起探索K8S容器編排的奧妙。

⬇️ 點選“下方連結”,提升測試核心競爭力!https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=bokeyuan&timestamp=1650615531

>>更多技術文章分享和免費資料領取