前言
部署Kubernetes除了手动方式外,还有诸如Kubeadm、Kubespray、Breeze、Rancher、kargo等多种自动化方式。工具没有好坏之分,能干事、效率高就行。这里,笔者仍使用Kubespray部署当前K8s最新版本(用着真的很贴身),可自动化部署HA集群、可灵活定制开发、高稳定性等。
本篇将介绍如何在不用科学上网的背景下,快速自动化部署K8s集群。那么,开始吧!
初始化环境
环境说明
环境实在有限,只有一台机器,想玩HA集群也没环境啊
主机名 | IP地址 | 角色 |
---|---|---|
K8s | 172.16.0.180 | Master+node |
环境为Centos 7系统,各节点配置hosts和hostname,如1
2cat /etc/hosts
172.16.0.180 K8s
关闭防火墙等1
2sed -i 's/SELINUX=*/SELINUX=disabled/' /etc/selinux/config
systemctl disable firewalld && systemctl stop firewalld
Kubernetes 1.8开始要求关闭系统的Swap交换分区,方法如下1
swapoff -a && echo "vm.swappiness=0" >> /etc/sysctl.conf && sysctl -p && free –h
Docker从1.13版本开始调整了默认的防火墙规则,禁用了iptables filter表中FOWARD链,这样会引起Kubernetes集群中跨Node的Pod无法通信,在各个Docker节点执行下面的命令:1
iptables -P FORWARD ACCEPT
配置ssh key 认证。确保本机也可以 ssh 连接,否则下面部署失败1
2ssh-keygen -t rsa -N ""
cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
更新系统内核为 4.4.x , CentOS 默认为3.10.x1
2
3
4rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
yum --enablerepo=elrepo-kernel install -y kernel-lt kernel-lt-devel
grub2-set-default 0
重启系统1
reboot
增加内核配置1
2
3
4vim /etc/sysctl.conf
# docker
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
使其内核配置生效1
sysctl -p
安装kubespray
安装 centos的epel源1
yum -y install epel-release
make缓存1
yum clean all
安装软件,ansible 必须 >= 2.71
yum install -y python-pip python34 python-netaddr python34-pip ansible git
下载源码,当前kubespray项目的master分支默认安装k8s 1.13.1版本1
git clone https://github.com/kubernetes-sigs/kubespray
安装 kubespray 依赖,若无特殊说明,后续操作均在~/kubespray目录下执行1
2cd kubespray
pip install -r requirements.txt
配置kubespray1
cp -rfp inventory/sample inventory/mycluster
修改配置文件 hosts.ini。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18vim inventory/mycluster/hosts.ini
[all]
k8s ansible_host=k8s ip=172.16.0.180
[kube-master]
k8s
[etcd]
k8s
[kube-node]
k8s
[k8s-cluster:children]
kube-master
kube-node
[calico-rr]
修改配置文件all.yaml1
2
3
4
5vim inventory/mycluster/group_vars/all/all.yml
# 修改如下配置:
loadbalancer_apiserver_localhost: true
# 加载内核模块,否则 ceph, gfs 等无法挂载客户端
kubelet_load_modules: true
默认镜像从 gcr.io/google-containers 下载,由于墙的原因不能下载。这里我将k8s 1.13.1版本所必须的镜像push到了DockerHub上,方便大家下载使用。1
2
3
4
5
6
7
8
9
10
11
12
13
14# 下载镜像(该步骤可不用执行)
docker pull xiaoxu780/kube-proxy:v1
docker pull xiaoxu780/kube-controller-manager:v1
docker pull xiaoxu780/kube-scheduler:v1
docker pull xiaoxu780/kube-apiserver:v1
docker pull xiaoxu780/coredns:1.2
docker pull xiaoxu780/cluster-proportional-autoscaler-amd64:1.3
docker pull xiaoxu780/kubernetes-dashboard-amd64:v1
docker pull xiaoxu780/etcd:3.2
docker pull xiaoxu780/node:v3
docker pull xiaoxu780/ctl:v3
docker pull xiaoxu780/kube-controllers:v3
docker pull xiaoxu780/cni:v3
docker pull xiaoxu780/pause-amd64:3.1
修改镜像默认的repo地址,使用Calico三层网络,同时可以指定安装的k8s版本,参数为kube_version。编辑文件1
2vim inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml
kube_image_repo: "gcr.io/google-containers" //修改为kube_image_repo: "xiaoxu780"
修改配置文件main.yml,使用sed命令批量替换1
2
3sed -i 's/gcr\.io\/google_containers/xiaoxu780/g' roles/download/defaults/main.yml
sed -i 's/quay\.io\/coreos/xiaoxu780/g' roles/download/defaults/main.yml
sed -i 's/quay\.io\/calico/xiaoxu780/g' roles/download/defaults/main.yml
修改代码,使用NodePort方式访问Dashboard。1
2
3
4
5
6
7
8vim . kubernetes-apps templates/dashboard.yml.j2
……
……
targetPort: 8443
type: NodePort //添加这一行
selector:
k8s-app: kubernetes-dashboard
注意
如果是单节点部署K8s,Kubespray默认会创建2个coredns Pod,但Deployment中又用到了podAntiAffinity,因此会导致其中一个coredns pod pending,所以需要修改代码如下1
2
3
4
5
6
7
8
9
10
11
12
13vim ./roles/kubernetes-apps/ansible/templates/coredns-deployment.yml.j2
//注释掉以下几行代码
affinity:
#podAntiAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# - topologyKey: "kubernetes.io/hostname"
# labelSelector:
# matchLabels:
# k8s-app: coredns{{ coredns_ordinal_suffix | default('') }}
或者在spec一行添加代码:
spec:
replicas: 1 //指定pod为1个副本
安装K8s集群
K8s高可用方案
Kubernetes的高可用,要解决的核心其实是kube-apiserver组件和etcd的高可用,其它组件在多节点模式下,本身拥有天然容灾性。
etcd高可用
etcd本身就支持集群模式,所以啥都不用考虑,只要保证节点数量足够,升级备份之类的事情,kubespray本身就支持多节点etcd部署。由于etcd采用Raft一致性算法,集群规模最好不要超过9个,推荐3,5,7,9个数量。具体看集群规模。如果性能不够,宁可多分配资源,也最好不要超过9个。
api 高可用
api的高可用,一般有2种思路。
各节点自己代理
使用这种方式,会在每个Node节点启动一个Nginx代理,然后由这个Nginx代理负载所有的master节点的api。master会访问自己节点下的api(localhost)。这是Kubespray部署的默认方式。
外置负载均衡
利用外部的负载均衡实现,例如阿里云的SLB或自建的HAproxy等。
将hyperkube和kubeadm包下载到所有k8s节点的/tmp/releases 目录下,为了避免科学上网,此处,我下载存放到了网盘上。
https://pan.baidu.com/s/1m2rF1dRXIZh_15OevTDbnA
执行部署命令1
ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml -b -v -k
运维经验
如果需要扩容Work节点,则修改hosts.ini文件,增加新增的机器信息。然后执行下面的命令:1
ansible-playbook -i inventory/mycluster/hosts.ini scale.yml -b -v -k
将hosts.ini文件中的master和etcd的机器增加到多台,执行部署命令1
ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml -b -vvv
刪除节点,如果不指定节点就是刪除整个集群:1
ansible-playbook -i inventory/mycluster/hosts.ini remove-node.yml -b -v
如果需要卸载,可以执行以下命令:1
ansible-playbook -i inventory/mycluster/hosts.ini reset.yml -b –vvv
升级K8s集群,选择对应的k8s版本信息,执行升级命令。涉及文件为upgrade-cluster.yml。1
ansible-playbook upgrade-cluster.yml -b -i inventory/mycluster/hosts.ini -e kube_version=vX.XX.XX -vvv
登录Dashboard
登陆Dashboard 支持 kubeconfig 和 token 两种认证方式,kubeconfig 也依赖 token 字段,所以生成 token这一步是必不可少的。此处,我们获取集群管理员(拥有所有命名空间的 admin 权限)的token。
查看kubernetes-dashboard暴露的端口,如下所示,这里是31777端口。1
2# kubectl get svc --all-namespaces | grep kubernetes-dashboard
kube-system kubernetes-dashboard NodePort 10.233.34.183 <none> 443:31777/TCP 12h
获取admin的token1
2
3
4# kubectl -n kube-system describe $(kubectl -n kube-system get secret -n kube-system -o name | grep namespace) | grep token
Name: namespace-controller-token-kmtg7
Type: kubernetes.io/service-account-token
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJuYW1lc3BhY2UtY29udHJvbGxlci10b2tlbi1rbXRnNyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJuYW1lc3BhY2UtY29udHJvbGxlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImQwYTI0N2JkLTEwY2EtMTFlOS1iYTFiLWEwMzY5ZjNmMDQwNCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTpuYW1lc3BhY2UtY29udHJvbGxlciJ9.v689nSk_SxDLWk5Mna0t9uITRE1Jy2mstZxeJfZmQmm2UsQ-vIm4ueUNtCoA-PNx49s9hic-Pn6PfqyWQQW_QQ1yLDjjp1wl4J3tdar8fBfuR7Zvm5aKw8kyRhfQzQQZgEKlgBEHaYyKicgVUwEupa3zevXdUTnLH8FudcOdWEwgCflCveHdkRwoy88pYPyL5wh2egEKpeDhzOEztULsi2g3tpdlyg_uQIaKJ1OBODJZz5PXVFMYyIk06SyciEOX0YxF3pH_uSlPqg4RxMaeTfPhlWTnFPlIjQ2juK4s0o2Tyg_sftLSXvd3QtOg3tBavRm3pzHISIPbtN7EZAyWZQ
在dashboard登录页面上使用上面输出中的那个非常长的字符串作为token登录,即可以拥有管理员权限操作整个kubernetes集群中的对象。当然您也可以将这串token加到admin用户的kubeconfig文件中,继续使用kubeconfig登录,两种认证方式任您选择。登录dashboard。
https://172.16.0.180:31777
注意
由于这里使用的HTTPS,并未使用证书,因此使用Google等浏览器会终止访问(真想说一句,Google真尼玛操蛋,强制使用HTTPS协议)。建议使用firefox浏览器。
验证K8s集群
查看集群状态1
2
3# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s Ready master,node 36m v1.13.1
查看集群Pod状态1
2
3
4
5
6
7
8
9
10
11
12# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-687b7cc79c-knj87 1/1 Running 0 35m
kube-system calico-node-7rj8c 1/1 Running 0 35m
kube-system coredns-5b47d4476c-8wdb7 1/1 Running 0 35m
kube-system coredns-5b47d4476c-92wnq 1/1 Running 0 35m
kube-system dns-autoscaler-5b547856bc-95cft 1/1 Running 0 35m
kube-system kube-apiserver-k8s 1/1 Running 0 36m
kube-system kube-controller-manager-k8s 1/1 Running 0 36m
kube-system kube-proxy-cdlzp 1/1 Running 0 35m
kube-system kube-scheduler-k8s 1/1 Running 0 36m
kube-system kubernetes-dashboard-d7978b5cc-lvf6l 1/1 Running 0 35m
查看ipvs1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25# ipvsadm -L -n
IP Virtual Server version 1.2 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16 :32714 rr
-> 10.233 :8443 Masq 1 0 0
TCP 172.17 :32714 rr
-> 10.233 :8443 Masq 1 0 0
TCP 10.233 :443 rr
-> 172.16 :6443 Masq 1 5 0
TCP 10.233 :53 rr
-> 10.233 :53 Masq 1 0 0
-> 10.233 :53 Masq 1 0 0
TCP 10.233 :9153 rr
-> 10.233 :9153 Masq 1 0 0
-> 10.233 :9153 Masq 1 0 0
TCP 10.233 :443 rr
-> 10.233 :8443 Masq 1 0 0
TCP 10.233 :32714 rr
-> 10.233 :8443 Masq 1 0 0
TCP 127.0 :32714 rr
-> 10.233 :8443 Masq 1 0 0
UDP 10.233 :53 rr
-> 10.233 :53 Masq 1 0 0
-> 10.233 :53 Masq 1 0 0
创建一个Nginx应用的deplpyment。K8s中,针对无状态类服务推荐使用Deployment,有状态类服务则建议使用Statefulset。RC和RS已不支持目前K8s的诸多新特性了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37# vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 3
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
name: http
targetPort: 80
protocol: TCP
selector:
name: nginx
1 | # kubectl apply -f nginx-deployment.yaml |
测试nginx服务是否正常1
2
3
4
5
6
7
8
9
10# curl -I 10.233.42.172
HTTP/1.1 200 OK
Server: nginx/1.15.8
Date: Sat, 05 Jan 2019 09:58:16 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Wed, 26 Dec 2018 23:21:49 GMT
Connection: keep-alive
ETag: "5c240d0d-264"
Accept-Ranges: bytes
后续
K8s从1.11版本起便废弃了Heapster监控组件,取而代之的是metrics-server 和 custom metrics API,后面将陆续完善包括Prometheus+Grafana监控,Kibana+Fluentd日志管理,cephfs-provisioner存储(可能需要重新build kube-controller-manager装上rbd相关的包才能使用Ceph RBD StorageClass),traefik ingress等服务。
参考资料
https://github.com/kubernetes-sigs/kubespray/blob/master/docs/getting-started.md