English docsnode
sealos旨在作一個簡單幹淨輕量級穩定的kubernetes安裝工具,能很好的支持高可用安裝。 其實把一個東西作的功能強大並不難,可是作到極簡且靈活可擴展就比較難。
因此在實現時就必需要遵循這些原則。python
sealos特性與優點:nginx
爲何不使用ansile
1.0版本確實是用ansible實現,可是用戶仍是須要先裝ansible,裝ansible有須要裝python和一些依賴等,爲了避免讓用戶那麼麻煩把ansible放到了容器裏供用戶使用。若是不想配置免密鑰使用用戶名密碼時又須要ssh-pass等,總之不能讓我滿意,不是我想的極簡。git
因此我想就來一個二進制文件工具,沒有任何依賴,文件分發與遠程命令都經過調用sdk實現因此不依賴其它任何東西,總算讓我這個有潔癖的人滿意了。github
爲何不用keepalived haproxy
haproxy用static pod跑沒有太大問題還算好管理,keepalived如今大部分開源ansible腳本都用yum 或者apt等裝,這樣很是的不可控,有以下劣勢:golang
因此爲了解決這個問題,我把keepalived跑在了容器中(社區提供的鏡像基本是不可用的) 改造中間也是發生過不少問題,最終好在解決了。docker
總而言之,累覺不愛,因此在想能不能甩開haproxy和keepalived作出更簡單更可靠的方案出來,還真找到了。。。shell
本地負載爲何不使用envoy或者nginx
咱們經過本地負載解決高可用問題api
解釋一下本地負載,就是在每一個node節點上都啓動一個負載均衡,上游就是三個master,負載方式有不少 ipvs envoy nginx等,咱們最終使用內核ipvs服務器
若是使用envoy等須要在每一個節點上都跑一個進程,消耗更多資源,這是我不但願的。ipvs實際也多跑了一個進程lvscare,可是lvscare只是負責管理ipvs規則,和kube-proxy相似,真正的流量仍是從很穩定的內核走的,不須要再把包走到用戶態中去處理。
實現上有個問題會讓使用envoy等變得很是尷尬,就是join時若是負載均衡沒有創建那是會卡住的,kubelet就不會起,因此爲此你須要先把envory起起來,意味着你又不能用static pod去管理它,同上面keepalived宿主機部署同樣的問題,用static pod就會相互依賴,邏輯死鎖,雞說要先有蛋,蛋說要先有雞,最後誰都沒有。
使用ipvs就不同,我能夠在join以前先把ipvs規則創建好,再去join就能夠join進去了,而後對規則進行守護便可。一旦apiserver不可訪問了,會自動清理掉全部node上對應的ipvs規則, master恢復正常時添加回來。
爲何要定製kubeadm
首先是因爲kubeadm把證書時間寫死了,因此須要定製把它改爲99年,雖然大部分人能夠本身去籤個新證書,可是咱們仍是不想再依賴個別的工具,就直接改源碼了。
其次就是作本地負載時修改kubeadm代碼是最方便的,由於在join時咱們須要作兩個事,第一join以前先建立好ipvs規則,第二建立static pod,若是這塊不去定製kubeadm就把報靜態pod目錄已存在的錯誤,忽略這個錯誤很不優雅。 並且kubeadm中已經提供了一些很好用的sdk供咱們去實現這個功能。
且這樣作以後最核心的功能都集成到kubeadm中了,sealos就單單變成分發和執行上層命令的輕量級工具了,增長節點時咱們也就能夠直接用kubeadm了
多master HA:
sealos init --master 192.168.0.2 \ --master 192.168.0.3 \ --master 192.168.0.4 \ --node 192.168.0.5 \ --user root \ --passwd your-server-password \ --version v1.14.1 \ --pkg-url /root/kube1.14.1.tar.gz
或者單master多node:
sealos init --master 192.168.0.2 \ --node 192.168.0.5 \ --user root \ --passwd your-server-password \ --version v1.14.1 \ --pkg-url /root/kube1.14.1.tar.gz
使用免密鑰或者密鑰對:
sealos init --master 172.16.198.83 \ --node 172.16.198.84 \ --pkg-url https://sealyun.oss-cn-beijing.aliyuncs.com/free/kube1.15.0.tar.gz \ --pk /root/kubernetes.pem # this is your ssh private key file \ --version v1.15.0
--master master服務器地址列表 --node node服務器地址列表 --user 服務器ssh用戶名 --passwd 服務器ssh用戶密碼 --pkg-url 離線包位置,能夠放在本地目錄,也能夠放在一個http服務器上,sealos會wget到安裝目標機 --version kubernetes版本 --pk ssh私鑰地址,配置免密鑰默認就是/root/.ssh/id_rsa
Other flags:
--kubeadm-config string kubeadm-config.yaml kubeadm配置文件,可自定義kubeadm配置文件 --vip string virtual ip (default "10.103.97.2") 本地負載時虛擬ip,不推薦修改,集羣外不可訪問
檢查安裝是否正常:
[root@iZj6cdqfqw4o4o9tc0q44rZ ~]# kubectl get node NAME STATUS ROLES AGE VERSION izj6cdqfqw4o4o9tc0q44rz Ready master 2m25s v1.14.1 izj6cdqfqw4o4o9tc0q44sz Ready master 119s v1.14.1 izj6cdqfqw4o4o9tc0q44tz Ready master 63s v1.14.1 izj6cdqfqw4o4o9tc0q44uz Ready <none> 38s v1.14.1 [root@iZj6cdqfqw4o4o9tc0q44rZ ~]# kubectl get pod --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system calico-kube-controllers-5cbcccc885-9n2p8 1/1 Running 0 3m1s kube-system calico-node-656zn 1/1 Running 0 93s kube-system calico-node-bv5hn 1/1 Running 0 2m54s kube-system calico-node-f2vmd 1/1 Running 0 3m1s kube-system calico-node-tbd5l 1/1 Running 0 118s kube-system coredns-fb8b8dccf-8bnkv 1/1 Running 0 3m1s kube-system coredns-fb8b8dccf-spq7r 1/1 Running 0 3m1s kube-system etcd-izj6cdqfqw4o4o9tc0q44rz 1/1 Running 0 2m25s kube-system etcd-izj6cdqfqw4o4o9tc0q44sz 1/1 Running 0 2m53s kube-system etcd-izj6cdqfqw4o4o9tc0q44tz 1/1 Running 0 118s kube-system kube-apiserver-izj6cdqfqw4o4o9tc0q44rz 1/1 Running 0 2m15s kube-system kube-apiserver-izj6cdqfqw4o4o9tc0q44sz 1/1 Running 0 2m54s kube-system kube-apiserver-izj6cdqfqw4o4o9tc0q44tz 1/1 Running 1 47s kube-system kube-controller-manager-izj6cdqfqw4o4o9tc0q44rz 1/1 Running 1 2m43s kube-system kube-controller-manager-izj6cdqfqw4o4o9tc0q44sz 1/1 Running 0 2m54s kube-system kube-controller-manager-izj6cdqfqw4o4o9tc0q44tz 1/1 Running 0 63s kube-system kube-proxy-b9b9z 1/1 Running 0 2m54s kube-system kube-proxy-nf66n 1/1 Running 0 3m1s kube-system kube-proxy-q2bqp 1/1 Running 0 118s kube-system kube-proxy-s5g2k 1/1 Running 0 93s kube-system kube-scheduler-izj6cdqfqw4o4o9tc0q44rz 1/1 Running 1 2m43s kube-system kube-scheduler-izj6cdqfqw4o4o9tc0q44sz 1/1 Running 0 2m54s kube-system kube-scheduler-izj6cdqfqw4o4o9tc0q44tz 1/1 Running 0 61s kube-system kube-sealyun-lvscare-izj6cdqfqw4o4o9tc0q44uz 1/1 Running 0 86s
sealos clean \ --master 192.168.0.2 \ --master 192.168.0.3 \ --master 192.168.0.4 \ --node 192.168.0.5 \ --user root \ --passwd your-server-password
獲取 join command, 在master上執行:
kubeadm token create --print-join-command
可使用super kubeadm, 可是join時須要增長一個--master
參數:
cd kube/shell && init.sh echo "10.103.97.2 apiserver.cluster.local" >> /etc/hosts # using vip kubeadm join 10.103.97.2:6443 --token 9vr73a.a8uxyaju799qwdjv \ --master 10.103.97.100:6443 \ --master 10.103.97.101:6443 \ --master 10.103.97.102:6443 \ --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
也能夠用sealos join命令:
sealos join --master 192.168.0.2 \ --master 192.168.0.3 \ --master 192.168.0.4 \ --vip 10.103.97.2 \ --node 192.168.0.5 \ --user root \ --passwd your-server-password \ --pkg-url /root/kube1.15.0.tar.gz
好比咱們須要在證書里加入 sealyun.com
:
先獲取配置文件模板:
sealos config -t kubeadm >> kubeadm-config.yaml.tmpl
修改kubeadm-config.yaml.tmpl
,文件便可, 編輯增長 sealyun.com
, 注意其它部分不用動,sealos會自動填充模板裏面的內容:
apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration kubernetesVersion: {{.Version}} controlPlaneEndpoint: "apiserver.cluster.local:6443" networking: podSubnet: 100.64.0.0/10 apiServer: certSANs: - sealyun.com # this is what I added - 127.0.0.1 - apiserver.cluster.local {{range .Masters -}} - {{.}} {{end -}} - {{.VIP}} --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: "ipvs" ipvs: excludeCIDRs: - "{{.VIP}}/32"
使用 --kubeadm-config 指定配置文件模板便可:
sealos init --kubeadm-config kubeadm-config.yaml.tmpl \ --master 192.168.0.2 \ --master 192.168.0.3 \ --master 192.168.0.4 \ --node 192.168.0.5 \ --user root \ --passwd your-server-password \ --version v1.14.1 \ --pkg-url /root/kube1.14.1.tar.gz
本教程以1.14版本升級到1.15爲例,其它版本原理大差不差,懂了這個其它的參考官方教程便可
把離線包拷貝到全部節點執行 cd kube/shell && sh init.sh
這裏會把kubeadm kubectl kubelet bin文件都更新掉,並且會導入高版本鏡像
kubeadm upgrade plan kubeadm upgrade apply v1.15.0
重啓kubelet:
systemctl restart kubelet
其實kubelet升級簡單粗暴,咱們只須要把新版本的kubelet拷貝到/usr/bin下面,重啓kubelet service便可,若是程序正在使用不讓覆蓋那麼就停一下kubelet再進行拷貝,kubelet bin文件在 conf/bin
目錄下
kubeadm upgrade apply
驅逐節點(要不要驅逐看狀況, 喜歡粗暴的直接來也沒啥)
kubectl drain $NODE --ignore-daemonsets
更新kubelet配置:
kubeadm upgrade node config --kubelet-version v1.15.0
而後升級kubelet 同樣是替換二進制再重啓 kubelet service
systemctl restart kubelet
召回失去的愛情:
kubectl uncordon $NODE
kubectl get nodes
若是版本信息對的話基本就ok了
由於使用了netlink庫,因此推薦在容器內進行編譯
docker run --rm -v $GOPATH/src/github.com/fanux/sealos:/go/src/github.com/fanux/sealos -w /go/src/github.com/fanux/sealos -it golang:1.12.7 go build
若是使用go mod 指定經過vendor 編譯:
go build -mod vendor
有個細節是全部對apiserver進行訪問都是經過域名,由於master上鍊接本身就行,node須要經過虛擬ip連接多個master,這個每一個節點的kubelet與kube-proxy訪問apiserver的地址是不同的,而kubeadm又只能在配置文件中指定一個地址,因此使用一個域名可是每一個節點解析不一樣。
使用域名的好處還有就是IP地址發生變化時僅須要修改解析便可。
經過這樣的方式實現每一個node上經過本地內核負載均衡訪問masters:
+----------+ +---------------+ virturl server: 127.0.0.1:6443 | mater0 |<----------------------| ipvs nodes | real servers: +----------+ |+---------------+ 10.103.97.200:6443 | 10.103.97.201:6443 +----------+ | 10.103.97.202:6443 | mater1 |<---------------------+ +----------+ | | +----------+ | | mater2 |<---------------------+ +----------+
在node上起了一個lvscare的static pod去守護這個 ipvs, 一旦apiserver不可訪問了,會自動清理掉全部node上對應的ipvs規則, master恢復正常時添加回來。
因此在你的node上加了三個東西,能夠直觀的看到:
cat /etc/kubernetes/manifests # 這下面增長了lvscare的static pod ipvsadm -Ln # 能夠看到建立的ipvs規則 cat /etc/hosts # 增長了虛擬IP的地址解析
對kubeadm改動很是少,主要是證書時間延長和join命令的擴展,主要講講join命令的改造:
首先join命令增長--master參數用於指定master地址列表
flagSet.StringSliceVar( &locallb.LVScare.Masters, "master", []string{}, "A list of ha masters, --master 192.168.0.2:6443 --master 192.168.0.2:6443 --master 192.168.0.2:6443", )
這樣就能夠拿到master地址列表去作ipvs了
若是不是控制節點切不是單master,那麼就建立一條ipvs規則,控制節點上不須要建立,連本身的apiserver便可:
if data.cfg.ControlPlane == nil { fmt.Println("This is not a control plan") if len(locallb.LVScare.Masters) != 0 { locallb.CreateLocalLB(args[0]) } }
而後再去建立lvscare static pod去守護ipvs:
if len(locallb.LVScare.Masters) != 0 { locallb.LVScareStaticPodToDisk("/etc/kubernetes/manifests") }
因此哪怕你不使用sealos,也能夠直接用定製過的kubeadm去裝集羣,只是麻煩一些:
apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration kubernetesVersion: v1.14.0 controlPlaneEndpoint: "apiserver.cluster.local:6443" # apiserver DNS name apiServer: certSANs: - 127.0.0.1 - apiserver.cluster.local - 172.20.241.205 - 172.20.241.206 - 172.20.241.207 - 172.20.241.208 - 10.103.97.1 # virturl ip --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: "ipvs" ipvs: excludeCIDRs: - "10.103.97.1/32" # 注意不加這個kube-proxy會清理你的規則
echo "10.103.97.100 apiserver.cluster.local" >> /etc/hosts # 解析的是master0的地址 kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs mkdir ~/.kube && cp /etc/kubernetes/admin.conf ~/.kube/config kubectl apply -f https://docs.projectcalico.org/v3.6/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
echo "10.103.97.100 apiserver.cluster.local" >> /etc/hosts #解析的是master0的地址,爲了能正常join進去 kubeadm join 10.103.97.100:6443 --token 9vr73a.a8uxyaju799qwdjv \ --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 \ --experimental-control-plane \ --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07 sed "s/10.103.97.100/10.103.97.101/g" -i /etc/hosts # 解析再換成本身的地址,不然就都依賴master0的僞高可用了
echo "10.103.97.100 apiserver.cluster.local" >> /etc/hosts kubeadm join 10.103.97.100:6443 --token 9vr73a.a8uxyaju799qwdjv \ --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 \ --experimental-control-plane \ --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07 sed "s/10.103.97.100/10.103.97.101/g" -i /etc/hosts
join時加上--master指定master地址列表
echo "10.103.97.1 apiserver.cluster.local" >> /etc/hosts # 須要解析成虛擬ip kubeadm join 10.103.97.1:6443 --token 9vr73a.a8uxyaju799qwdjv \ --master 10.103.97.100:6443 \ --master 10.103.97.101:6443 \ --master 10.103.97.102:6443 \ --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
. ├── bin # 指定版本的bin文件,只須要這三個,其它組件跑容器裏 │ ├── kubeadm │ ├── kubectl │ └── kubelet ├── conf │ ├── 10-kubeadm.conf # 這個文件新版本沒用到,我在shell裏直接生成,這樣能夠檢測cgroup driver │ ├── dashboard │ │ ├── dashboard-admin.yaml │ │ └── kubernetes-dashboard.yaml │ ├── heapster │ │ ├── grafana.yaml │ │ ├── heapster.yaml │ │ ├── influxdb.yaml │ │ └── rbac │ │ └── heapster-rbac.yaml │ ├── kubeadm.yaml # kubeadm的配置文件 │ ├── kubelet.service # kubelet systemd配置文件 │ ├── net │ │ └── calico.yaml │ └── promethus ├── images # 全部鏡像包 │ └── images.tar └── shell ├── init.sh # 初始化腳本 └── master.sh # 運行master腳本
init.sh腳本中拷貝bin文件到$PATH下面,配置systemd,關閉swap防火牆等,而後導入集羣所須要的鏡像。
master.sh主要執行了kubeadm init
conf下面有有我須要的如kubeadm的配置文件,calico yaml文件等等
sealos會會調用兩者。 因此大部分兼容不一樣版本均可以微調腳本作到。
關注咱們就是關注技術乾貨