- OpenShift在企業(yè)中的實踐:PaaS DevOps微服務(第2版)
- 魏新宇 郭躍軍
- 12817字
- 2021-11-05 10:17:13
2.2.2 OpenShift的技術架構
了解OpenShift的邏輯架構之后,接下來講解在OpenShift中使用了哪些關鍵性技術。OpenShift的技術架構如圖2-7所示。

圖2-7 OpenShift的技術架構
按照層級,我們自下往上進行介紹。
·OpenShift的基礎操作系統(tǒng)是Red Hat CoreOS。Red Hat CoreOS是一個精簡的RHEL發(fā)行版,專用于容器執(zhí)行的操作系統(tǒng)。
·CRI-O是Kubernetes CRI(容器運行時接口)的實現(xiàn),以支持使用OCI(Open Container Initiative)兼容的運行時。CRI-O可以使用滿足CRI的任何容器運行時,如runC、libpod或rkt。
·Kubernetes是容器調度編排和管理平臺,關于它的具體功能我們不再贅述。
·Etcd是一個分布式鍵值存儲,Kubernetes使用它來存儲有關Kubernetes集群元數(shù)據(jù)和其他資源的配置及狀態(tài)信息。
·自定義資源定義(CRD)是Kubernetes提供的用于擴展資源類型的接口,自定義對象同樣存儲在Etcd中并由Kubernete管理。
·容器化服務(Containerized Service)實現(xiàn)了PaaS功能組件以容器方式在OpenShift上運行。
·應用程序運行時和xPaaS(Runtime and xPaaS)是可供開發(fā)人員使用的基本容器鏡像,每個鏡像都預先配置了特定的運行時語言或數(shù)據(jù)庫。xPaaS產(chǎn)品是紅帽中間件產(chǎn)品(如JBoss EAP和ActiveMQ)的一組基礎鏡像。OpenShift應用程序運行時(RHOAR)是在OpenShift中運行云原生應用的程序運行時,包含Red Hat JBoss EAP、OpenJDK、Thorntail、Eclipse Vert.x、Spring Boot和Node.js。
·DevOps工具和用戶體驗:OpenShift提供用于管理用戶應用程序和OpenShift服務的Web UI和CLI管理工具。OpenShift Web UI和CLI工具是使用REST API構建的,可以與IDE和CI平臺等外部工具集成使用。
我們已經(jīng)從技術架構圖中了解到技術組件的概貌,接下來將深入介紹OpenShift中一些關鍵技術的細節(jié)。
1.CoreOS操作系統(tǒng)介紹
CoreOS是一個容器化操作系統(tǒng),由CoreOS公司開發(fā)。后來CoreOS被紅帽收購,形成了Red Hat Enterprise Linux CoreOS(簡稱RHCOS)產(chǎn)品。
RHCOS代表了下一代單用途容器操作系統(tǒng)技術。RHCOS由創(chuàng)建了Red Hat Enterprise Linux Atomic Host和CoreOS Container Linux的同一開發(fā)團隊打造,它將Red Hat Enterprise Linux(RHEL)的質量標準與Container Linux的自動化遠程升級功能結合在一起。
OpenShift的Master節(jié)點必須使用RHCOS,Worker節(jié)點可以選擇RHCOS或RHEL。目前RHCOS只能作為OpenShift的基礎操作系統(tǒng),不能獨立使用。RHCOS的組件管理也由OpenShift進行,如圖2-8所示。

圖2-8 OpenShift基礎架構的變化
RHCOS底層操作系統(tǒng)主要由RHEL組件構成。它支持RHEL的相同質量、安全性和控制措施,也支持RHCOS。例如,RHCOS軟件位于RPM軟件包中,并且每個RHCOS系統(tǒng)都以RHEL內核以及由Systemd初始化系統(tǒng)管理的一組服務啟動。
RHCOS系統(tǒng)包含的組件如圖2-9所示。

圖2-9 RHCOS系統(tǒng)包含的組件
我們查看CoreOS的版本,它與OpenShift的版本匹配,如OpenShift 4.4使用RHCOS 4.4。
# cat /etc/redhat-release Red Hat Enterprise Linux CoreOS release 4.4
查看Kubelet、CRI-O,這兩個是Systemd,如圖2-10和圖2-11所示。

圖2-10 RHCOS系統(tǒng)中的Kubelet狀態(tài)

圖2-11 RHCOS系統(tǒng)中的CRI-O狀態(tài)
對于RHCOS系統(tǒng),rpm-ostree文件系統(tǒng)的布局如下:
·/usr是操作系統(tǒng)二進制文件和庫的存儲位置,并且是只讀的。
·/etc、/boot和/var在系統(tǒng)上是可寫的,但只能由Machine Config Operator更改。
·/var/lib/containers是用于存儲容器鏡像的Graph存儲位置。
在OpenShift中,Machine Config Operator負責處理RHCOS操作系統(tǒng)升級,rpm-ostree以原子單元形式提供升級,不像Yum升級那樣單獨升級各個軟件包。新的RHCOS部署在升級過程中進行,并在下次重啟時才會生效。如果升級出現(xiàn)問題,則進行一次回滾并重啟,就能使系統(tǒng)恢復到以前的狀態(tài)。需要指出的是,RHCOS升級是在OpenShift集群更新期間執(zhí)行的,不能單獨升級RHCOS。
2.OpenShift中的Operator介紹
在OpenShift中大量使用了Operator。Operator是打包、運行和維護Kubernetes應用程序的一種方式,主要針對有狀態(tài)應用集群,如etcd。Operator同樣也是一種Kubernetes應用程序,它不僅部署在Kubernetes上,還要與Kubernetes的設施和工具協(xié)同工作,以實現(xiàn)軟件自動化的整個生命周期。通過Operator,使用者可以更輕松地部署和運行基礎應用程序所依賴的服務。對于基礎架構工程師和供應商,Operator提供了一種在Kubernetes集群上分發(fā)軟件的一致方法,并且能夠在發(fā)現(xiàn)和糾正應用程序問題之前減少支持負擔和異常出現(xiàn)。
Operator最初由CoreOS公司開發(fā),逐步成為一種非常流行的打包、部署和管理Kubernetes/OpenShift應用的方法,如圖2-12所示。

圖2-12 Operator發(fā)展史
OpenShift中的Operator按作用不同,主要可分為Cluster Operator和Application Operator。下面分別說明OpenShift中的這兩類Operator。
(1)OpenShift Cluster Operator
Cluster Operator用來對OpenShift集群組件進行生命周期管理,如OpenShift的版本升級實際上是升級Cluster Operator和CoreOS,在本章后面我們將詳細說明升級過程。也就是說,OpenShift自身能力的提供是通過各類Cluster Operator實現(xiàn)的,如圖2-13所示。
每個Cluster Operator相關的Namespace通常有兩個,一個Namespace運行Operator本身的Pod,另一個Namespace運行由這個Operator控制的、負責具體工作的Pod,實際工作的Pod通常有多個,分別運行在OpenShift的不同節(jié)點上。

圖2-13 OpenShift上的Cluster Operator
我們以dns的Cluster Operator為例,和dns相關的Namespace有兩個:openshift-dns-operator Namespace和openshift-dns Namespace。其中openshift-dns-operator Namespace中運行dns Cluster Operator本身的Pod,Pod名稱類似于dns-operator-5995b99c68-sf2b9;
openshift-dns Namespace中運行具體負責DNS解析的Coredns的Pod。我們查看該Namespace下的Pod,就可以看到每個OpenShift節(jié)點上都會運行一個Coredns的Pod。這些Coredns Pod是由dns Cluster Operator管理的Daemonset控制的,默認名稱為dns-default。
綜上所述,dns通過Operator的啟動和控制流程為:dns Cluster Operator(openshift-dns-operator Namespace下)創(chuàng)建dns-default Daemonset(openshift-dns Namespace下),再由dns-default Deamonset在每個OpenShift節(jié)點創(chuàng)建Coredns Pod,負責集群中的DNS解析。這樣我們就需要通過配置dns Cluster Operator的參數(shù)來改變dns-default Daemonset的參數(shù),進而改變Coredns的行為。
在OpenShift中,有的Cluster Operator具體負責工作的Pod無須運行在所有的節(jié)點上,只需有多副本保證高可用即可。如Ingress,Ingress負責對外發(fā)布路由,同樣由Cluster Operator控制,運行在openshift-ingress-operator和openshift-ingress兩個Namespace上。同樣,在openshift-ingress-operator Namespace中運行ingress operator Pod;openshift-ingress Namespace中運行兩個負責具體路由功能的Router Pod。而Router Pod是由Ingress Operator管理的Deployments控制的。
默認安裝完成后,Router Pod會運行在不固定的兩個節(jié)點上,比如Master節(jié)點中的兩個節(jié)點。通常在生產(chǎn)上我們需要專門規(guī)劃節(jié)點來運行Router,在后文將介紹如何將Router遷移到Infra節(jié)點(特殊的Worker節(jié)點)上。
經(jīng)過前面的介紹,相信讀者已經(jīng)了解了OpenShift中Cluster Operator的運作模式。限于篇幅,我們在此就不一一介紹了,OpenShift中所有Cluster Operator的整體概覽性介紹如表2-1所示。
表2-1 OpenShift中的Cluster Operator清單


(2)OpenShift Application Operator
OpenShift推出OperatorHub,可以基于Operator模式管理應用,我們稱這類Operator為Application Operator(與Cluster Operator相對應)。
Operator Framework也是紅帽推出的,用于構建、測試和打包Operator的開源工具包。它提供了以下三個組件:
·Operator軟件開發(fā)套件(Operator SDK):提供了一組Golang庫和源代碼示例,這些示例在Operator應用程序中實現(xiàn)了通用模式。它還提供了一個鏡像和Playbook示例,我們可以使用Ansible開發(fā)Operator。
·Operator Metering:為提供專業(yè)服務的Operator啟用使用情況報告。
·Operator生命周期管理器(Operator Lifecycle Manager,OLM):提供了一種陳述式的方式來安裝、管理和升級Operator以及Operator在集群中所依賴的資源。
其中Operator Lifecycle Manager(OLM)可幫助用戶安裝、更新和管理跨集群運行的所有Operator及其關聯(lián)服務的生命周期。OLM承載著OpenShift OperatorHub,目前可以提供近200個Operator,如圖2-14所示。

圖2-14 OLM中的Operator
在OLM生態(tài)系統(tǒng)中,以下資源負責Operator的安裝和升級:
·ClusterServiceVersion
·CatalogSource
·Subscription
ClusterServiceVersion(CSV)是從Operator Metadata創(chuàng)建的YAML清單,可幫助OLM在集群中運行Operator。一個CSV包括Metadata(應用的name、version、icon、required resources、installation等)、Install strategy(包括ServiceAccount、Deployments)、CRDs。
不同Operator的元數(shù)據(jù)以CSV存儲在CatalogSource中。在CatalogSource中,Operator被存儲到Package中,然后以Channel來區(qū)分Update Stream。OLM使用CatalogSources(調用Operator Registry API)來查詢可用的Operator以及已安裝的Operator的升級,如圖2-15所示。

圖2-15 OLM調用CatalogSources查詢版本
以Etcd Operator為例,它整體上是個Package,分為alpha和beta兩個Channel,每個Channel中通過CSV來區(qū)分版本,如etcdoperator.v0.6.1、etcdoperator.v0.9.0、etcdoperator.v0.9.2。在Channel中也定義了通過CSV實現(xiàn)的升級途徑。
用戶在Subscription的特定CatalogSource中指示特定的軟件包和Channel,例如etcd Package及其alpha Channel。如果在尚未安裝該Package的Namespace中進行訂閱,則會安裝Package選擇的Channel中最新版本的Operator。
在OpenShift中有四種CatalogSource,如圖2-16所示。

圖2-16 查看OCP中的CatalogSources
四種CatalogSource分別為certified-operators(紅帽認證的Operator)、community-operators(開源社區(qū)的Operator)、redhat-marketplace(紅帽認證過的由第三方銷售的Operator)和redhat-operators(紅帽公司提供的Operator)。這與圖2-16 OpenShift OperatorHub顯示的四類Provider Type是對應的(框線標記)。
接下來,我們通過在OpenShift安裝Etcd Operator來說明OLM的工作原理。
首先在Operator中搜索etcd,如圖2-17所示,我們看到etcd屬于community-operators的CatalogSource。

圖2-17 查找etcd Operator
我們可以看到Operator Version、Repository、Container Image、創(chuàng)建時間等關鍵信息,如圖2-18所示,點擊Install。

圖2-18 etcd Operator的信息
我們看到需要指定etcd安裝的Namespace、Update Channel、Approval Strategy(當本Channel有新版的軟件時采用自動還是手動更新),我們根據(jù)需要做出選擇,然后點擊Install,如圖2-19所示。

圖2-19 etcd Operator安裝時的選擇
稍等一會兒,etcd Operator就可以安裝成功,如圖2-20所示。

圖2-20 etcd Operator安裝成功
此時,我們可以選擇編輯CSV,如圖2-21所示。

圖2-21 編輯etcd Operator的CSV
如前文所示,CSV中包含大量的元數(shù)據(jù)信息,將其中的metadata.name字段由example修改為example-davidwei。修改完成后,點擊Save,界面會提示需要Reload,如圖2-22所示。

圖2-22 編輯CSV的內容
接下來,我們使用etcd Operator提供的API創(chuàng)建etcd Cluster實例,如圖2-23所示。

圖2-23 使用etcd Operator API創(chuàng)建etcd Cluster
我們看到metadata中的name字段為example-davidwei,這是此前我們修改CSV時指定的,如圖2-24所示,點擊Create。

圖2-24 創(chuàng)建EtcdCluster
稍等一會兒,EtcdCluster就會創(chuàng)建成功,此時通過命令行查看Pod。
# oc get pods NAME READY STATUS RESTARTS AGE etcd-operator-59dc995496-mdkjk 3/3 Running 0 6m example-davidwei-mzfl7nm566 1/1 Running 0 38s example-davidwei-nxphptkn95 1/1 Running 0 30s example-davidwei-qt98qwrm79 1/1 Running 0 14s
此時應用已經(jīng)可以使用這個etcd集群存儲數(shù)據(jù)了。
如果我們想對etcd Cluster進行擴容,例如增加一個實例,通過Operator操作即可,如圖2-25所示,點擊Update Size。

圖2-25 增加etcd Cluster節(jié)點數(shù)量
etcd Cluster很快開始進行擴容,如圖2-26所示。
擴容完成后,查看運行的Pod,已經(jīng)變成4個節(jié)點的etcd集群。
# oc get pods NAME READY STATUS RESTARTS AGE etcd-operator-59dc995496-mdkjk 3/3 Running 0 9m14s example-davidwei-f6vpv8mzqv 1/1 Running 0 10s example-davidwei-mzfl7nm566 1/1 Running 0 3m52s example-davidwei-nxphptkn95 1/1 Running 0 3m44s example-davidwei-qt98qwrm79 1/1 Running 0 3m28s

圖2-26 etcd Cluster擴容完畢
通過擴容這個示例可以看出,通過Application Operator管理的應用可以大幅度減少運維層面的操作。
值得一提的是,在etcd Operator安裝后,我們仍然可以修改Channel,如圖2-27所示。

圖2-27 修改etcd Operator的Channel
至此,我們在OpenShift上通過etcd Operator安裝并擴容了etcd Cluster。
3.OpenShift核心進程運行分析
為了更清楚地了解OpenShift各節(jié)點上運行的服務,我們先簡單回顧原生Kubernetes各節(jié)點上運行的服務或進程。
(1)Kubernetes各節(jié)點核心進程簡介
原生Kubernetes中的核心進程架構如圖2-28所示。

圖2-28 Kubernetes中的核心進程
Kubernetes Master節(jié)點上有如下核心進程:
·kube-apiserver:Kubernetes API server驗證并配置API對象的數(shù)據(jù),這些對象包括Pod、Service、ReplicationController等。此外,API Server提供REST操作服務,并為集群的共享狀態(tài)提供前端訪問,所有其他組件都通過該前端進行交互。
·etcd:一個鍵值數(shù)據(jù)庫,用于存放kube-apiserver的相關數(shù)據(jù),如服務注冊信息等。
·controller manager:kube-controller-manager只在Master節(jié)點運行,管理多個controller進程。kube-controller-manager監(jiān)控對象包括Node、Workload(replication controller)、Namespace(namespace controller)、Service Account(service account controller)等,當這些被監(jiān)控對象實際狀態(tài)和期望狀態(tài)不匹配時采取糾正措施。
·scheduler:即kube-scheduler。主要負責整個集群資源的調度功能,根據(jù)特定的調度算法和策略,將Pod調度到最優(yōu)的Worker節(jié)點上。
Kubernetes Node節(jié)點上有如下核心進程:
·kubelet:kubelet是在Kubernetes節(jié)點上運行的Node Agent。kubelet可以通過hostname將Node注冊到kube-apiserver。
·kube-proxy:即Kubernetes network proxy。kube-proxy部署在每個Node節(jié)點上,它是實現(xiàn)Kubernetes Service的通信與負載均衡機制的重要組件;kube-proxy負責為Pod創(chuàng)建代理服務,從kube-apiserver獲取所有Service信息,并根據(jù)Service信息創(chuàng)建代理服務,實現(xiàn)Service到Pod的請求路由和轉發(fā),從而實現(xiàn)Kubernetes層級的虛擬轉發(fā)網(wǎng)絡。
·容器運行時:kubelet通過調用容器運行時管理節(jié)點上的容器。
(2)OpenShift各節(jié)點核心進程分析
在OpenShift中,同樣將節(jié)點分為Master節(jié)點和Worker節(jié)點,下面先介紹Master節(jié)點。
OpenShift Master節(jié)點的進程結構如圖2-29所示。

圖2-29 OpenShift Master節(jié)點的進程結構
我們看到OpenShift Master中會有兩個API Server:kube-apiserver和openshift-apiserver,后者是前者的API請求代理;兩個controller manager:kube-controller-manager和openshift-controller-manager,后者是前者的代理,對前者進行了一定拓展。在OpenShift集群中,任何操作都不會直接調用kube-apiserver和kube-controller-manager,而是由openshift-apiserver和openshift-controller-manager完成。
同時從圖2-29中可以看到,Master上進程的運行方式分以下三類:
·普通Pod(由Cluster Operator管理)
·靜態(tài)Pod
·Systemd服務
首先我們先看靜態(tài)Pod。靜態(tài)Pod是不需要連接到API Server即可啟動的容器,它們由特定節(jié)點上的Kubelet守護程序直接管理,Kubelet會監(jiān)視每個靜態(tài)Pod(并在崩潰時重新啟動它),靜態(tài)Pod始終綁定到特定節(jié)點上的一個Kubelet。
我們查看Master節(jié)點上運行的靜態(tài)Pod,首先登錄節(jié)點,如master-0。切換到/etc/kubernetes/static-pod-resources目錄。
通過ls命令查看該目錄下的文件,可以看到Master節(jié)點被Kubelet管理的靜態(tài)Pod正是etcd、kube-controller-manager、kube-apiserver、kube-scheduler四個。這些Pod實際上是在OpenShift安裝完成前,在Bootstrap階段就已經(jīng)啟動了,第5章會詳細介紹安裝的各個階段。
接下來,我們查看Master節(jié)點上運行的兩個Systemd服務:kubelet和cri-o,我們看到它們處于正常運行的狀態(tài),如圖2-30、圖2-31所示。

圖2-30 OpenShift Master節(jié)點的kubelet進程

圖2-31 OpenShift Master節(jié)點的cri-o進程
除了Kubernetes Master的6個核心組件之外,OpenShift Master節(jié)點上還運行openshift-apiserver、openshift-controller-manager、openshift authentication,這些組件都由OpenShift Cluster Operator管理,并且都是普通Pod。
openshift-controller-manager用于管理OpenShift集群中的多個controller,我們通過命令行查看OpenShift中的controller,如圖2-32所示。

圖2-32 查看OpenShift中的controller
從圖2-32中看到,有sdn-controller(負責管理SDN)、machine-config-controller(負責對底層CoreOS進行配置管理,第5章會進行詳細介紹)、multus-admission-controller(負責OpenShift中多網(wǎng)絡平面管理,本章后文詳細介紹)、csi-snapshot-controller(用于實現(xiàn)第三方CSI的volume snapshot生命周期管理)。這些組件的特點是控制平面只運行在Master節(jié)點上,所有OpenShift計算節(jié)點都承擔數(shù)據(jù)平面的職責。
以SDN為例查看相關的Pod,如圖2-33所示。

圖2-33 查看OpenShift中SDN相關的Pod
其中sdn-controller Pod只運行在Master節(jié)點上,OVS Pod則在每個節(jié)點上都會運行。其余的controller組件的結構都類似,不再一一列出。
當我們清楚了Master節(jié)點上的進程如何運行之后,接下來看Worker節(jié)點。在Worker節(jié)點上運行OpenShift自身核心的組件有crio、kubelet、kube-proxy。此外還有由openshift-controller-manager控制的controller對應的數(shù)據(jù)平面,如sdn、machine-config等,Worker節(jié)點上無靜態(tài)Pod。
Worker節(jié)點上的crio、kubelet同樣是Systemd服務。而Worker節(jié)點上的kube-proxy在OpenShift的每個節(jié)點上運行,并由Cluster Network Operator(CNO)管理。kube-proxy維護用于轉發(fā)與Service關聯(lián)的Endpoints的網(wǎng)絡規(guī)則。
kube-proxy的安裝方式取決于集群配置的SDN插件。如果使用SDN插件內置kube-proxy(如OpenShift SDN),則不需要獨立安裝kube-proxy;還有一些SDN插件需要獨立安裝kube-proxy,也有一些SDN插件(如ovn-kubernetes)根本就不需要kube-proxy。
在安裝集群的時候,在文件manifests/cluster-network-03-config.yml中的deployKube-Proxy參數(shù)可用于指示CNO是否應部署獨立的kube-proxy。對于OpenShift官方明確支持的SDN插件,將自動配置正確的值;當使用第三方插件的時候可以修改此值。
由于OpenShift SDN內置了kube-proxy進程,因此Worker節(jié)點上的kube-proxy進程由openshift-sdn項目下的Pod sdn-xxxxx啟動,啟動命令為/usr/bin/openshift-sdn-node--proxy-config=/config/kube-proxy-config.yaml。
我們可以通過Network Operator的參數(shù)來配置kube-proxy,以便控制OpenShift節(jié)點上的kube-proxy參數(shù)。
kube-proxy配置參數(shù)包含的內容如表2-2所示。
表2-2 kube-proxy配置參數(shù)

以調整kube-proxy參數(shù)iptables-min-sync-period為例,該參數(shù)控制刷新iptables規(guī)則之前的最短持續(xù)時間,此參數(shù)確保不會太頻繁地發(fā)生刷新,默認值為30s。
Iptables的同步觸發(fā)條件如下:
·events觸發(fā):是指Service或Endpoint對象發(fā)生變化,如創(chuàng)建Service。
·自上次同步以來的時間超過了kube-proxy定義的同步時間,默認30s。
通過修改Network.operator.openshift.io自定義資源(CR)實現(xiàn)修改kube-proxy的配置。默認配置中,沒有任何與kube-proxy相關的配置。
# oc edit network.operator.openshift.io cluster
增加如圖2-34中框選的內容。

圖2-34 修改kube-proxy的配置
運行以下命令以確認配置更新,如圖2-35所示。
# oc get networks.operator.openshift.io -o yaml
這樣,我們就設置了Iptables的同步時間為30s,iptables刷新之前最短持續(xù)時間為30s。

圖2-35 確保kube-proxy的配置修改成功
4.OpenShift的認證與授權
OpenShift認證體系包含認證和授權。認證層負責識別用戶的身份,驗證用戶身份后,通過RBAC(Role-Based Access Control,基于角色的訪問控制)策略定義該用戶允許執(zhí)行的操作,這屬于授權。OpenShift通過RBAC實現(xiàn)權限控制。
(1)OpenShift認證體系介紹
OpenShift支持以下兩種認證方式:
·OAuth Access Token:使用OpenShift內的OAuth Server頒發(fā)的Access Token認證,可以通過用戶登錄、ServiceAccount或者API獲取。
·X.509 Client Certificate:通過證書認證,證書大多數(shù)用于集群組件向API Server認證。
任何具有無效Token或無效證書的請求都將被身份驗證層拒絕,并返回401錯誤。OpenShift內置OAuth Server,由authentication operator提供,如圖2-36所示。

圖2-36 查看OpenShift內置OAuth Server
接下來簡單介紹與認證相關的幾個概念。
·User:OpenShift中的User是與API Server進行交互的實體。通過直接向User或User所屬的Group添加角色來分配權限。OpenShift中的User分為三種:System User、Regular User和Service Account。System User是OpenShift自動生成的,主要用于基礎組件與API交互。Regular User表示user對象,是用戶和OpenShift API交互最活躍的部分。Service Account是與Project相關聯(lián)的特殊的系統(tǒng)用戶,可以看作OpenShift運行應用的用戶代表,通過Service Account配置應用具有的OpenShift權限。
·Identity:OpenShift中的每個用戶都有一個身份(identity)用于認證,本質上Identity是OpenShift與Identity Providers集成的產(chǎn)物。在使用Identity Providers中的用戶登錄后,會自動在OpenShift中創(chuàng)建User對象和Identity對象,Identity對象中記錄User和Identity Providers的信息,實現(xiàn)唯一標識一個用戶,尤其在多個Identity Providers中有重名時這種方式很有效。
當User嘗試向API Server進行身份驗證時,OAuth Server首先會通過Identity Providers來驗證請求者的身份,只有身份驗證通過,OAuth Server才會向用戶提供OAuth Access Token。OpenShift提供了可以與多種Identity Providers對接的能力,主要包括:
·HTPasswd:使用HTPasswd生成的用戶名和密碼文件驗證。
·Keystone:啟用與OpenStack Keystone v3服務器的共享身份驗證。
·LDAP:使用簡單綁定身份驗證,配置LDAP身份提供程序以針對LDAP v3服務器驗證用戶名和密碼。
·GitHub或GitHub Enterprise:配置GitHub身份提供者以針對GitHub或GitHub Enterprises OAuth身份驗證服務器驗證用戶名和密碼。
·OpenID Connect:使用授權代碼流與OpenID Connect身份提供者集成。
我們可以在同一個OpenShift集群中定義相同或不同種類的多個身份提供者。例如,既有通過HTPasswd認證的方式,又有通過OpenID Connect認證的方式。此外,我們既可以使用OpenShift內置的OAuth做認證,也可以對接外部的OAuth服務器,尤其是我們在實現(xiàn)微服務的Single Sign On時,例如使用Red Hat Single Sign On(Keycloack企業(yè)版)。在本章后面安裝環(huán)節(jié)將介紹身份提供者的配置。
綜上所述,OpenShift中的認證流程如圖2-37所示。

圖2-37 OpenShift的認證流程
在認證成功之后,訪問Master API還需要經(jīng)過鑒權來判斷該用戶對資源是否有操作權限,下面就介紹OpenShift中的RBAC權限模型。
(2)OpenShift RBAC權限模型介紹
在獲取到OAuth Access Token之后,任何的操作都要經(jīng)過鑒權。OpenShift中與RBAC相關的資源類型有User(前文已經(jīng)介紹)、Group、Role等概念。接下來,我們簡單介紹這幾個概念。
·Group:代表一組特定的用戶。用戶被分配到一個或多個組。在實施授權策略后,可以利用組同時向多個用戶分配權限。例如,如果要允許20個用戶訪問某個項目中的資源,更好的方式是使用組而不是單獨授予每個用戶訪問權限。除了自定義組之外,OpenShift默認還提供了系統(tǒng)組或虛擬組,這些組由系統(tǒng)自動創(chuàng)建,常用的系統(tǒng)組如system:authenticated:oauth,所有通過OAuth Access Token認證的用戶會自動加入該組,這個組被賦予self-provisioners Cluster Role,使得所有通過OAuth Access Token認證的用戶具有新建Project的權限。
·Role:是一組權限,使用戶可以對一種或多種資源類型執(zhí)行API操作。按作用范圍,可將Role分為Cluster Role和Local Role。Cluster Role是整個集群范圍內的,任何Namespace都可以使用,但是Local Role是屬于Namespace級別的資源,而且需要自行創(chuàng)建。你可以通過對User、Group分配Cluster Role或Local Role來為其授予權限。
OpenShift中的RBAC模型如圖2-38所示。

圖2-38 OpenShift中的RBAC模型
從圖2-38中可以看出授權的對象可以是Service Account、Group和User。Role可以是Cluster Role,也可以是Local Role。授權后會生成相應的Role Binding對象,相當于記錄授權對象與Role的授權關系。
很多企業(yè)對容器云的分權控制要求很高,這時候就需要借助OpenShift中的RBAC進行細致的權限劃分。我們不再贅述RBAC的基本概念,這里列出幾個常見的場景供讀者參考。
場景1:只擁有審計權限,沒有管理權限。預期:登錄后只能查看審計日志,無法查看租戶。
# oc login -u admin # oc create clusterrole audit-no-admin --verb=get --resource=nodes/log --verb=list --resource=nodes --verb=get --resource=nodes/proxy # oc adm policy add-cluster-role-to-user audit-no-admin auditnoadmin # oc login -u auditnoadmin # oc adm node-logs --role=master --path=openshift-apiserver/
場景2:只擁有管理權限,沒有審計權限。預期:登錄后無法查看審計日志,可以查看租戶。
# oc login -u admin # oc adm policy add-cluster-role-to-user admin adminnoaudit # oc login -u adminnoaudit # oc adm node-logs --role=master --path=openshift-apiserver/
場景3:不能審計、不能管理的安全員。預期:登錄后無法查看審計日志,無法查看租戶。
# oc login -u admin # oc adm policy add-cluster-role-to-user cluster-status safetyofficer # oc login -u safetyofficer # oc adm node-logs --role=master --path=openshift-apiserver/ # oc get projects
讀者在理解了RBAC的模型后,可以自行創(chuàng)建滿足需求的Role,實現(xiàn)細粒度的權限控制。
5.OpenShift中的安全上下文約束(SCC)
除了通過RBAC來控制用戶的權限之外,OpenShift還提供了安全上下文約束(SCC)來控制Pod的權限。這些權限包含Pod可以執(zhí)行的操作和可以訪問的資源,包含對主機環(huán)境的訪問限制。SCC允許控制如下內容:
·運行特權容器。
·在容器中獲取額外的能力。
·使用宿主機目錄作為Pod Volume。
·容器的SELinux上下文。
·容器的用戶ID。
·宿主機命名空間和網(wǎng)絡的使用。
·Pod Volume的屬組FSGroup。
·附加組的配置。
·根文件系統(tǒng)只讀。
·可以使用的Volume類型。
·配置允許的seccomp策略。
OpenShift中默認提供了8個SCC策略,SCC需要授權User或Group后才能被使用,默認策略中允許使用User和Group如表2-3所示。
表2-3 OpenShift中SCC策略的說明

需要特別提醒的是,絕不要修改默認的8個SCC策略的內容,否則會導致集群升級出現(xiàn)問題,正確的做法是創(chuàng)建新的SCC策略。
上述8個SCC策略中,只有anyuid的優(yōu)先級最高,會被優(yōu)先匹配。我們最常用的是privileged和restricted,前者表示幾乎無限制的特權容器,后者表示受嚴格限制的容器。大部分容器會匹配restricted SCC,我們以restricted SCC為例,查看策略內容如下所示。
Name: restricted Priority: <none> Access: Users: <none> Groups: system:authenticated Settings: Allow Privileged: false Allow Privilege Escalation: true Default Add Capabilities: <none> Required Drop Capabilities: KILL,MKNOD,SETUID,SETGID Allowed Capabilities: <none> Allowed Seccomp Profiles: <none> Allowed Volume Types:configMap,downwardAPI,emptyDir,persistentVolumeClaim, projected,secret Allowed Flexvolumes: <all> Allowed Unsafe Sysctls: <none> Forbidden Sysctls: <none> Allow Host Network: false Allow Host Ports: false Allow Host PID: false Allow Host IPC: false Read Only Root Filesystem: false Run As User Strategy: MustRunAsRange UID: <none> UID Range Min: <none> UID Range Max: <none> SELinux Context Strategy: MustRunAs User: <none> Role: <none> Type: <none> Level: <none> FSGroup Strategy: MustRunAs Ranges: <none> Supplemental Groups Strategy: RunAsAny Ranges: <none>
可以看到SCC由Setting和Strategy兩部分來控制Pod的權限。這些配置的值分為以下三類:
·通過布爾值設置,只有True和False,如Allow Privileged:false。
·通過一組允許的值設置,如Allow Volume Types。
·通過策略控制,這類配置通過設置策略實現(xiàn)不同的權限控制。策略分為生成固定值的和指定允許范圍的。
通過布爾值設置以及通過一組允許的值設置這兩種方式大家都比較好理解,這里我們著重說明策略控制類型的SCC配置。有四個策略控制類型:Run As User、SELinux Context、Supplemental Groups、FSGroup。
·Run As User:該設置控制Pod啟動后運行進程的用戶。
允許配置四種策略:
1)MustRunAs:如果SCC中設定為此策略,則必須在Pod的定義中通過security-Context.runAsUser設定明確的Pod運行UID,否則Pod將無法啟動。
2)MustRunAsRange:SCC Resricted的默認配置。此策略表示Pod運行的UID必須在一個范圍內,如果在SCC中沒有定義范圍的最小最大值,則每個Project Pod運行的UID范圍使用Project上Annotation openshift.io/sa.scc.uid-range定義的范圍,如1000060000/10000,表示最小值為1000060000,向后步增,共10000個。如果不在Pod的定義中通過securityContext.runAsUser設定Pod運行UID,則使用范圍的最小值作為默認值。設定runAsUser必須在MustRunAsRange設定的最大最小值范圍里。比如某個Pod匹配到Resricted SCC,由于Resricted默認未設置MustRunAsRange的最大最小值,則會使用Project上定義的范圍,假設為1000060000/10000。如果該Pod中也沒有明確定義runAsUser,那么該Pod運行的UID為范圍最小值1000060000;如果該Pod中有明確定義運行的UID,那么必須在1000060000~1000070000范圍內。
3)MustRunAsNonRoot:該策略表示只要不是Root(UID=0)用戶就可以。沒有提供默認值,要求Pod必須提供一個非零的UID。可以在Pod定義中通過securityContext.runAsUser設定,也可以在Pod使用的鏡像的Dockerfile中通過USER指令來定義非Root用戶。
4)RunAsAny:該策略表示可以使用任何UID運行。沒有提供默認值,可以在Pod定義中通過securityContext.runAsUser設定,也可以在Pod使用的鏡像的Dockerfile中通過USER指令定義。
·SELinux Context:該設置控制Pod啟動后的SELinux標簽。
允許配置兩種策略:
1)MustRunAs:SCC Resricted的默認配置。必須以指定的SELinux標簽運行。可以通過在SCC策略中設定,也可以在Pod定義中通過securityContext.SELinuxOptions設定,如果上述兩處都沒有設定,那么將使用Project上Annotaions openshift.io/sa.scc.mcs定義的值。
2)RunAsAny:允許以任何SELinux標簽運行,未提供默認值。在這種策略下,如果SCC和Pod定義中都未指定,則為空。
·Supplemental Groups:該設置控制Pod運行用戶的附加組。
允許配置兩種策略:
1)MustRunAs:必須以指定的附加組范圍運行。可以在SCC中定義附加組范圍,如果SCC中沒有定義附加組范圍,將使用Project上Annotation openshift.io/sa.scc.supplemental-groups定義的范圍,如1000060000/10000。你可以在Pod的定義中通過securityContext.supplementalGroups設定附加組GID,但必須在定義的范圍內。如果Pod定義中未明確設置附加組,將以生效范圍的最小值作為Pod的附加組GID。
2)RunAsAny:SCC Resricted的默認配置。允許Pod設定任何的附加組。
·FSGroup:該設置控制Pod運行的FSGroup。
允許配置兩種策略:
1)MustRunAs:SCC Resricted的默認配置。必須以指定的FSGroup范圍運行。可以在SCC中定義FSGroup范圍,如果SCC中沒有定義FSGroup范圍,將同樣使用Project上Annotation openshift.io/sa.scc.supplemental-groups定義的范圍。你可以在Pod的定義中通過securityContext.fsGroup設定FSGroup ID,但必須在定義的范圍內。如果Pod定義中未明確設置FSGroup,將以生效范圍的最小值作為Pod的FSGroup ID。
2)RunAsAny:允許任何的FSGroup設置。
可以看到,Pod的SCC權限受Pod的定義、SCC策略以及Project三者的相互作用,優(yōu)先級順序大致為Pod的定義>SCC策略>Project Annotations默認值。
我們在清楚了SCC中的配置內容之后,接下來看看SCC是如何匹配的。
在本章開始已提到,SCC是控制Pod權限的,所以SCC匹配也是與Pod匹配。SCC匹配大致經(jīng)過過濾和匹配兩個過程。過濾是指在集群中所有的SCC必須允許Pod使用,即Pod有權限使用SCC列表;匹配是指在過濾后的SCC中,逐個匹配Pod的需求與各項策略的定義,如果有滿足Pod環(huán)境需求的,則匹配成功,否則Pod無法啟動。如果有多個SCC滿足,則需要評估SCC的優(yōu)先級(SCC中的優(yōu)先級參數(shù)設置,比如anyuid 10),優(yōu)先級高的將被匹配;如果在優(yōu)先級相同的情況下,則選擇策略限制更加嚴格的SCC。
綜上所述,SCC匹配將與以下四點相關:
1)啟動Pod的用戶的權限,注意權限有可能來源于User或Group。
2)Pod中securityContext的定義。
3)Pod使用的鏡像中USER的定義,注意如果Dockerfile沒有明確定義USER,則默認為Root。
4)SCC的優(yōu)先級和策略配置,注意anyuid的優(yōu)先級最高。
介紹完SCC匹配的原理之后,我們來看默認SCC策略的情況。默認情況下,項目中未經(jīng)特殊授權的普通Pod只能使用restricted SCC,由于該SCC允許system:authenticated組匹配,其余的默認均無法被普通Pod使用,也就是說,普通Pod必須滿足restricted SCC的策略和權限,否則就會啟動失敗。我們可以根據(jù)需要創(chuàng)建新的SCC使用,也可以對默認的SCC賦權后使用,但絕對不要修改默認SCC策略的內容!
通常使用SCC的做法是通過Pod綁定的Service Account實現(xiàn)賦權,然后在Pod中定義特殊需求(比如hostnetwork、anyuid等)以匹配合適的SCC。過程大致如下。
首先需要創(chuàng)建Pod運行的Service Account。
# oc create serviceaccount scc-demo serviceaccount/scc-demo created
然后將創(chuàng)建的Service Account賦權給特定的SCC。
# oc adm policy add-scc-to-user hostnetwork -z scc-demo securitycontextconstraints.security.openshift.io/hostnetwork added to: ["scc-demo"]
執(zhí)行后可以去查看SCC中的Access.user會增加我們新建的Service Account。然后,就可以創(chuàng)建自己的Pod,Pod需要使用scc-demo Service Account。
注意,如果Pod中沒有必要使用hostnetwork SCC的需求,根據(jù)優(yōu)先級相同的匹配原則,依然會使用策略限制更加嚴格的restricted SCC,所以并不是賦權就一定使用hostnetwork SCC。
6.OpenShift中Pod調度策略
Pod調度程序用于根據(jù)特定的算法與策略將Pod調度到節(jié)點上。調度的主要過程是接受API Server創(chuàng)建新Pod的請求,并為其安排一個主機信息(也就是調度到節(jié)點上),最后將信息寫入Etcd中。但實際上,調度過程遠遠沒有這么簡單,需要綜合考慮很多決策因素。調度策略可分為默認調度策略和高級調度策略,下面我們分別介紹。
(1)默認調度策略
默認調度策略是OpenShift為kube-scheduler進程配置的策略,主要通過Predicates和Priorities(優(yōu)先級)定義策略。
1)Predicates的概念
Predicates本質上是過濾掉不合格節(jié)點的規(guī)則。OpenShift提供了多個Predicates。我們可以通過參數(shù)自定義Predicates,也可以組合多個Predicates以提供節(jié)點的過濾。Predicates包含Static(靜態(tài))和General(普通)兩類。
靜態(tài)的Predicates不接受用戶的任何配置參數(shù)或輸入,這些在調度程序配置中使用其確切名稱指定。靜態(tài)的Predicates示例如下所示(完整列表參考Repo中“默認靜態(tài)Predicates”)。
PodToleratesNodeTaints檢查Pod是否可以容忍節(jié)點污點。
{"name" : "PodToleratesNodeTaints"}
普通的Predicates包含Non-critical predicates和Essential predicates兩類。Non-critical predicates是只針對非關鍵Pod的節(jié)點過濾策略,Essential predicates是針對所有Pod的節(jié)點過濾策略。
Non-critical General Predicates示例如下:
PodFitsResources:根據(jù)資源可用性(CPU、內存、GPU等)確定適合度(根據(jù)Request資源)。
{"name" : "PodFitsResources"}
Essential General Predicates示例如下:
PodFitsHostPorts:確定節(jié)點是否具有用于請求的Pod端口的空閑端口(不存在端口沖突)。
{"name" : "PodFitsHostPorts"}
2)Priorities的概念
Priorities是根據(jù)優(yōu)先級對節(jié)點進行排名的規(guī)則。我們可以指定一組定制的Priorities來配置調度程序。默認情況下,OpenShift容器平臺中提供了Priorities,其他Priorities策略可以通過提供某些參數(shù)進行自定義。我們也可以組合多個Priorities,并且可以為每個Priorities賦予不同的權重,以設定節(jié)點優(yōu)先級。Priorities包含Static(靜態(tài))和Configurable(可配置)兩類。
Static類型除權重外不接受用戶的任何配置參數(shù)。必須要指定權重,并且不能為0或負數(shù)。(除NodePreferAvoidPodsPriority為10000外,每個Priorities函數(shù)的權重均為1。)
默認使用的優(yōu)先級都是Static類型的,如下所示(完整列表見Repo中“默認靜態(tài)優(yōu)先級策略”):
NodeAffinityPriority:根據(jù)節(jié)點相似性調度首選項對節(jié)點進行優(yōu)先級排序。
{"name" : "NodeAffinityPriority", "weight" : 1}
Configurable類型是除了OpenShift提供之外自行配置的優(yōu)先級。我們可以在openshift-config項目的調度程序中使用Configmap配置這些優(yōu)先級,后文我們將演示如何實現(xiàn)。
(2)高級調度策略
默認的調度策略是在集群運行前就配置好的,而且是全局生效的。那么,如果需要更多控制以調整某些Pod的調度呢?為了滿足多樣化的需求,OpenShift還提供了高級調度策略,也被稱為運行時調度策略,這種策略允許在創(chuàng)建應用時設置策略來影響Pod調度的位置。目前官方明確支持的高級調度策略有:
·使用node selectors規(guī)則。
node selectors是目前最為簡單的一種節(jié)點約束規(guī)則。通過在Pod中定義nodeSelector,然后匹配節(jié)點上的鍵值對Labels。OpenShift也提供了一部分內置的節(jié)點標簽,如kubernetes.io/hostname。
·使用affinity(親和)與anti-affinity(反親和)規(guī)則。
雖然nodeSelector提供了一種非常簡單的方法來將Pod調度到預期節(jié)點上,但是缺少靈活性。親和與反親和規(guī)則相當于nodeSelector的擴展,增強了語法的多樣化以及軟/偏好規(guī)則。目前包含Node親和、Pod親和與Pod反親和。
Node親和:目前支持requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution兩種類型的節(jié)點親和,可以分別視為硬條件限制和軟條件限制。在調度過程中,必須滿足requiredDuringSchedulingIgnoredDuringExecution定義的規(guī)則,如果不匹配,則調度失敗;preferredDuringSchedulingIgnoredDuringExecution中定義的規(guī)則為優(yōu)先選擇,即如果存在滿足條件的節(jié)點,則優(yōu)先使用,如果沒有滿足條件的節(jié)點,則忽略規(guī)則。
Pod親和與Pod反親和:Pod親和與反親和使得可以基于已經(jīng)在節(jié)點上運行的Pod的標簽來約束Pod可以調度到的節(jié)點,而不是基于節(jié)點上的標簽。Pod親和用于調度Pod可以和哪些Pod部署在同一拓撲結構下,Pod反親和則相反。同樣支持requiredDuringScheduling IgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution兩種類型。需要注意的是,使用這種策略的所有節(jié)點上必須有適當?shù)臉撕灡硎就負溆颍矣捎谶@種策略需要大量的計算,不建議在大規(guī)模集群中使用。
·使用taints(污點)和tolerations(容忍)規(guī)則。
節(jié)點親和是將Pod調度到預期的節(jié)點上,而污點則是反過來將一個節(jié)點標記為污點,那么該節(jié)點默認就不會被調度Pod,除非Pod明確被標識為可以容忍污點節(jié)點。標識節(jié)點為污點的每個鍵值對有三種效果:NoSchedule、PreferNoSchedule和NoExecute。NoSchedule表示Pod不會被調度到標記為污點的節(jié)點,PreferNoSchedule相當于NoSchedule的軟限制或偏好版本,NoExecute則意味著一旦污點被設置,該節(jié)點上所有正在運行的Pod只要沒有容忍污點的設置都將被直接驅逐。
(3)Pod調度程序算法
我們在了解了OpenShift中的調度策略后,接下來看看大部分(某些Pod會跳過調度程序,如Daemonsets、Static Pod)情況下Pod調度程序算法遵循的三個步驟。
第一步:過濾節(jié)點。
調度程序通過Predicate來過濾正在運行的節(jié)點的列表。此外,Pod可以定義與集群節(jié)點中的Label匹配的Node Selector,Label不匹配的節(jié)點不符合條件。
·Pod定義資源請求(例如CPU、內存和存儲),可用資源不足的節(jié)點不符合條件。
·評估節(jié)點列表是否有污點,如果有,則Pod是否有容忍污點的設置可以接受污點。如果Pod無法接受污點節(jié)點,則該節(jié)點不符合條件。
我們查看默認設置在Master節(jié)點上的污點。
# oc describe nodes master-0 |grep -i taints Taints: node-role.kubernetes.io/master:NoSchedule
然后查看目前在Master節(jié)點上運行Pod設置的容忍污點。
# oc describe pods oauth-openshift-69bb54fb9f-4bf6w | grep -i toleration Tolerations: node-role.kubernetes.io/master:NoSchedule
我們看到,oauth-openshift Pod因為包含了容忍污點,所以可以在Master節(jié)點上運行,如圖2-39所示。

圖2-39 oauth-openshift Pod在Master節(jié)點上運行
過濾步驟的最終結果通常是有資格運行Pod的節(jié)點候選短列表。在某些情況下不會過濾掉任何節(jié)點,這意味著Pod可以在任何節(jié)點上運行。當然也可能所有節(jié)點都被過濾掉,這意味著沒有合適的節(jié)點滿足先決條件,調度將失敗。
第二步:對節(jié)點候選短列表排優(yōu)先級。
節(jié)點候選短列表是使用多個Priorities進行評估的,這些Priorities和權限計算得出的總和為加權得分,得分較高的節(jié)點更適合運行Pod。
親和與反親和是重要的判斷標準。對Pod具有親和性的節(jié)點得分較高,而具有反親和性的節(jié)點得分較低。
第三步:選擇最適合的節(jié)點。
根據(jù)這些得分對節(jié)點候選短列表進行排序,并選擇得分最高的節(jié)點來運行Pod。如果多個節(jié)點具有相同的高分,則以循環(huán)方式選擇一個。
(4)修改Pod調度策略
通常默認調度策略和高級調度策略就能滿足大部分場景的需求,但也不排除我們需要根據(jù)實際的基礎設施拓撲自定義調度策略。接下來,我們將展示如何在OpenShift中修改Pod默認調度策略。
調度程序配置文件是一個JSON文件,必須命名為policy.cfg,用于指定調度程序將考慮的Predicates和Priorities。我們創(chuàng)建policy.cfg的JSON文件如下。
# cat policy.cfg { "kind" : "Policy", "apiVersion" : "v1", "predicates" : [ {"name" : "PodFitsHostPorts"}, {"name" : "PodFitsResources"}, {"name" : "NoDiskConflict"}, {"name" : "NoVolumeZoneConflict"}, {"name" : "MatchNodeSelector"}, {"name" : "MaxEBSVolumeCount"}, {"name" : "MaxAzureDiskVolumeCount"}, {"name" : "checkServiceAffinity"}, {"name" : "PodToleratesNodeNoExecuteTaints"}, {"name" : "MaxGCEPDVolumeCount"}, {"name" : "MatchInterPodAffinity"}, {"name" : "PodToleratesNodeTaints"}, {"name" : "HostName"} ], "priorities" : [ {"name" : "LeastRequestedPriority", "weight" : 1}, {"name" : "BalancedResourceAllocation", "weight" : 1}, {"name" : "ServiceSpreadingPriority", "weight" : 1}, {"name" : "EqualPriority", "weight" : 1} ] }
創(chuàng)建上述文件為Configmap。
# oc create configmap custom-scheduler-policy --from-file=policy.cfg -n openshift-config
編輯Scheduler Operator自定義資源(CR)以添加Configmap。
# oc patch scheduler cluster --type='merge' -p '{"spec":{"policy": {"name":"custom-scheduler-policy"}}}' --type=merge
對scheduler config資源進行更改后,請等待相關容器重新部署,這可能需要幾分鐘。在容器重新部署之前,新的調度程序不會生效。
7.OpenShift中的CRD和CR
在OpenShift中我們會大量使用CRD。為了方便讀者理解,本小節(jié)對此展開介紹。
CRD的全稱是Custom Resource Definition(自定義資源定義),CR的全稱是Custom Resource(自定義資源)。CRD本質上是Kubernetes的一種資源。在Kubernetes中一切都可視為資源,Kubernetes 1.7之后增加了使用CRD進行二次開發(fā)來擴展Kubernetes API,通過CRD我們可以向Kubernetes API中增加新資源類型,而不需要修改Kubernetes源碼。該功能大大提高了Kubernetes的擴展能力。當你創(chuàng)建一個新CRD時,Kubernetes API服務器將為你指定的每個版本創(chuàng)建一個新的RESTful資源路徑。CRD根據(jù)其作用域,可以分為Cluster級別和Namespace級別。
CRD在OpenShift中被大量使用,以OpenShift 4.6為例,CRD的數(shù)量多達上百個,這些CRD都是Cluster級別的。
# oc get crd | wc -l 108
那么,站在OpenShift角度,我們該怎樣使用CRD呢?下面舉例說明。
安裝OpenShift后內置的image registry是不會啟動的(只有Operator),如圖2-40所示。

圖2-40 查看項目中Pod
如果我們想讓OpenShift啟動image registry Pod,就需要修改image registry Operator對應crd:configs.imageregistry.operator.openshift.io。
# oc get crd |grep -i configs.imageregistry.operator.openshift.io configs.imageregistry.operator.openshift.io 2020-10-09T00:48:20Z
查看CRD的RESTful資源路徑(selfLink)。
# oc get configs.imageregistry.operator.openshift.io -o yaml |grep selfLink selfLink: /apis/imageregistry.operator.openshift.io/v1/configs/cluster
接下來,我們將CRD的managementState從Removed修改為Managed,同時也可以設置副本數(shù),這里我們保持1不變,如圖2-41所示。
# oc edit configs.imageregistry.operator.openshift.io cluster
修改后,我們發(fā)現(xiàn)image registry Pod被自動創(chuàng)建,如圖2-42所示。
也就是說,我們通過修改image registry Operator的CRD,完成了image registry的狀態(tài)設置和副本數(shù)修改。
在OpenShift中我們大量使用Cluster Operator(CO),每個Cluster Operator都有對應的CRD。例如我們查看ingress這個CO對應的CRD,如圖2-43所示。
在OpenShift的運維中少不了修改Cluster Operator對應的CRD,這類CRD都是以operator.openshift.io為后綴。例如,我們想要在OpenShift中啟用multus,就需要修改networks.operator.openshift.io這個CRD,增加如圖2-44所示內容。

圖2-41 修改CRD

圖2-42 image registry Pod自動創(chuàng)建

圖2-43 查看ingress CO對應的CRD

圖2-44 修改CRD
截至目前,我們介紹了CRD的作用。那么CR的作用是什么?
CR是CRD中的一個字段。我們在上文修改networks.operator.openshift.io CRD增加的內容,其實就是增加了一個macvlan-network的CR,而且將這個CR作用在Tomcat的Namespace上(而不是Cluster級別)。
- Offer來了:Java面試核心知識點精講(原理篇)
- 碼上行動:零基礎學會Python編程(ChatGPT版)
- Java程序設計與計算思維
- INSTANT Weka How-to
- UI智能化與前端智能化:工程技術、實現(xiàn)方法與編程思想
- Learning Selenium Testing Tools(Third Edition)
- Kubernetes進階實戰(zhàn)
- Hands-On JavaScript for Python Developers
- 大學計算機基礎
- Clojure High Performance Programming(Second Edition)
- C# 7.0本質論
- C語言程序設計
- Roslyn Cookbook
- Django 3 Web應用開發(fā)從零開始學(視頻教學版)
- C語言程序設計