Kubernetes集群部署
预备知识
如果你不知道以下是做什么的,那么请参考下面链接(包括但不限于)进行学习:
前置要求与约定
约定:Master(s)节点为Kubernetes主节点、Worker(s)节点为Kubernetes普通节点、Etcd节点为将部署Etcd的节点,按本教程安装Master(s)节点与Etcd节点必须一致,Etcd官方建议Etcd集群节点个数为奇数个(比如1、3、5)以防止脑裂。
按本教程安装Kubernetes集群只会在Master(s)节点上安装kubectl命令。
防火墙及端口检测
请检测防火墙状态,如果防火墙已开启请仔细阅读端口要求并按下面方式开放指定的端口;若未开启防火墙请跳过本节操作。
检测防火墙状态(不同的发行版本具体操作可能不一样以供应商说明文档为准)
检测firewall-cmd状态
$ firewall-cmd --state not running
not running
表示防火墙未启动,如果出现running
则为启动状态。检测iptables状态
service iptables status
当状态为inactive或者提示
Unit iptables.service could not be found.
均表示iptables未启动。
开放指定端口
如果防火墙已启用,则需要开放指定端口,下面分别列举使用firewalld和iptables设置开放端口命令(不同发行版可能存在差异)。
firewalld
firewall-cmd --add-port=6443/tcp --permanent # 永久开放6443端口 firewall-cmd --reload # 重新加载firewall
iptables
$ iptables -A INPUT -p tcp --dport 6443 -j ACCEPT # 开放6443端口 $ iptables -A INPUT -p tcp --dport 2379:2380 -j ACCEPT # 开放2379到2380端口 $ iptables-save > /etc/sysconfig/iptables && service iptables restart # 保存并重启iptables
同步服务器时区
时区和时间的同步性对于服务器很重要(例如您在更新数据库时,时间的准确性对业务的影响会非常大),为避免实例上运行的业务逻辑混乱和避免网络请求错误,您需要将一台或多台服务器设置在同一时区下,比如 Asia/Shanghai 或 America/Los Angeles。您可以根据自己的业务需求并参照本文为服务器设置或者修改时区。此外,NTP(Network Time Protocol)服务能保证您的服务器的时间与标准时间同步,您可以根据本文配置 NTP 服务。 详细过程可以参考此处
本地虚拟机安装示例
本地虚拟机安装指的是在个人电脑上模拟安装。一般情况下个人电脑无法满足安装choerodon的要求,如果你需要在个人电脑上安装choerodon请确认CPU8核以上,内存48G以上。
安装Docker
使用k3s创建一个本地集群(https://github.com/rancher/k3s)
私有云安装示例
私有云安装模式指的是在已有的虚拟机中安装,绝大部分centos 7.3+的虚拟机可以通过执行下述命令进行安装,如果你需要安装choerodno请确认集群总内存在48G以上,CPU总核心数大于8核。
环境准备
在要执行ansible脚本的机器上部署ansible运行需要的环境:
sudo yum install epel-release -y sudo yum install git python3-pip sshpass -y pip3 install --no-cache-dir ansible==2.7.5 netaddr -i https://mirrors.aliyun.com/pypi/simple/
克隆项目:
git clone https://github.com/choerodon/kubeadm-ansible.git
修改hosts文件
在修改配置文件前请注意以下几点:
- 注意Etcd节点和Master节点需要在相同的机器。
- 示例中的node1为主机的hostname
- ansible_host为目标主机的连接地址,比如您可以通过
192.168.56.11
这个ip连接到node1
的ssh服务,则此处填写192.168.56.11
- ip为目标主机的
内网网卡对应的ip
及内网ip 请勿将外网ip配置到ip字段中,否则极有可能部署失败
编辑项目下的
kubeadm-ansible/inventory/hosts
文件,修改各机器的访问地址、用户名、密码,并维护好各节点与角色的关系,node1为机器的hostname。该用户必须是具有root权限的用户。但并非要求一定是root用户,其他具有root权限的用户也可以。比如,想要部署单节点集群,只需要这样配置(参考):[all] node1 ansible_host=192.168.56.11 ip=192.168.56.11 ansible_user=root ansible_ssh_pass=change_it ansible_become=true [kube-master] node1 # 请与kube-master节点一致 [etcd] node1 [kube-node] node1
ansible_host指节点内网IP,IP指Kubernetes目标绑定网卡IP
如果所有机器以
代理的方式
访问外网,请配置以下几个变量,否则请不要配置:http_proxy: http://1.2.3.4:3128 https_proxy: http://1.2.3.4:3128 no_proxy: localhost,127.0.0.0/8 docker_proxy_enable: true
部署
执行:
export ANSIBLE_HOST_KEY_CHECKING=False #在kubeadm-ansible/目录下执行 ansible-playbook -i inventory/hosts -e @inventory/vars cluster.yml -K
如果你配置的是root用户则无需添加-K参数
查看等待pod的状态为runnning:
kubectl get po -n kube-system
如果部署失败,想要重置集群(所有数据),执行:
#在kubeadm-ansible/目录下执行 ansible-playbook -i inventory/hosts reset.yml -K
添加节点
通过本小节教程添加的节点不能是Master或Etcd节点,只能是普通的Work节点。若你使用的是NFS作为存储,建议你先安装nfs-utils。
若集群搭建完毕后还想再添加节点,请按以下方式进行添加:
修改kubeadm-ansible/inventory/hosts文件,在
[all]
分区按照原有格式添加新增节点信息,在[kube-node]
分区添加新增节点名,其他分区请一定不要改动。比如原有信息如下,我们添加一个ip为192.168.56.12的node2节点:[all] node1 ansible_host=192.168.56.11 ip=192.168.56.11 ansible_user=root ansible_ssh_pass=vagrant ansible_become=true [kube-master] node1 # 请与kube-master节点一致 [etcd] node1 [kube-node] node1
修改后信息如下:
[all] node1 ansible_host=192.168.56.11 ip=192.168.56.11 ansible_user=root ansible_ssh_pass=vagrant ansible_become=true node2 ansible_host=192.168.56.12 ip=192.168.56.12 ansible_user=root ansible_ssh_pass=vagrant ansible_become=true [kube-master] node1 # 请与kube-master节点一致 [etcd] node1 [kube-node] node1 node2
执行添加节点命令
#在kubeadm-ansible/目录下执行 ansible-playbook -i inventory/hosts -e @inventory/vars scale.yml -K
公有云安装示例
公有云安装以阿里云ECS为例进行讲解,其它公有云可参考本教程,但具体安装方式请咨相应云提供商。目前只支持Centos 7.2及以上版本。
环境准备
在要执行ansible脚本的机器上部署ansible运行需要的环境:
sudo yum install epel-release -y sudo yum install git python3-pip sshpass -y pip3 install --no-cache-dir ansible==2.7.5 netaddr -i https://mirrors.aliyun.com/pypi/simple/
克隆项目:
git clone https://github.com/choerodon/kubeadm-ansible.git
修改hosts文件
在阿里云的ECS的控制面板上修改ECS实例的hostname,名称最好只包含小写字母、数字和中划线。并保持与inventory/hosts中的名称与ECS控制台上的名称保持一致,重启生效。
执行下一步前请注意以下几点:
- 注意Etcd节点和Master节点需要在相同的机器。
- 示例中的node1为主机的hostname
- ansible_host为目标主机的连接地址,比如您可以通过
192.168.56.11
这个ip连接到node1
的ssh服务,则此处填写192.168.56.11
- ip为目标主机的
内网网卡对应的ip
及内网ip - 请勿将外网ip配置到ip字段中,否则极有可能部署失败
开始安装
编辑项目下的
kubeadm-ansible/inventory/hosts
文件,修改各机器的访问地址、用户名、密码,并维护好各节点与角色的关系。该用户必须是具有root权限的用户。但并非要求一定是root用户,其他具有root权限的用户也可以。比如,想要部署单节点集群,只需要这样配置(参考):[all] node1 ansible_host=192.168.56.11 ip=192.168.56.11 ansible_user=root ansible_ssh_pass=change_it ansible_become=true [kube-master] node1 # 请与kube-master节点一致 [etcd] node1 [kube-node] node1
ansible_host指节点内网IP,IP指Kubernetes目标绑定网卡IP
修改kubeadm-ansible/inventory/vars
变量文件
本文档部署的网络类型为flannel类型
在使用VPC网络的ECS上部署k8s时,flannel网络的Backend类型需要是
ali-vpc
。在本脚本中默认使用的是vxlan
类型,虽然在vpc环境下网络能通,但是不稳定波动较大。所以推荐使用ali-vpc
的类型。因此,首先需要设置默认的flannel网络不部署,通过在
kubeadm-ansible/inventory/vars
文件中添加变量:flannel_enable: false
网段选择,如果ECS服务器用的是专有网络,pod和service的网段不能与vpc网段重叠,若有重叠请配置kube_pods_subnet和kube_service_addresses变量设置pod和service的网段,示例参考:
# 如果vpc网段为`192.168.*` kube_pods_subnet: 172.16.0.0/20 kube_service_addresses: 172.16.16.0/20
如果所有机器以
代理的方式
访问外网,配置以下几个变量,否则请不要配置:http_proxy: http://1.2.3.4:3128 https_proxy: http://1.2.3.4:3128 no_proxy: localhost,127.0.0.0/8 docker_proxy_enable: true
部署
下面开始部署集群:
export ANSIBLE_HOST_KEY_CHECKING=False #在kubeadm-ansible/目录下执行 ansible-playbook -i inventory/hosts -e @inventory/vars cluster.yml -K
如果你配置的是root用户则无需添加-K参数
获取阿里云ACCESS_KEY,该
ACCESS_KEY
需要拥有以下权限:- 只读访问云服务器(ECS)的权限
- 管理专有网络(VPC)的权限
手动部署flannel网络插件,在任意一个Master节点创建配置文件
kube-flannel-aliyun.yml
:kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:name: flannelrules:- apiGroups:- ""resources:- podsverbs:- get- apiGroups:- ""resources:- nodesverbs:- list- watch- apiGroups:- ""resources:- nodes/statusverbs:- patch---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata:name: flannelroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: flannelsubjects:- kind: ServiceAccountname: flannelnamespace: kube-system---apiVersion: v1kind: ServiceAccountmetadata:name: flannelnamespace: kube-system---kind: ConfigMapapiVersion: v1metadata:name: kube-flannel-cfgnamespace: kube-systemlabels:tier: nodeapp: flanneldata:cni-conf.json: |{"name": "cbr0","type": "flannel","delegate": {"isDefaultGateway": true}}net-conf.json: |{"Network": "172.16.0.0/20","Backend": {"Type": "ali-vpc"}}---apiVersion: extensions/v1beta1kind: DaemonSetmetadata:name: kube-flannel-dsnamespace: kube-systemlabels:tier: nodeapp: flannelspec:template:metadata:labels:tier: nodeapp: flannelspec:hostNetwork: truenodeSelector:beta.kubernetes.io/arch: amd64tolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoScheduleserviceAccountName: flannelinitContainers:- name: install-cniimage: registry.cn-hangzhou.aliyuncs.com/google-containers/flannel:v0.9.0command:- cpargs:- -f- /etc/kube-flannel/cni-conf.json- /etc/cni/net.d/10-flannel.confvolumeMounts:- name: cnimountPath: /etc/cni/net.d- name: flannel-cfgmountPath: /etc/kube-flannel/containers:- name: kube-flannelimage: registry.cn-hangzhou.aliyuncs.com/google-containers/flannel:v0.9.0command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ]securityContext:privileged: trueenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespace- name: ACCESS_KEY_IDvalue: YOUR_ACCESS_KEY_ID- name: ACCESS_KEY_SECRETvalue: YOUR_ACCESS_KEY_SECRETvolumeMounts: - name: run mountPath: /run - name: flannel-cfg mountPath: /etc/kube-flannel/ volumes: - name: run hostPath: path: /run - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg配置的pod网段,即变量文件kubeadm-ansible/inventory/vars中的kube_pods_subnet值阿里云中创建的 ACCESS_KEY_ID阿里云中创建的 ACCESS_KEY_SECRET然后使用kubectl命令部署,部署成功后在vpc的路由表中会添加多条路由条目,下一跳分别为每个节点的pod ip段:
kubectl apply -f kube-flannel-aliyun.yml
接下来需要在ECS安全组,在入方向规则中加上pod网段的地址。否则在pod容器中无法访问别的节点的pod的端口,比如:
授权策略 协议类型 端口范围 授权类型 授权对象 允许 全部 -1/-1 地址段访问 172.16.0.0/20 允许 TCP 443⁄443 地址段访问 0.0.0.0/0 允许 TCP 80⁄80 地址段访问 0.0.0.0/0 查看等待pod的状态为runnning:
kubectl get po -n kube-system
如果部署失败,想要重置集群(所有数据),执行:
#在kubeadm-ansible/目录下执行 ansible-playbook -i inventory/hosts reset.yml -K
添加节点
通过本小节教程添加的节点不能是Master或Etcd节点,只能是普通的Work节点。若你使用的是NFS作为存储,建议你先安装nfs-utils
若集群搭建完毕后还想再添加节点,请按以下方式进行添加:
修改kubeadm-ansible/inventory/hosts文件,在
[all]
分区按照原有格式添加新增节点信息,在[kube-node]
分区添加新增节点名,其他分区请一定不要改动。比如原有信息如下,我们添加一个ip为192.168.56.12的node2节点:[all] node1 ansible_host=192.168.56.11 ip=192.168.56.11 ansible_user=root ansible_ssh_pass=vagrant ansible_become=true [kube-master] node1 # 请与kube-master节点一致 [etcd] node1 [kube-node] node1
修改后信息如下:
[all] node1 ansible_host=192.168.56.11 ip=192.168.56.11 ansible_user=root ansible_ssh_pass=vagrant ansible_become=true node2 ansible_host=192.168.56.12 ip=192.168.56.12 ansible_user=root ansible_ssh_pass=vagrant ansible_become=true [kube-master] node1 # 请与kube-master节点一致 [etcd] node1 [kube-node] node1 node2
执行添加节点命令
#在kubeadm-ansible/目录下执行 ansible-playbook -i inventory/hosts -e @inventory/vars scale.yml -K
Kubernetes网络测试
集群搭建完成后请一定进行以下测试步骤进行测试。
集群访问公网测试
测试说明
镜像中将以下核心代码进行封装成为
curls
命令,使用方式curls url [times]
,例如curls choerodon.io 20
则为访问choerodon.io
20次并打印测试出的时间指标,命令默认访问10次。curl -o /dev/null -s -w '%{time_connect} %{time_starttransfer} %{time_total}' "choerodon.io"
时间指标说明
- 单位:秒
- time_connect:建立到服务器的 TCP 连接所用的时间
- time_starttransfer:在发出请求之后,Web 服务器返回数据的第一个字节所用的时间
- time_total:完成请求所用的时间
场景一、 Kubernetes集群node节点访问公网
测试命令
docker run -it --rm --net=host \ registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0 \ curls choerodon.io
测试结果
No time_connect time_starttransfer time_total 1 0.015071 0.027448 0.027570 2 0.010049 0.024527 0.024612 3 0.010025 0.022209 0.022311 4 0.012600 0.025269 0.025369 5 0.012847 0.025849 0.025932 6 0.009973 0.023102 0.023220 7 0.013074 0.029310 0.029411 8 0.015137 0.029992 0.030103 9 0.010994 0.029040 0.029173 10 0.010554 0.022011 0.022130
平均响应时间:26ms
场景二、Kubernetes集群Pod访问公网
测试命令
kubectl run curl-test \ -it --quiet --rm --restart=Never \ --image='registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0' \ -- bash -c "sleep 3; curls choerodon.io"
测试结果
No time_connect time_starttransfer time_total 1 0.014916 0.027232 0.027418 2 0.020213 0.034626 0.034762 3 0.014945 0.028014 0.028165 4 0.016916 0.030483 0.032091 5 0.020519 0.033075 0.033281 6 0.015398 0.027727 0.028003 7 0.015260 0.027099 0.027247 8 0.019549 0.033506 0.033597 9 0.020941 0.032935 0.035226 10 0.014298 0.026570 0.026983
平均响应时间:29ms
集群内部网络延迟测试
测试说明
测试数据
Service Name: default-http-backend.kube-system.svc
Service Cluster IP: 172.16.17.173 (可通过
kubectl get svc default-http-backend -n kube-system
进行查看)Service Port: 80
通过向
default-http-backend
的healthz
api执行curl命令进行网络延迟测试$ curl "http://172.16.17.173/healthz" ok
场景一、 Kubernetes集群node节点上通过Service Cluster IP访问
测试命令
docker run -it --rm --net=host \ registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0 \ curls http://172.16.17.173/healthz
测试结果
No time_connect time_starttransfer time_total 1 0.000491 0.000983 0.001038 2 0.000347 0.002051 0.002122 3 0.000298 0.000894 0.000975 4 0.000263 0.082559 0.082665 5 0.000351 0.000732 0.000785 6 0.000234 0.084351 0.084445 7 0.000245 0.000550 0.000592 8 0.000436 0.086836 0.086947 9 0.000215 0.000536 0.000573 10 0.000369 0.089528 0.089635
平均响应时间:34ms
场景二、Kubernetes集群内部通过service访问
测试命令
kubectl run curl-test \ -it --quiet --rm --restart=Never \ --image='registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0' \ -- bash -c "sleep 3; curls http://default-http-backend.kube-system.svc/healthz"
测试结果
No time_connect time_starttransfer time_total 1 0.040173 0.080107 0.080205 2 0.047826 0.065836 0.065932 3 0.064808 0.091835 0.091938 4 0.075448 0.087315 0.087410 5 0.112765 0.195511 0.195640 6 0.104970 0.199655 0.199777 7 0.127144 0.139747 0.139834 8 0.056066 0.063325 0.063456 9 0.021773 0.028471 0.028578 10 0.017777 0.023236 0.023330
平均响应时间:112ms
注意: 执行测试的node节点/Pod与Serivce所在的Pod的距离(是否在同一台主机上),对这两个场景可以能会有一定影响。
集群内部网络性能测试
测试说明
- 使用iperf进行测试.
场景一、主机之间
服务端命令:
docker run -it --rm --net=host \ registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0 \ iperf -s -p 12345 -i 1 -M
注意: 此时该服务端命令会前台运行,一直等待客户端请求,请另起一个终端窗口进行执行客户端命令。
客户端命令:
docker run -it --rm --net=host \ registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0 \ iperf -c 服务端主机IP -p 12345 -i 1 -t 10 -w 20K
测试结果
[ ID] Interval Transfer Bandwidth [ 3] 0.0- 1.0 sec 225 MBytes 1.89 Gbits/sec [ 3] 1.0- 2.0 sec 223 MBytes 1.87 Gbits/sec [ 3] 2.0- 3.0 sec 237 MBytes 1.98 Gbits/sec [ 3] 3.0- 4.0 sec 223 MBytes 1.87 Gbits/sec [ 3] 4.0- 5.0 sec 273 MBytes 2.29 Gbits/sec [ 3] 5.0- 6.0 sec 259 MBytes 2.17 Gbits/sec [ 3] 6.0- 7.0 sec 308 MBytes 2.59 Gbits/sec [ 3] 7.0- 8.0 sec 257 MBytes 2.16 Gbits/sec [ 3] 8.0- 9.0 sec 261 MBytes 2.19 Gbits/sec [ 3] 9.0-10.0 sec 234 MBytes 1.96 Gbits/sec [ 3] 0.0-10.0 sec 2.44 GBytes 2.10 Gbits/sec
场景二、不同主机的Pod之间
服务端命令:
kubectl run iperf-server \ -it --quiet --rm --restart=Never \ --overrides='{"spec":{"template":{"spec":{"nodeName":"指定服务端运行的节点"}}}}' \ --image='registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0' \ -- bash -c "sleep 3; ifconfig eth0; iperf -s -p 12345 -i 1 -M"
注意: 此时该服务端命令会前台运行,一直等待客户端请求,请另起一个终端窗口进行执行客户端命令。查看输出的日志,替换下面客户端命令中POD的IP
客户端命令:
kubectl run iperf-client \ -it --quiet --rm --restart=Never \ --overrides='{"spec":{"nodeName":"指定客户端运行的节点"}}' \ --image='registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0' \ -- iperf -c 服务端POD的IP -p 12345 -i 1 -t 10 -w 20K
测试结果
[ ID] Interval Transfer Bandwidth [ 3] 0.0- 1.0 sec 1.42 GBytes 12.2 Gbits/sec [ 3] 1.0- 2.0 sec 1.39 GBytes 11.9 Gbits/sec [ 3] 2.0- 3.0 sec 1.22 GBytes 10.5 Gbits/sec [ 3] 3.0- 4.0 sec 1.27 GBytes 10.9 Gbits/sec [ 3] 4.0- 5.0 sec 1.04 GBytes 8.91 Gbits/sec [ 3] 5.0- 6.0 sec 1.36 GBytes 11.7 Gbits/sec [ 3] 6.0- 7.0 sec 1.42 GBytes 12.2 Gbits/sec [ 3] 7.0- 8.0 sec 1.57 GBytes 13.5 Gbits/sec [ 3] 8.0- 9.0 sec 1.25 GBytes 10.8 Gbits/sec [ 3] 9.0-10.0 sec 1.56 GBytes 13.4 Gbits/sec [ 3] 0.0-10.0 sec 13.5 GBytes 11.6 Gbits/sec
场景三、Node与非同主机的Pod之间
服务端命令:
docker run -it --rm --net=host \ registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0 \ iperf -s -p 12345 -i 1 -M
注意: 此时该服务端命令会前台运行,一直等待客户端请求,请另起一个终端窗口进行执行客户端命令。
客户端命令:
kubectl run iperf-client \ -it --quiet --rm --restart=Never \ --overrides='{"spec":{"nodeName":"指定客户端运行的节点"}}' \ --image='registry.cn-hangzhou.aliyuncs.com/choerodon-tools/network-and-cluster-perfermance-test:0.1.0' \ -- iperf -c 服务端主机IP -p 12345 -i 1 -t 10 -w 20K
测试结果
[ ID] Interval Transfer Bandwidth [ 3] 0.0- 1.0 sec 289 MBytes 2.43 Gbits/sec [ 3] 1.0- 2.0 sec 290 MBytes 2.43 Gbits/sec [ 3] 2.0- 3.0 sec 226 MBytes 1.89 Gbits/sec [ 3] 3.0- 4.0 sec 209 MBytes 1.75 Gbits/sec [ 3] 4.0- 5.0 sec 254 MBytes 2.13 Gbits/sec [ 3] 5.0- 6.0 sec 257 MBytes 2.15 Gbits/sec [ 3] 6.0- 7.0 sec 265 MBytes 2.23 Gbits/sec [ 3] 7.0- 8.0 sec 184 MBytes 1.55 Gbits/sec [ 3] 8.0- 9.0 sec 217 MBytes 1.82 Gbits/sec [ 3] 9.0-10.0 sec 236 MBytes 1.98 Gbits/sec [ 3] 0.0-10.0 sec 2.37 GBytes 2.04 Gbits/sec