kubernetes運維

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而不是直接管理容器。

  1. 在一個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配置文件

  1. 用kubectl 命令直接創建,比如:
    kubectl run httpd-app --image=reg.tstack.com/tstack/httpd:latest --replicas=2 在命令行中通過參數指定資源的屬性。
  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 目錄如下所示:


image.png

◆ 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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯系作者。

推薦閱讀更多精彩內容