K8s 一、(1、容器基本概念 2、k8s基本概念 )


1、容器基本概念

容器其實就是一種特殊的進程,容器是一個 ‘單進程’模型。

 

Namespace :隔離 Namespace 技術實際上修改了應用進程看待整個計算機“視圖”,即它的“視線”被操作系統做了限制,只能“看到”某些指定的內容

Linux Cgroups :限制  它最主要的作用,就是限制一個進程組能夠使用的資源上限,包括 CPU、內存、磁盤、網絡帶寬等等。 

 

通過修改 配置文件來限制某個進程的可使用的資源

可以看到,在 /sys/fs/cgroup 下面有很多諸如 cpuset、cpu、 memory 這樣的子目錄,也叫子系統。這些都是我這台機器當前可以被 Cgroups 進行限制的資源種類。而在子系統對應的資源種類下,你就可以看到該類資源具體可以被限制的方法。比如,對 CPU 子系統來說,我們就可以看到如下幾個配置文件,這個指令是:

 ls /sys/fs/cgroup/cpu
cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us  cpu.shares notify_on_release
cgroup.procs      cpu.cfs_quota_us  cpu.rt_runtime_us cpu.stat  tasks

如果熟悉 Linux CPU 管理的話,你就會在它的輸出里注意到 cfs_period 和 cfs_quota 這樣的關鍵詞。這兩個參數需要組合使用,可以用來限制進程在長度為 cfs_period 的一段時間內,只能被分配到總量為 cfs_quota 的 CPU 時間。

 

-1代表不限制

$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us 
-1
$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_period_us 
100000

接下來,我們可以通過修改這些文件的內容來設置限制。

比如,向 container 組里的 cfs_quota 文件寫入 20 ms(20000 us):

$ echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us

 

它意味着在每 100 ms 的時間里,被該控制組限制的進程只能使用 20 ms 的 CPU 時間,也就是說這個進程只能使用到 20% 的 CPU 帶寬。

接下來,我們把被限制的進程的 PID 寫入 container 組里的 tasks 文件,上面的設置就會對該進程生效了:

$ echo 226 > /sys/fs/cgroup/cpu/container/tasks 

可以看到,計算機的 CPU 使用率立刻降到了 20%(%Cpu0 : 20.3 us)。

除 CPU 子系統外,Cgroups 的每一項子系統都有其獨有的資源限制能力,比如:

  • blkio,為​​​塊​​​設​​​備​​​設​​​定​​​I/O 限​​​制,一般用於磁盤等設備;
  • cpuset,為進程分配單獨的 CPU 核和對應的內存節點;
  • memory,為進程設定內存使用的限制。

Linux Cgroups 的設計還是比較易用的,簡單粗暴地理解呢,它就是一個子系統目錄加上一組資源限制文件的組合。而對於 Docker 等 Linux 容器項目來說,它們只需要在每個子系統下面,為每個容器創建一個控制組(即創建一個新目錄),然后在啟動容器進程之后,把這個進程的 PID 填寫到對應控制組的 tasks 文件中就可以了。

當然這些如果使用Kubernetes 這些都會幫咱們做了 

 

Mount Namespace 和 rootfs :夠為進程構建出一個完善的文件系統隔離環境

容器的rootfs由下圖所示的三部分組成:

第一部分,只讀層。

它是這個容器的 rootfs 最下面的五層,對應的正是 ubuntu:latest 鏡像的五層。可以看到,它們的掛載方式都是只讀的(ro+wh,即 readonly+whiteout,至於什么是 whiteout,我下面馬上會講到)。

這時,我們可以分別查看一下這些層的內容:

$ ls /var/lib/docker/aufs/diff/72b0744e06247c7d0...
etc sbin usr var
$ ls /var/lib/docker/aufs/diff/32e8e20064858c0f2...
run
$ ls /var/lib/docker/aufs/diff/a524a729adadedb900...
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

可以看到,這些層,都以增量的方式分別包含了 Ubuntu 操作系統的一部分。

第二部分,可讀寫層。

它是這個容器的 rootfs 最上面的一層(6e3be5d2ecccae7cc),它的掛載方式為:rw,即 read write。在沒有寫入文件之前,這個目錄是空的。而一旦在容器里做了寫操作,你修改產生的內容就會以增量的方式出現在這個層中。

可是,你有沒有想到這樣一個問題:如果我現在要做的,是刪除只讀層里的一個文件呢?

為了實現這樣的刪除操作,AuFS 會在可讀寫層創建一個 whiteout 文件,把只讀層里的文件“遮擋”起來。

比如,你要刪除只讀層里一個名叫 foo 的文件,那么這個刪除操作實際上是在可讀寫層創建了一個名叫.wh.foo 的文件。這樣,當這兩個層被聯合掛載之后,foo 文件就會被.wh.foo 文件“遮擋”起來,“消失”了。這個功能,就是“ro+wh”的掛載方式,即只讀 +whiteout 的含義。我喜歡把 whiteout 形象地翻譯為:“白障”。

所以,最上面這個可讀寫層的作用,就是專門用來存放你修改 rootfs 后產生的增量,無論是增、刪、改,都發生在這里。而當我們使用完了這個被修改過的容器之后,還可以使用 docker commit 和 push 指令,保存這個被修改過的可讀寫層,並上傳到 Docker Hub 上,供其他人使用;而與此同時,原先的只讀層里的內容則不會有任何變化。這,就是增量 rootfs 的好處

第三部分,Init 層。

它是一個以“-init”結尾的層,夾在只讀層和讀寫層之間。Init 層是 Docker 項目單獨生成的一個內部層,專門用來存放 /etc/hosts、/etc/resolv.conf 等信息。

需要這樣一層的原因是,這些文件本來屬於只讀的 Ubuntu 鏡像的一部分,但是用戶往往需要在啟動容器時寫入一些指定的值比如 hostname,所以就需要在可讀寫層對它們進行修改。

可是,這些修改往往只對當前的容器有效,我們並不希望執行 docker commit 時,把這些信息連同可讀寫層一起提交掉。

所以,Docker 做法是,在修改了這些文件之后,以一個單獨的層掛載了出來。而用戶執行 docker commit 只會提交可讀寫層,所以是不包含這些內容的。

最終,這 7 個層都被聯合掛載到 /var/lib/docker/aufs/mnt 目錄下,表現為一個完整的 Ubuntu 操作系統供容器使用。

虛擬機與容器的對比圖

這幅圖的左邊,畫出了虛擬機的工作原理。其中,名為 Hypervisor 的軟件是虛擬機最主要的部分。它通過硬件虛擬化功能,模擬出了運行一個操作系統需要的各種硬件,比如 CPU、內存、I/O 設備等等。然后,它在這些虛擬的硬件上安裝了一個新的操作系統,即 Guest OS。

這樣,用戶的應用進程就可以運行在這個虛擬的機器中,它能看到的自然也只有 Guest OS 的文件和目錄,以及這個機器里的虛擬設備。這就是為什么虛擬機也能起到將不同的應用進程相互隔離的作用。

而這幅圖的右邊,則用一個名為 Docker Engine 的軟件替換了 Hypervisor。這也是為什么,很多人會把 Docker 項目稱為“輕量級”虛擬化技術的原因,實際上就是把虛擬機的概念套在了容器上。

 2、k8s基本概念

Kubernetes 項目最主要的設計思想是,從更宏觀的角度,以統一的方式來定義任務之間的各種關系,並且為將來支持更多種類的關系留有余地。

Kubernetes 項目核心功能的“全景圖”。

 Kubernetes 項目中,我們所推崇的使用方法是:

  • 首先,通過一個“編排對象”,比如 Pod、Job、CronJob 等,來描述你試圖管理的應用;
  • 然后,再為它定義一些“服務對象”,比如 Service、Secret、Horizontal Pod Autoscaler(自動水平擴展器)等。這些對象,會負責具體的平台級功能。

這種使用方法,就是所謂的“聲明式 API”。這種 API 對應的“編排對象”和“服務對象”,都是 Kubernetes 項目中的 API 對象(API Object)。

 

例子:

最后,我來回答一個更直接的問題:Kubernetes 項目如何啟動一個容器化任務呢?

比如,我現在已經制作好了一個 Nginx 容器鏡像,希望讓平台幫我啟動這個鏡像。並且,我要求平台幫我運行兩個完全相同的 Nginx 副本,以負載均衡的方式共同對外提供服務。

  • 如果是自己 DIY 的話,可能需要啟動兩台虛擬機,分別安裝兩個 Nginx,然后使用 keepalived 為這兩個虛擬機做一個虛擬 IP。

  • 而如果使用 Kubernetes 項目呢?你需要做的則是編寫如下這樣一個 YAML 文件(比如名叫 nginx-deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
     - containerPort: 80
 

在上面這個 YAML 文件中,我們定義了一個 Deployment 對象,它的主體部分(spec.template 部分)是一個使用 Nginx 鏡像的 Pod,而這個 Pod 的副本數是 2(replicas=2)。

然后執行:

kubectl create -f nginx-deployment.yaml

這樣,兩個完全相同的 Nginx 容器副本就被啟動了。

 

重點

Kubernetes 項目所擅長的,是按照用戶的意願和整個系統的規則,完全自動化地處理好容器之間的各種關系。這種功能,就是我們經常聽到的一個概念:編排。

所以說,Kubernetes 項目的本質,是為用戶提供一個具有普遍意義的容器編排工具。

不過,更重要的是,Kubernetes 項目為用戶提供的不僅限於一個工具。它真正的價值,乃在於提供了一套基於容器構建分布式系統的基礎依賴


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM