Kubernetes學習筆記_尚硅谷


https://www.bilibili.com/video/BV1w4411y7Go?p=1

 

一、K8s介紹

 

k8s是一個編排容器的工具,其實也是管理應用的全生命周期的一個工具,從創建應用,應用的部署,應用提供服務,擴容縮容應用,應用更新,都非常的方便,而且可以做到故障自愈。

 

1.1 發展經歷

 

基礎設施級服務 iaas :阿里雲 

平台設施級服務 paas :新浪雲

軟件設施級服務 saas :Office365

 

資源管理器:

前生:

Apache:MESOS - 分布式系統內核 、分布式資源管理框架 2019-05 Twitter>k8s

docker:SWARM 集群,輕量 2019-07 阿里雲宣布 Docker Swarm集群框架從阿里雲選擇框架剔除

今世:

google:kubernetes,10年google容器基礎框架borg ,容器火了以后,Google使用GO語言參考Borg設計思路開發出K8s

  特點:輕量級,基於GO語言,消耗資源小

     開源

     彈性伸縮

     負載均衡:LVS(IPVS)

 

1.2 知識圖譜

 

圖片原圖

 


K8s框架

K8s關鍵字含義

基礎概念 什么是Pod 控制器類型 

Pod概念  最小的封裝集合,一個Pod會封裝多個容器,達到一個子節點的運行環境,K8s管理的最小單位

網絡通訊模式

K8s安裝:構建K8s集群

資源清單:資源 掌握資源清單的語法 編寫Pod 掌握Pod的生命周期***

Pod控制器:掌握各種控制器的特點以及使用定義方式

服務發現:SVC原理及其構建方式

存儲:掌握多種存儲類型的特點 並且能夠在不同環境中選擇合適的存儲方案(有自己的見解)

  服務分類

    有狀態服務:DBMS

    無狀態服務:LVS APACHE

   高可用集群副本數最好是>=3的奇數

調度器:掌握調度器原理,能夠根據要求把Pod定義到想要的節點運行

安全:集群的認證 鑒權 訪問控制 原理及其流程 集群安全機制

HELM:類Linux yum  掌握HELM原理   HELM模板自定義  HELM部署一些常用插件

運維:CICD構建 POD特殊的創建管理方式  修改Kubeadm達到證書可用期限10年  構建高可用K8S集群

 

1.3 組件說明

 

Borg架構:

 

K8s架構:

  

APISERVER:所有服務訪問統一入口
CrontrollerManager:維持副本期望數目
Scheduler::負責介紹任務,選擇合適的節點進行分配任務
ETCD:鍵值對數據庫 儲存K8S集群所有重要信息(持久化),協助分布式集群的正常運轉。
Kubelet:直接跟容器引擎交互實現容器的生命周期管理
Kube-proxy:負責寫入規則至 IPTABLES、IPVS 實現服務映射訪問的
COREDNS:可以為集群中的SVC創建一個域名IP的對應關系解析
DASHBOARD:給 K8S 集群提供一個 B/S 結構訪問體系
INGRESS CONTROLLER:官方只能實現四層代理,INGRESS 可以實現七層代理
FEDERATION:提供一個可以跨集群中心多K8S統一管理功能
PROMETHEUS:提供K8S集群的監控能力
ELK:提供 K8S 集群日志統一分析介入平台

 

推薦在 Kubernetes 集群中使用 Etcd v3,v2 版本已在 Kubernetes v1.11 中棄用

 

etcd 的官方將它定位成一個可信賴的分布式鍵值存儲服務,它能夠為整個分布式集群存儲一些關鍵數據,協助分布式集群的正常運轉

 

二、基礎概念

 

2.1 Pod概念

 

Pod類型:

 自主式Pod:(不是被控制器管理的Pod):死亡后不會被拉起來,也不會有人創建新的Pod

 

 

 每個Pod里運行着一個特殊的被稱為Pause容器,其他容器為業務容器,這些業務容器共享Pause容器的網絡棧和Volume掛載卷,因此他們之間通信和數據交互更為高效。

 在設計時我們可以充分利用這一特性將一組密切相關的服務進程放入同一個Pod中,同一個Pod里的容器之間僅需通過localhost就能互相通信。

 

 控制器管理的Pod

 

POD控制器類型:

 ReplicationController & ReplicaSet & Deployment

 ReplicationController :確保期望值,少了就創建新的Pod替代,多了會自動回收。

  新版本的K8S種建議使用ReplicaSet來取代ReplicationControlle,沒有本質不同,但只有RS支持集合式的selector(每個Pod有不同標簽,RS操作Pod可以按照標簽條件操作)

  雖然RS可以獨立,但是一般還是建議使用Deployment來自動管理RS,這樣就無需擔心跟其他機制不兼容問題(如RS不支持rolling-update(滾動更新),但是D支持(D本身並不支持Pod創建),所以這倆要一起運行。)

 Deployment(ReplicaSet)
  Deployment 為 Pod 和 ReplicaSet 提供了一個聲明式定義 (declarative) 方法,用來替代以前的 ReplicationController 來方便的管理應用。典型的應用場景包括:
   * 定義 Deployment 來創建 Pod 和 ReplicaSet
   * 滾動升級和回滾應用
   * 擴容和縮容
   * 暫停和繼續 Deployment

 滾動更新:

  

  更新V1到V2,新建個RS然后創建1個V2,刪除1個V1

  

  >直至

  

  達到滾動更新,此時RS,停用、保留,可以回滾>

  

  RS啟用,開始回滾老版V1以此類推。

 

 HPA(HorizontalPodAutoScale)根據利用率平滑擴展僅適用於D和RS,在V1版本中支持根據Pod的利用率擴容,在vlalpha版本中,支持根據內存和用戶自定義的metric擴縮容。

 

  HPA基於RS定義,並且監控V2Pod的資源利用率

  

 

  當符合條件后,會創建Pod

  

 

  每次創建后判斷條件,符合后繼續創建,直到最大值。使用率小就回收,直到最小值,實現水平自動擴展(彈性伸縮)。

 

 StatefulSet:為了解決有狀態服務的問題(Deployment和RS是為了解決無狀態服務而設計(Docker主要也是)),其場景包括:

  *穩定的持久化存儲,即有個Pod死了,重新調度回來以后還是能訪問到相同的持久化數據(數據不丟失),基於PVC實現。

  *穩定的網絡標識,即重新調度后的PodName和HostName不變,基於Headless Service(即沒有Cluster IP的Service)來實現

  *有序部署,有序擴展,按照順序進行M>A>N(從0到N-1,在下一個Pod運行前,之前所有的Pod必須是running和Ready狀態),基於init containers來實現。

  *有序收縮,有序刪除(即從N-1到0) Nagix > Apache >Mysql

 

 DaemonSet

  確保全部(或者一些)Node上 運行一個Pod的副本。當有Node加入集群時,也會為他們新增一個Pod。當有Node從集群移除時,這些Pod也會被回收。刪除DaemonSet將會刪除它創建的所有Pod。除非打污點,正常情況所有Node都會運行一個且只有一個Pod。

  典型用法:

    *運行集群存儲 daemon,例如在每個Node上運行glusterd、ceph

    *在每個Node上運行日志收集daemon,例如fluentd、logstash

    *在每個Node上運行監控daemon,例如Prometheus Node Exporter、Zabix Agent 都可以封裝在DaemonSet中在每個Node上運行,幫我們收集數據。

 

 Job,Cronjob

  job負責批處理任務,即僅執行一次的任務,他保證批處理任務的一個或者多個Pod成功結束。(比如要備份數據庫,備份代碼可以放到統一Pod里,再放到Job里執行,與Linux直接運行不同點是是封裝好的Job可以重復利用,並且腳本執行異常退出可以重復執行,並且可以設置正常退出次數才算Job執行成功)

  Cronjob管理基於時間的Job,即

    *在給定時間點運行一次

    *周期性地在給定時間點運行

 

 服務發現:

  Client訪問service的IP和端口,使用RR(Round ribbon輪訓)等算法間接訪問到Pod。

  

 

 

2.2 網絡通訊方式

 

網絡通訊模式:

 Kubernetes的網絡模型假定了所有Pod都在一個可以直接連通的扁平的網絡空間中(都可以通過IP直接到達,其實底層有很多轉換機制),這在GCE(Google Compute Engine) 里面是現成的網絡模型,K8S假定這個網絡已存在。而在私有雲搭建K8S集群,就不能假定這個網絡已經存在了。我們需要自己實現這個網絡假設,將不同節點上的Docker容器之間互相訪問先打通,然后再運行K8S。

 同一個Pod內的多個容器間:lo     pause

 各Pod之間的通訊: Overlay Network

 Pod與Service之間的通訊:各節點的Iptables規則,新版本支持LVS 轉發上限、效率更高

 

網絡解決方案K8S+Flannel 

  Flannel是CoreOS團隊針對K8S設計的一個網絡規划服務,簡單來說他,他的功能是讓集群中的不同節點主機創建的Docker容器具有全集群唯一的虛擬IP主機。而且它還能在這些IP之間建立一個覆蓋網絡(Overlay Network),通過這個覆蓋網絡,將數據包原封不動地傳遞到目標容器內

  

 ETCD之Flannel提供說明:

  >存儲管理Flannel可分配的IP地址段資源

  >監控ETCD中每個Pod的實際地址,並在內存中建立維護Pod節點路由表

 

不同情況下網絡通信方式

 同一個 Pod 內部通訊:同一個 Pod 共享同一個網絡命名空間,共享同一個 Linux 協議棧

 Pod1 至 Pod2

  > Pod1 與 Pod2 不在同一台主機,Pod的地址是與docker0在同一個網段的,但docker0網段與宿主機網卡是兩個完全不同的IP網段,並且不同Node之間的通信只能通過宿主機的物理網卡進行。將Pod的IP和所在Node的IP關聯起來,通過 這個關聯讓Pod可以互相訪問

  > Pod1 與 Pod2 在同一台機器,由 Docker0 網橋直接轉發請求至 Pod2,不需要經過 Flannel

 Pod 至 Service 的網絡:目前基於性能考慮,全部為 iptables 維護和轉發

 Pod 到外網:Pod 向外網發送請求,查找路由表, 轉發數據包到宿主機的網卡,宿主網卡完成路由選擇后,iptables執 行Masquerade,把源 IP 更改為宿主網卡的 IP,然后向外網服務器發送請求

 外網訪問 Pod:Service

 

 組件通訊示意圖

  

 

三、集群安裝

 

K8S構建1台master2台node+Harbor_筆記 :https://www.cnblogs.com/yyq1/p/13991453.html

 

四、資源清單

 

資源:K8s 中所有的內容都抽象為資源, 資源實例化之后,叫做對象

 

4.1 K8S 中的資源

名稱空間級別
 工作負載型資源( workload ): Pod、ReplicaSet、Deployment、StatefulSet、DaemonSet、Job、 CronJob ( ReplicationController 在 v1.11 版本被廢棄 )

 服務發現及負載均衡型資源( ServiceDiscovery LoadBalance ): Service、Ingress、...

 配置與存儲型資源:Volume( 存儲卷 )、CSI( 容器存儲接口,可以擴展各種各樣的第三方存儲卷 )
 特殊類型的存儲卷:ConfigMap( 當配置中心來使用的資源類型 )、Secret(保存敏感數據)、 DownwardAPI(把外部環境中的信息輸出給容器)

集群級資源:Namespace、Node、Role、ClusterRole、RoleBinding、ClusterRoleBinding

元數據型資源:(根據某些指標進行操作):HPA、PodTemplate、LimitRange 

 

4.2 資源清單

 

資源清單含義:

  在 k8s 中,一般使用 yaml 格式的文件來創建符合我們預期期望的 pod ,這樣的 yaml 文件我們一般 稱為資源清單

 

簡單說明

  是一個可讀性高,用來表達數據序列的格式。YAML 的意思其實是:仍是一種標記語言,但為了強調這種語言以數 據做為中心,而不是以標記語言為重點


基本語法
  縮進時不允許使用Tab鍵,只允許使用空格

  縮進的空格數目不重要,只要相同層級的元素左側對齊即可

  #標識注釋,從這個字符一直到行尾,都會被解釋器忽略

 

YAML 支持的數據結構
  對象:鍵值對的集合,又稱為映射(mapping)/ 哈希(hashes) / 字典(dictionary)

  數組:一組按次序排列的值,又稱為序列(sequence) / 列表 (list)

  純量(scalars):單個的、不可再分的值

 

對象類型:對象的一組鍵值對,使用冒號結構表示

  name: Steve

  age: 18

 

Yaml 也允許另一種寫法,將所有鍵值對寫成一個行內對象

  hash: { name: Steve, age: 18 }

 

數組類型:一組連詞線開頭的行,構成一個數組

  animal

    - Cat

    - Dog

 

數組也可以采用行內表示法

  animal: [Cat, Dog]

 

復合結構:對象和數組可以結合使用,形成復合結構

  1 languages:

  2 - Ruby

  3 - Perl

  4 - Python

  5 websites:

  6 YAML: yaml.org

  7 Ruby: ruby-lang.org

  8 Python: python.org

  9 Perl: use.perl.org

  

純量:純量是最基本的、不可再分的值。以下數據類型都屬於純量

1 字符串 布爾值 整數 浮點數 Null
2 時間 日期

數值直接以字面量的形式表示 number: 12.30
布爾值用true和false表示 isSet: true null用 ~ 表示 parent: ~ 時間采用 ISO8601 格式 iso8601: 2001-12-14t21:59:43.10-05:00 日期采用復合 iso8601 格式的年、月、日表示 date: 1976-07-31 YAML 允許使用兩個感嘆號,強制轉換數據類型 e: !!str 123 f: !!str true

  

字符串

字符串默認不使用引號表示

str: 這是一行字符串

  

如果字符串之中包含空格或特殊字符,需要放在引號之中

  str: '內容: 字符串'

   

單引號和雙引號都可以使用,雙引號不會對特殊字符轉義

s1: '內容\n字符串'
s2: "內容\n字符串"

  

單引號之中如果還有單引號,必須連續使用兩個單引號轉義

str: 'labor''s day'

   

字符串可以寫成多行,從第二行開始,必須有一個單空格縮進。換行符會被轉為 空格

str: 這是一段

 多行

 字符串

   

多行字符串可以使用|保留換行符,也可以使用>折疊換行

this:|

Foo

Bar

that: >

Foo

Bar

   

+ 表示保留文字塊末尾的換行,- 表示刪除字符串末尾的換行

s1: |

 Foo

s2: |+

 Foo


s3: |-

 Foo

   

4.3 常用字段的解釋

  參考資料: https://www.cnblogs.com/panwenbin-logs/p/9895953.html

  必須存在的屬性:

   主要對象:

  

額外的參數項:

 

kubectl explain pod  

查看pod模板

 

 

繼續查看

kubectl explain pod.spec

  

kubectl explain pod.spec.containers

 

 

創建一個簡單的yaml模板

vi pod.yaml

  

這里使用相同鏡像,默認情況會端口沖突

使用yaml文件創建pod:

kubectl apply -f pod.yaml

  

已經創建

查看運行情況 

  

發現容器報錯,不斷重啟,已經重啟4次了

排查問題:

kubectl describe pod mynginx-pod

第二個 test容器報錯了

 

查看test容器

kubectl log mynginx-pod -c test
kubectl logs mynginx-pod -c test

指定查看pod和容器日志

80端口被占用

 

刪除 test容器:

vim pod.yaml

 

 

kubectl delete pod mynginx-pod
kubectl get pod
kubectl apply -f pod.yaml
kubectl get pod 

 

 

4.4 容器生命周期

 

 

 

Init 容器
  Pod 能夠具有多個容器,應用運行在容器里面,但是它也可能有一個或多個先於應用容器啟動的 Init 容器

  Init 容器與普通的容器非常像,除了如下兩點:

    Ø Init 容器總是運行到成功完成為止

    Ø 每個 Init 容器都必須在下一個 Init 容器啟動之前成功完成

  如果 Pod 的 Init 容器失敗,Kubernetes 會不斷地重啟該 Pod,直到 Init 容器成功為止。然而,

  如果 Pod 對應的 restartPolicy 為 Never,它不會重新啟動

 

Init 容器的作用

  因為 Init 容器具有與應用程序容器分離的單獨鏡像,所以它們的啟動相關代碼具有如下優勢:

    Ø 它們可以包含並運行實用工具,但是出於安全考慮,是不建議在應用程序容器鏡像中包含這 些實用工具的

    Ø 它們可以包含使用工具和定制化代碼來安裝,但是不能出現在應用程序鏡像中。例如,創建 鏡像沒必要 FROM 另一個鏡像,只需要在安裝過程中使用類似 sed、 awk、 python 或 dig 這樣的工具。

    Ø 應用程序鏡像可以分離出創建和部署的角色,而沒有必要聯合它們構建一個單獨的鏡像。

    Ø Init 容器使用 Linux Namespace,所以相對應用程序容器來說具有不同的文件系統視圖。因 此,它們能夠具有訪問 Secret 的權限,而應用程序容器則不能。

    Ø 它們必須在應用程序容器啟動之前運行完成,而應用程序容器是並行運行的,所以 Init 容 器能夠提供了一種簡單的阻塞或延遲應用容器的啟動的方法,直到滿足了一組先決條件。

 

 

Init 容器

init 模板

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

 

kind: Service
apiVersion: v1
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

 

檢測探針 - 就緒檢測

 

readinessProbe-httpget

apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-pod
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: wangyanglinux/myapp:v1
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3

  

檢測探針 - 存活檢測

livenessProbe-exec

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: hub.atguigu.com/library/busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/live"]
      initialDelaySeconds: 1
      periodSeconds: 3

  

livenessProbe-httpget

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: hub.atguigu.com/library/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

  

livenessProbe-tcp

apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: hub.atguigu.com/library/myapp:v1
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 80

  

啟動、退出動作

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the poststop handler > /usr/share/message"]

 

開始測試:

在節點執行

docker pull busybox
vim init.pod.yaml

  

kubectl create -f init.pod.yaml

 

 如果遇到重名,刪除操作:

kubectl get pod
kubectl delete deployment --all

 

kubectl get pod

  

kubectl delete pod --all

 

  

kubectl get pod

  

kubectl get svc
kubectl delete svc nginx-deployment

 

kubectl get svc

 

kubectl create -f init.pod.yaml

狀態沒有ready

 

kubectl describe pod myapp-pod

  

kubectl log  myapp-pod -c init-myservice

  

一直沒解析到 myservice

創建 myservice

vim myservice.yaml

  

kubectl log  myapp-pod -c init-myservice

等待后

kubectl get pod

  

已經成功了1個

  

發現已經創建了myservice的svc

這個svc會被集群內部的dns解析

 

  

創建pod時指定了myservice的svc,創建svc后會寫入到coredns,pod請求core會返回請求,至此按照pod yaml的配置已經過去了第一個myservice,還剩一個mydb。

創建mydb

vim mydb.yaml

  

kubectl create -f mydb.yaml

 

成功啟來了

只有所有init c成功運行后 ,main c才會被運行。

如果報錯

 

kubectl describe pod myapp-pod

原因為node1下載busybox失敗,可能原因為 不指定版本號,會使用latest標簽保存,每次使用都會去下載最新版,下載失敗就會報錯。

 

特殊說明 -1
  在 Pod 啟動過程中,Init 容器會按順序在網絡和數據卷初始化之后啟動。每個容器必須在下一個 容器啟動之前成功退出
  如果由於運行時或失敗退出,將導致容器啟動失敗,它會根據 Pod 的 restartPolicy 指定的策略 進行重試。然而,如果 Pod 的 restartPolicy 設置為 Always,Init 容器失敗時會使用 RestartPolicy 策略
  在所有的 Init 容器沒有成功之前,Pod 將不會變成 Ready 狀態。Init 容器的端口將不會在 Service 中進行聚集。 正在初始化中的 Pod 處於 Pending 狀態,但應該會將 Initializing 狀 態設置為 true
  如果 Pod 重啟,所有 Init 容器必須重新執行

  # 對 Init 容器 spec 的修改被限制在容器 image 字段,修改其他字段都不會生效。更改 Init 容器的 image 字段,等價於重啟該 Pod

  Init 容器具有應用容器的所有字段。除了 readinessProbe,因為 Init 容器無法定義不同於完成 (completion)的就緒(readiness)之外的其他狀態。這會在驗證過程中強制執行

  在 Pod 中的每個 app 和 Init 容器的名稱必須唯一;與任何其它容器共享同一個名稱,會在驗證 時拋出錯誤

 

容器探針
  探針是由 kubelet 對容器執行的定期診斷。要執行診斷,kubelet 調用由容器實現的 Handler。有三 種類型的處理程序:

    ExecAction:在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。

    TCPSocketAction:對指定端口上的容器的 IP 地址進行 TCP 檢查。如果端口打開,則診斷 被認為是成功的。
    HTTPGetAction:對指定的端口和路徑上的容器的 IP 地址執行 HTTP Get 請求。如果響應的 狀態碼大於等於200 且小於 400,則診斷被認為是成功的
  每次探測都將獲得以下三種結果之一:

    成功:容器通過了診斷。

    失敗:容器未通過診斷。

    未知:診斷失敗,因此不會采取任何行動

 

探測方式
  livenessProbe:指示容器是否正在運行。如果存活探測失敗,則 kubelet 會殺死容器,並且容器將 受到其 重啟策略 的影響。如果容器不提供存活探針,則默認狀態為 Success
  readinessProbe:指示容器是否准備好服務請求。如果就緒探測失敗,端點控制器將從與 Pod 匹配的 所有 Service 的端點中刪除該 Pod 的 IP 地址。初始延遲之前的就緒狀態默認為 Failure。如果容 器不提供就緒探針,則默認狀態為 Success

 

檢測探針 - 就緒檢測(符合條件才READY狀態) 測試:

  readinessProbe-httpget 方案

vim read.yaml

  

kubectl create -f read.yaml

  

kubectl get pod

  

雖然顯示Running 但是沒有READY查看日志

kubectl describe pod  readiness-httpget-pod

  

沒有找到index1.html 報404頁面不存在,原因為yaml文件里檢測的index1.html ,真實不存在

進入容器 readiness-httpget-pod

kubectl exec readiness-httpget-pod -it -- /bin/sh 
cd /usr/share/nginx/html
echo "123" > index1.html
exit
kubectl get pod

  

因為文件已經存在,檢測到就READY了,測試完畢,刪除:

kubectl delete pod --all
kubectl delete svc mydb myservice

 

檢測探針 - 存活檢測(不符合條件就重啟) 測試:

 

  livenessProbe-exec方案

vim live-exec.yaml

  

kubectl create -f live-exec.yaml

 

等待一分鍾

 

重啟原因為yaml文件設置如果文件不存在,存活檢測會重啟Pod,達到60秒(排除啟動和延遲,實際要多一點)重啟的結果。清理:

kubectl delete pod --all

 

  livenessProbe-httpget方案

vim live.http.yaml

 

kubectl create -f live.http.yaml
kubectl get pod

 

正常啟動

可以訪問

刪除index.html 

kubectl exec liveness-httpget-pod -it -- /bin/sh
# rm -rf /usr/share/nginx/html/index.html
exit
curl 10.244.2.9/index.html

報錯404

 

kubectl get pod

 

由於yaml文件中設置了檢測index.html是否存在,如果不存在就重啟, 查看重啟次數已經是1了。

 

由於重啟后index.html又回來, 之后就沒有重啟。

再刪一次:

由於設置的是3秒檢測一次,很快就又重啟了。

清理:

kubectl delete pod --all

 

  livenessProbe-tcp方案

vim live-tcp.yaml

 

kubectl create -f live-tcp.yaml
kubectl get pod -w

 

由於檢測的端口是8080,nginx端口是80,初始5秒后開始檢測,發現沒有8080,1秒后重啟。

 

合並檢測方式:

vim live-http.yaml

 

同時進行 readinessProbe(就緒檢測) 和livenessProbe(存活檢測)

 

發現由於沒有index1.html 一直沒ready

kubectl exec liveness-httpget-pod -it -- /bin/bash
echo "123" >> /usr/share/nginx/html/index1.html
exit
kubectl get pod

 

發現已經就緒了 

繼續測試 存活檢測:

kubectl exec liveness-httpget-pod -it -- rm -rf /usr/share/nginx/html/index.html
kubectl get pod -w

發現刪除后就重啟,並且由於重啟后又沒有index1.html,就緒檢測執行后未通過。

 

readinessProbe(就緒檢測) 和livenessProbe(存活檢測)可以配合init c  start stop 使用

 了解 start stop

  

vim post.yaml

 

kubectl create -f post.yaml

 

kubectl exec lifecycle-demo -it -- cat /usr/share/message 

 

驗證通過 

此不會采取任何行動

 

Pod hook
  Pod hook(鈎子)是由 Kubernetes 管理的 kubelet 發起的,當容器中的進程啟動前或者容器中的進 程終止之前運行,這是包含在容器的生命周期之中。可以同時為 Pod 中的所有容器都配置 hook

  Hook 的類型包括兩種:

    exec:執行一段命令

    HTTP:發送HTTP請求

 

重啟策略
  PodSpec 中有一個 restartPolicy 字段,可能的值為 Always、OnFailure 和 Never。默認為 Always。 restartPolicy 適用於 Pod 中的所有容器。restartPolicy 僅指通過同一節點上的 kubelet 重新啟動容器。失敗的容器由 kubelet 以五分鍾為上限的指數退避延遲(10秒,20秒,40 秒...)重新啟動,並在成功執行十分鍾后重置。如 Pod 文檔 中所述,一旦綁定到一個節點,Pod 將 永遠不會重新綁定到另一個節點。

 

Pod phase

  Pod 的 status 字段是一個 PodStatus 對象,PodStatus中有一個 phase 字段。
  Pod 的相位(phase)是 Pod 在其生命周期中的簡單宏觀概述。該階段並不是對容器或 Pod 的綜合匯 總,也不是為了做為綜合狀態機
  Pod 相位的數量和含義是嚴格指定的。除了本文檔中列舉的狀態外,不應該再假定 Pod 有其他的 phase 值

 

Pod phase 可能存在的值
  掛起(Pending):Pod 已被 Kubernetes 系統接受,但有一個或者多個容器鏡像尚未創建。等待時間 包括調度 Pod 的時間和通過網絡下載鏡像的時間,這可能需要花點時間
  運行中(Running):該 Pod 已經綁定到了一個節點上,Pod 中所有的容器都已被創建。至少有一個容 器正在運行,或者正處於啟動或重啟狀態

  成功(Succeeded):Pod 中的所有容器都被成功終止,並且不會再重啟
  失敗(Failed):Pod 中的所有容器都已終止了,並且至少有一個容器是因為失敗終止。也就是說,容 器以非 0 狀態退出或者被系統終止

  未知(Unknown):因為某些原因無法取得 Pod 的狀態,通常是因為與 Pod 所在主機通信失敗

 

 

五、資源控制器

Pod 的分類

  自主式 Pod:Pod 退出了,此類型的 Pod 不會被創建
  控制器管理的 Pod:在控制器的生命周期里,始終要維持 Pod 的副本數目

 

5.1 Kubernetes Pod 控制器

什么是控制器
  Kubernetes 中內建了很多 controller(控制器),這些相當於一個狀態機,用來控制 Pod 的具體狀態和行為

控制器類型
  ReplicationController 和 ReplicaSet (無狀態服務RS-Deployment)
  Deployment
  DaemonSet(以Node為節點部署)
  StateFulSet (有狀態服務)
  Job/CronJob (批處理任務部署)
  Horizontal Pod Autoscaling (可以理解為並不是一個控制器,而是一個控制器的附屬品,以其他控制器作為模板)
ReplicationController 和 ReplicaSet
  ReplicationController(RC)用來確保容器應用的副本數始終保持在用戶定義的副本數,即如果有容器異常退出,會自動創建新的 Pod 來替代;而如果異常多出來的容器也會自動回收;
  在新版本的 Kubernetes 中建議使用 ReplicaSet 來取代 ReplicationController 。ReplicaSet 跟ReplicationController 沒有本質的不同,只是名字不一樣,並且 ReplicaSet 支持集合式的 selector;

Deployment
  Deployment 為 Pod 和 ReplicaSet 提供了一個聲明式定義 (declarative) 方法,用來替代以前的ReplicationController 來方便的管理應用。典型的應用場景包括;
    定義 Deployment 來創建 Pod 和 ReplicaSet
    滾動升級和回滾應用
    擴容和縮容
    暫停和繼續 Deployment

  命令式編程:它側重於如何實現程序,就像編程那樣,把步驟一步步寫下來。

  聲明式編程:它側重定義想要什么,然后告訴計算機/引擎,讓他幫你去實現。

  聲明式編程 (Deployment) apply(優) create
  命令式 (rs) create(優) apply

  

  

  Deployment創建rs,rs創建、管理pod 

DaemonSet

  DaemonSet 確保全部(或者一些,根據調度策略或者污點定義)Node 上運行一個 Pod 的副本。當有 Node 加入集群時,也會為他們新增一個Pod 。當有 Node 從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod使用 DaemonSet 的一些典型用法:
  運行集群存儲 daemon,例如在每個 Node 上運行 glusterd 、 ceph
  在每個 Node 上運行日志收集 daemon,例如 fluentd 、 logstash
  在每個 Node 上運行監控 daemon,例如 zabbix agent、Prometheus Node Exporter、 collectd 、Datadog 代理、New Relic 代理,或 Ganglia gmond
Job
  Job 負責批處理任務,即僅執行一次的任務,它保證批處理任務的一個或多個 Pod 成功結束(跟linux crontab比有糾錯功能)
CronJob (在特定的時間循環創建Job)
  Cron Job 管理基於時間的 Job,即:   分時日月周
    在給定時間點只運行一次
    周期性地在給定時間點運行
使用前提條件:**當前使用的 Kubernetes 集群,版本 >= 1.8(對 CronJob)。對於先前版本的集群,版本 <1.8,啟動 API Server時,通過傳遞選項 --runtime-config=batch/v2alpha1=true 可以開啟 batch/v2alpha1API**
典型的用法如下所示:
  在給定的時間點調度 Job 運行
  創建周期性運行的 Job,例如:數據庫備份、發送郵件

StatefulSet
  StatefulSet 作為 Controller 為 Pod 提供唯一的標識。它可以保證部署和 scale 的順序
  StatefulSet是為了解決有狀態服務的問題(對應Deployments和ReplicaSets是為無狀態服務而設計),其應用場景包括:
    穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基於PVC來實現
    穩定的網絡標志,即Pod重新調度后其PodName和HostName不變,基於Headless Service(即沒有Cluster IP的Service)來實現
    有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次依次進行(即從0到N-1,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態),基於init containers來實現
    有序收縮,有序刪除(即從N-1到0)

  

 

Horizontal Pod Autoscaling
應用的資源使用率通常都有高峰和低谷的時候,如何削峰填谷,提高集群的整體資源利用率,讓service中的Pod個數自動調整呢?這就有賴於Horizontal Pod Autoscaling了,顧名思義,使Pod水平自動縮放

 

5.2 Kubernetes Deployment 控制器

[root@k8s-master01 ~]# kubectl explain rs

RS 與 RC 與 Deployment 關聯

  RC (ReplicationController )主要的作用就是用來確保容器應用的副本數始終保持在用戶定義的副本數 。即如果有容器異常退出,會自動創建新的Pod來替代;而如果異常多出來的容器也會自動回收
  Kubernetes 官方建議使用 RS(ReplicaSet ) 替代 RC (ReplicationController ) 進行部署,RS 跟 RC 沒有本質的不同,只是名字不一樣,並且 RS 支持集合式的 selector

[root@k8s-master01 ~]# vim rs.yaml

 

kubectl create -f rs.yaml

kubectl get pod

多出了3個Pod

 

kubectl delete pod --all 

清理以前的Pod

kubectl get pod  

之前4個pod全被刪除,沒有刪除deployment,為了維持定義的副本數又創建了3個pod,但是名稱不一樣了。

 

查看標簽

kubectl get pod --show-labels

yaml文件中定義的標簽是 frontend

 

更改標簽

報錯,提示frontend-bdhhj已有標簽,除非添加--overwrite參數

 

kubectl label pod frontend-bdhhj tier=frontend1 --overwrite=True

  

提示已修改,可以看到frontend-bdhhj標簽已改,並且由於yaml模板中pod設置了匹配標簽選項,frontend標簽繼續保持副本數添加了一個新的pod。

 

刪除rs

kubectl delete rs --all
kubectl get pod --show-labels

僅刪除了rs關聯的pod

 

清理

kubectl delete pod --all

 

RS 與 Deployment 的關聯

 

Deployment
Deployment 為 Pod 和 ReplicaSet 提供了一個聲明式定義(declarative)方法,用來替代以前的ReplicationController 來方便的管理應用。典型的應用場景包括:
  定義Deployment來創建Pod和ReplicaSet
  滾動升級和回滾應用
  擴容和縮容
  暫停和繼續Deployment
I、部署一個簡單的 Nginx 應用

vim deployment.yaml

 

kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record

## --record參數可以記錄命令,我們可以很方便的查看每次 revision 的變化

 

kubectl get deployment
kubectl get rs
kubectl get pod

deployment創建會創建對應的rs

  

訪問

curl 10.244.1.16

  

II、擴容副本數

kubectl scale deployment nginx-deployment --replicas=10

  

發現像nginx這種無狀態服務擴容特別簡單

名稱未變,數目調整不會調整模板信息

 

III、更新鏡像:

kubectl set image deployment/nginx-deployment nginx=hub.yyq.com/library/mynginx:v2

 

提示已更新

 

查看rs

kubectl get rs

發現 期望是2 當前是2 但是ready是0 

 

查看Pod

發現當前並沒有v2版本,也就pull不到

 

創建一個v2

 

cd n/
vim Dockerfile

 

#Version:2
FROM hub.yyq.com/library/mynginx:v1
RUN echo $HOSTNAME > /usr/share/nginx/html/index.html
docker build -t="hub.yyq.com/library/mynginx:v2" .
docker login https://hub.yyq.com
docker push hub.yyq.com/library/mynginx:v2 

 

kubectl delete deployment nginx-deployment
kubectl create -f deployment.yaml
kubectl scale deployment nginx-deployment --replicas=10
kubectl set image deployment/nginx-deployment nginx=hub.yyq.com/library/mynginx:v2
kubectl get pod -o wide -w

過程如:

陸續更新完成

 

kubectl get rs

已全部更新

 

驗證

 

IV、回滾:

kubectl rollout undo deployment/nginx-deployment

交替過程

kubectget pod -w -o wide

kubectl rollout status deployment/nginx-deployment

 

 

kubect get rs

 

驗證

kubectl rollout status deployment/nginx-deployment

 

curl 10.244.2.64

 回v1版了

 

V、如果集群支持 horizontal pod autoscaling 的話,還可以為Deployment設置自動擴展

kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80


可以使用 edit 命令來編輯 Deployment

kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited

可以更新副本數或其他

 

 

Deployment 更新策略
  Deployment 可以保證在升級時只有一定數量的 Pod 是 down 的。默認的,它會確保至少有比期望的Pod數量少一個是up狀態(最多一個不可用)
  Deployment 同時也可以確保只創建出超過期望數量的一定數量的 Pod。默認的,它會確保最多比期望的Pod數量多一個的 Pod 是 up 的(最多1個 surge )
  未來的 Kuberentes 版本中,將從1-1變成25%-25% (無論數量多少,交替過程中每次操作25%的數量)

      

 

kubectl describe deployments

 

Rollover(多個rollout並行)
  假如您創建了一個有5個 niginx:1.7.9 replica的 Deployment,但是當還只有3個 nginx:1.7.9 的 replica 創建出來的時候您就開始更新含有5個 nginx:1.9.1 replica 的 Deployment。在這種情況下,Deployment 會立即殺掉已創建的3個 nginx:1.7.9 的 Pod,並開始創建 nginx:1.9.1 的 Pod。它不會等到所有的5個 nginx:1.7.9 的Pod 都創建完成后才開始改變航道


回退 Deployment

kubectl set image deployment/nginx-deployment nginx=nginx:1.91
kubectl rollout status deployments nginx-deployment
kubectl get pods
kubectl rollout history deployment/nginx-deployment

CHANGE-CAUSE 是none 因為創建時沒有加--record

 

測試一下:

  kubectl delete deployment --all
  kubectl create -f deployment.yaal  --record
  kubectl set image deployment/nginx-deployment nginx=hub.yyq.com/library/mynginx:v2
  kubectl rollout history deployment/nginx-deployment

  

 

   kubectl set image deployment/nginx-deployment nginx=hub.yyq.com/library/mynginx:v3
   kubectl rollout history deployment/nginx-deployment

  

 

  kubectl get rs

  

  產生了新的rs

   

kubectl rollout undo deployment/nginx-deployment --to-revision=1

## 可以使用 --revision參數指定某個歷史版本

 

 

再看歷史版本

kubectl rollout history deployment/nginx-deployment

當前版本的這里查看歷史版本,回退到以前的版本時以前的版本號會變成新的號,比如按照上圖回退到2,就會變成3 4 5,再會退到4就變成356

 

kubectl rollout pause deployment/nginx-deployment

 

## 暫停 deployment 的更新
您可以用 kubectl rollout status 命令查看 Deployment 是否完成。如果 rollout 成功完成, kubectl rollout
status 將返回一個0值的 Exit Code

kubectl rollout status deploy/nginx

 

Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx" successfully rolled out
$ echo $?
0 

 

kubectl delete deployment --all

 

清理 Policy
您可以通過設置 .spec.revisonHistoryLimit 項來指定 deployment 最多保留多少 revision 歷史記錄。默認的會
保留所有的 revision;如果將該項設置為0,Deployment 就不允許回退了

 

5.3 Kubernetes DaemonSet 控制器 

什么是 DaemonSet

  DaemonSet 確保全部(或者一些)Node 上運行一個 Pod 的副本。當有 Node 加入集群時,也會為他們新增一個 Pod 。當有 Node 從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod
使用 DaemonSet 的一些典型用法:
  運行集群存儲 daemon,例如在每個 Node 上運行 glusterd 、 ceph
  在每個 Node 上運行日志收集 daemon,例如 fluentd 、 logstash
  在每個 Node 上運行監控 daemon,例如 Zabbix agent、 Prometheus Node Exporter、 collectd 、Datadog 代理、New Relic 代理,或 Ganglia gmond
 

vim daemonset.yaml

 

 

 

kubectl create -f daemonset.yaml
kubect get pod 

 

kubectl get daemonset.apps

 

kubectl get pod 

 

5.4 Kubernetes JobCronJob 控制器

 

Job

 Job 負責批處理任務,即僅執行一次的任務,它保證批處理任務的一個或多個 Pod 成功結束
 特殊說明
  spec.template格式同Pod
  RestartPolicy僅支持Never或OnFailure
  單個Pod時,默認Pod成功運行后Job即結束
  .spec.completions 標志Job結束需要成功運行的Pod個數,默認為1
  .spec.parallelism 標志並行運行的Pod的個數,默認為1
  spec.activeDeadlineSeconds 標志失敗Pod的重試最大時間,超過這個時間不會繼續重試

vim job.yam

計算Pi2000位(根據機器性能可以調小點)

 

kubectl create -f job.yaml

 

 

kubectl get pod 

 

kubectl describe pod pi-lbrh5

 

正在下鏡像,太慢了,手動導入

yum -y install lrzsz

perl.tar.gz

[root@k8s-master01 ~]# tar xvf perl.tar.gz
[root@k8s-master01 ~]# docker load -i perl.tar
[root@k8s-master01 ~]# scp perl.tar root@k8s-node01:/root
[root@k8s-master01 ~]# scp perl.tar root@k8s-node02:/root
[root@k8s-node01 ~]# docker load -i perl.tar
[root@k8s-node02 ~]# docker load -i perl.tar
kubectl get pod

 

時間比較久,已經ImagePullBackOff了,刪除,自己重建。

 

kubectl get pod -o wide

等待

 

kubectl get pod 

已經Completed了

 

get pod job

作業完成

 

查看日志

已經將圓周率推算到2000位,如果運行太慢,修改yaml文件將數字改小,刪除后然后重新創建。

 

CronJob Spec

  spec.template格式同Pod
  RestartPolicy僅支持Never或OnFailure
  單個Pod時,默認Pod成功運行后Job即結束
  .spec.completions 標志Job結束需要成功運行的Pod個數,默認為1
  .spec.parallelism 標志並行運行的Pod的個數,默認為1
  spec.activeDeadlineSeconds 標志失敗Pod的重試最大時間,超過這個時間不會繼續重試

 

CronJob

 Cron Job 管理基於時間的 Job,即:
  在給定時間點只運行一次
  周期性地在給定時間點運行

 使用條件:當前使用的 Kubernetes 集群,版本 >= 1.8(對 CronJob)

 典型的用法如下所示:
  在給定的時間點調度 Job 運行
  創建周期性運行的 Job,例如:數據庫備份、發送郵件

CronJob Spec

  .spec.schedule :調度,必需字段,指定任務運行周期,格式同 Cron
  .spec.jobTemplate :Job 模板,必需字段,指定需要運行的任務,格式同 Job
  .spec.startingDeadlineSeconds :啟動 Job 的期限(秒級別),該字段是可選的。如果因為任何原因而錯過了被調度的時間,那么錯過執行時間的 Job 將被認為是失敗的。如果沒有指定,則沒有期限
  .spec.concurrencyPolicy :並發策略,該字段也是可選的。它指定了如何處理被 Cron Job 創建的 Job 的並發執行。只允許指定下面策略中的一種:
    Allow (默認):允許並發運行 Job
    Forbid :禁止並發運行,如果前一個還沒有完成,則直接跳過下一個
    Replace :取消當前正在運行的 Job,用一個新的來替換
    注意,當前策略只能應用於同一個 Cron Job 創建的 Job。如果存在多個 Cron Job,它們創建的 Job 之間總是允許並發運行。
  .spec.suspend :掛起,該字段也是可選的。如果設置為 true ,后續所有執行都會被掛起。它對已經開始執行的 Job 不起作用。默認值為 false 。
  .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit :歷史限制,是可選的字段。它們指定了可以保留多少完成和失敗的 Job。默認情況下,它們分別設置為 3 和 1 。設置限制的值為 0 ,相關類型的 Job 完成后將不會被保留。

 

vim cronjob.yaml

 

kubectl apply -f cronjob.yaml

 

 

kubectl get cronjob

 

 

kubectl get job

 

kubectl log hello-1605656340-gbf95

 

清理

kubectl delete cronjob --all

 

pods=$(kubectl get pods --selector=job-name=hello-1202039034 --output=jsonpath={.items..metadata.name})

  

CrondJob 本身的一些限制
  創建 Job 操作應該是 冪等 的

 

六、Service

Service 的概念

 

  Kubernetes Service 定義了這樣一種抽象:一個 Pod 的邏輯分組,一種可以訪問它們的策略 —— 通常稱為微服務。 這一組 Pod 能夠被 Service 訪問到,通常是通過 Label Selector

 

  這里的分配機制只有RR輪訓 

 

 

 Service能夠提供負載均衡的能力,但是在使用上有以下限制:
  只提供 4 層負載均衡能力,而沒有 7 層功能,但有時我們可能需要更多的匹配規則來轉發請求,這點上 4 層負載均衡是不支持的

Service 的類型
 Service 在 K8s 中有以下四種類型
  ClusterIp:默認類型,自動分配一個僅 Cluster 內部可以訪問的虛擬 IP

   

  NodePort:在 ClusterIP 基礎上為 Service 在每台機器上綁定一個端口,這樣就可以通過 : NodePort 來訪問該服務

  

  LoadBalancer:在 NodePort 的基礎上,借助 cloud provider 創建一個外部負載均衡器,並將請求轉發到: NodePort

  

   需要借助於供應商來保存注冊、端口等信息,需要單獨收費

  ExternalName:把集群外部的服務引入到集群內部來,在集群內部直接使用。沒有任何類型代理被創建,這只有 kubernetes1.7 或更高版本的 kube-dns 才支持

  

 

  

 

 

VIP 和 Service 代理
 在 Kubernetes 集群中,每個 Node 運行一個 kube-proxy 進程。 kube-proxy 負責為 Service 實現了一種VIP(虛擬 IP)的形式,而不是 ExternalName 的形式。 在 Kubernetes v1.0 版本,代理完全在 userspace。在Kubernetes v1.1 版本,新增了 iptables 代理,但並不是默認的運行模式。 從 Kubernetes v1.2 起,默認就是iptables 代理。 在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理
 在 Kubernetes 1.14 版本開始默認使用 ipvs 代理
 在 Kubernetes v1.0 版本, Service 是 “4層”(TCP/UDP over IP)概念。 在 Kubernetes v1.1 版本,新增了Ingress API(beta 版),用來表示 “7層”(HTTP)服務
  !為何不使用 round-robin DNS?

  解析在客戶端緩存,很多客戶端解析后不會及時清理,可能會造成無法及時更新。

 

代理模式的分類
 I、userspace 代理模式

 

 

 

 II、iptables 代理模式

  

 III、ipvs 代理模式

  這種模式,kube-proxy 會監視 Kubernetes Service 對象和 Endpoints ,調用 netlink 接口以相應地創建ipvs 規則並定期與 Kubernetes Service 對象和 Endpoints 對象同步 ipvs 規則,以確保 ipvs 狀態與期望一致。訪問服務時,流量將被重定向到其中一個后端 Pod

  與 iptables 類似,ipvs 於 netfilter 的 hook 功能,但使用哈希表作為底層數據結構並在內核空間中工作。這意味着 ipvs 可以更快地重定向流量,並且在同步代理規則時具有更好的性能。此外,ipvs 為負載均衡算法提供了更多選項,例如:
    rr :輪詢調度
    lc :最小連接數
    dh :目標哈希
    sh :源哈希
    sed :最短期望延遲
    nq : 不排隊調度


 

ClusterIP
 clusterIP 主要在每個 node 節點使用 iptables(或ipvs),將發向 clusterIP 對應端口的數據,轉發到 kube-proxy 中。然后 kube-proxy 自己內部實現有負載均衡的方法,並可以查詢到這個 service 下對應 pod 的地址和端口,進而把數據轉發給對應的 pod 的地址和端口

 

 

 為了實現圖上的功能,主要需要以下幾個組件的協同工作:

  apiserver 用戶通過kubectl命令向apiserver發送創建service的命令,apiserver接收到請求后將數據存儲到etcd中
  kube-proxy kubernetes的每個節點中都有一個叫做kube-porxy的進程,這個進程負責感知service,pod的變化,並將變化的信息寫入本地的iptables規則中
  iptables 使用NAT等技術將virtualIP的流量轉至endpoint中

wget https://github.com/kubernetes/ingress-nginx/blob/nginx-0.25.0/deploy/static/mandatory.yaml

wget https://github.com/kubernetes/ingress-nginx/blob/nginx-0.25.0/deploy/static/provider/baremetal/service-nodeport.yaml

 

由於鏡像獲取問題Service后續測試無法驗證。

delete deployment --all

delete ingress --all

delete svc svc-1 svc-2 svc-3

 

6.2 Kubernetes Ingress

 

 

7、存儲 configMap

7.1configMap(存儲配置文件)

7.2Secret(加密信息)

7.3volume(共享存儲卷)

7.4Persistent Volume(PV、PVC 持久卷)

 

7.1 configMap

 

configMap 描述信息

 ConfigMap 功能在 Kubernetes1.2 版本中引入,許多應用程序會從配置文件、命令行參數或環境變量中讀取配置信息。ConfigMap API 給我們提供了向容器中注入配置信息的機制,ConfigMap 可以被用來保存單個屬性,也可以用來保存整個配置文件或者 JSON二進制大對象

 

 

 

ConfigMap 的創建

 

I、使用目錄創建

mkdir configmap
cd configmap/
mkdir dir
cd dir/
vim game.properties

 

enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

 

vim ui.properties

 

color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

 

kubectl create configmap game-config --from-file=/root/configmap/dir/

—from-file 指定在目錄下的所有文件都會被用在 ConfigMap 里面創建一個鍵值對,鍵的名字就是文件名,就是文件的內容

 

kubectl get cm
kubectl get cm game-config -o yaml

可以看到設置的值信息

 

kubectl describe cm game-config

也可以看到

 

II、使用文件創建

只要指定為一個文件就可以從單個文件中創建 ConfigMap

kubectl create configmap game-config-2 --from-file=/root/configmap/dir/game.properties

—from-file 這個參數可以使用多次,你可以使用兩次分別指定上個實例中的那兩個配置文件,效果就跟指定整個目錄是一樣的

 

 

 

kubectl get configmaps game-config-2 -o yaml

 

III、使用字面值創建
使用文字值創建,利用 —from-literal 參數傳遞配置信息,該參數可以使用多次,格式如下

kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

 

 

kubectl get configmaps special-config -o yaml

 

kubectl describe configmap special-config

 

Pod 中使用 ConfigMap

 

I、使用 ConfigMap 來替代環境變量

已有

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

 

mkdir mkdir /root/configmap/env/
cd mkdir /root/configmap/env/
vim env.yaml 

 

kubectl get cm

  

vim pod.yaml

 

kubectl get pod

由於yaml設置的command執行成功后狀態就完成了

 

kubectl log dapi-test-pod

 

II、用 ConfigMap 設置命令行參數

已有

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

 

vim pod1.yaml

 

kubectl create -f pod1.yaml
kubectl get pod

 

kubectl log dapi-test-pod66

command 中的$(SPECIAL_LEVEL_KEY) 對應的 special-config中的special.how設置的的very charm

 

III、通過數據卷插件使用ConfigMap

已有

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

 

在數據卷里面使用這個 ConfigMap,有不同的選項。最基本的就是將文件填入數據卷,在這個文件中,鍵就是文件名,鍵值就是文件內容

 

vim 111.yaml

 

kubectl create -f 111.yaml
kubectl get pod
kubectl log dapi-test-pod11

報錯

 

修改yaml

vim 111.yaml

 

command: [ "/bin/sh", "-c", "sleep 600s" ]

 

delete -f 111.yaml
kubectl create -f 111.yaml
kubectl get pod

 

kubectl exec dapi-test-pod11 -it -- /bin/sh
cd /etc/config
ls
cat special.how

volumes掛載成功

 

清理

kubectl delete pod --all

kubectl delete cm --all

 

ConfigMap 的熱更新

 

mkdir /root/configmap/config
cd /root/configmap/config
vim 111.yaml

 

kubectl apply -f 111.yaml
kubectl get pod

 

kubectl exec my-nginx-64b66b49d8-rz6bc -it -- cat /etc/config/log_level

驗證完成

 

熱更新

修改 ConfigMap

 

kubectl edit configmap log-config

 

 

修改 log_level 的值為 DEBUG 等待大概 10 秒鍾時間,再次查看環境變量的值

 

kubectl exec my-nginx-64b66b49d8-rz6bc -it -- cat /etc/config/log_level

再次執行,發現已經改過來了。 

 

ConfigMap 更新后滾動更新 Pod
更新 ConfigMap 目前並不會觸發相關 Pod 的滾動更新,可以通過修改 pod annotations 的方式強制觸發滾動更新

kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations":{"version/config": "20190411" }}}}}'

這個例子里我們在 .spec.template.metadata.annotations 中添加 version/config ,每次通過修改version/config 來觸發滾動更新

!!! 更新 ConfigMap 后:
  使用該 ConfigMap 掛載的 Env 不會同步更新
  使用該 ConfigMap 掛載的 Volume 中的數據需要一段時間(實測大概10秒)才能同步更新

 

 

7.2Secret(加密信息)

 

Secret存在的意義
 Secret 解決了密碼、token、密鑰等敏感數據的配置問題,而不需要把這些敏感數據暴露到鏡像或者 Pod Spec中。Secret 可以以 Volume 或者環境變量的方式使用
 Secret 有三種類型:
  Service Account :用來訪問 Kubernetes API,由 Kubernetes 自動創建,並且會自動掛載到 Pod 的/run/secrets/kubernetes.io/serviceaccount 目錄中
  Opaque :base64編碼格式的Secret,用來存儲密碼、密鑰等
  kubernetes.io/dockerconfigjson :用來存儲私有 docker registry 的認證信息

 

Service Account(不常用)
 Service Account 用來訪問 Kubernetes API,由 Kubernetes 自動創建,並且會自動掛載到 Pod的/run/secrets/kubernetes.io/serviceaccount 目錄中

kubectl get pod
kubectl exec my-nginx-64b66b49d8-rz6bc -it -- /bin/sh
cd /run/secrets/kubernetes.io/serviceaccount 
ls  

 

 

ca.crt

namespace #pod所在namespace

token #認證信息

 

Opaque Secret

 

 

I、創建說明
Opaque 類型的數據是一個 map 類型,要求 value 是 base64 編碼格式:

echo -n "admin" | base64
YWRtaW4=
echo -n "1f2d1e2e67df" | base64
MWYyZDFlMmU2N2Rm

 

[root@k8s-master01 config]# vim secrets.yml

 

kubectl apply -f secrets.yml
kubectl get secrets

 已創建,並且每個名稱空間下都會有一個默認的token,用於pod的掛載。

 

 

kubectl get secrets -n kube-system

 

 

II、使用方式
1、將 Secret 掛載到 Volume 中

 

[root@k8s-master01 config]# vim pod1.yaml

 

kubectl apply -f pod1.yaml 
kubectl get pod 

 

kubectl exec seret-test -it -- /bin/sh
cat /erc/secrets/username

已經被解密

 

清理

kubectl delete pod --all

 

2、將 Secret 導出到環境變量中

 

[root@k8s-master01 config]# vim env.yaml

 

kubectl apply -f env.yaml

 

kubectl exec pod-deployment-564f59b6b7-6q5zg -it -- /bin/sh

測試通過

 

清理

kubectl delete -f env.yaml
kubectl delete deployment --all
kubernetes.io/dockerconfigjson

 

kubernetes.io/dockerconfigjson

使用 Kuberctl 創建 docker registry 認證的 secret 

模擬K8s啟動時候提示無法pull鏡像的場景,然后用認證解決,首先把倉庫設置成私有。

 

每台都刪除之前的鏡像

docker rmi hub.yyq.com/library/mynginx:v1

 

每台都退出登錄

docker logout hub.yyq.com

 

mkdir reg
cd reg
vim pod.yaml

 

kubectl create -f pod.yaml
kubectl get pod

報錯,查看日志

 

kubectl describe pod foo

無法pull鏡像,必須要認證以后才能下載

 

通過dockerconfigjson解決

 

kubectl create secret docker-registry myregistrykey --docker-server=hub.yyq.com --docker-username=admin --docker-password=Harbor12345 --docker-email=13439629295@139.com

 

secret 創建成功

 

編輯yaml文件,添加

vim pod.yaml

 

imagePullSecrets:
- name: myregistrykey

 

kubectl delete -f 
kubectl create -f pod.yaml
kubectl get pod

 

kubectl describe pod foo

pull成功

 

清理

kubectl delete pod --all

 

 

7.3 volume

  容器磁盤上的文件的生命周期是短暫的,這就使得在容器中運行重要應用時會出現一些問題。首先,當容器崩潰時,kubelet 會重啟它,但是容器中的文件將丟失——容器以干凈的狀態(鏡像最初的狀態)重新啟動。其次,在Pod 中同時運行多個容器時,這些容器之間通常需要共享文件。Kubernetes 中的 Volume 抽象就很好的解決了這些問題

 

背景

Kubernetes 中的有明確的壽命 —— 與封裝它的 Pod 相同。所f以,卷的生命比 Pod 中的所有容器都長,當這個容器重啟時數據仍然得以保存。當然,當 Pod 不再存在時,卷也將不復存在。也許更重要的是,Kubernetes支持多種類型的卷,Pod 可以同時使用任意數量的卷

 

卷的類型

Kubernetes 支持以下類型的卷:

awsElasticBlockStore
azureDisk
azureFile
cephfs
csi
downwardAPI
emptyDir
fc
flocker
gcePersistentDisk
gitRepo
glusterfs
hostPath
iscsi
local
nfs
persistentVolumeClaim
projected
portworxVolume
quobyte
rbd
scaleIO
secret
storageos
vsphereVolume


emptyDir
  當 Pod 被分配給節點時,首先創建 emptyDir 卷,並且只要該 Pod 在該節點上運行,該卷就會存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以讀取和寫入 emptyDir 卷中的相同文件,盡管該卷可以掛載到每個容器中的相同或不同路徑上。當出於任何原因從節點中刪除 Pod 時, emptyDir 中的數據將被永久刪除

 <--注意:容器崩潰不會從節點中移除 pod,因此 ·emptyDir· 卷中的數據在容器崩潰時是安全的-->

emptyDir 的用法有:
  暫存空間,例如用於基於磁盤的合並排序
  用作長時間計算崩潰恢復時的檢查點
  Web服務器容器提供數據時,保存內容管理器容器提取的文件

 

 

[root@k8s-master01 reg]# ntpdate ntp1.aliyun.com

 

mkdir volume
cd volume
vim em.yaml

 

 

kubectl apply -f em.yaml

  

kubectl exec test-pd -it -- /bin/sh

 

修改yaml,再添加一個容器

vim em.yaml

 

 

kubectl create -f em.yaml

 

 

kubectl exec test-pd1 -c test-container -it -- /bin/sh

 

使用另外一個終端登錄另外一個容器

 

有index.html,繼續測

 

返回另外一個容器

同步了

 

清理

kubectl delete pod --all

 

hostPath

  hostPath 卷將主機節點的文件系統中的文件或目錄掛載到集群中
hostPath 的用途如下:
  運行需要訪問 Docker 內部的容器;使用 /var/lib/docker 的 hostPath,本機需要訪問容器內部使用
  在容器中運行 cAdvisor;使用 /dev/cgroups 的 hostPath
  允許 pod 指定給定的 hostPath 是否應該在 pod 運行之前存在,是否應該創建,以及它應該以什么形式存在
除了所需的 path 屬性之外,用戶還可以為 hostPath 卷指定 type

 

使用這種卷類型是請注意,因為:
  由於每個節點上的文件都不同,具有相同配置(例如從 podTemplate 創建的)的 pod 在不同節點上的行為可能會有所不同
  當 Kubernetes 按照計划添加資源感知調度時,將無法考慮 hostPath 使用的資源
  在底層主機上創建的文件或目錄只能由 root 寫入。您需要在特權容器中以 root 身份運行進程,或修改主機上的文件權限以便寫入 hostPath 卷

vim pod1.yaml

 

在node01 node02上創建文件

mkdir /data
kubectl create -f pod1.yaml

 

kubectl exec test-pd -it -- /bin/sh

 

在node02上查看 /data

 

在node上重新寫入 

 

查看容器 

同步了

 

7.4  Persistent Volume

 

概念

PersistentVolume (PV)

  是由管理員設置的存儲,它是群集的一部分。就像節點是集群中的資源一樣,PV 也是集群中的資源。 PV 是Volume 之類的卷插件,但具有獨立於使用 PV 的 Pod 的生命周期。此 API 對象包含存儲實現的細節,即 NFS、iSCSI 或特定於雲供應商的存儲系統

PersistentVolumeClaim (PVC)

  是用戶存儲的請求。它與 Pod 相似。Pod 消耗節點資源,PVC 消耗 PV 資源。Pod 可以請求特定級別的資源(CPU 和內存)。聲明可以請求特定的大小和訪問模式(例如,可以以讀/寫一次或 只讀多次模式掛載)

靜態 pv
  集群管理員創建一些 PV。它們帶有可供群集用戶使用的實際存儲的細節。它們存在於 Kubernetes API 中,可用於消費

動態
  當管理員創建的靜態 PV 都不匹配用戶的 PersistentVolumeClaim 時,集群可能會嘗試動態地為 PVC 創建卷。此配置基於 StorageClasses :PVC 必須請求 [存儲類],並且管理員必須創建並配置該類才能進行動態創建。聲明該類為 "" 可以有效地禁用其動態配置
  要啟用基於存儲級別的動態存儲配置,集群管理員需要啟用 API server 上的 DefaultStorageClass [准入控制器]。例如,通過確保 DefaultStorageClass 位於 API server 組件的 --admission-control 標志,使用逗號分隔的有序值列表中,可以完成此操作

綁定
  master 中的控制環路監視新的 PVC,尋找匹配的 PV(如果可能),並將它們綁定在一起。如果為新的 PVC 動態調配 PV,則該環路將始終將該 PV 綁定到 PVC。否則,用戶總會得到他們所請求的存儲,但是容量可能超出要求的數量。一旦 PV 和 PVC 綁定后, PersistentVolumeClaim 綁定是排他性的,不管它們是如何綁定的。 PVC 跟PV 綁定是一對一的映射

持久化卷聲明的保護
  PVC 保護的目的是確保由 pod 正在使用的 PVC 不會從系統中移除,因為如果被移除的話可能會導致數據丟失

 <!--注意:當 pod 狀態為 'Pending' 並且 pod 已經分配給節點或 pod 為 'Runing' 狀態時,PVC處於活動狀態-->
  當啟用PVC 保護 alpha 功能時,如果用戶刪除了一個 pod 正在使用的 PVC,則該 PVC 不會被立即刪除。PVC 的刪除將被推遲,直到 PVC 不再被任何 pod 使用

持久化卷類型
PersistentVolume 類型以插件形式實現。Kubernetes 目前支持以下插件類型:
  GCEPersistentDisk AWSElasticBlockStore AzureFile AzureDisk FC (Fibre Channel)
  FlexVolume Flocker NFS iSCSI RBD (Ceph Block Device) CephFS
  Cinder (OpenStack block storage) Glusterfs VsphereVolume Quobyte Volumes
  HostPath VMware Photon Portworx Volumes ScaleIO Volumes StorageOS

持久卷演示代碼

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
storageClassName: slow mountOptions: - hard - nfsvers=4.1 nfs: path: /tmp server: 172.17.0.2

 

PV 訪問模式

  PersistentVolume 可以以資源提供者支持的任何方式掛載到主機上。如下表所示,供應商具有不同的功能,每個PV 的訪問模式都將被設置為該卷支持的特定模式。例如,NFS 可以支持多個讀/寫客戶端,但特定的 NFS PV 可能以只讀方式導出到服務器上。每個 PV 都有一套自己的用來描述特定功能的訪問模式
  ReadWriteOnce——該卷可以被單個節點以讀/寫模式掛載
  ReadOnlyMany——該卷可以被多個節點以只讀模式掛載
  ReadWriteMany——該卷可以被多個節點以讀/寫模式掛載
在命令行中,訪問模式縮寫為:
  RWO - ReadWriteOnce
  ROX - ReadOnlyMany
  RWX - ReadWriteMany
Volume 插件

 

回收策略
  Retain(保留)——手動回收
  Recycle(回收)——基本擦除( rm -rf /thevolume/* )
  Delete(刪除)——關聯的存儲資產(例如 AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder 卷)
  將被刪除
 當前,只有 NFS 和 HostPath 支持回收策略。AWS EBS、GCE PD、Azure Disk 和 Cinder 卷支持刪除策略

狀態
  卷可以處於以下的某種狀態:
  Available(可用)——一塊空閑資源還沒有被任何聲明綁定
  Bound(已綁定)——卷已經被聲明綁定
  Released(已釋放)——聲明被刪除,但是資源還未被集群重新聲明
  Failed(失敗)——該卷的自動回收失敗
 命令行會顯示綁定到 PV 的 PVC 的名稱

持久化演示說明 - NFS
I、安裝 NFS 服務器

在Harbor上部署NFS:

Harbor啟動:

docker-compose start

 

yum install -y nfs-common nfs-utils rpcbind
mkdir /nfs
chown 777 /nfs/
chown nfsnobody /nfs/
cat /etc/exports
/nfs *(rw,no_root_squash,no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs

  

其他節點安裝客戶端

yum -y install nfs-utils rpcbind

 

測試NFS是否可用

mkdir /test
showmount -e 192.168.66.100

 

mount -t nfs 192.168.66.100:/nfs /test
cd /test
echo "iifsdfsdf" > /test/1.html
cd ..
umount /nfs
rm -rf /nfs

 

II、部署 PV

 

mkdir ~/pv
cd ~/pv
vim py.yaml

 

kubectl create -f pv.yaml
kubectl get pv

  

III、創建服務並使用 PVC

 

mkdir /nfs{1..3}
[root@hub ~]# cat /etc/exports

 

mkdir /nfs{1..3}
chmod 777 /nfs{1..3}
chown nfsnobody /nfs{1..3}
systemctl restart rpcbind
systemctl restart nfs

  

在其他節點測試:

mount -t nfs 192.168.66.100:/nfs1 /test
echo "22" > /test/index.html
umount /test/
rm -rf /test/

 

 

vim pv.yaml 

 

kubectl create -f pv.yaml
kubectl get pv

 

調整一下nfspv3的類
vim pv1.yaml

 

 

kubectl delete pv nfspv3
kubectl create -f pv1.yaml
kubectl get pv

 

 

[root@k8s-master01 pv]# vim pod.yaml

 

kubectl apply -f pod.yaml
kubectl get pod

狀態不對

 

kubectl describe pod web-1

沒有對應的請求被綁定,因為yaml文件里面定義的條件和實際存在的pv不匹配。

 

排查:

查看PV

kubectl get pv

 

查看yaml

 

 

再看pod

yaml匹配要求類是nfs,訪問控制列表要求是RWO,同時滿足這兩個條件的只有nfspv1,並且RWO只能綁定一個,所以第二個pod一直等待了,副本數定義的3個,但是由於有序部署,第二個狀態不是ready或者running,第三個pod還沒出來。

  yaml定義的大小只要>=storage即可,滿足條件后優先選擇小資源的(最低要求)進行綁定。

 

調整:

改PV3和4符合要求的。

kubectl delete pv nfspv3 nfspv4
vim pv2.yaml

 

kubectl create -f pv2.yaml

 

 

ubectl describe pod web-2 

 

kubectl get pv 

 

vim pv2.yaml

 

kubectl delete -f pv2.yaml
kubectl create -f pv2.yaml

 

 

kubectl get pvc 

 

 

kubectl describe pv  nfspv1 

 

在nfs上創建一個Index.html

[root@hub ~]# cd /nfs
[root@hub nfs]# ls
1.html
[root@hub nfs]# rm 1.html rm:是否刪除普通文件 "1.html"?y
[root@hub nfs]# echo "aaa" > index.html [root@hub nfs]# chmod 777 index.html

 

[root@k8s-master01 pv]# kubectl get pod -o wide

 

curl 10.244.2.124

 

同理

kubectl get pvc
kubectl get pv
kubectl get pod -o wide
kubectl describe pv nfspv3
kubectl describe pv nfspv4

 

[root@hub nfs]# echo "bbb" > /nfs2/index.html
[root@hub nfs]# echo "ccc" > /nfs3/index.html

 

curl 10.244.1.104
curl 10.244.2.125

  

kubectl delete pod  web-0
kubectl get pod -o wide

刪除后保留副本又啟了一個新的容器IP變了,訪問名稱還一致,測試 數據依然存在

可以通過 Pod域名或者FQDN訪問同一個名稱

 

 

關於 StatefulSet

  匹配 Pod name ( 網絡標識 ) 的模式為:$(statefulset名稱)-$(序號),比如上面的示例:web-0,web-1,web-2
  StatefulSet 為每個 Pod 副本創建了一個 DNS 域名,這個域名的格式為: $(podname).(headless servername),也就意味着服務間是通過Pod域名來通信而非 Pod IP,因為當Pod所在Node發生故障時, Pod 會被飄移到其它 Node 上,Pod IP 會發生變化,但是 Pod 域名不會有變化
  StatefulSet 使用 Headless 服務來控制 Pod 的域名,這個域名的 FQDN 為:$(servicename).$(namespace).svc.cluster.local,其中,“cluster.local” 指的是集群的域名
  根據 volumeClaimTemplates,為每個 Pod 創建一個 pvc,pvc 的命名規則匹配模式:(volumeClaimTemplates.name)-(pod_name),比如上面的 volumeMounts.name=www, Podname=web-[0-2],因此創建出來的 PVC 是 www-web-0、www-web-1、www-web-2
  刪除 Pod 不會刪除其 pvc,手動刪除 pvc 將自動釋放 pv

Statefulset的啟停順序:
  有序部署:部署StatefulSet時,如果有多個Pod副本,它們會被順序地創建(從0到N-1)並且,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態。
  有序刪除:當Pod被刪除時,它們被終止的順序是從N-1到0。
  有序擴展:當對Pod執行擴展操作時,與部署一樣,它前面的Pod必須都處於Running和Ready狀態。

StatefulSet使用場景:

  穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基於 PVC 來實現。
  穩定的網絡標識符,即 Pod 重新調度后其 PodName 和 HostName 不變。
  有序部署,有序擴展,基於 init containers 來實現。
  有序收縮。

 

statefulset名稱:

kubectl get pod -o wide
kubectl get svc

 

容器內需要用到ping,測試效果:

kubectl exec test-pd -it -- /bin/sh

 

 

 

StatefulSet的Headless地址:

 

 

kubectl get pod -o wide -n kube-system

 

 

dig -t A  nginx.default.svc.cluster.local. @10.244.0.7 

解析成功

 

啟停順序:

kubectl delete statefulset --all

 

kubectl get pod -w

 

 

kubectl create -f pv/pod.yaml 

 

 

 

測試訪問

 

kubectl delete -f pv/pod.yaml

 

 

[root@k8s-master01 pv]# kubectl get statefullset 

 

[root@k8s-master01 pv]# kubectl get svc

 

kubectl delete svc nginx
kubectl get pv

 

kubectl get pvc

 

pod刪除pvc並不會跟隨刪除

kubectl delete pvc --all
kubectl get pvc

 

kubectl get pv

 

狀態已經變成Released(已釋放)——聲明被刪除,但是資源還未被集群重新聲明,之前是Bound(已綁定)——卷已經被聲明綁定

先去刪除數據

 

kubectl get pv

 

還是Released

kubectl get pv nfspv1 -o yaml

nfspv並不會檢查文件數據,但是pv依然有使用者信息

 

手動回收

kubectl edit pv nfspv1

刪除選中行

 

kubectl get pv

狀態已經變成Available(可用)——一塊空閑資源還沒有被任何聲明綁定

 

 

8、集群調度

 

8.1、Kubernetes 調度器 - 調度說明

8.2、Kubernetes 調度器 - 調度親和性

8.3、Kubernetes 調度器 - 污點

8.4、Kubernetes 調度器 - 固定節點

 

8.1 Kubernetes 調度器 - 調度說明

 

簡介
Scheduler 是 kubernetes 的調度器,主要的任務是把定義的 pod 分配到集群的節點上。聽起來非常簡單,但有很多要考慮的問題:
  公平:如何保證每個節點都能被分配資源
  資源高效利用:集群所有資源最大化被使用
  效率:調度的性能要好,能夠盡快地對大批量的 pod 完成調度工作
  靈活:允許用戶根據自己的需求控制調度的邏輯
 Sheduler 是作為單獨的程序運行的,啟動之后會一直堅挺 API Server,獲取 PodSpec.NodeName 為空的 pod,對每個 pod 都會創建一個 binding,表明該 pod 應該放到哪個節點上

調度過程
  調度分為幾個部分:首先是過濾掉不滿足條件的節點,這個過程稱為 predicate ;然后對通過的節點按照優先級排序,這個是 priority ;最后從中選擇優先級最高的節點。如果中間任何一步驟有錯誤,就直接返回錯誤
 Predicate 有一系列的算法可以使用:
  PodFitsResources :節點上剩余的資源是否大於 pod 請求的資源
  PodFitsHost :如果 pod 指定了 NodeName,檢查節點名稱是否和 NodeName 匹配
  PodFitsHostPorts :節點上已經使用的 port 是否和 pod 申請的 port 沖突
  PodSelectorMatches :過濾掉和 pod 指定的 label 不匹配的節點
  NoDiskConflict :已經 mount 的 volume 和 pod 指定的 volume 不沖突,除非它們都是只讀
 如果在 predicate 過程中沒有合適的節點,pod 會一直在 pending 狀態,不斷重試調度,直到有節點滿足條件。經過這個步驟,如果有多個節點滿足條件,就繼續 priorities 過程: 按照優先級大小對節點排序

 優先級由一系列鍵值對組成,鍵是該優先級項的名稱,值是它的權重(該項的重要性)。這些優先級選項包括:
  LeastRequestedPriority :通過計算 CPU 和 Memory 的使用率來決定權重,使用率越低權重越高。換句話說,這個優先級指標傾向於資源使用比例更低的節點
  BalancedResourceAllocation :節點上 CPU 和 Memory 使用率越接近,權重越高。這個應該和上面的一起使用,不應該單獨使用
  ImageLocalityPriority :傾向於已經有要使用鏡像的節點,鏡像總大小值越大,權重越高通過算法對所有的優先級項目和權重進行計算,得出最終的結果

自定義調度器
  除了 kubernetes 自帶的調度器,你也可以編寫自己的調度器。通過 spec:schedulername 參數指定調度器的名字,可以為 pod 選擇某個調度器進行調度。比如下面的 pod 選擇 my-scheduler 進行調度,而不是默認的
  default-scheduler :

apiVersion: v1
kind: Pod
metadata:
  name: annotation-second-scheduler
  labels:
    name: multischeduler-example
spec:
  schedulername: my-scheduler
  containers:
  - name: pod-with-second-annotation-container
    image: gcr.io/google_containers/pause:2.0

 

 

8.2 Kubernetes 調度器 - 調度親和性

  通過配置可以讓不同pod處於同一節點或者不同節點

 

8.1.1 節點親和性

pod.spec.nodeAffinity
  preferredDuringSchedulingIgnoredDuringExecution:軟策略
  requiredDuringSchedulingIgnoredDuringExecution:硬策略

 

查看鍵名

kubectl get node --show-labels

 

 

requiredDuringSchedulingIgnoredDuringExecution

硬策略:

測試一下NotIn效果:

[root@k8s-master01 ~]# mkdir affi
[root@k8s-master01 ~]# cd affi
[root@k8s-master01 affi]# vim pod1.yaml

這里的匹配關系是NotIn,意思是只要不是node02就可以運行,排除了node02

 

kubectl create -f pod1.yaml
kubectl get pod -o wide

節點在01上

 

kubectl delete pod --all && kubectl create -f pod1.yaml && kubectl get pod -o wide

 

改成運算關系改成In

vim pod1.yaml

 

kubectl delete pod --all && kubectl create -f pod1.yaml && kubectl get pod -o wide
kubectl delete pod --all && kubectl create -f pod1.yaml && kubectl get pod -o wide  

只運行在02節點

 

改成03節點

 

 

kubectl delete pod --all && kubectl create -f pod1.yaml && kubectl get pod -o wide  

 

狀態不對

 

kubectl describe pod affinity

由於沒有03節點,並且是硬策略,所以堅持在03上運行,最終報節點不匹配。

 


preferredDuringSchedulingIgnoredDuringExecution

軟策略:

查看鍵名

kubectl get node --show-labels

 

vim pod3.yaml 

 

這里配置的軟策略期望hostname in 節點名node03

kubectl delete pod --all
kubectl create -f pod3.yaml && kubectl get pod -o wide

 

沒有03軟策略也會在其他節點運行

改成01

權重值是遇到重復時的優先權 0~100

 

kubectl delete -f pod3.yaml && kubectl create -f pod3.yaml && kubectl get pod -o wide

 

發現01優先,但是也有在02上運行的

改成硬策略:

 

kubectl delete -f pod3.yaml && kubectl create -f pod3.yaml && kubectl get pod -o wide

全都在node01上運行了 

 

kubectl delete -f pod3.yaml

 

合體:

node節點不多,演示效果不太好

vim pod5.yaml

 

排除02節點,選擇其他節點運行,並優先選擇01

由於只有2個節點排除掉02以后只剩下01了

 

kubectl delete -f pod5.yaml

 

鍵值運算關系
  In:label 的值在某個列表中
  NotIn:label 的值不在某個列表中
  Gt:label 的值大於某個值
  Lt:label 的值小於某個值
  Exists:某個 label 存在
  DoesNotExist:某個 label 不存在

 

Pod 親和性

 pod.spec.affinity.podAffinity/podAntiAffinity
  preferredDuringSchedulingIgnoredDuringExecution:軟策略
  requiredDuringSchedulingIgnoredDuringExecution:硬策略

 

創建一個pod

vim pod6.yaml

 

kubectl get pod -o wide --show-labels

 

演示pod親和性:

vim pod7.yaml

 

kubectl create -f pod7.yaml
kubectl get pod -o wide --show-labels

在同一拓撲域

 

修改不親和

kubectl delete -f pod7.yaml
vim pod7.yaml

  

podAffinity改成podAntiAffinity

kubectl create -f pod7.yaml
kubectl get pod -o wide

由於是podAntiAffinity和硬限制,結果不在同一節點運行

 

kubectl delete -f pod7.yaml

 

如果是硬限制匹配labels不存在的話:

kubectl get pod -o wide --show-labels

 

vim pod7.yaml

 

 

 

kubectl get pod -o wide --show-labels 

等待

 

describe pod pod-3

提示2個節點都不匹配運行

 

測試效果,改一下標簽名成匹配的node02

kubectl label pod node01 app=node02

提示已經存在並且當前--overwrite is false

 

kubectl label pod node01 app=node02 --overwrite=True
kubectl get pod -o wide --show-labels

匹配到了,running了,節點也一樣

 

親和性/反親和性調度策略比較如下:

 

8.3 Kubernetes 調度器 - 污點

 

Taint 和 Toleration


 節點親和性,是 pod 的一種屬性(偏好或硬性要求),它使 pod 被吸引到一類特定的節點。Taint 則相反,它使節點 能夠 排斥 一類特定的 pod

 Taint 和 toleration 相互配合,可以用來避免 pod 被分配到不合適的節點上。每個節點上都可以應用一個或多個taint ,這表示對於那些不能容忍這些Taint 的 pod,是不會被該節點接受的。如果將 toleration 應用於 pod上,則表示這些 pod 可以(但不要求)被調度到具有匹配 taint 的節點上

 

污點(Taint)


I、 污點 ( Taint ) 的組成
 使用 kubectl taint 命令可以給某個 Node 節點設置污點,Node 被設置上污點之后就和 Pod 之間存在了一種相斥的關系,可以讓 Node 拒絕 Pod 的調度執行,甚至將 Node 已經存在的 Pod 驅逐出去
 每個污點的組成如下:

  key=value:effect


 每個污點有一個 key 和 value 作為污點的標簽,其中 value 可以為空,effect 描述污點的作用。當前 tainteffect 支持如下三個選項:
  NoSchedule :表示 k8s 將不會將 Pod 調度到具有該污點的 Node 上
  PreferNoSchedule :表示 k8s 將盡量避免將 Pod 調度到具有該污點的 Node 上
  NoExecute :表示 k8s 將不會將 Pod 調度到具有該污點的 Node 上,同時會將 Node 上已經存在的 Pod 驅逐出去

 

kubectl get node

查看mster的污點配置

kubectl describe node k8s-master01

pod不會在master上運行,因為已經配置了污點

 

II、污點的設置、查看和去除

 

kubectl get pod -o wide

 

設置污點

kubectl taint nodes k8s-node01 check=yyq:NoExecute (kubectl taint nodes node1 key1=value1:NoSchedule)

 

由於是單獨的pod被刪除以后就沒有了,如果是deployment控制的Pod會在node02上再起來

 

如果把02也設置污點

kubectl taint nodes k8s-node02 check=yyq:NoExecute
kubectl create -f pod1.yaml
kubectl get pod

 

 容忍污點

  vim pod8.yaml

  

  這里設置了之前污點命令的參數和值,並且tolerationSeconds 用於描述當 Pod 需要被驅逐時可以在 Pod 上繼續保留運行的時間

 

  

  配置了容忍已經可以運行起來了

 

  kubectl delete pod pod-3

  有多個 Master 存在時,防止資源浪費,可以如下設置 

  kubectl taint nodes Node-Name node-ole.kubernetes.io/master=:PreferNoSchedule
  kubectl get node

  

 

 

   kubectl taint nodes k8s-master01 node-role.kubernetes.io/master=:PreferNoSchedule

  

   調整成盡可能不在master01上運行,也就是說如果node節點資源不夠用或者不可用,會在master01上運行。

 

  vim pod9.yaml

  

 

  kubectl create -f pod9.yaml
  kubectl get pod

  

  和預想結果不一樣還是沒有運行,查看問題

  

  kubectl describe pod pod-3

  

  提示3個節點pod都無法容忍

 

  查看master01節點污點設置

  kubectl describe node k8s-master01

  

  配置無法替換,疊加了

 

  把NoSchedule污點去除

  kubectl taint nodes k8s-master01 node-role.kubernetes.io/master=:NoSchedule-

 

  再查看

  kubectl describe node k8s-master01

  

 

   kubectl get pod -o wide

  

  由於matser之前沒有下載過鏡像,並且鏡像倉庫目前權限是私人,而且沒有配置Secret

 

  docker login hub.yyq.com
  docker pull hub.yyq.com/library/mynginx:v1
  kubectl get pod  -o wide

  

 

  清除污點

  taint nodes k8s-node01 check=yyq:NoExecute-
  taint nodes k8s-node02 check=yyq:NoExecute-
  kubectl describe node k8s-node01
  kubectl describe node k8s-node02

  

 

 

 

8.2.2 容忍(Tolerations)

 

  設置了污點的 Node 將根據 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之間產生互斥的關系,Pod 將在一定程度上不會被調度到 Node 上。 但我們可以在 Pod 上設置容忍 ( Toleration ) ,意思是設置了容忍的 Pod 將可以容忍污點的存在,可以被調度到存在污點的 Node 上
pod.spec.tolerations

tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerationSeconds: 3600

  

- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"

 

- key: "key2"
operator: "Exists"
effect: "NoSchedule"

  其中 key, vaule, effect 要與 Node 上設置的 taint 保持一致

  operator 的值為 Exists 將會忽略 value 值
  tolerationSeconds 用於描述當 Pod 需要被驅逐時可以在 Pod 上繼續保留運行的時間
I、當不指定 key 值時,表示容忍所有的污點 key:

tolerations:
- operator: "Exists"


II、當不指定 effect 值時,表示容忍所有的污點作用

tolerations:
- key: "key"
  operator: "Exists"


III、有多個 Master 存在時,防止資源浪費,可以如下設置

kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule

 

 

8.4 Kubernetes 調度器 - 固定節點

  指定節點名稱或者label來進行強制選擇。

 

指定調度節點

I、Pod.spec.nodeName 將 Pod 直接調度到指定的 Node 節點上,會跳過 Scheduler 的調度策略,該匹配規則是強制匹配

 

mkdir /root/nod
cd /root/node
vim pod1.yaml

 

配置根據節node01點選擇

 

kubectl apply -f pod1.yaml
kubectl get pod -o wide

 

 

II、Pod.spec.nodeSelector:通過 kubernetes 的 label-selector 機制選擇節點,由調度器調度策略匹配 label,而后調度 Pod 到目標節點,該匹配規則屬於強制約束

 

vim pod2.yaml

定義了只在disk:ssd的節點上運行

 

kubectl delete deployment --all
kubectl delete pod --all
kubectl apply -f pod2.yaml
kubectl get pod

由於不滿足disk:ssd的條件,沒有運行

 

通過修改標簽完成測試

kubectl label node k8s-node01 disk=ssd

 

kubectl get pod

 

把node02也改成ssd

kubectl label node k8s-node02 disk=ssd

 

增加副本數

kubectl get deployment
kubectl edit deployment myweb11

 

kubectl get pod -o wide

 

 

9、安全

  9.1機制說明

  9.2認證

  9.3鑒權

  9.4准入控制

 

9.1 Kubernetes 集群安全 - 機制說明

  Kubernetes 作為一個分布式集群的管理工具,保證集群的安全性是其一個重要的任務。API Server 是集群內部各個組件通信的中介,也是外部控制的入口。所以 Kubernetes 的安全機制基本就是圍繞保護 API Server 來設計的。Kubernetes 使用了認證(Authentication)、鑒權(Authorization)、准入控制(AdmissionControl)三步來保證API Server的安全

 

 

9.2 Kubernetes 集群安全 - 認證

 

Authentication

 HTTP Token 認證:通過一個 Token 來識別合法用戶
  HTTP Token 的認證是用一個很長的特殊編碼方式的並且難以被模仿的字符串 - Token 來表達客戶的一種方式。Token 是一個很長的很復雜的字符串,每一個 Token 對應一個用戶名存儲在 API Server 能訪問的文件中。當客戶端發起 API 調用請求時,需要在 HTTP Header 里放入 Token
 HTTP Base 認證:通過 用戶名+密碼 的方式認證
  用戶名+:+密碼 用 BASE64 算法進行編碼后的字符串放在 HTTP Request 中的 HeatherAuthorization 域里發送給服務端,服務端收到后進行編碼,獲取用戶名及密碼
 最嚴格的 HTTPS 證書認證:基於 CA 根證書簽名的客戶端身份認證方式(雙向)

 

I、HTTPS 證書認證:

 

II、需要認證的節點

 

兩種類型
  Kubenetes 組件對 API Server 的訪問:kubectl、Controller Manager、Scheduler、kubelet、kube-proxy
  Kubernetes 管理的 Pod 對容器的訪問:Pod(dashborad 也是以 Pod 形式運行)
安全性說明
  Controller Manager、Scheduler 與 API Server 在同一台機器,所以直接使用 API Server 的非安全端口訪問, --insecure-bind-address=127.0.0.1
  kubectl、kubelet、kube-proxy 訪問 API Server 就都需要證書進行 HTTPS 雙向認證
證書頒發
  手動簽發:通過 k8s 集群的跟 ca 進行簽發 HTTPS 證書
  自動簽發:kubelet 首次訪問 API Server 時,使用 token 做認證,通過后,Controller Manager 會為kubelet 生成一個證書,以后的訪問都是用證書做認證了


III、kubeconfig
  kubeconfig 文件包含集群參數(CA證書、API Server地址),客戶端參數(上面生成的證書和私鑰),集群context 信息(集群名稱、用戶名)。Kubenetes 組件通過啟動時指定不同的 kubeconfig 文件可以切換到不同的集群

 

[root@k8s-master01 node]# cat ~/.kube/config

包含了集群的訪問方式和認證信息

  

 

IV、ServiceAccount

  Pod中的容器訪問API Server。因為Pod的創建、銷毀是動態的,所以要為它手動生成證書就不可行了。Kubenetes使用了Service Account解決Pod 訪問API Server的認證問題

V、Secret 與 SA 的關系
  Kubernetes 設計了一種資源對象叫做 Secret,分為兩類,一種是用於 ServiceAccount 的 service-account-token, 另一種是用於保存用戶自定義保密信息的 Opaque。ServiceAccount 中用到包含三個部分:Token、ca.crt、namespace
  token是使用 API Server 私鑰簽名的 JWT。用於訪問API Server時,Server端認證
  ca.crt,根證書。用於Client端驗證API Server發送的證書

  namespace, 標識這個service-account-token的作用域名空間

    <!--Json Web token (JWT),是為了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開發標准({RFC 7519}).該token被設計為緊湊且安全的,特別適用於分布式站點的單點登錄(SSO)場景。JWT的聲明一般被用來在身份提供者和訪問提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也可以增加一些額外的其他業務邏輯所必需的聲明信息,該token也可直接被用於認證,也可被加密-->

 

  kubectl get secret --all-namespaces
  kubectl describe secret default-token-5gm9r --namespace=kube-syste

默認情況下,每個 namespace 都會有一個 ServiceAccount,如果 Pod 在創建時沒有指定 ServiceAccount,就會使用 Pod 所屬的 namespace 的 ServiceAccount

  <!--默認掛載目錄:/run/secrets/kubernetes.io/serviceaccount/-->

 

  kubectl get pod -n kube-system

  

 

  kubectl exec kube-proxy-m5fw7 -n kube-system -it -- /bin/sh
  ls /run/secrets/kubernetes.io/serviceaccount

  

  
總結

 

 

 

9.3 Kubernetes 集群安全 - 鑒權

 

!---->

Authorization


 上面認證過程,只是確認通信的雙方都確認了對方是可信的,可以相互通信。而鑒權是確定請求方有哪些資源的權限。API Server 目前支持以下幾種授權策略 (通過 API Server 的啟動參數 “--authorization-mode” 設置)
  AlwaysDeny:表示拒絕所有的請求,一般用於測試
  AlwaysAllow:允許接收所有請求,如果集群不需要授權流程,則可以采用該策略
  ABAC(Attribute-Based Access Control):基於屬性的訪問控制,表示使用用戶配置的授權規則對用戶請求進行匹配和控制(太麻煩已經淘汰了)
  Webbook:通過調用外部 REST 服務對用戶進行授權
  RBAC(Role-Based Access Control):基於角色的訪問控制,現行默認規則

RBAC 授權模式
 RBAC(Role-Based Access Control)基於角色的訪問控制,在 Kubernetes 1.5 中引入,現行版本成為默認標准。相對其它訪問控制方式,擁有以下優勢:
  對集群中的資源和非資源均擁有完整的覆蓋
  整個 RBAC 完全由幾個 API 對象完成,同其它 API 對象一樣,可以用 kubectl 或 API 進行操作
  可以在運行時進行調整,無需重啟 API Server


I、RBAC 的 API 資源對象說明
RBAC 引入了 4 個新的頂級資源對象:Role、ClusterRole、RoleBinding、ClusterRoleBinding,4 種對象類型均可以通過 kubectl 與 API 操作

 

需要注意的是 Kubenetes 並不會提供用戶管理,那么 User、Group、ServiceAccount 指定的用戶又是從哪里來的呢? Kubenetes 組件(kubectl、kube-proxy)或是其他自定義的用戶在向 CA 申請證書時,需要提供一個證書請求文件

{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "HangZhou",
      "L": "XS",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}

 

API Server會把客戶端證書的 CN 字段作為User,把 names.O 字段作為Group

kubelet 使用 TLS Bootstaping 認證時,API Server 可以使用 Bootstrap Tokens 或者 Token authenticationfile 驗證 =token,無論哪一種,Kubenetes 都會為 token 綁定一個默認的 User 和 Group

Pod使用 ServiceAccount 認證時,service-account-token 中的 JWT 會保存 User  信息

有了用戶信息,再創建一對角色/角色綁定(集群角色/集群角色綁定)資源對象,就可以完成權限綁定了

 

Role and ClusterRole
  在 RBAC API 中,Role 表示一組規則權限,權限只會增加(累加權限),不存在一個資源一開始就有很多權限而通過RBAC 對其進行減少的操作;Role 可以定義在一個 namespace 中,如果想要跨 namespace 則可以創建ClusterRole

 

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]


ClusterRole 具有與 Role 相同的權限角色控制能力,不同的是 ClusterRole 是集群級別的,ClusterRole 可以用於:
  集群級別的資源控制( 例如 node 訪問權限 )
  非資源型 endpoints( 例如 /healthz 訪問 )
  所有命名空間資源控制(例如 pods )

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

 

RoleBinding and ClusterRoleBinding
  RoloBinding 可以將角色中定義的權限授予用戶或用戶組,RoleBinding 包含一組權限列表(subjects),權限列表中包含有不同形式的待授予權限資源類型(users, groups, or service accounts);RoloBinding 同樣包含對被Bind 的 Role 引用;RoleBinding 適用於某個命名空間內授權,而 ClusterRoleBinding 適用於集群范圍內的授權
  將 default 命名空間的 pod-reader Role 授予 jane 用戶,此后 jane 用戶在 default 命名空間中將具有 pod-reader 的權限

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

 

  RoleBinding 同樣可以引用 ClusterRole 來對當前 namespace 內用戶、用戶組或 ServiceAccount 進行授權,這種操作允許集群管理員在整個集群內定義一些通用的 ClusterRole,然后在不同的 namespace 中使用RoleBinding 來引用
  例如,以下 RoleBinding 引用了一個 ClusterRole,這個 ClusterRole 具有整個集群內對 secrets 的訪問權限;但是其授權用戶 dave 只2能訪問 development 空間中的 secrets(因為 RoleBinding 定義在 development 命名空間)

# This role binding allows "dave" to read secrets in the "development" namespace.
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: development # This only grants permissions within the "development" namespace.
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

 

  使用 ClusterRoleBinding 可以對整個集群中的所有命名空間資源權限進行授權;以下 ClusterRoleBinding 樣例展示了授權 manager 組內所有用戶在全部命名空間中對 secrets 進行訪問

# This cluster role binding allows anyone in the "manager" group to read secrets in any
namespace.
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io


Resources
  Kubernetes 集群內一些資源一般以其名稱字符串來表示,這些字符串一般會在 API 的 URL 地址中出現;同時某些資源也會包含子資源,例如 logs 資源就屬於 pods 的子資源,API 中 URL 樣例如下

GET /api/v1/namespaces/{namespace}/pods/{name}/log


  如果要在 RBAC 授權模型中控制這些子資源的訪問權限,可以通過 / 分隔符來實現,以下是一個定義 pods 資資源logs 訪問權限的 Role 定義樣例

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get", "list"]

  

to Subjects
  RoleBinding 和 ClusterRoleBinding 可以將 Role 綁定到 Subjects;Subjects 可以是 groups、users 或者service accounts

  Subjects 中 Users 使用字符串表示,它可以是一個普通的名字字符串,如 “alice”;也可以是 email 格式的郵箱地址,如 “wangyanglinux@163.com”;甚至是一組字符串形式的數字 ID 。但是 Users 的前綴 system: 是系統保留的,集群管理員應該確保普通用戶不會使用這個前綴格式

  Groups 書寫格式與 Users 相同,都為一個字符串,並且沒有特定的格式要求;同樣 system: 前綴為系統保留

 

實踐:創建一個用戶只能管理 dev 空間

[root@k8s-master01 ~]# useradd devuser
[root@k8s-master01 ~]# passwd devuser
ssh devuser@192.168.66.10
[devuser@k8s-master01 ~]$ kubectl get pod
The connection to the server localhost:8080 was refused - did you specify the right host or port?

 

沒有權限,創建證書請求:

cd /usr/local/install-k8s/cert/devuser
vim devuser-csr.json

  

cd /usr/local/bin/

 

生成證書

cd /etc/kubernetes/pki/
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /usr/local/install-k8s/cert/devuser/devuser-csr.json | cfssljson -bare devuser

 

ls

 

 

 

# 設置集群參數
cd /usr/local/install-k8s/cert/devuser/

# 聲明環境變量
export KUBE_APISERVER="https://192.168.66.10:6443"

# 設置集群、指定CA證書、是否加密、服務器信息、創建配置文件
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=devuser.kubeconfig

 

# 設置客戶端認證參數

創建devuser證書、指定客戶端證書、客戶端私鑰、開啟認證方式、寫入文件
kubectl config set-credentials devuser \
--client-certificate=/etc/kubernetes/pki/devuser.pem \
--client-key=/etc/kubernetes/pki/devuser-key.pem \
--embed-certs=true \
--kubeconfig=devuser.kubeconfig

cat devuser.kubeconfig

多了用戶名、用戶證書、用戶私鑰信息
# 設置上下文參數

創建名稱空間
kubectl create namespace dev
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=devuser \
--namespace=dev \
--kubeconfig=devuser.kubeconfig

cat devuser.kubeconfig 多了namespace和用戶名信息
# 設置默認上下文 創建一個rolebinding,devuser可以在dev名稱空間下有管理員權限 kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev

 

 

[devuser@k8s-master01 ~]$ mkdir .kube
[root@k8s-master01 devuser]# cp devuser.kubeconfig /home/devuser/.kube/config
chown devuser:devuser /home/devuser/.kube/config

[devuser@k8s-master01 .kube]$  kubectl config use-context kubernetes --kubeconfig=config

 

 

 

kubectl get pod
kubectl run nginx --image=hub.yyq.com/library/mynginx:v1
kubectl get pod

 

 

 

kubectl get pod --all-namespaces -o wide | grep nginx 

 

kubectl get pod -n default 

只定義了dev沒有定義default無法訪問。

 

9.4 Kubernetes 集群安全 - 准入控制

 

准入控制


 准入控制是API Server的插件集合,通過添加不同的插件,實現額外的准入控制規則。甚至於API Server的一些主要的功能都需要通過 Admission Controllers 實現,比如 ServiceAccount
 官方文檔上有一份針對不同版本的准入控制器推薦列表,其中最新的 1.14 的推薦列表是:

NamespaceLifecycle,
LimitRanger,
ServiceAccount,
DefaultStorageClass,
DefaultTolerationSeconds,
MutatingAdmissionWebhook,
ValidatingAdmissionWebhook,
ResourceQuota

 

 列舉幾個插件的功能:
  NamespaceLifecycle: 防止在不存在的 namespace 上創建對象,防止刪除系統預置 namespace,刪除namespace 時,連帶刪除它的所有資源對象。
  LimitRanger:確保請求的資源不會超過資源所在 Namespace 的 LimitRange 的限制
  ServiceAccount: 實現了自動化添加 ServiceAccount。
  ResourceQuota:確保請求的資源不會超過資源的 ResourceQuota 限制。

 

10、Helm及其它功能性組件

 

helm命令詳解 

http://www.coderdocument.com/docs/helm/v2/helm_commands/helm_repo_add.html#helm-repo-add

 

10.1 部署 Helm

  包管理工具(類linux yum)下yaml文件

10.2 使用 Helm 部署 dashboard

10.3 使用 Helm 部署 metrics-server

10.4 部署 prometheus

10.5 部署 EFK 平台

 

10.1 部署 Helm

  

https://github.com/helm/helm/blob/master/docs/charts.md
什么是 Helm


 在沒使用 helm 之前,向 kubernetes 部署應用,我們要依次部署 deployment、svc 等,步驟較繁瑣。況且隨着很多項目微服務化,復雜的應用在容器中部署以及管理顯得較為復雜,helm 通過打包的方式,支持發布的版本管理和控制,很大程度上簡化了 Kubernetes 應用的部署和管理
 Helm 本質就是讓 K8s 的應用管理(Deployment,Service 等 ) 可配置,能動態生成。通過動態生成 K8s 資源清單文件(deployment.yaml,service.yaml)。然后調用 Kubectl 自動執行 K8s 資源部署
 Helm 是官方提供的類似於 YUM 的包管理器,是部署環境的流程封裝。Helm 有兩個重要的概念:chart 和release
  chart 是創建一個應用的信息集合,包括各種 Kubernetes 對象的配置模板、參數定義、依賴關系、文檔說明等。chart 是應用部署的自包含邏輯單元。可以將 chart 想象成 apt、yum 中的軟件安裝包
  release 是 chart 的運行實例,代表了一個正在運行的應用。當 chart 被安裝到 Kubernetes 集群,就生成一個 release。chart 能夠多次安裝到同一個集群,每次安裝都是一個 release
 Helm 包含兩個組件:Helm 客戶端和 Tiller 服務器,如下圖所示

  

 

 

 Helm 客戶端負責 chart 和 release 的創建和管理以及和 Tiller 的交互。Tiller 服務器運行在 Kubernetes 集群中,它會處理 Helm 客戶端的請求,與 Kubernetes API Server 交互

Helm 部署
 越來越多的公司和團隊開始使用 Helm 這個 Kubernetes 的包管理器,我們也將使用 Helm 安裝 Kubernetes 的常用組件。 Helm 由客戶端命 helm 令行工具和服務端 tiller 組成,Helm 的安裝十分簡單。 下載 helm 命令行工具到master 節點 node1 的 /usr/local/bin 下,這里下載的 2.13. 1版本:

ntpdate ntp1.aliyun.com
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz
tar -zxvf helm-v2.13.1-linux-amd64.tar.gz
cd linux-amd64/
cp helm /usr/local/bin/


 為了安裝服務端 tiller,還需要在這台機器上配置好 kubectl 工具和 kubeconfig 文件,確保 kubectl 工具可以在這台機器上訪問 apiserver 且正常使用。 這里的 node1 節點以及配置好了 kubectl
 因為 Kubernetes APIServer 開啟了 RBAC 訪問控制,所以需要創建 tiller 使用的 service account: tiller 並分配合適的角色給它。 詳細內容可以查看helm文檔中的 Role-based Access Control。 這里簡單起見直接分配cluster- admin 這個集群內置的 ClusterRole 給它。創建 rbac-config.yaml 文件:

 

[root@k8s-master01 helm]# vim rbac.yaml

 

kubectl create -f rbac.yaml

 

helm init --service-account tiller --skip-refresh

 

tiller 默認被部署在 k8s 集群中的 kube-system 這個namespace 下

kubectl get pod -n kube-system -l app=helm

 

kubectl describe pod tiller-deploy-58565b5464-f55cv -n kube-system

 

docker pull gcr.io/kubernetes-helm/tiller:v2.13.1 
或者
docker load -i helm-tiller.tar
kubectl get pod -n kube-system -l app=helm

 

helm version

 

自己找helm如reids:

訪問 hub.helm.sh

 

Helm 自定義模板

 

# 創建文件夾
[root@k8s-master01 helm]# mkdir test && cd test

 

# 創建自描述文件 Chart.yaml , 這個文件必須有 name 和 version 定義
$ cat <<'EOF' > ./Chart.yaml
name: hello-world
version: 1.0.0
EOF

 

# 創建模板文件, 用於生成 Kubernetes 資源清單(manifests)
$ mkdir ./templates

 

vim ./deployment.yaml

 

 

vim ./templates/service.yaml 

 

# 使用命令 helm install RELATIVE_PATH_TO_CHART 創建一次Release
helm install .

 

# 列出已經部署的 Release
helm ls 

 

 

helm upgrade tinseled-dolphinhelm upgrade tinseled-dolphin . 
helm list 

 

helm  history tinseled-dolphin

 

也可以通過helm看

# 查詢一個特定的 Release 的狀態
helm  status tinseled-dolphin

 

瀏覽器訪問:192.168.66.10:31586

 

# 配置體現在配置文件 values.yaml
[root@k8s-master01 test]# vim values.yaml

 

# 這個文件中定義的值,在模板文件中可以通過 .VAlues對象訪問到
$ vim ./templates/deployment.yaml

 

helm list
helm upgrade tinseled-dolphin .

 

 

kubectl get pod 

 

刷新網頁

已經更新版本

 

# 返回v1版本
helm upgrade tinseled-dolphin --set image.tag='v1' .

 

其他命令:

# 移除所有與這個 Release 相關的 Kubernetes 資源
#$ helm delete tinseled-dolphin

 

再重新創建
helm install --name tinseled-dolphin .

提示已存在

 

helm list --deleted

還有保存的信息,默認保存 用於恢復,回滾:

 

helm rollback tinseled-dolphin 8

 

瀏覽器訪問:192.168.66.10:31344

版本變了,端口變了

 

[root@k8s-master01 test]# helm rollback tinseled-dolphin 4

 

# 如果想要全刪除需要添加 --perge參數
# 使用 helm delete --purge RELEASE_NAME 移除所有與指定 Release 相關的 KubernetesRelease 的記錄
helm delete --purge tinseled-dolphin
helm list --deleted

歷史已空

 

Debug
# 使用模板動態生成K8s資源清單,非常需要能提前預覽生成的結果。
# 使用--dry-run --debug 選項來打印出生成的清單文件內容,而不執行部署

helm install . --dry-run --debug --set image.tag=latest

 

helm install --dry-run .
helm list

 

10.2 使用 Helm 部署 dashboard

 

使用Helm部署 dashboard
cd /usr/local/install-k8s/plugin/dashboard
下載遠程安裝包到本地。
helm fetch stable/kubernetes-dashboard

 

  

提示repo更新

 helm repo update

 

遇到Unable to get an update from the “stable” chart repository (https://kubernetes-charts.storage.googleapis.com) 錯誤

 

手動更換stable 存儲庫為阿里雲的存儲庫
# 先移除原先的倉庫
helm repo remove stable
# 添加新的倉庫地址
helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
# 更新倉庫
helm repo update

 

查看已有倉庫

helm repo list

 

helm fetch stable/kubernetes-dashboard
vim kubernetes-dashboard.yaml

 

helm install . \
-n kubernetes-dashboard \
--namespace kube-system \
-f kubernetes-dashboard.yaml
kubectl -n kube-system get secret | grep kubernetes-dashboard-token
scp dashboard.tar root@192.168.66.20:/root/
scp dashboard.tar root@192.168.66.21:/root/
kubectl delete pod kubernetes-dashboard-79599d7b8d-ms9tb -n kube-system
kubectl get svc -n kube-system

 

kubectl edit svc -n kube-system kubernetes-dashboard

 

修改 ClusterIP 為 NodePort
[root@k8s-master01 kubernetes-dashboard]# kubectl get svc -n kube-system

 

瀏覽器訪問https://192.168.66.10:32756

 

瀏覽器非可信CA不可訪問

可以把證書導入本機 sz /etc/kubernetes/pki/ca.crt 或者使用火狐瀏覽器訪問

接受

 

 

查看 token令牌
kubectl -n kube-system get secret | grep kubernetes-dashboard-token
kubectl describe secret kubernetes-dashboard-token-h8tl4 -n kube-system

 

復制

 

 

 

 點擊創建部署新應用

 

點擊部署 

 

 

kubectl get pod -n kube-system

 

 

10.3 使用 Helm 部署 metrics-server

  prometheus集成了 metrics-server可跳過直接部署9.4 prometheus

 

使用Helm部署metrics-server
  從 Heapster 的 github <https://github.com/kubernetes/heapster >中可以看到已經,heapster 已經DEPRECATED。這里是 heapster的deprecation timeline。 可以看出 heapster 從 Kubernetes 1.12 開始將從 Kubernetes 各種安裝腳本中移除。Kubernetes 推薦使用 metrics-server。我們這里也使用helm來部署metrics-server。
metrics-server.yaml:

args:
- --logtostderr
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP

 

helm install stable/metrics-server \
-n metrics-server \
--namespace kube-system \
-f metrics-server.yaml

 

使用下面的命令可以獲取到關於集群節點基本的指標信息:
kubectl top node

 

10.4 部署 prometheus

 

相關地址信息
Prometheus github 地址:https://github.com/coreos/kube-prometheus

組件說明
  1.MetricServer:是kubernetes集群資源使用情況的聚合器,收集數據給kubernetes集群內使用,如kubectl,hpa,scheduler等。

  2.PrometheusOperator:是一個系統監測和警報工具箱,用來存儲監控數據。

  3.NodeExporter:用於各node的關鍵度量指標狀態數據。

  4.KubeStateMetrics:收集kubernetes集群內資源對象數據,制定告警規則。

  5.Prometheus:采用pull方式收集apiserver,scheduler,controller-manager,kubelet組件數據,通過http協議傳輸。

  6.Grafana:是可視化數據統計和監控平台。


構建記錄

git clone https://github.com/coreos/kube-prometheus.git
cd kube-prometheus/manifests 

 

修改 grafana-service.yaml 文件,使用 nodepode 方式訪問 grafana:

vim grafana-service.yaml
修改:
type: NodePort
nodePort: 30100

 

修改 prometheus-service.yaml 文件,使用 nodepode 方式訪問 grafana:

vim prometheus-service.yaml
修改:
type: NodePort
nodePort: 30200

 

修改 alertmanager-service.yaml 文件,使用 nodepode 方式訪問 grafana:

vim alertmanager-service.yaml
修改:
type: NodePort
nodePort: 30300

 

 

導入鏡像

/usr/local/install-k8s/plugin/prometheus
tar -zxvf prometheus.tar.gz
cat load-images.sh

#!/bin/bash cd /root/prometheus ls /root/prometheus | grep -v load-images.sh > /tmp/k8s-images.txt for i in $( cat /tmp/k8s-images.txt ) do docker load -i $i done rm -rf /tmp/k8s-images.txt

 

[root@k8s-master01 prometheus]# mv prometheus load-images.sh  /root/
cd
chmod a+x load-images.sh
./load-images.sh

 

 scp -r prometheus/ load-images.sh root@k8s-node01:/root
 scp -r prometheus/ load-images.sh root@k8s-node02:/root
.[root@k8s-node01 ~]# ./load-images.sh 
.[root@k8s-node02 ~]# ./load-images.sh 

  

 

cd /usr/local/install-k8s/plugin/prometheus/kube-prometheus/manifests
kubectl apply -f ../manifests/

由於會互相連接多執行幾次

如果遇到報錯namespaces "monitoring" not found 就執行一遍 kubectl apply -f ../manifests/setup/ 再執行 kubectl apply -f ../manifests/

ntpdate ntp1.aliyun.com
kubectl get pod -n monitoring
kubectl get svc --all-namespaces
其中k8s.gcr.io/addon-resizer:1.8.4鏡像被牆,無法下載,所以需要先通過阿里雲下載下來,再傳入本地鏡像倉庫
docker pull registry.cn-beijing.aliyuncs.com/minminmsn/addon-resizer:1.8.4
docker tag registry.cn-beijing.aliyuncs.com/minminmsn/addon-resizer:1.8.4 k8s.gcr.io/addon-resizer:1.8.4
kubectl get svc --all-namespaces
kubectl get pod -n monitoring -o wideipvsadm -Ln | grep -E "192.168.66.10:30300|192.168.66.10:30200|192.168.66.10:30100" -A 3

 

kubectl top node

 

top pod -n kube-system

 

瀏覽器訪問prometheus收集端

192.168.66.10:30200

通過訪問 http://MasterIP:30200/target 可以看到 prometheus 已經成功連接上了 k8s 的 apiserver

 

 

 

prometheus 的 WEB 界面上提供了基本的查詢 K8S 集群中每個 POD 的 CPU 使用情況,查詢條件如下:
sum by (pod_name)( rate(container_cpu_usage_seconds_total{image!="", pod_name!=""}[1m] ) )

 

 

kubectl get service -n monitoring | grep grafana

瀏覽器訪問grafana

http://MasterIP:30100

如上可以看到 grafana 的端口號是 30100, 用戶名密碼默認 admin/admin

首次登陸修改密碼

 

 

 

 

自帶了很多模板 

 

Horizontal Pod Autoscaling

 Horizontal Pod Autoscaling 可以根據 CPU 利用率自動伸縮一個 Replication Controller、Deployment 或者Replica Set 中的 Pod 數量

  創建一個apache,hpa限制請求資源cpu 200m

  kubectl run php-apache --image=gcr.io/google_containers/hpa-example --requests=cpu=200m --expose --port=80

 

 網絡問題無法pull 
  docker tag gcr.io/google_containers/hpa-example:latest gcr.io/google_containers/hpa-example:v1
  kubectl run php-apache --image=gcr.io/google_containers/hpa-example:v1 --requests=cpu=200m --expose --port=80

  [root@k8s-master01 prometheus]# kubectl top pod php-apache-5bb5df8bd4-lb86l

 

創建 HPA 控制器 - 相關算法的詳情請參閱這篇文檔

CPU超過50%自動創建,最多10個
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

  

kubectl get hpa

 

增加負載,查看負載節點數目
kubectl run -i --tty load-generator --image=busybox /bin/sh
while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

 

kubectl get hpa -w 

 

kubectl get pod -o wide

 

已經擴展滿了 

關閉壓力測試,等待cpu下來,然后pod會減少到1個


資源限制 - Pod
 Kubernetes 對資源的限制實際上是通過 cgroup 來控制的,cgroup 是容器的一組用來控制內核如何運行進程的相關屬性集合。針對內存、CPU 和各種設備都有對應的 cgroup
 默認情況下,Pod 運行沒有 CPU 和內存的限額。 這意味着系統中的任何 Pod 將能夠像執行該 Pod 所在的節點一樣,消耗足夠多的 CPU 和內存 。一般會針對某些應用的 pod 資源進行資源限制,這個資源限制是通過resources 的 requests 和 limits 來實現

  requests相當於軟限制,limits相當於硬限制

spec:
containers:
- image: xxxx
imagePullPolicy: Always
name: auth
ports:
- containerPort: 8080
protocol: TCP
resources:
limits:
cpu: "4"
memory: 2Gi
requests:
cpu: 250m
memory: 250Mi

requests 要分分配的資源,limits 為最高請求的資源值。可以簡單理解為初始值和最大值


資源限制 - 名稱空間
I、計算資源配額

apiVersion: v1
kind: ResourceQuota   # 資源配額
metadata:
name: compute-resources   #名稱
namespace: spark-cluster   #名稱空間
spec:
hard:
pods: "20"          #能夠創建的Pod數量
requests.cpu: "20"    #能夠使用的requests cpu20個
requests.memory: 100Gi  #內存
limits.cpu: "40"   
limits.memory: 200Gi


II、配置對象數量配額限制

apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
namespace: spark-cluster
spec:
hard:
configmaps: "10" 
persistentvolumeclaims:"4"  #PVC
replicationcontrollers:"20"    #RC
secrets: "10"
services: "10"
services.loadbalancers:"2"  #基於雲服務器負載的方案

 

III、配置 CPU 和 內存 LimitRange

apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
spec:
limits:
- default:
memory: 50Gi
cpu: 5
defaultRequest:
memory: 1Gi
cpu: 1
type: Container
default 即 limit 的值
defaultRequest 即 request 的值

 

10.5 部署 EFK 平台

 

 

[root@k8s-master01 containers]# cd /usr/local/install-k8s/
[root@k8s-master01 install-k8s]# mkdir efk && cd efk
helm fetch incubator/elasticsearch

 

添加 Google incubator 倉庫

helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator


部署 Elasticsearch

kubectl create namespace efk
helm fetch incubator/elasticsearch
helm install --name els1 --namespace=efk -f values.yaml incubator/elasticsearch
kubectl run cirror-$RANDOM --rm -it --image=cirros -- /bin/sh
  curl Elasticsearch:Port/_cat/nodes

 

部署 Fluentd (未使用Logstash因為Fluentd使用GO語言開發更輕量、消耗資源小,但還是Logstash功能更強)

helm fetch stable/fluentd-elasticsearch
vim values.yaml
  # 更改其中 Elasticsearch 訪問地址
helm install --name flu1 --namespace=efk -f values.yaml stable/fluentd-elasticsearch


部署 kibana

helm fetch stable/kibana --version 0.14.8
helm install --name kib1 --namespace=efk -f values.yaml stable/kibana --version 0.14.8

 

ls /var/log/containers/

F收集node節點log信息,傳給E,再用K進行數據展示

 

 

 

 

11、證書可用時間修改

 

查看SA\CA證書到日期
openssl x509 -in apiserver.crt -text -noout

 

 

openssl x509 -in ca.crt -text -noout

 

 

 

 

證書可用時限


1、go 環境部署

wget https://dl.google.com/go/go1.12.7.linux-amd64.tar.gz
tar -zxvf go1.12.1.linux-amd64.tar.gz -C /usr/local
vi /etc/profile
export PATH=$PATH:/usr/local/go/bin
source /etc/profile
go version

 

2、下載源碼

cd /data && git clone https://github.com/kubernetes/kubernetes.git
git checkout -b remotes/origin/release-1.15.1 v1.15.1


3、修改 Kubeadm 源碼包更新證書策略

vim staging/src/k8s.io/client-go/util/cert/cert.go # kubeadm 1.14 版本之前
vim cmd/kubeadm/app/util/pkiutil/pki_helpers.go # kubeadm 1.14 至今
  const duration365d = time.Hour * 24 * 365 * 10
  NotAfter:time.Now().Add(duration365d).UTC(),

 

make WHAT=cmd/kubeadm GOFLAGS=-v
cp _output/bin/kubeadm /root/kubeadm-new

 

4、更新 kubeadm

 

# 將 kubeadm 進行替換
cp /usr/bin/kubeadm /usr/bin/kubeadm.old cp /root/kubeadm-new /usr/bin/kubeadm chmod a+x /usr/bin/kubeadm


5、更新各節點證書至 Master 節點

cp -r /etc/kubernetes/pki /etc/kubernetes/pki.old
cd /etc/kubernetes/pki
 kubeadm alpha certs renew all --config=/usr/local/install-k8s/core/kubeadm-config.yaml
openssl x509 -in apiserver.crt -text -noout | grep Not

 

6、HA集群其余 mater 節點證書更新

#!/bin/bash
masterNode="192.168.66.20 192.168.66.21"
#for host in ${masterNode}; do
#  scp /etc/kubernetes/pki/{ca.crt,ca.key,sa.key,sa.pub,front-proxy-ca.crt,front-proxy-ca.key}
"${USER}"@$host:/etc/kubernetes/pki/
#  scp /etc/kubernetes/pki/etcd/{ca.crt,ca.key} "root"@$host:/etc/kubernetes/pki/etcd
#  scp /etc/kubernetes/admin.conf "root"@$host:/etc/kubernetes/
#done
for host in ${CONTROL_PLANE_IPS}; do
  scp /etc/kubernetes/pki/{ca.crt,ca.key,sa.key,sa.pub,front-proxy-ca.crt,front-proxy-ca.key}
"${USER}"@$host:/root/pki/
  scp /etc/kubernetes/pki/etcd/{ca.crt,ca.key} "root"@$host:/root/etcd
  scp /etc/kubernetes/admin.conf "root"@$host:/root/kubernetes/
done

 

12、高可用的K8S集群構建

 

https://www.cnblogs.com/yyq1/p/14146568.html


免責聲明!

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



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