天天看點

以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叢集的探索

繼續閱讀