雖然 Docker 已經很強大了,可是在實際使用上仍是有諸多不便,好比集羣管理、資源調度、文件管理等等。那麼在這樣一個百花齊放的容器時代涌現出了不少解決方案,好比 Mesos、Swarm、Kubernetes 等等,其中谷歌開源的 Kubernetes 是做爲老大哥的存在。html
kubernetes 已經成爲容器編排領域的王者,它是基於容器的集羣編排引擎,具有擴展集羣、滾動升級回滾、彈性伸縮、自動治癒、服務發現等多種特性能力。node
Kubernetes 的出現不只主宰了容器編排的市場,更改變了過去的運維方式,不只將開發與運維之間邊界變得更加模糊,並且讓 DevOps 這一角色變得更加清晰,每個軟件工程師均可以經過 Kubernetes 來定義服務之間的拓撲關係、線上的節點個數、資源使用量而且可以快速實現水平擴容、藍綠部署等在過去複雜的運維操做。mysql
主要介紹學習一些什麼知識linux
傳統的客戶端服務端架構nginx
Kubernetes 遵循很是傳統的客戶端/服務端的架構模式,客戶端能夠經過 RESTful 接口或者直接使用 kubectl 與 Kubernetes 集羣進行通訊,這二者在實際上並無太多的區別,後者也只是對 Kubernetes 提供的 RESTful API 進行封裝並提供出來。每個 Kubernetes 集羣都是由一組 Master 節點和一系列的 Worker 節點組成,其中 Master 節點主要負責存儲集羣的狀態併爲 Kubernetes 對象分配和調度資源。git
做爲管理集羣狀態的 Master 節點,它主要負責接收客戶端的請求,安排容器的執行而且運行控制循環,將集羣的狀態向目標狀態進行遷移。Master 節點內部由下面三個組件構成:web
API Server: 負責處理來自用戶的請求,其主要做用就是對外提供 RESTful 的接口,包括用於查看集羣狀態的讀請求以及改變集羣狀態的寫請求,也是惟一一個與 etcd 集羣通訊的組件。面試
etcd: 是兼具一致性和高可用性的鍵值數據庫,能夠做爲保存 Kubernetes 全部集羣數據的後臺數據庫。redis
Scheduler: 主節點上的組件,該組件監視那些新建立的未指定運行節點的 Pod,並選擇節點讓 Pod 在上面運行。調度決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬件/軟件/策略約束、親和性和反親和性規範、數據位置、工做負載間的干擾和最後時限。算法
controller-manager: 在主節點上運行控制器的組件,從邏輯上講,每一個控制器都是一個單獨的進程,可是爲了下降複雜性,它們都被編譯到同一個可執行文件,並在一個進程中運行。這些控制器包括:節點控制器(負責在節點出現故障時進行通知和響應)、副本控制器(負責爲系統中的每一個副本控制器對象維護正確數量的 Pod)、端點控制器(填充端點 Endpoints 對象,即加入 Service 與 Pod))、服務賬戶和令牌控制器(爲新的命名空間建立默認賬戶和 API 訪問令牌)。
其餘的 Worker 節點實現就相對比較簡單了,它主要由 kubelet 和 kube-proxy 兩部分組成。
kubelet: 是工做節點執行操做的 agent,負責具體的容器生命週期管理,根據從數據庫中獲取的信息來管理容器,並上報 pod 運行狀態等。
kube-proxy: 是一個簡單的網絡訪問代理,同時也是一個 Load Balancer。它負責將訪問到某個服務的請求具體分配給工做節點上同一類標籤的 Pod。kube-proxy 實質就是經過操做防火牆規則(iptables或者ipvs)來實現 Pod 的映射。
Container Runtime: 容器運行環境是負責運行容器的軟件,Kubernetes 支持多個容器運行環境: Docker、 containerd、cri-o、 rktlet 以及任何實現 Kubernetes CRI(容器運行環境接口)。
主要介紹關於 K8s 的一些基本概念
主要由如下幾個核心組件組成:
除了核心組件,還有一些推薦的插件:
以上內容參考連接: www.escapelife.site/posts/2c421…
安裝v1.16.0版本,居然成功了。記錄在此,避免後來者踩坑。
本篇文章,安裝大步驟以下:
詳細安裝步驟參考:CentOS 搭建 K8S,一次性成功,收藏了! 集羣安裝教程請參考:全網最新、最詳細基於V1.20版本,無坑部署最小化 K8S 集羣教程
Pod 就是最小而且最簡單的 Kubernetes 對象
Pod、Service、Volume 和 Namespace 是 Kubernetes 集羣中四大基本對象,它們可以表示系統中部署的應用、工做負載、網絡和磁盤資源,共同定義了集羣的狀態。Kubernetes 中不少其餘的資源其實只對這些基本的對象進行了組合。
詳細介紹請參考:Kubernetes 之 Pod 實現原理
Kuternetes 企業級 Docker 私有倉庫 Harbor 工具。 Harbor 的每一個組件都是以 Docker 容器的形式構建的,使用 Docker Compose 來對它進行部署。用於部署 Harbor 的 Docker Compose 模板位於 /Deployer/docker-compose.yml 中,其由 5 個容器組成,這幾個容器經過 Docker link 的形式鏈接在一塊兒,在容器之間經過容器名字互相訪問。對終端用戶而言,只須要暴露 Proxy(即Nginx) 的服務端口便可。
詳細介紹與搭建步驟請參考:企業級環境中基於 Harbor 搭建
YAML 是一種很是簡潔/強大/專門用來寫配置文件的語言!
YAML 全稱是 」YAML Ain’t a Markup Language」 的遞歸縮寫,該語言的設計參考了 JSON / XML 和 SDL 等語言,強調以數據爲中心,簡潔易讀,編寫簡單。
學過編程的人理解起來應該很是容易
推薦給你們一篇文章:Kubernetes 之 YAML 語法,這篇文章介紹的很是詳細,有不少例子說明。
K8S 中全部的內容都抽象爲了資源,資源實例化以後就叫作對象。
在 Kubernetes 系統中,Kubernetes 對象是持久化的實體,Kubernetes 使用這些實體去表示整個集羣的狀態。特別地,它們描述了以下信息:
Kubernetes 對象是 「目標性記錄」 —— 一旦建立對象,Kubernetes 系統將持續工做以確保對象存在。經過建立對象,本質上是在告知 Kubernetes 系統,所須要的集羣工做負載看起來是什麼樣子的,這就是 Kubernetes 集羣的指望狀態。
Kubernetes 資源控制器配置文件的編寫是學習 K8S 的重中之重!
資源配額控制器確保了指定的資源對象始終不會超過配置的資源,可以有效的下降整個系統宕機的機率,加強系統的魯棒性,對整個集羣的穩定性有很是重要的做用。
Kubernetes 中爲了實現服務實例間的負載均衡和不一樣服務間的服務發現,創造了 Service 對象,同時又爲從集羣外部訪問集羣建立了 Ingress 對象。
咱們都知道傳統的 SVC 只支持四層上面的代碼,而對於七層上的代碼而無能爲力。好比:咱們使用 K8S 集羣對外提供 HTTPS 的服務,爲了方便和便捷,咱們須要在對外的 Nginx 服務上面配置 SSL 加密,可是將請求發送給後端服務的時候,進行證書卸載的操做,後續都是用 HTTP 的協議進行處理。而面對此問題,K8S 中給出了使用 Ingress (K8S在1.11版本中推出了)來進行處理。
更多詳細內容請參閱:Kubernetes 之 Ingress 服務,介紹關於 Ingress 服務的安裝方式,配置關於 Ingress 服務的 HTTP 代理訪問,介紹 Ingress 服務的 BasicAuth 認證方式,介紹 Ingress 的進行規則重寫的方式。
在以前的文章中,咱們已經知道了不少 K8S 中的組件了,包括資源控制器等。在資源控制器中,咱們說到了 StatefulSet 這個控制器組件,其專門爲了有狀態服務而生的,而對應的存儲要存放到哪裏呢?
介紹 K8S 中常見的存儲機制可讓咱們所使用的:Kubernetes 之數據存儲
有這樣一個需求,就是集羣中多臺服務的配置是不一致的。這就致使資源分配並非均勻的,好比咱們須要有些服務節點用來運行計算密集型的服務,而有些服務節點來運行須要大量內存的服務。而在 k8s 中固然也配置了相關服務來處理上述的問題,那就是 Scheduler。
Scheduler 是 kubernetes 的調度器,主要的任務是把定義的 Pod 分配到集羣的節點上。聽起來很是簡單,但有不少要考慮的問題:
Scheduler 是做爲單獨的程序運行的,啓動以後會一直堅挺 API Server,獲取 PodSpec.NodeName 爲空的 Pod,對每一個 Pod 都會建立一個 binding,代表該 Pod 應該放到哪一個節點上。
詳細的介紹請參考:Kubernetes 之集羣調度
kubectl 是 Kubernetes 自帶的客戶端,能夠用它來直接操做 Kubernetes 集羣。
平常在使用 Kubernetes 的過程當中,kubectl 工具多是最經常使用的工具了,因此當咱們花費大量的時間去研究和學習 Kuernetes 的時候,那麼咱們就很是有必要去了解下如何高效的使用它了。
從用戶角度來講,kubectl 就是控制 Kubernetes 的駕駛艙,它容許你執行全部可能的 Kubernetes 操做;從技術角度來看,kubectl 就是 Kubernetes API 的一個客戶端而已。
Kubernetes API 是一個 HTTP REST API 服務,該 API 服務纔是 Kubernetes 的真正用到的用戶接口,因此 Kubernetes 經過該 API 進行實際的控制。這也就意味着每一個 Kubernetes 的操做都會經過 API 端點暴露出去,固然也就能夠經過對這些 API 端口進行 HTTP 請求來執行相應的操做。因此,kubectl 最主要的工做就是執行 Kubernetes API 的 HTTP 請求。
get #顯示一個或多個資源
describe #顯示資源詳情
create #從文件或標準輸入建立資源
update #從文件或標準輸入更新資源
delete #經過文件名、標準輸入、資源名或者 label 刪除資源
log #輸出 pod 中一個容器的日誌
rolling-update #對指定的 RC 執行滾動升級
exec #在容器內部執行命令
port-forward #將本地端口轉發到 Pod
proxy #爲 Kubernetes API server 啓動代理服務器
run #在集羣中使用指定鏡像啓動容器
expose #將 SVC 或 pod 暴露爲新的 kubernetes service
label #更新資源的 label
config #修改 kubernetes 配置文件
cluster-info #顯示集羣信息
api-versions #以」組/版本」的格式輸出服務端支持的 API 版本
version #輸出服務端和客戶端的版本信息
help #顯示各個命令的幫助信息
ingress-nginx #管理 ingress 服務的插件(官方安裝和使用方式)
複製代碼
# Kubectl自動補全
$ source <(kubectl completion zsh)
$ source <(kubectl completion bash)
# 顯示合併後的 kubeconfig 配置
$ kubectl config view
# 獲取pod和svc的文檔
$ kubectl explain pods,svc
複製代碼
# yaml
kubectl create -f xxx-rc.yaml
kubectl create -f xxx-service.yaml
# json
kubectl create -f ./pod.json
cat pod.json | kubectl create -f -
# yaml2json
kubectl create -f docker-registry.yaml --edit -o json
複製代碼
kubectl create -f xxx-service.yaml -f xxx-rc.yaml
複製代碼
kubectl create -f <目錄>
複製代碼
kubectl create -f https://git.io/vPieo
複製代碼
kubectl get nodes
kubectl get namespace
複製代碼
# 查看子命令幫助信息
kubectl get --help
# 列出默認namespace中的全部pod
kubectl get pods
# 列出指定namespace中的全部pod
kubectl get pods --namespace=test
# 列出全部namespace中的全部pod
kubectl get pods --all-namespaces
# 列出全部pod並顯示詳細信息
kubectl get pods -o wide
kubectl get replicationcontroller web
kubectl get -k dir/
kubectl get -f pod.yaml -o json
kubectl get rc/web service/frontend pods/web-pod-13je7
kubectl get pods/app-prod-78998bf7c6-ttp9g --namespace=test -o wide
kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}
# 列出該namespace中的全部pod包括未初始化的
kubectl get pods,rc,services --include-uninitialized
複製代碼
kubectl get rc
複製代碼
# 查看所有deployment
kubectl get deployment
# 列出指定deployment
kubectl get deployment my-app
複製代碼
kubectl get svc
kubectl get service
複製代碼
kubectl get pods -n default
kubectl get pods --all-namespace
複製代碼
kubectl describe pods/nginx
kubectl describe pods my-pod
kubectl describe -f pod.json
複製代碼
kubectl describe nodes c1
複製代碼
kubectl describe pods <rc-name>
複製代碼
# 滾動更新 pod frontend-v1
kubectl rolling-update frontend-v1 -f frontend-v2.json
# 更新資源名稱並更新鏡像
kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
# 更新 frontend pod 中的鏡像
kubectl rolling-update frontend --image=image:v2
# 退出已存在的進行中的滾動更新
kubectl rolling-update frontend-v1 frontend-v2 --rollback
# 強制替換; 刪除後從新建立資源; 服務會中斷
kubectl replace --force -f ./pod.json
# 添加標籤
kubectl label pods my-pod new-label=awesome
# 添加註解
kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq
複製代碼
# 部分更新節點
kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'
# 更新容器鏡像;spec.containers[*].name 是必須的,由於這是合併的關鍵字
kubectl patch pod valid-pod -p \
'{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
複製代碼
# Scale a replicaset named 'foo' to 3
kubectl scale --replicas=3 rs/foo
# Scale a resource specified in "foo.yaml" to 3
kubectl scale --replicas=3 -f foo.yaml
# If the deployment named mysql's current size is 2, scale mysql to 3
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql
# Scale multiple replication controllers
kubectl scale --replicas=5 rc/foo rc/bar rc/baz
複製代碼
# yaml文件名字按照你建立時的文件一致
kubectl delete -f xxx.yaml
複製代碼
kubectl delete pods -l name=<label-name>
複製代碼
kubectl delete services -l name=<label-name>
複製代碼
kubectl delete pods,services -l name=<label-name>
複製代碼
kubectl delete pods --all
kubectl delete service --all
kubectl delete deployment --all
複製代碼
在編輯器中編輯任何 API 資源
# 編輯名爲docker-registry的service
kubectl edit svc/docker-registry
複製代碼
在寄主機上,不進入容器直接執行命令
kubectl exec mypod -- date
kubectl exec mypod --namespace=test -- date
複製代碼
kubectl exec mypod -c ruby-container -- date
複製代碼
kubectl exec mypod -c ruby-container -it -- bash
複製代碼
# 不實時刷新kubectl logs mypod
kubectl logs mypod --namespace=test
複製代碼
kubectl logs -f mypod -c ruby-container
複製代碼
Kubernetes正在不斷加快在雲原生環境的應用,但如何以統1、安全的方式對運行於任何地方的Kubernetes集羣進行管理面臨着挑戰,而有效的管理工具可以大大下降管理的難度。
k9s是基於終端的資源儀表板。它只有一個命令行界面。不管在Kubernetes儀表板Web UI上作什麼,均可以在終端使用K9s儀表板工具進行相同的操做。k9s持續關注Kubernetes集羣,並提供命令以使用集羣上定義的資源。
使用Kubernetes的一些策略,在安全性、監控、網絡、治理、存儲、容器生命週期管理和平臺選擇方面應用最佳實踐。下面讓咱們來看看Kubernetes的一些生產最佳實踐。在生產中運行Kubernetes並不容易; 有如下幾個方面須要注意。
管理大型分佈式系統可能會很複雜,特別是當出現問題時,咱們沒法及時獲得通知。爲了確保應用實例正常工做,設置Kubernetes健康檢查相當重要。
經過建立自定義運行健康檢查,能夠有效避免分佈式系統中殭屍服務運行,具體能夠根據環境和須要對其進行調整。
就緒探針的目的是讓Kubernetes知道該應用是否已經準備好爲流量服務。Kubernetes將始終確保準備就緒探針經過以後開始分配服務,將流量發送到Pod。
你怎麼知道你的應用程序是活的仍是死的?存活探針可讓你作到這一點。若是你的應用死了,Kubernetes會移除舊的Pod並用新Pod替換它。
爲單個容器指定資源請求和限制是一個很好的實踐。另外一個好的實踐是將Kubernetes環境劃分爲不一樣團隊、部門、應用程序和客戶機的獨立名稱空間。
Kubernetes資源使用指的是容器/pod在生產中所使用的資源數量。
所以,密切關注pods的資源使用狀況是很是重要的。一個明顯的緣由是成本,由於越高的資源利用證實越少的資源浪費。
Ops團隊一般但願優化和最大化pods消耗的資源百分比。資源使用狀況是Kubernetes環境實際優化程度的指標之一。
您能夠認爲優化後的Kubernetes環境中運行的容器的平均CPU等資源利用率是最優的。
RBAC表明基於角色的訪問控制。它是一種用於限制系統/網絡上的用戶和應用程序的訪問和准入的方法。!
他們從Kubernetes 1.8版本引入了RBAC。使用rbac.authorization.k8s RBAC用於建立受權策略。
在Kubernetes中,RBAC用於受權,使用RBAC,您將可以授予用戶、賬戶、添加/刪除權限、設置規則等權限。所以,它基本上爲Kubernetes集羣添加了額外的安全層。RBAC限制誰能夠訪問您的生產環境和集羣。
生產級Kubernetes基礎設施一般須要考慮某些關鍵方面,例如高可用性、多主機、多etcd Kubernetes集羣等。此類集羣的配置一般涉及到Terraform或Ansible等工具。
一旦集羣都設置好了,而且爲運行應用程序建立了pods,這些pods就配備了負載平衡器;這些負載均衡器將流量路由到服務。開源的Kubernetes項目並非默認的負載平衡器;所以,它須要與NGINX Ingress controller與HAProxy或ELB等工具集成,或任何其餘工具,擴大Kubernetes的Ingress插件,以提供負載均衡能力。
標籤就像附加到對象上的鍵/值對,好比pods。標籤是用來標識對象的屬性的,這些屬性對用戶來講是重要的和有意義的。
在生產中使用Kubernetes時,不能忽視的一個重要問題是標籤;標籤容許批量查詢和操做Kubernetes對象。標籤的特殊之處在於,它們還能夠用於識別Kubernetes對象並將其組織成組。這樣作的最佳用例之一是根據pod所屬的應用程序對它們進行分組。在這裏,團隊能夠構建並擁有任意數量的標籤約定。
使用Kubernetes時,設置網絡策略相當重要。網絡策略只不過是一個對象,它使你可以明確地聲明和決定哪些流量是容許的,哪些是不容許的。這樣,Kubernetes將可以阻止全部其餘不想要的和不符合規則的流量。在咱們的集羣中定義和限制網絡流量是強烈推薦的基本且必要的安全措施之一。
Kubernetes中的每一個網絡策略都定義了一個如上所述的受權鏈接列表。不管什麼時候建立任何網絡策略,它所引用的全部pod都有資格創建或接受列出的鏈接。簡單地說,網絡策略基本上就是受權和容許鏈接的白名單——一個鏈接,不管它是到仍是從pod,只有在應用於pod的至少一個網絡策略容許的狀況下才被容許。
在使用Kubernetes時,監控部署是相當重要的。確保配置、性能和流量保持安全更是重要。若是不進行日誌記錄和監控,就不可能診斷出發生的問題。爲了確保合規性,監視和日誌記錄變得很是重要。在進行監視時,有必要在體系結構的每一層上設置日誌記錄功能。生成的日誌將幫助咱們啓用安全工具、審計功能和分析性能。
運行無狀態應用要比運行有狀態應用簡單得多,但隨着Kubernetes運營商的不斷增加,這種想法正在改變。對於剛接觸Kubernetes的團隊來講,建議首先使用無狀態應用程序。
建議使用無狀態後端,這樣開發團隊就能夠確保不存在長時間運行的鏈接,從而增長了擴展的難度。使用無狀態,開發人員還能夠更有效地、零停機部署應用程序。人們廣泛認爲,無狀態應用程序能夠方便地根據業務須要進行遷移和擴展。
Kubernetes有三種用於部署的自動伸縮功能:水平pod自動伸縮(HPA)、垂直pod自動伸縮(VPA)和集羣自動伸縮。
水平pod autoscaler根據感知到的CPU利用率自動擴展deployment、replicationcontroller, replicaset, statefulset的數量。
Vertical pod autoscaling爲CPU和內存請求和限制推薦合適的值,它能夠自動更新這些值。
Cluster Autoscaler擴展和縮小工做節點池的大小。它根據當前的利用率調整Kubernetes集羣的大小。
控制在集羣中運行全部容器的鏡像源。若是您容許您的Pod從公共資源中拉取鏡像,您就不知道其中真正運行的是什麼。
若是從受信任的註冊表中提取它們,則能夠在註冊表上應用策略以提取安全和通過認證的鏡像。
不斷評估應用程序的狀態和設置,以學習和改進。例如,回顧容器的歷史內存使用狀況能夠得出這樣的結論:咱們能夠分配更少的內存,在長期內節省成本。
使用Pod優先級,您能夠決定設置不一樣服務運行的重要性。例如,爲了更好的穩定性,你須要確保RabbitMQ pod比你的應用pod更重要。或者你的入口控制器pods比數據處理pods更重要,以保持服務對用戶可用。
經過在HA中運行全部服務,支持集羣和服務的零停機升級。這也將保證您的客戶得到更高的可用性。
使用pod反親和性來確保在不一樣的節點上調度一個pod的多個副本,從而經過計劃中的和計劃外的集羣節點停機來確保服務可用性。
使用pod Disruptions策略,不惜一切代價確保您有最低的Pod副本數量!
硬件最終會失敗,軟件最終會運行。--(邁克爾·哈頓)
衆所周知,Kubernetes實際上已經成爲DevOps領域的編排平臺標準。Kubernetes從可用性、可伸縮性、安全性、彈性、資源管理和監控的角度來應對生產環境產生的風暴。因爲許多公司都在生產中使用Kubernetes,所以必須遵循上面提到的最佳實踐,以順利和可靠地擴展應用程序。
內容來源:my.oschina.net/u/1787735/b…
對於新安裝的 Kubernetes,常常出現的一個問題是 Service 沒有正常工做。若是您已經運行了 Deployment 並建立了一個 Service,可是當您嘗試訪問它時沒有獲得響應,但願這份文檔(全網最詳細的 K8s Service 不能訪問排查流程)能幫助您找出問題所在。
在某些狀況下,常常發現 kubectl 進程掛起現象,而後在 get 時候發現刪了一半,而另外的刪除不了
[root@k8s-master ~]# kubectl get -f fluentd-elasticsearch/
NAME DESIRED CURRENT READY AGE
rc/elasticsearch-logging-v1 0 2 2 15h
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/kibana-logging 0 1 1 1 15h
Error from server (NotFound): services "elasticsearch-logging" not found
Error from server (NotFound): daemonsets.extensions "fluentd-es-v1.22" not found
Error from server (NotFound): services "kibana-logging" not found
複製代碼
刪除這些 deployment,service 或者 rc 命令以下:
kubectl delete deployment kibana-logging -n kube-system --cascade=false
kubectl delete deployment kibana-logging -n kube-system --ignore-not-found
delete rc elasticsearch-logging-v1 -n kube-system --force now --grace-period=0
複製代碼
rm -rf /var/lib/etcd/*
複製代碼
刪除後從新 reboot master 結點。
reset etcd 後須要從新設置網絡
etcdctl mk /atomic.io/network/config '{ "Network": "192.168.0.0/16" }'
複製代碼
每次啓動都是報以下問題:
start request repeated too quickly for kube-apiserver.service
複製代碼
但其實不是啓動頻率問題,須要查看, /var/log/messages,在個人狀況中是由於開啓 ServiceAccount 後找不到 ca.crt 等文件,致使啓動出錯。
May 21 07:56:41 k8s-master kube-apiserver: Flag --port has been deprecated, see --insecure-port instead.
May 21 07:56:41 k8s-master kube-apiserver: F0521 07:56:41.692480 4299 universal_validation.go:104] Validate server run options failed: unable to load client CA file: open /var/run/kubernetes/ca.crt: no such file or directory
May 21 07:56:41 k8s-master systemd: kube-apiserver.service: main process exited, code=exited, status=255/n/a
May 21 07:56:41 k8s-master systemd: Failed to start Kubernetes API Server.
May 21 07:56:41 k8s-master systemd: Unit kube-apiserver.service entered failed state.
May 21 07:56:41 k8s-master systemd: kube-apiserver.service failed.
May 21 07:56:41 k8s-master systemd: kube-apiserver.service holdoff time over, scheduling restart.
May 21 07:56:41 k8s-master systemd: start request repeated too quickly for kube-apiserver.service
May 21 07:56:41 k8s-master systemd: Failed to start Kubernetes API Server.
複製代碼
在部署 fluentd 等日誌組件的時候,不少問題都是由於須要開啓 ServiceAccount 選項須要配置安全致使,因此說到底仍是須要配置好 ServiceAccount.
在配置 fluentd 時候出現cannot create /var/log/fluentd.log: Permission denied 錯誤,這是由於沒有關掉 SElinux 安全致使。
能夠在 /etc/selinux/config 中將 SELINUX=enforcing 設置成 disabled,而後 reboot
首先生成各類須要的 keys,k8s-master 需替換成 master 的主機名.
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=k8s-master" -days 10000 -out ca.crt
openssl genrsa -out server.key 2048
echo subjectAltName=IP:10.254.0.1 > extfile.cnf
#ip由下述命令決定
#kubectl get services --all-namespaces |grep 'default'|grep 'kubernetes'|grep '443'|awk '{print $3}'
openssl req -new -key server.key -subj "/CN=k8s-master" -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out server.crt -days 10000
複製代碼
若是修改 /etc/kubernetes/apiserver 的配置文件參數的話,經過 systemctl start kube-apiserver 啓動失敗,出錯信息爲:
Validate server run options failed: unable to load client CA file: open /root/keys/ca.crt: permission denied
複製代碼
但能夠經過命令行啓動 API Server
/usr/bin/kube-apiserver --logtostderr=true --v=0 --etcd-servers=http://k8s-master:2379 --address=0.0.0.0 --port=8080 --kubelet-port=10250 --allow-privileged=true --service-cluster-ip-range=10.254.0.0/16 --admission-control=ServiceAccount --insecure-bind-address=0.0.0.0 --client-ca-file=/root/keys/ca.crt --tls-cert-file=/root/keys/server.crt --tls-private-key-file=/root/keys/server.key --basic-auth-file=/root/keys/basic_auth.csv --secure-port=443 &>> /var/log/kubernetes/kube-apiserver.log &
複製代碼
命令行啓動 Controller-manager
/usr/bin/kube-controller-manager --logtostderr=true --v=0 --master=http://k8s-master:8080 --root-ca-file=/root/keys/ca.crt --service-account-private-key-file=/root/keys/server.key & >>/var/log/kubernetes/kube-controller-manage.log
複製代碼
etcd是kubernetes 集羣的zookeeper進程,幾乎全部的service都依賴於etcd的啓動,好比flanneld,apiserver,docker.....在啓動etcd是報錯日誌以下:
May 24 13:39:09 k8s-master systemd: Stopped Flanneld overlay address etcd agent.
May 24 13:39:28 k8s-master systemd: Starting Etcd Server...
May 24 13:39:28 k8s-master etcd: recognized and used environment variable ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379,http://etcd:4001
May 24 13:39:28 k8s-master etcd: recognized environment variable ETCD_NAME, but unused: shadowed by corresponding flag
May 24 13:39:28 k8s-master etcd: recognized environment variable ETCD_DATA_DIR, but unused: shadowed by corresponding flag
May 24 13:39:28 k8s-master etcd: recognized environment variable ETCD_LISTEN_CLIENT_URLS, but unused: shadowed by corresponding flag
May 24 13:39:28 k8s-master etcd: etcd Version: 3.1.3
May 24 13:39:28 k8s-master etcd: Git SHA: 21fdcc6
May 24 13:39:28 k8s-master etcd: Go Version: go1.7.4
May 24 13:39:28 k8s-master etcd: Go OS/Arch: linux/amd64
May 24 13:39:28 k8s-master etcd: setting maximum number of CPUs to 1, total number of available CPUs is 1
May 24 13:39:28 k8s-master etcd: the server is already initialized as member before, starting as etcd member...
May 24 13:39:28 k8s-master etcd: listening for peers on http://localhost:2380
May 24 13:39:28 k8s-master etcd: listening for client requests on 0.0.0.0:2379
May 24 13:39:28 k8s-master etcd: listening for client requests on 0.0.0.0:4001
May 24 13:39:28 k8s-master etcd: recovered store from snapshot at index 140014
May 24 13:39:28 k8s-master etcd: name = master
May 24 13:39:28 k8s-master etcd: data dir = /var/lib/etcd/default.etcd
May 24 13:39:28 k8s-master etcd: member dir = /var/lib/etcd/default.etcd/member
May 24 13:39:28 k8s-master etcd: heartbeat = 100ms
May 24 13:39:28 k8s-master etcd: election = 1000ms
May 24 13:39:28 k8s-master etcd: snapshot count = 10000
May 24 13:39:28 k8s-master etcd: advertise client URLs = http://etcd:2379,http://etcd:4001
May 24 13:39:28 k8s-master etcd: ignored file 0000000000000001-0000000000012700.wal.broken in wal
May 24 13:39:29 k8s-master etcd: restarting member 8e9e05c52164694d in cluster cdf818194e3a8c32 at commit index 148905
May 24 13:39:29 k8s-master etcd: 8e9e05c52164694d became follower at term 12
May 24 13:39:29 k8s-master etcd: newRaft 8e9e05c52164694d [peers: [8e9e05c52164694d], term: 12, commit: 148905, applied: 140014, lastindex: 148905, lastterm: 12]
May 24 13:39:29 k8s-master etcd: enabled capabilities for version 3.1
May 24 13:39:29 k8s-master etcd: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32 from store
May 24 13:39:29 k8s-master etcd: set the cluster version to 3.1 from store
May 24 13:39:29 k8s-master etcd: starting server... [version: 3.1.3, cluster version: 3.1]
May 24 13:39:29 k8s-master etcd: raft save state and entries error: open /var/lib/etcd/default.etcd/member/wal/0.tmp: is a directory
May 24 13:39:29 k8s-master systemd: etcd.service: main process exited, code=exited, status=1/FAILURE
May 24 13:39:29 k8s-master systemd: Failed to start Etcd Server.
May 24 13:39:29 k8s-master systemd: Unit etcd.service entered failed state.
May 24 13:39:29 k8s-master systemd: etcd.service failed.
May 24 13:39:29 k8s-master systemd: etcd.service holdoff time over, scheduling restart.
複製代碼
核心語句:
raft save state and entries error: open /var/lib/etcd/default.etcd/member/wal/0.tmp: is a directory
複製代碼
進入相關目錄,刪除 0.tmp,而後就能夠啓動啦!
問題背景:當前部署了 3 個 etcd 節點,忽然有一天 3 臺集羣所有停電宕機了。從新啓動以後發現 K8S 集羣是能夠正常使用的,可是檢查了一遍組件以後,發現有一個節點的 etcd 啓動不了。
通過一遍探查,發現時間不許確,經過如下命令 ntpdate ntp.aliyun.com 從新將時間調整正確,從新啓動 etcd,發現仍是起不來,報錯以下:
Mar 05 14:27:15 k8s-node2 etcd[3248]: etcd Version: 3.3.13
Mar 05 14:27:15 k8s-node2 etcd[3248]: Git SHA: 98d3084
Mar 05 14:27:15 k8s-node2 etcd[3248]: Go Version: go1.10.8
Mar 05 14:27:15 k8s-node2 etcd[3248]: Go OS/Arch: linux/amd64
Mar 05 14:27:15 k8s-node2 etcd[3248]: setting maximum number of CPUs to 4, total number of available CPUs is 4
Mar 05 14:27:15 k8s-node2 etcd[3248]: the server is already initialized as member before, starting as etcd member
...
Mar 05 14:27:15 k8s-node2 etcd[3248]: peerTLS: cert = /opt/etcd/ssl/server.pem, key = /opt/etcd/ssl/server-key.pe
m, ca = , trusted-ca = /opt/etcd/ssl/ca.pem, client-cert-auth = false, crl-file =
Mar 05 14:27:15 k8s-node2 etcd[3248]: listening for peers on https://192.168.25.226:2380
Mar 05 14:27:15 k8s-node2 etcd[3248]: The scheme of client url http://127.0.0.1:2379 is HTTP while peer key/cert
files are presented. Ignored key/cert files.
Mar 05 14:27:15 k8s-node2 etcd[3248]: listening for client requests on 127.0.0.1:2379
Mar 05 14:27:15 k8s-node2 etcd[3248]: listening for client requests on 192.168.25.226:2379
Mar 05 14:27:15 k8s-node2 etcd[3248]: member 9c166b8b7cb6ecb8 has already been bootstrapped
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service: main process exited, code=exited, status=1/FAILURE
Mar 05 14:27:15 k8s-node2 systemd[1]: Failed to start Etcd Server.
Mar 05 14:27:15 k8s-node2 systemd[1]: Unit etcd.service entered failed state.
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service failed.
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service failed.
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service holdoff time over, scheduling restart.
Mar 05 14:27:15 k8s-node2 systemd[1]: Starting Etcd Server...
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_NAME, but unused: shadowed by correspo
nding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_DATA_DIR, but unused: shadowed by corr
esponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_LISTEN_PEER_URLS, but unused: shadowed
by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_LISTEN_CLIENT_URLS, but unused: shadow
ed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_ADVERTISE_PEER_URLS, but unuse
d: shadowed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_ADVERTISE_CLIENT_URLS, but unused: sha
dowed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_CLUSTER, but unused: shadowed
by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_CLUSTER_TOKEN, but unused: sha
dowed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_CLUSTER_STATE, but unused: sha
dowed by corresponding flag
複製代碼
解決方法:
檢查日誌發現並無特別明顯的錯誤,根據經驗來說,etcd 節點壞掉一個其實對集羣沒有大的影響,這時集羣已經能夠正常使用了,可是這個壞掉的 etcd 節點並無啓動,解決方法以下:
進入 etcd 的數據存儲目錄進行備份 備份原有數據:
cd /var/lib/etcd/default.etcd/member/
cp * /data/bak/
複製代碼
刪除這個目錄下的全部數據文件
rm -rf /var/lib/etcd/default.etcd/member/*
複製代碼
中止另外兩臺 etcd 節點,由於 etcd 節點啓動時須要全部節點一塊兒啓動,啓動成功後便可使用。
#master 節點
systemctl stop etcd
systemctl restart etcd
#node1 節點
systemctl stop etcd
systemctl restart etcd
#node2 節點
systemctl stop etcd
systemctl restart etcd
複製代碼
在每臺服務器須要創建主機互信的用戶名執行如下命令生成公鑰/密鑰,默認回車便可
ssh-keygen -t rsa
複製代碼
能夠看到生成個公鑰的文件。
互傳公鑰,第一次須要輸入密碼,以後就OK了。
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.199.132 (-p 2222)
複製代碼
-p 端口 默認端口不加-p,若是更改過端口,就得加上-p. 能夠看到是在.ssh/下生成了個 authorized_keys的文件,記錄了能登錄這臺服務器的其餘服務器的公鑰。
測試看是否能登錄:
ssh 192.168.199.132 (-p 2222)
複製代碼
hostnamectl set-hostname k8s-master1
複製代碼
若是不安裝或者不輸出,能夠將 update 修改爲 install 再運行。
yum install update
yum update kernel
yum update kernel-devel
yum install kernel-headers
yum install gcc
yum install gcc make
複製代碼
運行完後
sh VBoxLinuxAdditions.run
複製代碼
能夠經過下面命令強制刪除
kubectl delete pod NAME --grace-period=0 --force
複製代碼
刪除namespace一直處於Terminating狀態
能夠經過如下腳本強制刪除
[root@k8s-master1 k8s]# cat delete-ns.sh
#!/bin/bash
set -e
useage(){
echo "useage:"
echo " delns.sh NAMESPACE"
}
if [ $# -lt 1 ];then
useage
exit
fi
NAMESPACE=$1
JSONFILE=${NAMESPACE}.json
kubectl get ns "${NAMESPACE}" -o json > "${JSONFILE}"
vi "${JSONFILE}"
curl -k -H "Content-Type: application/json" -X PUT --data-binary @"${JSONFLE}" \
http://127.0.0.1:8001/api/v1/namespaces/"${NAMESPACE}"/finalize
複製代碼
下面咱們建立一個對應的容器,該容器只有 requests 設定,可是沒有 limits 設定,
- name: busybox-cnt02
image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello from cnt02; sleep 10;done"]
resources:
requests:
memory: "100Mi"
cpu: "100m"
複製代碼
這個容器建立出來會有什麼問題呢?
其實對於正常的環境來講沒有什麼問題,可是對於資源型 pod 來講,若是有的容器沒有設定 limit 限制,資源會被其餘的 pod 搶佔走,可能會形成容器應用失敗的狀況。能夠經過 limitrange 策略來去匹配,讓 pod 自動設定,前提是要提早配置好limitrange 規則。
Kubernetes 上對應用程序進行故障排除的 6 個技巧 推薦給你們,平常排錯必備。分享一份阿里雲內部超全K8s實戰手冊,免費下載!
一個目標:容器操做;兩地三中心;四層服務發現;五種 Pod 共享資源;六個 CNI 經常使用插件;七層負載均衡;八種隔離維度;九個網絡模型原則;十類 IP 地址;百級產品線;千級物理機;萬級容器;相如無億,k8s 有億:億級日服務人次。
Kubernetes(k8s)是自動化容器操做的開源平臺。這些容器操做包括:部署、調度和節點集羣間擴展。
自動化容器部署和複製。
實時彈性收縮容器規模。
容器編排成組,並提供容器間的負載均衡。
調度:容器在哪一個機器上運行。
kubectl:客戶端命令行工具,做爲整個系統的操做入口。
kube-apiserver:以 REST API 服務形式提供接口,做爲整個系統的控制入口。
kube-controller-manager:執行整個系統的後臺任務,包括節點狀態情況、Pod 個數、Pods 和Service 的關聯等。
kube-scheduler:負責節點資源管理,接收來自 kube-apiserver 建立 Pods 任務,並分配到某個節點。
etcd:負責節點間的服務發現和配置共享。
kube-proxy:運行在每一個計算節點上,負責 Pod 網絡代理。定時從 etcd 獲取到 service 信息來作相應的策略。
kubelet:運行在每一個計算節點上,做爲 agent,接收分配該節點的 Pods 任務及管理容器,週期性獲取容器狀態,反饋給 kube-apiserver。
DNS:一個可選的 DNS 服務,用於爲每一個 Service 對象建立 DNS 記錄,這樣全部的 Pod 就能夠經過 DNS 訪問服務了。
下面是 k8s 的架構拓撲圖:
兩地三中心
兩地三中心包括本地生產中心、本地災備中心、異地災備中心。
兩地三中心要解決的一個重要問題就是數據一致性問題。
k8s 使用 etcd 組件做爲一個高可用、強一致性的服務發現存儲倉庫。用於配置共享和服務發現。
它做爲一個受到 Zookeeper 和 doozer 啓發而催生的項目。除了擁有他們的全部功能以外,還擁有如下 4 個特色:
簡單:基於 HTTP+JSON 的 API 讓你用 curl 命令就能夠輕鬆使用。
安全:可選 SSL 客戶認證機制。
快速:每一個實例每秒支持一千次寫操做。
可信:使用 Raft 算法充分實現了分佈式。
先一張圖解釋一下網絡七層協議:
k8s 提供了兩種方式進行服務發現:
以上兩種方式,一個是基於 TCP,DNS 基於 UDP,它們都是創建在四層協議之上。
Pod 是 k8s 最基本的操做單元,包含一個或多個緊密相關的容器。
一個 Pod 能夠被一個容器化的環境看做應用層的「邏輯宿主機」;一個 Pod 中的多個容器應用一般是緊密耦合的,Pod 在 Node 上被建立、啓動或者銷燬;每一個 Pod 裏運行着一個特殊的被稱之爲 Volume 掛載卷,所以他們之間通訊和數據交換更爲高效。在設計時咱們能夠充分利用這一特性將一組密切相關的服務進程放入同一個 Pod 中。
同一個 Pod 裏的容器之間僅需經過 localhost 就能互相通訊。
一個 Pod 中的應用容器共享五種資源:
PID 命名空間:Pod 中的不一樣應用程序能夠看到其餘應用程序的進程 ID。
網絡命名空間:Pod 中的多個容器可以訪問同一個IP和端口範圍。
IPC 命名空間:Pod 中的多個容器可以使用 SystemV IPC 或 POSIX 消息隊列進行通訊。
UTS 命名空間:Pod 中的多個容器共享一個主機名。
Volumes(共享存儲卷):Pod 中的各個容器能夠訪問在 Pod 級別定義的 Volumes。
Pod 的生命週期經過 Replication Controller 來管理;經過模板進行定義,而後分配到一個 Node 上運行,在 Pod 所包含容器運行結束後,Pod 結束。
Kubernetes 爲 Pod 設計了一套獨特的網絡配置,包括爲每一個 Pod 分配一個IP地址,使用 Pod 名做爲容器間通訊的主機名等。
CNI(Container Network Interface)容器網絡接口是 Linux 容器網絡配置的一組標準和庫,用戶須要根據這些標準和庫來開發本身的容器網絡插件。CNI 只專一解決容器網絡鏈接和容器銷燬時的資源釋放,提供一套框架。因此 CNI 能夠支持大量不一樣的網絡模式,而且容易實現。
下面用一張圖表示六個 CNI 經常使用插件:
提負載均衡就不得不先提服務器之間的通訊。
IDC(Internet Data Center)也可稱數據中心、機房,用來放置服務器。IDC 網絡是服務器間通訊的橋樑。
上圖裏畫了不少網絡設備,它們都是幹啥用的呢?
路由器、交換機、MGW/NAT 都是網絡設備,按照性能、內外網劃分不一樣的角色。
先說說各層負載均衡:
這裏用一張圖來講說四層和七層負載均衡的區別:
上面四層服務發現講的主要是 k8s 原生的 kube-proxy 方式。k8s 關於服務的暴露主要是經過 NodePort 方式,經過綁定 minion 主機的某個端口,而後進行 Pod 的請求轉發和負載均衡,但這種方式有下面的缺陷:
Service 可能有不少個,若是每一個都綁定一個 Node 主機端口的話,主機須要開放外圍的端口進行服務調用,管理混亂。
沒法應用不少公司要求的防火牆規則。
理想的方式是經過一個外部的負載均衡器,綁定固定的端口,好比 80;而後根據域名或者服務名向後面的 Service IP 轉發。
Nginx 很好的解決了這個需求,但問題是若是有的新的服務加入,如何去修改而且加載這些 Nginx 配置?
Kubernetes 給出的方案就是 Ingress。這是一個基於七層的方案。
k8s 集羣調度這邊須要對上面從上到下、從粗粒度到細粒度的隔離作相應的調度策略。
k8s 網絡模型要符合四個基礎原則、三個網絡要求原則、一個架構原則、一個 IP 原則。
每一個 Pod 都擁有一個獨立的 IP 地址,並且假定全部 Pod 都在一個能夠直接連通的、扁平的網絡空間中,無論是否運行在同一 Node 上均可以經過 Pod 的 IP 來訪問。
k8s 中的 Pod 的 IP 是最小粒度 IP。同一個 Pod 內全部的容器共享一個網絡堆棧,該模型稱爲 IP-per-Pod 模型。
Pod 由 docker0 實際分配的 IP。
Pod 內部看到的 IP 地址和端口與外部保持一致。
同一個 Pod 內的不一樣容器共享網絡,能夠經過localhost來訪問對方的端口,相似同一個虛擬機內不一樣的進程。
IP-per-Pod 模型從端口分配、域名解析、服務發現、負載均衡、應用配置等角度看,Pod 能夠看作是一臺獨立的虛擬機或物理機。
全部容器均可以不用 NAT 的方式同別的容器通訊。
全部節點均可以在不一樣 NAT 方式下同全部容器通訊,反之亦然。
容器的地址和別人看到的地址是同一個地址。
要符合下面的架構:
由上圖架構引伸出來 IP 概念從集羣外部到集羣內部:
十類IP地址
你們都知道 IP 地址分爲 ABCDE 類,另外還有五類特殊用途的 IP。
第一類
A 類:1.0.0.0-1226.255.255.255,默認子網掩碼/8,即255.0.0.0。
B 類:128.0.0.0-191.255.255.255,默認子網掩碼/16,即255.255.0.0。
C 類:192.0.0.0-223.255.255.255,默認子網掩碼/24,即255.255.255.0。
D 類:224.0.0.0-239.255.255.255,通常用於組播。
E 類:240.0.0.0-255.255.255.255(其中255.255.255.255爲全網廣播地址)。E 類地址通常用於研究用途。
複製代碼
第二類
0.0.0.0
嚴格來講,0.0.0.0 已經不是一個真正意義上的 IP 地址了。它表示的是這樣一個集合:全部不清楚的主機和目的網絡。這裏的不清楚是指在本機的路由表裏沒有特定條目指明如何到達。做爲缺省路由。
127.0.0.1 本機地址。
複製代碼
第三類
224.0.0.1 組播地址。
若是你的主機開啓了IRDP(internet路由發現,使用組播功能),那麼你的主機路由表中應該有這樣一條路由。
複製代碼
第四類
169.254.x.x
使用了 DHCP 功能自動獲取了 IP 的主機,DHCP 服務器發生故障,或響應時間太長而超出了一個系統規定的時間,系統會爲你分配這樣一個 IP,表明網絡不能正常運行。
複製代碼
第五類
10.xxx、172.16.x.x~172.31.x.x、192.168.x.x 私有地址。
大量用於企業內部。保留這樣的地址是爲了不亦或是哪一個接入公網時引發地址混亂。
複製代碼
連接:blog.csdn.net/huakai_sun/article/details/82378856