系到生產(chǎn)運(yùn)維實(shí)戰(zhàn))
如果你是從 Kubernetes 社區(qū)轉(zhuǎn)到 OpenShift Container Platform 的第一次打開官方文檔大概率會看到一個高頻詞oc。我先說我的結(jié)論——oc不是kubectl的簡單改名它是 OpenShift Container Platform 面向使用者、開發(fā)者、運(yùn)維者統(tǒng)一暴露的命令行入口。這個工具值得你花一個下午認(rèn)真過一遍因?yàn)楹竺嫠腥粘2僮鲝牡卿浖?、?chuàng)建應(yīng)用、查看構(gòu)建、滾動發(fā)布到給用戶授權(quán)、節(jié)點(diǎn)維護(hù)幾乎都離不開它。我最早接手的一個集群環(huán)境比較特殊控制臺頁面有時因?yàn)榫W(wǎng)絡(luò)策略限制訪問不了但跳板機(jī)上只要配好了oc所有操作照常進(jìn)行。團(tuán)隊(duì)成員里有從kubectl轉(zhuǎn)過來的也有完全不懂 K8s 的通過oc反而更快上手了。這篇文章不打算寫成像文檔那樣逐條列命令而是按我實(shí)際使用的路徑來梳理先搞懂它和kubectl的關(guān)系再把環(huán)境準(zhǔn)備好接著跑通一個應(yīng)用上線的完整鏈路最后聊聊排障和運(yùn)維。這樣一套下來你至少能應(yīng)付 80% 的日常工作。1. 為什么 OpenShift 要單獨(dú)維護(hù)一把oc而不是直接用kubectl1.1 命令層面oc是kubectl的超集最直觀的理解方式是所有kubectl能做的事oc都能做。oc get pod、oc describe node、oc apply -f、oc logs這些命令的語法和輸出習(xí)慣和kubectl保持一致所以如果你已經(jīng)熟悉kubectl遷移成本幾乎為零。但oc不是只做了命令改名它額外擴(kuò)展了一批 OpenShift 特有資源的操作。比如oc get route查看路由規(guī)則oc get imagestream查看鏡像流oc get buildconfig查看構(gòu)建配置oc get deploymentconfig查看部署配置這些對象在標(biāo)準(zhǔn) K8s 里沒有對應(yīng)概念用kubectl查不到。剛轉(zhuǎn)換過來的同事最容易在這卡住明明oc get all里能看到一堆資源切回kubectl get all卻少了很多。不是集群出問題了而是kubectl根本不認(rèn)識這些擴(kuò)展 API 對象。1.2 對象層面OCP 在 K8s 之上多了一層應(yīng)用編排模型標(biāo)準(zhǔn) Kubernetes 的世界里應(yīng)用上線大概是這樣準(zhǔn)備鏡像 - 寫 Deployment YAML - 用 kubectl apply - 暴露 Service - 再搞 Ingress。這套流程沒問題但遇到源碼構(gòu)建、鏡像流跟蹤、自動觸發(fā)部署這類更貼近平臺的需求時就得自己組裝很多工具。OpenShift 把這套流程沉淀成了平臺原生的對象BuildConfig定義怎么從源碼或 Dockerfile 構(gòu)建出鏡像ImageStream相當(dāng)于一個鏡像倉庫的抽象層標(biāo)記某個鏡像的 tag 變化DeploymentConfig類似 Deployment但支持更豐富的部署策略和觸發(fā)器Route在 Ingress 之上封裝的 HTTP/HTTPS 路由對象配置更簡單oc把這些對象的操作都封裝進(jìn)了命令里。舉個例子你不用手動寫五個 YAML 再 Apply一個oc new-app就能把源碼地址、構(gòu)建策略、鏡像流、部署配置、服務(wù)暴露串聯(lián)起來。這種一條命令完成應(yīng)用上線的體驗(yàn)是kubectl給不了的。1.3 同一套 kubeconfig心智模型卻要切換oc底層用的是和kubectl一樣的 kubeconfig 文件認(rèn)證方式也兼容。你用oc login登錄后~/.kube/config會被更新之后kubectl也能用這份配置直接訪問集群的 K8s 原生資源。但注意這不代表兩者可以隨意混用。我見過有人把 Deployment 用kubectl建好后跑到 OpenShift 控制臺里發(fā)現(xiàn)它確實(shí)是已部署狀態(tài)但構(gòu)建歷史、鏡像流那一欄是空的。反過來用oc new-app建出來的 DeploymentConfigkubectl rollout status是看不懂的必須用oc rollout status。要我說日常順手用kubectl沒問題但凡是涉及 OpenShift 擴(kuò)展能力的操作養(yǎng)成先想一下這是不是 OCP 特有的功能是就用oc的習(xí)慣能省很多困惑。2. 環(huán)境準(zhǔn)備拿 CLI、登錄、項(xiàng)目切換這些基本功課2.1 從集群控制臺拿匹配版本的oc安裝oc最穩(wěn)妥的路徑不是從第三方網(wǎng)站隨便下載一個二進(jìn)制而是從你實(shí)際連接的集群控制臺頁面里拿。OpenShift 控制臺的右上角有一個命令行工具入口點(diǎn)開后能看到對應(yīng)這個集群版本的oc客戶端下載鏈接。為什么強(qiáng)調(diào)版本匹配因?yàn)榭蛻舳税姹咎禄蛱f都可能出現(xiàn) API 兼容問題。我就遇到過客戶端版本比集群新一個大版本的情況執(zhí)行某些命令直接報GroupVersionKind不匹配排查了半天最后發(fā)現(xiàn)是客戶端版本的問題。下載回來后是 tar.gz 壓縮包解壓后把oc可執(zhí)行文件放到 PATH 目錄里比如/usr/local/bin或者~/bin。驗(yàn)證是否可用oc version能看到類似于Client Version和Server Version兩行信息就說明客戶端能正常連接集群了。如果Server Version顯示不出來通常是你還沒登錄或者是網(wǎng)絡(luò)層面根本訪問不到集群的 API Server 地址。2.2 三種登錄方式用戶名密碼、token、service accountoc login是最常見的登錄入口適合交互式輸入用戶名密碼oc login https://api.example.openshift.com:6443 -u yourname -p yourpassword登錄成功后系統(tǒng)會提示你當(dāng)前所在的 project并把 context 信息寫入 kubeconfig。這種做法適合開發(fā)者在本地終端里用。如果你在用多因素認(rèn)證或者 SSO可能需要先通過瀏覽器拿 token 再粘貼回來。自動化腳本或 CI 環(huán)境里我更推薦直接用 token 登錄oc login --tokensha256~xxxxxxxx --serverhttps://api.example.openshift.com:6443Token 可以是你自己賬號的也可以是某個 ServiceAccount 的。用 ServiceAccount token 的好處是權(quán)限范圍明確便于審計而且不依賴某個人是否離職。但要注意別把 token 寫在腳本里直接提交到代碼倉庫我習(xí)慣用環(huán)境變量引用比如oc login --token$OC_TOKEN --server$OC_SERVER還有一種場景是集群剛裝完你需要用管理員賬號去初始化。這種可以直接用 kubeconfig 文件切換OpenShift 安裝生成的kubeadmin用戶配置文件通常在安裝目錄下把KUBECONFIG環(huán)境變量指過去即可export KUBECONFIG/path/to/kubeadmin.kubeconfig2.3 項(xiàng)目namespace的切換和身份確認(rèn)OpenShift 里的項(xiàng)目Project本質(zhì)上就是帶注解的 Namespace但它在用戶層面多了一點(diǎn)點(diǎn)隔離語義。用下面命令查看當(dāng)前項(xiàng)目oc project切換項(xiàng)目用oc project name新建項(xiàng)目用oc new-project name。注意oc new-project不僅會創(chuàng)建 Namespace還會自動幫你把當(dāng)前用戶綁定成該項(xiàng)目的管理員這個行為在標(biāo)準(zhǔn) K8s 里是沒有的。我在用這個命令時有個習(xí)慣每次登錄完先執(zhí)行一條oc whoami再執(zhí)行一條oc project。這不是多此一舉而是因?yàn)?OpenShift 環(huán)境里經(jīng)常要做身份切換有時候你以為自己在用管理員身份操作實(shí)際某個上下文中已經(jīng)切成了普通用戶不看這兩條命令直接部署很容易把應(yīng)用建到錯誤項(xiàng)目里或者因?yàn)闄?quán)限不足收到一串聽不懂的 403。3. 應(yīng)用上線主鏈路用oc new-app、start-build、rollout把業(yè)務(wù)跑起來3.1 推薦用oc new-app而不是手寫一堆 YAML 的場景我見過很多 K8s 背景的同行拿到 OpenShift 第一反應(yīng)是繼續(xù)寫 YAML然后oc apply -f。這沒有任何問題但如果你只是想把一個應(yīng)用快速跑起來特別是還在開發(fā)階段oc new-app的效率要高得多。oc new-app的基本邏輯是你給它一個源碼倉庫地址、一個鏡像名、或一組基礎(chǔ)鏡像它自動幫你生成對應(yīng)的 BuildConfig、DeploymentConfig、Service 等資源。舉個例子把一個 Node.js 源碼倉庫部署到集群oc new-app https://github.com/example/nodejs-demo.git --namenodejs-demo執(zhí)行完之后看輸出它會告訴你已經(jīng)創(chuàng)建了 imagestream、buildconfig、deploymentconfig、service 這些對象。然后你只需要手動創(chuàng)建一條 Route應(yīng)用就能用域名訪問了——當(dāng)然 Route 也可以讓oc new-app自動生成加上--as-deployment-config或指定--route相關(guān)參數(shù)即可。這個過程中 OpenShift 會先探測倉庫里的語言類型然后選擇對應(yīng)的 Source-to-ImageS2I構(gòu)建器。比如識別到 package.json 就用 Node.js 構(gòu)建器識別到 pom.xml 就用 Java 構(gòu)建器。如果倉庫結(jié)構(gòu)比較復(fù)雜可能探測不準(zhǔn)這時候你用--image參數(shù)明確指定鏡像反而更可靠oc new-app nodejs:20~https://github.com/example/nodejs-demo.git --namenodejs-demo注意nodejs:20是從 ImageStream 里引用的 tag~后面接源碼倉庫地址表示用這個基礎(chǔ)鏡像去構(gòu)建后面的源碼。3.2 構(gòu)建策略的選型S2I 還是 Dockerfileoc new-app默認(rèn)傾向使用 S2I 策略也就是把源碼注入基礎(chǔ)鏡像的固定目錄執(zhí)行構(gòu)建器腳本最后生成一個新的運(yùn)行時鏡像。這種方式對常見的 Node.js、Java、Python、Ruby 等語言很友好你不用維護(hù)自己的 Dockerfile平臺幫你處理依賴安裝和啟動命令。但遇到特殊需求比如要定制系統(tǒng)庫、要跑多階段構(gòu)建、要修改鏡像的非默認(rèn)啟動參數(shù)S2I 反而變得別扭。好在你可以在源碼倉庫根目錄放一個 Dockerfile然后顯式指定這次構(gòu)建走 Docker 策略oc new-app --strategydocker https://github.com/example/custom-runtime.git --namecustom-app或者先創(chuàng)建一個 BuildConfig再手動觸發(fā)。我個人的選型經(jīng)驗(yàn)是能用 S2I 就用 S2I特別是團(tuán)隊(duì)里沒有專人維護(hù)鏡像的場合一旦應(yīng)用對基礎(chǔ)環(huán)境有強(qiáng)定制要求果斷切 Docker 策略別勉強(qiáng)在 S2I 里塞各種 hack。S2I 最大的好處是構(gòu)建過程可重復(fù)、增量構(gòu)建快缺點(diǎn)是調(diào)試構(gòu)建器腳本的時候比較難受。Docker 策略則完全就是標(biāo)準(zhǔn)docker build的邏輯團(tuán)隊(duì)里懂的人更多。構(gòu)建開始后用oc logs -f實(shí)時看構(gòu)建日志oc logs -f bc/nodejs-demobc是 buildconfig 的簡寫。日志里能看到拉取基礎(chǔ)鏡像、注入源碼、執(zhí)行構(gòu)建步驟、推送鏡像到內(nèi)部倉庫的全過程。這一步是排查源碼依賴安裝問題的主要途徑比如 npm 私服地址配錯了、maven 倉庫連不通都會在這里暴露。構(gòu)建成功后鏡像會被推送到 OpenShift 內(nèi)部的 ImageStream 里。查看當(dāng)前鏡像流和 tagoc get imagestream oc describe imagestream nodejs-demo3.3 部署策略與版本回滾鏡像流更新后如果 DeploymentConfig 配置了 ImageChange 觸發(fā)器會自動發(fā)起一次新部署。查看部署狀態(tài)oc rollout status dc/nodejs-demo這里的dc是 deploymentconfig 的簡寫。OpenShift 支持兩種部署策略Rolling滾動更新和 Recreate先停舊再起新。默認(rèn)是 Rolling適合無狀態(tài)應(yīng)用Recreate 適合那些數(shù)據(jù)庫遷移類應(yīng)用舊版本必須完全退出才能啟動新版本避免同時存在新舊邏輯讀寫同一份數(shù)據(jù)。部署歷史保留多少份會影響你回滾時能選到哪個版本。查看歷史版本oc rollout history dc/nodejs-demo回滾到上一個版本oc rollout undo dc/nodejs-demo如果一切正常確認(rèn)當(dāng)前可用副本數(shù)oc get pods看到Running且 READY 列為1/1同時底下的oc rollout status輸出successfully rolled out這條鏈路就算跑通了。這里有個容易混淆的點(diǎn)如果你是用oc new-app自動生成的它是 DeploymentConfig如果你自己寫的 YAML 里用的是標(biāo)準(zhǔn) Deployment那回滾命令要換成kubectl rollout undo deployment/xxx。我在文中和團(tuán)隊(duì)講解時都會強(qiáng)調(diào)先確認(rèn)對象類型再選命令不要想當(dāng)然。3.4 把服務(wù)暴露成集群外可訪問的地址構(gòu)建和部署都完成后還需要解決外面怎么訪問的問題。OpenShift 使用 Route 對象對外暴露 HTTP/HTTPS 服務(wù)。最簡單的方式oc expose service/nodejs-demo它會自動用當(dāng)前項(xiàng)目名和應(yīng)用名生成一個默認(rèn)域名。查看生成的路由oc get route如果你想自定義域名路徑或者配置 TLS 證書可以導(dǎo)出現(xiàn)有對象再修改oc get route nodejs-demo -o yaml route.yaml然后把spec.host改成自己的域名需要 HTTPS 的話可以配置spec.tls.termination: edge、insecureEdgeTerminationPolicy: Redirect最后oc apply -f route.yaml如果域名不是集群默認(rèn)的泛域名記得去 DNS 側(cè)加一條解析記錄指向集群的入口點(diǎn)。這一步經(jīng)常被忽略導(dǎo)致 Route 建好了curl 卻一直超時。4. 故障排查鏈路從日志、事件到 debug 容器4.1 日志oc logs的正確打開方式應(yīng)用跑起來后看日志是日常操作里頻率最高的。最基礎(chǔ)的當(dāng)然是oc logs pod/nodejs-demo-1-abcd但很多時候 Pod 名字是自動生成的隨機(jī)后綴敲起來并不方便。你完全可以直接用資源名oc logs deploymentconfig/nodejs-demo或者直接用dc/前綴oc logs dc/nodejs-demo如果你確定目前在跑的只有一個 Pod這種寫法會直接給你日志輸出。Pod 內(nèi)有多個容器時必須用-c指定容器名oc logs pod/nodejs-demo-1-abcd -c my-container調(diào)試時搭配參數(shù)很有用。實(shí)時跟蹤日志用-f只看最近 200 行用--tail200只看最近 10 分鐘用--since10m。oc logs dc/nodejs-demo --tail200 -f有些啟動失敗的場景下Pod 反復(fù)重啟你看到的日志是上一個實(shí)例留下的殘留內(nèi)容。這時候加--previous參數(shù)能看到容器在崩潰前最后輸出oc logs pod/nodejs-demo-1-abcd --previous這個參數(shù)在排查CrashLoopBackOff時特別好使。4.2 事件與 describe快速定位 ImagePullBackOff / CrashLoopBackOffPod 起不來的時候oc get pods看到的通常是ImagePullBackOff、CrashLoopBackOff、Pending這類狀態(tài)。先看事件oc get events --sort-by.lastTimestamp | tail -20事件信息可能比較雜如果你心里已經(jīng)有明確的 Pod 名用oc describe更直接oc describe pod/nodejs-demo-1-abcd輸出里注意看兩個部分Events部分明確告訴你發(fā)生了什么。比如拉取鏡像失敗底下會寫Failed to pull image以及具體錯誤碼調(diào)度失敗會寫0/3 nodes are available。Conditions部分描述 Pod 當(dāng)前各條件的通過情況比如PodScheduled是否是 True。以ImagePullBackOff為例常見的根因是國內(nèi)環(huán)境拉取外部鏡像超時、鏡像 tag 寫錯、或者內(nèi)部鏡像倉庫沒有開放訪問。定位思路先看事件里的錯誤信息再查它實(shí)際拉取的鏡像地址是哪一行。如果用的是 S2I 構(gòu)建很可能是 BuildConfig 里配置的output.to指向了一個不存在的 ImageStreamTag。CrashLoopBackOff則意味著容器能啟動但馬上退出排查路徑通常是oc logs --previous看最后輸出 - 查看啟動命令和探針配置 - 驗(yàn)證依賴的服務(wù)是否就緒。我曾經(jīng)遇到過一次其實(shí)只是容器里的進(jìn)程綁定端口和 Service 暴露端口不一致日志里卻一直顯示莫名其妙的內(nèi)存錯誤這時候用oc debug進(jìn)去看實(shí)際情況就特別必要。4.3oc debug給故障 Pod 開一個同款副本oc debug是我排查問題時的王牌命令它和kubectl exec不太一樣。直接oc debug pod/xxx會創(chuàng)建一個和當(dāng)前 Pod 配置幾乎一樣的臨時副本但不會啟動原來的容器而是用調(diào)試鏡像啟動一個 shell。這樣做的好處是即使原容器已經(jīng)崩潰、無法exec進(jìn)去你依然可以進(jìn)到 Pod 的運(yùn)行時環(huán)境里檢查文件、進(jìn)程、網(wǎng)絡(luò)。oc debug pod/nodejs-demo-1-abcd進(jìn)去之后你會發(fā)現(xiàn)自己是通過一個 debug 容器在操作Pod 里的其他容器文件系統(tǒng)需要手動掛載路徑才能訪問。訪問節(jié)點(diǎn)文件系統(tǒng)時用chroot /host這個命令在排查節(jié)點(diǎn)級問題時非常有用比如檢查節(jié)點(diǎn)上的磁盤占用、清理殘留鏡像。有一個坑要提醒oc debug創(chuàng)建的調(diào)試 Pod 是會占用臨時資源的而且有些集群開啟了 Pod Security 策略可能導(dǎo)致 debug Pod 創(chuàng)建失敗。要記得用完刪掉別留下一堆調(diào)試用 Pod 占著調(diào)度資源。4.4 路由層跟進(jìn)的檢查順序?qū)ν庠L問不通時我習(xí)慣按順序排查Route 是否存在oc get route確認(rèn) Host、Path、Service 名、端口都正確。Endpoint 是否正常oc get endpoints確認(rèn) Service 后端 Pod 地址有值。如果 Endpoint 列表為空說明 Service 的 selector 和 Pod 標(biāo)簽不匹配。Router 是否運(yùn)行OpenShift 的入口流量默認(rèn)由 Ingress Operator 和 Router 處理。查看相關(guān) Podoc get pods -n openshift-ingress如果 Router Pod 異常外部流量自然進(jìn)不來。Router 日志里也經(jīng)常能翻到 TLS 證書失效、后端連接被拒這類的線索。 4.Service 是否工作如果 Pod 里能 curl 到 Service 域名說明鏈路內(nèi)部正常如果 Pod 里也 curl 不通那就是 Service 配置或 Pod 端口映射的問題。這套鏈路走下來大部分域名訪問不了的問題都能定位到具體環(huán)節(jié)。5. 運(yùn)維視角oc adm系列命令和權(quán)限管理的實(shí)操心法5.1 節(jié)點(diǎn)維護(hù)三部曲cordon、drain、uncordon如果你需要重啟某臺節(jié)點(diǎn)機(jī)器或者給節(jié)點(diǎn)打補(bǔ)丁千萬別直接關(guān)機(jī)。先把這個節(jié)點(diǎn)標(biāo)記為不可調(diào)度oc adm cordon node-namecordon 之后新調(diào)度的 Pod 不會跑到這個節(jié)點(diǎn)上但已經(jīng)在節(jié)點(diǎn)上運(yùn)行的 Pod 不會自動挪走。接下來執(zhí)行 drain把已有 Pod 遷移到其他節(jié)點(diǎn)oc adm drain node-name --ignore-daemonsets --delete-emptydir-data--ignore-daemonsets是必需的因?yàn)?DaemonSet 類 Pod 本來就應(yīng)該留在節(jié)點(diǎn)上--delete-emptydir-data要根據(jù)業(yè)務(wù)情況決定如果節(jié)點(diǎn)上用了 emptyDir 且有臨時數(shù)據(jù)刪除它就意味著清掉這些數(shù)據(jù)。維護(hù)完成后讓節(jié)點(diǎn)恢復(fù)調(diào)度oc adm uncordon node-name我還習(xí)慣在 drain 之前確認(rèn)一下節(jié)點(diǎn)上有哪些關(guān)鍵 Pod以及它們的 PDBPodDisruptionBudget狀態(tài)。沒有 PDB 的 Pod 在 drain 時會直接強(qiáng)制驅(qū)逐可能導(dǎo)致服務(wù)短暫不可用。有一個 PDB 保護(hù)的應(yīng)用drain 時會被優(yōu)雅地滾動遷移。5.2 常用權(quán)限操作add-role-to-user 與集群角色OpenShift 的 RBAC 和 K8s 一致但oc提供了一些更便捷的封裝命令。給某個用戶授予某個項(xiàng)目的 view 權(quán)限oc adm policy add-role-to-user view username -n project-name把用戶提升為項(xiàng)目管理員oc adm policy add-role-to-user admin username -n project-name如果需要集群級權(quán)限用oc adm policy add-cluster-role-to-user cluster-admin username這個命令給出的權(quán)限極大操作前一定確認(rèn)是你真正要授權(quán)的對象。我在生產(chǎn)環(huán)境里很少直接給 cluster-admin除非是平臺運(yùn)維團(tuán)隊(duì)的核心成員。平時給到特定 Namespace 的 admin 權(quán)限已經(jīng)覆蓋絕大多數(shù)需求。查看某用戶當(dāng)前權(quán)限oc policy can-i create deployment -n project-name --asusername這條命令在寫自動化權(quán)限審批流程時特別有用可以提前驗(yàn)證某用戶是否具備執(zhí)行某操作的資格。新版本的 OpenShift 里部分舊的oc adm policy命令會提示改用統(tǒng)一的 RBAC API 管理但老集群上這些命令依然能用。作為運(yùn)維兩套寫法都最好了解。5.3 巡檢與集群診斷oc adm must-gather、top集群出問題需要報工單或者給平臺團(tuán)隊(duì)提供現(xiàn)場數(shù)據(jù)時oc adm must-gather是標(biāo)準(zhǔn)的取證命令oc adm must-gather它會收集集群里的大量診斷信息包括事件、日志、資源定義、Operator 狀態(tài)等打包成一個壓縮目錄。這個命令執(zhí)行時間可能比較長數(shù)據(jù)量也大但它是排查集群級問題的關(guān)鍵材料。我每次執(zhí)行完會順手把產(chǎn)物目錄名改得帶有日期和集群標(biāo)識方便后續(xù)追溯??焖倏垂?jié)點(diǎn)和 Pod 的資源占用oc adm top nodes oc adm top pods -n project-nameoc adm top pods的結(jié)果依賴 metrics-server如果集群沒有安裝監(jiān)控棧可能為空。不過 OpenShift 通常默認(rèn)自帶監(jiān)控所以絕大多數(shù)環(huán)境都能正常出數(shù)據(jù)。日常巡檢腳本里我一般把這三樣組合起來oc get nodes看節(jié)點(diǎn)狀態(tài)、oc get clusteroperators看各組件健康、oc get co發(fā)現(xiàn)問題后再用 must-gather 深入。6. 忘不了的教訓(xùn)幾個讓老手也翻車的細(xì)節(jié)6.1new-app的語言探測有時過于自作主張oc new-app的自動探測很方便但它不是萬能的。有一次我給一個 Python 項(xiàng)目執(zhí)行oc new-app因?yàn)閭}庫里恰好還有一個不相關(guān)的pom.xml結(jié)果平臺把項(xiàng)目識別成了 Java構(gòu)建了半天依賴直接失敗。后來我都是先檢查倉庫根目錄確認(rèn)語言特征明確后再交給oc new-app處理。如果倉庫結(jié)構(gòu)本身就容易誤導(dǎo)探測干脆顯式指定--image或者--strategy別把選擇權(quán)完全交給自動探測。另一個相關(guān)問題是oc new-app如果給的不是源碼倉庫而是純鏡像名它會直接創(chuàng)建 DeploymentConfig 并啟動鏡像而不經(jīng)過構(gòu)建。這個行為有時候有驚喜快速部署一個現(xiàn)成鏡像但很多時候用戶本意是希望走構(gòu)建流程結(jié)果資源類型完全不同了。執(zhí)行完oc new-app后養(yǎng)成習(xí)慣看一眼輸出確認(rèn)有沒有出現(xiàn) buildconfig 對象。6.2 DeploymentConfig 和 Deployment 的 rollout 行為差異前面提到過一次這個坑值得再展開。OpenShift 里同時存在DeploymentConfig和Deployment兩種部署對象觸發(fā)更新和回滾的命令行為不完全一樣對 DeploymentConfig用oc rollout status dc/xxx、oc rollout undo dc/xxx對 Deployment用oc rollout status deployment/xxx或kubectl rollout status deployment/xxx如果搞混了最典型的報錯是Error from server (NotFound): deploymentconfigs.apps.openshift.io xxx not found。你明明知道資源存在命令卻找不到就是因?yàn)橘Y源類型寫錯了。用oc get all查看所有工作負(fù)載時注意區(qū)分deploymentconfig.apps.openshift.io和deployment.apps兩列。另外DeploymentConfig 的部署歷史默認(rèn)保留 10 個版本Deployment 的revisionHistoryLimit默認(rèn)也是 10。如果你期待回滾到很久以前的版本可能需要先調(diào)整保留數(shù)量否則歷史版本早被清理了。6.3 客戶端版本不匹配和 TLS 跳過的取舍我在前面提過從控制臺下載與集群版本匹配的oc。這里再補(bǔ)一個細(xì)節(jié)如果你連接的是一個版本比較舊的集群新版oc登錄時可能會提示配置了不兼容的 API 組或者一些命令報the server could not find the requested resource。這時候優(yōu)先考慮是不是版本匹配問題。TLS 證書方面很多測試環(huán)境沒有接入正式 CA用oc login時會提示證書不受信任。有些人習(xí)慣加--insecure-skip-tls-verifytrue跳過校驗(yàn)這確實(shí)能快速通過認(rèn)證但生產(chǎn)環(huán)境不建議這么做。證書校驗(yàn)失敗背后往往意味著中間人風(fēng)險或者集群入口證書配置有誤。正確的做法是把集群的 CA 證書下載到本地并配置到客戶端信任鏈里。如果只是臨時連測試環(huán)境跳過校驗(yàn)可以接受但要有意識確保這是短期的測試行為。我還踩過一次比較低級的坑登錄腳本里把--insecure-skip-tls-verifytrue寫死了后來這個腳本被復(fù)制到生產(chǎn)環(huán)境使用導(dǎo)致生產(chǎn)集群跳過證書校驗(yàn)了很長時間?,F(xiàn)在我的做法是這類開關(guān)參數(shù)通過環(huán)境變量單獨(dú)傳遞不同環(huán)境各寫各的配置絕不在腳本里寫死。6.4 我給團(tuán)隊(duì)沉淀的常用命令速查表最后把我平時最常用的命令整理成一張表內(nèi)容是根據(jù)我這邊的維護(hù)場景總結(jié)的你可以直接抄走放到團(tuán)隊(duì)文檔里。場景命令說明查看當(dāng)前用戶oc whoami確認(rèn)身份防止上下文切換錯亂查看當(dāng)前項(xiàng)目oc project確認(rèn)當(dāng)前所在 Namespace/Project切換項(xiàng)目oc project name切換后建議再跑一次oc whoami復(fù)核查看所有資源oc get all查看項(xiàng)目內(nèi)各類資源概覽查看 Pod 詳情oc describe pod/name事件和條件都在這里實(shí)時日志oc logs dc/name -f --tail100適合跟蹤部署過程查看崩潰前日志oc logs pod/name --previousCrashLoopBackOff 排查利器創(chuàng)建應(yīng)用oc new-app repo --nameapp自動生成構(gòu)建/部署/服務(wù)資源手動觸發(fā)構(gòu)建oc start-build bc/name重新執(zhí)行一次構(gòu)建流程查看構(gòu)建日志oc logs -f bc/name構(gòu)建失敗時必用查看部署狀態(tài)oc rollout status dc/name等待部署完成回滾部署oc rollout undo dc/name回滾到上一個可用版本暴露服務(wù)oc expose service/name創(chuàng)建默認(rèn) Route查看事件oc get events --sort-by.lastTimestamp全局事件排查進(jìn)入調(diào)試副本oc debug pod/name容器崩潰也能進(jìn)去查節(jié)點(diǎn)維護(hù)oc adm cordon/drain/uncordon node三步走別跳步驟用戶授權(quán)oc adm policy add-role-to-user role user -n project按最小權(quán)限給集群診斷收集oc adm must-gather提交平臺團(tuán)隊(duì)前先跑這個這張表沒有覆蓋所有命令但日常 90% 的操作都夠了。最后分享一個小習(xí)慣。我在本地的 shell 配置里放了幾個函數(shù)比如ocp-login-test、ocp-login-prod、ocp-desc分別用來切換不同環(huán)境的登錄和快速描述資源。這樣不僅避免重復(fù)敲一長串參數(shù)還能防止在測試環(huán)境配好的腳本不小心在生產(chǎn)環(huán)境執(zhí)行的問題。配置方式很簡單就是普通的 shell 函數(shù)加別名但用起來確實(shí)能減少很多低級失誤。不同團(tuán)隊(duì)管理規(guī)模不一樣你可以按自己的集群數(shù)量和環(huán)境命名習(xí)慣來做這層封裝。總的原則只有一個能讓命令少敲一半的封裝都值得做能把環(huán)境區(qū)分開的封裝必須做。