本文主要讲Kubernetes的一种原始部署方式。Kubernetes从开发至今,其部署方式已经变得越来越简单。常见的有三种:

a. 最简单的就是使用Minikube方式。下载一个二进制文件即可拥有一个单机版的Kubernetes,而且支持各个平台。
b. 从源码安装。这种方式也是简单的进行一些配置,然后执行kube-up.sh就可以部署一个Kubernetes集群。可参见官方文档《Manually Deploying Kubernetes on Ubuntu Nodes》。PS:目前,该文档部署Kubernetes 1.5.3版本会有些问题。
c. 通过kubeadm部署。可参见官方文档《Installing Kubernetes on Linux with kubeadm》

  其实,除了上面三种方式外,有些Linux发行版已经提供了Kubernetes的安装包,比如在CentOS 7上面,直接执行yum install -y etcd kubernetes即可安装Kubernetes,然后做些配置就可以完成部署了。我相信对于Google这种追求自动化、智能化的公司,他们会让Kubernetes部署方式还会更加简化。但这些都不是本文的重点,本文要讲述的是如何像堆积木一样一个模块一个模块的部署Kubernetes。为什么要这样做?

  为了更好的理解学习Kubernetes。现在简单化的部署方式屏蔽了很多细节,使得我们对于各个模块的感知少了很多。而且很容器觉得Kubernetes的内部部署细节非常的麻烦或者复杂,但其实并非如此,其实Kubernetes集群就是由为数不多的几个二进制文件组成,部署一个基本的集群也非难事。因为是使用Go开发的,这些二进制文件也没有任何依赖,从别的地方拷贝过来就可使用。本文就介绍如何从这些二进制文件搭建一个Kubernetes集群, 以加深对Kubernetes的理解。而且,其他部署方式其实也只是对这种方式的一种封装。

  现在Systemd逐渐替代了Upstart,有的部署方式也只支持Systemd的Linux发行版,如果是Upstart,还得做适配。至于什么是Systemd和Upstart,不是本文要讨论的,后续会总结发出来。这里我使用的Linux发行版是Ubuntu 16.04。当然Ubuntu 15.04+的都使用的是Systemd,应该都是适用的,其他使用Systemd的系统应该也是适用的,但可能需要做些小的改动。另外,前文介绍了Kubernetes集群分为Master和Node,所以我们部署也一样,分为Master的部署和Node的部署。

  我的环境是用Virtualbox虚拟了两台Ubuntu 16.04,虚拟机和主机的通信方式是NAT和host-only方式。NAT用于访问外网,host-only用于两台虚拟机之间访问,IP分别为192.168.67.133和192.168.67.134.其中133这台机器机器既是Master,又是Node;134是Node。本文只装了133,后面再测试网络等需要多台的时候再安装134.因为Kubernetes里面Node是主动向Master注册的(通过Node上面的kubelet),所以要扩展Node的话也非常容易。

  Kubernetes集群内主要包含这些模块:Master中:APIServer、scheduler、controller manager、etcd;Node中:kubelet、kube-proxy、runtime(这里指Docker)。

  上面每个模块都由一个二进制文件实现,所以我们需要上面每个模块对应的那个二进制文件。获取方式有很多。最直观的方式就是去github上面下载release的包,里面有二进制文件。但那个包有1GB+大小,特别对于中国用户就呵呵了,当然还有许多其他获取的方式。这里我说一个地方,在Kubernetes源码的kubernetes/cluster/ubuntu目录下有master和minion目录,下面的init_scripts里面就有Master和Node上面需要的二进制文件。另外,你也可以使用如下命令下载kubernetes-server-linux-amd64.tar.gz包:

wget -c https://github.com/kubernetes/kubernetes/releases/download/v1.5.2/kubernetes.tar.gz

  tar -zxvf 解压kubernetes.tar.gz文件后在kubernetes/server目录中找到kubernetes-server-linux-amd64.tar.gz将其解压,这个包解压后的kubernetes/server/bin目录下就有我们需要的二进制文件,我将这些二进制文件都放到了/opt/bin目录下,并且将该目录加到了PATH中(vi /etc/environment)。你也可以直接将这些文件放到系统的PATH路径中,比如/usr/bin。OK,有了这些二进制文件,我们就可以开始部署了。

1、部署Master

  前文介绍过,Master上面主要四个模块:APIServer、scheduler、controller manager、etcd,我们一一来部署。

部署etcd

我建议直接使用apt install etcd命令去安装,这样同时也会安装etcdctl。安装完后etcd的数据默认存储在/var/lib/etcd/default目录,默认配置文件为/etc/default/etcd,可通过/lib/systemd/system/etcd.service文件进行修改。

安装好以后,执行以下命令:

systemctl enable etcd.service # 将etcd加到开机启动列表中 
 systemctl start etcd.service # 启动etcd

安装好以后,etcd默认监听http://127.0.0.1:2379地址供客户端连接。我们可以使用etcdctl来检查etcd是否正确启动:

ubuntu➜ bin etcdctl cluster-health 
 member ce2a822cea30bfca is healthy: got healthy result from http://localhost:2379 
 cluster is healthy

可以看到运行正常。当然,部署多台的话,因为所有Node都需要访问etcd,所以etcd必须要监听在其他Node可以访问的IP上面才可以,在/etc/default/etcd中增加以下两行:

ETCD_LISTEN_CLIENT_URLS=”http://0.0.0.0:2379” 
 ETCD_ADVERTISE_CLIENT_URLS=”http://0.0.0.0:2379”

重启etcd即可使etcd在所有IP上起监听。

部署APIServer

APIServer对应的二进制文件是kube-apiserver,我们先来设置systemd服务文件/lib/systemd/system/kube-apiserver.service:

[Unit] 
 Description=Kubernetes API Server 
 Documentation=https://github.com/kubernetes 
 After=etcd.service 
 Wants=etcd.service[Service] 
 EnvironmentFile=/etc/kubernetes/apiserver 
 ExecStart=/opt/bin/kube-apiserver $KUBE_API_ARGS 
 Restart=on-failure 
 Type=notify 
 LimitNOFILE=65536[Install] 
 WantedBy=multi-user.target

重点项简单说明:

kube-apiserver服务依赖etcd,所以设置了After。

EnvironmentFile是该服务的配置文件。

ExecStart说明如何启动该服务。

我们看到kube-apiserver的启动参数为$KUBE_API_ARGS,我们在配置文件/etc/kubernetes/apiserver中定义这个环境变量:
KUBE_API_ARGS=”–etcd_servers=http://127.0.0.1:2379 –insecure-bind-address=0.0.0.0 –insecure-port=8080 –service-cluster-ip-range=169.169.0.0/16 –service-node-port-range=1-65535 –admission_control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ResourceQuota –logtostderr=false –log-dir=/var/log/kubernetes –v=2”

选项说明:

--etcd_servers:就是etcd的地址。

--insecure-bind-address:apiserver绑定主机的非安全IP地址,设置0.0.0.0表示绑定所有IP地址。

--insecure-port:apiserver绑定主机的非安全端口,默认为8080。

--service-cluster-ip-range:Kubernetes集群中Service的虚拟IP地址段范围,以CIDR格式表示,该IP范围不能与物理机真实IP段有重合。

-service-node-port-range:Kubernetes集群中Service可映射的物理机端口范围,默认为30000~32767.

--admission_control: Kubernetes集群的准入控制设置,各控制模块以插件形式依次生效。

--logtostderr:设置为false表示将日志写入文件,不写入stderr。

--log-dir: 日志目录。

--v:日志级别。

OK,APIServer的部署配置完成了。后面其他模块的配置与之大同小异。

部署controller manager

controller manager对应的二进制文件是kube-controller-manager,且该服务依赖于kube-apiserver。

依旧先配置systemd的服务文件/lib/systemd/system/kube-controller-manager.service

[Unit] 
 Description=Kubernetes Controller Manager 
 Documentation=https://github.com/kubernetes 
 After=kube-apiserver.service 
 Requires=kube-apiserver.service[Service] 
 EnvironmentFile=/etc/kubernetes/controller-manager 
 ExecStart=/opt/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS 
 Restart=on-failure 
 LimitNOFILE=65536[Install] 
 WantedBy=multi-user.target

/etc/kubernetes/controller-manager中设置$KUBE_CONTROLLER_MANAGER_ARGS

KUBE_CONTROLLER_MANAGER_ARGS=”–master=http://192.168.67.133:8080 –logtostderr=false –log-dir=/var/log/kubernetes –v=2”

–master指的是APIServer的地址。

部署scheduler

scheduler对应的二进制文件是kube-scheduler,scheduler依赖于APIServer。

配置systemd服务文件/lib/systemd/system/kube-scheduler.service

[Unit] 
 Description=Kubernetes Scheduler Manager 
 Documentation=https://github.com/kubernetes 
 After=kube-apiserver.service 
 Requires=kube-apiserver.service[Service] 
 EnvironmentFile=/etc/kubernetes/scheduler 
 ExecStart=/opt/bin/kube-scheduler $KUBE_SCHEDULER_ARGS 
 Restart=on-failure 
 LimitNOFILE=65536[Install] 
 WantedBy=multi-user.target

在配置文件/etc/kubernetes/scheduler中设置$KUBE_SCHEDULER_ARGS

KUBE_SCHEDULER_ARGS=”–master=http://192.168.67.133:8080 –logtostderr=false –log-dir=/var/log/kubernetes –v=2”

至此,Master上面的四个模块都部署完了,我们按照顺序启动他们,并将其加入到开机自启动选项中:

//重新加载systemd配置管理,切记增加*.service后一定要先执行该命令,否则启动服务时会报错 
 systemctl daemon-reload 
 // enable表示该服务开机自启,start表示启动该服务 
 systemctl enable kube-apiserver.service 
 systemctl start kube-apiserver.service 
 systemctl enable kube-controller-manager.service 
 systemctl start kube-controller-manager.service 
 systemctl enable kube-scheduler.service 
 systemctl start kube-scheduler.service

然后我们分别运行systemctl status <service_name>来验证服务的状态,“running”表示启动成功。如果未成,也可看到错误日志。

部署Node

Node上面运行三个模块:kubelet、kube-proxy、runtime。其中runtime目前指的是docker或者rkt,这里我们使用docker,docker的安装这里就不赘述了,最好安装最新版本的docker。

部署kubelet

kubelet对应的二进制文件是kubelet,且其依赖Docker服务。
配置systemd服务文件/lib/systemd/system/kubelet.service

[Unit] 
 Description=Kubernetes Kubelet Server 
 Documentation=https://github.com/kubernetes 
 After=docker.service 
 Requires=docker.service[Service] 
 WorkingDirectory=/var/lib/kubelet 
 EnvironmentFile=/etc/kubernetes/kubelet 
 ExecStart=/opt/bin/kubelet $KUBELET_ARGS 
 Restart=on-failure[Install] 
 WantedBy=multi-user.target

在配置文件/etc/kubernetes/kubelet中设置参数$KUBELET_ARGS

KUBELET_ARGS=”–api-servers=http://192.168.67.133:8080 –hostname-override=192.168.56.101 –logtostderr=false –log-dir=/var/log/kubernetes –v=2”


其中--hostname-override设置本Node的名称。

部署kube-proxy

kube-proxy对应的二进制文件为kube-proxy,且该服务依赖于network服务。

配置systemd服务文件/lib/systemd/system/kube-proxy.service

[Unit] 
 Description=Kubernetes Kube-Proxt Server 
 Documentation=https://github.com/kubernetes 
 After=network.target 
 Requires=network.target[Service] 
 EnvironmentFile=/etc/kubernetes/proxy 
 ExecStart=/opt/bin/kube-proxy $KUBE_PROXY_ARGS 
 Restart=on-failure 
 LimitNOFILE=65536[Install] 
 WantedBy=multi-user.target

在配置文件/etc/kubernetes/proxy中设置参数$KUBE_PROXY_ARGS

KUBE_PROXY_ARGS=”–master=http://192.168.67.133:8080 –logtostderr=false –log-dir=/var/log/kubernetes –v=2”

然后我们依次启动Node上的服务(Docker安装好以后默认开机自启且已经启动,这里不再启动):

systemctl daemon-reload
systemctl enable kubelet.service 
 systemctl start kubelet.service 
 systemctl enable kube-proxy.service 
 systemctl start kube-proxy.service

待服务都成功启动后,kubelet会主动向Master注册自己所在的Node。如果所有服务都启动成功,我们就可以看到可用的Node了:

ubuntu➜ system kubectl get node 
 NAME | STATUS | AGE 
 192.168.67.133 | Ready | 1h

再在另外一台Node上面也部署一下,就可以看到两个节点了。

至此,本文就介绍完了。不过要应用到生产环境中,我们还有一些安全项和网络项需要配置,后面再介绍。