kubernetes是Google開源的基于Docker的容器叢集管理系統,是谷歌内部大規模叢集管理系統Borg的開源版本。kubernetes基于Borg叢集軟體模型。
Kubernetes(K8s)是一個真正的平台,提供運作環境,使得複雜要求的應用在上面建構。它通過yaml語言寫的配置檔案,很簡單快速的就能自動通過Docker鏡像部署好應用環境,支援應用橫向擴充,并且可以組織、編排、管理和遷移這些容器化的應用。
本文主要介紹在Ubuntu16.04上使用kubeadm搭建kubernetes1.5.5環境。
kubeadm是kubernetes的自動部署化工具旨在改善開發者在安裝、調試和使用k8s時的體驗,降低安裝和使用門檻。理論上通過兩個指令:init和join即可搭建出一套完整的Kubernetes cluster。理論上通過kubeadm使用init和join指令即可建立一個叢集,這init就是在master節點對叢集進行初始化。和k8s之前的部署方式不同的是kubeadm安裝的k8s核心元件都是以容器的形式運作于master node上的。
Kubeadm被設計成針對大規模叢集部署環境中使用的,當然也可以很容易的手動安裝。如果在你自己IaaS基礎架構上或者已經存在的自動化系統上部署Kubernetes,kubeadm是一個很好的選擇。
不過,kubeadm目前也在active development中,也不是那麼stable,是以即便在目前最新的k8s 1.5.5版本中,它仍然處于Alpha狀态,官方不建議在Production環境下使用。每次執行kubeadm init時,它都會列印如下提醒日志:
[kubeadm] WARNING: kubeadm is in alpha, please do not use it for production clusters.
一:前期環境準備與限制
- Kubernetes官網上提到kubeadm支援的Ubuntu 16.04+, CentOS 7 or HypriotOSv1.0.1+三種作業系統。
- 并且每台機器至少要有1GB記憶體,不然叢集運作之後,留給運作在容器内的應用的記憶體就很少了。
- 同時要保證所有機器之前的網絡是互相連通的。
我準備了兩台Ubuntu 16.04虛拟機,一個作為master,一個作為node。
Kubeadm預設安裝時,master node将不會參與Pod排程,不會承載work load,即不會有非核心元件的Pod在Master node上被建立出來。當然通過kubectl taint指令可以解除這一限制,不過這是後話了。
準備了兩台Ubuntu 16.04虛拟機,叢集拓撲參數如下:
節點名 IP位址 CPU 記憶體
ubuntu-01 192.168.11.74 2核 4GB
ubuntu-02 192.168.11.75 2核 4GB
二:部署目标
- 部署一套兩個節點的Kubernetes叢集。
- 在叢集上安裝Pod網絡插件flannel,允許POD之間互相通訊。
- 在Kubernetes叢集上部署一個微服務應用樣例。
三 部署步驟
3.1 部署Kubernetes Master
安裝内容包括:
- docker:容器運作的軟體。
- kubelet:kubelet是Kubernets最重要的元件,它要運作在叢集上所有的機器,用來執行類似于開啟pods和容器。
- kubectl:在叢集運作時,控制容器的部件。隻需要将其運作在主節點上,但是它将對所有節點都有效。
- Kubeadm:叢集部署工具。
以下指令,在兩個Node上均要執行。
3.1.1 安裝docker 和kubernetes元件
添加apt-key
apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
添加Kubernetes源
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
更新包資訊
apt-get update
安裝docker
說明:此篇文檔安裝docker是內建與kubernetes源中的。如果需要提前安裝或者單獨安裝docker 請參考:
https://docs.docker.com/engine/installation/linux/ubuntu/#install-docker
apt-get install -y docker.io
#如果已經安裝了docker這步可以跳過。
安裝Kubernetes核心元件
apt-get install -y kubelet kubeadm kubectl kubernetes-cni
# 此處的Kubernetes的核心元件,包括kubelet、kubeadm、kubectl和kubernetes-cni等
下載下傳後的kube元件會自動運作起來。在 /lib/systemd/system下面我們能看到kubelet.service:
# cat /lib/systemd/system/kubelet.service
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
[Service]
ExecStart=/usr/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target
注意:以上指令所有節點都需要執行。
3.1.2 初始化叢集
理論上通過kubeadm使用init和join指令即可建立一個叢集,這init就是在master節點對叢集進行初始化。和k8s 之前的部署方式不同的是kubeadm安裝的k8s核心元件都是以容器的形式運作于master node上的。是以需要一些鏡像。
由于牆的原因無法直接通路到Google的軟體倉庫(packages.cloud.google.com)和容器倉庫(gcr.io),解決方法有兩種:一是直接配置的Hosts檔案,二是使用三方源或轉存的容器倉庫。這裡使用修改Hosts檔案的方法。
把下面幾行内容加入到hosts檔案中
# vim /etc/hosts
gcr.io
www.gcr.io
packages.cloud.google.com
最新可用的Google hosts檔案可在這裡擷取:https://github.com/racaljk/hosts
kubeadm要從gcr.io/google_containers repository中pull許多核心元件的images,大約有如下一些:
gcr.io/google_containers/kube-apiserver-amd64 v1 c9bd8bd15d days ago MB
gcr.io/google_containers/kube-controller-manager-amd64 v1 f9819d4efc8 days ago MB
gcr.io/google_containers/kube-proxy-amd64 v1 f37c0b77c days ago MB
gcr.io/google_containers/kube-scheduler-amd64 v1 b06cdc92ebd9 days ago MB
gcr.io/google_containers/etcd-amd64 -kubeadm d31c95 months ago MB
gcr.io/google_containers/kubedns-amd64 c708a19f42 months ago MB
gcr.io/google_containers/dnsmasq-metrics-amd64 aabced07 months ago MB
gcr.io/google_containers/kube-dnsmasq-amd64 ec65756a89b months ago MB
gcr.io/google_containers/kube-discovery-amd64 fd11e7a0f months ago MB
gcr.io/google_containers/exechealthz-amd64 a43bfb39bf months ago MB
gcr.io/google_containers/pause-amd64 f495ffa months ago kB
3.1.3 初始化master
在Kubeadm的文檔中,Pod Network的安裝是作為一個單獨的步驟的。kubeadm init并沒有選擇一個預設的Pod network進行安裝。這裡采用Flannel 作為Pod network,如果我們要使用Flannel,那麼在執行init時,按照kubeadm文檔要求,我們必須給init指令帶上option:–pod-network-cidr=10.244.0.0/16。如果有多網卡的,可以根據實際情況配置–api-advertise-addresses=,單網卡情況可以省略。多網卡的并沒有驗證過。
使用kubeadm init初始化kubernetes master。執行kubeadm init指令:
# kubeadm init --pod-network-cidr=10.244.0.0/16
[kubeadm] WARNING: kubeadm is in alpha, please do not use it for production clusters.
[preflight] Running pre-flight checks
[init] Using Kubernetes version: v1
[tokens] Generated token: "3c43f1.9a42d02deda012ef"
[certificates] Generated Certificate Authority key and certificate.
[certificates] Generated API Server key and certificate
[certificates] Generated Service Account signing keys
[certificates] Created keys and certificates in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[apiclient] Created API client, waiting for the control plane to become ready
[apiclient] All control plane components are healthy after seconds
[apiclient] Waiting for at least one node to register and become ready
[apiclient] First node is ready after seconds
[apiclient] Creating a test deployment
[apiclient] Test deployment succeeded
[token-discovery] Created the kube-discovery deployment, waiting for it to become ready
[token-discovery] kube-discovery is ready after seconds
[addons] Created essential addon: kube-proxy
[addons] Created essential addon: kube-dns
Your Kubernetes master has initialized successfully!
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
http://kubernetes.io/docs/admin/addons/
You can now join any number of machines by running the following on each node:
kubeadm join --token=c43f1a42d02deda012ef
3.1.3.1 驗證初始化
kubeadm join –token=3c43f1.9a42d02deda012ef 192.168.11.74初始化成功後,檢查Kubernetes的核心元件均正常啟動。
一種方式通過程序方式啟動的,一種通過容器方式啟動的。
程序方式啟動:
#ps -ef|grep kube
root Mar31 ? :: /opt/bin/flanneld --ip-masq --kube-subnet-mgr
root Mar31 ? :: /bin/sh -c set -e -x; cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/-flannel.conf; while true; do sleep ; done
root Mar31 ? :: /kube-dns --domain=cluster.local --dns-port= --config-map=kube-dns --v=
root Mar31 ? :: /exechealthz --cmd=nslookup kubernetes.default.svc.cluster.local >/dev/null --url=/healthz-dnsmasq --cmd=nslookup kubernetes.default.svc.cluster.local : >/dev/null --url=/healthz-kubedns --port= --quiet
root Mar31 ? :: /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= --cluster-domain=cluster.local
root Mar31 ? :: kube-apiserver --insecure-bind-address= --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota --service-cluster-ip-range=/ --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= --allow-privileged --advertise-address= --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --anonymous-auth=false --etcd-servers=http://127.0.0.1:2379
root Mar31 ? :: /usr/local/bin/kube-discovery
root Mar31 ? :: kube-proxy --kubeconfig=/run/kubeconfig
root : ? :: kube-controller-manager --address= --leader-elect --master=: --cluster-name=kubernetes --root-ca-file=/etc/kubernetes/pki/ca.pem --service-account-private-key-file=/etc/kubernetes/pki/apiserver-key.pem --cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem --cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem --insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap --allocate-node-cidrs=true --cluster-cidr=/
root : ? :: kube-scheduler --address= --leader-elect --master=:
root : pts/ :: grep --color=auto kube
以容器方式啟動的各個元件
c04fe13e2 gcr.io/google_containers/etcd-amd64:-kubeadm "etcd --listen-client" hours ago Up hours k8s_etcd.c323986f_etcd-luyun-ubuntu1604-_kube-system_3a26566bb004c61cd05382212e3f978f_ae83a29b
d0716998ed9c gcr.io/google_containers/kube-scheduler-amd64:v1 "kube-scheduler --add" hours ago Up hours k8s_kube-schedulereffd754_kube-scheduler-luyun-ubuntu1604-_kube-system_3b5b3d1d0ac46813935348ff689f3682_014091fb
d248f44 gcr.io/google_containers/kube-controller-manager-amd64:v1 "kube-controller-mana" hours ago Up hours k8s_kube-controller-manager.a14db2e9_kube-controller-manager-luyun-ubuntu1604-_kube-system_dfaeb92756800dbc0ecd2345b9739eda_35ef6a2f
f76220ab3e97 nginx: "nginx -g 'daemon off" hours ago Up hours k8s_my-nginxf88336e_my-nginx--j3cx_default_78b9446c-f1--ca7-fa163eeee269_49d49f85
c340de gcr.io/google_containers/pause-amd64: "/pause" hours ago Up hours k8s_POD.d8dbe16c_my-nginx--j3cx_default_78b9446c-f1--ca7-fa163eeee269_2aab9aee
a7f4654ca5a3 gcr.io/google_containers/exechealthz-amd64: "/exechealthz '--cmd=" hours ago Up hours k8s_healthzb93f43_kube-dns--nln_kube-system_6411f13b-ee--ca7-fa163eeee269_6ebbcad4
d402450ac7d7 gcr.io/google_containers/dnsmasq-metrics-amd64: "/dnsmasq-metrics --v" hours ago Up hours k8s_dnsmasq-metrics.e7b55ee6_kube-dns--nln_kube-system_6411f13b-ee--ca7-fa163eeee269_cffd3cf9
ab13faadc4 gcr.io/google_containers/kube-dnsmasq-amd64: "/usr/sbin/dnsmasq --" hours ago Up hours k8s_dnsmasq.bf9489f0_kube-dns--nln_kube-system_6411f13b-ee--ca7-fa163eeee269_e18d2ff0
ee1e3574 gcr.io/google_containers/kubedns-amd64: "/kube-dns --domain=c" hours ago Up hours k8s_kube-dns.d3da1fe_kube-dns--nln_kube-system_6411f13b-ee--ca7-fa163eeee269_f98f846e
a4f49289d892 gcr.io/google_containers/pause-amd64: "/pause" hours ago Up hours k8s_POD.d8dbe16c_kube-dns--nln_kube-system_6411f13b-ee--ca7-fa163eeee269_cf0167a8
...
...
不過這些核心元件并不是跑在pod network中的(沒錯,此時的pod network還沒有建立),而是采用了host network。
# kubectl get pod --all-namespaces -o wide
kube-system dummy--zs5xs / Running h ubuntu-
kube-system ubuntu- / Running h ubuntu-
kube-system kube-apiserver-ubuntu- / Running h ubuntu-
kube-system kube-controller-manager-ubuntu- / Running h ubuntu-
kube-system kube-discovery--sdx9n / Running h ubuntu-
kube-system kube-dns--nln / ContainerCreating h ubuntu-
kube-system kube-proxy-dv / Running h ubuntu-
kube-system kube-scheduler-ubuntu-- / Running h ubuntu-
3.1.4 安裝flannel pod網絡
初始化叢集後,檢視一下元件狀态,會發現異常
通過指令kubectl get pod –all-namespaces -o wide,你也會發現kube-dns pod處于ContainerCreating狀态。檢視dns日志會發現一些錯誤的資訊:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
s s {default-scheduler } Normal Scheduled Successfully assigned kube-dns--h6kt to ubuntu-
s s {kubelet ubuntu-} Warning FailedSync Error syncing pod, skipping: failed to "SetupNetwork" for "kube-dns-2924299975-0h6kt_kube-system" with SetupNetworkError: "Failed to setup network for pod \"kube-dns--h6kt_kube-system(cc36f-ec--bf45-fa163eeee269)\" using network plugins \"cni\": open /run/flannel/subnet.env: no such file or directory; Skipping pod"
這種錯誤是由于沒有裝網絡元件造成的,是以我們要安裝網絡元件。
Kubernetes一共提供五種網絡元件,可以根據自己的需要選擇。我使用的Flannel網絡,需要執行如下安裝指令:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
serviceaccount "flannel" created
configmap "kube-flannel-cfg" created
daemonset "kube-flannel-ds" created
也可以将flannel從git上下載下傳到本地。執行安裝指令:
kubectl apply -f /root/flannel/Documentation/kube-flannel.yml
安裝flannel需要下載下傳flannel鏡像,安裝過程需要一定的時間。
稍等片刻,我們再來看master node上的cluster資訊:
# ps aux|grep kube|grep flannel
root ? Ssl Mar31 : /opt/bin/flanneld --ip-masq --kube-subnet-mgr
root ? Ss Mar31 : /bin/sh -c set -e -x; cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/-flannel.conf; while true; do sleep ; done
檢查各節點元件運作狀态,叢集的核心元件已經全部run起來了:
kube-system dummy--zs5xs / Running h ubuntu-
kube-system ubuntu- / Running h ubuntu-
kube-system kube-apiserver-ubuntu- / Running h ubuntu-
kube-system kube-controller-manager-ubuntu- / Running h ubuntu-
kube-system kube-discovery--sdx9n / Running h ubuntu-
kube-system kube-dns--nln / Running h ubuntu-
kube-system kube-proxy-dv / Running h ubuntu-
kube-system kube-scheduler-ubuntu-- / Running h ubuntu-
測試DNS
- 建立檢測DNS pod
# kubectl run curl --image=radial/busyboxplus:curl -i --tty
Waiting for pod default/curl--xx4j to be running, status is Pending, pod ready: false
Waiting for pod default/curl--xx4j to be running, status is Pending, pod ready: false
Waiting for pod default/curl--xx4j to be running, status is Pending, pod ready: false
Waiting for pod default/curl--xx4j to be running, status is Pending, pod ready: false
- 進入後執行nslookup kubernetes.default确認解析正常。
[ [email protected]:/ ]$ nslookup kubernetes.default
Server:
Address : kube-dns.kube-system.svc.cluster.local
Name: kubernetes.default
Address : kubernetes.default.svc.cluster.local
- 測試OK後,删除掉curl這個Pod。
到這一步就可以向叢集中釋出微服務了,同時可以使用kubeadm join指令添加新的Node到叢集中
3.1.6 部署node節點
将node加入cluster了。這裡使用:kubeadm join。在執行此指令時需要執行3.1.1步驟的指令。
在node上執行(注意:這裡要保證token是正确的從init的日志裡可以擷取到,),根據Master上初始化成功後會列印的token:
# kubeadm join --token=c43f1a42d02deda012ef
Node join complete:
* Certificate signing request sent to master and response
received.
* Kubelet informed of new secure connection details.
3.1.6.1 驗證node元件情況
在node上看到的k8s元件情況如下:
# docker ps
cb97385e37 quay.io/coreos/flannel:v0-amd64 "/opt/bin/flanneld --" hours ago Up hours k8s_kube-flannel.e9308be1_kube-flannel-ds-q45x4_default_8f3335ab-f0--ca7-fa163eeee269_78864901
b88c81c5b3b gcr.io/google_containers/kube-proxy-amd64:v1 "kube-proxy --kubecon" hours ago Up hours k8s_kube-proxycab4d8_kube-proxy-c99k_kube-system_8f32be43-f0--ca7-fa163eeee269_28972d3e
quay.io/coreos/flannel:v0-amd64 "/bin/sh -c 'set -e -" hours ago Up hours k8s_install-cni.efd78816_kube-flannel-ds-q45x4_default_8f3335ab-f0--ca7-fa163eeee269_2bde126b
bdae2b7908da gcr.io/google_containers/pause-amd64: "/pause" hours ago Up hours k8s_POD.d8dbe16c_kube-proxy-c99k_kube-system_8f32be43-f0--ca7-fa163eeee269_085249bc
a627d637c6d gcr.io/google_containers/pause-amd64: "/pause" hours ago Up hours k8s_POD.d8dbe16c_kube-flannel-ds-q45x4_default_8f3335ab-f0--ca7-fa163eeee269_9968e26c
3.1.7 驗證叢集狀态
現在叢集搭建完成了,驗證叢集狀态,在master node上檢視目前cluster狀态:
# kubectl get nodes
NAME STATUS AGE
ubuntu01 Ready,master h
ubuntu02 Ready h
出現以上狀态,表面礎環境就搭好了,可以後續繼續驗證是否真正成功,可以嘗試部署服務等
3.1.8 部署微服務(可選)
上面步驟已經部署完成了一套kubernetes環境,下面部署一個官方提供的電商微服務應用。
# kubectl create namespace sock-shop
# kubectl apply -n sock-shop -f "https://github.com/microservices-demo/microservices-demo/blob/master/deploy/kubernetes/complete-demo.yaml?raw=true"
然後檢視配置設定給樣例應用的服務資訊:
# kubectl describe svc front-end -n sock-shop
Name: front-end
Namespace: sock-shop
Labels: name=front-end
Selector: name=front-end
Type: NodePort
IP:
Port: <unset> /TCP
NodePort: <unset> /TCP
Endpoints: :
Session Affinity: None
No events.
經過幾分鐘,會下載下傳所需鏡像病啟動樣例應用所需容器,然後就可以通過指令kubectl get pods -n sock-shop的輸出檢視樣例應用POD詳細資訊
# kubectl get pods -n sock-shop
NAME READY STATUS RESTARTS AGE
carts-2925342755-hvwcc 1/1 Running 0 22h
carts-db-2797325130-vst02 1/1 Running 0 22h
catalogue-1279937814-tplnb 1/1 Running 0 22h
catalogue-db-2290683463-6bf7p 1/1 Running 0 22h
front-end--gk1qc / Running h
orders--qkm9 / Running h
orders-db--stcmc / Running h
payment--zhq9v / Running h
queue-master--wn0d5 / Running h
rabbitmq--gftt / Running h
shipping--jznnj / Running h
user--jgt9h / Running h
user-db--nl4 / Running h
進入到Kubernetes叢集的master節點上,通過浏覽器通路http://:。在上面這個例子中,端口是30001,這個端口可以通過指令kubectl describe查詢出來。
通路http://:會出現以下頁面:
如果有防火牆,那麼確定這個端口可以被通路到。
3.1.9 将maste節點設為可排程的節點(可選)
Kubeadm預設安裝時,master node将不會參與Pod排程,不會承載work load,即不會有非核心元件的Pod在Master node上被建立出來。當然通過kubectl taint指令可以解除這一限制
#kubectl taint nodes ubuntu-01 dedicated-
node "ubuntu-01" tainted
3.2.0 不在master節點上操作叢集,而是在其他工作節點上操作叢集(可選)
需要将master節點上面的kubernetes配置檔案拷貝到目前節點上,然後執行kubectl指令:
# scp [email protected]<master ip>:/etc/kubernetes/admin.conf .
# kubectl --kubeconfig ./admin.conf get nodes
3.2.1 解除安裝(可選)
參照問題總結的2和3.
四.安裝問題總結: ###
- 由于使用kubeadm安裝的kubernetes核心元件都是以docker容器的形式運作,如果安裝過程出現問題,需要先執行下面的指令清理之前的執行殘留後,才能重新開始。
- 如果需要重新部署删除node節點需要執行一下指令:
# kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
# kubectl delete node <node name>
3 kubeadm會自動檢查目前環境是否有上次指令執行的“殘留”。如果有,必須清理後再行執行init。我們可以通過”kubeadm reset”來清理環境,以備重來。
# kubeadm reset
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
[reset] Deleting contents of stateful directories: [/var/lib/kubelet /etc/cni/net.d /var/lib/etcd]
[reset] Deleting contents of config directories: [/etc/kubernetes/manifests /etc/kubernetes/pki]
[reset] Deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf]
4 初始化叢集如果想要指定kubernetes版本,可使用一下指令:(,如果不指定使用最新版本)
kubeadm init --use-kubernetes-version=v1 --pod-network-cidr=/
5 如果想要檢視容器詳情可以通過。可使用如下指令:
$ kubectl describe 指令
$ kubectl logs 指令
參考文檔:
Installing Kubernetes on Linux with kubeadm主要參照這篇官方文檔。
https://www.hi-linux.com/posts/64604.html
http://blog.frognew.com/2017/01/install-kubernetes-with-kubeadm.html
https://mritd.me/2016/10/29/set-up-kubernetes-cluster-by-kubeadm/#34%E5%88%9D%E5%A7%8B%E5%8C%96-master