k8s原理知識(shí)點(diǎn)總結(jié)(上)

自己的筆記,沒(méi)有整理,慎看。。

章節(jié)目錄

1. 容器

1.1 容器的本質(zhì)

1.2 容器鏡像

1.3 容器編排

2. k8s集群搭建

2.1 kubeadm工作流程介紹

2.2 搭建完整的k8s集群

2.3 編寫(xiě)yaml文件

3. K8s容器編排和作業(yè)管理

3.1 Pod

3.2 Deployment

3.3 StatfulSet

3.4 DeamonSet

3.5 Job


1. 容器

1.1 容器的本質(zhì)

容器的本質(zhì)是一種特殊的進(jìn)程

啟動(dòng)進(jìn)程的時(shí)候指定namespace,在/proc/pid/ns查看

/sys/fs/cgroup/下面限制進(jìn)程的資源使用

1.2 容器鏡像

容器鏡像rootfs打包了所有的程序依賴(lài)的操作系統(tǒng)文件和目錄(但不包含內(nèi)核),解決了一致性的問(wèn)題

docker鏡像的創(chuàng)新:層。多個(gè)增量rootfs聯(lián)合掛載成為一個(gè)rootfs

層都放置在 /var/lib/docker/aufs/diff 目錄下

每個(gè)層是一個(gè)增量rootfs,層們疊加起來(lái)是一個(gè)完整的操作系統(tǒng)環(huán)境,被聯(lián)合掛載在/var/lib/docker/aufs/mnt/

一個(gè)鏡像由哪些層組成:/sys/fs/aufs

對(duì)容器鏡像rootfs來(lái)說(shuō),層分三部分:

第一部分只讀層:掛載方式都是只讀的ro+wh,即 readonly+whiteout

第二部分可讀寫(xiě)層:掛載方式為:rw即read write。存放對(duì)rootfs的增刪改

第三部分init層:docker內(nèi)部層,專(zhuān)門(mén)存放/etc/hosts, /etc/resolv.conf。

分三類(lèi)層的原因是可以分開(kāi)使用,docker commit時(shí),實(shí)際上就是在容器運(yùn)行起來(lái)后,把可讀寫(xiě)層,加上原先容器鏡像的只讀層,打包組成了一個(gè)新的鏡像,而init層的文件故意不打包了,因?yàn)槟鞘悄阕约涵h(huán)境的修改

1.3 Volume

解決的問(wèn)題:如何讓容器里的進(jìn)程訪問(wèn)到宿主機(jī)上的文件?

在docker run的時(shí)候聲明一個(gè)volume,實(shí)現(xiàn)原理:

在rootfs準(zhǔn)備好后,在chroot執(zhí)行之前,執(zhí)行bind mount掛載,這個(gè)掛載只有容器內(nèi)部可見(jiàn),宿主機(jī)不可見(jiàn),由于是綁定掛載,在容器目錄進(jìn)行的所有操作實(shí)際發(fā)生在宿主機(jī),而由于宿主機(jī)看不到掛載點(diǎn)的存在,容器中可讀寫(xiě)層的目錄也是空的,不會(huì)被打到鏡像里

1.4 k8s里的容器編排

k8s不僅僅提供一個(gè)給定的集群能夠?qū)⑷萜饕匀萜麋R像為基礎(chǔ)運(yùn)行起來(lái),并提供路由、監(jiān)控、災(zāi)備、可擴(kuò)展等運(yùn)維能力,

他的設(shè)計(jì)思想在于普適性,以宏觀的角度,以統(tǒng)一的方式能適配各種任務(wù)與任務(wù)之間的關(guān)系,并對(duì)將來(lái)可能出現(xiàn)的新的關(guān)系支持自定義

例如,兩個(gè)任務(wù)需要非常頻繁的交互,通過(guò)本地文件進(jìn)行信息交互,在常規(guī)情況下,他們會(huì)部署在同一臺(tái)機(jī)器,在k8s中,他們做為兩個(gè)容器被劃分為一個(gè)pod,pod里的他們共享同一個(gè)network ns,同一個(gè)volume

又例如,web應(yīng)用和db的關(guān)系,如果他們是兩個(gè)容器,當(dāng)他們的ip變化,將無(wú)法找到服務(wù),而k8s里,給數(shù)據(jù)庫(kù)pod綁定service,service的ip終生不變,作為pod的入口暴露一個(gè)穩(wěn)定ip

再例如,web應(yīng)用需要訪問(wèn)db,k8s提供secret對(duì)象,保存在etcd里的數(shù)據(jù),啟動(dòng)pod時(shí),以volume的方式掛載到容器,就有權(quán)限了


本章命令總結(jié)

docker build -t helloworld .

docker image ls

docker run -p 4000:80 helloworld????啟動(dòng)容器

docker tag helloworld geektime/helloworld:v1????起名字

docker push geektime/helloworld:v1????push到docker倉(cāng)庫(kù)

docker exec -it 4ddf4638572d /bin/sh????進(jìn)入容器,使用setns()系統(tǒng)調(diào)用

docker commit 4ddf4638572d geektime/helloworld:v2????提交修改到鏡像中保存


2. K8s集群搭建

2.1 使用kubeadm,kubeadm工作流程:

0. 安裝kubeadm,kubeadm 和 kubelet、kubectl、kubernetes-cni會(huì)一起安裝好

1. 前置檢查

2. 生成證書(shū)和目錄

3. 為其他組件生成訪問(wèn)kube-apiserver所需的配置文件/etc/kubernetes/xxx.conf

4. 為master組件(kube-apiserver、kube-controller-manager、kube-scheduler)生成pod配置文件

5. 為集群生成一個(gè) bootstrap token, 安全認(rèn)證用到,用來(lái)讓安裝了 kubelet 和 kubadm 的節(jié)點(diǎn)通過(guò)kubeadm join加入到集群中

6. kubeadm 會(huì)將 ca.crt 等 Master 節(jié)點(diǎn)的重要信息,通過(guò) ConfigMap 的方式保存在 Etcd 當(dāng)中,供后續(xù)部署 Node 節(jié)點(diǎn)使用

7. 最后一步, 安裝默認(rèn)插件kube-proxy 和 DNS,提供服務(wù)發(fā)現(xiàn)和DNS功能,也是通過(guò)yaml創(chuàng)建pod


2.2 部署完整的k8s集群的過(guò)程

1. 在所有節(jié)點(diǎn)上安裝 Docker 和 kubeadm;

2. 部署 Kubernetes Master;

3. 部署容器網(wǎng)絡(luò)插件;

4. 部署 Kubernetes Worker;

5. 部署 Dashboard 可視化插件;

6. 部署容器存儲(chǔ)插件。


2.3 yaml配置文件說(shuō)明

示例:
apiVersion: apps/v1

kind: Deployment

metadata:

? name: nginx-deployment

spec:

? selector:

? ? matchLabels:

? ? ? app: nginx

? replicas: 2

? template:

? ? metadata:

? ? ? labels:

? ? ? ? app: nginx

? ? spec:

? ? ? containers:

? ? ? - name: nginx

? ? ? ? image: nginx:1.8

? ? ? ? ports:

? ? ? ? - containerPort: 80

? ? ? ? volumeMounts:

? ? ? ? - mountPath: "/usr/share/nginx/html"

? ? ? ? ? name: nginx-vol

? ? ? volumes:

? ? ? - name: nginx-vol

? ? ? ? emptyDir: {}

總體分為兩部分:metadata存放元數(shù)據(jù);spec存放對(duì)象定義和功能的描述

apiVersion: apps/v1 --- 表示這是一個(gè)api對(duì)象,這里是Deployment api對(duì)象管理Pod api對(duì)象??刂破髂J?/p>

metadata --- 元數(shù)據(jù),api對(duì)象的標(biāo)識(shí),包含name, Annotations, labels等, labels用來(lái)給spec.selector.matchLabels過(guò)濾

kind: Deployment --- 類(lèi)型是Deployment

spec.replicas --- Pod副本數(shù)是2

spec.template --- Pod長(zhǎng)什么樣

spec.containers.image --- Pod的鏡像

volume:emptyDir 不顯示聲明宿主機(jī)目錄;對(duì)應(yīng)的有hostPath,顯示聲明

spec.volumeMounts 要掛載哪個(gè)volume


3. k8s容器編排基礎(chǔ)

3.1 pod

是k8s里最小調(diào)度單位,可看做一個(gè)進(jìn)程組或者像虛擬機(jī),容器則是進(jìn)程,如果多個(gè)進(jìn)程(容器)因?yàn)闀?huì)有直接的文件交換/本地通信/頻繁調(diào)用/共享資源必須放在一起部署

本質(zhì)上Pod是邏輯概念,他們只是一組共享了同一個(gè) Network Namespace,并且可以聲明共享同一個(gè) Volume的容器

Pod中,會(huì)有一個(gè)infra容器被第一個(gè)創(chuàng)建,他很小用的是k8s.gcr.io/pause鏡像,其他的容器通過(guò)join network ns的方式,與infra關(guān)聯(lián),作用是讓容器們是平等關(guān)系。


三個(gè)例子幫助理解pod

例子一:考慮一個(gè)war包和web服務(wù)器的關(guān)系

方式1. 把WAR包和web服務(wù)器打進(jìn)一個(gè)鏡像

方式2. 只把web服務(wù)器打成鏡像,掛載一個(gè)volume保存war包

POD方式:把war包和web服務(wù)器分別做成鏡像,然后作為同一個(gè)Pod,volume被兩個(gè)容器共享。是sidecar的方式,意識(shí)是啟動(dòng)一個(gè)輔助容器,完成主容器之外的工作


例子二,容器日志收集

主容器將日志輸出到/var/log,volume掛載

sidecar容器同樣的volume掛載,只做一件事,把日志拿出來(lái)處理


例子三,sidercar和主容器共享network ns,所以可以用sidecar來(lái)管理網(wǎng)絡(luò),不用影響主容器


3.1.1 pod和容器

pod實(shí)際上是對(duì)容器的進(jìn)一步抽象和封裝

如何判斷哪些屬性是屬于pod哪些是屬于容器的呢?

原則:凡是調(diào)度、網(wǎng)絡(luò)、存儲(chǔ),以及安全相關(guān)的屬性,跟容器的namespace相關(guān)的屬性 ,共享宿主機(jī)的ns屬性,這些都是 Pod 級(jí)別的。他們都是描述機(jī)器的

一些pod屬性:

NodeSelector將POD與node綁定

NodeName一旦賦值,會(huì)被k8s認(rèn)為已經(jīng)調(diào)度過(guò)

HostAliases定義pod里的hosts文件

一些容器屬性:

ImagePullPolicy(always,Never 或者 IfNotPresentAlways每次都拉取鏡像

LifecyclepostStart,preStop 容器啟動(dòng)/退出時(shí)做的事


3.1.2 Pod聲明周期

Pending這個(gè)狀態(tài)意味著,Pod 的 YAML 文件已經(jīng)提交給了 Kubernetes,API 對(duì)象已經(jīng)被創(chuàng)建并保存在 Etcd 當(dāng)中。但是,這個(gè) Pod 里有些容器因?yàn)槟撤N原因而不能被順利創(chuàng)建。比如,調(diào)度不成功。

Running這個(gè)狀態(tài)下,Pod 已經(jīng)調(diào)度成功,跟一個(gè)具體的節(jié)點(diǎn)綁定。它包含的容器都已經(jīng)創(chuàng)建成功,并且至少有一個(gè)正在運(yùn)行中。

Succeeded這個(gè)狀態(tài)意味著,Pod 里的所有容器都正常運(yùn)行完畢,并且已經(jīng)退出了。這種情況在運(yùn)行一次性任務(wù)時(shí)最為常見(jiàn)。

Failed這個(gè)狀態(tài)下,Pod 里至少有一個(gè)容器以不正常的狀態(tài)(非 0 的返回碼)退出。這個(gè)狀態(tài)的出現(xiàn),意味著你得想辦法 Debug 這個(gè)容器的應(yīng)用,比如查看 Pod 的 Events 和日志。

Unknown這是一個(gè)異常狀態(tài),意味著 Pod 的狀態(tài)不能持續(xù)地被 kubelet 匯報(bào)給 kube-apiserver,這很有可能是主從節(jié)點(diǎn)(Master 和 Kubelet)間的通信出現(xiàn)了問(wèn)題。

3.1.3 Project Volume

Project Volume存在的意義不是為了存放容器里的數(shù)據(jù),也不是用來(lái)進(jìn)行容器和宿主機(jī)之間的數(shù)據(jù)交換。這些特殊 Volume 的作用,是為容器提供預(yù)先定義好的數(shù)據(jù)。所以,從容器的角度來(lái)看,這些 Volume 里的信息就是仿佛是被 Kubernetes“投射”(Project)進(jìn)入容器當(dāng)中的。

相比環(huán)境變量重要的優(yōu)點(diǎn):可以被自動(dòng)更新

有以下4種:

1. Secret;需要加密的,生產(chǎn)環(huán)境使用加密插件,例如數(shù)據(jù)庫(kù)連接

2. ConfigMap;不需要加密的配置信息,例如普通配置文件

3. Downward API;讓 Pod 里的容器能夠直接獲取到這個(gè) Pod API 對(duì)象本身的靜態(tài)信息,例如打印pod信息到日志

4. ServiceAccountToken訪問(wèn)api的授權(quán),默認(rèn)會(huì)有默認(rèn)的volume


3.1.4 容器健康檢查和恢復(fù)

這個(gè)探針通過(guò)靜態(tài)文件和http url兩種方式:

1. cat /tmp/healthy判斷容器健康,返回0就正常

2. 配置一個(gè)url

initialDelaySeconds: 5 pod啟動(dòng)5秒后執(zhí)行

pod狀態(tài)不是running會(huì)重新創(chuàng)建,在同個(gè)node,不想同node用deployment,合理設(shè)置restartPolicy

還有個(gè)readinessProbe 的字段

readinessProbe 檢查結(jié)果的成功與否,決定的這個(gè) Pod 是不是能被通過(guò) Service 的方式訪問(wèn)到


關(guān)于pod和容器的狀態(tài),兩個(gè)原理:

1. 只要 Pod 的 restartPolicy 指定的策略允許重啟異常的容器(比如:Always),那么這個(gè) Pod 就會(huì)保持 Running 狀態(tài),并進(jìn)行容器重啟。否則,2. Pod 就會(huì)進(jìn)入 Failed 狀態(tài) 。對(duì)于包含多個(gè)容器的 Pod,只有它里面所有的容器都進(jìn)入異常狀態(tài)后,Pod 才會(huì)進(jìn)入 Failed 狀態(tài)。在此之前,Pod 都是 Running 狀態(tài)。

示例:

apiVersion: v1

kind: Pod

metadata:

labels:

test: liveness

name: test-liveness-exec

spec:

containers:

- name: liveness

image: busybox

args:

- /bin/sh

- -c

- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600

livenessProbe:

exec:

command:

- cat

- /tmp/healthy

initialDelaySeconds: 5

periodSeconds: 5


3.2 控制器Deployment

其他控制器:

$ cd kubernetes/pkg/controller/

$ ls -d */? ? ? ? ? ? ?

deployment/? ? ? ? ? ? job/? ? ? ? ? ? ? ? ? ? podautoscaler/? ? ? ? ?

cloud/? ? ? ? ? ? ? ? ? disruption/? ? ? ? ? ? namespace/? ? ? ? ? ? ?

replicaset/? ? ? ? ? ? serviceaccount/? ? ? ? volume/

cronjob/? ? ? ? ? ? ? ? garbagecollector/? ? ? nodelifecycle/? ? ? ? ? replication/? ? ? ? ? ? statefulset/? ? ? ? ? ? daemon/

...

控制器們都遵循 Kubernetes 項(xiàng)目中的一個(gè)通用編排模式,即:控制循環(huán)(control loop)

意思是會(huì)對(duì)比實(shí)際狀態(tài)和期望狀態(tài),并且循環(huán)的調(diào)整直到達(dá)到期望狀態(tài)。

deployment操縱是replicaSet 而不是pod

deployment創(chuàng)建會(huì)同時(shí)創(chuàng)建rs,rs名字里有一個(gè)hash字符串,被作為受它管理的pod的標(biāo)簽,不與其他pod混淆

deployment的狀態(tài):

DESIRED用戶期望的

CURRENT當(dāng)前處于running狀態(tài)的pod

UP-TO-DATE(deployment有而rs沒(méi)有)當(dāng)前處于最新版本的POD,所謂最新版本指的是 Pod 的 Spec 部分與 Deployment 里 Pod 模板里定義的完全一致;

AVAILABLE當(dāng)前可用的,即既是Running狀態(tài),又是最新版本,并且處于Ready(健康檢查正確)的個(gè)數(shù)

滾動(dòng)更新的實(shí)現(xiàn):把原rs里的副本一個(gè)個(gè)減少,把新rs里的副本一個(gè)個(gè)增加


apiVersion: apps/v1

kind: Deployment

metadata:

name: nginx-deployment

labels:

app: nginx

spec:

...

strategy:

type: RollingUpdate

rollingUpdate:

maxSurge: 1

maxUnavailable: 1

maxSurge 指定的是除了 DESIRED 數(shù)量之外,在一次“滾動(dòng)”中,Deployment 控制器還可以創(chuàng)建多少個(gè)新 Pod;而 maxUnavailable 指的是,在一次“滾動(dòng)”中,Deployment 控制器可以刪除多少個(gè)舊 Pod。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容