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-scheduler
、kube-controller-manager
和kube-apiserver
三者的功能緊密相關;- 同時只能有一個
kube-scheduler
、kube-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接口,成爲集羣內各個功能模塊之間數據交互和通信的中心樞紐,是整個系統的數據總線和數據中心。除此之外,他還有以下的特性:
- 是集羣管理的API入口;
- 是資源配額控制的入口;
- 提供完備的集羣安全機制;
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: kubeletcgroupDriver: 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