k8s實踐(3)--k8s集羣安裝詳解

k8s實踐系列的相關配置都在github:https://github.com/huangguisu/k8s.git

一、部署架構規劃和環境準備


1、安裝方式選擇

目前有三種安裝方式

下面給出兩種安裝方式:
第一種是yum安裝
配置yum源後,使用yum安裝,好處是簡單,壞處也很明顯,需要google更新yum源才能獲得最新版本的軟件,而所有軟件的依賴又不能自己指定,尤其是你的操作系統版本如果低的話,使用yum源安裝的kubernetes的版本也會受到限制。

第一種是二進制安裝
使用二進制文件安裝,好處是可以安裝任意版本的kubernetes,壞處是配置比較複雜。

雖然二進制安裝包安裝的方式比較費勁,但是二進制便於熟悉各個組件,對學習k8s是很有好處的,因此我們的教程裏面全都是二進制安裝。

第三種是kubeadm安裝
kubeadm是Kubernetes官方提供的用於快速安裝Kubernetes集羣的工具,將k8s的各個組件都安裝在docker之上,以容器的方式運行。伴隨Kubernetes每個版本的發佈都會同步更新,kubeadm會對集羣配置方面的一些實踐做調整,通過實驗kubeadm可以學習到Kubernetes官方在集羣配置上一些新的最佳實踐。

 

 

2、下載

https://github.com/kubernetes/kubernetes/releases
從上邊的網址中選擇相應的版本,從 CHANGELOG頁面 下載二進制文件,本文以1.14.1版本爲例

https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md#v1142

選擇Service Binaries中的kubernetes-server-linux-amd64.tar.gz 

該文件已經包含了 K8S所需要的全部組件,無需單獨下載Client等組件。 

解壓後,在kubernetes/server/bin 路徑下包含一些必須的組件:

設置環境變量:

export K8S_BIN=/mnt/app/kubernetes/server/bin/
export PATH="$K8S_BIN:$PATH"

 

3、節點規劃和環境準備

k8s至少需要一個master和一個node才能組成一個可用集羣。

本章我們搭建一個master節點和2個node節點。
我們在生產環境中使用時k8s時可以適當增加節點。

我們有三臺服務器,ip和身份規劃如下:
192.168.10.21 master node
192.168.10.22 node2
192.168.10.23 node3

1.設置主機名hostname,管理節點設置主機名爲 k8s-master。

hostname k8s-master

需要設置其他主機名稱時,可將 master 替換爲正確的主機名k8s-node1、k8s-node2即可。

2.編輯 /etc/hosts 文件,添加域名解析。

cat <<EOF >>/etc/hosts
192.168.10.21  k8s-master
192.168.10.22  k8s-node1
192.168.10.23  k8s-node1
192.168.10.21 node1.etcd.k8-cluster.com
192.168.10.22 node2.etcd.k8-cluster.com
192.168.10.23 node3.etcd.k8-cluster.com
EOF

3.關閉防火牆、selinux和swap。

systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
#關閉swap
sudo swapoff -a
#要永久禁掉swap分區,打開如下文件註釋掉swap那一行 
sudo vi /etc/fstab

 

 二、高可用Kubernetes Master節點安裝


kubernetes master 節點包含的組件:

  • kube-apiserver
  • kube-scheduler
  • kube-controller-manager

目前這三個組件需要部署在同一臺機器上。

  • kube-schedulerkube-controller-manager 和 kube-apiserver 三者的功能緊密相關;
  • 同時只能有一個 kube-schedulerkube-controller-manager 進程處於工作狀態,如果運行多個,則需要通過選舉產生一個 leader;

Kubernetes 的服務都是通過直接運行二進制文件加啓動參數完成,爲了便於管理,常見的做法是將Kubernetes服務進程配置成系統服務,我們在這都是通過supervisor來管理。

 

2.1、Kuber-apiserver


Kubernetes API服務器爲API對象驗證和配置數據,這些對象包含Pod,Service,ReplicationController等等。API Server提供REST操作以及前端到集羣的共享狀態,所有其它組件可以通過這些共享狀態交互。

啓動:kube-apiserver

簡單啓動,由於本地端口8080被佔用,修改kube-apiserver端口爲9090.

nohup /mnt/app/kubernetes/server/bin/kube-apiserver --insecure-bind-address=0.0.0.0 --insecure-port=9090 --etcd-servers=http://node1.etcd.k8-cluster.com:2379 --service-cluster-ip-range=192.168.10.0/16   --admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/mnt/logs/k8s-kube-apiserver/ --v=2 &

使用ssl認證啓動:

nohup /mnt/app/kubernetes/server/bin/kube-apiserver --insecure-bind-address=0.0.0.0 --insecure-port=9090 --etcd-servers=http://node1.etcd.k8-cluster.com:2379 --service-cluster-ip-range=192.168.10.0/16  --service-account-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem --client-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem --tls-private-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem  --tls-cert-file=/mnt/app/kubernetes/ssl/apiserver-public.pem --admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota --logtostderr=false --log-dir=/mnt/logs/k8s-kube-apiserver/ --v=2 &

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kube-apiserver.conf

配置選項

通用參數:

–admission-control=”AlwaysAdmit”:集羣中資源的Admission Controller的插件的有序列表,分別使用逗號分隔,AlwaysAdmit,

–admission-control-config-file=””: Admission Controller配置文件。
–advertise-address=<nil>: 廣播API Server給所有集羣成員的IP地址。其它集羣都可以訪問該IP地址,如果爲空,會使用—-allow-privileged[=false]: true,表示允許特權容器。
–authorization-mode=”AlwaysAllow”: 安全端口授權插件的有序列表,分別以逗號分隔,AlwaysAllow,AlwaysDeny,ABAC–authorization-policy-file=””: 授權策略的CSV文件,使用於–authorization-mode=ABAC模式的配置。
–basic-auth-file=””: 如果配置該選項,該文件會通過HTTP基本認證允許API Server安全端口的請求。
–bind-address=0.0.0.0: 服務–read-only-port和–secure-port端口的IP地址。相關接口必須是其它集羣通過CLI/web客–cert-dir=”/var/run/kubernetes”: TLS證書的目錄(默認/var/run/kubernetes)。如果配置–tls-cert-file和–tls—client-ca-file=””: 如果設置,任何提交客戶端證書的請求都會驗證與相關客戶端證書的CommonName的身份。該客戶端證書是–cloud-config=””: 雲提供商配置文件的路徑,空表示沒有該配置文件。
–cloud-provider=””: 雲服務的提供商,空表示沒有該提供商。
–cluster-name=”kubernetes”: 集羣實例的前綴。
–cors-allowed-origins=[]: CORS的允許起源(allowed origins, 翻譯待考慮)的列表,用逗號分隔。一個允許起源可以是

ETCD參數:

–etcd-config=””: ETCD客戶端的配置文件,與-etcd-servers配置項互斥。
–etcd-prefix=”/registry”: ETCD中所有資源路徑的前綴。
–etcd-servers=[]: ETCD服務器(http://ip:port)列表,以逗號分隔。與-etcd-config配置項互斥。
–etcd-servers-overrides=[]: 每個資源ETCD服務器覆蓋文件,以逗號分隔。獨立覆蓋格式,group/resource#servers,服–event-ttl=1h0m0s: 保留事件的時間值,默認1小時。
–experimental-keystone-url=””: 如果Passed,激活Keystone認證插件。
–external-hostname=””: 爲Master生成外部URLs使用的主機名。
–google-json-key=””: 用戶Google Cloud Platform Service Account JSON Key認證。
–insecure-bind-address=127.0.0.1:非安全端口(所有接口都設置爲0.0.0.0)的服務IP地址。默認是本地地址。
–insecure-port=8080: 不安全且沒有認證的進程訪問端口,默認8080。假設防火牆規則設置該端口從集羣外部禁止訪問,並且在–kubelet-certificate-authority=””: 證書路徑。證書授權文件。
–kubelet-client-certificate=””: TLS客戶端證書文件路徑。
–kubelet-client-key=””: TLS客戶端祕鑰文件路徑。
–kubelet-https[=true]: 使用https建立Kubelet連接。
–kubelet-port=10250: Kubelet端口。
–kubelet-timeout=5s: Kubelet操作Timeout值。
–log-flush-frequency=5s: 日誌緩衝秒數的最大值。
–long-running-request-regexp=”(/|^)((watch|proxy)(/|$)|(logs?|portforward|exec|attach)/?$)”: 匹配長–master-service-namespace=”default”: Namespace,該Namespace的Kubernetes主服務應該注入Pod。
–max-connection-bytes-per-sec=0: 如果非零,表示每個用戶連接的最大值,字節數/秒,當前只適用於長時間運行的請求。
–max-requests-inflight=400: 給定時間內運行的請求的最大值。如果超過最大值,該請求就會被拒絕。零表示沒有限制。
–min-request-timeout=1800: 這是個可選字段,表示一個請求處理的最短時間,單位是秒。在超時之前,這個請求必須是激活的–oidc-ca-file=””: 如果設置該選項,Oidc-ca-file中的相關機構會驗證OpenID服務的證書。否則,會使用主機的根證書。
–oidc-client-id=””: 如果設置了oidc-issuer-url字段,該字段,OpenID連接客戶端的客戶ID也必須設置。
–oidc-issuer-url=””: OpenID發行的URL,只接受HTTPS協議。如果設置該字段,將被用來驗證OIDC JSON Web Token(JWT)–oidc-username-claim=”sub”: 。默認值之外的那些值,可能是不唯一的,可變的。這個標誌還在嘗試中,詳情請參考Authentication –profiling[=true]: 通過web接口進行分析 host:port/debug/pprof/。
–runtime-config=: key=value鍵值對集,描述運行時配置,也會回傳輸到apiserver。apis/鍵值用於打開–secure-port=6443: 用於HTTPS的認證和授權。0表示不支持HTTPS服務。
–service-account-key-file=””: 該文件包含RPM-encoded x509 RSA的私鑰和公鑰,用於驗證ServiceAccount的Token。–service-account-lookup[=false]: true, 表示驗證Service Account的Token做爲Authentication一部分在ETCD中的

–service-cluster-ip-range=: CIDR標記的IP範圍,從中分配IP給服務集羣。該範圍不能與分配給Pod節點的任何IP範圍–service-node-port-range=: NodePort可見性服務的端口範圍,包含範圍的兩端。如’30000-32767’,包含30000和32767–ssh-keyfile=””: 如果非空,使用安全SSH代理到該節點,用該祕鑰文件。
–ssh-user=””: 如果非空,使用安全SSH代理到該節點,用該用戶名。
–storage-versions=”extensions/v1beta1,v1″: 存儲資源的版本。不同的組存儲在不同的版本里面,指定格式”group1/version1,–tls-cert-file=””: 該文件包含HTTPS的x509證書。(CA證書,如果存在,連接在服務器證書之後)。如果支持HTTPS服務,且沒–tls-private-key-file=””: 該文件包含x509私鑰匹配項–tls-cert-file.
–token-auth-file=””: 該文件使用Token驗證保護API Server的安全端口。
–watch-cache[=true]: 可以在API Server查看緩存。

Kubernetes API Server原理分析

總體來看,Kubernetes API Server的核心功能是提供了Kubernetes各類資源對象(如Pod、RC、Service等)的增、刪、改、查及Watch等HTTP Rest接口,成爲集羣內各個功能模塊之間數據交互和通信的中心樞紐,是整個系統的數據總線和數據中心。除此之外,他還有以下的特性:

  1. 是集羣管理的API入口;
  2. 是資源配額控制的入口;
  3. 提供完備的集羣安全機制;

Kubernetes API Server概述

Kubernetes API Server通過一個名爲Kube-apiserver的進程提供服務,該進程運行在Master節點上。在默認情況下,kube-apiserver進程在本機的8080端口(對應參數--insecure-port)提供REST服務。我們可以同時啓動HTTPS安全端口(--secure-port=6443)來啓動安全機制,加強REST API訪問的安全性。

通常我們可以通過命令行工具kubectl來與kubernetes API Server交互,他們之間的接口是REST調用。測試和學習的情況下也可以使用curl命令行工具進行快速驗證。

比如,在Master節點上,運行下面的curl命令可以得到JSON方式返回的Kubernetes API的版本信息:

  • curl localhost:8080/api

運行下面的命令查看Kubernetes API Server目前支持的資源對象的種類i:

  • curl localhost:8080/api/v1

返回不同資源列表信息:

  • curl localhost:8080/api/v1/pods
  • curl localhost:8080/api/v1/services
  • curl localhost:8080/api/v1/replicationcontrollers

如果我們只想對外暴露部分REST服務,則可以在Master或其他任何節點上通過運行kube-proxy進程啓動一個內部代理來實現。

運行下面的命令,我們在8001端口啓動代理,並且拒絕客戶端訪問RC的API:

  • kubectl proxy --reject-paths=“^/api/v1/replicationcontrollers” --port=8001 --v=2

通過下面的命令進行驗證:

  • curl localhost:8001/api/v1/replicationcontrollers

kubectl proxy具有很多特性,最實用的一個特性是提供簡單有效的安全機制,比如採用白名單來限制非法客戶端訪問時,只要採用下面的參數即可:

  • --accept-host=“^localhost$,^127\\.0\\.0\\.1$,^\\[::1\\]$”

最後一種方式是通過b編程的方式調用Kubernetes API Server。具體使用場景又細分爲以下兩種:

第一種使用場景:運行在Pod中的用戶進程調用Kubernetes API,通常用來實現分佈式集羣搭建的目標。Pod中的進程如何知道API Server的訪問地址呢,因爲Kubernetes API Server本身也是一個Service,其名字就是Kubernetes,他的clusterIP地址是ClusterIP地址池中的第一個IP,他所服務的端口是HTTPS端口443,通過kubectl get svc可以確認這一點。

第二種使用場景:開發基於Kubernetes的管理平臺。比如調用Kubernetes API 來完成Pod、Service、RC等資源對象的圖形化創建和管理界面,此時可以使用kubernetes及各開源社區爲開發人員提供的各種語言版本的Client Library。

獨特的Kubernetes-Proxy API接口

這類接口的作用是代理REST請求,即kubernetes API Server把收到的REST請求轉發到某個Node上的kubelet守護進程的REST端口上,由該kubelet進程負責響應。

Kubernetes Proxy API中管理Node的相關接口,該接口的REST路徑爲/api/v1/proxy/nodes/{name},其中name爲節點名稱或IP地址,包括以下幾個具體的接口:

  • /api/v1/proxy/nodes/{name}/pods  #列出指定節點內的所有Pod的信息
  • /api/v1/proxy/nodes/{name}/stats       #列出指定節點內物理資源的統計信息
  • /api/v1/proxy/nodes/{name}/spec       #列出指定節點的概要信息

例:節點名爲k8s-node-1,下面命令獲取該節點上所有運行中的pod:

  • curl localhost:8080/api/v1/proxy/nodes/k8s-node-1/pods

需要說明的是,此處獲取pod信息數據來自Node而非etcd數據庫,所以兩者可能在某些時間點會有偏差。此外如果kubelet進程在啓東時包含--enable-debugging-handles=true,namekubernetes Proxy API 還會增加下面的接口:

  • /api/v1/proxy/nodes/{name}/run           #在節點上運行某個容器
  • /api/v1/proxy/nodes/{name}/exec        #在節點的某個容器中運行某條命令
  • /api/v1/proxy/nodes/{name}/attach      #在節點上attach某個容器
  • /api/v1/proxy/nodes/{name}/portForward      #實現節點上的Pod端口轉發
  • /api/v1/proxy/nodes/{name}/logs          #列出節點的各類日誌信息,例如tallylog、lastlog、wtmp、ppp/、rhsm、audit、tuned、和anaconda等
  • /api/v1/proxy/nodes/{name}/metrics      #列出和該節點相關的Metrics信息
  • /api/v1/proxy/nodes/{name}/runningpods        #列出節點內運行中的Pod信息
  • /api/v1/proxy/nodes/{name}/debug/pprof        #列出節點內當前Web服務的狀態,包括CPU和內存的使用情況

Kubernetes Proxy API裏關於Pod的相關接口,通過這些接口,我們可以訪問pod裏某個容器提供的服務(如Tomcat在8080提供的服務)

  • /api/v1/proxy/namespaces/{namespace}/pods/{name}/{patch:*}         #訪問pod的某個服務接口
  • /api/v1/proxy/namespaces/{namespace}/pods/{name}                        #訪問pod
  • /api/v1/proxy/namespaces/{namespace}/pods/{name}/proxy/{patch:*}         #訪問pod的某個服務接口
  • /api/v1/proxy/namespaces/{namespace}/pods/{name}/proxy              #訪問pod

在上面的4個接口中,後面兩個接口的功能和前面兩個完全一樣,只是寫法不同。

集羣功能模塊之間的通信

集羣內各個功能模塊通過API Server將信息存入etcd,當需要獲取和操作這些數據時,則通過API Server提供的REST接口(用GET/LIST/WTCH方法)來實現,從而實現各模之間的信息交互;

例:kubelet進程與API Server的交互:每個node上的kubelet每隔一個時間週期,就會調用一次API Server的REST接口報告自身狀態,API Server接收到這些信息後,將各節點信息更新到etcd中。此外kubelet也通過API Server的watch接口監聽pod信息,如果監聽到新的Pod副本被調度綁定到本節點,則執行Pod對應的容器的創建和啓動邏輯;如果監聽到Pod對象被刪除,則刪除本節點上的相應的Pod容器;如果監聽到修改Pod信息,則kubelet監聽到變化後,會相應的修改本節點的Pod容器。

例:另外一個交互場景:kube-controller-manager進程與API Server的交互。kube-controller-manager中的Node Controller模塊通過API Server提供的Watch接口,實時監控Node的信息並做相應的處理;

例:kube-scheduler與API Server交互的場景,當scheduler通過API Server的Watch接口監聽到新建Pod副本的信息後,他會檢索所有符合該Pod要求的Node列表,開始執行Pod調度邏輯,調度成功後將Pod綁定到目標節點上。爲了緩解集羣各模塊對API Server的壓力,各功能模塊都採用緩存的機制來緩存數據。各功能模塊定時從API Server獲取指定資源對象的信息(通過LIST或watch),然後將這些信息保存到本地緩存,功能模塊在某些情況下不直接訪問API Server,而是通過訪問緩存數據來間接訪問API Server

 

2.2、Kuber-controller-manager


Kube-controller-manager依賴kube-apiserver:

如果APIServer做的是前臺的工作的話,那麼controller manager就是負責後臺的。每一個資源都對應一個控制器。而control manager就是負責管理這些控制器的,比如我們通過APIServer創建了一個Pod,當這個Pod創建成功後,APIServer的任務就算完成了。

nohup kube-controller-manager --master=http://k8s-master:8080  --logtostderr=false --log-dir=/mnt/logs/k8s-kube-controller-manager/  --v=2 &

Kube-controller-manager主要的配置參數:

--master: 指定apiserver的URL地址

--logtostderr=false: 設置爲false表示將日誌寫入文件,不寫入則爲stderr

--log-dir=/mnt/logs/k8s/  :日誌目錄

--v=2 :日誌等級

上面這個啓動命令比較簡單,由於發佈pod等相關資源需要安全驗證,因此需要使用https。

關於Kubernetes安全:  https://guisu.blog.csdn.net/article/details/95067232   和ssl證書:https://guisu.blog.csdn.net/article/details/95459273

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kube-controller-manager.conf

supervisor啓動是最終集羣版的結果:

[program:k8s-kube-controller-manager]
command =/mnt/app/kubernetes/server/bin/kube-controller-manager --master=https://master.k8s.tulingapi.com:6443 --cluster-cidr=10.0.0.0/16 --service-account-private-key-file=/mnt/app/kubernetes/ssl/apis
erver-private.pem  --root-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem  --cluster-signing-cert-file=/mnt/app/kubernetes/ssl/ca-public.pem  --cluster-signing-key-file=/mnt/app/kubernetes/ssl/ca-private
.pem --kubeconfig=/mnt/app/kubernetes/ssl/kubeconfig.yaml   --logtostderr=false --log-dir=/mnt/logs/k8s-kube-controller-manager/  --v=2
process_name=%(program_name)s
numprocs=1
directory=/mnt/app/kubernetes/
user=root
stdout_logfile=/mnt/logs/%(program_name)s/server.log
stderr_logfile=/mnt/logs/%(program_name)s/error.log
serverurl=AUTO = /mnt/logs/k8s-kube-apiserver/error.log

 

 

2.3、Kuber-scheduler


kube-scheduler 也依賴kube-apiserver:

schedule負責調度Pod到合適的Node上,如果把scheduler看成一個黑匣子,那麼它的輸入是pod和由多個Node組成的列表,輸出是Pod和一個Node的綁定。 kubernetes目前提供了調度算法,同樣也保留了接口。用戶根據自己的需求定義自己的調度算法。

nohup kube-scheduler --master=http://k8s-master:8080  --logtostderr=false --log-dir=/mnt/logs/k8s-kube-scheduler/  --v=2 &

驗證Master是否安裝成功

$ kubectl get componentstatuses

使用supervisor管理:

[program:k8s-kube-scheduler]
command =/mnt/app/kubernetes/server/bin/kube-scheduler --master=http://k8s-master:9090 --address=0.0.0.0  --logtostderr=false --log-dir=/mnt/logs/k8s-kube-scheduler/  --v=2
process_name=%(program_name)s
numprocs=1
directory=/mnt/app/kubernetes/
umask=022
priority=999
autostart=true
autorestart=true
startsecs=10
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
user=root
redirect_stderr=true
stdout_logfile=/mnt/logs/%(program_name)s/server.log
stdout_logfile_maxbytes=50000MB
stdout_logfile_backups=10
stdout_capture_maxbytes=0MB
stdout_events_enabled=false
stderr_logfile=/mnt/logs/%(program_name)s/error.log
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_capture_maxbytes=1MB
stderr_events_enabled=false
;environment=JAVA_HOME="/usr/java"
serverurl=AUTO = /mnt/logs/k8s-kube-apiserver/error.log

 

三、Node節點


每個Node節點主要由四個模板組成:kublet, kube-proxy,docker,flanneld

kube-scheduler 也依賴kube-apiserver

在工作node節點上,先安裝好docker,並且啓動docker deamon.

將kubernetes-server-linux-amd64.tar.gz複製所有的node節點服務器上解壓到:/mnt/app/kubernetes/

設置環境變量:

export K8S_BIN=/mnt/app/kubernetes/server/bin/
export PATH="$K8S_BIN:$PATH"

1 kubeket服務

kublet是Master在每個Node節點上面的agent,是Node節點上面最重要的模塊,它負責維護和管理該Node上的所有容器,但是如果容器不是通過kubernetes創建的,它並不會管理。本質上,它負責使Pod的運行狀態與期望的狀態一致。

  kublet 運行在每個 worker 節點上,接收 kube-apiserver 發送的請求,管理 Pod 容器,執行交互式命令,如exec、run、logs 等;
kublet 啓動時自動向 kube-apiserver 註冊節點信息,內置的 cadvisor 統計和監控節點的資源使用情況;
爲確保安全,本文檔只開啓接收 https 請求的安全端口,對請求進行認證和授權,拒絕未授權的訪問(如apiserver、heapster)。

而官方推薦我們使用--config指定配置文件,並在配置文件中指定原來這些flag所配置的內容。具體內容可以查看這裏Set Kubelet parameters via a config file。這也是Kubernetes爲了支持動態Kubelet配置(Dynamic Kubelet Configuration)才這麼做的,參考Reconfigure a Node’s Kubelet in a Live Cluster

kubelet的配置文件必須是json或yaml格式,具體可查看這裏

Kubernetes 1.8開始要求關閉系統的Swap,如果不關閉,默認配置下kubelet將無法啓動。 關閉系統的Swap方法如下:

swapoff -a

修改 /etc/fstab 文件,註釋掉 SWAP 的自動掛載,使用free -m確認swap已經關閉。 swappiness參數調整,修改/etc/sysctl.d/k8s.conf添加下面一行:

vm.swappiness=0

在從Kubernetes 1.10開始Dynamic Kubelet Configuration特性進入beta階段,kubelet的大多數命令行參數都改爲推薦在--config指定位置的配置文件中進行配置,包括---cluster-dns--cluster-domain兩個參數.

因爲1.9.0在kubelet裏不再使用KUBELET_API_SERVER來跟API通信,而是通過別一個yaml的配置來實現。

nohup kubelet   --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kube-scheduler/  --v=2 &

使用這個:

nohup kubelet   --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kubelet/  --v=2  --cgroup-driver=systemd   --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice &

/mnt/app/kubernetes/conf/kubelet.yaml:

chown -R kubelet.kubelet /mnt/app/kubernetes/conf/kubelet.yaml

apiVersion: v1
kind: Config
users:
- name: kubelet

cgroupDriver: systemd
clusters:
- name: kubernetes
  cluster:
    server: http://k8s-master:8080
contexts:
- context:
    cluster: kubernetes
    user: kubelet
  name: service-account-context
current-context: service-account-contex

cgroupDriver 默認是cgroupfs

 

  • Kubelet Node Allocatable用來爲Kube組件和System進程預留資源,從而保證當節點出現滿負荷時也能保證Kube和System進程有足夠的資源。
  • 目前支持cpu, memory, ephemeral-storage三種資源預留。
  • Node Capacity是Node的所有硬件資源,kube-reserved是給kube組件預留的資源,system-reserved是給System進程預留的資源, eviction-threshold是kubelet eviction的閾值設定,allocatable纔是真正scheduler調度Pod時的參考值(保證Node上所有Pods的request resource不超過Allocatable)。
  • Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold

--enforce-node-allocatable,默認爲pods,要爲kube組件和System進程預留資源,則需要設置爲pods,kube-reserved,system-reserve。
--cgroups-per-qos,Enabling QoS and Pod level cgroups,默認開啓。開啓後,kubelet會將管理所有workload Pods的cgroups。
--cgroup-driver,默認爲cgroupfs,另一可選項爲systemd。取決於容器運行時使用的cgroup driver,kubelet與其保持一致。比如你配置docker使用systemd cgroup driver,那麼kubelet也需要配置--cgroup-driver=systemd。
--kube-reserved,用於配置爲kube組件(kubelet,kube-proxy,dockerd等)預留的資源量,比如—kube-reserved=cpu=1000m,memory=8Gi,ephemeral-storage=16Gi。
--kube-reserved-cgroup,如果你設置了--kube-reserved,那麼請一定要設置對應的cgroup,並且該cgroup目錄要事先創建好,否則kubelet將不會自動創建導致kubelet啓動失敗。比如設置爲kube-reserved-cgroup=/kubelet.service 。
--system-reserved,用於配置爲System進程預留的資源量,比如—system-reserved=cpu=500m,memory=4Gi,ephemeral-storage=4Gi。
--system-reserved-cgroup,如果你設置了--system-reserved,那麼請一定要設置對應的cgroup,並且該cgroup目錄要事先創建好,否則kubelet將不會自動創建導致kubelet啓動失敗。比如設置爲system-reserved-cgroup=/system.slice。
--eviction-hard,用來配置kubelet的hard eviction條件,只支持memory和ephemeral-storage兩種不可壓縮資源。當出現MemoryPressure時,Scheduler不會調度新的Best-Effort QoS Pods到此節點。當出現DiskPressure時,Scheduler不會調度任何新Pods到此節點。關於Kubelet Eviction的更多解讀,請參考我的相關博文。
Kubelet Node Allocatable的代碼很簡單,主要在pkg/kubelet/cm/node_container_manager.go,感興趣的同學自己去走讀一遍。

–hostname-override 指定 hostname,如果非空會使用這個值作爲節點在集羣中的標識

然後檢查節點是否成功加入集羣:

kubectl get cs,nodes

如果修改了apiserver端口:

 kubectl -s  http://localhost:9090 get cs,nodes

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kubelet.conf

 

2 kube-proxy服務

該模塊實現了kubernetes中的服務發現和反向代理功能。kube-proxy支持TCP和UDP連接轉發,默認基Round Robin算法將客戶端流量轉發到與service對應的一組後端pod。服務發現方面,kube-proxy使用etcd的watch機制監控集羣中service和endpoint對象數據的動態變化,並且維護一個service到endpoint的映射關係,從而保證了後端pod的IP變化不會對訪問者造成影響,另外,kube-proxy還支持session affinity。

 

 

nohup kube-proxy --master http://k8s-master:8080 --hostname-override=k8s-node1 --logtostderr=false --log-dir=/mnt/logs/k8s-kube-proxy --v=2 &

 

kubectl -s  http://localhost:9090 get nodes

 

使用supervisor管理: https://github.com/huangguisu/k8s/tree/master/supervisor/k8s-kube-proxy.conf

 

 

問題


1、kubelet啓動:

# 看到最後一行:error: failed to run Kubelet: failed to create kubelet: misconfiguration: kubelet cgroup driver: "cgroupfs" is different from docker cgroup driver: "systemd"

kubelet的cgroup-driver與docker設置的不一致導致無法啓動

這個好特麼坑,docker是使用cgroup技術來限制容器的資源的。 docker的啓動參數中特意有一個參數是--cgroup-driver
kubelet文件驅動默認cgroupfs, 而我們安裝的docker使用的文件驅動是systemd, 造成不一致, 導致鏡像無法啓動。
現在有兩種方式, 一種是修改docker, 另一種是修改kubelet。
我這裏採用修改docker的方式
注意:

修改或創建/etc/docker/daemon.json,加入下面的內容:

{ "exec-opts": ["native.cgroupdriver=systemd"] }

或者修改docker.service
# vim /lib/systemd/system/docker.service
# 將 --exec-opt native.cgroupdriver=systemd  修改爲:
#  --exec-opt native.cgroupdriver=cgroupfs
# systemctl daemon-reload
# systemctl restart docker.service
# kubelet顯示正常

修改kubelet的啓動參數--cgroup-driver=systemd:

kubelet   --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kubelet/  --v=2  --cgroup-driver=systemd

 

2、kubelet啓動報錯:

0617 14:25:16.541259   26288 summary.go:102] Failed to get system container stats for "/system.slice/docker.service": failed to get cgroup stats for "/system.slice/docker.service": failed to get container info for "/system.slice/docker.service": unknown container "/system.slice/docker.service"

解決方案,添加啓動參數:

--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice

 

3、 用kubectl logs <podname> -n kube-system查看日誌會發現有這樣的日誌存在
Expected to load root CA config from /var/run/secrets/kubernetes.io/serviceaccount/ca.crt, but got err: open /var/run/secrets/kubernetes.io/serviceaccount/ca.crt: no such file or directory
這是因爲kubernetes默認創建的secrets 資源不包含用於訪問apiserver的根證書
這需要重新生產證書和祕鑰

 

4、日誌報錯:k8s-kube-scheduler

Error from server (NotFound): the server could not find the requested resource

或者kubectl get nodes                               
error: the server doesn't have a resource type "nodes"

錯誤原因:

默認連接的server 是http://localhost:8080,由於改了端口號需指定server

alias kubectl=" kubectl -s http://localhost:9090"
echo  alias kubectl=" kubectl -s http://localhost:9090"  >>  ~/.bashrc



 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章