License: Attribution-NonCommercial-ShareAlike 4.0 International
本文出自 Suzf Blog。 如未注明,均为 SUZF.NET 原创。
转载请注明:http://suzf.net/post/951
什么是 Kubernetes
Kubernetes 是来自 Google 云平台的开源容器集群管理系统。基于 Docker 构建一个容器的调度服务。该系统可以自动在一个容器集群中选择一个工作容器供使用。其核心概念是 Container Pod。详细的设计思路请参考这里。 关于 Kubernetes 系统架构及组件介绍见 这里。 本文通过实际操作来演示Kubernetes的使用,主要包括如下内容:
- 部署环境介绍,以及Kubernetes集群逻辑架构
- 安装部署Open vSwitch跨机器容器通信工具
- 安装部署Etcd和Kubernetes的各大组件
- 演示Kubernetes管理容器和服务
部署环境及架构
- 操作系统: ubuntu 14.04 x86_64
- Kubernetes: v1.0.1
- Etcd版本: 3.0.0
- Docker版本: 1.6.2
- Open vSwith版本: 2.0.2
- 主机信息
- 服务器信息:
Role service Hostname IP Address master Kube-APIServer kubelet proxy etcd lucy.suzf.net 172.16.3.100 Minion1 kubelet proxy open-switch docker eva.suzf.net 172.16.3.10 Minion2 kubelet proxy open-switch docker cali.suzf.net 172.16.3.20
在详细介绍部署Kubernetes集群前,先给大家展示下集群的逻辑架构。从下图可知,整个系统分为两部分,第一部分是Kubernetes APIServer,是整个系统的核心,承担集群中所有容器的管理工作;第二部分是minion,运行Container Daemon,是所有容器栖息之地,同时在minion上运行Open vSwitch程序,通过GRE Tunnel负责minions之间Pod的网络通信工作。
http://suzf.net 纯手工锻造 欢迎关注与交流 ^_^
安装Open vSwitch及配置GRE
为了解决跨minion之间Pod的通信问题,我们在每个minion上安装Open vSwtich,并使用GRE或者VxLAN使得跨机器之间P11od能相互通信,本文使用GRE,而VxLAN通常用在需要隔离的大规模网络中。对于Open vSwitch的介绍请参考另一篇文章Open vSwitch。
[ both minion ] sudo apt-get install openvswitch-switch bridge-utils -y
安装完Open vSwitch和桥接工具后,接下来便建立minion节点之间的隧道。 首先在所有minion上分别建立OVS Bridge:
sudo ovs-vsctl add-br obr0
接下来建立gre,并将新建的gre0添加到obr0
# minion1 sudo ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=172.16.3.20 # minion2 sudo ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=172.16.3.10
至此,minion1和minion2之间的隧道已经建立。然后我们在minion1和minion2上创建Linux网桥kbr0替代Docker默认的docker0(我们假设minion1和minion2都已安装Docker),设置minion1的kbr0的地址为172.17.1.1/24, minion2的kbr0的地址为172.17.2.1/24,并添加obr0为kbr0的接口,以下命令在minion1和minion2上执行:
[ both minion ] # sudo brctl addbr kbr0 # 创建linux bridge代替docker0 # sudo brctl addif kbr0 obr0 # 添加obr0为kbr0的接口 # # sudo ip link set dev obr0 up # 设置obr0为up状态 # sudo ip link set dev docker0 down # 设置docker0为down状态 # sudo ip link del dev docker0 # 删除docker0,可选
查看这些接口的状态
# service openvswitch-switch status openvswitch-switch start/running @eva:~# ovs-vsctl show 52c65487-12fc-4228-b2ee-7c5ba409d8d2 Bridge "obr0" Port "gre0" Interface "gre0" type: gre options: {remote_ip="172.16.3.20"} Port "obr0" Interface "obr0" type: internal ovs_version: "2.0.2" @eva:~# brctl show bridge name bridge id STP enabled interfaces kbr0 8000.de14d8a90948 no obr0
为了使新建的kbr0在每次系统重启后任然有效,我们在minion1的/etc/network/interfaces文件中 追加内容如下:(在CentOS上会有些不一样)
@eva:~# tail -9 /etc/network/interfaces auto kbr0 iface kbr0 inet static address 172.16.1.1 netmask 255.255.255.0 # gateway 172.16.1.0 # dns-nameservers 172.31.1.1 up route add 172.16.2.0/24 via 172.16.3.20 dev eth0 down route add 172.16.2.0/24 via 172.16.3.20 dev eth0
minion2 网卡配置类似 。然后 启动虚拟网络接口
sudo ip link set dev obr0 up
你能在minion1和minion2上发现kbr0都设置了相应的IP地址。 这是我们创建的隧道还不能通信。经查找这是因为在minion1和minion2上缺少访问172.17.2.1和172.17.1.1的路由,因此我们需要添加路由保证彼此之间能通信:
# minion1 上执行 sudo ip route add 172.16.2.0/24 via 172.16.3.20 dev eth0 # minion2 上执行 sudo ip route add 172.16.1.0/24 via 172.16.3.10 dev eth0
现在网络之间可以正常通信了
@eva:~# ping 172.16.2.1 -c 2 PING 172.16.2.1 (172.16.2.1) 56(84) bytes of data. 64 bytes from 172.16.2.1: icmp_seq=1 ttl=64 time=0.714 ms 64 bytes from 172.16.2.1: icmp_seq=2 ttl=64 time=0.337 ms --- 172.16.2.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.337/0.525/0.714/0.189 ms @cali:~# ping 172.16.1.1 -c 2 PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data. 64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=0.577 ms 64 bytes from 172.16.1.1: icmp_seq=2 ttl=64 time=0.269 ms --- 172.16.1.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.269/0.423/0.577/0.154 ms
Minion 节点安装 docker
[ both minion ] sudo apt-get install docker.io -y
修改docker默认桥接网桥,并重启
sudo vi /etc/default/docker DOCKER_OPTS="-b kbr0" sudo service docker restart
Etcd 安装与配置
etcd是一个开源的用于配置共享和服务发现的高性能的键值存储系统。 注意:创建存放所有组件二进制文件目录,最好是/opt/bin目录,因为启动脚本里面写的就是这个目录。
@lucy:~# cd /usr/local/src/ @lucy:/usr/local/src#sudo wget https://github.com/coreos/etcd/releases/download/v3.0.0/etcd-v3.0.0-linux-amd64.tar.gz tar xf etcd-v3.0.0-linux-amd64.tar.gz cd etcd-v3.0.0-linux-amd64/ mkdir /opt/bin cp -a etcd etcdctl /opt/bin
etcd官方建议使用新的2379端口代替4001
cat > /etc/default/etcd << EOF ETCD_OPTS="\\ --listen-client-urls http://0.0.0.0:4001 \\ --advertise-client-urls http://0.0.0.0:4001 \\ --data-dir /var/lib/etcd/default.etcd" EOF # 选项说明: --listen-peer-urls :etcd作为分布式节点通信端口,默认指定端口7001,我们这里做的是单节点,这个参数可以不写,需要知道的是v2版本中改变为2380,7001仍可用 --listen-client-urls :客户端操作etcd API的端口,默认指定端口4001,v2中改变为2379,在k8s中我们要使用4001端口 --data-dir :指定数据存放目录 --advertise-client-urls :作为分布式的客户端连接端口,如果不写这个参数会出现以下报错 etcdmain: error verifying flags, -advertise-client-urls is required when -listen-client-urls is set explicitly. See 'etcd --help'. etcdmain: When listening on specific address(es), this etcd process must advertise accessible url(s) to each connected client.
etcd服务配置好后先不启动,待会用下面kubernetes提供的启动脚本启动! one key start cool ~ ~~ 下面安装 Kubernetes APIServer 及kubelet、proxy 等服务。
安装Kubernetes APIServer
下载安装kubernetes各组件
可以自己从源码编译kubernetes(需要安装golang环境),也可以从GitHub Kubernetes repo release page.选择源码包v1.0.1版本下载。
@lucy:~# cd /usr/local/src/ @lucy:/usr/local/src#sudo wget https://github.com/coreos/etcd/releases/download/v3.0.0/etcd-v3.0.0-linux-amd64.tar.gz @lucy:/usr/local/src#sudo wget https://github.com/GoogleCloudPlatform/kubernetes/releases/download/v1.0.1/kubernetes.tar.gz
然后解压下载的kubernetes和etcd包,并在kubernetes(minion1)、minion2上创建目录/opt/bin
[ All nodes ] # mkdir /opt/bin # echo "export PATH=\$PATH:/opt/bin" >> /etc/profile # source /etc/profile
解压kubernetes
tar xf kubernetes.tar.gz cd kubernetes/server && tar xf kubernetes-server-linux-amd64.tar.gz cd kubernetes/server/bin/
APIserver本身需要的是kube-apiserver kube-scheduler kube-controller-manager kubecfg四个
@lucy #cp kube-apiserver kube-scheduler kube-controller-manager kubecfg /opt/bin/
把proxy和kubelet复制到其他minions,确保这些文件都是可执行的
scp kube-proxy kubelet [email protected]:/opt/bin scp kube-proxy kubelet [email protected]:/opt/bin
拷贝相关组件启动脚本
cd /usr/local/src/kubernetes/cluster/ubuntu @lucy:/usr/local/src/kubernetes/cluster/ubuntu# cp master/init_scripts/* /etc/init.d/ @lucy:/usr/local/src/kubernetes/cluster/ubuntu# cp master/init_conf/* /etc/init/
配置kube*启动选项
# kube-apiserver cat > /etc/default/kube-apiserver << EOF KUBE_APISERVER_OPTS="--address=0.0.0.0 \\ --port=8080 \\ --etcd_servers=http://127.0.0.1:4001 \\ --logtostderr=true \\ --portal_net=172.16.9.0/24" EOF # 选项说明: --insecure-bind-address:api监听地址 --insecure-port:api监听端口 --service-cluster-ip-range:上面说到service角色是定义集群中一个pod集合,这个pod中容器提供一种服务,当创建service时会分配一个CLUSTER_IP提供统一的访问入口,那么,这个选项就是指定分配的IP范围 --etcd_servers:指定etcd连接地址 # kube-scheduler cat > /etc/default/kube-scheduler << EOF KUBE_SCHEDULER_OPTS="--master=127.0.0.1:8080 \\ --logtostderr=true" EOF # kube-controller-manager cat > /etc/default/kube-controller-manager << EOF KUBE_CONTROLLER_MANAGER_OPTS="--master=127.0.0.1:8080 \\ --logtostderr=true" EOF<br>
Minion 配置
* 复制kubelet、kube-proxy等到 minion1: @lucy:/usr/local/src/kubernetes/cluster/ubuntu# scp minion/init_scripts/kube* 172.16.9.10:/etc/init.d/ @lucy:/usr/local/src/kubernetes/cluster/ubuntu# scp minion/init_conf/{kubelet,kube-proxy}.conf 172.16.9.10:/etc/init/ # 注意:ubuntu默认禁止root远程登录,需要配置允许ssh登录,也可以先将二进制包拷贝到minion服务器能ssh登录的用户,然后再sudo移动到/opt/bin目录 * 在 minion1 端进行 cat> /etc/default/kubelet << EOF KUBELET_OPTS="--address=0.0.0.0 \\ --port=10250 \\ --hostname_override=172.16.3.10 \\ --api_servers=http://172.16.3.100:8080 \\ --pod-infra-container-image=docker.io/kubernetes/pause:latest \\ --logtostderr=true" EOF 选项说明 --hostname_override:在master端显示的节点名称,对应的minion主机修改对应的IP --pod-infra-container-image:创建pod时下载镜像地址,默认是gcr.io/google_containers/pause:0.8.0,需要翻墙才能访问,所以指定了官方镜像下载源 cat> /etc/default/kube-proxy << EOF KUBE_PROXY_OPTS="--master=http://172.16.3.100:8080 \\ --logtostderr=true" EOF # (对 minion2 重复上面 * 两个步骤,把上面.10改成.20)
所有配置就绪,Launch
@lucy:~# service etcd start etcd start/running, process 4030 # 注意:如果etcd启动后进程不存在,尝试去掉/etc/init.d/etcd第64行的 >> $ETCD_LOGFILE 2>&1追加日志这部分再启动试试。 @lucy:~# /etc/init.d/kube-apiserver start * Kube-Apiserver is managed via upstart, try using service kube-apiserver start What are you 弄啥嘞? 查看一下etcd 的启动脚本 发现少一个判断 @lucy:~# sed -n '36,39'p /etc/init.d/etcd # see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it) if false && [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | grep -q upstart; then log_failure_msg "$ETCD_DESC is managed via upstart, try using service $BASE $1" exit 1 @lucy:~# sed -n '36,39'p /etc/init.d/kube-apiserver # see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it) if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | grep -q upstart; then log_failure_msg "$KUBE_APISERVER_DESC is managed via upstart, try using service $BASE $1" exit 1 加上判断在试一试, 呵呵 好了~ @lucy:~# service kube-apiserver start kube-apiserver start/running, process 4222 kube-apiserver启动后会自动运行kube-scheduler、kube-controller-manager 这些服务的日志可以从/var/log/upstart/中找到。 lucy:~# ls /var/log/upstart/kube-* /var/log/upstart/kube-apiserver.log /var/log/upstart/kube-controller-manager.log /var/log/upstart/kube-scheduler.log
可以通过etcdctl查看到etcd存储着关于集群的各种信息
@lucy:~# etcdctl ls /registry /registry/minions /registry/namespaces /registry/pods /registry/ranges /registry/serviceaccounts /registry/services /registry/controllers /registry/events
启动 minion 节点 服务
[ both minion ] # service kube-proxy start # service kubelet start
到这 kubernetes 就配置完了,查看下集群节点: kubernetes常用命令
# kubectl get nodes # 查查看minion主机 # kubectl get pods # 查看pods清单 # kubectl get services # 查看service清单 # kubectl get services -o json # 查看service清单 以 json 形式输出 # kubectl get replicationControllers # 查看replicationControllers清单 # for i in `kubectl get pod|tail -n +2|awk '{print $1}'`; do kubectl delete pod $i; done #删除所有pods
或者通过Server api for REST方式(推荐,及时性更高)
kubernetes 测试
命令启动一个nginx:
# kubectl run --image=nginx nginx-test-by-suzf-net replicationcontroller "nginx-test-by-suzf-net" created
初次创建要下载镜像,需等待数分钟,查看集群pods:
# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-test-by-suzf-net-uepzq 1/1 Running 0 8h
使用yaml 文件创建 pod
root@lucy:~# cat nginx-pod.yaml apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 root@lucy:~# kubectl create -f nginx-pod.yaml pods/nginx root@lucy:~# kubectl get pod NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 29s nginx-test-by-suzf-net-uepzq 1/1 Running 0 8h
查看下创建的nginx信息 访问一下 试试 当然我们也可以使用Kubernetes提供的例子Guestbook(下载的源码example目录下可以找到)来做测试。 至此,kubernetes集群就部署成功了。欢迎继续关注 ^_^.
参考文档
http://kubernetes.io/docs/getting-started-guides/ubuntu/
http://lizhenliang.blog.51cto.com/7876557/1736572
http://blog.liuts.com/post/247/
https://segmentfault.com/a/1190000002620961