注:本案例在個人部署環境下是可行的,但不保證在全部環境下均可行。我儘量講得直白而詳細,由於我本身也纔剛開始接觸,已經作過深刻研究的能夠瀏覽,如有什麼錯誤,煩請指正,感激涕零!node
個人環境: K8S1.0.0+flannel+docker1.6的分佈式集羣。git
這裏先不贅述flannel的部署了,之後有時間再寫相關的文檔。github
先講講kubernetes的serviceaccount,咱們的服務有時候須要一些帶有隱私信息的東西,token,certification file等等,這些東西咱們能夠在master上建立,而後在建立pod的時候導入進去。具體能夠去看github上的secret.md,那裏有具體的例子。golang
咱們執行:web
kubectl get serviceaccount
若是以下:docker
NAME SECRETS default 1
那麼是正常的(用腳本啓動的kubernetes通常會是這樣的狀況) 而若是是:json
NAME SECRETS default 0
這就麻煩了,用腳本啓動k8s,啓動的時候是會自動建立一個serviceaccount的,而serviceaccount建立出來的時候又會自動建立一個secret做爲這個serviceaccount的token。api
咱們在apiserver的啓動參數中添加:curl
--admission_control=ServiceAccount
apiserver在啓動的時候會本身建立一個key和crt(見/var/run/kubernetes/apiserver.crt
和apiserver.key
)tcp
而後在啓動./kube-controller-manager
時添加flag:
--service_account_private_key_file=/var/run/kubernetes/apiserver.key
這樣啓動k8smaster後,咱們就會發現
kubectl get serviceaccount
結果以下:
NAME SECRETS default 1
注意,這裏可能會啓動apiserver失敗,或者啓動後沒有效果,由於沒有secrets的serviceaccount會保存在etcd中,因此咱們在正常啓動前最好刪掉etcd中的舊數據($etcdctl rm --recursive registry
)。
正常啓動後咱們在這種狀態下建立pod,pod中會加入serviceaccount這個字段,即使咱們在建立的json或yaml中不指定,那麼它的默認值也會是默認的serviceaccount:default。 而這個serviceaccount的secret就會被導入到pod啓動的containers中。 舉個例子,咱們在這種狀態下建立一個pod,而後執行:
[root@vm-56-65 bin]# kubectl get pods/imgpod -o yaml
在yaml中會發現:
spec: containers: - image: registry.hub.gome.com.cn/img_server:1.1 imagePullPolicy: IfNotPresent name: imgpod resources: limits: cpu: 600m memory: 1181116006400m terminationMessagePath: /dev/termination-log volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: default-token-n0i1i readOnly: true dnsPolicy: ClusterFirst nodeName: 10.58.56.62 restartPolicy: Always serviceAccountName: default volumes: - name: default-token-n0i1i secret: secretName: default-token-n0i1i
有了serviceaccountName字段,而且volumn裝載了一個secret.是的,這個secret:default-token-n0i1i就是咱們default這個serviceaccount下的secret。它被裝載到mountPath: /var/run/secrets/kubernetes.io/serviceaccount
目錄中,咱們若是在slaver上進入相關容器,即可以找到這個目錄和相應的token(注:建立這個pod的json中不用指定serviceaccount,也不用寫volumn字段去掛載secret,這些都會自動完成的,是否能夠手動指定呢?期待大神們的指點)。
爲何要先說這些呢? 由於咱們的heapster啓動的時候會有這種狀況: pod狀態爲running,可是反覆地restart;咱們用webapi查看該pod的日誌,發現:
/var/run/secret/kubernetes.io/serviceaccount/token no such file or directory
我認爲這是由於heapster在運行時須要向k8smaster作https的鏈接,可是沒有token和證書是不能鏈接的,heapster的程序找不到token就error並exit了,k8s會再啓動之,因而就反覆restart。
以下是我heapster啓動的json(一個replicationcontroller)
heaprep.json: { "apiVersion": "v1", "kind": "ReplicationController", "metadata": { "labels": { "name": "heapster" }, "name": "monitoring-heapster-controller" }, "spec": { "replicas": 1, "selector": { "name": "heapster" }, "template": { "metadata": { "labels": { "name": "heapster" } }, "spec": { "containers": [ { "image": "registry.hub.gome.com.cn/kubernetes/heapster:v0.16.0", "name": "heapster", "command":[ "/heapster", "--source=kubernetes:'https://kubernetes:443?auth='", "--sink=influxdb:http://10.126.53.10:8086" ], "resources": { "limits":{ "cpu":"0.5", "memory":"1.1Gi" } }, "env": [ { "name": "KUBERNETES_SERVICE_HOST", "value": "vm-56-65" } ] } ] } } } }
這裏"env"中的環境變量是必需要加的,不然heapster會報錯,具體什麼錯不大記得了,應該是有關10.0.0.1 這個域名的(heapster中的KUBERNETES_SERVICE_HOST變量默認是10.0.0.1)。 *10.0.0.1是k8s集羣中master服務的ClusterIP(kubectl get svc 就能夠看到),其餘slaver是能夠經過這個ip:port訪問到master服務的。可是由於heapster作的是https的請求,須要crt證書和token。而10.0.0.1不是一個hostname而且沒有相關的證書(感受這是heapster最大的一個坑),因此我乾脆本身作證書,本身作hosts引導,本身作環境變量。
如今咱們須要一個hostname爲vm-56-65的證書,執行這些命令:
openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -subj "/CN=abc.com" -days 5000 -out ca.crt openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/CN=vm-56-65" -out server.csr openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000
注意,這裏兩個 -subj "***"中第二個要寫hostname,且強烈建議第一個subj和第二個不要相同(設爲相同可能會致使普通的curl https命令認證失敗)。具體關於證書的生成,能夠參考: http://wangzhezhe.github.io/blog/2015/08/05/httpsandgolang/ 執行這些命令後,會生成一系列文件,將它們一併copy到master的/var/run/kubernetes/
中,咱們的master啓動要用這些證書文件:
./kube-apiserver --logtostderr=true --log-dir=/var/log/ --v=0 --admission_control=ServiceAccount --etcd_servers=http://127.0.0.1:4001 --insecure_bind_address=0.0.0.0 --insecure_port=8080 --kubelet_port=10250 --service-cluster-ip-range=10.0.0.1/24 --allow_privileged=false --service-node-port-range='30000-35535' --secure-port=443 --client_ca_file=/var/run/kubernetes/ca.crt --tls-private-key-file=/var/run/kubernetes/server.key --tls-cert-file=/var/run/kubernetes/server.crt
這裏--secure-port=443
是由於我在heapster訪問master時,沒有采用內部ClusterIP,而是直接訪問物理IP,而端口沒有變,因此將master上apiserver的https監聽端口修改了以便訪問。
這樣啓動了apiserver後,咱們再從新create pod。 容器啓動,咱們進入pod的日誌,看到很是多的:
dial tcp: lookup vm-56-65: no such host
進入容器中修改容器裏的/etc/hosts,添加一個:
10.58.56.65 vm-56-65
如前文所說,我這裏用了物理ip,固然,若是咱們這裏配10.0.0.1 也是能夠的(若是使用10.0.0.1,api-server啓動的時候就不用再添加--secure-port=443
了)。 具體怎麼進容器、改hosts這裏我就不細講了,你們都懂的~
修改完畢後,再刷新幾回pod的日誌,會發現,日誌慢慢就不更新了(或者該說,不報錯了),恭喜你,heapster已經在正常跑了。
不止如此,只要再添加一個token的配置,就能夠在任何一臺能與10.58.56.65直連的機器上,向apiserver作帶認證的https請求。
heapster最大的好處是其抓取的監控數據能夠按pod,container,namespace等方式group,這樣就能進行監控信息的隱私化,即每一個k8s的用戶只能看到本身的應用的資源使用狀況,然後臺管理者又能看到每臺機器的資源使用狀況,相似自動擴容之類的功能就有了一個可靠的信息來源。
以上只是我我的在部署過程當中遇到的問題,不能保證這個方案100%可行,我也仍在作進一步的研究,相信heapster還有不少的坑,你們多多交流吧~^_^