久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

一文快速了解 Docker 和 Kubernetes

 hewii 2022-10-20 發(fā)布于上海
從單機(jī)容器化技術(shù) Docker 到分布式容器化架構(gòu)方案 Kubernetes,,當(dāng)今容器化技術(shù)發(fā)展盛行。本文面向小白讀者,,旨在快速帶領(lǐng)讀者了解 Docker,、Kubernetes 的架構(gòu)、原理,、組件及相關(guān)使用場景,。

Docker

1.什么是 Docker

Docker 是一個開源的應(yīng)用容器引擎,是一種資源虛擬化技術(shù),,讓開發(fā)者可以打包他們的應(yīng)用以及依賴包到一個可移植的容器中,,然后發(fā)布到任何流行的 Linux 機(jī)器上。虛擬化技術(shù)演歷路徑可分為三個時代:

  1. 物理機(jī)時代,,多個應(yīng)用程序可能跑在一臺物理機(jī)器上

  1. 虛擬機(jī)時代,,一臺物理機(jī)器啟動多個虛擬機(jī)實(shí)例,一個虛擬機(jī)跑多個應(yīng)用程序

  1. 容器化時代,,一臺物理機(jī)上啟動多個容器實(shí)例,,一個容器跑多個應(yīng)用程序

在沒有 Docker 的時代,我們會使用硬件虛擬化(虛擬機(jī))以提供隔離,。這里,,虛擬機(jī)通過在操作系統(tǒng)上建立了一個中間虛擬軟件層 Hypervisor ,并利用物理機(jī)器的資源虛擬出多個虛擬硬件環(huán)境來共享宿主機(jī)的資源,,其中的應(yīng)用運(yùn)行在虛擬機(jī)內(nèi)核上,。但是,虛擬機(jī)對硬件的利用率存在瓶頸,,因為虛擬機(jī)很難根據(jù)當(dāng)前業(yè)務(wù)量動態(tài)調(diào)整其占用的硬件資源,,加之容器化技術(shù)蓬勃發(fā)展使其得以流行。

Docker,、虛擬機(jī)對比:

特性Docker虛擬機(jī)

另外開發(fā)人員在實(shí)際的工作中,,經(jīng)常會遇到測試環(huán)境或生產(chǎn)環(huán)境與本地開發(fā)環(huán)境不一致的問題,,輕則修復(fù)保持環(huán)境一致,重則可能需要返工,。但 Docker 恰好解決了這一問題,,它將軟件程序和運(yùn)行的基礎(chǔ)環(huán)境分開。開發(fā)人員編碼完成后將程序整合環(huán)境通過 DockerFile 打包到一個容器鏡像中,,從根本上解決了環(huán)境不一致的問題,。

2.Docker 的構(gòu)成

Docker 由鏡像、鏡像倉庫,、容器三個部分組成

  • 鏡像: 跨平臺,、可移植的程序+環(huán)境包

  • 鏡像倉庫: 鏡像的存儲位置,有云端倉庫和本地倉庫之分,,官方鏡像倉庫地址(https://hub./

  • 容器: 進(jìn)行了資源隔離的鏡像運(yùn)行時環(huán)境

3.Docker 的實(shí)現(xiàn)原理

到此讀者們肯定很好奇 Docker 是如何進(jìn)行資源虛擬化的,,并且如何實(shí)現(xiàn)資源隔離的,其核心技術(shù)原理主要有(內(nèi)容部分參考自 Docker 核心技術(shù)與實(shí)現(xiàn)原理):

(1).Namespace

在日常使用 Linux 或者 macOS 時,,我們并沒有運(yùn)行多個完全分離的服務(wù)器的需要,,但是如果我們在服務(wù)器上啟動了多個服務(wù),這些服務(wù)其實(shí)會相互影響的,,每一個服務(wù)都能看到其他服務(wù)的進(jìn)程,,也可以訪問宿主機(jī)器上的任意文件,這是很多時候我們都不愿意看到的,,我們更希望運(yùn)行在同一臺機(jī)器上的不同服務(wù)能做到完全隔離,,就像運(yùn)行在多臺不同的機(jī)器上一樣。

命名空間 (Namespaces) 是 Linux 為我們提供的用于分離進(jìn)程樹,、網(wǎng)絡(luò)接口,、掛載點(diǎn)以及進(jìn)程間通信等資源的方法。Linux 的命名空間機(jī)制提供了以下七種不同的命名空間,,通過這七個選項我們能在創(chuàng)建新的進(jìn)程時設(shè)置新進(jìn)程應(yīng)該在哪些資源上與宿主機(jī)器進(jìn)行隔離,。

  1. CLONE_NEWCGROUP

  2. CLONE_NEWIPC

  3. CLONE_NEWNET

  4. CLONE_NEWNS

  5. CLONE_NEWPID

  6. CLONE_NEWUSER

  7. CLONE_NEWUTS

在 Linux 系統(tǒng)中,有兩個特殊的進(jìn)程,,一個是 pid 為 1 的 /sbin/init 進(jìn)程,,另一個是 pid 為 2 的 kthreadd 進(jìn)程,這兩個進(jìn)程都是被 Linux 中的上帝進(jìn)程 idle 創(chuàng)建出來的,,其中前者負(fù)責(zé)執(zhí)行內(nèi)核的一部分初始化工作和系統(tǒng)配置,,也會創(chuàng)建一些類似 getty 的注冊進(jìn)程,而后者負(fù)責(zé)管理和調(diào)度其他的內(nèi)核進(jìn)程,。

當(dāng)在宿主機(jī)運(yùn)行 Docker,,通過docker rundocker start創(chuàng)建新容器進(jìn)程時,會傳入 CLONE_NEWPID 實(shí)現(xiàn)進(jìn)程上的隔離,。

接著,,在方法createSpecsetNamespaces中,,完成除進(jìn)程命名空間之外與用戶、網(wǎng)絡(luò),、IPC 以及 UTS 相關(guān)的命名空間的設(shè)置,。

func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
 s := oci.DefaultSpec()

 // ...
 if err := setNamespaces(daemon, &s, c); err != nil {
  return nil, fmt.Errorf("linux spec namespaces: %v", err)
 }

 return &s, nil
}

func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error {
 // user
 // network
 // ipc
 // uts

 // pid
 if c.HostConfig.PidMode.IsContainer() {
  ns := specs.LinuxNamespace{Type: "pid"}
  pc, err := daemon.getPidContainer(c)
  if err != nil {
   return err
  }
  ns.Path = fmt.Sprintf("/proc/%d/ns/pid", pc.State.GetPID())
  setNamespace(s, ns)
 } else if c.HostConfig.PidMode.IsHost() {
  oci.RemoveNamespace(s, specs.LinuxNamespaceType("pid"))
 } else {
  ns := specs.LinuxNamespace{Type: "pid"}
  setNamespace(s, ns)
 }

 return nil
}

網(wǎng)絡(luò)

當(dāng) Docker 容器完成命名空間的設(shè)置,其網(wǎng)絡(luò)也變成了獨(dú)立的命名空間,,與宿主機(jī)的網(wǎng)絡(luò)互聯(lián)便產(chǎn)生了限制,這就導(dǎo)致外部很難訪問到容器內(nèi)的應(yīng)用程序服務(wù),。Docker 提供了 4 種網(wǎng)絡(luò)模式,,通過--net指定。

  1. host

  2. container

  3. none

  4. bridge

由于后續(xù)介紹 Kubernetes 利用了 Docker 的 bridge 網(wǎng)絡(luò)模式,,所以僅介紹該模式,。Linux 中為了方便各網(wǎng)絡(luò)命名空間的網(wǎng)絡(luò)互相訪問,設(shè)置了 Veth Pair 和網(wǎng)橋來實(shí)現(xiàn),,Docker 也是基于此方式實(shí)現(xiàn)了網(wǎng)絡(luò)通信,。

下圖中 eth0veth9953b75 是一個 Veth Pair,eth0veth3e84d4f 為另一個 Veth Pair,。Veth Pair 在容器內(nèi)一側(cè)會被設(shè)置為 eth0 模擬網(wǎng)卡,,另一側(cè)連接 Docker0 網(wǎng)橋,這樣就實(shí)現(xiàn)了不同容器間網(wǎng)絡(luò)的互通,。加之 Docker0 為每個容器配置的 iptables 規(guī)則,,又實(shí)現(xiàn)了與宿主機(jī)外部網(wǎng)絡(luò)的互通。

掛載點(diǎn)

解決了進(jìn)程和網(wǎng)絡(luò)隔離的問題,,但是 Docker 容器中的進(jìn)程仍然能夠訪問或者修改宿主機(jī)器上的其他目錄,,這是我們不希望看到的。

在新的進(jìn)程中創(chuàng)建隔離的掛載點(diǎn)命名空間需要在 clone 函數(shù)中傳入 CLONE_NEWNS,,這樣子進(jìn)程就能得到父進(jìn)程掛載點(diǎn)的拷貝,,如果不傳入這個參數(shù)子進(jìn)程對文件系統(tǒng)的讀寫都會同步回父進(jìn)程以及整個主機(jī)的文件系統(tǒng)。當(dāng)一個容器需要啟動時,,它一定需要提供一個根文件系統(tǒng)(rootfs),,容器需要使用這個文件系統(tǒng)來創(chuàng)建一個新的進(jìn)程,所有二進(jìn)制的執(zhí)行都必須在這個根文件系統(tǒng)中,,并建立一些符號鏈接來保證 IO 不會出現(xiàn)問題,。

另外,通過 Linux 的chroot命令能夠改變當(dāng)前的系統(tǒng)根目錄結(jié)構(gòu),,通過改變當(dāng)前系統(tǒng)的根目錄,,我們能夠限制用戶的權(quán)利,在新的根目錄下并不能夠訪問舊系統(tǒng)根目錄的結(jié)構(gòu)個文件,,也就建立了一個與原系統(tǒng)完全隔離的目錄結(jié)構(gòu),。

(2).Control Groups(CGroups)

Control Groups(CGroups) 提供了宿主機(jī)上物理資源的隔離,,例如 CPU、內(nèi)存,、磁盤 I/O 和網(wǎng)絡(luò)帶寬,。主要由這幾個組件構(gòu)成:

  1. 控制組(CGroup) 一個 CGroup 包含一組進(jìn)程,并可以在這個 CGroup 上增加 Linux Subsystem 的各種參數(shù)配置,,將一組進(jìn)程和一組 Subsystem 關(guān)聯(lián)起來,。

  2. Subsystem 子系統(tǒng) 是一組資源控制模塊,比如 CPU 子系統(tǒng)可以控制 CPU 時間分配,,內(nèi)存子系統(tǒng)可以限制 CGroup 內(nèi)存使用量,。可以通過lssubsys -a命令查看當(dāng)前內(nèi)核支持哪些 Subsystem,。

  3. Hierarchy 層級樹 主要功能是把 CGroup 串成一個樹型結(jié)構(gòu),,使 CGruop 可以做到繼承,每個 Hierarchy 通過綁定對應(yīng)的 Subsystem 進(jìn)行資源調(diào)度,。

  4. Task 在 CGroups 中,,task 就是系統(tǒng)的一個進(jìn)程。一個任務(wù)可以加入某個 CGroup,,也可以從某個 CGroup 遷移到另外一個 CGroup,。

在 Linux 的 Docker 安裝目錄下有一個 docker 目錄,當(dāng)啟動一個容器時,,就會創(chuàng)建一個與容器標(biāo)識符相同的 CGroup,,舉例來說當(dāng)前的主機(jī)就會有以下層級關(guān)系:

每一個 CGroup 下面都有一個 tasks 文件,其中存儲著屬于當(dāng)前控制組的所有進(jìn)程的 pid,,作為負(fù)責(zé) cpu 的子系統(tǒng),,cpu.cfs_quota_us 文件中的內(nèi)容能夠?qū)?CPU 的使用作出限制,如果當(dāng)前文件的內(nèi)容為 50000,,那么當(dāng)前控制組中的全部進(jìn)程的 CPU 占用率不能超過 50%,。

當(dāng)我們使用 Docker 關(guān)閉掉正在運(yùn)行的容器時,Docker 的子控制組對應(yīng)的文件夾也會被 Docker 進(jìn)程移除,。

(3).UnionFS

聯(lián)合文件系統(tǒng)(Union File System),,它可以把多個目錄內(nèi)容聯(lián)合掛載到同一個目錄下,而目錄的物理位置是分開的,。UnionFS 可以把只讀和可讀寫文件系統(tǒng)合并在一起,,具有寫時復(fù)制功能,允許只讀文件系統(tǒng)的修改可以保存到可寫文件系統(tǒng)當(dāng)中,。Docker 之前使用的為 AUFS(Advanced UnionFS),,現(xiàn)為 Overlay2。

Docker 中的每一個鏡像都是由一系列只讀的層組成的,,Dockerfile 中的每一個命令都會在已有的只讀層上創(chuàng)建一個新的層:

FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py

容器中的每一層都只對當(dāng)前容器進(jìn)行了非常小的修改,,上述的 Dockerfile 文件會構(gòu)建一個擁有四層 layer 的鏡像:

當(dāng)鏡像被 命令創(chuàng)建時就會在鏡像的最上層添加一個可寫的層,,也就是容器層,所有對于運(yùn)行時容器的修改其實(shí)都是對這個容器讀寫層的修改,。容器和鏡像的區(qū)別就在于,,所有的鏡像都是只讀的,而每一個容器其實(shí)等于鏡像加上一個可讀寫的層,,也就是同一個鏡像可以對應(yīng)多個容器,。

Kubernetes

Kubernetes,簡稱 K8s,,其中 8 代指中間的 8 個字符,。Kubernetes 項目龐大復(fù)雜,文章不能面面俱到,,因此這個部分將向讀者提供一種主線學(xué)習(xí)思路:
  • 什么是 Kubernetes,?

  • Kubernetes 提供的組件及適用場景

  • Kubernetes 的架構(gòu)

  • Kubernetes 架構(gòu)模塊實(shí)現(xiàn)原理

有更多未交代或淺嘗輒止的地方讀者可以查閱文章或書籍深入研究,。

1.為什么要 Kubernetes

盡管 Docker 為容器化的應(yīng)用程序提供了開放標(biāo)準(zhǔn),,但隨著容器越來越多出現(xiàn)了一系列新問題:

  • 單機(jī)不足以支持更多的容器

  • 分布式環(huán)境下容器如何通信?

  • 如何協(xié)調(diào)和調(diào)度這些容器,?

  • 如何在升級應(yīng)用程序時不會中斷服務(wù),?

  • 如何監(jiān)視應(yīng)用程序的運(yùn)行狀況?

  • 如何批量重新啟動容器里的程序,?

  • ...

Kubernetes 應(yīng)運(yùn)而生,。

2.什么是 Kubernetes

Kubernetes 是一個全新的基于容器技術(shù)的分布式架構(gòu)方案,這個方案雖然還很新,,但卻是 Google 十幾年來大規(guī)模應(yīng)用容器技術(shù)的經(jīng)驗積累和升華的重要成果,,確切的說是 Google 一個久負(fù)盛名的內(nèi)部使用的大規(guī)模集群管理系統(tǒng)——Borg 的開源版本,其目的是實(shí)現(xiàn)資源管理的自動化以及跨數(shù)據(jù)中心的資源利用率最大化,。

Kubernetes 具有完備的集群管理能力,,包括多層次的安全防護(hù)和準(zhǔn)入機(jī)制、多租戶應(yīng)用支撐能力,、透明的服務(wù)注冊和服務(wù)發(fā)現(xiàn)機(jī)制,、內(nèi)建的智能負(fù)載均衡器、強(qiáng)大的故障發(fā)現(xiàn)和自我修復(fù)能力,、服務(wù)滾動升級和在線擴(kuò)容能力,、可擴(kuò)展的資源自動調(diào)度機(jī)制,以及多力度的資源配額管理能力,。同時,,Kubernetes 提供了完善的管理工具,這些工具涵蓋了包括開發(fā),、部署測試,、運(yùn)維監(jiān)控在內(nèi)的各個環(huán)節(jié),,不僅是一個全新的基于容器技術(shù)的分布式架構(gòu)解決方案,還是一個一站式的完備分布式系統(tǒng)開發(fā)和支撐平臺,。

3.Kubernetes 術(shù)語

(1).Pod

Pod 是 Kubernetes 最重要的基本概念,,可由多個容器(一般而言一個容器一個進(jìn)程,不建議一個容器多個進(jìn)程)組成,,它是系統(tǒng)中資源分配和調(diào)度的最小單位,。下圖是 Pod 的組成示意圖,其中有一個特殊的 Pause 容器:

Pause 容器的狀態(tài)標(biāo)識了一個 Pod 的狀態(tài),,也就是代表了 Pod 的生命周期,。另外 Pod 中其余容器共享 Pause 容器的命名空間,使得 Pod 內(nèi)的容器能夠共享 Pause 容器的 IP,,以及實(shí)現(xiàn)文件共享,。以下是一個 Pod 的定義:

apiVersion: v1  # 分組和版本
kind: Pod       # 資源類型
metadata:
  name: myWeb   # Pod名
  labels:
    app: myWeb # Pod的標(biāo)簽
spec:
  containers:
  - name: myWeb # 容器名
    image: kubeguide/tomcat-app:v1  # 容器使用的鏡像
    ports:
    - containerPort: 8080 # 容器監(jiān)聽的端口
    env:  # 容器內(nèi)環(huán)境變量
    - name: MYSQL_SERVICE_HOST
      value: 'mysql'
    - name: MYSQL_SERVICE_PORT
      value: '3306'
    resources:   # 容器資源配置
      requests:  # 資源下限,m表示cpu配額的最小單位,,為1/1000核
        memory: "64Mi"
        cpu: "250m"
      limits:    # 資源上限
        memory: "128Mi"
        cpu: "500m"
EndPoint : PodIP + containerPort,,代表一個服務(wù)進(jìn)程的對外通信地址。一個 Pod 也存在具有多個 Endpoint 的情 況,,比如當(dāng)我們把 Tomcat 定義為一個 Pod 時,,可以對外暴露管理端口與服務(wù)端口這兩個 Endpoint。

(2).Label

Label 是 Kubernetes 系統(tǒng)中的一個核心概念,,一個 Label 表示一個 key=value 的鍵值對,,key、value 的值由用戶指定,。Label 可以被附加到各種資源對象上,,例如 Node、Pod,、Service,、RC 等,一個資源對 象可以定義任意數(shù)量的 Label,,同一個 Label 也可以被添加到任意數(shù)量的資源對象上,。Label 通常在資源對象定義時確定,也可以在對象創(chuàng)建后動態(tài)添加或者刪除,。給一個資源對象定義了 Label 后,,我們隨后可以通過 Label Selector 查詢和篩選擁有這個 Label 的資源對象,來實(shí)現(xiàn)多維度的資源分組管理功能,,以便靈活,、方便地進(jìn)行資源分配、調(diào) 度、配置,、部署等管理工作,。

Label Selector 當(dāng)前有兩種表達(dá)式,基于等式的和基于集合的:

  • name=redis-slave: 匹配所有具有標(biāo)簽name=redis-slave的資源對象,。

  • env!=production: 匹配所有不具有標(biāo)簽env=production的資源對象,。

  • name in(redis-master, redis-slave):name=redis-master或者name=redis-slave的資源對象。

  • name not in(php-frontend):匹配所有不具有標(biāo)簽name=php-frontend的資源對象,。

以 myWeb Pod 為例:

apiVersion: v1  # 分組和版本
kind: Pod       # 資源類型
metadata:
  name: myWeb   # Pod名
  labels:
    app: myWeb # Pod的標(biāo)簽

當(dāng)一個 Service 的 selector 中指明了這個 Pod 時,,該 Pod 就會與該 Service 綁定

apiVersion: v1
kind: Service
metadata:
  name: myWeb
spec:
  selector:
    app: myWeb
  ports:
  - port: 8080

(3).Replication Controller

Replication Controller,簡稱 RC,,簡單來說,,它其實(shí)定義了一個期望的場景,即聲明某種 Pod 的副本數(shù)量在任意時刻都符合某個預(yù)期值,。

RC 的定義包括如下幾個部分:

  • Pod 期待的副本數(shù)量

  • 用于篩選目標(biāo) Pod 的 Label Selector

  • 當(dāng) Pod 的副本數(shù)小于預(yù)期數(shù)量時,,用于創(chuàng)建新 Pod 的模版(template)

apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
spec:
  replicas: 3  # Pod 副本數(shù)量
  selector:
    app: frontend
  template:   # Pod 模版
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: tomcat_demp
        image: tomcat
        ports:
        - containerPort: 8080

當(dāng)提交這個 RC 在集群中后,Controller Manager 會定期巡檢,,確保目標(biāo) Pod 實(shí)例的數(shù)量等于 RC 的預(yù)期值,,過多的數(shù)量會被停掉,少了則會創(chuàng)建補(bǔ)充,。通過kubectl scale可以動態(tài)指定 RC 的預(yù)期副本數(shù)量,。

目前,,RC 已升級為新概念——Replica Set(RS),,兩者當(dāng)前唯一區(qū)別是,RS 支持了基于集合的 Label Selector,,而 RC 只支持基于等式的 Label Selector,。RS 很少單獨(dú)使用,更多是被 Deployment 這個更高層的資源對象所使用,,所以可以視作 RS+Deployment 將逐漸取代 RC 的作用,。

(4).Deployment

Deployment 和 RC 相似度超過 90%,無論是作用,、目的,、Yaml 定義還是具體命令行操作,所以可以將其看作是 RC 的升級,。而 Deployment 相對于 RC 的一個最大區(qū)別是我們可以隨時知道當(dāng)前 Pod“部署”的進(jìn)度,。實(shí)際上由于一個 Pod 的創(chuàng)建、調(diào)度,、綁定節(jié)點(diǎn)及在目 標(biāo) Node 上啟動對應(yīng)的容器這一完整過程需要一定的時間,,所以我們期待系統(tǒng)啟動 N 個 Pod 副本的目標(biāo)狀態(tài),實(shí)際上是一個連續(xù)變化的“部署過程”導(dǎo)致的最終狀態(tài),。

apiVersion: v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
    matchExpressions:
      - {key: app, operator: In, values [frontend]}
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: tomcat_demp
        image: tomcat
        ports:
        - containerPort: 8080

(5).Horizontal Pod Autoscaler

除了手動執(zhí)行kubectl scale完成 Pod 的擴(kuò)縮容之外,,還可以通過 Horizontal Pod Autoscaling(HPA)橫向自動擴(kuò)容來進(jìn)行自動擴(kuò)縮容,。其原理是追蹤分析目標(biāo) Pod 的負(fù)載變化情況,來確定是否需要針對性地調(diào)整目標(biāo) Pod 數(shù)量,。當(dāng)前,,HPA 有一下兩種方式作為 Pod 負(fù)載的度量指標(biāo):

  • CPUUtilizationPercentage,目標(biāo) Pod 所有副本自身的 CPU 利用率的平均值,。

  • 應(yīng)用程序自定義的度量指標(biāo),,比如服務(wù)在每秒內(nèi)的相應(yīng)請求數(shù)(TPS 或 QPS)

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  maxReplicas: 3
  minReplicas: 1
  scaletargetRef:
    kind: Deployment
    name: php-apache
  targetCPUUtilizationPercentage: 90

根據(jù)上邊定義,當(dāng) Pod 副本的 CPUUtilizationPercentage 超過 90%時就會出發(fā)自動擴(kuò)容行為,,數(shù)量約束為 1 ~ 3 個,。

(6).StatefulSet

在 Kubernetes 系統(tǒng)中,Pod 的管理對象 RC,、Deployment,、DaemonSet 和 Job 都面向無狀態(tài)的服務(wù)。但現(xiàn)實(shí)中有很多服務(wù)是有狀態(tài)的,,特別是 一些復(fù)雜的中間件集群,,例如 MySQL 集群、MongoDB 集群,、Akka 集 群,、ZooKeeper 集群等,這些應(yīng)用集群有 4 個共同點(diǎn),。

  1. 每個節(jié)點(diǎn)都有固定的身份 ID,,通過這個 ID,集群中的成員可 以相互發(fā)現(xiàn)并通信,。

  2. 集群的規(guī)模是比較固定的,,集群規(guī)模不能隨意變動。

  3. 集群中的每個節(jié)點(diǎn)都是有狀態(tài)的,,通常會持久化數(shù)據(jù)到永久 存儲中,。

  4. 如果磁盤損壞,則集群里的某個節(jié)點(diǎn)無法正常運(yùn)行,,集群功 能受損,。

因此,StatefulSet 具有以下特點(diǎn):

  • StatefulSet 里的每個 Pod 都有穩(wěn)定,、唯一的網(wǎng)絡(luò)標(biāo)識,,可以用來 發(fā)現(xiàn)集群內(nèi)的其他成員。假設(shè) StatefulSet 的名稱為 kafka,,那么第 1 個 Pod 叫 kafka-0,,第 2 個叫 kafka-1,以此類推。

  • StatefulSet 控制的 Pod 副本的啟停順序是受控的,,操作第 n 個 Pod 時,,前 n-1 個 Pod 已經(jīng)是運(yùn)行且準(zhǔn)備好的狀態(tài)。

  • StatefulSet 里的 Pod 采用穩(wěn)定的持久化存儲卷,,通過 PV 或 PVC 來 實(shí)現(xiàn),,刪除 Pod 時默認(rèn)不會刪除與 StatefulSet 相關(guān)的存儲卷(為了保證數(shù) 據(jù)的安全)。

  • StatefulSet 除了要與 PV 卷捆綁使用以存儲 Pod 的狀態(tài)數(shù)據(jù),,還要與 Headless Service 配合使用,。
    Headless Service : Headless Service 與普通 Service 的關(guān)鍵區(qū)別在于, 它沒有 Cluster IP,,如果解析 Headless Service 的 DNS 域名,,則返回的是該 Service 對應(yīng)的全部 Pod 的 Endpoint 列表。

(7).Service

Service 在 Kubernetes 中定義了一個服務(wù)的訪問入口地址,,前段的應(yīng)用(Pod)通過這個入口地址訪問其背后的一組由 Pod 副本組成的集群實(shí)例,,Service 與其后端 Pod 副本集群之間則是通過 Label Selector 來實(shí)現(xiàn)無縫對接的。

apiVersion: v1
kind: service
metadata:
  name: tomcat_service
spec:
  ports:
  - port: 8080
   name: service_port
  - port: 8005
   name: shutdown_port
  selector:
    app: backend

Service 的負(fù)載均衡

在 Kubernetes 集群中,,每個 Node 上會運(yùn)行著 kube-proxy 組件,,這其實(shí)就是一個負(fù)載均衡器,負(fù)責(zé)把對 Service 的請求轉(zhuǎn)發(fā)到后端的某個 Pod 實(shí)例上,,并在內(nèi)部實(shí)現(xiàn)服務(wù)的負(fù)載均衡和繪畫保持機(jī)制,。其主要的實(shí)現(xiàn)就是每個 Service 在集群中都被分配了一個全局唯一的 Cluster IP,因此我們對 Service 的網(wǎng)絡(luò)通信根據(jù)內(nèi)部的負(fù)載均衡算法和會話機(jī)制,,便能與 Pod 副本集群通信,。

Service 的服務(wù)發(fā)現(xiàn)

因為 Cluster IP 在 Service 的整個聲明周期內(nèi)是固定的,所以在 Kubernetes 中,,只需將 Service 的 Name 和 其 Cluster IP 做一個 DNS 域名映射即可解決,。

(8).Volume

Volume 是 Pod 中能夠被多個容器訪問的共享目錄,,Kubernetes 中的 Volume 概念,、用途、目的與 Docker 中的 Volumn 比較類似,,但不等價,。首先,其可被定義在 Pod 上,,然后被 一個 Pod 里的多個容器掛載到具體的文件目錄下,;其次,Kubernetes 中的 Volume 與 Pod 的生命周期相同,,但與容器的生命周期不相關(guān),,當(dāng)容器終止或者重啟時,Volume 中的數(shù)據(jù)也不會丟失。

template:
  metadata:
    labels:
      app: frontend
  spec:
    volumes:  # 聲明可掛載的volume
      - name: dataVol
       emptyDir: {}
    containers:
    - name: tomcat_demo
      image: tomcat
      ports:
      - containerPort: 8080
      volumeMounts:  # 將volume通過name掛載到容器內(nèi)的/mydata-data目錄
        - mountPath: /mydata-data
         name: dataVol

Kubernetes 提供了非常豐富的 Volume 類型:

  • emptyDir,,它的初始內(nèi)容為空,,并且無須指定宿主機(jī)上對應(yīng)的目錄文件,因為這是 Kubernetes 自動分配的一個目錄,,當(dāng) Pod 從 Node 上移除 emptyDir 中的數(shù)據(jù)也會被永久刪除,,適用于臨時數(shù)據(jù)。

  • hostPath,,hostPath 為在 Pod 上掛載宿主機(jī)上的文件或目錄,,適用于持久化保存的數(shù)據(jù),比如容器應(yīng)用程序生成的日志文件,。

  • NFS,,可使用 NFS 網(wǎng)絡(luò)文件系統(tǒng)提供的共享目錄存儲數(shù)據(jù)。

  • 其他云持久化盤等

(9).Persistent Volume

在使用虛擬機(jī)的情況下,,我們通常會先定義一個網(wǎng)絡(luò)存儲,,然后從中 劃出一個“網(wǎng)盤”并掛接到虛擬機(jī)上。Persistent Volume(PV) 和與之相關(guān)聯(lián)的 Persistent Volume Claim(PVC) 也起到了類似的作用,。PV 可以被理解成 Kubernetes 集群中的某個網(wǎng)絡(luò)存儲對應(yīng)的一塊存儲,,它與 Volume 類似,但有以下區(qū)別:

  • PV 只能是網(wǎng)絡(luò)存儲,,不屬于任何 Node,,但可以在每個 Node 上訪問。

  • PV 并不是被定義在 Pod 上的,,而是獨(dú)立于 Pod 之外定義的,。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  spec:
    capacity:
      storage: 5Gi
    accessMods:
      - ReadWriteOnce
    nfs:
      path: /somePath
      server: xxx.xx.xx.x
accessModes,有幾種類型,,1.ReadWriteOnce:讀寫權(quán)限,,并且只能被單個 Node 掛載。 2. ReadOnlyMany:只讀權(quán)限,,允許被多個 Node 掛載,。 3.ReadWriteMany:讀寫權(quán)限,允許被多個 Node 掛載,。

如果 Pod 想申請某種類型的 PV,,首先需要定義一個 PersistentVolumeClaim 對象,

apiVersion: v1
kind: PersistentVolumeClaim  # 聲明pvc
metadata:
  name: pvc001
  spec:
    resources:
      requests:
        storage: 5Gi
    accessMods:
      - ReadWriteOnce

然后在 Pod 的 Volume 中引用 PVC 即可,。

volumes:
  - name: mypd
   persistentVolumeClaim:
     claimName: pvc001

PV 有以下幾種狀態(tài):

  • Available:空閑

  • Bound:已綁定到 PVC

  • Relead:對應(yīng) PVC 被刪除,,但 PV 還沒被回收

  • Faild: PV 自動回收失敗

(10).Namespace

Namespace 在很多情況下用于實(shí)現(xiàn)多租戶的資源隔離。分組的不同項目,、小組或用戶組,,便于不同的分組在共享使用整個集群的資源的同時還能被分別管理,。Kubernetes 集群在啟動后會創(chuàng)建一個名為 default 的 Namespace,通過 kubectl 可以查看:

(11).ConfigMap

我們知道,,Docker 通過將程序,、依賴庫、數(shù)據(jù)及 配置文件“打包固化”到一個不變的鏡像文件中的做法,,解決了應(yīng)用的部署的難題,,但這同時帶來了棘手的問題,即配置文件中的參數(shù)在運(yùn)行期如何修改的問題,。我們不可能在啟動 Docker 容器后再修改容器里的配置 文件,,然后用新的配置文件重啟容器里的用戶主進(jìn)程。為了解決這個問題,,Docker 提供了兩種方式:

  • 在運(yùn)行時通過容器的環(huán)境變量來傳遞參數(shù);

  • 通過 Docker Volume 將容器外的配置文件映射到容器內(nèi),。

在大多數(shù)情況下,后一種方式更合 適我們的系統(tǒng),,因為大多數(shù)應(yīng)用通常從一個或多個配置文件中讀取參數(shù),。但這種方式也有明顯的缺陷:我們必須在目標(biāo)主機(jī)上先創(chuàng)建好對應(yīng) 配置文件,然后才能映射到容器里,。上述缺陷在分布式情況下變得更為嚴(yán)重,,因為無論采用哪種方式, 寫入(修改)多臺服務(wù)器上的某個指定文件,,并確保這些文件保持一致,,都是一個很難完成的目標(biāo)。針對上述問題,, Kubernetes 給出了一個很巧妙的設(shè)計實(shí)現(xiàn),。

首先,把所有的配置項都當(dāng)作 key-value 字符串,,這些配置項可以 作為 Map 表中的一個項,,整個 Map 的數(shù)據(jù)可以被持久化存儲在 Kubernetes 的 Etcd 數(shù)據(jù)庫中,然后提供 API 以方便 Kubernetes 相關(guān)組件或 客戶應(yīng)用 CRUD 操作這些數(shù)據(jù),,上述專門用來保存配置參數(shù)的 Map 就是 Kubernetes ConfigMap 資源對象,。Kubernetes 提供了一種內(nèi)建機(jī)制,將存儲在 etcd 中的 ConfigMap 通過 Volume 映射的方式變成目標(biāo) Pod 內(nèi)的配置文件,,不管目標(biāo) Pod 被調(diào)度到哪臺服務(wù)器上,,都會完成自動映射。進(jìn)一步地,,如果 ConfigMap 中的 key-value 數(shù)據(jù)被修改,則映射到 Pod 中的“配置文件”也會隨之自動更新,。

4.Kubernetes 的架構(gòu)

Kubernetes 由 Master 節(jié)點(diǎn),、 Node 節(jié)點(diǎn)以及外部的 ETCD 集群組成,,集群的狀態(tài)、資源對象,、網(wǎng)絡(luò)等信息存儲在 ETCD 中,,Mater 節(jié)點(diǎn)管控整個集群,包括通信,、調(diào)度等,,Node 節(jié)點(diǎn)為工作真正執(zhí)行的節(jié)點(diǎn),并向主節(jié)點(diǎn)報告,。Master 節(jié)點(diǎn)由以下組件構(gòu)成:

(1).Master 組件:

  1. API Server —— 提供 HTTP Rest 接口,,是所有資源增刪改查和集群控制的唯一入口。(在集群中表現(xiàn)為名稱是 kubernetes 的 service),??梢酝ㄟ^ Dashboard 的 UI 或 kubectl 工具來與其交互。 (1)集群管理的 API 入口,;
    (2)資源配額控制入口,;
    (3)提供完備的集群安全機(jī)制。

  2. Controller Manager —— 資源對象的控制自動化中心,。即監(jiān)控 Node,,當(dāng)故障時轉(zhuǎn)移資源對象,自動修復(fù)集群到期望狀態(tài),。

  3. Scheduler —— 負(fù)責(zé) Pod 的調(diào)度,,調(diào)度到最優(yōu)的 Node。

(2).Node 組件:

  1. kubelet —— 負(fù)責(zé) Pod 內(nèi)容器的創(chuàng)建,、啟停,,并與 Master 密切協(xié)作實(shí)現(xiàn)集群管理(注冊自己,匯報 Node 狀態(tài)),。

  2. kube-proxy —— 實(shí)現(xiàn) k8s Service 的通信與負(fù)載均衡,。

  3. Docker Engine —— Docker 引擎,負(fù)責(zé)本機(jī)容器的創(chuàng)建和管理,。

5.Kubernetes 架構(gòu)模塊實(shí)現(xiàn)原理

(1).API Server

Kubernetes API Server 通過一個名為 kube-apiserver 的進(jìn)程提供服務(wù),,該進(jìn)程運(yùn)行在 Master 上。在默認(rèn)情況下,,kube-apiserver 進(jìn)程在本機(jī)的 8080 端口(對應(yīng)參數(shù)--insecure-port)提供 REST 服務(wù),。我們可以同時啟動 HTTPS 安全端口(--secure-port=6443)來啟動安全機(jī)制,加強(qiáng) REST API 訪問的安全性,。

由于 API Server 是 Kubernetes 集群數(shù)據(jù)的唯一訪問入口,,因此安全性與高性能就成為 API Server 設(shè)計和實(shí)現(xiàn)的兩大核心目標(biāo)。通過采用 HTTPS 安全傳輸通道與 CA 簽名數(shù)字證書強(qiáng)制雙向認(rèn)證的方式,,API Server 的安全性得以保障,。此外,,為了更細(xì)粒度地控制用戶或應(yīng)用對 Kubernetes 資源對象的訪問權(quán)限,Kubernetes 啟用了 RBAC 訪問控制策略,。Kubernetes 的設(shè)計者綜合運(yùn)用以下方式來最大程度地保證 API Server 的性 能,。

  1. API Server 擁有大量高性能的底層代碼。在 API Server 源碼中 使用協(xié)程(Coroutine)+隊列(Queue)這種輕量級的高性能并發(fā)代碼,, 使得單進(jìn)程的 API Server 具備了超強(qiáng)的多核處理能力,,從而以很快的速 度并發(fā)處理大量的請求。

  2. 普通 List 接口結(jié)合異步 Watch 接口,,不但完美解決了 Kubernetes 中各種資源對象的高性能同步問題,,也極大提升了 Kubernetes 集群實(shí)時響應(yīng)各種事件的靈敏度。

  3. 采用了高性能的 etcd 數(shù)據(jù)庫而非傳統(tǒng)的關(guān)系數(shù)據(jù)庫,,不僅解決 了數(shù)據(jù)的可靠性問題,,也極大提升了 API Server 數(shù)據(jù)訪問層的性能。在 常見的公有云環(huán)境中,,一個 3 節(jié)點(diǎn)的 etcd 集群在輕負(fù)載環(huán)境中處理一個請 求的時間可以低于 1ms,,在重負(fù)載環(huán)境中可以每秒處理超過 30000 個請求。

(2).安全認(rèn)證

RBAC

Role-Based Access Control(RBAC),,基于角色的訪問控制,。

4 種資源對象

  1. Role

  2. RoleBinding

  3. ClusterRole

  4. ClusterRoleBinding

Role 與 ClusterRole

一個角色就是一組權(quán)限的集合,都是以許可形式,,不存在拒絕的規(guī)則,。Role 作用于一個命名空間中,ClusterRole 作用于整個集群,。

apiVersion:rbac.authorization.k8s.io/v1beta1
kind:Role
metadata:
  namespace: default #ClusterRole可以省略,,畢竟是作用于整個集群
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pod"]
  verbs: ["get","watch","list"]

RoleBinding 和 ClusterRoleBinding 是把 Role 和 ClusterRole 的權(quán)限綁定到 ServiceAccount 上。

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
    namespace: default
    name: app-admin
subjects:
-   kind: ServiceAccount
    name: app
    apiGroup: ""
    namespace: default
roleRef:
    kind: ClusterRole
    name: cluster-admin
    apiGroup: rbac.authorization.k8s.io

ServiceAccount

Service Account 也是一種賬號,,但它并不是給 Kubernetes 集群的用戶 (系統(tǒng)管理員,、運(yùn)維人員、租戶用戶等)用的,,而是給運(yùn)行在 Pod 里的進(jìn)程用的,,它為 Pod 里的進(jìn)程提供了必要的身份證明。在每個 Namespace 下都有一個名為 default 的默認(rèn) Service Account 對象,,在這個 Service Account 里面有一個名為 Tokens 的可以當(dāng)作 Volume 被掛載到 Pod 里的 Secret,,當(dāng) Pod 啟動時,這個 Secret 會自動被掛載到 Pod 的指定目錄下,,用來協(xié)助完成 Pod 中的進(jìn)程訪問 API Server 時的身份鑒權(quán),。

(3).Controller Manager

下邊介紹幾種 Controller Manager 的實(shí)現(xiàn)組件

ResourceQuota Controller

kubernetes 的配額管理使用過 Admission Control 來控制的,提供了兩種約束,,LimitRanger 和 ResourceQuota,。LimitRanger 作用于 Pod 和 Container 之上(limit ,request),,ResourceQuota 則作用于 Namespace,。 資源配額,,分三個層次:

  1. 容器級別,對容器的 CPU,、memory 做限制

  2. Pod 級別,,對一個 Pod 內(nèi)所有容器的可用資源做限制

  3. Namespace 級別,為 namespace 做限制,,包括:

+ pod數(shù)量
    + RC數(shù)量
    + Service數(shù)量
    + ResourceQuota數(shù)量
    + Secrete數(shù)量
    + PV數(shù)量

Namespace Controller

管理 Namesoace 創(chuàng)建刪除.

Endpoints Controller

Endpoints 表示一個 service 對應(yīng)的所有 Pod 副本的訪問地址,,而 Endpoints Controller 就是負(fù)責(zé)生成和維護(hù)所有 Endpoints 對象的控制器。

  • 負(fù)責(zé)監(jiān)聽 Service 和對應(yīng) Pod 副本的變化,,若 Service 被創(chuàng)建,、更新、刪除,,則相應(yīng)創(chuàng)建,、更新、刪除與 Service 同名的 Endpoints 對象,。

  • EndPoints 對象被 Node 上的 kube-proxy 使用,。

(4).Scheduler

Kubernetes Scheduler 的作用是將待調(diào)度的 Pod(API 新創(chuàng) 建的 Pod、Controller Manager 為補(bǔ)足副本而創(chuàng)建的 Pod 等)按照特定的調(diào) 度算法和調(diào)度策略綁定(Binding)到集群中某個合適的 Node 上,,并將綁定信息寫入 etcd 中,。Kubernetes Scheduler 當(dāng)前提供的默認(rèn)調(diào)度流程分為以下兩步。

  1. 預(yù)選調(diào)度過程,,即遍歷所有目標(biāo) Node,,篩選出符合要求的候 選節(jié)點(diǎn)。為此,,Kubernetes 內(nèi)置了多種預(yù)選策略(xxx Predicates)供用戶選擇,。

  2. 確定最優(yōu)節(jié)點(diǎn),在第 1 步的基礎(chǔ)上,,采用優(yōu)選策略(xxx Priority)計算出每個候選節(jié)點(diǎn)的積分,,積分最高者勝出。

(5).網(wǎng)絡(luò)

Kubernetes 的網(wǎng)絡(luò)利用了 Docker 的網(wǎng)絡(luò)原理,,并在此基礎(chǔ)上實(shí)現(xiàn)了跨 Node 容器間的網(wǎng)絡(luò)通信,。

  1. 同一個 Node 下 Pod 間通信模型:

  1. 不同 Node 下 Pod 間的通信模型(CNI 模型實(shí)現(xiàn)):

CNI 提供了一種應(yīng)用容器的插件化網(wǎng)絡(luò)解決方案,定義對容器網(wǎng)絡(luò) 進(jìn)行操作和配置的規(guī)范,,通過插件的形式對 CNI 接口進(jìn)行實(shí)現(xiàn),,以 Flannel 舉例,完成了 Node 間容器的通信模型,。

可以看到,,F(xiàn)lannel 首先創(chuàng)建了一個名為 flannel0 的網(wǎng)橋,,而且這個 網(wǎng)橋的一端連接 docker0 網(wǎng)橋,另一端連接一個叫作 flanneld 的服務(wù)進(jìn)程,。flanneld 進(jìn)程并不簡單,,它上連 etcd,利用 etcd 來管理可分配的 IP 地 址段資源,,同時監(jiān)控 etcd 中每個 Pod 的實(shí)際地址,,并在內(nèi)存中建立了一 個 Pod 節(jié)點(diǎn)路由表;它下連 docker0 和物理網(wǎng)絡(luò),使用內(nèi)存中的 Pod 節(jié)點(diǎn) 路由表,,將 docker0 發(fā)給它的數(shù)據(jù)包包裝起來,,利用物理網(wǎng)絡(luò)的連接將 數(shù)據(jù)包投遞到目標(biāo) flanneld 上,從而完成 Pod 到 Pod 之間的直接地址通信,。

(6).服務(wù)發(fā)現(xiàn)

從 Kubernetes 1.11 版本開始,,Kubernetes 集群的 DNS 服務(wù)由 CoreDNS 提供。CoreDNS 是 CNCF 基金會的一個項目,,是用 Go 語言實(shí)現(xiàn)的高性能,、插件式、易擴(kuò)展的 DNS 服務(wù)端,。

結(jié)語

文章包含的內(nèi)容說多不多,,說少不少,但對于 Docker,、Kubernetes 知識原理的小白來說是足夠的,,筆者按照自己的學(xué)習(xí)經(jīng)驗,以介紹為出發(fā)點(diǎn),,讓大家更能了解相關(guān)技術(shù)原理,,所以實(shí)操的部分較少。Kubernetes 技術(shù)組件還是十分豐富的,,文章有選擇性地進(jìn)行了介紹,,感興趣的讀者可以再自行從官方或者書籍中學(xué)習(xí)了解。(附《Kubernetes 權(quán)威指南——從 Docker 到 Kubernetes 實(shí)踐全接觸》第四版)

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多