1.kubernetes介紹
Kubernetes容器集群管理系統,是Google開源的一個項目,目標是管理跨多個主機的容器,用于自動部署、擴展和管理容器化的應用程序,主要實現語言為Go 語言。
1.1特點:
可移植性、可擴展性、存儲編排、自動化部署回滾、自我修復、服務發現負載均衡、機密管理配置管理
2.Kubernetes架構
2.1Kubernetes Master:
Master 節點是Kubernetes 集群的控制節點,負責整個集群的管理和控制。
Master 節點上包含以下組件:
1.kube-apiserver:提供了資源操作的唯一入口并提供認證、授權、訪問控制、API 注冊和發現等機制
2.kube-scheduler:負責資源的調度
3.kube-controller-manager:負責維護集群的狀態比如故障檢測、自動擴展、滾動更新等
4.etcd(鍵值數據庫):保存了整個集群的狀態,可用于服務發現、共享配置以及一致性保障(如數據庫選主、分布式鎖等)
2.2Kubernetes Node:
Node 節點是Kubernetes 集群中的工作節點,Node 上的工作負載由Master 節點分配,工作負載主要是運行容器應用。
Node 節點上包含以下組件:
1.kubelet:負責維持容器的生命周期,同時也負責Volume(CVI,Container Volume Interface)和網絡(CNI,Container Network Interface)的管理
2.kube-proxy:負責為Service 提供cluster 內部的服務發現和負載均衡
3.Pod 網絡(貫穿整個集群):Pod 要能夠相互通信,Kubernetes Cluster 必須
部署Pod 網絡Flannel 是其中一個可選方案,還有OpenvSwitch、Calico等
3.Kubernetes關鍵概念
1.namespace
1.Namespace用于實現多租戶的資源隔離,通過將集群內部的資源對象“分配”到不同的Namespace中,形成邏輯上分組的不同項目、小組或用戶組,便于不同的分組在共享使用整個集群的資源的同時還能被分別管理。
2.每個命名空間內的資源名稱都是唯一的。
3.同一個命名空間內的服務可以通過DNS 使用服務名稱互訪,跨命名空間的服務,可以使用servicename.namespace 的方式進行訪問。
查看命令空間:kubectl get namespaces
創建命令空間:kubectl create ns test
1.default --創建資源時如果不指定,將被放到這個Namespace 中
2.kube-system --Kubernetes 自己創建的系統資源將放到這個Namespace 中
3.kube-public --Kubernetes 公共的系統資源將放到這個Namespace 中
2.pod
1.Pod 是Kubernetes 應用程序的基本執行單元(最小資源單位),是一組容器的集合。
2.Pod 內部的容器共享網絡棧
3.Pod 內部的容器可以共享存儲卷
注釋:
1.Pause Container:啟動每個Pod都有一個特殊的被稱為“根容器”的Pause容器,以它的狀態代表整個容器組的狀態。Pod里的多個業務容器共享Pause容器的IP,共享Pause容器掛接的Volume,簡化了密切關聯的業務容器之間的通信問題,也很好地解決了它們之間的文件共享問題。
2.Init Container:在業務容器啟動之前,會首先一次性的執行Init Container 的指令,這是一種專用的容器,在應用程序容器啟動之前運行,用來包含一些應用鏡像中不存在的實用工具或安裝腳本。
3.業務容器:自定義容器,用于運行真正的業務代碼
2.1在Kubernetes集群中Pod有如下兩種使用方式:
1.一個Pod中運行一個容器。“每個Pod中一個容器”的模式是最常見的用法;在這種使用方式中,可以把Pod想象成是單個容器的封裝,kuberentes管理的是Pod而不是直接管理容器。
- 在一個Pod中同時運行多個容器。一個Pod中也可以同時封裝幾個需要緊密耦合互相協作的容器,它們之間共享資源。
2.2Pod中可以共享兩種資源:網絡和存儲
2.2.1.網絡
每個Pod都會被分配一個唯一的IP地址。Pod中的所有容器共享網絡空間,包括IP地址和端口。Pod內部的容器可以使用localhost互相通信。Pod中的容器與外界通信時,必須分配共享網絡資源(例如使用宿主機的端口映射)。
2.2.2.存儲
可以為一個Pod指定多個共享的Volume。Pod中的所有容器都可以訪問共享的volume。Volume也可以用來持久化Pod中的存儲資源,以防容器重啟后文件丟失。
3.Controller
Kubernetes 通常不會直接創建Pod,而是通過Controller 來管理Pod 的。
1.Controller 中定義了Pod 的部署特性,可以創建和管理多個Pod,提供副本管理、滾動升級和集群級別的自愈能力、在什么樣的Node 上運行Pod等。
2.為了滿足不同的業務場景,Kubernetes 提供了多種Controller,包括Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job 等。
3.1 Deployment
是最常用的Controller,定義Deployment創建Pod和ReplicaSet,可以管理Pod 的多個副本,并確保Pod 按照期望的狀態運行。典型的應用場景包括:
?滾動升級和回滾應用
?擴容和縮容
?暫停和繼續Deployment
3.2 ReplicaSet
實現了Pod 的多副本管理。使用Deployment 時會自動創建ReplicaSet,也就是說Deployment是通過ReplicaSet 來管理Pod 的多個副本,我們通常不需要直接使用ReplicaSet。
3.3 StatefulSet
StatefulSet 作為Controller 為Pod 提供唯一的標識。解決有狀態服務的Pod 的每個副本在整個生命周期中名稱是不變,同時保證副本按照固定的順序啟動、更新或者刪除(對應Deployments和ReplicaSets是為無狀態服務而設計),其應用場景包括:
?穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基于PVC來實現
?穩定的網絡標志,即Pod重新調度后其PodName和HostName不變,基于Headless Service(即沒有Cluster IP的Service)來實現
?有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次進行(即從0到N-1,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態),基于initcontainers來實現
?有序收縮,有序刪除(即從N-1到0)
3.4 daemonset
DaemonSet 確保全部(或者一些)Node 上運行一個Pod 的副本。當有Node 加入集群時,也會為他們新增一個Pod 。當有Node 從集群移除時,這些Pod 也會被回收。刪除DaemonSet 將會刪除它創建的所有Pod。
使用DaemonSet 的一些典型用法:
?運行集群存儲daemon,例如在每個Node 上運行glusterd、ceph。
?在每個Node 上運行日志收集daemon,例如fluentd、logstash。
?在每個Node 上運行監控daemon,例如Prometheus Node Exporter、
collectd、Datadog 代理、New Relic 代理,或Ganglia gmond。
3.5 Job
用于運行一次性任務,運行結束就刪除的應用。
保證批處理任務的一個或多個Pod成功結束,而其他類型的Controller 中Pod 通常是長期持續運行。
3.6 CronJob
1.CronJob其實就是在Job的基礎上加上了時間調度
2.在給定的時間點運行一個任務,也可以周期性地在給定時間點運行。
這個實際上和Linux中的crontab就非常類似。一個CronJob對象其實就對應中crontab文件中的一行,它根據配置的時間格式周期性地運行一個Job,格式和crontab也是一樣的。
4..Kubernetes 創建資源的方式:
4.1Kubernetes命令vs配置文件
- 用kubectl 命令直接創建,比如:
kubectl run httpd-app --image=reg.tstack.com/tstack/httpd:latest --replicas=2 在命令行中通過參數指定資源的屬性。 - 通過yaml編排文件創建,要完成前面同樣的工作,可執行命令:
kubectl apply -f httpd.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd-deployment
spec:
replicas: 2 #副本數
template:
metadata:
labels:
name: httpd
spec:
containers:
- name: httpd-app
image: reg.tstack.com/tstack/httpd:latest #容器鏡像
4.2YAML 基礎:
kubernetes 集群通常使用YAML 文件來創建相關的資源。
它的基本語法規則如下:
格式規范:
大小寫敏感
使用縮進表示層級關系
縮進時不允許使用Tab鍵,只允許使用空格。
縮進的空格數目不重要,只要相同層級的元素左側對齊即可
井號表示注釋,從這個字符一直到行尾,都會被解析器忽略。
4.2.1在kubernetes 中,需要兩種結構類型:
Maps:是字典,就是一個key:value
Lists:列表,就是數組
list 的子項也可以是Maps,Maps 的子項也可以是list
#yaml格式:
---
apiVersion:v1
kind:Pod
metadata:
name:kube100-site
labels:
app:web
#json格式:
{
"apiVersion":"v1",
"kind":"Pod",
"metadata":{
"name":"kube100-site",
"labels":{
"app":"web"
}
}
}
#yaml格式:
---
apiVersion: v1
kind: Deployment
metadata:
name: kube100-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports:
- containerPort: 5000
5.Servcie:
1.Pod 可以部署多個副本,每個Pod 都有自己的IP,Pod 很可能會被頻繁地銷毀和重啟,它們的IP 會發生變化,用IP 來訪問不太現實。Kubernetes 運行容器(Pod)是由Controller執行,而訪問容器(Pod)是Service 執行。
2.Service是將請求進行負載分發到后端的各個pod容器應用上的控制器。它定義了一個服務的訪問入口地址,前端的應用(Pod)通過這個入口地址訪問其背后的一組由Pod副本組成的集群實例,Service與其后端Pod副本集群之間則是通過Label Selector(標簽選擇器)來實現無縫對接的。
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
tier: frontend
5.1 Pod IP:
每個Pod的IP地址,一個Pod里的容器訪問另外一個Pod里的容器時,就是通過Pod IP所在的虛擬二層網絡進行通信的,而真實的TCP/IP流量是通過Node IP所在的物理網卡流出。
5.2 Cluster IP :
就是Service 的IP ,是一個虛擬IP地址并由Kubernetes管理和分配。Service 為Pod 提供了負載均衡。
5.3 Node IP:
是Kubernetes集群中每個節點的物理網卡的IP地址,是一個真實存在的物理網絡,所有屬于這個網絡的服務器都能通過這個網絡直接通信,不管其中是否有部分節點不屬于這個Kubernetes集群。
5.4 NodePort:
通過Cluster IP 只能是kubernetes集群內部的客戶端訪問到一組Pod,集群外部訪問要在Pod所運行的Node上指定一個特定Port轉發到Service Port 這個Port就是Node Port。
5.5 內部訪問方式ClusterIP
ClusterIP服務是Kubernetes 的默認服務。是一個集群內的服務,集群內的其它應用都可以訪問該服務。集群外部無法訪問它。在某些場景下我們可以使用Kubernetes 的Proxy 模式來訪問服務,比如調試服務時。
---
apiVersion: v1
kind: Namespace
metadata:
name: test
namespace: test
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: test
labels:
app: web
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-front-end
namespace: test
spec:
replicas: 2
template:
metadata:
labels:
name: nginx-front-end
app: web
spec:
containers:
- image: nginx
name: nginx-front-end
ports:
- containerPort: 80
5.6 外部訪問方式NodePort
NodePort服務是引導外部流量到內部服務的最原始方式。NodePort,正如這個名字所示,在所有節點(虛擬機)上開放一個特定端口,任何發送到該端口的流量都被轉發到對應服務。
5.6.1 NodePort服務特征如下:
? 每個端口只能是一種服務
? 端口范圍只能是30000-32767(可調)
? 不在YAML 配置文件中指定則會分配一個默認端口
5.6.2 建議:
不要在生產環境中使用這種方式暴露服務,大多數時候應該讓Kubernetes 來選擇端口
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: test
labels:
app: web
spec:
selector:
app: web
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
nodeProt: 31005
6.laber
Label標簽,是附著到object上(例如Node、Pod、Service、RC等)的鍵值對。給object加入一些特定信息,通過LabelSelector (標簽選擇器)進行檢索。
◆可以在創建object的時候指定,也可以在object創建后隨時指定。
◆一個資源對象可以定義任意數量的Label,同一個Label也可以被添加到任意數量的資源對象上。
◆一個Label是一個key=value的鍵值對,其中key與value由用戶自己指定。
6.1 Label案例:控制Pod 啟動的位置
默認配置下,Scheduler 會將Pod 調度到所有可用的Node。不過有些情況我們希望將Pod 部署到指定的Node,比如將有大量磁盤I/O 的Pod 部署到配置了SSD 的Node;或者Pod 需要GPU,需要運行在配置了GPU 的節點上。
Kubernetes 是通過label 來實現這個功能,靈活添加各種自定義屬性。比如執行如下命令標注k8s-node3 是配置了SSD 的節點。
節點打標簽
kubectl label node 172.16.254.23 disktype=ssd
查看節點標簽
kubectl get node --show-labels
刪除節點上的標簽
kubectl label node 172.16.254.23 disktype-
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd-deployment
spec:
replicas: 2
template:
metadata:
labels:
name: httpd
spec:
containers:
- name: httpd-app
image: reg.tstack.com/tstack/httpd:latest
nodeSelector:
disktype: ssd
7.ConfigMap:
分布式系統經常需要使用配置信息,Kubernetes 中使用Configmap 進行配置存儲,所有配置參數存儲在Etcd中,然后通過Volume映射的方式變成目標Pod內的配置文件,如果數據被修改,則映射到Pod中的“配置文件”也會隨之自動更新。
7.1 ConfigMap 也支持四種創建方式:
7.1.1 通過--from-literal:
kubectl create configmap myconfigmap --from-literal=config1=xxx --from-literal=config2=yyy
每個--from-literal 對應一個信息條目。
7.1.2 通過--from-file:
echo -n xxx > ./config1
echo -n yyy > ./config2
kubectl create configmap myconfigmap --from-file=./config1 --from-file=./config2
每個文件內容對應一個信息條目。
7.1.3 通過--from-env-file:
cat << EOF > env.txt
config1=xxx
config2=yyy
EOF
kubectl create configmap myconfigmap --from-env-file=env.txt
文件env.txt 中每行Key=Value 對應一個信息條目。
7.1.4 通過YAML 配置文件:
Configmap 的結構很簡單,除了Metadata,就只有一個Data 字段,其中保存了Keyvalue 的信息,例如:
apiVersion:v1
kind:ConfigMap
metadata:
name:myconfigmap
data:
key1:value1
key2:value2
7.1.5 平臺內查看對應的configmap
kubectl get cm
如果需要修改服務對應的配置只需要修改對應configmap:kubectl edit cm xxx-config
8. Kubernetes網絡——基礎介紹
1.CNI(Container Network Interface):
容器網絡接口,由一組用于配置Linux 容器的網絡接口的規范和庫組成,同時還包含了一些插件。CNI 僅關心容器創建時的網絡分配,和當容器被刪除時釋放網絡資源。
2.CNI 插件:
負責將網絡接口插入容器網絡命名空間(例如,vethpair的一端),并在主機上進行任何必要的改變(例如將veth pair的另一端連接到網橋)。然后將IP 分配給接口,并通過調用適當的IPAM 插件來設置與“IP 地址管理”部分一致的路由。
1、同一個Pod中容器間通信:同一個Pod的容器共享同一個網絡命名空間,它們之間的訪問可以用localhost地址+ 容器端口就可以訪問。
2、同一Node中Pod間通信:同一Node中Pod的默認路由都是docker0的地址,由于它們關聯在同一個docker0網橋上,地址網段相同,所有它們之間應當是能直接通信的。
3、不同Node中Pod間通信:不同Node中Pod間通信要滿足2個條件:Pod的IP不能沖突;將Pod的IP和所在的Node的IP關聯起來,通過這個關聯讓Pod可以互相訪問。
8.1 Kubernetes網絡——Flannel方案
Flannel是作為一個二進制文件的方式部署在每個node上:
8.1.1 主要實現兩個功能:
? 為每個node分配subnet(子網),容器將自動從該子網中獲取IP地址
? 當有node加入到網絡中時,為每個node增加路由配置
9.Kubernetes網絡——外部訪問服務方式
9.2 ingress
通常情況下,Service 和Pod 的IP 僅可在集群內部訪問。集群外部的請求需要通過負載均衡轉發到Service 在Node 上暴露的NodePort上,然后再由kube-proxy 通過邊緣路由器(edge router) 將其轉發給相關的Pod 或者丟棄。而Ingress 就是為進入集群的請求提供路由規則的集合
10. Kubernetes存儲管理
10.1 Kubernetes Volume
容器和Pod 是短暫的,會被頻繁地銷毀和創建。容器銷毀時,保存在容器內部文件系統中的數據都會被清除。使用Kubernetes Volume 可以持久化保存容器的數據,Volume 的生命周期獨立于容器,Pod 中的容器可能被銷毀和重建,但Volume 會被保留。
10.1.1 Kubernetes Volume 類型:
◆ emptyDir:最基礎的Volume 類型。正如其名字所示,一個emptyDir Volume 是Host 上的一個空目錄。
◆ hostPath Volume:將Docker Host 文件系統中已經存在的目錄mount 給Pod 的容器。
◆ 外部Storage Provider:Kubernetes可以對接第三方存儲作為Volume 供給,例如NFS、GlusterFS、Ceph等。
10.2 Kubernetes中跟存儲相關的概念有PersistentVolume(PV)和PersistentVolumeClaim(PVC):
◆ Persistent Volume(PV、持久卷)是集群之中的一塊網絡存儲。跟Node 一樣,也是集群的資源。PV 跟Volume (卷) 類似,不過會有獨立于Pod 的生命周期。
◆ Persistent Volume Claim(PVC、持久卷消費者)作為用戶對存儲資源的需求,主要包括存儲空間請求、訪問模式、PV選擇條件和存儲類別等信息的設置。
10.2.1 PV又分為靜態供給PV和動態PV供給:
1.靜態供給(Static Provision):提前創建了PV,然后通過PVC 申請PV 并在Pod 中使用
2.動態供給(Dynamical Provision):即如果沒有滿足PVC 條件的PV,會動態創建PV。相比靜態供給,動態供給有明顯的優勢:不需要提前創建PV,減少了管理員的工作量,效率高。
3.動態供給是通過StorageClass 實現的,StorageClass 定義了如何創建PV
10.2.2 Kubernetes存儲管理——PV和PVC以及對應的rbd查看
kubectl get pv
kubectl get pvc
10.3Kubernetes通過訪問模式給存儲分為三大類:
◆ ReadWriteMany:多路讀寫,卷能被集群多個節點掛載并讀寫
◆ ReadWriteOnce:單路讀寫,卷只能被單個集群節點掛載讀寫
◆ ReadOnlyMany:多路只讀,卷能被多個集群節點掛載且只能讀
11.helm介紹
11.1 為什么使用helm?
Kubernetes雖然提供了多種容器編排對象,例如Deployment StatefulSet、DeamonSet、Job等,還有多種基礎資源封裝例如ConfigMap、Secret、Serivce等,但是一個應用往往有多個服務,有的可能還要依賴持久化存儲,當這些服務之間直接互相依賴,需要有一定的組合的情況下,使用YAML文件的方式配置應用往往十分繁瑣還容易出錯,這時候就需要服務編排工具。
helm 類似于Linux系統下的包管理器,如yum/apt等,可以方便快捷的將之前打包好的yaml文件快速部署進kubernetes內,方便管理維護。只不過helm這兒管理的是在k8s上安裝的各種容器。
? helm的作用:像centos7中的yum命令一樣,管理軟件包。
? tiller的作用:像centos7的軟件倉庫一樣,簡單說類似于/etc/yum.repos.d目錄下的xxx.repo。
11.2Helm 三個重要概念:
◆ chart:包含了創建Kubernetes的一個應用實例的必要信息
◆ config:包含了應用發布配置信息
◆ release:是一個chart 及其配置的一個運行實例
11.3 Helm具有如下功能:
◆ 創建新的chart
◆ chart 打包成tgz 格式
◆ 上傳chart 到chart 倉庫或從倉庫中下載chart
◆ 在Kubernetes集群中安裝或卸載chart
◆ 管理用Helm安裝的chart 的發布周期
11.3 chart 的基本結構
Helm的打包格式叫做chart,所謂chart就是一系列文件, 它描述了一組相關的k8s 集群資源。比如Service、Deployment、PersistentVolumeClaim、Secret、ConfigMap 等。Chart中的文件安裝特定的目錄結構組織, 最簡單的chart 目錄如下所示:
◆ charts:保存其他依賴的chart
◆ Chart.yaml:包含Chart的基本信息,包括chart版本,名稱等
◆ templates:目錄下存放應用一系列k8s 資源的yaml 模板
◆ _helpers.tpl:此文件中定義一些可重用的模板片斷,此文件中的定義
在任何資源定義模板中可用
◆ NOTES.txt:介紹chart 部署后的幫助信息,如何使用chart等
◆ values.yaml:包含了必要的值定義(默認值), 用于存儲templates
目錄中模板文件中用到變量的值
11.4 Helm 架構
Helm 包含兩個組件:Helm 客戶端和Tiller 服務器。
11.4.1Helm 客戶端是終端用戶使用的命令行工具,用戶可以:
1.在本地開發chart。
2.管理chart 倉庫。
3.與Tiller 服務器交互。
4.在遠程Kubernetes 集群上安裝chart。
5.查看release 信息。
6.升級或卸載已有的release
11.4.2 Tiller 服務器運行在Kubernetes 集群中,它會處理Helm 客戶端的請求,與Kubernetes API Server 交互。Tiller 服務器負責:
1.監聽來自Helm 客戶端的請求。
2.通過chart 構建release。
3.在Kubernetes 中安裝chart,并跟蹤release 的狀態。
4.通過API Server 升級或卸載已有的release。
11.5 Helm 工作原理
11.5.1 Chart Install 過程:
Helm 從指定的目錄或者TAR 文件中解析出Chart 結構信息。
Helm 將指定的Chart 結構和Values 信息通過gRPC傳遞給Tiller。
iller 根據Chart 和Values 生成一個Release。
Tiller 將Release 發送給Kubernetes 用于生成Release。
11.6 Helm 常用命令如下:
helm create:在本地創建新的chart
helm dependency:管理chart 依賴
helm intall:安裝chart
helm lint:檢查chart 配置是否有誤
helm list:列出所有release
helm package:打包本地chart
helm repo:列出、增加、更新、刪除chart 倉庫
helm rollback:回滾release 到歷史版本
helm pull:拉取遠程chart 到本地
helm search:使用關鍵詞搜索chart
helm uninstall:卸載release
helm upgrade:升級release