以Kubeadm方式安裝的Kubernetes集羣的探索

以Kubeadm方式安裝的Kubernetes集羣的探索 博客分類: Kubernetes

當前手上有兩個Kubernetes cluster,一個是採用kube-up.sh安裝的k8s 1.3.7版本,另外一個則是採用kubeadm安裝的k8s 1.5.1版本。由於1.3.7版本安裝在前,並且目前它也是承載了我們PaaS平臺的環境,因此對於這個版本的Kubernetes安裝環境、配置操作、日誌查看、集羣操作等相對較爲熟悉。而Kubeadm安裝的1.5.1版本K8s集羣在組件部署、配置、日誌等諸多方面與1.3.7版本有了較大差異。剛上手的時候,你會發現你原來所熟知的1.3.7的東西都不在原先的位置上了。估計很多和我一樣,採用kubeadm將集羣升級到1.5.1版本的朋友們都會遇到這類問題,於是這裏打算對Kubeadm方式安裝的Kubernetes集羣進行一些小小的探索,把一些變動較大的點列出來,供大家參考。

一、環境

這裏使用的依然是文章《使用Kubeadm安裝Kubernetes》中安裝完畢的Kubernetes 1.5.1集羣環境,底層是阿里雲ECS,操作系統是Ubuntu 16.04.1。網絡用的是weave network

試驗集羣只有兩個Node:一個master node和一個minion node。但Master node由於被taint了,因此它與minion node一樣參與集羣調度和承擔負載。

二、核心組件的Pod化

Kubeadm安裝的k8s集羣與kube-up.sh安裝集羣相比,最大的不同應該算是kubernetes核心組件的Pod化,即:kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、kube-discovery以及etcd等核心組件都運行在集羣中的Pod裏的,這頗有些CoreOS的風格。只有一個組件是例外的,那就是負責在node上與本地容器引擎交互的Kubelet。

K8s的核心組件Pod均放在kube-system namespace中,通過kubectl(on master node)可以查看到:

# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
etcd-iz25beglnhtz 1/1 Running 2 26d
kube-apiserver-iz25beglnhtz 1/1 Running 3 26d
kube-controller-manager-iz25beglnhtz 1/1 Running 2 26d
kube-scheduler-iz25beglnhtz 1/1 Running 4 26d
... ...

另外細心的朋友可能會發現,這些核心組建的Pod名字均以所在Node的主機名爲結尾,比如:kube-apiserver-iz25beglnhtz中的”iz25beglnhtz”就是其所在Node的主機名。

不過,即便這些核心組件是一個容器的形式運行在集羣中,組件所使用網絡依然是所在Node的主機網絡,而不是Pod Network

# docker ps|grep apiserver 98ea64bbf6c8 gcr.io/google_containers/kube-apiserver-amd64:v1.5.1 "kube-apiserver --ins" 10 days ago Up 10 days k8s_kube-apiserver.6c2e367b_kube-apiserver-iz25beglnhtz_kube-system_033de1afc0844729cff5e100eb700a81_557d1fb2
4f87d22b8334 gcr.io/google_containers/pause-amd64:3.0 "/pause" 10 days ago Up 10 days k8s_POD.d8dbe16c_kube-apiserver-iz25beglnhtz_kube-system_033de1afc0844729cff5e100eb700a81_5931e490

# docker inspect 98ea64bbf6c8 ... ...
"HostConfig": {
"NetworkMode": "container:4f87d22b833425082be55851d72268023d41b50649e46c738430d9dfd3abea11",
}
... ...

# docker inspect 4f87d22b833425082be55851d72268023d41b50649e46c738430d9dfd3abea11 ... ...
"HostConfig": {
"NetworkMode": "host",
}
... ...

從上面docker inspect的輸出可以看出kube-apiserver pod裏面的pause容器採用的網絡模式是host網絡,而以pause容器網絡爲基礎的kube-apiserver 容器顯然就繼承了這一network namespace。因此從外面看,訪問Kube-apiserver這樣的組件和以前沒什麼兩樣:在Master node上可以通過localhost:8080訪問;在Node外,可以通過master_node_ip:6443端口訪問。

三、核心組件啓動配置調整

在kube-apiserver等核心組件還是以本地程序運行在物理機上的時代,修改kube-apiserver的啓動參數,比如修改一下–service-node-port-range的範圍、添加一個–basic-auth-file等,我們都可以通過直接修改/etc/default/kube-apiserver(以Ubuntu 14.04爲例)文件的內容並重啓kube-apiserver service(service restart kube-apiserver)的方式實現。其他核心組件:諸如:kube-controller-manager、kube-proxy和kube-scheduler均是如此。

但在kubeadm時代,這些配置文件不再存在,取而代之的是和用戶Pod描述文件類似的manifest文件(都放置在/etc/kubernetes/manifests下面):

/etc/kubernetes/manifests# ls
etcd.json kube-apiserver.json kube-controller-manager.json kube-scheduler.json

我們以爲kube-apiserver增加一個啓動參數:”–service-node-port-range=80-32767″ 爲例:

打開並編輯/etc/kubernetes/manifests/kube-apiserver.json,在“command字段對應的值中添加”–service-node-port-range=80-32767″:

"containers": [
 {
 "name": "kube-apiserver",
 "image": "gcr.io/google_containers/kube-apiserver-amd64:v1.5.1",
 "command": [
 "kube-apiserver",
 "--insecure-bind-address=127.0.0.1",
 "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
 "--service-cluster-ip-range=10.96.0.0/12",
 "--service-account-key-file=/etc/kubernetes/pki/apiserver-key.pem",
 "--client-ca-file=/etc/kubernetes/pki/ca.pem",
 "--tls-cert-file=/etc/kubernetes/pki/apiserver.pem",
 "--tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem",
 "--token-auth-file=/etc/kubernetes/pki/tokens.csv",
 "--secure-port=6443",
 "--allow-privileged",
 "--advertise-address=10.47.217.91",
 "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
 "--anonymous-auth=false",
 "--etcd-servers=http://127.0.0.1:2379",
 "--service-node-port-range=80-32767"
 ],

注意:不要忘記在–etcd-servers這一行後面添加一個逗號,否則kube-apiserver會退出。

修改後,你會發現kube-apiserver會被自動重啓。這是kubelet的功勞。kubelet在啓動時監聽/etc/kubernetes/manifests目錄下的文件變化並做適當處理:

# ps -ef|grep kubelet
root 1633 1 5 2016 ? 1-09:24:47 /usr/bin/kubelet --kubeconfig=/etc/kubernetes/kubelet.conf --require-kubeconfig=true --pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin --cluster-dns=10.96.0.10 --cluster-domain=cluster.local

kubelet自身是一個systemd的service,它的啓動配置可以通過下面文件修改:

# cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf [Service] Environment="KUBELET_KUBECONFIG_ARGS=--kubeconfig=/etc/kubernetes/kubelet.conf --require-kubeconfig=true" Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true" Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin" Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local" ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_EXTRA_ARGS 

四、kubectl的配置

kube-up.sh安裝的k8s集羣會在每個Node上的~/.kube/下創建config文件,用於kubectl訪問apiserver和操作集羣使用。但在kubeadm模式下,~/.kube/下面的內容變成了:

~/.kube# ls
cache/ schema/

於是有了問題1:config哪裏去了?

之所以在master node上我們的kubectl依舊可以工作,那是因爲默認kubectl會訪問localhost:8080來與kube-apiserver交互。如果kube-apiserver沒有關閉–insecure-port,那麼kubectl便可以正常與kube-apiserver交互,因爲–insecure-port是沒有任何校驗機制的。

於是又了問題2:如果是其他node上的kubectl與kube-apiserver通信或者master node上的kubectl通過secure port與kube-apiserver通信,應該如何配置?

接下來,我們一併來回答上面兩個問題。kubeadm在創建集羣時,在master node的/etc/kubernetes下面創建了兩個文件:

/etc/kubernetes# ls -l
total 32
-rw------- 1 root root 9188 Dec 28 17:32 admin.conf
-rw------- 1 root root 9188 Dec 28 17:32 kubelet.conf
... ...

這兩個文件的內容是完全一樣的,僅從文件名可以看出是誰在使用。比如kubelet.conf這個文件,我們就在kubelet程序的啓動參數中看到過:–kubeconfig=/etc/kubernetes/kubelet.conf

# ps -ef|grep kubelet
root 1633 1 5 2016 ? 1-09:26:41 /usr/bin/kubelet --kubeconfig=/etc/kubernetes/kubelet.conf --require-kubeconfig=true --pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin --cluster-dns=10.96.0.10 --cluster-domain=cluster.local

打開這個文件,你會發現這就是一個kubeconfig文件,文件內容較長,我們通過kubectl config view來查看一下這個文件的結構:

# kubectl --kubeconfig /etc/kubernetes/kubelet.conf config view apiVersion: v1 clusters:
- cluster:
 certificate-authority-data: REDACTED
 server: https://{master node local ip}:6443
 name: kubernetes
contexts:
- context:
 cluster: kubernetes
 user: admin
 name: admin@kubernetes
- context:
 cluster: kubernetes
 user: kubelet
 name: kubelet@kubernetes
current-context: admin@kubernetes kind: Config preferences: {} users:
- name: admin
 user:
 client-certificate-data: REDACTED
 client-key-data: REDACTED
- name: kubelet
 user:
 client-certificate-data: REDACTED
 client-key-data: REDACTED

這和我們在《Kubernetes集羣Dashboard插件安裝》一文中介紹的kubeconfig文件內容並不二致。不同之處就是“REDACTED”這個字樣的值,我們對應到kubelet.conf中,發現每個REDACTED字樣對應的都是一段數據,這段數據是由對應的數字證書內容或密鑰內容轉換(base64)而來的,在訪問apiserver時會用到。

我們在minion node上測試一下:

minion node:

# kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?

# kubectl --kubeconfig /etc/kubernetes/kubelet.conf get pods
NAME READY STATUS RESTARTS AGE
my-nginx-1948696469-359d6 1/1 Running 2 26d
my-nginx-1948696469-3g0n7 1/1 Running 3 26d
my-nginx-1948696469-xkzsh 1/1 Running 2 26d
my-ubuntu-2560993602-5q7q5 1/1 Running 2 26d
my-ubuntu-2560993602-lrrh0 1/1 Running 2 26d

kubeadm創建k8s集羣時,會在master node上創建一些用於組件間訪問的證書、密鑰和token文件,上面的kubeconfig中的“REDACTED”所代表的內容就是從這些文件轉化而來的:

/etc/kubernetes/pki# ls
apiserver-key.pem apiserver.pem apiserver-pub.pem ca-key.pem ca.pem ca-pub.pem sa-key.pem sa-pub.pem tokens.csv
  • apiserver-key.pem:kube-apiserver的私鑰文件
  • apiserver.pem:kube-apiserver的公鑰證書
  • apiserver-pub.pem kube-apiserver的公鑰文件
  • ca-key.pem:CA的私鑰文件
  • ca.pem:CA的公鑰證書
  • ca-pub.pem :CA的公鑰文件
  • sa-key.pem :serviceaccount私鑰文件
  • sa-pub.pem :serviceaccount的公鑰文件
  • tokens.csv:kube-apiserver用於校驗的token文件

在k8s各核心組件的啓動參數中會看到上面文件的身影,比如:

 kube-apiserver --insecure-bind-address=127.0.0.1 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota --service-cluster-ip-range=10.96.0.0/12 --service-account-key-file=/etc/kubernetes/pki/apiserver-key.pem --client-ca-file=/etc/kubernetes/pki/ca.pem --tls-cert-file=/etc/kubernetes/pki/apiserver.pem --tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem --token-auth-file=/etc/kubernetes/pki/tokens.csv --secure-port=6443 --allow-privileged --advertise-address={master node local ip} --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --anonymous-auth=false --etcd-servers=http://127.0.0.1:2379 --service-node-port-range=80-32767 

我們還可以在minion node上通過curl還手工測試一下通過安全通道訪問master node上的kube-apiserver。在《Kubernetes集羣的安全配置》一文中,我們提到過k8s的authentication(包括:客戶端證書認證、basic auth、static token等)只要通過其中一個即可。當前kube-apiserver開啓了客戶端證書認證(–client-ca-file)和static token驗證(–token-auth-file),我們只要通過其中一個,就可以通過authentication,於是我們使用static token方式。static token file的內容格式:

token,user,uid,"group1,group2,group3" 

對應到master node上的tokens.csv

# cat /etc/kubernetes/pki/tokens.csv
{token},{user},812ffe41-cce0-11e6-9bd3-00163e1001d7,system:kubelet-bootstrap

我們用這個token通過curl與apiserver交互:

# curl --cacert /etc/kubernetes/pki/ca.pem -H "Authorization: Bearer {token}" https://{master node local ip}:6443 { "paths": [ "/api", "/api/v1", "/apis", "/apis/apps", "/apis/apps/v1beta1", "/apis/authentication.k8s.io", "/apis/authentication.k8s.io/v1beta1", "/apis/authorization.k8s.io", "/apis/authorization.k8s.io/v1beta1", "/apis/autoscaling", "/apis/autoscaling/v1", "/apis/batch", "/apis/batch/v1", "/apis/batch/v2alpha1", "/apis/certificates.k8s.io", "/apis/certificates.k8s.io/v1alpha1", "/apis/extensions", "/apis/extensions/v1beta1", "/apis/policy", "/apis/policy/v1beta1", "/apis/rbac.authorization.k8s.io", "/apis/rbac.authorization.k8s.io/v1alpha1", "/apis/storage.k8s.io", "/apis/storage.k8s.io/v1beta1", "/healthz", "/healthz/poststarthook/bootstrap-controller", "/healthz/poststarthook/extensions/third-party-resources", "/healthz/poststarthook/rbac/bootstrap-roles", "/logs", "/metrics", "/swaggerapi/", "/ui/", "/version" ] }
本文轉自開源中國-以Kubeadm方式安裝的Kubernetes集羣的探索
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章