K8S这么火,网上教程不少,但是无奈官方更新太快,很多部署教程都已落后,并有无数的坑点,对于初学者来说,不是每个人都有能力爬出来。

对于,每个想进步的同学来说,部署K8S就是一座大山,能清晰的部署出来,那么已经对各种组件和功能略知一二,所以今天这篇笔记式教程能在自己和同学前进的路上铺上一层厚实的奠基石,无论您因为什么原因看到这篇文章,那么,说明你在探索的路上是想进步的,那么, 既然有人想求知,那么,就没有道理不分享自己的小小的心得。

注明:感谢bokeyuan的小水滴,我只是站在巨人的肩膀上更进一步,很多内容也修改自他的文章。

docker?:?kubernetes依赖的容器运行时
kubelet:?kubernetes最核心的agent组件,每个节点都会启动一个,负责像pods及节点的生命周期等管理
kubectl:?kubernetes的命令行控制工具,只可以在master上使用.
kubeadm:?用来bootstrap?kubernetes.?初始化一个k8s集群.

一、所有节点环境准备

1、软件版本

软件版本
kubernetesv1.15.2
CentOS
Minimal 7.6.1809 (ESXi 虚拟机)
Dockerv18.09
flannelv0.10.0-amd64

2、节点规划

IP角色主机名
192.168.3.10k8s mastermaster
192.168.3.11k8s node01slaver1
192.168.3.12k8s node02slaver2

这里我就不贴网络架构图了,并且假设你已经部准备好虚拟机并关闭防火墙和selinux,并且将三个节点添加好了hosts文件,并修改好了hostname,并保证网络通畅,

对于需要代理或加速docker镜像拉取,为了简化本教程,这里一律都假设你处于自由网路世界可拉取任意文件(需要的请自己参考其他教程或者手动拉取镜像);

我的测试主机位于香港,所以无需配置代理或者加速:

iptables对bridge的数据进行处理:

创建/etc/sysctl.d/k8s.conf文件,添加如下内容:

net.bridge.bridge-nf-call-ip6tables?=?1
net.bridge.bridge-nf-call-iptables?=?1
net.ipv4.ip_forward?=?1

执行命令使修改生效。

modprobe?br_netfilter
sysctl?-p?/etc/sysctl.d/k8s.conf

关闭系统Swap

Kubernetes 1.8开始要求关闭系统的Swap,如果不关闭,默认配置下kubelet将无法启动。方法一,通过kubelet的启动参数–fail-swap-on=false更改这个限制。方法二,关闭系统的Swap。

swapoff?-a

修改/etc/fstab文件,注释掉SWAP的自动挂载,使用free -m确认swap已经关闭。

#注释掉swap分区
[root@localhost?/]#?sed?-i?'s/.*swap.*/#&/'?/etc/fstab

[root@localhost?/]#?free?-m
??????????????total????????used????????free??????shared??buff/cache???available
Mem:????????????962?????????154?????????446???????????6?????????361?????????612
Swap:?????????????0???????????0???????????0

永久禁用swap

echo?"vm.swappiness?=?0">>?/etc/sysctl.conf

在所有的Kubernetes节点node1和node2上执行以下脚本:

cat?>?/etc/sysconfig/modules/ipvs.modules?<<EOF
#!/bin/bash
modprobe?--?ip_vs
modprobe?--?ip_vs_rr
modprobe?--?ip_vs_wrr
modprobe?--?ip_vs_sh
modprobe?--?nf_conntrack_ipv4
EOF
chmod?755?/etc/sysconfig/modules/ipvs.modules?&&?bash?/etc/sysconfig/modules/ipvs.modules?&&?lsmod?|?grep?-e?ip_vs?-e?nf_conntrack_ipv4

安装docker

docker的版本对于K8S的成功至关重要,不少朋友会掉进去(有的身处坑中而不自知),K8S 1.15.2支持的最高docker版本为18.09,那我们就装这个版本中的最高小版本18.09.8。

按照docker的官方安装教程:

先清理centos自带所有docker程序:

yum?remove?docker?\
??????????????????docker-client?\
??????????????????docker-client-latest?\
??????????????????docker-common?\
??????????????????docker-latest?\
??????????????????docker-latest-logrotate?\
??????????????????docker-logrotate?\
??????????????????docker-engine
yum?install?-y?yum-utils?\
??device-mapper-persistent-data?\
??lvm2

添加最新的docker yum仓库:

yum-config-manager?\
????--add-repo?\
????/download_docker_com/linux/centos/docker-ce.repo

官方给出的安装命令:

yum?install?docker-ce-<VERSION_STRING>?docker-ce-cli-<VERSION_STRING>?containerd.io

查看仓库提供的各种版本信息并按照版本从高到底排序:

yum?list?docker-ce.x86_64??--showduplicates?|sort?-r

这里我们安装18.09.8:

yum?install?docker-ce-18.09.8?docker-ce-cli-18.09.8?containerd.io?-y

启动:

systemctl?start?docker?;?systemctl?enable?docker

修改docker cgroup driver为systemd

对于使用systemd作为init system的Linux的发行版,使用systemd作为docker的cgroup driver可以确保服务器节点在资源紧张的情况更加稳定,因此这里修改各个节点上docker的cgroup driver为systemd。

创建或修改/etc/docker/daemon.json

{
????"exec-opts":?["native.cgroupdriver=systemd"]
}

重启docker:

systemctl?restart?docker

docker?info?|?grep?Cgroup
Cgroup?Driver:?systemd

安装kubeadm和kubelet

cat?<<EOF?>?/etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=/packages_cloud_google_com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=/packages_cloud_google_com/yum/doc/yum-key.gpg
????????/packages_cloud_google_com/yum/doc/rpm-package-key.gpg
EOF

安装:

yum?install?-y?kubelet?kubeadm?kubectl

上面命令会默认安装最新版的程序,目前都为1.15.2

安装kubeadm init初始化集群所需docker镜像

开始初始化集群之前可以使用kubeadm config images pull预先在各个节点上拉取所k8s需要的docker镜像

[root@localhost?/]#?kubeadm?config?images?list
k8s.gcr.io/kube-apiserver:v1.15.2
k8s.gcr.io/kube-controller-manager:v1.15.2
k8s.gcr.io/kube-scheduler:v1.15.2
k8s.gcr.io/kube-proxy:v1.15.2
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.3.10
k8s.gcr.io/coredns:1.3.1

逐个手动拉取,先来个小技巧,在每行前面加个docker? pull ,免得写脚本或手工输入麻烦:

kubeadm?config?images?list?|awk?'{print?"docker?pull?"?$0}'
docker?pull?k8s.gcr.io/kube-apiserver:v1.15.2
docker?pull?k8s.gcr.io/kube-controller-manager:v1.15.2
docker?pull?k8s.gcr.io/kube-scheduler:v1.15.2
docker?pull?k8s.gcr.io/kube-proxy:v1.15.2
docker?pull?k8s.gcr.io/pause:3.1
docker?pull?k8s.gcr.io/etcd:3.3.10
docker?pull?k8s.gcr.io/coredns:1.3.1

直接复制运行即可。

kubeadm初始化集群

使用kubeadm初始化集群,在master上执行下面的命令:

kubeadm?init?--kubernetes-version=v1.15.2?--pod-network-cidr=10.244.0.0/16?--service-cidr=10.96.0.0/12

部署成功后,重点在这里:

图片.png

按照提示配置必要的环境路径:

mkdir?-p?$HOME/.kube
cp?-i?/etc/kubernetes/admin.conf?$HOME/.kube/config
chown?$(id?-u):$(id?-g)?$HOME/.kube/config

查看一下集群状态,确认个组件都处于healthy状态:

[root@master?/]#?kubectl?get?cs
NAME?????????????????STATUS????MESSAGE?????????????ERROR
scheduler????????????Healthy???ok??????????????????
controller-manager???Healthy???ok??????????????????
etcd-0???????????????Healthy???{"health":"true"}

图片.png

因为还没有部署pod网络,所以coredns被延时等待启动。

给pod配置网络

pod网络插件是必要安装,以便pod可以相互通信。在部署应用和启动kube-dns之前,需要部署网络,kubeadm仅支持CNI的网络。

pod支持的网络插件有很多,如CalicoCanalFlannelRomanaWeave Net等,因为之前我们初始化使用了参数--pod-network-cidr=10.244.0.0/16,所以我们使用插件flannel

安装:

kubectl?apply?-f?/raw_githubusercontent_com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml

配置完后,通过命令可以清晰的看到随着flannel被安装成功并初始化后coredns渐渐被调度起来的过程:

图片.png

kube-proxy 启动 ipvs

我假设你前面已经按照步骤在每个节点都加载好了ipvs内核,并设置了开机启动

kubectl?edit?configmap?kube-proxy?-n?kube-system

找到如下部分。

??kind:?KubeProxyConfiguration????
??metricsBindAddress:?127.0.0.1:10249?
??mode:?"ipvs"?
??nodePortAddresses:?null?
??oomScoreAdj:?-999
其中mode原来是空,默认为iptables模式,改为ipvs。scheduler默认是空,默认负载均衡算法为轮训。

查找并删除所有kube-proxy的pod

kubectl??get??pod?-n?kube-system?-o?wide?|grep?kube-proxy
kubectl?delete?pod?kube-proxy-xxx?-n?kube-system

查看kube-proxy的pod日志

kubectl logs kube-proxy-XXX -n kube-system

或者后面部署了DashBoard直接web页面查看。

安装ipvsadm

使用ipvsadm查看ipvs相关规则,如果没有这个命令可以直接yum安装

yum?install?-y?ipvsadm
[root@master?~]#?ipvsadm?-ln
IP?Virtual?Server?version?1.2.1?(size=4096)
Prot?LocalAddress:Port?Scheduler?Flags
??->?RemoteAddress:Port???????????Forward?Weight?ActiveConn?InActConn
TCP??127.0.0.1:31896?rr
??->?10.244.0.7:3000??????????????Masq????1??????0??????????0?????????
TCP??172.17.0.1:31896?rr
??->?10.244.0.7:3000??????????????Masq????1??????0??????????0?????????
TCP??172.17.0.1:32238?rr
??->?10.244.0.9:8443??????????????Masq????1??????0??????????0?????????
TCP??192.168.3.10:31896?rr
??->?10.244.0.7:3000??????????????Masq????1??????0??????????0?????????
TCP??192.168.3.10:32238?rr
??->?10.244.0.9:8443??????????????Masq????1??????0??????????0?????????
TCP??10.96.0.1:443?rr
??->?192.168.3.10:6443????????????Masq????1??????0??????????0?????????
TCP??10.96.0.10:53?rr
??->?10.244.0.2:53????????????????Masq????1??????0??????????0?????????
??->?10.244.0.3:53????????????????Masq????1??????0??????????0

不要着急添加节点,先把master配置到底:

部署完了,就开始部署dashboard,有命令行没有web,感觉差点什么;

安装 Kubernetes Dashboard

k8s dashboard 的 docker镜像是

k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0

先准备好dashboard镜像,没办法,就是这么随意,国内得绕弯去别处找并打标签:

docker?pull?k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1

安装,这个是目前最新的编排文件地址,网上很多坑就是因为这个文件路径都已变更:

kubectl?apply?-f?/raw_githubusercontent_com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

修改NodePort:

因为Service 是ClusterIP 类型,为了方便使用,我们可通过下面命令修改成NodePort 类型。

kubectl?patch?svc?kubernetes-dashboard?-p?'{"spec":{"type":"NodePort"}}'?-n?kube-system

查看端口

[root@master?~]#?kubectl?get?svc?-n?kube-system
NAME???????????TYPE???????????CLUSTER-IP???????EXTERNAL-IP???????PORT(S)????????AGE
kube-dns???????ClusterIP?????10.96.0.10???????<none>???????????53/UDP,53/TCP???6h
kubernetes-dashboard??NodePort??10.107.238.193??<none>?????????443:32238/TCP???167m

登录web端:太阳城娱乐网最快登入/192_168_3_10:32238

图片.png

?

配置登录权限

Dashboard 支持 Kubeconfig 和 Token 两种认证方式,为了简化配置,我们通过配置文件 dashboard-admin.yaml 为 Dashboard 默认用户赋予 admin 权限。

[root@ken?~]#?cat?dashboard-admin.yml
apiVersion:?rbac.authorization.k8s.io/v1beta1
kind:?ClusterRoleBinding
metadata:
??name:?kubernetes-dashboard
??labels:?
?????k8s-app:?kubernetes-dashboard
roleRef:
??apiGroup:?rbac.authorization.k8s.io
??kind:?ClusterRole
??name:?cluster-admin
subjects:
-?kind:?ServiceAccount
??name:?kubernetes-dashboard
??namespace:?kube-system

这里的重点是创建了一个ServiceAccountName为kubernetes-dashboard的系统服务账号,我们要记住它,有大用。

应用并且获取token:

kubectl?apply?-f?dashboard-admin.yaml
kubectl?-n?kube-system?describe?secret?$(kubectl?-n?kube-system?get?secret?|?grep?kubernetes-dashboard|?awk?'{print?$1}')

类似于下面这一段,把 token 填入确定即可。

Name:?admin-user-token-xln5d
Namespace:?kube-system
Labels:?<none>Annotations:?kubernetes.io/service-account.name:?admin-user
kubernetes.io/service-account.uid:?54801c01-01e2-11e9-857e-00505689640f
Type:?kubernetes.io/service-account-token
Data====ca.crt:?1025?bytes
namespace:?11?bytes
token:?
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJ
lLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXhsbjVkIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3V
udC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI1NDgwMWMwMS0wMWUyLTE
xZTktODU3ZS0wMDUwNTY4OTY0MGYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.MbGeROnjA9f1AhBO8v2GuHC1ihVk1UcxpM8lYk
IC_P9Mx9jVZcM56zr4jcxjSnIuZPZxIznLJIIo7TRY94Ya2VujzF2lpDxlNYF2hWY3Ss9d5LqRtP3JsJNZVLmxvYIGnmnGyVCEikCM6W44WPu-S

基本就登录成功了,但是还没完,想要直观的看到每个pod和容器的资源使用情况,得安装K8S原生支持的基本可视化监控插件,这里说的就是:heapster+influxdb+grafana组合;

Heapster 本身是一个 Kubernetes 应用,部署方法很简单,但是它不像dashboard那样apply下就起来,因为它不是K8S默认系统应用,所以master默认是不允许直接调度到master节点上运行,所以,为了将heapster部署到master节点,必须首先放开这个限制:

kubectl?taint?node?master?node-role.kubernetes.io/master-

为了保险起见,还是先手动把需要的镜像拉取过来吧,不然服务一直处于延时等待启动状态:

docker?pull?k8s.gcr.io/heapster-amd64:v1.5.4
docker?pull?k8s.gcr.io/heapster-grafana-amd64:v5.0.4
docker?pull?k8s.gcr.io/heapster-influxdb-amd64:v1.5.2

这样这三剑客就这么来了,

上官方克隆heapster并安装:

git?clone?/github_com/kubernetes/heapster.git
kubectl?apply?-f?heapster/deploy/kube-config/influxdb/
kubectl?apply?-f?heapster/deploy/kube-config/rbac/heapster-rbac.yaml

部署完了就恢复Master Only状态,禁止调度其他pod到master节点:

kubectl?taint?node?master?node-role.kubernetes.io/master=:NoSchedule

运行命令查看部署情况:

kubectl?get?pod?-n?kube-system?|grep?-e?heapster?-e?monitor
kubectl?get?deploy?-n?kube-system?|grep?-e?heapster?-e?monitor
kubectl?get?svc?-n?kube-system?|grep?-e?heapster?-e?monitor

图片.png

修改NodePort,将grafana暴露到公网访问:

kubectl?patch?svc?monitoring-grafana?-p?'{"spec":{"type":"NodePort"}}'?-n?kube-system

图片.png

好,这就算部署完了,你以为基本的master就这么简单的部署完了,更多的坑在向你招手;

在web页面等了半天怎么刷新发现可视化监控图表都没有出来,我们打开heapster容器的日志发现api接口被拒问题,于是修改heapster的部署文件:

#?heapster.yaml文件中的
-?--source=kubernetes:/kubernetes_default
?
#?修改为
-?--source=kubernetes:kubernetes:/kubernetes_default?useServiceAccount=true&kubeletHttps=true&kubeletPort=10250&insecure=true

并修改这个地方,前面部署token的时候让你记住有大用,这里就是用了这个账号:

图片.png

这里是使用dashboard的web编辑器,当然有点反人类,好好的yaml语法就这样被破坏了,所以,你也可以直接命令行搞定:

kubectl?edit?deployment?heapster??-n?kube-system

更新后,K8S销毁原来的容器,又自动重新创建了一个新容器,现象就出来了:

图片.png

图片.png

最后, token登录dashboard的超时设置,又是默认的一个坑,官方的默认是900S也就是15分钟,这对于搞实验的同学简直是一痛苦,

参数名?????默认值?????说明
token-ttl?????15?minutes?????Expiration?time?(in?seconds)?of?JWE?tokens?generated?by?dashboard.?Default:?15?min.?0?-?never?expires.

直接修改kubernetes-dashboard的部署文件,Dashboard的Token失效时间可以通过 token-ttl 参数来设置,

ports:
-?containerPort:?8443
??protocol:?TCP
args:
??-?--auto-generate-certificates
??-?--token-ttl=43200

如果你的docker 和docker-CLI版本不太对,那么你可能入另外一个坑,无法shell登录容器,

kubectl exec -it 容器名称 -n kube-system sh? (/bin/sh , /bin/bash, bash )无论哪种都说没有这个路径无法执行,查看yaml文件又发现已经设置加载了/bin/sh,暂时无解。

后面,你将发现容器日志的时间又是UTC时区格式,又是一个坑,慢慢爬吧。

grafana有兴趣去官网下载K8S模板,直接导入,慢慢玩吧!