DockOne微信分享(一四八):Kubernetes的多集群管理实践


【编者的话】随着容器技术发展,Kubernetes逐渐崭露头角,本次分享跟大家交流Kubernetes使用集群联邦实现多集群管理的相关问题,以及我们实践中如何在Kubernetes使用集群联邦进行多集群管理。

Kubernetes在1.3版本之后,增加了“集群联邦”Federation的功能。这个功能使企业能够快速有效的、低成本的跨区跨域、甚至在不同的云平台上运行集群。这个功能可以按照地理位置创建一个复制机制,将多个Kubernetes集群进行复制,即使遇到某个区域连接中断或某个数据中心故障,也会保持最关键的服务运行。在1.7版以后支持本地多个集群联邦管理,不需要使用依赖云平台

Kubernetes集群联邦介绍

1、管理多個Kubernetes集群

“集群联邦”在架构上同Kubernetes集群很相似。有一个“集群联邦”的API server提供一个标准的Kubernetes API,并且通过etcd来存储状态。不同的是,一个通常的Kubernetes只是管理节点计算,而“集群联邦”管理所有的Kubernetes集群。
微信图片_20171108134012.png

2、跨集群服务发现

Kubernetes有一个标准的插件:kube-dns,这个插件可以在集群内部提供DNS服务,通过DNS解析service名字来访问kubernetes服务。Kubernetes服务是由一组KubernetesPOD组成的,这些POD是一些已经容器化了的应用,这些POD前面使用到了负载均衡器。假如我们有一个Kubernetes集群,这个集群裡面有一个服务叫做MySQL,这个服务是由一组MySQL POD组成的。在这个Kubernetes集群中,其他应用可以通过DNS来访问这个MySQL服务。

集群联邦federation/v1beta1API扩展基于DNS服务发现的功能。利用DNS,让POD可以跨集群、透明的解析服务。
233232.png

3、跨集群调度

为了追求高可用性和更高的性能,集群联邦能够把不同POD指定给不同的Kubernetes集群中。集群联邦调度器将决定如何在不同Kubernetes集群中分配工作负载。

通过跨集群调度,我们可以:
  • 跨Kubernetes集群均匀的调度任务负载。
  • 将各个Kubernetes集群的工作负载进行最大化,如果当前Kubernetes集群超出了承受能力,那麽将额外的工作负载路由到另一个比较空闲的Kubernetes集群中。
  • 根据应用地理区域需求,调度工作负载到不同的Kubernetes集群中,对于不同的终端用户,提供更高的带宽和更低的延迟。


4、集群高可用,故障自动迁移

集群联邦可以跨集群冗馀部署,当某个集群所在区域出现故障时,并不影响整个服务。集群联邦还可以检测集群是否为不可用状态,如果发现某个集群为不可用状态时,可以将失败的任务重新分配给集群联邦中其他可用状态的集群上。

Kubernetes使用集群联邦实现多集群管理

1、系统环境及初始化

1.1 系统环境
56565.png

1.2 安装前准备

1.2.1 准备Kubernetes组件镜像

Kubernetes 1.7版本的集群与联邦集群功能的安装方式均为镜像安装,所有组件功能都使用官方提供的镜像来实现,由于官方镜像国内无法正常下载,需要提前准备好镜像或科学上网,具体镜像列表如下:
7777.png


1.2.2 安装Docker 1.12

Kubernetes 1.7还没有针对Docker 1.13上做测试和验证,所以这里安装Kubernetes官方推荐的Docker 1.12版本。

1.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.13test01.example.com
192.168.5.14test02.example.com

关闭防火墙服务与禁用开机启动项
systemctl stopfirewalld
systemctl disable firewalld关闭SELINUX选项

关闭SELINUX选项
setenforce 0
sed -i's/SELINUX=enforcing/SELINUX=disabled/g'/etc/sysconfig/selinux

1.2.4 安装Kuberadm与Kubelet

注意:该yum源需要科学才能正常安装。

在每个节点安装Kubeadm和Kubelet:
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、Kubernetes-cni
yum install -ykubelet kubeadm kubectl kubernetes-cni

Kubelet服务设置开机启动
systemctl enablekubelet.service

安装完成后初始化环境准备完成。

2、安装Kubernetes集群

首先在一个节点上安装Kubernetes作为master节点,将master节点参与集群调度,然后在该节点上安装联邦集群功能,作为联邦集群的控制平面。

2.1 初始化集群

使用Kubeadm初始化集群,选择node1作为Master,在node1上执行下面的命令:
kubeadm init--kubernetes-version=v1.7.0 --pod-network-cidr=10.240.0.0/16--apiserver-advertise-address=192.168.5.13



注:因为我们选择flannel作为Pod网络插件,所以命令指定--pod-network-cidr=10.240.0.0/16。
kubeadm init执行成功后输出下面的信息:
You can now join anynumber of machines by running the following on each node
as root:
kubeadm join --tokene7986d.e440de5882342711 192.168.5.13:6443



注:请保存好该信息,后续节点加入集群需要使用该命令。
为了使用kubectl访问apiserver,在~/.bash_profile中追加下面的环境变量:
echo "exportKUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
source /etc/profile


此时kubectl命令在master node上就好用了,查看一下当前机器中的Node:
kubectl get nodes
NAME      STATUS    AGE       VERSION
node0     Ready     3m        v1.7.0

2.2 安装Pod网络组件

接下来安装flannel network add-on:
wgethttps://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel-rbac.yml
wgethttps://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"]   //改为本机网卡名称

部署网络组件:
kubectlcreate -f kube-flannel-rbac.yml
kubectlapply -f kube-flannel.yml

确保所有的Pod都处于Running状态。
kubectlget pod --all-namespaces -o wide

微信图片999.png

使用下面的命令使MasterNode参与工作负载。
kubectltaint nodes --all node-role.kubernetes.io/master-

3、安装联邦集群组件

3.1 安装前配置修改

修改前先停止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.2 安装Helm工具部署CoreDNS
curlhttps://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

初始化Helm,并使用Helm安装CoreDNS组件:
helm init
helm install --namespace default --name coredns-f /opt/Values.yaml stable/coredns

新建CoreDNS配置文件:
vi /root/coredns-provider.conf
[Global]
etcd-endpoints = http://192.168.0.51:2379
zones = example.com.

3.3 添加Kubernetes从节点

在Kubernetes工作节点上初始安装后执行以下命令:
kubeadmjoin --token e7986d.e440de5882342711 192.168.5.13:6443

在master节点查看节点状态:
kubectlget nodes

重复上述步骤创建多个Kubernetes集群,为联邦集群添加集群节点做准备。

3.4初始化联邦集群
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。
77777.png


3.5其他Kubernetes集群加入联邦集群

选择集群的Context:
kubectlconfig use-context fellowship   //fellowship为联邦初始化时创建

添加联邦集群文件:
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

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

添加集群到联邦
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

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

添加集群到联邦:
kubectlcreate -f c1.yaml
kubectlcreate -f c2.yaml

查看联邦集群状态:
[root@test01~]# kubectl get cluster
NAME      STATUS     AGE
c1        Ready     2d
c2        Ready     2d

3.6 通过联邦集群部署应用

通过联邦集群部署应用,需要在联邦集群控制平面的节点上,切换到联邦的Context。
kubectlconfig 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个集群中:
[root@test01 ~]# kubectl create namespace default
namespace"default" created

[root@test01 ~]#kubectl create -f tomcat.yaml
replicaset"tomcat" created

[root@test01 ~]#kubectl get rs
NAME      DESIRED     CURRENT       AGE
tomcat    4           4             <invalid>

[root@test01 ~]#kubectl -s 192.168.15.53:8080 get pod
NAME           READY     STATUS       RESTARTS   AGE
tomcat-juywx  1/1      Running      0           33s
tomcat-siidb  1/1      Running      0           33s

[root@test01 ~]#kubectl -s 192.168.8.12:8080 get pod
NAME           READY     STATUS       RESTARTS   AGE
tomcat-sw437  1/1      Running      0           33s
tomcat-n7z74  1/1      Running      0           33s 

集群联邦只支持以下几种类型资源的创建:
  • Cluster
  • ConfigMap
  • DaemonSets
  • Deployment
  • Events
  • Ingress
  • Namespaces
  • ReplicaSets
  • Secrets
  • Services


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组目录没有支持高可用,但联邦功能主要是为了调度管理Kubernetes集群的,所以联邦集群Federation组件出现故障时并不会直接影响到下面各个集群自身的已经在运行的服务。
Q:根据应用地理区域需求,调度工作负载到不同的Kubernetes集群中,对于不同的终端用户,提供更高的带宽和更低的延迟. 这个调度到不同的集群,是Kubernetes根据地理位置调度吗?是Kubernetes自己调度吗?

A:工作负载Kubernetes可以自己调度到比较空闲的集群上,地理位置调度这个需要通过编排文件控制应用的容器分配到更合适的区域机房。
Q:是先建立3个Kubernetes集群,然后在1个集群的master上kubefed init fellowship是吗?

A:是的,在其中1个集群的master上安装Federation组件,然后把3个Kubernetes集群加进来管理。
Q:添加联邦集群文件时,里面的serverAddress是什么地址?

A:serverAddress就是Kubernetes集群的API server的IP和端口,c1.yaml里面的serverAddress就是集群01的API server的IP和端口,c2.yaml里面的serverAddress就是集群02的API server的IP和端口。
以上内容根据2017年10月24日晚微信群分享内容整理。 分享人吕龙,有容云系统工程师。曾工作于宝德科技,云智慧,专注云平台系统架构的设计与研究,对云计算解决方案方面有较深的技术造诣和行业理解。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesa,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册