Kubernetes在1.3版本之后,增加了“集群聯邦”Federation的功能。這個功能使企業能夠快速有效的、低成本的跨區跨域、甚至在不同的雲平台上運行集群。這個功能可以按照地理位置創建一個復制機制,將多個kubernetes集群進行復制,即使遇到某個區域連接中斷或某個數據中心故障,也會保持最關鍵的服務運行。在1.7版以后支持本地多個集群聯邦管理,不需要使用依賴雲平台。
1 Kubernetes聯邦介紹
1.1 管理多個kubernetes集群
“集群聯邦”在架構上同kubernetes集群很相似。有一個“集群聯邦”的API server提供一個標准的Kubernetes API,並且通過etcd來存儲狀態。不同的是,一個通常的Kubernetes只是管理節點計算,而“集群聯邦”管理所有的kubernetes集群。
1.2 跨集群服務發現
Kubernetes有一個標准的插件:kube-dns,這個插件可以在集群內部提供DNS服務,通過DNS解析service名字來訪問kubernetes服務。Kubernetes服務是由一組kubernetesPOD組成的,這些POD是一些已經容器化了的應用,這些POD前面使用到了負載均衡器。假如我們有一個kubernetes集群,這個集群裡面有一個服務叫做mysql,這個服務是由一組mysql POD組成的。在這個kubernetes集群中,其他應用可以通過DNS來訪問這個mysql服務。
集群聯邦federation/v1beta1 API擴展基於DNS服務發現的功能。利用DNS,讓POD可以跨集群、透明的解析服務。
1.3 跨集群調度
為了追求高可用性和更高的性能,集群聯邦能夠把不同POD指定給不同的Kubernetes集群中。集群聯邦調度器將決定如何在不同kubernetes集群中分配工作負載。
通過跨集群調度,我們可以:
l 跨kubernetes集群均勻的調度任務負載
l 將各個kubernetes集群的工作負載進行最大化,如果當前kubernetes集群超出了承受能力,那麽將額外的工作負載路由到另一個比較空閑的kubernetes集群中
l 根據應用地理區域需求,調度工作負載到不同的kubernetes集群中,對於不同的終端用戶,提供更高的帶寬和更低的延遲。
1.4 集群高可用,故障自動遷移
集群聯邦可以跨集群冗餘部署,當某個集群所在區域出現故障時,並不影響整個服務。集群聯邦還可以檢測集群是否為不可用狀態,如果發現某個集群為不可用狀態時,可以將失敗的任務重新分配給集群聯邦中其他可用狀態的集群上。
2 Kubernetes使用集群聯邦實現多集群管理
2.1 系統環境及初始化
2.2 安裝前准備
2.2.1 准備kubernetes組件鏡像
Kubernetes1.7版本的集群與聯邦集群功能的安裝方式均為鏡像安裝,所有組件功能都使用官方提供的鏡像來實現,由於官方鏡像國內無法正常下載,需要提前准備好鏡像或科學上網。
具體鏡像列表如下:
2.2.2 安裝Docker 1.12
Kubernetes 1.7還沒有針對docker 1.13上做測試和驗證,所以這里安裝Kubernetes官方推薦的Docker 1.12版本。
2.2.3 修改系統配置
創建/etc/sysctl.d/k8s.conf文件,添加如下內容:
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
執行sysctl -p /etc/sysctl.d/k8s.conf使修改生效。
在/etc/hostname中修改各節點的hostname,在/etc/hosts設置hostname對應ip:
192.168.5.13 test01.example.com
192.168.5.14 test02.example.com
關閉防火牆服務與禁用開機啟動項
systemctl stop firewalld
systemctl disable firewalld
關閉SELINUX選項
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g'/etc/sysconfig/selinux
2.2.4 安裝Kuberadm與Kubelet
注意:該yum源需要科學才能正常安裝
在每個節點安裝kubeadm和kubelet,首先是添加kubernetes的YUM源:
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://yum.kubernetes.io/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
安裝kubeadm, kubelet, kubectl, kubernets-cni
yum install -y kubelet kubeadm kubectl kubernetes-cni
kubelet服務設置開機啟動
systemctl enable kubelet.service
以上安裝完成后,初始化環境的准備就完成了。
3 安裝kubernetes集群
首先在一個節點上安裝kubernetes作為master節點,將master節點參與集群調度.然后在該節點上安裝聯邦集群功能,作為聯邦集群的控制平面。
3.1 初始化集群
使用kubeadm初始化集群,選擇node1作為Master
在node1上執行下面的命令:
注:因為我們選擇flannel作為Pod網絡插件,所以命令指定--pod-network-cidr=10.240.0.0/16
kubeadm init --kubernetes-version=v1.7.0 --pod-network-cidr=10.240.0.0/16 --apiserver-advertise-address=192.168.5.13
kubeadm init執行成功后輸出下面的信息:
You can now join any number of machines by running the following on each node
as root:
kubeadm join --token e7986d.e440de5882342711 192.168.5.13:6443
請保存好kubeadm join 的信息,后續節點加入集群需要使用該命令.
為了使用kubectl訪問apiserver,在~/.bash_profile中追加下面的環境變量:
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
source /etc/profile
此時kubectl命令在master node上就可以用了,查看一下當前機器中的Node,看到node0狀態為Ready:
kubectl get nodes
NAME STATUS AGE VERSION
node0 Ready 3m v1.7.0
3.2 安裝Pod網絡組件
接下來安裝flannel network add-on,首先下載需要的yaml文件:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel-rbac.yml
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
目前需要在kube-flannel.yml中使用--iface參數指定集群主機內網網卡的名稱,否則可能會出現dns無法解析。需要將kube-flannel.yml下載到本地,flanneld啟動參數加上--iface=<iface-name>
vi kube-flannel.yml
command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr", "--iface=eth1" ] //--iface=eth1
改為本機網卡名稱
部署網絡組件:
kubectl create -f kube-flannel-rbac.yml
kubectl apply -f kube-flannel.yml
確保所有的Pod都處於Running狀態。
kubectl get pod --all-namespaces -o wide
如下圖:
使用下面的命令使Master Node參與工作負載:
kubectl taint nodes --all node-role.kubernetes.io/master-
3.3 安裝聯邦集群組件
3.3.1 安裝前配置修改
修改etcd與apiserver的監聽端口,修改前先停止kubelet服務
vi /etc/kubernetes/manifests/etcd.yaml
- --listen-client-urls=http://0.0.0.0:2379
- --advertise-client-urls=http://0.0.0.0:2379
vi /etc/kubernetes/manifests/kube-apiserver.yaml
- --insecure-port=8080
- --insecure-bind-address=0.0.0.0
重啟kubelet服務讓etcd與apiserver監聽端口生效
systemctl restart kubelet
3.3.2 安裝helm工具部署Coredns
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh
修改RBAC臨時訪問權限(這是比較關鍵的地方,沒有這步后面會失敗)
kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
創建coredns鍵值文件
cat <<EOF > /opt/Values.yaml
isClusterService: false
serviceType: "NodePort"
middleware:
kubernetes:
enabled: false
etcd:
enabled: true
zones:
- "example.com."
endpoint: "http://192.168.5.13:2379"
EOF
新建coredns配置文件
vi /root/coredns-provider.conf
[Global]
etcd-endpoints = http://192.168.0.51:2379
zones = example.com.
3.3.3 添加kubernetes從節點
在kubernetes工作節點上初始安裝后執行以下命令,就可以加入集群
kubeadm join --token e7986d.e440de5882342711 192.168.5.13:6443
在master節點查看節點狀態,添加之后可以在master上執行這個查看是否添加成功
kubectl get nodes
重復上述步驟創建多個kubernetes集群,為聯邦集群添加集群節點做准備。
3.3.4 初始化聯邦集群
執行這個進行聯邦的初始化,在控制平面的master節點上執行:
kubefed init fellowship \
--host-cluster-context=kubernetes-admin@kubernetes \
--dns-provider="coredns" \
--dns-zone-name="example.com." \
--dns-provider-config="/root/coredns-provider.conf" \
--apiserver-enable-basic-auth=true \
--apiserver-enable-token-auth=true \
--apiserver-arg-overrides="--anonymous-auth=false,--v=4" \
--api-server-service-type="NodePort" \
--api-server-advertise-address="192.168.5.13" \
--etcd-persistent-storage=false
初始化完成后集群聯邦會在federation-system命名空間中創建兩個POD
3.3.5 其他kubernetes集群加入聯邦集群
選擇集群的context
kubectl config use-context fellowship //fellowship為聯邦初始化時創建的名稱
添加聯邦集群文件
集群1
cat /home/tmp/c1.yaml
apiVersion: federation/v1beta1
kind: Cluster
metadata:
name: c1
spec:
serverAddressByClientCIDRs:
- clientCIDR: 0.0.0.0/0
serverAddress: http://192.168.15.53:8080
集群2
cat /home/tmp/c2.yaml
apiVersion: federation/v1beta1
kind: Cluster
metadata:
name: c2
spec:
serverAddressByClientCIDRs:
- clientCIDR: 0.0.0.0/0
serverAddress: http://192.168.8.12:8080
執行添加這2個集群到聯邦
kubectl create -f c1.yaml
kubectl create -f c2.yaml
查看聯邦集群狀態,狀態為Ready就是成功了。
[root@test01 ~]# kubectl get cluster
NAME STATUS AGE
c1 Ready 2d
c2 Ready 2d
3.3.6 通過聯邦集群部署應用
通過聯邦集群部署應用,需要在聯邦集群控制平面的節點上,切換到聯邦的context
kubectl config use-context fellowship //fellowship為聯邦初始化時創建的名稱
配置應用在分布在2個集群中:
vi tomcat.yaml
apiVersion: exensions/v1beta1
kind: ReplicaSet
metadata:
name: tomcat
lables:
app: tomcat
annotaions:
federation.kubernetes.io/replica-set-preferences:
{
"rebalance": true,
"clusters": {
"c1": {
"weight": 1
},
"c2": {
"weight": 1
}
}
}
spec:
replicas: 4
template:
metadata:
labels:
#region: tomcat
app: tomcat
spec:
containers:
- name: fed-tomcat
image: 192.168.18.250:5002/admin/tomcat:v0.0.5
resourcces:
requests:
cpu: 200M
memory: 500Mi
ports:
- containerPort: 80
通過以上編排創建應用在聯邦,應用的4個實例按比例分布到2個集群中
目前集群聯邦只支持以下幾種類型資源的創建:
Cluster
ConfigMap
DaemonSets
Deployment
Events
Ingress
Namespaces
ReplicaSets
Secrets
Services
4 Q&A
Q:node機器推薦命名規則與生成使用經驗
A:推薦使用“地理位置+機房編號+機櫃號+應用名稱”的縮寫字母來命名,這樣便於運維人員后續的管理和維護。
Q:為什么要修改etcd與apiserver的監聽端口?
A:修改etcd監聽IP為0.0.0.0是為了防止出現監聽了lo網卡的127.0.0.1的IP,出現不能連接的情況。apiserver則是開啟8080端口用於接收http請求,這樣是為了測試時方便不用使用CA證書認證。
Q:請問docker 源怎么弄,國內一般不好連接,下載不了?另外還有1.6要升級到1.7怎么做?
A:建議使用科學上網方式,這樣就不需要改動配置。1.6升級到1.7,先停止kubelet服務,然后下載1.7版本的kubernetes-server-linux-amd64.tar.gz包,解壓替換/usr/bin目錄下的同名文件,然后再把kubelet服務啟動
Q:在聯邦集群中部署服務,可以將服務只部署在一個集群中么?
A:可以只部署服務在一個集群中,通過編排文件中federation.kubernetes.io/replica-set-preference來控制副本分布在哪個集群。
Q:聯邦集群的幾個組件現在有支持高可用么?沒有的話,我們應該怎么避免聯邦組件的bug導致的服務不可用?
A:聯邦集群的Federation組目錄沒有支持高可用,但聯邦功能主要是為了調度管理k8s集群的,所以聯邦集群Federation組件出現故障時並不會直接影響到下面各個集群自身的已經在運行的服務。