6

Ubuntu16.04手动部署Kubernetes(1)——Master和Node部署

 3 years ago
source link: https://niyanchun.com/deploy-kubernetes-step-by-step-on-trusty-section-1.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Ubuntu16.04手动部署Kubernetes(1)——Master和Node部署

2017-02-16 技术 Kubernetes 10019次阅读 35 条评论

之前在《Kubernetes初体验》中我们使用Minikube快速体验了一把Kubernetes,然后在《Kubernetes架构及资源关系简单总结》一文中我们又简单介绍了Kubernetes的框架以及Kubernetes中的一些关键术语和概念,或者称之为资源、对象。本文主要讲Kubernetes的一种原始部署方式。Kubernetes从开发至今,其部署方式已经变得越来越简单。常见的有三种:

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

其实,除了上面三种方式外,有些Linux发行版已经提供了Kubernetes的安装包,比如在CentOS 7上面,直接执行yum install -y etcd kubernetes即可安装Kubernetes,然后做些配置就可以完成部署了。我相信对于Google这种追求自动化、智能化的公司,他们会让Kubernetes部署方式还会更加简化。但这些都不是本文的重点,本文要讲述的是如何像堆积木一样一个模块一个模块的部署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.56.101和192.168.56.102.其中101这台机器机器既是Master,又是Node;102是Node。本文只装了101,后面再测试网络等需要多台的时候再安装102.因为Kubernetes里面Node是主动向Master注册的(通过Node上面的kubelet),所以要扩展Node的话也非常容易。

获取二进制文件

我们都需要哪些二进制文件呢?回想一下《Kubernetes架构及资源关系简单总结》中,Kubernetes集群内主要包含这些模块:Master中:APIServer、scheduler、controller manager、etcd;Node中:kubelet、kube-proxy、runtime(这里指Docker)。

上面每个模块都由一个二进制文件实现,所以我们需要上面每个模块对应的那个二进制文件。获取方式有很多。最直观的方式就是去github上面下载release的包,里面有二进制文件。但那个包有1GB+大小,特别对于中国用户就呵呵了,当然还有许多其他获取的方式。

注意:源代码目录里面也有很多名字和二进制名字相同的文件,但那些不是二进制文件,而是一些去掉后缀的shell脚步,都只有KB级别的大小,而真正的二进制文件都是MB级别的,注意别搞错了。

推荐使用下面的命令下载kubernetes-server-linux-amd64.tar.gz包:

curl -L https://storage.googleapis.com/kubernetes-release/release/v${KUBE_VERSION}/kubernetes-server-linux-amd64.tar.gz -o kubernetes-server-linux-amd64.tar.gzcurl -L https://storage.googleapis.com/kubernetes-release/release/v${KUBE_VERSION}/kubernetes-server-linux-amd64.tar.gz -o kubernetes-server-linux-amd64.tar.gz

这个包解压后的kubernetes/server/bin目录下就有我们需要的二进制文件(只使用了其中6个):

ubuntu➜  bin ll
total 1.3G
-rwxr-x--- 1 root root 145M Dec 14 09:06 hyperkube
-rwxr-x--- 1 root root 118M Dec 14 09:06 kube-apiserver
-rw-r----- 1 root root   33 Dec 14 09:06 kube-apiserver.docker_tag
-rw-r----- 1 root root 119M Dec 14 09:06 kube-apiserver.tar
-rwxr-x--- 1 root root  97M Dec 14 09:06 kube-controller-manager
-rw-r----- 1 root root   33 Dec 14 09:06 kube-controller-manager.docker_tag
-rw-r----- 1 root root  98M Dec 14 09:06 kube-controller-manager.tar
-rwxr-x--- 1 root root 6.6M Dec 14 09:06 kube-discovery
-rwxr-x--- 1 root root  44M Dec 14 09:05 kube-dns
-rwxr-x--- 1 root root  44M Dec 14 09:05 kube-proxy
-rw-r----- 1 root root   33 Dec 14 09:06 kube-proxy.docker_tag
-rw-r----- 1 root root 174M Dec 14 09:06 kube-proxy.tar
-rwxr-x--- 1 root root  51M Dec 14 09:06 kube-scheduler
-rw-r----- 1 root root   33 Dec 14 09:06 kube-scheduler.docker_tag
-rw-r----- 1 root root  52M Dec 14 09:06 kube-scheduler.tar
-rwxr-x--- 1 root root  91M Dec 14 09:06 kubeadm
-rwxr-x--- 1 root root  49M Dec 14 09:06 kubectl
-rwxr-x--- 1 root root  46M Dec 14 09:06 kubefed
-rwxr-x--- 1 root root 103M Dec 14 09:06 kubelet

我将这些二进制文件都放到了/opt/bin目录下,并且将该目录加到了PATH中。你也可以直接将这些文件放到系统的PATH路径中,比如/usr/bin

OK,有了这些二进制文件,我们就可以开始部署了。

部署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文件进行修改。

2017.9.4更新

Kubernets新版本(我记得好像是1.6开始吧,记不清了)已经不支持etcd 2.x版本了,但是在Ubuntu 16.04上面通过apt install装的是2.2版本,这样会导致api-server无法和etcd通讯,而导致一些问题,所以建议从github下载最新etcd 3.x(https://github.com/coreos/etcd/releases),然后手动安装。创建/lib/systemd/system/etcd.service文件:

[Unit]
Description=Etcd Server
Documentation=https://github.com/coreos/etcd
After=network.target

[Service]
User=root
Type=simple
EnvironmentFile=-/etc/default/etcd
ExecStart=/opt/k8s/v1_6_9/etcd-v3.2.7-linux-amd64/etcd    # 改为你自己路径
Restart=on-failure
RestartSec=10s
LimitNOFILE=40000

[Install]
WantedBy=multi-user.target

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

# 重新加载systemd配置管理,切记增加`*.service`后一定要先执行该命令,否则启动服务时会报错
systemctl daemon-reload

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的部署配置完成了,其实主要分两部分:

  • 创建systemd服务文件,有了该文件,就可以使用systemd去控制该服务,比如启停、开机自启等。systemd的命令、语法等后面写文章介绍。
  • 模块的配置文件,用于控制模块如何启动及功能控制。

后面其他模块的配置与之大同小异。

部署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.56.101: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.56.101: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.56.101: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.56.101: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.56.101   Ready     1h

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK